diff --git a/ModelDescriber/ObjectModelDescriber.php b/ModelDescriber/ObjectModelDescriber.php index aae6f19..d5f293c 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,17 +25,23 @@ 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, + $propertyDescribers ) { $this->propertyInfo = $propertyInfo; $this->doctrineReader = $reader; + $this->propertyDescribers = $propertyDescribers; } public function describe(Model $model, Schema $schema) @@ -86,40 +93,24 @@ 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)); - } + $this->describeProperty($type, $model, $property, $propertyName); + } + } - $property->setType('array'); - $property = $property->getItems(); + private function describeProperty(Type $type, Model $model, Schema $property, string $propertyName) + { + foreach ($this->propertyDescribers as $propertyDescriber) { + if ($propertyDescriber instanceof ModelRegistryAwareInterface) { + $propertyDescriber->setModelRegistry($this->modelRegistry); } + if ($propertyDescriber->supports($type)) { + $propertyDescriber->describe($type, $property, $model->getGroups()); - 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)); + return; } } + + 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(), $model->getType()->getClassName(), $propertyName)); } public function supports(Model $model): bool diff --git a/PropertyDescriber/ArrayPropertyDescriber.php b/PropertyDescriber/ArrayPropertyDescriber.php new file mode 100644 index 0000000..1882d7f --- /dev/null +++ b/PropertyDescriber/ArrayPropertyDescriber.php @@ -0,0 +1,57 @@ +propertyDescribers = $propertyDescribers; + } + + public function describe(Type $type, Schema $property, array $groups = null) + { + $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, $groups); + + break; + } + } + } + + public function supports(Type $type): bool + { + return $type->isCollection(); + } +} diff --git a/PropertyDescriber/BooleanPropertyDescriber.php b/PropertyDescriber/BooleanPropertyDescriber.php new file mode 100644 index 0000000..6d3b4ed --- /dev/null +++ b/PropertyDescriber/BooleanPropertyDescriber.php @@ -0,0 +1,28 @@ +setType('boolean'); + } + + public function supports(Type $type): bool + { + return Type::BUILTIN_TYPE_BOOL === $type->getBuiltinType(); + } +} diff --git a/PropertyDescriber/DateTimePropertyDescriber.php b/PropertyDescriber/DateTimePropertyDescriber.php new file mode 100644 index 0000000..56ea985 --- /dev/null +++ b/PropertyDescriber/DateTimePropertyDescriber.php @@ -0,0 +1,30 @@ +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); + } +} diff --git a/PropertyDescriber/FloatPropertyDescriber.php b/PropertyDescriber/FloatPropertyDescriber.php new file mode 100644 index 0000000..e87d91e --- /dev/null +++ b/PropertyDescriber/FloatPropertyDescriber.php @@ -0,0 +1,29 @@ +setType('number'); + $property->setFormat('float'); + } + + public function supports(Type $type): bool + { + return Type::BUILTIN_TYPE_FLOAT === $type->getBuiltinType(); + } +} diff --git a/PropertyDescriber/IntegerPropertyDescriber.php b/PropertyDescriber/IntegerPropertyDescriber.php new file mode 100644 index 0000000..e66a11c --- /dev/null +++ b/PropertyDescriber/IntegerPropertyDescriber.php @@ -0,0 +1,28 @@ +setType('integer'); + } + + public function supports(Type $type): bool + { + return Type::BUILTIN_TYPE_INT === $type->getBuiltinType(); + } +} diff --git a/PropertyDescriber/ObjectPropertyDescriber.php b/PropertyDescriber/ObjectPropertyDescriber.php new file mode 100644 index 0000000..cc9619e --- /dev/null +++ b/PropertyDescriber/ObjectPropertyDescriber.php @@ -0,0 +1,37 @@ +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(); + } +} diff --git a/PropertyDescriber/PropertyDescriberInterface.php b/PropertyDescriber/PropertyDescriberInterface.php new file mode 100644 index 0000000..bd92789 --- /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(); + } +} diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 978930e..c575d42 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -41,6 +41,7 @@ + @@ -49,6 +50,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +