From 8dacd0b2f11bbf1404bc4de75c63bce2aaf1af27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Thu, 16 Nov 2023 09:28:11 +0100 Subject: [PATCH] feat: Support hidden commands Closes #194. --- src/Bridge/Command/SymfonyCommand.php | 3 +- src/Command/Configuration.php | 8 +- .../ApplicationHiddenCommandSupportTest.php | 100 ++++++++++++++++++ .../ApplicationSimpleConfigSupportTest.php | 4 + .../ConfigurableCommandsApplication.php | 9 +- tests/Command/Fixture/HiddenCommand.php | 43 ++++++++ 6 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 tests/Application/Feature/ApplicationHiddenCommandSupportTest.php create mode 100644 tests/Command/Fixture/HiddenCommand.php diff --git a/src/Bridge/Command/SymfonyCommand.php b/src/Bridge/Command/SymfonyCommand.php index dff858f6..be6f6ccb 100644 --- a/src/Bridge/Command/SymfonyCommand.php +++ b/src/Bridge/Command/SymfonyCommand.php @@ -65,7 +65,8 @@ protected function configure(): void $this ->setDescription($configuration->getDescription()) - ->setHelp($configuration->getHelp()); + ->setHelp($configuration->getHelp()) + ->setHidden($configuration->isHidden()); $definition = $this->getDefinition(); diff --git a/src/Command/Configuration.php b/src/Command/Configuration.php index 268a5943..5d0624b9 100644 --- a/src/Command/Configuration.php +++ b/src/Command/Configuration.php @@ -34,7 +34,8 @@ public function __construct( private readonly string $description, private readonly string $help, private readonly array $arguments = [], - private readonly array $options = [] + private readonly array $options = [], + private readonly bool $hidden = false, ) { } @@ -68,4 +69,9 @@ public function getOptions(): array { return $this->options; } + + public function isHidden(): bool + { + return $this->hidden; + } } diff --git a/tests/Application/Feature/ApplicationHiddenCommandSupportTest.php b/tests/Application/Feature/ApplicationHiddenCommandSupportTest.php new file mode 100644 index 00000000..dddf1b80 --- /dev/null +++ b/tests/Application/Feature/ApplicationHiddenCommandSupportTest.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Fidry\Console\Tests\Application\Feature; + +use Fidry\Console\Application\Application; +use Fidry\Console\Application\ApplicationRunner; +use Fidry\Console\Bridge\Application\SymfonyApplication; +use Fidry\Console\Bridge\Command\SymfonyCommand; +use Fidry\Console\Tests\Application\Fixture\ConfigurableCommandsApplication; +use Fidry\Console\Tests\Application\OutputAssertions; +use Fidry\Console\Tests\Command\Fixture\HiddenCommand; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Input\StringInput; +use Symfony\Component\Console\Output\BufferedOutput; + +#[CoversClass(ApplicationRunner::class)] +#[CoversClass(SymfonyApplication::class)] +#[CoversClass(SymfonyCommand::class)] +final class ApplicationHiddenCommandSupportTest extends TestCase +{ + public function test_it_can_show_the_list_of_the_available_commands(): void + { + $input = new StringInput('list'); + $output = new BufferedOutput(); + + ApplicationRunner::runApplication( + self::createApplication(), + $input, + $output, + ); + + $actual = $output->fetch(); + $expected = <<<'EOT' + help message + + Usage: + command [options] [arguments] + + Options: + -h, --help Display help for the given command. When no command is given display help for the app:foo command + -q, --quiet Do not output any message + -V, --version Display this application version + --ansi|--no-ansi Force (or disable --no-ansi) ANSI output + -n, --no-interaction Do not ask any interactive question + -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug + + Available commands: + completion Dump the shell completion script + help Display help for a command + list List commands + + EOT; + + OutputAssertions::assertSameOutput( + $expected, + $actual, + ); + } + + public function test_it_can_execute_the_hidden_command(): void + { + $input = new StringInput('app:hidden'); + $output = new BufferedOutput(); + + ApplicationRunner::runApplication( + self::createApplication(), + $input, + $output, + ); + + $actual = $output->fetch(); + + OutputAssertions::assertSameOutput( + <<<'EOF' + OK + + EOF, + $actual, + ); + } + + private static function createApplication(): Application + { + return new ConfigurableCommandsApplication([ + new HiddenCommand(), + ]); + } +} diff --git a/tests/Application/Feature/ApplicationSimpleConfigSupportTest.php b/tests/Application/Feature/ApplicationSimpleConfigSupportTest.php index 8716d86a..a332bd3b 100644 --- a/tests/Application/Feature/ApplicationSimpleConfigSupportTest.php +++ b/tests/Application/Feature/ApplicationSimpleConfigSupportTest.php @@ -15,6 +15,8 @@ use Fidry\Console\Application\ApplicationRunner; use Fidry\Console\Bridge\Application\SymfonyApplication; +use Fidry\Console\Bridge\Command\SymfonyCommand; +use Fidry\Console\Command\Configuration; use Fidry\Console\Tests\Application\Fixture\SimpleApplication; use Fidry\Console\Tests\Application\OutputAssertions; use PHPUnit\Framework\Attributes\CoversClass; @@ -24,6 +26,8 @@ #[CoversClass(ApplicationRunner::class)] #[CoversClass(SymfonyApplication::class)] +#[CoversClass(SymfonyCommand::class)] +#[CoversClass(Configuration::class)] final class ApplicationSimpleConfigSupportTest extends TestCase { public function test_it_can_show_the_list_of_the_available_commands(): void diff --git a/tests/Application/Fixture/ConfigurableCommandsApplication.php b/tests/Application/Fixture/ConfigurableCommandsApplication.php index 7a97629c..0bae23e6 100644 --- a/tests/Application/Fixture/ConfigurableCommandsApplication.php +++ b/tests/Application/Fixture/ConfigurableCommandsApplication.php @@ -16,14 +16,15 @@ use Closure; use Fidry\Console\Application\Application; use Fidry\Console\Command\Command; +use function is_array; final class ConfigurableCommandsApplication implements Application { /** - * @param Closure(): Command[] $commandsFactory + * @param Command[]|Closure(): Command[] $commandsFactory */ public function __construct( - private readonly Closure $commandsFactory + private readonly Closure|array $commandsFactory ) { } @@ -44,6 +45,10 @@ public function getLongVersion(): string public function getCommands(): array { + if (is_array($this->commandsFactory)) { + return $this->commandsFactory; + } + return ($this->commandsFactory)(); } diff --git a/tests/Command/Fixture/HiddenCommand.php b/tests/Command/Fixture/HiddenCommand.php new file mode 100644 index 00000000..2460f3c5 --- /dev/null +++ b/tests/Command/Fixture/HiddenCommand.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Fidry\Console\Tests\Command\Fixture; + +use Fidry\Console\Command\Command; +use Fidry\Console\Command\Configuration; +use Fidry\Console\ExitCode; +use Fidry\Console\IO; + +/** + * Most basic command: only has a name & description and does not do anything + * during execution. + */ +final class HiddenCommand implements Command +{ + public function getConfiguration(): Configuration + { + return new Configuration( + 'app:hidden', + 'Description content', + 'Command name: "%command.name%", command full name: "%command.full_name%"', + hidden: true, + ); + } + + public function execute(IO $io): int + { + $io->writeln('OK'); + + return ExitCode::SUCCESS; + } +}