Skip to content
Snippets Groups Projects
Commit 370de7f9 authored by Benjamin Franzke's avatar Benjamin Franzke Committed by Helmut Hummel
Browse files

[BUGFIX] Avoid loading console commands before container is current

The shortcut handling added in #86248 caused the matching command
to be loaded before the symfony DI container was made available to
GeneralUtility::makeInstance (FailsafeContainer was still active).
This caused services (e.g in #93442) that are instantiated using the
GeneralUtility::makeInstance-to-DI-Container bridge to fail
as these services are not available in the FailsafeContainer.

Background: the symfony Application:find() method did not just
search for a matching command, but it also initialized it, once found.
Therefore shortcut resolving is now handled within the TYPO3 command
application to ensure commands are only instantiated once the
symfony container (and localconf) is fully loaded.

Resolves: #93569
Related: #86248
Related: #93442
Releases: master
Change-Id: I717df6aa03f4f474e437f98eef62d291e39010fc
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/68254


Tested-by: default avatarcore-ci <typo3@b13.com>
Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: default avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: default avatarBenni Mack <benni@typo3.org>
Tested-by: default avatarHelmut Hummel <typo3@helhum.io>
Reviewed-by: default avatarBenni Mack <benni@typo3.org>
Reviewed-by: default avatarHelmut Hummel <typo3@helhum.io>
parent 732adf42
Branches
Tags
No related merge requests found
......@@ -85,20 +85,16 @@ class CommandApplication implements ApplicationInterface
$commandName = $this->getCommandName($input);
if ($this->wantsFullBoot($commandName)) {
// Do a full boot if command is not a low-level command
// Do a full container boot if command is not a 1:1 matching low-level command
$container = $this->bootService->getContainer();
$this->application->setCommandLoader($container->get(CommandRegistry::class));
$commandRegistry = $container->get(CommandRegistry::class);
$this->application->setCommandLoader($commandRegistry);
$this->context = $container->get(Context::class);
$isLowLevelCommandShortcut = false;
try {
$realName = $this->application->find($commandName)->getName();
// Do not load ext_localconf if a low level command was found
// due to using a shortcut
$isLowLevelCommandShortcut = !$this->wantsFullBoot($realName);
} catch (ExceptionInterface $e) {
// Errors must be ignored, full binding/validation happens later when the console application runs.
}
$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 && $this->essentialConfigurationExists()) {
$this->bootService->loadExtLocalconfDatabaseAndExtTables();
}
......@@ -120,6 +116,27 @@ class CommandApplication implements ApplicationInterface
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') {
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment