2 namespace TYPO3\CMS\Scheduler\Controller;
99 $this->
getLanguageService()->includeLLFile(
'EXT:scheduler/Resources/Private/Language/locallang.xlf');
100 $this->MCONF = array(
101 'name' => $this->moduleName,
106 $this->view->getRequest()->setControllerExtensionName(
'scheduler');
107 $this->moduleUri = BackendUtility::getModuleUrl($this->moduleName);
110 $pageRenderer->loadRequireJsModule(
'TYPO3/CMS/Backend/Modal');
111 $pageRenderer->loadRequireJsModule(
'TYPO3/CMS/Backend/SplitButtons');
134 $this->MOD_MENU = array(
141 parent::menuConfig();
155 $this->content =
'<form name="tx_scheduler_form" id="tx_scheduler_form" method="post" action="">';
158 $this->content .=
'<h1>' . $this->
getLanguageService()->getLL(
'function.' . $this->MOD_SETTINGS[
'function']) .
'</h1>';
160 $this->content .=
'</form>';
164 $this->content .=
'<div style="padding-top: 5px;"></div>';
175 $menu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
176 $menu->setIdentifier(
'SchedulerJumpMenu');
178 foreach ($this->MOD_MENU[
'function'] as $controller => $title) {
182 BackendUtility::getModuleUrl(
187 'function' => $controller
193 if ($controller === $this->MOD_SETTINGS[
'function']) {
194 $item->setActive(
true);
196 $menu->addMenuItem($item);
198 $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($menu);
212 $this->submittedData[
'uid'] = (int)$this->submittedData[
'uid'];
214 if ($this->CMD ===
'save' || $this->CMD ===
'saveclose' || $this->CMD ===
'savenew') {
217 $result = $this->preprocessData();
221 if ($this->CMD ===
'saveclose') {
224 }
elseif ($this->CMD ===
'save') {
227 }
elseif ($this->CMD ===
'savenew') {
229 unset($this->submittedData);
234 $this->CMD = $previousCMD;
237 $this->CMD = $previousCMD;
242 switch ((
string)$this->MOD_SETTINGS[
'function']) {
246 switch ($this->CMD) {
251 $content .= $this->editTaskAction();
253 }
catch (\Exception $e) {
254 if ($e->getCode() === 1305100019) {
262 $content .= $this->listTasksAction();
267 $content .= $this->listTasksAction();
271 $content .= $this->listTasksAction();
275 $content .= $this->listTasksAction();
280 $content .= $this->listTasksAction();
287 $content .= $this->checkScreenAction();
296 return '<h2>' . $sectionTitle .
'</h2><div class="tx_scheduler_mod1">' .
$content .
'</div>';
313 $this->moduleTemplate->setContent($this->content);
314 $response->
getBody()->write($this->moduleTemplate->renderContent());
339 $schedulerUserStatus = -1;
345 $schedulerUserStatus = 0;
350 $schedulerUserStatus = 1;
354 return $schedulerUserStatus;
362 protected function createSchedulerUser()
370 if ($checkUser == -1) {
375 $password = $objInstanceSaltedPW->getHashedPassword($password);
377 $data = array(
'be_users' => array(
'NEW' => array(
'username' =>
'_cli_scheduler',
'password' => $password,
'pid' => 0)));
380 $tcemain->stripslashes_values = 0;
381 $tcemain->start($data, array());
382 $tcemain->process_datamap();
385 $numberOfNewIDs = count($tcemain->substNEWwithIDs);
386 if ($numberOfNewIDs === 1) {
403 protected function checkScreenAction()
405 $this->view->setTemplatePathAndFilename($this->backendTemplatePath .
'CheckScreen.html');
408 if ($this->CMD ===
'user') {
409 $this->createSchedulerUser();
415 $lastRun =
$registry->get(
'tx_scheduler',
'lastRun');
416 if (!is_array($lastRun)) {
420 if (empty($lastRun[
'end']) || empty($lastRun[
'start']) || empty($lastRun[
'type'])) {
424 $startDate = date(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'], $lastRun[
'start']);
425 $startTime = date(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'hhmm'], $lastRun[
'start']);
426 $endDate = date(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'], $lastRun[
'end']);
427 $endTime = date(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'hhmm'], $lastRun[
'end']);
428 $label =
'automatically';
429 if ($lastRun[
'type'] ===
'manual') {
433 $message = sprintf($this->
getLanguageService()->getLL(
'msg.lastRun'), $type, $startDate, $startTime, $endDate, $endTime);
437 $this->view->assign(
'lastRunMessage', $message);
438 $this->view->assign(
'lastRunSeverity', $severity);
442 if ($checkUser == -1) {
443 $link = $this->moduleUri .
'&SET[function]=check&CMD=user';
444 $message = sprintf($this->
getLanguageService()->getLL(
'msg.schedulerUserMissing'), htmlspecialchars($link));
446 }
elseif ($checkUser == 0) {
453 $this->view->assign(
'cliUserMessage', $message);
454 $this->view->assign(
'cliUserSeverity', $severity);
457 $script = PATH_typo3 .
'cli_dispatch.phpsh';
458 $this->view->assign(
'script', $script);
462 if (TYPO3_OS ===
'WIN') {
463 $isExecutable =
true;
465 $isExecutable = is_executable($script);
474 $this->view->assign(
'isExecutableMessage', $message);
475 $this->view->assign(
'isExecutableSeverity', $severity);
477 return $this->view->render();
489 if (empty($registeredClasses)) {
490 $this->view->setTemplatePathAndFilename($this->backendTemplatePath .
'InfoScreenNoClasses.html');
491 return $this->view->render();
494 $this->view->setTemplatePathAndFilename($this->backendTemplatePath .
'InfoScreen.html');
495 $this->view->assign(
'registeredClasses', $registeredClasses);
497 return $this->view->render();
508 $progressText = $this->
getLanguageService()->getLL(
'status.progress') .
': ' . $progress .
'%';
509 return '<div class="progress">'
510 .
'<div class="progress-bar progress-bar-striped" role="progressbar" aria-valuenow="' . $progress .
'" aria-valuemin="0" aria-valuemax="100" style="width: ' . $progress .
'%;">' . $progressText .
'</div>'
523 $task = $this->scheduler->fetchTask($this->submittedData[
'uid']);
525 if ($task->isExecutionRunning()) {
528 if ($this->scheduler->removeTask($task)) {
529 $this->
getBackendUser()->writeLog(4, 0, 0, 0,
'Scheduler task "%s" (UID: %s, Class: "%s") was deleted', array($task->getTaskTitle(), $task->getTaskUid(), $task->getTaskClassName()));
535 }
catch (\UnexpectedValueException $e) {
537 $result = $this->
getDatabaseConnection()->exec_DELETEquery(
'tx_scheduler_task',
'uid = ' . (
int)$this->submittedData[
'uid']);
543 }
catch (\OutOfBoundsException $e) {
561 $task = $this->scheduler->fetchTask($this->submittedData[
'uid']);
562 if ($task->isExecutionRunning()) {
564 $result = $task->unmarkAllExecutions();
574 }
catch (\Exception $e) {
587 $task = $this->scheduler->fetchTask($this->submittedData[
'uid']);
588 $task->setDisabled(!$task->isDisabled());
597 protected function editTaskAction()
599 $this->view->setTemplatePathAndFilename($this->backendTemplatePath .
'EditTask.html');
608 if ($this->submittedData[
'uid'] > 0) {
611 $taskRecord = $this->scheduler->fetchTaskRecord($this->submittedData[
'uid']);
613 if (!empty($taskRecord[
'serialized_executions'])) {
615 throw new \LogicException(
'Runnings tasks cannot not be edited', 1251232849);
620 $task = unserialize($taskRecord[
'serialized_task_object']);
623 $taskInfo[
'disable'] = $taskRecord[
'disable'];
624 $taskInfo[
'description'] = $taskRecord[
'description'];
625 $taskInfo[
'task_group'] = $taskRecord[
'task_group'];
628 if (isset($registeredClasses[get_class($task)]) && $this->scheduler->isValidTaskObject($task)) {
630 $taskInfo[
'class'] = get_class($task);
632 $taskInfo[
'start'] = (int)$task->getExecution()->getStart();
633 $taskInfo[
'end'] = (int)$task->getExecution()->getEnd();
634 $taskInfo[
'interval'] = $task->getExecution()->getInterval();
635 $taskInfo[
'croncmd'] = $task->getExecution()->getCronCmd();
636 $taskInfo[
'multiple'] = $task->getExecution()->getMultiple();
637 if (!empty($taskInfo[
'interval']) || !empty($taskInfo[
'croncmd'])) {
641 $taskInfo[
'type'] = 2;
642 $taskInfo[
'frequency'] = $taskInfo[
'interval'] ?: $taskInfo[
'croncmd'];
646 $taskInfo[
'type'] = 1;
647 $taskInfo[
'frequency'] =
'';
648 $taskInfo[
'end'] = 0;
655 $taskInfo[
'start'] = 0;
656 $taskInfo[
'end'] = 0;
657 $taskInfo[
'frequency'] =
'';
658 $taskInfo[
'multiple'] =
false;
659 $taskInfo[
'type'] = 1;
661 }
catch (\OutOfBoundsException $e) {
668 $taskInfo[
'class'] = key($registeredClasses);
669 $taskInfo[
'type'] = 2;
670 $taskInfo[
'start'] =
$GLOBALS[
'EXEC_TIME'];
671 $taskInfo[
'end'] =
'';
672 $taskInfo[
'frequency'] =
'';
673 $taskInfo[
'multiple'] = 0;
679 if (!empty($this->submittedData)) {
680 \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($taskInfo, $this->submittedData);
684 $allAdditionalFields = array();
685 if ($process ===
'add') {
686 foreach ($registeredClasses as $class => $registrationInfo) {
687 if (!empty($registrationInfo[
'provider'])) {
690 if ($providerObject instanceof \TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface) {
691 $additionalFields = $providerObject->getAdditionalFields($taskInfo, null, $this);
692 $allAdditionalFields = array_merge($allAdditionalFields, array($class => $additionalFields));
697 if (!empty($registeredClasses[$taskInfo[
'class']][
'provider'])) {
699 if ($providerObject instanceof \TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface) {
700 $allAdditionalFields[$taskInfo[
'class']] = $providerObject->getAdditionalFields($taskInfo, $task, $this);
707 $this->
getPageRenderer()->loadRequireJsModule(
'TYPO3/CMS/Scheduler/Scheduler');
708 $this->
getPageRenderer()->loadRequireJsModule(
'TYPO3/CMS/Backend/DateTimePicker');
711 $this->view->assign(
'uid', htmlspecialchars($this->submittedData[
'uid']));
712 $this->view->assign(
'cmd', htmlspecialchars($this->CMD));
717 $label =
'<label for="task_disable">' . $this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:disable') .
'</label>';
719 '<div class="form-section" id="task_disable_row"><div class="form-group">'
720 . BackendUtility::wrapInHelp($this->cshKey,
'task_disable', $label)
721 .
'<div class="form-control-wrap">'
722 .
'<input type="hidden" name="tx_scheduler[disable]" value="0">'
723 .
'<input class="checkbox" type="checkbox" name="tx_scheduler[disable]" value="1" id="task_disable" ' . ($taskInfo[
'disable'] ?
' checked="checked"' :
'') .
'>'
728 $label =
'<label for="task_class">' . $this->
getLanguageService()->getLL(
'label.class') .
'</label>';
731 if ($this->submittedData[
'uid'] > 0 && !empty($taskInfo[
'class'])) {
732 $cell =
'<div>' . $registeredClasses[$taskInfo[
'class']][
'title'] .
' (' . $registeredClasses[$taskInfo[
'class']][
'extension'] .
')</div>';
733 $cell .=
'<input type="hidden" name="tx_scheduler[class]" id="task_class" value="' . htmlspecialchars($taskInfo[
'class']) .
'">';
735 $cell =
'<select name="tx_scheduler[class]" id="task_class" class="form-control">';
737 $groupedClasses = array();
738 foreach ($registeredClasses as $class => $classInfo) {
739 $groupedClasses[$classInfo[
'extension']][$class] = $classInfo;
741 ksort($groupedClasses);
743 foreach ($groupedClasses as $extension => $class) {
744 $cell .=
'<optgroup label="' . htmlspecialchars($extension) .
'">';
745 foreach ($groupedClasses[$extension] as $class => $classInfo) {
746 $selected = $class == $taskInfo[
'class'] ?
' selected="selected"' :
'';
747 $cell .=
'<option value="' . htmlspecialchars($class) .
'"' .
'title="' . htmlspecialchars($classInfo[
'description']) .
'" ' . $selected .
'>' . htmlspecialchars($classInfo[
'title']) .
'</option>';
749 $cell .=
'</optgroup>';
751 $cell .=
'</select>';
754 '<div class="form-section" id="task_class_row"><div class="form-group">'
755 . BackendUtility::wrapInHelp($this->cshKey,
'task_class', $label)
756 .
'<div class="form-control-wrap">'
762 $label =
'<label for="task_type">' . $this->
getLanguageService()->getLL(
'label.type') .
'</label>';
764 '<div class="form-section" id="task_type_row"><div class="form-group">'
765 . BackendUtility::wrapInHelp($this->cshKey,
'task_type', $label)
766 .
'<div class="form-control-wrap">'
767 .
'<select name="tx_scheduler[type]" id="task_type" class="form-control">'
768 .
'<option value="1" ' . ((int)$taskInfo[
'type'] === 1 ?
' selected="selected"' :
'') .
'>' . $this->
getLanguageService()->getLL(
'label.type.single') .
'</option>'
769 .
'<option value="2" ' . ((int)$taskInfo[
'type'] === 2 ?
' selected="selected"' :
'') .
'>' . $this->
getLanguageService()->getLL(
'label.type.recurring') .
'</option>'
775 $label =
'<label for="task_group">' . $this->
getLanguageService()->getLL(
'label.group') .
'</label>';
776 $cell =
'<select name="tx_scheduler[task_group]" id="task_class" class="form-control">';
779 $cell .=
'<option value="0" title=""></option>';
780 foreach ($registeredTaskGroups as $taskGroup) {
781 $selected = $taskGroup[
'uid'] == $taskInfo[
'task_group'] ?
' selected="selected"' :
'';
782 $cell .=
'<option value="' . $taskGroup[
'uid'] .
'"' .
'title="';
783 $cell .= htmlspecialchars($taskGroup[
'groupName']) .
'"' . $selected .
'>';
784 $cell .= htmlspecialchars($taskGroup[
'groupName']) .
'</option>';
786 $cell .=
'</select>';
789 '<div class="form-section" id="task_group_row"><div class="form-group">'
790 . BackendUtility::wrapInHelp($this->cshKey,
'task_group', $label)
791 .
'<div class="form-control-wrap">'
796 $dateFormat =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'USdateFormat'] ?
'%H:%M %m-%d-%Y' :
'%H:%M %d-%m-%Y';
798 $label =
'<label for="tceforms-datetimefield-task_start">' . BackendUtility::wrapInHelp($this->cshKey,
'task_start', $this->
getLanguageService()->getLL(
'label.start')) .
'</label>';
799 $value = ($taskInfo[
'start'] > 0 ? strftime($dateFormat, $taskInfo[
'start']) :
'');
801 '<div class="form-section"><div class="row"><div class="form-group col-sm-6">'
803 .
'<div class="form-control-wrap">'
804 .
'<div class="input-group" id="tceforms-datetimefield-task_start_row-wrapper">'
805 .
'<input name="tx_scheduler[start]_hr" value="' . $value .
'" class="form-control t3js-datetimepicker t3js-clearable" data-date-type="datetime" data-date-offset="0" type="text" id="tceforms-datetimefield-task_start_row">'
806 .
'<input name="tx_scheduler[start]" value="' . $taskInfo[
'start'] .
'" type="hidden">'
807 .
'<span class="input-group-btn"><label class="btn btn-default" for="tceforms-datetimefield-task_start_row"><span class="fa fa-calendar"></span></label></span>'
814 $value = ($taskInfo[
'end'] > 0 ? strftime($dateFormat, $taskInfo[
'end']) :
'');
815 $label =
'<label for="tceforms-datetimefield-task_end">' . $this->
getLanguageService()->getLL(
'label.end') .
'</label>';
817 '<div class="form-group col-sm-6">'
818 . BackendUtility::wrapInHelp($this->cshKey,
'task_end', $label)
819 .
'<div class="form-control-wrap">'
820 .
'<div class="input-group" id="tceforms-datetimefield-task_end_row-wrapper">'
821 .
'<input name="tx_scheduler[end]_hr" value="' . $value .
'" class="form-control t3js-datetimepicker t3js-clearable" data-date-type="datetime" data-date-offset="0" type="text" id="tceforms-datetimefield-task_end_row">'
822 .
'<input name="tx_scheduler[end]" value="' . $taskInfo[
'end'] .
'" type="hidden">'
823 .
'<span class="input-group-btn"><label class="btn btn-default" for="tceforms-datetimefield-task_end_row"><span class="fa fa-calendar"></span></label></span>'
826 .
'</div></div></div>';
829 $label =
'<label for="task_frequency">' . $this->
getLanguageService()->getLL(
'label.frequency.long') .
'</label>';
831 '<div class="form-section" id="task_frequency_row"><div class="form-group">'
832 . BackendUtility::wrapInHelp($this->cshKey,
'task_frequency', $label)
833 .
'<div class="form-control-wrap">'
834 .
'<input type="text" name="tx_scheduler[frequency]" class="form-control" id="task_frequency" value="' . htmlspecialchars($taskInfo[
'frequency']) .
'">'
839 $label =
'<label for="task_multiple">' . $this->
getLanguageService()->getLL(
'label.parallel.long') .
'</label>';
841 '<div class="form-section" id="task_multiple_row"><div class="form-group">'
842 . BackendUtility::wrapInHelp($this->cshKey,
'task_multiple', $label)
843 .
'<div class="form-control-wrap">'
844 .
'<input type="hidden" name="tx_scheduler[multiple]" value="0">'
845 .
'<input class="checkbox" type="checkbox" name="tx_scheduler[multiple]" value="1" id="task_multiple" ' . ($taskInfo[
'multiple'] ?
'checked="checked"' :
'') .
'>'
850 $label =
'<label for="task_description">' . $this->
getLanguageService()->getLL(
'label.description') .
'</label>';
852 '<div class="form-section" id="task_description_row"><div class="form-group">'
853 . BackendUtility::wrapInHelp($this->cshKey,
'task_description', $label)
854 .
'<div class="form-control-wrap">'
855 .
'<textarea class="form-control" name="tx_scheduler[description]">' . htmlspecialchars($taskInfo[
'description']) .
'</textarea>'
860 foreach ($allAdditionalFields as $class => $fields) {
861 if ($class == $taskInfo[
'class']) {
862 $additionalFieldsStyle =
'';
864 $additionalFieldsStyle =
' style="display: none"';
867 if (isset($fields) && is_array($fields)) {
868 foreach ($fields as $fieldID => $fieldInfo) {
869 $label =
'<label for="' . $fieldID .
'">' . $this->
getLanguageService()->sL($fieldInfo[
'label']) .
'</label>';
870 $htmlClassName = strtolower(str_replace(
'\\',
'-', $class));
873 '<div class="form-section extraFields extra_fields_' . $htmlClassName .
'" ' . $additionalFieldsStyle .
' id="' . $fieldID .
'_row"><div class="form-group">'
874 . BackendUtility::wrapInHelp($fieldInfo[
'cshKey'], $fieldInfo[
'cshLabel'], $label)
875 .
'<div class="form-control-wrap">' . $fieldInfo[
'code'] .
'</div>'
881 $this->view->assign(
'table', implode(LF, $table));
884 $dateFormat =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'] .
' ' .
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'hhmm'] .
' T (e';
885 $this->view->assign(
'now', date($dateFormat) .
', GMT ' . date(
'P') .
')');
887 return $this->view->render();
899 $this->scheduler->scheduleNextSchedulerRunUsingAtDaemon();
902 if (isset($this->submittedData[
'execute']) && !empty($this->submittedData[
'execute'])) {
906 foreach ($this->submittedData[
'execute'] as $uid) {
909 $task = $this->scheduler->fetchTask($uid);
910 $class = get_class($task);
911 $name = $registeredClasses[$class][
'title'] .
' (' . $registeredClasses[$class][
'extension'] .
')';
914 $result = $this->scheduler->executeTask($task);
920 }
catch (\Exception $e) {
924 }
catch (\OutOfBoundsException $e) {
926 }
catch (\UnexpectedValueException $e) {
931 $this->scheduler->recordLastRun(
'manual');
942 protected function listTasksAction()
944 $this->view->setTemplatePathAndFilename($this->backendTemplatePath .
'ListTasks.html');
947 $dateFormat =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'] .
' ' .
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'hhmm'];
956 array_unshift($registeredTaskGroups, array(
'uid' => 0,
'groupName' =>
''));
963 tx_scheduler_task_group.groupName as taskGroupName,
964 tx_scheduler_task_group.description as taskGroupDescription,
965 tx_scheduler_task_group.deleted as isTaskGroupDeleted
969 LEFT JOIN tx_scheduler_task_group ON tx_scheduler_task_group.uid = tx_scheduler_task.task_group
972 'ORDERBY' =>
'tx_scheduler_task_group.sorting'
979 $this->view->setTemplatePathAndFilename($this->backendTemplatePath .
'ListTasksNoTasks.html');
980 return $this->view->render();
983 $this->
getPageRenderer()->loadRequireJsModule(
'TYPO3/CMS/Scheduler/Scheduler');
988 .
'<th><a href="#" id="checkall" title="' . $this->
getLanguageService()->getLL(
'label.checkAll',
true) .
'" class="icon">' . $this->moduleTemplate->getIconFactory()->getIcon(
'actions-document-select',
Icon::SIZE_SMALL)->render() .
'</a></th>'
1000 $temporaryResult = array();
1002 if ($row[
'taskGroupName'] === null || $row[
'isTaskGroupDeleted'] ===
'1') {
1003 $row[
'taskGroupName'] =
'';
1004 $row[
'taskGroupDescription'] =
'';
1005 $row[
'task_group'] = 0;
1007 $temporaryResult[$row[
'task_group']][
'groupName'] = $row[
'taskGroupName'];
1008 $temporaryResult[$row[
'task_group']][
'groupDescription'] = $row[
'taskGroupDescription'];
1009 $temporaryResult[$row[
'task_group']][
'tasks'][] = $row;
1012 foreach ($temporaryResult as $taskGroup) {
1013 if (!empty($taskGroup[
'groupName'])) {
1014 $groupText =
'<strong>' . htmlspecialchars($taskGroup[
'groupName']) .
'</strong>';
1015 if (!empty($taskGroup[
'groupDescription'])) {
1016 $groupText .=
'<br>' . nl2br(htmlspecialchars($taskGroup[
'groupDescription']));
1018 $table[] =
'<tr><td colspan="9">' . $groupText .
'</td></tr>';
1021 foreach ($taskGroup[
'tasks'] as $schedulerRecord) {
1022 $link = htmlspecialchars($this->moduleUri .
'&CMD=edit&tx_scheduler[uid]=' . $schedulerRecord[
'uid']);
1023 $editAction =
'<a class="btn btn-default" href="' . $link .
'" title="' . $this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:edit',
true) .
'" class="icon">' .
1024 $this->moduleTemplate->getIconFactory()->getIcon(
'actions-document-open',
Icon::SIZE_SMALL)->render() .
'</a>';
1025 if ((
int)$schedulerRecord[
'disable'] === 1) {
1026 $translationKey =
'enable';
1027 $icon = $this->moduleTemplate->getIconFactory()->getIcon(
'actions-edit-unhide',
Icon::SIZE_SMALL);
1029 $translationKey =
'disable';
1030 $icon = $this->moduleTemplate->getIconFactory()->getIcon(
'actions-edit-hide',
Icon::SIZE_SMALL);
1032 $toggleHiddenAction =
'<a class="btn btn-default" href="' . htmlspecialchars($this->moduleUri
1033 .
'&CMD=toggleHidden&tx_scheduler[uid]=' . $schedulerRecord[
'uid']) .
'" title="'
1034 . $this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:' . $translationKey,
true)
1035 .
'" class="icon">' . $icon->render() .
'</a>';
1036 $deleteAction =
'<a class="btn btn-default t3js-modal-trigger" href="' . htmlspecialchars($this->moduleUri .
'&CMD=delete&tx_scheduler[uid]=' . $schedulerRecord[
'uid']) .
'" '
1037 .
' data-severity="warning"'
1038 .
' data-title="' . $this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:delete',
true) .
'"'
1039 .
' data-button-close-text="' . $this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:cancel',
true) .
'"'
1041 .
' title="' . $this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:delete',
true) .
'" class="icon">' .
1042 $this->moduleTemplate->getIconFactory()->getIcon(
'actions-edit-delete',
Icon::SIZE_SMALL)->render() .
'</a>';
1043 $stopAction =
'<a class="btn btn-default t3js-modal-trigger" href="' . htmlspecialchars($this->moduleUri .
'&CMD=stop&tx_scheduler[uid]=' . $schedulerRecord[
'uid']) .
'" '
1044 .
' data-severity="warning"'
1045 .
' data-title="' . $this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:stop',
true) .
'"'
1046 .
' data-button-close-text="' . $this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:cancel',
true) .
'"'
1048 .
' title="' . $this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:stop',
true) .
'" class="icon">' .
1049 $this->moduleTemplate->getIconFactory()->getIcon(
'actions-document-close',
Icon::SIZE_SMALL)->render() .
'</a>';
1050 $runAction =
'<a class="btn btn-default" href="' . htmlspecialchars($this->moduleUri .
'&tx_scheduler[execute][]=' . $schedulerRecord[
'uid']) .
'" title="' . $this->
getLanguageService()->getLL(
'action.run_task',
true) .
'" class="icon">' .
1051 $this->moduleTemplate->getIconFactory()->getIcon(
'extensions-scheduler-run-task',
Icon::SIZE_SMALL)->render() .
'</a>';
1054 $lastExecution =
'-';
1056 $showAsDisabled =
false;
1057 $startExecutionElement =
'<span class="btn btn-default disabled">' . $this->moduleTemplate->getIconFactory()->getIcon(
'empty-empty',
Icon::SIZE_SMALL)->render() .
'</span>';
1060 $task = unserialize($schedulerRecord[
'serialized_task_object']);
1061 $class = get_class($task);
1062 if ($class ===
'__PHP_Incomplete_Class' && preg_match(
'/^O:[0-9]+:"(?P<classname>.+?)"/', $schedulerRecord[
'serialized_task_object'], $matches) === 1) {
1063 $class = $matches[
'classname'];
1066 if (!empty($schedulerRecord[
'lastexecution_time'])) {
1067 $lastExecution = date($dateFormat, $schedulerRecord[
'lastexecution_time']);
1068 if ($schedulerRecord[
'lastexecution_context'] ==
'CLI') {
1073 $lastExecution .=
' (' . $context .
')';
1076 if (isset($registeredClasses[get_class($task)]) && $this->scheduler->isValidTaskObject($task)) {
1079 $name = htmlspecialchars($registeredClasses[$class][
'title'] .
' (' . $registeredClasses[$class][
'extension'] .
')');
1080 $additionalInformation = $task->getAdditionalInformation();
1081 if ($task instanceof \TYPO3\CMS\Scheduler\ProgressProviderInterface) {
1082 $progress = round(floatval($task->getProgress()), 2);
1085 if (!empty($additionalInformation)) {
1086 $name .=
'<div class="additional-information">' . nl2br(htmlspecialchars($additionalInformation)) .
'</div>';
1089 if (!empty($schedulerRecord[
'serialized_executions'])) {
1091 'class' =>
'success',
1100 if ($isRunning || $schedulerRecord[
'disable']) {
1103 $nextDate = date($dateFormat, $schedulerRecord[
'nextexecution']);
1104 if (empty($schedulerRecord[
'nextexecution'])) {
1106 }
elseif ($schedulerRecord[
'nextexecution'] <
$GLOBALS[
'EXEC_TIME']) {
1108 'class' =>
'warning',
1115 if ($task->getExecution()->getInterval() == 0 && $task->getExecution()->getCronCmd() ==
'') {
1120 if ($task->getExecution()->getCronCmd() ==
'') {
1121 $frequency = $task->getExecution()->getInterval();
1123 $frequency = $task->getExecution()->getCronCmd();
1127 if ($task->getExecution()->getMultiple()) {
1128 $multiple = $this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:yes');
1133 $startExecutionElement =
'<label class="btn btn-default btn-checkbox"><input type="checkbox" name="tx_scheduler[execute][]" value="' . $schedulerRecord[
'uid'] .
'" id="task_' . $schedulerRecord[
'uid'] .
'"><span class="t3-icon fa"></span></label>';
1135 $actions = $editAction . $toggleHiddenAction . $deleteAction;
1139 if ($schedulerRecord[
'disable'] && !$isRunning) {
1141 'class' =>
'default',
1144 $showAsDisabled =
true;
1149 $actions = $stopAction;
1151 $actions .= $runAction;
1155 if (!empty($schedulerRecord[
'lastexecution_failure'])) {
1158 $exceptionArray = @unserialize($schedulerRecord[
'lastexecution_failure']);
1160 if (!is_array($exceptionArray) || empty($exceptionArray)) {
1161 $labelDescription = $this->
getLanguageService()->getLL(
'msg.executionFailureDefault');
1163 $labelDescription = sprintf($this->
getLanguageService()->getLL(
'msg.executionFailureReport'), $exceptionArray[
'code'], $exceptionArray[
'message']);
1166 'class' =>
'danger',
1168 'description' => $labelDescription
1174 if ($schedulerRecord[
'description'] !==
'') {
1175 $taskDesc =
'<span class="description">' . nl2br(htmlspecialchars($schedulerRecord[
'description'])) .
'</span>';
1177 $taskName =
'<span class="name"><a href="' . $link .
'">' . $name .
'</a></span>';
1180 '<tr class="' . ($showAsDisabled ?
'disabled' :
'') .
'">'
1181 .
'<td>' . $startExecutionElement .
'</td>'
1182 .
'<td class="right">' . $schedulerRecord[
'uid'] .
'</td>'
1183 .
'<td>' . $this->
makeStatusLabel($labels) . $taskName . $taskDesc .
'</td>'
1184 .
'<td>' . $execType .
'</td>'
1185 .
'<td>' . $frequency .
'</td>'
1186 .
'<td>' . $multiple .
'</td>'
1187 .
'<td>' . $lastExecution .
'</td>'
1188 .
'<td>' . $nextDate .
'</td>'
1189 .
'<td nowrap="nowrap"><div class="btn-group" role="group">' . $actions .
'</div></td>'
1196 $executionStatusOutput = $flashMessage->render();
1199 .
'<td>' . $startExecutionElement .
'</td>'
1200 .
'<td class="right">' . $schedulerRecord[
'uid'] .
'</td>'
1201 .
'<td colspan="6">' . $executionStatusOutput .
'</td>'
1202 .
'<td nowrap="nowrap"><div class="btn-group" role="group">'
1203 .
'<span class="btn btn-default disabled">' . $this->moduleTemplate->getIconFactory()->getIcon(
'empty-empty',
Icon::SIZE_SMALL)->render() .
'</span>'
1204 .
'<span class="btn btn-default disabled">' . $this->moduleTemplate->getIconFactory()->getIcon(
'empty-empty',
Icon::SIZE_SMALL)->render() .
'</span>'
1206 .
'<span class="btn btn-default disabled">' . $this->moduleTemplate->getIconFactory()->getIcon(
'empty-empty',
Icon::SIZE_SMALL)->render() .
'</span>'
1214 $this->view->assign(
'table',
'<table class="table table-striped table-hover">' . implode(LF, $table) .
'</table>');
1217 $dateFormat =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'] .
' ' .
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'hhmm'] .
' T (e';
1218 $this->view->assign(
'now', date($dateFormat) .
', GMT ' . date(
'P') .
')');
1221 return $this->view->render();
1232 $htmlLabels = array();
1233 foreach ($labels as $label) {
1234 if (empty($label[
'text'])) {
1237 $htmlLabels[] =
'<span class="label label-' . htmlspecialchars($label[
'class']) .
' pull-right" title="' . htmlspecialchars($label[
'description']) .
'">' . htmlspecialchars($label[
'text']) .
'</span>';
1240 return implode(
' ', $htmlLabels);
1248 protected function saveTask()
1251 if (!empty($this->submittedData[
'uid'])) {
1253 $taskRecord = $this->scheduler->fetchTaskRecord($this->submittedData[
'uid']);
1255 $task = unserialize($taskRecord[
'serialized_task_object']);
1256 }
catch (\OutOfBoundsException $e) {
1263 if ((
int)$this->submittedData[
'type'] === 1) {
1264 $task->registerSingleExecution($this->submittedData[
'start']);
1266 if (!empty($this->submittedData[
'croncmd'])) {
1269 $cronCmd = $this->submittedData[
'croncmd'];
1272 $interval = $this->submittedData[
'interval'];
1276 $task->registerRecurringExecution($this->submittedData[
'start'], $interval, $this->submittedData[
'end'], $this->submittedData[
'multiple'], $cronCmd);
1279 $task->setDisabled($this->submittedData[
'disable']);
1281 $task->setDescription($this->submittedData[
'description']);
1283 $task->setTaskGroup($this->submittedData[
'task_group']);
1285 if (!empty(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'scheduler'][
'tasks'][$this->submittedData[
'class']][
'additionalFields'])) {
1288 if ($providerObject instanceof \TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface) {
1289 $providerObject->saveAdditionalFields($this->submittedData, $task);
1293 $result = $this->scheduler->saveTask($task);
1295 $this->
getBackendUser()->writeLog(4, 0, 0, 0,
'Scheduler task "%s" (UID: %s, Class: "%s") was updated', array($task->getTaskTitle(), $task->getTaskUid(), $task->getTaskClassName()));
1305 if ((
int)$this->submittedData[
'type'] === 1) {
1307 $task->registerSingleExecution($this->submittedData[
'start']);
1310 $task->registerRecurringExecution($this->submittedData[
'start'], $this->submittedData[
'interval'], $this->submittedData[
'end'], $this->submittedData[
'multiple'], $this->submittedData[
'croncmd']);
1313 if (!empty(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'scheduler'][
'tasks'][$this->submittedData[
'class']][
'additionalFields'])) {
1316 if ($providerObject instanceof \TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface) {
1317 $providerObject->saveAdditionalFields($this->submittedData, $task);
1321 $task->setDisabled($this->submittedData[
'disable']);
1323 $task->setDescription($this->submittedData[
'description']);
1325 $task->setTaskGroup($this->submittedData[
'task_group']);
1327 $result = $this->scheduler->addTask($task);
1329 $this->
getBackendUser()->writeLog(4, 0, 0, 0,
'Scheduler task "%s" (UID: %s, Class: "%s") was added', array($task->getTaskTitle(), $task->getTaskUid(), $task->getTaskClassName()));
1334 $this->submittedData[
'uid'] = $task->getTaskUid();
1351 protected function preprocessData()
1355 $this->submittedData[
'uid'] = empty($this->submittedData[
'uid']) ? 0 : (int)$this->submittedData[
'uid'];
1357 if (!class_exists($this->submittedData[
'class'])) {
1361 if (empty($this->submittedData[
'start'])) {
1366 $this->submittedData[
'start'] = (int)$this->submittedData[
'start'];
1367 }
catch (\Exception $e) {
1373 if ($this->submittedData[
'type'] == 2 && !empty($this->submittedData[
'end'])) {
1375 $this->submittedData[
'end'] = (int)$this->submittedData[
'end'];
1376 if ($this->submittedData[
'end'] < $this->submittedData[
'start']) {
1380 }
catch (\Exception $e) {
1386 $this->submittedData[
'interval'] = 0;
1387 $this->submittedData[
'croncmd'] =
'';
1389 if ($this->submittedData[
'type'] == 2) {
1390 $frequency = trim($this->submittedData[
'frequency']);
1391 if (empty($frequency)) {
1397 $cronErrorMessage =
'';
1400 \TYPO3\CMS\Scheduler\CronCommand\NormalizeCommand::normalize($frequency);
1401 $this->submittedData[
'croncmd'] = $frequency;
1402 }
catch (\Exception $e) {
1404 $cronErrorMessage = $e->getMessage();
1405 $cronErrorCode = $e->getCode();
1408 if (is_numeric($frequency)) {
1409 $this->submittedData[
'interval'] = (int)$frequency;
1410 unset($cronErrorCode);
1414 if (!empty($cronErrorCode)) {
1421 if (!empty(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'scheduler'][
'tasks'][$this->submittedData[
'class']][
'additionalFields'])) {
1424 if ($providerObject instanceof \TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface) {
1427 $result &= $providerObject->validateAdditionalFields($this->submittedData, $this);
1449 $timestamp = strtotime($string);
1451 if ($timestamp ===
false) {
1456 if (count($dateParts) == 2) {
1457 list($time, $date) = $dateParts;
1461 $timestamp = @mktime($hour, $minutes, 0, $month, $day, $year);
1464 if ($timestamp ===
false) {
1465 throw new \InvalidArgumentException(
'"' . $string .
'" seems not to be a correct date.', 1294587694);
1485 $this->moduleTemplate->addFlashMessage($message,
'', $severity);
1504 if (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'scheduler'][
'tasks'])) {
1505 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'scheduler'][
'tasks'] as $class => $registrationInformation) {
1506 $title = isset($registrationInformation[
'title']) ? $this->
getLanguageService()->sL($registrationInformation[
'title']) :
'';
1507 $description = isset($registrationInformation[
'description']) ? $this->
getLanguageService()->sL($registrationInformation[
'description']) :
'';
1508 $list[$class] = array(
1509 'extension' => $registrationInformation[
'extension'],
1511 'description' => $description,
1512 'provider' => isset($registrationInformation[
'additionalFields']) ? $registrationInformation[
'additionalFields'] :
''
1531 'FROM' =>
'tx_scheduler_task_group',
1535 'ORDERBY' =>
'sorting'
1540 $list[] = $groupRecord;
1560 'CONTENT' => $this->content,
1570 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
1572 $helpButton = $buttonBar->makeHelpButton()
1573 ->setModuleName(
'_MOD_' . $this->moduleName)
1575 $buttonBar->addButton($helpButton);
1577 if (empty($this->CMD) || $this->CMD ===
'list' || $this->CMD ===
'delete' || $this->CMD ===
'stop' || $this->CMD ===
'toggleHidden') {
1578 $reloadButton = $buttonBar->makeLinkButton()
1579 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_core.xlf:labels.reload',
true))
1580 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-refresh',
Icon::SIZE_SMALL))
1581 ->setHref($this->moduleUri);
1583 if ($this->MOD_SETTINGS[
'function'] ===
'scheduler' && !empty($this->
getRegisteredClasses())) {
1584 $addButton = $buttonBar->makeLinkButton()
1586 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-document-new',
Icon::SIZE_SMALL))
1587 ->setHref($this->moduleUri .
'&CMD=add');
1592 if ($this->CMD ===
'add' || $this->CMD ===
'edit') {
1594 $closeButton = $buttonBar->makeLinkButton()
1595 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:cancel',
true))
1596 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-document-close',
Icon::SIZE_SMALL))
1601 $saveButtonDropdown = $buttonBar->makeSplitButton();
1602 $saveButton = $buttonBar->makeInputButton()
1605 ->setForm(
'tx_scheduler_form')
1606 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-document-save',
Icon::SIZE_SMALL))
1607 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:save',
true));
1608 $saveButtonDropdown->addItem($saveButton);
1609 $saveAndCloseButton = $buttonBar->makeInputButton()
1611 ->setValue(
'saveclose')
1612 ->setForm(
'tx_scheduler_form')
1613 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-document-save-close',
Icon::SIZE_SMALL))
1614 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:saveAndClose',
true));
1615 $saveButtonDropdown->addItem($saveAndCloseButton);
1616 $saveAndNewButton = $buttonBar->makeInputButton()
1618 ->setValue(
'savenew')
1619 ->setForm(
'tx_scheduler_form')
1620 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-document-save-new',
Icon::SIZE_SMALL))
1621 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:saveAndCreateNewDoc',
true));
1622 $saveButtonDropdown->addItem($saveAndNewButton);
1626 if ($this->CMD ===
'edit') {
1627 $deleteButton = $buttonBar->makeInputButton()
1629 ->setValue(
'delete')
1630 ->setForm(
'tx_scheduler_form')
1631 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-edit-delete',
Icon::SIZE_SMALL))
1632 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_common.xlf:delete',
true));
1636 $shortcutButton = $buttonBar->makeShortcutButton()
1637 ->setModuleName($this->moduleName)
1638 ->setDisplayName($this->MOD_MENU[
'function'][$this->MOD_SETTINGS[
'function']])
1639 ->setSetVariables([
'function']);
1640 $buttonBar->addButton($shortcutButton);