NelmioApiDocBundle/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php
Filip Benčo 78664ef9ec
OpenApi 3 Support (#1623)
* Initial pass for OA3 upgrade

* Fix Util Tests

* Fix first batch of Unit Tests. Up to Model

* Another batch of fixed tests

* Update annotations

* Convert Model & Property Describers

* Update tests, Fix RouteDescribers, FIx additional bugs

* Another batch of updates

* Another batch of fixed Functional Tests

* Fix FunctionalTest tests

* Fix Bazinga Tests

* FIx FOS Rest

* Fix JMS TEsts & describers

* Fix all Tests

* Fix few stuff from own CR

* CS Fixes

* CS Fixes 2

* CS Fixes 3

* CS Fixes 4

* Remove collection bug

* Updates after first CRs

* CS

* Drop support for SF3

* Update the docs

* Add an upgrade guide

* misc doc fixes

* Configurable media types

* Code Style Fixes

* Don't use ::$ref for @Response and @RequestBody

* Fix upgrading guide

* Fix OA case

Co-authored-by: Filip Benčo <filip.benco@websupport.sk>
Co-authored-by: Guilhem Niot <guilhem.niot@gmail.com>
Co-authored-by: Mantis Development <mantis@users.noreply.github.com>
2020-05-28 13:19:11 +02:00

122 lines
4.1 KiB
PHP

<?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 OpenApi\Annotations as OA;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @internal
*/
class SymfonyConstraintAnnotationReader
{
/**
* @var Reader
*/
private $annotationsReader;
/**
* @var OA\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, OA\Property $property): void
{
$annotations = $this->annotationsReader->getPropertyAnnotations($reflectionProperty);
foreach ($annotations as $annotation) {
if ($annotation instanceof Assert\NotBlank || $annotation instanceof Assert\NotNull) {
// The field is required
if (null === $this->schema) {
continue;
}
$propertyName = $this->getSchemaPropertyName($property);
if (null === $propertyName) {
continue;
}
$existingRequiredFields = OA\UNDEFINED !== $this->schema->required ? $this->schema->required : [];
$existingRequiredFields[] = $propertyName;
$this->schema->required = array_values(array_unique($existingRequiredFields));
} elseif ($annotation instanceof Assert\Length) {
$property->minLength = $annotation->min;
$property->maxLength = $annotation->max;
} elseif ($annotation instanceof Assert\Regex) {
$this->appendPattern($property, $annotation->getHtmlPattern());
} elseif ($annotation instanceof Assert\Count) {
$property->minItems = $annotation->min;
$property->maxItems = $annotation->max;
} elseif ($annotation instanceof Assert\Choice) {
$values = $annotation->callback ? call_user_func(is_array($annotation->callback) ? $annotation->callback : [$reflectionProperty->class, $annotation->callback]) : $annotation->choices;
$property->enum = array_values($values);
} elseif ($annotation instanceof Assert\Expression) {
$this->appendPattern($property, $annotation->message);
} elseif ($annotation instanceof Assert\Range) {
$property->minimum = $annotation->min;
$property->maximum = $annotation->max;
} elseif ($annotation instanceof Assert\LessThan) {
$property->exclusiveMaximum= $annotation->value;
} elseif ($annotation instanceof Assert\LessThanOrEqual) {
$property->maximum = $annotation->value;
}
}
}
public function setSchema($schema): void
{
$this->schema = $schema;
}
/**
* Get assigned property name for property schema.
*/
private function getSchemaPropertyName(OA\Schema $property): ?string
{
if (null === $this->schema) {
return null;
}
foreach ($this->schema->properties as $schemaProperty) {
if ($schemaProperty === $property) {
return OA\UNDEFINED !== $schemaProperty->property ? $schemaProperty->property : null;
}
}
return null;
}
/**
* Append the pattern from the constraint to the existing pattern.
*/
private function appendPattern(OA\Schema $property, $newPattern): void
{
if (null === $newPattern) {
return;
}
if (OA\UNDEFINED !== $property->pattern) {
$property->pattern = sprintf('%s, %s', $property->pattern, $newPattern);
} else {
$property->pattern = $newPattern;
}
}
}