diff --git a/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php index 69064e2ec4..669ced43a6 100644 --- a/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php @@ -13,6 +13,7 @@ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\ArrayNode; use Symfony\Component\Config\Definition\PrototypedArrayNode; +use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; /** * This class provides a fluent interface for defining an array node. @@ -259,13 +260,38 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition protected function createNode() { if (null === $this->prototype) { - $node = new ArrayNode($this->name, $this->parent); + if (null !== $this->key) { + throw new InvalidDefinitionException( + sprintf('%s::useAttributeAsKey() is not applicable to concrete nodes.', __CLASS__) + ); + } + if (true === $this->atLeastOne) { + throw new InvalidDefinitionException( + sprintf('%s::requiresAtLeastOneElement() is not applicable to concrete nodes.', __CLASS__) + ); + } + + if ($this->default) { + throw new InvalidDefinitionException( + sprintf('%s::defaultValue() is not applicable to concrete nodes.', __CLASS__) + ); + } + + $node = new ArrayNode($this->name, $this->parent); + $node->setAddIfNotSet($this->addDefaults); + foreach ($this->children as $child) { $child->parent = $node; $node->addChild($child->getNode()); } } else { + if ($this->addDefaults) { + throw new InvalidDefinitionException( + sprintf('%s::addDefaultsIfNotSet() is not applicable to prototype nodes.', __CLASS__) + ); + } + $node = new PrototypedArrayNode($this->name, $this->parent); if (null !== $this->key) { @@ -284,7 +310,6 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition $node->setPrototype($this->prototype->getNode()); } - $node->setAddIfNotSet($this->addDefaults); $node->setAllowNewKeys($this->allowNewKeys); $node->addEquivalentValue(null, $this->nullEquivalent); $node->addEquivalentValue(true, $this->trueEquivalent); diff --git a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php index 0393378f2a..561143bc61 100644 --- a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php @@ -325,6 +325,8 @@ abstract class NodeDefinition implements NodeParentInterface * Instantiate and configure the node according to this definition * * @return NodeInterface $node The node instance + * + * @throws Symfony\Component\Config\Definition\Exception\InvalidDefinitionException When the definition is invalid */ abstract protected function createNode(); diff --git a/src/Symfony/Component/Config/Definition/Exception/InvalidDefinitionException.php b/src/Symfony/Component/Config/Definition/Exception/InvalidDefinitionException.php new file mode 100644 index 0000000000..98310dae02 --- /dev/null +++ b/src/Symfony/Component/Config/Definition/Exception/InvalidDefinitionException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Exception; + +/** + * Thrown when an error is detected in a node Definition. + * + * @author Victor Berchet + */ +class InvalidDefinitionException extends Exception +{ +} diff --git a/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php b/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php index 7d5fa1a098..e49d0d49f0 100644 --- a/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php +++ b/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\Definition\Exception\DuplicateKeyException; use Symfony\Component\Config\Definition\Exception\UnsetKeyException; +use Symfony\Component\Config\Definition\Exception\Exception; /** * Represents a prototyped Array node in the config tree. @@ -158,7 +159,7 @@ class PrototypedArrayNode extends ArrayNode */ public function addChild(NodeInterface $node) { - throw new \RuntimeException('A prototyped array node can not have concrete children.'); + throw new Exception('A prototyped array node can not have concrete children.'); } /** diff --git a/tests/Symfony/Tests/Component/Config/Definition/Builder/ArrayNodeDefinitionTest.php b/tests/Symfony/Tests/Component/Config/Definition/Builder/ArrayNodeDefinitionTest.php index 7b34b17bdd..337d8ee428 100644 --- a/tests/Symfony/Tests/Component/Config/Definition/Builder/ArrayNodeDefinitionTest.php +++ b/tests/Symfony/Tests/Component/Config/Definition/Builder/ArrayNodeDefinitionTest.php @@ -32,6 +32,38 @@ class ArrayNodeDefinitionTest extends \PHPUnit_Framework_TestCase $this->assertTrue(in_array($child, $this->getField($parent, 'children'))); } + /** + * @expectedException Symfony\Component\Config\Definition\Exception\InvalidDefinitionException + * @dataProvider providePrototypeNodeSpecificCalls + */ + public function testPrototypeNodeSpecificOption($method, $args) + { + $node = new ArrayNodeDefinition('root'); + + call_user_method_array($method, $node, $args); + + $node->getNode(); + } + + public function providePrototypeNodeSpecificCalls() + { + return array( + array('defaultValue', array(array())), + array('requiresAtLeastOneElement', array()), + array('useAttributeAsKey', array('foo')) + ); + } + + /** + * @expectedException Symfony\Component\Config\Definition\Exception\InvalidDefinitionException + */ + public function testConcreteNodeSpecificOption() + { + $node = new ArrayNodeDefinition('root'); + $node->addDefaultsIfNotSet()->prototype('array'); + $node->getNode(); + } + protected function getField($object, $field) { $reflection = new \ReflectionProperty($object, $field);