Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationLatte
      • ApplicationTracy
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsLatte
      • Framework
      • HttpTracy
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Drivers
      • Reflection
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Templating
    • Utils
  • NetteModule
  • none
  • Tracy

Classes

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

Interfaces

  • IControl
  • IFormRenderer
  • ISubmitterControl
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  • Nette homepage
  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:  * @author     David Grudl
 17:  */
 18: class Rules extends Nette\Object implements \IteratorAggregate
 19: {
 20:     /** @internal */
 21:     const VALIDATE_PREFIX = 'validate';
 22: 
 23:     /** @var array */
 24:     public static $defaultMessages = array(
 25:         Form::PROTECTION => 'Your session has expired. Please return to the home page and try again.',
 26:         Form::EQUAL => 'Please enter %s.',
 27:         Form::NOT_EQUAL => 'This value should not be %s.',
 28:         Form::FILLED => 'This field is required.',
 29:         Form::BLANK => 'This field should be blank.',
 30:         Form::MIN_LENGTH => 'Please enter at least %d characters.',
 31:         Form::MAX_LENGTH => 'Please enter no more than %d characters.',
 32:         Form::LENGTH => 'Please enter a value between %d and %d characters long.',
 33:         Form::EMAIL => 'Please enter a valid email address.',
 34:         Form::URL => 'Please enter a valid URL.',
 35:         Form::INTEGER => 'Please enter a valid integer.',
 36:         Form::FLOAT => 'Please enter a valid number.',
 37:         Form::MIN => 'Please enter a value greater than or equal to %d.',
 38:         Form::MAX => 'Please enter a value less than or equal to %d.',
 39:         Form::RANGE => 'Please enter a value between %d and %d.',
 40:         Form::MAX_FILE_SIZE => 'The size of the uploaded file can be up to %d bytes.',
 41:         Form::MAX_POST_SIZE => 'The uploaded data exceeds the limit of %d bytes.',
 42:         Form::IMAGE => 'The uploaded file must be image in format JPEG, GIF or PNG.',
 43:         Form::MIME_TYPE => 'The uploaded file is not in the expected format.',
 44:         Nette\Forms\Controls\SelectBox::VALID => 'Please select a valid option.',
 45:     );
 46: 
 47:     /** @var Rule */
 48:     private $required;
 49: 
 50:     /** @var Rule[] */
 51:     private $rules = array();
 52: 
 53:     /** @var Rules */
 54:     private $parent;
 55: 
 56:     /** @var array */
 57:     private $toggles = array();
 58: 
 59:     /** @var IControl */
 60:     private $control;
 61: 
 62: 
 63:     public function __construct(IControl $control)
 64:     {
 65:         $this->control = $control;
 66:     }
 67: 
 68: 
 69:     /**
 70:      * Makes control mandatory.
 71:      * @param  mixed  state or error message
 72:      * @return self
 73:      */
 74:     public function setRequired($value = TRUE)
 75:     {
 76:         if ($value) {
 77:             $this->addRule(Form::REQUIRED, is_string($value) ? $value : NULL);
 78:         } else {
 79:             $this->required = NULL;
 80:         }
 81:         return $this;
 82:     }
 83: 
 84: 
 85:     /**
 86:      * Is control mandatory?
 87:      * @return bool
 88:      */
 89:     public function isRequired()
 90:     {
 91:         return $this->required instanceof Rule ? !$this->required->isNegative : FALSE;
 92:     }
 93: 
 94: 
 95:     /**
 96:      * Adds a validation rule for the current control.
 97:      * @param  mixed      rule type
 98:      * @param  string     message to display for invalid data
 99:      * @param  mixed      optional rule arguments
100:      * @return self
101:      */
102:     public function addRule($validator, $message = NULL, $arg = NULL)
103:     {
104:         $rule = new Rule;
105:         $rule->control = $this->control;
106:         $rule->validator = $validator;
107:         $this->adjustOperation($rule);
108:         $rule->arg = $arg;
109:         $rule->message = $message;
110:         if ($rule->validator === Form::REQUIRED) {
111:             $this->required = $rule;
112:         } else {
113:             $this->rules[] = $rule;
114:         }
115:         return $this;
116:     }
117: 
118: 
119:     /**
120:      * Adds a validation condition and returns new branch.
121:      * @param  mixed      condition type
122:      * @param  mixed      optional condition arguments
123:      * @return Rules      new branch
124:      */
125:     public function addCondition($validator, $arg = NULL)
126:     {
127:         return $this->addConditionOn($this->control, $validator, $arg);
128:     }
129: 
130: 
131:     /**
132:      * Adds a validation condition on specified control a returns new branch.
133:      * @param  IControl form control
134:      * @param  mixed      condition type
135:      * @param  mixed      optional condition arguments
136:      * @return Rules      new branch
137:      */
138:     public function addConditionOn(IControl $control, $validator, $arg = NULL)
139:     {
140:         $rule = new Rule;
141:         $rule->control = $control;
142:         $rule->validator = $validator;
143:         $this->adjustOperation($rule);
144:         $rule->arg = $arg;
145:         $rule->branch = new static($this->control);
146:         $rule->branch->parent = $this;
147: 
148:         $this->rules[] = $rule;
149:         return $rule->branch;
150:     }
151: 
152: 
153:     /**
154:      * Adds a else statement.
155:      * @return Rules      else branch
156:      */
157:     public function elseCondition()
158:     {
159:         $rule = clone end($this->parent->rules);
160:         $rule->isNegative = !$rule->isNegative;
161:         $rule->branch = new static($this->parent->control);
162:         $rule->branch->parent = $this->parent;
163:         $this->parent->rules[] = $rule;
164:         return $rule->branch;
165:     }
166: 
167: 
168:     /**
169:      * Ends current validation condition.
170:      * @return Rules      parent branch
171:      */
172:     public function endCondition()
173:     {
174:         return $this->parent;
175:     }
176: 
177: 
178:     /**
179:      * Toggles HTML element visibility.
180:      * @param  string     element id
181:      * @param  bool       hide element?
182:      * @return self
183:      */
184:     public function toggle($id, $hide = TRUE)
185:     {
186:         $this->toggles[$id] = $hide;
187:         return $this;
188:     }
189: 
190: 
191:     /**
192:      * @param  bool
193:      * @return array
194:      */
195:     public function getToggles($actual = FALSE)
196:     {
197:         return $actual ? $this->getToggleStates() : $this->toggles;
198:     }
199: 
200: 
201:     /**
202:      * @internal
203:      * @return array
204:      */
205:     public function getToggleStates($toggles = array(), $success = TRUE)
206:     {
207:         foreach ($this->toggles as $id => $hide) {
208:             $toggles[$id] = ($success xor !$hide) || !empty($toggles[$id]);
209:         }
210: 
211:         foreach ($this as $rule) {
212:             if ($rule->branch) {
213:                 $toggles = $rule->branch->getToggleStates($toggles, $success && static::validateRule($rule));
214:             }
215:         }
216:         return $toggles;
217:     }
218: 
219: 
220:     /**
221:      * Validates against ruleset.
222:      * @return bool
223:      */
224:     public function validate()
225:     {
226:         foreach ($this as $rule) {
227:             $success = $this->validateRule($rule);
228: 
229:             if ($success && $rule->branch && !$rule->branch->validate()) {
230:                 return FALSE;
231: 
232:             } elseif (!$success && !$rule->branch) {
233:                 $rule->control->addError($this->formatMessage($rule, TRUE));
234:                 return FALSE;
235:             }
236:         }
237:         return TRUE;
238:     }
239: 
240: 
241:     /**
242:      * Validates single rule.
243:      * @return bool
244:      */
245:     public static function validateRule(Rule $rule)
246:     {
247:         $args = is_array($rule->arg) ? $rule->arg : array($rule->arg);
248:         foreach ($args as & $val) {
249:             $val = $val instanceof IControl ? $val->getValue() : $val;
250:         }
251:         return $rule->isNegative
252:             xor call_user_func(self::getCallback($rule), $rule->control, is_array($rule->arg) ? $args : $args[0]);
253:     }
254: 
255: 
256:     /**
257:      * Iterates over complete ruleset.
258:      * @return \ArrayIterator
259:      */
260:     public function getIterator()
261:     {
262:         $rules = $this->rules;
263:         if ($this->required) {
264:             array_unshift($rules, $this->required);
265:         }
266:         return new \ArrayIterator($rules);
267:     }
268: 
269: 
270:     /**
271:      * Process 'operation' string.
272:      * @param  Rule
273:      * @return void
274:      */
275:     private function adjustOperation($rule)
276:     {
277:         if (is_string($rule->validator) && ord($rule->validator[0]) > 127) {
278:             $rule->isNegative = TRUE;
279:             $rule->validator = ~$rule->validator;
280:         }
281: 
282:         if (!is_callable($this->getCallback($rule))) {
283:             $validator = is_scalar($rule->validator) ? " '$rule->validator'" : '';
284:             throw new Nette\InvalidArgumentException("Unknown validator$validator for control '{$rule->control->name}'.");
285:         }
286:     }
287: 
288: 
289:     private static function getCallback($rule)
290:     {
291:         $op = $rule->validator;
292:         if (is_string($op) && strncmp($op, ':', 1) === 0) {
293:             return get_class($rule->control) . '::' . self::VALIDATE_PREFIX . ltrim($op, ':');
294:         } else {
295:             return $op;
296:         }
297:     }
298: 
299: 
300:     public static function formatMessage(Rule $rule, $withValue = TRUE)
301:     {
302:         $message = $rule->message;
303:         if ($message instanceof Nette\Utils\Html) {
304:             return $message;
305: 
306:         } elseif ($message === NULL && is_string($rule->validator) && isset(self::$defaultMessages[$rule->validator])) {
307:             $message = self::$defaultMessages[$rule->validator];
308: 
309:         } elseif ($message == NULL) { // intentionally ==
310:             trigger_error("Missing validation message for control '{$rule->control->getName()}'.", E_USER_WARNING);
311:         }
312: 
313:         if ($translator = $rule->control->getForm()->getTranslator()) {
314:             $message = $translator->translate($message, is_int($rule->arg) ? $rule->arg : NULL);
315:         }
316: 
317:         $message = preg_replace_callback('#%(name|label|value|\d+\$[ds]|[ds])#', function ($m) use ($rule, $withValue) {
318:             static $i = -1;
319:             switch ($m[1]) {
320:                 case 'name': return $rule->control->getName();
321:                 case 'label': return $rule->control->translate($rule->control->caption);
322:                 case 'value': return $withValue ? $rule->control->getValue() : $m[0];
323:                 default:
324:                     $args = is_array($rule->arg) ? $rule->arg : array($rule->arg);
325:                     $i = (int) $m[1] ? $m[1] - 1 : $i + 1;
326:                     return isset($args[$i]) ? ($args[$i] instanceof IControl ? ($withValue ? $args[$i]->getValue() : "%$i") : $args[$i]) : '';
327:             }
328:         }, $message);
329:         return $message;
330:     }
331: 
332: }
333: 
Nette 2.2 API documentation generated by ApiGen 2.8.0