4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Config\Tests\Definition;
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\Config\Definition\PrototypedArrayNode;
16 use Symfony\Component\Config\Definition\ArrayNode;
17 use Symfony\Component\Config\Definition\ScalarNode;
18 use Symfony\Component\Config\Definition\VariableNode;
20 class PrototypedArrayNodeTest extends TestCase
22 public function testGetDefaultValueReturnsAnEmptyArrayForPrototypes()
24 $node = new PrototypedArrayNode('root');
25 $prototype = new ArrayNode(null, $node);
26 $node->setPrototype($prototype);
27 $this->assertEmpty($node->getDefaultValue());
30 public function testGetDefaultValueReturnsDefaultValueForPrototypes()
32 $node = new PrototypedArrayNode('root');
33 $prototype = new ArrayNode(null, $node);
34 $node->setPrototype($prototype);
35 $node->setDefaultValue(array('test'));
36 $this->assertEquals(array('test'), $node->getDefaultValue());
39 // a remapped key (e.g. "mapping" -> "mappings") should be unset after being used
40 public function testRemappedKeysAreUnset()
42 $node = new ArrayNode('root');
43 $mappingsNode = new PrototypedArrayNode('mappings');
44 $node->addChild($mappingsNode);
46 // each item under mappings is just a scalar
47 $prototype = new ScalarNode(null, $mappingsNode);
48 $mappingsNode->setPrototype($prototype);
50 $remappings = array();
51 $remappings[] = array('mapping', 'mappings');
52 $node->setXmlRemappings($remappings);
54 $normalized = $node->normalize(array('mapping' => array('foo', 'bar')));
55 $this->assertEquals(array('mappings' => array('foo', 'bar')), $normalized);
59 * Tests that when a key attribute is mapped, that key is removed from the array.
62 * <option id="option1" value="foo">
63 * <option id="option2" value="bar">
66 * The above should finally be mapped to an array that looks like this
67 * (because "id" is the key attribute).
76 public function testMappedAttributeKeyIsRemoved()
78 $node = new PrototypedArrayNode('root');
79 $node->setKeyAttribute('id', true);
81 // each item under the root is an array, with one scalar item
82 $prototype = new ArrayNode(null, $node);
83 $prototype->addChild(new ScalarNode('foo'));
84 $node->setPrototype($prototype);
87 $children[] = array('id' => 'item_name', 'foo' => 'bar');
88 $normalized = $node->normalize($children);
91 $expected['item_name'] = array('foo' => 'bar');
92 $this->assertEquals($expected, $normalized);
96 * Tests the opposite of the testMappedAttributeKeyIsRemoved because
97 * the removal can be toggled with an option.
99 public function testMappedAttributeKeyNotRemoved()
101 $node = new PrototypedArrayNode('root');
102 $node->setKeyAttribute('id', false);
104 // each item under the root is an array, with two scalar items
105 $prototype = new ArrayNode(null, $node);
106 $prototype->addChild(new ScalarNode('foo'));
107 $prototype->addChild(new ScalarNode('id')); // the key attribute will remain
108 $node->setPrototype($prototype);
111 $children[] = array('id' => 'item_name', 'foo' => 'bar');
112 $normalized = $node->normalize($children);
115 $expected['item_name'] = array('id' => 'item_name', 'foo' => 'bar');
116 $this->assertEquals($expected, $normalized);
119 public function testAddDefaultChildren()
121 $node = $this->getPrototypeNodeWithDefaultChildren();
122 $node->setAddChildrenIfNoneSet();
123 $this->assertTrue($node->hasDefaultValue());
124 $this->assertEquals(array(array('foo' => 'bar')), $node->getDefaultValue());
126 $node = $this->getPrototypeNodeWithDefaultChildren();
127 $node->setKeyAttribute('foobar');
128 $node->setAddChildrenIfNoneSet();
129 $this->assertTrue($node->hasDefaultValue());
130 $this->assertEquals(array('defaults' => array('foo' => 'bar')), $node->getDefaultValue());
132 $node = $this->getPrototypeNodeWithDefaultChildren();
133 $node->setKeyAttribute('foobar');
134 $node->setAddChildrenIfNoneSet('defaultkey');
135 $this->assertTrue($node->hasDefaultValue());
136 $this->assertEquals(array('defaultkey' => array('foo' => 'bar')), $node->getDefaultValue());
138 $node = $this->getPrototypeNodeWithDefaultChildren();
139 $node->setKeyAttribute('foobar');
140 $node->setAddChildrenIfNoneSet(array('defaultkey'));
141 $this->assertTrue($node->hasDefaultValue());
142 $this->assertEquals(array('defaultkey' => array('foo' => 'bar')), $node->getDefaultValue());
144 $node = $this->getPrototypeNodeWithDefaultChildren();
145 $node->setKeyAttribute('foobar');
146 $node->setAddChildrenIfNoneSet(array('dk1', 'dk2'));
147 $this->assertTrue($node->hasDefaultValue());
148 $this->assertEquals(array('dk1' => array('foo' => 'bar'), 'dk2' => array('foo' => 'bar')), $node->getDefaultValue());
150 $node = $this->getPrototypeNodeWithDefaultChildren();
151 $node->setAddChildrenIfNoneSet(array(5, 6));
152 $this->assertTrue($node->hasDefaultValue());
153 $this->assertEquals(array(0 => array('foo' => 'bar'), 1 => array('foo' => 'bar')), $node->getDefaultValue());
155 $node = $this->getPrototypeNodeWithDefaultChildren();
156 $node->setAddChildrenIfNoneSet(2);
157 $this->assertTrue($node->hasDefaultValue());
158 $this->assertEquals(array(array('foo' => 'bar'), array('foo' => 'bar')), $node->getDefaultValue());
161 public function testDefaultChildrenWinsOverDefaultValue()
163 $node = $this->getPrototypeNodeWithDefaultChildren();
164 $node->setAddChildrenIfNoneSet();
165 $node->setDefaultValue(array('bar' => 'foo'));
166 $this->assertTrue($node->hasDefaultValue());
167 $this->assertEquals(array(array('foo' => 'bar')), $node->getDefaultValue());
170 protected function getPrototypeNodeWithDefaultChildren()
172 $node = new PrototypedArrayNode('root');
173 $prototype = new ArrayNode(null, $node);
174 $child = new ScalarNode('foo');
175 $child->setDefaultValue('bar');
176 $prototype->addChild($child);
177 $prototype->setAddIfNotSet(true);
178 $node->setPrototype($prototype);
184 * Tests that when a key attribute is mapped, that key is removed from the array.
185 * And if only 'value' element is left in the array, it will replace its wrapper array.
188 * <option id="option1" value="value1">
191 * The above should finally be mapped to an array that looks like this
192 * (because "id" is the key attribute).
196 * 'option1' => 'value1'
200 * It's also possible to mix 'value-only' and 'non-value-only' elements in the array.
203 * <option id="option1" value="value1">
204 * <option id="option2" value="value2" foo="foo2">
207 * The above should finally be mapped to an array as follows
211 * 'option1' => 'value1',
212 * 'option2' => array(
213 * 'value' => 'value2',
219 * The 'value' element can also be ArrayNode:
222 * <option id="option1">
230 * The above should be finally be mapped to an array as follows
234 * 'option1' => array(
241 * If using VariableNode for value node, it's also possible to mix different types of value nodes:
244 * <option id="option1">
250 * <option id="option2" value="value2">
253 * The above should be finally mapped to an array as follows
257 * 'option1' => array(
261 * 'option2' => 'value2'
266 * @dataProvider getDataForKeyRemovedLeftValueOnly
268 public function testMappedAttributeKeyIsRemovedLeftValueOnly($value, $children, $expected)
270 $node = new PrototypedArrayNode('root');
271 $node->setKeyAttribute('id', true);
273 // each item under the root is an array, with one scalar item
274 $prototype = new ArrayNode(null, $node);
275 $prototype->addChild(new ScalarNode('id'));
276 $prototype->addChild(new ScalarNode('foo'));
277 $prototype->addChild($value);
278 $node->setPrototype($prototype);
280 $normalized = $node->normalize($children);
281 $this->assertEquals($expected, $normalized);
284 public function getDataForKeyRemovedLeftValueOnly()
286 $scalarValue = new ScalarNode('value');
288 $arrayValue = new ArrayNode('value');
289 $arrayValue->addChild(new ScalarNode('foo'));
290 $arrayValue->addChild(new ScalarNode('bar'));
292 $variableValue = new VariableNode('value');
298 array('id' => 'option1', 'value' => 'value1'),
300 array('option1' => 'value1'),
306 array('id' => 'option1', 'value' => 'value1'),
307 array('id' => 'option2', 'value' => 'value2', 'foo' => 'foo2'),
310 'option1' => 'value1',
311 'option2' => array('value' => 'value2', 'foo' => 'foo2'),
320 'value' => array('foo' => 'foo1', 'bar' => 'bar1'),
324 'option1' => array('foo' => 'foo1', 'bar' => 'bar1'),
328 array($variableValue,
331 'id' => 'option1', 'value' => array('foo' => 'foo1', 'bar' => 'bar1'),
333 array('id' => 'option2', 'value' => 'value2'),
336 'option1' => array('foo' => 'foo1', 'bar' => 'bar1'),
337 'option2' => 'value2',