[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.
This commit is contained in:
Christophe Coevoet 2012-07-12 00:19:02 +02:00
parent d4b40fb24b
commit ac7875569a
3 changed files with 33 additions and 3 deletions

View File

@ -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";

View File

@ -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()
{

View File

@ -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]]);
}
}