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 into46ffbd52
). --------------------------------------------------------------------------- by travisbot at 2012-05-14T14:32:59Z This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1327430) (mergedb7fc0093
into46ffbd52
). --------------------------------------------------------------------------- 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.
This commit is contained in:
commit
1a1403f599
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user