[Validator] Added ConstraintViolation::getConstraint()

This commit is contained in:
Bernhard Schussek 2014-08-12 15:33:06 +02:00
parent 1d7599d97f
commit ce1d2093bd
9 changed files with 120 additions and 18 deletions

19
UPGRADE-2.6.md Normal file
View File

@ -0,0 +1,19 @@
UPGRADE FROM 2.5 to 2.6
=======================
Validator
---------
* The internal method `setConstraint()` was added to
`Symfony\Component\Validator\Context\ExecutionContextInterface`. With
this method, the context is informed about the constraint that is currently
being validated.
If you implement this interface, make sure to add the method to your
implementation. The easiest solution is to just implement an empty method:
```php
public function setConstraint(Constraint $constraint)
{
}
```

View File

@ -6,6 +6,8 @@ CHANGELOG
* [BC BREAK] `FileValidator` disallow empty files
* [BC BREAK] `UserPasswordValidator` source message change
* [BC BREAK] added internal `ExecutionContextInterface::setConstraint()`
* added `ConstraintViolation::getConstraint()`
2.5.0
-----

View File

@ -53,6 +53,11 @@ class ConstraintViolation implements ConstraintViolationInterface
*/
private $invalidValue;
/**
* @var Constraint|null
*/
private $constraint;
/**
* @var mixed
*/
@ -74,8 +79,10 @@ class ConstraintViolation implements ConstraintViolationInterface
* @param int|null $plural The number for determining the plural
* form when translating the message
* @param mixed $code The error code of the violation
* @param Constraint|null $constraint The constraint that caused the
* violation
*/
public function __construct($message, $messageTemplate, array $parameters, $root, $propertyPath, $invalidValue, $plural = null, $code = null)
public function __construct($message, $messageTemplate, array $parameters, $root, $propertyPath, $invalidValue, $plural = null, $code = null, Constraint $constraint = null)
{
$this->message = $message;
$this->messageTemplate = $messageTemplate;
@ -84,6 +91,7 @@ class ConstraintViolation implements ConstraintViolationInterface
$this->root = $root;
$this->propertyPath = $propertyPath;
$this->invalidValue = $invalidValue;
$this->constraint = $constraint;
$this->code = $code;
}
@ -188,6 +196,16 @@ class ConstraintViolation implements ConstraintViolationInterface
return $this->invalidValue;
}
/**
* Returns the constraint that caused the violation.
*
* @return Constraint|null The constraint or null if it is not known
*/
public function getConstraint()
{
return $this->constraint;
}
/**
* {@inheritdoc}
*/

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\Validator\Context;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\ClassBasedInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\Exception\BadMethodCallException;
@ -99,6 +100,13 @@ class ExecutionContext implements ExecutionContextInterface
*/
private $group;
/**
* The currently validated constraint.
*
* @var Constraint|null
*/
private $constraint;
/**
* Stores which objects have been validated in which group.
*
@ -162,6 +170,14 @@ class ExecutionContext implements ExecutionContextInterface
$this->group = $group;
}
/**
* {@inheritdoc}
*/
public function setConstraint(Constraint $constraint)
{
$this->constraint = $constraint;
}
/**
* {@inheritdoc}
*/
@ -186,7 +202,8 @@ class ExecutionContext implements ExecutionContextInterface
$this->propertyPath,
$this->value,
null,
null
null,
$this->constraint
));
}
@ -197,6 +214,7 @@ class ExecutionContext implements ExecutionContextInterface
{
return new ConstraintViolationBuilder(
$this->violations,
$this->constraint,
$message,
$parameters,
$this->root,

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Validator\Context;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ExecutionContextInterface as LegacyExecutionContextInterface;
use Symfony\Component\Validator\Mapping\MetadataInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
@ -136,6 +137,16 @@ interface ExecutionContextInterface extends LegacyExecutionContextInterface
*/
public function setGroup($group);
/**
* Sets the currently validated constraint.
*
* @param Constraint $constraint The validated constraint
*
* @internal Used by the validator engine. Should not be called by user
* code.
*/
public function setConstraint(Constraint $constraint);
/**
* Marks an object as validated in a specific validation group.
*

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Validator\Tests\Constraints;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\ConstraintValidatorInterface;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\Context\ExecutionContext;
@ -49,6 +50,8 @@ abstract class AbstractConstraintValidatorTest extends \PHPUnit_Framework_TestCa
protected $propertyPath;
protected $constraint;
protected function setUp()
{
$this->group = 'MyGroup';
@ -57,6 +60,15 @@ abstract class AbstractConstraintValidatorTest extends \PHPUnit_Framework_TestCa
$this->value = 'InvalidValue';
$this->root = 'root';
$this->propertyPath = 'property.path';
// Initialize the context with some constraint so that we can
// successfully build a violation.
// The 2.4 API does not keep a reference to the current
// constraint yet. There the violation stores null.
$this->constraint = Validation::API_VERSION_2_4 === $this->getApiVersion()
? null
: new NotNull();
$this->context = $this->createContext();
$this->validator = $this->createValidator();
$this->validator->initialize($this->context);
@ -108,6 +120,7 @@ abstract class AbstractConstraintValidatorTest extends \PHPUnit_Framework_TestCa
$context->setGroup($this->group);
$context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
$context->setConstraint($this->constraint);
$validator->expects($this->any())
->method('inContext')
@ -127,7 +140,8 @@ abstract class AbstractConstraintValidatorTest extends \PHPUnit_Framework_TestCa
$propertyPath,
$invalidValue,
$plural,
$code
$code,
$this->constraint
);
}

View File

@ -20,6 +20,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\MetadataFactoryInterface;
use Symfony\Component\Validator\Tests\Fixtures\Entity;
use Symfony\Component\Validator\Tests\Fixtures\FailingConstraint;
use Symfony\Component\Validator\Tests\Fixtures\FakeClassMetadata;
use Symfony\Component\Validator\Tests\Fixtures\Reference;
use Symfony\Component\Validator\Validator\ValidatorInterface;
@ -752,4 +753,13 @@ abstract class Abstract2Dot5ApiTest extends AbstractValidatorTest
$this->assertTrue($entity->initialized);
}
public function testPassConstraintToViolation()
{
$constraint = new FailingConstraint();
$violations = $this->validate('Foobar', $constraint);
$this->assertCount(1, $violations);
$this->assertSame($constraint, $violations[0]->getConstraint());
}
}

View File

@ -856,6 +856,8 @@ class RecursiveContextualValidator implements ContextualValidatorInterface
$context->markConstraintAsValidated($cacheKey, $constraintHash);
}
$context->setConstraint($constraint);
$validator = $this->validatorFactory->getInstance($constraint);
$validator->initialize($context);
$validator->validate($value, $constraint);

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Validator\Violation;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\Util\PropertyPath;
@ -72,12 +73,17 @@ class ConstraintViolationBuilder implements ConstraintViolationBuilderInterface
*/
private $plural;
/**
* @var Constraint
*/
private $constraint;
/**
* @var mixed
*/
private $code;
public function __construct(ConstraintViolationList $violations, $message, array $parameters, $root, $propertyPath, $invalidValue, TranslatorInterface $translator, $translationDomain = null)
public function __construct(ConstraintViolationList $violations, Constraint $constraint, $message, array $parameters, $root, $propertyPath, $invalidValue, TranslatorInterface $translator, $translationDomain = null)
{
$this->violations = $violations;
$this->message = $message;
@ -87,6 +93,7 @@ class ConstraintViolationBuilder implements ConstraintViolationBuilderInterface
$this->invalidValue = $invalidValue;
$this->translator = $translator;
$this->translationDomain = $translationDomain;
$this->constraint = $constraint;
}
/**
@ -195,7 +202,8 @@ class ConstraintViolationBuilder implements ConstraintViolationBuilderInterface
$this->propertyPath,
$this->invalidValue,
$this->plural,
$this->code
$this->code,
$this->constraint
));
}
}