Skip to content

Commit a980b43

Browse files
committed
merged branch asm89/numeric-keys-config (PR #4276)
Commits ------- b7fc009 [Config] Numerical keys for prot. arrays if useAttributeAsKey is set Discussion ---------- [Config] Numerical keys for prot. arrays if useAttributeAsKey is set Bug fix: not sure Feature addition: not sure Backwards compatibility break: not sure Symfony2 tests pass: [![Build Status](https://secure.travis-ci.org/asm89/symfony.png?branch=numeric-keys-config)](http://travis-ci.org/asm89/symfony) License of the code: MIT When using an array node with children of prototype array and `useAttributeAsKey`, using numerical values for the keys throws an exception. For example (`useAttributeAsKey('id')`): ``` php <?php // works array ( 'thing' => array( array('foo', 'bar', 'id' => 'a') ) ); // works and is the same as above array ( 'thing' => array( 'a' => array('foo', 'bar') ) ); // works array( 'thing' => array( array('foo', 'bar', 'id' => 42), array('baz', 'qux', 'id' => 1337), ), ); // works with this patch and is the same as above array( 'thing' => array( 42 => array('foo', 'bar'), 1337 => array('baz', 'qux'), ), ); ``` --------------------------------------------------------------------------- by travisbot at 2012-05-14T14:26:32Z This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1327383) (merged 42d252da into 46ffbd52). --------------------------------------------------------------------------- by travisbot at 2012-05-14T14:32:59Z This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1327430) (merged b7fc0093 into 46ffbd52). --------------------------------------------------------------------------- by vicb at 2012-05-21T15:16:24Z Could this be fixed by changing [PrototypedArrayNode](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php#L255) `$k = $v[$this->keyAttribute];` -> `$k = (string) $v[$this->keyAttribute];` --------------------------------------------------------------------------- by asm89 at 2012-05-22T07:01:53Z I tried it and the test I added still fails. The code change you propose doesn't execute because `if (!isset($v[$this->keyAttribute]) && is_int($k))` will still evaluate to true.
2 parents 17a8abc + c680a59 commit a980b43

File tree

2 files changed

+68
-1
lines changed

2 files changed

+68
-1
lines changed

Definition/PrototypedArrayNode.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,11 @@ protected function normalizeValue($value)
242242

243243
$value = $this->remapXml($value);
244244

245+
$isAssoc = array_keys($value) === range(0, count($value) -1);
245246
$normalized = array();
246247
foreach ($value as $k => $v) {
247248
if (null !== $this->keyAttribute && is_array($v)) {
248-
if (!isset($v[$this->keyAttribute]) && is_int($k)) {
249+
if (!isset($v[$this->keyAttribute]) && is_int($k) && $isAssoc) {
249250
$msg = sprintf('The attribute "%s" must be set for path "%s".', $this->keyAttribute, $this->getPath());
250251
$ex = new InvalidConfigurationException($msg);
251252
$ex->setPath($this->getPath());

Tests/Definition/NormalizationTest.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,74 @@ public function getAnonymousKeysTests()
137137
return array_map(function($v) { return array($v); }, $configs);
138138
}
139139

140+
/**
141+
* @dataProvider getNumericKeysTests
142+
*/
143+
public function testNumericKeysAsAttributes($denormalized)
144+
{
145+
$normalized = array(
146+
'thing' => array(42 => array('foo', 'bar'), 1337 => array('baz', 'qux')),
147+
);
148+
149+
$this->assertNormalized($this->getNumericKeysTestTree(), $denormalized, $normalized);
150+
}
151+
152+
public function getNumericKeysTests()
153+
{
154+
$configs = array();
155+
156+
$configs[] = array(
157+
'thing' => array(
158+
42 => array('foo', 'bar'), 1337 => array('baz', 'qux'),
159+
),
160+
);
161+
162+
$configs[] = array(
163+
'thing' => array(
164+
array('foo', 'bar', 'id' => 42), array('baz', 'qux', 'id' => 1337),
165+
),
166+
);
167+
168+
return array_map(function($v) { return array($v); }, $configs);
169+
}
170+
171+
/**
172+
* @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
173+
* @expectedExceptionMessage The attribute "id" must be set for path "root.thing".
174+
*/
175+
public function testNonAssociativeArrayThrowsExceptionIfAttributeNotSet()
176+
{
177+
$denormalized = array(
178+
'thing' => array(
179+
array('foo', 'bar'), array('baz', 'qux')
180+
)
181+
);
182+
183+
$this->assertNormalized($this->getNumericKeysTestTree(), $denormalized, array());
184+
}
185+
140186
public static function assertNormalized(NodeInterface $tree, $denormalized, $normalized)
141187
{
142188
self::assertSame($normalized, $tree->normalize($denormalized));
143189
}
190+
191+
private function getNumericKeysTestTree()
192+
{
193+
$tb = new TreeBuilder();
194+
$tree = $tb
195+
->root('root', 'array')
196+
->children()
197+
->node('thing', 'array')
198+
->useAttributeAsKey('id')
199+
->prototype('array')
200+
->prototype('scalar')->end()
201+
->end()
202+
->end()
203+
->end()
204+
->end()
205+
->buildTree()
206+
;
207+
208+
return $tree;
209+
}
144210
}

0 commit comments

Comments
 (0)