Browse Source

Re-implemented Table::validateUnique to reuse logic

Jose Lorenzo Rodriguez 11 years ago
parent
commit
5bbd189080
3 changed files with 48 additions and 26 deletions
  1. 4 1
      src/ORM/Rule/IsUnique.php
  2. 12 25
      src/ORM/Table.php
  3. 32 0
      tests/TestCase/ORM/TableTest.php

+ 4 - 1
src/ORM/Rule/IsUnique.php

@@ -53,7 +53,10 @@ class IsUnique {
 		$conditions = $entity->extract($this->_fields);
 		if ($entity->isNew() === false) {
 			$keys = (array)$options['repository']->primaryKey();
-			$conditions['NOT'] = $entity->extract($keys);
+			$keys = $entity->extract($keys);
+			if (array_filter($keys, 'strlen')) {
+				$conditions['NOT'] = $keys;
+			}
 		}
 
 		return !$options['repository']->exists($conditions);

+ 12 - 25
src/ORM/Table.php

@@ -34,6 +34,7 @@ use Cake\ORM\BehaviorRegistry;
 use Cake\ORM\Exception\MissingEntityException;
 use Cake\ORM\Marshaller;
 use Cake\ORM\RulesChecker;
+use Cake\ORM\Rule\IsUnique;
 use Cake\Utility\Inflector;
 use Cake\Validation\Validator;
 use RuntimeException;
@@ -1900,33 +1901,19 @@ class Table implements RepositoryInterface, EventListenerInterface {
  *
  * @param mixed $value The value of column to be checked for uniqueness
  * @param array $options The options array, optionally containing the 'scope' key
- * @param array $context The validation context as provided by the validation routine
  * @return bool true if the value is unique
  */
-	public function validateUnique($value, array $options, array $context = []) {
-		if (empty($context)) {
-			$context = $options;
-		}
-
-		$conditions = [$context['field'] => $value];
-		if (!empty($options['scope']) && isset($context['data'][$options['scope']])) {
-			$scope = $options['scope'];
-			$scopedValue = $context['data'][$scope];
-			$conditions[$scope] = $scopedValue;
-		}
-
-		if (!$context['newRecord']) {
-			$keys = (array)$this->primaryKey();
-			$not = [];
-			foreach ($keys as $key) {
-				if (isset($context['data'][$key])) {
-					$not[$key] = $context['data'][$key];
-				}
-			}
-			$conditions['NOT'] = $not;
-		}
-
-		return !$this->exists($conditions);
+	public function validateUnique($value, array $options) {
+		$entity = new Entity(
+			$options['data'],
+			['useSetters' => false, 'markNew' => $options['newRecord']]
+		);
+		$fields = array_merge(
+			[$options['field']],
+			isset($options['scope']) ? (array)$options['scope'] : []
+		);
+		$rule = new IsUnique($fields);
+		return $rule($entity, ['repository' => $this]);
 	}
 
 /**

+ 32 - 0
tests/TestCase/ORM/TableTest.php

@@ -3168,4 +3168,36 @@ class TableTest extends TestCase {
 		$this->assertEquals(1, $count, 'Callback should be called only once');
 	}
 
+/**
+ * Tests the validateUnique method with different combinations
+ *
+ * @return void
+ */
+	public function testValidateUnique() {
+		$table = TableRegistry::get('Users');
+		$validator = new Validator;
+		$validator->add('username', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']);
+		$validator->provider('table', $table);
+		$data = ['username' => 'larry'];
+		$this->assertNotEmpty($validator->errors($data));
+
+		$data = ['username' => 'jose'];
+		$this->assertEmpty($validator->errors($data));
+
+		$data = ['username' => 'larry', 'id' => 3];
+		$this->assertEmpty($validator->errors($data, false));
+
+		$data = ['username' => 'larry', 'id' => 3];
+		$this->assertNotEmpty($validator->errors($data));
+
+		$data = ['username' => 'larry'];
+		$this->assertNotEmpty($validator->errors($data, false));
+
+		$validator->add('username', 'unique', [
+			'rule' => 'validateUnique', 'provider' => 'table'
+		]);
+		$data = ['username' => 'larry'];
+		$this->assertNotEmpty($validator->errors($data, false));
+	}
+
 }