diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
index 1ecd16712ab2f..ff147727d45a3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
+++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
@@ -6,6 +6,7 @@ CHANGELOG
* Add `DomCrawlerAssertionsTrait::assertSelectorCount(int $count, string $selector)`
* Allow to avoid `limit` definition in a RateLimiter configuration when using the `no_limit` policy
+ * Add `--format` option to the `debug:config` command
6.2
---
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php
index c5078d1b5b401..b80bf4d0b0319 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php
@@ -16,6 +16,7 @@
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
+use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@@ -40,13 +41,17 @@ class ConfigDebugCommand extends AbstractConfigCommand
{
protected function configure()
{
+ $commentedHelpFormats = array_map(static fn (string $format): string => sprintf('%s', $format), $this->getAvailableFormatOptions());
+ $helpFormats = implode('", "', $commentedHelpFormats);
+
$this
->setDefinition([
new InputArgument('name', InputArgument::OPTIONAL, 'The bundle name or the extension alias'),
new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'),
new InputOption('resolve-env', null, InputOption::VALUE_NONE, 'Display resolved environment variable values instead of placeholders'),
+ new InputOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), class_exists(Yaml::class) ? 'yaml' : 'json'),
])
- ->setHelp(<<<'EOF'
+ ->setHelp(<<%command.name% command dumps the current configuration for an
extension/bundle.
@@ -55,6 +60,11 @@ protected function configure()
php %command.full_name% framework
php %command.full_name% FrameworkBundle
+The --format option specifies the format of the configuration,
+this is either "{$helpFormats}".
+
+ php %command.full_name% framework --format=json
+
For dumping a specific option, add its path as second argument:
php %command.full_name% framework serializer.enabled
@@ -92,12 +102,20 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$config = $this->getConfig($extension, $container, $input->getOption('resolve-env'));
+ $format = $input->getOption('format');
+
+ if ('yaml' === $format && !class_exists(Yaml::class)) {
+ $errorIo->error('Setting the "format" option to "yaml" requires the Symfony Yaml component. Try running "composer install symfony/yaml" or use "--format=json" instead.');
+
+ return 1;
+ }
+
if (null === $path = $input->getArgument('path')) {
$io->title(
sprintf('Current configuration for %s', $name === $extensionAlias ? sprintf('extension with alias "%s"', $extensionAlias) : sprintf('"%s"', $name))
);
- $io->writeln(Yaml::dump([$extensionAlias => $config], 10));
+ $io->writeln($this->convertToFormat([$extensionAlias => $config], $format));
return 0;
}
@@ -112,11 +130,20 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$io->title(sprintf('Current configuration for "%s.%s"', $extensionAlias, $path));
- $io->writeln(Yaml::dump($config, 10));
+ $io->writeln($this->convertToFormat($config, $format));
return 0;
}
+ private function convertToFormat(mixed $config, string $format): string
+ {
+ return match ($format) {
+ 'yaml' => Yaml::dump($config, 10),
+ 'json' => json_encode($config, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE),
+ default => throw new InvalidArgumentException(sprintf('Supported formats are "%s".', implode('", "', $this->getAvailableFormatOptions()))),
+ };
+ }
+
private function compileContainer(): ContainerBuilder
{
$kernel = clone $this->getApplication()->getKernel();
@@ -194,6 +221,10 @@ public function complete(CompletionInput $input, CompletionSuggestions $suggesti
} catch (LogicException) {
}
}
+
+ if ($input->mustSuggestOptionValuesFor('format')) {
+ $suggestions->suggestValues($this->getAvailableFormatOptions());
+ }
}
private function getAvailableBundles(bool $alias): array
@@ -228,4 +259,9 @@ private static function buildPathsCompletion(array $paths, string $prefix = ''):
return $completionPaths;
}
+
+ private function getAvailableFormatOptions(): array
+ {
+ return ['yaml', 'json'];
+ }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php
index 09b99f82f7c64..ce4764be765ec 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php
@@ -13,6 +13,7 @@
use Symfony\Bundle\FrameworkBundle\Command\ConfigDebugCommand;
use Symfony\Bundle\FrameworkBundle\Console\Application;
+use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Tester\CommandCompletionTester;
@@ -50,6 +51,19 @@ public function testDumpBundleOption()
$this->assertStringContainsString('foo', $tester->getDisplay());
}
+ public function testDumpWithUnsupportedFormat()
+ {
+ $tester = $this->createCommandTester();
+
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage('Supported formats are "yaml", "json"');
+
+ $tester->execute([
+ 'name' => 'test',
+ '--format' => 'xml',
+ ]);
+ }
+
public function testParametersValuesAreResolved()
{
$tester = $this->createCommandTester();
@@ -157,6 +171,8 @@ public function provideCompletionSuggestions(): \Generator
yield 'name (started CamelCase)' => [['Fra'], ['DefaultConfigTestBundle', 'ExtensionWithoutConfigTestBundle', 'FrameworkBundle', 'TestBundle']];
yield 'name with existing path' => [['framework', ''], ['secret', 'router.resource', 'router.utf8', 'router.enabled', 'validation.enabled', 'default_locale']];
+
+ yield 'option --format' => [['--format', ''], ['yaml', 'json']];
}
private function createCommandTester(): CommandTester