diff --git a/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php b/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php index c3261814f..421ddaba4 100644 --- a/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php +++ b/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php @@ -76,13 +76,21 @@ public function updateProperty($reflection, OA\Property $property): void } elseif ($annotation instanceof Assert\Regex) { $this->appendPattern($property, $annotation->getHtmlPattern()); } elseif ($annotation instanceof Assert\Count) { - $property->minItems = (int) $annotation->min; - $property->maxItems = (int) $annotation->max; + if (isset($annotation->min)) { + $property->minItems = (int) $annotation->min; + } + if (isset($annotation->max)) { + $property->maxItems = (int) $annotation->max; + } } elseif ($annotation instanceof Assert\Choice) { $this->applyEnumFromChoiceConstraint($property, $annotation, $reflection); } elseif ($annotation instanceof Assert\Range) { - $property->minimum = (int) $annotation->min; - $property->maximum = (int) $annotation->max; + if (isset($annotation->min)) { + $property->minimum = (int) $annotation->min; + } + if (isset($annotation->max)) { + $property->maximum = (int) $annotation->max; + } } elseif ($annotation instanceof Assert\LessThan) { $property->exclusiveMaximum = true; $property->maximum = (int) $annotation->value; diff --git a/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php b/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php index 6afa2d67b..d3c96f347 100644 --- a/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php +++ b/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php @@ -244,4 +244,148 @@ public function provideLengthConstraintDoesNotSetMinLengthIfMinIsNotSet(): itera }]; } } + + /** + * @param object $entity + * @group https://github.com/nelmio/NelmioApiDocBundle/issues/1821 + * @dataProvider provideCountConstraintDoesNotSetMinItemsIfMinIsNotSet + */ + public function testCountConstraintDoesNotSetMinItemsIfMinIsNotSet($entity) + { + $schema = new OA\Schema([]); + $schema->merge([new OA\Property(['property' => 'property1'])]); + + $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader()); + $symfonyConstraintAnnotationReader->setSchema($schema); + + $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); + + $this->assertSame(OA\UNDEFINED, $schema->properties[0]->minItems); + $this->assertSame(10, $schema->properties[0]->maxItems); + } + + public function provideCountConstraintDoesNotSetMinItemsIfMinIsNotSet(): iterable + { + yield 'Annotations' => [new class() { + /** + * @Assert\Count(max = 10) + */ + private $property1; + }]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'Attributes' => [new class() { + #[Assert\Count(max: 10)] + private $property1; + }]; + } + } + + /** + * @param object $entity + * @group https://github.com/nelmio/NelmioApiDocBundle/issues/1821 + * @dataProvider provideCountConstraintDoesNotSetMaxItemsIfMaxIsNotSet + */ + public function testCountConstraintDoesNotSetMaxItemsIfMaxIsNotSet($entity) + { + $schema = new OA\Schema([]); + $schema->merge([new OA\Property(['property' => 'property1'])]); + + $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader()); + $symfonyConstraintAnnotationReader->setSchema($schema); + + $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); + + $this->assertSame(OA\UNDEFINED, $schema->properties[0]->maxItems); + $this->assertSame(10, $schema->properties[0]->minItems); + } + + public function provideCountConstraintDoesNotSetMaxItemsIfMaxIsNotSet(): iterable + { + yield 'Annotations' => [new class() { + /** + * @Assert\Count(min = 10) + */ + private $property1; + }]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'Attributes' => [new class() { + #[Assert\Count(min: 10)] + private $property1; + }]; + } + } + + /** + * @param object $entity + * @group https://github.com/nelmio/NelmioApiDocBundle/issues/1822 + * @dataProvider provideRangeConstraintDoesNotSetMaximumIfMaxIsNotSet + */ + public function testRangeConstraintDoesNotSetMaximumIfMaxIsNotSet($entity) + { + $schema = new OA\Schema([]); + $schema->merge([new OA\Property(['property' => 'property1'])]); + + $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader()); + $symfonyConstraintAnnotationReader->setSchema($schema); + + $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); + + $this->assertSame(OA\UNDEFINED, $schema->properties[0]->maximum); + $this->assertSame(10, $schema->properties[0]->minimum); + } + + public function provideRangeConstraintDoesNotSetMaximumIfMaxIsNotSet(): iterable + { + yield 'Annotations' => [new class() { + /** + * @Assert\Range(min = 10) + */ + private $property1; + }]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'Attributes' => [new class() { + #[Assert\Range(min: 10)] + private $property1; + }]; + } + } + + /** + * @param object $entity + * @group https://github.com/nelmio/NelmioApiDocBundle/issues/1822 + * @dataProvider provideRangeConstraintDoesNotSetMinimumIfMinIsNotSet + */ + public function testRangeConstraintDoesNotSetMinimumIfMinIsNotSet($entity) + { + $schema = new OA\Schema([]); + $schema->merge([new OA\Property(['property' => 'property1'])]); + + $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader()); + $symfonyConstraintAnnotationReader->setSchema($schema); + + $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); + + $this->assertSame(OA\UNDEFINED, $schema->properties[0]->minimum); + $this->assertSame(10, $schema->properties[0]->maximum); + } + + public function provideRangeConstraintDoesNotSetMinimumIfMinIsNotSet(): iterable + { + yield 'Annotations' => [new class() { + /** + * @Assert\Range(max = 10) + */ + private $property1; + }]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'Attributes' => [new class() { + #[Assert\Range(max: 10)] + private $property1; + }]; + } + } }