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: use Symfony\Component\Config\Definition\Exception\UnsetKeyException;
14:
15: /**
16: * This class builds an if expression.
17: *
18: * @author Johannes M. Schmitt <schmittjoh@gmail.com>
19: * @author Christophe Coevoet <stof@notk.org>
20: */
21: class ExprBuilder
22: {
23: protected $node;
24: public $ifPart;
25: public $thenPart;
26:
27: /**
28: * Constructor
29: *
30: * @param NodeDefinition $node The related node
31: */
32: public function __construct(NodeDefinition $node)
33: {
34: $this->node = $node;
35: }
36:
37: /**
38: * Marks the expression as being always used.
39: *
40: * @param \Closure $then
41: *
42: * @return ExprBuilder
43: */
44: public function always(\Closure $then = null)
45: {
46: $this->ifPart = function($v) { return true; };
47:
48: if (null !== $then) {
49: $this->thenPart = $then;
50: }
51:
52: return $this;
53: }
54:
55: /**
56: * Sets a closure to use as tests.
57: *
58: * The default one tests if the value is true.
59: *
60: * @param \Closure $closure
61: *
62: * @return ExprBuilder
63: */
64: public function ifTrue(\Closure $closure = null)
65: {
66: if (null === $closure) {
67: $closure = function($v) { return true === $v; };
68: }
69:
70: $this->ifPart = $closure;
71:
72: return $this;
73: }
74:
75: /**
76: * Tests if the value is a string.
77: *
78: * @return ExprBuilder
79: */
80: public function ifString()
81: {
82: $this->ifPart = function($v) { return is_string($v); };
83:
84: return $this;
85: }
86:
87: /**
88: * Tests if the value is null.
89: *
90: * @return ExprBuilder
91: */
92: public function ifNull()
93: {
94: $this->ifPart = function($v) { return null === $v; };
95:
96: return $this;
97: }
98:
99: /**
100: * Tests if the value is an array.
101: *
102: * @return ExprBuilder
103: */
104: public function ifArray()
105: {
106: $this->ifPart = function($v) { return is_array($v); };
107:
108: return $this;
109: }
110:
111: /**
112: * Tests if the value is in an array.
113: *
114: * @param array $array
115: *
116: * @return ExprBuilder
117: */
118: public function ifInArray(array $array)
119: {
120: $this->ifPart = function($v) use ($array) { return in_array($v, $array, true); };
121:
122: return $this;
123: }
124:
125: /**
126: * Tests if the value is not in an array.
127: *
128: * @param array $array
129: *
130: * @return ExprBuilder
131: */
132: public function ifNotInArray(array $array)
133: {
134: $this->ifPart = function($v) use ($array) { return !in_array($v, $array, true); };
135:
136: return $this;
137: }
138:
139: /**
140: * Sets the closure to run if the test pass.
141: *
142: * @param \Closure $closure
143: *
144: * @return ExprBuilder
145: */
146: public function then(\Closure $closure)
147: {
148: $this->thenPart = $closure;
149:
150: return $this;
151: }
152:
153: /**
154: * Sets a closure returning an empty array.
155: *
156: * @return ExprBuilder
157: */
158: public function thenEmptyArray()
159: {
160: $this->thenPart = function($v) { return array(); };
161:
162: return $this;
163: }
164:
165: /**
166: * Sets a closure marking the value as invalid at validation time.
167: *
168: * if you want to add the value of the node in your message just use a %s placeholder.
169: *
170: * @param string $message
171: *
172: * @return ExprBuilder
173: *
174: * @throws \InvalidArgumentException
175: */
176: public function thenInvalid($message)
177: {
178: $this->thenPart = function ($v) use ($message) {throw new \InvalidArgumentException(sprintf($message, json_encode($v))); };
179:
180: return $this;
181: }
182:
183: /**
184: * Sets a closure unsetting this key of the array at validation time.
185: *
186: * @return ExprBuilder
187: *
188: * @throws UnsetKeyException
189: */
190: public function thenUnset()
191: {
192: $this->thenPart = function ($v) { throw new UnsetKeyException('Unsetting key'); };
193:
194: return $this;
195: }
196:
197: /**
198: * Returns the related node
199: *
200: * @return NodeDefinition
201: *
202: * @throws \RuntimeException
203: */
204: public function end()
205: {
206: if (null === $this->ifPart) {
207: throw new \RuntimeException('You must specify an if part.');
208: }
209: if (null === $this->thenPart) {
210: throw new \RuntimeException('You must specify a then part.');
211: }
212:
213: return $this->node;
214: }
215:
216: /**
217: * Builds the expressions.
218: *
219: * @param ExprBuilder[] $expressions An array of ExprBuilder instances to build
220: *
221: * @return array
222: */
223: public static function buildExpressions(array $expressions)
224: {
225: foreach ($expressions as $k => $expr) {
226: if ($expr instanceof ExprBuilder) {
227: $expressions[$k] = function($v) use ($expr) {
228: return call_user_func($expr->ifPart, $v) ? call_user_func($expr->thenPart, $v) : $v;
229: };
230: }
231: }
232:
233: return $expressions;
234: }
235: }
236: