/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php

https://github.com/deviantintegral/symfony · PHP · 375 lines · 162 code · 48 blank · 165 comment · 9 complexity · 5d2f64436f228d2792947a86f3e8adb2 MD5 · raw file

  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\Definition\Builder;
  11. use Symfony\Component\Config\Definition\BaseNode;
  12. use Symfony\Component\Config\Definition\NodeInterface;
  13. use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
  14. /**
  15. * This class provides a fluent interface for defining a node.
  16. *
  17. * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  18. */
  19. abstract class NodeDefinition implements NodeParentInterface
  20. {
  21. protected $name;
  22. protected $normalization;
  23. protected $validation;
  24. protected $defaultValue;
  25. protected $default = false;
  26. protected $required = false;
  27. protected $deprecationMessage = null;
  28. protected $merge;
  29. protected $allowEmptyValue = true;
  30. protected $nullEquivalent;
  31. protected $trueEquivalent = true;
  32. protected $falseEquivalent = false;
  33. protected $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR;
  34. protected $parent;
  35. protected $attributes = array();
  36. public function __construct(?string $name, NodeParentInterface $parent = null)
  37. {
  38. $this->parent = $parent;
  39. $this->name = $name;
  40. }
  41. /**
  42. * Sets the parent node.
  43. *
  44. * @return $this
  45. */
  46. public function setParent(NodeParentInterface $parent)
  47. {
  48. $this->parent = $parent;
  49. return $this;
  50. }
  51. /**
  52. * Sets info message.
  53. *
  54. * @param string $info The info text
  55. *
  56. * @return $this
  57. */
  58. public function info($info)
  59. {
  60. return $this->attribute('info', $info);
  61. }
  62. /**
  63. * Sets example configuration.
  64. *
  65. * @param string|array $example
  66. *
  67. * @return $this
  68. */
  69. public function example($example)
  70. {
  71. return $this->attribute('example', $example);
  72. }
  73. /**
  74. * Sets an attribute on the node.
  75. *
  76. * @param string $key
  77. * @param mixed $value
  78. *
  79. * @return $this
  80. */
  81. public function attribute($key, $value)
  82. {
  83. $this->attributes[$key] = $value;
  84. return $this;
  85. }
  86. /**
  87. * Returns the parent node.
  88. *
  89. * @return NodeParentInterface|NodeBuilder|NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition|null The builder of the parent node
  90. */
  91. public function end()
  92. {
  93. return $this->parent;
  94. }
  95. /**
  96. * Creates the node.
  97. *
  98. * @param bool $forceRootNode Whether to force this node as the root node
  99. *
  100. * @return NodeInterface
  101. */
  102. public function getNode($forceRootNode = false)
  103. {
  104. if ($forceRootNode) {
  105. $this->parent = null;
  106. }
  107. if (null !== $this->normalization) {
  108. $this->normalization->before = ExprBuilder::buildExpressions($this->normalization->before);
  109. }
  110. if (null !== $this->validation) {
  111. $this->validation->rules = ExprBuilder::buildExpressions($this->validation->rules);
  112. }
  113. $node = $this->createNode();
  114. $node->setAttributes($this->attributes);
  115. return $node;
  116. }
  117. /**
  118. * Sets the default value.
  119. *
  120. * @param mixed $value The default value
  121. *
  122. * @return $this
  123. */
  124. public function defaultValue($value)
  125. {
  126. $this->default = true;
  127. $this->defaultValue = $value;
  128. return $this;
  129. }
  130. /**
  131. * Sets the node as required.
  132. *
  133. * @return $this
  134. */
  135. public function isRequired()
  136. {
  137. $this->required = true;
  138. return $this;
  139. }
  140. /**
  141. * Sets the node as deprecated.
  142. *
  143. * You can use %node% and %path% placeholders in your message to display,
  144. * respectively, the node name and its complete path.
  145. *
  146. * @param string $message Deprecation message
  147. *
  148. * @return $this
  149. */
  150. public function setDeprecated($message = 'The child node "%node%" at path "%path%" is deprecated.')
  151. {
  152. $this->deprecationMessage = $message;
  153. return $this;
  154. }
  155. /**
  156. * Sets the equivalent value used when the node contains null.
  157. *
  158. * @param mixed $value
  159. *
  160. * @return $this
  161. */
  162. public function treatNullLike($value)
  163. {
  164. $this->nullEquivalent = $value;
  165. return $this;
  166. }
  167. /**
  168. * Sets the equivalent value used when the node contains true.
  169. *
  170. * @param mixed $value
  171. *
  172. * @return $this
  173. */
  174. public function treatTrueLike($value)
  175. {
  176. $this->trueEquivalent = $value;
  177. return $this;
  178. }
  179. /**
  180. * Sets the equivalent value used when the node contains false.
  181. *
  182. * @param mixed $value
  183. *
  184. * @return $this
  185. */
  186. public function treatFalseLike($value)
  187. {
  188. $this->falseEquivalent = $value;
  189. return $this;
  190. }
  191. /**
  192. * Sets null as the default value.
  193. *
  194. * @return $this
  195. */
  196. public function defaultNull()
  197. {
  198. return $this->defaultValue(null);
  199. }
  200. /**
  201. * Sets true as the default value.
  202. *
  203. * @return $this
  204. */
  205. public function defaultTrue()
  206. {
  207. return $this->defaultValue(true);
  208. }
  209. /**
  210. * Sets false as the default value.
  211. *
  212. * @return $this
  213. */
  214. public function defaultFalse()
  215. {
  216. return $this->defaultValue(false);
  217. }
  218. /**
  219. * Sets an expression to run before the normalization.
  220. *
  221. * @return ExprBuilder
  222. */
  223. public function beforeNormalization()
  224. {
  225. return $this->normalization()->before();
  226. }
  227. /**
  228. * Denies the node value being empty.
  229. *
  230. * @return $this
  231. */
  232. public function cannotBeEmpty()
  233. {
  234. $this->allowEmptyValue = false;
  235. return $this;
  236. }
  237. /**
  238. * Sets an expression to run for the validation.
  239. *
  240. * The expression receives the value of the node and must return it. It can
  241. * modify it.
  242. * An exception should be thrown when the node is not valid.
  243. *
  244. * @return ExprBuilder
  245. */
  246. public function validate()
  247. {
  248. return $this->validation()->rule();
  249. }
  250. /**
  251. * Sets whether the node can be overwritten.
  252. *
  253. * @param bool $deny Whether the overwriting is forbidden or not
  254. *
  255. * @return $this
  256. */
  257. public function cannotBeOverwritten($deny = true)
  258. {
  259. $this->merge()->denyOverwrite($deny);
  260. return $this;
  261. }
  262. /**
  263. * Gets the builder for validation rules.
  264. *
  265. * @return ValidationBuilder
  266. */
  267. protected function validation()
  268. {
  269. if (null === $this->validation) {
  270. $this->validation = new ValidationBuilder($this);
  271. }
  272. return $this->validation;
  273. }
  274. /**
  275. * Gets the builder for merging rules.
  276. *
  277. * @return MergeBuilder
  278. */
  279. protected function merge()
  280. {
  281. if (null === $this->merge) {
  282. $this->merge = new MergeBuilder($this);
  283. }
  284. return $this->merge;
  285. }
  286. /**
  287. * Gets the builder for normalization rules.
  288. *
  289. * @return NormalizationBuilder
  290. */
  291. protected function normalization()
  292. {
  293. if (null === $this->normalization) {
  294. $this->normalization = new NormalizationBuilder($this);
  295. }
  296. return $this->normalization;
  297. }
  298. /**
  299. * Instantiate and configure the node according to this definition.
  300. *
  301. * @return NodeInterface $node The node instance
  302. *
  303. * @throws InvalidDefinitionException When the definition is invalid
  304. */
  305. abstract protected function createNode();
  306. /**
  307. * Set PathSeparator to use.
  308. *
  309. * @param string $separator
  310. *
  311. * @return $this
  312. */
  313. public function setPathSeparator(string $separator)
  314. {
  315. if ($this instanceof ParentNodeDefinitionInterface) {
  316. if (method_exists($this, 'getChildNodeDefinitions')) {
  317. foreach ($this->getChildNodeDefinitions() as $child) {
  318. $child->setPathSeparator($separator);
  319. }
  320. } else {
  321. @trigger_error('Passing a ParentNodeDefinitionInterface without getChildNodeDefinitions() is deprecated since Symfony 4.1.', E_USER_DEPRECATED);
  322. }
  323. }
  324. $this->pathSeparator = $separator;
  325. return $this;
  326. }
  327. }