2 /***************************************************************
5 * (c) 2005 Christian Jul Jensen (julle@typo3.org)
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.
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
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.
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
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
31 * @author Francois Suter <francois@typo3.org>
32 * @author Christian Jul Jensen <julle@typo3.org>
35 * @subpackage tx_scheduler
37 * $Id: class.tx_scheduler_task.php 1262 2009-09-15 21:04:22Z francois $
39 abstract class tx_scheduler_Task
{
42 * Reference to a scheduler object
49 * The unique id of the task used to identify it in the database
56 * Disable flag, true if task is disabled, false otherwise
60 protected $disabled = false;
63 * The execution object related to the task
65 * @var tx_scheduler_Execution
70 * This variable contains the time of next execution of the task
74 protected $executionTime = 0;
79 public function __construct() {
80 $this->setScheduler();
81 $this->execution
= t3lib_div
::makeInstance('tx_scheduler_Execution');
85 * This is the main method that is called when a task is executed
86 * It MUST be implemented by all classes inheriting from this one
87 * Note that there is no error handling, errors and failures are expected
88 * to be handled and logged by the client implementations.
89 * Should return true on successful execution, false on error.
91 * @return boolean Returns true on successful execution, false on error
93 abstract public function execute();
96 * This method is designed to return some additional information about the task,
97 * that may help to set it apart from other tasks from the same class
98 * This additional information is used - for example - in the Scheduler's BE module
99 * This method should be implemented in most task classes
101 * @return string Information to display
103 public function getAdditionalInformation() {
108 * This method is used to set the unique id of the task
110 * @param integer $id: primary key (from the database record) of the scheduled task
113 public function setTaskUid($id) {
114 $this->taskUid
= intval($id);
118 * This method returns the unique id of the task
120 * @return integer The id of the task
122 public function getTaskUid() {
123 return $this->taskUid
;
127 * This method returns the disable status of the task
129 * @return boolean True if task is disabled, false otherwise
131 public function isDisabled() {
132 return $this->disabled
;
136 * This method is used to set the disable status of the task
138 * @param boolean $flag: true if task should be disabled, false otherwise
141 public function setDisabled($flag) {
143 $this->disabled
= true;
145 $this->disabled
= false;
150 * This method is used to set the timestamp corresponding to the next execution time of the task
152 * @param integer $timestamp: timestamp of next execution
155 public function setExecutionTime($timestamp) {
156 $this->executionTime
= intval($timestamp);
160 * This method returns the timestamp corresponding to the next execution time of the task
161 * @return integer Timestamp of next execution
163 public function getExecutionTime() {
164 return $this->executionTime
;
168 * Sets the internal reference to the singleton instance of the Scheduler
172 public function setScheduler() {
173 $this->scheduler
= t3lib_div
::makeInstance('tx_scheduler');
177 * Unsets the internal reference to the singleton instance of the Scheduler
178 * This is done before a task is serialized, so that the scheduler instance
179 * is not saved to the database too
183 public function unsetScheduler() {
184 unset($this->scheduler
);
188 * Registers a single execution of the task
190 * @param integer $timestamp: Timestamp of the next execution
192 public function registerSingleExecution($timestamp) {
193 $execution = t3lib_div
::makeInstance('tx_scheduler_Execution');
194 $execution->setStart($timestamp);
195 $execution->setInterval(0);
196 $execution->setEnd($timestamp);
197 $execution->setCronCmd('');
198 $execution->setMultiple(0);
199 $execution->setIsNewSingleExecution(TRUE);
200 // Replace existing execution object
201 $this->execution
= $execution;
205 * Registers a reccuring excecution of the task
207 * @param integer $start: the first date/time where this execution should occur (timestamp)
208 * @param string $interval: execution interval in seconds
209 * @param integer $end: the last date/time where this execution should occur (timestamp)
210 * @param boolean $multiple: set to false if multiple executions of this task are not permitted in parallel
211 * @param string $croncmd: used like in crontab (minute hour day month weekday)
214 public function registerRecurringExecution($start, $interval, $end = 0, $multiple = false, $cron_cmd = '') {
215 $execution = t3lib_div
::makeInstance('tx_scheduler_Execution');
216 // Set general values
217 $execution->setStart($start);
218 $execution->setEnd($end);
219 $execution->setMultiple($multiple);
221 if (empty($cron_cmd)) {
223 $execution->setInterval($interval);
224 $execution->setCronCmd('');
227 $execution->setInterval(0);
228 $execution->setCronCmd($cron_cmd);
230 // Replace existing execution object
231 $this->execution
= $execution;
235 * Sets the internal execution object
237 * @param tx_scheduler_Execution $execution: the execution to add
239 public function setExecution(tx_scheduler_Execution
$execution) {
240 $this->execution
= $execution;
244 * Returns the execution object
246 * @return tx_scheduler_Execution The internal execution object
248 public function getExecution() {
249 return $this->execution
;
253 * Returns the timestamp for next due execution of the task
255 * @return integer Date and time of the next execution as a timestamp
257 public function getNextDueExecution() {
259 // NOTE: this call may throw an exception, but we let it bubble up
260 return $this->execution
->getNextExecution();
264 * Returns true if several runs of the task are allowed concurrently
266 * @return boolean True if concurrent executions are allowed, false otherwise
268 public function areMultipleExecutionsAllowed() {
269 return $this->execution
->getMultiple();
273 * Returns true if an instance of the task is already running
275 * @return boolean True if an instance is already running, false otherwise
277 public function isExecutionRunning() {
281 'SELECT' => 'serialized_executions',
282 'FROM' => 'tx_scheduler_task',
283 'WHERE' => 'uid = ' . intval($this->taskUid
),
286 $res = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryArr);
288 if (($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
289 if (strlen($row['serialized_executions']) > 0) {
293 $GLOBALS['TYPO3_DB']->sql_free_result($res);
299 * This method adds current execution to the execution list
300 * It also logs the execution time and mode
302 * @return integer Execution id
304 public function markExecution() {
306 'SELECT' => 'serialized_executions',
307 'FROM' => 'tx_scheduler_task',
308 'WHERE' => 'uid = ' . intval($this->taskUid
),
311 $res = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryArr);
313 $runningExecutions = array();
314 if (($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
315 if (strlen($row['serialized_executions']) > 0) {
316 $runningExecutions = unserialize($row['serialized_executions']);
319 $GLOBALS['TYPO3_DB']->sql_free_result($res);
321 // Count the number of existing executions and use that number as a key
322 // (we need to know that number, because it is returned at the end of the method)
323 $numExecutions = count($runningExecutions);
324 $runningExecutions[$numExecutions] = time();
326 // Define the context in which the script is running
328 if (defined('TYPO3_cliMode') && TYPO3_cliMode
) {
332 $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
334 'uid = ' . intval($this->taskUid
),
336 'serialized_executions' => serialize($runningExecutions),
337 'lastexecution_time' => time(),
338 'lastexecution_context' => $context
342 return $numExecutions;
346 * Removes given execution from list
348 * @param integer Id of the execution to remove.
349 * @param Exception An exception to signal a failed execution
352 public function unmarkExecution($executionID, Exception
$failure = null) {
353 // Get the executions for the task
355 'SELECT' => 'serialized_executions',
356 'FROM' => 'tx_scheduler_task',
357 'WHERE' => 'uid = ' . intval($this->taskUid
),
361 $res = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryArr);
362 if (($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
363 if (strlen($row['serialized_executions']) > 0) {
364 $runningExecutions = unserialize($row['serialized_executions']);
365 // Remove the selected execution
366 unset($runningExecutions[$executionID]);
368 if (count($runningExecutions) > 0) {
369 // Re-serialize the updated executions list (if necessary)
370 $runningExecutionsSerialized = serialize($runningExecutions);
372 $runningExecutionsSerialized = '';
375 if ($failure instanceof Exception
) {
376 // Log failed execution
377 $logMessage = 'Task failed to execute successfully. Class: '
378 . get_class($this) . ', UID: '
379 . $this->taskUid
. '. '
380 . $failure->getMessage();
381 $this->scheduler
->log($logMessage, 1, $failure->getCode());
383 $failure = serialize($failure);
388 // Save the updated executions list
389 $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
391 'uid = ' . intval($this->taskUid
),
393 'serialized_executions' => $runningExecutionsSerialized,
394 'lastexecution_failure' => $failure
399 $GLOBALS['TYPO3_DB']->sql_free_result($res);
403 * Clears all marked executions
405 * @return boolean True if the clearing succeeded, false otherwise
407 public function unmarkAllExecutions() {
408 // Set the serialized executions field to empty
409 $result = $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
411 'uid = ' . intval($this->taskUid
),
413 'serialized_executions' => ''
420 * Saves the details of the task to the database.
424 public function save() {
425 return $this->scheduler
->saveTask($this);
429 * Stops the task, by replacing the execution object by an empty one
430 * NOTE: the task still needs to be saved after that
434 public function stop() {
435 $this->execution
= t3lib_div
::makeInstance('tx_scheduler_Execution');
439 * Removes the task totally from the system.
443 public function remove() {
444 $this->scheduler
->removeTask($this);
448 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE
]['XCLASS']['ext/scheduler/class.tx_scheduler_task.php']) {
449 include_once($TYPO3_CONF_VARS[TYPO3_MODE
]['XCLASS']['ext/scheduler/class.tx_scheduler_task.php']);