context = $context; $this->commandRegistry = $commandRegistry; $this->configurationManager = $configurationMananger; $this->bootService = $bootService; $this->languageServiceFactory = $languageServiceFactory; $this->checkEnvironmentOrDie(); $this->application = new Application('TYPO3 CMS', (new Typo3Version())->getVersion()); $this->application->setAutoExit(false); $this->application->setDispatcher($eventDispatcher); $this->application->setCommandLoader($commandRegistry); // Replace default list command with TYPO3 override $this->application->addCommands([$commandRegistry->get('list')]); } /** * Run the Symfony Console application in this TYPO3 application */ public function run() { $input = new ArgvInput(); $output = new ConsoleOutput(); $commandName = $this->getCommandName($input); if ($this->wantsFullBoot($commandName)) { // Do a full container boot if command is not a 1:1 matching low-level command $container = $this->bootService->getContainer(); $eventDispatcher = $container->get(SymfonyEventDispatcher::class); $commandRegistry = $container->get(CommandRegistry::class); $this->application->setDispatcher($eventDispatcher); $this->application->setCommandLoader($commandRegistry); $this->context = $container->get(Context::class); $realName = $this->resolveShortcut($commandName, $commandRegistry); $isLowLevelCommandShortcut = $realName !== null && !$this->wantsFullBoot($realName); // Load ext_localconf, except if a low level command shortcut was found // or if essential configuration is missing if (!$isLowLevelCommandShortcut && Bootstrap::checkIfEssentialConfigurationExists($this->configurationManager)) { $this->bootService->loadExtLocalconfDatabase(); } } // Make sure output is not buffered, so command-line output and interaction can take place. // Bootstrap does not open a buffer anymore, but third-party extension code may have done // so while ext_localconf.php files were loaded. while (ob_get_level()) { ob_end_clean(); } $this->initializeContext(); // create the BE_USER object (not logged in yet) Bootstrap::initializeBackendUser(CommandLineUserAuthentication::class); $GLOBALS['LANG'] = $this->languageServiceFactory->createFromUserPreferences($GLOBALS['BE_USER']); $exitCode = $this->application->run($input, $output); // exit codes > 255 are not handled in UNIX if ($exitCode > 255) { $exitCode = 255; } exit($exitCode); } private function resolveShortcut(string $commandName, CommandRegistry $commandRegistry): ?string { if ($commandRegistry->has($commandName)) { return $commandName; } $allCommands = $commandRegistry->getNames(); $expr = implode('[^:]*:', array_map(preg_quote(...), explode(':', $commandName))) . '[^:]*'; $commands = preg_grep('{^' . $expr . '}', $allCommands); if ($commands === false || count($commands) === 0) { $commands = preg_grep('{^' . $expr . '}i', $allCommands); } if ($commands === false || count($commands) !== 1) { return null; } return reset($commands); } protected function wantsFullBoot(string $commandName): bool { if ($commandName === 'help') { return true; } return !$this->commandRegistry->has($commandName); } protected function getCommandName(ArgvInput $input): string { try { $input->bind($this->application->getDefinition()); } catch (ExceptionInterface $e) { // Errors must be ignored, full binding/validation happens later when the console application runs. } return $input->getFirstArgument() ?? 'list'; } /** * Check the script is called from a cli environment. */ protected function checkEnvironmentOrDie(): void { if (PHP_SAPI !== 'cli') { die('Not called from a command line interface (e.g. a shell or scheduler).' . LF); } } /** * Initializes the Context used for accessing data and finding out the current state of the application */ protected function initializeContext(): void { $this->context->setAspect('date', new DateTimeAspect(DateTimeFactory::createFromTimestamp($GLOBALS['EXEC_TIME']))); $this->context->setAspect('visibility', new VisibilityAspect(true, true, false, true)); $this->context->setAspect('workspace', new WorkspaceAspect(0)); $this->context->setAspect('backend.user', new UserAspect(null)); } }