Added Symfony constraint annotation reader (#1202)

* Added Symfony constraint annotation reader

* StyleCI analysis changes

* StyleCI analysis

* StyleCI analysis

* No longer adding the constraint description for NotBlank and NotNull

* Updated doc comment

* Removed @param

* Removed the AbstractComparison condition

* Using Assert and removed unused method
This commit is contained in:
Martijn van Kempen 2018-01-25 14:59:48 +01:00 committed by Guilhem N
parent f193fdb1f1
commit b07043ce33
4 changed files with 128 additions and 0 deletions

View File

@ -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);
}
}

View File

@ -0,0 +1,115 @@
<?php
/*
* This file is part of the NelmioApiDocBundle package.
*
* (c) Nelmio
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Nelmio\ApiDocBundle\ModelDescriber\Annotations;
use Doctrine\Common\Annotations\Reader;
use EXSyst\Component\Swagger\Schema;
use ReflectionProperty;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @internal
*/
class SymfonyConstraintAnnotationReader
{
/**
* @var Reader
*/
private $annotationsReader;
/**
* @var Schema
*/
private $schema;
public function __construct(Reader $annotationsReader)
{
$this->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);
}
}
}

View File

@ -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;

View File

@ -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());
}