Namespaces

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
      • Adapters
      • Extensions
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Diagnostics
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
      • PhpGenerator
  • NetteModule
  • none

Classes

  • Container
  • ControlGroup
  • Form
  • 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 (http://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::FILLED => 'Please complete mandatory field.',
 28:         Form::MIN_LENGTH => 'Please enter a value of at least %d characters.',
 29:         Form::MAX_LENGTH => 'Please enter a value no longer than %d characters.',
 30:         Form::LENGTH => 'Please enter a value between %d and %d characters long.',
 31:         Form::EMAIL => 'Please enter a valid email address.',
 32:         Form::URL => 'Please enter a valid URL.',
 33:         Form::INTEGER => 'Please enter a numeric value.',
 34:         Form::FLOAT => 'Please enter a numeric value.',
 35:         Form::RANGE => 'Please enter a value between %d and %d.',
 36:         Form::MAX_FILE_SIZE => 'The size of the uploaded file can be up to %d bytes.',
 37:         Form::IMAGE => 'The uploaded file must be image in format JPEG, GIF or PNG.',
 38:         Form::MIME_TYPE => 'The uploaded file is not in the expected format.',
 39:     );
 40: 
 41:     /** @var Rule[] */
 42:     private $rules = array();
 43: 
 44:     /** @var Rules */
 45:     private $parent;
 46: 
 47:     /** @var array */
 48:     private $toggles = array();
 49: 
 50:     /** @var IControl */
 51:     private $control;
 52: 
 53: 
 54:     public function __construct(IControl $control)
 55:     {
 56:         $this->control = $control;
 57:     }
 58: 
 59: 
 60:     /**
 61:      * Adds a validation rule for the current control.
 62:      * @param  mixed      rule type
 63:      * @param  string     message to display for invalid data
 64:      * @param  mixed      optional rule arguments
 65:      * @return self
 66:      */
 67:     public function addRule($operation, $message = NULL, $arg = NULL)
 68:     {
 69:         $rule = new Rule;
 70:         $rule->control = $this->control;
 71:         $rule->operation = $operation;
 72:         $this->adjustOperation($rule);
 73:         $rule->arg = $arg;
 74:         $rule->type = Rule::VALIDATOR;
 75:         if ($message === NULL && is_string($rule->operation) && isset(static::$defaultMessages[$rule->operation])) {
 76:             $rule->message = static::$defaultMessages[$rule->operation];
 77:         } else {
 78:             $rule->message = $message;
 79:         }
 80:         $this->rules[] = $rule;
 81:         return $this;
 82:     }
 83: 
 84: 
 85:     /**
 86:      * Adds a validation condition a returns new branch.
 87:      * @param  mixed      condition type
 88:      * @param  mixed      optional condition arguments
 89:      * @return Rules      new branch
 90:      */
 91:     public function addCondition($operation, $arg = NULL)
 92:     {
 93:         return $this->addConditionOn($this->control, $operation, $arg);
 94:     }
 95: 
 96: 
 97:     /**
 98:      * Adds a validation condition on specified control a returns new branch.
 99:      * @param  IControl form control
100:      * @param  mixed      condition type
101:      * @param  mixed      optional condition arguments
102:      * @return Rules      new branch
103:      */
104:     public function addConditionOn(IControl $control, $operation, $arg = NULL)
105:     {
106:         $rule = new Rule;
107:         $rule->control = $control;
108:         $rule->operation = $operation;
109:         $this->adjustOperation($rule);
110:         $rule->arg = $arg;
111:         $rule->type = Rule::CONDITION;
112:         $rule->subRules = new static($this->control);
113:         $rule->subRules->parent = $this;
114: 
115:         $this->rules[] = $rule;
116:         return $rule->subRules;
117:     }
118: 
119: 
120:     /**
121:      * Adds a else statement.
122:      * @return Rules      else branch
123:      */
124:     public function elseCondition()
125:     {
126:         $rule = clone end($this->parent->rules);
127:         $rule->isNegative = !$rule->isNegative;
128:         $rule->subRules = new static($this->parent->control);
129:         $rule->subRules->parent = $this->parent;
130:         $this->parent->rules[] = $rule;
131:         return $rule->subRules;
132:     }
133: 
134: 
135:     /**
136:      * Ends current validation condition.
137:      * @return Rules      parent branch
138:      */
139:     public function endCondition()
140:     {
141:         return $this->parent;
142:     }
143: 
144: 
145:     /**
146:      * Toggles HTML elememnt visibility.
147:      * @param  string     element id
148:      * @param  bool       hide element?
149:      * @return self
150:      */
151:     public function toggle($id, $hide = TRUE)
152:     {
153:         $this->toggles[$id] = $hide;
154:         return $this;
155:     }
156: 
157: 
158:     /**
159:      * Validates against ruleset.
160:      * @param  bool    stop before first error?
161:      * @return bool    is valid?
162:      */
163:     public function validate($onlyCheck = FALSE)
164:     {
165:         foreach ($this->rules as $rule) {
166:             if ($rule->control->isDisabled()) {
167:                 continue;
168:             }
169: 
170:             $success = ($rule->isNegative xor $this->getCallback($rule)->invoke($rule->control, $rule->arg));
171: 
172:             if ($rule->type === Rule::CONDITION && $success) {
173:                 if (!$rule->subRules->validate($onlyCheck)) {
174:                     return FALSE;
175:                 }
176: 
177:             } elseif ($rule->type === Rule::VALIDATOR && !$success) {
178:                 if (!$onlyCheck) {
179:                     $rule->control->addError(static::formatMessage($rule, TRUE));
180:                 }
181:                 return FALSE;
182:             }
183:         }
184:         return TRUE;
185:     }
186: 
187: 
188:     /**
189:      * Iterates over ruleset.
190:      * @return \ArrayIterator
191:      */
192:     public function getIterator()
193:     {
194:         return new \ArrayIterator($this->rules);
195:     }
196: 
197: 
198:     /**
199:      * @return array
200:      */
201:     public function getToggles()
202:     {
203:         return $this->toggles;
204:     }
205: 
206: 
207:     /**
208:      * Process 'operation' string.
209:      * @param  Rule
210:      * @return void
211:      */
212:     private function adjustOperation($rule)
213:     {
214:         if (is_string($rule->operation) && ord($rule->operation[0]) > 127) {
215:             $rule->isNegative = TRUE;
216:             $rule->operation = ~$rule->operation;
217:         }
218: 
219:         if (!$this->getCallback($rule)->isCallable()) {
220:             $operation = is_scalar($rule->operation) ? " '$rule->operation'" : '';
221:             throw new Nette\InvalidArgumentException("Unknown operation$operation for control '{$rule->control->getName()}'.");
222:         }
223:     }
224: 
225: 
226:     private function getCallback($rule)
227:     {
228:         $op = $rule->operation;
229:         if (is_string($op) && strncmp($op, ':', 1) === 0) {
230:             return new Nette\Callback(get_class($rule->control), self::VALIDATE_PREFIX . ltrim($op, ':'));
231:         } else {
232:             return new Nette\Callback($op);
233:         }
234:     }
235: 
236: 
237:     public static function formatMessage($rule, $withValue)
238:     {
239:         $message = $rule->message;
240:         if ($message instanceof Nette\Utils\Html) {
241:             return $message;
242:         }
243:         if ($message == NULL) { // intentionally ==
244:             trigger_error("Missing validation message for control '{$rule->control->getName()}'.", E_USER_WARNING);
245:         }
246:         if ($translator = $rule->control->getForm()->getTranslator()) {
247:             $message = $translator->translate($message, is_int($rule->arg) ? $rule->arg : NULL);
248:         }
249:         $message = vsprintf(preg_replace('#%(name|label|value)#', '%$0', $message), (array) $rule->arg);
250:         $message = str_replace('%name', $rule->control->getName(), $message);
251:         $message = str_replace('%label', $rule->control->translate($rule->control->caption), $message);
252:         if ($withValue && strpos($message, '%value') !== FALSE) {
253:             $message = str_replace('%value', $rule->control->getValue(), $message);
254:         }
255:         return $message;
256:     }
257: 
258: }
259: 
Nette 2.0 API documentation generated by ApiGen 2.8.0