diff --git a/ModelDescriber/Annotations/AnnotationsReader.php b/ModelDescriber/Annotations/AnnotationsReader.php index 294d62c..ed0f5e6 100644 --- a/ModelDescriber/Annotations/AnnotationsReader.php +++ b/ModelDescriber/Annotations/AnnotationsReader.php @@ -23,6 +23,7 @@ class AnnotationsReader private $phpDocReader; private $swgAnnotationsReader; + private $symfonyConstraintAnnotationReader; public function __construct(Reader $annotationsReader) { @@ -30,16 +31,19 @@ class AnnotationsReader $this->phpDocReader = new PropertyPhpDocReader(); $this->swgAnnotationsReader = new SwgAnnotationsReader($annotationsReader); + $this->symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($annotationsReader); } public function updateDefinition(\ReflectionClass $reflectionClass, Schema $schema) { $this->swgAnnotationsReader->updateDefinition($reflectionClass, $schema); + $this->symfonyConstraintAnnotationReader->setSchema($schema); } public function updateProperty(\ReflectionProperty $reflectionProperty, Schema $property) { $this->phpDocReader->updateProperty($reflectionProperty, $property); $this->swgAnnotationsReader->updateProperty($reflectionProperty, $property); + $this->symfonyConstraintAnnotationReader->updateProperty($reflectionProperty, $property); } } diff --git a/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php b/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php new file mode 100644 index 0000000..fac864d --- /dev/null +++ b/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php @@ -0,0 +1,115 @@ +annotationsReader = $annotationsReader; + } + + /** + * Update the given property and schema with defined Symfony constraints. + */ + public function updateProperty(ReflectionProperty $reflectionProperty, Schema $property) + { + $annotations = $this->annotationsReader->getPropertyAnnotations($reflectionProperty); + + foreach ($annotations as $annotation) { + if ($annotation instanceof Assert\NotBlank || $annotation instanceof Assert\NotNull) { + $this->updateSchemaDefinitionWithRequiredProperty($reflectionProperty); + } + + if ($annotation instanceof Assert\Length) { + if ($annotation->min > 0) { + $this->updateSchemaDefinitionWithRequiredProperty($reflectionProperty); + } + + $property->setMinLength($annotation->min); + $property->setMaxLength($annotation->max); + } + + if ($annotation instanceof Assert\Regex) { + $this->appendPattern($property, $annotation->getHtmlPattern()); + } + + if ($annotation instanceof Assert\DateTime) { + $this->appendPattern($property, $annotation->format); + } + + if ($annotation instanceof Assert\Count) { + $property->setMinItems($annotation->min); + $property->setMaxItems($annotation->max); + } + + if ($annotation instanceof Assert\Choice) { + $property->setEnum($annotation->choices); + } + + if ($annotation instanceof Assert\Expression) { + $this->appendPattern($property, $annotation->message); + } + } + } + + public function setSchema($schema) + { + $this->schema = $schema; + } + + /** + * Set the required properties on the scheme. + */ + private function updateSchemaDefinitionWithRequiredProperty(ReflectionProperty $reflectionProperty) + { + if (null === $this->schema) { + return; + } + + $existingRequiredFields = $this->schema->getRequired() ?? []; + + $existingRequiredFields[] = $reflectionProperty->getName(); + + $this->schema->setRequired(array_unique($existingRequiredFields)); + } + + /** + * Append the pattern from the constraint to the existing pattern. + */ + private function appendPattern(Schema $property, string $newPattern) + { + if (null !== $property->getPattern()) { + $property->setPattern(sprintf('%s, %s', $property->getPattern(), $newPattern)); + } else { + $property->setPattern($newPattern); + } + } +} diff --git a/Tests/Functional/Entity/JMSUser.php b/Tests/Functional/Entity/JMSUser.php index 7a7dc7e..7eb5cab 100644 --- a/Tests/Functional/Entity/JMSUser.php +++ b/Tests/Functional/Entity/JMSUser.php @@ -13,6 +13,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use JMS\Serializer\Annotation as Serializer; use Swagger\Annotations as SWG; +use Symfony\Component\Validator\Constraints as Assert; /** * User. @@ -27,6 +28,8 @@ class JMSUser * @Serializer\Groups({"list"}) * * @SWG\Property(description = "User id", readOnly = true, title = "userid", example=1, default = null) + * + * @Assert\NotBlank() */ private $id; diff --git a/Tests/Functional/JMSFunctionalTest.php b/Tests/Functional/JMSFunctionalTest.php index 9304a78..73b3035 100644 --- a/Tests/Functional/JMSFunctionalTest.php +++ b/Tests/Functional/JMSFunctionalTest.php @@ -67,6 +67,9 @@ class JMSFunctionalTest extends WebTestCase 'type' => 'date', ], ], + 'required' => [ + 'id', + ], ], $this->getModel('JMSUser')->toArray()); } @@ -96,6 +99,9 @@ class JMSFunctionalTest extends WebTestCase 'example' => '1', ], ], + 'required' => [ + 'id', + ], ], $this->getModel('JMSUser2')->toArray()); }