Skip to content

[FrameworkBundle] Fix debug:config & config:dump in debug mode #50546

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,14 @@ protected function getContainerBuilder(KernelInterface $kernel): ContainerBuilde
$container->getCompilerPassConfig()->setAfterRemovingPasses([]);
$container->compile();
} else {
(new XmlFileLoader($container = new ContainerBuilder(), new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump'));
$buildContainer = \Closure::bind(function () {
$containerBuilder = $this->getContainerBuilder();
$this->prepareContainer($containerBuilder);

return $containerBuilder;
}, $kernel, \get_class($kernel));
$container = $buildContainer();
(new XmlFileLoader($container, new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump'));
$locatorPass = new ServiceLocatorTagPass();
$locatorPass->process($container);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,12 @@ private function getConfigForExtension(ExtensionInterface $extension, ContainerB

// Fall back to default config if the extension has one

if (!$extension instanceof ConfigurationExtensionInterface) {
if (!$extension instanceof ConfigurationExtensionInterface && !$extension instanceof ConfigurationInterface) {
throw new \LogicException(sprintf('The extension with alias "%s" does not have configuration.', $extensionAlias));
}

$configs = $container->getExtensionConfig($extensionAlias);
$configuration = $extension->getConfiguration($configs, $container);
$configuration = $extension instanceof ConfigurationInterface ? $extension : $extension->getConfiguration($configs, $container);
$this->validateConfiguration($extension, $configuration);

return (new Processor())->processConfiguration($configuration, $configs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,114 +23,159 @@
*/
class ConfigDebugCommandTest extends AbstractWebTestCase
{
private $application;

protected function setUp(): void
/**
* @testWith [true]
* [false]
*/
public function testDumpKernelExtension(bool $debug)
{
$kernel = static::createKernel(['test_case' => 'ConfigDump', 'root_config' => 'config.yml']);
$this->application = new Application($kernel);
$this->application->doRun(new ArrayInput([]), new NullOutput());
$tester = $this->createCommandTester($debug);
$ret = $tester->execute(['name' => 'foo']);

$this->assertSame(0, $ret, 'Returns 0 in case of success');
$this->assertStringContainsString('foo:', $tester->getDisplay());
$this->assertStringContainsString(' foo: bar', $tester->getDisplay());
}

public function testDumpBundleName()
/**
* @testWith [true]
* [false]
*/
public function testDumpBundleName(bool $debug)
{
$tester = $this->createCommandTester();
$tester = $this->createCommandTester($debug);
$ret = $tester->execute(['name' => 'TestBundle']);

$this->assertSame(0, $ret, 'Returns 0 in case of success');
$this->assertStringContainsString('custom: foo', $tester->getDisplay());
}

public function testDumpBundleOption()
/**
* @testWith [true]
* [false]
*/
public function testDumpBundleOption(bool $debug)
{
$tester = $this->createCommandTester();
$tester = $this->createCommandTester($debug);
$ret = $tester->execute(['name' => 'TestBundle', 'path' => 'custom']);

$this->assertSame(0, $ret, 'Returns 0 in case of success');
$this->assertStringContainsString('foo', $tester->getDisplay());
}

public function testParametersValuesAreResolved()
/**
* @testWith [true]
* [false]
*/
public function testParametersValuesAreResolved(bool $debug)
{
$tester = $this->createCommandTester();
$tester = $this->createCommandTester($debug);
$ret = $tester->execute(['name' => 'framework']);

$this->assertSame(0, $ret, 'Returns 0 in case of success');
$this->assertStringContainsString("locale: '%env(LOCALE)%'", $tester->getDisplay());
$this->assertStringContainsString('secret: test', $tester->getDisplay());
}

public function testDefaultParameterValueIsResolvedIfConfigIsExisting()
/**
* @testWith [true]
* [false]
*/
public function testDefaultParameterValueIsResolvedIfConfigIsExisting(bool $debug)
{
$tester = $this->createCommandTester();
$tester = $this->createCommandTester($debug);
$ret = $tester->execute(['name' => 'framework']);

$this->assertSame(0, $ret, 'Returns 0 in case of success');
$kernelCacheDir = $this->application->getKernel()->getContainer()->getParameter('kernel.cache_dir');
$kernelCacheDir = self::$kernel->getContainer()->getParameter('kernel.cache_dir');
$this->assertStringContainsString(sprintf("dsn: 'file:%s/profiler'", $kernelCacheDir), $tester->getDisplay());
}

public function testDumpExtensionConfigWithoutBundle()
/**
* @testWith [true]
* [false]
*/
public function testDumpExtensionConfigWithoutBundle(bool $debug)
{
$tester = $this->createCommandTester();
$tester = $this->createCommandTester($debug);
$ret = $tester->execute(['name' => 'test_dump']);

$this->assertSame(0, $ret, 'Returns 0 in case of success');
$this->assertStringContainsString('enabled: true', $tester->getDisplay());
}

public function testDumpUndefinedBundleOption()
/**
* @testWith [true]
* [false]
*/
public function testDumpUndefinedBundleOption(bool $debug)
{
$tester = $this->createCommandTester();
$tester = $this->createCommandTester($debug);
$tester->execute(['name' => 'TestBundle', 'path' => 'foo']);

$this->assertStringContainsString('Unable to find configuration for "test.foo"', $tester->getDisplay());
}

public function testDumpWithPrefixedEnv()
/**
* @testWith [true]
* [false]
*/
public function testDumpWithPrefixedEnv(bool $debug)
{
$tester = $this->createCommandTester();
$tester = $this->createCommandTester($debug);
$tester->execute(['name' => 'FrameworkBundle']);

$this->assertStringContainsString("cookie_httponly: '%env(bool:COOKIE_HTTPONLY)%'", $tester->getDisplay());
}

public function testDumpFallsBackToDefaultConfigAndResolvesParameterValue()
/**
* @testWith [true]
* [false]
*/
public function testDumpFallsBackToDefaultConfigAndResolvesParameterValue(bool $debug)
{
$tester = $this->createCommandTester();
$tester = $this->createCommandTester($debug);
$ret = $tester->execute(['name' => 'DefaultConfigTestBundle']);

$this->assertSame(0, $ret, 'Returns 0 in case of success');
$this->assertStringContainsString('foo: bar', $tester->getDisplay());
}

public function testDumpFallsBackToDefaultConfigAndResolvesEnvPlaceholder()
/**
* @testWith [true]
* [false]
*/
public function testDumpFallsBackToDefaultConfigAndResolvesEnvPlaceholder(bool $debug)
{
$tester = $this->createCommandTester();
$tester = $this->createCommandTester($debug);
$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()
/**
* @testWith [true]
* [false]
*/
public function testDumpThrowsExceptionWhenDefaultConfigFallbackIsImpossible(bool $debug)
{
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('The extension with alias "extension_without_config_test" does not have configuration.');

$tester = $this->createCommandTester();
$tester = $this->createCommandTester($debug);
$tester->execute(['name' => 'ExtensionWithoutConfigTestBundle']);
}

/**
* @dataProvider provideCompletionSuggestions
*/
public function testComplete(array $input, array $expectedSuggestions)
public function testComplete(bool $debug, array $input, array $expectedSuggestions)
{
$this->application->add(new ConfigDebugCommand());

$tester = new CommandCompletionTester($this->application->get('debug:config'));
$application = $this->createApplication($debug);

$application->add(new ConfigDebugCommand());
$tester = new CommandCompletionTester($application->get('debug:config'));
$suggestions = $tester->complete($input);

foreach ($expectedSuggestions as $expectedSuggestion) {
Expand All @@ -140,17 +185,32 @@ public function testComplete(array $input, array $expectedSuggestions)

public static function provideCompletionSuggestions(): \Generator
{
yield 'name' => [[''], ['default_config_test', 'extension_without_config_test', 'framework', 'test']];
$name = ['default_config_test', 'extension_without_config_test', 'framework', 'test'];
yield 'name, no debug' => [false, [''], $name];
yield 'name, debug' => [true, [''], $name];

yield 'name (started CamelCase)' => [['Fra'], ['DefaultConfigTestBundle', 'ExtensionWithoutConfigTestBundle', 'FrameworkBundle', 'TestBundle']];
$nameCamelCased = ['DefaultConfigTestBundle', 'ExtensionWithoutConfigTestBundle', 'FrameworkBundle', 'TestBundle'];
yield 'name (started CamelCase), no debug' => [false, ['Fra'], $nameCamelCased];
yield 'name (started CamelCase), debug' => [true, ['Fra'], $nameCamelCased];

yield 'name with existing path' => [['framework', ''], ['secret', 'router.resource', 'router.utf8', 'router.enabled', 'validation.enabled', 'default_locale']];
$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];
}

private function createCommandTester(): CommandTester
private function createCommandTester(bool $debug): CommandTester
{
$command = $this->application->find('debug:config');
$command = $this->createApplication($debug)->find('debug:config');

return new CommandTester($command);
}

private function createApplication(bool $debug): Application
{
$kernel = static::bootKernel(['debug' => $debug, 'test_case' => 'ConfigDump', 'root_config' => 'config.yml']);
$application = new Application($kernel);
$application->doRun(new ArrayInput([]), new NullOutput());

return $application;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,45 +23,54 @@
*/
class ConfigDumpReferenceCommandTest extends AbstractWebTestCase
{
private $application;

protected function setUp(): void
{
$kernel = static::createKernel(['test_case' => 'ConfigDump', 'root_config' => 'config.yml']);
$this->application = new Application($kernel);
$this->application->doRun(new ArrayInput([]), new NullOutput());
}

public function testDumpKernelExtension()
/**
* @testWith [true]
* [false]
*/
public function testDumpKernelExtension(bool $debug)
{
$tester = $this->createCommandTester();
$tester = $this->createCommandTester($debug);
$ret = $tester->execute(['name' => 'foo']);

$this->assertSame(0, $ret, 'Returns 0 in case of success');
$this->assertStringContainsString('foo:', $tester->getDisplay());
$this->assertStringContainsString(' bar', $tester->getDisplay());
}

public function testDumpBundleName()
/**
* @testWith [true]
* [false]
*/
public function testDumpBundleName(bool $debug)
{
$tester = $this->createCommandTester();
$tester = $this->createCommandTester($debug);
$ret = $tester->execute(['name' => 'TestBundle']);

$this->assertSame(0, $ret, 'Returns 0 in case of success');
$this->assertStringContainsString('test:', $tester->getDisplay());
$this->assertStringContainsString(' custom:', $tester->getDisplay());
}

public function testDumpExtensionConfigWithoutBundle()
/**
* @testWith [true]
* [false]
*/
public function testDumpExtensionConfigWithoutBundle(bool $debug)
{
$tester = $this->createCommandTester();
$tester = $this->createCommandTester($debug);
$ret = $tester->execute(['name' => 'test_dump']);

$this->assertSame(0, $ret, 'Returns 0 in case of success');
$this->assertStringContainsString('enabled: true', $tester->getDisplay());
}

public function testDumpAtPath()
/**
* @testWith [true]
* [false]
*/
public function testDumpAtPath(bool $debug)
{
$tester = $this->createCommandTester();
$tester = $this->createCommandTester($debug);
$ret = $tester->execute([
'name' => 'test',
'path' => 'array',
Expand All @@ -79,9 +88,13 @@ public function testDumpAtPath()
, $tester->getDisplay(true));
}

public function testDumpAtPathXml()
/**
* @testWith [true]
* [false]
*/
public function testDumpAtPathXml(bool $debug)
{
$tester = $this->createCommandTester();
$tester = $this->createCommandTester($debug);
$ret = $tester->execute([
'name' => 'test',
'path' => 'array',
Expand All @@ -95,24 +108,40 @@ public function testDumpAtPathXml()
/**
* @dataProvider provideCompletionSuggestions
*/
public function testComplete(array $input, array $expectedSuggestions)
public function testComplete(bool $debug, array $input, array $expectedSuggestions)
{
$this->application->add(new ConfigDumpReferenceCommand());
$tester = new CommandCompletionTester($this->application->get('config:dump-reference'));
$suggestions = $tester->complete($input, 2);
$application = $this->createApplication($debug);

$application->add(new ConfigDumpReferenceCommand());
$tester = new CommandCompletionTester($application->get('config:dump-reference'));
$suggestions = $tester->complete($input);
$this->assertSame($expectedSuggestions, $suggestions);
}

public static function provideCompletionSuggestions(): iterable
{
yield 'name' => [[''], ['DefaultConfigTestBundle', 'default_config_test', 'ExtensionWithoutConfigTestBundle', 'extension_without_config_test', 'FrameworkBundle', 'framework', 'TestBundle', 'test']];
yield 'option --format' => [['--format', ''], ['yaml', 'xml']];
$name = ['DefaultConfigTestBundle', 'default_config_test', 'ExtensionWithoutConfigTestBundle', 'extension_without_config_test', 'FrameworkBundle', 'framework', 'TestBundle', 'test'];
yield 'name, no debug' => [false, [''], $name];
yield 'name, debug' => [true, [''], $name];

$optionFormat = ['yaml', 'xml'];
yield 'option --format, no debug' => [false, ['--format', ''], $optionFormat];
yield 'option --format, debug' => [true, ['--format', ''], $optionFormat];
}

private function createCommandTester(): CommandTester
private function createCommandTester(bool $debug): CommandTester
{
$command = $this->application->find('config:dump-reference');
$command = $this->createApplication($debug)->find('config:dump-reference');

return new CommandTester($command);
}

private function createApplication(bool $debug): Application
{
$kernel = static::createKernel(['debug' => $debug, 'test_case' => 'ConfigDump', 'root_config' => 'config.yml']);
$application = new Application($kernel);
$application->doRun(new ArrayInput([]), new NullOutput());

return $application;
}
}