Skip to content

Commit 587c291

Browse files
author
symfonyaml
committed
[Validator][Choice] Fix callback option if not array or iterable returned
1 parent ebd2270 commit 587c291

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ public function validate($value, Constraint $constraint)
5555
throw new ConstraintDefinitionException('The Choice constraint expects a valid callback.');
5656
}
5757
$choices = $choices();
58+
if ($choices instanceof \Traversable) {
59+
$choices = iterator_to_array($choices);
60+
}
61+
if (!is_array($choices)) {
62+
throw new ConstraintDefinitionException(sprintf('The Choice constraint callback "%s" expects to return an iterable, got "%s".', trim($this->formatValue($constraint->callback), '"'), get_debug_type($choices)));
63+
}
5864
} else {
5965
$choices = $constraint->choices;
6066
}

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ public function objectMethodCallback()
3939
return ['foo', 'bar'];
4040
}
4141

42+
public static function staticCallbackTraversable()
43+
{
44+
yield 1;
45+
yield 2;
46+
yield 3;
47+
}
48+
49+
public static function staticCallbackInvalid()
50+
{
51+
return null;
52+
}
53+
4254
public function testExpectArrayIfMultipleIsTrue()
4355
{
4456
$this->expectException(UnexpectedValueException::class);
@@ -134,6 +146,31 @@ public function testValidChoiceCallbackContextMethod()
134146
$this->assertNoViolation();
135147
}
136148

149+
public function testInvalidChoiceCallbackContextMethod()
150+
{
151+
$this->expectException(ConstraintDefinitionException::class);
152+
$this->expectExceptionMessage('The Choice constraint callback "staticCallbackInvalid" expects to return an iterable, got "null".');
153+
154+
// search $this for "staticCallbackInvalid"
155+
$this->setObject($this);
156+
157+
$constraint = new Choice(['callback' => 'staticCallbackInvalid']);
158+
159+
$this->validator->validate('bar', $constraint);
160+
}
161+
162+
public function testValidChoiceCallbackContextMethodTraversable()
163+
{
164+
// search $this for "staticCallbackTraversable"
165+
$this->setObject($this);
166+
167+
$constraint = new Choice(['callback' => 'staticCallbackTraversable']);
168+
169+
$this->validator->validate(2, $constraint);
170+
171+
$this->assertNoViolation();
172+
}
173+
137174
public function testValidChoiceCallbackContextObjectMethod()
138175
{
139176
// search $this for "objectMethodCallback"

0 commit comments

Comments
 (0)