From b4a1d2d45124b7ca87ec1e3bae40455c6be0cad8 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Fri, 3 Jun 2022 14:46:29 +0200 Subject: [PATCH 1/2] [Console] Escape % in command name & description from getDefault*() --- DependencyInjection/AddConsoleCommandPass.php | 2 +- .../AddConsoleCommandPassTest.php | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/DependencyInjection/AddConsoleCommandPass.php b/DependencyInjection/AddConsoleCommandPass.php index 666c8fa59..aff892cc2 100644 --- a/DependencyInjection/AddConsoleCommandPass.php +++ b/DependencyInjection/AddConsoleCommandPass.php @@ -55,7 +55,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)); } - $commandName = $class::getDefaultName(); + $commandName = $class::getDefaultName() !== null ? str_replace('%', '%%', $class::getDefaultName()) : null; } if (null === $commandName) { diff --git a/Tests/DependencyInjection/AddConsoleCommandPassTest.php b/Tests/DependencyInjection/AddConsoleCommandPassTest.php index 5e59f8fab..9c86fa98f 100644 --- a/Tests/DependencyInjection/AddConsoleCommandPassTest.php +++ b/Tests/DependencyInjection/AddConsoleCommandPassTest.php @@ -118,6 +118,30 @@ public function visibilityProvider() ]; } + 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'], $commandLoader->getArgument(1)); + $this->assertEquals([['to-escape' => new ServiceClosureArgument(new TypedReference('to-escape', EscapedDefaultsFromPhpCommand::class))]], $commandLocator->getArguments()); + $this->assertSame([], $container->getParameter('console.command.ids')); + + $command = $container->get('console.command_loader')->get('%%cmd%%'); + + $this->assertSame('%cmd%', $command->getName()); + } + public function testProcessThrowAnExceptionIfTheServiceIsAbstract() { $this->expectException(\InvalidArgumentException::class); @@ -250,3 +274,8 @@ class NamedCommand extends Command { protected static $defaultName = 'default'; } + +class EscapedDefaultsFromPhpCommand extends Command +{ + protected static $defaultName = '%cmd%'; +} From 77972627c95a1c36eefbc1776dbe98dc4ea1d852 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 23 Jun 2022 12:21:08 +0200 Subject: [PATCH 2/2] Fix global state pollution between tests run with ApplicationTester --- Tester/ApplicationTester.php | 38 +++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/Tester/ApplicationTester.php b/Tester/ApplicationTester.php index 4f99da18d..ce4e5c18d 100644 --- a/Tester/ApplicationTester.php +++ b/Tester/ApplicationTester.php @@ -54,17 +54,37 @@ public function __construct(Application $application) */ public function run(array $input, $options = []) { - $this->input = new ArrayInput($input); - if (isset($options['interactive'])) { - $this->input->setInteractive($options['interactive']); - } + $prevShellVerbosity = getenv('SHELL_VERBOSITY'); - if ($this->inputs) { - $this->input->setStream(self::createStream($this->inputs)); - } + try { + $this->input = new ArrayInput($input); + if (isset($options['interactive'])) { + $this->input->setInteractive($options['interactive']); + } - $this->initOutput($options); + if ($this->inputs) { + $this->input->setStream(self::createStream($this->inputs)); + } - return $this->statusCode = $this->application->run($this->input, $this->output); + $this->initOutput($options); + + return $this->statusCode = $this->application->run($this->input, $this->output); + } finally { + // SHELL_VERBOSITY is set by Application::configureIO so we need to unset/reset it + // to its previous value to avoid one test's verbosity to spread to the following tests + if (false === $prevShellVerbosity) { + if (\function_exists('putenv')) { + @putenv('SHELL_VERBOSITY'); + } + unset($_ENV['SHELL_VERBOSITY']); + unset($_SERVER['SHELL_VERBOSITY']); + } else { + if (\function_exists('putenv')) { + @putenv('SHELL_VERBOSITY='.$prevShellVerbosity); + } + $_ENV['SHELL_VERBOSITY'] = $prevShellVerbosity; + $_SERVER['SHELL_VERBOSITY'] = $prevShellVerbosity; + } + } } }