diff --git a/src/Symfony/Component/Console/Descriptor/ApplicationDescription.php b/src/Symfony/Component/Console/Descriptor/ApplicationDescription.php index 442a569711c0..7e214712da6f 100644 --- a/src/Symfony/Component/Console/Descriptor/ApplicationDescription.php +++ b/src/Symfony/Component/Console/Descriptor/ApplicationDescription.php @@ -129,23 +129,29 @@ private function sortCommands(array $commands) { $namespacedCommands = []; $globalCommands = []; + $sortedCommands = []; foreach ($commands as $name => $command) { $key = $this->application->extractNamespace($name, 1); - if (!$key) { - $globalCommands['_global'][$name] = $command; + if (\in_array($key, ['', self::GLOBAL_NAMESPACE], true)) { + $globalCommands[$name] = $command; } else { $namespacedCommands[$key][$name] = $command; } } - ksort($namespacedCommands); - $namespacedCommands = array_merge($globalCommands, $namespacedCommands); - foreach ($namespacedCommands as &$commandsSet) { - ksort($commandsSet); + if ($globalCommands) { + ksort($globalCommands); + $sortedCommands[self::GLOBAL_NAMESPACE] = $globalCommands; } - // unset reference to keep scope clear - unset($commandsSet); - return $namespacedCommands; + if ($namespacedCommands) { + ksort($namespacedCommands); + foreach ($namespacedCommands as $key => $commandsSet) { + ksort($commandsSet); + $sortedCommands[$key] = $commandsSet; + } + } + + return $sortedCommands; } } diff --git a/src/Symfony/Component/Console/Tests/Descriptor/ApplicationDescriptionTest.php b/src/Symfony/Component/Console/Tests/Descriptor/ApplicationDescriptionTest.php new file mode 100644 index 000000000000..33d5c3840f3e --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Descriptor/ApplicationDescriptionTest.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\Descriptor; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Descriptor\ApplicationDescription; + +final class ApplicationDescriptionTest extends TestCase +{ + /** + * @dataProvider getNamespacesProvider + */ + public function testGetNamespaces(array $expected, array $names) + { + $application = new TestApplication(); + foreach ($names as $name) { + $application->add(new Command($name)); + } + + $this->assertSame($expected, array_keys((new ApplicationDescription($application))->getNamespaces())); + } + + public function getNamespacesProvider() + { + return [ + [['_global'], ['foobar']], + [['a', 'b'], ['b:foo', 'a:foo', 'b:bar']], + [['_global', 'b', 'z', 22, 33], ['z:foo', '1', '33:foo', 'b:foo', '22:foo:bar']], + ]; + } +} + +final class TestApplication extends Application +{ + /** + * {@inheritdoc} + */ + protected function getDefaultCommands() + { + return []; + } +}