pictcode / lib / Cake / Model / ModelValidator.php @ 22fd3a57
履歴 | 表示 | アノテート | ダウンロード (18.189 KB)
| 1 | 635eef61 | spyder1211 | <?php
|
|---|---|---|---|
| 2 | /**
|
||
| 3 | * ModelValidator.
|
||
| 4 | *
|
||
| 5 | * Provides the Model validation logic.
|
||
| 6 | *
|
||
| 7 | * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||
| 8 | * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||
| 9 | *
|
||
| 10 | * Licensed under The MIT License
|
||
| 11 | * For full copyright and license information, please see the LICENSE.txt
|
||
| 12 | * Redistributions of files must retain the above copyright notice.
|
||
| 13 | *
|
||
| 14 | * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||
| 15 | * @link http://cakephp.org CakePHP(tm) Project
|
||
| 16 | * @package Cake.Model
|
||
| 17 | * @since CakePHP(tm) v 2.2.0
|
||
| 18 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||
| 19 | */
|
||
| 20 | |||
| 21 | App::uses('CakeValidationSet', 'Model/Validator'); |
||
| 22 | App::uses('Hash', 'Utility'); |
||
| 23 | |||
| 24 | /**
|
||
| 25 | * ModelValidator object encapsulates all methods related to data validations for a model
|
||
| 26 | * It also provides an API to dynamically change validation rules for each model field.
|
||
| 27 | *
|
||
| 28 | * Implements ArrayAccess to easily modify rules as usually done with `Model::$validate`
|
||
| 29 | * definition array
|
||
| 30 | *
|
||
| 31 | * @package Cake.Model
|
||
| 32 | * @link http://book.cakephp.org/2.0/en/data-validation.html
|
||
| 33 | */
|
||
| 34 | class ModelValidator implements ArrayAccess, IteratorAggregate, Countable { |
||
| 35 | |||
| 36 | /**
|
||
| 37 | * Holds the CakeValidationSet objects array
|
||
| 38 | *
|
||
| 39 | * @var array
|
||
| 40 | */
|
||
| 41 | protected $_fields = array(); |
||
| 42 | |||
| 43 | /**
|
||
| 44 | * Holds the reference to the model this Validator is attached to
|
||
| 45 | *
|
||
| 46 | * @var Model
|
||
| 47 | */
|
||
| 48 | protected $_model = array(); |
||
| 49 | |||
| 50 | /**
|
||
| 51 | * The validators $validate property, used for checking whether validation
|
||
| 52 | * rules definition changed in the model and should be refreshed in this class
|
||
| 53 | *
|
||
| 54 | * @var array
|
||
| 55 | */
|
||
| 56 | protected $_validate = array(); |
||
| 57 | |||
| 58 | /**
|
||
| 59 | * Holds the available custom callback methods, usually taken from model methods
|
||
| 60 | * and behavior methods
|
||
| 61 | *
|
||
| 62 | * @var array
|
||
| 63 | */
|
||
| 64 | protected $_methods = array(); |
||
| 65 | |||
| 66 | /**
|
||
| 67 | * Holds the available custom callback methods from the model
|
||
| 68 | *
|
||
| 69 | * @var array
|
||
| 70 | */
|
||
| 71 | protected $_modelMethods = array(); |
||
| 72 | |||
| 73 | /**
|
||
| 74 | * Holds the list of behavior names that were attached when this object was created
|
||
| 75 | *
|
||
| 76 | * @var array
|
||
| 77 | */
|
||
| 78 | protected $_behaviors = array(); |
||
| 79 | |||
| 80 | /**
|
||
| 81 | * Constructor
|
||
| 82 | *
|
||
| 83 | * @param Model $Model A reference to the Model the Validator is attached to
|
||
| 84 | */
|
||
| 85 | public function __construct(Model $Model) { |
||
| 86 | $this->_model = $Model; |
||
| 87 | } |
||
| 88 | |||
| 89 | /**
|
||
| 90 | * Returns true if all fields pass validation. Will validate hasAndBelongsToMany associations
|
||
| 91 | * that use the 'with' key as well. Since `Model::_saveMulti` is incapable of exiting a save operation.
|
||
| 92 | *
|
||
| 93 | * Will validate the currently set data. Use `Model::set()` or `Model::create()` to set the active data.
|
||
| 94 | *
|
||
| 95 | * @param array $options An optional array of custom options to be made available in the beforeValidate callback
|
||
| 96 | * @return bool True if there are no errors
|
||
| 97 | */
|
||
| 98 | public function validates($options = array()) { |
||
| 99 | $errors = $this->errors($options); |
||
| 100 | if (empty($errors) && $errors !== false) { |
||
| 101 | $errors = $this->_validateWithModels($options); |
||
| 102 | } |
||
| 103 | if (is_array($errors)) { |
||
| 104 | return count($errors) === 0; |
||
| 105 | } |
||
| 106 | return $errors; |
||
| 107 | } |
||
| 108 | |||
| 109 | /**
|
||
| 110 | * Validates a single record, as well as all its directly associated records.
|
||
| 111 | *
|
||
| 112 | * #### Options
|
||
| 113 | *
|
||
| 114 | * - atomic: If true (default), returns boolean. If false returns array.
|
||
| 115 | * - fieldList: Equivalent to the $fieldList parameter in Model::save()
|
||
| 116 | * - deep: If set to true, not only directly associated data , but deeper nested associated data is validated as well.
|
||
| 117 | *
|
||
| 118 | * Warning: This method could potentially change the passed argument `$data`,
|
||
| 119 | * If you do not want this to happen, make a copy of `$data` before passing it
|
||
| 120 | * to this method
|
||
| 121 | *
|
||
| 122 | * @param array &$data Record data to validate. This should be an array indexed by association name.
|
||
| 123 | * @param array $options Options to use when validating record data (see above), See also $options of validates().
|
||
| 124 | * @return array|bool If atomic: True on success, or false on failure.
|
||
| 125 | * Otherwise: array similar to the $data array passed, but values are set to true/false
|
||
| 126 | * depending on whether each record validated successfully.
|
||
| 127 | */
|
||
| 128 | public function validateAssociated(&$data, $options = array()) { |
||
| 129 | $model = $this->getModel(); |
||
| 130 | $options += array('atomic' => true, 'deep' => false); |
||
| 131 | $model->validationErrors = $validationErrors = $return = array(); |
||
| 132 | $model->create(null); |
||
| 133 | $return[$model->alias] = true; |
||
| 134 | if (!($model->set($data) && $model->validates($options))) { |
||
| 135 | $validationErrors[$model->alias] = $model->validationErrors; |
||
| 136 | $return[$model->alias] = false; |
||
| 137 | } |
||
| 138 | $data = $model->data; |
||
| 139 | if (!empty($options['deep']) && isset($data[$model->alias])) { |
||
| 140 | $recordData = $data[$model->alias]; |
||
| 141 | unset($data[$model->alias]); |
||
| 142 | $data += $recordData; |
||
| 143 | } |
||
| 144 | |||
| 145 | $associations = $model->getAssociated(); |
||
| 146 | foreach ($data as $association => &$values) { |
||
| 147 | $validates = true; |
||
| 148 | if (isset($associations[$association])) { |
||
| 149 | if (in_array($associations[$association], array('belongsTo', 'hasOne'))) { |
||
| 150 | if ($options['deep']) { |
||
| 151 | $validates = $model->{$association}->validateAssociated($values, $options); |
||
| 152 | } else {
|
||
| 153 | $model->{$association}->create(null); |
||
| 154 | $validates = $model->{$association}->set($values) && $model->{$association}->validates($options); |
||
| 155 | $data[$association] = $model->{$association}->data[$model->{$association}->alias]; |
||
| 156 | } |
||
| 157 | if (is_array($validates)) { |
||
| 158 | $validates = !in_array(false, Hash::flatten($validates), true); |
||
| 159 | } |
||
| 160 | $return[$association] = $validates; |
||
| 161 | } elseif ($associations[$association] === 'hasMany') { |
||
| 162 | $validates = $model->{$association}->validateMany($values, $options); |
||
| 163 | $return[$association] = $validates; |
||
| 164 | } |
||
| 165 | if (!$validates || (is_array($validates) && in_array(false, $validates, true))) { |
||
| 166 | $validationErrors[$association] = $model->{$association}->validationErrors; |
||
| 167 | } |
||
| 168 | } |
||
| 169 | } |
||
| 170 | |||
| 171 | $model->validationErrors = $validationErrors; |
||
| 172 | if (isset($validationErrors[$model->alias])) { |
||
| 173 | $model->validationErrors = $validationErrors[$model->alias]; |
||
| 174 | unset($validationErrors[$model->alias]); |
||
| 175 | $model->validationErrors = array_merge($model->validationErrors, $validationErrors); |
||
| 176 | } |
||
| 177 | if (!$options['atomic']) { |
||
| 178 | return $return; |
||
| 179 | } |
||
| 180 | if ($return[$model->alias] === false || !empty($model->validationErrors)) { |
||
| 181 | return false; |
||
| 182 | } |
||
| 183 | return true; |
||
| 184 | } |
||
| 185 | |||
| 186 | /**
|
||
| 187 | * Validates multiple individual records for a single model
|
||
| 188 | *
|
||
| 189 | * #### Options
|
||
| 190 | *
|
||
| 191 | * - atomic: If true (default), returns boolean. If false returns array.
|
||
| 192 | * - fieldList: Equivalent to the $fieldList parameter in Model::save()
|
||
| 193 | * - deep: If set to true, all associated data will be validated as well.
|
||
| 194 | *
|
||
| 195 | * Warning: This method could potentially change the passed argument `$data`,
|
||
| 196 | * If you do not want this to happen, make a copy of `$data` before passing it
|
||
| 197 | * to this method
|
||
| 198 | *
|
||
| 199 | * @param array &$data Record data to validate. This should be a numerically-indexed array
|
||
| 200 | * @param array $options Options to use when validating record data (see above), See also $options of validates().
|
||
| 201 | * @return mixed If atomic: True on success, or false on failure.
|
||
| 202 | * Otherwise: array similar to the $data array passed, but values are set to true/false
|
||
| 203 | * depending on whether each record validated successfully.
|
||
| 204 | */
|
||
| 205 | public function validateMany(&$data, $options = array()) { |
||
| 206 | $model = $this->getModel(); |
||
| 207 | $options += array('atomic' => true, 'deep' => false); |
||
| 208 | $model->validationErrors = $validationErrors = $return = array(); |
||
| 209 | foreach ($data as $key => &$record) { |
||
| 210 | if ($options['deep']) { |
||
| 211 | $validates = $model->validateAssociated($record, $options); |
||
| 212 | } else {
|
||
| 213 | $model->create(null); |
||
| 214 | $validates = $model->set($record) && $model->validates($options); |
||
| 215 | $data[$key] = $model->data; |
||
| 216 | } |
||
| 217 | if ($validates === false || (is_array($validates) && in_array(false, Hash::flatten($validates), true))) { |
||
| 218 | $validationErrors[$key] = $model->validationErrors; |
||
| 219 | $validates = false; |
||
| 220 | } else {
|
||
| 221 | $validates = true; |
||
| 222 | } |
||
| 223 | $return[$key] = $validates; |
||
| 224 | } |
||
| 225 | $model->validationErrors = $validationErrors; |
||
| 226 | if (!$options['atomic']) { |
||
| 227 | return $return; |
||
| 228 | } |
||
| 229 | return empty($model->validationErrors); |
||
| 230 | } |
||
| 231 | |||
| 232 | /**
|
||
| 233 | * Returns an array of fields that have failed validation. On the current model. This method will
|
||
| 234 | * actually run validation rules over data, not just return the messages.
|
||
| 235 | *
|
||
| 236 | * @param string $options An optional array of custom options to be made available in the beforeValidate callback
|
||
| 237 | * @return array Array of invalid fields
|
||
| 238 | * @triggers Model.afterValidate $model
|
||
| 239 | * @see ModelValidator::validates()
|
||
| 240 | */
|
||
| 241 | public function errors($options = array()) { |
||
| 242 | if (!$this->_triggerBeforeValidate($options)) { |
||
| 243 | return false; |
||
| 244 | } |
||
| 245 | $model = $this->getModel(); |
||
| 246 | |||
| 247 | if (!$this->_parseRules()) { |
||
| 248 | return $model->validationErrors; |
||
| 249 | } |
||
| 250 | |||
| 251 | $fieldList = $model->whitelist; |
||
| 252 | if (empty($fieldList) && !empty($options['fieldList'])) { |
||
| 253 | if (!empty($options['fieldList'][$model->alias]) && is_array($options['fieldList'][$model->alias])) { |
||
| 254 | $fieldList = $options['fieldList'][$model->alias]; |
||
| 255 | } else {
|
||
| 256 | $fieldList = $options['fieldList']; |
||
| 257 | } |
||
| 258 | } |
||
| 259 | |||
| 260 | $exists = $model->exists(); |
||
| 261 | $methods = $this->getMethods(); |
||
| 262 | $fields = $this->_validationList($fieldList); |
||
| 263 | |||
| 264 | foreach ($fields as $field) { |
||
| 265 | $field->setMethods($methods); |
||
| 266 | $field->setValidationDomain($model->validationDomain); |
||
| 267 | $data = isset($model->data[$model->alias]) ? $model->data[$model->alias] : array(); |
||
| 268 | $errors = $field->validate($data, $exists); |
||
| 269 | foreach ($errors as $error) { |
||
| 270 | $this->invalidate($field->field, $error); |
||
| 271 | } |
||
| 272 | } |
||
| 273 | |||
| 274 | $model->getEventManager()->dispatch(new CakeEvent('Model.afterValidate', $model)); |
||
| 275 | return $model->validationErrors; |
||
| 276 | } |
||
| 277 | |||
| 278 | /**
|
||
| 279 | * Marks a field as invalid, optionally setting a message explaining
|
||
| 280 | * why the rule failed
|
||
| 281 | *
|
||
| 282 | * @param string $field The name of the field to invalidate
|
||
| 283 | * @param string $message Validation message explaining why the rule failed, defaults to true.
|
||
| 284 | * @return void
|
||
| 285 | */
|
||
| 286 | public function invalidate($field, $message = true) { |
||
| 287 | $this->getModel()->validationErrors[$field][] = $message; |
||
| 288 | } |
||
| 289 | |||
| 290 | /**
|
||
| 291 | * Gets all possible custom methods from the Model and attached Behaviors
|
||
| 292 | * to be used as validators
|
||
| 293 | *
|
||
| 294 | * @return array List of callables to be used as validation methods
|
||
| 295 | */
|
||
| 296 | public function getMethods() { |
||
| 297 | $behaviors = $this->_model->Behaviors->enabled(); |
||
| 298 | if (!empty($this->_methods) && $behaviors === $this->_behaviors) { |
||
| 299 | return $this->_methods; |
||
| 300 | } |
||
| 301 | $this->_behaviors = $behaviors; |
||
| 302 | |||
| 303 | if (empty($this->_modelMethods)) { |
||
| 304 | foreach (get_class_methods($this->_model) as $method) { |
||
| 305 | $this->_modelMethods[strtolower($method)] = array($this->_model, $method); |
||
| 306 | } |
||
| 307 | } |
||
| 308 | |||
| 309 | $methods = $this->_modelMethods; |
||
| 310 | foreach (array_keys($this->_model->Behaviors->methods()) as $method) { |
||
| 311 | $methods += array(strtolower($method) => array($this->_model, $method)); |
||
| 312 | } |
||
| 313 | |||
| 314 | return $this->_methods = $methods; |
||
| 315 | } |
||
| 316 | |||
| 317 | /**
|
||
| 318 | * Returns a CakeValidationSet object containing all validation rules for a field, if no
|
||
| 319 | * params are passed then it returns an array with all CakeValidationSet objects for each field
|
||
| 320 | *
|
||
| 321 | * @param string $name [optional] The fieldname to fetch. Defaults to null.
|
||
| 322 | * @return CakeValidationSet|array|null
|
||
| 323 | */
|
||
| 324 | public function getField($name = null) { |
||
| 325 | $this->_parseRules();
|
||
| 326 | if ($name !== null) { |
||
| 327 | if (!empty($this->_fields[$name])) { |
||
| 328 | return $this->_fields[$name]; |
||
| 329 | } |
||
| 330 | return null; |
||
| 331 | } |
||
| 332 | return $this->_fields; |
||
| 333 | } |
||
| 334 | |||
| 335 | /**
|
||
| 336 | * Sets the CakeValidationSet objects from the `Model::$validate` property
|
||
| 337 | * If `Model::$validate` is not set or empty, this method returns false. True otherwise.
|
||
| 338 | *
|
||
| 339 | * @return bool true if `Model::$validate` was processed, false otherwise
|
||
| 340 | */
|
||
| 341 | protected function _parseRules() { |
||
| 342 | if ($this->_validate === $this->_model->validate) { |
||
| 343 | return true; |
||
| 344 | } |
||
| 345 | |||
| 346 | if (empty($this->_model->validate)) { |
||
| 347 | $this->_validate = array(); |
||
| 348 | $this->_fields = array(); |
||
| 349 | return false; |
||
| 350 | } |
||
| 351 | |||
| 352 | $this->_validate = $this->_model->validate; |
||
| 353 | $this->_fields = array(); |
||
| 354 | $methods = $this->getMethods(); |
||
| 355 | foreach ($this->_validate as $fieldName => $ruleSet) { |
||
| 356 | $this->_fields[$fieldName] = new CakeValidationSet($fieldName, $ruleSet); |
||
| 357 | $this->_fields[$fieldName]->setMethods($methods); |
||
| 358 | } |
||
| 359 | return true; |
||
| 360 | } |
||
| 361 | |||
| 362 | /**
|
||
| 363 | * Sets the I18n domain for validation messages. This method is chainable.
|
||
| 364 | *
|
||
| 365 | * @param string $validationDomain [optional] The validation domain to be used.
|
||
| 366 | * @return $this
|
||
| 367 | */
|
||
| 368 | public function setValidationDomain($validationDomain = null) { |
||
| 369 | if (empty($validationDomain)) { |
||
| 370 | $validationDomain = 'default'; |
||
| 371 | } |
||
| 372 | $this->getModel()->validationDomain = $validationDomain; |
||
| 373 | return $this; |
||
| 374 | } |
||
| 375 | |||
| 376 | /**
|
||
| 377 | * Gets the model related to this validator
|
||
| 378 | *
|
||
| 379 | * @return Model
|
||
| 380 | */
|
||
| 381 | public function getModel() { |
||
| 382 | return $this->_model; |
||
| 383 | } |
||
| 384 | |||
| 385 | /**
|
||
| 386 | * Processes the passed fieldList and returns the list of fields to be validated
|
||
| 387 | *
|
||
| 388 | * @param array $fieldList list of fields to be used for validation
|
||
| 389 | * @return array List of validation rules to be applied
|
||
| 390 | */
|
||
| 391 | protected function _validationList($fieldList = array()) { |
||
| 392 | if (empty($fieldList) || Hash::dimensions($fieldList) > 1) { |
||
| 393 | return $this->_fields; |
||
| 394 | } |
||
| 395 | |||
| 396 | $validateList = array(); |
||
| 397 | $this->validationErrors = array(); |
||
| 398 | foreach ((array)$fieldList as $f) { |
||
| 399 | if (!empty($this->_fields[$f])) { |
||
| 400 | $validateList[$f] = $this->_fields[$f]; |
||
| 401 | } |
||
| 402 | } |
||
| 403 | |||
| 404 | return $validateList; |
||
| 405 | } |
||
| 406 | |||
| 407 | /**
|
||
| 408 | * Runs validation for hasAndBelongsToMany associations that have 'with' keys
|
||
| 409 | * set and data in the data set.
|
||
| 410 | *
|
||
| 411 | * @param array $options Array of options to use on Validation of with models
|
||
| 412 | * @return bool Failure of validation on with models.
|
||
| 413 | * @see Model::validates()
|
||
| 414 | */
|
||
| 415 | protected function _validateWithModels($options) { |
||
| 416 | $valid = true; |
||
| 417 | $model = $this->getModel(); |
||
| 418 | |||
| 419 | foreach ($model->hasAndBelongsToMany as $assoc => $association) { |
||
| 420 | if (empty($association['with']) || !isset($model->data[$assoc])) { |
||
| 421 | continue;
|
||
| 422 | } |
||
| 423 | list($join) = $model->joinModel($model->hasAndBelongsToMany[$assoc]['with']); |
||
| 424 | $data = $model->data[$assoc]; |
||
| 425 | |||
| 426 | $newData = array(); |
||
| 427 | foreach ((array)$data as $row) { |
||
| 428 | if (isset($row[$model->hasAndBelongsToMany[$assoc]['associationForeignKey']])) { |
||
| 429 | $newData[] = $row; |
||
| 430 | } elseif (isset($row[$join]) && isset($row[$join][$model->hasAndBelongsToMany[$assoc]['associationForeignKey']])) { |
||
| 431 | $newData[] = $row[$join]; |
||
| 432 | } |
||
| 433 | } |
||
| 434 | foreach ($newData as $data) { |
||
| 435 | $data[$model->hasAndBelongsToMany[$assoc]['foreignKey']] = $model->id; |
||
| 436 | $model->{$join}->create($data); |
||
| 437 | $valid = ($valid && $model->{$join}->validator()->validates($options)); |
||
| 438 | } |
||
| 439 | } |
||
| 440 | return $valid; |
||
| 441 | } |
||
| 442 | |||
| 443 | /**
|
||
| 444 | * Propagates beforeValidate event
|
||
| 445 | *
|
||
| 446 | * @param array $options Options to pass to callback.
|
||
| 447 | * @return bool
|
||
| 448 | * @triggers Model.beforeValidate $model, array($options)
|
||
| 449 | */
|
||
| 450 | protected function _triggerBeforeValidate($options = array()) { |
||
| 451 | $model = $this->getModel(); |
||
| 452 | $event = new CakeEvent('Model.beforeValidate', $model, array($options)); |
||
| 453 | list($event->break, $event->breakOn) = array(true, false); |
||
| 454 | $model->getEventManager()->dispatch($event); |
||
| 455 | if ($event->isStopped()) { |
||
| 456 | return false; |
||
| 457 | } |
||
| 458 | return true; |
||
| 459 | } |
||
| 460 | |||
| 461 | /**
|
||
| 462 | * Returns whether a rule set is defined for a field or not
|
||
| 463 | *
|
||
| 464 | * @param string $field name of the field to check
|
||
| 465 | * @return bool
|
||
| 466 | */
|
||
| 467 | public function offsetExists($field) { |
||
| 468 | $this->_parseRules();
|
||
| 469 | return isset($this->_fields[$field]); |
||
| 470 | } |
||
| 471 | |||
| 472 | /**
|
||
| 473 | * Returns the rule set for a field
|
||
| 474 | *
|
||
| 475 | * @param string $field name of the field to check
|
||
| 476 | * @return CakeValidationSet
|
||
| 477 | */
|
||
| 478 | public function offsetGet($field) { |
||
| 479 | $this->_parseRules();
|
||
| 480 | return $this->_fields[$field]; |
||
| 481 | } |
||
| 482 | |||
| 483 | /**
|
||
| 484 | * Sets the rule set for a field
|
||
| 485 | *
|
||
| 486 | * @param string $field name of the field to set
|
||
| 487 | * @param array|CakeValidationSet $rules set of rules to apply to field
|
||
| 488 | * @return void
|
||
| 489 | */
|
||
| 490 | public function offsetSet($field, $rules) { |
||
| 491 | $this->_parseRules();
|
||
| 492 | if (!$rules instanceof CakeValidationSet) { |
||
| 493 | $rules = new CakeValidationSet($field, $rules); |
||
| 494 | $methods = $this->getMethods(); |
||
| 495 | $rules->setMethods($methods); |
||
| 496 | } |
||
| 497 | $this->_fields[$field] = $rules; |
||
| 498 | } |
||
| 499 | |||
| 500 | /**
|
||
| 501 | * Unsets the rule set for a field
|
||
| 502 | *
|
||
| 503 | * @param string $field name of the field to unset
|
||
| 504 | * @return void
|
||
| 505 | */
|
||
| 506 | public function offsetUnset($field) { |
||
| 507 | $this->_parseRules();
|
||
| 508 | unset($this->_fields[$field]); |
||
| 509 | } |
||
| 510 | |||
| 511 | /**
|
||
| 512 | * Returns an iterator for each of the fields to be validated
|
||
| 513 | *
|
||
| 514 | * @return ArrayIterator
|
||
| 515 | */
|
||
| 516 | public function getIterator() { |
||
| 517 | $this->_parseRules();
|
||
| 518 | return new ArrayIterator($this->_fields); |
||
| 519 | } |
||
| 520 | |||
| 521 | /**
|
||
| 522 | * Returns the number of fields having validation rules
|
||
| 523 | *
|
||
| 524 | * @return int
|
||
| 525 | */
|
||
| 526 | public function count() { |
||
| 527 | $this->_parseRules();
|
||
| 528 | return count($this->_fields); |
||
| 529 | } |
||
| 530 | |||
| 531 | /**
|
||
| 532 | * Adds a new rule to a field's rule set. If second argument is an array or instance of
|
||
| 533 | * CakeValidationSet then rules list for the field will be replaced with second argument and
|
||
| 534 | * third argument will be ignored.
|
||
| 535 | *
|
||
| 536 | * ## Example:
|
||
| 537 | *
|
||
| 538 | * ```
|
||
| 539 | * $validator
|
||
| 540 | * ->add('title', 'required', array('rule' => 'notBlank', 'required' => true))
|
||
| 541 | * ->add('user_id', 'valid', array('rule' => 'numeric', 'message' => 'Invalid User'))
|
||
| 542 | *
|
||
| 543 | * $validator->add('password', array(
|
||
| 544 | * 'size' => array('rule' => array('lengthBetween', 8, 20)),
|
||
| 545 | * 'hasSpecialCharacter' => array('rule' => 'validateSpecialchar', 'message' => 'not valid')
|
||
| 546 | * ));
|
||
| 547 | * ```
|
||
| 548 | *
|
||
| 549 | * @param string $field The name of the field where the rule is to be added
|
||
| 550 | * @param string|array|CakeValidationSet $name name of the rule to be added or list of rules for the field
|
||
| 551 | * @param array|CakeValidationRule $rule or list of rules to be added to the field's rule set
|
||
| 552 | * @return $this
|
||
| 553 | */
|
||
| 554 | public function add($field, $name, $rule = null) { |
||
| 555 | $this->_parseRules();
|
||
| 556 | if ($name instanceof CakeValidationSet) { |
||
| 557 | $this->_fields[$field] = $name; |
||
| 558 | return $this; |
||
| 559 | } |
||
| 560 | |||
| 561 | if (!isset($this->_fields[$field])) { |
||
| 562 | $rule = (is_string($name)) ? array($name => $rule) : $name; |
||
| 563 | $this->_fields[$field] = new CakeValidationSet($field, $rule); |
||
| 564 | } else {
|
||
| 565 | if (is_string($name)) { |
||
| 566 | $this->_fields[$field]->setRule($name, $rule); |
||
| 567 | } else {
|
||
| 568 | $this->_fields[$field]->setRules($name); |
||
| 569 | } |
||
| 570 | } |
||
| 571 | |||
| 572 | $methods = $this->getMethods(); |
||
| 573 | $this->_fields[$field]->setMethods($methods); |
||
| 574 | |||
| 575 | return $this; |
||
| 576 | } |
||
| 577 | |||
| 578 | /**
|
||
| 579 | * Removes a rule from the set by its name
|
||
| 580 | *
|
||
| 581 | * ## Example:
|
||
| 582 | *
|
||
| 583 | * ```
|
||
| 584 | * $validator
|
||
| 585 | * ->remove('title', 'required')
|
||
| 586 | * ->remove('user_id')
|
||
| 587 | * ```
|
||
| 588 | *
|
||
| 589 | * @param string $field The name of the field from which the rule will be removed
|
||
| 590 | * @param string $rule the name of the rule to be removed
|
||
| 591 | * @return $this
|
||
| 592 | */
|
||
| 593 | public function remove($field, $rule = null) { |
||
| 594 | $this->_parseRules();
|
||
| 595 | if ($rule === null) { |
||
| 596 | unset($this->_fields[$field]); |
||
| 597 | } else {
|
||
| 598 | $this->_fields[$field]->removeRule($rule); |
||
| 599 | } |
||
| 600 | return $this; |
||
| 601 | } |
||
| 602 | } |