1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Symfony\Component\Config\Definition;
13:
14: use Symfony\Component\Config\Definition\Exception\Exception;
15: use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException;
16: use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
17:
18: 19: 20: 21: 22:
23: abstract class BaseNode implements NodeInterface
24: {
25: protected $name;
26: protected $parent;
27: protected $normalizationClosures;
28: protected $finalValidationClosures;
29: protected $allowOverwrite;
30: protected $required;
31: protected $equivalentValues;
32: protected $attributes = array();
33:
34: 35: 36: 37: 38: 39: 40: 41:
42: public function __construct($name, NodeInterface $parent = null)
43: {
44: if (false !== strpos($name, '.')) {
45: throw new \InvalidArgumentException('The name must not contain ".".');
46: }
47:
48: $this->name = $name;
49: $this->parent = $parent;
50: $this->normalizationClosures = array();
51: $this->finalValidationClosures = array();
52: $this->allowOverwrite = true;
53: $this->required = false;
54: $this->equivalentValues = array();
55: }
56:
57: public function setAttribute($key, $value)
58: {
59: $this->attributes[$key] = $value;
60: }
61:
62: public function getAttribute($key, $default = null)
63: {
64: return isset($this->attributes[$key]) ? $this->attributes[$key] : $default;
65: }
66:
67: public function hasAttribute($key)
68: {
69: return isset($this->attributes[$key]);
70: }
71:
72: public function getAttributes()
73: {
74: return $this->attributes;
75: }
76:
77: public function setAttributes(array $attributes)
78: {
79: $this->attributes = $attributes;
80: }
81:
82: public function removeAttribute($key)
83: {
84: unset($this->attributes[$key]);
85: }
86:
87: 88: 89: 90: 91:
92: public function setInfo($info)
93: {
94: $this->setAttribute('info', $info);
95: }
96:
97: 98: 99: 100: 101:
102: public function getInfo()
103: {
104: return $this->getAttribute('info');
105: }
106:
107: 108: 109: 110: 111:
112: public function setExample($example)
113: {
114: $this->setAttribute('example', $example);
115: }
116:
117: 118: 119: 120: 121:
122: public function getExample()
123: {
124: return $this->getAttribute('example');
125: }
126:
127: 128: 129: 130: 131: 132:
133: public function addEquivalentValue($originalValue, $equivalentValue)
134: {
135: $this->equivalentValues[] = array($originalValue, $equivalentValue);
136: }
137:
138: 139: 140: 141: 142:
143: public function setRequired($boolean)
144: {
145: $this->required = (Boolean) $boolean;
146: }
147:
148: 149: 150: 151: 152:
153: public function setAllowOverwrite($allow)
154: {
155: $this->allowOverwrite = (Boolean) $allow;
156: }
157:
158: 159: 160: 161: 162:
163: public function setNormalizationClosures(array $closures)
164: {
165: $this->normalizationClosures = $closures;
166: }
167:
168: 169: 170: 171: 172:
173: public function setFinalValidationClosures(array $closures)
174: {
175: $this->finalValidationClosures = $closures;
176: }
177:
178: 179: 180: 181: 182:
183: public function isRequired()
184: {
185: return $this->required;
186: }
187:
188: 189: 190: 191: 192:
193: public function getName()
194: {
195: return $this->name;
196: }
197:
198: 199: 200: 201: 202:
203: public function getPath()
204: {
205: $path = $this->name;
206:
207: if (null !== $this->parent) {
208: $path = $this->parent->getPath().'.'.$path;
209: }
210:
211: return $path;
212: }
213:
214: 215: 216: 217: 218: 219: 220: 221: 222: 223:
224: final public function merge($leftSide, $rightSide)
225: {
226: if (!$this->allowOverwrite) {
227: throw new ForbiddenOverwriteException(sprintf(
228: 'Configuration path "%s" cannot be overwritten. You have to '
229: .'define all options for this path, and any of its sub-paths in '
230: .'one configuration section.',
231: $this->getPath()
232: ));
233: }
234:
235: $this->validateType($leftSide);
236: $this->validateType($rightSide);
237:
238: return $this->mergeValues($leftSide, $rightSide);
239: }
240:
241: 242: 243: 244: 245: 246: 247:
248: final public function normalize($value)
249: {
250: $value = $this->preNormalize($value);
251:
252:
253: foreach ($this->normalizationClosures as $closure) {
254: $value = $closure($value);
255: }
256:
257:
258: foreach ($this->equivalentValues as $data) {
259: if ($data[0] === $value) {
260: $value = $data[1];
261: }
262: }
263:
264:
265: $this->validateType($value);
266:
267:
268: return $this->normalizeValue($value);
269: }
270:
271: 272: 273: 274: 275: 276: 277:
278: protected function preNormalize($value)
279: {
280: return $value;
281: }
282:
283: 284: 285: 286: 287: 288: 289: 290: 291:
292: final public function finalize($value)
293: {
294: $this->validateType($value);
295:
296: $value = $this->finalizeValue($value);
297:
298:
299:
300: foreach ($this->finalValidationClosures as $closure) {
301: try {
302: $value = $closure($value);
303: } catch (Exception $correctEx) {
304: throw $correctEx;
305: } catch (\Exception $invalid) {
306: throw new InvalidConfigurationException(sprintf(
307: 'Invalid configuration for path "%s": %s',
308: $this->getPath(),
309: $invalid->getMessage()
310: ), $invalid->getCode(), $invalid);
311: }
312: }
313:
314: return $value;
315: }
316:
317: 318: 319: 320: 321: 322: 323:
324: abstract protected function validateType($value);
325:
326: 327: 328: 329: 330: 331: 332:
333: abstract protected function normalizeValue($value);
334:
335: 336: 337: 338: 339: 340: 341: 342:
343: abstract protected function mergeValues($leftSide, $rightSide);
344:
345: 346: 347: 348: 349: 350: 351:
352: abstract protected function finalizeValue($value);
353: }
354: