merged branch stof/unique_validator_error_mapping (PR #4868)

Commits
-------

ac78755 [DoctrineBridge] Added an option to choose the subpath for the violation

Discussion
----------

[DoctrineBridge] Added an option to choose the subpath for the violation

Bug fix: no
Feature addition: yes
Backwards compatibility break: no
Symfony2 tests pass: yes
Fixes the following tickets: #3866
Todo: -

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:
Fabien Potencier 2012-07-12 07:05:33 +02:00
commit 7680101c5e
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]]);
}
}