diff --git a/src/Symfony/Component/Config/Definition/ArrayNode.php b/src/Symfony/Component/Config/Definition/ArrayNode.php index a1b89317f7..a95bcee57b 100644 --- a/src/Symfony/Component/Config/Definition/ArrayNode.php +++ b/src/Symfony/Component/Config/Definition/ArrayNode.php @@ -34,7 +34,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface protected $minNumberOfElements; protected $performDeepMerging; protected $defaultValue; - protected $allowUnnamedChildren; + protected $preventExtraKeys; /** * Constructor. @@ -53,7 +53,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface $this->allowNewKeys = true; $this->performDeepMerging = true; $this->minNumberOfElements = 0; - $this->allowUnnamedChildren = false; + $this->preventExtraKeys = true; } /** @@ -310,14 +310,6 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface } } - // if extra fields are present and allowUnnamedChildren is false, throw exception - if (!$this->allowUnnamedChildren && $diff = array_diff(array_keys($value), array_keys($this->children))) { - $msg = sprintf('Unrecognized options "%s" under "%s"', implode(', ', $diff), $this->getPath()); - - throw new InvalidConfigurationException($msg); - } - - return $value; } @@ -406,6 +398,13 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface $value[$name] = $child->normalize($value[$name]); } + // if extra fields are present and preventExtraKeys is true, throw exception + if ($this->preventExtraKeys && $diff = array_diff(array_keys($value), array_keys($this->children))) { + $msg = sprintf('Unrecognized options "%s" under "%s"', implode(', ', $diff), $this->getPath()); + + throw new InvalidConfigurationException($msg); + } + return $value; } @@ -467,8 +466,12 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface } /** - * Set whether or not to allow this array to have child values that - * are not represented as nodes. + * Set whether or not to this array should just prevent child values from + * keys that have no corresponding child nodes. + * + * If true (default), an exception will be thrown if unrecognized options + * are introduced. If false, extra keys are allowed in and included in + * the final array. * * An example would be an "options" array node, where its children * could be any key of any form. In this case, no children are placed @@ -476,8 +479,8 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface * * @param Boolean $v Whether to allow unnamed children */ - public function setAllowUnnamedChildren($v) + public function setPreventExtraKeys($v) { - $this->allowUnnamedChildren = $v; + $this->preventExtraKeys = $v; } } \ No newline at end of file diff --git a/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php b/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php index 174a4585f6..01a3ce3c20 100644 --- a/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php +++ b/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php @@ -42,7 +42,7 @@ class NodeBuilder public $trueEquivalent; public $falseEquivalent; public $performDeepMerging; - public $allowUnnamedChildren; + public $preventExtraKeys; /** * Constructor @@ -65,7 +65,7 @@ class NodeBuilder $this->allowEmptyValue = true; $this->children = array(); $this->performDeepMerging = true; - $this->allowUnnamedChildren = false; + $this->preventExtraKeys = true; if ('boolean' === $type) { $this->nullEquivalent = true; @@ -467,7 +467,11 @@ class NodeBuilder } /** - * Allows child values not represented by a node. + * Allow un-named child values to be set into an array node. + * + * By default, any values under an array node must be represented by + * a child node. This allows an array node to accept any values set + * on it, regardless of whether or not a node is present to normalize it. * * An example would be an "options" array node, where its children * could be any key of any form. In this case, no children are placed @@ -475,9 +479,9 @@ class NodeBuilder * * @return Symfony\Component\DependencyInjection\Configuration\Builder\NodeBuilder */ - public function allowUnnamedChildren() + public function allowExtraKeys() { - $this->allowUnnamedChildren = true; + $this->preventExtraKeys = false; return $this; } diff --git a/src/Symfony/Component/Config/Definition/Builder/TreeBuilder.php b/src/Symfony/Component/Config/Definition/Builder/TreeBuilder.php index 900286d7dd..ed9b070d11 100644 --- a/src/Symfony/Component/Config/Definition/Builder/TreeBuilder.php +++ b/src/Symfony/Component/Config/Definition/Builder/TreeBuilder.php @@ -163,7 +163,7 @@ class TreeBuilder $configNode->addEquivalentValue(false, $node->falseEquivalent); $configNode->setPerformDeepMerging($node->performDeepMerging); $configNode->setRequired($node->required); - $configNode->setAllowUnnamedChildren($node->allowUnnamedChildren); + $configNode->setPreventExtraKeys($node->preventExtraKeys); if (null !== $node->key) { $configNode->setKeyAttribute($node->key); diff --git a/tests/Symfony/Tests/Component/Config/Definition/ArrayNodeTest.php b/tests/Symfony/Tests/Component/Config/Definition/ArrayNodeTest.php index 1cd3919fb2..91220e80fa 100644 --- a/tests/Symfony/Tests/Component/Config/Definition/ArrayNodeTest.php +++ b/tests/Symfony/Tests/Component/Config/Definition/ArrayNodeTest.php @@ -56,27 +56,16 @@ class ArrayNodeTest extends \PHPUnit_Framework_TestCase { $this->setExpectedException('Symfony\Component\DependencyInjection\Configuration\Exception\InvalidConfigurationException'); $node = new ArrayNode('root'); - $node->finalize(array('foo' => 'bar')); + $node->normalize(array('foo' => 'bar')); } - // if unnamedChildren is true, finalize allows them + // if prevent extra keys is false, normalize allows them public function textNoExceptionForUnrecognizedChildWithUnnamedChildren() { $node = new ArrayNode('root'); - $node->setAllowUnnamedChildren(true); - $finalized = $node->finalize(array('foo' => 'bar')); - - $this->assertEquals(array('foo' => 'bar'), $finalized); - } - - /** - * normalize() should not strip values that don't have children nodes. - * Validation will take place later in finalizeValue(). - */ - public function testNormalizeKeepsExtraArrayValues() - { - $node = new ArrayNode('root'); + $node->setPreventExtraKeys(false); $normalized = $node->normalize(array('foo' => 'bar')); + $this->assertEquals(array('foo' => 'bar'), $normalized); } @@ -84,6 +73,9 @@ class ArrayNodeTest extends \PHPUnit_Framework_TestCase public function testRemappedKeysAreUnset() { $node = new ArrayNode('root'); + $mappingsNode = new ArrayNode('mappings'); + $mappingsNode->setPreventExtraKeys(false); // just so we can add anything to it + $node->addChild($mappingsNode); $remappings = array(); $remappings[] = array('mapping', 'mappings'); @@ -117,6 +109,7 @@ class ArrayNodeTest extends \PHPUnit_Framework_TestCase $node->setKeyAttribute('id'); $prototype = new ArrayNode(null); + $prototype->setPreventExtraKeys(false); // just so it allows anything $node->setPrototype($prototype); $children = array();