mirror of
https://github.com/retailcrm/NelmioApiDocBundle.git
synced 2025-02-09 02:59:27 +03:00
Merge branch 'master' into complex_groups
This commit is contained in:
commit
48107de67d
@ -22,14 +22,9 @@ matrix:
|
||||
include:
|
||||
- php: 7.0
|
||||
env: COMPOSER_FLAGS="--prefer-lowest"
|
||||
- php: 7.1
|
||||
env: SF_4="true"
|
||||
|
||||
before_install:
|
||||
- phpenv config-rm xdebug.ini
|
||||
- if [ "$SF_4" == "true" ]; then composer config minimum-stability dev; fi
|
||||
- if [ "$SF_4" == "true" ]; then composer require symfony/symfony:4.0.* --dev --no-update; fi
|
||||
- if [ "$SF_4" == "true" ]; then composer require jms/serializer-bundle:dev-master --dev --no-update; fi
|
||||
|
||||
install: composer update $COMPOSER_FLAGS --prefer-stable
|
||||
|
||||
|
35
DependencyInjection/Compiler/ConfigurationPass.php
Normal file
35
DependencyInjection/Compiler/ConfigurationPass.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?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\DependencyInjection\Compiler;
|
||||
|
||||
use Nelmio\ApiDocBundle\ModelDescriber\FormModelDescriber;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Enables the FormModelDescriber only if forms are enabled.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class ConfigurationPass implements CompilerPassInterface
|
||||
{
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if ($container->hasDefinition('form.factory')) {
|
||||
$container->register('nelmio_api_doc.model_describers.form', FormModelDescriber::class)
|
||||
->setPublic(false)
|
||||
->addArgument(new Reference('form.factory'))
|
||||
->addTag('nelmio_api_doc.model_describer', ['priority' => 100]);
|
||||
}
|
||||
}
|
||||
}
|
@ -12,7 +12,6 @@
|
||||
namespace Nelmio\ApiDocBundle\DependencyInjection;
|
||||
|
||||
use FOS\RestBundle\Controller\Annotations\ParamInterface;
|
||||
use Nelmio\ApiDocBundle\ModelDescriber\FormModelDescriber;
|
||||
use Nelmio\ApiDocBundle\ModelDescriber\JMSModelDescriber;
|
||||
use Nelmio\ApiDocBundle\Routing\FilteredRouteCollectionBuilder;
|
||||
use phpDocumentor\Reflection\DocBlockFactory;
|
||||
@ -22,7 +21,6 @@ use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
|
||||
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
@ -52,13 +50,6 @@ final class NelmioApiDocExtension extends Extension implements PrependExtensionI
|
||||
|
||||
$loader->load('services.xml');
|
||||
|
||||
if (interface_exists(FormInterface::class)) {
|
||||
$container->register('nelmio_api_doc.model_describers.form', FormModelDescriber::class)
|
||||
->setPublic(false)
|
||||
->addArgument(new Reference('form.factory'))
|
||||
->addTag('nelmio_api_doc.model_describer', ['priority' => 100]);
|
||||
}
|
||||
|
||||
// Filter routes
|
||||
$routesDefinition = (new Definition(RouteCollection::class))
|
||||
->setFactory([new Reference('router'), 'getRouteCollection']);
|
||||
@ -103,6 +94,7 @@ final class NelmioApiDocExtension extends Extension implements PrependExtensionI
|
||||
new Reference('jms_serializer.metadata_factory'),
|
||||
new Reference('jms_serializer.naming_strategy'),
|
||||
new Reference('nelmio_api_doc.model_describers.swagger_property_annotation_reader'),
|
||||
new Reference('nelmio_api_doc.model_describers.phpdoc_property_annotation_reader'),
|
||||
])
|
||||
->addTag('nelmio_api_doc.model_describer', ['priority' => 50]);
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ final class SwaggerPhpDescriber extends ExternalDocDescriber implements ModelReg
|
||||
|
||||
private function normalizePath(string $path): string
|
||||
{
|
||||
if (substr($path, -10) === '.{_format}') {
|
||||
if ('.{_format}' === substr($path, -10)) {
|
||||
$path = substr($path, 0, -10);
|
||||
}
|
||||
|
||||
|
@ -78,6 +78,11 @@ final class FormModelDescriber implements ModelDescriberInterface, ModelRegistry
|
||||
break;
|
||||
}
|
||||
|
||||
if ('integer' === $blockPrefix) {
|
||||
$property->setType('integer');
|
||||
break;
|
||||
}
|
||||
|
||||
if ('date' === $blockPrefix) {
|
||||
$property->setType('string');
|
||||
$property->setFormat('date');
|
||||
@ -98,6 +103,11 @@ final class FormModelDescriber implements ModelDescriberInterface, ModelRegistry
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ('checkbox' === $blockPrefix) {
|
||||
$property->setType('boolean');
|
||||
}
|
||||
|
||||
if ('collection' === $blockPrefix) {
|
||||
$subType = $config->getOption('entry_type');
|
||||
$property->setType('array');
|
||||
|
@ -35,15 +35,18 @@ class JMSModelDescriber implements ModelDescriberInterface, ModelRegistryAwareIn
|
||||
|
||||
private $swaggerPropertyAnnotationReader;
|
||||
|
||||
private $phpdocPropertyAnnotationsReader;
|
||||
|
||||
public function __construct(
|
||||
MetadataFactoryInterface $factory,
|
||||
PropertyNamingStrategyInterface $namingStrategy,
|
||||
SwaggerPropertyAnnotationReader $swaggerPropertyAnnotationReader
|
||||
)
|
||||
{
|
||||
SwaggerPropertyAnnotationReader $swaggerPropertyAnnotationReader,
|
||||
PhpdocPropertyAnnotationReader $phpdocPropertyAnnotationReader
|
||||
) {
|
||||
$this->factory = $factory;
|
||||
$this->namingStrategy = $namingStrategy;
|
||||
$this->swaggerPropertyAnnotationReader = $swaggerPropertyAnnotationReader;
|
||||
$this->phpdocPropertyAnnotationsReader = $phpdocPropertyAnnotationReader;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,7 +75,7 @@ class JMSModelDescriber implements ModelDescriberInterface, ModelRegistryAwareIn
|
||||
}
|
||||
|
||||
$name = $this->namingStrategy->translateName($item);
|
||||
$property = $properties->get($name);
|
||||
$realProp = $property = $properties->get($name);
|
||||
|
||||
if ($type = $this->getNestedTypeInArray($item)) {
|
||||
$property->setType('array');
|
||||
@ -81,8 +84,10 @@ class JMSModelDescriber implements ModelDescriberInterface, ModelRegistryAwareIn
|
||||
$type = $item->type['name'];
|
||||
}
|
||||
|
||||
if (in_array($type, ['boolean', 'integer', 'string', 'array'])) {
|
||||
if (in_array($type, ['boolean', 'string', 'array'])) {
|
||||
$property->setType($type);
|
||||
} elseif (in_array($type, ['int', 'integer'])) {
|
||||
$property->setType('integer');
|
||||
} elseif (in_array($type, ['double', 'float'])) {
|
||||
$property->setType('number');
|
||||
$property->setFormat($type);
|
||||
@ -108,7 +113,10 @@ class JMSModelDescriber implements ModelDescriberInterface, ModelRegistryAwareIn
|
||||
}
|
||||
|
||||
// read property options from Swagger Property annotation if it exists
|
||||
$this->swaggerPropertyAnnotationReader->updateWithSwaggerPropertyAnnotation($item->reflection, $property);
|
||||
if (null !== $item->reflection) {
|
||||
$this->phpdocPropertyAnnotationsReader->updateWithPhpdoc($item->reflection, $realProp);
|
||||
$this->swaggerPropertyAnnotationReader->updateWithSwaggerPropertyAnnotation($item->reflection, $realProp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,8 +29,7 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
|
||||
public function __construct(
|
||||
PropertyInfoExtractorInterface $propertyInfo,
|
||||
SwaggerPropertyAnnotationReader $swaggerPropertyAnnotationReader
|
||||
)
|
||||
{
|
||||
) {
|
||||
$this->propertyInfo = $propertyInfo;
|
||||
$this->swaggerPropertyAnnotationReader = $swaggerPropertyAnnotationReader;
|
||||
}
|
||||
@ -61,7 +60,7 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
|
||||
}
|
||||
|
||||
$type = $types[0];
|
||||
$property = $properties->get($propertyName);
|
||||
$realProp = $property = $properties->get($propertyName);
|
||||
|
||||
if (Type::BUILTIN_TYPE_ARRAY === $type->getBuiltinType()) {
|
||||
$type = $type->getCollectionValueType();
|
||||
@ -69,16 +68,16 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
|
||||
$property = $property->getItems();
|
||||
}
|
||||
|
||||
if ($type->getBuiltinType() === Type::BUILTIN_TYPE_STRING) {
|
||||
if (Type::BUILTIN_TYPE_STRING === $type->getBuiltinType()) {
|
||||
$property->setType('string');
|
||||
} elseif ($type->getBuiltinType() === Type::BUILTIN_TYPE_BOOL) {
|
||||
} elseif (Type::BUILTIN_TYPE_BOOL === $type->getBuiltinType()) {
|
||||
$property->setType('boolean');
|
||||
} elseif ($type->getBuiltinType() === Type::BUILTIN_TYPE_INT) {
|
||||
} elseif (Type::BUILTIN_TYPE_INT === $type->getBuiltinType()) {
|
||||
$property->setType('integer');
|
||||
} elseif ($type->getBuiltinType() === Type::BUILTIN_TYPE_FLOAT) {
|
||||
} elseif (Type::BUILTIN_TYPE_FLOAT === $type->getBuiltinType()) {
|
||||
$property->setType('number');
|
||||
$property->setFormat('float');
|
||||
} elseif ($type->getBuiltinType() === Type::BUILTIN_TYPE_OBJECT) {
|
||||
} elseif (Type::BUILTIN_TYPE_OBJECT === $type->getBuiltinType()) {
|
||||
if (in_array($type->getClassName(), ['DateTime', 'DateTimeImmutable'])) {
|
||||
$property->setType('string');
|
||||
$property->setFormat('date-time');
|
||||
@ -88,14 +87,14 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new \Exception(sprintf("Unknown type: %s", $type->getBuiltinType()));
|
||||
throw new \Exception(sprintf('Unknown type: %s', $type->getBuiltinType()));
|
||||
}
|
||||
|
||||
// read property options from Swagger Property annotation if it exists
|
||||
if (property_exists($class, $propertyName)) {
|
||||
$this->swaggerPropertyAnnotationReader->updateWithSwaggerPropertyAnnotation(
|
||||
new \ReflectionProperty($class, $propertyName),
|
||||
$property
|
||||
$realProp
|
||||
);
|
||||
}
|
||||
}
|
||||
|
69
ModelDescriber/PhpdocPropertyAnnotationReader.php
Normal file
69
ModelDescriber/PhpdocPropertyAnnotationReader.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?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;
|
||||
|
||||
use EXSyst\Component\Swagger\Schema;
|
||||
use EXSyst\Component\Swagger\Items;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Var_;
|
||||
use phpDocumentor\Reflection\DocBlockFactory;
|
||||
use phpDocumentor\Reflection\DocBlockFactoryInterface;
|
||||
|
||||
/**
|
||||
* Extract information about properties of a model from the DocBlock comment.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class PhpdocPropertyAnnotationReader
|
||||
{
|
||||
private $docBlockFactory;
|
||||
|
||||
public function __construct(DocBlockFactoryInterface $docBlockFactory = null)
|
||||
{
|
||||
if (null === $docBlockFactory) {
|
||||
$docBlockFactory = DocBlockFactory::createInstance();
|
||||
}
|
||||
$this->docBlockFactory = $docBlockFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the Swagger information with information from the DocBlock comment.
|
||||
*
|
||||
* @param \ReflectionProperty $reflectionProperty
|
||||
* @param Items|Schema $property
|
||||
*/
|
||||
public function updateWithPhpdoc(\ReflectionProperty $reflectionProperty, $property)
|
||||
{
|
||||
try {
|
||||
$docBlock = $this->docBlockFactory->create($reflectionProperty);
|
||||
} catch (\Exception $e) {
|
||||
// ignore
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$title = $docBlock->getSummary()) {
|
||||
/** @var Var_ $var */
|
||||
foreach ($docBlock->getTagsByName('var') as $var) {
|
||||
if (!$description = $var->getDescription()) {
|
||||
continue;
|
||||
}
|
||||
$title = $description->render();
|
||||
if ($title) break;
|
||||
}
|
||||
}
|
||||
if ($property->getTitle() === null && $title) {
|
||||
$property->setTitle($title);
|
||||
}
|
||||
if ($property->getDescription() === null && $docBlock->getDescription() && $docBlock->getDescription()->render()) {
|
||||
$property->setDescription($docBlock->getDescription()->render());
|
||||
}
|
||||
}
|
||||
}
|
@ -11,10 +11,11 @@
|
||||
|
||||
namespace Nelmio\ApiDocBundle\ModelDescriber;
|
||||
|
||||
use EXSyst\Component\Swagger\Schema;
|
||||
use EXSyst\Component\Swagger\Items;
|
||||
use Swagger\Annotations\Property as SwgProperty;
|
||||
use Doctrine\Common\Annotations\Reader;
|
||||
use EXSyst\Component\Swagger\Items;
|
||||
use EXSyst\Component\Swagger\Schema;
|
||||
use Swagger\Annotations\Property as SwgProperty;
|
||||
use const Swagger\Annotations\UNDEFINED;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -36,20 +37,28 @@ class SwaggerPropertyAnnotationReader
|
||||
{
|
||||
$swgProperty = $this->annotationsReader->getPropertyAnnotation($reflectionProperty, SwgProperty::class);
|
||||
if ($swgProperty instanceof SwgProperty) {
|
||||
if ($swgProperty->description !== null) {
|
||||
$property->setDescription($swgProperty->description);
|
||||
}
|
||||
if ($swgProperty->type !== null) {
|
||||
if (null !== $swgProperty->type) {
|
||||
$property->setType($swgProperty->type);
|
||||
}
|
||||
if ($swgProperty->readOnly !== null) {
|
||||
$property->setReadOnly($swgProperty->readOnly);
|
||||
if (UNDEFINED !== $swgProperty->default) {
|
||||
$property->setDefault($swgProperty->default);
|
||||
}
|
||||
if ($swgProperty->title !== null) {
|
||||
$property->setTitle($swgProperty->title);
|
||||
if (null !== $swgProperty->enum) {
|
||||
$property->setEnum($swgProperty->enum);
|
||||
}
|
||||
if ($swgProperty->example !== null) {
|
||||
$property->setExample((string) $swgProperty->example);
|
||||
if ($property instanceof Schema) {
|
||||
if (null !== $swgProperty->description) {
|
||||
$property->setDescription($swgProperty->description);
|
||||
}
|
||||
if (null !== $swgProperty->title) {
|
||||
$property->setTitle($swgProperty->title);
|
||||
}
|
||||
if (null !== $swgProperty->example) {
|
||||
$property->setExample($swgProperty->example);
|
||||
}
|
||||
if (null !== $swgProperty->readOnly) {
|
||||
$property->setReadOnly($swgProperty->readOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ namespace Nelmio\ApiDocBundle;
|
||||
use Nelmio\ApiDocBundle\DependencyInjection\Compiler\AddDescribersPass;
|
||||
use Nelmio\ApiDocBundle\DependencyInjection\Compiler\AddModelDescribersPass;
|
||||
use Nelmio\ApiDocBundle\DependencyInjection\Compiler\AddRouteDescribersPass;
|
||||
use Nelmio\ApiDocBundle\DependencyInjection\Compiler\ConfigurationPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
@ -24,6 +25,7 @@ final class NelmioApiDocBundle extends Bundle
|
||||
*/
|
||||
public function build(ContainerBuilder $container)
|
||||
{
|
||||
$container->addCompilerPass(new ConfigurationPass());
|
||||
$container->addCompilerPass(new AddDescribersPass());
|
||||
$container->addCompilerPass(new AddModelDescribersPass());
|
||||
$container->addCompilerPass(new AddRouteDescribersPass());
|
||||
|
@ -16,7 +16,7 @@ for your APIs.
|
||||
|
||||
## Installation
|
||||
|
||||
First, open a command console, enter your project directory and execute the following command to download the latest version of this bundle (still in beta, for a stable version look [here](https://github.com/nelmio/NelmioApiDocBundle/tree/2.x)):
|
||||
First, open a command console, enter your project directory and execute the following command to download the latest version of this bundle:
|
||||
|
||||
```
|
||||
composer require nelmio/api-doc-bundle dev-master
|
||||
@ -151,7 +151,8 @@ serialization groups when using the Symfony serializer.
|
||||
### If you're using the JMS Serializer
|
||||
|
||||
The metadata of the JMS serializer are used by default to describe your
|
||||
models. Note that PHP doc blocks aren't supported in this case.
|
||||
models. Additional information is extracted from the PHP doc block comment,
|
||||
but the property types must be specified in the JMS annotations.
|
||||
|
||||
In case you prefer using the [Symfony PropertyInfo component](https://symfony.com/doc/current/components/property_info.html) (you
|
||||
won't be able to use JMS serialization groups), you can disable JMS serializer
|
||||
|
@ -54,6 +54,12 @@
|
||||
<argument type="service" id="annotation_reader" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
id="nelmio_api_doc.model_describers.phpdoc_property_annotation_reader"
|
||||
class="Nelmio\ApiDocBundle\ModelDescriber\PhpdocPropertyAnnotationReader"
|
||||
public="false"
|
||||
/>
|
||||
|
||||
<service id="nelmio_api_doc.model_describers.object" class="Nelmio\ApiDocBundle\ModelDescriber\ObjectModelDescriber" public="false">
|
||||
<argument type="service" id="property_info" />
|
||||
<argument type="service" id="nelmio_api_doc.model_describers.swagger_property_annotation_reader" />
|
||||
|
@ -43,7 +43,7 @@ trait RouteDescriberTrait
|
||||
|
||||
private function normalizePath(string $path): string
|
||||
{
|
||||
if (substr($path, -10) === '.{_format}') {
|
||||
if ('.{_format}' === substr($path, -10)) {
|
||||
$path = substr($path, 0, -10);
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller;
|
||||
use Nelmio\ApiDocBundle\Annotation\Model;
|
||||
use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSUser;
|
||||
use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex;
|
||||
use Nelmio\ApiDocBundle\Tests\Functional\Entity\VirtualProperty;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
use Swagger\Annotations as SWG;
|
||||
|
||||
@ -31,6 +32,18 @@ class JMSController
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/api/yaml", methods={"GET"})
|
||||
* @SWG\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @Model(type=VirtualProperty::class)
|
||||
* )
|
||||
*/
|
||||
public function yamlAction()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/api/jms_complex", methods={"GET"})
|
||||
* @SWG\Response(
|
||||
@ -41,6 +54,5 @@ class JMSController
|
||||
*/
|
||||
public function complexAction()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,20 @@ class JMSUser
|
||||
* @Serializer\Type("integer")
|
||||
* @Serializer\Expose
|
||||
* @Serializer\Groups({"list"})
|
||||
* @SWG\Property(description = "User id", required = true, readOnly = true, title = "userid", example=1)
|
||||
*
|
||||
* @SWG\Property(description = "User id", required = true, readOnly = true, title = "userid", example=1, default = null)
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @Serializer\Type("int")
|
||||
* @Serializer\Expose
|
||||
* @Serializer\SerializedName("daysOnline")
|
||||
*
|
||||
* @SWG\Property(default = 0)
|
||||
*/
|
||||
private $daysOnline;
|
||||
|
||||
/**
|
||||
* @Serializer\Type("string")
|
||||
* @Serializer\Expose
|
||||
@ -41,6 +51,8 @@ class JMSUser
|
||||
* @Serializer\Type("array<string>")
|
||||
* @Serializer\Accessor(getter="getRoles", setter="setRoles")
|
||||
* @Serializer\Expose
|
||||
*
|
||||
* @SWG\Property(default = {"user"}, description = "Roles list", example="[""ADMIN"",""SUPERUSER""]", title="roles")
|
||||
*/
|
||||
private $roles;
|
||||
|
||||
@ -77,6 +89,19 @@ class JMSUser
|
||||
*/
|
||||
private $bestFriend;
|
||||
|
||||
/**
|
||||
* Whether this user is enabled or disabled.
|
||||
*
|
||||
* Only enabled users may be used in actions.
|
||||
*
|
||||
* @var string
|
||||
* @Serializer\Type("string")
|
||||
* @Serializer\Expose
|
||||
*
|
||||
* @SWG\Property(enum = {"disabled", "enabled"})
|
||||
*/
|
||||
private $status;
|
||||
|
||||
public function setRoles($roles)
|
||||
{
|
||||
}
|
||||
|
@ -19,9 +19,9 @@ use Swagger\Annotations as SWG;
|
||||
class User
|
||||
{
|
||||
/**
|
||||
* @var integer
|
||||
* @var int
|
||||
*
|
||||
* @SWG\Property(description = "User id", required = true, readOnly = true, title = "userid", example=1)
|
||||
* @SWG\Property(description = "User id", required = true, readOnly = true, title = "userid", example=1, default = null)
|
||||
*/
|
||||
private $id;
|
||||
|
||||
@ -32,6 +32,19 @@ class User
|
||||
*/
|
||||
private $email;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*
|
||||
* @SWG\Property(
|
||||
* description = "User roles",
|
||||
* required = true,
|
||||
* title = "roles",
|
||||
* example="[""ADMIN"",""SUPERUSER""]",
|
||||
* default = {"user"},
|
||||
* )
|
||||
*/
|
||||
private $roles;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
@ -41,6 +54,7 @@ class User
|
||||
|
||||
/**
|
||||
* @var float
|
||||
* @SWG\Property(default = 0.0)
|
||||
*/
|
||||
private $money;
|
||||
|
||||
@ -54,6 +68,13 @@ class User
|
||||
*/
|
||||
private $users;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @SWG\Property(enum = {"disabled", "enabled"})
|
||||
*/
|
||||
private $status;
|
||||
|
||||
/**
|
||||
* @param float $money
|
||||
*/
|
||||
@ -78,6 +99,14 @@ class User
|
||||
$this->email = $email;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $roles
|
||||
*/
|
||||
public function setRoles(array $roles)
|
||||
{
|
||||
$this->roles = $roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $friendsNumber
|
||||
*/
|
||||
@ -97,4 +126,8 @@ class User
|
||||
public function setDummy(Dummy $dummy)
|
||||
{
|
||||
}
|
||||
|
||||
public function setStatus(string $status)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
45
Tests/Functional/Entity/VirtualProperty.php
Normal file
45
Tests/Functional/Entity/VirtualProperty.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?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\Tests\Functional\Entity;
|
||||
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* Class VirtualProperty.
|
||||
*
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
* @Serializer\VirtualProperty(
|
||||
* "email",
|
||||
* exp="object.user.email",
|
||||
* options={@Serializer\Type("string")}
|
||||
* )
|
||||
*/
|
||||
class VirtualProperty
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
* @Serializer\Type("integer")
|
||||
* @Serializer\Expose
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
private $user;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->user = new User();
|
||||
$this->user->setEmail('dummy@test.com');
|
||||
}
|
||||
}
|
@ -12,7 +12,9 @@
|
||||
namespace Nelmio\ApiDocBundle\Tests\Functional\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
@ -22,5 +24,7 @@ class DummyType extends AbstractType
|
||||
{
|
||||
$builder->add('bar', TextType::class, ['required' => false]);
|
||||
$builder->add('foo', ChoiceType::class, ['choices' => ['male', 'female']]);
|
||||
$builder->add('baz', CheckboxType::class, ['required' => false]);
|
||||
$builder->add('bey', IntegerType::class, ['required' => false]);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ class UserType extends AbstractType
|
||||
$builder
|
||||
->add('dummy', DummyType::class)
|
||||
->add('dummies', CollectionType::class, [
|
||||
'entry_type' => DummyType::class
|
||||
'entry_type' => DummyType::class,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -156,18 +156,27 @@ class FunctionalTest extends WebTestCase
|
||||
'money' => [
|
||||
'type' => 'number',
|
||||
'format' => 'float',
|
||||
'default' => 0.0,
|
||||
],
|
||||
'id' => [
|
||||
'type' => 'integer',
|
||||
'description' => "User id",
|
||||
'description' => 'User id',
|
||||
'readOnly' => true,
|
||||
'title' => "userid",
|
||||
'title' => 'userid',
|
||||
'example' => 1,
|
||||
],
|
||||
'email' => [
|
||||
'type' => 'string',
|
||||
'readOnly' => false,
|
||||
],
|
||||
'roles' => [
|
||||
'title' => 'roles',
|
||||
'type' => 'array',
|
||||
'description' => 'User roles',
|
||||
'example' => '["ADMIN","SUPERUSER"]',
|
||||
'items' => ['type' => 'string'],
|
||||
'default' => ['user'],
|
||||
],
|
||||
'friendsNumber' => [
|
||||
'type' => 'string',
|
||||
],
|
||||
@ -184,6 +193,10 @@ class FunctionalTest extends WebTestCase
|
||||
'dummy' => [
|
||||
'$ref' => '#/definitions/Dummy2',
|
||||
],
|
||||
'status' => [
|
||||
'type' => 'string',
|
||||
'enum' => ['disabled', 'enabled'],
|
||||
],
|
||||
],
|
||||
],
|
||||
$this->getModel('User')->toArray()
|
||||
@ -199,8 +212,8 @@ class FunctionalTest extends WebTestCase
|
||||
'dummies' => [
|
||||
'items' => ['$ref' => '#/definitions/DummyType'],
|
||||
'type' => 'array',
|
||||
'example' => sprintf('[{%s}]', DummyType::class)
|
||||
]
|
||||
'example' => sprintf('[{%s}]', DummyType::class),
|
||||
],
|
||||
],
|
||||
'required' => ['dummy', 'dummies'],
|
||||
], $this->getModel('UserType')->toArray());
|
||||
@ -215,6 +228,12 @@ class FunctionalTest extends WebTestCase
|
||||
'type' => 'string',
|
||||
'enum' => ['male', 'female'],
|
||||
],
|
||||
'baz' => [
|
||||
'type' => 'boolean',
|
||||
],
|
||||
'bey' => [
|
||||
'type' => 'integer',
|
||||
],
|
||||
],
|
||||
'required' => ['foo'],
|
||||
], $this->getModel('DummyType')->toArray());
|
||||
|
@ -20,18 +20,26 @@ class JMSFunctionalTest extends WebTestCase
|
||||
'properties' => [
|
||||
'id' => [
|
||||
'type' => 'integer',
|
||||
'description' => "User id",
|
||||
'description' => 'User id',
|
||||
'readOnly' => true,
|
||||
'title' => "userid",
|
||||
'title' => 'userid',
|
||||
'example' => 1,
|
||||
],
|
||||
'daysOnline' => [
|
||||
'type' => 'integer',
|
||||
'default' => 0,
|
||||
],
|
||||
'email' => [
|
||||
'type' => 'string',
|
||||
'readOnly' => false,
|
||||
],
|
||||
'roles' => [
|
||||
'type' => 'array',
|
||||
'title' => 'roles',
|
||||
'example' => '["ADMIN","SUPERUSER"]',
|
||||
'items' => ['type' => 'string'],
|
||||
'default' => ['user'],
|
||||
'description' => 'Roles list',
|
||||
],
|
||||
'friendsNumber' => [
|
||||
'type' => 'string',
|
||||
@ -45,6 +53,12 @@ class JMSFunctionalTest extends WebTestCase
|
||||
'best_friend' => [
|
||||
'$ref' => '#/definitions/User',
|
||||
],
|
||||
'status' => [
|
||||
'type' => 'string',
|
||||
'title' => 'Whether this user is enabled or disabled.',
|
||||
'description' => 'Only enabled users may be used in actions.',
|
||||
'enum' => ['disabled', 'enabled'],
|
||||
],
|
||||
],
|
||||
], $this->getModel('JMSUser')->toArray());
|
||||
}
|
||||
@ -54,7 +68,7 @@ class JMSFunctionalTest extends WebTestCase
|
||||
$this->assertEquals([
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'id' => ['type' => 'integer'],
|
||||
'id' => ['type' => 'integer'],
|
||||
'user' => ['$ref' => '#/definitions/JMSUser2'],
|
||||
'name' => ['type' => 'string']
|
||||
],
|
||||
@ -72,7 +86,21 @@ class JMSFunctionalTest extends WebTestCase
|
||||
],
|
||||
],
|
||||
], $this->getModel('JMSUser2')->toArray());
|
||||
}
|
||||
|
||||
public function testYamlConfig()
|
||||
{
|
||||
$this->assertEquals([
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'id' => [
|
||||
'type' => 'integer',
|
||||
],
|
||||
'email' => [
|
||||
'type' => 'string',
|
||||
],
|
||||
],
|
||||
], $this->getModel('VirtualProperty')->toArray());
|
||||
}
|
||||
|
||||
protected static function createKernel(array $options = array())
|
||||
|
@ -81,7 +81,7 @@ class SwaggerDocblockConvertCommand extends ContainerAwareCommand
|
||||
* summary="'.$this->escapeQuotes($apiDoc->getDescription()).'"';
|
||||
|
||||
foreach ($apiDoc->getFilters() as $name => $parameter) {
|
||||
$description = array_key_exists('description', $parameter)
|
||||
$description = array_key_exists('description', $parameter) && null !== $parameter['description']
|
||||
? $this->escapeQuotes($parameter['description'])
|
||||
: 'todo';
|
||||
|
||||
@ -265,7 +265,7 @@ to ``~3.0@beta``:
|
||||
```json
|
||||
{
|
||||
"require": {
|
||||
"nelmio/api-doc-bundle": "~3.0@beta"
|
||||
"nelmio/api-doc-bundle": "^3.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -22,9 +22,6 @@
|
||||
"zircote/swagger-php": "^2.0.9"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/yaml": "Temporary: see https://github.com/symfony/symfony/pull/24634/files#r153192689",
|
||||
"symfony/yaml": "^2.8|^3.0|^4.0",
|
||||
|
||||
"symfony/templating": "^2.8|^3.0|^4.0",
|
||||
"symfony/twig-bundle": "^3.0|^4.0",
|
||||
"symfony/asset": "^2.8|^3.0|^4.0",
|
||||
@ -39,6 +36,7 @@
|
||||
"symfony/phpunit-bridge": "^3.3",
|
||||
"symfony/stopwatch": "^2.8|^3.0|^4.0",
|
||||
"sensio/framework-extra-bundle": "^3.0",
|
||||
"symfony/stopwatch": "^2.8|^3.0|^4.0",
|
||||
"doctrine/annotations": "^1.2",
|
||||
|
||||
"phpdocumentor/reflection-docblock": "^3.1",
|
||||
|
Loading…
x
Reference in New Issue
Block a user