diff --git a/DependencyInjection/AddConsoleCommandPass.php b/DependencyInjection/AddConsoleCommandPass.php index 433455666..62c80c3b0 100644 --- a/DependencyInjection/AddConsoleCommandPass.php +++ b/DependencyInjection/AddConsoleCommandPass.php @@ -50,7 +50,7 @@ public function process(ContainerBuilder $container) if (!$r->isSubclassOf(Command::class)) { throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, 'console.command', Command::class)); } - $aliases = $class::getDefaultName(); + $aliases = str_replace('%', '%%', $class::getDefaultName() ?? ''); } $aliases = explode('|', $aliases ?? ''); @@ -107,7 +107,7 @@ public function process(ContainerBuilder $container) if (!$r->isSubclassOf(Command::class)) { throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, 'console.command', Command::class)); } - $description = $class::getDefaultDescription(); + $description = str_replace('%', '%%', $class::getDefaultDescription() ?? ''); } if ($description) { diff --git a/Tests/DependencyInjection/AddConsoleCommandPassTest.php b/Tests/DependencyInjection/AddConsoleCommandPassTest.php index adbc61e85..ddda0f472 100644 --- a/Tests/DependencyInjection/AddConsoleCommandPassTest.php +++ b/Tests/DependencyInjection/AddConsoleCommandPassTest.php @@ -154,6 +154,33 @@ public function testProcessFallsBackToDefaultDescription() $this->assertSame(1 + $initCounter, DescribedCommand::$initCounter); } + public function testEscapesDefaultFromPhp() + { + $container = new ContainerBuilder(); + $container + ->register('to-escape', EscapedDefaultsFromPhpCommand::class) + ->addTag('console.command') + ; + + $pass = new AddConsoleCommandPass(); + $pass->process($container); + + $commandLoader = $container->getDefinition('console.command_loader'); + $commandLocator = $container->getDefinition((string) $commandLoader->getArgument(0)); + + $this->assertSame(ContainerCommandLoader::class, $commandLoader->getClass()); + $this->assertSame(['%%cmd%%' => 'to-escape', '%%cmdalias%%' => 'to-escape'], $commandLoader->getArgument(1)); + $this->assertEquals([['to-escape' => new ServiceClosureArgument(new Reference('.to-escape.lazy'))]], $commandLocator->getArguments()); + $this->assertSame([], $container->getParameter('console.command.ids')); + + $command = $container->get('console.command_loader')->get('%%cmd%%'); + + $this->assertInstanceOf(LazyCommand::class, $command); + $this->assertSame('%cmd%', $command->getName()); + $this->assertSame(['%cmdalias%'], $command->getAliases()); + $this->assertSame('Creates a 80% discount', $command->getDescription()); + } + public function testProcessThrowAnExceptionIfTheServiceIsAbstract() { $this->expectException(\InvalidArgumentException::class); @@ -287,6 +314,11 @@ class NamedCommand extends Command { } +#[AsCommand(name: '%cmd%|%cmdalias%', description: 'Creates a 80% discount')] +class EscapedDefaultsFromPhpCommand extends Command +{ +} + #[AsCommand(name: '|cmdname|cmdalias', description: 'Just testing')] class DescribedCommand extends Command {