Jelajahi Sumber

merged branch jmikola/entity-validator (PR #2076)

Commits
-------

d19f1d7 [Doctrine] Fix UniqueEntityValidator reporting a false positive by ignoring multiple query results

Discussion
----------

[Doctrine] Fix UniqueEntityValidator reporting a false positive by ignoring multiple query results

An entity should only be considered unique if its search criteria returns no matches or a single, identical entity. Multiple results indicates that conflicting entities exist.

Note: the DoctrineMongoDBBundle's unique validator checks identifier values if the object strict-equality check is false. This may be a worthwhile improvement, as it would prevent reporting a validation error for an enttiy which is going to overwrite its conflicting counter-part in the database.

---------------------------------------------------------------------------

by jmikola at 2011/09/01 14:23:27 -0700

This is the Doctrine bridge equivalent for my fix to DoctrineMongoDBBundle: https://github.com/symfony/DoctrineMongoDBBundle/pull/42

---------------------------------------------------------------------------

by fabpot at 2011/09/02 00:13:52 -0700

As this is a bug fix, can you base your PR on the symfony/2.0 branch? Thanks.
Fabien Potencier 14 tahun lalu
induk
melakukan
6677dabda5

+ 11 - 5
src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php

@@ -75,13 +75,19 @@ class UniqueEntityValidator extends ConstraintValidator
         $repository = $em->getRepository($className);
         $result = $repository->findBy($criteria);
 
-        if (count($result) > 0 && $result[0] !== $entity) {
-            $oldPath = $this->context->getPropertyPath();
-            $this->context->setPropertyPath( empty($oldPath) ? $fields[0] : $oldPath.".".$fields[0]);
-            $this->context->addViolation($constraint->message, array(), $criteria[$fields[0]]);
-            $this->context->setPropertyPath($oldPath);
+        /* If no entity matched the query criteria or a single entity matched,
+         * which is the same as the entity being validated, the criteria is
+         * unique.
+         */
+        if (0 == count($result) || (1 == count($result) && $entity === $result[0])) {
+            return true;
         }
 
+        $oldPath = $this->context->getPropertyPath();
+        $this->context->setPropertyPath( empty($oldPath) ? $fields[0] : $oldPath.".".$fields[0]);
+        $this->context->addViolation($constraint->message, array(), $criteria[$fields[0]]);
+        $this->context->setPropertyPath($oldPath);
+
         return true; // all true, we added the violation already!
     }
 }

+ 21 - 0
tests/Symfony/Tests/Bridge/Doctrine/Validator/Constraints/UniqueValidatorTest.php

@@ -129,4 +129,25 @@ class UniqueValidatorTest extends DoctrineOrmTestCase
         $violationsList = $validator->validate($entity1);
         $this->assertEquals(0, $violationsList->count(), "No violations found on entity having a null value.");
     }
+
+    public function testValidateUniquenessAfterConsideringMultipleQueryResults()
+    {
+        $entityManagerName = "foo";
+        $em = $this->createTestEntityManager();
+        $this->createSchema($em);
+        $validator = $this->createValidator($entityManagerName, $em);
+
+        $entity1 = new SingleIdentEntity(1, 'foo');
+        $entity2 = new SingleIdentEntity(2, 'foo');
+
+        $em->persist($entity1);
+        $em->persist($entity2);
+        $em->flush();
+
+        $violationsList = $validator->validate($entity1);
+        $this->assertEquals(1, $violationsList->count(), 'Violation found on entity with conflicting entity existing in the database.');
+
+        $violationsList = $validator->validate($entity2);
+        $this->assertEquals(1, $violationsList->count(), 'Violation found on entity with conflicting entity existing in the database.');
+    }
 }