mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2025-01-19 11:06:15 +00:00
Merge branch '2.2-validator' into 2.2
Conflicts: lib/Cake/Model/Model.php lib/Cake/Test/Case/Model/ModelValidationTest.php
This commit is contained in:
commit
2ad406ab64
10 changed files with 2676 additions and 383 deletions
|
@ -25,6 +25,7 @@ App::uses('String', 'Utility');
|
|||
App::uses('Hash', 'Utility');
|
||||
App::uses('BehaviorCollection', 'Model');
|
||||
App::uses('ModelBehavior', 'Model');
|
||||
App::uses('ModelValidator', 'Model');
|
||||
App::uses('ConnectionManager', 'Model');
|
||||
App::uses('Xml', 'Utility');
|
||||
App::uses('CakeEvent', 'Event');
|
||||
|
@ -618,6 +619,13 @@ class Model extends Object implements CakeEventListener {
|
|||
*/
|
||||
protected $_eventManager = null;
|
||||
|
||||
/**
|
||||
* Instance of the ModelValidator
|
||||
*
|
||||
* @var ModelValidator
|
||||
*/
|
||||
protected $_validator = null;
|
||||
|
||||
/**
|
||||
* Constructor. Binds the model's database table to the object.
|
||||
*
|
||||
|
@ -736,6 +744,7 @@ class Model extends Object implements CakeEventListener {
|
|||
'Model.beforeFind' => array('callable' => 'beforeFind', 'passParams' => true),
|
||||
'Model.afterFind' => array('callable' => 'afterFind', 'passParams' => true),
|
||||
'Model.beforeValidate' => array('callable' => 'beforeValidate', 'passParams' => true),
|
||||
'Model.afterValidate' => array('callable' => 'afterValidate'),
|
||||
'Model.beforeSave' => array('callable' => 'beforeSave', 'passParams' => true),
|
||||
'Model.afterSave' => array('callable' => 'afterSave', 'passParams' => true),
|
||||
'Model.beforeDelete' => array('callable' => 'beforeDelete', 'passParams' => true),
|
||||
|
@ -969,8 +978,8 @@ class Model extends Object implements CakeEventListener {
|
|||
$value = array();
|
||||
|
||||
if (strpos($assoc, '.') !== false) {
|
||||
list($plugin, $assoc) = pluginSplit($assoc);
|
||||
$this->{$type}[$assoc] = array('className' => $plugin . '.' . $assoc);
|
||||
list($plugin, $assoc) = pluginSplit($assoc, true);
|
||||
$this->{$type}[$assoc] = array('className' => $plugin . $assoc);
|
||||
} else {
|
||||
$this->{$type}[$assoc] = $value;
|
||||
}
|
||||
|
@ -2128,32 +2137,7 @@ class Model extends Object implements CakeEventListener {
|
|||
* depending on whether each record validated successfully.
|
||||
*/
|
||||
public function validateMany(&$data, $options = array()) {
|
||||
$options = array_merge(array('atomic' => true, 'deep' => false), $options);
|
||||
$this->validationErrors = $validationErrors = $return = array();
|
||||
foreach ($data as $key => &$record) {
|
||||
if ($options['deep']) {
|
||||
$validates = $this->validateAssociated($record, $options);
|
||||
} else {
|
||||
$this->create(null);
|
||||
$validates = $this->set($record) && $this->validates($options);
|
||||
$data[$key] = $this->data;
|
||||
}
|
||||
if ($validates === false || (is_array($validates) && in_array(false, $validates, true))) {
|
||||
$validationErrors[$key] = $this->validationErrors;
|
||||
$validates = false;
|
||||
} else {
|
||||
$validates = true;
|
||||
}
|
||||
$return[$key] = $validates;
|
||||
}
|
||||
$this->validationErrors = $validationErrors;
|
||||
if (!$options['atomic']) {
|
||||
return $return;
|
||||
}
|
||||
if (empty($this->validationErrors)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return $this->validator()->validateMany($data, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2333,61 +2317,7 @@ class Model extends Object implements CakeEventListener {
|
|||
* depending on whether each record validated successfully.
|
||||
*/
|
||||
public function validateAssociated(&$data, $options = array()) {
|
||||
$options = array_merge(array('atomic' => true, 'deep' => false), $options);
|
||||
$this->validationErrors = $validationErrors = $return = array();
|
||||
$this->create(null);
|
||||
if (!($this->set($data) && $this->validates($options))) {
|
||||
$validationErrors[$this->alias] = $this->validationErrors;
|
||||
$return[$this->alias] = false;
|
||||
} else {
|
||||
$return[$this->alias] = true;
|
||||
}
|
||||
$data = $this->data;
|
||||
if (!empty($options['deep']) && isset($data[$this->alias])) {
|
||||
$recordData = $data[$this->alias];
|
||||
unset($data[$this->alias]);
|
||||
$data = array_merge($data, $recordData);
|
||||
}
|
||||
|
||||
$associations = $this->getAssociated();
|
||||
foreach ($data as $association => &$values) {
|
||||
$validates = true;
|
||||
if (isset($associations[$association])) {
|
||||
if (in_array($associations[$association], array('belongsTo', 'hasOne'))) {
|
||||
if ($options['deep']) {
|
||||
$validates = $this->{$association}->validateAssociated($values, $options);
|
||||
} else {
|
||||
$validates = $this->{$association}->create($values) !== null && $this->{$association}->validates($options);
|
||||
}
|
||||
if (is_array($validates)) {
|
||||
if (in_array(false, $validates, true)) {
|
||||
$validates = false;
|
||||
} else {
|
||||
$validates = true;
|
||||
}
|
||||
}
|
||||
$return[$association] = $validates;
|
||||
} elseif ($associations[$association] === 'hasMany') {
|
||||
$validates = $this->{$association}->validateMany($values, $options);
|
||||
$return[$association] = $validates;
|
||||
}
|
||||
if (!$validates || (is_array($validates) && in_array(false, $validates, true))) {
|
||||
$validationErrors[$association] = $this->{$association}->validationErrors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->validationErrors = $validationErrors;
|
||||
if (isset($validationErrors[$this->alias])) {
|
||||
$this->validationErrors = $validationErrors[$this->alias];
|
||||
}
|
||||
if (!$options['atomic']) {
|
||||
return $return;
|
||||
}
|
||||
if ($return[$this->alias] === false || !empty($this->validationErrors)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return $this->validator()->validateAssociated($data, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3074,14 +3004,7 @@ class Model extends Object implements CakeEventListener {
|
|||
* @return boolean True if there are no errors
|
||||
*/
|
||||
public function validates($options = array()) {
|
||||
$errors = $this->invalidFields($options);
|
||||
if (empty($errors) && $errors !== false) {
|
||||
$errors = $this->_validateWithModels($options);
|
||||
}
|
||||
if (is_array($errors)) {
|
||||
return count($errors) === 0;
|
||||
}
|
||||
return $errors;
|
||||
return $this->validator()->validates($options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3092,205 +3015,7 @@ class Model extends Object implements CakeEventListener {
|
|||
* @see Model::validates()
|
||||
*/
|
||||
public function invalidFields($options = array()) {
|
||||
$event = new CakeEvent('Model.beforeValidate', $this, array($options));
|
||||
list($event->break, $event->breakOn) = array(true, false);
|
||||
$this->getEventManager()->dispatch($event);
|
||||
if ($event->isStopped()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($this->validate) || empty($this->validate)) {
|
||||
return $this->validationErrors;
|
||||
}
|
||||
|
||||
$data = $this->data;
|
||||
$methods = array_map('strtolower', get_class_methods($this));
|
||||
$behaviorMethods = array_keys($this->Behaviors->methods());
|
||||
|
||||
if (isset($data[$this->alias])) {
|
||||
$data = $data[$this->alias];
|
||||
} elseif (!is_array($data)) {
|
||||
$data = array();
|
||||
}
|
||||
|
||||
$exists = null;
|
||||
|
||||
$_validate = $this->validate;
|
||||
$whitelist = $this->whitelist;
|
||||
|
||||
if (!empty($options['fieldList'])) {
|
||||
if (!empty($options['fieldList'][$this->alias]) && is_array($options['fieldList'][$this->alias])) {
|
||||
$whitelist = $options['fieldList'][$this->alias];
|
||||
} else {
|
||||
$whitelist = $options['fieldList'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($whitelist)) {
|
||||
$validate = array();
|
||||
foreach ((array)$whitelist as $f) {
|
||||
if (!empty($this->validate[$f])) {
|
||||
$validate[$f] = $this->validate[$f];
|
||||
}
|
||||
}
|
||||
$this->validate = $validate;
|
||||
}
|
||||
|
||||
$validationDomain = $this->validationDomain;
|
||||
if (empty($validationDomain)) {
|
||||
$validationDomain = 'default';
|
||||
}
|
||||
|
||||
foreach ($this->validate as $fieldName => $ruleSet) {
|
||||
if (!is_array($ruleSet) || (is_array($ruleSet) && isset($ruleSet['rule']))) {
|
||||
$ruleSet = array($ruleSet);
|
||||
}
|
||||
$default = array(
|
||||
'allowEmpty' => null,
|
||||
'required' => null,
|
||||
'rule' => 'blank',
|
||||
'last' => true,
|
||||
'on' => null
|
||||
);
|
||||
|
||||
foreach ($ruleSet as $index => $validator) {
|
||||
if (!is_array($validator)) {
|
||||
$validator = array('rule' => $validator);
|
||||
}
|
||||
$validator = array_merge($default, $validator);
|
||||
|
||||
if (!empty($validator['on']) || in_array($validator['required'], array('create', 'update'), true)) {
|
||||
if ($exists === null) {
|
||||
$exists = $this->exists();
|
||||
}
|
||||
if ($validator['on'] == 'create' && $exists || $validator['on'] == 'update' && !$exists) {
|
||||
continue;
|
||||
}
|
||||
if ($validator['required'] === 'create' && !$exists || $validator['required'] === 'update' && $exists) {
|
||||
$validator['required'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$valid = true;
|
||||
$requiredFail = (
|
||||
(!isset($data[$fieldName]) && $validator['required'] === true) ||
|
||||
(
|
||||
isset($data[$fieldName]) && (empty($data[$fieldName]) &&
|
||||
!is_numeric($data[$fieldName])) && $validator['allowEmpty'] === false
|
||||
)
|
||||
);
|
||||
|
||||
if (!$requiredFail && array_key_exists($fieldName, $data)) {
|
||||
if (empty($data[$fieldName]) && $data[$fieldName] != '0' && $validator['allowEmpty'] === true) {
|
||||
break;
|
||||
}
|
||||
if (is_array($validator['rule'])) {
|
||||
$rule = $validator['rule'][0];
|
||||
unset($validator['rule'][0]);
|
||||
$ruleParams = array_merge(array($data[$fieldName]), array_values($validator['rule']));
|
||||
} else {
|
||||
$rule = $validator['rule'];
|
||||
$ruleParams = array($data[$fieldName]);
|
||||
}
|
||||
|
||||
if (in_array(strtolower($rule), $methods)) {
|
||||
$ruleParams[] = $validator;
|
||||
$ruleParams[0] = array($fieldName => $ruleParams[0]);
|
||||
$valid = $this->dispatchMethod($rule, $ruleParams);
|
||||
} elseif (in_array($rule, $behaviorMethods) || in_array(strtolower($rule), $behaviorMethods)) {
|
||||
$ruleParams[] = $validator;
|
||||
$ruleParams[0] = array($fieldName => $ruleParams[0]);
|
||||
$valid = $this->Behaviors->dispatchMethod($this, $rule, $ruleParams);
|
||||
} elseif (method_exists('Validation', $rule)) {
|
||||
$valid = call_user_func_array(array('Validation', $rule), $ruleParams);
|
||||
} elseif (!is_array($validator['rule'])) {
|
||||
$valid = preg_match($rule, $data[$fieldName]);
|
||||
} elseif (Configure::read('debug') > 0) {
|
||||
trigger_error(__d('cake_dev', 'Could not find validation handler %s for %s', $rule, $fieldName), E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
if ($requiredFail || !$valid || (is_string($valid) && strlen($valid) > 0)) {
|
||||
if (is_string($valid)) {
|
||||
$message = $valid;
|
||||
} elseif (isset($validator['message'])) {
|
||||
$args = null;
|
||||
if (is_array($validator['message'])) {
|
||||
$message = $validator['message'][0];
|
||||
$args = array_slice($validator['message'], 1);
|
||||
} else {
|
||||
$message = $validator['message'];
|
||||
}
|
||||
if (is_array($validator['rule']) && $args === null) {
|
||||
$args = array_slice($ruleSet[$index]['rule'], 1);
|
||||
}
|
||||
if (!empty($args)) {
|
||||
foreach ($args as $k => $arg) {
|
||||
if (is_string($arg)) {
|
||||
$args[$k] = __d($validationDomain, $arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
$message = __d($validationDomain, $message, $args);
|
||||
} elseif (is_string($index)) {
|
||||
if (is_array($validator['rule'])) {
|
||||
$args = array_slice($ruleSet[$index]['rule'], 1);
|
||||
$message = __d($validationDomain, $index, $args);
|
||||
} else {
|
||||
$message = __d($validationDomain, $index);
|
||||
}
|
||||
} elseif (!$requiredFail && is_numeric($index) && count($ruleSet) > 1) {
|
||||
$message = $index + 1;
|
||||
} else {
|
||||
$message = __d('cake_dev', 'This field cannot be left blank');
|
||||
}
|
||||
|
||||
$this->invalidate($fieldName, $message);
|
||||
if ($validator['last']) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->validate = $_validate;
|
||||
return $this->validationErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs validation for hasAndBelongsToMany associations that have 'with' keys
|
||||
* set. And data in the set() data set.
|
||||
*
|
||||
* @param array $options Array of options to use on Validation of with models
|
||||
* @return boolean Failure of validation on with models.
|
||||
* @see Model::validates()
|
||||
*/
|
||||
protected function _validateWithModels($options) {
|
||||
$valid = true;
|
||||
foreach ($this->hasAndBelongsToMany as $assoc => $association) {
|
||||
if (empty($association['with']) || !isset($this->data[$assoc])) {
|
||||
continue;
|
||||
}
|
||||
list($join) = $this->joinModel($this->hasAndBelongsToMany[$assoc]['with']);
|
||||
$data = $this->data[$assoc];
|
||||
|
||||
$newData = array();
|
||||
foreach ((array)$data as $row) {
|
||||
if (isset($row[$this->hasAndBelongsToMany[$assoc]['associationForeignKey']])) {
|
||||
$newData[] = $row;
|
||||
} elseif (isset($row[$join]) && isset($row[$join][$this->hasAndBelongsToMany[$assoc]['associationForeignKey']])) {
|
||||
$newData[] = $row[$join];
|
||||
}
|
||||
}
|
||||
if (empty($newData)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($newData as $data) {
|
||||
$data[$this->hasAndBelongsToMany[$assoc]['foreignKey']] = $this->id;
|
||||
$this->{$join}->create($data);
|
||||
$valid = ($valid && $this->{$join}->validates($options));
|
||||
}
|
||||
}
|
||||
return $valid;
|
||||
return $this->validator()->errors($options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3303,10 +3028,7 @@ class Model extends Object implements CakeEventListener {
|
|||
* @return void
|
||||
*/
|
||||
public function invalidate($field, $value = true) {
|
||||
if (!is_array($this->validationErrors)) {
|
||||
$this->validationErrors = array();
|
||||
}
|
||||
$this->validationErrors[$field][] = $value;
|
||||
$this->validator()->invalidate($field, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3615,6 +3337,14 @@ class Model extends Object implements CakeEventListener {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after data has been checked for errors
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function afterValidate() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a DataSource-level error occurs.
|
||||
*
|
||||
|
@ -3653,4 +3383,21 @@ class Model extends Object implements CakeEventListener {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retunrs an instance of a model validator for this class
|
||||
*
|
||||
* @return ModelValidator
|
||||
*/
|
||||
public function validator($instance = null) {
|
||||
if ($instance instanceof ModelValidator) {
|
||||
return $this->_validator = $instance;
|
||||
}
|
||||
|
||||
if (is_null($instance)) {
|
||||
$this->_validator = new ModelValidator($this);
|
||||
}
|
||||
|
||||
return $this->_validator;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
570
lib/Cake/Model/ModelValidator.php
Normal file
570
lib/Cake/Model/ModelValidator.php
Normal file
|
@ -0,0 +1,570 @@
|
|||
<?php
|
||||
/**
|
||||
* ModelValidator.
|
||||
*
|
||||
* Provides the Model validation logic.
|
||||
*
|
||||
* PHP versions 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @package Cake.Model
|
||||
* @since CakePHP(tm) v 2.2.0
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
|
||||
App::uses('CakeValidationSet', 'Model/Validator');
|
||||
|
||||
/**
|
||||
* ModelValidator object encapsulates all methods related to data validations for a model
|
||||
* It also provides an API to dynamically change validation rules for each model field.
|
||||
*
|
||||
* Implements ArrayAccess to easily modify rules as usually done with `Model::$validate`
|
||||
* definition array
|
||||
*
|
||||
* @package Cake.Model
|
||||
* @link http://book.cakephp.org/2.0/en/data-validation.html
|
||||
*/
|
||||
class ModelValidator implements ArrayAccess, IteratorAggregate, Countable {
|
||||
|
||||
/**
|
||||
* Holds the CakeValidationSet objects array
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_fields = array();
|
||||
|
||||
/**
|
||||
* Holds the reference to the model this Validator is attached to
|
||||
*
|
||||
* @var Model
|
||||
*/
|
||||
protected $_model = array();
|
||||
|
||||
/**
|
||||
* The validators $validate property, used for checking wheter validation
|
||||
* rules definition changed in the model and should be refreshed in this class
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_validate = array();
|
||||
|
||||
/**
|
||||
* Holds the available custom callback methods, usually taken from model methods
|
||||
* and behavior methods
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_methods = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Model $Model A reference to the Model the Validator is attached to
|
||||
*/
|
||||
public function __construct(Model $Model) {
|
||||
$this->_model = $Model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all fields pass validation. Will validate hasAndBelongsToMany associations
|
||||
* that use the 'with' key as well. Since `Model::_saveMulti` is incapable of exiting a save operation.
|
||||
*
|
||||
* Will validate the currently set data. Use `Model::set()` or `Model::create()` to set the active data.
|
||||
*
|
||||
* @param array $options An optional array of custom options to be made available in the beforeValidate callback
|
||||
* @return boolean True if there are no errors
|
||||
*/
|
||||
public function validates($options = array()) {
|
||||
$errors = $this->errors($options);
|
||||
if (empty($errors) && $errors !== false) {
|
||||
$errors = $this->_validateWithModels($options);
|
||||
}
|
||||
if (is_array($errors)) {
|
||||
return count($errors) === 0;
|
||||
}
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a single record, as well as all its directly associated records.
|
||||
*
|
||||
* #### Options
|
||||
*
|
||||
* - atomic: If true (default), returns boolean. If false returns array.
|
||||
* - fieldList: Equivalent to the $fieldList parameter in Model::save()
|
||||
* - deep: If set to true, not only directly associated data , but deeper nested associated data is validated as well.
|
||||
*
|
||||
* Warning: This method could potentially change the passed argument `$data`,
|
||||
* If you do not want this to happen, make a copy of `$data` before passing it
|
||||
* to this method
|
||||
*
|
||||
* @param array $data Record data to validate. This should be an array indexed by association name.
|
||||
* @param array $options Options to use when validating record data (see above), See also $options of validates().
|
||||
* @return array|boolean If atomic: True on success, or false on failure.
|
||||
* Otherwise: array similar to the $data array passed, but values are set to true/false
|
||||
* depending on whether each record validated successfully.
|
||||
*/
|
||||
public function validateAssociated(&$data, $options = array()) {
|
||||
$model = $this->getModel();
|
||||
$options = array_merge(array('atomic' => true, 'deep' => false), $options);
|
||||
$model->validationErrors = $validationErrors = $return = array();
|
||||
$model->create(null);
|
||||
if (!($model->set($data) && $model->validates($options))) {
|
||||
$validationErrors[$model->alias] = $model->validationErrors;
|
||||
$return[$model->alias] = false;
|
||||
} else {
|
||||
$return[$model->alias] = true;
|
||||
}
|
||||
$data = $model->data;
|
||||
if (!empty($options['deep']) && isset($data[$model->alias])) {
|
||||
$recordData = $data[$model->alias];
|
||||
unset($data[$model->alias]);
|
||||
$data = array_merge($data, $recordData);
|
||||
}
|
||||
|
||||
$associations = $model->getAssociated();
|
||||
foreach ($data as $association => &$values) {
|
||||
$validates = true;
|
||||
if (isset($associations[$association])) {
|
||||
if (in_array($associations[$association], array('belongsTo', 'hasOne'))) {
|
||||
if ($options['deep']) {
|
||||
$validates = $model->{$association}->validateAssociated($values, $options);
|
||||
} else {
|
||||
$validates = $model->{$association}->create($values) !== null && $model->{$association}->validates($options);
|
||||
}
|
||||
if (is_array($validates)) {
|
||||
if (in_array(false, $validates, true)) {
|
||||
$validates = false;
|
||||
} else {
|
||||
$validates = true;
|
||||
}
|
||||
}
|
||||
$return[$association] = $validates;
|
||||
} elseif ($associations[$association] === 'hasMany') {
|
||||
$validates = $model->{$association}->validateMany($values, $options);
|
||||
$return[$association] = $validates;
|
||||
}
|
||||
if (!$validates || (is_array($validates) && in_array(false, $validates, true))) {
|
||||
$validationErrors[$association] = $model->{$association}->validationErrors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$model->validationErrors = $validationErrors;
|
||||
if (isset($validationErrors[$model->alias])) {
|
||||
$model->validationErrors = $validationErrors[$model->alias];
|
||||
}
|
||||
if (!$options['atomic']) {
|
||||
return $return;
|
||||
}
|
||||
if ($return[$model->alias] === false || !empty($model->validationErrors)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates multiple individual records for a single model
|
||||
*
|
||||
* #### Options
|
||||
*
|
||||
* - atomic: If true (default), returns boolean. If false returns array.
|
||||
* - fieldList: Equivalent to the $fieldList parameter in Model::save()
|
||||
* - deep: If set to true, all associated data will be validated as well.
|
||||
*
|
||||
* Warning: This method could potentially change the passed argument `$data`,
|
||||
* If you do not want this to happen, make a copy of `$data` before passing it
|
||||
* to this method
|
||||
*
|
||||
* @param array $data Record data to validate. This should be a numerically-indexed array
|
||||
* @param array $options Options to use when validating record data (see above), See also $options of validates().
|
||||
* @return boolean True on success, or false on failure.
|
||||
* @return mixed If atomic: True on success, or false on failure.
|
||||
* Otherwise: array similar to the $data array passed, but values are set to true/false
|
||||
* depending on whether each record validated successfully.
|
||||
*/
|
||||
public function validateMany(&$data, $options = array()) {
|
||||
$model = $this->getModel();
|
||||
$options = array_merge(array('atomic' => true, 'deep' => false), $options);
|
||||
$model->validationErrors = $validationErrors = $return = array();
|
||||
foreach ($data as $key => &$record) {
|
||||
if ($options['deep']) {
|
||||
$validates = $model->validateAssociated($record, $options);
|
||||
} else {
|
||||
$model->create(null);
|
||||
$validates = $model->set($record) && $model->validates($options);
|
||||
$data[$key] = $model->data;
|
||||
}
|
||||
if ($validates === false || (is_array($validates) && in_array(false, $validates, true))) {
|
||||
$validationErrors[$key] = $model->validationErrors;
|
||||
$validates = false;
|
||||
} else {
|
||||
$validates = true;
|
||||
}
|
||||
$return[$key] = $validates;
|
||||
}
|
||||
$model->validationErrors = $validationErrors;
|
||||
if (!$options['atomic']) {
|
||||
return $return;
|
||||
}
|
||||
if (empty($model->validationErrors)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of fields that have failed validation. On the current model. This method will
|
||||
* actually run validation rules over data, not just return the messages.
|
||||
*
|
||||
* @param string $options An optional array of custom options to be made available in the beforeValidate callback
|
||||
* @return array Array of invalid fields
|
||||
* @see ModelValidator::validates()
|
||||
*/
|
||||
public function errors($options = array()) {
|
||||
if (!$this->_triggerBeforeValidate($options)) {
|
||||
return false;
|
||||
}
|
||||
$model = $this->getModel();
|
||||
|
||||
if (!$this->_parseRules()) {
|
||||
return $model->validationErrors;
|
||||
}
|
||||
|
||||
$fieldList = isset($options['fieldList']) ? $options['fieldList'] : array();
|
||||
$exists = $model->exists();
|
||||
$methods = $this->getMethods();
|
||||
$fields = $this->_validationList($fieldList);
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$field->setMethods($methods);
|
||||
$field->setValidationDomain($model->validationDomain);
|
||||
$data = isset($model->data[$model->alias]) ? $model->data[$model->alias] : array();
|
||||
$errors = $field->validate($data, $exists);
|
||||
foreach ($errors as $error) {
|
||||
$this->invalidate($field->field, $error);
|
||||
}
|
||||
}
|
||||
|
||||
$model->getEventManager()->dispatch(new CakeEvent('Model.afterValidate', $model));
|
||||
return $model->validationErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a field as invalid, optionally setting a message explaining
|
||||
* why the rule failed
|
||||
*
|
||||
* @param string $field The name of the field to invalidate
|
||||
* @param string $message Validation message explaining why the rule failed, defaults to true.
|
||||
* @return void
|
||||
*/
|
||||
public function invalidate($field, $message = true) {
|
||||
$this->getModel()->validationErrors[$field][] = $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all possible custom methods from the Model and attached Behaviors
|
||||
* to be used as validators
|
||||
*
|
||||
* @return array List of callables to be used as validation methods
|
||||
*/
|
||||
public function getMethods() {
|
||||
if (!empty($this->_methods)) {
|
||||
return $this->_methods;
|
||||
}
|
||||
|
||||
$methods = array();
|
||||
foreach (get_class_methods($this->_model) as $method) {
|
||||
$methods[strtolower($method)] = array($this->_model, $method);
|
||||
}
|
||||
|
||||
foreach (array_keys($this->_model->Behaviors->methods()) as $method) {
|
||||
$methods += array(strtolower($method) => array($this->_model, $method));
|
||||
}
|
||||
|
||||
return $this->_methods = $methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a CakeValidationSet object containing all validation rules for a field, if no
|
||||
* params are passed then it returns an array with all CakeValidationSet objects for each field
|
||||
*
|
||||
* @param string $name [optional] The fieldname to fetch. Defaults to null.
|
||||
* @return CakeValidationSet|array
|
||||
*/
|
||||
public function getField($name = null) {
|
||||
if ($name !== null && !empty($this->_fields[$name])) {
|
||||
return $this->_fields[$name];
|
||||
} elseif ($name !==null) {
|
||||
return null;
|
||||
}
|
||||
return $this->_fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the CakeValidationSet objects from the `Model::$validate` property
|
||||
* If `Model::$validate` is not set or empty, this method returns false. True otherwise.
|
||||
*
|
||||
* @return boolean true if `Model::$validate` was processed, false otherwise
|
||||
*/
|
||||
protected function _parseRules() {
|
||||
if ($this->_validate === $this->_model->validate) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (empty($this->_model->validate)) {
|
||||
$this->_validate = array();
|
||||
$this->_fields = array();
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->_validate = $this->_model->validate;
|
||||
$this->_fields = array();
|
||||
$methods = $this->getMethods();
|
||||
foreach ($this->_validate as $fieldName => $ruleSet) {
|
||||
$this->_fields[$fieldName] = new CakeValidationSet($fieldName, $ruleSet, $methods);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the I18n domain for validation messages. This method is chainable.
|
||||
*
|
||||
* @param string $validationDomain [optional] The validation domain to be used.
|
||||
* @return ModelValidator
|
||||
*/
|
||||
public function setValidationDomain($validationDomain = null) {
|
||||
if (empty($validationDomain)) {
|
||||
$validationDomain = 'default';
|
||||
}
|
||||
$this->getModel()->validationDomain = $validationDomain;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the model related to this validator
|
||||
*
|
||||
* @return Model
|
||||
*/
|
||||
public function getModel() {
|
||||
return $this->_model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the Model's whitelist or passed fieldList and returns the list of fields
|
||||
* to be validated
|
||||
*
|
||||
* @param array $fieldList list of fields to be used for validation
|
||||
* @return array List of validation rules to be applied
|
||||
*/
|
||||
protected function _validationList($fieldList = array()) {
|
||||
$model = $this->getModel();
|
||||
$whitelist = $model->whitelist;
|
||||
|
||||
if (!empty($fieldList)) {
|
||||
if (!empty($fieldList[$model->alias]) && is_array($fieldList[$model->alias])) {
|
||||
$whitelist = $fieldList[$model->alias];
|
||||
} else {
|
||||
$whitelist = $fieldList;
|
||||
}
|
||||
}
|
||||
unset($fieldList);
|
||||
|
||||
$validateList = array();
|
||||
if (!empty($whitelist)) {
|
||||
$this->validationErrors = array();
|
||||
|
||||
foreach ((array)$whitelist as $f) {
|
||||
if (!empty($this->_fields[$f])) {
|
||||
$validateList[$f] = $this->_fields[$f];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return $this->_fields;
|
||||
}
|
||||
|
||||
return $validateList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs validation for hasAndBelongsToMany associations that have 'with' keys
|
||||
* set and data in the data set.
|
||||
*
|
||||
* @param array $options Array of options to use on Validation of with models
|
||||
* @return boolean Failure of validation on with models.
|
||||
* @see Model::validates()
|
||||
*/
|
||||
protected function _validateWithModels($options) {
|
||||
$valid = true;
|
||||
$model = $this->getModel();
|
||||
|
||||
foreach ($model->hasAndBelongsToMany as $assoc => $association) {
|
||||
if (empty($association['with']) || !isset($model->data[$assoc])) {
|
||||
continue;
|
||||
}
|
||||
list($join) = $model->joinModel($model->hasAndBelongsToMany[$assoc]['with']);
|
||||
$data = $model->data[$assoc];
|
||||
|
||||
$newData = array();
|
||||
foreach ((array)$data as $row) {
|
||||
if (isset($row[$model->hasAndBelongsToMany[$assoc]['associationForeignKey']])) {
|
||||
$newData[] = $row;
|
||||
} elseif (isset($row[$join]) && isset($row[$join][$model->hasAndBelongsToMany[$assoc]['associationForeignKey']])) {
|
||||
$newData[] = $row[$join];
|
||||
}
|
||||
}
|
||||
if (empty($newData)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($newData as $data) {
|
||||
$data[$model->hasAndBelongsToMany[$assoc]['foreignKey']] = $model->id;
|
||||
$model->{$join}->create($data);
|
||||
$valid = ($valid && $model->{$join}->validator()->validates($options));
|
||||
}
|
||||
}
|
||||
return $valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Propagates beforeValidate event
|
||||
*
|
||||
* @param array $options
|
||||
* @return boolean
|
||||
*/
|
||||
protected function _triggerBeforeValidate($options = array()) {
|
||||
$model = $this->getModel();
|
||||
$event = new CakeEvent('Model.beforeValidate', $model, array($options));
|
||||
list($event->break, $event->breakOn) = array(true, false);
|
||||
$model->getEventManager()->dispatch($event);
|
||||
if ($event->isStopped()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns wheter a rule set is defined for a field or not
|
||||
*
|
||||
* @param string $field name of the field to check
|
||||
* @return boolean
|
||||
**/
|
||||
public function offsetExists($field) {
|
||||
$this->_parseRules();
|
||||
return isset($this->_fields[$field]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rule set for a field
|
||||
*
|
||||
* @param string $field name of the field to check
|
||||
* @return CakeValidationSet
|
||||
**/
|
||||
public function offsetGet($field) {
|
||||
$this->_parseRules();
|
||||
return $this->_fields[$field];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the rule set for a field
|
||||
*
|
||||
* @param string $field name of the field to set
|
||||
* @param array|CakeValidationSet $rules set of rules to apply to field
|
||||
* @return void
|
||||
**/
|
||||
public function offsetSet($field, $rules) {
|
||||
$this->_parseRules();
|
||||
if (!$rules instanceof CakeValidationSet) {
|
||||
$rules = new CakeValidationSet($field, $rules, $this->getMethods());
|
||||
}
|
||||
$this->_fields[$field] = $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets the rulset for a field
|
||||
*
|
||||
* @param string $field name of the field to unset
|
||||
* @return void
|
||||
**/
|
||||
public function offsetUnset($field) {
|
||||
$this->_parseRules();
|
||||
unset($this->_fields[$field]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator for each of the fields to be validated
|
||||
*
|
||||
* @return ArrayIterator
|
||||
**/
|
||||
public function getIterator() {
|
||||
$this->_parseRules();
|
||||
return new ArrayIterator($this->_fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of fields having validation rules
|
||||
*
|
||||
* @return int
|
||||
**/
|
||||
public function count() {
|
||||
$this->_parseRules();
|
||||
return count($this->_fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new rule to a field's rule set
|
||||
*
|
||||
* ## Example:
|
||||
*
|
||||
* {{{
|
||||
* $validator
|
||||
* ->add('title', 'required', array('rule' => 'notEmpty', 'required' => true))
|
||||
* ->add('user_id', 'valid', array('rule' => 'numeric', 'message' => 'Invalid User'))
|
||||
* }}}
|
||||
*
|
||||
* @param string $field The name of the field from wich the rule will be removed
|
||||
* @param array|CakeValidationRule $rule the rule to be added to the field's rule set
|
||||
* @return ModelValidator this instance
|
||||
**/
|
||||
public function add($field, $name, $rule) {
|
||||
$this->_parseRules();
|
||||
if (!isset($this->_fields[$field])) {
|
||||
$rule = array($name => $rule);
|
||||
$this->_fields[$field] = new CakeValidationSet($field, $rule, $this->getMethods());
|
||||
} else {
|
||||
$this->_fields[$field]->setRule($name, $rule);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a rule from the set by its name
|
||||
*
|
||||
* ## Example:
|
||||
*
|
||||
* {{{
|
||||
* $validator
|
||||
* ->remove('title', 'required')
|
||||
* ->remove('user_id')
|
||||
* }}}
|
||||
*
|
||||
* @param string $field The name of the field from wich the rule will be removed
|
||||
* @param string $rule the name of the rule to be removed
|
||||
* @return ModelValidator this instance
|
||||
**/
|
||||
public function remove($field, $rule = null) {
|
||||
$this->_parseRules();
|
||||
if ($rule === null) {
|
||||
unset($this->_fields[$field]);
|
||||
} else {
|
||||
$this->_fields[$field]->removeRule($rule);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
333
lib/Cake/Model/Validator/CakeValidationRule.php
Normal file
333
lib/Cake/Model/Validator/CakeValidationRule.php
Normal file
|
@ -0,0 +1,333 @@
|
|||
<?php
|
||||
/**
|
||||
* CakeValidationRule.
|
||||
*
|
||||
* Provides the Model validation logic.
|
||||
*
|
||||
* PHP versions 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @package Cake.Model.Validator
|
||||
* @since CakePHP(tm) v 2.2.0
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
App::uses('ModelValidator', 'Model');
|
||||
App::uses('CakeValidationSet', 'Model/Validator');
|
||||
App::uses('Validation', 'Utility');
|
||||
|
||||
/**
|
||||
* CakeValidationRule object. Represents a validation method, error message and
|
||||
* rules for applying such method to a field.
|
||||
*
|
||||
* @package Cake.Model.Validator
|
||||
* @link http://book.cakephp.org/2.0/en/data-validation.html
|
||||
*/
|
||||
class CakeValidationRule {
|
||||
|
||||
/**
|
||||
* Whether the field passed this validation rule
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $_valid = true;
|
||||
|
||||
/**
|
||||
* Holds whether the record being validated exists in datasource or not
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_recordExists = false;
|
||||
|
||||
/**
|
||||
* Validation method
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $_rule = null;
|
||||
|
||||
/**
|
||||
* Validation method arguments
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_ruleParams = array();
|
||||
|
||||
/**
|
||||
* Holds passed in options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_passedOptions = array();
|
||||
|
||||
/**
|
||||
* The 'rule' key
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
public $rule = 'blank';
|
||||
|
||||
/**
|
||||
* The 'required' key
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
public $required = null;
|
||||
|
||||
/**
|
||||
* The 'allowEmpty' key
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $allowEmpty = false;
|
||||
|
||||
/**
|
||||
* The 'on' key
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $on = null;
|
||||
|
||||
/**
|
||||
* The 'last' key
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $last = true;
|
||||
|
||||
/**
|
||||
* The 'message' key
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $message = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $validator [optional] The validator properties
|
||||
*/
|
||||
public function __construct($validator = array()) {
|
||||
$this->_addValidatorProps($validator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the rule is valid
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isValid() {
|
||||
if (!$this->_valid || (is_string($this->_valid) && !empty($this->_valid))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the field can be left blank according to this rule
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isEmptyAllowed() {
|
||||
return $this->skip() || $this->allowEmpty === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the field is required according to the `required` property
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isRequired() {
|
||||
if (in_array($this->required, array('create', 'update'), true)) {
|
||||
if ($this->required === 'create' && !$this->isUpdate() || $this->required === 'update' && $this->isUpdate()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->required;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the field failed the `field should be present` validation
|
||||
*
|
||||
* @param array $data data to check rule against
|
||||
* @return boolean
|
||||
*/
|
||||
public function checkRequired($field, &$data) {
|
||||
return (
|
||||
(!isset($data[$field]) && $this->isRequired() === true) ||
|
||||
(
|
||||
isset($data[$field]) && (empty($data[$field]) &&
|
||||
!is_numeric($data[$field])) && $this->allowEmpty === false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the allowEmpty key applies
|
||||
*
|
||||
* @param array $data data to check rule against
|
||||
* @return boolean
|
||||
*/
|
||||
public function checkEmpty($field, &$data) {
|
||||
if (empty($data[$field]) && $data[$field] != '0' && $this->allowEmpty === true) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the validation rule should be skipped
|
||||
*
|
||||
* @return boolean True if the ValidationRule can be skipped
|
||||
*/
|
||||
public function skip() {
|
||||
if (!empty($this->on)) {
|
||||
if ($this->on == 'create' && $this->isUpdate() || $this->on == 'update' && !$this->isUpdate()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whethere this rule should break validation process for associated field
|
||||
* after it fails
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isLast() {
|
||||
return (bool) $this->last;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the validation error message
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getValidationResult() {
|
||||
return $this->_valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array with the rule properties
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function _getPropertiesArray() {
|
||||
$rule = $this->rule;
|
||||
if (!is_string($rule)) {
|
||||
unset($rule[0]);
|
||||
}
|
||||
return array(
|
||||
'rule' => $rule,
|
||||
'required' => $this->required,
|
||||
'allowEmpty' => $this->allowEmpty,
|
||||
'on' => $this->on,
|
||||
'last' => $this->last,
|
||||
'message' => $this->message
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the recordExists configuration value for this rule,
|
||||
* ir refers to wheter the model record it is validating exists
|
||||
* exists in the collection or not (create or update operation)
|
||||
*
|
||||
* If called with no parameters it will return whether this rule
|
||||
* is configured for update operations or not.
|
||||
*
|
||||
* @return boolean
|
||||
**/
|
||||
public function isUpdate($exists = null) {
|
||||
if ($exists === null) {
|
||||
return $this->_recordExists;
|
||||
}
|
||||
return $this->_recordExists = $exists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the validation rule to the given validator method
|
||||
*
|
||||
* @return boolean True if the rule could be dispatched, false otherwise
|
||||
*/
|
||||
public function process($field, &$data, &$methods) {
|
||||
$this->_valid = true;
|
||||
$this->_parseRule($field, $data);
|
||||
|
||||
$validator = $this->_getPropertiesArray();
|
||||
$rule = strtolower($this->_rule);
|
||||
if (isset($methods[$rule])) {
|
||||
$this->_ruleParams[] = array_merge($validator, $this->_passedOptions);
|
||||
$this->_ruleParams[0] = array($field => $this->_ruleParams[0]);
|
||||
$this->_valid = call_user_func_array($methods[$rule], $this->_ruleParams);
|
||||
} elseif (class_exists('Validation') && method_exists('Validation', $this->_rule)) {
|
||||
$this->_valid = call_user_func_array(array('Validation', $this->_rule), $this->_ruleParams);
|
||||
} elseif (is_string($validator['rule'])) {
|
||||
$this->_valid = preg_match($this->_rule, $data[$field]);
|
||||
} elseif (Configure::read('debug') > 0) {
|
||||
trigger_error(__d('cake_dev', 'Could not find validation handler %s for %s', $this->_rule, $field), E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns passed options for this rule
|
||||
*
|
||||
* @return array
|
||||
**/
|
||||
public function getOptions($key) {
|
||||
if (!isset($this->_passedOptions[$key])) {
|
||||
return null;
|
||||
}
|
||||
return $this->_passedOptions[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the rule properties from the rule entry in validate
|
||||
*
|
||||
* @param array $validator [optional]
|
||||
* @return void
|
||||
*/
|
||||
protected function _addValidatorProps($validator = array()) {
|
||||
if (!is_array($validator)) {
|
||||
$validator = array('rule' => $validator);
|
||||
}
|
||||
foreach ($validator as $key => $value) {
|
||||
if (isset($value) || !empty($value)) {
|
||||
if (in_array($key, array('rule', 'required', 'allowEmpty', 'on', 'message', 'last'))) {
|
||||
$this->{$key} = $validator[$key];
|
||||
} else {
|
||||
$this->_passedOptions[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the rule and sets the rule and ruleParams
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function _parseRule($field, &$data) {
|
||||
if (is_array($this->rule)) {
|
||||
$this->_rule = $this->rule[0];
|
||||
$this->_ruleParams = array_merge(array($data[$field]), array_values(array_slice($this->rule, 1)));
|
||||
} else {
|
||||
$this->_rule = $this->rule;
|
||||
$this->_ruleParams = array($data[$field]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
343
lib/Cake/Model/Validator/CakeValidationSet.php
Normal file
343
lib/Cake/Model/Validator/CakeValidationSet.php
Normal file
|
@ -0,0 +1,343 @@
|
|||
<?php
|
||||
/**
|
||||
* CakeValidationSet.
|
||||
*
|
||||
* Provides the Model validation logic.
|
||||
*
|
||||
* PHP versions 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @package Cake.Model.Validator
|
||||
* @since CakePHP(tm) v 2.2.0
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
App::uses('ModelValidator', 'Model');
|
||||
App::uses('CakeValidationRule', 'Model/Validator');
|
||||
|
||||
/**
|
||||
* CakeValidationSet object. Holds all validation rules for a field and exposes
|
||||
* methods to dynamically add or remove validation rules
|
||||
*
|
||||
* @package Cake.Model.Validator
|
||||
* @link http://book.cakephp.org/2.0/en/data-validation.html
|
||||
*/
|
||||
class CakeValidationSet implements ArrayAccess, IteratorAggregate, Countable {
|
||||
|
||||
/**
|
||||
* Holds the CakeValidationRule objects
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_rules = array();
|
||||
|
||||
/**
|
||||
* List of methods available for validation
|
||||
*
|
||||
* @var array
|
||||
**/
|
||||
protected $_methods = array();
|
||||
|
||||
/**
|
||||
* I18n domain for validation messages.
|
||||
*
|
||||
* @var string
|
||||
**/
|
||||
protected $_validationDomain = null;
|
||||
|
||||
/**
|
||||
* Whether the validation is stopped
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $isStopped = false;
|
||||
|
||||
/**
|
||||
* Holds the fieldname
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $field = null;
|
||||
|
||||
/**
|
||||
* Holds the original ruleSet
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $ruleSet = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $fieldName The fieldname
|
||||
* @param array $ruleset
|
||||
*/
|
||||
public function __construct($fieldName, $ruleSet) {
|
||||
$this->field = $fieldName;
|
||||
|
||||
if (!is_array($ruleSet) || (is_array($ruleSet) && isset($ruleSet['rule']))) {
|
||||
$ruleSet = array($ruleSet);
|
||||
}
|
||||
|
||||
foreach ($ruleSet as $index => $validateProp) {
|
||||
$this->_rules[$index] = new CakeValidationRule($validateProp);
|
||||
}
|
||||
$this->ruleSet = $ruleSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of methods to use for validation
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
public function setMethods(&$methods) {
|
||||
$this->_methods =& $methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the I18n domain for validation messages.
|
||||
*
|
||||
* @param string $validationDomain The validation domain to be used.
|
||||
* @return void
|
||||
*/
|
||||
public function setValidationDomain($validationDomain) {
|
||||
$this->_validationDomain = $validationDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all validation rules in this set and returns a list of
|
||||
* validation errors
|
||||
*
|
||||
* @return array list of validation errors for this field
|
||||
*/
|
||||
public function validate($data, $isUpdate = false) {
|
||||
$errors = array();
|
||||
foreach ($this->getRules() as $name => $rule) {
|
||||
$rule->isUpdate($isUpdate);
|
||||
if ($rule->skip()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$checkRequired = $rule->checkRequired($this->field, $data);
|
||||
if (!$checkRequired && array_key_exists($this->field, $data)) {
|
||||
if ($rule->checkEmpty($this->field, $data)) {
|
||||
break;
|
||||
}
|
||||
$rule->process($this->field, $data, $this->_methods);
|
||||
}
|
||||
|
||||
if ($checkRequired || !$rule->isValid()) {
|
||||
$errors[] = $this->_processValidationResponse($name, $rule);
|
||||
if ($rule->isLast()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a rule for a given name if exists
|
||||
*
|
||||
* @param string $name
|
||||
* @return CakeValidationRule
|
||||
*/
|
||||
public function getRule($name) {
|
||||
if (!empty($this->_rules[$name])) {
|
||||
return $this->_rules[$name];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all rules for this validation set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRules() {
|
||||
return $this->_rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a CakeValidationRule $rule with a $name
|
||||
*
|
||||
* ## Example:
|
||||
*
|
||||
* {{{
|
||||
* $set
|
||||
* ->setRule('required', array('rule' => 'notEmpty', 'required' => true))
|
||||
* ->setRule('inRange', array('rule' => array('between', 4, 10))
|
||||
* }}}
|
||||
*
|
||||
* @param mixed $name The name under which the rule should be set
|
||||
* @param CakeValidationRule|array $rule The validation rule to be set
|
||||
* @return CakeValidationSet this instance
|
||||
*/
|
||||
public function setRule($name, $rule) {
|
||||
if (!$rule instanceof CakeValidationRule) {
|
||||
$rule = new CakeValidationRule($rule);
|
||||
}
|
||||
$this->_rules[$name] = $rule;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a validation rule from the set
|
||||
*
|
||||
* ## Example:
|
||||
*
|
||||
* {{{
|
||||
* $set
|
||||
* ->removeRule('required')
|
||||
* ->removeRule('inRange')
|
||||
* }}}
|
||||
*
|
||||
* @param mixed $name The name under which the rule should be unset
|
||||
* @return CakeValidationSet this instance
|
||||
*/
|
||||
public function removeRule($name) {
|
||||
unset($this->_rules[$name]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the rules for a given field
|
||||
*
|
||||
* ## Example:
|
||||
*
|
||||
* {{{
|
||||
* $set->setRules(array(
|
||||
* 'required' => array('rule' => 'notEmpty', 'required' => true),
|
||||
* 'inRange' => array('rule' => array('between', 4, 10)
|
||||
* ));
|
||||
* }}}
|
||||
*
|
||||
* @param array $rules The rules to be set
|
||||
* @param bolean $mergeVars [optional] If true, merges vars instead of replace. Defaults to true.
|
||||
* @return ModelField
|
||||
*/
|
||||
public function setRules($rules = array(), $mergeVars = true) {
|
||||
if ($mergeVars === false) {
|
||||
$this->_rules = $rules;
|
||||
} else {
|
||||
$this->_rules = array_merge($this->_rules, $rules);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the correct error message for a failed validation
|
||||
*
|
||||
* @param string $name the name of the rule as it was configured
|
||||
* @param CakeValidationRule $rule the object containing validation information
|
||||
* @return string
|
||||
*/
|
||||
protected function _processValidationResponse($name, $rule) {
|
||||
$message = $rule->getValidationResult();
|
||||
if (is_string($message)) {
|
||||
return $message;
|
||||
}
|
||||
$message = $rule->message;
|
||||
|
||||
if ($message !== null) {
|
||||
$args = null;
|
||||
if (is_array($message)) {
|
||||
$result = $message[0];
|
||||
$args = array_slice($message, 1);
|
||||
} else {
|
||||
$result = $message;
|
||||
}
|
||||
if (is_array($rule->rule) && $args === null) {
|
||||
$args = array_slice($rule->rule, 1);
|
||||
}
|
||||
if (!empty($args)) {
|
||||
foreach ($args as $k => $arg) {
|
||||
$args[$k] = __d($this->_validationDomain, $arg);
|
||||
}
|
||||
}
|
||||
|
||||
$message = __d($this->_validationDomain, $result, $args);
|
||||
} elseif (is_string($name)) {
|
||||
if (is_array($rule->rule)) {
|
||||
$args = array_slice($rule->rule, 1);
|
||||
if (!empty($args)) {
|
||||
foreach ($args as $k => $arg) {
|
||||
$args[$k] = __d($this->_validationDomain, $arg);
|
||||
}
|
||||
}
|
||||
$message = __d($this->_validationDomain, $name, $args);
|
||||
} else {
|
||||
$message = __d($this->_validationDomain, $name);
|
||||
}
|
||||
} else {
|
||||
$message = __d('cake_dev', 'This field cannot be left blank');
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns wheter an index exists in the rule set
|
||||
*
|
||||
* @param string $index name of the rule
|
||||
* @return boolean
|
||||
**/
|
||||
public function offsetExists($index) {
|
||||
return isset($this->_rules[$index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rule object by its index
|
||||
*
|
||||
* @param string $index name of the rule
|
||||
* @return CakeValidationRule
|
||||
**/
|
||||
public function offsetGet($index) {
|
||||
return $this->_rules[$index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or replace a validation rule
|
||||
*
|
||||
* @param string $index name of the rule
|
||||
* @param CakeValidationRule|array rule to add to $index
|
||||
**/
|
||||
public function offsetSet($index, $rule) {
|
||||
$this->setRule($index, $rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets a validation rule
|
||||
*
|
||||
* @param string $index name of the rule
|
||||
* @return void
|
||||
**/
|
||||
public function offsetUnset($index) {
|
||||
unset($this->_rules[$index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator for each of the rules to be applied
|
||||
*
|
||||
* @return ArrayIterator
|
||||
**/
|
||||
public function getIterator() {
|
||||
return new ArrayIterator($this->_rules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of rules in this set
|
||||
*
|
||||
* @return int
|
||||
**/
|
||||
public function count() {
|
||||
return count($this->_rules);
|
||||
}
|
||||
|
||||
}
|
|
@ -34,6 +34,8 @@ class ModelTest extends PHPUnit_Framework_TestSuite {
|
|||
public static function suite() {
|
||||
$suite = new PHPUnit_Framework_TestSuite('All Model related class tests');
|
||||
|
||||
$suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'Validator' . DS .'CakeValidationSetTest.php');
|
||||
$suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'Validator' . DS .'CakeValidationRuleTest.php');
|
||||
$suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'ModelReadTest.php');
|
||||
$suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'ModelWriteTest.php');
|
||||
$suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'ModelDeleteTest.php');
|
||||
|
|
|
@ -48,7 +48,8 @@ class ModelValidationTest extends BaseModelTest {
|
|||
'on' => null,
|
||||
'last' => true,
|
||||
'allowEmpty' => false,
|
||||
'required' => true
|
||||
'required' => true,
|
||||
'message' => null
|
||||
),
|
||||
'or' => true,
|
||||
'ignoreOnSame' => 'id'
|
||||
|
@ -84,7 +85,8 @@ class ModelValidationTest extends BaseModelTest {
|
|||
'on' => null,
|
||||
'last' => true,
|
||||
'allowEmpty' => false,
|
||||
'required' => true
|
||||
'required' => true,
|
||||
'message' => null
|
||||
),
|
||||
'six' => 6
|
||||
);
|
||||
|
@ -110,7 +112,8 @@ class ModelValidationTest extends BaseModelTest {
|
|||
'on' => null,
|
||||
'last' => true,
|
||||
'allowEmpty' => false,
|
||||
'required' => true
|
||||
'required' => true,
|
||||
'message' => null
|
||||
)
|
||||
);
|
||||
$this->assertEquals($expected, $TestModel->validatorParams);
|
||||
|
@ -537,6 +540,8 @@ class ModelValidationTest extends BaseModelTest {
|
|||
'title' => array('tooShort', 'onlyLetters')
|
||||
);
|
||||
$this->assertEquals($expected, $result);
|
||||
$result = $TestModel->validationErrors;
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -601,6 +606,7 @@ class ModelValidationTest extends BaseModelTest {
|
|||
* @return void
|
||||
*/
|
||||
public function testValidatesWithModelsAndSaveAll() {
|
||||
$this->loadFixtures('Something', 'SomethingElse', 'JoinThing');
|
||||
$data = array(
|
||||
'Something' => array(
|
||||
'id' => 5,
|
||||
|
@ -621,7 +627,11 @@ class ModelValidationTest extends BaseModelTest {
|
|||
$Something->create();
|
||||
$result = $Something->saveAll($data, array('validate' => 'only'));
|
||||
$this->assertFalse($result);
|
||||
$result = $Something->validateAssociated($data);
|
||||
$this->assertFalse($result);
|
||||
$this->assertEquals($expectedError, $JoinThing->validationErrors);
|
||||
$result = $Something->validator()->validateAssociated($data);
|
||||
$this->assertFalse($result);
|
||||
|
||||
$Something->create();
|
||||
$result = $Something->saveAll($data, array('validate' => 'first'));
|
||||
|
@ -663,6 +673,9 @@ class ModelValidationTest extends BaseModelTest {
|
|||
$Author->create();
|
||||
$result = $Author->saveAll($data, array('validate' => 'only'));
|
||||
$this->assertTrue($result);
|
||||
$result = $Author->validateAssociated($data);
|
||||
$this->assertTrue($result);
|
||||
$this->assertTrue($result);
|
||||
|
||||
$Author->create();
|
||||
$result = $Author->saveAll($data, array('validate' => 'first'));
|
||||
|
@ -742,22 +755,22 @@ class ModelValidationTest extends BaseModelTest {
|
|||
);
|
||||
|
||||
$TestModel->create();
|
||||
$TestModel->invalidFields();
|
||||
$expected = array(
|
||||
'title' => array(
|
||||
'Minimum length allowed is 6 chars',
|
||||
)
|
||||
);
|
||||
$TestModel->invalidFields();
|
||||
$this->assertEquals($expected, $TestModel->validationErrors);
|
||||
|
||||
$TestModel->create(array('title' => 'foo'));
|
||||
$TestModel->invalidFields();
|
||||
$expected = array(
|
||||
'title' => array(
|
||||
'Minimum length allowed is 6 chars',
|
||||
'You may enter up to 14 chars (minimum is 6 chars)'
|
||||
)
|
||||
);
|
||||
$TestModel->invalidFields();
|
||||
$this->assertEquals($expected, $TestModel->validationErrors);
|
||||
}
|
||||
|
||||
|
@ -786,12 +799,12 @@ class ModelValidationTest extends BaseModelTest {
|
|||
);
|
||||
|
||||
$TestModel->create();
|
||||
$TestModel->invalidFields();
|
||||
$expected = array(
|
||||
'title' => array(
|
||||
'Translated validation failed: Translated arg1',
|
||||
)
|
||||
);
|
||||
$TestModel->invalidFields();
|
||||
$this->assertEquals($expected, $TestModel->validationErrors);
|
||||
|
||||
$TestModel->validationDomain = 'default';
|
||||
|
@ -1029,6 +1042,864 @@ class ModelValidationTest extends BaseModelTest {
|
|||
$this->assertFalse($Article->validates());
|
||||
}
|
||||
|
||||
/**
|
||||
* testSaveAllDeepValidateOnly
|
||||
* tests the validate methods with deeper recursive data
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSaveAllDeepValidateOnly() {
|
||||
$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
|
||||
$TestModel = new Article();
|
||||
$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
|
||||
$TestModel->hasAndBelongsToMany = array();
|
||||
$TestModel->Comment->Attachment->validate['attachment'] = 'notEmpty';
|
||||
$TestModel->Comment->validate['comment'] = 'notEmpty';
|
||||
|
||||
$data = array(
|
||||
'Article' => array('id' => 2),
|
||||
'Comment' => array(
|
||||
array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
|
||||
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
|
||||
)
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true));
|
||||
$this->assertTrue($result);
|
||||
$result = $TestModel->validateAssociated($data, array('deep' => true));
|
||||
$this->assertTrue($result);
|
||||
|
||||
$data = array(
|
||||
'Article' => array('id' => 2),
|
||||
'Comment' => array(
|
||||
array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
|
||||
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
|
||||
)
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true));
|
||||
$this->assertFalse($result);
|
||||
$result = $TestModel->validateAssociated($data, array('deep' => true));
|
||||
$this->assertFalse($result);
|
||||
|
||||
$data = array(
|
||||
'Article' => array('id' => 2),
|
||||
'Comment' => array(
|
||||
array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
|
||||
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
|
||||
)
|
||||
);
|
||||
$expected = array(
|
||||
'Article' => true,
|
||||
'Comment' => array(
|
||||
true,
|
||||
true
|
||||
)
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
|
||||
$this->assertSame($expected, $result);
|
||||
$result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true));
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$data = array(
|
||||
'Article' => array('id' => 2),
|
||||
'Comment' => array(
|
||||
array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
|
||||
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
|
||||
)
|
||||
);
|
||||
$expected = array(
|
||||
'Article' => true,
|
||||
'Comment' => array(
|
||||
false,
|
||||
true
|
||||
)
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
|
||||
$this->assertSame($expected, $result);
|
||||
$result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true));
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$data = array(
|
||||
'Article' => array('id' => 2),
|
||||
'Comment' => array(
|
||||
array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
|
||||
array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsaved'))
|
||||
)
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true));
|
||||
$this->assertTrue($result);
|
||||
$result = $TestModel->validateAssociated($data, array('deep' => true));
|
||||
$this->assertTrue($result);
|
||||
|
||||
$data = array(
|
||||
'Article' => array('id' => 2),
|
||||
'Comment' => array(
|
||||
array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
|
||||
array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
|
||||
)
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true));
|
||||
$this->assertFalse($result);
|
||||
$result = $TestModel->validateAssociated($data, array('deep' => true));
|
||||
$this->assertFalse($result);
|
||||
|
||||
$data = array(
|
||||
'Article' => array('id' => 2),
|
||||
'Comment' => array(
|
||||
array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
|
||||
array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsave'))
|
||||
)
|
||||
);
|
||||
$expected = array(
|
||||
'Article' => true,
|
||||
'Comment' => array(
|
||||
true,
|
||||
true
|
||||
)
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
|
||||
$this->assertSame($expected, $result);
|
||||
$result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true));
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$data = array(
|
||||
'Article' => array('id' => 2),
|
||||
'Comment' => array(
|
||||
array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
|
||||
array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
|
||||
)
|
||||
);
|
||||
$expected = array(
|
||||
'Article' => true,
|
||||
'Comment' => array(
|
||||
true,
|
||||
false
|
||||
)
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
|
||||
$this->assertSame($expected, $result);
|
||||
$result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true));
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$expected = array(
|
||||
'Comment' => array(
|
||||
1 => array(
|
||||
'Attachment' => array(
|
||||
'attachment' => array('This field cannot be left blank')
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
$result = $TestModel->validationErrors;
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$data = array(
|
||||
'Attachment' => array(
|
||||
'attachment' => 'deepsave insert',
|
||||
),
|
||||
'Comment' => array(
|
||||
'comment' => 'First comment deepsave insert',
|
||||
'published' => 'Y',
|
||||
'user_id' => 5,
|
||||
'Article' => array(
|
||||
'title' => 'First Article deepsave insert',
|
||||
'body' => 'First Article Body deepsave insert',
|
||||
'User' => array(
|
||||
'user' => 'deepsave',
|
||||
'password' => 'magic'
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
|
||||
$this->assertTrue($result);
|
||||
$result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => true));
|
||||
$this->assertTrue($result);
|
||||
|
||||
$expected = array(
|
||||
'Attachment' => true,
|
||||
'Comment' => true
|
||||
);
|
||||
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
|
||||
$this->assertSame($expected, $result);
|
||||
$result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$data = array(
|
||||
'Attachment' => array(
|
||||
'attachment' => 'deepsave insert',
|
||||
),
|
||||
'Comment' => array(
|
||||
'comment' => 'First comment deepsave insert',
|
||||
'published' => 'Y',
|
||||
'user_id' => 5,
|
||||
'Article' => array(
|
||||
'title' => 'First Article deepsave insert',
|
||||
'body' => 'First Article Body deepsave insert',
|
||||
'User' => array(
|
||||
'user' => '',
|
||||
'password' => 'magic'
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
|
||||
$this->assertFalse($result);
|
||||
$result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => true));
|
||||
$this->assertFalse($result);
|
||||
|
||||
$result = $TestModel->Comment->Attachment->validationErrors;
|
||||
$expected = array(
|
||||
'Comment' => array(
|
||||
'Article' => array(
|
||||
'User' => array(
|
||||
'user' => array('This field cannot be left blank')
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$expected = array(
|
||||
'Attachment' => true,
|
||||
'Comment' => false
|
||||
);
|
||||
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
|
||||
$this->assertEquals($expected, $result);
|
||||
$result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$data['Comment']['Article']['body'] = '';
|
||||
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
|
||||
$this->assertFalse($result);
|
||||
$result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => true));
|
||||
$this->assertFalse($result);
|
||||
|
||||
$result = $TestModel->Comment->Attachment->validationErrors;
|
||||
$expected = array(
|
||||
'Comment' => array(
|
||||
'Article' => array(
|
||||
'body' => array('This field cannot be left blank')
|
||||
)
|
||||
)
|
||||
);
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$expected = array(
|
||||
'Attachment' => true,
|
||||
'Comment' => false
|
||||
);
|
||||
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
|
||||
$this->assertEquals($expected, $result);
|
||||
$result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$data['Comment']['comment'] = '';
|
||||
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
|
||||
$this->assertFalse($result);
|
||||
$result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => true));
|
||||
$this->assertFalse($result);
|
||||
|
||||
$result = $TestModel->Comment->Attachment->validationErrors;
|
||||
$expected = array(
|
||||
'Comment' => array(
|
||||
'comment' => array('This field cannot be left blank')
|
||||
)
|
||||
);
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$expected = array(
|
||||
'Attachment' => true,
|
||||
'Comment' => false
|
||||
);
|
||||
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
|
||||
$this->assertEquals($expected, $result);
|
||||
$result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$data['Attachment']['attachment'] = '';
|
||||
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
|
||||
$this->assertFalse($result);
|
||||
$result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => true));
|
||||
$this->assertFalse($result);
|
||||
|
||||
$result = $TestModel->Comment->Attachment->validationErrors;
|
||||
$expected = array('attachment' => array('This field cannot be left blank'));
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$result = $TestModel->Comment->validationErrors;
|
||||
$expected = array('comment' => array('This field cannot be left blank'));
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$expected = array(
|
||||
'Attachment' => false,
|
||||
'Comment' => false
|
||||
);
|
||||
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
|
||||
$this->assertEquals($expected, $result);
|
||||
$result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* testSaveAllNotDeepValidateOnly
|
||||
* tests the validate methods to not validate deeper recursive data
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSaveAllNotDeepValidateOnly() {
|
||||
$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
|
||||
$TestModel = new Article();
|
||||
$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
|
||||
$TestModel->hasAndBelongsToMany = array();
|
||||
$TestModel->Comment->Attachment->validate['attachment'] = 'notEmpty';
|
||||
$TestModel->Comment->validate['comment'] = 'notEmpty';
|
||||
|
||||
$data = array(
|
||||
'Article' => array('id' => 2, 'body' => ''),
|
||||
'Comment' => array(
|
||||
array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
|
||||
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
|
||||
)
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => false));
|
||||
$this->assertFalse($result);
|
||||
$result = $TestModel->validateAssociated($data, array('deep' => false));
|
||||
$this->assertFalse($result);
|
||||
|
||||
$expected = array('body' => array('This field cannot be left blank'));
|
||||
$result = $TestModel->validationErrors;
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$data = array(
|
||||
'Article' => array('id' => 2, 'body' => 'Ignore invalid user data'),
|
||||
'Comment' => array(
|
||||
array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
|
||||
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
|
||||
)
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => false));
|
||||
$this->assertTrue($result);
|
||||
$result = $TestModel->validateAssociated($data, array('deep' => false));
|
||||
$this->assertTrue($result);
|
||||
|
||||
$data = array(
|
||||
'Article' => array('id' => 2, 'body' => 'Ignore invalid user data'),
|
||||
'Comment' => array(
|
||||
array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
|
||||
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
|
||||
)
|
||||
);
|
||||
$expected = array(
|
||||
'Article' => true,
|
||||
'Comment' => array(
|
||||
true,
|
||||
true
|
||||
)
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
|
||||
$this->assertSame($expected, $result);
|
||||
$result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => false));
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$data = array(
|
||||
'Article' => array('id' => 2, 'body' => 'Ignore invalid attachment data'),
|
||||
'Comment' => array(
|
||||
array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
|
||||
array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
|
||||
)
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => false));
|
||||
$this->assertTrue($result);
|
||||
$result = $TestModel->validateAssociated($data, array('deep' => false));
|
||||
$this->assertTrue($result);
|
||||
|
||||
$data = array(
|
||||
'Article' => array('id' => 2, 'body' => 'Ignore invalid attachment data'),
|
||||
'Comment' => array(
|
||||
array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
|
||||
array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
|
||||
)
|
||||
);
|
||||
$expected = array(
|
||||
'Article' => true,
|
||||
'Comment' => array(
|
||||
true,
|
||||
true
|
||||
)
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
|
||||
$this->assertSame($expected, $result);
|
||||
$result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => false));
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$expected = array();
|
||||
$result = $TestModel->validationErrors;
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$data = array(
|
||||
'Attachment' => array(
|
||||
'attachment' => 'deepsave insert',
|
||||
),
|
||||
'Comment' => array(
|
||||
'comment' => 'First comment deepsave insert',
|
||||
'published' => 'Y',
|
||||
'user_id' => 5,
|
||||
'Article' => array(
|
||||
'title' => 'First Article deepsave insert ignored',
|
||||
'body' => 'First Article Body deepsave insert',
|
||||
'User' => array(
|
||||
'user' => '',
|
||||
'password' => 'magic'
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => false));
|
||||
$this->assertTrue($result);
|
||||
$result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => false));
|
||||
$this->assertTrue($result);
|
||||
|
||||
$result = $TestModel->Comment->Attachment->validationErrors;
|
||||
$expected = array();
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$expected = array(
|
||||
'Attachment' => true,
|
||||
'Comment' => true
|
||||
);
|
||||
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
|
||||
$this->assertEquals($expected, $result);
|
||||
$result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => false));
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$data['Comment']['Article']['body'] = '';
|
||||
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => false));
|
||||
$this->assertTrue($result);
|
||||
$result = $TestModel->Comment->Attachment->validateAssociated($data, array('deep' => false));
|
||||
$this->assertTrue($result);
|
||||
|
||||
$result = $TestModel->Comment->Attachment->validationErrors;
|
||||
$expected = array();
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$expected = array(
|
||||
'Attachment' => true,
|
||||
'Comment' => true
|
||||
);
|
||||
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
|
||||
$this->assertEquals($expected, $result);
|
||||
$result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => false));
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* testValidateAssociated method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testValidateAssociated() {
|
||||
$this->loadFixtures('Comment', 'Attachment');
|
||||
$TestModel = new Comment();
|
||||
$TestModel->Attachment->validate = array('attachment' => 'notEmpty');
|
||||
|
||||
$data = array(
|
||||
'Comment' => array(
|
||||
'comment' => 'This is the comment'
|
||||
),
|
||||
'Attachment' => array(
|
||||
'attachment' => ''
|
||||
)
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only'));
|
||||
$this->assertFalse($result);
|
||||
$result = $TestModel->validateAssociated($data);
|
||||
$this->assertFalse($result);
|
||||
|
||||
$TestModel->validate = array('comment' => 'notEmpty');
|
||||
$record = array(
|
||||
'Comment' => array(
|
||||
'user_id' => 1,
|
||||
'article_id' => 1,
|
||||
'comment' => '',
|
||||
),
|
||||
'Attachment' => array(
|
||||
'attachment' => ''
|
||||
)
|
||||
);
|
||||
$result = $TestModel->saveAll($record, array('validate' => 'only'));
|
||||
$this->assertFalse($result);
|
||||
$result = $TestModel->validateAssociated($record);
|
||||
$this->assertFalse($result);
|
||||
|
||||
$fieldList = array(
|
||||
'Comment' => array('id', 'article_id', 'user_id'),
|
||||
'Attachment' => array('comment_id')
|
||||
);
|
||||
$result = $TestModel->saveAll($record, array(
|
||||
'fieldList' => $fieldList, 'validate' => 'only'
|
||||
));
|
||||
$this->assertTrue($result);
|
||||
$this->assertEmpty($TestModel->validationErrors);
|
||||
$result = $TestModel->validateAssociated($record, array('fieldList' => $fieldList));
|
||||
$this->assertTrue($result);
|
||||
$this->assertEmpty($TestModel->validationErrors);
|
||||
|
||||
$TestModel = new Article();
|
||||
$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
|
||||
$TestModel->Comment->validate = array('comment' => 'notEmpty');
|
||||
$data = array(
|
||||
'Article' => array('id' => 2),
|
||||
'Comment' => array(
|
||||
array(
|
||||
'id' => 1,
|
||||
'comment' => '',
|
||||
'published' => 'Y',
|
||||
'user_id' => 1,
|
||||
),
|
||||
array(
|
||||
'id' => 2,
|
||||
'comment' =>
|
||||
'comment',
|
||||
'published' => 'Y',
|
||||
'user_id' => 1
|
||||
),
|
||||
array(
|
||||
'id' => 3,
|
||||
'comment' => '',
|
||||
'published' => 'Y',
|
||||
'user_id' => 1
|
||||
)));
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only'));
|
||||
$this->assertFalse($result);
|
||||
$result = $TestModel->validateAssociated($data);
|
||||
$this->assertFalse($result);
|
||||
|
||||
$expected = array(
|
||||
'Article' => true,
|
||||
'Comment' => array(false, true, false)
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('atomic' => false, 'validate' => 'only'));
|
||||
$this->assertSame($expected, $result);
|
||||
$result = $TestModel->validateAssociated($data, array('atomic' => false));
|
||||
$this->assertSame($expected, $result);
|
||||
|
||||
$expected = array('Comment' => array(
|
||||
0 => array('comment' => array('This field cannot be left blank')),
|
||||
2 => array('comment' => array('This field cannot be left blank'))
|
||||
));
|
||||
$this->assertEquals($expected['Comment'], $TestModel->Comment->validationErrors);
|
||||
|
||||
$model = new Comment();
|
||||
$model->deleteAll(true);
|
||||
$model->validate = array('comment' => 'notEmpty');
|
||||
$model->Attachment->validate = array('attachment' => 'notEmpty');
|
||||
$model->Attachment->bindModel(array('belongsTo' => array('Comment')));
|
||||
$expected = array(
|
||||
'Comment' => array('comment' => array('This field cannot be left blank')),
|
||||
'Attachment' => array('attachment' => array('This field cannot be left blank'))
|
||||
);
|
||||
|
||||
$data = array(
|
||||
'Comment' => array('comment' => '', 'article_id' => 1, 'user_id' => 1),
|
||||
'Attachment' => array('attachment' => '')
|
||||
);
|
||||
$result = $model->saveAll($data, array('validate' => 'only'));
|
||||
$this->assertFalse($result);
|
||||
$result = $model->validateAssociated($data);
|
||||
$this->assertFalse($result);
|
||||
$this->assertEquals($expected['Comment'], $model->validationErrors);
|
||||
$this->assertEquals($expected['Attachment'], $model->Attachment->validationErrors);
|
||||
}
|
||||
|
||||
/**
|
||||
* testValidateMany method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testValidateMany() {
|
||||
$TestModel = new Article();
|
||||
$TestModel->validate = array('title' => 'notEmpty');
|
||||
$data = array(
|
||||
0 => array('title' => ''),
|
||||
1 => array('title' => 'title 1'),
|
||||
2 => array('title' => 'title 2'),
|
||||
);
|
||||
$expected = array(
|
||||
0 => array('title' => array('This field cannot be left blank')),
|
||||
);
|
||||
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only'));
|
||||
$this->assertFalse($result);
|
||||
$this->assertEquals($expected, $TestModel->validationErrors);
|
||||
$result = $TestModel->validateMany($data);
|
||||
$this->assertFalse($result);
|
||||
$this->assertEquals($expected, $TestModel->validationErrors);
|
||||
|
||||
$data = array(
|
||||
0 => array('title' => 'title 0'),
|
||||
1 => array('title' => ''),
|
||||
2 => array('title' => 'title 2'),
|
||||
);
|
||||
$expected = array(
|
||||
1 => array('title' => array('This field cannot be left blank')),
|
||||
);
|
||||
$result = $TestModel->saveAll($data, array('validate' => 'only'));
|
||||
$this->assertFalse($result);
|
||||
$this->assertEquals($expected, $TestModel->validationErrors);
|
||||
$result = $TestModel->validateMany($data);
|
||||
$this->assertFalse($result);
|
||||
$this->assertEquals($expected, $TestModel->validationErrors);
|
||||
}
|
||||
|
||||
/**
|
||||
* testGetMethods method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetMethods() {
|
||||
$this->loadFixtures('Article', 'Comment');
|
||||
$TestModel = new Article();
|
||||
$Validator = $TestModel->validator();
|
||||
|
||||
$result = $Validator->getMethods();
|
||||
|
||||
$expected = array_map('strtolower', get_class_methods('Article'));
|
||||
$this->assertEquals($expected, array_keys($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* testSetValidationDomain method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSetValidationDomain() {
|
||||
$this->loadFixtures('Article', 'Comment');
|
||||
$TestModel = new Article();
|
||||
$Validator = $TestModel->validator();
|
||||
|
||||
$result = $Validator->setValidationDomain('default');
|
||||
$this->assertEquals('default', $TestModel->validationDomain);
|
||||
|
||||
$result = $Validator->setValidationDomain('other');
|
||||
$this->assertEquals('other', $TestModel->validationDomain);
|
||||
}
|
||||
|
||||
/**
|
||||
* testGetModel method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetModel() {
|
||||
$TestModel = new Article();
|
||||
$Validator = $TestModel->validator();
|
||||
|
||||
$result = $Validator->getModel();
|
||||
$this->assertInstanceOf('Article', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests it is possible to get validation sets for a field using an array inteface
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testArrayAccessGet() {
|
||||
$TestModel = new Article();
|
||||
$Validator = $TestModel->validator();
|
||||
|
||||
$titleValidator = $Validator['title'];
|
||||
$this->assertEquals('title', $titleValidator->field);
|
||||
$this->assertCount(1, $titleValidator->getRules());
|
||||
$rule = current($titleValidator->getRules());
|
||||
$this->assertEquals('notEmpty', $rule->rule);
|
||||
|
||||
$titleValidator = $Validator['body'];
|
||||
$this->assertEquals('body', $titleValidator->field);
|
||||
$this->assertCount(1, $titleValidator->getRules());
|
||||
$rule = current($titleValidator->getRules());
|
||||
$this->assertEquals('notEmpty', $rule->rule);
|
||||
|
||||
$titleValidator = $Validator['user_id'];
|
||||
$this->assertEquals('user_id', $titleValidator->field);
|
||||
$this->assertCount(1, $titleValidator->getRules());
|
||||
$rule = current($titleValidator->getRules());
|
||||
$this->assertEquals('numeric', $rule->rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests it is possible to check for validation sets for a field using an array inteface
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testArrayAccessExists() {
|
||||
$TestModel = new Article();
|
||||
$Validator = $TestModel->validator();
|
||||
|
||||
$this->assertTrue(isset($Validator['title']));
|
||||
$this->assertTrue(isset($Validator['body']));
|
||||
$this->assertTrue(isset($Validator['user_id']));
|
||||
$this->assertFalse(isset($Validator['other']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests it is possible to set validation rules for a field using an array inteface
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testArrayAccessSet() {
|
||||
$TestModel = new Article();
|
||||
$Validator = $TestModel->validator();
|
||||
|
||||
$set = array(
|
||||
'numeric' => array('rule' => 'numeric', 'allowEmpty' => false),
|
||||
'range' => array('rule' => array('between', 1, 5), 'allowEmpty' => false),
|
||||
);
|
||||
$Validator['other'] = $set;
|
||||
$rules = $Validator['other'];
|
||||
$this->assertEquals('other', $rules->field);
|
||||
|
||||
$validators = $rules->getRules();
|
||||
$this->assertCount(2, $validators);
|
||||
$this->assertEquals('numeric', $validators['numeric']->rule);
|
||||
$this->assertEquals(array('between', 1, 5), $validators['range']->rule);
|
||||
|
||||
$Validator['new'] = new CakeValidationSet('new', $set, array());
|
||||
$rules = $Validator['new'];
|
||||
$this->assertEquals('new', $rules->field);
|
||||
|
||||
$validators = $rules->getRules();
|
||||
$this->assertCount(2, $validators);
|
||||
$this->assertEquals('numeric', $validators['numeric']->rule);
|
||||
$this->assertEquals(array('between', 1, 5), $validators['range']->rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests it is possible to unset validation rules
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testArrayAccessUset() {
|
||||
$TestModel = new Article();
|
||||
$Validator = $TestModel->validator();
|
||||
|
||||
$this->assertTrue(isset($Validator['title']));
|
||||
unset($Validator['title']);
|
||||
$this->assertFalse(isset($Validator['title']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests it is possible to iterate a validation object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIterator() {
|
||||
$TestModel = new Article();
|
||||
$Validator = $TestModel->validator();
|
||||
|
||||
$i = 0;
|
||||
foreach ($Validator as $field => $rules) {
|
||||
if ($i === 0) {
|
||||
$this->assertEquals('user_id', $field);
|
||||
}
|
||||
if ($i === 1) {
|
||||
$this->assertEquals('title', $field);
|
||||
}
|
||||
if ($i === 2) {
|
||||
$this->assertEquals('body', $field);
|
||||
}
|
||||
$this->assertInstanceOf('CakeValidationSet', $rules);
|
||||
$i++;
|
||||
}
|
||||
$this->assertEquals(3, $i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests countable interface in ModelValidator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCount() {
|
||||
$TestModel = new Article();
|
||||
$Validator = $TestModel->validator();
|
||||
$this->assertCount(3, $Validator);
|
||||
|
||||
$set = array(
|
||||
'numeric' => array('rule' => 'numeric', 'allowEmpty' => false),
|
||||
'range' => array('rule' => array('between', 1, 5), 'allowEmpty' => false),
|
||||
);
|
||||
$Validator['other'] = $set;
|
||||
$this->assertCount(4, $Validator);
|
||||
|
||||
unset($Validator['title']);
|
||||
$this->assertCount(3, $Validator);
|
||||
unset($Validator['body']);
|
||||
$this->assertCount(2, $Validator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests it is possible to add validation rules
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAddRule() {
|
||||
$TestModel = new Article();
|
||||
$Validator = $TestModel->validator();
|
||||
|
||||
$set = array(
|
||||
'numeric' => array('rule' => 'numeric', 'allowEmpty' => false),
|
||||
'range' => array('rule' => array('between', 1, 5), 'allowEmpty' => false),
|
||||
);
|
||||
|
||||
$Validator->add('other', 'numeric', array('rule' => 'numeric', 'allowEmpty' => false));
|
||||
$Validator->add('other', 'range', array('rule' => array('between', 1, 5), 'allowEmpty' => false));
|
||||
$rules = $Validator['other'];
|
||||
$this->assertEquals('other', $rules->field);
|
||||
|
||||
$validators = $rules->getRules();
|
||||
$this->assertCount(2, $validators);
|
||||
$this->assertEquals('numeric', $validators['numeric']->rule);
|
||||
$this->assertEquals(array('between', 1, 5), $validators['range']->rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests it is possible to remove validation rules
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testRemoveRule() {
|
||||
$TestModel = new Article();
|
||||
$Validator = $TestModel->validator();
|
||||
|
||||
$this->assertTrue(isset($Validator['title']));
|
||||
$Validator->remove('title');
|
||||
$this->assertFalse(isset($Validator['title']));
|
||||
|
||||
$Validator->add('other', 'numeric', array('rule' => 'numeric', 'allowEmpty' => false));
|
||||
$Validator->add('other', 'range', array('rule' => array('between', 1, 5), 'allowEmpty' => false));
|
||||
$this->assertTrue(isset($Validator['other']));
|
||||
|
||||
$Validator->remove('other', 'numeric');
|
||||
$this->assertTrue(isset($Validator['other']));
|
||||
$this->assertFalse(isset($Validator['other']['numeric']));
|
||||
$this->assertTrue(isset($Validator['other']['range']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests validation callbacks are triggered
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testValidateCallbacks() {
|
||||
$TestModel = $this->getMock('Article', array('beforeValidate', 'afterValidate'));
|
||||
$TestModel->expects($this->once())->method('beforeValidate');
|
||||
$TestModel->expects($this->once())->method('afterValidate');
|
||||
|
||||
$TestModel->set(array('title' => '', 'body' => 'body'));
|
||||
$TestModel->validates();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that altering data in a beforeValidate callback will lead to saving those
|
||||
* values in database
|
||||
|
@ -1054,6 +1925,7 @@ class ModelValidationTest extends BaseModelTest {
|
|||
);
|
||||
$result = $model->saveAll($data, array('validate' => 'first'));
|
||||
$this->assertTrue($result);
|
||||
|
||||
$this->assertFalse($model->findMethods['unPublished'], 'beforeValidate was run twice');
|
||||
|
||||
$model->findMethods['unPublished'] = true;
|
||||
|
@ -1074,8 +1946,6 @@ class ModelValidationTest extends BaseModelTest {
|
|||
array('body' => 'foo4')
|
||||
);
|
||||
|
||||
$result = $model->saveAll($data, array('validate' => 'first'));
|
||||
$this->assertTrue($result);
|
||||
$result = $model->saveAll($data, array('validate' => 'first', 'deep' => true));
|
||||
$this->assertTrue($result);
|
||||
|
||||
|
@ -1165,4 +2035,4 @@ class ModelValidationTest extends BaseModelTest {
|
|||
$this->assertEquals($expected['Article'], $result['Article']);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ class ModelWriteTest extends BaseModelTest {
|
|||
|
||||
$testResult = $Article->find('first', array('conditions' => array('Article.title' => 'Test Title')));
|
||||
|
||||
$this->assertEquals($testResult['Article']['title'], $data['Article']['title']);
|
||||
$this->assertEquals($data['Article']['title'], $testResult['Article']['title']);
|
||||
$this->assertEquals('2008-01-01 00:00:00', $testResult['Article']['created']);
|
||||
}
|
||||
|
||||
|
@ -151,8 +151,8 @@ class ModelWriteTest extends BaseModelTest {
|
|||
$TestModel->save(array('title' => 'Test record'));
|
||||
$result = $TestModel->findByTitle('Test record');
|
||||
$this->assertEquals(
|
||||
array_keys($result['Uuid']),
|
||||
array('id', 'title', 'count', 'created', 'updated')
|
||||
array('id', 'title', 'count', 'created', 'updated'),
|
||||
array_keys($result['Uuid'])
|
||||
);
|
||||
$this->assertEquals(36, strlen($result['Uuid']['id']));
|
||||
}
|
||||
|
@ -173,8 +173,8 @@ class ModelWriteTest extends BaseModelTest {
|
|||
$TestModel->save(array('title' => 'Test record', 'id' => null));
|
||||
$result = $TestModel->findByTitle('Test record');
|
||||
$this->assertEquals(
|
||||
array_keys($result['Uuid']),
|
||||
array('id', 'title', 'count', 'created', 'updated')
|
||||
array('id', 'title', 'count', 'created', 'updated'),
|
||||
array_keys($result['Uuid'])
|
||||
);
|
||||
$this->assertEquals(36, strlen($result['Uuid']['id']));
|
||||
}
|
||||
|
@ -2345,7 +2345,7 @@ class ModelWriteTest extends BaseModelTest {
|
|||
'User' => array(
|
||||
'user' => 'updated user'
|
||||
)));
|
||||
$this->assertEquals($TestModel->id, $id);
|
||||
$this->assertEquals($id, $TestModel->id);
|
||||
|
||||
$result = $TestModel->findById($id);
|
||||
$this->assertEquals('updated user', $result['User']['user']);
|
||||
|
@ -2940,7 +2940,7 @@ class ModelWriteTest extends BaseModelTest {
|
|||
$model->Attachment->validate = array('attachment' => 'notEmpty');
|
||||
$model->Attachment->bindModel(array('belongsTo' => array('Comment')));
|
||||
|
||||
$this->assertEquals($model->saveAll(
|
||||
$result = $model->saveAll(
|
||||
array(
|
||||
'Comment' => array(
|
||||
'comment' => '',
|
||||
|
@ -2950,23 +2950,14 @@ class ModelWriteTest extends BaseModelTest {
|
|||
'Attachment' => array('attachment' => '')
|
||||
),
|
||||
array('validate' => 'first')
|
||||
), false);
|
||||
);
|
||||
$this->assertEquals(false, $result);
|
||||
$expected = array(
|
||||
'Comment' => array('comment' => array('This field cannot be left blank')),
|
||||
'Attachment' => array('attachment' => array('This field cannot be left blank'))
|
||||
);
|
||||
$this->assertEquals($expected['Comment'], $model->validationErrors);
|
||||
$this->assertEquals($expected['Attachment'], $model->Attachment->validationErrors);
|
||||
|
||||
$this->assertFalse($model->saveAll(
|
||||
array(
|
||||
'Comment' => array('comment' => '', 'article_id' => 1, 'user_id' => 1),
|
||||
'Attachment' => array('attachment' => '')
|
||||
),
|
||||
array('validate' => 'only')
|
||||
));
|
||||
$this->assertEquals($expected['Comment'], $model->validationErrors);
|
||||
$this->assertEquals($expected['Attachment'], $model->Attachment->validationErrors);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4329,7 +4320,7 @@ class ModelWriteTest extends BaseModelTest {
|
|||
$this->assertTrue(Set::matches('/Post[2][title=Just update the title]', $result));
|
||||
}
|
||||
|
||||
$this->assertEquals($TestModel->validationErrors, $errors);
|
||||
$this->assertEquals($errors, $TestModel->validationErrors);
|
||||
|
||||
$TestModel->validate = array('title' => 'notEmpty', 'author_id' => 'numeric');
|
||||
$data = array(
|
||||
|
@ -4400,7 +4391,7 @@ class ModelWriteTest extends BaseModelTest {
|
|||
$result[3]['Post']['updated'], $result[3]['Post']['created']
|
||||
);
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertEquals($TestModel->validationErrors, $errors);
|
||||
$this->assertEquals($errors, $TestModel->validationErrors);
|
||||
|
||||
$data = array(
|
||||
array(
|
||||
|
@ -4422,7 +4413,7 @@ class ModelWriteTest extends BaseModelTest {
|
|||
$result[3]['Post']['updated'], $result[3]['Post']['created']
|
||||
);
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertEquals($TestModel->validationErrors, $errors);
|
||||
$this->assertEquals($errors, $TestModel->validationErrors);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5037,7 +5028,7 @@ class ModelWriteTest extends BaseModelTest {
|
|||
$model->Attachment->validate = array('attachment' => 'notEmpty');
|
||||
$model->Attachment->bindModel(array('belongsTo' => array('Comment')));
|
||||
|
||||
$this->assertEquals($model->saveAssociated(
|
||||
$result = $model->saveAssociated(
|
||||
array(
|
||||
'Comment' => array(
|
||||
'comment' => '',
|
||||
|
@ -5046,7 +5037,8 @@ class ModelWriteTest extends BaseModelTest {
|
|||
),
|
||||
'Attachment' => array('attachment' => '')
|
||||
)
|
||||
), false);
|
||||
);
|
||||
$this->assertFalse($result);
|
||||
$expected = array(
|
||||
'Comment' => array('comment' => array('This field cannot be left blank')),
|
||||
'Attachment' => array('attachment' => array('This field cannot be left blank'))
|
||||
|
@ -5688,7 +5680,7 @@ class ModelWriteTest extends BaseModelTest {
|
|||
$this->assertTrue(Set::matches('/Post[2][title=Just update the title]', $result));
|
||||
}
|
||||
|
||||
$this->assertEquals($TestModel->validationErrors, $errors);
|
||||
$this->assertEquals($errors, $TestModel->validationErrors);
|
||||
|
||||
$TestModel->validate = array('title' => 'notEmpty', 'author_id' => 'numeric');
|
||||
$data = array(
|
||||
|
@ -5746,7 +5738,7 @@ class ModelWriteTest extends BaseModelTest {
|
|||
'published' => 'N',
|
||||
)));
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertEquals($TestModel->validationErrors, $errors);
|
||||
$this->assertEquals($errors, $TestModel->validationErrors);
|
||||
|
||||
$data = array(
|
||||
array(
|
||||
|
@ -5768,7 +5760,7 @@ class ModelWriteTest extends BaseModelTest {
|
|||
'order' => 'Post.id ASC'
|
||||
));
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertEquals($TestModel->validationErrors, $errors);
|
||||
$this->assertEquals($errors, $TestModel->validationErrors);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5876,8 +5868,8 @@ class ModelWriteTest extends BaseModelTest {
|
|||
|
||||
$result = $model->find('all');
|
||||
$this->assertEquals(
|
||||
$result[0]['Article']['title'],
|
||||
'Post with Author saveAlled from comment'
|
||||
'Post with Author saveAlled from comment',
|
||||
$result[0]['Article']['title']
|
||||
);
|
||||
$this->assertEquals('Only new comment', $result[0]['Comment'][0]['comment']);
|
||||
}
|
||||
|
|
164
lib/Cake/Test/Case/Model/Validator/CakeValidationRuleTest.php
Normal file
164
lib/Cake/Test/Case/Model/Validator/CakeValidationRuleTest.php
Normal file
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
/**
|
||||
* CakeValidationRuleTest file
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
|
||||
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice
|
||||
*
|
||||
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
|
||||
* @package Cake.Test.Case.Model.Validator
|
||||
* @since CakePHP(tm) v 2.2.0
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
|
||||
App::uses('CakeValidationRule', 'Model/Validator');
|
||||
|
||||
/**
|
||||
* CakeValidationRuleTest
|
||||
*
|
||||
* @package Cake.Test.Case.Model.Validator
|
||||
*/
|
||||
class CakeValidationRuleTest extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* setUp method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Auxiliary method to test custom validators
|
||||
*
|
||||
* @return boolean
|
||||
**/
|
||||
public function myTestRule() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auxiliary method to test custom validators
|
||||
*
|
||||
* @return boolean
|
||||
**/
|
||||
public function myTestRule2() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auxiliary method to test custom validators
|
||||
*
|
||||
* @return string
|
||||
**/
|
||||
public function myTestRule3() {
|
||||
return 'string';
|
||||
}
|
||||
|
||||
/**
|
||||
* Test isValid method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIsValid() {
|
||||
$def = array('rule' => 'notEmpty', 'message' => 'Can not be empty');
|
||||
$data = array(
|
||||
'fieldName' => ''
|
||||
);
|
||||
$methods = array();
|
||||
|
||||
$Rule = new CakeValidationRule($def);
|
||||
$Rule->process('fieldName', $data, $methods);
|
||||
$this->assertFalse($Rule->isValid());
|
||||
|
||||
$data = array('fieldName' => 'not empty');
|
||||
$Rule->process('fieldName', $data, $methods);
|
||||
$this->assertTrue($Rule->isValid());
|
||||
}
|
||||
/**
|
||||
* tests that passing custom validation methods work
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCustomMethods() {
|
||||
$def = array('rule' => 'myTestRule');
|
||||
$data = array(
|
||||
'fieldName' => 'some data'
|
||||
);
|
||||
$methods = array('mytestrule' => array($this, 'myTestRule'));
|
||||
|
||||
$Rule = new CakeValidationRule($def);
|
||||
$Rule->process('fieldName', $data, $methods);
|
||||
$this->assertFalse($Rule->isValid());
|
||||
|
||||
$methods = array('mytestrule' => array($this, 'myTestRule2'));
|
||||
$Rule->process('fieldName', $data, $methods);
|
||||
$this->assertTrue($Rule->isValid());
|
||||
|
||||
$methods = array('mytestrule' => array($this, 'myTestRule3'));
|
||||
$Rule->process('fieldName', $data, $methods);
|
||||
$this->assertFalse($Rule->isValid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test isRequired method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIsRequired() {
|
||||
$def = array('rule' => 'notEmpty', 'required' => true);
|
||||
$Rule = new CakeValidationRule($def);
|
||||
$this->assertTrue($Rule->isRequired());
|
||||
|
||||
$def = array('rule' => 'notEmpty', 'required' => false);
|
||||
$Rule = new CakeValidationRule($def);
|
||||
$this->assertFalse($Rule->isRequired());
|
||||
|
||||
$def = array('rule' => 'notEmpty', 'required' => 'create');
|
||||
$Rule = new CakeValidationRule($def);
|
||||
$this->assertTrue($Rule->isRequired());
|
||||
|
||||
$def = array('rule' => 'notEmpty', 'required' => 'update');
|
||||
$Rule = new CakeValidationRule($def);
|
||||
$this->assertFalse($Rule->isRequired());
|
||||
|
||||
$Rule->isUpdate(true);
|
||||
$this->assertTrue($Rule->isRequired());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test isEmptyAllowed method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIsEmplyAllowed() {
|
||||
$def = array('rule' => 'aRule', 'allowEmpty' => true);
|
||||
$Rule = new CakeValidationRule($def);
|
||||
$this->assertTrue($Rule->isEmptyAllowed());
|
||||
|
||||
$def = array('rule' => 'aRule', 'allowEmpty' => false);
|
||||
$Rule = new CakeValidationRule($def);
|
||||
$this->assertFalse($Rule->isEmptyAllowed());
|
||||
|
||||
$def = array('rule' => 'notEmpty', 'allowEmpty' => false, 'on' => 'update');
|
||||
$Rule = new CakeValidationRule($def);
|
||||
$this->assertTrue($Rule->isEmptyAllowed());
|
||||
|
||||
$Rule->isUpdate(true);
|
||||
$this->assertFalse($Rule->isEmptyAllowed());
|
||||
|
||||
$def = array('rule' => 'notEmpty', 'allowEmpty' => false, 'on' => 'create');
|
||||
$Rule = new CakeValidationRule($def);
|
||||
$this->assertFalse($Rule->isEmptyAllowed());
|
||||
|
||||
$Rule->isUpdate(true);
|
||||
$this->assertTrue($Rule->isEmptyAllowed());
|
||||
}
|
||||
}
|
316
lib/Cake/Test/Case/Model/Validator/CakeValidationSetTest.php
Normal file
316
lib/Cake/Test/Case/Model/Validator/CakeValidationSetTest.php
Normal file
|
@ -0,0 +1,316 @@
|
|||
<?php
|
||||
/**
|
||||
* CakeValidationSetTest file
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
|
||||
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice
|
||||
*
|
||||
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
|
||||
* @package Cake.Test.Case.Model.Validator
|
||||
* @since CakePHP(tm) v 2.2.0
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
|
||||
App::uses('CakeValidationSet', 'Model/Validator');
|
||||
|
||||
/**
|
||||
* CakeValidationSetTest
|
||||
*
|
||||
* @package Cake.Test.Case.Model.Validator
|
||||
*/
|
||||
class CakeValidationSetTest extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* setUp method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* testValidate method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testValidate() {
|
||||
$Field = new CakeValidationSet('title', 'notEmpty');
|
||||
$data = array(
|
||||
'title' => '',
|
||||
'body' => 'a body'
|
||||
);
|
||||
|
||||
$result = $Field->validate($data);
|
||||
$expected = array('This field cannot be left blank');
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$Field = new CakeValidationSet('body', 'notEmpty');
|
||||
|
||||
$result = $Field->validate($data);
|
||||
$this->assertEmpty($result);
|
||||
|
||||
$Field = new CakeValidationSet('nothere', array('notEmpty' => array('rule' => 'notEmpty', 'required' => true)));
|
||||
|
||||
$result = $Field->validate($data);
|
||||
$expected = array('notEmpty');
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* testGetRule method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetRule() {
|
||||
$rules = array('notEmpty' => array('rule' => 'notEmpty', 'message' => 'Can not be empty'));
|
||||
$Field = new CakeValidationSet('title', $rules);
|
||||
$data = array(
|
||||
'title' => '',
|
||||
'body' => 'a body'
|
||||
);
|
||||
|
||||
$result = $Field->getRule('notEmpty');
|
||||
$this->assertInstanceOf('CakeValidationRule', $result);
|
||||
$this->assertEquals('notEmpty', $result->rule);
|
||||
$this->assertEquals(null, $result->required);
|
||||
$this->assertEquals(false, $result->allowEmpty);
|
||||
$this->assertEquals(null, $result->on);
|
||||
$this->assertEquals(true, $result->last);
|
||||
$this->assertEquals('Can not be empty', $result->message);
|
||||
}
|
||||
|
||||
/**
|
||||
* testGetRules method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetRules() {
|
||||
$rules = array('notEmpty' => array('rule' => 'notEmpty', 'message' => 'Can not be empty'));
|
||||
$Field = new CakeValidationSet('title', $rules);
|
||||
|
||||
$result = $Field->getRules();
|
||||
$this->assertEquals(array('notEmpty'), array_keys($result));
|
||||
$this->assertInstanceOf('CakeValidationRule', $result['notEmpty']);
|
||||
}
|
||||
|
||||
/**
|
||||
* testSetRule method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSetRule() {
|
||||
$rules = array('notEmpty' => array('rule' => 'notEmpty', 'message' => 'Can not be empty'));
|
||||
$Field = new CakeValidationSet('title', $rules);
|
||||
$Rule = new CakeValidationRule($rules['notEmpty']);
|
||||
|
||||
$this->assertEquals($Rule, $Field->getRule('notEmpty'));
|
||||
|
||||
$rules = array('validEmail' => array('rule' => 'email', 'message' => 'Invalid email'));
|
||||
$Rule = new CakeValidationRule($rules['validEmail']);
|
||||
$Field->setRule('validEmail', $Rule);
|
||||
$result = $Field->getRules();
|
||||
$this->assertEquals(array('notEmpty', 'validEmail'), array_keys($result));
|
||||
|
||||
$rules = array('validEmail' => array('rule' => 'email', 'message' => 'Other message'));
|
||||
$Rule = new CakeValidationRule($rules['validEmail']);
|
||||
$Field->setRule('validEmail', $Rule);
|
||||
$result = $Field->getRules();
|
||||
$this->assertEquals(array('notEmpty', 'validEmail'), array_keys($result));
|
||||
$result = $Field->getRule('validEmail');
|
||||
$this->assertInstanceOf('CakeValidationRule', $result);
|
||||
$this->assertEquals('email', $result->rule);
|
||||
$this->assertEquals(null, $result->required);
|
||||
$this->assertEquals(false, $result->allowEmpty);
|
||||
$this->assertEquals(null, $result->on);
|
||||
$this->assertEquals(true, $result->last);
|
||||
$this->assertEquals('Other message', $result->message);
|
||||
}
|
||||
|
||||
/**
|
||||
* testSetRules method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSetRules() {
|
||||
$rule = array('notEmpty' => array('rule' => 'notEmpty', 'message' => 'Can not be empty'));
|
||||
$Field = new CakeValidationSet('title', $rule);
|
||||
$RuleEmpty = new CakeValidationRule($rule['notEmpty']);
|
||||
|
||||
$rule = array('validEmail' => array('rule' => 'email', 'message' => 'Invalid email'));
|
||||
$RuleEmail = new CakeValidationRule($rule['validEmail']);
|
||||
|
||||
$rules = array('validEmail' => $RuleEmail);
|
||||
$Field->setRules($rules, false);
|
||||
$result = $Field->getRules();
|
||||
$this->assertEquals(array('validEmail'), array_keys($result));
|
||||
|
||||
$rules = array('notEmpty' => $RuleEmpty);
|
||||
$Field->setRules($rules, true);
|
||||
$result = $Field->getRules();
|
||||
$this->assertEquals(array('validEmail', 'notEmpty'), array_keys($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests getting a rule from the set using array access
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testArrayAccessGet() {
|
||||
$Set = new CakeValidationSet('title', array(
|
||||
'notEmpty' => array('rule' => 'notEmpty', 'required' => true),
|
||||
'numeric' => array('rule' => 'numeric'),
|
||||
'other' => array('rule' => array('other', 1)),
|
||||
));
|
||||
|
||||
$rule = $Set['notEmpty'];
|
||||
$this->assertInstanceOf('CakeValidationRule', $rule);
|
||||
$this->assertEquals('notEmpty', $rule->rule);
|
||||
|
||||
$rule = $Set['numeric'];
|
||||
$this->assertInstanceOf('CakeValidationRule', $rule);
|
||||
$this->assertEquals('numeric', $rule->rule);
|
||||
|
||||
$rule = $Set['other'];
|
||||
$this->assertInstanceOf('CakeValidationRule', $rule);
|
||||
$this->assertEquals(array('other', 1), $rule->rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests checking a rule from the set using array access
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testArrayAccessExists() {
|
||||
$Set = new CakeValidationSet('title', array(
|
||||
'notEmpty' => array('rule' => 'notEmpty', 'required' => true),
|
||||
'numeric' => array('rule' => 'numeric'),
|
||||
'other' => array('rule' => array('other', 1)),
|
||||
));
|
||||
|
||||
$this->assertTrue(isset($Set['notEmpty']));
|
||||
$this->assertTrue(isset($Set['numeric']));
|
||||
$this->assertTrue(isset($Set['other']));
|
||||
$this->assertFalse(isset($Set['fail']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests setting a rule in the set using array access
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testArrayAccessSet() {
|
||||
$Set = new CakeValidationSet('title', array(
|
||||
'notEmpty' => array('rule' => 'notEmpty', 'required' => true),
|
||||
));
|
||||
|
||||
$this->assertFalse(isset($Set['other']));
|
||||
$Set['other'] = array('rule' => array('other', 1));
|
||||
$rule = $Set['other'];
|
||||
$this->assertInstanceOf('CakeValidationRule', $rule);
|
||||
$this->assertEquals(array('other', 1), $rule->rule);
|
||||
|
||||
$this->assertFalse(isset($Set['numeric']));
|
||||
$Set['numeric'] = new CakeValidationRule(array('rule' => 'numeric'));
|
||||
$rule = $Set['numeric'];
|
||||
$this->assertInstanceOf('CakeValidationRule', $rule);
|
||||
$this->assertEquals('numeric', $rule->rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests unseting a rule from the set using array access
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testArrayAccessUnset() {
|
||||
$Set = new CakeValidationSet('title', array(
|
||||
'notEmpty' => array('rule' => 'notEmpty', 'required' => true),
|
||||
'numeric' => array('rule' => 'numeric'),
|
||||
'other' => array('rule' => array('other', 1)),
|
||||
));
|
||||
|
||||
unset($Set['notEmpty']);
|
||||
$this->assertFalse(isset($Set['notEmpty']));
|
||||
|
||||
unset($Set['numeric']);
|
||||
$this->assertFalse(isset($Set['notEmpty']));
|
||||
|
||||
unset($Set['other']);
|
||||
$this->assertFalse(isset($Set['notEmpty']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests it is possible to iterate a validation set object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIterator() {
|
||||
$Set = new CakeValidationSet('title', array(
|
||||
'notEmpty' => array('rule' => 'notEmpty', 'required' => true),
|
||||
'numeric' => array('rule' => 'numeric'),
|
||||
'other' => array('rule' => array('other', 1)),
|
||||
));
|
||||
|
||||
$i = 0;
|
||||
foreach ($Set as $name => $rule) {
|
||||
if ($i === 0) {
|
||||
$this->assertEquals('notEmpty', $name);
|
||||
}
|
||||
if ($i === 1) {
|
||||
$this->assertEquals('numeric', $name);
|
||||
}
|
||||
if ($i === 2) {
|
||||
$this->assertEquals('other', $name);
|
||||
}
|
||||
$this->assertInstanceOf('CakeValidationRule', $rule);
|
||||
$i++;
|
||||
}
|
||||
$this->assertEquals(3, $i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests countable interface
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCount() {
|
||||
$Set = new CakeValidationSet('title', array(
|
||||
'notEmpty' => array('rule' => 'notEmpty', 'required' => true),
|
||||
'numeric' => array('rule' => 'numeric'),
|
||||
'other' => array('rule' => array('other', 1)),
|
||||
));
|
||||
$this->assertCount(3, $Set);
|
||||
|
||||
unset($Set['other']);
|
||||
$this->assertCount(2, $Set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test removeRule method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testRemoveRule() {
|
||||
$Set = new CakeValidationSet('title', array(
|
||||
'notEmpty' => array('rule' => 'notEmpty', 'required' => true),
|
||||
'numeric' => array('rule' => 'numeric'),
|
||||
'other' => array('rule' => array('other', 1)),
|
||||
));
|
||||
|
||||
$Set->removeRule('notEmpty');
|
||||
$this->assertFalse(isset($Set['notEmpty']));
|
||||
|
||||
$Set->removeRule('numeric');
|
||||
$this->assertFalse(isset($Set['numeric']));
|
||||
|
||||
$Set->removeRule('other');
|
||||
$this->assertFalse(isset($Set['other']));
|
||||
}
|
||||
|
||||
}
|
|
@ -218,7 +218,7 @@ class FormHelper extends AppHelper {
|
|||
if ($key === 'validates' && !isset($this->fieldset[$model]['validates'])) {
|
||||
$validates = array();
|
||||
if (!empty($object->validate)) {
|
||||
foreach ($object->validate as $validateField => $validateProperties) {
|
||||
foreach ($object->validator() as $validateField => $validateProperties) {
|
||||
if ($this->_isRequiredField($validateProperties)) {
|
||||
$validates[$validateField] = true;
|
||||
}
|
||||
|
@ -240,61 +240,17 @@ class FormHelper extends AppHelper {
|
|||
/**
|
||||
* Returns if a field is required to be filled based on validation properties from the validating object.
|
||||
*
|
||||
* @param array $validateProperties
|
||||
* @param CakeValidationSet $validationRules
|
||||
* @return boolean true if field is required to be filled, false otherwise
|
||||
*/
|
||||
protected function _isRequiredField($validateProperties) {
|
||||
$required = false;
|
||||
if (is_string($validateProperties)) {
|
||||
return true;
|
||||
} elseif (is_array($validateProperties)) {
|
||||
|
||||
$dims = Hash::dimensions($validateProperties);
|
||||
if ($dims == 1 || ($dims == 2 && isset($validateProperties['rule']))) {
|
||||
$validateProperties = array($validateProperties);
|
||||
}
|
||||
|
||||
foreach ($validateProperties as $rule => $validateProp) {
|
||||
$isRequired = $this->_isRequiredRule($validateProp);
|
||||
if ($isRequired === false) {
|
||||
continue;
|
||||
}
|
||||
$rule = isset($validateProp['rule']) ? $validateProp['rule'] : false;
|
||||
$required = $rule || empty($validateProp);
|
||||
if ($required) {
|
||||
break;
|
||||
}
|
||||
protected function _isRequiredField($validationRules) {
|
||||
foreach ($validationRules as $rule) {
|
||||
$rule->isUpdate($this->requestType === 'put');
|
||||
if (!$rule->isEmptyAllowed()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return $required;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the field is required by the 'on' key in validation properties.
|
||||
* If no 'on' key is present in validation props, this method returns true.
|
||||
*
|
||||
* @param array $validateProp
|
||||
* @return mixed. Boolean for required
|
||||
*/
|
||||
protected function _isRequiredRule($validateProp) {
|
||||
if (isset($validateProp['on'])) {
|
||||
if (
|
||||
($validateProp['on'] == 'create' && $this->requestType != 'post') ||
|
||||
($validateProp['on'] == 'update' && $this->requestType != 'put')
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (
|
||||
isset($validateProp['allowEmpty']) &&
|
||||
$validateProp['allowEmpty'] === true
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (isset($validateProp['required']) && empty($validateProp['required'])) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue