Skip to content

Commit 9382f67

Browse files
committed
Register all commands via #[AsCommand], even non-invokable ones
1 parent c0ddc10 commit 9382f67

File tree

3 files changed

+19
-24
lines changed

3 files changed

+19
-24
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -613,15 +613,7 @@ public function load(array $configs, ContainerBuilder $container): void
613613
$container->registerForAutoconfiguration(Command::class)
614614
->addTag('console.command');
615615
$container->registerAttributeForAutoconfiguration(AsCommand::class, static function (ChildDefinition $definition, AsCommand $attribute, \ReflectionClass $reflector): void {
616-
if ($reflector->isSubclassOf(Command::class)) {
617-
return;
618-
}
619-
620-
if (!$reflector->hasMethod('__invoke')) {
621-
throw new LogicException(\sprintf('The class "%s" must implement the "__invoke()" method to be registered as an invokable command.', $reflector->getName()));
622-
}
623-
624-
$definition->addTag('console.command', ['command' => $attribute->name, 'description' => $attribute->description ?? $reflector->getName(), 'invokable' => true]);
616+
$definition->addTag('console.command', ['command' => $attribute->name, 'description' => $attribute->description ?? $reflector->getName()]);
625617
});
626618
$container->registerForAutoconfiguration(ResourceCheckerInterface::class)
627619
->addTag('config_cache.resource_checker');

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

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,25 +37,28 @@ public function process(ContainerBuilder $container): void
3737
$serviceIds = [];
3838

3939
foreach ($commandServices as $id => $tags) {
40-
if ($tags[0]['invokable'] ?? false) {
41-
$invokableRef = new Reference($id);
42-
$definition = $container->register($id .= '.command', $class = Command::class)
43-
->addMethodCall('setCode', [$invokableRef]);
44-
} else {
45-
$definition = $container->getDefinition($id);
46-
$class = $container->getParameterBag()->resolveValue($definition->getClass());
47-
}
40+
$definition = $container->getDefinition($id);
41+
$class = $container->getParameterBag()->resolveValue($definition->getClass());
4842
$definition->addTag('container.no_preload');
4943

44+
if (!$r = $container->getReflectionClass($class)) {
45+
throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
46+
}
47+
48+
if (!$r->isSubclassOf(Command::class)) {
49+
if (\method_exists($class, '__invoke')) {
50+
$invokableRef = new Reference($id);
51+
$definition = $container->register($id .= '.command', $class = Command::class)
52+
->addMethodCall('setCode', [$invokableRef]);
53+
} else {
54+
throw new InvalidArgumentException(\sprintf('The service "%s" tagged "%s" must either be a subclass of "%s" or have an "__invoke()" method.', $id, 'console.command', Command::class));
55+
}
56+
}
57+
58+
5059
if (isset($tags[0]['command'])) {
5160
$aliases = $tags[0]['command'];
5261
} else {
53-
if (!$r = $container->getReflectionClass($class)) {
54-
throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
55-
}
56-
if (!$r->isSubclassOf(Command::class)) {
57-
throw new InvalidArgumentException(\sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, 'console.command', Command::class));
58-
}
5962
$aliases = str_replace('%', '%%', $class::getDefaultName() ?? '');
6063
}
6164

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ public function testProcessThrowAnExceptionIfTheServiceIsNotASubclassOfCommand()
206206
$container->setDefinition('my-command', $definition);
207207

208208
$this->expectException(\InvalidArgumentException::class);
209-
$this->expectExceptionMessage('The service "my-command" tagged "console.command" must be a subclass of "Symfony\Component\Console\Command\Command".');
209+
$this->expectExceptionMessage('The service "my-command" tagged "console.command" must either be a subclass of "Symfony\Component\Console\Command\Command" or have an "__invoke()" method');
210210

211211
$container->compile();
212212
}

0 commit comments

Comments
 (0)