Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Config key normalization #6367

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 16, 2012
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 @@ -76,6 +76,7 @@ private function addGlobalsSection(ArrayNodeDefinition $rootNode)
->fixXmlConfig('global')
->children()
->arrayNode('globals')
->keepKeys()
->useAttributeAsKey('key')
->example(array('foo' => '"@bar"', 'pi' => 3.14))
->prototype('array')
Expand Down Expand Up @@ -126,6 +127,7 @@ private function addTwigOptions(ArrayNodeDefinition $rootNode)
->scalarNode('auto_reload')->end()
->scalarNode('optimizations')->end()
->arrayNode('paths')
->keepKeys()
->beforeNormalization()
->always()
->then(function ($paths) {
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/Config/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 36 additions & 0 deletions src/Symfony/Component/Config/Definition/ArrayNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
protected $addIfNotSet;
protected $performDeepMerging;
protected $ignoreExtraKeys;
protected $normalizeKeys;

/**
* Constructor.
Expand All @@ -47,6 +48,41 @@ public function __construct($name, NodeInterface $parent = null)
$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;
}

/**
Expand Down
14 changes: 14 additions & 0 deletions src/Symfony/Component/Config/Definition/BaseNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ final public function merge($leftSide, $rightSide)
*/
final public function normalize($value)
{
$value = $this->preNormalize($value);

// run custom normalization closures
foreach ($this->normalizationClosures as $closure) {
$value = $closure($value);
Expand All @@ -266,6 +268,18 @@ final public function normalize($value)
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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
protected $addDefaults;
protected $addDefaultChildren;
protected $nodeBuilder;
protected $normalizeKeys;

/**
* {@inheritDoc}
Expand All @@ -51,6 +52,7 @@ public function __construct($name, NodeParentInterface $parent = null)
$this->performDeepMerging = true;
$this->nullEquivalent = array();
$this->trueEquivalent = array();
$this->normalizeKeys = true;
}

/**
Expand Down Expand Up @@ -281,6 +283,18 @@ public function ignoreExtraKeys()
return $this;
}

/**
* Disables key normalization.
*
* @return ArrayNodeDefinition
*/
public function keepKeys()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO an other unfortunate name what aboutnormalizeKeys($enabled = true) ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. Your suggestion is much better. I've just rename it. Thanks.

{
$this->normalizeKeys = false;

return $this;
}

/**
* Appends a node definition.
*
Expand Down Expand Up @@ -368,6 +382,7 @@ protected function createNode()
$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);
Expand Down
41 changes: 3 additions & 38 deletions src/Symfony/Component/Config/Definition/Processor.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -47,42 +42,12 @@ public function process(NodeInterface $configTree, array $configs, $normalizeKey
*
* @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)
{
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)
public function processConfiguration(ConfigurationInterface $configuration, array $configs)
{
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);
}

/**
Expand Down
32 changes: 32 additions & 0 deletions src/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -54,4 +55,35 @@ public function testIgnoreExtraKeysNoException()
$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'),
)
);
}
}
51 changes: 0 additions & 51 deletions src/Symfony/Component/Config/Tests/Definition/ProcessorTest.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

class PrototypedArrayNodeTest extends \PHPUnit_Framework_TestCase
{

public function testGetDefaultValueReturnsAnEmptyArrayForPrototypes()
{
$node = new PrototypedArrayNode('root');
Expand All @@ -31,8 +30,8 @@ public function testGetDefaultValueReturnsDefaultValueForPrototypes()
$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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ public function getAlias()
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);
}

/**
Expand Down