/** * Tests the opposite of the testMappedAttributeKeyIsRemoved because * the removal can be toggled with an option. */ public function testMappedAttributeKeyNotRemoved() { $node = new PrototypedArrayNode('root'); $node->setKeyAttribute('id', false); // each item under the root is an array, with two scalar items $prototype = new ArrayNode(null, $node); $prototype->addChild(new ScalarNode('foo')); $prototype->addChild(new ScalarNode('id')); // the key attribute will remain $node->setPrototype($prototype); $children = array(); $children[] = array('id' => 'item_name', 'foo' => 'bar'); $normalized = $node->normalize($children); $expected = array(); $expected['item_name'] = array('id' => 'item_name', 'foo' => 'bar'); $this->assertEquals($expected, $normalized); }
/** * @param PrototypedArrayNode $node * * @return array */ private function getPrototypeChildren(PrototypedArrayNode $node) { $prototype = $node->getPrototype(); $key = $node->getKeyAttribute(); // Do not expand prototype if it isn't an array node nor uses attribute as key if (!$key && !$prototype instanceof ArrayNode) { return $node->getChildren(); } if ($prototype instanceof ArrayNode) { $keyNode = new ArrayNode($key, $node); $children = $prototype->getChildren(); if ($prototype instanceof PrototypedArrayNode && $prototype->getKeyAttribute()) { $children = $this->getPrototypeChildren($prototype); } // add children foreach ($children as $childNode) { $keyNode->addChild($childNode); } } else { $keyNode = new ScalarNode($key, $node); } $info = 'Prototype'; if (null !== $prototype->getInfo()) { $info .= ': ' . $prototype->getInfo(); } $keyNode->setInfo($info); return array($key => $keyNode); }
/** * {@inheritDoc} */ protected function createNode() { if (null == $this->prototype) { $node = new ArrayNode($this->name, $this->parent); } else { $node = new PrototypedArrayNode($this->name, $this->parent); } $node->setAddIfNotSet($this->addDefaults); $node->setAllowNewKeys($this->allowNewKeys); $node->addEquivalentValue(null, $this->nullEquivalent); $node->addEquivalentValue(true, $this->trueEquivalent); $node->addEquivalentValue(false, $this->falseEquivalent); $node->setPerformDeepMerging($this->performDeepMerging); $node->setRequired($this->required); $node->setIgnoreExtraKeys($this->ignoreExtraKeys); if (null !== $this->normalization) { $node->setNormalizationClosures($this->normalization->before); $node->setXmlRemappings($this->normalization->remappings); } if (null !== $this->merge) { $node->setAllowOverwrite($this->merge->allowOverwrite); $node->setAllowFalse($this->merge->allowFalse); } if (null !== $this->validation) { $node->setFinalValidationClosures($this->validation->rules); } if (null == $this->prototype) { foreach ($this->children as $child) { $child->parent = $node; $node->addChild($child->getNode()); } } else { if (null !== $this->key) { $node->setKeyAttribute($this->key, $this->removeKeyItem); } if (true === $this->atLeastOne) { $node->setMinNumberOfElements(1); } if (null !== $this->defaultValue) { $node->setDefaultValue($this->defaultValue); } $this->prototype->parent = $node; $node->setPrototype($this->prototype->getNode()); } return $node; }
protected function validatePrototypeNode(PrototypedArrayNode $node) { $path = $node->getPath(); if ($this->addDefaults) { throw new InvalidDefinitionException(sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s"', $path)); } if (false !== $this->addDefaultChildren) { if ($this->default) { throw new InvalidDefinitionException(sprintf('A default value and default children might not be used together at path "%s"', $path)); } if (null !== $this->key && (null === $this->addDefaultChildren || is_int($this->addDefaultChildren) && $this->addDefaultChildren > 0)) { throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s"', $path)); } if (null === $this->key && (is_string($this->addDefaultChildren) || is_array($this->addDefaultChildren))) { throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s"', $path)); } } }
protected function getPrototypeNodeWithDefaultChildren() { $node = new PrototypedArrayNode('root'); $prototype = new ArrayNode(null, $node); $child = new ScalarNode('foo'); $child->setDefaultValue('bar'); $prototype->addChild($child); $prototype->setAddIfNotSet(true); $node->setPrototype($prototype); return $node; }
/** * Tests that when a key attribute is mapped, that key is removed from the array. * And if only 'value' element is left in the array, it will replace its wrapper array. * * <things> * <option id="option1" value="value1"> * </things> * * The above should finally be mapped to an array that looks like this * (because "id" is the key attribute). * * array( * 'things' => array( * 'option1' => 'value1' * ) * ) * * It's also possible to mix 'value-only' and 'non-value-only' elements in the array. * * <things> * <option id="option1" value="value1"> * <option id="option2" value="value2" foo="foo2"> * </things> * * The above should finally be mapped to an array as follows * * array( * 'things' => array( * 'option1' => 'value1', * 'option2' => array( * 'value' => 'value2', * 'foo' => 'foo2' * ) * ) * ) * * The 'value' element can also be ArrayNode: * * <things> * <option id="option1"> * <value> * <foo>foo1</foo> * <bar>bar1</bar> * </value> * </option> * </things> * * The above should be finally be mapped to an array as follows * * array( * 'things' => array( * 'option1' => array( * 'foo' => 'foo1', * 'bar' => 'bar1' * ) * ) * ) * * If using VariableNode for value node, it's also possible to mix different types of value nodes: * * <things> * <option id="option1"> * <value> * <foo>foo1</foo> * <bar>bar1</bar> * </value> * </option> * <option id="option2" value="value2"> * </things> * * The above should be finally mapped to an array as follows * * array( * 'things' => array( * 'option1' => array( * 'foo' => 'foo1', * 'bar' => 'bar1' * ), * 'option2' => 'value2' * ) * ) * * * @dataProvider getDataForKeyRemovedLeftValueOnly */ public function testMappedAttributeKeyIsRemovedLeftValueOnly($value, $children, $expected) { $node = new PrototypedArrayNode('root'); $node->setKeyAttribute('id', true); // each item under the root is an array, with one scalar item $prototype = new ArrayNode(null, $node); $prototype->addChild(new ScalarNode('id')); $prototype->addChild(new ScalarNode('foo')); $prototype->addChild($value); $node->setPrototype($prototype); $normalized = $node->normalize($children); $this->assertEquals($expected, $normalized); }