Packages

  • 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
  • PHP

Classes

  • NForm
  • NFormContainer
  • NFormGroup
  • NRule
  • NRules

Interfaces

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