‪TYPO3CMS  ‪main
SchedulerCommand.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Symfony\Component\Console\Command\Command;
19 use Symfony\Component\Console\Input\InputInterface;
20 use Symfony\Component\Console\Input\InputOption;
21 use Symfony\Component\Console\Output\OutputInterface;
22 use Symfony\Component\Console\Style\SymfonyStyle;
29 
35 class ‪SchedulerCommand extends Command
36 {
40  protected ‪$io;
41 
47  protected ‪$overwrittenTaskList;
48 
54  protected ‪$stopTasks = false;
55 
59  protected ‪$forceExecution;
60 
61  public function ‪__construct(
62  protected readonly ‪Scheduler $scheduler,
63  protected readonly ‪SchedulerTaskRepository $taskRepository
64  ) {
65  parent::__construct();
66  }
67 
71  public function ‪configure()
72  {
73  $this
74  ->setHelp('If no parameter is given, the scheduler executes any tasks that are overdue to run.
75 Call it like this: typo3/sysext/core/bin/typo3 scheduler:run --task=13 -f')
76  ->addOption(
77  'task',
78  'i',
79  InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
80  'UID of a specific task. Can be provided multiple times to execute multiple tasks sequentially.'
81  )
82  ->addOption(
83  'force',
84  'f',
85  InputOption::VALUE_NONE,
86  'Force execution of the task which is passed with --task option'
87  )
88  ->addOption(
89  'stop',
90  's',
91  InputOption::VALUE_NONE,
92  'Stop the task which is passed with --task option'
93  );
94  }
95 
99  protected function ‪execute(InputInterface $input, OutputInterface ‪$output): int
100  {
101  $this->io = new SymfonyStyle($input, ‪$output);
102 
103  // Make sure the _cli_ user is loaded
105 
106  ‪$overwrittenTaskList = $input->getOption('task');
109  ‪$overwrittenTaskList = array_map('intval', ‪$overwrittenTaskList);
110  if (‪$overwrittenTaskList !== []) {
111  $this->overwrittenTaskList = ‪$overwrittenTaskList;
112  }
113 
114  $this->forceExecution = (bool)$input->getOption('force');
115  $this->stopTasks = $this->‪shouldStopTasks((bool)$input->getOption('stop'));
116  return $this->‪loopTasks() ? Command::SUCCESS : Command::FAILURE;
117  }
118 
126  protected function ‪shouldStopTasks(bool $stopOption): bool
127  {
128  if (!$stopOption) {
129  return false;
130  }
131 
132  if ($this->overwrittenTaskList !== []) {
133  return true;
134  }
135 
136  if ($this->io->isVerbose()) {
137  $this->io->warning('Stopping tasks is only possible when the --task option is provided.');
138  }
139  return false;
140  }
141 
145  protected function ‪stopTask(‪AbstractTask $task)
146  {
147  $this->taskRepository->removeAllRegisteredExecutionsForTask($task);
148  if ($this->io->isVeryVerbose()) {
149  $this->io->writeln(sprintf('Task #%d was stopped', $task->‪getTaskUid()));
150  }
151  }
152 
156  protected function ‪getTask(int $taskUid): ?‪AbstractTask
157  {
158  $force = $this->stopTasks || ‪$this->forceExecution;
159  if ($force) {
160  return $this->taskRepository->findByUid($taskUid);
161  }
162 
163  return $this->taskRepository->findNextExecutableTaskForUid($taskUid);
164  }
165 
169  protected function ‪loopTasks(): bool
170  {
171  $hasError = false;
172  do {
173  $task = null;
174  // Try getting the next task and execute it
175  // If there are no more tasks to execute, an exception is thrown by \TYPO3\CMS\Scheduler\Scheduler::fetchTask()
176  try {
177  $task = $this->‪fetchNextTask();
178  if ($task === null) {
179  break;
180  }
181  try {
182  $this->‪executeOrStopTask($task);
183  } catch (\‪Exception $e) {
184  $this->io->getErrorStyle()->error($e->getMessage());
185  $hasError = true;
186  // We ignore any exception that may have been thrown during execution,
187  // as this is a background process.
188  // The exception message has been recorded to the database anyway
189  continue;
190  }
191  } catch (\UnexpectedValueException $e) {
192  $this->io->getErrorStyle()->error($e->getMessage());
193  $hasError = true;
194  continue;
195  }
196  } while ($task !== null);
197  // Record the run in the system registry
198  $this->scheduler->recordLastRun();
199  return !$hasError;
200  }
201 
210  protected function ‪fetchNextTask(): ?‪AbstractTask
211  {
212  if ($this->overwrittenTaskList === null) {
213  return $this->taskRepository->findNextExecutableTask();
214  }
215 
216  if (count($this->overwrittenTaskList) === 0) {
217  return null;
218  }
219 
220  $taskUid = (int)array_shift($this->overwrittenTaskList);
221  $task = $this->‪getTask($taskUid);
222  if (!(new TaskValidator())->isValid($task)) {
223  throw new \UnexpectedValueException(
224  sprintf('The task #%d is not scheduled for execution or does not exist.', $taskUid),
225  1547675557
226  );
227  }
228  return $task;
229  }
230 
234  protected function ‪executeOrStopTask(‪AbstractTask $task): void
235  {
236  if ($this->stopTasks) {
237  $this->‪stopTask($task);
238  return;
239  }
240 
241  $this->scheduler->executeTask($task);
242  if ($this->io->isVeryVerbose()) {
243  $this->io->writeln(sprintf('Task #%d was executed', $task->‪getTaskUid()));
244  }
245  }
246 }
‪TYPO3\CMS\Scheduler\Command\SchedulerCommand\$overwrittenTaskList
‪int[] null $overwrittenTaskList
Definition: SchedulerCommand.php:45
‪TYPO3\CMS\Scheduler\Command\SchedulerCommand\shouldStopTasks
‪shouldStopTasks(bool $stopOption)
Definition: SchedulerCommand.php:122
‪TYPO3\CMS\Scheduler\Command\SchedulerCommand\loopTasks
‪loopTasks()
Definition: SchedulerCommand.php:165
‪TYPO3\CMS\Scheduler\Command\SchedulerCommand
Definition: SchedulerCommand.php:36
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getTaskUid
‪int getTaskUid()
Definition: AbstractTask.php:134
‪TYPO3\CMS\Scheduler\Command\SchedulerCommand\stopTask
‪stopTask(AbstractTask $task)
Definition: SchedulerCommand.php:141
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository
Definition: SchedulerTaskRepository.php:36
‪TYPO3\CMS\Scheduler\Command
Definition: SchedulerCommand.php:16
‪TYPO3\CMS\Scheduler\Command\SchedulerCommand\executeOrStopTask
‪executeOrStopTask(AbstractTask $task)
Definition: SchedulerCommand.php:230
‪TYPO3\CMS\Scheduler\Command\SchedulerCommand\configure
‪configure()
Definition: SchedulerCommand.php:67
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger(mixed $var)
Definition: MathUtility.php:69
‪TYPO3\CMS\Scheduler\Task\AbstractTask
Definition: AbstractTask.php:33
‪TYPO3\CMS\Scheduler\Scheduler
Definition: Scheduler.php:34
‪TYPO3\CMS\Scheduler\Command\SchedulerCommand\$stopTasks
‪bool $stopTasks
Definition: SchedulerCommand.php:51
‪TYPO3\CMS\Scheduler\Command\SchedulerCommand\$forceExecution
‪bool $forceExecution
Definition: SchedulerCommand.php:55
‪TYPO3\CMS\Scheduler\Exception
Definition: Exception.php:25
‪TYPO3\CMS\Scheduler\Command\SchedulerCommand\$io
‪SymfonyStyle $io
Definition: SchedulerCommand.php:39
‪$output
‪$output
Definition: annotationChecker.php:114
‪TYPO3\CMS\Scheduler\Validation\Validator\TaskValidator
Definition: TaskValidator.php:23
‪TYPO3\CMS\Scheduler\Command\SchedulerCommand\execute
‪execute(InputInterface $input, OutputInterface $output)
Definition: SchedulerCommand.php:95
‪TYPO3\CMS\Core\Core\Bootstrap
Definition: Bootstrap.php:62
‪TYPO3\CMS\Scheduler\Command\SchedulerCommand\getTask
‪getTask(int $taskUid)
Definition: SchedulerCommand.php:152
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:24
‪TYPO3\CMS\Scheduler\Command\SchedulerCommand\__construct
‪__construct(protected readonly Scheduler $scheduler, protected readonly SchedulerTaskRepository $taskRepository)
Definition: SchedulerCommand.php:57
‪TYPO3\CMS\Scheduler\Command\SchedulerCommand\fetchNextTask
‪fetchNextTask()
Definition: SchedulerCommand.php:206
‪TYPO3\CMS\Core\Core\Bootstrap\initializeBackendAuthentication
‪static initializeBackendAuthentication()
Definition: Bootstrap.php:527