From a70c8c7ac3fcd8df7148dacddd5ffef1acb9be32 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 19 Jan 2012 22:50:40 -0500 Subject: [PATCH] Merge changes from 1.3 to 2.0 Merge changes from #GH284 from 1.3 to 2.0. Model::validate() no longer does queries when its not necessary. --- lib/Cake/Model/Model.php | 142 +++++++++--------- .../Test/Case/Model/ModelValidationTest.php | 53 +++++++ 2 files changed, 126 insertions(+), 69 deletions(-) diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index 07eb0398485..6df1b106823 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -2928,7 +2928,7 @@ public function invalidFields($options = array()) { $data = array(); } - $exists = $this->exists(); + $exists = null; $_validate = $this->validate; $whitelist = $this->whitelist; @@ -2970,81 +2970,85 @@ public function invalidFields($options = array()) { } $validator = array_merge($default, $validator); - if ( - empty($validator['on']) || ($validator['on'] == 'create' && - !$exists) || ($validator['on'] == 'update' && $exists - )) { - $valid = true; - $requiredFail = ( - (!isset($data[$fieldName]) && $validator['required'] === true) || - ( - isset($data[$fieldName]) && (empty($data[$fieldName]) && - !is_numeric($data[$fieldName])) && $validator['allowEmpty'] === false - ) - ); + if (!empty($validator['on'])) { + if ($exists === null) { + $exists = $this->exists(); + } + if (($validator['on'] == 'create' && $exists) || ($validator['on'] == 'update' && !$exists)) { + continue; + } + } - 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]); - } + $valid = true; + $requiredFail = ( + (!isset($data[$fieldName]) && $validator['required'] === true) || + ( + isset($data[$fieldName]) && (empty($data[$fieldName]) && + !is_numeric($data[$fieldName])) && $validator['allowEmpty'] === false + ) + ); - 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 && 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 ($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); - } - $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; + 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 = __d('cake_dev', 'This field cannot be left blank'); + $message = $validator['message']; } - - $this->invalidate($fieldName, $message); - if ($validator['last']) { - break; + if (is_array($validator['rule']) && $args === null) { + $args = array_slice($ruleSet[$index]['rule'], 1); } + $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; } } } diff --git a/lib/Cake/Test/Case/Model/ModelValidationTest.php b/lib/Cake/Test/Case/Model/ModelValidationTest.php index 4c0e54aeba3..8435eda3a77 100644 --- a/lib/Cake/Test/Case/Model/ModelValidationTest.php +++ b/lib/Cake/Test/Case/Model/ModelValidationTest.php @@ -761,4 +761,57 @@ public function testValidationMessageAsArray() { $this->assertEquals($TestModel->validationErrors, $expected); } +/** + * Test for 'on' => [create|update] in validation rules. + * + * @return void + */ + function testStateValidation() { + $this->loadFixtures('Article'); + $Article = new Article(); + + $data = array( + 'Article' => array( + 'title' => '', + 'body' => 'Extra Fields Body', + 'published' => '1' + ) + ); + + $Article->validate = array( + 'title' => array( + 'notempty' => array( + 'rule' => 'notEmpty', + 'on' => 'create' + ) + ) + ); + + $Article->create($data); + $this->assertFalse($Article->validates()); + + $Article->save(null, array('validate' => false)); + $data['Article']['id'] = $Article->id; + $Article->set($data); + $this->assertTrue($Article->validates()); + + unset($data['Article']['id']); + $Article->validate = array( + 'title' => array( + 'notempty' => array( + 'rule' => 'notEmpty', + 'on' => 'update' + ) + ) + ); + + $Article->create($data); + $this->assertTrue($Article->validates()); + + $Article->save(null, array('validate' => false)); + $data['Article']['id'] = $Article->id; + $Article->set($data); + $this->assertFalse($Article->validates()); + } + }