Browse Source

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.
mark_story 14 years ago
parent
commit
a70c8c7ac3
2 changed files with 126 additions and 69 deletions
  1. 73 69
      lib/Cake/Model/Model.php
  2. 53 0
      lib/Cake/Test/Case/Model/ModelValidationTest.php

+ 73 - 69
lib/Cake/Model/Model.php

@@ -2928,7 +2928,7 @@ class Model extends Object {
 			$data = array();
 		}
 
-		$exists = $this->exists();
+		$exists = null;
 
 		$_validate = $this->validate;
 		$whitelist = $this->whitelist;
@@ -2970,81 +2970,85 @@ class Model extends Object {
 				}
 				$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;
 					}
 				}
 			}

+ 53 - 0
lib/Cake/Test/Case/Model/ModelValidationTest.php

@@ -761,4 +761,57 @@ class ModelValidationTest extends BaseModelTest {
 		$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());
+	}
+
 }