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