From 5bdcdda3176999eb73027a85344e6fd63f27d188 Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Tue, 9 Jan 2018 15:49:24 +0200 Subject: [PATCH 1/9] Add options to automatically run suggested command if there is only 1 alternative --- UPGRADE-4.1.md | 22 +++++++- UPGRADE-5.0.md | 23 +++++++- src/Symfony/Component/Console/Application.php | 21 +++++-- src/Symfony/Component/Console/CHANGELOG.md | 9 ++- .../Exception/NamespaceNotFoundException.php | 23 ++++++++ .../Console/Tests/ApplicationTest.php | 55 ++++++++++++++----- .../Tests/Fixtures/FooWithoutAliasCommand.php | 21 +++++++ 7 files changed, 151 insertions(+), 23 deletions(-) create mode 100644 src/Symfony/Component/Console/Exception/NamespaceNotFoundException.php create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/FooWithoutAliasCommand.php diff --git a/UPGRADE-4.1.md b/UPGRADE-4.1.md index b6b94be57aae2..e6f8444bfb3e7 100644 --- a/UPGRADE-4.1.md +++ b/UPGRADE-4.1.md @@ -7,11 +7,31 @@ Config * Implementing `ParentNodeDefinitionInterface` without the `getChildNodeDefinitions()` method is deprecated and will be unsupported in 5.0. +Console +------- + * The `Application::findNamespace` method throws an instance of `NamespaceNotFoundException` instead `CommandNotFoundException`. All catch statements should be updated to cater for both exceptions, E.G + + Before: + ```php + try { + $app->run(); + } catch (CommandNotFoundException $e) { + } + ``` + + After: + ```php + try { + $app->run(); + } catch (NamespaceNotFoundException | CommandNotFoundException $e) { + } + ``` + EventDispatcher --------------- * The `TraceableEventDispatcherInterface` has been deprecated and will be removed in 5.0. - + HttpFoundation -------------- diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md index d4d2a49d481f6..ed148bd256dda 100644 --- a/UPGRADE-5.0.md +++ b/UPGRADE-5.0.md @@ -5,12 +5,33 @@ Config ------ * Added the `getChildNodeDefinitions()` method to `ParentNodeDefinitionInterface`. + +Console +------- + + * The `NamespaceNotFoundException` doesn't extend `CommandNotFoundException` anymore. All catch statements should be updated to cater for both exceptions, E.G + + Before: + ```php + try { + $app->run(); + } catch (CommandNotFoundException $e) { + } + ``` + + After: + ```php + try { + $app->run(); + } catch (NamespaceNotFoundException | CommandNotFoundException $e) { + } + ``` EventDispatcher --------------- * The `TraceableEventDispatcherInterface` has been removed. - + HttpFoundation -------------- diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 00e941f13238a..38c807044b2ef 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -13,6 +13,7 @@ use Symfony\Component\Console\CommandLoader\CommandLoaderInterface; use Symfony\Component\Console\Exception\ExceptionInterface; +use Symfony\Component\Console\Exception\NamespaceNotFoundException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\DebugFormatterHelper; use Symfony\Component\Console\Helper\Helper; @@ -39,6 +40,7 @@ use Symfony\Component\Console\Event\ConsoleTerminateEvent; use Symfony\Component\Console\Exception\CommandNotFoundException; use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Debug\ErrorHandler; use Symfony\Component\Debug\Exception\FatalThrowableError; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -234,7 +236,18 @@ public function doRun(InputInterface $input, OutputInterface $output) $e = $event->getError(); } - throw $e; + if (!($e instanceof CommandNotFoundException && !$e instanceof NamespaceNotFoundException) || 1 !== count($alternatives = $e->getAlternatives()) || !$input->isInteractive()) { + throw $e; + } + + $alternative = $alternatives[0]; + $question = new ConfirmationQuestion(sprintf("Command \"%s\" is not defined.\n\nDo you want to run \"%s\" instead? [y/n] ", $name, $alternative), false); + + if (!(new QuestionHelper())->ask($input, $output, $question)) { + return 1; + } + + $command = $this->find($alternative); } $this->runningCommand = $command; @@ -533,7 +546,7 @@ public function getNamespaces() * * @return string A registered namespace * - * @throws CommandNotFoundException When namespace is incorrect or ambiguous + * @throws NamespaceNotFoundException When namespace is incorrect or ambiguous */ public function findNamespace($namespace) { @@ -554,12 +567,12 @@ public function findNamespace($namespace) $message .= implode("\n ", $alternatives); } - throw new CommandNotFoundException($message, $alternatives); + throw new NamespaceNotFoundException($message, $alternatives); } $exact = in_array($namespace, $namespaces, true); if (count($namespaces) > 1 && !$exact) { - throw new CommandNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces)); + throw new NamespaceNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces)); } return $exact ? $namespace : reset($namespaces); diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 2437748ae56e6..6dbca05b60517 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.1.0 +----- + + * added option to run suggested command if command is not found and only 1 alternative is available + 4.0.0 ----- @@ -8,8 +13,8 @@ CHANGELOG * removed `QuestionHelper::setInputStream()/getInputStream()` * removed `Application::getTerminalWidth()/getTerminalHeight()` and `Application::setTerminalDimensions()/getTerminalDimensions()` -* removed `ConsoleExceptionEvent` -* removed `ConsoleEvents::EXCEPTION` + * removed `ConsoleExceptionEvent` + * removed `ConsoleEvents::EXCEPTION` 3.4.0 ----- diff --git a/src/Symfony/Component/Console/Exception/NamespaceNotFoundException.php b/src/Symfony/Component/Console/Exception/NamespaceNotFoundException.php new file mode 100644 index 0000000000000..33fa99c12d4a1 --- /dev/null +++ b/src/Symfony/Component/Console/Exception/NamespaceNotFoundException.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * Represents an incorrect namespace typed in the console. + * + * @author Pierre du Plessis + * + * @deprecated This class won't extend CommandNotFoundException in Symfony 5 + */ +class NamespaceNotFoundException extends CommandNotFoundException +{ +} diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index e9432c522d6f7..981b8131b8e05 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -16,6 +16,7 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\CommandLoader\FactoryCommandLoader; use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; +use Symfony\Component\Console\Exception\NamespaceNotFoundException; use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Helper\FormatterHelper; use Symfony\Component\Console\Input\ArgvInput; @@ -56,6 +57,7 @@ public static function setUpBeforeClass() require_once self::$fixturesPath.'/BarBucCommand.php'; require_once self::$fixturesPath.'/FooSubnamespaced1Command.php'; require_once self::$fixturesPath.'/FooSubnamespaced2Command.php'; + require_once self::$fixturesPath.'/FooWithoutAliasCommand.php'; require_once self::$fixturesPath.'/TestTiti.php'; require_once self::$fixturesPath.'/TestToto.php'; } @@ -275,10 +277,10 @@ public function testFindAmbiguousNamespace() $expectedMsg = "The namespace \"f\" is ambiguous.\nDid you mean one of these?\n foo\n foo1"; if (method_exists($this, 'expectException')) { - $this->expectException(CommandNotFoundException::class); + $this->expectException(NamespaceNotFoundException::class); $this->expectExceptionMessage($expectedMsg); } else { - $this->setExpectedException(CommandNotFoundException::class, $expectedMsg); + $this->setExpectedException(NamespaceNotFoundException::class, $expectedMsg); } $application->findNamespace('f'); @@ -293,7 +295,7 @@ public function testFindNonAmbiguous() } /** - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException + * @expectedException \Symfony\Component\Console\Exception\NamespaceNotFoundException * @expectedExceptionMessage There are no commands defined in the "bar" namespace. */ public function testFindInvalidNamespace() @@ -457,6 +459,29 @@ public function testFindAlternativeExceptionMessageSingle($name) $application->find($name); } + public function testCanRunAlternativeCommandName() + { + $application = new Application(); + $application->add(new \FooWithoutAliasCommand()); + $application->setAutoExit(false); + $tester = new ApplicationTester($application); + $tester->setInputs(array('y')); + $tester->run(array('command' => 'foos'), array('decorated' => false)); + $this->assertSame("Command \"foos\" is not defined.\n\nDo you want to run \"foo\" instead? [y/n] called\n", $tester->getDisplay(true)); + } + + public function testDontRunAlternativeCommandName() + { + $application = new Application(); + $application->add(new \FooWithoutAliasCommand()); + $application->setAutoExit(false); + $tester = new ApplicationTester($application); + $tester->setInputs(array('n')); + $exitCode = $tester->run(array('command' => 'foos'), array('decorated' => false)); + $this->assertSame(1, $exitCode); + $this->assertSame("Command \"foos\" is not defined.\n\nDo you want to run \"foo\" instead? [y/n] ", $tester->getDisplay(true)); + } + public function provideInvalidCommandNamesSingle() { return array( @@ -486,10 +511,10 @@ public function testFindAlternativeExceptionMessageMultiple() // Namespace + plural try { $application->find('foo2:bar'); - $this->fail('->find() throws a CommandNotFoundException if command does not exist, with alternatives'); + $this->fail('->find() throws a NamespaceNotFoundException if command does not exist, with alternatives'); } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); - $this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); + $this->assertInstanceOf('Symfony\Component\Console\Exception\NamespaceNotFoundException', $e, '->find() throws a NamespaceNotFoundException if command does not exist, with alternatives'); + $this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws a NamespaceNotFoundException if command does not exist, with alternatives'); $this->assertRegExp('/foo1/', $e->getMessage()); } @@ -563,26 +588,26 @@ public function testFindAlternativeNamespace() try { $application->find('Unknown-namespace:Unknown-command'); - $this->fail('->find() throws a CommandNotFoundException if namespace does not exist'); + $this->fail('->find() throws a NamespaceNotFoundException if namespace does not exist'); } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if namespace does not exist'); + $this->assertInstanceOf('Symfony\Component\Console\Exception\NamespaceNotFoundException', $e, '->find() throws a NamespaceNotFoundException if namespace does not exist'); $this->assertSame(array(), $e->getAlternatives()); - $this->assertEquals('There are no commands defined in the "Unknown-namespace" namespace.', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, without alternatives'); + $this->assertEquals('There are no commands defined in the "Unknown-namespace" namespace.', $e->getMessage(), '->find() throws a NamespaceNotFoundException if namespace does not exist, without alternatives'); } try { $application->find('foo2:command'); - $this->fail('->find() throws a CommandNotFoundException if namespace does not exist'); + $this->fail('->find() throws a NamespaceNotFoundException if namespace does not exist'); } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if namespace does not exist'); + $this->assertInstanceOf('Symfony\Component\Console\Exception\NamespaceNotFoundException', $e, '->find() throws a NamespaceNotFoundException if namespace does not exist'); $this->assertCount(3, $e->getAlternatives()); $this->assertContains('foo', $e->getAlternatives()); $this->assertContains('foo1', $e->getAlternatives()); $this->assertContains('foo3', $e->getAlternatives()); - $this->assertRegExp('/There are no commands defined in the "foo2" namespace./', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative'); - $this->assertRegExp('/foo/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo"'); - $this->assertRegExp('/foo1/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo1"'); - $this->assertRegExp('/foo3/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo3"'); + $this->assertRegExp('/There are no commands defined in the "foo2" namespace./', $e->getMessage(), '->find() throws a NamespaceNotFoundException if namespace does not exist, with alternative'); + $this->assertRegExp('/foo/', $e->getMessage(), '->find() throws a NamespaceNotFoundException if namespace does not exist, with alternative : "foo"'); + $this->assertRegExp('/foo1/', $e->getMessage(), '->find() throws a NamespaceNotFoundException if namespace does not exist, with alternative : "foo1"'); + $this->assertRegExp('/foo3/', $e->getMessage(), '->find() throws a NamespaceNotFoundException if namespace does not exist, with alternative : "foo3"'); } } diff --git a/src/Symfony/Component/Console/Tests/Fixtures/FooWithoutAliasCommand.php b/src/Symfony/Component/Console/Tests/Fixtures/FooWithoutAliasCommand.php new file mode 100644 index 0000000000000..e301cc5f5b3ab --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/FooWithoutAliasCommand.php @@ -0,0 +1,21 @@ +setName('foo') + ->setDescription('The foo command') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $output->writeln('called'); + } +} From d93ca23357b166a44d6bcdbdceca6389fc037d87 Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Fri, 12 Jan 2018 15:44:24 +0200 Subject: [PATCH 2/9] Remove deprecation and future BC break --- UPGRADE-4.1.md | 20 ------------------ UPGRADE-5.0.md | 21 ------------------- .../Exception/NamespaceNotFoundException.php | 2 -- 3 files changed, 43 deletions(-) diff --git a/UPGRADE-4.1.md b/UPGRADE-4.1.md index e6f8444bfb3e7..2cfd6597cc7ce 100644 --- a/UPGRADE-4.1.md +++ b/UPGRADE-4.1.md @@ -7,26 +7,6 @@ Config * Implementing `ParentNodeDefinitionInterface` without the `getChildNodeDefinitions()` method is deprecated and will be unsupported in 5.0. -Console -------- - * The `Application::findNamespace` method throws an instance of `NamespaceNotFoundException` instead `CommandNotFoundException`. All catch statements should be updated to cater for both exceptions, E.G - - Before: - ```php - try { - $app->run(); - } catch (CommandNotFoundException $e) { - } - ``` - - After: - ```php - try { - $app->run(); - } catch (NamespaceNotFoundException | CommandNotFoundException $e) { - } - ``` - EventDispatcher --------------- diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md index ed148bd256dda..09fe44ac18562 100644 --- a/UPGRADE-5.0.md +++ b/UPGRADE-5.0.md @@ -6,27 +6,6 @@ Config * Added the `getChildNodeDefinitions()` method to `ParentNodeDefinitionInterface`. -Console -------- - - * The `NamespaceNotFoundException` doesn't extend `CommandNotFoundException` anymore. All catch statements should be updated to cater for both exceptions, E.G - - Before: - ```php - try { - $app->run(); - } catch (CommandNotFoundException $e) { - } - ``` - - After: - ```php - try { - $app->run(); - } catch (NamespaceNotFoundException | CommandNotFoundException $e) { - } - ``` - EventDispatcher --------------- diff --git a/src/Symfony/Component/Console/Exception/NamespaceNotFoundException.php b/src/Symfony/Component/Console/Exception/NamespaceNotFoundException.php index 33fa99c12d4a1..dd16e45086a73 100644 --- a/src/Symfony/Component/Console/Exception/NamespaceNotFoundException.php +++ b/src/Symfony/Component/Console/Exception/NamespaceNotFoundException.php @@ -15,8 +15,6 @@ * Represents an incorrect namespace typed in the console. * * @author Pierre du Plessis - * - * @deprecated This class won't extend CommandNotFoundException in Symfony 5 */ class NamespaceNotFoundException extends CommandNotFoundException { From f42a2bb6b1023a41edb8e317064202798d80e641 Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Mon, 15 Jan 2018 13:23:30 +0200 Subject: [PATCH 3/9] Revert unrelated changes in the changelog --- src/Symfony/Component/Console/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 6dbca05b60517..887ac2f83a8dc 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -13,8 +13,8 @@ CHANGELOG * removed `QuestionHelper::setInputStream()/getInputStream()` * removed `Application::getTerminalWidth()/getTerminalHeight()` and `Application::setTerminalDimensions()/getTerminalDimensions()` - * removed `ConsoleExceptionEvent` - * removed `ConsoleEvents::EXCEPTION` +* removed `ConsoleExceptionEvent` +* removed `ConsoleEvents::EXCEPTION` 3.4.0 ----- From e4deda713cbbd8436c15c639a631af996ccf5ce4 Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Mon, 15 Jan 2018 13:32:34 +0200 Subject: [PATCH 4/9] Dispatch console error event --- UPGRADE-4.1.md | 2 +- UPGRADE-5.0.md | 4 +-- src/Symfony/Component/Console/Application.php | 25 ++++++++++++------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/UPGRADE-4.1.md b/UPGRADE-4.1.md index 2cfd6597cc7ce..b6b94be57aae2 100644 --- a/UPGRADE-4.1.md +++ b/UPGRADE-4.1.md @@ -11,7 +11,7 @@ EventDispatcher --------------- * The `TraceableEventDispatcherInterface` has been deprecated and will be removed in 5.0. - + HttpFoundation -------------- diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md index 09fe44ac18562..d4d2a49d481f6 100644 --- a/UPGRADE-5.0.md +++ b/UPGRADE-5.0.md @@ -5,12 +5,12 @@ Config ------ * Added the `getChildNodeDefinitions()` method to `ParentNodeDefinitionInterface`. - + EventDispatcher --------------- * The `TraceableEventDispatcherInterface` has been removed. - + HttpFoundation -------------- diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 38c807044b2ef..4bc34a3f2cca2 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -225,18 +225,18 @@ public function doRun(InputInterface $input, OutputInterface $output) // the command name MUST be the first element of the input $command = $this->find($name); } catch (\Throwable $e) { - if (null !== $this->dispatcher) { - $event = new ConsoleErrorEvent($input, $output, $e); - $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); + if (!($e instanceof CommandNotFoundException && !$e instanceof NamespaceNotFoundException) || 1 !== count($alternatives = $e->getAlternatives()) || !$input->isInteractive()) { + if (null !== $this->dispatcher) { + $event = new ConsoleErrorEvent($input, $output, $e); + $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); - if (0 === $event->getExitCode()) { - return 0; - } + if (0 === $event->getExitCode()) { + return 0; + } - $e = $event->getError(); - } + $e = $event->getError(); + } - if (!($e instanceof CommandNotFoundException && !$e instanceof NamespaceNotFoundException) || 1 !== count($alternatives = $e->getAlternatives()) || !$input->isInteractive()) { throw $e; } @@ -244,6 +244,13 @@ public function doRun(InputInterface $input, OutputInterface $output) $question = new ConfirmationQuestion(sprintf("Command \"%s\" is not defined.\n\nDo you want to run \"%s\" instead? [y/n] ", $name, $alternative), false); if (!(new QuestionHelper())->ask($input, $output, $question)) { + if (null !== $this->dispatcher) { + $event = new ConsoleErrorEvent($input, $output, $e); + $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); + + return $event->getExitCode(); + } + return 1; } From 1b9f9eb59e77b3d67e446f610ccb1302af8a7e4f Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Mon, 29 Jan 2018 14:59:04 +0200 Subject: [PATCH 5/9] Dont run command if suggestion is only a namespace --- .../Console/Tests/ApplicationTest.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 981b8131b8e05..c337cb3ea27aa 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -459,6 +459,24 @@ public function testFindAlternativeExceptionMessageSingle($name) $application->find($name); } + public function testDontRunAlternativeNamespaceName() + { + $application = new Application(); + $application->add(new \Foo1Command()); + $application->setAutoExit(false); + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'foos:bar1'), array('decorated' => false)); + $this->assertSame(" + + There are no commands defined in the \"foos\" namespace. + + Did you mean this? + foo + + +", $tester->getDisplay(true)); + } + public function testCanRunAlternativeCommandName() { $application = new Application(); From f8a816d8ca96928a49cd8ca971551595d5a20d49 Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Sun, 11 Feb 2018 20:49:38 +0200 Subject: [PATCH 6/9] Use SymfonyStyle --- src/Symfony/Component/Console/Application.php | 6 +++-- .../Console/Tests/ApplicationTest.php | 25 +++++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 4bc34a3f2cca2..6f929ecb35278 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -41,6 +41,7 @@ use Symfony\Component\Console\Exception\CommandNotFoundException; use Symfony\Component\Console\Exception\LogicException; use Symfony\Component\Console\Question\ConfirmationQuestion; +use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Debug\ErrorHandler; use Symfony\Component\Debug\Exception\FatalThrowableError; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -241,9 +242,10 @@ public function doRun(InputInterface $input, OutputInterface $output) } $alternative = $alternatives[0]; - $question = new ConfirmationQuestion(sprintf("Command \"%s\" is not defined.\n\nDo you want to run \"%s\" instead? [y/n] ", $name, $alternative), false); - if (!(new QuestionHelper())->ask($input, $output, $question)) { + $style = new SymfonyStyle($input, $output); + $style->block(sprintf("\nCommand \"%s\" is not defined.\n", $name), null, 'error'); + if (!$style->confirm(sprintf("Do you want to run \"%s\" instead? ", $alternative), false)) { if (null !== $this->dispatcher) { $event = new ConsoleErrorEvent($input, $output, $e); $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index c337cb3ea27aa..3efec8f56f678 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -485,7 +485,18 @@ public function testCanRunAlternativeCommandName() $tester = new ApplicationTester($application); $tester->setInputs(array('y')); $tester->run(array('command' => 'foos'), array('decorated' => false)); - $this->assertSame("Command \"foos\" is not defined.\n\nDo you want to run \"foo\" instead? [y/n] called\n", $tester->getDisplay(true)); + $this->assertSame(<< +called + +OUTPUT +, $tester->getDisplay(true)); } public function testDontRunAlternativeCommandName() @@ -497,7 +508,17 @@ public function testDontRunAlternativeCommandName() $tester->setInputs(array('n')); $exitCode = $tester->run(array('command' => 'foos'), array('decorated' => false)); $this->assertSame(1, $exitCode); - $this->assertSame("Command \"foos\" is not defined.\n\nDo you want to run \"foo\" instead? [y/n] ", $tester->getDisplay(true)); + $this->assertSame(<< + +OUTPUT + , $tester->getDisplay(true)); } public function provideInvalidCommandNamesSingle() From bf46ffe943abaf3db994b5dfd84697fb745db06a Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Sun, 11 Feb 2018 20:53:38 +0200 Subject: [PATCH 7/9] Revert some changes to tests --- .../Console/Tests/ApplicationTest.php | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 3efec8f56f678..ee695e977480f 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -550,10 +550,10 @@ public function testFindAlternativeExceptionMessageMultiple() // Namespace + plural try { $application->find('foo2:bar'); - $this->fail('->find() throws a NamespaceNotFoundException if command does not exist, with alternatives'); + $this->fail('->find() throws a CommandNotFoundException if command does not exist, with alternatives'); } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\NamespaceNotFoundException', $e, '->find() throws a NamespaceNotFoundException if command does not exist, with alternatives'); - $this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws a NamespaceNotFoundException if command does not exist, with alternatives'); + $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); + $this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); $this->assertRegExp('/foo1/', $e->getMessage()); } @@ -627,26 +627,27 @@ public function testFindAlternativeNamespace() try { $application->find('Unknown-namespace:Unknown-command'); - $this->fail('->find() throws a NamespaceNotFoundException if namespace does not exist'); + $this->fail('->find() throws a CommandNotFoundException if namespace does not exist'); } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\NamespaceNotFoundException', $e, '->find() throws a NamespaceNotFoundException if namespace does not exist'); + $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if namespace does not exist'); $this->assertSame(array(), $e->getAlternatives()); - $this->assertEquals('There are no commands defined in the "Unknown-namespace" namespace.', $e->getMessage(), '->find() throws a NamespaceNotFoundException if namespace does not exist, without alternatives'); + $this->assertEquals('There are no commands defined in the "Unknown-namespace" namespace.', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, without alternatives'); } try { $application->find('foo2:command'); - $this->fail('->find() throws a NamespaceNotFoundException if namespace does not exist'); + $this->fail('->find() throws a CommandNotFoundException if namespace does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\Component\Console\Exception\NamespaceNotFoundException', $e, '->find() throws a NamespaceNotFoundException if namespace does not exist'); + $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, 'NamespaceNotFoundException extends from CommandNotFoundException'); $this->assertCount(3, $e->getAlternatives()); $this->assertContains('foo', $e->getAlternatives()); $this->assertContains('foo1', $e->getAlternatives()); $this->assertContains('foo3', $e->getAlternatives()); - $this->assertRegExp('/There are no commands defined in the "foo2" namespace./', $e->getMessage(), '->find() throws a NamespaceNotFoundException if namespace does not exist, with alternative'); - $this->assertRegExp('/foo/', $e->getMessage(), '->find() throws a NamespaceNotFoundException if namespace does not exist, with alternative : "foo"'); - $this->assertRegExp('/foo1/', $e->getMessage(), '->find() throws a NamespaceNotFoundException if namespace does not exist, with alternative : "foo1"'); - $this->assertRegExp('/foo3/', $e->getMessage(), '->find() throws a NamespaceNotFoundException if namespace does not exist, with alternative : "foo3"'); + $this->assertRegExp('/There are no commands defined in the "foo2" namespace./', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative'); + $this->assertRegExp('/foo/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo"'); + $this->assertRegExp('/foo1/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo1"'); + $this->assertRegExp('/foo3/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo3"'); } } From d7dc6c778b238cf7c6461d1176692c6a2439b896 Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Sun, 11 Feb 2018 20:56:22 +0200 Subject: [PATCH 8/9] Fix CS --- src/Symfony/Component/Console/Application.php | 3 +-- src/Symfony/Component/Console/Tests/ApplicationTest.php | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 6f929ecb35278..4020bd527fc67 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -40,7 +40,6 @@ use Symfony\Component\Console\Event\ConsoleTerminateEvent; use Symfony\Component\Console\Exception\CommandNotFoundException; use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Debug\ErrorHandler; use Symfony\Component\Debug\Exception\FatalThrowableError; @@ -245,7 +244,7 @@ public function doRun(InputInterface $input, OutputInterface $output) $style = new SymfonyStyle($input, $output); $style->block(sprintf("\nCommand \"%s\" is not defined.\n", $name), null, 'error'); - if (!$style->confirm(sprintf("Do you want to run \"%s\" instead? ", $alternative), false)) { + if (!$style->confirm(sprintf('Do you want to run "%s" instead? ', $alternative), false)) { if (null !== $this->dispatcher) { $event = new ConsoleErrorEvent($input, $output, $e); $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index ee695e977480f..df97c70d44efd 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -466,15 +466,15 @@ public function testDontRunAlternativeNamespaceName() $application->setAutoExit(false); $tester = new ApplicationTester($application); $tester->run(array('command' => 'foos:bar1'), array('decorated' => false)); - $this->assertSame(" + $this->assertSame(' - There are no commands defined in the \"foos\" namespace. + There are no commands defined in the "foos" namespace. Did you mean this? foo -", $tester->getDisplay(true)); +', $tester->getDisplay(true)); } public function testCanRunAlternativeCommandName() From 4de52d225f3b06b965ec9099d1c89875489e751a Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Thu, 22 Feb 2018 08:00:13 +0200 Subject: [PATCH 9/9] Change spacing --- .../Component/Console/Tests/ApplicationTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index df97c70d44efd..2c36acb651a60 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -487,9 +487,9 @@ public function testCanRunAlternativeCommandName() $tester->run(array('command' => 'foos'), array('decorated' => false)); $this->assertSame(<< @@ -510,9 +510,9 @@ public function testDontRunAlternativeCommandName() $this->assertSame(1, $exitCode); $this->assertSame(<<