From c0e661f9fce8b5e9d97ef535c53679f21ef73689 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Fri, 20 Feb 2026 18:10:04 +0100 Subject: [PATCH 1/2] Fix missing required properties when using GroupSequence --- .../Metadata/Property/ValidatorPropertyMetadataFactory.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php b/src/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php index cd0fb0f600..ddfa7991f3 100644 --- a/src/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php +++ b/src/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php @@ -162,6 +162,10 @@ private function getValidationGroups(ValidatorClassMetadataInterface $classMetad } } + if ($classMetadata->hasGroupSequence()) { + return $classMetadata->getGroupSequence()->groups; + } + if (!method_exists($classMetadata, 'getDefaultGroup')) { throw new \UnexpectedValueException(\sprintf('Validator class metadata expected to have method "%s".', 'getDefaultGroup')); } From cca47749998f20309b71d77d2e3d27eda1db4079 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Fri, 20 Feb 2026 18:26:51 +0100 Subject: [PATCH 2/2] Add test --- .../DummyValidatedEntityWithGroupSequence.php | 89 +++++++++++++++++++ .../ValidatorPropertyMetadataFactoryTest.php | 25 ++++++ 2 files changed, 114 insertions(+) create mode 100644 src/Symfony/Tests/Fixtures/DummyValidatedEntityWithGroupSequence.php diff --git a/src/Symfony/Tests/Fixtures/DummyValidatedEntityWithGroupSequence.php b/src/Symfony/Tests/Fixtures/DummyValidatedEntityWithGroupSequence.php new file mode 100644 index 0000000000..354207b6eb --- /dev/null +++ b/src/Symfony/Tests/Fixtures/DummyValidatedEntityWithGroupSequence.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Symfony\Tests\Fixtures; + +use Symfony\Component\Validator\Constraints as Assert; + +/** + * Dummy Validated Entity. + * + * @author Baptiste Meyer + */ +#[Assert\GroupSequence(['dummy', 'DummyValidatedEntityWithGroupSequence'])] +class DummyValidatedEntityWithGroupSequence +{ + /** + * @var int A dummy ID + */ + public $dummyId; + + /** + * @var string A dummy + */ + #[Assert\NotBlank] + #[Assert\Length(max: 4, min: 10)] + #[Assert\Regex(pattern: '/^dummy$/')] + public $dummy; + + /** + * @var string + */ + #[Assert\Email] + #[Assert\NotBlank(allowNull: true)] + public $dummyEmail; + + /** + * @var string + */ + #[Assert\Uuid] + public $dummyUuid; + + /** + * @var string + */ + #[Assert\Ip] + public $dummyIpv4; + + /** + * @var string + */ + #[Assert\Ip(version: '6')] + public $dummyIpv6; + + /** + * @var \DateTimeInterface A dummy date + */ + #[Assert\Date] + public $dummyDate; + + /** + * @var string A dummy group + */ + #[Assert\NotNull(groups: ['dummy'])] + public $dummyGroup; + + /** + * @var string A dummy url + */ + #[Assert\Url()] + public $dummyUrl; + + /** + * @return string[] + */ + public static function getValidationGroups(): array + { + return ['dummy']; + } +} diff --git a/src/Symfony/Tests/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php b/src/Symfony/Tests/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php index 9dcb0d94be..7b2b6031ac 100644 --- a/src/Symfony/Tests/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php +++ b/src/Symfony/Tests/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php @@ -26,6 +26,7 @@ use ApiPlatform\Symfony\Tests\Fixtures\DummyUniqueValidatedEntity; use ApiPlatform\Symfony\Tests\Fixtures\DummyValidatedChoiceEntity; use ApiPlatform\Symfony\Tests\Fixtures\DummyValidatedEntity; +use ApiPlatform\Symfony\Tests\Fixtures\DummyValidatedEntityWithGroupSequence; use ApiPlatform\Symfony\Tests\Fixtures\DummyValidatedHostnameEntity; use ApiPlatform\Symfony\Tests\Fixtures\DummyValidatedUlidEntity; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaChoiceRestriction; @@ -141,6 +142,30 @@ public function testCreateWithPropertyWithoutConstraints(): void $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); } + public function testCreateWithPropertyWithRequiredConstraintsAndGroupSequence(): void + { + $propertyMetadata = (new ApiProperty())->withDescription('A dummy group')->withReadable(true)->withWritable(true); + $expectedPropertyMetadata = $propertyMetadata->withRequired(true); + + $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); + $decoratedPropertyMetadataFactory->create(DummyValidatedEntityWithGroupSequence::class, 'dummyGroup', [])->willReturn($propertyMetadata)->shouldBeCalled(); + + $validatorClassMetadata = new ClassMetadata(DummyValidatedEntityWithGroupSequence::class); + (new AttributeLoader())->loadClassMetadata($validatorClassMetadata); + + $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); + $validatorMetadataFactory->getMetadataFor(DummyValidatedEntityWithGroupSequence::class)->willReturn($validatorClassMetadata)->shouldBeCalled(); + + $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( + $validatorMetadataFactory->reveal(), + $decoratedPropertyMetadataFactory->reveal(), + [] + ); + $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntityWithGroupSequence::class, 'dummyGroup'); + + $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); + } + public function testCreateWithPropertyWithRightValidationGroupsAndRequiredConstraints(): void { $propertyMetadata = (new ApiProperty())->withDescription('A dummy group')->withReadable(true)->withWritable(true);