From 26815fcac3ef4667620c30bddf94482fd3504b56 Mon Sep 17 00:00:00 2001 From: Julien Rosset Date: Fri, 25 Oct 2024 11:25:08 +0200 Subject: [PATCH] Add command requirements support --- composer.json | 13 ++-- src/CliProgram/OutputHelper.php | 22 ++++++ src/CliProgram/Requirements/IRequirements.php | 24 +++++++ .../Requirements/TRequirementsApplication.php | 72 +++++++++++++++++++ tests/Application.php | 3 + tests/Commands/FailedHello.php | 15 ++++ tests/Commands/Hello.php | 6 +- tests/FailedRequirement.php | 19 +++++ tests/SuccessRequirement.php | 17 +++++ 9 files changed, 183 insertions(+), 8 deletions(-) create mode 100644 src/CliProgram/OutputHelper.php create mode 100644 src/CliProgram/Requirements/IRequirements.php create mode 100644 src/CliProgram/Requirements/TRequirementsApplication.php create mode 100644 tests/Commands/FailedHello.php create mode 100644 tests/FailedRequirement.php create mode 100644 tests/SuccessRequirement.php diff --git a/composer.json b/composer.json index 6b3c649..c739b50 100644 --- a/composer.json +++ b/composer.json @@ -15,12 +15,13 @@ "minimum-stability": "stable", "require": { - "php": "^8.1", - "jrosset/betterphptoken": "^1.0", - "jrosset/extendedmonolog": "^2.0", - "psr/log": "^2.0", - "symfony/console": "^6.1", - "voku/arrayy": "^7.9" + "php": "^8.1", + "jrosset/betterphptoken": "^1.0", + "jrosset/extendedmonolog": "^2.0", + "psr/log": "^2.0", + "symfony/console": "^6.1", + "symfony/event-dispatcher": "^6.1", + "voku/arrayy": "^7.9" }, "autoload": { "psr-4": { diff --git a/src/CliProgram/OutputHelper.php b/src/CliProgram/OutputHelper.php new file mode 100644 index 0000000..b92944b --- /dev/null +++ b/src/CliProgram/OutputHelper.php @@ -0,0 +1,22 @@ +getErrorOutput() : $output; + } +} \ No newline at end of file diff --git a/src/CliProgram/Requirements/IRequirements.php b/src/CliProgram/Requirements/IRequirements.php new file mode 100644 index 0000000..181e3af --- /dev/null +++ b/src/CliProgram/Requirements/IRequirements.php @@ -0,0 +1,24 @@ +addListener(ConsoleEvents::COMMAND, $this->checkCommandRequirements(...)); + $this->setDispatcher($dispatcher); + } + + /** + * Check the requirements of a command + * + * @param ConsoleCommandEvent $event The command event + * + * @return void + */ + private function checkCommandRequirements (ConsoleCommandEvent $event): void { + $commandInput = $event->getInput(); + $commandOutput = $event->getOutput(); + try { + //region Check the command is valid + if (($command = $event->getCommand()) === null) { + return; + } + + $commandReflection = new ReflectionClass($command); + //endregion + //region Check attribute requirements + foreach ($commandReflection->getAttributes(IRequirements::class, ReflectionAttribute::IS_INSTANCEOF) as $commandRequirementsAttribute) { + /** @var IRequirements $commandRequirementsAttributeInstance */ + $commandRequirementsAttributeInstance = $commandRequirementsAttribute->newInstance(); + $commandRequirementsAttributeInstance->checkRequirements($commandInput, $commandOutput); + } + //endregion + //region Contrôle pré-requis (implémentation directe) + if ($command instanceof IRequirements) { + $command->checkRequirements($commandInput, $commandOutput); + } + //endregion + } + catch (Throwable $exception) { + $this->renderThrowable($exception, OutputHelper::getErrorOutput($commandOutput)); + + $event->disableCommand(); + $event->stopPropagation(); + return; + } + } +} \ No newline at end of file diff --git a/tests/Application.php b/tests/Application.php index 16748cf..22e8e2a 100644 --- a/tests/Application.php +++ b/tests/Application.php @@ -6,12 +6,15 @@ use jrosset\CliProgram\ApplicationWithCommandMonolog; use jrosset\CliProgram\AutoDiscovery\AutoDiscoveryDirectory; use jrosset\CliProgram\AutoDiscovery\TAutoDiscoveryApplication; use jrosset\CliProgram\AutoPrefix\AutoPrefixNamespaceManager; +use jrosset\CliProgram\Requirements\TRequirementsApplication; class Application extends ApplicationWithCommandMonolog { use TAutoDiscoveryApplication; + use TRequirementsApplication; public function __construct (string $name = 'UNKNOWN', string $version = 'UNKNOWN') { parent::__construct(__DIR__ . '/logs/', $name, $version); + $this->registerCommandRequirementsListener(); $spot = new AutoDiscoveryDirectory(__DIR__ . '/Commands'); $spot->getAutoPrefixManagers()->prepend(new AutoPrefixNamespaceManager('\\jrosset\\Tests\\Commands', 'test')); diff --git a/tests/Commands/FailedHello.php b/tests/Commands/FailedHello.php new file mode 100644 index 0000000..27ad9ba --- /dev/null +++ b/tests/Commands/FailedHello.php @@ -0,0 +1,15 @@ +