[BUGFIX] Replace deprecated unit test method
[Packages/TYPO3.CMS.git] / typo3 / sysext / scheduler / class.tx_scheduler_task.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2005 Christian Jul Jensen (julle@typo3.org)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24
25
26 /**
27 * This is the base class for all Scheduler tasks
28 * It's an abstract class, not designed to be instantiated directly
29 * All Scheduler tasks should inherit from this class
30 *
31 * @author Fran├žois Suter <francois@typo3.org>
32 * @author Christian Jul Jensen <julle@typo3.org>
33 *
34 * @package TYPO3
35 * @subpackage tx_scheduler
36 */
37 abstract class tx_scheduler_Task {
38
39 /**
40 * Reference to a scheduler object
41 *
42 * @var tx_scheduler
43 */
44 protected $scheduler;
45
46 /**
47 * The unique id of the task used to identify it in the database
48 *
49 * @var int
50 */
51 protected $taskUid;
52
53 /**
54 * Disable flag, TRUE if task is disabled, FALSE otherwise
55 *
56 * @var boolean
57 */
58 protected $disabled = FALSE;
59
60 /**
61 * The execution object related to the task
62 *
63 * @var tx_scheduler_Execution
64 */
65 protected $execution;
66
67 /**
68 * This variable contains the time of next execution of the task
69 *
70 * @var timestamp
71 */
72 protected $executionTime = 0;
73
74 /**
75 * Constructor
76 */
77 public function __construct() {
78 $this->setScheduler();
79 $this->execution = t3lib_div::makeInstance('tx_scheduler_Execution');
80 }
81
82 /**
83 * This is the main method that is called when a task is executed
84 * It MUST be implemented by all classes inheriting from this one
85 * Note that there is no error handling, errors and failures are expected
86 * to be handled and logged by the client implementations.
87 * Should return TRUE on successful execution, FALSE on error.
88 *
89 * @return boolean Returns TRUE on successful execution, FALSE on error
90 */
91 abstract public function execute();
92
93 /**
94 * This method is designed to return some additional information about the task,
95 * that may help to set it apart from other tasks from the same class
96 * This additional information is used - for example - in the Scheduler's BE module
97 * This method should be implemented in most task classes
98 *
99 * @return string Information to display
100 */
101 public function getAdditionalInformation() {
102 return '';
103 }
104
105 /**
106 * This method is used to set the unique id of the task
107 *
108 * @param integer $id: primary key (from the database record) of the scheduled task
109 * @return void
110 */
111 public function setTaskUid($id) {
112 $this->taskUid = intval($id);
113 }
114
115 /**
116 * This method returns the unique id of the task
117 *
118 * @return integer The id of the task
119 */
120 public function getTaskUid() {
121 return $this->taskUid;
122 }
123
124 /**
125 * This method returns the disable status of the task
126 *
127 * @return boolean TRUE if task is disabled, FALSE otherwise
128 */
129 public function isDisabled() {
130 return $this->disabled;
131 }
132
133 /**
134 * This method is used to set the disable status of the task
135 *
136 * @param boolean $flag: TRUE if task should be disabled, FALSE otherwise
137 * @return void
138 */
139 public function setDisabled($flag) {
140 if ($flag) {
141 $this->disabled = TRUE;
142 } else {
143 $this->disabled = FALSE;
144 }
145 }
146
147 /**
148 * This method is used to set the timestamp corresponding to the next execution time of the task
149 *
150 * @param integer $timestamp: timestamp of next execution
151 * @return void
152 */
153 public function setExecutionTime($timestamp) {
154 $this->executionTime = intval($timestamp);
155 }
156
157 /**
158 * This method returns the timestamp corresponding to the next execution time of the task
159 * @return integer Timestamp of next execution
160 */
161 public function getExecutionTime() {
162 return $this->executionTime;
163 }
164
165 /**
166 * Sets the internal reference to the singleton instance of the Scheduler
167 *
168 * @return void
169 */
170 public function setScheduler() {
171 $this->scheduler = t3lib_div::makeInstance('tx_scheduler');
172 }
173
174 /**
175 * Unsets the internal reference to the singleton instance of the Scheduler
176 * This is done before a task is serialized, so that the scheduler instance
177 * is not saved to the database too
178 *
179 * @return void
180 */
181 public function unsetScheduler() {
182 unset($this->scheduler);
183 }
184
185 /**
186 * Registers a single execution of the task
187 *
188 * @param integer $timestamp: Timestamp of the next execution
189 */
190 public function registerSingleExecution($timestamp) {
191 $execution = t3lib_div::makeInstance('tx_scheduler_Execution');
192 $execution->setStart($timestamp);
193 $execution->setInterval(0);
194 $execution->setEnd($timestamp);
195 $execution->setCronCmd('');
196 $execution->setMultiple(0);
197 $execution->setIsNewSingleExecution(TRUE);
198 // Replace existing execution object
199 $this->execution = $execution;
200 }
201
202 /**
203 * Registers a reccuring excecution of the task
204 *
205 * @param integer $start: the first date/time where this execution should occur (timestamp)
206 * @param string $interval: execution interval in seconds
207 * @param integer $end: the last date/time where this execution should occur (timestamp)
208 * @param boolean $multiple: set to FALSE if multiple executions of this task are not permitted in parallel
209 * @param string $croncmd: used like in crontab (minute hour day month weekday)
210 * @return void
211 */
212 public function registerRecurringExecution($start, $interval, $end = 0, $multiple = FALSE, $cron_cmd = '') {
213 $execution = t3lib_div::makeInstance('tx_scheduler_Execution');
214 // Set general values
215 $execution->setStart($start);
216 $execution->setEnd($end);
217 $execution->setMultiple($multiple);
218
219 if (empty($cron_cmd)) {
220 // Use interval
221 $execution->setInterval($interval);
222 $execution->setCronCmd('');
223 } else {
224 // Use cron syntax
225 $execution->setInterval(0);
226 $execution->setCronCmd($cron_cmd);
227 }
228 // Replace existing execution object
229 $this->execution = $execution;
230 }
231
232 /**
233 * Sets the internal execution object
234 *
235 * @param tx_scheduler_Execution $execution: the execution to add
236 */
237 public function setExecution(tx_scheduler_Execution $execution) {
238 $this->execution = $execution;
239 }
240
241 /**
242 * Returns the execution object
243 *
244 * @return tx_scheduler_Execution The internal execution object
245 */
246 public function getExecution() {
247 return $this->execution;
248 }
249
250 /**
251 * Returns the timestamp for next due execution of the task
252 *
253 * @return integer Date and time of the next execution as a timestamp
254 */
255 public function getNextDueExecution() {
256
257 // NOTE: this call may throw an exception, but we let it bubble up
258 return $this->execution->getNextExecution();
259 }
260
261 /**
262 * Returns TRUE if several runs of the task are allowed concurrently
263 *
264 * @return boolean TRUE if concurrent executions are allowed, FALSE otherwise
265 */
266 public function areMultipleExecutionsAllowed() {
267 return $this->execution->getMultiple();
268 }
269
270 /**
271 * Returns TRUE if an instance of the task is already running
272 *
273 * @return boolean TRUE if an instance is already running, FALSE otherwise
274 */
275 public function isExecutionRunning() {
276 $isRunning = FALSE;
277
278 $queryArr = array(
279 'SELECT' => 'serialized_executions',
280 'FROM' => 'tx_scheduler_task',
281 'WHERE' => 'uid = ' . intval($this->taskUid),
282 'LIMIT' => 1
283 );
284 $res = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryArr);
285
286 if (($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
287 if (strlen($row['serialized_executions']) > 0) {
288 $isRunning = TRUE;
289 }
290 }
291 $GLOBALS['TYPO3_DB']->sql_free_result($res);
292
293 return $isRunning;
294 }
295
296 /**
297 * This method adds current execution to the execution list
298 * It also logs the execution time and mode
299 *
300 * @return integer Execution id
301 */
302 public function markExecution() {
303 $queryArr = array(
304 'SELECT' => 'serialized_executions',
305 'FROM' => 'tx_scheduler_task',
306 'WHERE' => 'uid = ' . intval($this->taskUid),
307 'LIMIT' => 1
308 );
309 $res = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryArr);
310
311 $runningExecutions = array();
312 if (($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
313 if (strlen($row['serialized_executions']) > 0) {
314 $runningExecutions = unserialize($row['serialized_executions']);
315 }
316 }
317 $GLOBALS['TYPO3_DB']->sql_free_result($res);
318
319 // Count the number of existing executions and use that number as a key
320 // (we need to know that number, because it is returned at the end of the method)
321 $numExecutions = count($runningExecutions);
322 $runningExecutions[$numExecutions] = time();
323
324 // Define the context in which the script is running
325 $context = 'BE';
326 if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI) {
327 $context = 'CLI';
328 }
329
330 $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
331 'tx_scheduler_task',
332 'uid = ' . intval($this->taskUid),
333 array(
334 'serialized_executions' => serialize($runningExecutions),
335 'lastexecution_time' => time(),
336 'lastexecution_context' => $context
337 )
338 );
339
340 return $numExecutions;
341 }
342
343 /**
344 * Removes given execution from list
345 *
346 * @param integer Id of the execution to remove.
347 * @param Exception An exception to signal a failed execution
348 * @return void
349 */
350 public function unmarkExecution($executionID, Exception $failure = NULL) {
351 // Get the executions for the task
352 $queryArr = array(
353 'SELECT' => 'serialized_executions',
354 'FROM' => 'tx_scheduler_task',
355 'WHERE' => 'uid = ' . intval($this->taskUid),
356 'LIMIT' => 1
357 );
358
359 $res = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryArr);
360 if (($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
361 if (strlen($row['serialized_executions']) > 0) {
362 $runningExecutions = unserialize($row['serialized_executions']);
363 // Remove the selected execution
364 unset($runningExecutions[$executionID]);
365
366 if (count($runningExecutions) > 0) {
367 // Re-serialize the updated executions list (if necessary)
368 $runningExecutionsSerialized = serialize($runningExecutions);
369 } else {
370 $runningExecutionsSerialized = '';
371 }
372
373 if ($failure instanceof Exception) {
374 // Log failed execution
375 $logMessage = 'Task failed to execute successfully. Class: '
376 . get_class($this) . ', UID: '
377 . $this->taskUid . '. '
378 . $failure->getMessage();
379 $this->scheduler->log($logMessage, 1, $failure->getCode());
380
381 $failure = serialize($failure);
382 } else {
383 $failure = '';
384 }
385
386 // Save the updated executions list
387 $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
388 'tx_scheduler_task',
389 'uid = ' . intval($this->taskUid),
390 array(
391 'serialized_executions' => $runningExecutionsSerialized,
392 'lastexecution_failure' => $failure
393 )
394 );
395 }
396 }
397 $GLOBALS['TYPO3_DB']->sql_free_result($res);
398 }
399
400 /**
401 * Clears all marked executions
402 *
403 * @return boolean TRUE if the clearing succeeded, FALSE otherwise
404 */
405 public function unmarkAllExecutions() {
406 // Set the serialized executions field to empty
407 $result = $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
408 'tx_scheduler_task',
409 'uid = ' . intval($this->taskUid),
410 array(
411 'serialized_executions' => ''
412 )
413 );
414 return $result;
415 }
416
417 /**
418 * Saves the details of the task to the database.
419 *
420 * @return bool
421 */
422 public function save() {
423 return $this->scheduler->saveTask($this);
424 }
425
426 /**
427 * Stops the task, by replacing the execution object by an empty one
428 * NOTE: the task still needs to be saved after that
429 *
430 * @return void
431 */
432 public function stop() {
433 $this->execution = t3lib_div::makeInstance('tx_scheduler_Execution');
434 }
435
436 /**
437 * Removes the task totally from the system.
438 *
439 * @return void
440 */
441 public function remove() {
442 $this->scheduler->removeTask($this);
443 }
444 }
445
446 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/scheduler/class.tx_scheduler_task.php'])) {
447 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/scheduler/class.tx_scheduler_task.php']);
448 }
449
450
451 ?>