Skip to content

Commit baaff20

Browse files
[DI] Fix tracking env vars when merging configs (bis)
1 parent 726c567 commit baaff20

File tree

3 files changed

+38
-41
lines changed

3 files changed

+38
-41
lines changed

src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php

+23-39
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,14 @@ public function process(ContainerBuilder $container)
4545
// this extension was not called
4646
continue;
4747
}
48-
// EnvPlaceholderParameterBag tracks env vars when calling resolveValue().
49-
// Clone so that tracking is done in a dedicated bag.
50-
$resolvingBag = clone $container->getParameterBag();
48+
$resolvingBag = $container->getParameterBag();
49+
if ($resolvingBag instanceof EnvPlaceholderParameterBag && $extension instanceof Extension) {
50+
// create a dedicated bag so that we can track env vars per-extension
51+
$resolvingBag = new MergeExtensionConfigurationParameterBag($resolvingBag);
52+
}
5153
$config = $resolvingBag->resolveValue($config);
5254

53-
$tmpContainer = new ContainerBuilder($container->getParameterBag());
55+
$tmpContainer = new ContainerBuilder($resolvingBag);
5456
$tmpContainer->setResourceTracking($container->isTrackingResources());
5557
$tmpContainer->addObjectResource($extension);
5658
if ($extension instanceof ConfigurationExtensionInterface && null !== $configuration = $extension->getConfiguration($config, $tmpContainer)) {
@@ -63,13 +65,9 @@ public function process(ContainerBuilder $container)
6365

6466
$extension->load($config, $tmpContainer);
6567

66-
if ($resolvingBag instanceof EnvPlaceholderParameterBag) {
67-
// $resolvingBag keeps track of env vars encoutered *before* merging configs
68-
if ($extension instanceof Extension) {
69-
// but we don't want to keep track of env vars that are *overridden* when configs are merged
70-
$resolvingBag = new MergeExtensionConfigurationParameterBag($extension, $resolvingBag);
71-
}
72-
$container->getParameterBag()->mergeEnvPlaceholders($resolvingBag);
68+
if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) {
69+
// don't keep track of env vars that are *overridden* when configs are merged
70+
$resolvingBag->freezeAfterProcessing($extension);
7371
}
7472

7573
$container->merge($tmpContainer);
@@ -86,55 +84,41 @@ public function process(ContainerBuilder $container)
8684
*/
8785
class MergeExtensionConfigurationParameterBag extends EnvPlaceholderParameterBag
8886
{
89-
private $beforeProcessingEnvPlaceholders;
87+
private $processedEnvPlaceholders;
9088

91-
public function __construct(Extension $extension, parent $resolvingBag)
89+
public function __construct(parent $parameterBag)
9290
{
93-
$this->beforeProcessingEnvPlaceholders = $resolvingBag->getEnvPlaceholders();
94-
$config = $this->resolveEnvPlaceholders($extension->getProcessedConfigs());
95-
parent::__construct($this->resolveValue($config));
91+
parent::__construct($parameterBag->all());
92+
$this->mergeEnvPlaceholders($parameterBag);
9693
}
9794

98-
/**
99-
* {@inheritdoc}
100-
*/
101-
public function get($name)
95+
public function freezeAfterProcessing(Extension $extension)
10296
{
103-
return $this->has($name) || (0 === strpos($name, 'env(') && ')' === substr($name, -1) && 'env()' !== $name) ? parent::get($name) : '';
97+
$this->processedEnvPlaceholders = array();
98+
$this->processMergedConfig($extension->getProcessedConfigs(), parent::getEnvPlaceholders());
10499
}
105100

106101
/**
107102
* {@inheritdoc}
108103
*/
109104
public function getEnvPlaceholders()
110105
{
111-
// contains the list of env vars that are still used after configs have been merged
112-
$envPlaceholders = parent::getEnvPlaceholders();
113-
114-
foreach ($envPlaceholders as $env => $placeholders) {
115-
if (isset($this->beforeProcessingEnvPlaceholders[$env])) {
116-
// for still-used env vars, keep track of their before-processing placeholders
117-
$envPlaceholders[$env] += $this->beforeProcessingEnvPlaceholders[$env];
118-
}
119-
}
120-
121-
return $envPlaceholders;
106+
return null !== $this->processedEnvPlaceholders ? $this->processedEnvPlaceholders : parent::getEnvPlaceholders();
122107
}
123108

124-
/**
125-
* Replaces-back env placeholders to their original "%env(FOO)%" version.
126-
*/
127-
private function resolveEnvPlaceholders($value)
109+
private function processMergedConfig($value, array $envPlaceholders)
128110
{
129111
if (is_array($value)) {
130112
foreach ($value as $k => $v) {
131-
$value[$this->resolveEnvPlaceholders($k)] = $this->resolveEnvPlaceholders($v);
113+
$this->processMergedConfig($k, $envPlaceholders);
114+
$this->processMergedConfig($v, $envPlaceholders);
132115
}
133116
} elseif (is_string($value)) {
134-
foreach ($this->beforeProcessingEnvPlaceholders as $env => $placeholders) {
117+
foreach ($envPlaceholders as $env => $placeholders) {
135118
foreach ($placeholders as $placeholder) {
136119
if (false !== stripos($value, $placeholder)) {
137-
$value = str_ireplace($placeholder, "%env($env)%", $value);
120+
$this->processedEnvPlaceholders[$env] = $placeholders;
121+
break;
138122
}
139123
}
140124
}

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

+6
Original file line numberDiff line numberDiff line change
@@ -641,10 +641,16 @@ public function merge(ContainerBuilder $container)
641641
}
642642

643643
if ($this->getParameterBag() instanceof EnvPlaceholderParameterBag && $container->getParameterBag() instanceof EnvPlaceholderParameterBag) {
644+
$envPlaceholders = $container->getParameterBag()->getEnvPlaceholders();
644645
$this->getParameterBag()->mergeEnvPlaceholders($container->getParameterBag());
646+
} else {
647+
$envPlaceholders = array();
645648
}
646649

647650
foreach ($container->envCounters as $env => $count) {
651+
if (!$count && !isset($envPlaceholders[$env])) {
652+
continue;
653+
}
648654
if (!isset($this->envCounters[$env])) {
649655
$this->envCounters[$env] = $count;
650656
} else {

src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php

+9-2
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,13 @@ public function testOverriddenEnvsAreMerged()
7676
$container = new ContainerBuilder();
7777
$container->registerExtension(new FooExtension());
7878
$container->prependExtensionConfig('foo', array('bar' => '%env(FOO)%'));
79-
$container->prependExtensionConfig('foo', array('bar' => '%env(BAR)%'));
79+
$container->prependExtensionConfig('foo', array('bar' => '%env(BAR)%', 'baz' => '%env(BAZ)%'));
8080

8181
$pass = new MergeExtensionConfigurationPass();
8282
$pass->process($container);
8383

84-
$this->assertSame(array('FOO'), array_keys($container->getParameterBag()->getEnvPlaceholders()));
84+
$this->assertSame(array('FOO', 'BAZ'), array_keys($container->getParameterBag()->getEnvPlaceholders()));
85+
$this->assertSame(array('BAZ' => 1, 'FOO' => 0), $container->getEnvCounters());
8586
}
8687
}
8788

@@ -94,6 +95,7 @@ public function getConfigTreeBuilder()
9495
$rootNode
9596
->children()
9697
->scalarNode('bar')->end()
98+
->scalarNode('baz')->end()
9799
->end();
98100

99101
return $treeBuilder;
@@ -116,5 +118,10 @@ public function load(array $configs, ContainerBuilder $container)
116118
{
117119
$configuration = $this->getConfiguration($configs, $container);
118120
$config = $this->processConfiguration($configuration, $configs);
121+
122+
if (isset($config['baz'])) {
123+
$container->getParameterBag()->get('env(BOZ)');
124+
$container->resolveEnvPlaceholders($config['baz']);
125+
}
119126
}
120127
}

0 commit comments

Comments
 (0)