Set version to 5.51.alpha1
[civicrm-core.git] / CRM / Admin / Form / Job.php
CommitLineData
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 */
21class 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}