diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php index f0d5a9814864..415b2758a48b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php @@ -57,6 +57,47 @@ protected function listBundles($output) } } + /** + * @param OutputInterface|StyleInterface $output + */ + protected function listNonBundleExtensions($output) + { + $title = 'Available registered non-bundle extension aliases'; + $headers = ['Extension alias']; + $rows = []; + + $kernel = $this->getApplication()->getKernel(); + + $bundleExtensions = []; + foreach ($kernel->getBundles() as $bundle) { + if ($extension = $bundle->getContainerExtension()) { + $bundleExtensions[\get_class($extension)] = true; + } + } + + $extensions = $this->getContainerBuilder($kernel)->getExtensions(); + + foreach ($extensions as $alias => $extension) { + if (isset($bundleExtensions[\get_class($extension)])) { + continue; + } + $rows[] = [$alias]; + } + + if (!$rows) { + return; + } + + if ($output instanceof StyleInterface) { + $output->title($title); + $output->table($headers, $rows); + } else { + $output->writeln($title); + $table = new Table($output); + $table->setHeaders($headers)->setRows($rows)->render(); + } + } + /** * @return ExtensionInterface */ diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php index 6a5ba5dcf224..cc0444eae7de 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php @@ -77,14 +77,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if (null === $name = $input->getArgument('name')) { $this->listBundles($errorIo); - - $kernel = $this->getApplication()->getKernel(); - if ($kernel instanceof ExtensionInterface - && ($kernel instanceof ConfigurationInterface || $kernel instanceof ConfigurationExtensionInterface) - && $kernel->getAlias() - ) { - $errorIo->table(['Kernel Extension'], [[$kernel->getAlias()]]); - } + $this->listNonBundleExtensions($errorIo); $errorIo->comment('Provide the name of a bundle as the first argument of this command to dump its configuration. (e.g. debug:config FrameworkBundle)'); $errorIo->comment('For dumping a specific option, add its path as the second argument of this command. (e.g. debug:config FrameworkBundle serializer to dump the framework.serializer configuration)'); @@ -190,7 +183,8 @@ private function getConfigForExtension(ExtensionInterface $extension, ContainerB public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void { if ($input->mustSuggestArgumentValuesFor('name')) { - $suggestions->suggestValues($this->getAvailableBundles(!preg_match('/^[A-Z]/', $input->getCompletionValue()))); + $suggestions->suggestValues($this->getAvailableExtensions()); + $suggestions->suggestValues($this->getAvailableBundles()); return; } @@ -205,11 +199,23 @@ public function complete(CompletionInput $input, CompletionSuggestions $suggesti } } - private function getAvailableBundles(bool $alias): array + private function getAvailableExtensions(): array + { + $kernel = $this->getApplication()->getKernel(); + + $extensions = []; + foreach ($this->getContainerBuilder($kernel)->getExtensions() as $alias => $extension) { + $extensions[] = $alias; + } + + return $extensions; + } + + private function getAvailableBundles(): array { $availableBundles = []; foreach ($this->getApplication()->getKernel()->getBundles() as $bundle) { - $availableBundles[] = $alias ? $bundle->getContainerExtension()->getAlias() : $bundle->getName(); + $availableBundles[] = $bundle->getName(); } return $availableBundles; diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php index 63e6496bd1bc..10387d798593 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php @@ -22,8 +22,6 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; use Symfony\Component\Yaml\Yaml; /** @@ -88,14 +86,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if (null === $name = $input->getArgument('name')) { $this->listBundles($errorIo); - - $kernel = $this->getApplication()->getKernel(); - if ($kernel instanceof ExtensionInterface - && ($kernel instanceof ConfigurationInterface || $kernel instanceof ConfigurationExtensionInterface) - && $kernel->getAlias() - ) { - $errorIo->table(['Kernel Extension'], [[$kernel->getAlias()]]); - } + $this->listNonBundleExtensions($errorIo); $errorIo->comment([ 'Provide the name of a bundle as the first argument of this command to dump its default configuration. (e.g. config:dump-reference FrameworkBundle)', @@ -163,6 +154,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void { if ($input->mustSuggestArgumentValuesFor('name')) { + $suggestions->suggestValues($this->getAvailableExtensions()); $suggestions->suggestValues($this->getAvailableBundles()); } @@ -171,13 +163,24 @@ public function complete(CompletionInput $input, CompletionSuggestions $suggesti } } + private function getAvailableExtensions(): array + { + $kernel = $this->getApplication()->getKernel(); + + $extensions = []; + foreach ($this->getContainerBuilder($kernel)->getExtensions() as $alias => $extension) { + $extensions[] = $alias; + } + + return $extensions; + } + private function getAvailableBundles(): array { $bundles = []; foreach ($this->getApplication()->getKernel()->getBundles() as $bundle) { $bundles[] = $bundle->getName(); - $bundles[] = $bundle->getContainerExtension()->getAlias(); } return $bundles; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php index a5dd42058df4..143c632be629 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php @@ -23,6 +23,26 @@ */ class ConfigDebugCommandTest extends AbstractWebTestCase { + /** + * @testWith [true] + * [false] + */ + public function testShowList(bool $debug) + { + $tester = $this->createCommandTester($debug); + $ret = $tester->execute([]); + + $this->assertSame(0, $ret, 'Returns 0 in case of success'); + $this->assertStringContainsString('Available registered bundles with their extension alias if available', $tester->getDisplay()); + $this->assertStringContainsString(' DefaultConfigTestBundle default_config_test', $tester->getDisplay()); + $this->assertStringContainsString(' ExtensionWithoutConfigTestBundle extension_without_config_test', $tester->getDisplay()); + $this->assertStringContainsString(' FrameworkBundle framework', $tester->getDisplay()); + $this->assertStringContainsString(' TestBundle test', $tester->getDisplay()); + $this->assertStringContainsString('Available registered non-bundle extension aliases', $tester->getDisplay()); + $this->assertStringContainsString(' foo', $tester->getDisplay()); + $this->assertStringContainsString(' test_dump', $tester->getDisplay()); + } + /** * @testWith [true] * [false] @@ -185,14 +205,10 @@ public function testComplete(bool $debug, array $input, array $expectedSuggestio public static function provideCompletionSuggestions(): \Generator { - $name = ['default_config_test', 'extension_without_config_test', 'framework', 'test']; + $name = ['default_config_test', 'extension_without_config_test', 'framework', 'test', 'foo', 'test_dump']; yield 'name, no debug' => [false, [''], $name]; yield 'name, debug' => [true, [''], $name]; - $nameCamelCased = ['DefaultConfigTestBundle', 'ExtensionWithoutConfigTestBundle', 'FrameworkBundle', 'TestBundle']; - yield 'name (started CamelCase), no debug' => [false, ['Fra'], $nameCamelCased]; - yield 'name (started CamelCase), debug' => [true, ['Fra'], $nameCamelCased]; - $nameWithPath = ['secret', 'router.resource', 'router.utf8', 'router.enabled', 'validation.enabled', 'default_locale']; yield 'name with existing path, no debug' => [false, ['framework', ''], $nameWithPath]; yield 'name with existing path, debug' => [true, ['framework', ''], $nameWithPath]; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php index 8d1a8963b188..8f5930faac2e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php @@ -23,6 +23,26 @@ */ class ConfigDumpReferenceCommandTest extends AbstractWebTestCase { + /** + * @testWith [true] + * [false] + */ + public function testShowList(bool $debug) + { + $tester = $this->createCommandTester($debug); + $ret = $tester->execute([]); + + $this->assertSame(0, $ret, 'Returns 0 in case of success'); + $this->assertStringContainsString('Available registered bundles with their extension alias if available', $tester->getDisplay()); + $this->assertStringContainsString(' DefaultConfigTestBundle default_config_test', $tester->getDisplay()); + $this->assertStringContainsString(' ExtensionWithoutConfigTestBundle extension_without_config_test', $tester->getDisplay()); + $this->assertStringContainsString(' FrameworkBundle framework', $tester->getDisplay()); + $this->assertStringContainsString(' TestBundle test', $tester->getDisplay()); + $this->assertStringContainsString('Available registered non-bundle extension aliases', $tester->getDisplay()); + $this->assertStringContainsString(' foo', $tester->getDisplay()); + $this->assertStringContainsString(' test_dump', $tester->getDisplay()); + } + /** * @testWith [true] * [false] @@ -120,7 +140,7 @@ public function testComplete(bool $debug, array $input, array $expectedSuggestio public static function provideCompletionSuggestions(): iterable { - $name = ['DefaultConfigTestBundle', 'default_config_test', 'ExtensionWithoutConfigTestBundle', 'extension_without_config_test', 'FrameworkBundle', 'framework', 'TestBundle', 'test']; + $name = ['foo', 'default_config_test', 'extension_without_config_test', 'framework', 'test', 'test_dump', 'DefaultConfigTestBundle', 'ExtensionWithoutConfigTestBundle', 'FrameworkBundle', 'TestBundle']; yield 'name, no debug' => [false, [''], $name]; yield 'name, debug' => [true, [''], $name];