Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
bc77d7c0 | 4 | | Copyright CiviCRM LLC. All rights reserved. | |
6a488035 | 5 | | | |
bc77d7c0 TO |
6 | | This work is published under the GNU AGPLv3 license with some | |
7 | | permitted exceptions and without any warranty. For full license | | |
8 | | and copyright information, see https://civicrm.org/licensing | | |
6a488035 | 9 | +--------------------------------------------------------------------+ |
d25dd0ee | 10 | */ |
6a488035 TO |
11 | |
12 | /** | |
13 | * | |
14 | * @package CRM | |
ca5cec67 | 15 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
6a488035 TO |
16 | */ |
17 | ||
18 | /** | |
b6c94f42 | 19 | * Class for configuring jobs. |
6a488035 TO |
20 | */ |
21 | class CRM_Admin_Form_Job extends CRM_Admin_Form { | |
e57fc8ca | 22 | public $_id = NULL; |
430ae6dd | 23 | |
88aae6d4 A |
24 | /** |
25 | * @var bool | |
26 | */ | |
27 | public $submitOnce = TRUE; | |
28 | ||
00be9182 | 29 | public function preProcess() { |
6a488035 TO |
30 | |
31 | parent::preProcess(); | |
ed2ee15a | 32 | $this->setContext(); |
6a488035 | 33 | |
483cfbc4 | 34 | $this->setTitle(ts('Manage - Scheduled Jobs')); |
6a488035 TO |
35 | |
36 | if ($this->_id) { | |
37 | $refreshURL = CRM_Utils_System::url('civicrm/admin/job', | |
38 | "reset=1&action=update&id={$this->_id}", | |
39 | FALSE, NULL, FALSE | |
40 | ); | |
41 | } | |
42 | else { | |
43 | $refreshURL = CRM_Utils_System::url('civicrm/admin/job', | |
44 | "reset=1&action=add", | |
45 | FALSE, NULL, FALSE | |
46 | ); | |
47 | } | |
48 | ||
49 | $this->assign('refreshURL', $refreshURL); | |
50 | } | |
51 | ||
52 | /** | |
eceb18cc | 53 | * Build the form object. |
6a488035 | 54 | * |
77b97be7 | 55 | * @param bool $check |
6a488035 TO |
56 | */ |
57 | public function buildQuickForm($check = FALSE) { | |
58 | parent::buildQuickForm(); | |
59 | ||
60 | if ($this->_action & CRM_Core_Action::DELETE) { | |
61 | return; | |
62 | } | |
63 | ||
d71d4aae | 64 | if ($this->_action & CRM_Core_Action::VIEW) { |
d05f3550 | 65 | $this->assign('jobName', self::getJobName($this->_id)); |
a098caf2 SL |
66 | $this->addButtons([ |
67 | [ | |
68 | 'type' => 'submit', | |
69 | 'name' => ts('Execute'), | |
70 | 'isDefault' => TRUE, | |
71 | ], | |
72 | [ | |
73 | 'type' => 'cancel', | |
74 | 'name' => ts('Cancel'), | |
75 | ], | |
76 | ]); | |
77 | return; | |
78 | } | |
a098caf2 | 79 | |
6a488035 TO |
80 | $attributes = CRM_Core_DAO::getAttribute('CRM_Core_DAO_Job'); |
81 | ||
82 | $this->add('text', 'name', ts('Name'), | |
83 | $attributes['name'], TRUE | |
84 | ); | |
85 | ||
be2fb01f | 86 | $this->addRule('name', ts('Name already exists in Database.'), 'objectExists', [ |
0d48f1cc TO |
87 | 'CRM_Core_DAO_Job', |
88 | $this->_id, | |
89 | ]); | |
6a488035 TO |
90 | |
91 | $this->add('text', 'description', ts('Description'), | |
92 | $attributes['description'] | |
93 | ); | |
94 | ||
95 | $this->add('text', 'api_entity', ts('API Call Entity'), | |
96 | $attributes['api_entity'], TRUE | |
97 | ); | |
98 | ||
99 | $this->add('text', 'api_action', ts('API Call Action'), | |
100 | $attributes['api_action'], TRUE | |
101 | ); | |
102 | ||
56251ea7 | 103 | $this->add('select', 'run_frequency', ts('Run frequency'), CRM_Core_SelectValues::getJobFrequency()); |
6a488035 | 104 | |
e8f61813 | 105 | // CRM-17686 |
99f914d4 | 106 | $this->add('datepicker', 'scheduled_run_date', ts('Scheduled Run Date'), NULL, FALSE, ['minDate' => date('Y-m-d')]); |
e8f61813 | 107 | |
6a488035 | 108 | $this->add('textarea', 'parameters', ts('Command parameters'), |
4367e964 | 109 | ['cols' => 50, 'rows' => 6] |
6a488035 TO |
110 | ); |
111 | ||
112 | // is this job active ? | |
113 | $this->add('checkbox', 'is_active', ts('Is this Scheduled Job active?')); | |
114 | ||
be2fb01f | 115 | $this->addFormRule(['CRM_Admin_Form_Job', 'formRule']); |
6a488035 TO |
116 | } |
117 | ||
e0ef6999 | 118 | /** |
3fd42bb5 | 119 | * @param array $fields |
e0ef6999 EM |
120 | * |
121 | * @return array|bool | |
122 | * @throws API_Exception | |
123 | */ | |
00be9182 | 124 | public static function formRule($fields) { |
6a488035 | 125 | |
be2fb01f | 126 | $errors = []; |
6a488035 TO |
127 | |
128 | require_once 'api/api.php'; | |
129 | ||
c65db512 | 130 | /** @var \Civi\API\Kernel $apiKernel */ |
048222df | 131 | $apiKernel = \Civi::service('civi_api_kernel'); |
5a3846f7 | 132 | $apiRequest = \Civi\API\Request::create($fields['api_entity'], $fields['api_action'], ['version' => 3]); |
c65db512 TO |
133 | try { |
134 | $apiKernel->resolve($apiRequest); | |
0db6c3e1 TO |
135 | } |
136 | catch (\Civi\API\Exception\NotImplementedException $e) { | |
6a488035 TO |
137 | $errors['api_action'] = ts('Given API command is not defined.'); |
138 | } | |
139 | ||
140 | if (!empty($errors)) { | |
141 | return $errors; | |
142 | } | |
143 | ||
144 | return empty($errors) ? TRUE : $errors; | |
145 | } | |
146 | ||
e0ef6999 EM |
147 | /** |
148 | * @return array | |
149 | */ | |
00be9182 | 150 | public function setDefaultValues() { |
be2fb01f | 151 | $defaults = []; |
6a488035 TO |
152 | |
153 | if (!$this->_id) { | |
154 | $defaults['is_active'] = $defaults['is_default'] = 1; | |
155 | return $defaults; | |
156 | } | |
157 | $domainID = CRM_Core_Config::domainID(); | |
158 | ||
353ffa53 TO |
159 | $dao = new CRM_Core_DAO_Job(); |
160 | $dao->id = $this->_id; | |
6a488035 TO |
161 | $dao->domain_id = $domainID; |
162 | if (!$dao->find(TRUE)) { | |
163 | return $defaults; | |
164 | } | |
165 | ||
166 | CRM_Core_DAO::storeValues($dao, $defaults); | |
167 | ||
e8f61813 | 168 | // CRM-17686 |
d7bace22 DRJ |
169 | if (!empty($dao->scheduled_run_date)) { |
170 | $ts = strtotime($dao->scheduled_run_date); | |
9ee4786b | 171 | $defaults['scheduled_run_date'] = date("Y-m-d H:i:s", $ts); |
e8f61813 DRJ |
172 | } |
173 | ||
6a488035 TO |
174 | // CRM-10708 |
175 | // job entity thats shipped with core is all lower case. | |
176 | // this makes sure camel casing is followed for proper working of default population. | |
a7488080 | 177 | if (!empty($defaults['api_entity'])) { |
6a488035 TO |
178 | $defaults['api_entity'] = ucfirst($defaults['api_entity']); |
179 | } | |
180 | ||
181 | return $defaults; | |
182 | } | |
183 | ||
184 | /** | |
eceb18cc | 185 | * Process the form submission. |
6a488035 TO |
186 | */ |
187 | public function postProcess() { | |
188 | ||
d7d6c461 | 189 | CRM_Utils_System::flushCache(); |
6a488035 TO |
190 | |
191 | if ($this->_action & CRM_Core_Action::DELETE) { | |
192 | CRM_Core_BAO_Job::del($this->_id); | |
193 | CRM_Core_Session::setStatus("", ts('Scheduled Job Deleted.'), "success"); | |
194 | return; | |
195 | } | |
196 | ||
a098caf2 SL |
197 | // using View action for Execute. Doh. |
198 | if ($this->_action & CRM_Core_Action::VIEW) { | |
199 | $jm = new CRM_Core_JobManager(); | |
200 | $jm->executeJobById($this->_id); | |
d71d4aae SL |
201 | $jobName = self::getJobName($this->_id); |
202 | CRM_Core_Session::setStatus(ts('%1 Scheduled Job has been executed. See the log for details.', [1 => $jobName]), ts("Executed"), "success"); | |
ed2ee15a MW |
203 | |
204 | if ($this->getContext() === 'joblog') { | |
205 | // If we were triggered via the joblog form redirect back there when we finish | |
206 | $redirectUrl = CRM_Utils_System::url('civicrm/admin/joblog', 'reset=1&jid=' . $this->_id); | |
207 | } | |
208 | else { | |
209 | $redirectUrl = CRM_Utils_System::url('civicrm/admin/job', 'reset=1'); | |
210 | } | |
211 | CRM_Utils_System::redirect($redirectUrl); | |
a098caf2 SL |
212 | return; |
213 | } | |
214 | ||
6a488035 TO |
215 | $values = $this->controller->exportValues($this->_name); |
216 | $domainID = CRM_Core_Config::domainID(); | |
217 | ||
218 | $dao = new CRM_Core_DAO_Job(); | |
219 | ||
353ffa53 TO |
220 | $dao->id = $this->_id; |
221 | $dao->domain_id = $domainID; | |
6a488035 | 222 | $dao->run_frequency = $values['run_frequency']; |
353ffa53 TO |
223 | $dao->parameters = $values['parameters']; |
224 | $dao->name = $values['name']; | |
225 | $dao->api_entity = $values['api_entity']; | |
226 | $dao->api_action = $values['api_action']; | |
227 | $dao->description = $values['description']; | |
228 | $dao->is_active = CRM_Utils_Array::value('is_active', $values, 0); | |
6a488035 | 229 | |
e8f61813 | 230 | // CRM-17686 |
9ee4786b | 231 | $ts = strtotime($values['scheduled_run_date']); |
e8f61813 DRJ |
232 | // if a date/time is supplied and not in the past, then set the next scheduled run... |
233 | if ($ts > time()) { | |
d7bace22 | 234 | $dao->scheduled_run_date = CRM_Utils_Date::currentDBDate($ts); |
e8f61813 DRJ |
235 | // warn about monthly/quarterly scheduling, if applicable |
236 | if (($dao->run_frequency == 'Monthly') || ($dao->run_frequency == 'Quarter')) { | |
237 | $info = getdate($ts); | |
238 | if ($info['mday'] > 28) { | |
239 | CRM_Core_Session::setStatus( | |
240 | ts('Relative month values are calculated based on the length of month(s) that they pass through. | |
9ee4786b | 241 | The result will land on the same day of the month except for days 29-31 when the target month contains fewer days than the previous month. |
d7bace22 | 242 | For example, if a job is scheduled to run on August 31st, the following invocation will occur on October 1st, and then the 1st of every month thereafter. |
e8f61813 | 243 | To avoid this issue, please schedule Monthly and Quarterly jobs to run within the first 28 days of the month.'), |
be2fb01f | 244 | ts('Warning'), 'info', ['expires' => 0]); |
e8f61813 DRJ |
245 | } |
246 | } | |
247 | } | |
248 | // ...otherwise, if this isn't a new scheduled job, clear the next scheduled run | |
9ee4786b | 249 | elseif ($dao->id) { |
be2fb01f | 250 | $job = new CRM_Core_ScheduledJob(['id' => $dao->id]); |
d7bace22 | 251 | $job->clearScheduledRunDate(); |
e8f61813 DRJ |
252 | } |
253 | ||
6a488035 | 254 | $dao->save(); |
f813f78e | 255 | |
6a488035 TO |
256 | // CRM-11143 - Give warning message if update_greetings is Enabled (is_active) since it generally should not be run automatically via execute action or runjobs url. |
257 | if ($values['api_action'] == 'update_greeting' && CRM_Utils_Array::value('is_active', $values) == 1) { | |
d05f3550 | 258 | $docLink = CRM_Utils_System::docURL2("user/initial-set-up/scheduled-jobs/#job_update_greeting"); |
be2fb01f | 259 | $msg = ts('The update greeting job can be very resource intensive and is typically not necessary to run on a regular basis. If you do choose to enable the job, we recommend you do not run it with the force=1 option, which would rebuild greetings on all records. Leaving that option absent, or setting it to force=0, will only rebuild greetings for contacts that do not currently have a value stored. %1', [1 => $docLink]); |
6a488035 TO |
260 | CRM_Core_Session::setStatus($msg, ts('Warning: Update Greeting job enabled'), 'alert'); |
261 | } | |
262 | ||
6a488035 | 263 | } |
96025800 | 264 | |
d71d4aae SL |
265 | /** |
266 | * Get the API action aka Job Name for this scheduled job | |
267 | * @param int $id - Id of the stored Job | |
268 | * | |
269 | * @return string | |
270 | */ | |
271 | private static function getJobName($id) { | |
272 | $entity = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Job', $id, 'api_entity'); | |
273 | $action = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Job', $id, 'api_action'); | |
274 | $name = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Job', $id, 'name'); | |
275 | return $name . ' (' . $entity . '.' . $action . ')'; | |
276 | } | |
277 | ||
6a488035 | 278 | } |