|
TYPO3 API
SVNRelease
|
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][] = ' '; 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 = ' '; 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 ?>
1.8.0