Skip to content

Commit ca804fb

Browse files
author
symfonyaml
committed
[Validator] Fix choice callback option if not array or iterable returned
1 parent a52bbe7 commit ca804fb

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ public function validate($value, Constraint $constraint)
5555
throw new ConstraintDefinitionException('The Choice constraint expects a valid callback.');
5656
}
5757
$choices = $choices();
58+
if (is_iterable($choices)) {
59+
$choices = iterator_to_array($choices, true);
60+
}
61+
if (!is_array($choices)) {
62+
throw new ConstraintDefinitionException(sprintf(
63+
'The Choice constraint expects the callback to return an iterable value, got %s.',
64+
get_debug_type($choices),
65+
));
66+
}
5867
} else {
5968
$choices = $constraint->choices;
6069
}

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ public static function staticCallback()
3434
return ['foo', 'bar'];
3535
}
3636

37+
public static function staticCallbackInvalid()
38+
{
39+
return null;
40+
}
41+
42+
public static function staticCallbackIterable()
43+
{
44+
yield 1;
45+
yield 2;
46+
yield 3;
47+
}
48+
3749
public function objectMethodCallback()
3850
{
3951
return ['foo', 'bar'];
@@ -185,6 +197,30 @@ public function testInvalidChoice(Choice $constraint)
185197
->assertRaised();
186198
}
187199

200+
public function testInvalidChoiceCallbackContextMethod()
201+
{
202+
$this->expectException(ConstraintDefinitionException::class);
203+
$this->expectExceptionMessage('The Choice constraint expects the callback to return an iterable value, got null.');
204+
// search $this for "staticCallbackIterable"
205+
$this->setObject($this);
206+
207+
$constraint = new Choice(['callback' => 'staticCallbackInvalid']);
208+
209+
$this->validator->validate('bar', $constraint);
210+
}
211+
212+
public function testValidChoiceCallbackContextMethodIterable()
213+
{
214+
// search $this for "staticCallbackIterable"
215+
$this->setObject($this);
216+
217+
$constraint = new Choice(['callback' => 'staticCallbackIterable']);
218+
219+
$this->validator->validate(1, $constraint);
220+
221+
$this->assertNoViolation();
222+
}
223+
188224
public static function provideConstraintsWithMessage(): iterable
189225
{
190226
yield 'Doctrine style' => [new Choice(['choices' => ['foo', 'bar'], 'message' => 'myMessage'])];

0 commit comments

Comments
 (0)