‪TYPO3CMS  11.5
CommandApplication.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\Application as SymfonyConsoleApplication;
19 use Symfony\Component\Console\Exception\ExceptionInterface;
20 use Symfony\Component\Console\Input\ArgvInput;
21 use Symfony\Component\Console\Output\ConsoleOutput;
22 use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
24 use TYPO3\CMS\Core\Configuration\ConfigurationManager;
35 use TYPO3\SymfonyPsrEventDispatcherAdapter\EventDispatcherAdapter as SymfonyEventDispatcher;
36 
42 {
44 
46 
47  protected ConfigurationManager ‪$configurationManager;
48 
50 
52 
53  protected SymfonyConsoleApplication ‪$application;
54 
55  public function ‪__construct(
58  EventDispatcherInterface $eventDispatcher,
59  ConfigurationManager $configurationMananger,
62  ) {
63  $this->context = ‪$context;
64  $this->commandRegistry = ‪$commandRegistry;
65  $this->configurationManager = $configurationMananger;
66  $this->bootService = ‪$bootService;
67  $this->languageServiceFactory = ‪$languageServiceFactory;
68 
69  $this->‪checkEnvironmentOrDie();
70  $this->application = new ‪Application('TYPO3 CMS', (new ‪Typo3Version())->getVersion());
71  $this->application->setAutoExit(false);
72  $this->application->setDispatcher($eventDispatcher);
73  $this->application->setCommandLoader(‪$commandRegistry);
74  // Replace default list command with TYPO3 override
75  $this->application->add(‪$commandRegistry->‪get('list'));
76  }
77 
83  public function ‪run(callable $execute = null)
84  {
85  $input = new ArgvInput();
86  ‪$output = new ConsoleOutput();
87 
88  $commandName = $this->‪getCommandName($input);
89  if ($this->‪wantsFullBoot($commandName)) {
90  // Do a full container boot if command is not a 1:1 matching low-level command
91  $container = $this->bootService->getContainer();
92  $eventDispatcher = $container->get(SymfonyEventDispatcher::class);
93  ‪$commandRegistry = $container->‪get(CommandRegistry::class);
94  $this->application->setDispatcher($eventDispatcher);
95  $this->application->setCommandLoader(‪$commandRegistry);
96  $this->context = $container->get(Context::class);
97 
98  $realName = $this->‪resolveShortcut($commandName, ‪$commandRegistry);
99  $isLowLevelCommandShortcut = $realName !== null && !$this->‪wantsFullBoot($realName);
100  // Load ext_localconf, except if a low level command shortcut was found
101  // or if essential configuration is missing
102  if (!$isLowLevelCommandShortcut && ‪Bootstrap::checkIfEssentialConfigurationExists($this->configurationManager)) {
103  $this->bootService->loadExtLocalconfDatabaseAndExtTables();
104  }
105  }
106 
107  $this->‪initializeContext();
108  // create the BE_USER object (not logged in yet)
109  ‪Bootstrap::initializeBackendUser(CommandLineUserAuthentication::class);
110  ‪$GLOBALS['LANG'] = $this->languageServiceFactory->createFromUserPreferences(‪$GLOBALS['BE_USER']);
111  // Make sure output is not buffered, so command-line output and interaction can take place
112  ob_clean();
113 
114  $exitCode = $this->application->run($input, ‪$output);
115 
116  if ($execute !== null) {
117  trigger_error('Custom execution of Application code will be removed in TYPO3 v12.0.', E_USER_DEPRECATED);
118  $execute();
119  }
120 
121  exit($exitCode);
122  }
123 
124  private function ‪resolveShortcut(string $commandName, ‪CommandRegistry ‪$commandRegistry): ?string
125  {
126  if (‪$commandRegistry->‪has($commandName)) {
127  return $commandName;
128  }
129 
130  $allCommands = ‪$commandRegistry->‪getNames();
131  $expr = implode('[^:]*:', array_map('preg_quote', explode(':', $commandName))) . '[^:]*';
132  $commands = preg_grep('{^' . $expr . '}', $allCommands);
133 
134  if ($commands === false || count($commands) === 0) {
135  $commands = preg_grep('{^' . $expr . '}i', $allCommands);
136  }
137 
138  if ($commands === false || count($commands) !== 1) {
139  return null;
140  }
141 
142  return reset($commands);
143  }
144 
145  protected function ‪wantsFullBoot(string $commandName): bool
146  {
147  if ($commandName === 'help') {
148  return true;
149  }
150  return !$this->commandRegistry->has($commandName);
151  }
152 
153  protected function ‪getCommandName(ArgvInput $input): string
154  {
155  try {
156  $input->bind($this->application->getDefinition());
157  } catch (ExceptionInterface $e) {
158  // Errors must be ignored, full binding/validation happens later when the console application runs.
159  }
160 
161  return $input->getFirstArgument() ?? 'list';
162  }
163 
167  protected function ‪checkEnvironmentOrDie(): void
168  {
169  if (PHP_SAPI !== 'cli') {
170  die('Not called from a command line interface (e.g. a shell or scheduler).' . LF);
171  }
172  }
173 
177  protected function ‪initializeContext(): void
178  {
179  $this->context->setAspect(
180  'date',
181  new ‪DateTimeAspect(
182  (new \DateTimeImmutable())->setTimestamp(‪$GLOBALS['EXEC_TIME'])
183  )
184  );
185  $this->context->setAspect('visibility', new ‪VisibilityAspect(true, true));
186  $this->context->setAspect('workspace', new ‪WorkspaceAspect(0));
187  $this->context->setAspect('backend.user', new ‪UserAspect(null));
188  }
189 }
‪TYPO3\CMS\Core\Localization\LanguageServiceFactory
Definition: LanguageServiceFactory.php:25
‪TYPO3\CMS\Core\Context\VisibilityAspect
Definition: VisibilityAspect.php:31
‪TYPO3\CMS\Core\Console\CommandApplication\resolveShortcut
‪resolveShortcut(string $commandName, CommandRegistry $commandRegistry)
Definition: CommandApplication.php:124
‪TYPO3\CMS\Core\Context\WorkspaceAspect
Definition: WorkspaceAspect.php:31
‪TYPO3\CMS\Core\Information\Typo3Version
Definition: Typo3Version.php:21
‪TYPO3\CMS\Core\Console
Definition: Application.php:18
‪TYPO3\CMS\Core\Core\BootService
Definition: BootService.php:33
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:53
‪TYPO3\CMS\Core\Console\CommandApplication
Definition: CommandApplication.php:42
‪TYPO3\CMS\Core\Console\Application
Definition: Application.php:26
‪TYPO3\CMS\Core\Console\CommandRegistry
Definition: CommandRegistry.php:31
‪TYPO3\CMS\Core\Console\CommandApplication\$configurationManager
‪ConfigurationManager $configurationManager
Definition: CommandApplication.php:47
‪TYPO3\CMS\Core\Console\CommandApplication\run
‪run(callable $execute=null)
Definition: CommandApplication.php:83
‪TYPO3\CMS\Core\Core\ApplicationInterface
Definition: ApplicationInterface.php:25
‪TYPO3\CMS\Core\Core\Bootstrap\initializeBackendUser
‪static initializeBackendUser($className=BackendUserAuthentication::class, ServerRequestInterface $request=null)
Definition: Bootstrap.php:572
‪TYPO3\CMS\Core\Console\CommandApplication\checkEnvironmentOrDie
‪checkEnvironmentOrDie()
Definition: CommandApplication.php:167
‪TYPO3\CMS\Core\Console\CommandApplication\$commandRegistry
‪CommandRegistry $commandRegistry
Definition: CommandApplication.php:45
‪TYPO3\CMS\Core\Console\CommandApplication\wantsFullBoot
‪wantsFullBoot(string $commandName)
Definition: CommandApplication.php:145
‪$output
‪$output
Definition: annotationChecker.php:121
‪TYPO3\CMS\Core\Console\CommandRegistry\has
‪has($name)
Definition: CommandRegistry.php:59
‪TYPO3\CMS\Core\Console\CommandApplication\getCommandName
‪getCommandName(ArgvInput $input)
Definition: CommandApplication.php:153
‪TYPO3\CMS\Core\Console\CommandApplication\$context
‪Context $context
Definition: CommandApplication.php:43
‪TYPO3\CMS\Core\Console\CommandApplication\$bootService
‪BootService $bootService
Definition: CommandApplication.php:49
‪TYPO3\CMS\Core\Console\CommandRegistry\getNames
‪getNames()
Definition: CommandRegistry.php:79
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Core\Bootstrap
Definition: Bootstrap.php:70
‪TYPO3\CMS\Core\Console\CommandApplication\$application
‪SymfonyConsoleApplication $application
Definition: CommandApplication.php:53
‪TYPO3\CMS\Core\Core\Bootstrap\checkIfEssentialConfigurationExists
‪static bool checkIfEssentialConfigurationExists(ConfigurationManager $configurationManager)
Definition: Bootstrap.php:234
‪TYPO3\CMS\Core\Console\CommandRegistry\get
‪get($name)
Definition: CommandRegistry.php:67
‪TYPO3\CMS\Core\Console\CommandApplication\initializeContext
‪initializeContext()
Definition: CommandApplication.php:177
‪TYPO3\CMS\Core\Console\CommandApplication\$languageServiceFactory
‪LanguageServiceFactory $languageServiceFactory
Definition: CommandApplication.php:51
‪TYPO3\CMS\Core\Console\CommandApplication\__construct
‪__construct(Context $context, CommandRegistry $commandRegistry, EventDispatcherInterface $eventDispatcher, ConfigurationManager $configurationMananger, BootService $bootService, LanguageServiceFactory $languageServiceFactory)
Definition: CommandApplication.php:55
‪TYPO3\CMS\Core\Context\DateTimeAspect
Definition: DateTimeAspect.php:35
‪TYPO3\CMS\Core\Context\UserAspect
Definition: UserAspect.php:37
‪TYPO3\CMS\Core\Authentication\CommandLineUserAuthentication
Definition: CommandLineUserAuthentication.php:31