Namespaces

  • Nette
    • Application
    • Caching
    • Collections
    • Config
    • Forms
    • IO
    • Loaders
    • Mail
    • Reflection
    • Security
    • Templates
    • Web
  • None
  • PHP

Classes

  • Button
  • Checkbox
  • ConventionalRenderer
  • FileUpload
  • Form
  • FormContainer
  • FormControl
  • FormGroup
  • HiddenField
  • ImageButton
  • InstantClientScript
  • MultiSelectBox
  • RadioList
  • Rule
  • Rules
  • SelectBox
  • SubmitButton
  • TextArea
  • TextBase
  • TextInput

Interfaces

  • IFormControl
  • IFormRenderer
  • INamingContainer
  • ISubmitterControl
  • Overview
  • Namespace
  • Class
  • Tree
  • Other releases
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://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: /**
 19:  * List of validation & condition rules.
 20:  *
 21:  * @author     David Grudl
 22:  */
 23: final class Rules extends Nette\Object implements \IteratorAggregate
 24: {
 25:     /** @internal */
 26:     const VALIDATE_PREFIX = 'validate';
 27: 
 28:     /** @var array */
 29:     public static $defaultMessages = array(
 30:     );
 31: 
 32:     /** @var array of Rule */
 33:     private $rules = array();
 34: 
 35:     /** @var Rules */
 36:     private $parent;
 37: 
 38:     /** @var array */
 39:     private $toggles = array();
 40: 
 41:     /** @var IFormControl */
 42:     private $control;
 43: 
 44: 
 45: 
 46:     public function __construct(IFormControl $control)
 47:     {
 48:         $this->control = $control;
 49:     }
 50: 
 51: 
 52: 
 53:     /**
 54:      * Adds a validation rule for the current control.
 55:      * @param  mixed      rule type
 56:      * @param  string     message to display for invalid data
 57:      * @param  mixed      optional rule arguments
 58:      * @return Rules      provides a fluent interface
 59:      */
 60:     public function addRule($operation, $message = NULL, $arg = NULL)
 61:     {
 62:         $rule = new Rule;
 63:         $rule->control = $this->control;
 64:         $rule->operation = $operation;
 65:         $this->adjustOperation($rule);
 66:         $rule->arg = $arg;
 67:         $rule->type = Rule::VALIDATOR;
 68:         if ($message === NULL && is_string($rule->operation) && isset(self::$defaultMessages[$rule->operation])) {
 69:             $rule->message = self::$defaultMessages[$rule->operation];
 70:         } else {
 71:             $rule->message = $message;
 72:         }
 73: 
 74:         if ($this->parent === NULL) {
 75:             // notify only direct rules
 76:             $this->control->notifyRule($rule);
 77:         }
 78:         $this->rules[] = $rule;
 79:         return $this;
 80:     }
 81: 
 82: 
 83: 
 84:     /**
 85:      * Adds a validation condition a returns new branch.
 86:      * @param  mixed      condition type
 87:      * @param  mixed      optional condition arguments
 88:      * @return Rules      new branch
 89:      */
 90:     public function addCondition($operation, $arg = NULL)
 91:     {
 92:         return $this->addConditionOn($this->control, $operation, $arg);
 93:     }
 94: 
 95: 
 96: 
 97:     /**
 98:      * Adds a validation condition on specified control a returns new branch.
 99:      * @param  IFormControl form control
100:      * @param  mixed      condition type
101:      * @param  mixed      optional condition arguments
102:      * @return Rules      new branch
103:      */
104:     public function addConditionOn(IFormControl $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 self($this->control);
113:         $rule->subRules->parent = $this;
114: 
115:         $this->rules[] = $rule;
116:         return $rule->subRules;
117:     }
118: 
119: 
120: 
121:     /**
122:      * Adds a else statement.
123:      * @return Rules      else branch
124:      */
125:     public function elseCondition()
126:     {
127:         $rule = clone end($this->parent->rules);
128:         $rule->isNegative = !$rule->isNegative;
129:         $rule->subRules = new self($this->parent->control);
130:         $rule->subRules->parent = $this->parent;
131:         $this->parent->rules[] = $rule;
132:         return $rule->subRules;
133:     }
134: 
135: 
136: 
137:     /**
138:      * Ends current validation condition.
139:      * @return Rules      parent branch
140:      */
141:     public function endCondition()
142:     {
143:         return $this->parent;
144:     }
145: 
146: 
147: 
148:     /**
149:      * Toggles HTML elememnt visibility.
150:      * @param  string     element id
151:      * @param  bool       hide element?
152:      * @return Rules      provides a fluent interface
153:      */
154:     public function toggle($id, $hide = TRUE)
155:     {
156:         $this->toggles[$id] = $hide;
157:         return $this;
158:     }
159: 
160: 
161: 
162:     /**
163:      * Validates against ruleset.
164:      * @param  bool    stop before first error?
165:      * @return bool    is valid?
166:      */
167:     public function validate($onlyCheck = FALSE)
168:     {
169:         foreach ($this->rules as $rule)
170:         {
171:             if ($rule->control->isDisabled()) continue;
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(self::formatMessage($rule, TRUE));
183:                 }
184:                 return FALSE;
185:             }
186:         }
187:         return TRUE;
188:     }
189: 
190: 
191: 
192:     /**
193:      * Iterates over ruleset.
194:      * @return \ArrayIterator
195:      */
196:     final public function getIterator()
197:     {
198:         return new \ArrayIterator($this->rules);
199:     }
200: 
201: 
202: 
203:     /**
204:      * @return array
205:      */
206:     final public function getToggles()
207:     {
208:         return $this->toggles;
209:     }
210: 
211: 
212: 
213:     /**
214:      * Process 'operation' string.
215:      * @param  Rule
216:      * @return void
217:      */
218:     private function adjustOperation($rule)
219:     {
220:         if (is_string($rule->operation) && ord($rule->operation[0]) > 127) {
221:             $rule->isNegative = TRUE;
222:             $rule->operation = ~$rule->operation;
223:         }
224: 
225:         if (!$this->getCallback($rule)->isCallable()) {
226:             $operation = is_scalar($rule->operation) ? " '$rule->operation'" : '';
227:             throw new \InvalidArgumentException("Unknown operation$operation for control '{$rule->control->name}'.");
228:         }
229:     }
230: 
231: 
232: 
233:     private function getCallback($rule)
234:     {
235:         $op = $rule->operation;
236:         if (is_string($op) && strncmp($op, ':', 1) === 0) {
237:             return callback(get_class($rule->control), self::VALIDATE_PREFIX . ltrim($op, ':'));
238:         } else {
239:             return callback($op);
240:         }
241:     }
242: 
243: 
244: 
245:     public static function formatMessage($rule, $withValue)
246:     {
247:         $message = $rule->message;
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 0.9.7 API documentation generated by ApiGen 2.3.0