From 7bcd714381442d642f9932f15b7ffa8328344520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Sat, 6 Apr 2019 20:49:38 +0200 Subject: [PATCH] [FrameworkBundle] Fixed issue when a parameter container a '%' On my computer: ``` dump(get_cfg_var('xdebug.file_link_format')); "subl://%f:%l" ``` When I ran `bin/console debug:config framework` I got this exception: ``` In ParameterBag.php line 100: [Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException] The parameter "templating.helper.code.file_link_format" has a dependency on a non-existent parameter "f:". Exception trace: () at /home/gregoire/dev/github.com/lyrixx/symfony/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php:100 ... ``` This issue was introduced [here](https://github.com/symfony/symfony/pull/27684/files#diff-b3847149480405e1de881530b4c75ab5L212) --- .../Command/ContainerDebugCommand.php | 7 +-- .../Console/Descriptor/Descriptor.php | 26 +++++++++-- .../Functional/ContainerDebugCommandTest.php | 44 ++++++------------- .../Functional/Fixtures/describe_env_vars.txt | 17 +++++++ 4 files changed, 56 insertions(+), 38 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Fixtures/describe_env_vars.txt diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php index 3736d4dc9d..b7c4fba033 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php @@ -224,15 +224,12 @@ EOF if (!$kernel->isDebug() || !(new ConfigCache($kernel->getContainer()->getParameter('debug.container.dump'), true))->isFresh()) { $buildContainer = \Closure::bind(function () { return $this->buildContainer(); }, $kernel, \get_class($kernel)); $container = $buildContainer(); + $container->getCompilerPassConfig()->setRemovingPasses([]); + $container->compile(); } else { (new XmlFileLoader($container = new ContainerBuilder(), new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump')); - $container->setParameter('container.build_hash', $hash = ContainerBuilder::hash(__METHOD__)); - $container->setParameter('container.build_id', hash('crc32', $hash.time())); } - $container->getCompilerPassConfig()->setRemovingPasses([]); - $container->compile(); - return $this->containerBuilder = $container; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php index 7babbd3912..e454633c78 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php @@ -322,21 +322,41 @@ abstract class Descriptor implements DescriptorInterface private function getContainerEnvVars(ContainerBuilder $container): array { + if (!$container->hasParameter('debug.container.dump')) { + return []; + } + + if (!is_file($container->getParameter('debug.container.dump'))) { + return []; + } + + $file = file_get_contents($container->getParameter('debug.container.dump')); + preg_match_all('{%env\(((?:\w++:)*+\w++)\)%}', $file, $envVars); + $envVars = array_unique($envVars[1]); + + $bag = $container->getParameterBag(); + $getDefaultParameter = function (string $name) { + return parent::get($name); + }; + $getDefaultParameter = $getDefaultParameter->bindTo($bag, \get_class($bag)); + $getEnvReflection = new \ReflectionMethod($container, 'getEnv'); $getEnvReflection->setAccessible(true); + $envs = []; - foreach (array_keys($container->getEnvCounters()) as $env) { + + foreach ($envVars as $env) { $processor = 'string'; if (false !== $i = strrpos($name = $env, ':')) { $name = substr($env, $i + 1); $processor = substr($env, 0, $i); } - $defaultValue = ($hasDefault = $container->hasParameter("env($name)")) ? $container->getParameter("env($name)") : null; + $defaultValue = ($hasDefault = $container->hasParameter("env($name)")) ? $getDefaultParameter("env($name)") : null; if (false === ($runtimeValue = $_ENV[$name] ?? $_SERVER[$name] ?? getenv($name))) { $runtimeValue = null; } $processedValue = ($hasRuntime = null !== $runtimeValue) || $hasDefault ? $getEnvReflection->invoke($container, $env) : null; - $envs[$name.$processor] = [ + $envs["$name$processor"] = [ 'name' => $name, 'processor' => $processor, 'default_available' => $hasDefault, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php index 9f833afbe7..229f1419cf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php @@ -83,11 +83,13 @@ class ContainerDebugCommandTest extends WebTestCase public function testDescribeEnvVars() { putenv('REAL=value'); - static::bootKernel(['test_case' => 'ContainerDebug', 'root_config' => 'config.yml']); + static::bootKernel(['test_case' => 'ContainerDebug', 'root_config' => 'config.yml', 'debug' => true]); $application = new Application(static::$kernel); $application->setAutoExit(false); + @unlink(static::$container->getParameter('debug.container.dump')); + $tester = new ApplicationTester($application); $tester->run(['command' => 'debug:container', '--env-vars' => true], ['decorated' => false]); @@ -96,13 +98,13 @@ class ContainerDebugCommandTest extends WebTestCase Symfony Container Environment Variables ======================================= - --------- ----------------- ------------ - Name Default value Real value - --------- ----------------- ------------ - JSON "[1, "2.5", 3]" n/a - REAL n/a "value" - UNKNOWN n/a n/a - --------- ----------------- ------------ + --------- ----------------- ------------%w + Name Default value Real value%w + --------- ----------------- ------------%w + JSON "[1, "2.5", 3]" n/a%w + REAL n/a "value"%w + UNKNOWN n/a n/a%w + --------- ----------------- ------------%w // Note real values might be different between web and CLI.%w @@ -118,35 +120,17 @@ TXT public function testDescribeEnvVar() { - static::bootKernel(['test_case' => 'ContainerDebug', 'root_config' => 'config.yml']); + static::bootKernel(['test_case' => 'ContainerDebug', 'root_config' => 'config.yml', 'debug' => true]); $application = new Application(static::$kernel); $application->setAutoExit(false); + @unlink(static::$container->getParameter('debug.container.dump')); + $tester = new ApplicationTester($application); $tester->run(['command' => 'debug:container', '--env-var' => 'js'], ['decorated' => false]); - $this->assertContains(<<<'TXT' -%env(float:key:2:json:JSON)% ----------------------------- - - ----------------- ----------------- - Default value "[1, "2.5", 3]" - Real value n/a - Processed value 3.0 - ----------------- ----------------- - -%env(int:key:2:json:JSON)% --------------------------- - - ----------------- ----------------- - Default value "[1, "2.5", 3]" - Real value n/a - Processed value 3 - ----------------- ----------------- - -TXT - , $tester->getDisplay(true)); + $this->assertContains(file_get_contents(__DIR__.'/Fixtures/describe_env_vars.txt'), $tester->getDisplay(true)); } public function provideIgnoreBackslashWhenFindingService() diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Fixtures/describe_env_vars.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Fixtures/describe_env_vars.txt new file mode 100644 index 0000000000..701e515ce1 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Fixtures/describe_env_vars.txt @@ -0,0 +1,17 @@ +%env(float:key:2:json:JSON)% +---------------------------- + + ----------------- ----------------- + Default value "[1, "2.5", 3]" + Real value n/a + Processed value 3.0 + ----------------- ----------------- + +%env(int:key:2:json:JSON)% +-------------------------- + + ----------------- ----------------- + Default value "[1, "2.5", 3]" + Real value n/a + Processed value 3 + ----------------- -----------------