Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
      • Traits
    • Reflection
    • Security
    • Tokenizer
    • Utils
  • Tracy
    • Bridges
      • Nette
  • none

Classes

  • Container
  • ControlGroup
  • Form
  • Helpers
  • Rule
  • Rules
  • Validator

Interfaces

  • IControl
  • IFormRenderer
  • ISubmitterControl
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\Forms;
  9: 
 10: use Nette;
 11: 
 12: 
 13: /**
 14:  * List of validation & condition rules.
 15:  */
 16: class Rules implements \IteratorAggregate
 17: {
 18:     use Nette\SmartObject;
 19: 
 20:     /** @deprecated */
 21:     public static $defaultMessages;
 22: 
 23:     /** @var Rule|false|null */
 24:     private $required;
 25: 
 26:     /** @var Rule[] */
 27:     private $rules = [];
 28: 
 29:     /** @var Rules */
 30:     private $parent;
 31: 
 32:     /** @var array */
 33:     private $toggles = [];
 34: 
 35:     /** @var IControl */
 36:     private $control;
 37: 
 38: 
 39:     public function __construct(IControl $control)
 40:     {
 41:         $this->control = $control;
 42:     }
 43: 
 44: 
 45:     /**
 46:      * Makes control mandatory.
 47:      * @param  mixed  state or error message
 48:      * @return static
 49:      */
 50:     public function setRequired($value = true)
 51:     {
 52:         if ($value) {
 53:             $this->addRule(Form::REQUIRED, $value === true ? null : $value);
 54:         } else {
 55:             $this->required = false;
 56:         }
 57:         return $this;
 58:     }
 59: 
 60: 
 61:     /**
 62:      * Is control mandatory?
 63:      * @return bool
 64:      */
 65:     public function isRequired()
 66:     {
 67:         return (bool) $this->required;
 68:     }
 69: 
 70: 
 71:     /**
 72:      * @internal
 73:      */
 74:     public function isOptional()
 75:     {
 76:         return $this->required === false;
 77:     }
 78: 
 79: 
 80:     /**
 81:      * Adds a validation rule for the current control.
 82:      * @param  mixed
 83:      * @param  string|object
 84:      * @param  mixed
 85:      * @return static
 86:      */
 87:     public function addRule($validator, $errorMessage = null, $arg = null)
 88:     {
 89:         if ($validator === Form::VALID || $validator === ~Form::VALID) {
 90:             throw new Nette\InvalidArgumentException('You cannot use Form::VALID in the addRule method.');
 91:         }
 92:         $rule = new Rule;
 93:         $rule->control = $this->control;
 94:         $rule->validator = $validator;
 95:         $this->adjustOperation($rule);
 96:         $rule->arg = $arg;
 97:         $rule->message = $errorMessage;
 98:         if ($rule->validator === Form::REQUIRED) {
 99:             $this->required = $rule;
100:         } else {
101:             $this->rules[] = $rule;
102:         }
103:         return $this;
104:     }
105: 
106: 
107:     /**
108:      * Adds a validation condition and returns new branch.
109:      * @param  mixed
110:      * @param  mixed
111:      * @return static       new branch
112:      */
113:     public function addCondition($validator, $arg = null)
114:     {
115:         if ($validator === Form::VALID || $validator === ~Form::VALID) {
116:             throw new Nette\InvalidArgumentException('You cannot use Form::VALID in the addCondition method.');
117:         } elseif (is_bool($validator)) {
118:             $arg = $validator;
119:             $validator = ':static';
120:         }
121:         return $this->addConditionOn($this->control, $validator, $arg);
122:     }
123: 
124: 
125:     /**
126:      * Adds a validation condition on specified control a returns new branch.
127:      * @param  IControl
128:      * @param  mixed
129:      * @param  mixed
130:      * @return static     new branch
131:      */
132:     public function addConditionOn(IControl $control, $validator, $arg = null)
133:     {
134:         $rule = new Rule;
135:         $rule->control = $control;
136:         $rule->validator = $validator;
137:         $rule->arg = $arg;
138:         $rule->branch = new static($this->control);
139:         $rule->branch->parent = $this;
140:         $this->adjustOperation($rule);
141: 
142:         $this->rules[] = $rule;
143:         return $rule->branch;
144:     }
145: 
146: 
147:     /**
148:      * Adds a else statement.
149:      * @return static    else branch
150:      */
151:     public function elseCondition()
152:     {
153:         $rule = clone end($this->parent->rules);
154:         $rule->isNegative = !$rule->isNegative;
155:         $rule->branch = new static($this->parent->control);
156:         $rule->branch->parent = $this->parent;
157:         $this->parent->rules[] = $rule;
158:         return $rule->branch;
159:     }
160: 
161: 
162:     /**
163:      * Ends current validation condition.
164:      * @return Rules      parent branch
165:      */
166:     public function endCondition()
167:     {
168:         return $this->parent;
169:     }
170: 
171: 
172:     /**
173:      * Adds a filter callback.
174:      * @param  callable
175:      * @return static
176:      */
177:     public function addFilter($filter)
178:     {
179:         Nette\Utils\Callback::check($filter);
180:         $this->rules[] = $rule = new Rule;
181:         $rule->control = $this->control;
182:         $rule->validator = function (IControl $control) use ($filter) {
183:             $control->setValue(call_user_func($filter, $control->getValue()));
184:             return true;
185:         };
186:         return $this;
187:     }
188: 
189: 
190:     /**
191:      * Toggles HTML element visibility.
192:      * @param  string
193:      * @param  bool
194:      * @return static
195:      */
196:     public function toggle($id, $hide = true)
197:     {
198:         $this->toggles[$id] = $hide;
199:         return $this;
200:     }
201: 
202: 
203:     /**
204:      * @param  bool
205:      * @return array
206:      */
207:     public function getToggles($actual = false)
208:     {
209:         return $actual ? $this->getToggleStates() : $this->toggles;
210:     }
211: 
212: 
213:     /**
214:      * @internal
215:      * @return array
216:      */
217:     public function getToggleStates($toggles = [], $success = true)
218:     {
219:         foreach ($this->toggles as $id => $hide) {
220:             $toggles[$id] = ($success xor !$hide) || !empty($toggles[$id]);
221:         }
222: 
223:         foreach ($this->rules as $rule) {
224:             if ($rule->branch) {
225:                 $toggles = $rule->branch->getToggleStates($toggles, $success && static::validateRule($rule));
226:             }
227:         }
228:         return $toggles;
229:     }
230: 
231: 
232:     /**
233:      * Validates against ruleset.
234:      * @return bool
235:      */
236:     public function validate($emptyOptional = false)
237:     {
238:         $emptyOptional = $emptyOptional || $this->isOptional() && !$this->control->isFilled();
239:         foreach ($this as $rule) {
240:             if (!$rule->branch && $emptyOptional && $rule->validator !== Form::FILLED) {
241:                 continue;
242:             }
243: 
244:             $success = $this->validateRule($rule);
245:             if ($success && $rule->branch && !$rule->branch->validate($rule->validator === Form::BLANK ? false : $emptyOptional)) {
246:                 return false;
247: 
248:             } elseif (!$success && !$rule->branch) {
249:                 $rule->control->addError(Validator::formatMessage($rule, true), false);
250:                 return false;
251:             }
252:         }
253:         return true;
254:     }
255: 
256: 
257:     /**
258:      * @internal
259:      */
260:     public function check()
261:     {
262:         if ($this->required !== null) {
263:             return;
264:         }
265:         foreach ($this->rules as $rule) {
266:             if ($rule->control === $this->control && ($rule->validator === Form::FILLED || $rule->validator === Form::BLANK)) {
267:                 // ignore
268:             } elseif ($rule->branch) {
269:                 if ($rule->branch->check() === true) {
270:                     return true;
271:                 }
272:             } else {
273:                 trigger_error("Missing setRequired(true | false) on field '{$rule->control->getName()}' in form '{$rule->control->getForm()->getName()}'.", E_USER_WARNING);
274:                 return true;
275:             }
276:         }
277:     }
278: 
279: 
280:     /**
281:      * Clear all validation rules.
282:      */
283:     public function reset()
284:     {
285:         $this->rules = [];
286:     }
287: 
288: 
289:     /**
290:      * Validates single rule.
291:      * @return bool
292:      */
293:     public static function validateRule(Rule $rule)
294:     {
295:         $args = is_array($rule->arg) ? $rule->arg : [$rule->arg];
296:         foreach ($args as &$val) {
297:             $val = $val instanceof IControl ? $val->getValue() : $val;
298:         }
299:         return $rule->isNegative
300:             xor call_user_func(self::getCallback($rule), $rule->control, is_array($rule->arg) ? $args : $args[0]);
301:     }
302: 
303: 
304:     /**
305:      * Iterates over complete ruleset.
306:      * @return \Iterator
307:      */
308:     public function getIterator()
309:     {
310:         $rules = $this->rules;
311:         if ($this->required) {
312:             array_unshift($rules, $this->required);
313:         }
314:         return new \ArrayIterator($rules);
315:     }
316: 
317: 
318:     /**
319:      * Process 'operation' string.
320:      * @return void
321:      */
322:     private function adjustOperation(Rule $rule)
323:     {
324:         if (is_string($rule->validator) && ord($rule->validator[0]) > 127) {
325:             $rule->isNegative = true;
326:             $rule->validator = ~$rule->validator;
327:             if (!$rule->branch) {
328:                 $name = strncmp($rule->validator, ':', 1) ? $rule->validator : 'Form:' . strtoupper($rule->validator);
329:                 trigger_error("Negative validation rules such as ~$name are deprecated.", E_USER_DEPRECATED);
330:             }
331:             if ($rule->validator === Form::FILLED) {
332:                 $rule->validator = Form::BLANK;
333:                 $rule->isNegative = false;
334:                 trigger_error('Replace negative validation rule ~Form::FILLED with Form::BLANK.', E_USER_DEPRECATED);
335:             }
336:         }
337: 
338:         if (!is_callable($this->getCallback($rule))) {
339:             $validator = is_scalar($rule->validator) ? " '$rule->validator'" : '';
340:             throw new Nette\InvalidArgumentException("Unknown validator$validator for control '{$rule->control->name}'.");
341:         }
342:     }
343: 
344: 
345:     private static function getCallback(Rule $rule)
346:     {
347:         $op = $rule->validator;
348:         if (is_string($op) && strncmp($op, ':', 1) === 0) {
349:             return 'Nette\Forms\Validator::validate' . ltrim($op, ':');
350:         } else {
351:             return $op;
352:         }
353:     }
354: }
355: 
356: Rules::$defaultMessages = &Validator::$messages;
357: 
Nette 2.4-20180918 API API documentation generated by ApiGen 2.8.0