From 7fd8c0ecfedc87bac6f0f39bd78503f23d0a18b4 Mon Sep 17 00:00:00 2001 From: Christopher Davis Date: Tue, 25 May 2021 06:26:27 -0500 Subject: [PATCH] Check if `min` and `max` Are Set on Count Constraints It's possible to set a count constraint with a min but no max, which would generate an OpenAPI Schema like... "property": { "type": "array", "minItems": 1, "maxItems": 0 } With this change the schema will only set `minItems` in that example. --- .../SymfonyConstraintAnnotationReader.php | 8 ++- .../SymfonyConstraintAnnotationReaderTest.php | 72 +++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php b/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php index c326181..aad50c6 100644 --- a/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php +++ b/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php @@ -76,8 +76,12 @@ class SymfonyConstraintAnnotationReader } 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) { diff --git a/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php b/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php index 6afa2d6..8e69ee8 100644 --- a/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php +++ b/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php @@ -244,4 +244,76 @@ class SymfonyConstraintAnnotationReaderTest extends TestCase }]; } } + + /** + * @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; + }]; + } + } }