diff --git a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php index 743e306d07b9a..2c9ebe668e517 100644 --- a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php +++ b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php @@ -67,7 +67,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, $this->commandTag, Command::class)); } - $aliases = $class::getDefaultName(); + $aliases = str_replace('%', '%%', $class::getDefaultName()); } $aliases = explode('|', $aliases ?? ''); @@ -124,7 +124,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, $this->commandTag, Command::class)); } - $description = $class::getDefaultDescription(); + $description = str_replace('%', '%%', $class::getDefaultDescription()); } if ($description) { diff --git a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php index aa92c76f159c3..eec4eff438eef 100644 --- a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php +++ b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php @@ -153,6 +153,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); @@ -286,6 +313,12 @@ class NamedCommand extends Command protected static $defaultName = 'default'; } +class EscapedDefaultsFromPhpCommand extends Command +{ + protected static $defaultName = '%cmd%|%cmdalias%'; + protected static $defaultDescription = 'Creates a 80% discount'; +} + class DescribedCommand extends Command { public static $initCounter = 0;