From ac7875569ae23d3e9df2f2cb1bd45d2a71de7441 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Thu, 12 Jul 2012 00:19:02 +0200 Subject: [PATCH] [DoctrineBridge] Added an option to choose the subpath for the violation By default, the UniqueEntityValidator maps the violation on the first field of the UniqueEntity constraint. The new option allows to control this behavior if a better mapping is suited. --- .../Constraints/UniqueValidatorTest.php | 27 +++++++++++++++++-- .../Validator/Constraints/UniqueEntity.php | 1 + .../Constraints/UniqueEntityValidator.php | 8 +++++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueValidatorTest.php index 9dac62d85c..1e8c07f3a7 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueValidatorTest.php @@ -69,7 +69,7 @@ class UniqueValidatorTest extends DoctrineOrmTestCase return $validatorFactory; } - public function createValidator($entityManagerName, $em, $validateClass = null, $uniqueFields = null) + public function createValidator($entityManagerName, $em, $validateClass = null, $uniqueFields = null, $errorPath = null) { if (!$validateClass) { $validateClass = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIdentEntity'; @@ -83,7 +83,7 @@ class UniqueValidatorTest extends DoctrineOrmTestCase $uniqueValidator = new UniqueEntityValidator($registry); $metadata = new ClassMetadata($validateClass); - $metadata->addConstraint(new UniqueEntity(array('fields' => $uniqueFields, 'em' => $entityManagerName))); + $metadata->addConstraint(new UniqueEntity(array('fields' => $uniqueFields, 'em' => $entityManagerName, 'errorPath' => $errorPath))); $metadataFactory = $this->createMetadataFactoryMock($metadata); $validatorFactory = $this->createValidatorFactory($uniqueValidator); @@ -132,6 +132,29 @@ class UniqueValidatorTest extends DoctrineOrmTestCase $this->assertEquals('Foo', $violation->getInvalidValue()); } + public function testValidateCustomErrorPath() + { + $entityManagerName = "foo"; + $em = $this->createTestEntityManager(); + $this->createSchema($em); + $validator = $this->createValidator($entityManagerName, $em, null, null, 'bar'); + + $entity1 = new SingleIdentEntity(1, 'Foo'); + + $em->persist($entity1); + $em->flush(); + + $entity2 = new SingleIdentEntity(2, 'Foo'); + + $violationsList = $validator->validate($entity2); + $this->assertEquals(1, $violationsList->count(), "No violations found on entity after it was saved to the database."); + + $violation = $violationsList[0]; + $this->assertEquals('This value is already used.', $violation->getMessage()); + $this->assertEquals('bar', $violation->getPropertyPath()); + $this->assertEquals('Foo', $violation->getInvalidValue()); + } + public function testValidateUniquenessWithNull() { $entityManagerName = "foo"; diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php index be9b9eee9f..55af119b3a 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php @@ -25,6 +25,7 @@ class UniqueEntity extends Constraint public $service = 'doctrine.orm.validator.unique'; public $em = null; public $fields = array(); + public $errorPath = null; public function getRequiredOptions() { diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php index 38929b02b9..13b7b251d1 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php @@ -47,6 +47,10 @@ class UniqueEntityValidator extends ConstraintValidator throw new UnexpectedTypeException($constraint->fields, 'array'); } + if (null !== $constraint->errorPath && !is_string($constraint->errorPath)) { + throw new UnexpectedTypeException($constraint->errorPath, 'string or null'); + } + $fields = (array) $constraint->fields; if (0 === count($fields)) { @@ -114,6 +118,8 @@ class UniqueEntityValidator extends ConstraintValidator return; } - $this->context->addViolationAtSubPath($fields[0], $constraint->message, array(), $criteria[$fields[0]]); + $errorPath = null !== $constraint->errorPath ? $constraint->errorPath : $fields[0]; + + $this->context->addViolationAtSubPath($errorPath, $constraint->message, array(), $criteria[$fields[0]]); } }