3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
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 |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
19 * Class for configuring jobs.
21 class CRM_Admin_Form_Job
extends CRM_Admin_Form
{
27 public $submitOnce = TRUE;
29 public function preProcess() {
34 $this->setTitle(ts('Manage - Scheduled Jobs'));
37 $refreshURL = CRM_Utils_System
::url('civicrm/admin/job',
38 "reset=1&action=update&id={$this->_id}",
43 $refreshURL = CRM_Utils_System
::url('civicrm/admin/job',
49 $this->assign('refreshURL', $refreshURL);
53 * Build the form object.
57 public function buildQuickForm($check = FALSE) {
58 parent
::buildQuickForm();
60 if ($this->_action
& CRM_Core_Action
::DELETE
) {
64 if ($this->_action
& CRM_Core_Action
::VIEW
) {
65 $this->assign('jobName', self
::getJobName($this->_id
));
69 'name' => ts('Execute'),
74 'name' => ts('Cancel'),
80 $attributes = CRM_Core_DAO
::getAttribute('CRM_Core_DAO_Job');
82 $this->add('text', 'name', ts('Name'),
83 $attributes['name'], TRUE
86 $this->addRule('name', ts('Name already exists in Database.'), 'objectExists', [
91 $this->add('text', 'description', ts('Description'),
92 $attributes['description']
95 $this->add('text', 'api_entity', ts('API Call Entity'),
96 $attributes['api_entity'], TRUE
99 $this->add('text', 'api_action', ts('API Call Action'),
100 $attributes['api_action'], TRUE
103 $this->add('select', 'run_frequency', ts('Run frequency'), CRM_Core_SelectValues
::getJobFrequency());
106 $this->add('datepicker', 'scheduled_run_date', ts('Scheduled Run Date'), NULL, FALSE, ['minDate' => date('Y-m-d')]);
108 $this->add('textarea', 'parameters', ts('Command parameters'),
109 ['cols' => 50, 'rows' => 6]
112 // is this job active ?
113 $this->add('checkbox', 'is_active', ts('Is this Scheduled Job active?'));
115 $this->addFormRule(['CRM_Admin_Form_Job', 'formRule']);
122 * @throws API_Exception
124 public static function formRule($fields) {
128 require_once 'api/api.php';
130 /** @var \Civi\API\Kernel $apiKernel */
131 $apiKernel = \Civi
::service('civi_api_kernel');
132 $apiRequest = \Civi\API\Request
::create($fields['api_entity'], $fields['api_action'], ['version' => 3]);
134 $apiKernel->resolve($apiRequest);
136 catch (\Civi\API\Exception\NotImplementedException
$e) {
137 $errors['api_action'] = ts('Given API command is not defined.');
140 if (!empty($errors)) {
144 return empty($errors) ?
TRUE : $errors;
150 public function setDefaultValues() {
154 $defaults['is_active'] = $defaults['is_default'] = 1;
157 $domainID = CRM_Core_Config
::domainID();
159 $dao = new CRM_Core_DAO_Job();
160 $dao->id
= $this->_id
;
161 $dao->domain_id
= $domainID;
162 if (!$dao->find(TRUE)) {
166 CRM_Core_DAO
::storeValues($dao, $defaults);
169 if (!empty($dao->scheduled_run_date
)) {
170 $ts = strtotime($dao->scheduled_run_date
);
171 $defaults['scheduled_run_date'] = date("Y-m-d H:i:s", $ts);
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.
177 if (!empty($defaults['api_entity'])) {
178 $defaults['api_entity'] = ucfirst($defaults['api_entity']);
185 * Process the form submission.
187 public function postProcess() {
189 CRM_Utils_System
::flushCache();
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");
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
);
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");
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
);
209 $redirectUrl = CRM_Utils_System
::url('civicrm/admin/job', 'reset=1');
211 CRM_Utils_System
::redirect($redirectUrl);
215 $values = $this->controller
->exportValues($this->_name
);
216 $domainID = CRM_Core_Config
::domainID();
218 $dao = new CRM_Core_DAO_Job();
220 $dao->id
= $this->_id
;
221 $dao->domain_id
= $domainID;
222 $dao->run_frequency
= $values['run_frequency'];
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);
231 $ts = strtotime($values['scheduled_run_date']);
232 // if a date/time is supplied and not in the past, then set the next scheduled run...
234 $dao->scheduled_run_date
= CRM_Utils_Date
::currentDBDate($ts);
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.
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.
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.
243 To avoid this issue, please schedule Monthly and Quarterly jobs to run within the first 28 days of the month.'),
244 ts('Warning'), 'info', ['expires' => 0]);
248 // ...otherwise, if this isn't a new scheduled job, clear the next scheduled run
250 $job = new CRM_Core_ScheduledJob(['id' => $dao->id
]);
251 $job->clearScheduledRunDate();
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) {
258 $docLink = CRM_Utils_System
::docURL2("user/initial-set-up/scheduled-jobs/#job_update_greeting");
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]);
260 CRM_Core_Session
::setStatus($msg, ts('Warning: Update Greeting job enabled'), 'alert');
266 * Get the API action aka Job Name for this scheduled job
267 * @param int $id - Id of the stored Job
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 . ')';