2 declare(strict_types = 1);
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\ServerRequestInterface;
61 'addMessage' =>
'Using SchedulerModuleController::addMessage() is deprecated and will not be possible anymore in TYPO3 v10.0.',
68 'CMD' =>
'Using SchedulerModuleController::$CMD is deprecated and will not be possible anymore in TYPO3 v10.0. Use SchedulerModuleController::getCurrentAction() instead.',
89 protected $cshKey =
'_MOD_system_txschedulerM1';
157 $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
160 $this->view = GeneralUtility::makeInstance(StandaloneView::class);
161 $this->view->getRequest()->setControllerExtensionName(
'scheduler');
163 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
164 $this->moduleUri = (string)$uriBuilder->buildUriFromRoute(
'system_txschedulerM1');
165 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
166 $this->scheduler = GeneralUtility::makeInstance(Scheduler::class);
178 public function mainAction(ServerRequestInterface $request): ResponseInterface
180 $parsedBody = $request->getParsedBody();
181 $queryParams = $request->getQueryParams();
191 $settings = $parsedBody[
'SET'] ?? $queryParams[
'SET'] ??
null;
195 $content =
'<form name="tx_scheduler_form" id="tx_scheduler_form" method="post" action="">';
199 $previousCMD =
Action::cast($parsedBody[
'previousCMD'] ?? $queryParams[
'previousCMD'] ??
null);
201 $content .=
'<div id="extraFieldsSection"></div></form><div id="extraFieldsHidden"></div>';
206 $this->moduleTemplate->setContent($content);
207 return new HtmlResponse($this->moduleTemplate->renderContent());
225 $menu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
226 $menu->setIdentifier(
'SchedulerJumpMenu');
228 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
229 foreach ($this->MOD_MENU[
'function'] as $controller => $title) {
233 (
string)$uriBuilder->buildUriFromRoute(
234 'system_txschedulerM1',
238 'function' => $controller
244 if ($controller === $this->MOD_SETTINGS[
'function']) {
245 $item->setActive(
true);
247 $menu->addMenuItem($item);
249 $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($menu);
263 $this->submittedData = GeneralUtility::_GPmerged(
'tx_scheduler');
264 $this->submittedData[
'uid'] = (int)$this->submittedData[
'uid'];
282 unset($this->submittedData);
295 switch ((
string)$this->MOD_SETTINGS[
'function']) {
306 }
catch (\LogicException|\UnexpectedValueException|\OutOfBoundsException $e) {
310 }
catch (\Exception $e) {
349 return '<h2>' . $sectionTitle .
'</h2><div class="tx_scheduler_mod1">' . $content .
'</div>';
360 $this->view->setTemplatePathAndFilename($this->backendTemplatePath .
'CheckScreen.html');
363 $registry = GeneralUtility::makeInstance(Registry::class);
364 $lastRun = $registry->get(
'tx_scheduler',
'lastRun');
365 if (!is_array($lastRun)) {
369 if (empty($lastRun[
'end']) || empty($lastRun[
'start']) || empty($lastRun[
'type'])) {
373 $startDate = date(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'], $lastRun[
'start']);
374 $startTime = date(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'hhmm'], $lastRun[
'start']);
375 $endDate = date(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'], $lastRun[
'end']);
376 $endTime = date(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'hhmm'], $lastRun[
'end']);
377 $label =
'automatically';
378 if ($lastRun[
'type'] ===
'manual') {
382 $message = sprintf($this->
getLanguageService()->getLL(
'msg.lastRun'), $type, $startDate, $startTime, $endDate, $endTime);
386 $this->view->assign(
'lastRunMessage', $message);
387 $this->view->assign(
'lastRunSeverity', $severity);
390 $this->view->assign(
'composerMode',
true);
393 $script = GeneralUtility::getFileAbsFileName(
'EXT:core/bin/typo3');
394 $this->view->assign(
'script', $script);
398 $isExecutable =
true;
400 $isExecutable = is_executable($script);
409 $this->view->assign(
'isExecutableMessage', $message);
410 $this->view->assign(
'isExecutableSeverity', $severity);
415 return $this->view->render();
427 if (empty($registeredClasses)) {
428 $this->view->setTemplatePathAndFilename($this->backendTemplatePath .
'InfoScreenNoClasses.html');
429 return $this->view->render();
432 $this->view->setTemplatePathAndFilename($this->backendTemplatePath .
'InfoScreen.html');
433 $this->view->assign(
'registeredClasses', $registeredClasses);
435 return $this->view->render();
445 $task = $this->scheduler->fetchTask($this->submittedData[
'uid']);
447 if ($task->isExecutionRunning()) {
450 if ($this->scheduler->removeTask($task)) {
451 $this->
getBackendUser()->
writelog(4, 0, 0, 0,
'Scheduler task "%s" (UID: %s, Class: "%s") was deleted', [$task->getTaskTitle(), $task->getTaskUid(), $task->getTaskClassName()]);
457 }
catch (\UnexpectedValueException $e) {
459 $taskUid = (int)$this->submittedData[
'uid'];
460 $result = GeneralUtility::makeInstance(ConnectionPool::class)
461 ->getConnectionForTable(
'tx_scheduler_task')
462 ->update(
'tx_scheduler_task', [
'deleted' => 1], [
'uid' => $taskUid]);
468 }
catch (\OutOfBoundsException $e) {
484 $task = $this->scheduler->fetchTask($this->submittedData[
'uid']);
485 if ($task->isExecutionRunning()) {
487 $result = $task->unmarkAllExecutions();
497 }
catch (\Exception $e) {
508 $task = $this->scheduler->fetchTask($this->submittedData[
'uid']);
509 $task->setDisabled(!$task->isDisabled());
513 $task->registerSingleExecution(time());
523 $task = $this->scheduler->fetchTask($this->submittedData[
'uid']);
524 $task->setRunOnNextCronJob(
true);
535 $this->view->setTemplatePathAndFilename($this->backendTemplatePath .
'EditTask.html');
544 if ($this->submittedData[
'uid'] > 0) {
547 $taskRecord = $this->scheduler->fetchTaskRecord($this->submittedData[
'uid']);
549 if (!empty($taskRecord[
'serialized_executions'])) {
551 throw new \LogicException(
'Runnings tasks cannot not be edited', 1251232849);
556 $task = unserialize($taskRecord[
'serialized_task_object']);
559 $taskInfo[
'disable'] = $taskRecord[
'disable'];
560 $taskInfo[
'description'] = $taskRecord[
'description'];
561 $taskInfo[
'task_group'] = $taskRecord[
'task_group'];
564 if (isset($registeredClasses[get_class($task)]) && $this->scheduler->isValidTaskObject($task)) {
566 $taskInfo[
'class'] = get_class($task);
568 $taskInfo[
'start'] = (int)$task->getExecution()->getStart();
569 $taskInfo[
'end'] = (int)$task->getExecution()->getEnd();
570 $taskInfo[
'interval'] = $task->getExecution()->getInterval();
571 $taskInfo[
'croncmd'] = $task->getExecution()->getCronCmd();
572 $taskInfo[
'multiple'] = $task->getExecution()->getMultiple();
573 if (!empty($taskInfo[
'interval']) || !empty($taskInfo[
'croncmd'])) {
577 $taskInfo[
'frequency'] = $taskInfo[
'interval'] ?: $taskInfo[
'croncmd'];
582 $taskInfo[
'frequency'] =
'';
583 $taskInfo[
'end'] = 0;
590 $taskInfo[
'start'] = 0;
591 $taskInfo[
'end'] = 0;
592 $taskInfo[
'frequency'] =
'';
593 $taskInfo[
'multiple'] =
false;
596 }
catch (\OutOfBoundsException $e) {
603 $taskInfo[
'class'] = key($registeredClasses);
605 $taskInfo[
'start'] =
$GLOBALS[
'EXEC_TIME'];
606 $taskInfo[
'end'] =
'';
607 $taskInfo[
'frequency'] =
'';
608 $taskInfo[
'multiple'] = 0;
614 if (!empty($this->submittedData)) {
619 $allAdditionalFields = [];
620 if ($process ===
'add') {
621 foreach ($registeredClasses as $class => $registrationInfo) {
622 if (!empty($registrationInfo[
'provider'])) {
624 $providerObject = GeneralUtility::makeInstance($registrationInfo[
'provider']);
625 if ($providerObject instanceof AdditionalFieldProviderInterface) {
626 $additionalFields = $providerObject->getAdditionalFields($taskInfo,
null, $this);
627 $allAdditionalFields = array_merge($allAdditionalFields, [$class => $additionalFields]);
631 } elseif ($task !==
null && !empty($registeredClasses[$taskInfo[
'class']][
'provider'])) {
633 $providerObject = GeneralUtility::makeInstance($registeredClasses[$taskInfo[
'class']][
'provider']);
634 if ($providerObject instanceof AdditionalFieldProviderInterface) {
635 $allAdditionalFields[$taskInfo[
'class']] = $providerObject->getAdditionalFields($taskInfo, $task, $this);
644 function setFormValueFromBrowseWin(fieldReference, elValue, elName) {
645 var res = elValue.split("_");
646 var element = document.getElementById(fieldReference);
647 element.value = res[1];
652 $this->view->assign(
'uid', htmlspecialchars((
string)$this->submittedData[
'uid']));
653 $this->view->assign(
'cmd', htmlspecialchars((
string)$this->
getCurrentAction()));
654 $this->view->assign(
'csh', $this->cshKey);
655 $this->view->assign(
'lang',
'LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf:');
660 $this->view->assign(
'task_disable', ($taskInfo[
'disable'] ?
' checked="checked"' :
''));
661 $this->view->assign(
'task_disable_label',
'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:disable');
665 if ($this->submittedData[
'uid'] > 0 && !empty($taskInfo[
'class'])) {
666 $this->view->assign(
'task_class', $taskInfo[
'class']);
667 $this->view->assign(
'task_class_title', $registeredClasses[$taskInfo[
'class']][
'title']);
668 $this->view->assign(
'task_class_extension', $registeredClasses[$taskInfo[
'class']][
'extension']);
671 $groupedClasses = [];
672 foreach ($registeredClasses as $class => $classInfo) {
673 $groupedClasses[$classInfo[
'extension']][$class] = $classInfo;
675 ksort($groupedClasses);
676 foreach ($groupedClasses as $extension => $class) {
677 foreach ($groupedClasses[$extension] as $class => $classInfo) {
678 $selected = $class == $taskInfo[
'class'] ?
' selected="selected"' :
'';
679 $groupedClasses[$extension][$class][
'selected'] = $selected;
682 $this->view->assign(
'groupedClasses', $groupedClasses);
686 $this->view->assign(
'task_type_selected_1', ((
int)$taskInfo[
'type'] ===
AbstractTask::TYPE_SINGLE ?
' selected="selected"' :
''));
690 foreach ($registeredTaskGroups as $key => $taskGroup) {
691 $selected = $taskGroup[
'uid'] == $taskInfo[
'task_group'] ?
' selected="selected"' :
'';
692 $registeredTaskGroups[$key][
'selected'] = $selected;
694 $this->view->assign(
'registeredTaskGroups', $registeredTaskGroups);
697 $dateFormat =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'USdateFormat'] ?
'%H:%M %m-%d-%Y' :
'%H:%M %d-%m-%Y';
698 $this->view->assign(
'start_value_hr', ($taskInfo[
'start'] > 0 ? strftime($dateFormat, $taskInfo[
'start']) :
''));
699 $this->view->assign(
'start_value', $taskInfo[
'start']);
703 $this->view->assign(
'end_value_hr', ($taskInfo[
'end'] > 0 ? strftime($dateFormat, $taskInfo[
'end']) :
''));
704 $this->view->assign(
'end_value', $taskInfo[
'end']);
707 $this->view->assign(
'frequency', $taskInfo[
'frequency']);
710 $this->view->assign(
'multiple', ($taskInfo[
'multiple'] ?
'checked="checked"' :
''));
713 $this->view->assign(
'description', $taskInfo[
'description']);
716 $additionalFieldList = [];
717 foreach ($allAdditionalFields as $class =>
$fields) {
718 if ($class == $taskInfo[
'class']) {
719 $additionalFieldsStyle =
'';
721 $additionalFieldsStyle =
' style="display: none"';
725 foreach (
$fields as $fieldID => $fieldInfo) {
726 $htmlClassName = strtolower(str_replace(
'\\',
'-', $class));
728 $field[
'htmlClassName'] = $htmlClassName;
729 $field[
'code'] = $fieldInfo[
'code'];
730 $field[
'cshKey'] = $fieldInfo[
'cshKey'];
731 $field[
'cshLabel'] = $fieldInfo[
'cshLabel'];
732 $field[
'langLabel'] = $fieldInfo[
'label'];
733 $field[
'fieldID'] = $fieldID;
734 $field[
'additionalFieldsStyle'] = $additionalFieldsStyle;
736 $additionalFieldList[] = $field;
740 $this->view->assign(
'additionalFields', $additionalFieldList);
742 $this->view->assign(
'returnUrl', (
string)GeneralUtility::getIndpEnv(
'REQUEST_URI'));
743 $this->view->assign(
'table', implode(LF, $table));
745 $this->view->assign(
'frequencyOptions', (array)
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'scheduler'][
'frequencyOptions']);
747 return $this->view->render();
757 if (isset($fieldInfo[
'browser']) && ($fieldInfo[
'browser'] ===
'page')) {
758 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
759 $url = (string)$uriBuilder->buildUriFromRoute(
760 'wizard_element_browser',
761 [
'mode' =>
'db',
'bparams' => $fieldID .
'|||pages|']
763 $title = htmlspecialchars($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.browse_db'));
765 <div><a href="#" data-url=' . htmlspecialchars($url) .
' class="btn btn-default t3js-pageBrowser" title="' . $title .
'">
766 <span class="t3js-icon icon icon-size-small icon-state-default icon-actions-insert-record" data-identifier="actions-insert-record">
767 <span class="icon-markup">' . $this->iconFactory->getIcon(
768 'actions-insert-record',
770 )->render() .
'</span>
772 </a><span id="page_' . $fieldID .
'"> ' . htmlspecialchars($fieldInfo[
'pageTitle']) .
'</span></div>';
783 if (isset($this->submittedData[
'execute']) && !empty($this->submittedData[
'execute'])) {
787 foreach ($this->submittedData[
'execute'] as $uid) {
790 $task = $this->scheduler->fetchTask($uid);
791 $class = get_class($task);
792 $name = $registeredClasses[$class][
'title'] .
' (' . $registeredClasses[$class][
'extension'] .
')';
793 if (GeneralUtility::_POST(
'go_cron') !==
null) {
794 $task->setRunOnNextCronJob(
true);
799 $result = $this->scheduler->executeTask($task);
805 }
catch (\Exception $e) {
810 }
catch (\OutOfBoundsException $e) {
812 }
catch (\UnexpectedValueException $e) {
817 $this->scheduler->recordLastRun(
'manual');
830 $this->view->setTemplatePathAndFilename($this->backendTemplatePath .
'ListTasks.html');
833 $dateFormat =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'] .
' ' .
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'hhmm'];
840 array_unshift($registeredTaskGroups, [
'uid' => 0,
'groupName' =>
'']);
844 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
845 ->getQueryBuilderForTable(
'tx_scheduler_task');
846 $queryBuilder->getRestrictions()->removeAll();
848 $result = $queryBuilder->select(
't.*')
850 'g.groupName AS taskGroupName',
851 'g.description AS taskGroupDescription',
852 'g.deleted AS isTaskGroupDeleted'
854 ->from(
'tx_scheduler_task',
't')
857 'tx_scheduler_task_group',
859 $queryBuilder->expr()->eq(
't.task_group', $queryBuilder->quoteIdentifier(
'g.uid'))
862 $queryBuilder->expr()->eq(
't.deleted', 0)
864 ->orderBy(
'g.sorting')
868 $temporaryResult = [];
869 while ($row = $result->fetch()) {
870 if ($row[
'taskGroupName'] ===
null || $row[
'isTaskGroupDeleted'] ===
'1') {
871 $row[
'taskGroupName'] =
'';
872 $row[
'taskGroupDescription'] =
'';
873 $row[
'task_group'] = 0;
875 $temporaryResult[$row[
'task_group']][
'groupName'] = $row[
'taskGroupName'];
876 $temporaryResult[$row[
'task_group']][
'groupDescription'] = $row[
'taskGroupDescription'];
877 $temporaryResult[$row[
'task_group']][
'tasks'][] = $row;
881 if (empty($temporaryResult)) {
882 $this->view->setTemplatePathAndFilename($this->backendTemplatePath .
'ListTasksNoTasks.html');
883 return $this->view->render();
889 $tasks = $temporaryResult;
892 $missingClasses = [];
893 foreach ($temporaryResult as $taskIndex => $taskGroup) {
894 foreach ($taskGroup[
'tasks'] as $recordIndex => $schedulerRecord) {
895 if ((
int)$schedulerRecord[
'disable'] === 1) {
896 $translationKey =
'enable';
898 $translationKey =
'disable';
900 $tasks[$taskIndex][
'tasks'][$recordIndex][
'translationKey'] = $translationKey;
903 $lastExecution =
'-';
905 $showAsDisabled =
false;
908 $task = unserialize($schedulerRecord[
'serialized_task_object']);
909 $class = get_class($task);
910 if ($class ===
'__PHP_Incomplete_Class' && preg_match(
'/^O:[0-9]+:"(?P<classname>.+?)"/', $schedulerRecord[
'serialized_task_object'], $matches) === 1) {
911 $class = $matches[
'classname'];
913 $tasks[$taskIndex][
'tasks'][$recordIndex][
'class'] = $class;
915 if (!empty($schedulerRecord[
'lastexecution_time'])) {
916 $lastExecution = date($dateFormat, (
int)$schedulerRecord[
'lastexecution_time']);
917 if ($schedulerRecord[
'lastexecution_context'] ===
'CLI') {
922 $lastExecution .=
' (' . $context .
')';
924 $tasks[$taskIndex][
'tasks'][$recordIndex][
'lastExecution'] = $lastExecution;
926 if (isset($registeredClasses[get_class($task)]) && $this->scheduler->isValidTaskObject($task)) {
927 $tasks[$taskIndex][
'tasks'][$recordIndex][
'validClass'] =
true;
930 $additionalInformation = $task->getAdditionalInformation();
931 if ($task instanceof ProgressProviderInterface) {
932 $progress = round((
float)$task->getProgress(), 2);
933 $tasks[$taskIndex][
'tasks'][$recordIndex][
'progress'] = $progress;
935 $tasks[$taskIndex][
'tasks'][$recordIndex][
'classTitle'] = $registeredClasses[$class][
'title'];
936 $tasks[$taskIndex][
'tasks'][$recordIndex][
'classExtension'] = $registeredClasses[$class][
'extension'];
937 $tasks[$taskIndex][
'tasks'][$recordIndex][
'additionalInformation'] = $additionalInformation;
939 if (!empty($schedulerRecord[
'serialized_executions'])) {
941 'class' =>
'success',
946 $tasks[$taskIndex][
'tasks'][$recordIndex][
'isRunning'] = $isRunning;
951 if ($isRunning || $schedulerRecord[
'disable']) {
954 $nextDate = date($dateFormat, (
int)$schedulerRecord[
'nextexecution']);
955 if (empty($schedulerRecord[
'nextexecution'])) {
957 } elseif ($schedulerRecord[
'nextexecution'] <
$GLOBALS[
'EXEC_TIME']) {
959 'class' =>
'warning',
965 $tasks[$taskIndex][
'tasks'][$recordIndex][
'nextDate'] = $nextDate;
972 if ($task->getExecution()->getCronCmd() ==
'') {
973 $frequency = $task->getExecution()->getInterval();
975 $frequency = $task->getExecution()->getCronCmd();
980 if ($schedulerRecord[
'disable'] && !$isRunning) {
982 'class' =>
'default',
985 $showAsDisabled =
true;
987 $tasks[$taskIndex][
'tasks'][$recordIndex][
'execType'] = $execType;
988 $tasks[$taskIndex][
'tasks'][$recordIndex][
'frequency'] = $frequency;
990 if ($task->getExecution()->getMultiple()) {
991 $multiple = $this->
getLanguageService()->
sL(
'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:yes');
993 $multiple = $this->
getLanguageService()->
sL(
'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:no');
995 $tasks[$taskIndex][
'tasks'][$recordIndex][
'multiple'] = $multiple;
998 if (!empty($schedulerRecord[
'lastexecution_failure'])) {
1001 $exceptionArray = @unserialize($schedulerRecord[
'lastexecution_failure']);
1003 if (!is_array($exceptionArray) || empty($exceptionArray)) {
1006 $labelDescription = sprintf($this->
getLanguageService()->getLL(
'msg.executionFailureReport'), $exceptionArray[
'code'], $exceptionArray[
'message']);
1009 'class' =>
'danger',
1011 'description' => $labelDescription
1014 $tasks[$taskIndex][
'tasks'][$recordIndex][
'labels'] = $labels;
1015 if ($showAsDisabled) {
1016 $tasks[$taskIndex][
'tasks'][$recordIndex][
'showAsDisabled'] =
'disabled';
1019 $missingClasses[] = $tasks[$taskIndex][
'tasks'][$recordIndex];
1020 unset($tasks[$taskIndex][
'tasks'][$recordIndex]);
1025 $this->view->assign(
'tasks', $tasks);
1026 $this->view->assign(
'missingClasses', $missingClasses);
1027 $this->view->assign(
'moduleUri', $this->moduleUri);
1030 return $this->view->render();
1042 foreach ($labels as $label) {
1043 if (empty($label[
'text'])) {
1046 $htmlLabels[] =
'<span class="label label-' . htmlspecialchars($label[
'class']) .
' pull-right" title="' . htmlspecialchars($label[
'description']) .
'">' . htmlspecialchars($label[
'text']) .
'</span>';
1049 return implode(
' ', $htmlLabels);
1058 if (!empty($this->submittedData[
'uid'])) {
1060 $taskRecord = $this->scheduler->fetchTaskRecord($this->submittedData[
'uid']);
1062 $task = unserialize($taskRecord[
'serialized_task_object']);
1063 }
catch (\OutOfBoundsException $e) {
1071 $task->registerSingleExecution($this->submittedData[
'start']);
1073 if (!empty($this->submittedData[
'croncmd'])) {
1076 $cronCmd = $this->submittedData[
'croncmd'];
1079 $interval = $this->submittedData[
'interval'];
1083 $task->registerRecurringExecution($this->submittedData[
'start'], $interval, $this->submittedData[
'end'], $this->submittedData[
'multiple'], $cronCmd);
1086 $task->setDisabled($this->submittedData[
'disable']);
1088 $task->setDescription($this->submittedData[
'description']);
1090 $task->setTaskGroup($this->submittedData[
'task_group']);
1092 if (!empty(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'scheduler'][
'tasks'][$this->submittedData[
'class']][
'additionalFields'])) {
1094 $providerObject = GeneralUtility::makeInstance(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'scheduler'][
'tasks'][$this->submittedData[
'class']][
'additionalFields']);
1095 if ($providerObject instanceof AdditionalFieldProviderInterface) {
1096 $providerObject->saveAdditionalFields($this->submittedData, $task);
1100 $result = $this->scheduler->saveTask($task);
1102 $this->
getBackendUser()->
writelog(4, 0, 0, 0,
'Scheduler task "%s" (UID: %s, Class: "%s") was updated', [$task->getTaskTitle(), $task->getTaskUid(), $task->getTaskClassName()]);
1111 $task = GeneralUtility::makeInstance($this->submittedData[
'class']);
1114 $task->registerSingleExecution($this->submittedData[
'start']);
1117 $task->registerRecurringExecution($this->submittedData[
'start'], $this->submittedData[
'interval'], $this->submittedData[
'end'], $this->submittedData[
'multiple'], $this->submittedData[
'croncmd']);
1120 if (!empty(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'scheduler'][
'tasks'][$this->submittedData[
'class']][
'additionalFields'])) {
1122 $providerObject = GeneralUtility::makeInstance(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'scheduler'][
'tasks'][$this->submittedData[
'class']][
'additionalFields']);
1123 if ($providerObject instanceof AdditionalFieldProviderInterface) {
1124 $providerObject->saveAdditionalFields($this->submittedData, $task);
1128 $task->setDisabled($this->submittedData[
'disable']);
1130 $task->setDescription($this->submittedData[
'description']);
1132 $task->setTaskGroup($this->submittedData[
'task_group']);
1134 $result = $this->scheduler->addTask($task);
1136 $this->
getBackendUser()->
writelog(4, 0, 0, 0,
'Scheduler task "%s" (UID: %s, Class: "%s") was added', [$task->getTaskTitle(), $task->getTaskUid(), $task->getTaskClassName()]);
1141 $this->submittedData[
'uid'] = $task->getTaskUid();
1162 $this->submittedData[
'uid'] = empty($this->submittedData[
'uid']) ? 0 : (int)$this->submittedData[
'uid'];
1164 if (!class_exists($this->submittedData[
'class'])) {
1168 if (empty($this->submittedData[
'start'])) {
1171 } elseif (is_string($this->submittedData[
'start']) && (!is_numeric($this->submittedData[
'start']))) {
1173 $this->submittedData[
'start'] = $this->
convertToTimestamp($this->submittedData[
'start']);
1174 }
catch (\Exception $e) {
1179 $this->submittedData[
'start'] = (int)$this->submittedData[
'start'];
1183 if (is_string($this->submittedData[
'end']) && (!is_numeric($this->submittedData[
'end']))) {
1186 }
catch (\Exception $e) {
1191 $this->submittedData[
'end'] = (int)$this->submittedData[
'end'];
1193 if ($this->submittedData[
'end'] < $this->submittedData[
'start']) {
1202 $this->submittedData[
'interval'] = 0;
1203 $this->submittedData[
'croncmd'] =
'';
1206 $frequency = trim($this->submittedData[
'frequency']);
1207 if (empty($frequency)) {
1213 $cronErrorMessage =
'';
1217 $this->submittedData[
'croncmd'] = $frequency;
1218 }
catch (\Exception $e) {
1220 $cronErrorMessage = $e->getMessage();
1221 $cronErrorCode = $e->getCode();
1224 if (is_numeric($frequency)) {
1225 $this->submittedData[
'interval'] = (int)$frequency;
1226 unset($cronErrorCode);
1230 if (!empty($cronErrorCode)) {
1237 if (!empty(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'scheduler'][
'tasks'][$this->submittedData[
'class']][
'additionalFields'])) {
1239 $providerObject = GeneralUtility::makeInstance(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'scheduler'][
'tasks'][$this->submittedData[
'class']][
'additionalFields']);
1240 if ($providerObject instanceof AdditionalFieldProviderInterface) {
1243 $result &= $providerObject->validateAdditionalFields($this->submittedData, $this);
1258 $dateTime = new \DateTime($input);
1259 $value = $dateTime->getTimestamp();
1261 $value -= date(
'Z', $value);
1274 $this->moduleTemplate->addFlashMessage($message,
'', $severity);
1293 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'scheduler'][
'tasks'] ?? [] as $class => $registrationInformation) {
1294 $title = isset($registrationInformation[
'title']) ? $this->
getLanguageService()->
sL($registrationInformation[
'title']) :
'';
1295 $description = isset($registrationInformation[
'description']) ? $this->
getLanguageService()->
sL($registrationInformation[
'description']) :
'';
1297 'extension' => $registrationInformation[
'extension'],
1299 'description' => $description,
1300 'provider' => $registrationInformation[
'additionalFields'] ??
''
1313 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
1314 ->getQueryBuilderForTable(
'tx_scheduler_task_group');
1316 return $queryBuilder
1318 ->from(
'tx_scheduler_task_group')
1319 ->orderBy(
'sorting')
1329 protected function getButtons(ServerRequestInterface $request): void
1331 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
1333 $helpButton = $buttonBar->makeHelpButton()
1334 ->setModuleName(
'_MOD_system_txschedulerM1')
1336 $buttonBar->addButton($helpButton);
1340 $reloadButton = $buttonBar->makeLinkButton()
1341 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.reload'))
1342 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-refresh',
Icon::SIZE_SMALL))
1343 ->setHref($this->moduleUri);
1346 $addButton = $buttonBar->makeLinkButton()
1348 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-add',
Icon::SIZE_SMALL))
1357 $closeButton = $buttonBar->makeLinkButton()
1358 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:cancel'))
1359 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-close',
Icon::SIZE_SMALL))
1360 ->setOnClick(
'document.location=' . GeneralUtility::quoteJSvalue($this->moduleUri))
1364 $saveButtonDropdown = $buttonBar->makeSplitButton();
1365 $saveButton = $buttonBar->makeInputButton()
1368 ->setForm(
'tx_scheduler_form')
1369 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-document-save',
Icon::SIZE_SMALL))
1370 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:save'));
1371 $saveButtonDropdown->addItem($saveButton);
1372 $saveAndNewButton = $buttonBar->makeInputButton()
1375 ->setForm(
'tx_scheduler_form')
1376 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-document-save-new',
Icon::SIZE_SMALL))
1377 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf:label.saveAndCreateNewTask'));
1378 $saveButtonDropdown->addItem($saveAndNewButton);
1379 $saveAndCloseButton = $buttonBar->makeInputButton()
1382 ->setForm(
'tx_scheduler_form')
1383 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-document-save-close',
Icon::SIZE_SMALL))
1384 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:saveAndClose'));
1385 $saveButtonDropdown->addItem($saveAndCloseButton);
1391 $deleteButton = $buttonBar->makeLinkButton()
1392 ->setHref($this->moduleUri .
'&CMD=' .
Action::DELETE .
'&tx_scheduler[uid]=' . $request->getQueryParams()[
'tx_scheduler'][
'uid'])
1393 ->setClasses(
't3js-modal-trigger')
1394 ->setDataAttributes([
1395 'severity' =>
'warning',
1396 'title' => $this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:delete'),
1397 'button-close-text' => $this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:cancel'),
1400 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-edit-delete',
Icon::SIZE_SMALL))
1401 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:delete'));
1406 $shortcutButton = $buttonBar->makeShortcutButton()
1407 ->setModuleName(
'system_txschedulerM1')
1408 ->setDisplayName($this->MOD_MENU[
'function'][$this->MOD_SETTINGS[
'function']])
1409 ->setSetVariables([
'function']);
1410 $buttonBar->addButton($shortcutButton);
1430 $dateFormat =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'] .
' ' .
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'hhmm'] .
' T (e';
1431 return date($dateFormat) .
', GMT ' . date(
'P') .
')';
1458 return GeneralUtility::makeInstance(PageRenderer::class);