‪TYPO3CMS  ‪main
SchedulerListCommand.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Symfony\Component\Console\Command\Command;
21 use Symfony\Component\Console\Helper\Table;
22 use Symfony\Component\Console\Helper\TableCell;
23 use Symfony\Component\Console\Helper\TableSeparator;
24 use Symfony\Component\Console\Input\InputInterface;
25 use Symfony\Component\Console\Input\InputOption;
26 use Symfony\Component\Console\Output\BufferedOutput;
27 use Symfony\Component\Console\Output\ConsoleOutputInterface;
28 use Symfony\Component\Console\Output\ConsoleSectionOutput;
29 use Symfony\Component\Console\Output\OutputInterface;
30 use Symfony\Component\Console\Style\SymfonyStyle;
37 
41 class ‪SchedulerListCommand extends Command
42 {
43  protected SymfonyStyle ‪$io;
44 
45  public function ‪__construct(
46  protected readonly ‪Context $context,
47  protected readonly ‪SchedulerTaskRepository $taskRepository,
48  ) {
49  parent::__construct();
50  }
51 
52  public function ‪configure()
53  {
54  $this
55  ->addOption(
56  'group',
57  'g',
58  InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
59  'Show only groups with given uid',
60  )
61  ->addOption(
62  'watch',
63  'w',
64  InputOption::VALUE_OPTIONAL,
65  'Start watcher mode (polling)',
66  );
67  }
68 
69  public function ‪execute(InputInterface $input, OutputInterface ‪$output): int
70  {
71  if (!‪$output instanceof ConsoleOutputInterface) {
72  throw new \InvalidArgumentException('This command accepts only an instance of "ConsoleOutputInterface".', 1678645754);
73  }
74 
75  // Make sure the _cli_ user is loaded
77  $this->io = new SymfonyStyle($input, ‪$output);
78  $languageService = $this->‪getLanguageService();
79 
80  $tableHeader = [
81  $languageService->sL('LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf:label.id'),
82  $languageService->sL('LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf:task'),
83  $languageService->sL('LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf:label.description'),
84  $languageService->sL('LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf:label.frequency'),
85  $languageService->sL('LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf:status'),
86  ];
87 
88  $tableSection = ‪$output->section();
89  $tableBuffer = new BufferedOutput(OutputInterface::VERBOSITY_NORMAL, true);
90  $table = new Table($tableBuffer);
91  $table->setHeaders($tableHeader);
92  $showGroups = $input->getOption('group');
93  $rows = $this->‪getTableRows($showGroups);
94  $table->setRows($rows);
95  $table->setColumnMaxWidth(1, 50);
96  $table->setColumnMaxWidth(2, 50);
97  $table->render();
98 
99  $bufferedData = $tableBuffer->fetch();
100  $tableSection->overwrite($bufferedData);
101 
102  $doWatch = $input->hasParameterOption('--watch') || $input->hasParameterOption('-w');
103  if ($doWatch) {
104  $infoSection = ‪$output->section();
105  $interval = (int)($input->getOption('watch') ?: 1);
106  $infoSection->write('Watching tasks every ' . $interval . ' seconds, press CTRL+C to stop watching');
107 
109  while (true) {
110  sleep($interval);
111  $this->‪updateTable($input, $table, $tableBuffer, $tableSection);
112  }
113  }
114 
115  return Command::SUCCESS;
116  }
117 
118  private function ‪getTableRows(array $groups = []): array
119  {
120  $tasks = $this->taskRepository->getGroupedTasks();
121  $languageService = $this->‪getLanguageService();
122 
123  $rows = [];
124  foreach ($tasks['taskGroupsWithTasks'] as ‪$uid => $group) {
125  if (!in_array(‪$uid, $groups) && count($groups) > 0) {
126  continue;
127  }
128 
129  // Flag as disabled group
130  $groupDisabledLabel = $group['hidden'] ? '<fg=yellow>' . $this->‪getLanguageService()->sL('LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf:status.disabled') . '</>' : '';
131  $groupLabel = ($group['groupName'] ?? $languageService->sL('LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf:label.noGroup')) . ' (id:' . ‪$uid . ') ' . $groupDisabledLabel;
132 
133  $rows[] = [new TableSeparator(['colspan' => 5])];
134  $rows[] = [new TableCell('<options=bold>' . $groupLabel . '</>', ['colspan' => 5])];
135  $rows[] = [new TableSeparator(['colspan' => 5])];
136 
137  foreach ($group['tasks'] as $task) {
138  $progress = $task['progress'] ?? false;
139  $runningLabel = '<fg=green>' . $languageService->sL('LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf:status.running') . ($progress ? ' (' . $progress . ')' : '') . '</>';
140  $taskStatus = [];
141 
142  if ($task['isRunning']) {
143  $taskStatus[] = $runningLabel;
144  }
145 
146  $now = $this->context->getAspect('date')->get('timestamp');
147 
148  // Flag as late
149  if ($task['nextExecution'] && $task['nextExecution'] < $now && !(int)$group['hidden'] && !(int)$task['disabled']) {
150  $taskStatus[] = '<fg=yellow>' . $languageService->sL('LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf:status.late') . '</>';
151  }
152 
153  // Flag as disabled
154  if ($task['disabled'] && !$task['isRunning']) {
155  $taskStatus[] = '<fg=yellow>' . $languageService->sL('LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf:status.disabled') . '</>';
156  }
157 
158  // Flag as error
159  if ($task['lastExecutionFailureMessage'] ?? false) {
160  $taskStatus[] = '<fg=red>' . $languageService->sL('LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf:status.failure') . '</>';
161  }
162 
163  // Flag as disabled by group
164  if ($group['hidden'] && !$task['isRunning']) {
165  $taskStatus[] = '<fg=yellow>' . $languageService->sL('LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf:status.disabledByGroup') . '</>';
166  }
167 
168  $taskTitle = $task['classTitle'] . (empty($task['additionalInformation']) ? '' : ' (' . $task['additionalInformation'] . ')');
169  $rows[] = [
170  $task['uid'],
171  $taskTitle,
172  $task['description'],
173  $task['frequency'],
174  implode(', ', $taskStatus),
175  ];
176  }
177  }
178 
179  return $rows;
180  }
181 
183  {
184  return GeneralUtility::makeInstance(LanguageServiceFactory::class)->create('default');
185  }
186 
187  protected function ‪updateTable(InputInterface $input, Table $table, BufferedOutput $buffer, ConsoleSectionOutput $tableSection): void
188  {
189  $tableSection->overwrite('');
190  $rows = $this->‪getTableRows($input->getOption('group'));
191  $table->setRows($rows)->render();
192  $bufferedData = $buffer->fetch();
193  $tableSection->overwrite($bufferedData);
194  }
195 }
‪TYPO3\CMS\Core\Localization\LanguageServiceFactory
Definition: LanguageServiceFactory.php:25
‪TYPO3\CMS\Scheduler\Command\SchedulerListCommand\getTableRows
‪getTableRows(array $groups=[])
Definition: SchedulerListCommand.php:118
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository
Definition: SchedulerTaskRepository.php:36
‪TYPO3\CMS\Scheduler\Command
Definition: SchedulerCommand.php:16
‪TYPO3\CMS\Scheduler\Command\SchedulerListCommand\updateTable
‪updateTable(InputInterface $input, Table $table, BufferedOutput $buffer, ConsoleSectionOutput $tableSection)
Definition: SchedulerListCommand.php:187
‪TYPO3\CMS\Scheduler\Command\SchedulerListCommand
Definition: SchedulerListCommand.php:42
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:54
‪TYPO3\CMS\Scheduler\Command\SchedulerListCommand\getLanguageService
‪getLanguageService()
Definition: SchedulerListCommand.php:182
‪TYPO3\CMS\Scheduler\Command\SchedulerListCommand\__construct
‪__construct(protected readonly Context $context, protected readonly SchedulerTaskRepository $taskRepository,)
Definition: SchedulerListCommand.php:45
‪TYPO3\CMS\Scheduler\Command\SchedulerListCommand\execute
‪execute(InputInterface $input, OutputInterface $output)
Definition: SchedulerListCommand.php:69
‪$output
‪$output
Definition: annotationChecker.php:114
‪TYPO3\CMS\Webhooks\Message\$uid
‪identifier readonly int $uid
Definition: PageModificationMessage.php:35
‪TYPO3\CMS\Core\Core\Bootstrap
Definition: Bootstrap.php:62
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Scheduler\Command\SchedulerListCommand\$io
‪SymfonyStyle $io
Definition: SchedulerListCommand.php:43
‪TYPO3\CMS\Core\Core\Bootstrap\initializeBackendAuthentication
‪static initializeBackendAuthentication()
Definition: Bootstrap.php:527
‪TYPO3\CMS\Scheduler\Command\SchedulerListCommand\configure
‪configure()
Definition: SchedulerListCommand.php:52