81 $GLOBALS[
'LANG']->includeLLFile(
'EXT:scheduler/mod1/locallang.xlf');
83 $this->backPath =
$GLOBALS[
'BACK_PATH'];
85 $this->cshKey =
'_MOD_' .
$GLOBALS[
'MCONF'][
'name'];
98 $this->pageRenderer = $this->doc->getPageRenderer();
101 $this->doc->bodyTagId =
'typo3-mod-php';
102 $this->doc->bodyTagAdditions =
'class="tx_scheduler_mod1"';
113 $this->MOD_MENU = array(
115 'scheduler' =>
$GLOBALS[
'LANG']->getLL(
'function.scheduler'),
116 'check' =>
$GLOBALS[
'LANG']->getLL(
'function.check'),
117 'info' =>
$GLOBALS[
'LANG']->getLL(
'function.info')
120 parent::menuConfig();
131 if (
$GLOBALS[
'BE_USER']->user[
'admin']) {
133 $this->doc->form =
'<form name="tx_scheduler_form" id="tx_scheduler_form" method="post" action="">';
136 $this->content = $this->doc->header(
$GLOBALS[
'LANG']->getLL(
'function.' . $this->MOD_SETTINGS[
'function']));
140 $this->content = $this->doc->header(
$GLOBALS[
'LANG']->getLL(
'title'));
141 $this->content .= $this->doc->spacer(5);
146 $this->content = $this->doc->render(
$GLOBALS[
'LANG']->getLL(
'title'),
$content);
159 $this->submittedData[
'uid'] = (int)$this->submittedData[
'uid'];
161 if ($this->CMD ===
'save' || $this->CMD ===
'saveclose' || $this->CMD ===
'savenew') {
164 $result = $this->preprocessData();
168 if ($this->CMD ==
'saveclose') {
171 } elseif ($this->CMD ==
'save') {
174 } elseif ($this->CMD ===
'savenew') {
176 unset($this->submittedData);
181 $this->CMD = $previousCMD;
184 $this->CMD = $previousCMD;
188 switch ((
string) $this->MOD_SETTINGS[
'function']) {
193 switch ($this->CMD) {
200 $sectionTitle =
$GLOBALS[
'LANG']->getLL(
'action.' . $this->CMD);
201 }
catch (\Exception $e) {
202 if ($e->getCode() === 1305100019) {
230 $content .= $this->displayCheckScreen();
234 $content .= $this->displayInfoScreen();
238 return $this->doc->section($sectionTitle,
'<div class="tx_scheduler_mod1">' .
$content .
'</div>', 0, 1);
258 $schedulerUserStatus = -1;
262 $res =
$GLOBALS[
'TYPO3_DB']->exec_SELECTquery(
'1',
'be_users', $where);
263 if (
$GLOBALS[
'TYPO3_DB']->sql_fetch_assoc($res)) {
264 $schedulerUserStatus = 0;
267 if (
$GLOBALS[
'TYPO3_DB']->sql_fetch_assoc($res)) {
268 $schedulerUserStatus = 1;
271 $GLOBALS[
'TYPO3_DB']->sql_free_result($res);
272 return $schedulerUserStatus;
280 protected function createSchedulerUser() {
284 $message =
$GLOBALS[
'LANG']->getLL(
'msg.userExists');
287 if ($checkUser == -1) {
289 $password = uniqid(
'scheduler', TRUE);
292 $password = $objInstanceSaltedPW->getHashedPassword($password);
294 $data = array(
'be_users' => array(
'NEW' => array(
'username' =>
'_cli_scheduler',
'password' => $password,
'pid' => 0)));
297 $tcemain->stripslashes_values = 0;
298 $tcemain->start($data, array());
299 $tcemain->process_datamap();
302 $numberOfNewIDs = count($tcemain->substNEWwithIDs);
303 if ($numberOfNewIDs == 1) {
304 $message =
$GLOBALS[
'LANG']->getLL(
'msg.userCreated');
307 $message =
$GLOBALS[
'LANG']->getLL(
'msg.userNotCreated');
311 $this->addMessage($message, $severity);
320 protected function displayCheckScreen() {
324 if ($this->CMD ==
'user') {
325 $this->createSchedulerUser();
329 $content =
'<p class="lead">' .
$GLOBALS[
'LANG']->getLL(
'msg.schedulerSetupCheck') .
'</p>';
334 $lastRun =
$registry->get(
'tx_scheduler',
'lastRun');
335 if (!is_array($lastRun)) {
336 $message =
$GLOBALS[
'LANG']->getLL(
'msg.noLastRun');
339 if (empty($lastRun[
'end']) || empty($lastRun[
'start']) || empty($lastRun[
'type'])) {
340 $message =
$GLOBALS[
'LANG']->getLL(
'msg.incompleteLastRun');
343 $startDate = date(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'], $lastRun[
'start']);
344 $startTime = date(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'hhmm'], $lastRun[
'start']);
345 $endDate = date(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'], $lastRun[
'end']);
346 $endTime = date(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'hhmm'], $lastRun[
'end']);
347 $label =
'automatically';
348 if ($lastRun[
'type'] ==
'manual') {
351 $type =
$GLOBALS[
'LANG']->getLL(
'label.' . $label);
352 $message = sprintf(
$GLOBALS[
'LANG']->getLL(
'msg.lastRun'), $type, $startDate, $startTime, $endDate, $endTime);
359 $content .=
'<div class="info-block">';
361 $content .= $flashMessage->render();
365 $content .=
'<div class="info-block">';
366 $content .=
'<h2>' .
$GLOBALS[
'LANG']->getLL(
'hdg.schedulerUser') .
'</h2>';
369 if ($checkUser == -1) {
370 $link =
$GLOBALS[
'MCONF'][
'_'] .
'&SET[function]=check&CMD=user';
371 $message = sprintf(
$GLOBALS[
'LANG']->getLL(
'msg.schedulerUserMissing'), htmlspecialchars($link));
373 } elseif ($checkUser == 0) {
374 $message =
$GLOBALS[
'LANG']->getLL(
'msg.schedulerUserFoundButDisabled');
377 $message =
$GLOBALS[
'LANG']->getLL(
'msg.schedulerUserFound');
381 $content .= $flashMessage->render() .
'</div>';
384 $script = PATH_typo3 .
'cli_dispatch.phpsh';
385 $isExecutable = FALSE;
388 if (TYPO3_OS ===
'WIN') {
389 $isExecutable = TRUE;
391 $isExecutable = is_executable($script);
393 $content .=
'<div class="info-block">';
395 $content .=
'<p>' . sprintf(
$GLOBALS[
'LANG']->getLL(
'msg.cliScript'), $script) .
'</p>';
397 $message =
$GLOBALS[
'LANG']->getLL(
'msg.cliScriptExecutable');
400 $message =
$GLOBALS[
'LANG']->getLL(
'msg.cliScriptNotExecutable');
404 $content .= $flashMessage->render() .
'</div>';
413 protected function displayInfoScreen() {
415 $registeredClasses = self::getRegisteredClasses();
417 if (count($registeredClasses) == 0) {
420 $content .= $flashMessage->render();
423 $tableLayout = array(
424 'table' => array(
'<table class="t3-table">',
'</table>'),
426 'tr' => array(
'<thead><tr>',
'</tr></thead>'),
427 'defCol' => array(
'<td>',
'</td>')
430 'tr' => array(
'<tr>',
'</tr>'),
431 'defCol' => array(
'<td>',
'</td>')
437 $table[$tr][] =
$GLOBALS[
'LANG']->getLL(
'label.name');
438 $table[$tr][] =
$GLOBALS[
'LANG']->getLL(
'label.extension');
439 $table[$tr][] =
$GLOBALS[
'LANG']->getLL(
'label.description');
443 foreach ($registeredClasses as $class => $classInfo) {
444 $table[$tr][] = htmlspecialchars($classInfo[
'title']);
445 $table[$tr][] = htmlspecialchars($classInfo[
'extension']);
446 $table[$tr][] = htmlspecialchars($classInfo[
'description']);
447 $link =
$GLOBALS[
'MCONF'][
'_'] .
'&SET[function]=list&CMD=add&tx_scheduler[class]=' . $class;
448 $table[$tr][] =
'<a href="' . htmlspecialchars($link) .
'" title="' .
$GLOBALS[
'LANG']->sL(
'LLL:EXT:lang/locallang_common.xlf:new', TRUE) .
'" class="icon">' .
IconUtility::getSpriteIcon(
'actions-document-new') .
'</a>';
452 $content =
'<p class="lead">' .
$GLOBALS[
'LANG']->getLL(
'msg.infoScreenIntro') .
'</p>';
453 $content .= $this->doc->table($table, $tableLayout);
466 $dateFormat =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'] .
' ' .
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'hhmm'] .
' T (e';
467 $now = date($dateFormat) .
', GMT ' . date(
'P') .
')';
469 $serverTime =
'<h3>' .
$GLOBALS[
'LANG']->getLL(
'label.serverTime') .
'</h3>';
470 $serverTime .=
'<p>' .
$GLOBALS[
'LANG']->getLL(
'msg.serverTimeHelp') .
'</p>';
471 $serverTime .=
'<p>' . sprintf(
$GLOBALS[
'LANG']->getLL(
'msg.serverTime'), $now) .
'</p>';
482 $progressText =
$GLOBALS[
'LANG']->getLL(
'status.progress') .
': ' . $progress .
'%';
483 $progressBar =
'<div class="progress"> <div class="bar" style="width: ' . $progress .
'%;">' . $progressText .
'</div> </div>';
495 $task = $this->scheduler->fetchTask($this->submittedData[
'uid']);
497 if ($task->isExecutionRunning()) {
500 if ($this->scheduler->removeTask($task)) {
501 $GLOBALS[
'BE_USER']->writeLog(4, 0, 0, 0,
'Scheduler task "%s" (UID: %s, Class: "%s") was deleted', array($task->getTaskTitle(), $task->getTaskUid(), $task->getTaskClassName()));
502 $this->addMessage(
$GLOBALS[
'LANG']->getLL(
'msg.deleteSuccess'));
507 }
catch (\UnexpectedValueException $e) {
509 $result =
$GLOBALS[
'TYPO3_DB']->exec_DELETEquery(
'tx_scheduler_task',
'uid = ' . (
int)$this->submittedData[
'uid']);
511 $this->addMessage(
$GLOBALS[
'LANG']->getLL(
'msg.deleteSuccess'));
515 }
catch (\OutOfBoundsException $e) {
532 $task = $this->scheduler->fetchTask($this->submittedData[
'uid']);
533 if ($task->isExecutionRunning()) {
535 $result = $task->unmarkAllExecutions();
537 $this->addMessage(
$GLOBALS[
'LANG']->getLL(
'msg.stopSuccess'));
545 }
catch (\Exception $e) {
556 protected function editTask() {
557 $registeredClasses = self::getRegisteredClasses();
558 $registeredTaskGroups = self::getRegisteredTaskGroups();
563 if ($this->submittedData[
'uid'] > 0) {
566 $taskRecord = $this->scheduler->fetchTaskRecord($this->submittedData[
'uid']);
568 if (!empty($taskRecord[
'serialized_executions'])) {
570 throw new \LogicException(
'Runnings tasks cannot not be edited', 1251232849);
574 $task = unserialize($taskRecord[
'serialized_task_object']);
576 $taskInfo[
'disable'] = $taskRecord[
'disable'];
577 $taskInfo[
'description'] = $taskRecord[
'description'];
578 $taskInfo[
'task_group'] = $taskRecord[
'task_group'];
580 if ($this->scheduler->isValidTaskObject($task)) {
582 $taskInfo[
'class'] = get_class($task);
584 $taskInfo[
'start'] = $task->getExecution()->getStart();
585 $taskInfo[
'end'] = $task->getExecution()->getEnd();
586 $taskInfo[
'interval'] = $task->getExecution()->getInterval();
587 $taskInfo[
'croncmd'] = $task->getExecution()->getCronCmd();
588 $taskInfo[
'multiple'] = $task->getExecution()->getMultiple();
589 if (!empty($taskInfo[
'interval']) || !empty($taskInfo[
'croncmd'])) {
593 $taskInfo[
'type'] = 2;
594 $taskInfo[
'frequency'] = $taskInfo[
'interval'] ?: $taskInfo[
'croncmd'];
598 $taskInfo[
'type'] = 1;
599 $taskInfo[
'frequency'] =
'';
600 $taskInfo[
'end'] = 0;
607 $taskInfo[
'start'] = 0;
608 $taskInfo[
'end'] = 0;
609 $taskInfo[
'frequency'] =
'';
610 $taskInfo[
'multiple'] = FALSE;
611 $taskInfo[
'type'] = 1;
613 }
catch (\OutOfBoundsException $e) {
620 $taskInfo[
'class'] = key($registeredClasses);
621 $taskInfo[
'type'] = 2;
622 $taskInfo[
'start'] =
$GLOBALS[
'EXEC_TIME'];
623 $taskInfo[
'end'] =
'';
624 $taskInfo[
'frequency'] =
'';
625 $taskInfo[
'multiple'] = 0;
628 if (count($this->submittedData) > 0) {
634 $allAdditionalFields = array();
635 if ($process ==
'add') {
636 foreach ($registeredClasses as $class => $registrationInfo) {
637 if (!empty($registrationInfo[
'provider'])) {
641 $additionalFields = $providerObject->getAdditionalFields($taskInfo, NULL, $this);
642 $allAdditionalFields = array_merge($allAdditionalFields, array($class => $additionalFields));
647 if (!empty($registeredClasses[$taskInfo[
'class']][
'provider'])) {
650 $allAdditionalFields[$taskInfo[
'class']] = $providerObject->getAdditionalFields($taskInfo, $task, $this);
655 $this->pageRenderer->loadExtJS();
657 $this->pageRenderer->addJsFile($this->backPath .
'sysext/backend/Resources/Public/JavaScript/tceforms.js');
658 $this->pageRenderer->addJsFile($this->backPath .
'js/extjs/ux/Ext.ux.DateTimePicker.js');
660 $typo3Settings = array(
661 'datePickerUSmode' =>
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'USdateFormat'] ? 1 : 0,
662 'dateFormat' => array(
'j-n-Y',
'G:i j-n-Y'),
663 'dateFormatUS' => array(
'n-j-Y',
'G:i n-j-Y')
665 $this->pageRenderer->addInlineSettingArray(
'', $typo3Settings);
667 $tableLayout = array(
668 'table' => array(
'<table border="0" cellspacing="0" cellpadding="0" id="edit_form" class="typo3-usersettings">',
'</table>')
673 if ($taskInfo[
'type'] == 1) {
674 $style =
' style="display: none"';
677 $content .=
'<input type="hidden" name="tx_scheduler[uid]" value="' . htmlspecialchars($this->submittedData[
'uid']) .
'" />';
678 $content .=
'<input type="hidden" name="previousCMD" value="' . htmlspecialchars($this->CMD) .
'" />';
681 $defaultCell = array(
'<td class="td-input">',
'</td>');
683 $label =
'<label for="task_disable">' .
$GLOBALS[
'LANG']->sL(
'LLL:EXT:lang/locallang_common.xlf:disable') .
'</label>';
685 $table[$tr][] =
'<input type="hidden" name="tx_scheduler[disable]" value="0" /> 686 <input type="checkbox" name="tx_scheduler[disable]" value="1" id="task_disable"' . ($taskInfo[
'disable'] == 1 ?
' checked="checked"' :
'') .
' />';
687 $tableLayout[$tr] = array(
688 'tr' => array(
'<tr id="task_disable_row">',
'</tr>'),
689 'defCol' => $defaultCell,
690 '0' => array(
'<td class="td-label">',
'</td>')
694 $label =
'<label for="task_class">' .
$GLOBALS[
'LANG']->getLL(
'label.class') .
'</label>';
697 if ($this->submittedData[
'uid'] > 0 && !empty($taskInfo[
'class'])) {
698 $cell = $registeredClasses[$taskInfo[
'class']][
'title'] .
' (' . $registeredClasses[$taskInfo[
'class']][
'extension'] .
')';
699 $cell .=
'<input type="hidden" name="tx_scheduler[class]" id="task_class" value="' . htmlspecialchars($taskInfo[
'class']) .
'" />';
701 $cell =
'<select name="tx_scheduler[class]" id="task_class" class="wide" onchange="actOnChangedTaskClass(this)">';
703 $groupedClasses = array();
704 foreach ($registeredClasses as $class => $classInfo) {
705 $groupedClasses[$classInfo[
'extension']][$class] = $classInfo;
707 ksort($groupedClasses);
709 foreach ($groupedClasses as $extension => $class) {
710 $cell .=
'<optgroup label="' . htmlspecialchars($extension) .
'">';
711 foreach ($groupedClasses[$extension] as $class => $classInfo) {
712 $selected = $class == $taskInfo[
'class'] ?
' selected="selected"' :
'';
713 $cell .=
'<option value="' . htmlspecialchars($class) .
'"' .
'title="' . htmlspecialchars($classInfo[
'description']) .
'"' . $selected .
'>' . htmlspecialchars($classInfo[
'title']) .
'</option>';
715 $cell .=
'</optgroup>';
717 $cell .=
'</select>';
719 $table[$tr][] = $cell;
721 $tableLayout[$tr] = array(
722 'tr' => array(
'<tr id="task_class_row">',
'</tr>'),
723 'defCol' => $defaultCell,
724 '0' => array(
'<td class="td-label">',
'</td>')
728 $label =
'<label for="task_type">' .
$GLOBALS[
'LANG']->getLL(
'label.type') .
'</label>';
730 $table[$tr][] =
'<select name="tx_scheduler[type]" id="task_type" onchange="actOnChangedTaskType(this)">' .
'<option value="1"' . ($taskInfo[
'type'] == 1 ?
' selected="selected"' :
'') .
'>' .
$GLOBALS[
'LANG']->getLL(
'label.type.single') .
'</option>' .
'<option value="2"' . ($taskInfo[
'type'] == 2 ?
' selected="selected"' :
'') .
'>' .
$GLOBALS[
'LANG']->getLL(
'label.type.recurring') .
'</option>' .
'</select>';
731 $tableLayout[$tr] = array(
732 'tr' => array(
'<tr id="task_type_row">',
'</tr>'),
733 'defCol' => $defaultCell,
734 '0' => array(
'<td class="td-label">',
'</td>')
738 $label =
'<label for="task_group">' .
$GLOBALS[
'LANG']->getLL(
'label.group') .
'</label>';
740 $cell =
'<select name="tx_scheduler[task_group]" id="task_class" class="wide">';
742 $cell .=
'<option value="0" title=""></option>';
743 foreach ($registeredTaskGroups as $taskGroup) {
744 $selected = $taskGroup[
'uid'] == $taskInfo[
'task_group'] ?
' selected="selected"' :
'';
745 $cell .=
'<option value="' . $taskGroup[
'uid'] .
'"' .
'title="';
746 $cell .= htmlspecialchars($taskGroup[
'groupName']) .
'"' . $selected .
'>';
747 $cell .= htmlspecialchars($taskGroup[
'groupName']) .
'</option>';
749 $cell .=
'</select>';
750 $table[$tr][] = $cell;
751 $tableLayout[$tr] = array(
752 'tr' => array(
'<tr id="task_group_row">',
'</tr>'),
753 'defCol' => $defaultCell,
754 '0' => array(
'<td class="td-label">',
'</td>')
759 $label =
'<label for="tceforms-datetimefield-task_start">' .
$GLOBALS[
'LANG']->getLL(
'label.start') .
'</label>';
761 $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'])) .
'" />' .
IconUtility::getSpriteIcon(
'actions-edit-pick-date', array(
762 'style' =>
'cursor:pointer;',
763 'id' =>
'picker-tceforms-datetimefield-task_start' 765 $tableLayout[$tr] = array(
766 'tr' => array(
'<tr id="task_start_row">',
'</tr>'),
767 'defCol' => $defaultCell,
768 '0' => array(
'<td class="td-label">',
'</td>')
773 $label =
'<label for="tceforms-datetimefield-task_end">' .
$GLOBALS[
'LANG']->getLL(
'label.end') .
'</label>';
775 $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'])) .
'" />' .
IconUtility::getSpriteIcon(
'actions-edit-pick-date', array(
776 'style' =>
'cursor:pointer;',
777 'id' =>
'picker-tceforms-datetimefield-task_end' 779 $tableLayout[$tr] = array(
780 'tr' => array(
'<tr id="task_end_row"' . $style .
'>',
'</tr>'),
781 'defCol' => $defaultCell,
782 '0' => array(
'<td class="td-label">',
'</td>')
786 $label =
'<label for="task_frequency">' .
$GLOBALS[
'LANG']->getLL(
'label.frequency.long') .
'</label>';
788 $cell =
'<input type="text" name="tx_scheduler[frequency]" id="task_frequency" value="' . htmlspecialchars($taskInfo[
'frequency']) .
'" />';
789 $table[$tr][] = $cell;
790 $tableLayout[$tr] = array(
791 'tr' => array(
'<tr id="task_frequency_row"' . $style .
'>',
'</tr>'),
792 'defCol' => $defaultCell,
793 '0' => array(
'<td class="td-label">',
'</td>')
797 $label =
'<label for="task_multiple">' .
$GLOBALS[
'LANG']->getLL(
'label.parallel.long') .
'</label>';
799 $table[$tr][] =
'<input type="hidden" name="tx_scheduler[multiple]" value="0" /> 800 <input type="checkbox" name="tx_scheduler[multiple]" value="1" id="task_multiple"' . ($taskInfo[
'multiple'] == 1 ?
' checked="checked"' :
'') .
' />';
801 $tableLayout[$tr] = array(
802 'tr' => array(
'<tr id="task_multiple_row"' . $style .
'>',
'</tr>'),
803 'defCol' => $defaultCell,
804 '0' => array(
'<td class="td-label">',
'</td>')
808 $label =
'<label for="task_description">' .
$GLOBALS[
'LANG']->getLL(
'label.description') .
'</label>';
810 $table[$tr][] =
'<textarea name="tx_scheduler[description]">' . htmlspecialchars($taskInfo[
'description']) .
'</textarea>';
811 $tableLayout[$tr] = array(
812 'tr' => array(
'<tr id="task_description_row">',
'</tr>'),
813 'defCol' => $defaultCell,
814 '0' => array(
'<td class="td-label">',
'</td>')
818 foreach ($allAdditionalFields as $class => $fields) {
819 if ($class == $taskInfo[
'class']) {
820 $additionalFieldsStyle =
'';
822 $additionalFieldsStyle =
' style="display: none"';
825 if (isset($fields) && is_array($fields)) {
826 foreach ($fields as $fieldID => $fieldInfo) {
827 $label =
'<label for="' . $fieldID .
'">' .
$GLOBALS[
'LANG']->sL($fieldInfo[
'label']) .
'</label>';
829 $table[$tr][] = $fieldInfo[
'code'];
830 $htmlClassName = strtolower(str_replace(
'\\',
'-', $class));
831 $tableLayout[$tr] = array(
832 'tr' => array(
'<tr id="' . $fieldID .
'_row"' . $additionalFieldsStyle .
' class="extraFields extra_fields_' . $htmlClassName .
'">',
'</tr>'),
833 'defCol' => $defaultCell,
834 '0' => array(
'<td class="td-label">',
'</td>')
841 $content .=
'<div style="float: left;"><div class="typo3-dyntabmenu-divs">';
842 $content .= $this->doc->table($table, $tableLayout);
844 $content .=
'<div style="padding-top: 20px; clear: both;"></div>';
858 $this->scheduler->scheduleNextSchedulerRunUsingAtDaemon();
861 if (isset($this->submittedData[
'execute']) && count($this->submittedData[
'execute']) > 0) {
863 $registeredClasses = self::getRegisteredClasses();
865 foreach ($this->submittedData[
'execute'] as
$uid) {
868 $task = $this->scheduler->fetchTask($uid);
869 $class = get_class($task);
870 $name = $registeredClasses[$class][
'title'] .
' (' . $registeredClasses[$class][
'extension'] .
')';
873 $result = $this->scheduler->executeTask($task);
875 $this->addMessage(sprintf(
$GLOBALS[
'LANG']->getLL(
'msg.executed'), $name));
879 }
catch (\Exception $e) {
883 }
catch (\OutOfBoundsException $e) {
885 }
catch (\UnexpectedValueException $e) {
890 $this->scheduler->recordLastRun(
'manual');
901 protected function listTasks() {
903 $dateFormat =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'] .
' ' .
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'hhmm'];
906 $registeredClasses = self::getRegisteredClasses();
908 $registeredTaskGroups = self::getRegisteredTaskGroups();
912 array_unshift($registeredTaskGroups, array(
'uid' => 0,
'groupName' =>
''));
919 tx_scheduler_task_group.groupName as taskGroupName, 920 tx_scheduler_task_group.description as taskGroupDescription, 921 tx_scheduler_task_group.deleted as isTaskGroupDeleted 925 LEFT JOIN tx_scheduler_task_group ON tx_scheduler_task_group.uid = tx_scheduler_task.task_group 928 'ORDERBY' =>
'tx_scheduler_task_group.sorting' 937 $content .= $flashMessage->render();
940 $this->pageRenderer->loadExtJS();
943 $tableLayout = array(
945 '<table class="t3-table">',
949 'tr' => array(
'<thead><tr>',
'</tr></thead>'),
950 'defCol' => array(
'<td>',
'</td>'),
951 '1' => array(
'<td style="width: 56px;">',
'</td>'),
952 '3' => array(
'<td colspan="2">',
'</td>')
955 'tr' => array(
'<tr class="db_list_normal">',
'</tr>'),
956 'defCol' => array(
'<td>',
'</td>'),
957 '1' => array(
'<td class="right">',
'</td>'),
958 '2' => array(
'<td class="right">',
'</td>')
961 $disabledTaskRow = array(
962 'tr' => array(
'<tr class="db_list_normal disabled">',
'</tr>'),
963 'defCol' => array(
'<td>',
'</td>'),
964 '1' => array(
'<td class="right">',
'</td>'),
965 '2' => array(
'<td class="right">',
'</td>')
967 $rowWithSpan = array(
968 'tr' => array(
'<tr class="db_list_normal">',
'</tr>'),
969 'defCol' => array(
'<td>',
'</td>'),
970 '1' => array(
'<td class="right">',
'</td>'),
971 '2' => array(
'<td class="right">',
'</td>'),
972 '3' => array(
'<td colspan="6">',
'</td>')
974 $taskGroupRow = array(
975 'tr' => array(
'<tr class="db_list_normal">',
'</tr>'),
976 'defCol' => array(
'<td>',
'</td>'),
977 '0' => array(
'<td colspan="10">',
'</td>')
982 $table[$tr][] =
'<a href="#" onclick="toggleCheckboxes();" title="' .
$GLOBALS[
'LANG']->getLL(
'label.checkAll', TRUE) .
'" class="icon">' .
IconUtility::getSpriteIcon(
'actions-document-select') .
'</a>';
983 $table[$tr][] =
' ';
984 $table[$tr][] =
$GLOBALS[
'LANG']->getLL(
'label.id');
985 $table[$tr][] =
$GLOBALS[
'LANG']->getLL(
'task');
986 $table[$tr][] =
$GLOBALS[
'LANG']->getLL(
'label.type');
987 $table[$tr][] =
$GLOBALS[
'LANG']->getLL(
'label.frequency');
988 $table[$tr][] =
$GLOBALS[
'LANG']->getLL(
'label.parallel');
989 $table[$tr][] =
$GLOBALS[
'LANG']->getLL(
'label.lastExecution');
990 $table[$tr][] =
$GLOBALS[
'LANG']->getLL(
'label.nextExecution');
994 $temporaryResult = array();
996 if ($row[
'taskGroupName'] === NULL || $row[
'isTaskGroupDeleted'] ===
'1') {
997 $row[
'taskGroupName'] =
'';
998 $row[
'taskGroupDescription'] =
'';
999 $row[
'task_group'] = 0;
1001 $temporaryResult[$row[
'task_group']][
'groupName'] = $row[
'taskGroupName'];
1002 $temporaryResult[$row[
'task_group']][
'groupDescription'] = $row[
'taskGroupDescription'];
1003 $temporaryResult[$row[
'task_group']][
'tasks'][] = $row;
1005 foreach ($temporaryResult as $taskGroup) {
1006 if (!empty($taskGroup[
'groupName'])) {
1007 $groupText =
'<strong>' . htmlspecialchars($taskGroup[
'groupName']) .
' </strong>';
1008 if (!empty($taskGroup[
'groupDescription'])) {
1009 $groupText .=
'<br />' . nl2br(htmlspecialchars($taskGroup[
'groupDescription']));
1011 $table[$tr++][] =
'<tr><td colspan="10">' . $groupText .
'</td></tr>';
1016 foreach ($taskGroup[
'tasks'] as $schedulerRecord) {
1017 $editAction =
'<a href="' .
$GLOBALS[
'MCONF'][
'_'] .
'&CMD=edit&tx_scheduler[uid]=' . $schedulerRecord[
'uid'] .
'" title="' . $this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:edit', TRUE) .
'" class="icon">' .
1019 $deleteAction =
'<a href="' .
$GLOBALS[
'MCONF'][
'_'] .
'&CMD=delete&tx_scheduler[uid]=' . $schedulerRecord[
'uid'] .
'" onclick="return confirm(\'' . $this->
getLanguageService()->getLL(
'msg.delete') .
'\');
" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:
delete', TRUE) . '" class="icon
">' . 1020 IconUtility::getSpriteIcon('actions-edit-delete') . '</a>'; 1021 $stopAction = '<a href="' . $GLOBALS['MCONF
']['_
'] . '&CMD=stop&
tx_scheduler[uid]=
' . $schedulerRecord['uid
'] . '" onclick="return confirm(\
'' . $this->
getLanguageService()->getLL(
'msg.stop') .
'\');
" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:stop
', TRUE) . '" class="icon
">' . 1022 '<img ' . IconUtility::skinImg($this->backPath, (ExtensionManagementUtility::extRelPath('scheduler') . 'res/gfx/stop.png')) . ' alt="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:stop
') . '" /></a>'; 1023 $runAction = '<a href="' . $GLOBALS['MCONF
']['_
'] . '&tx_scheduler[execute][]=
' . $schedulerRecord['uid
'] . '" title="' . $this->getLanguageService()->getLL('action.run_task
') . '" class="icon
">' . 1024 IconUtility::getSpriteIcon('extensions-scheduler-run-task') . '</a>'; 1026 // Define some default values 1027 $lastExecution = '-'; 1029 $executionStatus = 'scheduled'; 1030 $executionStatusOutput = ''; 1036 $startExecutionElement = ' '; 1037 // Restore the serialized task and pass it a reference to the scheduler object 1039 $task = unserialize($schedulerRecord['serialized_task_object']); 1040 $class = get_class($task); 1041 if ($class === '__PHP_Incomplete_Class' && preg_match('/^O:[0-9]+:"(?P<classname>.+?)
"/', $schedulerRecord['serialized_task_object'], $matches) === 1) { 1042 $class = $matches['classname']; 1044 // Assemble information about last execution 1046 if (!empty($schedulerRecord['lastexecution_time'])) { 1047 $lastExecution = date($dateFormat, $schedulerRecord['lastexecution_time']); 1048 if ($schedulerRecord['lastexecution_context'] == 'CLI') { 1049 $context = $GLOBALS['LANG']->getLL('label.cron'); 1051 $context = $GLOBALS['LANG']->getLL('label.manual'); 1053 $lastExecution .= ' (' . $context . ')'; 1056 if ($this->scheduler->isValidTaskObject($task)) { 1057 // The task object is valid 1058 $name = htmlspecialchars($registeredClasses[$class]['title'] . ' (' . $registeredClasses[$class]['extension'] . ')'); 1059 $additionalInformation = $task->getAdditionalInformation(); 1060 if ($task instanceof \TYPO3\CMS\Scheduler\ProgressProviderInterface) { 1061 $progress = round(floatval($task->getProgress()), 2); 1062 $name .= '<br />' . $this->renderTaskProgressBar($progress); 1064 if (!empty($additionalInformation)) { 1065 $name .= '<br />[' . htmlspecialchars($additionalInformation) . ']'; 1067 // Check if task currently has a running execution 1068 if (!empty($schedulerRecord['serialized_executions'])) { 1070 $executionStatus = 'running'; 1073 // Prepare display of next execution date 1074 // If task is currently running, date is not displayed (as next hasn't been calculated yet) 1075 // Also hide the date if task is disabled (the information doesn't make sense, as it will not run anyway) 1076 if ($isRunning || $schedulerRecord['disable'] == 1) { 1079 $nextDate = date($dateFormat, $schedulerRecord['nextexecution']); 1080 if (empty($schedulerRecord['nextexecution'])) { 1081 $nextDate = $GLOBALS['LANG']->getLL('none'); 1082 } elseif ($schedulerRecord['nextexecution'] < $GLOBALS['EXEC_TIME']) { 1083 // Next execution is overdue, highlight date 1084 $nextDate = '<span class="late
" title="' . $GLOBALS['LANG
']->getLL('status.legend.scheduled
') . '">' . $nextDate . '</span>'; 1085 $executionStatus = 'late'; 1088 // Get execution type 1089 if ($task->getExecution()->getInterval() == 0 && $task->getExecution()->getCronCmd() == '') { 1090 $execType = $GLOBALS['LANG']->getLL('label.type.single'); 1093 $execType = $GLOBALS['LANG']->getLL('label.type.recurring'); 1094 if ($task->getExecution()->getCronCmd() == '') { 1095 $frequency = $task->getExecution()->getInterval(); 1097 $frequency = $task->getExecution()->getCronCmd(); 1100 // Get multiple executions setting 1101 if ($task->getExecution()->getMultiple()) { 1102 $multiple = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xlf:yes'); 1104 $multiple = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xlf:no'); 1107 $startExecutionElement = '<input type="checkbox
" name="tx_scheduler[execute][]
" value="' . $schedulerRecord['uid
'] . '" id="task_
' . $schedulerRecord['uid
'] . '" class="checkboxes
" />'; 1109 $actions = $editAction . $deleteAction; 1111 // Check the disable status 1112 // Row is shown dimmed if task is disabled, unless it is still running 1113 if ($schedulerRecord['disable'] == 1 && !$isRunning) { 1114 $tableLayout[$tr] = $disabledTaskRow; 1115 $executionStatus = 'disabled'; 1118 // Show no action links (edit, delete) if task is running 1120 $actions = $stopAction; 1122 $actions .= $runAction; 1125 // Check if the last run failed 1126 $failureOutput = ''; 1127 if (!empty($schedulerRecord['lastexecution_failure'])) { 1128 // Try to get the stored exception array 1130 $exceptionArray = @unserialize($schedulerRecord['lastexecution_failure']); 1131 if (!is_array($exceptionArray) || empty($exceptionArray)) { 1132 $failureDetail = $GLOBALS['LANG']->getLL('msg.executionFailureDefault'); 1134 $failureDetail = sprintf($GLOBALS['LANG']->getLL('msg.executionFailureReport'), $exceptionArray['code'], $exceptionArray['message']); 1136 $failureOutput = ' <img ' . IconUtility::skinImg(ExtensionManagementUtility::extRelPath('scheduler'), 'res/gfx/status_failure.png') . ' alt="' . htmlspecialchars($GLOBALS['LANG
']->getLL('status.failure
')) . '" title="' . htmlspecialchars($failureDetail) . '" />'; 1138 // Format the execution status, 1139 // including failure feedback, if any 1140 $executionStatusOutput = '<img ' . IconUtility::skinImg(ExtensionManagementUtility::extRelPath('scheduler'), ('res/gfx/status_' . $executionStatus . '.png')) . ' id="executionstatus_
' . $schedulerRecord['uid
'] . '" alt="' . htmlspecialchars($GLOBALS['LANG
']->getLL(('status.
' . $executionStatus))) . '" title="' . htmlspecialchars($GLOBALS['LANG
']->getLL(('status.legend.
' . $executionStatus))) . '" />' . $failureOutput; 1141 $table[$tr][] = $startExecutionElement; 1142 $table[$tr][] = $actions; 1143 $table[$tr][] = $schedulerRecord['uid']; 1144 $table[$tr][] = $executionStatusOutput; 1145 if ($schedulerRecord['description'] !== '') { 1146 if (!empty($this->scheduler->extConf['listShowTaskDescriptionAsHover'])) { 1147 $table[$tr][] = '<span title="' . htmlspecialchars($schedulerRecord['description
']) . '">' . $name . '</span>'; 1149 $table[$tr][] = $name . '<br />' . nl2br(htmlspecialchars($schedulerRecord['description'])) . '<br />'; 1152 $table[$tr][] = $name; 1154 $table[$tr][] = $execType; 1155 $table[$tr][] = $frequency; 1156 $table[$tr][] = $multiple; 1157 $table[$tr][] = $lastExecution; 1158 $table[$tr][] = $nextDate; 1160 // The task object is not valid 1161 // Prepare to issue an error 1163 $flashMessage = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessage', sprintf($GLOBALS['LANG']->getLL('msg.invalidTaskClass'), $class), '', \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR); 1164 $executionStatusOutput = $flashMessage->render(); 1165 $tableLayout[$tr] = $rowWithSpan; 1166 $table[$tr][] = $startExecutionElement; 1167 $table[$tr][] = $deleteAction; 1168 $table[$tr][] = $schedulerRecord['uid']; 1169 $table[$tr][] = $executionStatusOutput; 1174 $this->getDatabaseConnection()->sql_free_result($res); 1177 $content .= $this->doc->table($table, $tableLayout); 1179 $content .= '<button name="go
" id="scheduler_executeselected
">' . 1180 IconUtility::getSpriteIcon('extensions-scheduler-run-task') . ' ' . 1181 $GLOBALS['LANG']->getLL('label.executeSelected') . '</button>'; 1183 if (!count($registeredClasses) > 0) { 1185 $flashMessage = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessage', $GLOBALS['LANG']->getLL('msg.noTasksDefined'), '', \TYPO3\CMS\Core\Messaging\FlashMessage::INFO); 1186 $content .= $flashMessage->render(); 1188 // Display legend, if there's at least one registered task 1189 // Also display information about the usage of server time 1191 $content .= $this->doc->spacer(20); 1192 $content .= '<h3>' . $GLOBALS['LANG']->getLL('status.legend') . '</h3> 1194 <li><img ' . IconUtility::skinImg(ExtensionManagementUtility::extRelPath('scheduler'), 'res/gfx/status_failure.png') . ' alt="' . htmlspecialchars($GLOBALS['LANG
']->getLL('status.failure
')) . '" title="' . htmlspecialchars($GLOBALS['LANG
']->getLL('status.failure
')) . '" /> ' . $GLOBALS['LANG']->getLL('status.legend.failure') . '</li> 1195 <li><img ' . IconUtility::skinImg(ExtensionManagementUtility::extRelPath('scheduler'), 'res/gfx/status_late.png') . ' alt="' . htmlspecialchars($GLOBALS['LANG
']->getLL('status.late
')) . '" title="' . htmlspecialchars($GLOBALS['LANG
']->getLL('status.late
')) . '" /> ' . $GLOBALS['LANG']->getLL('status.legend.late') . '</li> 1196 <li><img ' . IconUtility::skinImg(ExtensionManagementUtility::extRelPath('scheduler'), 'res/gfx/status_running.png') . ' alt="' . htmlspecialchars($GLOBALS['LANG
']->getLL('status.running
')) . '" title="' . htmlspecialchars($GLOBALS['LANG
']->getLL('status.running
')) . '" /> ' . $GLOBALS['LANG']->getLL('status.legend.running') . '</li> 1197 <li><img ' . IconUtility::skinImg(ExtensionManagementUtility::extRelPath('scheduler'), 'res/gfx/status_scheduled.png') . ' alt="' . htmlspecialchars($GLOBALS['LANG
']->getLL('status.scheduled
')) . '" title="' . htmlspecialchars($GLOBALS['LANG
']->getLL('status.scheduled
')) . '" /> ' . $GLOBALS['LANG']->getLL('status.legend.scheduled') . '</li> 1198 <li><img ' . IconUtility::skinImg(ExtensionManagementUtility::extRelPath('scheduler'), 'res/gfx/status_disabled.png') . ' alt="' . htmlspecialchars($GLOBALS['LANG
']->getLL('status.disabled
')) . '" title="' . htmlspecialchars($GLOBALS['LANG
']->getLL('status.disabled
')) . '" /> ' . $GLOBALS['LANG']->getLL('status.legend.disabled') . '</li> 1200 $content .= $this->displayServerTime(); 1210 protected function saveTask() { 1211 // If a task is being edited fetch old task data 1212 if (!empty($this->submittedData['uid'])) { 1214 $taskRecord = $this->scheduler->fetchTaskRecord($this->submittedData['uid']); 1216 $task = unserialize($taskRecord['serialized_task_object']); 1217 } catch (\OutOfBoundsException $e) { 1218 // If the task could not be fetched, issue an error message 1220 $this->addMessage(sprintf($GLOBALS['LANG']->getLL('msg.taskNotFound'), $this->submittedData['uid']), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR); 1223 // Register single execution 1224 if ($this->submittedData['type'] == 1) { 1225 $task->registerSingleExecution($this->submittedData['start']); 1227 if (!empty($this->submittedData['croncmd'])) { 1228 // Definition by cron-like syntax 1230 $cronCmd = $this->submittedData['croncmd']; 1232 // Definition by interval 1233 $interval = $this->submittedData['interval']; 1236 // Register recurring execution 1237 $task->registerRecurringExecution($this->submittedData['start'], $interval, $this->submittedData['end'], $this->submittedData['multiple'], $cronCmd); 1240 $task->setDisabled($this->submittedData['disable']); 1242 $task->setDescription($this->submittedData['description']); 1244 $task->setTaskGroup($this->submittedData['task_group']); 1245 // Save additional input values 1246 if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][$this->submittedData['class']]['additionalFields'])) { 1248 $providerObject = GeneralUtility::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][$this->submittedData['class']]['additionalFields']); 1249 if ($providerObject instanceof \TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface) { 1250 $providerObject->saveAdditionalFields($this->submittedData, $task); 1254 $result = $this->scheduler->saveTask($task); 1256 $GLOBALS['BE_USER']->writeLog(4, 0, 0, 0, 'Scheduler task "%s
" (UID: %s, Class: "%s
") was updated', array($task->getTaskTitle(), $task->getTaskUid(), $task->getTaskClassName())); 1257 $this->addMessage($GLOBALS['LANG']->getLL('msg.updateSuccess')); 1259 $this->addMessage($GLOBALS['LANG']->getLL('msg.updateError'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR); 1262 // A new task is being created 1263 // Create an instance of chosen class 1264 $task = GeneralUtility::makeInstance($this->submittedData['class']); 1265 if ($this->submittedData['type'] == 1) { 1266 // Set up single execution 1267 $task->registerSingleExecution($this->submittedData['start']); 1269 // Set up recurring execution 1270 $task->registerRecurringExecution($this->submittedData['start'], $this->submittedData['interval'], $this->submittedData['end'], $this->submittedData['multiple'], $this->submittedData['croncmd']); 1272 // Save additional input values 1273 if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][$this->submittedData['class']]['additionalFields'])) { 1275 $providerObject = GeneralUtility::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][$this->submittedData['class']]['additionalFields']); 1276 if ($providerObject instanceof \TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface) { 1277 $providerObject->saveAdditionalFields($this->submittedData, $task); 1281 $task->setDisabled($this->submittedData['disable']); 1283 $task->setDescription($this->submittedData['description']); 1285 $task->setTaskGroup($this->submittedData['task_group']); 1287 $result = $this->scheduler->addTask($task); 1289 $GLOBALS['BE_USER']->writeLog(4, 0, 0, 0, 'Scheduler task "%s
" (UID: %s, Class: "%s
") was added', array($task->getTaskTitle(), $task->getTaskUid(), $task->getTaskClassName())); 1290 $this->addMessage($GLOBALS['LANG']->getLL('msg.addSuccess')); 1292 // set the uid of the just created task so that we 1293 // can continue editing after initial saving 1294 $this->submittedData['uid'] = $task->getTaskUid(); 1296 $this->addMessage($GLOBALS['LANG']->getLL('msg.addError'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR); 1301 /************************* 1303 * INPUT PROCESSING UTILITIES 1305 *************************/ 1311 protected function preprocessData() { 1314 $this->submittedData['uid'] = empty($this->submittedData['uid']) ? 0 : (int)$this->submittedData['uid']; 1315 // Validate selected task class 1316 if (!class_exists($this->submittedData['class'])) { 1317 $this->addMessage($GLOBALS['LANG']->getLL('msg.noTaskClassFound'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR); 1320 if (empty($this->submittedData['start'])) { 1321 $this->addMessage($GLOBALS['LANG']->getLL('msg.noStartDate'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR); 1325 $timestamp = $this->checkDate($this->submittedData['start']); 1326 $this->submittedData['start'] = $timestamp; 1327 } catch (\Exception $e) { 1328 $this->addMessage($GLOBALS['LANG']->getLL('msg.invalidStartDate'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR); 1332 // Check end date, if recurring task 1333 if ($this->submittedData['type'] == 2 && !empty($this->submittedData['end'])) { 1335 $timestamp = $this->checkDate($this->submittedData['end']); 1336 $this->submittedData['end'] = $timestamp; 1337 if ($this->submittedData['end'] < $this->submittedData['start']) { 1338 $this->addMessage($GLOBALS['LANG']->getLL('msg.endDateSmallerThanStartDate'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR); 1341 } catch (\Exception $e) { 1342 $this->addMessage($GLOBALS['LANG']->getLL('msg.invalidEndDate'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR); 1346 // Set default values for interval and cron command 1347 $this->submittedData['interval'] = 0; 1348 $this->submittedData['croncmd'] = ''; 1349 // Check type and validity of frequency, if recurring 1350 if ($this->submittedData['type'] == 2) { 1351 $frequency = trim($this->submittedData['frequency']); 1352 if (empty($frequency)) { 1353 // Empty frequency, not valid 1354 $this->addMessage($GLOBALS['LANG']->getLL('msg.noFrequency'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR); 1358 $cronErrorMessage = ''; 1359 // Try interpreting the cron command 1361 \TYPO3\CMS\Scheduler\CronCommand\NormalizeCommand::normalize($frequency); 1362 $this->submittedData['croncmd'] = $frequency; 1363 } catch (\Exception $e) { 1364 // Store the exception's result 1365 $cronErrorMessage = $e->getMessage(); 1366 $cronErrorCode = $e->getCode(); 1367 // Check if the frequency is a valid number 1368 // If yes, assume it is a frequency in seconds, and unset cron error code 1369 if (is_numeric($frequency)) { 1370 $this->submittedData['interval'] = (int)$frequency; 1371 unset($cronErrorCode); 1374 // If there's a cron error code, issue validation error message 1375 if (!empty($cronErrorCode)) { 1376 $this->addMessage(sprintf($GLOBALS['LANG']->getLL('msg.frequencyError'), $cronErrorMessage, $cronErrorCode), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR); 1381 // Validate additional input fields 1382 if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][$this->submittedData['class']]['additionalFields'])) { 1384 $providerObject = GeneralUtility::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][$this->submittedData['class']]['additionalFields']); 1385 if ($providerObject instanceof \TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface) { 1386 // The validate method will return TRUE if all went well, but that must not 1387 // override previous FALSE values => AND the returned value with the existing one 1388 $result &= $providerObject->validateAdditionalFields($this->submittedData, $this); 1405 public function checkDate($string) { 1406 // Try with strtotime 1407 $timestamp = strtotime($string); 1408 // That failed. Try TYPO3's standard date/time input format 1409 if ($timestamp === FALSE) { 1410 // Split time and date 1411 $dateParts = GeneralUtility::trimExplode(' ', $string, TRUE); 1412 // Proceed if there are indeed two parts 1413 // Extract each component of date and time 1414 if (count($dateParts) == 2) { 1415 list($time, $date) = $dateParts; 1416 list($hour, $minutes) = GeneralUtility::trimExplode(':', $time, TRUE); 1417 list($day, $month, $year) = GeneralUtility::trimExplode('-', $date, TRUE); 1418 // Get a timestamp from all these parts 1419 $timestamp = @mktime($hour, $minutes, 0, $month, $day, $year); 1421 // If the timestamp is still FALSE, throw an exception 1422 if ($timestamp === FALSE) { 1423 throw new \InvalidArgumentException('"' . $string . '" seems not to be a correct date.', 1294587694); 1429 /************************* 1431 * APPLICATION LOGIC UTILITIES 1433 *************************/ 1441 public function addMessage($message, $severity = \TYPO3\CMS\Core\Messaging\FlashMessage::OK) { 1442 $flashMessage = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessage', $message, '', $severity); 1444 $flashMessageService = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessageService'); 1446 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); 1447 $defaultFlashMessageQueue->enqueue($flashMessage); 1463 static protected function getRegisteredClasses() { 1465 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'])) { 1466 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'] as $class => $registrationInformation) { 1467 $title = isset($registrationInformation['title']) ? $GLOBALS['LANG']->sL($registrationInformation['title']) : ''; 1468 $description = isset($registrationInformation['description']) ? $GLOBALS['LANG']->sL($registrationInformation['description']) : ''; 1469 $list[$class] = array( 1470 'extension' => $registrationInformation['extension'], 1472 'description' => $description, 1473 'provider' => isset($registrationInformation['additionalFields']) ? $registrationInformation['additionalFields'] : '' 1485 static protected function getRegisteredTaskGroups() { 1488 // Get all registered task groups 1491 'FROM' => 'tx_scheduler_task_group', 1493 . BackendUtility::BEenableFields('tx_scheduler_task_group') 1494 . BackendUtility::deleteClause('tx_scheduler_task_group'), 1495 'ORDERBY' => 'sorting' 1497 $res = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($query); 1499 while (($groupRecord = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) !== FALSE) { 1500 $list[] = $groupRecord; 1502 $GLOBALS['TYPO3_DB']->sql_free_result($res); 1507 /************************* 1509 * RENDERING UTILITIES 1511 *************************/ 1517 protected function getTemplateMarkers() { 1519 'CSH' => BackendUtility::wrapInHelp('_MOD_system_txschedulerM1', ''), 1520 'FUNC_MENU' => $this->getFunctionMenu(), 1521 'CONTENT' => $this->content, 1522 'TITLE' => $GLOBALS['LANG']->getLL('title') 1532 protected function getFunctionMenu() { 1533 $functionMenu = BackendUtility::getFuncMenu(0, 'SET[function]', $this->MOD_SETTINGS['function'], $this->MOD_MENU['function']); 1534 return $functionMenu; 1542 protected function getDocHeaderButtons() { 1551 'shortcut' => $this->getShortcutButton() 1553 if (empty($this->CMD) || $this->CMD == 'list' || $this->CMD == 'delete' || $this->CMD == 'stop') { 1554 $buttons['reload'] = '<a href="' . $GLOBALS['MCONF
']['_
'] . '" title="' . $GLOBALS['LANG
']->sL('LLL:EXT:lang/locallang_core.xlf:labels.reload
', TRUE) . '">' . IconUtility::getSpriteIcon('actions-system-refresh') . '</a>'; 1555 if ($this->MOD_SETTINGS['function'] === 'scheduler' && count(self::getRegisteredClasses())) { 1556 $link = $GLOBALS['MCONF']['_'] . '&CMD=add'; 1557 $image = IconUtility::getSpriteIcon('actions-document-new', array('alt' => $GLOBALS['LANG']->getLL('action.add'))); 1558 $buttons['addtask'] = '<a href="' . htmlspecialchars($link) . '" ' . 'title="' . $GLOBALS['LANG
']->getLL('action.add
') . '">' . $image . '</a>'; 1561 if ($this->CMD === 'add' || $this->CMD === 'edit') { 1562 $buttons['close'] = '<a href="#
" onclick="document.location=\
'' .
$GLOBALS[
'MCONF'][
'_'] .
'\'" title="' . $GLOBALS['LANG
']->sL('LLL:EXT:lang/locallang_common.xlf:cancel
', TRUE) . '">' . IconUtility::getSpriteIcon('actions-document-close') . '</a>'; 1563 $buttons['save'] = '<button style="padding: 0; margin: 0; cursor: pointer;
" type="submit
" name="CMD
" value="save
" class="c-inputButton
" src="clear.gif
" title="' . $GLOBALS['LANG
']->sL('LLL:EXT:lang/locallang_common.xlf:save
', TRUE) . '" />' . IconUtility::getSpriteIcon('actions-document-save') . '</button>'; 1564 $buttons['saveclose'] = '<button style="padding: 0; margin: 0; cursor: pointer;
" type="submit
" name="CMD
" value="saveclose
" class="c-inputButton
" src="clear.gif
" title="' . $GLOBALS['LANG
']->sL('LLL:EXT:lang/locallang_common.xlf:saveAndClose
', TRUE) . '" />' . IconUtility::getSpriteIcon('actions-document-save-close') . '</button>'; 1565 $buttons['savenew'] = '<button style="padding: 0; margin: 0; cursor: pointer;
" type="submit
" name="CMD
" value="savenew
" class="c-inputButton
" src="clear.gif
" title="' . $GLOBALS['LANG
']->sL('LLL:EXT:lang/locallang_common.xlf:saveAndCreateNewDoc
', TRUE) . '" />' . IconUtility::getSpriteIcon('actions-document-save-new') . '</button>'; 1567 if ($this->CMD === 'edit') { 1568 $buttons['delete'] = '<button style="padding: 0; margin: 0; cursor: pointer;
" type="submit
" name="CMD
" value="delete" class="c-inputButton
" src="clear.gif
" title="' . $GLOBALS['LANG
']->sL('LLL:EXT:lang/locallang_common.xlf:
delete', TRUE) . '" />' . IconUtility::getSpriteIcon('actions-edit-delete') . '</button>'; 1578 protected function getShortcutButton() { 1580 if ($GLOBALS['BE_USER']->mayMakeShortcut()) { 1581 $result = $this->doc->makeShortcutIcon('', 'function', $this->MCONF['name']); 1591 protected function getBackendUserAuthentication() { 1592 return $GLOBALS['BE_USER']; 1600 protected function getDatabaseConnection() { 1601 return $GLOBALS['TYPO3_DB'];
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=TRUE, $includeEmptyValues=TRUE, $enableUnsetFeature=TRUE)
renderTaskProgressBar($progress)
static extPath($key, $script='')
static getSaltingInstance($saltedHash='', $mode=TYPO3_MODE)
static getUserObj($classRef, $checkPrefix='', $silent=FALSE)
static makeInstance($className)
static wrapInHelp($table, $field, $text='', array $overloadHelpText=array())
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren't numeric.
static getSpriteIcon($iconName, array $options=array(), array $overlays=array())
static _GPmerged($parameter)
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
static isUsageEnabled($mode=TYPO3_MODE)
static BEenableFields($table, $inv=0)
static deleteClause($table, $tableAlias='')