From b898c179891b575b500b4011fa901c74952b3844 Mon Sep 17 00:00:00 2001 From: Benni Mack <benni@typo3.org> Date: Tue, 28 Feb 2017 08:51:15 +0100 Subject: [PATCH] [FEATURE] Allow Extbase CLI commands to be available via new CLI API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensures to call extbase commands & command controllers automatically via the new CLI binary. Extbase now also overrides the help command by symfony to allow extbase custom HelpCommandController to come into play when an Extbase command was called. This patch is critical for v8 so all core-internal CLI commands are available via "typo3/sysext/core/bin/typo3", otherwise we'd need to explain every admin that there are two CLI entrypoints for v8 which are relevant, because Extbase is still solely using "typo3/cli_dispatch.phpsh" until now, while all other entry points have been migrated already. Resolves: #80452 Releases: master Change-Id: I70e56c2cbef993cf16dfb212ba1a11add0017a01 Reviewed-on: https://review.typo3.org/51886 Tested-by: TYPO3com <no-reply@typo3.com> Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch> Tested-by: Christian Kuhn <lolli@schwarzbu.ch> Reviewed-by: Frank Nägler <frank.naegler@typo3.org> Tested-by: Frank Nägler <frank.naegler@typo3.org> --- ...xtbaseCLICommandsAvailableViaNewCLIAPI.rst | 18 ++++ .../extbase/Classes/Command/CoreCommand.php | 84 +++++++++++++++++ .../Classes/Command/ExtbaseCommand.php | 85 ++++++++++++++++++ .../extbase/Classes/Command/HelpCommand.php | 89 +++++++++++++++++++ .../Classes/Mvc/Cli/RequestHandler.php | 7 +- .../sysext/extbase/Configuration/Commands.php | 16 ++++ 6 files changed, 298 insertions(+), 1 deletion(-) create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Feature-80452-ExtbaseCLICommandsAvailableViaNewCLIAPI.rst create mode 100644 typo3/sysext/extbase/Classes/Command/CoreCommand.php create mode 100644 typo3/sysext/extbase/Classes/Command/ExtbaseCommand.php create mode 100644 typo3/sysext/extbase/Classes/Command/HelpCommand.php create mode 100644 typo3/sysext/extbase/Configuration/Commands.php diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-80452-ExtbaseCLICommandsAvailableViaNewCLIAPI.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-80452-ExtbaseCLICommandsAvailableViaNewCLIAPI.rst new file mode 100644 index 000000000000..9312119b0c39 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-80452-ExtbaseCLICommandsAvailableViaNewCLIAPI.rst @@ -0,0 +1,18 @@ +.. include:: ../../Includes.txt + +================================================================ +Feature: #80452 - Extbase CLI commands available via new CLI API +================================================================ + +See :issue:`80452` + +Description +=========== + +Any Extbase Command Controller can now be accessed via the new Symfony Console CLI entrypoint by +simply calling `typo3/sysext/core/bin/typo3 controller:command`. + +Using the existing CLI entrypoint via `typo3/cli_dispatch.phpsh extbase controller:command` still +works as expected. + +.. index:: CLI \ No newline at end of file diff --git a/typo3/sysext/extbase/Classes/Command/CoreCommand.php b/typo3/sysext/extbase/Classes/Command/CoreCommand.php new file mode 100644 index 000000000000..15f1bff454f6 --- /dev/null +++ b/typo3/sysext/extbase/Classes/Command/CoreCommand.php @@ -0,0 +1,84 @@ +<?php +namespace TYPO3\CMS\Extbase\Command; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Core\Bootstrap; +use TYPO3\CMS\Extbase\Mvc\Cli\CommandManager; +use TYPO3\CMS\Extbase\Object\ObjectManager; + +/** + * Main call to register any Extbase command from Extbase command controllers + * + * Fetches all registered Extbase commands and adds them to the application as custom Extbase commands + */ +class CoreCommand extends Command +{ + /** + * @var Bootstrap + */ + protected $extbaseBootstrap; + + /** + * Configure the command, since this is a command + */ + protected function configure() + { + $this->setHidden(true); + } + + /** + * Sets the application instance for this command. + * This is done in setApplication() because configure() is called too early to do it in that place. + * The method 'setApplication()' is done right afterwards but has the application object to call. + * Then registers additional commands that act as wrappers to the actual Extbase commands. + * + * @param Application $application An Application instance + */ + public function setApplication(Application $application = null) + { + parent::setApplication($application); + + // Find any registered Extbase commands + $this->extbaseBootstrap = GeneralUtility::makeInstance(Bootstrap::class); + $this->extbaseBootstrap->initialize([]); + + $objectManager = GeneralUtility::makeInstance(ObjectManager::class); + + /** @var CommandManager $commandManager */ + $commandManager = $objectManager->get(CommandManager::class); + $commands = $commandManager->getAvailableCommands(); + foreach ($commands as $command) { + $commandName = $commandManager->getShortestIdentifierForCommand($command); + $fullCommandName = $command->getCommandIdentifier(); + if ($fullCommandName === 'extbase:help:error' || $fullCommandName === 'extbase:help:helpstub') { + continue; + } + if ($commandName === 'help') { + $commandName = 'extbase:help'; + } + $extbaseCommand = GeneralUtility::makeInstance(ExtbaseCommand::class, $fullCommandName); + + if ($commandName !== $fullCommandName) { + $extbaseCommand->setAliases([$commandName]); + } + + $extbaseCommand->setExtbaseCommand($command); + $this->getApplication()->add($extbaseCommand); + } + } +} diff --git a/typo3/sysext/extbase/Classes/Command/ExtbaseCommand.php b/typo3/sysext/extbase/Classes/Command/ExtbaseCommand.php new file mode 100644 index 000000000000..34c000cb14f5 --- /dev/null +++ b/typo3/sysext/extbase/Classes/Command/ExtbaseCommand.php @@ -0,0 +1,85 @@ +<?php +namespace TYPO3\CMS\Extbase\Command; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Core\Bootstrap; + +/** + * Wrapper to wrap an Extbase command from a command controller into a Symfony Command + */ +class ExtbaseCommand extends Command +{ + /** + * Extbase's command + * @var \TYPO3\CMS\Extbase\Mvc\Cli\Command + */ + protected $command; + + /** + * Extbase has its own validation logic, so it is disabled in this place + */ + protected function configure() + { + $this->ignoreValidationErrors(); + } + + /** + * Sets the extbase command to be used for fetching the description etc. + * + * @param \TYPO3\CMS\Extbase\Mvc\Cli\Command $command + */ + public function setExtbaseCommand(\TYPO3\CMS\Extbase\Mvc\Cli\Command $command) + { + $this->command = $command; + } + + /** + * Sets the application instance for this command. + * Also uses the setApplication call now, as $this->configure() is called + * too early + * + * @param Application $application An Application instance + */ + public function setApplication(Application $application = null) + { + parent::setApplication($application); + $description = $this->command->getDescription(); + $description = str_replace(LF, ' ', $description); + $this->setDescription($description); + } + + /** + * Executes the command to find any Extbase command + * + * @param InputInterface $input + * @param OutputInterface $output + * @return void + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + // ugly hack because extbase only knows "help" (hardcoded, but already defined by symfony) + // and "extbase:help:help" + if ($_SERVER['argv'][1] === 'extbase:help') { + $_SERVER['argv'][1] = 'extbase:help:help'; + } + $bootstrap = GeneralUtility::makeInstance(Bootstrap::class); + $bootstrap->run('', []); + } +} diff --git a/typo3/sysext/extbase/Classes/Command/HelpCommand.php b/typo3/sysext/extbase/Classes/Command/HelpCommand.php new file mode 100644 index 000000000000..065eb775f4f6 --- /dev/null +++ b/typo3/sysext/extbase/Classes/Command/HelpCommand.php @@ -0,0 +1,89 @@ +<?php +namespace TYPO3\CMS\Extbase\Command; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Core\Bootstrap; + +/** + * Extends the help command of symfony to show the specific help for Extbase commands + */ +class HelpCommand extends \Symfony\Component\Console\Command\HelpCommand +{ + /** + * This needs to be re-set as the parent command has this property declared as "private" as well. + * + * @var Command + */ + private $command; + + /** + * {@inheritdoc} + */ + protected function configure() + { + parent::configure(); + $this->setAliases([]); + } + + /** + * Sets the command. + * + * @param Command $command The command to set + */ + public function setCommand(Command $command) + { + $this->command = $command; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + if (null === $this->command) { + $this->command = $this->getApplication()->find($input->getArgument('command_name')); + } + + // Extbase help was explicitly called + if ($input->getArgument('command') === 'extbase:help' || $input->getArgument('command') === 'extbase:help:help') { + $_SERVER['argv'][1] = 'extbase:help:help'; + $bootstrap = GeneralUtility::makeInstance(Bootstrap::class); + $bootstrap->run('', []); + + // An extbase command was originally called, but is now required to show the help information + } elseif ($this->command instanceof ExtbaseCommand) { + // Ugly hack to modify 'argv' so the help command for a specific command is shown + $args = [$_SERVER['argv'][0], 'help']; + foreach ($_SERVER['argv'] as $k => $value) { + if ($k === 0 || $value === '--help' || $value === '-h') { + continue; + } + $args[] = $value; + } + $_SERVER['argv'] = $args; + + // run Extbase bootstrap + $bootstrap = GeneralUtility::makeInstance(Bootstrap::class); + $bootstrap->run('', []); + } else { + // Any other symfony command should just show up the regular info + parent::execute($input, $output); + } + } +} diff --git a/typo3/sysext/extbase/Classes/Mvc/Cli/RequestHandler.php b/typo3/sysext/extbase/Classes/Mvc/Cli/RequestHandler.php index f2d3b2047b42..01f4f7f00be9 100644 --- a/typo3/sysext/extbase/Classes/Mvc/Cli/RequestHandler.php +++ b/typo3/sysext/extbase/Classes/Mvc/Cli/RequestHandler.php @@ -85,7 +85,12 @@ class RequestHandler implements \TYPO3\CMS\Extbase\Mvc\RequestHandlerInterface if ($callingScript !== $_SERVER['_']) { $callingScript = $_SERVER['_'] . ' ' . $callingScript; } - $request = $this->requestBuilder->build($commandLine, $callingScript . ' extbase'); + + // Add the "extbase" prefix for the cli_dispatch command line tool + if (strpos($callingScript, 'cli_dispatch') !== false) { + $callingScript .= ' extbase'; + } + $request = $this->requestBuilder->build($commandLine, $callingScript); /** @var $response \TYPO3\CMS\Extbase\Mvc\Cli\Response */ $response = $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\Cli\Response::class); $this->dispatcher->dispatch($request, $response); diff --git a/typo3/sysext/extbase/Configuration/Commands.php b/typo3/sysext/extbase/Configuration/Commands.php new file mode 100644 index 000000000000..7bb11c5e143c --- /dev/null +++ b/typo3/sysext/extbase/Configuration/Commands.php @@ -0,0 +1,16 @@ +<?php +/** + * Commands to be executed by typo3, where the key of the array + * is the name of the command (to be called as the first argument after typo3). + * Required parameter is the "class" of the command which needs to be a subclass + * of Symfony/Console/Command. + */ +return [ + 'extbase' => [ + 'class' => \TYPO3\CMS\Extbase\Command\CoreCommand::class + ], + // Overriding Symfony Help command to use Extbase-specific output + '_extbase_help' => [ + 'class' => \TYPO3\CMS\Extbase\Command\HelpCommand::class + ] +]; -- GitLab