1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Forms;
9:
10: use Nette;
11:
12:
13: 14: 15:
16: class Rules extends Nette\Object implements \IteratorAggregate
17: {
18:
19: public static $defaultMessages;
20:
21:
22: private $required;
23:
24:
25: private $rules = array();
26:
27:
28: private $parent;
29:
30:
31: private $toggles = array();
32:
33:
34: private $control;
35:
36:
37: public function __construct(IControl $control)
38: {
39: $this->control = $control;
40: }
41:
42:
43: 44: 45: 46: 47:
48: public function setRequired($value = TRUE)
49: {
50: if ($value) {
51: $this->addRule(Form::REQUIRED, is_string($value) ? $value : NULL);
52: } else {
53: $this->required = NULL;
54: }
55: return $this;
56: }
57:
58:
59: 60: 61: 62:
63: public function isRequired()
64: {
65: return $this->required instanceof Rule ? !$this->required->isNegative : FALSE;
66: }
67:
68:
69: 70: 71: 72: 73: 74: 75:
76: public function addRule($validator, $message = NULL, $arg = NULL)
77: {
78: $rule = new Rule;
79: $rule->control = $this->control;
80: $rule->validator = $validator;
81: $this->adjustOperation($rule);
82: $rule->arg = $arg;
83: $rule->message = $message;
84: if ($rule->validator === Form::REQUIRED) {
85: $this->required = $rule;
86: } else {
87: $this->rules[] = $rule;
88: }
89: return $this;
90: }
91:
92:
93: 94: 95: 96: 97: 98:
99: public function addCondition($validator, $arg = NULL)
100: {
101: return $this->addConditionOn($this->control, $validator, $arg);
102: }
103:
104:
105: 106: 107: 108: 109: 110: 111:
112: public function addConditionOn(IControl $control, $validator, $arg = NULL)
113: {
114: $rule = new Rule;
115: $rule->control = $control;
116: $rule->validator = $validator;
117: $this->adjustOperation($rule);
118: $rule->arg = $arg;
119: $rule->branch = new static($this->control);
120: $rule->branch->parent = $this;
121:
122: $this->rules[] = $rule;
123: return $rule->branch;
124: }
125:
126:
127: 128: 129: 130:
131: public function elseCondition()
132: {
133: $rule = clone end($this->parent->rules);
134: $rule->isNegative = !$rule->isNegative;
135: $rule->branch = new static($this->parent->control);
136: $rule->branch->parent = $this->parent;
137: $this->parent->rules[] = $rule;
138: return $rule->branch;
139: }
140:
141:
142: 143: 144: 145:
146: public function endCondition()
147: {
148: return $this->parent;
149: }
150:
151:
152: 153: 154: 155: 156:
157: public function addFilter($filter)
158: {
159: Nette\Utils\Callback::check($filter);
160: $this->rules[] = $rule = new Rule;
161: $rule->control = $this->control;
162: $rule->validator = function (IControl $control) use ($filter) {
163: $control->setValue(call_user_func($filter, $control->getValue()));
164: return TRUE;
165: };
166: return $this;
167: }
168:
169:
170: 171: 172: 173: 174: 175:
176: public function toggle($id, $hide = TRUE)
177: {
178: $this->toggles[$id] = $hide;
179: return $this;
180: }
181:
182:
183: 184: 185: 186:
187: public function getToggles($actual = FALSE)
188: {
189: return $actual ? $this->getToggleStates() : $this->toggles;
190: }
191:
192:
193: 194: 195: 196:
197: public function getToggleStates($toggles = array(), $success = TRUE)
198: {
199: foreach ($this->toggles as $id => $hide) {
200: $toggles[$id] = ($success xor !$hide) || !empty($toggles[$id]);
201: }
202:
203: foreach ($this as $rule) {
204: if ($rule->branch) {
205: $toggles = $rule->branch->getToggleStates($toggles, $success && static::validateRule($rule));
206: }
207: }
208: return $toggles;
209: }
210:
211:
212: 213: 214: 215:
216: public function validate()
217: {
218: foreach ($this as $rule) {
219: $success = $this->validateRule($rule);
220:
221: if ($success && $rule->branch && !$rule->branch->validate()) {
222: return FALSE;
223:
224: } elseif (!$success && !$rule->branch) {
225: $rule->control->addError(Validator::formatMessage($rule, TRUE));
226: return FALSE;
227: }
228: }
229: return TRUE;
230: }
231:
232:
233: 234: 235: 236:
237: public static function validateRule(Rule $rule)
238: {
239: $args = is_array($rule->arg) ? $rule->arg : array($rule->arg);
240: foreach ($args as & $val) {
241: $val = $val instanceof IControl ? $val->getValue() : $val;
242: }
243: return $rule->isNegative
244: xor call_user_func(self::getCallback($rule), $rule->control, is_array($rule->arg) ? $args : $args[0]);
245: }
246:
247:
248: 249: 250: 251:
252: public function getIterator()
253: {
254: $rules = $this->rules;
255: if ($this->required) {
256: array_unshift($rules, $this->required);
257: }
258: return new \ArrayIterator($rules);
259: }
260:
261:
262: 263: 264: 265: 266:
267: private function adjustOperation($rule)
268: {
269: if (is_string($rule->validator) && ord($rule->validator[0]) > 127) {
270: $rule->isNegative = TRUE;
271: $rule->validator = ~$rule->validator;
272: }
273:
274: if (!is_callable($this->getCallback($rule))) {
275: $validator = is_scalar($rule->validator) ? " '$rule->validator'" : '';
276: throw new Nette\InvalidArgumentException("Unknown validator$validator for control '{$rule->control->name}'.");
277: }
278: }
279:
280:
281: private static function getCallback($rule)
282: {
283: $op = $rule->validator;
284: if (is_string($op) && strncmp($op, ':', 1) === 0) {
285: return 'Nette\Forms\Validator::validate' . ltrim($op, ':');
286: } else {
287: return $op;
288: }
289: }
290:
291: }
292:
293: Rules::$defaultMessages = & Validator::$messages;
294: