Bladeren bron

[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.
Jeremy Mikola 13 jaren geleden
bovenliggende
commit
d19f1d7621

+ 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.');
+    }
 }