From 56c8ff8b219cbb4d151f2459cb1c2b2718f6059a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 28 Nov 2016 07:53:19 +0100 Subject: [PATCH] ensure the proper context for nested validations --- .../Validator/Context/ExecutionContext.php | 5 +++++ .../Tests/Validator/Abstract2Dot5ApiTest.php | 19 +++++++++++++++++++ .../RecursiveContextualValidator.php | 10 ++++++++++ 3 files changed, 34 insertions(+) diff --git a/src/Symfony/Component/Validator/Context/ExecutionContext.php b/src/Symfony/Component/Validator/Context/ExecutionContext.php index dce975c2038e6..721766a253383 100644 --- a/src/Symfony/Component/Validator/Context/ExecutionContext.php +++ b/src/Symfony/Component/Validator/Context/ExecutionContext.php @@ -287,6 +287,11 @@ public function getGroup() return $this->group; } + public function getConstraint() + { + return $this->constraint; + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php b/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php index 27d5a25ce26a8..1e6f3403e7284 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Validator\Tests\Validator; use Symfony\Component\Validator\Constraints\Callback; +use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Traverse; @@ -720,4 +721,22 @@ public function testPassConstraintToViolation() $this->assertCount(1, $violations); $this->assertSame($constraint, $violations[0]->getConstraint()); } + + public function testCollectionConstraitViolationHasCorrectContext() + { + $data = array( + 'foo' => 'fooValue', + ); + + // Missing field must not be the first in the collection validation + $constraint = new Collection(array( + 'foo' => new NotNull(), + 'bar' => new NotNull(), + )); + + $violations = $this->validate($data, $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 db5d8809690d1..bbd09b821241c 100644 --- a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php +++ b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php @@ -14,6 +14,7 @@ use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\ConstraintValidatorFactoryInterface; +use Symfony\Component\Validator\Context\ExecutionContext; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\NoSuchMetadataException; @@ -110,6 +111,11 @@ public function validate($value, $constraints = null, $groups = null) $previousMetadata = $this->context->getMetadata(); $previousPath = $this->context->getPropertyPath(); $previousGroup = $this->context->getGroup(); + $previousConstraint = null; + + if ($this->context instanceof ExecutionContext || method_exists($this->context, 'getConstraint')) { + $previousConstraint = $this->context->getConstraint(); + } // If explicit constraints are passed, validate the value against // those constraints @@ -138,6 +144,10 @@ public function validate($value, $constraints = null, $groups = null) $this->context->setNode($previousValue, $previousObject, $previousMetadata, $previousPath); $this->context->setGroup($previousGroup); + if (null !== $previousConstraint) { + $this->context->setConstraint($previousConstraint); + } + return $this; }