From 82587f387f37c94a4079865ed4b1cc530bb49158 Mon Sep 17 00:00:00 2001 From: Yoann Renard Date: Sun, 6 Jun 2021 13:20:25 +0200 Subject: [PATCH 1/2] Fix AsCommand usage without DI --- .../Component/Console/Command/Command.php | 42 ++++++++++ .../Console/Tests/Command/CommandTest.php | 82 ++++++++++++++++--- .../Fixtures/Commands/Php8TestCommand.php | 29 +++++++ .../Fixtures/{ => Commands}/TestCommand.php | 0 4 files changed, 143 insertions(+), 10 deletions(-) create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/Commands/Php8TestCommand.php rename src/Symfony/Component/Console/Tests/Fixtures/{ => Commands}/TestCommand.php (100%) diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index e35ae51ebfa28..cff67b624e2ab 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -45,6 +45,11 @@ class Command */ protected static $defaultDescription; + /** + * @var bool|null The default command visibility (true if hidden or false) + */ + protected static $defaultHidden; + private $application; private $name; private $processTitle; @@ -92,6 +97,22 @@ public static function getDefaultDescription(): ?string return $class === $r->class ? static::$defaultDescription : null; } + /** + * @return bool The default command hidden or false + */ + public static function getDefaultHidden(): ?bool + { + $class = static::class; + + if (\PHP_VERSION_ID >= 80000 && $attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class)) { + return $attribute[0]->getArguments()['hidden'] ?? false; + } + + $r = new \ReflectionProperty($class, 'defaultHidden'); + + return $class === $r->class ? static::$defaultHidden : false; + } + /** * @param string|null $name The name of the command; passing null means it must be set in configure() * @@ -109,6 +130,10 @@ public function __construct(string $name = null) $this->setDescription(static::getDefaultDescription() ?? ''); } + if (true !== $this->hidden) { + $this->setHidden(static::getDefaultHidden() ?? false); + } + $this->configure(); } @@ -490,6 +515,16 @@ public function setProcessTitle(string $title) */ public function getName() { + if (false !== strpos($this->name, '|')) { + return current( + array_values( + array_filter( + explode('|', $this->name) + ) + ) + ); + } + return $this->name; } @@ -613,6 +648,13 @@ public function setAliases(iterable $aliases) */ public function getAliases() { + if (false !== strpos($this->name, '|')) { + $aliases = array_values(array_filter(explode('|', $this->name))); + array_shift($aliases); + + return $aliases; + } + return $this->aliases; } diff --git a/src/Symfony/Component/Console/Tests/Command/CommandTest.php b/src/Symfony/Component/Console/Tests/Command/CommandTest.php index 68c0366210374..b1fad6f364366 100644 --- a/src/Symfony/Component/Console/Tests/Command/CommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/CommandTest.php @@ -33,7 +33,11 @@ class CommandTest extends TestCase public static function setUpBeforeClass(): void { self::$fixturesPath = __DIR__.'/../Fixtures/'; - require_once self::$fixturesPath.'/TestCommand.php'; + require_once self::$fixturesPath.'/Commands/TestCommand.php'; + + if (\PHP_VERSION_ID >= 80000) { + require_once self::$fixturesPath.'/Commands/Php8TestCommand.php'; + } } public function testConstructor() @@ -410,10 +414,73 @@ public function testSetCodeWithStaticAnonymousFunction() /** * @requires PHP 8 */ - public function testCommandAttribute() - { - $this->assertSame('|foo|f', Php8Command::getDefaultName()); - $this->assertSame('desc', Php8Command::getDefaultDescription()); + public function provideCommandsWithAttribute(): \Traversable + { + yield '`name` only' => [ + [ + 'defaultName' => 'foo', + 'defaultDescription' => null, + 'name' => 'foo', + 'description' => '', + 'aliases' => [], + ], + \Php8Command2::class, + ]; + + yield '`name` and `description` set' => [ + [ + 'defaultName' => 'foo', + 'defaultDescription' => 'desc', + 'name' => 'foo', + 'description' => 'desc', + 'aliases' => [], + ], + \Php8Command3::class, + ]; + + yield '`name`, `description` and `aliases` set' => [ + [ + 'defaultName' => 'foo|f', + 'defaultDescription' => 'desc', + 'name' => 'foo', + 'description' => 'desc', + 'aliases' => ['f'], + ], + \Php8Command4::class, + ]; + + yield '`name`, `description`, `aliases` and `hidden` = true set' => [ + [ + 'defaultName' => '|foo|f', + 'defaultDescription' => 'desc', + 'name' => 'foo', + 'description' => 'desc', + 'aliases' => ['f'], + ], + \Php8Command5::class, + ]; + } + + /** + * @requires PHP 8 + * + * @dataProvider provideCommandsWithAttribute + */ + public function testCommandAttribute(array $expectedCommandValues, string $commandPath) + { + /** @var Command $command */ + $command = new $commandPath(); + + $this->assertSame( + $expectedCommandValues, + [ + 'defaultName' => $command::getDefaultName(), + 'defaultDescription' => $command::getDefaultDescription(), + 'name' => $command->getName(), + 'description' => $command->getDescription(), + 'aliases' => $command->getAliases(), + ] + ); } } @@ -425,8 +492,3 @@ function createClosure() $output->writeln($this instanceof Command ? 'bound to the command' : 'not bound to the command'); }; } - -#[AsCommand(name: 'foo', description: 'desc', hidden: true, aliases: ['f'])] -class Php8Command extends Command -{ -} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Commands/Php8TestCommand.php b/src/Symfony/Component/Console/Tests/Fixtures/Commands/Php8TestCommand.php new file mode 100644 index 0000000000000..9e46c5f03e65a --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Commands/Php8TestCommand.php @@ -0,0 +1,29 @@ + Date: Sun, 6 Jun 2021 14:22:05 +0200 Subject: [PATCH 2/2] fixup! Fix AsCommand usage without DI --- src/Symfony/Component/Console/Tests/Command/CommandTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Component/Console/Tests/Command/CommandTest.php b/src/Symfony/Component/Console/Tests/Command/CommandTest.php index b1fad6f364366..d0de380af1e7d 100644 --- a/src/Symfony/Component/Console/Tests/Command/CommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/CommandTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Application; -use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Exception\InvalidOptionException; use Symfony\Component\Console\Helper\FormatterHelper;