‪TYPO3CMS  ‪main
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;
23 use ‪TYPO3\CMS\Core\Adapter\EventDispatcherAdapter as SymfonyEventDispatcher;
25 use TYPO3\CMS\Core\Configuration\ConfigurationManager;
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 
81  public function ‪run()
82  {
83  $input = new ArgvInput();
84  ‪$output = new ConsoleOutput();
85 
86  $commandName = $this->‪getCommandName($input);
87  if ($this->‪wantsFullBoot($commandName)) {
88  // Do a full container boot if command is not a 1:1 matching low-level command
89  $container = $this->bootService->getContainer();
90  $eventDispatcher = $container->get(SymfonyEventDispatcher::class);
91  ‪$commandRegistry = $container->‪get(CommandRegistry::class);
92  $this->application->setDispatcher($eventDispatcher);
93  $this->application->setCommandLoader(‪$commandRegistry);
94  $this->context = $container->get(Context::class);
95 
96  $realName = $this->‪resolveShortcut($commandName, ‪$commandRegistry);
97  $isLowLevelCommandShortcut = $realName !== null && !$this->‪wantsFullBoot($realName);
98  // Load ext_localconf, except if a low level command shortcut was found
99  // or if essential configuration is missing
100  if (!$isLowLevelCommandShortcut && ‪Bootstrap::checkIfEssentialConfigurationExists($this->configurationManager)) {
101  $this->bootService->loadExtLocalconfDatabaseAndExtTables();
102  }
103  }
104 
105  $this->‪initializeContext();
106  // create the BE_USER object (not logged in yet)
107  ‪Bootstrap::initializeBackendUser(CommandLineUserAuthentication::class);
108  ‪$GLOBALS['LANG'] = $this->languageServiceFactory->createFromUserPreferences(‪$GLOBALS['BE_USER']);
109  // Make sure output is not buffered, so command-line output and interaction can take place
110  ob_clean();
111 
112  $exitCode = $this->application->run($input, ‪$output);
113  // exit codes > 255 are not handled in UNIX
114  if ($exitCode > 255) {
115  $exitCode = 255;
116  }
117 
118  exit($exitCode);
119  }
120 
121  private function ‪resolveShortcut(string $commandName, ‪CommandRegistry ‪$commandRegistry): ?string
122  {
123  if (‪$commandRegistry->‪has($commandName)) {
124  return $commandName;
125  }
126 
127  $allCommands = ‪$commandRegistry->‪getNames();
128  $expr = implode('[^:]*:', array_map(preg_quote(...), explode(':', $commandName))) . '[^:]*';
129  $commands = preg_grep('{^' . $expr . '}', $allCommands);
130 
131  if ($commands === false || count($commands) === 0) {
132  $commands = preg_grep('{^' . $expr . '}i', $allCommands);
133  }
134 
135  if ($commands === false || count($commands) !== 1) {
136  return null;
137  }
138 
139  return reset($commands);
140  }
141 
142  protected function ‪wantsFullBoot(string $commandName): bool
143  {
144  if ($commandName === 'help') {
145  return true;
146  }
147  return !$this->commandRegistry->has($commandName);
148  }
149 
150  protected function ‪getCommandName(ArgvInput $input): string
151  {
152  try {
153  $input->bind($this->application->getDefinition());
154  } catch (ExceptionInterface $e) {
155  // Errors must be ignored, full binding/validation happens later when the console application runs.
156  }
157 
158  return $input->getFirstArgument() ?? 'list';
159  }
160 
164  protected function ‪checkEnvironmentOrDie(): void
165  {
166  if (PHP_SAPI !== 'cli') {
167  die('Not called from a command line interface (e.g. a shell or scheduler).' . LF);
168  }
169  }
170 
174  protected function ‪initializeContext(): void
175  {
176  $this->context->setAspect('date', new ‪DateTimeAspect(new \DateTimeImmutable('@' . ‪$GLOBALS['EXEC_TIME'])));
177  $this->context->setAspect('visibility', new ‪VisibilityAspect(true, true));
178  $this->context->setAspect('workspace', new ‪WorkspaceAspect(0));
179  $this->context->setAspect('backend.user', new ‪UserAspect(null));
180  }
181 }
‪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:121
‪TYPO3\CMS\Core\Console\CommandApplication\run
‪run()
Definition: CommandApplication.php:81
‪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:35
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:54
‪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\Core\ApplicationInterface
Definition: ApplicationInterface.php:27
‪TYPO3\CMS\Core\Core\Bootstrap\initializeBackendUser
‪static initializeBackendUser($className=BackendUserAuthentication::class, ServerRequestInterface $request=null)
Definition: Bootstrap.php:514
‪TYPO3\CMS\Core\Console\CommandApplication\checkEnvironmentOrDie
‪checkEnvironmentOrDie()
Definition: CommandApplication.php:164
‪TYPO3\CMS\Core\Console\CommandRegistry\get
‪get(string $name)
Definition: CommandRegistry.php:64
‪TYPO3\CMS\Core\Console\CommandApplication\$commandRegistry
‪CommandRegistry $commandRegistry
Definition: CommandApplication.php:45
‪TYPO3\CMS\Core\Console\CommandRegistry\has
‪has(string $name)
Definition: CommandRegistry.php:56
‪TYPO3\CMS\Core\Adapter\EventDispatcherAdapter
Definition: EventDispatcherAdapter.php:24
‪TYPO3\CMS\Core\Console\CommandApplication\wantsFullBoot
‪wantsFullBoot(string $commandName)
Definition: CommandApplication.php:142
‪$output
‪$output
Definition: annotationChecker.php:119
‪TYPO3\CMS\Core\Console\CommandApplication\getCommandName
‪getCommandName(ArgvInput $input)
Definition: CommandApplication.php:150
‪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:76
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Core\Bootstrap
Definition: Bootstrap.php:64
‪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:216
‪TYPO3\CMS\Core\Console\CommandApplication\initializeContext
‪initializeContext()
Definition: CommandApplication.php:174
‪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