‪TYPO3CMS  10.4
CommandRegistry.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 Psr\Container\ContainerInterface;
21 use Symfony\Component\Console\Command\Command;
22 use Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
23 use Symfony\Component\Console\Exception\CommandNotFoundException;
24 use TYPO3\CMS\Core\Package\PackageManager;
27 
31 class ‪CommandRegistry implements CommandLoaderInterface, \IteratorAggregate, ‪SingletonInterface
32 {
36  protected ‪$packageManager;
37 
41  protected ‪$container;
42 
48  protected ‪$commands = [];
49 
55  protected ‪$commandConfigurations = [];
56 
62  protected ‪$lazyCommandConfigurations = [];
63 
68  public function ‪__construct(PackageManager ‪$packageManager, ContainerInterface ‪$container)
69  {
70  $this->packageManager = ‪$packageManager;
71  $this->container = ‪$container;
72  }
73 
77  public function ‪has($name)
78  {
80 
81  return array_key_exists($name, $this->commands);
82  }
83 
87  public function get($name)
88  {
89  try {
90  return $this->‪getCommandByIdentifier($name);
91  } catch (UnknownCommandException $e) {
92  throw new CommandNotFoundException($e->getMessage(), [], 1567969355, $e);
93  }
94  }
95 
99  public function ‪getNames()
100  {
102 
103  return array_keys($this->commands);
104  }
105 
110  public function ‪getIterator(): \Generator
111  {
112  trigger_error('Using ' . self::class . ' as iterable has been deprecated and will stop working in TYPO3 11.0.', E_USER_DEPRECATED);
113 
115  foreach ($this->commands as $commandName => $command) {
116  if (is_string($command)) {
117  $command = $this->‪getInstance($command);
118  }
119  yield $commandName => $command;
120  }
121  }
122 
128  public function ‪getSchedulableCommands(): \Generator
129  {
131  foreach ($this->commands as $commandName => $command) {
132  if ($this->commandConfigurations[$commandName]['schedulable'] ?? true) {
133  if (is_string($command)) {
134  $command = $this->‪getInstance($command);
135  }
136  yield $commandName => $command;
137  }
138  }
139  }
140 
145  public function ‪getLegacyCommands(): \Generator
146  {
148  foreach ($this->commands as $commandName => $command) {
149  // Type string indicates lazy loading
150  if (is_string($command)) {
151  continue;
152  }
153  yield $commandName => $command;
154  }
155  }
156 
163  public function ‪getCommandByIdentifier(string $identifier): ?Command
164  {
166 
167  if (!isset($this->commands[$identifier])) {
168  throw new ‪UnknownCommandException(
169  sprintf('Command "%s" has not been registered.', $identifier),
170  1510906768
171  );
172  }
173 
174  $command = $this->commands[$identifier] ?? null;
175  if (is_string($command)) {
176  $command = $this->‪getInstance($command);
177  }
178 
179  return $command;
180  }
181 
197  protected function ‪populateCommandsFromPackages()
198  {
199  if ($this->commands) {
200  return;
201  }
202 
203  foreach ($this->lazyCommandConfigurations as $commandName => $commandConfig) {
204  // Lazy commands shall be loaded from the Container on demand, store the command as string to indicate lazy loading
205  $this->commands[$commandName] = $commandConfig['class'];
206  $this->commandConfigurations[$commandName] = $commandConfig;
207  }
208 
209  foreach ($this->packageManager->getActivePackages() as $package) {
210  $commandsOfExtension = $package->getPackagePath() . 'Configuration/Commands.php';
211  if (@is_file($commandsOfExtension)) {
212  /*
213  * We use require instead of require_once here because it eases the testability as require_once returns
214  * a boolean from the second execution on. As this class is a singleton, this require is only called
215  * once per request anyway.
216  */
217  ‪$commands = require $commandsOfExtension;
218  if (is_array(‪$commands)) {
219  foreach (‪$commands as $commandName => $commandConfig) {
220  if (array_key_exists($commandName, $this->lazyCommandConfigurations)) {
221  // Lazy (DI managed) commands override classic commands from Configuration/Commands.php
222  // Skip this case to allow extensions to provide commands via DI config and to allow
223  // TYPO3 v9 backwards compatible configuration via Configuration/Commands.php.
224  // Note: Also the deprecation error is skipped on-demand as the extension has been
225  // adapted and the configuration will be ignored as of TYPO3 v11.
226  continue;
227  }
228  if (array_key_exists($commandName, $this->commands)) {
229  throw new CommandNameAlreadyInUseException(
230  'Command "' . $commandName . '" registered by "' . $package->getPackageKey() . '" is already in use',
231  1484486383
232  );
233  }
234  $this->commands[$commandName] = GeneralUtility::makeInstance($commandConfig['class'], $commandName);
235  $this->commandConfigurations[$commandName] = $commandConfig;
236 
237  trigger_error(
238  'Registering console commands in Configuration/Commands.php has been deprecated and will stop working in TYPO3 v11.0.',
239  E_USER_DEPRECATED
240  );
241  }
242  }
243  }
244  }
245  }
246 
247  protected function ‪getInstance(string $class): Command
248  {
249  return $this->container->get($class);
250  }
251 
255  public function ‪addLazyCommand(string $commandName, string $serviceName, bool $schedulable = true): void
256  {
257  $this->lazyCommandConfigurations[$commandName] = [
258  'class' => $serviceName,
259  'schedulable' => $schedulable,
260  ];
261  }
262 }
‪TYPO3\CMS\Core\Console\CommandRegistry\getIterator
‪Generator getIterator()
Definition: CommandRegistry.php:105
‪TYPO3\CMS\Core\Console\CommandRegistry\getInstance
‪getInstance(string $class)
Definition: CommandRegistry.php:242
‪TYPO3\CMS\Core\Console\UnknownCommandException
Definition: UnknownCommandException.php:26
‪TYPO3\CMS\Core\Console\CommandRegistry\getCommandByIdentifier
‪Command null getCommandByIdentifier(string $identifier)
Definition: CommandRegistry.php:158
‪TYPO3\CMS\Core\Console\CommandRegistry\$commandConfigurations
‪array[] $commandConfigurations
Definition: CommandRegistry.php:51
‪TYPO3\CMS\Core\Console\CommandRegistry\addLazyCommand
‪addLazyCommand(string $commandName, string $serviceName, bool $schedulable=true)
Definition: CommandRegistry.php:250
‪TYPO3\CMS\Core\Console\CommandRegistry\$container
‪ContainerInterface $container
Definition: CommandRegistry.php:39
‪TYPO3\CMS\Core\Console
Definition: CommandApplication.php:16
‪TYPO3\CMS\Core\Console\CommandRegistry
Definition: CommandRegistry.php:32
‪TYPO3\CMS\Core\Console\CommandRegistry\getLegacyCommands
‪Generator getLegacyCommands()
Definition: CommandRegistry.php:140
‪TYPO3\CMS\Core\Console\CommandRegistry\$lazyCommandConfigurations
‪array $lazyCommandConfigurations
Definition: CommandRegistry.php:57
‪TYPO3\CMS\Core\Console\CommandNameAlreadyInUseException
Definition: CommandNameAlreadyInUseException.php:25
‪TYPO3\CMS\Core\Console\CommandRegistry\getSchedulableCommands
‪Generator getSchedulableCommands()
Definition: CommandRegistry.php:123
‪TYPO3\CMS\Core\Console\CommandRegistry\has
‪has($name)
Definition: CommandRegistry.php:72
‪TYPO3\CMS\Core\Console\CommandRegistry\getNames
‪getNames()
Definition: CommandRegistry.php:94
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:23
‪TYPO3\CMS\Core\Console\CommandRegistry\populateCommandsFromPackages
‪populateCommandsFromPackages()
Definition: CommandRegistry.php:192
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Console\CommandRegistry\$commands
‪array $commands
Definition: CommandRegistry.php:45
‪TYPO3\CMS\Core\Console\CommandRegistry\__construct
‪__construct(PackageManager $packageManager, ContainerInterface $container)
Definition: CommandRegistry.php:63
‪TYPO3\CMS\Core\Console\CommandRegistry\$packageManager
‪PackageManager $packageManager
Definition: CommandRegistry.php:35