TYPO3 API  SVNRelease
class.tx_scheduler_task.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2005 Christian Jul Jensen (julle@typo3.org)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *
00017 *  This script is distributed in the hope that it will be useful,
00018 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 *  GNU General Public License for more details.
00021 *
00022 *  This copyright notice MUST APPEAR in all copies of the script!
00023 ***************************************************************/
00024 
00025 
00026 /**
00027  * This is the base class for all Scheduler tasks
00028  * It's an abstract class, not designed to be instantiated directly
00029  * All Scheduler tasks should inherit from this class
00030  *
00031  * @author  François Suter <francois@typo3.org>
00032  * @author  Christian Jul Jensen <julle@typo3.org>
00033  *
00034  * @package     TYPO3
00035  * @subpackage  tx_scheduler
00036  *
00037  * $Id: class.tx_scheduler_task.php 9758 2010-12-05 11:25:36Z stephenking $
00038  */
00039 abstract class tx_scheduler_Task {
00040 
00041     /**
00042      * Reference to a scheduler object
00043      *
00044      * @var tx_scheduler
00045      */
00046     protected $scheduler;
00047 
00048     /**
00049      * The unique id of the task used to identify it in the database
00050      *
00051      * @var int
00052      */
00053     protected $taskUid;
00054 
00055     /**
00056      * Disable flag, true if task is disabled, false otherwise
00057      *
00058      * @var boolean
00059      */
00060     protected $disabled = false;
00061 
00062     /**
00063      * The execution object related to the task
00064      *
00065      * @var tx_scheduler_Execution
00066      */
00067     protected $execution;
00068 
00069     /**
00070      * This variable contains the time of next execution of the task
00071      *
00072      * @var timestamp
00073      */
00074     protected $executionTime = 0;
00075 
00076     /**
00077      * Constructor
00078      */
00079     public function __construct() {
00080         $this->setScheduler();
00081         $this->execution = t3lib_div::makeInstance('tx_scheduler_Execution');
00082     }
00083 
00084     /**
00085      * This is the main method that is called when a task is executed
00086      * It MUST be implemented by all classes inheriting from this one
00087      * Note that there is no error handling, errors and failures are expected
00088      * to be handled and logged by the client implementations.
00089      * Should return true on successful execution, false on error.
00090      *
00091      * @return boolean  Returns true on successful execution, false on error
00092      */
00093     abstract public function execute();
00094 
00095     /**
00096      * This method is designed to return some additional information about the task,
00097      * that may help to set it apart from other tasks from the same class
00098      * This additional information is used - for example - in the Scheduler's BE module
00099      * This method should be implemented in most task classes
00100      *
00101      * @return  string  Information to display
00102      */
00103     public function getAdditionalInformation() {
00104         return '';
00105     }
00106 
00107     /**
00108      * This method is used to set the unique id of the task
00109      *
00110      * @param   integer $id: primary key (from the database record) of the scheduled task
00111      * @return  void
00112      */
00113     public function setTaskUid($id) {
00114         $this->taskUid = intval($id);
00115     }
00116 
00117     /**
00118      * This method returns the unique id of the task
00119      *
00120      * @return  integer     The id of the task
00121      */
00122     public function getTaskUid() {
00123         return $this->taskUid;
00124     }
00125 
00126     /**
00127      * This method returns the disable status of the task
00128      *
00129      * @return  boolean     True if task is disabled, false otherwise
00130      */
00131     public function isDisabled() {
00132         return $this->disabled;
00133     }
00134 
00135     /**
00136      * This method is used to set the disable status of the task
00137      *
00138      * @param   boolean $flag: true if task should be disabled, false otherwise
00139      * @return  void
00140      */
00141     public function setDisabled($flag) {
00142         if ($flag) {
00143             $this->disabled = true;
00144         } else {
00145             $this->disabled = false;
00146         }
00147     }
00148 
00149     /**
00150      * This method is used to set the timestamp corresponding to the next execution time of the task
00151      *
00152      * @param   integer     $timestamp: timestamp of next execution
00153      * @return  void
00154      */
00155     public function setExecutionTime($timestamp) {
00156         $this->executionTime = intval($timestamp);
00157     }
00158 
00159     /**
00160      * This method returns the timestamp corresponding to the next execution time of the task
00161      * @return  integer     Timestamp of next execution
00162      */
00163     public function getExecutionTime() {
00164         return $this->executionTime;
00165     }
00166 
00167     /**
00168      * Sets the internal reference to the singleton instance of the Scheduler
00169      *
00170      * @return void
00171      */
00172     public function setScheduler() {
00173         $this->scheduler = t3lib_div::makeInstance('tx_scheduler');
00174     }
00175 
00176     /**
00177      * Unsets the internal reference to the singleton instance of the Scheduler
00178      * This is done before a task is serialized, so that the scheduler instance
00179      * is not saved to the database too
00180      *
00181      * @return void
00182      */
00183     public function unsetScheduler() {
00184         unset($this->scheduler);
00185     }
00186 
00187     /**
00188      * Registers a single execution of the task
00189      *
00190      * @param   integer $timestamp: Timestamp of the next execution
00191      */
00192     public function registerSingleExecution($timestamp) {
00193         $execution = t3lib_div::makeInstance('tx_scheduler_Execution');
00194         $execution->setStart($timestamp);
00195         $execution->setInterval(0);
00196         $execution->setEnd($timestamp);
00197         $execution->setCronCmd('');
00198         $execution->setMultiple(0);
00199         $execution->setIsNewSingleExecution(TRUE);
00200             // Replace existing execution object
00201         $this->execution = $execution;
00202     }
00203 
00204     /**
00205      * Registers a reccuring excecution of the task
00206      *
00207      * @param   integer     $start: the first date/time where this execution should occur (timestamp)
00208      * @param   string      $interval: execution interval in seconds
00209      * @param   integer     $end: the last date/time where this execution should occur (timestamp)
00210      * @param   boolean     $multiple: set to false if multiple executions of this task are not permitted in parallel
00211      * @param   string      $croncmd: used like in crontab (minute hour day month weekday)
00212      * @return  void
00213      */
00214     public function registerRecurringExecution($start, $interval, $end = 0, $multiple = false, $cron_cmd = '') {
00215         $execution = t3lib_div::makeInstance('tx_scheduler_Execution');
00216             // Set general values
00217         $execution->setStart($start);
00218         $execution->setEnd($end);
00219         $execution->setMultiple($multiple);
00220 
00221         if (empty($cron_cmd)) {
00222                 // Use interval
00223             $execution->setInterval($interval);
00224             $execution->setCronCmd('');
00225         } else {
00226                 // Use cron syntax
00227             $execution->setInterval(0);
00228             $execution->setCronCmd($cron_cmd);
00229         }
00230             // Replace existing execution object
00231         $this->execution = $execution;
00232     }
00233 
00234     /**
00235      * Sets the internal execution object
00236      *
00237      * @param   tx_scheduler_Execution  $execution: the execution to add
00238      */
00239     public function setExecution(tx_scheduler_Execution $execution) {
00240         $this->execution = $execution;
00241     }
00242 
00243     /**
00244      * Returns the execution object
00245      *
00246      * @return  tx_scheduler_Execution  The internal execution object
00247      */
00248     public function getExecution() {
00249         return $this->execution;
00250     }
00251 
00252     /**
00253      * Returns the timestamp for next due execution of the task
00254      *
00255      * @return  integer     Date and time of the next execution as a timestamp
00256      */
00257     public function getNextDueExecution() {
00258 
00259             // NOTE: this call may throw an exception, but we let it bubble up
00260         return $this->execution->getNextExecution();
00261     }
00262 
00263     /**
00264      * Returns true if several runs of the task are allowed concurrently
00265      *
00266      * @return  boolean     True if concurrent executions are allowed, false otherwise
00267      */
00268     public function areMultipleExecutionsAllowed() {
00269         return $this->execution->getMultiple();
00270     }
00271 
00272     /**
00273      * Returns true if an instance of the task is already running
00274      *
00275      * @return  boolean     True if an instance is already running, false otherwise
00276      */
00277     public function isExecutionRunning() {
00278         $isRunning = false;
00279 
00280         $queryArr = array(
00281             'SELECT' => 'serialized_executions',
00282             'FROM'   => 'tx_scheduler_task',
00283             'WHERE'  => 'uid = ' . intval($this->taskUid),
00284             'LIMIT'  => 1
00285         );
00286         $res = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryArr);
00287 
00288         if (($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
00289             if (strlen($row['serialized_executions']) > 0) {
00290                 $isRunning = true;
00291             }
00292         }
00293         $GLOBALS['TYPO3_DB']->sql_free_result($res);
00294 
00295         return $isRunning;
00296     }
00297 
00298     /**
00299      * This method adds current execution to the execution list
00300      * It also logs the execution time and mode
00301      *
00302      * @return  integer     Execution id
00303      */
00304     public function markExecution() {
00305         $queryArr = array(
00306             'SELECT' => 'serialized_executions',
00307             'FROM'   => 'tx_scheduler_task',
00308             'WHERE'  => 'uid = ' . intval($this->taskUid),
00309             'LIMIT'  => 1
00310         );
00311         $res = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryArr);
00312 
00313         $runningExecutions = array();
00314         if (($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
00315             if (strlen($row['serialized_executions']) > 0) {
00316                 $runningExecutions = unserialize($row['serialized_executions']);
00317             }
00318         }
00319         $GLOBALS['TYPO3_DB']->sql_free_result($res);
00320 
00321             // Count the number of existing executions and use that number as a key
00322             // (we need to know that number, because it is returned at the end of the method)
00323         $numExecutions = count($runningExecutions);
00324         $runningExecutions[$numExecutions] = time();
00325 
00326             // Define the context in which the script is running
00327         $context = 'BE';
00328         if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI) {
00329             $context = 'CLI';
00330         }
00331 
00332         $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
00333             'tx_scheduler_task',
00334             'uid = ' . intval($this->taskUid),
00335             array(
00336                 'serialized_executions' => serialize($runningExecutions),
00337                 'lastexecution_time'    => time(),
00338                 'lastexecution_context' => $context
00339             )
00340         );
00341 
00342         return $numExecutions;
00343     }
00344 
00345     /**
00346      * Removes given execution from list
00347      *
00348      * @param   integer     Id of the execution to remove.
00349      * @param   Exception   An exception to signal a failed execution
00350      * @return  void
00351      */
00352     public function unmarkExecution($executionID, Exception $failure = null) {
00353             // Get the executions for the task
00354         $queryArr = array(
00355             'SELECT' => 'serialized_executions',
00356             'FROM'   => 'tx_scheduler_task',
00357             'WHERE'  => 'uid = ' . intval($this->taskUid),
00358             'LIMIT'  => 1
00359         );
00360 
00361         $res = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryArr);
00362         if (($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
00363             if (strlen($row['serialized_executions']) > 0) {
00364                 $runningExecutions = unserialize($row['serialized_executions']);
00365                     // Remove the selected execution
00366                 unset($runningExecutions[$executionID]);
00367 
00368                 if (count($runningExecutions) > 0) {
00369                         // Re-serialize the updated executions list (if necessary)
00370                     $runningExecutionsSerialized = serialize($runningExecutions);
00371                 } else {
00372                     $runningExecutionsSerialized = '';
00373                 }
00374 
00375                 if ($failure instanceof Exception) {
00376                         // Log failed execution
00377                     $logMessage = 'Task failed to execute successfully. Class: '
00378                             . get_class($this) . ', UID: '
00379                             . $this->taskUid . '. '
00380                             . $failure->getMessage();
00381                     $this->scheduler->log($logMessage, 1, $failure->getCode());
00382 
00383                     $failure = serialize($failure);
00384                 } else {
00385                     $failure = '';
00386                 }
00387 
00388                     // Save the updated executions list
00389                 $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
00390                     'tx_scheduler_task',
00391                     'uid = ' . intval($this->taskUid),
00392                     array(
00393                         'serialized_executions' => $runningExecutionsSerialized,
00394                         'lastexecution_failure' => $failure
00395                     )
00396                 );
00397             }
00398         }
00399         $GLOBALS['TYPO3_DB']->sql_free_result($res);
00400     }
00401 
00402     /**
00403      * Clears all marked executions
00404      *
00405      * @return  boolean     True if the clearing succeeded, false otherwise
00406      */
00407     public function unmarkAllExecutions() {
00408             // Set the serialized executions field to empty
00409         $result = $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
00410             'tx_scheduler_task',
00411             'uid = ' . intval($this->taskUid),
00412             array(
00413                 'serialized_executions' => ''
00414             )
00415         );
00416         return $result;
00417     }
00418 
00419     /**
00420      * Saves the details of the task to the database.
00421      *
00422      * @return bool
00423      */
00424     public function save() {
00425         return $this->scheduler->saveTask($this);
00426     }
00427 
00428     /**
00429      * Stops the task, by replacing the execution object by an empty one
00430      * NOTE: the task still needs to be saved after that
00431      *
00432      * @return  void
00433      */
00434     public function stop() {
00435         $this->execution = t3lib_div::makeInstance('tx_scheduler_Execution');
00436     }
00437 
00438     /**
00439      * Removes the task totally from the system.
00440      *
00441      * @return  void
00442      */
00443     public function remove() {
00444         $this->scheduler->removeTask($this);
00445     }
00446 }
00447 
00448 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/scheduler/class.tx_scheduler_task.php'])) {
00449     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/scheduler/class.tx_scheduler_task.php']);
00450 }
00451 
00452 
00453 ?>