ArrayNodeDefinitionTest.php 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Config\Tests\Definition\Builder;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
  13. use Symfony\Component\Config\Definition\Builder\ScalarNodeDefinition;
  14. use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
  15. use Symfony\Component\Config\Definition\Processor;
  16. class ArrayNodeDefinitionTest extends TestCase
  17. {
  18. public function testAppendingSomeNode()
  19. {
  20. $parent = new ArrayNodeDefinition('root');
  21. $child = new ScalarNodeDefinition('child');
  22. $parent
  23. ->children()
  24. ->scalarNode('foo')->end()
  25. ->scalarNode('bar')->end()
  26. ->end()
  27. ->append($child);
  28. $this->assertCount(3, $this->getField($parent, 'children'));
  29. $this->assertContains($child, $this->getField($parent, 'children'));
  30. }
  31. /**
  32. * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException
  33. * @dataProvider providePrototypeNodeSpecificCalls
  34. */
  35. public function testPrototypeNodeSpecificOption($method, $args)
  36. {
  37. $node = new ArrayNodeDefinition('root');
  38. \call_user_func_array(array($node, $method), $args);
  39. $node->getNode();
  40. }
  41. public function providePrototypeNodeSpecificCalls()
  42. {
  43. return array(
  44. array('defaultValue', array(array())),
  45. array('addDefaultChildrenIfNoneSet', array()),
  46. array('requiresAtLeastOneElement', array()),
  47. array('useAttributeAsKey', array('foo')),
  48. );
  49. }
  50. /**
  51. * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException
  52. */
  53. public function testConcreteNodeSpecificOption()
  54. {
  55. $node = new ArrayNodeDefinition('root');
  56. $node
  57. ->addDefaultsIfNotSet()
  58. ->prototype('array')
  59. ;
  60. $node->getNode();
  61. }
  62. /**
  63. * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException
  64. */
  65. public function testPrototypeNodesCantHaveADefaultValueWhenUsingDefaultChildren()
  66. {
  67. $node = new ArrayNodeDefinition('root');
  68. $node
  69. ->defaultValue(array())
  70. ->addDefaultChildrenIfNoneSet('foo')
  71. ->prototype('array')
  72. ;
  73. $node->getNode();
  74. }
  75. public function testPrototypedArrayNodeDefaultWhenUsingDefaultChildren()
  76. {
  77. $node = new ArrayNodeDefinition('root');
  78. $node
  79. ->addDefaultChildrenIfNoneSet()
  80. ->prototype('array')
  81. ;
  82. $tree = $node->getNode();
  83. $this->assertEquals(array(array()), $tree->getDefaultValue());
  84. }
  85. /**
  86. * @dataProvider providePrototypedArrayNodeDefaults
  87. */
  88. public function testPrototypedArrayNodeDefault($args, $shouldThrowWhenUsingAttrAsKey, $shouldThrowWhenNotUsingAttrAsKey, $defaults)
  89. {
  90. $node = new ArrayNodeDefinition('root');
  91. $node
  92. ->addDefaultChildrenIfNoneSet($args)
  93. ->prototype('array')
  94. ;
  95. try {
  96. $tree = $node->getNode();
  97. $this->assertFalse($shouldThrowWhenNotUsingAttrAsKey);
  98. $this->assertEquals($defaults, $tree->getDefaultValue());
  99. } catch (InvalidDefinitionException $e) {
  100. $this->assertTrue($shouldThrowWhenNotUsingAttrAsKey);
  101. }
  102. $node = new ArrayNodeDefinition('root');
  103. $node
  104. ->useAttributeAsKey('attr')
  105. ->addDefaultChildrenIfNoneSet($args)
  106. ->prototype('array')
  107. ;
  108. try {
  109. $tree = $node->getNode();
  110. $this->assertFalse($shouldThrowWhenUsingAttrAsKey);
  111. $this->assertEquals($defaults, $tree->getDefaultValue());
  112. } catch (InvalidDefinitionException $e) {
  113. $this->assertTrue($shouldThrowWhenUsingAttrAsKey);
  114. }
  115. }
  116. public function providePrototypedArrayNodeDefaults()
  117. {
  118. return array(
  119. array(null, true, false, array(array())),
  120. array(2, true, false, array(array(), array())),
  121. array('2', false, true, array('2' => array())),
  122. array('foo', false, true, array('foo' => array())),
  123. array(array('foo'), false, true, array('foo' => array())),
  124. array(array('foo', 'bar'), false, true, array('foo' => array(), 'bar' => array())),
  125. );
  126. }
  127. public function testNestedPrototypedArrayNodes()
  128. {
  129. $nodeDefinition = new ArrayNodeDefinition('root');
  130. $nodeDefinition
  131. ->addDefaultChildrenIfNoneSet()
  132. ->prototype('array')
  133. ->prototype('array')
  134. ;
  135. $node = $nodeDefinition->getNode();
  136. $this->assertInstanceOf('Symfony\Component\Config\Definition\PrototypedArrayNode', $node);
  137. $this->assertInstanceOf('Symfony\Component\Config\Definition\PrototypedArrayNode', $node->getPrototype());
  138. }
  139. public function testEnabledNodeDefaults()
  140. {
  141. $node = new ArrayNodeDefinition('root');
  142. $node
  143. ->canBeEnabled()
  144. ->children()
  145. ->scalarNode('foo')->defaultValue('bar')->end()
  146. ;
  147. $this->assertEquals(array('enabled' => false, 'foo' => 'bar'), $node->getNode()->getDefaultValue());
  148. }
  149. /**
  150. * @dataProvider getEnableableNodeFixtures
  151. */
  152. public function testTrueEnableEnabledNode($expected, $config, $message)
  153. {
  154. $processor = new Processor();
  155. $node = new ArrayNodeDefinition('root');
  156. $node
  157. ->canBeEnabled()
  158. ->children()
  159. ->scalarNode('foo')->defaultValue('bar')->end()
  160. ;
  161. $this->assertEquals(
  162. $expected,
  163. $processor->process($node->getNode(), $config),
  164. $message
  165. );
  166. }
  167. public function testCanBeDisabled()
  168. {
  169. $node = new ArrayNodeDefinition('root');
  170. $node->canBeDisabled();
  171. $this->assertTrue($this->getField($node, 'addDefaults'));
  172. $this->assertEquals(array('enabled' => false), $this->getField($node, 'falseEquivalent'));
  173. $this->assertEquals(array('enabled' => true), $this->getField($node, 'trueEquivalent'));
  174. $this->assertEquals(array('enabled' => true), $this->getField($node, 'nullEquivalent'));
  175. $nodeChildren = $this->getField($node, 'children');
  176. $this->assertArrayHasKey('enabled', $nodeChildren);
  177. $enabledNode = $nodeChildren['enabled'];
  178. $this->assertTrue($this->getField($enabledNode, 'default'));
  179. $this->assertTrue($this->getField($enabledNode, 'defaultValue'));
  180. }
  181. public function testIgnoreExtraKeys()
  182. {
  183. $node = new ArrayNodeDefinition('root');
  184. $this->assertFalse($this->getField($node, 'ignoreExtraKeys'));
  185. $result = $node->ignoreExtraKeys();
  186. $this->assertEquals($node, $result);
  187. $this->assertTrue($this->getField($node, 'ignoreExtraKeys'));
  188. }
  189. public function testNormalizeKeys()
  190. {
  191. $node = new ArrayNodeDefinition('root');
  192. $this->assertTrue($this->getField($node, 'normalizeKeys'));
  193. $result = $node->normalizeKeys(false);
  194. $this->assertEquals($node, $result);
  195. $this->assertFalse($this->getField($node, 'normalizeKeys'));
  196. }
  197. public function testUnsetChild()
  198. {
  199. $node = new ArrayNodeDefinition('root');
  200. $node
  201. ->children()
  202. ->scalarNode('value')
  203. ->beforeNormalization()
  204. ->ifTrue(function ($value) {
  205. return empty($value);
  206. })
  207. ->thenUnset()
  208. ->end()
  209. ->end()
  210. ->end()
  211. ;
  212. $this->assertSame(array(), $node->getNode()->normalize(array('value' => null)));
  213. }
  214. public function getEnableableNodeFixtures()
  215. {
  216. return array(
  217. array(array('enabled' => true, 'foo' => 'bar'), array(true), 'true enables an enableable node'),
  218. array(array('enabled' => true, 'foo' => 'bar'), array(null), 'null enables an enableable node'),
  219. array(array('enabled' => true, 'foo' => 'bar'), array(array('enabled' => true)), 'An enableable node can be enabled'),
  220. array(array('enabled' => true, 'foo' => 'baz'), array(array('foo' => 'baz')), 'any configuration enables an enableable node'),
  221. array(array('enabled' => false, 'foo' => 'baz'), array(array('foo' => 'baz', 'enabled' => false)), 'An enableable node can be disabled'),
  222. array(array('enabled' => false, 'foo' => 'bar'), array(false), 'false disables an enableable node'),
  223. );
  224. }
  225. protected function getField($object, $field)
  226. {
  227. $reflection = new \ReflectionProperty($object, $field);
  228. $reflection->setAccessible(true);
  229. return $reflection->getValue($object);
  230. }
  231. }