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 @@ +