diff --git a/UPGRADE-2.6.md b/UPGRADE-2.6.md new file mode 100644 index 0000000000000..c03c3730084e8 --- /dev/null +++ b/UPGRADE-2.6.md @@ -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) + { + } + ``` diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index 6cb64292bd21d..ad92e56230b54 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -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 ----- diff --git a/src/Symfony/Component/Validator/ConstraintViolation.php b/src/Symfony/Component/Validator/ConstraintViolation.php index d6a4e3095f424..5cf57ed4f8dc5 100644 --- a/src/Symfony/Component/Validator/ConstraintViolation.php +++ b/src/Symfony/Component/Validator/ConstraintViolation.php @@ -53,6 +53,11 @@ class ConstraintViolation implements ConstraintViolationInterface */ private $invalidValue; + /** + * @var Constraint|null + */ + private $constraint; + /** * @var mixed */ @@ -61,21 +66,23 @@ class ConstraintViolation implements ConstraintViolationInterface /** * Creates a new constraint violation. * - * @param string $message The violation message - * @param string $messageTemplate The raw violation message - * @param array $parameters The parameters to substitute in the - * raw violation message - * @param mixed $root The value originally passed to the - * validator - * @param string $propertyPath The property path from the root - * value to the invalid value - * @param mixed $invalidValue The invalid value that caused this - * violation - * @param int|null $plural The number for determining the plural - * form when translating the message - * @param mixed $code The error code of the violation - */ - public function __construct($message, $messageTemplate, array $parameters, $root, $propertyPath, $invalidValue, $plural = null, $code = null) + * @param string $message The violation message + * @param string $messageTemplate The raw violation message + * @param array $parameters The parameters to substitute in the + * raw violation message + * @param mixed $root The value originally passed to the + * validator + * @param string $propertyPath The property path from the root + * value to the invalid value + * @param mixed $invalidValue The invalid value that caused this + * violation + * @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, Constraint $constraint = null) { $this->message = $message; $this->messageTemplate = $messageTemplate; @@ -84,6 +91,7 @@ public function __construct($message, $messageTemplate, array $parameters, $root $this->root = $root; $this->propertyPath = $propertyPath; $this->invalidValue = $invalidValue; + $this->constraint = $constraint; $this->code = $code; } @@ -188,6 +196,16 @@ public function getInvalidValue() 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} */ diff --git a/src/Symfony/Component/Validator/Context/ExecutionContext.php b/src/Symfony/Component/Validator/Context/ExecutionContext.php index a30382d3b7c2f..c38490739d32c 100644 --- a/src/Symfony/Component/Validator/Context/ExecutionContext.php +++ b/src/Symfony/Component/Validator/Context/ExecutionContext.php @@ -13,6 +13,7 @@ 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 @@ public function setGroup($group) $this->group = $group; } + /** + * {@inheritdoc} + */ + public function setConstraint(Constraint $constraint) + { + $this->constraint = $constraint; + } + /** * {@inheritdoc} */ @@ -186,7 +202,8 @@ public function addViolation($message, array $parameters = array(), $invalidValu $this->propertyPath, $this->value, null, - null + null, + $this->constraint )); } @@ -197,6 +214,7 @@ public function buildViolation($message, array $parameters = array()) { return new ConstraintViolationBuilder( $this->violations, + $this->constraint, $message, $parameters, $this->root, diff --git a/src/Symfony/Component/Validator/Context/ExecutionContextInterface.php b/src/Symfony/Component/Validator/Context/ExecutionContextInterface.php index f63ce15261298..cd4bae6057f67 100644 --- a/src/Symfony/Component/Validator/Context/ExecutionContextInterface.php +++ b/src/Symfony/Component/Validator/Context/ExecutionContextInterface.php @@ -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 @@ public function setNode($value, $object, MetadataInterface $metadata = null, $pr */ 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. * diff --git a/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php index 5aecf5470b7f7..ef29fe34a7f3d 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php @@ -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 @@ protected function setUp() $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 @@ protected function createContext() $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 @@ protected function createViolation($message, array $parameters = array(), $prope $propertyPath, $invalidValue, $plural, - $code + $code, + $this->constraint ); } diff --git a/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php b/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php index e920da9a72197..ac63d94010336 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php @@ -20,6 +20,7 @@ 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 @@ public function testInitializeObjectsOnFirstValidation() $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()); + } } diff --git a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php index 29d0c6c00c71c..2da1887afd338 100644 --- a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php +++ b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php @@ -856,6 +856,8 @@ private function validateInGroup($value, $cacheKey, MetadataInterface $metadata, $context->markConstraintAsValidated($cacheKey, $constraintHash); } + $context->setConstraint($constraint); + $validator = $this->validatorFactory->getInstance($constraint); $validator->initialize($context); $validator->validate($value, $constraint); diff --git a/src/Symfony/Component/Validator/Violation/ConstraintViolationBuilder.php b/src/Symfony/Component/Validator/Violation/ConstraintViolationBuilder.php index 969b79cdeddd5..6d6bd02774468 100644 --- a/src/Symfony/Component/Validator/Violation/ConstraintViolationBuilder.php +++ b/src/Symfony/Component/Validator/Violation/ConstraintViolationBuilder.php @@ -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 @@ public function __construct(ConstraintViolationList $violations, $message, array $this->invalidValue = $invalidValue; $this->translator = $translator; $this->translationDomain = $translationDomain; + $this->constraint = $constraint; } /** @@ -195,7 +202,8 @@ public function addViolation() $this->propertyPath, $this->invalidValue, $this->plural, - $this->code + $this->code, + $this->constraint )); } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy