Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 97779ec

Browse files
bug #39872 [Validator] propagate the object being validated to nested constraints (xabbuh)
This PR was merged into the 5.1 branch. Discussion ---------- [Validator] propagate the object being validated to nested constraints | Q | A | ------------- | --- | Branch? | 5.1 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #39145 | License | MIT | Doc PR | Commits ------- 8c1bac9 propagate the object being validated to sub-constraints
2 parents 5532e0a + 8c1bac9 commit 97779ec

File tree

3 files changed

+61
-22
lines changed

3 files changed

+61
-22
lines changed

src/Symfony/Component/Validator/Constraints/AtLeastOneOfValidator.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@ public function validate($value, Constraint $constraint)
3434
$messages = [$constraint->message];
3535

3636
foreach ($constraint->constraints as $key => $item) {
37-
$violations = $validator->validate($value, $item, $this->context->getGroup());
37+
$executionContext = clone $this->context;
38+
$executionContext->setNode($value, $this->context->getObject(), $this->context->getMetadata(), $this->context->getPropertyPath());
39+
$violations = $validator->inContext($executionContext)->validate($value, $item, $this->context->getGroup())->getViolations();
3840

39-
if (0 === \count($violations)) {
41+
if (\count($this->context->getViolations()) === \count($violations)) {
4042
return;
4143
}
4244

src/Symfony/Component/Validator/Context/ExecutionContext.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,4 +364,9 @@ public function generateCacheKey($object)
364364

365365
return $this->cachedObjectsRefs[$object];
366366
}
367+
368+
public function __clone()
369+
{
370+
$this->violations = clone $this->violations;
371+
}
367372
}

src/Symfony/Component/Validator/Tests/Constraints/AtLeastOneOfValidatorTest.php

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,22 @@
1818
use Symfony\Component\Validator\Constraints\Country;
1919
use Symfony\Component\Validator\Constraints\DivisibleBy;
2020
use Symfony\Component\Validator\Constraints\EqualTo;
21+
use Symfony\Component\Validator\Constraints\Expression;
2122
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
2223
use Symfony\Component\Validator\Constraints\IdenticalTo;
2324
use Symfony\Component\Validator\Constraints\Language;
2425
use Symfony\Component\Validator\Constraints\Length;
2526
use Symfony\Component\Validator\Constraints\LessThan;
2627
use Symfony\Component\Validator\Constraints\Negative;
28+
use Symfony\Component\Validator\Constraints\NotNull;
2729
use Symfony\Component\Validator\Constraints\Range;
2830
use Symfony\Component\Validator\Constraints\Regex;
2931
use Symfony\Component\Validator\Constraints\Unique;
32+
use Symfony\Component\Validator\Constraints\Valid;
33+
use Symfony\Component\Validator\ConstraintViolation;
34+
use Symfony\Component\Validator\Mapping\ClassMetadata;
35+
use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;
36+
use Symfony\Component\Validator\Mapping\MetadataInterface;
3037
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
3138
use Symfony\Component\Validator\Validation;
3239

@@ -45,15 +52,7 @@ protected function createValidator()
4552
*/
4653
public function testValidCombinations($value, $constraints)
4754
{
48-
$i = 0;
49-
50-
foreach ($constraints as $constraint) {
51-
$this->expectViolationsAt($i++, $value, $constraint);
52-
}
53-
54-
$this->validator->validate($value, new AtLeastOneOf($constraints));
55-
56-
$this->assertNoViolation();
55+
$this->assertCount(0, Validation::createValidator()->validate($value, new AtLeastOneOf($constraints)));
5756
}
5857

5958
public function getValidCombinations()
@@ -96,18 +95,20 @@ public function getValidCombinations()
9695
public function testInvalidCombinationsWithDefaultMessage($value, $constraints)
9796
{
9897
$atLeastOneOf = new AtLeastOneOf(['constraints' => $constraints]);
98+
$validator = Validation::createValidator();
9999

100100
$message = [$atLeastOneOf->message];
101101

102102
$i = 0;
103103

104104
foreach ($constraints as $constraint) {
105-
$message[] = ' ['.($i + 1).'] '.$this->expectViolationsAt($i++, $value, $constraint)->get(0)->getMessage();
105+
$message[] = sprintf(' [%d] %s', ++$i, $validator->validate($value, $constraint)->get(0)->getMessage());
106106
}
107107

108-
$this->validator->validate($value, $atLeastOneOf);
108+
$violations = $validator->validate($value, $atLeastOneOf);
109109

110-
$this->buildViolation(implode('', $message))->setCode(AtLeastOneOf::AT_LEAST_ONE_OF_ERROR)->assertRaised();
110+
$this->assertCount(1, $violations, sprintf('1 violation expected. Got %u.', \count($violations)));
111+
$this->assertEquals(new ConstraintViolation(implode('', $message), implode('', $message), [], $value, '', $value, null, AtLeastOneOf::AT_LEAST_ONE_OF_ERROR, $atLeastOneOf), $violations->get(0));
111112
}
112113

113114
/**
@@ -117,15 +118,10 @@ public function testInvalidCombinationsWithCustomMessage($value, $constraints)
117118
{
118119
$atLeastOneOf = new AtLeastOneOf(['constraints' => $constraints, 'message' => 'foo', 'includeInternalMessages' => false]);
119120

120-
$i = 0;
121-
122-
foreach ($constraints as $constraint) {
123-
$this->expectViolationsAt($i++, $value, $constraint);
124-
}
121+
$violations = Validation::createValidator()->validate($value, $atLeastOneOf);
125122

126-
$this->validator->validate($value, $atLeastOneOf);
127-
128-
$this->buildViolation('foo')->setCode(AtLeastOneOf::AT_LEAST_ONE_OF_ERROR)->assertRaised();
123+
$this->assertCount(1, $violations, sprintf('1 violation expected. Got %u.', \count($violations)));
124+
$this->assertEquals(new ConstraintViolation('foo', 'foo', [], $value, '', $value, null, AtLeastOneOf::AT_LEAST_ONE_OF_ERROR, $atLeastOneOf), $violations->get(0));
129125
}
130126

131127
public function getInvalidCombinations()
@@ -184,4 +180,40 @@ public function testGroupsArePropagatedToNestedConstraints()
184180

185181
$this->assertCount(1, $violations);
186182
}
183+
184+
public function testContextIsPropagatedToNestedConstraints()
185+
{
186+
$validator = Validation::createValidatorBuilder()
187+
->setMetadataFactory(new class() implements MetadataFactoryInterface {
188+
public function getMetadataFor($classOrObject): MetadataInterface
189+
{
190+
return (new ClassMetadata(ExpressionConstraintNested::class))
191+
->addPropertyConstraint('foo', new AtLeastOneOf([
192+
new NotNull(),
193+
new Expression('this.getFoobar() in ["bar", "baz"]'),
194+
]));
195+
}
196+
197+
public function hasMetadataFor($classOrObject): bool
198+
{
199+
return ExpressionConstraintNested::class === $classOrObject;
200+
}
201+
})
202+
->getValidator()
203+
;
204+
205+
$violations = $validator->validate(new ExpressionConstraintNested(), new Valid());
206+
207+
$this->assertCount(0, $violations);
208+
}
209+
}
210+
211+
class ExpressionConstraintNested
212+
{
213+
private $foo;
214+
215+
public function getFoobar(): string
216+
{
217+
return 'bar';
218+
}
187219
}

0 commit comments

Comments
 (0)