From 026a7dfbbd79686c323080d17e4afa2d9e910799 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Mon, 13 Mar 2023 11:05:52 +0100 Subject: [PATCH] feat(event): Introduce a new ConsoleEventV2 modern event to replace depreciated ConsoleEvent event Signed-off-by: Thomas Citharel --- console.php | 5 +- lib/composer/composer/autoload_classmap.php | 1 + lib/composer/composer/autoload_static.php | 1 + lib/private/Console/Application.php | 80 +++++++++++---------- lib/public/Console/ConsoleEvent.php | 2 + lib/public/Console/ConsoleEventV2.php | 55 ++++++++++++++ 6 files changed, 107 insertions(+), 37 deletions(-) create mode 100644 lib/public/Console/ConsoleEventV2.php diff --git a/console.php b/console.php index f9a4689bd5895..41b99fdd3cd7e 100644 --- a/console.php +++ b/console.php @@ -34,6 +34,7 @@ require_once __DIR__ . '/lib/versioncheck.php'; use OC\Console\Application; +use OCP\Server; use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Output\ConsoleOutput; @@ -92,9 +93,11 @@ function exceptionHandler($exception) { $application = new Application( \OC::$server->getConfig(), \OC::$server->getEventDispatcher(), + Server::get(\OCP\EventDispatcher\IEventDispatcher::class), \OC::$server->getRequest(), \OC::$server->get(\Psr\Log\LoggerInterface::class), - \OC::$server->query(\OC\MemoryInfo::class) + \OC::$server->query(\OC\MemoryInfo::class), + Server::get(\OCP\Defaults::class) ); $application->loadCommands(new ArgvInput(), new ConsoleOutput()); $application->run(); diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 1ecd8152c0f37..ee2b6310a5fe8 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -179,6 +179,7 @@ 'OCP\\Config\\BeforePreferenceDeletedEvent' => $baseDir . '/lib/public/Config/BeforePreferenceDeletedEvent.php', 'OCP\\Config\\BeforePreferenceSetEvent' => $baseDir . '/lib/public/Config/BeforePreferenceSetEvent.php', 'OCP\\Console\\ConsoleEvent' => $baseDir . '/lib/public/Console/ConsoleEvent.php', + 'OCP\\Console\\ConsoleEventV2' => $baseDir . '/lib/public/Console/ConsoleEventV2.php', 'OCP\\Constants' => $baseDir . '/lib/public/Constants.php', 'OCP\\Contacts\\ContactsMenu\\IAction' => $baseDir . '/lib/public/Contacts/ContactsMenu/IAction.php', 'OCP\\Contacts\\ContactsMenu\\IActionFactory' => $baseDir . '/lib/public/Contacts/ContactsMenu/IActionFactory.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 2127835e51483..23eefa5a9d443 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -212,6 +212,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Config\\BeforePreferenceDeletedEvent' => __DIR__ . '/../../..' . '/lib/public/Config/BeforePreferenceDeletedEvent.php', 'OCP\\Config\\BeforePreferenceSetEvent' => __DIR__ . '/../../..' . '/lib/public/Config/BeforePreferenceSetEvent.php', 'OCP\\Console\\ConsoleEvent' => __DIR__ . '/../../..' . '/lib/public/Console/ConsoleEvent.php', + 'OCP\\Console\\ConsoleEventV2' => __DIR__ . '/../../..' . '/lib/public/Console/ConsoleEventV2.php', 'OCP\\Constants' => __DIR__ . '/../../..' . '/lib/public/Constants.php', 'OCP\\Contacts\\ContactsMenu\\IAction' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IAction.php', 'OCP\\Contacts\\ContactsMenu\\IActionFactory' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IActionFactory.php', diff --git a/lib/private/Console/Application.php b/lib/private/Console/Application.php index 07e9dbb317b27..46f4e4e8a7ff2 100644 --- a/lib/private/Console/Application.php +++ b/lib/private/Console/Application.php @@ -30,43 +30,48 @@ */ namespace OC\Console; +use ArgumentCountError; +use Exception; use OC\MemoryInfo; use OC\NeedsUpdateException; +use OC\SystemConfig; use OC_App; -use OCP\AppFramework\QueryException; use OCP\App\IAppManager; use OCP\Console\ConsoleEvent; +use OCP\Console\ConsoleEventV2; +use OCP\Defaults; +use OCP\EventDispatcher\IEventDispatcher; use OCP\IConfig; use OCP\IRequest; +use OCP\Server; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; use Symfony\Component\Console\Application as SymfonyApplication; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; class Application { - /** @var IConfig */ - private $config; + private IConfig $config; private SymfonyApplication $application; - /** @var EventDispatcherInterface */ - private $dispatcher; - /** @var IRequest */ - private $request; - /** @var LoggerInterface */ - private $logger; - /** @var MemoryInfo */ - private $memoryInfo; + private EventDispatcherInterface $legacyDispatcher; + private IEventDispatcher $dispatcher; + private IRequest $request; + private LoggerInterface $logger; + private MemoryInfo $memoryInfo; public function __construct(IConfig $config, - EventDispatcherInterface $dispatcher, + EventDispatcherInterface $legacyDispatcher, + IEventDispatcher $dispatcher, IRequest $request, LoggerInterface $logger, - MemoryInfo $memoryInfo) { - $defaults = \OC::$server->getThemingDefaults(); + MemoryInfo $memoryInfo, Defaults $defaults) { $this->config = $config; $this->application = new SymfonyApplication($defaults->getName(), \OC_Util::getVersionString()); + $this->legacyDispatcher = $legacyDispatcher; $this->dispatcher = $dispatcher; $this->request = $request; $this->logger = $logger; @@ -76,12 +81,14 @@ public function __construct(IConfig $config, /** * @param InputInterface $input * @param ConsoleOutputInterface $output - * @throws \Exception + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws Exception */ public function loadCommands( InputInterface $input, ConsoleOutputInterface $output - ) { + ): void { // $application is required to be defined in the register_command scripts $application = $this->application; $inputDefinition = $application->getDefinition(); @@ -119,7 +126,7 @@ public function loadCommands( $this->writeMaintenanceModeInfo($input, $output); } else { OC_App::loadApps(); - $appManager = \OCP\Server::get(IAppManager::class); + $appManager = Server::get(IAppManager::class); foreach ($appManager->getInstalledApps() as $app) { $appPath = \OC_App::getAppPath($app); if ($appPath === false) { @@ -136,7 +143,7 @@ public function loadCommands( if (file_exists($file)) { try { require $file; - } catch (\Exception $e) { + } catch (Exception $e) { $this->logger->error($e->getMessage(), [ 'exception' => $e, ]); @@ -148,7 +155,7 @@ public function loadCommands( $errorOutput = $output->getErrorOutput(); $errorOutput->writeln("Nextcloud is not installed - only a limited number of commands are available"); } - } catch (NeedsUpdateException $e) { + } catch (NeedsUpdateException) { if ($input->getArgument('command') !== '_completion') { $errorOutput = $output->getErrorOutput(); $errorOutput->writeln("Nextcloud or one of the apps require upgrade - only a limited number of commands are available"); @@ -157,14 +164,14 @@ public function loadCommands( } if ($input->getFirstArgument() !== 'check') { - $errors = \OC_Util::checkServer(\OC::$server->getSystemConfig()); + $errors = \OC_Util::checkServer(Server::get(SystemConfig::class)); if (!empty($errors)) { foreach ($errors as $error) { $output->writeln((string)$error['error']); $output->writeln((string)$error['hint']); $output->writeln(''); } - throw new \Exception("Environment not properly prepared."); + throw new Exception("Environment not properly prepared."); } } } @@ -180,7 +187,7 @@ public function loadCommands( */ private function writeMaintenanceModeInfo( InputInterface $input, ConsoleOutputInterface $output - ) { + ): void { if ($input->getArgument('command') !== '_completion' && $input->getArgument('command') !== 'maintenance:mode' && $input->getArgument('command') !== 'status') { @@ -197,37 +204,38 @@ private function writeMaintenanceModeInfo( * * @param bool $boolean Whether to automatically exit after a command execution or not */ - public function setAutoExit($boolean) { + public function setAutoExit(bool $boolean): void { $this->application->setAutoExit($boolean); } /** - * @param InputInterface $input - * @param OutputInterface $output - * @return int - * @throws \Exception + * @throws Exception */ - public function run(InputInterface $input = null, OutputInterface $output = null) { - $this->dispatcher->dispatch(ConsoleEvent::EVENT_RUN, new ConsoleEvent( + public function run(InputInterface $input = null, OutputInterface $output = null): int { + $this->legacyDispatcher->dispatch(ConsoleEvent::EVENT_RUN, new ConsoleEvent( ConsoleEvent::EVENT_RUN, $this->request->server['argv'] )); + $this->dispatcher->dispatchTyped(new ConsoleEventV2($this->request->server['argv'])); return $this->application->run($input, $output); } - private function loadCommandsFromInfoXml($commands) { + /** + * @throws Exception + */ + private function loadCommandsFromInfoXml($commands): void { foreach ($commands as $command) { try { - $c = \OC::$server->query($command); - } catch (QueryException $e) { + $c = Server::get($command); + } catch (ContainerExceptionInterface $e) { if (class_exists($command)) { try { $c = new $command(); - } catch (\ArgumentCountError $e2) { - throw new \Exception("Failed to construct console command '$command': " . $e->getMessage(), 0, $e); + } catch (ArgumentCountError) { + throw new Exception("Failed to construct console command '$command': " . $e->getMessage(), 0, $e); } } else { - throw new \Exception("Console command '$command' is unknown and could not be loaded"); + throw new Exception("Console command '$command' is unknown and could not be loaded"); } } diff --git a/lib/public/Console/ConsoleEvent.php b/lib/public/Console/ConsoleEvent.php index 99f42d2895fbb..1f1f7c2ee0677 100644 --- a/lib/public/Console/ConsoleEvent.php +++ b/lib/public/Console/ConsoleEvent.php @@ -28,6 +28,8 @@ /** * Class ConsoleEvent * + * @deprecated 27.0.0 Use ConsoleEventV2 typed event instead + * * @since 9.0.0 */ class ConsoleEvent extends Event { diff --git a/lib/public/Console/ConsoleEventV2.php b/lib/public/Console/ConsoleEventV2.php new file mode 100644 index 0000000000000..5b06c9c0f8dae --- /dev/null +++ b/lib/public/Console/ConsoleEventV2.php @@ -0,0 +1,55 @@ + + * @author Christoph Wurst + * @author Joas Schilling + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ +namespace OCP\Console; + +use OCP\EventDispatcher\Event; + +/** + * Class ConsoleEvent + * + * @since 27.0.0 + */ +class ConsoleEventV2 extends Event { + /** @var string[] */ + protected array $arguments; + + /** + * DispatcherEvent constructor. + * + * @param string[] $arguments + * @since 27.0.0 + */ + public function __construct(array $arguments) { + $this->arguments = $arguments; + parent::__construct(); + } + + /** + * @return string[] + * @since 27.0.0 + */ + public function getArguments(): array { + return $this->arguments; + } +}