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

Classes

  • Container
  • ControlGroup
  • Form
  • Rule
  • Rules

Interfaces

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