diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 8a9bdc39bf..d181e41e80 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -529,6 +529,10 @@ class Application { $namespaces = []; foreach ($this->all() as $command) { + if ($command->isHidden()) { + continue; + } + $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName())); foreach ($command->getAliases() as $alias) { @@ -622,6 +626,11 @@ class Application $message = sprintf('Command "%s" is not defined.', $name); if ($alternatives = $this->findAlternatives($name, $allCommands)) { + // remove hidden commands + $alternatives = array_filter($alternatives, function ($name) { + return !$this->get($name)->isHidden(); + }); + if (1 == \count($alternatives)) { $message .= "\n\nDid you mean this?\n "; } else { @@ -630,7 +639,7 @@ class Application $message .= implode("\n ", $alternatives); } - throw new CommandNotFoundException($message, $alternatives); + throw new CommandNotFoundException($message, array_values($alternatives)); } // filter out aliases for commands which are already on the list @@ -654,13 +663,18 @@ class Application } $abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen) { if (!$commandList[$cmd] instanceof Command) { - return $cmd; + $commandList[$cmd] = $this->commandLoader->get($cmd); } + + if ($commandList[$cmd]->isHidden()) { + return false; + } + $abbrev = str_pad($cmd, $maxLen, ' ').' '.$commandList[$cmd]->getDescription(); return Helper::strlen($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev; }, array_values($commands)); - $suggestions = $this->getAbbreviationSuggestions($abbrevs); + $suggestions = $this->getAbbreviationSuggestions(array_filter($abbrevs)); throw new CommandNotFoundException(sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $name, $suggestions), array_values($commands)); } diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 59ca5d9e15..c7e8495265 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -74,6 +74,7 @@ class ApplicationTest extends TestCase require_once self::$fixturesPath.'/FooSubnamespaced2Command.php'; require_once self::$fixturesPath.'/TestAmbiguousCommandRegistering.php'; require_once self::$fixturesPath.'/TestAmbiguousCommandRegistering2.php'; + require_once self::$fixturesPath.'/FooHiddenCommand.php'; } protected function normalizeLineBreaks($text) @@ -616,6 +617,7 @@ class ApplicationTest extends TestCase $application->add(new \Foo1Command()); $application->add(new \Foo2Command()); $application->add(new \Foo3Command()); + $application->add(new \FooHiddenCommand()); $expectedAlternatives = [ 'afoobar', diff --git a/src/Symfony/Component/Console/Tests/Fixtures/FooHiddenCommand.php b/src/Symfony/Component/Console/Tests/Fixtures/FooHiddenCommand.php new file mode 100644 index 0000000000..75fbf7804d --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/FooHiddenCommand.php @@ -0,0 +1,21 @@ +setName('foo:hidden') + ->setAliases(['afoohidden']) + ->setHidden(true) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + } +}