From b7fc009316511170b395c75d98b3348fe336a52a Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 14 May 2012 16:12:22 +0200 Subject: [PATCH] [Config] Numerical keys for prot. arrays if useAttributeAsKey is set --- .../Config/Definition/PrototypedArrayNode.php | 3 +- .../Tests/Definition/NormalizationTest.php | 66 +++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php b/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php index f800a3f8f5..695975ab50 100644 --- a/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php +++ b/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php @@ -242,10 +242,11 @@ class PrototypedArrayNode extends ArrayNode $value = $this->remapXml($value); + $isAssoc = array_keys($value) === range(0, count($value) -1); $normalized = array(); foreach ($value as $k => $v) { if (null !== $this->keyAttribute && is_array($v)) { - if (!isset($v[$this->keyAttribute]) && is_int($k)) { + if (!isset($v[$this->keyAttribute]) && is_int($k) && $isAssoc) { $msg = sprintf('The attribute "%s" must be set for path "%s".', $this->keyAttribute, $this->getPath()); $ex = new InvalidConfigurationException($msg); $ex->setPath($this->getPath()); diff --git a/src/Symfony/Component/Config/Tests/Definition/NormalizationTest.php b/src/Symfony/Component/Config/Tests/Definition/NormalizationTest.php index 4a475a74fb..ee49154478 100644 --- a/src/Symfony/Component/Config/Tests/Definition/NormalizationTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/NormalizationTest.php @@ -137,8 +137,74 @@ class NormalizerTest extends \PHPUnit_Framework_TestCase return array_map(function($v) { return array($v); }, $configs); } + /** + * @dataProvider getNumericKeysTests + */ + public function testNumericKeysAsAttributes($denormalized) + { + $normalized = array( + 'thing' => array(42 => array('foo', 'bar'), 1337 => array('baz', 'qux')), + ); + + $this->assertNormalized($this->getNumericKeysTestTree(), $denormalized, $normalized); + } + + public function getNumericKeysTests() + { + $configs = array(); + + $configs[] = array( + 'thing' => array( + 42 => array('foo', 'bar'), 1337 => array('baz', 'qux'), + ), + ); + + $configs[] = array( + 'thing' => array( + array('foo', 'bar', 'id' => 42), array('baz', 'qux', 'id' => 1337), + ), + ); + + return array_map(function($v) { return array($v); }, $configs); + } + + /** + * @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException + * @expectedExceptionMessage The attribute "id" must be set for path "root.thing". + */ + public function testNonAssociativeArrayThrowsExceptionIfAttributeNotSet() + { + $denormalized = array( + 'thing' => array( + array('foo', 'bar'), array('baz', 'qux') + ) + ); + + $this->assertNormalized($this->getNumericKeysTestTree(), $denormalized, array()); + } + public static function assertNormalized(NodeInterface $tree, $denormalized, $normalized) { self::assertSame($normalized, $tree->normalize($denormalized)); } + + private function getNumericKeysTestTree() + { + $tb = new TreeBuilder(); + $tree = $tb + ->root('root', 'array') + ->children() + ->node('thing', 'array') + ->useAttributeAsKey('id') + ->prototype('array') + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->end() + ->buildTree() + ; + + return $tree; + } }