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