[Security/DependencyInjection] adds support for merging security configurations
The merging is done in three steps:
1. Normalization:
=================
All passed config arrays will be transformed into the same structure
regardless of what format they come from.
2. Merging:
===========
This is the step when the actual merging is performed. Starting at the root
the configs will be passed along the tree until a node has no children, or
the merging of sub-paths of the current node has been specifically disabled.
Left-Side Right-Side Merge Result
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-nothing- array Right-Side will be taken.
scalar scalar Right-Side will be taken.
array false Right-Side will be taken if ->canBeUnset()
was called on the array node.
false array Right-Side will be taken.
array array Each value in the array will be passed to
the specific child node, or the prototype
node (whatever is present).
3. Finalization:
================
The normalized, and merged config will be passed through the config tree to
perform final validation on the submitted values, and set default values
where this has been requested.
You can influence this process in various ways, here is a list with some examples.
All of these methods must be called on the node on which they should be applied.
* isRequired(): Node must be present in at least one config file.
* requiresAtLeastOneElement(): PrototypeNode must have at least one element.
* treatNullLike($value): Replaces null with $value during normalization.
* treatTrueLike($value): Same as above just for true
* treatFalseLike($value): Same as above just for false
* defaultValue($value): Sets a default value for this node (only for scalars)
* addDefaultsIfNotSet(): Whether to add default values of an array which has not
been defined in any configuration file.
* disallowNewKeysInSubsequentConfigs(): All keys for this array must be defined
in one configuration file, subsequent
configurations may only overwrite these.
* fixXmlConfig($key, $plural = null): Transforms XML config into same structure
as YAML, and PHP configurations.
* useAttributeAsKey($name): Defines which XML attribute to use as array key.
* cannotBeOverwritten(): Declares a certain sub-path as non-overwritable. All
configuration for this path must be defined in the same
configuration file.
* cannotBeEmpty(): If value is set, it must be non-empty.
* canBeUnset(): If array values should be unset if false is specified.
Architecture:
=============
The configuration consists basically out of two different sets of classes.
1. Builder classes: These classes provide the fluent interface and
are used to construct the config tree.
2. Node classes: These classes contain the actual logic for normalization,
merging, and finalizing configurations.
After you have added all the metadata to your builders, the call to
->buildTree() will convert this metadata to actual node classes. Most of the
time, you will not have to interact with the config nodes directly, but will
delegate this to the Processor class which will call the respective methods
on the config node classes.
2011-02-04 13:37:01 +00:00
|
|
|
<?php
|
|
|
|
|
2011-02-17 15:03:48 +00:00
|
|
|
namespace Symfony\Tests\Component\Config\Definition;
|
[Security/DependencyInjection] adds support for merging security configurations
The merging is done in three steps:
1. Normalization:
=================
All passed config arrays will be transformed into the same structure
regardless of what format they come from.
2. Merging:
===========
This is the step when the actual merging is performed. Starting at the root
the configs will be passed along the tree until a node has no children, or
the merging of sub-paths of the current node has been specifically disabled.
Left-Side Right-Side Merge Result
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-nothing- array Right-Side will be taken.
scalar scalar Right-Side will be taken.
array false Right-Side will be taken if ->canBeUnset()
was called on the array node.
false array Right-Side will be taken.
array array Each value in the array will be passed to
the specific child node, or the prototype
node (whatever is present).
3. Finalization:
================
The normalized, and merged config will be passed through the config tree to
perform final validation on the submitted values, and set default values
where this has been requested.
You can influence this process in various ways, here is a list with some examples.
All of these methods must be called on the node on which they should be applied.
* isRequired(): Node must be present in at least one config file.
* requiresAtLeastOneElement(): PrototypeNode must have at least one element.
* treatNullLike($value): Replaces null with $value during normalization.
* treatTrueLike($value): Same as above just for true
* treatFalseLike($value): Same as above just for false
* defaultValue($value): Sets a default value for this node (only for scalars)
* addDefaultsIfNotSet(): Whether to add default values of an array which has not
been defined in any configuration file.
* disallowNewKeysInSubsequentConfigs(): All keys for this array must be defined
in one configuration file, subsequent
configurations may only overwrite these.
* fixXmlConfig($key, $plural = null): Transforms XML config into same structure
as YAML, and PHP configurations.
* useAttributeAsKey($name): Defines which XML attribute to use as array key.
* cannotBeOverwritten(): Declares a certain sub-path as non-overwritable. All
configuration for this path must be defined in the same
configuration file.
* cannotBeEmpty(): If value is set, it must be non-empty.
* canBeUnset(): If array values should be unset if false is specified.
Architecture:
=============
The configuration consists basically out of two different sets of classes.
1. Builder classes: These classes provide the fluent interface and
are used to construct the config tree.
2. Node classes: These classes contain the actual logic for normalization,
merging, and finalizing configurations.
After you have added all the metadata to your builders, the call to
->buildTree() will convert this metadata to actual node classes. Most of the
time, you will not have to interact with the config nodes directly, but will
delegate this to the Processor class which will call the respective methods
on the config node classes.
2011-02-04 13:37:01 +00:00
|
|
|
|
2011-02-17 15:03:48 +00:00
|
|
|
use Symfony\Component\Config\Definition\ArrayNode;
|
2011-02-17 13:52:57 +00:00
|
|
|
use Symfony\Component\Config\Definition\ScalarNode;
|
[Security/DependencyInjection] adds support for merging security configurations
The merging is done in three steps:
1. Normalization:
=================
All passed config arrays will be transformed into the same structure
regardless of what format they come from.
2. Merging:
===========
This is the step when the actual merging is performed. Starting at the root
the configs will be passed along the tree until a node has no children, or
the merging of sub-paths of the current node has been specifically disabled.
Left-Side Right-Side Merge Result
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-nothing- array Right-Side will be taken.
scalar scalar Right-Side will be taken.
array false Right-Side will be taken if ->canBeUnset()
was called on the array node.
false array Right-Side will be taken.
array array Each value in the array will be passed to
the specific child node, or the prototype
node (whatever is present).
3. Finalization:
================
The normalized, and merged config will be passed through the config tree to
perform final validation on the submitted values, and set default values
where this has been requested.
You can influence this process in various ways, here is a list with some examples.
All of these methods must be called on the node on which they should be applied.
* isRequired(): Node must be present in at least one config file.
* requiresAtLeastOneElement(): PrototypeNode must have at least one element.
* treatNullLike($value): Replaces null with $value during normalization.
* treatTrueLike($value): Same as above just for true
* treatFalseLike($value): Same as above just for false
* defaultValue($value): Sets a default value for this node (only for scalars)
* addDefaultsIfNotSet(): Whether to add default values of an array which has not
been defined in any configuration file.
* disallowNewKeysInSubsequentConfigs(): All keys for this array must be defined
in one configuration file, subsequent
configurations may only overwrite these.
* fixXmlConfig($key, $plural = null): Transforms XML config into same structure
as YAML, and PHP configurations.
* useAttributeAsKey($name): Defines which XML attribute to use as array key.
* cannotBeOverwritten(): Declares a certain sub-path as non-overwritable. All
configuration for this path must be defined in the same
configuration file.
* cannotBeEmpty(): If value is set, it must be non-empty.
* canBeUnset(): If array values should be unset if false is specified.
Architecture:
=============
The configuration consists basically out of two different sets of classes.
1. Builder classes: These classes provide the fluent interface and
are used to construct the config tree.
2. Node classes: These classes contain the actual logic for normalization,
merging, and finalizing configurations.
After you have added all the metadata to your builders, the call to
->buildTree() will convert this metadata to actual node classes. Most of the
time, you will not have to interact with the config nodes directly, but will
delegate this to the Processor class which will call the respective methods
on the config node classes.
2011-02-04 13:37:01 +00:00
|
|
|
|
|
|
|
class ArrayNodeTest extends \PHPUnit_Framework_TestCase
|
|
|
|
{
|
|
|
|
/**
|
2011-02-17 15:03:48 +00:00
|
|
|
* @expectedException Symfony\Component\Config\Definition\Exception\InvalidTypeException
|
[Security/DependencyInjection] adds support for merging security configurations
The merging is done in three steps:
1. Normalization:
=================
All passed config arrays will be transformed into the same structure
regardless of what format they come from.
2. Merging:
===========
This is the step when the actual merging is performed. Starting at the root
the configs will be passed along the tree until a node has no children, or
the merging of sub-paths of the current node has been specifically disabled.
Left-Side Right-Side Merge Result
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-nothing- array Right-Side will be taken.
scalar scalar Right-Side will be taken.
array false Right-Side will be taken if ->canBeUnset()
was called on the array node.
false array Right-Side will be taken.
array array Each value in the array will be passed to
the specific child node, or the prototype
node (whatever is present).
3. Finalization:
================
The normalized, and merged config will be passed through the config tree to
perform final validation on the submitted values, and set default values
where this has been requested.
You can influence this process in various ways, here is a list with some examples.
All of these methods must be called on the node on which they should be applied.
* isRequired(): Node must be present in at least one config file.
* requiresAtLeastOneElement(): PrototypeNode must have at least one element.
* treatNullLike($value): Replaces null with $value during normalization.
* treatTrueLike($value): Same as above just for true
* treatFalseLike($value): Same as above just for false
* defaultValue($value): Sets a default value for this node (only for scalars)
* addDefaultsIfNotSet(): Whether to add default values of an array which has not
been defined in any configuration file.
* disallowNewKeysInSubsequentConfigs(): All keys for this array must be defined
in one configuration file, subsequent
configurations may only overwrite these.
* fixXmlConfig($key, $plural = null): Transforms XML config into same structure
as YAML, and PHP configurations.
* useAttributeAsKey($name): Defines which XML attribute to use as array key.
* cannotBeOverwritten(): Declares a certain sub-path as non-overwritable. All
configuration for this path must be defined in the same
configuration file.
* cannotBeEmpty(): If value is set, it must be non-empty.
* canBeUnset(): If array values should be unset if false is specified.
Architecture:
=============
The configuration consists basically out of two different sets of classes.
1. Builder classes: These classes provide the fluent interface and
are used to construct the config tree.
2. Node classes: These classes contain the actual logic for normalization,
merging, and finalizing configurations.
After you have added all the metadata to your builders, the call to
->buildTree() will convert this metadata to actual node classes. Most of the
time, you will not have to interact with the config nodes directly, but will
delegate this to the Processor class which will call the respective methods
on the config node classes.
2011-02-04 13:37:01 +00:00
|
|
|
*/
|
|
|
|
public function testNormalizeThrowsExceptionWhenFalseIsNotAllowed()
|
|
|
|
{
|
|
|
|
$node = new ArrayNode('root');
|
|
|
|
$node->normalize(false);
|
|
|
|
}
|
2011-02-12 13:37:44 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @expectedException InvalidArgumentException
|
|
|
|
*/
|
|
|
|
public function testSetDefaultValueThrowsExceptionWhenNotAnArray()
|
|
|
|
{
|
|
|
|
$node = new ArrayNode('root');
|
|
|
|
$node->setDefaultValue('test');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @expectedException RuntimeException
|
|
|
|
*/
|
|
|
|
public function testSetDefaultValueThrowsExceptionWhenNotAnPrototype()
|
|
|
|
{
|
|
|
|
$node = new ArrayNode('root');
|
|
|
|
$node->setDefaultValue(array ('test'));
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testGetDefaultValueReturnsAnEmptyArrayForPrototypes()
|
|
|
|
{
|
|
|
|
$node = new ArrayNode('root');
|
|
|
|
$prototype = new ArrayNode(null, $node);
|
|
|
|
$node->setPrototype($prototype);
|
|
|
|
$this->assertEmpty($node->getDefaultValue());
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testGetDefaultValueReturnsDefaultValueForPrototypes()
|
|
|
|
{
|
|
|
|
$node = new ArrayNode('root');
|
|
|
|
$prototype = new ArrayNode(null, $node);
|
|
|
|
$node->setPrototype($prototype);
|
|
|
|
$node->setDefaultValue(array ('test'));
|
|
|
|
$this->assertEquals(array ('test'), $node->getDefaultValue());
|
|
|
|
}
|
2011-02-17 13:13:08 +00:00
|
|
|
|
|
|
|
// finalizeValue() should protect against child values with no corresponding node
|
|
|
|
public function testExceptionThrownOnUnrecognizedChild()
|
|
|
|
{
|
2011-02-18 12:59:35 +00:00
|
|
|
$this->setExpectedException('Symfony\Component\Config\Definition\Exception\InvalidConfigurationException');
|
2011-02-17 13:13:08 +00:00
|
|
|
$node = new ArrayNode('root');
|
2011-02-18 12:49:51 +00:00
|
|
|
$node->normalize(array('foo' => 'bar'));
|
2011-02-17 13:13:08 +00:00
|
|
|
}
|
|
|
|
|
2011-02-18 12:49:51 +00:00
|
|
|
// if prevent extra keys is false, normalize allows them
|
2011-02-17 13:13:08 +00:00
|
|
|
public function textNoExceptionForUnrecognizedChildWithUnnamedChildren()
|
|
|
|
{
|
|
|
|
$node = new ArrayNode('root');
|
2011-02-18 12:49:51 +00:00
|
|
|
$node->setPreventExtraKeys(false);
|
2011-02-17 13:13:08 +00:00
|
|
|
$normalized = $node->normalize(array('foo' => 'bar'));
|
2011-02-18 12:49:51 +00:00
|
|
|
|
2011-02-17 13:13:08 +00:00
|
|
|
$this->assertEquals(array('foo' => 'bar'), $normalized);
|
|
|
|
}
|
2011-02-17 13:52:57 +00:00
|
|
|
|
|
|
|
// a remapped key (e.g. "mapping" -> "mappings") should be unset after being used
|
|
|
|
public function testRemappedKeysAreUnset()
|
|
|
|
{
|
|
|
|
$node = new ArrayNode('root');
|
2011-02-18 12:49:51 +00:00
|
|
|
$mappingsNode = new ArrayNode('mappings');
|
|
|
|
$mappingsNode->setPreventExtraKeys(false); // just so we can add anything to it
|
|
|
|
$node->addChild($mappingsNode);
|
2011-02-17 13:52:57 +00:00
|
|
|
|
|
|
|
$remappings = array();
|
|
|
|
$remappings[] = array('mapping', 'mappings');
|
|
|
|
$node->setXmlRemappings($remappings);
|
|
|
|
|
|
|
|
$normalized = $node->normalize(array('mapping' => array('foo', 'bar')));
|
|
|
|
$this->assertEquals(array('mappings' => array('foo', 'bar')), $normalized);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tests that when a key attribute is mapped, that key is removed from the array:
|
|
|
|
*
|
|
|
|
* <things>
|
|
|
|
* <option id="option1" value="foo">
|
|
|
|
* <option id="option2" value="bar">
|
|
|
|
* </things>
|
|
|
|
*
|
|
|
|
* The above should finally be mapped to an array that looks like this
|
|
|
|
* (because "id" is the key attribute).
|
|
|
|
*
|
|
|
|
* array(
|
|
|
|
* 'things' => array(
|
|
|
|
* 'option1' => 'foo',
|
|
|
|
* 'option2' => 'bar',
|
|
|
|
* )
|
|
|
|
* )
|
|
|
|
*/
|
|
|
|
public function testMappedAttributeKeyIsRemoved()
|
|
|
|
{
|
|
|
|
$node = new ArrayNode('root');
|
|
|
|
$node->setKeyAttribute('id');
|
|
|
|
|
|
|
|
$prototype = new ArrayNode(null);
|
2011-02-18 12:49:51 +00:00
|
|
|
$prototype->setPreventExtraKeys(false); // just so it allows anything
|
2011-02-17 13:52:57 +00:00
|
|
|
$node->setPrototype($prototype);
|
|
|
|
|
|
|
|
$children = array();
|
|
|
|
$children[] = array('id' => 'item_name', 'foo' => 'bar');
|
|
|
|
$normalized = $node->normalize($children);
|
|
|
|
|
|
|
|
$expected = array();
|
|
|
|
$expected['item_name'] = array('foo' => 'bar');
|
|
|
|
$this->assertEquals($expected, $normalized);
|
|
|
|
}
|
2011-02-18 13:15:59 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Tests the opposite of the testMappedAttributeKeyIsRemoved because
|
|
|
|
* the removal can be toggled with an option.
|
|
|
|
*/
|
|
|
|
public function testMappedAttributeKeyNotRemoved()
|
|
|
|
{
|
|
|
|
$node = new ArrayNode('root');
|
|
|
|
$node->setKeyAttribute('id');
|
2011-02-18 14:38:09 +00:00
|
|
|
$node->setRemoveKeyAttribute(false);
|
2011-02-18 13:15:59 +00:00
|
|
|
|
|
|
|
$prototype = new ArrayNode(null);
|
|
|
|
$prototype->setPreventExtraKeys(false); // just so it allows anything
|
|
|
|
$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);
|
|
|
|
}
|
2011-02-17 13:52:57 +00:00
|
|
|
}
|