TYPO3 API  SVNRelease
index.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2009-2011 François Suter <francois@typo3.org>
00006 *  (c) 2005 Christian Jul Jensen <julle@typo3.org>
00007 *  All rights reserved
00008 *
00009 *  This script is part of the TYPO3 project. The TYPO3 project is
00010 *  free software; you can redistribute it and/or modify
00011 *  it under the terms of the GNU General Public License as published by
00012 *  the Free Software Foundation; either version 2 of the License, or
00013 *  (at your option) any later version.
00014 *
00015 *  The GNU General Public License can be found at
00016 *  http://www.gnu.org/copyleft/gpl.html.
00017 *
00018 *  This script is distributed in the hope that it will be useful,
00019 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00020 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021 *  GNU General Public License for more details.
00022 *
00023 *  This copyright notice MUST APPEAR in all copies of the script!
00024 ***************************************************************/
00025 
00026 require_once (t3lib_extMgm::extPath('scheduler') . 'interfaces/interface.tx_scheduler_additionalfieldprovider.php');
00027 
00028 $LANG->includeLLFile('EXT:scheduler/mod1/locallang.xml');
00029 $BE_USER->modAccess($MCONF, 1); // This checks permissions and exits if the users has no permission for entry.
00030 
00031 /**
00032  * Module 'TYPO3 Scheduler administration module' for the 'scheduler' extension.
00033  *
00034  * @author      François Suter <francois@typo3.org>
00035  * @author      Christian Jul Jensen <julle@typo3.org>
00036  * @author      Ingo Renner <ingo@typo3.org>
00037  * @package     TYPO3
00038  * @subpackage  tx_scheduler
00039  * @version     $Id: index.php 10195 2011-01-21 09:59:37Z francois $
00040  */
00041 class tx_scheduler_Module extends t3lib_SCbase {
00042 
00043     /**
00044      * Back path to typo3 main dir
00045      *
00046      * @var string      $backPath
00047      */
00048     public $backPath;
00049 
00050     /**
00051      * Array containing submitted data when editing or adding a task
00052      *
00053      * @var array       $submittedData
00054      */
00055     protected $submittedData = array();
00056 
00057     /**
00058      * Array containing all messages issued by the application logic
00059      * Contains the error's severity and the message itself
00060      *
00061      * @var array   $messages
00062      */
00063     protected $messages = array();
00064 
00065     /**
00066      * @var string  Key of the CSH file
00067      */
00068     protected $cshKey;
00069 
00070     /**
00071      *
00072      * @var tx_scheduler    Local scheduler instance
00073      */
00074     protected $scheduler;
00075 
00076     /**
00077      * Constructor
00078      *
00079      * @return  void
00080      */
00081     public function __construct() {
00082         $this->backPath = $GLOBALS['BACK_PATH'];
00083             // Set key for CSH
00084         $this->cshKey = '_MOD_' . $GLOBALS['MCONF']['name'];
00085     }
00086 
00087     /**
00088      * Initializes the backend module
00089      *
00090      * @return  void
00091      */
00092     public function init() {
00093         parent::init();
00094 
00095             // Initialize document
00096         $this->doc = t3lib_div::makeInstance('template');
00097         $this->doc->setModuleTemplate(t3lib_extMgm::extPath('scheduler') . 'mod1/mod_template.html');
00098         $this->doc->getPageRenderer()->addCssFile(t3lib_extMgm::extRelPath('scheduler') . 'res/tx_scheduler_be.css');
00099         $this->doc->backPath = $this->backPath;
00100         $this->doc->bodyTagId = 'typo3-mod-php';
00101         $this->doc->bodyTagAdditions = 'class="tx_scheduler_mod1"';
00102 
00103             // Create scheduler instance
00104         $this->scheduler = t3lib_div::makeInstance('tx_scheduler');
00105     }
00106 
00107     /**
00108      * Adds items to the ->MOD_MENU array. Used for the function menu selector.
00109      *
00110      * @return  void
00111      */
00112     public function menuConfig() {
00113         $this->MOD_MENU = array(
00114             'function' => array(
00115                 'scheduler' => $GLOBALS['LANG']->getLL('function.scheduler'),
00116                 'check'     => $GLOBALS['LANG']->getLL('function.check'),
00117                 'info'      => $GLOBALS['LANG']->getLL('function.info'),
00118             )
00119         );
00120 
00121         parent::menuConfig();
00122     }
00123 
00124     /**
00125      * Main function of the module. Write the content to $this->content
00126      *
00127      * @return  void
00128      */
00129     public function main() {
00130             // Access check!
00131             // The page will show only if user has admin rights
00132         if ($GLOBALS['BE_USER']->user['admin']) {
00133 
00134                 // Set the form
00135             $this->doc->form = '<form name="tx_scheduler_form" id="tx_scheduler_form" method="post" action="">';
00136 
00137                 // JavaScript for main function menu
00138             $this->doc->JScode = '
00139                 <script language="javascript" type="text/javascript">
00140                     script_ended = 0;
00141                     function jumpToUrl(URL) {
00142                         document.location = URL;
00143                     }
00144                 </script>
00145             ';
00146 
00147                 // Prepare main content
00148             $this->content  = $this->doc->header(
00149                 $GLOBALS['LANG']->getLL('function.' . $this->MOD_SETTINGS['function'])
00150             );
00151             $this->content .= $this->doc->spacer(5);
00152             $this->content .= $this->getModuleContent();
00153         } else {
00154                 // If no access, only display the module's title
00155             $this->content  = $this->doc->header($GLOBALS['LANG']->getLL('title'));
00156             $this->content .= $this->doc->spacer(5);
00157         }
00158 
00159             // Place content inside template
00160 
00161         $content = $this->doc->moduleBody(
00162             array(),
00163             $this->getDocHeaderButtons(),
00164             $this->getTemplateMarkers()
00165         );
00166 
00167             // Renders the module page
00168         $this->content = $this->doc->render(
00169             $GLOBALS['LANG']->getLL('title'),
00170             $content
00171         );
00172     }
00173 
00174     /**
00175      * Generate the module's content
00176      *
00177      * @return  string  HTML of the module's main content
00178      */
00179     protected function getModuleContent() {
00180         $content = '';
00181         $sectionTitle = '';
00182 
00183             // Get submitted data
00184         $this->submittedData = t3lib_div::_GPmerged('tx_scheduler');
00185 
00186             // If a save command was submitted, handle saving now
00187         if ($this->CMD == 'save') {
00188             $previousCMD = t3lib_div::_GP('previousCMD');
00189                 // First check the submitted data
00190             $result = $this->preprocessData();
00191 
00192                 // If result is ok, proceed with saving
00193             if ($result) {
00194                 $this->saveTask();
00195                     // Unset command, so that default screen gets displayed
00196                 unset($this->CMD);
00197 
00198                 // Errors occurred
00199                 // Go back to previous step
00200             } else {
00201                 $this->CMD = $previousCMD;
00202             }
00203         }
00204 
00205             // Handle chosen action
00206         switch((string)$this->MOD_SETTINGS['function']) {
00207             case 'scheduler':
00208                     // Scheduler's main screen
00209                 $content .= $this->executeTasks();
00210 
00211                     // Execute chosen action
00212                 switch ($this->CMD) {
00213                     case 'add':
00214                     case 'edit':
00215                         try {
00216                                 // Try adding or editing
00217                             $content .= $this->editTask();
00218                             $sectionTitle = $GLOBALS['LANG']->getLL('action.' . $this->CMD);
00219                         } catch (Exception $e) {
00220                                 // An exception may happen when the task to
00221                                 // edit could not be found. In this case revert
00222                                 // to displaying the list of tasks
00223                                 // It can also happend when attempting to edit a running task
00224                             $content .= $this->listTasks();
00225                         }
00226                         break;
00227                     case 'delete':
00228                         $this->deleteTask();
00229                         $content .= $this->listTasks();
00230                         break;
00231                     case 'stop':
00232                         $this->stopTask();
00233                         $content .= $this->listTasks();
00234                         break;
00235                     case 'list':
00236                     default:
00237                         $content .= $this->listTasks();
00238                         break;
00239                 }
00240                 break;
00241             case 'check':
00242                     // Setup check screen
00243                     // TODO: move check to the report module
00244                 $content .= $this->displayCheckScreen();
00245                 break;
00246             case 'info':
00247                     // Information screen
00248                 $content .= $this->displayInfoScreen();
00249                 break;
00250         }
00251 
00252             // Wrap the content in a section
00253         return $this->doc->section($sectionTitle, '<div class="tx_scheduler_mod1">' . $content . '</div>', 0, 1);
00254     }
00255 
00256     /**
00257      * This method actually prints out the module's HTML content
00258      *
00259      * @return  void
00260      */
00261     public function render() {
00262         echo $this->content;
00263     }
00264 
00265     /**
00266      * This method checks the status of the '_cli_scheduler' user
00267      * It will differentiate between a non-existing user and an existing,
00268      * but disabled user (as per enable fields)
00269      *
00270      * @return  integer     -1  if user doesn't exist
00271      *                       0  if user exists, but is disabled
00272      *                       1  if user exists and is not disabled
00273      */
00274     protected function checkSchedulerUser() {
00275         $schedulerUserStatus = -1;
00276             // Assemble base WHERE clause
00277         $where = 'username = \'_cli_scheduler\' AND admin = 0' . t3lib_BEfunc::deleteClause('be_users');
00278             // Check if user exists at all
00279         $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
00280             '1',
00281             'be_users',
00282             $where
00283         );
00284         if ($GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
00285             $schedulerUserStatus = 0;
00286                 // Check if user exists and is enabled
00287             $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
00288                 '1',
00289                 'be_users',
00290                 $where . t3lib_BEfunc::BEenableFields('be_users')
00291             );
00292             if ($GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
00293                 $schedulerUserStatus = 1;
00294             }
00295         }
00296         $GLOBALS['TYPO3_DB']->sql_free_result($res);
00297 
00298         return $schedulerUserStatus;
00299     }
00300 
00301     /**
00302      * This method creates the "cli_scheduler" BE user if it doesn't exist
00303      *
00304      * @return  void
00305      */
00306     protected function createSchedulerUser() {
00307             // Check _cli_scheduler user status
00308         $checkUser = $this->checkSchedulerUser();
00309             // Prepare default message
00310         $message = $GLOBALS['LANG']->getLL('msg.userExists');
00311         $severity = t3lib_FlashMessage::WARNING;
00312             // If the user does not exist, try creating it
00313         if ($checkUser == -1) {
00314                 // Prepare necessary data for _cli_scheduler user creation
00315             $password = md5(uniqid('scheduler', true));
00316             $data = array('be_users' => array('NEW' => array('username' => '_cli_scheduler', 'password' => $password, 'pid' => 0)));
00317                 /**
00318                  * Create an instance of TCEmain and execute user creation
00319                  *
00320                  * @var t3lib_TCEmain
00321                  */
00322             $tcemain = t3lib_div::makeInstance('t3lib_TCEmain');
00323             $tcemain->stripslashes_values = 0;
00324             $tcemain->start($data, array());
00325             $tcemain->process_datamap();
00326                 // Check if a new uid was indeed generated (i.e. a new record was created)
00327                 // (counting TCEmain errors doesn't work as some failures don't report errors)
00328             $numberOfNewIDs = count($tcemain->substNEWwithIDs);
00329             if ($numberOfNewIDs == 1) {
00330                 $message = $GLOBALS['LANG']->getLL('msg.userCreated');
00331                 $severity = t3lib_FlashMessage::OK;
00332             } else {
00333                 $message = $GLOBALS['LANG']->getLL('msg.userNotCreated');
00334                 $severity = t3lib_FlashMessage::ERROR;
00335             }
00336         }
00337         $this->addMessage($message, $severity);
00338     }
00339 
00340     /**
00341      * This method displays the result of a number of checks
00342      * on whether the Scheduler is ready to run or running properly
00343      *
00344      * @return  string  further information
00345      */
00346     protected function displayCheckScreen() {
00347         $message = '';
00348         $severity = t3lib_FlashMessage::OK;
00349 
00350             // First, check if cli_sceduler user creation was requested
00351         if ($this->CMD == 'user') {
00352             $this->createSchedulerUser();
00353         }
00354 
00355             // Start generating the content
00356         $content = $GLOBALS['LANG']->getLL('msg.schedulerSetupCheck');
00357 
00358             // Display information about last automated run, as stored in the system registry
00359             /**
00360              * @var t3lib_Registry
00361              */
00362         $registry = t3lib_div::makeInstance('t3lib_Registry');
00363         $lastRun = $registry->get('tx_scheduler', 'lastRun');
00364         if (!is_array($lastRun)) {
00365             $message = $GLOBALS['LANG']->getLL('msg.noLastRun');
00366             $severity = t3lib_FlashMessage::WARNING;
00367         } else {
00368             if (empty($lastRun['end']) || empty($lastRun['start']) || empty($lastRun['type'])) {
00369                 $message = $GLOBALS['LANG']->getLL('msg.incompleteLastRun');
00370                 $severity = t3lib_FlashMessage::WARNING;
00371             } else {
00372                 $startDate = date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'], $lastRun['start']);
00373                 $startTime = date($GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'], $lastRun['start']);
00374                 $endDate = date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'], $lastRun['end']);
00375                 $endTime = date($GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'], $lastRun['end']);
00376                 $label = 'automatically';
00377                 if ($lastRun['type'] == 'manual') {
00378                     $label = 'manually';
00379                 }
00380                 $type = $GLOBALS['LANG']->getLL('label.' . $label);
00381                 $message = sprintf($GLOBALS['LANG']->getLL('msg.lastRun'), $type, $startDate, $startTime, $endDate, $endTime);
00382                 $severity = t3lib_FlashMessage::INFO;
00383             }
00384         }
00385         $flashMessage = t3lib_div::makeInstance(
00386             't3lib_FlashMessage',
00387             $message,
00388             '',
00389             $severity
00390         );
00391         $content .= '<div class="info-block">';
00392         $content .= '<h3>' . $GLOBALS['LANG']->getLL('hdg.lastRun') . '</h3>';
00393         $content .= $flashMessage->render();
00394         $content .= '</div>';
00395 
00396             // Check CLI user
00397         $content .= '<div class="info-block">';
00398         $content .= '<h3>' . $GLOBALS['LANG']->getLL('hdg.schedulerUser') . '</h3>';
00399         $content .= '<p>' . $GLOBALS['LANG']->getLL('msg.schedulerUser') . '</p>';
00400 
00401         $checkUser = $this->checkSchedulerUser();
00402         if ($checkUser == -1) {
00403             $link = $GLOBALS['MCONF']['_'] . '&SET[function]=check&CMD=user';
00404             $message = sprintf($GLOBALS['LANG']->getLL('msg.schedulerUserMissing'), htmlspecialchars($link));
00405             $severity = t3lib_FlashMessage::ERROR;
00406         } elseif ($checkUser == 0) {
00407             $message = $GLOBALS['LANG']->getLL('msg.schedulerUserFoundButDisabled');
00408             $severity = t3lib_FlashMessage::WARNING;
00409         } else {
00410             $message = $GLOBALS['LANG']->getLL('msg.schedulerUserFound');
00411             $severity = t3lib_FlashMessage::OK;
00412         }
00413         $flashMessage = t3lib_div::makeInstance(
00414             't3lib_FlashMessage',
00415             $message,
00416             '',
00417             $severity
00418         );
00419         $content .= $flashMessage->render() . '</div>';
00420 
00421             // Check if CLI script is executable or not
00422         $script = PATH_typo3 . 'cli_dispatch.phpsh';
00423         $isExecutable = FALSE;
00424             // Skip this check if running Windows, as rights do not work the same way on this platform
00425             // (i.e. the script will always appear as *not* executable)
00426         if (TYPO3_OS === 'WIN') {
00427             $isExecutable = TRUE;
00428         } else {
00429             $isExecutable = is_executable($script);
00430         }
00431         $content .= '<div class="info-block">';
00432         $content .= '<h3>' . $GLOBALS['LANG']->getLL('hdg.cliScript') . '</h3>';
00433         $content .= '<p>' . sprintf($GLOBALS['LANG']->getLL('msg.cliScript'), $script) . '</p>';
00434 
00435         if ($isExecutable) {
00436             $message = $GLOBALS['LANG']->getLL('msg.cliScriptExecutable');
00437             $severity = t3lib_FlashMessage::OK;
00438         } else {
00439             $message = $GLOBALS['LANG']->getLL('msg.cliScriptNotExecutable');
00440             $severity = t3lib_FlashMessage::ERROR;
00441         }
00442         $flashMessage = t3lib_div::makeInstance(
00443             't3lib_FlashMessage',
00444             $message,
00445             '',
00446             $severity
00447         );
00448         $content .= $flashMessage->render() . '</div>';
00449 
00450         return $content;
00451     }
00452 
00453     /**
00454      * This method gathers information about all available task classes and displays it
00455      *
00456      * @return  string  HTML content to display
00457      */
00458     protected function displayInfoScreen() {
00459         $content = '';
00460         $registeredClasses = self::getRegisteredClasses();
00461 
00462             // No classes available, display information message
00463         if (count($registeredClasses) == 0) {
00464                 /** @var t3lib_FlashMessage $flashMessage */
00465             $flashMessage = t3lib_div::makeInstance('t3lib_FlashMessage',
00466                 $GLOBALS['LANG']->getLL('msg.noTasksDefined'),
00467                 '',
00468                 t3lib_FlashMessage::INFO
00469             );
00470             $content .= $flashMessage->render();
00471 
00472             // Display the list of all available classes
00473         } else {
00474                 // Initialise table layout
00475             $tableLayout = array (
00476                 'table' => array ('<table border="0" cellspacing="1" cellpadding="2" class="typo3-dblist">', '</table>'),
00477                 '0' => array (
00478                     'tr' => array('<tr class="t3-row-header" valign="top">', '</tr>'),
00479                     'defCol' => array('<td>', '</td>')
00480                 ),
00481                 'defRow' => array (
00482                     'tr' => array('<tr class="db_list_normal">', '</tr>'),
00483                     'defCol' => array('<td>', '</td>')
00484                 )
00485             );
00486             $table = array();
00487             $tr = 0;
00488 
00489                 // Header row
00490             $table[$tr][] = $GLOBALS['LANG']->getLL('label.name');
00491             $table[$tr][] = $GLOBALS['LANG']->getLL('label.extension');
00492             $table[$tr][] = $GLOBALS['LANG']->getLL('label.description');
00493             $table[$tr][] = '';
00494             $tr++;
00495 
00496                 // Display information about each service
00497             foreach ($registeredClasses as $class => $classInfo) {
00498                 $table[$tr][] = $classInfo['title'];
00499                 $table[$tr][] = $classInfo['extension'];
00500                 $table[$tr][] = $classInfo['description'];
00501                 $link = $GLOBALS['MCONF']['_'] . '&SET[function]=list&CMD=add&tx_scheduler[class]=' . $class;
00502                 $table[$tr][] = '<a href="' . htmlspecialchars($link) . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:new', TRUE) . '" class="icon">' . t3lib_iconWorks::getSpriteIcon('actions-document-new') . '</a>';
00503                 $tr++;
00504             }
00505 
00506                 // Render the table and return it
00507             $content  = '<div>' . $GLOBALS['LANG']->getLL('msg.infoScreenIntro') . '</div>';
00508             $content .= $this->doc->spacer(5);
00509             $content .= $this->doc->table($table, $tableLayout);
00510         }
00511 
00512         return $content;
00513     }
00514 
00515     /**
00516      * Display the current server's time along with a help text about server time
00517      * usage in the Scheduler
00518      *
00519      * @return  string  HTML to display
00520      */
00521     protected function displayServerTime() {
00522             // Get the current time, formatted
00523         $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] . ' ' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'] . ' T (e';
00524         $now = date($dateFormat) . ', GMT ' . date('P') . ')';
00525             // Display the help text
00526         $serverTime  = '<h4>' . $GLOBALS['LANG']->getLL('label.serverTime') . '</h4>';
00527         $serverTime .= '<p>' . $GLOBALS['LANG']->getLL('msg.serverTimeHelp') . '</p>';
00528         $serverTime .= '<p>' . sprintf($GLOBALS['LANG']->getLL('msg.serverTime'), $now) . '</p>';
00529         return $serverTime;
00530     }
00531 
00532     /**
00533      * Delete a task from the execution queue
00534      *
00535      * @return  void
00536      */
00537     protected function deleteTask() {
00538         try {
00539                 // Try to fetch the task and delete it
00540                 /**
00541                  * @var tx_scheduler_Task
00542                  */
00543             $task = $this->scheduler->fetchTask($this->submittedData['uid']);
00544                 // If the task is currently running, it may not be deleted
00545             if ($task->isExecutionRunning()) {
00546                 $this->addMessage($GLOBALS['LANG']->getLL('msg.maynotDeleteRunningTask'), t3lib_FlashMessage::ERROR);
00547             } else {
00548                 if ($this->scheduler->removeTask($task)) {
00549                     $this->addMessage($GLOBALS['LANG']->getLL('msg.deleteSuccess'));
00550                 } else {
00551                     $this->addMessage($GLOBALS['LANG']->getLL('msg.deleteError'), t3lib_FlashMessage::ERROR);
00552                 }
00553             }
00554         } catch (UnexpectedValueException $e) {
00555                 // The task could not be unserialized properly, simply delete the database record
00556             $result = $GLOBALS['TYPO3_DB']->exec_DELETEquery('tx_scheduler_task', 'uid = ' . intval($this->submittedData['uid']));
00557             if ($result) {
00558                 $this->addMessage($GLOBALS['LANG']->getLL('msg.deleteSuccess'));
00559             } else {
00560                 $this->addMessage($GLOBALS['LANG']->getLL('msg.deleteError'), t3lib_FlashMessage::ERROR);
00561             }
00562         } catch (OutOfBoundsException $e) {
00563                 // The task was not found, for some reason
00564             $this->addMessage(sprintf($GLOBALS['LANG']->getLL('msg.taskNotFound'), $this->submittedData['uid']), t3lib_FlashMessage::ERROR);
00565         }
00566     }
00567 
00568     /**
00569      * Clears the registered running executions from the task
00570      * Note that this doesn't actually stop the running script. It just unmarks
00571      * all executions.
00572      * TODO: find a way to really kill the running task
00573      *
00574      * @return  void
00575      */
00576     protected function stopTask() {
00577         try {
00578                 // Try to fetch the task and stop it
00579                 /**
00580                  * @var tx_scheduler_Task
00581                  */
00582             $task = $this->scheduler->fetchTask($this->submittedData['uid']);
00583             if ($task->isExecutionRunning()) {
00584                 // If the task is indeed currently running, clear marked executions
00585 
00586                 $result = $task->unmarkAllExecutions();
00587                 if ($result) {
00588                     $this->addMessage($GLOBALS['LANG']->getLL('msg.stopSuccess'));
00589                 } else {
00590                     $this->addMessage($GLOBALS['LANG']->getLL('msg.stopError'), t3lib_FlashMessage::ERROR);
00591                 }
00592             } else {
00593                 // The task is not running, nothing to unmark
00594 
00595                 $this->addMessage($GLOBALS['LANG']->getLL('msg.maynotStopNonRunningTask'), t3lib_FlashMessage::WARNING);
00596             }
00597         } catch (Exception $e) {
00598                 // The task was not found, for some reason
00599             $this->addMessage(sprintf($GLOBALS['LANG']->getLL('msg.taskNotFound'), $this->submittedData['uid']), t3lib_FlashMessage::ERROR);
00600         }
00601     }
00602 
00603     /**
00604      * Return a form to add a new task or edit an existing one
00605      *
00606      * @return  string  HTML form to add or edit a task
00607      */
00608     protected function editTask() {
00609         $registeredClasses = self::getRegisteredClasses();
00610         $content = '';
00611         $taskInfo = array();
00612         $task = NULL;
00613         $process = 'edit';
00614 
00615         if ($this->submittedData['uid'] > 0) {
00616                 // If editing, retrieve data for existing task
00617             try {
00618                 $taskRecord = $this->scheduler->fetchTaskRecord($this->submittedData['uid']);
00619                     // If there's a registered execution, the task should not be edited
00620                 if (!empty($taskRecord['serialized_executions'])) {
00621                     $this->addMessage($GLOBALS['LANG']->getLL('msg.maynotEditRunningTask'), t3lib_FlashMessage::ERROR);
00622                     throw new LogicException('Runnings tasks cannot not be edited', 1251232849);
00623                 }
00624                     // Get the task object
00625                 $task = unserialize($taskRecord['serialized_task_object']);
00626 
00627                     // Set some task information
00628                 $class = $taskRecord['classname'];
00629                 $taskInfo['disable'] = $taskRecord['disable'];
00630 
00631                     // Check that the task object is valid
00632                 if ($this->scheduler->isValidTaskObject($task)) {
00633                     // The task object is valid, process with fetching current data
00634 
00635                     $taskInfo['class'] = $class;
00636 
00637                         // Get execution information
00638                     $taskInfo['start']    = $task->getExecution()->getStart();
00639                     $taskInfo['end']      = $task->getExecution()->getEnd();
00640                     $taskInfo['interval'] = $task->getExecution()->getInterval();
00641                     $taskInfo['croncmd']  = $task->getExecution()->getCronCmd();
00642                     $taskInfo['multiple'] = $task->getExecution()->getMultiple();
00643 
00644                     if (!empty($taskInfo['interval']) || !empty($taskInfo['croncmd'])) {
00645                             // Guess task type from the existing information
00646                             // If an interval or a cron command is defined, it's a recurring task
00647 
00648                             // FIXME remove magic numbers for the type, use class constants instead
00649                         $taskInfo['type']      = 2;
00650                         $taskInfo['frequency'] = (empty($taskInfo['interval'])) ? $taskInfo['croncmd'] : $taskInfo['interval'];
00651                     } else {
00652                             // It's not a recurring task
00653                             // Make sure interval and cron command are both empty
00654                         $taskInfo['type']      = 1;
00655                         $taskInfo['frequency'] = '';
00656                         $taskInfo['end']       = 0;
00657                     }
00658                 } else {
00659                     // The task object is not valid
00660 
00661                         // Issue error message
00662                     $this->addMessage(sprintf($GLOBALS['LANG']->getLL('msg.invalidTaskClassEdit'), $class), t3lib_FlashMessage::ERROR);
00663                         // Initialize empty values
00664                     $taskInfo['start']     = 0;
00665                     $taskInfo['end']       = 0;
00666                     $taskInfo['frequency'] = '';
00667                     $taskInfo['multiple']  = false;
00668                     $taskInfo['type']      = 1;
00669                 }
00670             } catch (OutOfBoundsException $e) {
00671                     // Add a message and continue throwing the exception
00672                 $this->addMessage(sprintf($GLOBALS['LANG']->getLL('msg.taskNotFound'), $this->submittedData['uid']), t3lib_FlashMessage::ERROR);
00673                 throw $e;
00674             }
00675         } else {
00676                 // If adding a new object, set some default values
00677             $taskInfo['class'] = key($registeredClasses);
00678             $taskInfo['type'] = 2;
00679             $taskInfo['start'] = $GLOBALS['EXEC_TIME'];
00680             $taskInfo['end'] = '';
00681             $taskInfo['frequency'] = '';
00682             $taskInfo['multiple'] = 0;
00683             $process = 'add';
00684         }
00685 
00686         if (count($this->submittedData) > 0) {
00687                 // If some data was already submitted, use it to override
00688                 // existing data
00689             $taskInfo = t3lib_div::array_merge_recursive_overrule($taskInfo, $this->submittedData);
00690         }
00691 
00692             // Get the extra fields to display for each task that needs some
00693         $allAdditionalFields = array();
00694         if ($process == 'add') {
00695             foreach ($registeredClasses as $class => $registrationInfo) {
00696                 if (!empty($registrationInfo['provider'])) {
00697                     $providerObject = t3lib_div::getUserObj($registrationInfo['provider']);
00698                     if ($providerObject instanceof tx_scheduler_AdditionalFieldProvider) {
00699                         $additionalFields = $providerObject->getAdditionalFields($taskInfo, NULL, $this);
00700                         $allAdditionalFields = array_merge($allAdditionalFields, array($class => $additionalFields));
00701                     }
00702                 }
00703             }
00704 
00705             // In case of edit, get only the extra fields for the current task class
00706         } else {
00707             if (!empty($registeredClasses[$taskInfo['class']]['provider'])) {
00708                 $providerObject = t3lib_div::getUserObj($registeredClasses[$taskInfo['class']]['provider']);
00709                 if ($providerObject instanceof tx_scheduler_AdditionalFieldProvider) {
00710                     $allAdditionalFields[$taskInfo['class']] = $providerObject->getAdditionalFields($taskInfo, $task, $this);
00711                 }
00712             }
00713         }
00714 
00715             // Load necessary JavaScript
00716             /** @var $pageRenderer t3lib_PageRenderer */
00717         $pageRenderer = $this->doc->getPageRenderer();
00718         $pageRenderer->loadExtJS();
00719         $pageRenderer->addJsFile(t3lib_extMgm::extRelPath('scheduler') . 'res/tx_scheduler_be.js');
00720         $pageRenderer->addJsFile($this->backPath . '../t3lib/js/extjs/tceforms.js');
00721 
00722             // Define settings for Date Picker
00723         $typo3Settings = array(
00724             'datePickerUSmode' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? 1 : 0,
00725             'dateFormat'       => array('j-n-Y', 'G:i j-n-Y'),
00726             'dateFormatUS'     => array('n-j-Y', 'G:i n-j-Y'),
00727         );
00728         $pageRenderer->addInlineSettingArray('', $typo3Settings);
00729 
00730             // Define table layout for add/edit form
00731         $tableLayout = array (
00732             'table' => array ('<table border="0" cellspacing="0" cellpadding="0" id="edit_form" class="typo3-usersettings">', '</table>'),
00733         );
00734 
00735             // Define a style for hiding
00736             // Some fields will be hidden when the task is not recurring
00737         $style = '';
00738         if ($taskInfo['type'] == 1) {
00739             $style = ' style="display: none"';
00740         }
00741 
00742             // Start rendering the add/edit form
00743         $content .= '<input type="hidden" name="tx_scheduler[uid]" value="' . $this->submittedData['uid'] . '" />';
00744         $content .= '<input type="hidden" name="previousCMD" value="' . $this->CMD . '" />';
00745         $content .= '<input type="hidden" name="CMD" value="save" />';
00746 
00747         $table = array();
00748         $tr = 0;
00749         $defaultCell = array('<td class="td-input">', '</td>');
00750 
00751             // Disable checkbox
00752         $label = '<label for="task_disable">' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:disable') . '</label>';
00753         $table[$tr][] = t3lib_BEfunc::wrapInHelp($this->cshKey, 'task_disable', $label);
00754         $table[$tr][] =
00755             '<input type="hidden"   name="tx_scheduler[disable]" value="0" />
00756              <input type="checkbox" name="tx_scheduler[disable]" value="1" id="task_disable"' . ($taskInfo['disable'] == 1 ? ' checked="checked"' : '') . ' />';
00757         $tableLayout[$tr] = array (
00758             'tr'     => array('<tr id="task_disable_row">', '</tr>'),
00759             'defCol' => $defaultCell,
00760             '0'      => array('<td class="td-label">', '</td>')
00761         );
00762         $tr++;
00763 
00764             // Task class selector
00765         $label = '<label for="task_class">' . $GLOBALS['LANG']->getLL('label.class') . '</label>';
00766         $table[$tr][] = t3lib_BEfunc::wrapInHelp($this->cshKey, 'task_class', $label);
00767             // On editing, don't allow changing of the task class, unless it was not valid
00768         if ($this->submittedData['uid'] > 0 && !empty($taskInfo['class'])) {
00769             $cell = $registeredClasses[$taskInfo['class']]['title'] . ' (' . $registeredClasses[$taskInfo['class']]['extension'] . ')';
00770             $cell .= '<input type="hidden" name="tx_scheduler[class]" id="task_class" value="' . $taskInfo['class'] . '" />';
00771         } else {
00772             $cell = '<select name="tx_scheduler[class]" id="task_class" class="wide" onchange="actOnChangedTaskClass(this)">';
00773                 // Loop on all registered classes to display a selector
00774             foreach ($registeredClasses as $class => $classInfo) {
00775                 $selected = ($class == $taskInfo['class']) ? ' selected="selected"' : '';
00776                 $cell .= '<option value="' . $class . '"' . $selected . '>' . $classInfo['title'] . ' (' . $classInfo['extension'] . ')' . '</option>';
00777             }
00778             $cell .= '</select>';
00779         }
00780         $table[$tr][] = $cell;
00781             // Make sure each row has a unique id, for manipulation with JS
00782         $tableLayout[$tr] = array (
00783             'tr'     => array('<tr id="task_class_row">', '</tr>'),
00784             'defCol' => $defaultCell,
00785             '0'      => array('<td class="td-label">', '</td>')
00786         );
00787         $tr++;
00788 
00789             // Task type selector
00790         $label = '<label for="task_type">' . $GLOBALS['LANG']->getLL('label.type') . '</label>';
00791         $table[$tr][] = t3lib_BEfunc::wrapInHelp($this->cshKey, 'task_type', $label);
00792         $table[$tr][] =
00793             '<select name="tx_scheduler[type]" id="task_type" onchange="actOnChangedTaskType(this)">' .
00794                 '<option value="1"' . ($taskInfo['type'] == 1 ? ' selected="selected"' : '') . '>' . $GLOBALS['LANG']->getLL('label.type.single') . '</option>' .
00795                 '<option value="2"' . ($taskInfo['type'] == 2 ? ' selected="selected"' : '') . '>' . $GLOBALS['LANG']->getLL('label.type.recurring') . '</option>' .
00796             '</select>';
00797         $tableLayout[$tr] = array (
00798             'tr'     => array('<tr id="task_type_row">', '</tr>'),
00799             'defCol' => $defaultCell,
00800             '0'      => array('<td class="td-label">', '</td>'),
00801         );
00802         $tr++;
00803 
00804             // Start date/time field
00805             // NOTE: datetime fields need a special id naming scheme
00806         $label = '<label for="tceforms-datetimefield-task_start">' . $GLOBALS['LANG']->getLL('label.start') . '</label>';
00807         $table[$tr][] = t3lib_BEfunc::wrapInHelp($this->cshKey, 'task_start', $label);
00808         $table[$tr][] = '<input name="tx_scheduler[start]" type="text" id="tceforms-datetimefield-task_start" value="' . ((empty($taskInfo['start'])) ? '' : strftime('%H:%M %d-%m-%Y', $taskInfo['start'])) . '" />' .
00809             t3lib_iconWorks::getSpriteIcon(
00810                 'actions-edit-pick-date',
00811                 array(
00812                     'style' => 'cursor:pointer;',
00813                     'id' => 'picker-tceforms-datetimefield-task_start'
00814                 )
00815             );
00816         $tableLayout[$tr] = array (
00817             'tr' => array('<tr id="task_start_row">', '</tr>'),
00818             'defCol' => $defaultCell,
00819             '0'      => array('<td class="td-label">', '</td>')
00820         );
00821         $tr++;
00822 
00823             // End date/time field
00824             // NOTE: datetime fields need a special id naming scheme
00825         $label = '<label for="tceforms-datetimefield-task_end">' . $GLOBALS['LANG']->getLL('label.end') . '</label>';
00826         $table[$tr][] = t3lib_BEfunc::wrapInHelp($this->cshKey, 'task_end', $label);
00827         $table[$tr][] = '<input name="tx_scheduler[end]" type="text" id="tceforms-datetimefield-task_end" value="' . ((empty($taskInfo['end'])) ? '' : strftime('%H:%M %d-%m-%Y', $taskInfo['end'])) . '" />' .
00828             t3lib_iconWorks::getSpriteIcon(
00829                 'actions-edit-pick-date',
00830                 array(
00831                     'style' => 'cursor:pointer;',
00832                     'id' => 'picker-tceforms-datetimefield-task_end'
00833                 )
00834             );
00835         $tableLayout[$tr] = array (
00836             'tr'     => array('<tr id="task_end_row"' . $style . '>', '</tr>'),
00837             'defCol' => $defaultCell,
00838             '0'      => array('<td class="td-label">', '</td>'),
00839         );
00840         $tr++;
00841 
00842             // Frequency input field
00843         $label = '<label for="task_frequency">' . $GLOBALS['LANG']->getLL('label.frequency.long') . '</label>';
00844         $table[$tr][] = t3lib_BEfunc::wrapInHelp($this->cshKey, 'task_frequency', $label);
00845         $cell = '<input type="text" name="tx_scheduler[frequency]" id="task_frequency" value="' . $taskInfo['frequency'] . '" />';
00846         $table[$tr][] = $cell;
00847         $tableLayout[$tr] = array (
00848             'tr'     => array('<tr id="task_frequency_row"' . $style . '>', '</tr>'),
00849             'defCol' => $defaultCell,
00850             '0'      => array('<td class="td-label">', '</td>'),
00851         );
00852         $tr++;
00853 
00854             // Multiple execution selector
00855         $label = '<label for="task_multiple">' . $GLOBALS['LANG']->getLL('label.parallel.long') . '</label>';
00856         $table[$tr][] = t3lib_BEfunc::wrapInHelp($this->cshKey, 'task_multiple', $label);
00857         $table[$tr][] =
00858             '<input type="hidden"   name="tx_scheduler[multiple]" value="0" />
00859              <input type="checkbox" name="tx_scheduler[multiple]" value="1" id="task_multiple"' . ($taskInfo['multiple'] == 1 ? ' checked="checked"' : '') . ' />';
00860         $tableLayout[$tr] = array (
00861             'tr'     => array('<tr id="task_multiple_row"' . $style . '>', '</tr>'),
00862             'defCol' => $defaultCell,
00863             '0'      => array('<td class="td-label">', '</td>')
00864         );
00865         $tr++;
00866 
00867             // Display additional fields
00868         foreach ($allAdditionalFields as $class => $fields) {
00869             if ($class == $taskInfo['class']) {
00870                 $additionalFieldsStyle = '';
00871             } else {
00872                 $additionalFieldsStyle = ' style="display: none"';
00873             }
00874 
00875                 // Add each field to the display, if there are indeed any
00876             if (isset($fields) && is_array($fields)) {
00877                 foreach ($fields as $fieldID => $fieldInfo) {
00878                     $label = '<label for="' . $fieldID . '">' . $GLOBALS['LANG']->sL($fieldInfo['label']) . '</label>';
00879                     $table[$tr][] = t3lib_BEfunc::wrapInHelp($fieldInfo['cshKey'], $fieldInfo['cshLabel'], $label);
00880                     $table[$tr][] = $fieldInfo['code'];
00881                     $tableLayout[$tr] = array (
00882                         'tr'     => array('<tr id="' . $fieldID . '_row"' . $additionalFieldsStyle .' class="extraFields extra_fields_' . $class . '">', '</tr>'),
00883                         'defCol' => $defaultCell,
00884                         '0'      => array('<td class="td-label">', '</td>')
00885                     );
00886                     $tr++;
00887                 }
00888             }
00889         }
00890 
00891             // Render the add/edit task form
00892         $content .= '<div style="float: left;"><div class="typo3-dyntabmenu-divs">';
00893         $content .= $this->doc->table($table, $tableLayout);
00894         $content .= '</div></div>';
00895 
00896         $content .= '<div style="padding-top: 20px; clear: both;"></div><div><input type="submit" name="save" class="button" value="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:save', TRUE) . '" /> '
00897             . '<input type="button" name="cancel" class="button" value="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:cancel', TRUE) . '" onclick="document.location=\'' . $GLOBALS['MCONF']['_'] . '\'" /></div>';
00898 
00899             // Display information about server time usage
00900         $content .= $this->displayServerTime();
00901 
00902         return $content;
00903     }
00904 
00905     /**
00906      * Execute all selected tasks
00907      *
00908      * @return  void
00909      */
00910     protected function executeTasks() {
00911             // Continue if some elements have been chosen for execution
00912         if (isset($this->submittedData['execute']) && count($this->submittedData['execute']) > 0) {
00913 
00914                 // Get list of registered classes
00915             $registeredClasses = self::getRegisteredClasses();
00916 
00917                 // Loop on all selected tasks
00918             foreach ($this->submittedData['execute'] as $uid) {
00919 
00920                 try {
00921                         // Try fetching the task
00922                     $task = $this->scheduler->fetchTask($uid);
00923                     $class = get_class($task);
00924                     $name = $registeredClasses[$class]['title']. ' (' . $registeredClasses[$class]['extension'] . ')';
00925                         // Now try to execute it and report on outcome
00926                     try {
00927                         $result = $this->scheduler->executeTask($task);
00928                         if ($result) {
00929                             $this->addMessage(sprintf($GLOBALS['LANG']->getLL('msg.executed'), $name));
00930                         } else {
00931                             $this->addMessage(sprintf($GLOBALS['LANG']->getLL('msg.notExecuted'), $name), t3lib_FlashMessage::ERROR);
00932                         }
00933                     }
00934                     catch (Exception $e) {
00935                             // An exception was thrown, display its message as an error
00936                         $this->addMessage(sprintf($GLOBALS['LANG']->getLL('msg.executionFailed'), $name, $e->getMessage()), t3lib_FlashMessage::ERROR);
00937                     }
00938                 }
00939                     // The task was not found, for some reason
00940                 catch (OutOfBoundsException $e) {
00941                     $this->addMessage(sprintf($GLOBALS['LANG']->getLL('msg.taskNotFound'), $uid), t3lib_FlashMessage::ERROR);
00942                 }
00943                     // The task object was not valid
00944                 catch (UnexpectedValueException $e) {
00945                     $this->addMessage(sprintf($GLOBALS['LANG']->getLL('msg.executionFailed'), $name, $e->getMessage()), t3lib_FlashMessage::ERROR);
00946                 }
00947             }
00948                 // Record the run in the system registry
00949             $this->scheduler->recordLastRun('manual');
00950                 // Make sure to switch to list view after execution
00951             $this->CMD = 'list';
00952         }
00953     }
00954 
00955     /**
00956      * Assemble display of list of scheduled tasks
00957      *
00958      * @return  string          table of waiting schedulings
00959      */
00960     protected function listTasks() {
00961             // Define display format for dates
00962         $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] . ' ' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'];
00963         $content = '';
00964 
00965             // Get list of registered classes
00966         $registeredClasses = self::getRegisteredClasses();
00967 
00968             // Get all registered tasks
00969         $query = array(
00970             'SELECT'  => '*',
00971             'FROM'    => 'tx_scheduler_task',
00972             'WHERE'   => '1=1',
00973             'ORDERBY' => 'nextexecution'
00974         );
00975 
00976         $res = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($query);
00977         $numRows = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
00978             // No tasks defined, display information message
00979         if ($numRows == 0) {
00980                 /** @var t3lib_FlashMessage $flashMessage */
00981             $flashMessage = t3lib_div::makeInstance('t3lib_FlashMessage',
00982                 $GLOBALS['LANG']->getLL('msg.noTasks'),
00983                 '',
00984                 t3lib_FlashMessage::INFO
00985             );
00986             $content .= $flashMessage->render();
00987         } else {
00988                 // Load ExtJS framework and specific JS library
00989                 /** @var $pageRenderer t3lib_PageRenderer */
00990             $pageRenderer = $this->doc->getPageRenderer();
00991             $pageRenderer->loadExtJS();
00992             $pageRenderer->addJsFile(t3lib_extMgm::extRelPath('scheduler') . 'res/tx_scheduler_be.js');
00993 
00994                 // Initialise table layout
00995             $tableLayout = array(
00996                 'table' => array(
00997                     '<table border="0" cellspacing="1" cellpadding="2" class="typo3-dblist">', '</table>'
00998                 ),
00999                 '0'     => array(
01000                     'tr'     => array('<tr class="t3-row-header">', '</tr>'),
01001                     'defCol' => array('<td>', '</td>'),
01002                     '1'      => array('<td style="width: 36px;">', '</td>'),
01003                     '3'      => array('<td colspan="2">', '</td>'),
01004                 ),
01005                 'defRow' => array(
01006                     'tr'     => array('<tr class="db_list_normal">', '</tr>'),
01007                     'defCol' => array('<td>', '</td>'),
01008                     '1'      => array('<td class="right">', '</td>'),
01009                     '2'      => array('<td class="right">', '</td>'),
01010                 )
01011             );
01012             $disabledTaskRow = array (
01013                 'tr'     => array('<tr class="db_list_normal disabled">', '</tr>'),
01014                 'defCol' => array('<td>', '</td>'),
01015                 '1'      => array('<td class="right">', '</td>'),
01016                 '2'      => array('<td class="right">', '</td>'),
01017             );
01018             $rowWithSpan = array (
01019                 'tr'     => array('<tr class="db_list_normal">', '</tr>'),
01020                 'defCol' => array('<td>', '</td>'),
01021                 '1'      => array('<td class="right">', '</td>'),
01022                 '2'      => array('<td class="right">', '</td>'),
01023                 '3'      => array('<td colspan="6">', '</td>'),
01024             );
01025             $table = array();
01026             $tr = 0;
01027 
01028                 // Header row
01029             $table[$tr][] = '<a href="#" onclick="toggleCheckboxes();" title="' . $GLOBALS['LANG']->getLL('label.checkAll', TRUE) . '" class="icon">' .
01030                 t3lib_iconWorks::getSpriteIcon('actions-document-select') .
01031                 '</a>';
01032             $table[$tr][] = '&nbsp;';
01033             $table[$tr][] = $GLOBALS['LANG']->getLL('label.id');
01034             $table[$tr][] = $GLOBALS['LANG']->getLL('task');
01035             $table[$tr][] = $GLOBALS['LANG']->getLL('label.type');
01036             $table[$tr][] = $GLOBALS['LANG']->getLL('label.frequency');
01037             $table[$tr][] = $GLOBALS['LANG']->getLL('label.parallel');
01038             $table[$tr][] = $GLOBALS['LANG']->getLL('label.lastExecution');
01039             $table[$tr][] = $GLOBALS['LANG']->getLL('label.nextExecution');
01040             $tr++;
01041 
01042                 // Loop on all tasks
01043             while (($schedulerRecord = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
01044                     // Define action icons
01045                 $editAction = '<a href="' . $GLOBALS['MCONF']['_'] . '&CMD=edit&tx_scheduler[uid]=' . $schedulerRecord['uid'] . '" title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:edit', TRUE) . '" class="icon">' . t3lib_iconWorks::getSpriteIcon('actions-document-open') . '</a>';
01046                 $deleteAction = '<a href="' . $GLOBALS['MCONF']['_'] . '&CMD=delete&tx_scheduler[uid]=' . $schedulerRecord['uid'] . '" onclick="return confirm(\'' . $GLOBALS['LANG']->getLL('msg.delete') . '\');" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:delete', TRUE) . '" class="icon">' . t3lib_iconWorks::getSpriteIcon('actions-edit-delete') . '</a>';
01047                 $stopAction = '<a href="' . $GLOBALS['MCONF']['_'] . '&CMD=stop&tx_scheduler[uid]=' . $schedulerRecord['uid'] . '" onclick="return confirm(\'' . $GLOBALS['LANG']->getLL('msg.stop') . '\');" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:stop', TRUE) . '" class="icon"><img ' . t3lib_iconWorks::skinImg($this->backPath, t3lib_extMgm::extRelPath('scheduler') . '/res/gfx/stop.png') . ' alt="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:stop') . '" /></a>';
01048                     // Define some default values
01049                 $lastExecution = '-';
01050                 $isRunning = false;
01051                 $executionStatus = 'scheduled';
01052                 $executionStatusDetail = '';
01053                 $executionStatusOutput = '';
01054                 $name = '';
01055                 $nextDate = '-';
01056                 $execType = '-';
01057                 $frequency = '-';
01058                 $multiple = '-';
01059                 $startExecutionElement = '&nbsp;';
01060 
01061                     // Restore the serialized task and pass it a reference to the scheduler object
01062                 $task = unserialize($schedulerRecord['serialized_task_object']);
01063 
01064                     // Assemble information about last execution
01065                 $context = '';
01066                 if (!empty($schedulerRecord['lastexecution_time'])) {
01067                     $lastExecution = date($dateFormat, $schedulerRecord['lastexecution_time']);
01068                     if ($schedulerRecord['lastexecution_context'] == 'CLI') {
01069                         $context = $GLOBALS['LANG']->getLL('label.cron');
01070                     } else {
01071                         $context = $GLOBALS['LANG']->getLL('label.manual');
01072                     }
01073                     $lastExecution .= ' (' . $context . ')';
01074                 }
01075 
01076                 if ($this->scheduler->isValidTaskObject($task)) {
01077                     // The task object is valid
01078 
01079                     $name = htmlspecialchars($registeredClasses[$schedulerRecord['classname']]['title']. ' (' . $registeredClasses[$schedulerRecord['classname']]['extension'] . ')');
01080                     $additionalInformation = $task->getAdditionalInformation();
01081                     if (!empty($additionalInformation)) {
01082                         $name .= '<br />[' . htmlspecialchars($additionalInformation) . ']';
01083                     }
01084 
01085                         // Check if task currently has a running execution
01086                     if (!empty($schedulerRecord['serialized_executions'])) {
01087                         $isRunning = true;
01088                         $executionStatus = 'running';
01089                     }
01090 
01091                         // Prepare display of next execution date
01092                         // If task is currently running, date is not displayed (as next hasn't been calculated yet)
01093                         // Also hide the date if task is disabled (the information doesn't make sense, as it will not run anyway)
01094                     if ($isRunning || $schedulerRecord['disable'] == 1) {
01095                         $nextDate = '-';
01096                     }
01097                     else {
01098                         $nextDate = date($dateFormat, $schedulerRecord['nextexecution']);
01099                         if (empty($schedulerRecord['nextexecution'])) {
01100                             $nextDate = $GLOBALS['LANG']->getLL('none');
01101                         } elseif ($schedulerRecord['nextexecution'] < $GLOBALS['EXEC_TIME']) {
01102                                 // Next execution is overdue, highlight date
01103                             $nextDate = '<span class="late" title="' . $GLOBALS['LANG']->getLL('status.legend.scheduled') . '">' . $nextDate . '</span>';
01104                             $executionStatus = 'late';
01105                         }
01106                     }
01107 
01108                         // Get execution type
01109                     if ($task->getExecution()->getInterval() == 0 && $task->getExecution()->getCronCmd() == '') {
01110                         $execType = $GLOBALS['LANG']->getLL('label.type.single');
01111                         $frequency = '-';
01112                     } else {
01113                         $execType = $GLOBALS['LANG']->getLL('label.type.recurring');
01114                         if ($task->getExecution()->getCronCmd() == '') {
01115                             $frequency = $task->getExecution()->getInterval();
01116                         } else {
01117                             $frequency = $task->getExecution()->getCronCmd();
01118                         }
01119                     }
01120 
01121                         // Get multiple executions setting
01122                     if ($task->getExecution()->getMultiple()) {
01123                         $multiple = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes');
01124                     } else {
01125                         $multiple = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:no');
01126                     }
01127 
01128                         // Define checkbox
01129                     $startExecutionElement = '<input type="checkbox" name="tx_scheduler[execute][]" value="' . $schedulerRecord['uid'] . '" id="task_' . $schedulerRecord['uid'] . '" class="checkboxes" />';
01130 
01131                         // Show no action links (edit, delete) if task is running
01132                     $actions = $editAction . $deleteAction;
01133                     if ($isRunning) {
01134                         $actions = $stopAction;
01135                     }
01136 
01137                         // Check the disable status
01138                         // Row is shown dimmed if task is disabled, unless it is still running
01139                     if ($schedulerRecord['disable'] == 1 && !$isRunning) {
01140                         $tableLayout[$tr] = $disabledTaskRow;
01141                         $executionStatus  = 'disabled';
01142                     }
01143 
01144                         // Check if the last run failed
01145                     $failureOutput = '';
01146                     if (!empty($schedulerRecord['lastexecution_failure'])) {
01147                             // Try to get the stored exception object
01148                         $exception = unserialize($schedulerRecord['lastexecution_failure']);
01149                             // If the exception could not be unserialized, issue a default error message
01150                         if ($exception === FALSE) {
01151                             $failureDetail = $GLOBALS['LANG']->getLL('msg.executionFailureDefault');
01152                         } else {
01153                             $failureDetail = sprintf($GLOBALS['LANG']->getLL('msg.executionFailureReport'), $exception->getCode(), $exception->getMessage());
01154                         }
01155                         $failureOutput = ' <img ' . t3lib_iconWorks::skinImg(t3lib_extMgm::extRelPath('scheduler'), 'res/gfx/status_failure.png') . ' alt="' . htmlspecialchars($GLOBALS['LANG']->getLL('status.failure')) . '" title="' . htmlspecialchars($failureDetail) . '" />';
01156                     }
01157 
01158                         // Format the execution status,
01159                         // including failure feedback, if any
01160                     $executionStatusOutput = '<img ' . t3lib_iconWorks::skinImg(t3lib_extMgm::extRelPath('scheduler'), 'res/gfx/status_' . $executionStatus . '.png') . ' alt="' . htmlspecialchars($GLOBALS['LANG']->getLL('status.' . $executionStatus)) . '" title="' . htmlspecialchars($executionStatusDetail) . '" />' . $failureOutput;
01161 
01162                     $table[$tr][] = $startExecutionElement;
01163                     $table[$tr][] = $actions;
01164                     $table[$tr][] = $schedulerRecord['uid'];
01165                     $table[$tr][] = $executionStatusOutput;
01166                     $table[$tr][] = $name;
01167                     $table[$tr][] = $execType;
01168                     $table[$tr][] = $frequency;
01169                     $table[$tr][] = $multiple;
01170                     $table[$tr][] = $lastExecution;
01171                     $table[$tr][] = $nextDate;
01172 
01173                 } else {
01174                     // The task object is not valid
01175                     // Prepare to issue an error
01176 
01177                         /** @var t3lib_FlashMessage $flashMessage */
01178                     $flashMessage = t3lib_div::makeInstance('t3lib_FlashMessage',
01179                         sprintf($GLOBALS['LANG']->getLL('msg.invalidTaskClass'), $schedulerRecord['classname']),
01180                         '',
01181                         t3lib_FlashMessage::ERROR
01182                     );
01183                     $executionStatusOutput = $flashMessage->render();
01184 
01185                     $tableLayout[$tr] = $rowWithSpan;
01186                     $table[$tr][] = $startExecutionElement;
01187                     $table[$tr][] = $deleteAction;
01188                     $table[$tr][] = $schedulerRecord['uid'];
01189                     $table[$tr][] = $executionStatusOutput;
01190                 }
01191 
01192                 $tr++;
01193             }
01194                 // Render table
01195             $content .= $this->doc->table($table, $tableLayout);
01196 
01197             $content .= '<input type="submit" class="button" name="go" value="' . $GLOBALS['LANG']->getLL('label.executeSelected') . '" />';
01198         }
01199 
01200         if (count($registeredClasses) > 0) {
01201                 // Display add new task link
01202             $link = $GLOBALS['MCONF']['_'] . '&CMD=add';
01203             $content .= '<p><a href="' . htmlspecialchars($link) .'"><img '
01204                 . t3lib_iconWorks::skinImg($this->backPath, 'gfx/new_el.gif')
01205                 . ' alt="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:new', TRUE)
01206                 . '" /> ' . $GLOBALS['LANG']->getLL('action.add') . '</a></p>';
01207         } else {
01208                 /** @var t3lib_FlashMessage $flashMessage */
01209             $flashMessage = t3lib_div::makeInstance('t3lib_FlashMessage',
01210                 $GLOBALS['LANG']->getLL('msg.noTasksDefined'),
01211                 '',
01212                 t3lib_FlashMessage::INFO
01213             );
01214             $content .= $flashMessage->render();
01215         }
01216 
01217             // Display legend, if there's at least one registered task
01218             // Also display information about the usage of server time
01219         if ($numRows > 0) {
01220             $content .= $this->doc->spacer(20);
01221             $content .= '<h4>' . $GLOBALS['LANG']->getLL('status.legend') . '</h4>
01222             <ul>
01223                 <li><img ' . t3lib_iconWorks::skinImg(t3lib_extMgm::extRelPath('scheduler'), 'res/gfx/status_failure.png') . ' alt="' . htmlspecialchars($GLOBALS['LANG']->getLL('status.failure')) . '" /> ' . $GLOBALS['LANG']->getLL('status.legend.failure') . '</li>
01224                 <li><img ' . t3lib_iconWorks::skinImg(t3lib_extMgm::extRelPath('scheduler'), 'res/gfx/status_late.png') . ' alt="' . htmlspecialchars($GLOBALS['LANG']->getLL('status.late')) . '" /> ' . $GLOBALS['LANG']->getLL('status.legend.late') . '</li>
01225                 <li><img ' . t3lib_iconWorks::skinImg(t3lib_extMgm::extRelPath('scheduler'), 'res/gfx/status_running.png') . ' alt="' . htmlspecialchars($GLOBALS['LANG']->getLL('status.running')) . '" /> ' . $GLOBALS['LANG']->getLL('status.legend.running') . '</li>
01226                 <li><img ' . t3lib_iconWorks::skinImg(t3lib_extMgm::extRelPath('scheduler'), 'res/gfx/status_scheduled.png') . ' alt="' . htmlspecialchars($GLOBALS['LANG']->getLL('status.scheduled')) . '" /> ' . $GLOBALS['LANG']->getLL('status.legend.scheduled') . '</li>
01227                 <li><img ' . t3lib_iconWorks::skinImg(t3lib_extMgm::extRelPath('scheduler'), 'res/gfx/status_disabled.png') . ' alt="' . htmlspecialchars($GLOBALS['LANG']->getLL('status.disabled')) . '" /> ' . $GLOBALS['LANG']->getLL('status.legend.disabled') . '</li>
01228             </ul>';
01229             $content .= $this->doc->spacer(10);
01230             $content .= $this->displayServerTime();
01231         }
01232 
01233 
01234         $GLOBALS['TYPO3_DB']->sql_free_result($res);
01235 
01236         return $content;
01237     }
01238 
01239     /**
01240      * Saves a task specified in the backend form to the database
01241      *
01242      * @return  void
01243      */
01244     protected function saveTask() {
01245 
01246             // If a task is being edited fetch old task data
01247         if (!empty($this->submittedData['uid'])) {
01248             try {
01249                 $taskRecord = $this->scheduler->fetchTaskRecord($this->submittedData['uid']);
01250                 /**
01251                  * @var tx_scheduler_Task
01252                  */
01253                 $task = unserialize($taskRecord['serialized_task_object']);
01254             } catch (OutOfBoundsException $e) {
01255                     // If the task could not be fetched, issue an error message
01256                     // and exit early
01257                 $this->addMessage(sprintf($GLOBALS['LANG']->getLL('msg.taskNotFound'), $this->submittedData['uid']), t3lib_FlashMessage::ERROR);
01258                 return;
01259             }
01260 
01261                 // Register single execution
01262             if ($this->submittedData['type'] == 1) {
01263                 $task->registerSingleExecution($this->submittedData['start']);
01264 
01265                 // Else, it's a recurring task
01266             } else {
01267                 if (!empty($this->submittedData['croncmd'])) {
01268                         // Definition by cron-like syntax
01269 
01270                     $interval = 0;
01271                     $cronCmd = $this->submittedData['croncmd'];
01272                 } else {
01273                         // Definition by interval
01274 
01275                     $interval = $this->submittedData['interval'];
01276                     $cronCmd = '';
01277                 }
01278 
01279                     // Register recurring execution
01280                 $task->registerRecurringExecution($this->submittedData['start'], $interval, $this->submittedData['end'], $this->submittedData['multiple'], $cronCmd);
01281             }
01282 
01283                 // Set disable flag
01284             $task->setDisabled($this->submittedData['disable']);
01285 
01286                 // Save additional input values
01287             if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][$this->submittedData['class']]['additionalFields'])) {
01288                 $providerObject = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][$this->submittedData['class']]['additionalFields']);
01289                 if ($providerObject instanceof tx_scheduler_AdditionalFieldProvider) {
01290                     $providerObject->saveAdditionalFields($this->submittedData, $task);
01291                 }
01292             }
01293 
01294                 // Save to database
01295             $result = $this->scheduler->saveTask($task);
01296             if ($result) {
01297                 $this->addMessage($GLOBALS['LANG']->getLL('msg.updateSuccess'));
01298             } else {
01299                 $this->addMessage($GLOBALS['LANG']->getLL('msg.updateError'), t3lib_FlashMessage::ERROR);
01300             }
01301         } else {
01302                 // A new task is being created
01303 
01304                 // Create an instance of chosen class
01305             $task = t3lib_div::makeInstance($this->submittedData['class']);
01306 
01307             if ($this->submittedData['type'] == 1) {
01308                     // Set up single execution
01309                 $task->registerSingleExecution($this->submittedData['start']);
01310             } else {
01311                     // Set up recurring execution
01312                 $task->registerRecurringExecution($this->submittedData['start'], $this->submittedData['interval'], $this->submittedData['end'], $this->submittedData['multiple'], $this->submittedData['croncmd']);
01313             }
01314 
01315                 // Save additional input values
01316             if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][$this->submittedData['class']]['additionalFields'])) {
01317                 $providerObject = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][$this->submittedData['class']]['additionalFields']);
01318                 if ($providerObject instanceof tx_scheduler_AdditionalFieldProvider) {
01319                     $providerObject->saveAdditionalFields($this->submittedData, $task);
01320                 }
01321             }
01322 
01323                 // Set disable flag
01324             $task->setDisabled($this->submittedData['disable']);
01325 
01326                 // Add to database
01327             $result = $this->scheduler->addTask($task);
01328             if ($result) {
01329                 $this->addMessage($GLOBALS['LANG']->getLL('msg.addSuccess'));
01330             } else {
01331                 $this->addMessage($GLOBALS['LANG']->getLL('msg.addError'), t3lib_FlashMessage::ERROR);
01332             }
01333         }
01334     }
01335 
01336 
01337     /*************************
01338      *
01339      * INPUT PROCESSING UTILITIES
01340      *
01341      *************************/
01342 
01343     /**
01344      * Checks the submitted data and performs some preprocessing on it
01345      *
01346      * @return  boolean     True if everything was ok, false otherwise
01347      */
01348     protected function preprocessData() {
01349         $result = true;
01350 
01351             // Validate id
01352         $this->submittedData['uid'] = (empty($this->submittedData['uid'])) ? 0 : intval($this->submittedData['uid']);
01353 
01354             // Validate selected task class
01355         if (!class_exists($this->submittedData['class'])) {
01356             $this->addMessage($GLOBALS['LANG']->getLL('msg.noTaskClassFound'), t3lib_FlashMessage::ERROR);
01357         }
01358 
01359             // Check start date
01360         if (empty($this->submittedData['start'])) {
01361             $this->addMessage($GLOBALS['LANG']->getLL('msg.noStartDate'), t3lib_FlashMessage::ERROR);
01362             $result = false;
01363         } else {
01364             try {
01365                 $timestamp = $this->checkDate($this->submittedData['start']);
01366                 $this->submittedData['start'] = $timestamp;
01367             } catch (Exception $e) {
01368                 $this->addMessage($GLOBALS['LANG']->getLL('msg.invalidStartDate'), t3lib_FlashMessage::ERROR);
01369                 $result = false;
01370             }
01371         }
01372 
01373             // Check end date, if recurring task
01374         if ($this->submittedData['type'] == 2 && !empty($this->submittedData['end'])) {
01375             try {
01376                 $timestamp = $this->checkDate($this->submittedData['end']);
01377                 $this->submittedData['end'] = $timestamp;
01378 
01379                 if ($this->submittedData['end'] < $this->submittedData['start']) {
01380                     $this->addMessage($GLOBALS['LANG']->getLL('msg.endDateSmallerThanStartDate'), t3lib_FlashMessage::ERROR);
01381                     $result = false;
01382                 }
01383             } catch (Exception $e) {
01384                 $this->addMessage($GLOBALS['LANG']->getLL('msg.invalidEndDate'), t3lib_FlashMessage::ERROR);
01385                 $result = false;
01386             }
01387         }
01388 
01389             // Set default values for interval and cron command
01390         $this->submittedData['interval'] = 0;
01391         $this->submittedData['croncmd'] = '';
01392 
01393             // Check type and validity of frequency, if recurring
01394         if ($this->submittedData['type'] == 2) {
01395             $frequency = trim($this->submittedData['frequency']);
01396 
01397             if (empty($frequency)) {
01398                     // Empty frequency, not valid
01399 
01400                 $this->addMessage($GLOBALS['LANG']->getLL('msg.noFrequency'), t3lib_FlashMessage::ERROR);
01401                 $result = FALSE;
01402             } else {
01403                 $cronErrorCode = 0;
01404                 $cronErrorMessage = '';
01405 
01406                     // Try interpreting the cron command
01407                 try {
01408                     tx_scheduler_CronCmd_Normalize::normalize($frequency);
01409                     $this->submittedData['croncmd'] = $frequency;
01410                 }
01411                     // If the cron command was invalid, we may still have a valid frequency in seconds
01412                 catch (Exception $e) {
01413                         // Store the exception's result
01414                     $cronErrorMessage = $e->getMessage();
01415                     $cronErrorCode = $e->getCode();
01416                         // Check if the frequency is a valid number
01417                         // If yes, assume it is a frequency in seconds, and unset cron error code
01418                     if (is_numeric($frequency)) {
01419                         $this->submittedData['interval'] = intval($frequency);
01420                         unset($cronErrorCode);
01421                     }
01422                 }
01423                     // If there's a cron error code, issue validation error message
01424                 if (!empty($cronErrorCode)) {
01425                     $this->addMessage(sprintf($GLOBALS['LANG']->getLL('msg.frequencyError'), $cronErrorMessage, $cronErrorCode), t3lib_FlashMessage::ERROR);
01426                     $result = FALSE;
01427                 }
01428             }
01429         }
01430 
01431             // Validate additional input fields
01432         if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][$this->submittedData['class']]['additionalFields'])) {
01433             $providerObject = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][$this->submittedData['class']]['additionalFields']);
01434             if ($providerObject instanceof tx_scheduler_AdditionalFieldProvider) {
01435                     // The validate method will return true if all went well, but that must not
01436                     // override previous false values => AND the returned value with the existing one
01437                 $result &= $providerObject->validateAdditionalFields($this->submittedData, $this);
01438             }
01439         }
01440 
01441         return $result;
01442     }
01443 
01444     /**
01445      * This method checks whether the given string can be considered a valid date or not
01446      * Allowed values are anything that matches natural language (see PHP function strtotime())
01447      * or TYPO3's date syntax: HH:ii yyyy-mm-dd
01448      * If the string is a valid date, the corresponding timestamp is returned.
01449      * Otherwise an exception is thrown
01450      *
01451      * @param   string      $string: string to check
01452      * @return  integer     Unix timestamp
01453      */
01454     protected function checkDate($string) {
01455             // Try with strtotime
01456         $timestamp = strtotime($string);
01457 
01458             // That failed. Try TYPO3's standard date/time input format
01459         if ($timestamp === false) {
01460                 // Split time and date
01461             $dateParts = t3lib_div::trimExplode(' ', $string, true);
01462                 // Proceed if there are indeed two parts
01463                 // Extract each component of date and time
01464             if (count($dateParts) == 2) {
01465                 list($time, $date) = $dateParts;
01466                 list($hour, $minutes) = t3lib_div::trimExplode(':', $time, true);
01467                 list($day, $month, $year) = t3lib_div::trimExplode('-', $date, true);
01468                     // Get a timestamp from all these parts
01469                 $timestamp = mktime($hour, $minutes, 0, $month, $day, $year);
01470             }
01471                 // If the timestamp is still false, throw an exception
01472             if ($timestamp === false) {
01473                 throw new Exception;
01474             }
01475         }
01476         return $timestamp;
01477     }
01478 
01479     /*************************
01480      *
01481      * APPLICATION LOGIC UTILITIES
01482      *
01483      *************************/
01484 
01485     /**
01486      * This method is used to add a message to the internal queue
01487      *
01488      * @param   string  the message itself
01489      * @param   integer message level (-1 = success (default), 0 = info, 1 = notice, 2 = warning, 3 = error)
01490      * @return  void
01491      */
01492     public function addMessage($message, $severity = t3lib_FlashMessage::OK) {
01493         $message = t3lib_div::makeInstance(
01494             't3lib_FlashMessage',
01495             $message,
01496             '',
01497             $severity
01498         );
01499 
01500         t3lib_FlashMessageQueue::addMessage($message);
01501     }
01502 
01503     /**
01504      * This method a list of all classes that have been registered with the Scheduler
01505      * For each item the following information is provided, as an associative array:
01506      *
01507      * ['extension']    =>  Key of the extension which provides the class
01508      * ['filename']     =>  Path to the file containing the class
01509      * ['title']        =>  String (possibly localized) containing a human-readable name for the class
01510      * ['provider']     =>  Name of class that implements the interface for additional fields, if necessary
01511      *
01512      * The name of the class itself is used as the key of the list array
01513      *
01514      * @return  array   List of registered classes
01515      */
01516     protected static function getRegisteredClasses() {
01517         $list = array();
01518         if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'])) {
01519             foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'] as $class => $registrationInformation) {
01520 
01521                 $title         = isset($registrationInformation['title'])         ? $GLOBALS['LANG']->sL($registrationInformation['title'])         : '';
01522                 $description   = isset($registrationInformation['description'])   ? $GLOBALS['LANG']->sL($registrationInformation['description'])   : '';
01523 
01524                 $list[$class] = array(
01525                     'extension'     => $registrationInformation['extension'],
01526                     'title'         => $title,
01527                     'description'   => $description,
01528                     'provider'      => isset($registrationInformation['additionalFields']) ? $registrationInformation['additionalFields'] : ''
01529                 );
01530             }
01531         }
01532 
01533         return $list;
01534     }
01535 
01536 
01537     /*************************
01538      *
01539      * RENDERING UTILITIES
01540      *
01541      *************************/
01542 
01543     /**
01544      * Gets the filled markers that are used in the HTML template.
01545      *
01546      * @return  array       The filled marker array
01547      */
01548     protected function getTemplateMarkers() {
01549         $markers = array(
01550             'CSH' => t3lib_BEfunc::wrapInHelp('_MOD_tools_txschedulerM1', ''),
01551             'FUNC_MENU' => $this->getFunctionMenu(),
01552             'CONTENT'   => $this->content,
01553             'TITLE'     => $GLOBALS['LANG']->getLL('title'),
01554         );
01555 
01556         return $markers;
01557     }
01558 
01559     /**
01560      * Gets the function menu selector for this backend module.
01561      *
01562      * @return  string      The HTML representation of the function menu selector
01563      */
01564     protected function getFunctionMenu() {
01565         $functionMenu = t3lib_BEfunc::getFuncMenu(
01566             0,
01567             'SET[function]',
01568             $this->MOD_SETTINGS['function'],
01569             $this->MOD_MENU['function']
01570         );
01571 
01572         return $functionMenu;
01573     }
01574 
01575     /**
01576      * Gets the buttons that shall be rendered in the docHeader.
01577      *
01578      * @return  array       Available buttons for the docHeader
01579      */
01580     protected function getDocHeaderButtons() {
01581         $buttons = array(
01582             'reload'   => '',
01583             'shortcut' => $this->getShortcutButton(),
01584         );
01585 
01586         if (empty($this->CMD) || $this->CMD == 'list') {
01587             $buttons['reload'] = '<a href="' . $GLOBALS['MCONF']['_'] . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.reload', TRUE) . '">' .
01588               t3lib_iconWorks::getSpriteIcon('actions-system-refresh') .
01589           '</a>';
01590         }
01591 
01592         return $buttons;
01593     }
01594 
01595     /**
01596      * Gets the button to set a new shortcut in the backend (if current user is allowed to).
01597      *
01598      * @return  string      HTML representiation of the shortcut button
01599      */
01600     protected function getShortcutButton() {
01601         $result = '';
01602         if ($GLOBALS['BE_USER']->mayMakeShortcut()) {
01603             $result = $this->doc->makeShortcutIcon('', 'function', $this->MCONF['name']);
01604         }
01605 
01606         return $result;
01607     }
01608 }
01609 
01610 
01611 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/scheduler/mod1/index.php'])) {
01612     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/scheduler/mod1/index.php']);
01613 }
01614 
01615 
01616 
01617 
01618 // Make instance:
01619 $SOBE = t3lib_div::makeInstance('tx_scheduler_Module');
01620 $SOBE->init();
01621 
01622 // Include files?
01623 foreach($SOBE->include_once as $INC_FILE) {
01624     include_once($INC_FILE);
01625 }
01626 
01627 $SOBE->main();
01628 $SOBE->render();
01629 
01630 ?>