8000 [DI] Fix tracking env vars when merging configs (bis) by nicolas-grekas · Pull Request #24009 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content
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 @@ -45,12 +45,14 @@ public function process(ContainerBuilder $container)
// this extension was not called
continue;
}
// EnvPlaceholderParameterBag tracks env vars when calling resolveValue().
// Clone so that tracking is done in a dedicated bag.
$resolvingBag = clone $container->getParameterBag();
$resolvingBag = $container->getParameterBag();
if ($resolvingBag instanceof EnvPlace 8000 holderParameterBag && $extension instanceof Extension) {
// create a dedicated bag so that we can track env vars per-extension
$resolvingBag = new MergeExtensionConfigurationParameterBag($resolvingBag);
}
$config = $resolvingBag->resolveValue($config);

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

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

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

$container->merge($tmpContainer);
Expand All @@ -86,55 +84,41 @@ public function process(ContainerBuilder $container)
*/
class MergeExtensionConfigurationParameterBag extends EnvPlaceholderParameterBag
{
private $beforeProcessingEnvPlaceholders;
private $processedEnvPlaceholders;

public function __construct(Extension $extension, parent $resolvingBag)
public function __construct(parent $parameterBag)
{
$this->beforeProcessingEnvPlaceholders = $resolvingBag->getEnvPlaceholders();
$config = $this->resolveEnvPlaceholders($extension->getProcessedConfigs());
parent::__construct($this->resolveValue($config));
parent::__construct($parameterBag->all());
$this->mergeEnvPlaceholders($parameterBag);
}

/**
* {@inheritdoc}
*/
public function get($name)
public function freezeAfterProcessing(Extension $extension)
{
return $this->has($name) || (0 === strpos($name, 'env(') && ')' === substr($name, -1) && 'env()' !== $name) ? parent::get($name) : '';
$this->processedEnvPlaceholders = array();
$this->processMergedConfig($extension->getProcessedConfigs(), parent::getEnvPlaceholders());
}

/**
* {@inheritdoc}
*/
public function getEnvPlaceholders()
{
// contains the list of env vars that are still used after configs have been merged
$envPlaceholders = parent::getEnvPlaceholders();

foreach ($envPlaceholders as $env => $placeholders) {
if (isset($this->beforeProcessingEnvPlaceholders[$env])) {
// for still-used env vars, keep track of their before-processing placeholders
$envPlaceholders[$env] += $this->beforeProcessingEnvPlaceholders[$env];
}
}

return $envPlaceholders;
return null !== $this->processedEnvPlaceholders ? $this->processedEnvPlaceholders : parent::getEnvPlaceholders();
}

/**
* Replaces-back env placeholders to their original "%env(FOO)%" version.
*/
private function resolveEnvPlaceholders($value)
private function processMergedConfig($value, array $envPlaceholders)
{
if (is_array($value)) {
foreach ($value as $k => $v) {
$value[$this->resolveEnvPlaceholders($k)] = $this->resolveEnvPlaceholders($v);
$this->processMergedConfig($k, $envPlaceholders);
$this->processMergedConfig($v, $envPlaceholders);
}
} elseif (is_string($value)) {
foreach ($this->beforeProcessingEnvPlaceholders as $env => $placeholders) {
foreach ($envPlaceholders as $env => $placeholders) {
foreach ($placeholders as $placeholder) {
if (false !== stripos($value, $placeholder)) {
$value = str_ireplace($placeholder, "%env($env)%", $value);
$this->processedEnvPlaceholders[$env] = $placeholders;
break;
}
}
}
Expand Down
8000
Original file line number Diff line number Diff line change
Expand Up @@ -641,10 +641,16 @@ public function merge(ContainerBuilder $container)
}

if ($this->getParameterBag() instanceof EnvPlaceholderParameterBag && $container->getParameterBag() instanceof EnvPlaceholderParameterBag) {
$envPlaceholders = $container->getParameterBag()->getEnvPlaceholders();
$this->getParameterBag()->mergeEnvPlaceholders($container->getParameterBag());
} else {
$envPlaceholders = array();
}

foreach ($container->envCounters as $env => $count) {
if (!$count && !isset($envPlaceholders[$env])) {
continue;
}
if (!isset($this->envCounters[$env])) {
$this->envCounters[$env] = $count;
} else {
Expand Down
11 changes: 9 additions & 2 deletions < 8000 span class="diffstat" aria-hidden="true">11 ...fony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,13 @@ public function testOverriddenEnvsAreMerged()
$container = new ContainerBuilder();
$container->registerExtension(new FooExtension());
$container->prependExtensionConfig('foo', array('bar' => '%env(FOO)%'));
$container->prependExtensionConfig('foo', array('bar' => '%env(BAR)%'));
$container->prependExtensionConfig('foo', array('bar' => '%env(BAR)%', 'baz' => '%env(BAZ)%'));

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

$this->assertSame(array('FOO'), array_keys($container->getParameterBag()->getEnvPlaceholders()));
$this->assertSame(array('FOO', 'BAZ'), array_keys($container->getParameterBag()->getEnvPlaceholders()));
$this->assertSame(array('BAZ' => 1, 'FOO' => 0), $container->getEnvCounters());
}
}

Expand All @@ -94,6 +95,7 @@ public function getConfigTreeBuilder()
$rootNode
->children()
->scalarNode('bar')->end()
->scalarNode('baz')->end()
->end();

return $treeBuilder;
Expand All @@ -116,5 +118,10 @@ public function load(array $configs, ContainerBuilder $container)
{
$configuration = $this->getConfiguration($configs, $container);
$config = $this->processConfiguration($configuration, $configs);

if (isset($config['baz'])) {
$container->getParameterBag()->get('env(BOZ)');
$container->resolveEnvPlaceholders($config['baz']);
}
}
}
0