Skip to content

Commit e4d2645

Browse files
weitzmanchalasr
authored andcommitted
[Console] Allow Usages to be specified via #[AsCommand]
1 parent 9cae55b commit e4d2645

File tree

7 files changed

+25
-1
lines changed

7 files changed

+25
-1
lines changed

src/Symfony/Component/Console/Application.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,10 @@ public function addCommand(callable|Command $command): ?Command
564564
->setDescription($attribute->description ?? '')
565565
->setHelp($attribute->help ?? '')
566566
->setCode($command);
567+
568+
foreach ($attribute->usages as $usage) {
569+
$command->addUsage($usage);
570+
}
567571
}
568572

569573
$command->setApplication($this);

src/Symfony/Component/Console/Attribute/AsCommand.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ class AsCommand
2525
* @param string[] $aliases The list of aliases of the command. The command will be executed when using one of them (i.e. "cache:clean")
2626
* @param bool $hidden If true, the command won't be shown when listing all the available commands, but it can still be run as any other command
2727
* @param string|null $help The help content of the command, displayed with the help page
28+
* @param string[] $usages The list of usage examples, displayed with the help page
2829
*/
2930
public function __construct(
3031
public string $name,
3132
public ?string $description = null,
3233
array $aliases = [],
3334
bool $hidden = false,
3435
public ?string $help = null,
36+
public array $usages = [],
3537
) {
3638
if (!$hidden && !$aliases) {
3739
return;

src/Symfony/Component/Console/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ CHANGELOG
88
* Introduce `Symfony\Component\Console\Application::addCommand()` to simplify using invokable commands when the component is used standalone
99
* Deprecate `Symfony\Component\Console\Application::add()` in favor of `Symfony\Component\Console\Application::addCommand()`
1010
* Add `BackedEnum` support with `#[Argument]` and `#[Option]` inputs in invokable commands
11+
* Allow Usages to be specified via #[AsCommand] attribute.
1112

1213
7.3
1314
---

src/Symfony/Component/Console/Command/Command.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ public function __construct(?string $name = null)
134134
$this->setHelp($attribute?->help ?? '');
135135
}
136136

137+
foreach ($attribute?->usages ?? [] as $usage) {
138+
$this->addUsage($usage);
139+
}
140+
137141
if (\is_callable($this) && (new \ReflectionMethod($this, 'execute'))->getDeclaringClass()->name === self::class) {
138142
$this->code = new InvokableCommand($this, $this(...));
139143
}

src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ public function process(ContainerBuilder $container): void
9191

9292
$description = $tags[0]['description'] ?? null;
9393
$help = $tags[0]['help'] ?? null;
94+
$usages = $tags[0]['usages'] ?? null;
9495

9596
unset($tags[0]);
9697
$lazyCommandMap[$commandName] = $id;
@@ -108,6 +109,7 @@ public function process(ContainerBuilder $container): void
108109

109110
$description ??= $tag['description'] ?? null;
110111
$help ??= $tag['help'] ?? null;
112+
$usages ??= $tag['usages'] ?? null;
111113
}
112114

113115
$definition->addMethodCall('setName', [$commandName]);
@@ -124,6 +126,12 @@ public function process(ContainerBuilder $container): void
124126
$definition->addMethodCall('setHelp', [str_replace('%', '%%', $help)]);
125127
}
126128

129+
if ($usages) {
130+
foreach ($usages as $usage) {
131+
$definition->addMethodCall('addUsage', [$usage]);
132+
}
133+
}
134+
127135
if (!$description) {
128136
if (Command::class !== (new \ReflectionMethod($class, 'getDefaultDescription'))->class) {
129137
trigger_deprecation('symfony/console', '7.3', 'Overriding "Command::getDefaultDescription()" in "%s" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.', $class);

src/Symfony/Component/Console/Tests/Command/CommandTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,8 @@ public function testCommandAttribute()
457457
$this->assertSame('foo', $command->getName());
458458
$this->assertSame('desc', $command->getDescription());
459459
$this->assertSame('help', $command->getHelp());
460+
$this->assertCount(2, $command->getUsages());
461+
$this->assertStringContainsString('usage1', $command->getUsages()[0]);
460462
$this->assertTrue($command->isHidden());
461463
$this->assertSame(['f'], $command->getAliases());
462464
}
@@ -542,7 +544,7 @@ function createClosure()
542544
};
543545
}
544546

545-
#[AsCommand(name: 'foo', description: 'desc', hidden: true, aliases: ['f'], help: 'help')]
547+
#[AsCommand(name: 'foo', description: 'desc', usages: ['usage1', 'usage2'], hidden: true, aliases: ['f'], help: 'help')]
546548
class Php8Command extends Command
547549
{
548550
}

src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ public function testProcessInvokableCommand()
315315
$definition->addTag('console.command', [
316316
'command' => 'invokable',
317317
'description' => 'The command description',
318+
'usages' => ['usage1', 'usage2'],
318319
'help' => 'The %command.name% command help content.',
319320
]);
320321
$container->setDefinition('invokable_command', $definition);
@@ -325,6 +326,8 @@ public function testProcessInvokableCommand()
325326
self::assertTrue($container->has('invokable_command.command'));
326327
self::assertSame('The command description', $command->getDescription());
327328
self::assertSame('The %command.name% command help content.', $command->getHelp());
329+
self::assertCount(2, $command->getUsages());
330+
$this->assertStringContainsString('usage1', $command->getUsages()[0]);
328331
}
329332

330333
public function testProcessInvokableSignalableCommand()

0 commit comments

Comments
 (0)