[DependencyInjection][Config] Use several placeholder unique prefixes for dynamic placeholder values

This commit is contained in:
Thomas Calvet 2020-07-07 10:23:41 +02:00
parent 05fe56b88e
commit 3d754ad688
3 changed files with 68 additions and 8 deletions

View File

@ -26,7 +26,7 @@ abstract class BaseNode implements NodeInterface
{ {
const DEFAULT_PATH_SEPARATOR = '.'; const DEFAULT_PATH_SEPARATOR = '.';
private static $placeholderUniquePrefix; private static $placeholderUniquePrefixes = [];
private static $placeholders = []; private static $placeholders = [];
protected $name; protected $name;
@ -74,7 +74,7 @@ abstract class BaseNode implements NodeInterface
} }
/** /**
* Sets a common prefix for dynamic placeholder values. * Adds a common prefix for dynamic placeholder values.
* *
* Matching configuration values will be skipped from being processed and are returned as is, thus preserving the * Matching configuration values will be skipped from being processed and are returned as is, thus preserving the
* placeholder. An exact match provided by {@see setPlaceholder()} might take precedence. * placeholder. An exact match provided by {@see setPlaceholder()} might take precedence.
@ -83,7 +83,7 @@ abstract class BaseNode implements NodeInterface
*/ */
public static function setPlaceholderUniquePrefix(string $prefix): void public static function setPlaceholderUniquePrefix(string $prefix): void
{ {
self::$placeholderUniquePrefix = $prefix; self::$placeholderUniquePrefixes[] = $prefix;
} }
/** /**
@ -93,7 +93,7 @@ abstract class BaseNode implements NodeInterface
*/ */
public static function resetPlaceholders(): void public static function resetPlaceholders(): void
{ {
self::$placeholderUniquePrefix = null; self::$placeholderUniquePrefixes = [];
self::$placeholders = []; self::$placeholders = [];
} }
@ -513,10 +513,12 @@ abstract class BaseNode implements NodeInterface
return self::$placeholders[$value]; return self::$placeholders[$value];
} }
if (self::$placeholderUniquePrefix && 0 === strpos($value, self::$placeholderUniquePrefix)) { foreach (self::$placeholderUniquePrefixes as $placeholderUniquePrefix) {
if (0 === strpos($value, $placeholderUniquePrefix)) {
return []; return [];
} }
} }
}
return $value; return $value;
} }

View File

@ -79,11 +79,11 @@ class MergeExtensionConfigurationPass implements CompilerPassInterface
$container->getParameterBag()->mergeEnvPlaceholders($resolvingBag); $container->getParameterBag()->mergeEnvPlaceholders($resolvingBag);
} }
throw $e;
} finally {
if ($configAvailable) { if ($configAvailable) {
BaseNode::resetPlaceholders(); BaseNode::resetPlaceholders();
} }
throw $e;
} }
if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) { if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) {
@ -95,6 +95,10 @@ class MergeExtensionConfigurationPass implements CompilerPassInterface
$container->getParameterBag()->add($parameters); $container->getParameterBag()->add($parameters);
} }
if ($configAvailable) {
BaseNode::resetPlaceholders();
}
$container->addDefinitions($definitions); $container->addDefinitions($definitions);
$container->addAliases($aliases); $container->addAliases($aliases);
} }

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\DependencyInjection\Tests\Compiler; namespace Symfony\Component\DependencyInjection\Tests\Compiler;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\Definition\BaseNode;
use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Resource\FileResource;
@ -128,6 +129,23 @@ class MergeExtensionConfigurationPassTest extends TestCase
$this->assertSame(['FOO'], array_keys($container->getParameterBag()->getEnvPlaceholders())); $this->assertSame(['FOO'], array_keys($container->getParameterBag()->getEnvPlaceholders()));
} }
public function testReuseEnvPlaceholderGeneratedByPreviousExtension()
{
if (!property_exists(BaseNode::class, 'placeholderUniquePrefixes')) {
$this->markTestSkipped('This test requires symfony/config ^4.4.11|^5.0.11|^5.1.3');
}
$container = new ContainerBuilder();
$container->registerExtension(new FooExtension());
$container->registerExtension(new TestCccExtension());
$container->prependExtensionConfig('foo', ['bool_node' => '%env(bool:MY_ENV_VAR)%']);
$container->prependExtensionConfig('test_ccc', ['bool_node' => '%env(bool:MY_ENV_VAR)%']);
(new MergeExtensionConfigurationPass())->process($container);
$this->addToAssertionCount(1);
}
} }
class FooConfiguration implements ConfigurationInterface class FooConfiguration implements ConfigurationInterface
@ -139,6 +157,7 @@ class FooConfiguration implements ConfigurationInterface
->children() ->children()
->scalarNode('bar')->end() ->scalarNode('bar')->end()
->scalarNode('baz')->end() ->scalarNode('baz')->end()
->booleanNode('bool_node')->end()
->end(); ->end();
return $treeBuilder; return $treeBuilder;
@ -166,6 +185,8 @@ class FooExtension extends Extension
$container->getParameterBag()->get('env(BOZ)'); $container->getParameterBag()->get('env(BOZ)');
$container->resolveEnvPlaceholders($config['baz']); $container->resolveEnvPlaceholders($config['baz']);
} }
$container->setParameter('foo.param', 'ccc');
} }
} }
@ -194,3 +215,36 @@ class ThrowingExtension extends Extension
throw new \Exception(); throw new \Exception();
} }
} }
final class TestCccConfiguration implements ConfigurationInterface
{
public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder('test_ccc');
$treeBuilder->getRootNode()
->children()
->booleanNode('bool_node')->end()
->end();
return $treeBuilder;
}
}
final class TestCccExtension extends Extension
{
public function getAlias(): string
{
return 'test_ccc';
}
public function getConfiguration(array $config, ContainerBuilder $container): ?ConfigurationInterface
{
return new TestCccConfiguration();
}
public function load(array $configs, ContainerBuilder $container)
{
$configuration = $this->getConfiguration($configs, $container);
$this->processConfiguration($configuration, $configs);
}
}