NodeBuilder.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien.potencier@symfony-project.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\Definition\Builder;
  11. /**
  12. * This class provides a fluent interface for building a config tree.
  13. *
  14. * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  15. */
  16. class NodeBuilder
  17. {
  18. /************
  19. * READ-ONLY
  20. ************/
  21. public $name;
  22. public $type;
  23. public $key;
  24. public $removeKeyItem;
  25. public $parent;
  26. public $children;
  27. public $prototype;
  28. public $normalization;
  29. public $validation;
  30. public $merge;
  31. public $finalization;
  32. public $defaultValue;
  33. public $default;
  34. public $addDefaults;
  35. public $required;
  36. public $atLeastOne;
  37. public $allowNewKeys;
  38. public $allowEmptyValue;
  39. public $nullEquivalent;
  40. public $trueEquivalent;
  41. public $falseEquivalent;
  42. public $performDeepMerging;
  43. public $ignoreExtraKeys;
  44. /**
  45. * Constructor
  46. *
  47. * @param string $name the name of the node
  48. * @param string $type The type of the node
  49. * @param NodeBuilder $parent
  50. */
  51. public function __construct($name, $type, $parent = null)
  52. {
  53. $this->name = $name;
  54. $this->type = $type;
  55. $this->parent = $parent;
  56. $this->default = false;
  57. $this->required = false;
  58. $this->addDefaults = false;
  59. $this->allowNewKeys = true;
  60. $this->atLeastOne = false;
  61. $this->allowEmptyValue = true;
  62. $this->children = array();
  63. $this->performDeepMerging = true;
  64. if ('boolean' === $type) {
  65. $this->nullEquivalent = true;
  66. } else if ('array' === $type) {
  67. $this->nullEquivalent = array();
  68. }
  69. if ('array' === $type) {
  70. $this->trueEquivalent = array();
  71. } else {
  72. $this->trueEquivalent = true;
  73. }
  74. $this->falseEquivalent = false;
  75. }
  76. /****************************
  77. * FLUID INTERFACE
  78. ****************************/
  79. /**
  80. * Creates a child node.
  81. *
  82. * @param string $name The name of the node
  83. * @param string $type The type of the node
  84. *
  85. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder The builder of the child node
  86. */
  87. public function node($name, $type)
  88. {
  89. $node = new static($name, $type, $this);
  90. return $this->children[$name] = $node;
  91. }
  92. /**
  93. * Add a NodeBuilder instance directly.
  94. *
  95. * This helps achieve a fluid interface when a method on your Configuration
  96. * class returns a pre-build NodeBuilder instance on your behalf:
  97. *
  98. * $root = new NodeBuilder();
  99. * ->node('foo', 'scalar')
  100. * ->addNodeBuilder($this->getBarNodeBuilder())
  101. * ->node('baz', 'scalar')
  102. * ;
  103. *
  104. * @return Symfony\Component\DependencyInjection\Configuration\Builder\NodeBuilder This builder node
  105. */
  106. public function builder(NodeBuilder $node)
  107. {
  108. $node->parent = $this;
  109. $this->children[$node->name] = $node;
  110. return $this;
  111. }
  112. /**
  113. * Creates a child array node
  114. *
  115. * @param string $name The name of the node
  116. *
  117. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder The builder of the child node
  118. */
  119. public function arrayNode($name)
  120. {
  121. return $this->node($name, 'array');
  122. }
  123. /**
  124. * Creates a child scalar node.
  125. *
  126. * @param string $name the name of the node
  127. *
  128. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder The builder of the child node
  129. */
  130. public function scalarNode($name)
  131. {
  132. return $this->node($name, 'scalar');
  133. }
  134. /**
  135. * Creates a child Boolean node.
  136. *
  137. * @param string $name The name of the node
  138. *
  139. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder The builder of the child node
  140. */
  141. public function booleanNode($name)
  142. {
  143. return $this->node($name, 'boolean');
  144. }
  145. /**
  146. * Creates a child variable node.
  147. *
  148. * @param string $name The name of the node
  149. *
  150. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder The builder of the child node
  151. */
  152. public function variableNode($name)
  153. {
  154. return $this->node($name, 'variable');
  155. }
  156. /**
  157. * Sets the default value.
  158. *
  159. * @param mixed $value The default value
  160. *
  161. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  162. */
  163. public function defaultValue($value)
  164. {
  165. $this->default = true;
  166. $this->defaultValue = $value;
  167. return $this;
  168. }
  169. /**
  170. * Sets the node as required.
  171. *
  172. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  173. */
  174. public function isRequired()
  175. {
  176. $this->required = true;
  177. return $this;
  178. }
  179. /**
  180. * Requires the node to have at least one element.
  181. *
  182. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  183. */
  184. public function requiresAtLeastOneElement()
  185. {
  186. $this->atLeastOne = true;
  187. return $this;
  188. }
  189. /**
  190. * Sets the equivalent value used when the node contains null.
  191. *
  192. * @param mixed $value
  193. *
  194. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  195. */
  196. public function treatNullLike($value)
  197. {
  198. $this->nullEquivalent = $value;
  199. return $this;
  200. }
  201. /**
  202. * Sets the equivalent value used when the node contains true.
  203. *
  204. * @param mixed $value
  205. *
  206. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  207. */
  208. public function treatTrueLike($value)
  209. {
  210. $this->trueEquivalent = $value;
  211. return $this;
  212. }
  213. /**
  214. * Sets the equivalent value used when the node contains false.
  215. *
  216. * @param mixed $value
  217. *
  218. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  219. */
  220. public function treatFalseLike($value)
  221. {
  222. $this->falseEquivalent = $value;
  223. return $this;
  224. }
  225. /**
  226. * Sets null as the default value.
  227. *
  228. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  229. */
  230. public function defaultNull()
  231. {
  232. return $this->defaultValue(null);
  233. }
  234. /**
  235. * Sets true as the default value.
  236. *
  237. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  238. */
  239. public function defaultTrue()
  240. {
  241. return $this->defaultValue(true);
  242. }
  243. /**
  244. * Sets false as the default value.
  245. *
  246. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  247. */
  248. public function defaultFalse()
  249. {
  250. return $this->defaultValue(false);
  251. }
  252. /**
  253. * Adds the default value if the node is not set in the configuration.
  254. *
  255. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  256. */
  257. public function addDefaultsIfNotSet()
  258. {
  259. $this->addDefaults = true;
  260. return $this;
  261. }
  262. /**
  263. * Disallows adding news keys in a subsequent configuration.
  264. *
  265. * If used all keys have to be defined in the same configuration file.
  266. *
  267. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  268. */
  269. public function disallowNewKeysInSubsequentConfigs()
  270. {
  271. $this->allowNewKeys = false;
  272. return $this;
  273. }
  274. /**
  275. * Gets the builder for normalization rules.
  276. *
  277. * @return Symfony\Component\Config\Definition\Builder\NormalizationBuilder
  278. */
  279. protected function normalization()
  280. {
  281. if (null === $this->normalization) {
  282. $this->normalization = new NormalizationBuilder($this);
  283. }
  284. return $this->normalization;
  285. }
  286. /**
  287. * Sets an expression to run before the normalization.
  288. *
  289. * @return Symfony\Component\Config\Definition\Builder\ExprBuilder
  290. */
  291. public function beforeNormalization()
  292. {
  293. return $this->normalization()->before();
  294. }
  295. /**
  296. * Sets a normalization rule for XML configurations.
  297. *
  298. * @param string $singular The key to remap
  299. * @param string $plural The plural of the key for irregular plurals
  300. *
  301. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  302. */
  303. public function fixXmlConfig($singular, $plural = null)
  304. {
  305. $this->normalization()->remap($singular, $plural);
  306. return $this;
  307. }
  308. /**
  309. * Set the attribute which value is to be used as key.
  310. *
  311. * This is useful when you have an indexed array that should be an
  312. * associative array. You can select an item from within the array
  313. * to be the key of the particular item. For example, if "id" is the
  314. * "key", then:
  315. *
  316. * array(
  317. * array('id' => 'my_name', 'foo' => 'bar'),
  318. * )
  319. *
  320. * becomes
  321. *
  322. * array(
  323. * 'my_name' => array('foo' => 'bar'),
  324. * )
  325. *
  326. * If you'd like "'id' => 'my_name'" to still be present in the resulting
  327. * array, then you can set the second argument of this method to false.
  328. *
  329. * @param string $name The name of the key
  330. * @param Boolean $removeKeyItem Whether or not the key item should be removed.
  331. *
  332. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  333. */
  334. public function useAttributeAsKey($name, $removeKeyItem = true)
  335. {
  336. $this->key = $name;
  337. $this->removeKeyItem = $removeKeyItem;
  338. return $this;
  339. }
  340. /**
  341. * Gets the builder for merging rules.
  342. *
  343. * @return Symfony\Component\Config\Definition\Builder\MergeBuilder
  344. */
  345. protected function merge()
  346. {
  347. if (null === $this->merge) {
  348. $this->merge = new MergeBuilder($this);
  349. }
  350. return $this->merge;
  351. }
  352. /**
  353. * Sets whether the node can be overwritten.
  354. *
  355. * @param Boolean $deny Whether the overwriting is forbidden or not
  356. *
  357. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  358. */
  359. public function cannotBeOverwritten($deny = true)
  360. {
  361. $this->merge()->denyOverwrite($deny);
  362. return $this;
  363. }
  364. /**
  365. * Denies the node value being empty.
  366. *
  367. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  368. */
  369. public function cannotBeEmpty()
  370. {
  371. $this->allowEmptyValue = false;
  372. return $this;
  373. }
  374. /**
  375. * Sets whether the node can be unset.
  376. *
  377. * @param Boolean $allow
  378. *
  379. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  380. */
  381. public function canBeUnset($allow = true)
  382. {
  383. $this->merge()->allowUnset($allow);
  384. return $this;
  385. }
  386. /**
  387. * Sets a prototype for child nodes.
  388. *
  389. * @param string $type the type of node
  390. *
  391. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  392. */
  393. public function prototype($type)
  394. {
  395. return $this->prototype = new static(null, $type, $this);
  396. }
  397. /**
  398. * Disables the deep merging of the node.
  399. *
  400. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  401. */
  402. public function performNoDeepMerging()
  403. {
  404. $this->performDeepMerging = false;
  405. return $this;
  406. }
  407. /**
  408. * Gets the builder for validation rules.
  409. *
  410. * @return Symfony\Component\Config\Definition\Builder\ValidationBuilder
  411. */
  412. protected function validation()
  413. {
  414. if (null === $this->validation) {
  415. $this->validation = new ValidationBuilder($this);
  416. }
  417. return $this->validation;
  418. }
  419. /**
  420. * Sets an expression to run for the validation.
  421. *
  422. * The expression receives the value of the node and must return it. It can
  423. * modify it.
  424. * An exception should be thrown when the node is not valid.
  425. *
  426. * @return Symfony\Component\Config\Definition\Builder\ExprBuilder
  427. */
  428. public function validate()
  429. {
  430. return $this->validation()->rule();
  431. }
  432. /**
  433. * Returns the parent node.
  434. *
  435. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  436. */
  437. public function end()
  438. {
  439. return $this->parent;
  440. }
  441. /**
  442. * Allows extra config keys to be specified under an array without
  443. * throwing an exception.
  444. *
  445. * Those config values are simply ignored. This should be used only
  446. * in special cases where you want to send an entire configuration
  447. * array through a special tree that processes only part of the array.
  448. *
  449. * @return Symfony\Component\Config\Definition\Builder\NodeBuilder
  450. */
  451. public function ignoreExtraKeys()
  452. {
  453. $this->ignoreExtraKeys = true;
  454. return $this;
  455. }
  456. }