From f9eacee3fdbec2928a50247b22163b5bcff1341f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Ben=C4=8Do?= Date: Fri, 13 Dec 2019 21:40:42 +0100 Subject: [PATCH] Add exntensible Property Describers --- ModelDescriber/ObjectModelDescriber.php | 46 +++++---------- PropertyDescriber/ArrayPropertyDescriber.php | 58 +++++++++++++++++++ .../BooleanPropertyDescriber.php | 29 ++++++++++ .../DateTimePropertyDescriber.php | 31 ++++++++++ PropertyDescriber/FloatPropertyDescriber.php | 30 ++++++++++ .../IntegerPropertyDescriber.php | 29 ++++++++++ PropertyDescriber/ObjectPropertyDescriber.php | 36 ++++++++++++ .../PropertyDescriberInterface.php | 22 +++++++ PropertyDescriber/StringPropertyDescriber.php | 29 ++++++++++ Resources/config/services.xml | 30 ++++++++++ 10 files changed, 310 insertions(+), 30 deletions(-) create mode 100644 PropertyDescriber/ArrayPropertyDescriber.php create mode 100644 PropertyDescriber/BooleanPropertyDescriber.php create mode 100644 PropertyDescriber/DateTimePropertyDescriber.php create mode 100644 PropertyDescriber/FloatPropertyDescriber.php create mode 100644 PropertyDescriber/IntegerPropertyDescriber.php create mode 100644 PropertyDescriber/ObjectPropertyDescriber.php create mode 100644 PropertyDescriber/PropertyDescriberInterface.php create mode 100644 PropertyDescriber/StringPropertyDescriber.php diff --git a/ModelDescriber/ObjectModelDescriber.php b/ModelDescriber/ObjectModelDescriber.php index aae6f19..32f60c1 100644 --- a/ModelDescriber/ObjectModelDescriber.php +++ b/ModelDescriber/ObjectModelDescriber.php @@ -17,6 +17,7 @@ use Nelmio\ApiDocBundle\Describer\ModelRegistryAwareInterface; use Nelmio\ApiDocBundle\Describer\ModelRegistryAwareTrait; use Nelmio\ApiDocBundle\Model\Model; use Nelmio\ApiDocBundle\ModelDescriber\Annotations\AnnotationsReader; +use Nelmio\ApiDocBundle\PropertyDescriber\PropertyDescriberInterface; use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; use Symfony\Component\PropertyInfo\Type; @@ -24,16 +25,22 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar { use ModelRegistryAwareTrait; + /** @var PropertyInfoExtractorInterface */ private $propertyInfo; + /** @var Reader */ private $doctrineReader; + /** @var PropertyDescriberInterface[] */ + private $propertyDescribers; private $swaggerDefinitionAnnotationReader; public function __construct( PropertyInfoExtractorInterface $propertyInfo, - Reader $reader + Reader $reader, + array $propertyDescribers ) { $this->propertyInfo = $propertyInfo; + $this->propertyDescribers = $propertyDescribers; $this->doctrineReader = $reader; } @@ -86,39 +93,18 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar } $type = $types[0]; - if ($type->isCollection()) { - $type = $type->getCollectionValueType(); - if (null === $type) { - throw new \LogicException(sprintf('Property "%s:%s" is an array, but its items type isn\'t specified. You can specify that by using the type `string[]` for instance or `@SWG\Property(type="array", @SWG\Items(type="string"))`.', $class, $propertyName)); + foreach ($this->propertyDescribers as $propertyDescriber) { + if ($propertyDescriber instanceof ModelRegistryAwareInterface) { + $propertyDescriber->setModelRegistry($this->modelRegistry); } + if ($propertyDescriber->supports($type)) { + $propertyDescriber->describe($type, $property, $model->getGroups()); - $property->setType('array'); - $property = $property->getItems(); + break; + } } - if (Type::BUILTIN_TYPE_STRING === $type->getBuiltinType()) { - $property->setType('string'); - } elseif (Type::BUILTIN_TYPE_BOOL === $type->getBuiltinType()) { - $property->setType('boolean'); - } elseif (Type::BUILTIN_TYPE_INT === $type->getBuiltinType()) { - $property->setType('integer'); - } elseif (Type::BUILTIN_TYPE_FLOAT === $type->getBuiltinType()) { - $property->setType('number'); - $property->setFormat('float'); - } elseif (Type::BUILTIN_TYPE_OBJECT === $type->getBuiltinType()) { - if (is_a($type->getClassName(), \DateTimeInterface::class, true)) { - $property->setType('string'); - $property->setFormat('date-time'); - } else { - $type = new Type($type->getBuiltinType(), false, $type->getClassName(), $type->isCollection(), $type->getCollectionKeyType(), $type->getCollectionValueType()); // ignore nullable field - - $property->setRef( - $this->modelRegistry->register(new Model($type, $model->getGroups())) - ); - } - } else { - throw new \Exception(sprintf('Type "%s" is not supported in %s::$%s. You may use the `@SWG\Property(type="")` annotation to specify it manually.', $type->getBuiltinType(), $class, $propertyName)); - } + throw new \Exception(sprintf('Type "%s" is not supported in %s::$%s. You may use the `@SWG\Property(type="")` annotation to specify it manually.', $type->getBuiltinType(), $class, $propertyName)); } } diff --git a/PropertyDescriber/ArrayPropertyDescriber.php b/PropertyDescriber/ArrayPropertyDescriber.php new file mode 100644 index 0000000..fead14e --- /dev/null +++ b/PropertyDescriber/ArrayPropertyDescriber.php @@ -0,0 +1,58 @@ +propertyDescribers = $propertyDescribers; + } + + public function describe(Type $type, Schema $property, array $groups) + { + $type = $type->getCollectionValueType(); + if (null === $type) { + throw new \LogicException(sprintf('Property "%s:%s" is an array, but its items type isn\'t specified. You can specify that by using the type `string[]` for instance or `@SWG\Property(type="array", @SWG\Items(type="string"))`.', $class, $propertyName)); + } + + $property->setType('array'); + $property = $property->getItems(); + + foreach ($this->propertyDescribers as $propertyDescriber) { + if ($propertyDescriber instanceof ModelRegistryAwareInterface) { + $propertyDescriber->setModelRegistry($this->modelRegistry); + } + if ($propertyDescriber->supports($type)) { + $propertyDescriber->describe($type, $property); + + break; + } + } + } + + public function supports(Type $type): bool + { + return $type->isCollection(); + } + +} \ No newline at end of file diff --git a/PropertyDescriber/BooleanPropertyDescriber.php b/PropertyDescriber/BooleanPropertyDescriber.php new file mode 100644 index 0000000..b56daca --- /dev/null +++ b/PropertyDescriber/BooleanPropertyDescriber.php @@ -0,0 +1,29 @@ +setType('boolean'); + } + + public function supports(Type $type): bool + { + return Type::BUILTIN_TYPE_BOOL === $type->getBuiltinType(); + } +} \ No newline at end of file diff --git a/PropertyDescriber/DateTimePropertyDescriber.php b/PropertyDescriber/DateTimePropertyDescriber.php new file mode 100644 index 0000000..c7f10a1 --- /dev/null +++ b/PropertyDescriber/DateTimePropertyDescriber.php @@ -0,0 +1,31 @@ +setType('string'); + $property->setFormat('date-time'); + } + + public function supports(Type $type): bool + { + return Type::BUILTIN_TYPE_OBJECT === $type->getBuiltinType() + && is_a($type->getClassName(), \DateTimeInterface::class, true); + } +} \ No newline at end of file diff --git a/PropertyDescriber/FloatPropertyDescriber.php b/PropertyDescriber/FloatPropertyDescriber.php new file mode 100644 index 0000000..6aef4f8 --- /dev/null +++ b/PropertyDescriber/FloatPropertyDescriber.php @@ -0,0 +1,30 @@ +setType('number'); + $property->setFormat('float'); + } + + public function supports(Type $type): bool + { + return Type::BUILTIN_TYPE_FLOAT === $type->getBuiltinType(); + } +} \ No newline at end of file diff --git a/PropertyDescriber/IntegerPropertyDescriber.php b/PropertyDescriber/IntegerPropertyDescriber.php new file mode 100644 index 0000000..377aca8 --- /dev/null +++ b/PropertyDescriber/IntegerPropertyDescriber.php @@ -0,0 +1,29 @@ +setType('integer'); + } + + public function supports(Type $type): bool + { + return Type::BUILTIN_TYPE_INT === $type->getBuiltinType(); + } +} \ No newline at end of file diff --git a/PropertyDescriber/ObjectPropertyDescriber.php b/PropertyDescriber/ObjectPropertyDescriber.php new file mode 100644 index 0000000..5e66548 --- /dev/null +++ b/PropertyDescriber/ObjectPropertyDescriber.php @@ -0,0 +1,36 @@ +getBuiltinType(), false, $type->getClassName(), $type->isCollection(), $type->getCollectionKeyType(), $type->getCollectionValueType()); // ignore nullable field + + $property->setRef( + $this->modelRegistry->register(new Model($type, $groups)) + ); + } + + public function supports(Type $type): bool + { + return Type::BUILTIN_TYPE_OBJECT === $type->getBuiltinType(); + } +} \ No newline at end of file diff --git a/PropertyDescriber/PropertyDescriberInterface.php b/PropertyDescriber/PropertyDescriberInterface.php new file mode 100644 index 0000000..7f37d9d --- /dev/null +++ b/PropertyDescriber/PropertyDescriberInterface.php @@ -0,0 +1,22 @@ +setType('string'); + } + + public function supports(Type $type): bool + { + return Type::BUILTIN_TYPE_STRING === $type->getBuiltinType(); + } +} \ No newline at end of file diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 978930e..72df8e9 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -41,6 +41,7 @@ + @@ -49,6 +50,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +