From 9b6110bfaad5abfe4ec4f90506e8616cfbf48874 Mon Sep 17 00:00:00 2001 From: Martin Herndl Date: Wed, 4 Aug 2021 11:55:03 +0200 Subject: [PATCH] [FrameworkBundle] Fall back to default configuration in debug:config and consistently resolve parameter values --- .../Command/ConfigDebugCommand.php | 52 ++++++++++++++----- .../DefaultConfigTestBundle.php | 9 ++++ .../DependencyInjection/Configuration.php | 22 ++++++++ .../DefaultConfigTestExtension.php | 18 +++++++ .../ExtensionWithoutConfigTestExtension.php | 28 ++++++++++ .../ExtensionWithoutConfigTestBundle.php | 9 ++++ .../Functional/ConfigDebugCommandTest.php | 37 +++++++++++++ .../Functional/app/ConfigDump/bundles.php | 4 ++ .../Functional/app/ConfigDump/config.yml | 1 + 9 files changed, 166 insertions(+), 14 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DefaultConfigTestBundle.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/Configuration.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/DefaultConfigTestExtension.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/ExtensionWithoutConfigTestBundle.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php index 7f0a7813a8ddd..a0623f396127b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; +use Symfony\Component\Config\Definition\Processor; use Symfony\Component\Console\Exception\LogicException; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -18,6 +19,8 @@ use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\DependencyInjection\Compiler\ValidateEnvPlaceholdersPass; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; use Symfony\Component\Yaml\Yaml; /** @@ -77,22 +80,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $extension = $this->findExtension($name); - $container = $this->compileContainer(); - $extensionAlias = $extension->getAlias(); - $extensionConfig = []; - foreach ($container->getCompilerPassConfig()->getPasses() as $pass) { - if ($pass instanceof ValidateEnvPlaceholdersPass) { - $extensionConfig = $pass->getExtensionConfig(); - break; - } - } - - if (!isset($extensionConfig[$extensionAlias])) { - throw new \LogicException(sprintf('The extension with alias "%s" does not have configuration.', $extensionAlias)); - } + $container = $this->compileContainer(); - $config = $container->resolveEnvPlaceholders($extensionConfig[$extensionAlias]); + $config = $container->resolveEnvPlaceholders( + $container->getParameterBag()->resolveValue( + $this->getConfigForExtension($extension, $container) + ) + ); if (null === $path = $input->getArgument('path')) { $io->title( @@ -153,4 +148,33 @@ private function getConfigForPath(array $config, string $path, string $alias) return $config; } + + private function getConfigForExtension(ExtensionInterface $extension, ContainerBuilder $container): array + { + $extensionAlias = $extension->getAlias(); + + $extensionConfig = []; + foreach ($container->getCompilerPassConfig()->getPasses() as $pass) { + if ($pass instanceof ValidateEnvPlaceholdersPass) { + $extensionConfig = $pass->getExtensionConfig(); + break; + } + } + + if (isset($extensionConfig[$extensionAlias])) { + return $extensionConfig[$extensionAlias]; + } + + // Fall back to default config if the extension has one + + if (!$extension instanceof ConfigurationExtensionInterface) { + throw new \LogicException(sprintf('The extension with alias "%s" does not have configuration.', $extensionAlias)); + } + + $configs = $container->getExtensionConfig($extensionAlias); + $configuration = $extension->getConfiguration($configs, $container); + $this->validateConfiguration($extension, $configuration); + + return (new Processor())->processConfiguration($configuration, $configs); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DefaultConfigTestBundle.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DefaultConfigTestBundle.php new file mode 100644 index 0000000000000..8c7a89574729f --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DefaultConfigTestBundle.php @@ -0,0 +1,9 @@ +getRootNode() + ->children() + ->scalarNode('foo')->defaultValue('%default_config_test_foo%')->end() + ->scalarNode('baz')->defaultValue('%env(BAZ)%')->end() + ->end(); + + return $treeBuilder; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/DefaultConfigTestExtension.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/DefaultConfigTestExtension.php new file mode 100644 index 0000000000000..d380bcaad17fa --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/DefaultConfigTestExtension.php @@ -0,0 +1,18 @@ +processConfiguration($configuration, $configs); + + $container->setParameter('default_config_test', $config['foo']); + $container->setParameter('default_config_test', $config['baz']); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php new file mode 100644 index 0000000000000..e49f391bbafff --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php @@ -0,0 +1,28 @@ +assertStringContainsString('secret: test', $tester->getDisplay()); } + public function testDefaultParameterValueIsResolvedIfConfigIsExisting() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(['name' => 'framework']); + + $this->assertSame(0, $ret, 'Returns 0 in case of success'); + $kernelCacheDir = $this->application->getKernel()->getContainer()->getParameter('kernel.cache_dir'); + $this->assertStringContainsString(sprintf("dsn: 'file:%s/profiler'", $kernelCacheDir), $tester->getDisplay()); + } + public function testDumpUndefinedBundleOption() { $tester = $this->createCommandTester(); @@ -74,6 +84,33 @@ public function testDumpWithPrefixedEnv() $this->assertStringContainsString("cookie_httponly: '%env(bool:COOKIE_HTTPONLY)%'", $tester->getDisplay()); } + public function testDumpFallsBackToDefaultConfigAndResolvesParameterValue() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(['name' => 'DefaultConfigTestBundle']); + + $this->assertSame(0, $ret, 'Returns 0 in case of success'); + $this->assertStringContainsString('foo: bar', $tester->getDisplay()); + } + + public function testDumpFallsBackToDefaultConfigAndResolvesEnvPlaceholder() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(['name' => 'DefaultConfigTestBundle']); + + $this->assertSame(0, $ret, 'Returns 0 in case of success'); + $this->assertStringContainsString("baz: '%env(BAZ)%'", $tester->getDisplay()); + } + + public function testDumpThrowsExceptionWhenDefaultConfigFallbackIsImpossible() + { + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('The extension with alias "extension_without_config_test" does not have configuration.'); + + $tester = $this->createCommandTester(); + $tester->execute(['name' => 'ExtensionWithoutConfigTestBundle']); + } + private function createCommandTester(): CommandTester { $command = $this->application->find('debug:config'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/bundles.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/bundles.php index 15ff182c6fed5..c4fb0bbe8ce48 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/bundles.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/bundles.php @@ -10,9 +10,13 @@ */ use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\DefaultConfigTestBundle\DefaultConfigTestBundle; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ExtensionWithoutConfigTestBundle\ExtensionWithoutConfigTestBundle; use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle; return [ + new DefaultConfigTestBundle(), + new ExtensionWithoutConfigTestBundle(), new FrameworkBundle(), new TestBundle(), ]; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml index 432e35bd2f24d..a7a03a31d6602 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml @@ -11,3 +11,4 @@ parameters: env(LOCALE): en env(COOKIE_HTTPONLY): '1' secret: test + default_config_test_foo: bar