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: if ($validator === Form::VALID || $validator === ~Form::VALID) {
79: throw new Nette\InvalidArgumentException('You cannot use Form::VALID in the addRule method.');
80: }
81: $rule = new Rule;
82: $rule->control = $this->control;
83: $rule->validator = $validator;
84: $this->adjustOperation($rule);
85: $rule->arg = $arg;
86: $rule->message = $message;
87: if ($rule->validator === Form::REQUIRED) {
88: $this->required = $rule;
89: } else {
90: $this->rules[] = $rule;
91: }
92: return $this;
93: }
94:
95:
96: 97: 98: 99: 100: 101:
102: public function addCondition($validator, $arg = NULL)
103: {
104: if ($validator === Form::VALID || $validator === ~Form::VALID) {
105: throw new Nette\InvalidArgumentException('You cannot use Form::VALID in the addCondition method.');
106: }
107: return $this->addConditionOn($this->control, $validator, $arg);
108: }
109:
110:
111: 112: 113: 114: 115: 116: 117:
118: public function addConditionOn(IControl $control, $validator, $arg = NULL)
119: {
120: $rule = new Rule;
121: $rule->control = $control;
122: $rule->validator = $validator;
123: $this->adjustOperation($rule);
124: $rule->arg = $arg;
125: $rule->branch = new static($this->control);
126: $rule->branch->parent = $this;
127:
128: $this->rules[] = $rule;
129: return $rule->branch;
130: }
131:
132:
133: 134: 135: 136:
137: public function elseCondition()
138: {
139: $rule = clone end($this->parent->rules);
140: $rule->isNegative = !$rule->isNegative;
141: $rule->branch = new static($this->parent->control);
142: $rule->branch->parent = $this->parent;
143: $this->parent->rules[] = $rule;
144: return $rule->branch;
145: }
146:
147:
148: 149: 150: 151:
152: public function endCondition()
153: {
154: return $this->parent;
155: }
156:
157:
158: 159: 160: 161: 162:
163: public function addFilter($filter)
164: {
165: Nette\Utils\Callback::check($filter);
166: $this->rules[] = $rule = new Rule;
167: $rule->control = $this->control;
168: $rule->validator = function (IControl $control) use ($filter) {
169: $control->setValue(call_user_func($filter, $control->getValue()));
170: return TRUE;
171: };
172: return $this;
173: }
174:
175:
176: 177: 178: 179: 180: 181:
182: public function toggle($id, $hide = TRUE)
183: {
184: $this->toggles[$id] = $hide;
185: return $this;
186: }
187:
188:
189: 190: 191: 192:
193: public function getToggles($actual = FALSE)
194: {
195: return $actual ? $this->getToggleStates() : $this->toggles;
196: }
197:
198:
199: 200: 201: 202:
203: public function getToggleStates($toggles = array(), $success = TRUE)
204: {
205: foreach ($this->toggles as $id => $hide) {
206: $toggles[$id] = ($success xor !$hide) || !empty($toggles[$id]);
207: }
208:
209: foreach ($this as $rule) {
210: if ($rule->branch) {
211: $toggles = $rule->branch->getToggleStates($toggles, $success && static::validateRule($rule));
212: }
213: }
214: return $toggles;
215: }
216:
217:
218: 219: 220: 221:
222: public function validate()
223: {
224: foreach ($this as $rule) {
225: $success = $this->validateRule($rule);
226:
227: if ($success && $rule->branch && !$rule->branch->validate()) {
228: return FALSE;
229:
230: } elseif (!$success && !$rule->branch) {
231: $rule->control->addError(Validator::formatMessage($rule, TRUE));
232: return FALSE;
233: }
234: }
235: return TRUE;
236: }
237:
238:
239: 240: 241: 242:
243: public static function validateRule(Rule $rule)
244: {
245: $args = is_array($rule->arg) ? $rule->arg : array($rule->arg);
246: foreach ($args as & $val) {
247: $val = $val instanceof IControl ? $val->getValue() : $val;
248: }
249: return $rule->isNegative
250: xor call_user_func(self::getCallback($rule), $rule->control, is_array($rule->arg) ? $args : $args[0]);
251: }
252:
253:
254: 255: 256: 257:
258: public function getIterator()
259: {
260: $rules = $this->rules;
261: if ($this->required) {
262: array_unshift($rules, $this->required);
263: }
264: return new \ArrayIterator($rules);
265: }
266:
267:
268: 269: 270: 271: 272:
273: private function adjustOperation($rule)
274: {
275: if (is_string($rule->validator) && ord($rule->validator[0]) > 127) {
276: $rule->isNegative = TRUE;
277: $rule->validator = ~$rule->validator;
278: }
279:
280: if (!is_callable($this->getCallback($rule))) {
281: $validator = is_scalar($rule->validator) ? " '$rule->validator'" : '';
282: throw new Nette\InvalidArgumentException("Unknown validator$validator for control '{$rule->control->name}'.");
283: }
284: }
285:
286:
287: private static function getCallback($rule)
288: {
289: $op = $rule->validator;
290: if (is_string($op) && strncmp($op, ':', 1) === 0) {
291: return 'Nette\Forms\Validator::validate' . ltrim($op, ':');
292: } else {
293: return $op;
294: }
295: }
296:
297: }
298:
299: Rules::$defaultMessages = & Validator::$messages;
300: