diff --git a/src/Symfony/Component/Validator/Constraints/Choice.php b/src/Symfony/Component/Validator/Constraints/Choice.php index 1e37c31f4388b..b5bcc6d3d9864 100644 --- a/src/Symfony/Component/Validator/Constraints/Choice.php +++ b/src/Symfony/Component/Validator/Constraints/Choice.php @@ -52,7 +52,8 @@ public function getDefaultOption() } public function __construct( - $choices = null, + $options = [], + array $choices = null, $callback = null, bool $multiple = null, bool $strict = null, @@ -63,12 +64,13 @@ public function __construct( string $minMessage = null, string $maxMessage = null, $groups = null, - $payload = null, - array $options = [] + $payload = null ) { - if (\is_array($choices) && \is_string(key($choices))) { - $options = array_merge($choices, $options); - } elseif (null !== $choices) { + if (\is_array($options) && $options && array_is_list($options)) { + $choices = $choices ?? $options; + $options = []; + } + if (null !== $choices) { $options['value'] = $choices; } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ChoiceTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ChoiceTest.php index 8b5879aedcb42..e94bffbf28d3e 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ChoiceTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ChoiceTest.php @@ -12,6 +12,9 @@ namespace Symfony\Component\Validator\Tests\Constraints; use PHPUnit\Framework\TestCase; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader; use Symfony\Component\Validator\Tests\Fixtures\ConstraintChoiceWithPreset; class ChoiceTest extends TestCase @@ -22,4 +25,50 @@ public function testSetDefaultPropertyChoice() self::assertEquals(['A', 'B', 'C'], $constraint->choices); } + + /** + * @requires PHP 8 + */ + public function testAttributes() + { + $metadata = new ClassMetadata(ChoiceDummy::class); + $loader = new AnnotationLoader(); + self::assertTrue($loader->loadClassMetadata($metadata)); + + /** @var Choice $aConstraint */ + [$aConstraint] = $metadata->properties['a']->getConstraints(); + self::assertSame([1, 2], $aConstraint->choices); + self::assertSame(['Default', 'ChoiceDummy'], $aConstraint->groups); + + /** @var Choice $bConstraint */ + [$bConstraint] = $metadata->properties['b']->getConstraints(); + self::assertSame(['foo', 'bar'], $bConstraint->choices); + self::assertSame('myMessage', $bConstraint->message); + self::assertSame(['Default', 'ChoiceDummy'], $bConstraint->groups); + + /** @var Choice $cConstraint */ + [$cConstraint] = $metadata->properties['c']->getConstraints(); + self::assertSame([1, 2], $aConstraint->choices); + self::assertSame(['my_group'], $cConstraint->groups); + self::assertSame('some attached data', $cConstraint->payload); + + /** @var Choice $stringIndexedConstraint */ + [$stringIndexedConstraint] = $metadata->properties['stringIndexed']->getConstraints(); + self::assertSame(['one' => 1, 'two' => 2], $stringIndexedConstraint->choices); + } +} + +class ChoiceDummy +{ + #[Choice(choices: [1, 2])] + private $a; + + #[Choice(choices: ['foo', 'bar'], message: 'myMessage')] + private $b; + + #[Choice([1, 2], groups: ['my_group'], payload: 'some attached data')] + private $c; + + #[Choice(choices: ['one' => 1, 'two' => 2])] + private $stringIndexed; } diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index 659b13ceb0cfd..4caf290db196f 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -22,6 +22,7 @@ "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php73": "~1.0", "symfony/polyfill-php80": "^1.16", + "symfony/polyfill-php81": "^1.22", "symfony/translation-contracts": "^1.1|^2" }, "require-dev": {