mirror of
https://github.com/retailcrm/NelmioApiDocBundle.git
synced 2025-02-10 11:39:25 +03:00
Merge remote-tracking branch 'origin/3.x' into HEAD
This commit is contained in:
commit
ad4e5551f5
@ -8,8 +8,8 @@ CHANGELOG
|
|||||||
3.7.0
|
3.7.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
* remove pattern added from the Expression Violation message.
|
|
||||||
* Added `@SerializedName` annotation support and name converters when using Symfony >= 4.2.
|
* Added `@SerializedName` annotation support and name converters when using Symfony >= 4.2.
|
||||||
|
* remove pattern added from the Expression Violation message.
|
||||||
|
|
||||||
3.3.0
|
3.3.0
|
||||||
-----
|
-----
|
||||||
|
@ -43,15 +43,15 @@ class AnnotationsReader
|
|||||||
$this->symfonyConstraintAnnotationReader->setSchema($schema);
|
$this->symfonyConstraintAnnotationReader->setSchema($schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPropertyName(\ReflectionProperty $reflectionProperty, string $default): string
|
public function getPropertyName($reflection, string $default): string
|
||||||
{
|
{
|
||||||
return $this->openApiAnnotationsReader->getPropertyName($reflectionProperty, $default);
|
return $this->openApiAnnotationsReader->getPropertyName($reflection, $default);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateProperty(\ReflectionProperty $reflectionProperty, OA\Property $property, array $serializationGroups = null): void
|
public function updateProperty($reflection, OA\Property $property, array $serializationGroups = null): void
|
||||||
{
|
{
|
||||||
$this->openApiAnnotationsReader->updateProperty($reflectionProperty, $property, $serializationGroups);
|
$this->openApiAnnotationsReader->updateProperty($reflection, $property, $serializationGroups);
|
||||||
$this->phpDocReader->updateProperty($reflectionProperty, $property);
|
$this->phpDocReader->updateProperty($reflection, $property);
|
||||||
$this->symfonyConstraintAnnotationReader->updateProperty($reflectionProperty, $property);
|
$this->symfonyConstraintAnnotationReader->updateProperty($reflection, $property);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,29 +50,33 @@ class OpenApiAnnotationsReader
|
|||||||
$schema->mergeProperties($oaSchema);
|
$schema->mergeProperties($oaSchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPropertyName(\ReflectionProperty $reflectionProperty, string $default): string
|
public function getPropertyName($reflection, string $default): string
|
||||||
{
|
{
|
||||||
/** @var OA\Property $oaProperty */
|
/** @var OA\Property $oaProperty */
|
||||||
if (!$oaProperty = $this->annotationsReader->getPropertyAnnotation($reflectionProperty, OA\Property::class)) {
|
if ($reflection instanceof \ReflectionProperty && !$oaProperty = $this->annotationsReader->getPropertyAnnotation($reflection, OA\Property::class)) {
|
||||||
|
return $default;
|
||||||
|
} elseif ($reflection instanceof \ReflectionMethod && !$oaProperty = $this->annotationsReader->getMethodAnnotation($reflection, OA\Property::class)) {
|
||||||
return $default;
|
return $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OA\UNDEFINED !== $oaProperty->property ? $oaProperty->property : $default;
|
return OA\UNDEFINED !== $oaProperty->property ? $oaProperty->property : $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateProperty(\ReflectionProperty $reflectionProperty, OA\Property $property, array $serializationGroups = null): void
|
public function updateProperty($reflection, OA\Property $property, array $serializationGroups = null): void
|
||||||
{
|
{
|
||||||
// In order to have nicer errors
|
// In order to have nicer errors
|
||||||
$declaringClass = $reflectionProperty->getDeclaringClass();
|
$declaringClass = $reflection->getDeclaringClass();
|
||||||
Analyser::$context = new Context([
|
Analyser::$context = new Context([
|
||||||
'namespace' => $declaringClass->getNamespaceName(),
|
'namespace' => $declaringClass->getNamespaceName(),
|
||||||
'class' => $declaringClass->getShortName(),
|
'class' => $declaringClass->getShortName(),
|
||||||
'property' => $reflectionProperty->name,
|
'property' => $reflection->name,
|
||||||
'filename' => $declaringClass->getFileName(),
|
'filename' => $declaringClass->getFileName(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/** @var OA\Property $oaProperty */
|
/** @var OA\Property $oaProperty */
|
||||||
if (!$oaProperty = $this->annotationsReader->getPropertyAnnotation($reflectionProperty, OA\Property::class)) {
|
if ($reflection instanceof \ReflectionProperty && !$oaProperty = $this->annotationsReader->getPropertyAnnotation($reflection, OA\Property::class)) {
|
||||||
|
return;
|
||||||
|
} elseif ($reflection instanceof \ReflectionMethod && !$oaProperty = $this->annotationsReader->getMethodAnnotation($reflection, OA\Property::class)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Analyser::$context = null;
|
Analyser::$context = null;
|
||||||
|
@ -32,10 +32,10 @@ class PropertyPhpDocReader
|
|||||||
/**
|
/**
|
||||||
* Update the Swagger information with information from the DocBlock comment.
|
* Update the Swagger information with information from the DocBlock comment.
|
||||||
*/
|
*/
|
||||||
public function updateProperty(\ReflectionProperty $reflectionProperty, OA\Property $property): void
|
public function updateProperty($reflection, OA\Property $property): void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$docBlock = $this->docBlockFactory->create($reflectionProperty);
|
$docBlock = $this->docBlockFactory->create($reflection);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// ignore
|
// ignore
|
||||||
return;
|
return;
|
||||||
|
@ -38,9 +38,13 @@ class SymfonyConstraintAnnotationReader
|
|||||||
/**
|
/**
|
||||||
* Update the given property and schema with defined Symfony constraints.
|
* Update the given property and schema with defined Symfony constraints.
|
||||||
*/
|
*/
|
||||||
public function updateProperty(\ReflectionProperty $reflectionProperty, OA\Property $property): void
|
public function updateProperty($reflection, OA\Property $property): void
|
||||||
{
|
{
|
||||||
$annotations = $this->annotationsReader->getPropertyAnnotations($reflectionProperty);
|
if ($reflection instanceof \ReflectionProperty) {
|
||||||
|
$annotations = $this->annotationsReader->getPropertyAnnotations($reflection);
|
||||||
|
} else {
|
||||||
|
$annotations = $this->annotationsReader->getMethodAnnotations($reflection);
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($annotations as $annotation) {
|
foreach ($annotations as $annotation) {
|
||||||
if ($annotation instanceof Assert\NotBlank || $annotation instanceof Assert\NotNull) {
|
if ($annotation instanceof Assert\NotBlank || $annotation instanceof Assert\NotNull) {
|
||||||
@ -67,7 +71,7 @@ class SymfonyConstraintAnnotationReader
|
|||||||
$property->minItems = (int) $annotation->min;
|
$property->minItems = (int) $annotation->min;
|
||||||
$property->maxItems = (int) $annotation->max;
|
$property->maxItems = (int) $annotation->max;
|
||||||
} elseif ($annotation instanceof Assert\Choice) {
|
} elseif ($annotation instanceof Assert\Choice) {
|
||||||
$values = $annotation->callback ? call_user_func(is_array($annotation->callback) ? $annotation->callback : [$reflectionProperty->class, $annotation->callback]) : $annotation->choices;
|
$values = $annotation->callback ? call_user_func(is_array($annotation->callback) ? $annotation->callback : [$reflection->class, $annotation->callback]) : $annotation->choices;
|
||||||
$property->enum = array_values($values);
|
$property->enum = array_values($values);
|
||||||
} elseif ($annotation instanceof Assert\Range) {
|
} elseif ($annotation instanceof Assert\Range) {
|
||||||
$property->minimum = (int) $annotation->min;
|
$property->minimum = (int) $annotation->min;
|
||||||
|
@ -66,8 +66,9 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
|
|||||||
$context['serializer_groups'] = array_filter($model->getGroups(), 'is_string');
|
$context['serializer_groups'] = array_filter($model->getGroups(), 'is_string');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$reflClass = new \ReflectionClass($class);
|
||||||
$annotationsReader = new AnnotationsReader($this->doctrineReader, $this->modelRegistry, $this->mediaTypes);
|
$annotationsReader = new AnnotationsReader($this->doctrineReader, $this->modelRegistry, $this->mediaTypes);
|
||||||
$annotationsReader->updateDefinition(new \ReflectionClass($class), $schema);
|
$annotationsReader->updateDefinition($reflClass, $schema);
|
||||||
|
|
||||||
$propertyInfoProperties = $this->propertyInfo->getProperties($class, $context);
|
$propertyInfoProperties = $this->propertyInfo->getProperties($class, $context);
|
||||||
if (null === $propertyInfoProperties) {
|
if (null === $propertyInfoProperties) {
|
||||||
@ -77,19 +78,22 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
|
|||||||
foreach ($propertyInfoProperties as $propertyName) {
|
foreach ($propertyInfoProperties as $propertyName) {
|
||||||
$serializedName = null !== $this->nameConverter ? $this->nameConverter->normalize($propertyName, $class, null, null !== $model->getGroups() ? ['groups' => $model->getGroups()] : []) : $propertyName;
|
$serializedName = null !== $this->nameConverter ? $this->nameConverter->normalize($propertyName, $class, null, null !== $model->getGroups() ? ['groups' => $model->getGroups()] : []) : $propertyName;
|
||||||
|
|
||||||
// read property options from OpenApi Property annotation if it exists
|
$reflections = $this->getReflections($reflClass, $propertyName);
|
||||||
if (property_exists($class, $propertyName)) {
|
|
||||||
$reflectionProperty = new \ReflectionProperty($class, $propertyName);
|
|
||||||
$property = Util::getProperty($schema, $annotationsReader->getPropertyName($reflectionProperty, $serializedName));
|
|
||||||
|
|
||||||
$groups = $model->getGroups();
|
// Check if a custom name is set
|
||||||
if (isset($groups[$propertyName]) && is_array($groups[$propertyName])) {
|
foreach ($reflections as $reflection) {
|
||||||
$groups = $model->getGroups()[$propertyName];
|
$serializedName = $annotationsReader->getPropertyName($reflection, $serializedName);
|
||||||
}
|
}
|
||||||
|
|
||||||
$annotationsReader->updateProperty($reflectionProperty, $property, $groups);
|
$property = Util::getProperty($schema, $annotationsReader->getPropertyName($reflection, $serializedName));
|
||||||
} else {
|
|
||||||
$property = Util::getProperty($schema, $serializedName);
|
// Interpret additional options
|
||||||
|
$groups = $model->getGroups();
|
||||||
|
if (isset($groups[$propertyName]) && is_array($groups[$propertyName])) {
|
||||||
|
$groups = $model->getGroups()[$propertyName];
|
||||||
|
}
|
||||||
|
foreach ($reflections as $reflection) {
|
||||||
|
$annotationsReader->updateProperty($reflection, $property, $groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If type manually defined
|
// If type manually defined
|
||||||
@ -106,6 +110,34 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \ReflectionProperty[]|\ReflectionMethod[]
|
||||||
|
*/
|
||||||
|
private function getReflections(\ReflectionClass $reflClass, string $propertyName): array
|
||||||
|
{
|
||||||
|
$reflections = [];
|
||||||
|
if ($reflClass->hasProperty($propertyName)) {
|
||||||
|
$reflections[] = $reflClass->getProperty($propertyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
$camelProp = $this->camelize($propertyName);
|
||||||
|
foreach (['', 'get', 'is', 'has', 'can', 'add', 'remove', 'set'] as $prefix) {
|
||||||
|
if ($reflClass->hasMethod($prefix.$camelProp)) {
|
||||||
|
$reflections[] = $reflClass->getMethod($prefix.$camelProp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $reflections;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Camelizes a given string.
|
||||||
|
*/
|
||||||
|
private function camelize(string $string): string
|
||||||
|
{
|
||||||
|
return str_replace(' ', '', ucwords(str_replace('_', ' ', $string)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Type[] $types
|
* @param Type[] $types
|
||||||
*/
|
*/
|
||||||
|
@ -103,6 +103,8 @@ class SymfonyConstraints
|
|||||||
private $propertyLessThanOrEqual;
|
private $propertyLessThanOrEqual;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @Assert\Count(min="0", max="10")
|
||||||
|
*
|
||||||
* @param int $propertyNotBlank
|
* @param int $propertyNotBlank
|
||||||
*/
|
*/
|
||||||
public function setPropertyNotBlank(int $propertyNotBlank): void
|
public function setPropertyNotBlank(int $propertyNotBlank): void
|
||||||
|
@ -21,7 +21,7 @@ class User
|
|||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
*
|
*
|
||||||
* @OA\Property(description = "User id", readOnly = true, title = "userid", example=1, default = null)
|
* @OA\Property(description = "User id", readOnly = true, title = "userid", default = null)
|
||||||
*/
|
*/
|
||||||
private $id;
|
private $id;
|
||||||
|
|
||||||
@ -102,6 +102,7 @@ class User
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $id
|
* @param int $id
|
||||||
|
* @OA\Property(example=1)
|
||||||
*/
|
*/
|
||||||
public function setId(int $id)
|
public function setId(int $id)
|
||||||
{
|
{
|
||||||
|
@ -342,6 +342,8 @@ class FunctionalTest extends WebTestCase
|
|||||||
'properties' => [
|
'properties' => [
|
||||||
'propertyNotBlank' => [
|
'propertyNotBlank' => [
|
||||||
'type' => 'integer',
|
'type' => 'integer',
|
||||||
|
'maxItems' => '10',
|
||||||
|
'minItems' => '0',
|
||||||
],
|
],
|
||||||
'propertyNotNull' => [
|
'propertyNotNull' => [
|
||||||
'type' => 'integer',
|
'type' => 'integer',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user