[TASK] Replace Space Indent into Tab indent (CGL Cleanup)
[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 title of the scheduler task
126 *
127 * @return string
128 */
129 public function getTaskTitle() {
130 return $GLOBALS['LANG']->sL($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][get_class($this)]['title']);
131 }
132
133 /**
134 * This method returns the description of the scheduler task
135 *
136 * @return string
137 */
138 public function getTaskDescription() {
139 return $GLOBALS['LANG']->sL($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][get_class($this)]['description']);
140 }
141
142 /**
143 * This method returns the class name of the scheduler task
144 *
145 * @return string
146 */
147 public function getTaskClassName() {
148 return get_class($this);
149 }
150
151 /**
152 * This method returns the disable status of the task
153 *
154 * @return boolean TRUE if task is disabled, FALSE otherwise
155 */
156 public function isDisabled() {
157 return $this->disabled;
158 }
159
160 /**
161 * This method is used to set the disable status of the task
162 *
163 * @param boolean $flag TRUE if task should be disabled, FALSE otherwise
164 * @return void
165 */
166 public function setDisabled($flag) {
167 if ($flag) {
168 $this->disabled = TRUE;
169 } else {
170 $this->disabled = FALSE;
171 }
172 }
173
174 /**
175 * This method is used to set the timestamp corresponding to the next execution time of the task
176 *
177 * @param integer $timestamp Timestamp of next execution
178 * @return void
179 */
180 public function setExecutionTime($timestamp) {
181 $this->executionTime = intval($timestamp);
182 }
183
184 /**
185 * This method returns the timestamp corresponding to the next execution time of the task
186 *
187 * @return integer Timestamp of next execution
188 */
189 public function getExecutionTime() {
190 return $this->executionTime;
191 }
192
193 /**
194 * Sets the internal reference to the singleton instance of the Scheduler
195 *
196 * @return void
197 */
198 public function setScheduler() {
199 $this->scheduler = t3lib_div::makeInstance('tx_scheduler');
200 }
201
202 /**
203 * Unsets the internal reference to the singleton instance of the Scheduler
204 * This is done before a task is serialized, so that the scheduler instance
205 * is not saved to the database too
206 *
207 * @return void
208 */
209 public function unsetScheduler() {
210 unset($this->scheduler);
211 }
212
213 /**
214 * Registers a single execution of the task
215 *
216 * @param integer $timestamp Timestamp of the next execution
217 */
218 public function registerSingleExecution($timestamp) {
219 /** @var $execution tx_scheduler_Execution */
220 $execution = t3lib_div::makeInstance('tx_scheduler_Execution');
221 $execution->setStart($timestamp);
222 $execution->setInterval(0);
223 $execution->setEnd($timestamp);
224 $execution->setCronCmd('');
225 $execution->setMultiple(0);
226 $execution->setIsNewSingleExecution(TRUE);
227 // Replace existing execution object
228 $this->execution = $execution;
229 }
230
231 /**
232 * Registers a recurring execution of the task
233 *
234 * @param integer $start The first date/time where this execution should occur (timestamp)
235 * @param string $interval Execution interval in seconds
236 * @param integer $end The last date/time where this execution should occur (timestamp)
237 * @param boolean $multiple Set to FALSE if multiple executions of this task are not permitted in parallel
238 * @param string $cron_cmd Used like in crontab (minute hour day month weekday)
239 * @return void
240 */
241 public function registerRecurringExecution($start, $interval, $end = 0, $multiple = FALSE, $cron_cmd = '') {
242 /** @var $execution tx_scheduler_Execution */
243 $execution = t3lib_div::makeInstance('tx_scheduler_Execution');
244 // Set general values
245 $execution->setStart($start);
246 $execution->setEnd($end);
247 $execution->setMultiple($multiple);
248
249 if (empty($cron_cmd)) {
250 // Use interval
251 $execution->setInterval($interval);
252 $execution->setCronCmd('');
253 } else {
254 // Use cron syntax
255 $execution->setInterval(0);
256 $execution->setCronCmd($cron_cmd);
257 }
258 // Replace existing execution object
259 $this->execution = $execution;
260 }
261
262 /**
263 * Sets the internal execution object
264 *
265 * @param tx_scheduler_Execution $execution The execution to add
266 */
267 public function setExecution(tx_scheduler_Execution $execution) {
268 $this->execution = $execution;
269 }
270
271 /**
272 * Returns the execution object
273 *
274 * @return tx_scheduler_Execution The internal execution object
275 */
276 public function getExecution() {
277 return $this->execution;
278 }
279
280 /**
281 * Returns the timestamp for next due execution of the task
282 *
283 * @return integer Date and time of the next execution as a timestamp
284 */
285 public function getNextDueExecution() {
286
287 // NOTE: this call may throw an exception, but we let it bubble up
288 return $this->execution->getNextExecution();
289 }
290
291 /**
292 * Returns TRUE if several runs of the task are allowed concurrently
293 *
294 * @return boolean TRUE if concurrent executions are allowed, FALSE otherwise
295 */
296 public function areMultipleExecutionsAllowed() {
297 return $this->execution->getMultiple();
298 }
299
300 /**
301 * Returns TRUE if an instance of the task is already running
302 *
303 * @return boolean TRUE if an instance is already running, FALSE otherwise
304 */
305 public function isExecutionRunning() {
306 $isRunning = FALSE;
307
308 $queryArr = array(
309 'SELECT' => 'serialized_executions',
310 'FROM' => 'tx_scheduler_task',
311 'WHERE' => 'uid = ' . intval($this->taskUid),
312 'LIMIT' => 1
313 );
314 $res = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryArr);
315
316 if (($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
317 if (strlen($row['serialized_executions']) > 0) {
318 $isRunning = TRUE;
319 }
320 }
321 $GLOBALS['TYPO3_DB']->sql_free_result($res);
322
323 return $isRunning;
324 }
325
326 /**
327 * This method adds current execution to the execution list
328 * It also logs the execution time and mode
329 *
330 * @return integer Execution id
331 */
332 public function markExecution() {
333 $queryArr = array(
334 'SELECT' => 'serialized_executions',
335 'FROM' => 'tx_scheduler_task',
336 'WHERE' => 'uid = ' . intval($this->taskUid),
337 'LIMIT' => 1
338 );
339 $res = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryArr);
340
341 $runningExecutions = array();
342 if (($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
343 if (strlen($row['serialized_executions']) > 0) {
344 $runningExecutions = unserialize($row['serialized_executions']);
345 }
346 }
347 $GLOBALS['TYPO3_DB']->sql_free_result($res);
348
349 // Count the number of existing executions and use that number as a key
350 // (we need to know that number, because it is returned at the end of the method)
351 $numExecutions = count($runningExecutions);
352 $runningExecutions[$numExecutions] = time();
353
354 // Define the context in which the script is running
355 $context = 'BE';
356 if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI) {
357 $context = 'CLI';
358 }
359
360 $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
361 'tx_scheduler_task',
362 'uid = ' . intval($this->taskUid),
363 array(
364 'serialized_executions' => serialize($runningExecutions),
365 'lastexecution_time' => time(),
366 'lastexecution_context' => $context
367 )
368 );
369
370 return $numExecutions;
371 }
372
373 /**
374 * Removes given execution from list
375 *
376 * @param integer $executionID Id of the execution to remove.
377 * @param Exception $failure An exception to signal a failed execution
378 * @return void
379 */
380 public function unmarkExecution($executionID, Exception $failure = NULL) {
381 // Get the executions for the task
382 $queryArr = array(
383 'SELECT' => 'serialized_executions',
384 'FROM' => 'tx_scheduler_task',
385 'WHERE' => 'uid = ' . intval($this->taskUid),
386 'LIMIT' => 1
387 );
388
389 $res = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryArr);
390 if (($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
391 if (strlen($row['serialized_executions']) > 0) {
392 $runningExecutions = unserialize($row['serialized_executions']);
393 // Remove the selected execution
394 unset($runningExecutions[$executionID]);
395
396 if (count($runningExecutions) > 0) {
397 // Re-serialize the updated executions list (if necessary)
398 $runningExecutionsSerialized = serialize($runningExecutions);
399 } else {
400 $runningExecutionsSerialized = '';
401 }
402
403 if ($failure instanceof Exception) {
404 // Log failed execution
405 $logMessage = 'Task failed to execute successfully. Class: '
406 . get_class($this) . ', UID: '
407 . $this->taskUid . '. '
408 . $failure->getMessage();
409 $this->scheduler->log($logMessage, 1, $failure->getCode());
410
411 $failure = serialize($failure);
412 } else {
413 $failure = '';
414 }
415
416 // Save the updated executions list
417 $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
418 'tx_scheduler_task',
419 'uid = ' . intval($this->taskUid),
420 array(
421 'serialized_executions' => $runningExecutionsSerialized,
422 'lastexecution_failure' => $failure
423 )
424 );
425 }
426 }
427 $GLOBALS['TYPO3_DB']->sql_free_result($res);
428 }
429
430 /**
431 * Clears all marked executions
432 *
433 * @return boolean TRUE if the clearing succeeded, FALSE otherwise
434 */
435 public function unmarkAllExecutions() {
436 // Set the serialized executions field to empty
437 $result = $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
438 'tx_scheduler_task',
439 'uid = ' . intval($this->taskUid),
440 array(
441 'serialized_executions' => ''
442 )
443 );
444 return $result;
445 }
446
447 /**
448 * Saves the details of the task to the database.
449 *
450 * @return bool
451 */
452 public function save() {
453 return $this->scheduler->saveTask($this);
454 }
455
456 /**
457 * Stops the task, by replacing the execution object by an empty one
458 * NOTE: the task still needs to be saved after that
459 *
460 * @return void
461 */
462 public function stop() {
463 $this->execution = t3lib_div::makeInstance('tx_scheduler_Execution');
464 }
465
466 /**
467 * Removes the task totally from the system.
468 *
469 * @return void
470 */
471 public function remove() {
472 $this->scheduler->removeTask($this);
473 }
474 }
475 ?>