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: /**
15: * This class provides a fluent interface for building a node.
16: *
17: * @author Johannes M. Schmitt <schmittjoh@gmail.com>
18: */
19: class NodeBuilder implements NodeParentInterface
20: {
21: protected $parent;
22: protected $nodeMapping;
23:
24: /**
25: * Constructor
26: *
27: */
28: public function __construct()
29: {
30: $this->nodeMapping = array(
31: 'variable' => __NAMESPACE__.'\\VariableNodeDefinition',
32: 'scalar' => __NAMESPACE__.'\\ScalarNodeDefinition',
33: 'boolean' => __NAMESPACE__.'\\BooleanNodeDefinition',
34: 'integer' => __NAMESPACE__.'\\IntegerNodeDefinition',
35: 'float' => __NAMESPACE__.'\\FloatNodeDefinition',
36: 'array' => __NAMESPACE__.'\\ArrayNodeDefinition',
37: 'enum' => __NAMESPACE__.'\\EnumNodeDefinition',
38: );
39: }
40:
41: /**
42: * Set the parent node.
43: *
44: * @param ParentNodeDefinitionInterface $parent The parent node
45: *
46: * @return NodeBuilder This node builder
47: */
48: public function setParent(ParentNodeDefinitionInterface $parent = null)
49: {
50: $this->parent = $parent;
51:
52: return $this;
53: }
54:
55: /**
56: * Creates a child array node.
57: *
58: * @param string $name The name of the node
59: *
60: * @return ArrayNodeDefinition The child node
61: */
62: public function arrayNode($name)
63: {
64: return $this->node($name, 'array');
65: }
66:
67: /**
68: * Creates a child scalar node.
69: *
70: * @param string $name the name of the node
71: *
72: * @return ScalarNodeDefinition The child node
73: */
74: public function scalarNode($name)
75: {
76: return $this->node($name, 'scalar');
77: }
78:
79: /**
80: * Creates a child Boolean node.
81: *
82: * @param string $name The name of the node
83: *
84: * @return BooleanNodeDefinition The child node
85: */
86: public function booleanNode($name)
87: {
88: return $this->node($name, 'boolean');
89: }
90:
91: /**
92: * Creates a child integer node.
93: *
94: * @param string $name the name of the node
95: *
96: * @return IntegerNodeDefinition The child node
97: */
98: public function integerNode($name)
99: {
100: return $this->node($name, 'integer');
101: }
102:
103: /**
104: * Creates a child float node.
105: *
106: * @param string $name the name of the node
107: *
108: * @return FloatNodeDefinition The child node
109: */
110: public function floatNode($name)
111: {
112: return $this->node($name, 'float');
113: }
114:
115: /**
116: * Creates a child EnumNode.
117: *
118: * @param string $name
119: *
120: * @return EnumNodeDefinition
121: */
122: public function enumNode($name)
123: {
124: return $this->node($name, 'enum');
125: }
126:
127: /**
128: * Creates a child variable node.
129: *
130: * @param string $name The name of the node
131: *
132: * @return VariableNodeDefinition The builder of the child node
133: */
134: public function variableNode($name)
135: {
136: return $this->node($name, 'variable');
137: }
138:
139: /**
140: * Returns the parent node.
141: *
142: * @return ParentNodeDefinitionInterface The parent node
143: */
144: public function end()
145: {
146: return $this->parent;
147: }
148:
149: /**
150: * Creates a child node.
151: *
152: * @param string $name The name of the node
153: * @param string $type The type of the node
154: *
155: * @return NodeDefinition The child node
156: *
157: * @throws \RuntimeException When the node type is not registered
158: * @throws \RuntimeException When the node class is not found
159: */
160: public function node($name, $type)
161: {
162: $class = $this->getNodeClass($type);
163:
164: $node = new $class($name);
165:
166: $this->append($node);
167:
168: return $node;
169: }
170:
171: /**
172: * Appends a node definition.
173: *
174: * Usage:
175: *
176: * $node = new ArrayNodeDefinition('name')
177: * ->children()
178: * ->scalarNode('foo')->end()
179: * ->scalarNode('baz')->end()
180: * ->append($this->getBarNodeDefinition())
181: * ->end()
182: * ;
183: *
184: * @param NodeDefinition $node
185: *
186: * @return NodeBuilder This node builder
187: */
188: public function append(NodeDefinition $node)
189: {
190: if ($node instanceof ParentNodeDefinitionInterface) {
191: $builder = clone $this;
192: $builder->setParent(null);
193: $node->setBuilder($builder);
194: }
195:
196: if (null !== $this->parent) {
197: $this->parent->append($node);
198: // Make this builder the node parent to allow for a fluid interface
199: $node->setParent($this);
200: }
201:
202: return $this;
203: }
204:
205: /**
206: * Adds or overrides a node Type.
207: *
208: * @param string $type The name of the type
209: * @param string $class The fully qualified name the node definition class
210: *
211: * @return NodeBuilder This node builder
212: */
213: public function setNodeClass($type, $class)
214: {
215: $this->nodeMapping[strtolower($type)] = $class;
216:
217: return $this;
218: }
219:
220: /**
221: * Returns the class name of the node definition.
222: *
223: * @param string $type The node type
224: *
225: * @return string The node definition class name
226: *
227: * @throws \RuntimeException When the node type is not registered
228: * @throws \RuntimeException When the node class is not found
229: */
230: protected function getNodeClass($type)
231: {
232: $type = strtolower($type);
233:
234: if (!isset($this->nodeMapping[$type])) {
235: throw new \RuntimeException(sprintf('The node type "%s" is not registered.', $type));
236: }
237:
238: $class = $this->nodeMapping[$type];
239:
240: if (!class_exists($class)) {
241: throw new \RuntimeException(sprintf('The node class "%s" does not exist.', $class));
242: }
243:
244: return $class;
245: }
246:
247: }
248: