[Config] allowed the disabling of key normalization on some array nodes
This reverts #6086
This commit is contained in:
parent
1de60c902c
commit
e31d4f19d9
@ -4,6 +4,7 @@ CHANGELOG
|
||||
2.2.0
|
||||
-----
|
||||
|
||||
* added a `keepKeys()` method for array nodes (to avoid key normalization)
|
||||
* added numerical type handling for config definitions
|
||||
* added convenience methods for optional configuration sections to ArrayNodeDefinition
|
||||
* added a utils class for XML manipulations
|
||||
|
@ -29,6 +29,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
|
||||
protected $addIfNotSet;
|
||||
protected $performDeepMerging;
|
||||
protected $ignoreExtraKeys;
|
||||
protected $normalizeKeys;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -47,6 +48,41 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
|
||||
$this->addIfNotSet = false;
|
||||
$this->allowNewKeys = true;
|
||||
$this->performDeepMerging = true;
|
||||
$this->normalizeKeys = true;
|
||||
}
|
||||
|
||||
public function setNormalizeKeys($normalizeKeys)
|
||||
{
|
||||
$this->normalizeKeys = (Boolean) $normalizeKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes keys between the different configuration formats.
|
||||
*
|
||||
* Namely, you mostly have foo_bar in YAML while you have foo-bar in XML.
|
||||
* After running this method, all keys are normalized to foo_bar.
|
||||
*
|
||||
* If you have a mixed key like foo-bar_moo, it will not be altered.
|
||||
* The key will also not be altered if the target key already exists.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return array The value with normalized keys
|
||||
*/
|
||||
protected function preNormalize($value)
|
||||
{
|
||||
if (!$this->normalizeKeys || !is_array($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
foreach ($value as $k => $v) {
|
||||
if (false !== strpos($k, '-') && false === strpos($k, '_') && !array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) {
|
||||
$value[$normalizedKey] = $v;
|
||||
unset($value[$k]);
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -247,6 +247,8 @@ abstract class BaseNode implements NodeInterface
|
||||
*/
|
||||
final public function normalize($value)
|
||||
{
|
||||
$value = $this->preNormalize($value);
|
||||
|
||||
// run custom normalization closures
|
||||
foreach ($this->normalizationClosures as $closure) {
|
||||
$value = $closure($value);
|
||||
@ -266,6 +268,18 @@ abstract class BaseNode implements NodeInterface
|
||||
return $this->normalizeValue($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the value before any other normalization is applied.
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return $value The normalized array value
|
||||
*/
|
||||
protected function preNormalize($value)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalizes a value, applying all finalization closures.
|
||||
*
|
||||
|
@ -34,6 +34,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
|
||||
protected $addDefaults;
|
||||
protected $addDefaultChildren;
|
||||
protected $nodeBuilder;
|
||||
protected $normalizeKeys;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
@ -51,6 +52,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
|
||||
$this->performDeepMerging = true;
|
||||
$this->nullEquivalent = array();
|
||||
$this->trueEquivalent = array();
|
||||
$this->normalizeKeys = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -281,6 +283,18 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables key normalization.
|
||||
*
|
||||
* @return ArrayNodeDefinition
|
||||
*/
|
||||
public function keepKeys()
|
||||
{
|
||||
$this->normalizeKeys = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a node definition.
|
||||
*
|
||||
@ -368,6 +382,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
|
||||
$node->setPerformDeepMerging($this->performDeepMerging);
|
||||
$node->setRequired($this->required);
|
||||
$node->setIgnoreExtraKeys($this->ignoreExtraKeys);
|
||||
$node->setNormalizeKeys($this->normalizeKeys);
|
||||
|
||||
if (null !== $this->normalization) {
|
||||
$node->setNormalizationClosures($this->normalization->before);
|
||||
|
@ -23,16 +23,11 @@ class Processor
|
||||
*
|
||||
* @param NodeInterface $configTree The node tree describing the configuration
|
||||
* @param array $configs An array of configuration items to process
|
||||
* @param bool $normalizeKeys Flag indicating if config key normalization is needed. True by default.
|
||||
*
|
||||
* @return array The processed configuration
|
||||
*/
|
||||
public function process(NodeInterface $configTree, array $configs, $normalizeKeys = true)
|
||||
public function process(NodeInterface $configTree, array $configs)
|
||||
{
|
||||
if ($normalizeKeys) {
|
||||
$configs = self::normalizeKeys($configs);
|
||||
}
|
||||
|
||||
$currentConfig = array();
|
||||
foreach ($configs as $config) {
|
||||
$config = $configTree->normalize($config);
|
||||
@ -47,42 +42,12 @@ class Processor
|
||||
*
|
||||
* @param ConfigurationInterface $configuration The configuration class
|
||||
* @param array $configs An array of configuration items to process
|
||||
* @param bool $normalizeKeys Flag indicating if config key normalization is needed. True by default.
|
||||
*
|
||||
* @return array The processed configuration
|
||||
*/
|
||||
public function processConfiguration(ConfigurationInterface $configuration, array $configs, $normalizeKeys = true)
|
||||
public function processConfiguration(ConfigurationInterface $configuration, array $configs)
|
||||
{
|
||||
return $this->process($configuration->getConfigTreeBuilder()->buildTree(), $configs, $normalizeKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method normalizes keys between the different configuration formats
|
||||
*
|
||||
* Namely, you mostly have foo_bar in YAML while you have foo-bar in XML.
|
||||
* After running this method, all keys are normalized to foo_bar.
|
||||
*
|
||||
* If you have a mixed key like foo-bar_moo, it will not be altered.
|
||||
* The key will also not be altered if the target key already exists.
|
||||
*
|
||||
* @param array $config
|
||||
*
|
||||
* @return array the config with normalized keys
|
||||
*/
|
||||
public static function normalizeKeys(array $config)
|
||||
{
|
||||
foreach ($config as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$config[$key] = self::normalizeKeys($value);
|
||||
}
|
||||
|
||||
if (false !== strpos($key, '-') && false === strpos($key, '_') && !array_key_exists($normalizedKey = str_replace('-', '_', $key), $config)) {
|
||||
$config[$normalizedKey] = $config[$key];
|
||||
unset($config[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return $config;
|
||||
return $this->process($configuration->getConfigTreeBuilder()->buildTree(), $configs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\Config\Tests\Definition;
|
||||
|
||||
use Symfony\Component\Config\Definition\ArrayNode;
|
||||
use Symfony\Component\Config\Definition\PrototypedArrayNode;
|
||||
|
||||
class ArrayNodeTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
@ -54,4 +55,35 @@ class ArrayNodeTest extends \PHPUnit_Framework_TestCase
|
||||
$node->normalize(array('foo' => 'bar'));
|
||||
$this->assertTrue(true, 'No exception was thrown when setIgnoreExtraKeys is true');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getPreNormalizationTests
|
||||
*/
|
||||
public function testPreNormalize($denormalized, $normalized)
|
||||
{
|
||||
$node = new ArrayNode('foo');
|
||||
|
||||
$r = new \ReflectionMethod($node, 'preNormalize');
|
||||
$r->setAccessible(true);
|
||||
|
||||
$this->assertSame($normalized, $r->invoke($node, $denormalized));
|
||||
}
|
||||
|
||||
public function getPreNormalizationTests()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array('foo-bar' => 'foo'),
|
||||
array('foo_bar' => 'foo'),
|
||||
),
|
||||
array(
|
||||
array('foo-bar_moo' => 'foo'),
|
||||
array('foo-bar_moo' => 'foo'),
|
||||
),
|
||||
array(
|
||||
array('foo-bar' => null, 'foo_bar' => 'foo'),
|
||||
array('foo-bar' => null, 'foo_bar' => 'foo'),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,51 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Config\Tests\Definition;
|
||||
|
||||
use Symfony\Component\Config\Definition\Processor;
|
||||
|
||||
class ProcessorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getKeyNormalizationTests
|
||||
*/
|
||||
public function testNormalizeKeys($denormalized, $normalized)
|
||||
{
|
||||
$this->assertSame($normalized, Processor::normalizeKeys($denormalized));
|
||||
}
|
||||
|
||||
public function getKeyNormalizationTests()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array('foo-bar' => 'foo'),
|
||||
array('foo_bar' => 'foo'),
|
||||
),
|
||||
array(
|
||||
array('foo-bar_moo' => 'foo'),
|
||||
array('foo-bar_moo' => 'foo'),
|
||||
),
|
||||
array(
|
||||
array('foo-bar' => null, 'foo_bar' => 'foo'),
|
||||
array('foo-bar' => null, 'foo_bar' => 'foo'),
|
||||
),
|
||||
array(
|
||||
array('foo-bar' => array('foo-bar' => 'foo')),
|
||||
array('foo_bar' => array('foo_bar' => 'foo')),
|
||||
),
|
||||
array(
|
||||
array('foo_bar' => array('foo-bar' => 'foo')),
|
||||
array('foo_bar' => array('foo_bar' => 'foo')),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -17,7 +17,6 @@ use Symfony\Component\Config\Definition\ScalarNode;
|
||||
|
||||
class PrototypedArrayNodeTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
public function testGetDefaultValueReturnsAnEmptyArrayForPrototypes()
|
||||
{
|
||||
$node = new PrototypedArrayNode('root');
|
||||
@ -31,8 +30,8 @@ class PrototypedArrayNodeTest extends \PHPUnit_Framework_TestCase
|
||||
$node = new PrototypedArrayNode('root');
|
||||
$prototype = new ArrayNode(null, $node);
|
||||
$node->setPrototype($prototype);
|
||||
$node->setDefaultValue(array ('test'));
|
||||
$this->assertEquals(array ('test'), $node->getDefaultValue());
|
||||
$node->setDefaultValue(array('test'));
|
||||
$this->assertEquals(array('test'), $node->getDefaultValue());
|
||||
}
|
||||
|
||||
// a remapped key (e.g. "mapping" -> "mappings") should be unset after being used
|
||||
|
@ -75,11 +75,11 @@ abstract class Extension implements ExtensionInterface, ConfigurationExtensionIn
|
||||
return Container::underscore($classBaseName);
|
||||
}
|
||||
|
||||
final protected function processConfiguration(ConfigurationInterface $configuration, array $configs, $normalizeKeys = true)
|
||||
final protected function processConfiguration(ConfigurationInterface $configuration, array $configs)
|
||||
{
|
||||
$processor = new Processor();
|
||||
|
||||
return $processor->processConfiguration($configuration, $configs, $normalizeKeys);
|
||||
return $processor->processConfiguration($configuration, $configs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user