diff --git a/.travis.yml b/.travis.yml
index 2e3204a..3ee1346 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -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
diff --git a/DependencyInjection/Compiler/ConfigurationPass.php b/DependencyInjection/Compiler/ConfigurationPass.php
new file mode 100644
index 0000000..df128be
--- /dev/null
+++ b/DependencyInjection/Compiler/ConfigurationPass.php
@@ -0,0 +1,35 @@
+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]);
+ }
+ }
+}
diff --git a/DependencyInjection/NelmioApiDocExtension.php b/DependencyInjection/NelmioApiDocExtension.php
index 6f05139..cfc2796 100644
--- a/DependencyInjection/NelmioApiDocExtension.php
+++ b/DependencyInjection/NelmioApiDocExtension.php
@@ -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]);
}
diff --git a/Describer/SwaggerPhpDescriber.php b/Describer/SwaggerPhpDescriber.php
index 62552b4..0bac7ca 100644
--- a/Describer/SwaggerPhpDescriber.php
+++ b/Describer/SwaggerPhpDescriber.php
@@ -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);
}
diff --git a/ModelDescriber/FormModelDescriber.php b/ModelDescriber/FormModelDescriber.php
index 4694352..9444a14 100644
--- a/ModelDescriber/FormModelDescriber.php
+++ b/ModelDescriber/FormModelDescriber.php
@@ -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');
diff --git a/ModelDescriber/JMSModelDescriber.php b/ModelDescriber/JMSModelDescriber.php
index 8c90739..43aebdc 100644
--- a/ModelDescriber/JMSModelDescriber.php
+++ b/ModelDescriber/JMSModelDescriber.php
@@ -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);
+ }
}
}
diff --git a/ModelDescriber/ObjectModelDescriber.php b/ModelDescriber/ObjectModelDescriber.php
index cbd834c..bb6fad4 100644
--- a/ModelDescriber/ObjectModelDescriber.php
+++ b/ModelDescriber/ObjectModelDescriber.php
@@ -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
);
}
}
diff --git a/ModelDescriber/PhpdocPropertyAnnotationReader.php b/ModelDescriber/PhpdocPropertyAnnotationReader.php
new file mode 100644
index 0000000..2f30700
--- /dev/null
+++ b/ModelDescriber/PhpdocPropertyAnnotationReader.php
@@ -0,0 +1,69 @@
+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());
+ }
+ }
+}
diff --git a/ModelDescriber/SwaggerPropertyAnnotationReader.php b/ModelDescriber/SwaggerPropertyAnnotationReader.php
index e272b98..f2c05bc 100644
--- a/ModelDescriber/SwaggerPropertyAnnotationReader.php
+++ b/ModelDescriber/SwaggerPropertyAnnotationReader.php
@@ -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);
+ }
}
}
}
diff --git a/NelmioApiDocBundle.php b/NelmioApiDocBundle.php
index e356c05..df48166 100644
--- a/NelmioApiDocBundle.php
+++ b/NelmioApiDocBundle.php
@@ -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());
diff --git a/README.md b/README.md
index 770375a..3066e29 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/Resources/config/services.xml b/Resources/config/services.xml
index 00443e4..401b78d 100644
--- a/Resources/config/services.xml
+++ b/Resources/config/services.xml
@@ -54,6 +54,12 @@
+
+
diff --git a/RouteDescriber/RouteDescriberTrait.php b/RouteDescriber/RouteDescriberTrait.php
index 0de075b..a5e827c 100644
--- a/RouteDescriber/RouteDescriberTrait.php
+++ b/RouteDescriber/RouteDescriberTrait.php
@@ -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);
}
diff --git a/Tests/Functional/Controller/JMSController.php b/Tests/Functional/Controller/JMSController.php
index f338180..94bf5d8 100644
--- a/Tests/Functional/Controller/JMSController.php
+++ b/Tests/Functional/Controller/JMSController.php
@@ -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()
{
-
}
}
diff --git a/Tests/Functional/Entity/JMSUser.php b/Tests/Functional/Entity/JMSUser.php
index 7e91805..db0e760 100644
--- a/Tests/Functional/Entity/JMSUser.php
+++ b/Tests/Functional/Entity/JMSUser.php
@@ -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")
* @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)
{
}
diff --git a/Tests/Functional/Entity/User.php b/Tests/Functional/Entity/User.php
index abd5ae1..68cc737 100644
--- a/Tests/Functional/Entity/User.php
+++ b/Tests/Functional/Entity/User.php
@@ -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)
+ {
+ }
}
diff --git a/Tests/Functional/Entity/VirtualProperty.php b/Tests/Functional/Entity/VirtualProperty.php
new file mode 100644
index 0000000..3db68a1
--- /dev/null
+++ b/Tests/Functional/Entity/VirtualProperty.php
@@ -0,0 +1,45 @@
+user = new User();
+ $this->user->setEmail('dummy@test.com');
+ }
+}
diff --git a/Tests/Functional/Form/DummyType.php b/Tests/Functional/Form/DummyType.php
index a590dba..d8e2ccc 100644
--- a/Tests/Functional/Form/DummyType.php
+++ b/Tests/Functional/Form/DummyType.php
@@ -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]);
}
}
diff --git a/Tests/Functional/Form/UserType.php b/Tests/Functional/Form/UserType.php
index 8e7eb79..4b52fd6 100644
--- a/Tests/Functional/Form/UserType.php
+++ b/Tests/Functional/Form/UserType.php
@@ -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,
]);
}
diff --git a/Tests/Functional/FunctionalTest.php b/Tests/Functional/FunctionalTest.php
index 0bb4a71..9baaa53 100644
--- a/Tests/Functional/FunctionalTest.php
+++ b/Tests/Functional/FunctionalTest.php
@@ -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());
diff --git a/Tests/Functional/JMSFunctionalTest.php b/Tests/Functional/JMSFunctionalTest.php
index e02c7d6..3892e3f 100644
--- a/Tests/Functional/JMSFunctionalTest.php
+++ b/Tests/Functional/JMSFunctionalTest.php
@@ -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())
diff --git a/UPGRADE-3.0.md b/UPGRADE-3.0.md
index 2c2f87f..f7d8ae3 100644
--- a/UPGRADE-3.0.md
+++ b/UPGRADE-3.0.md
@@ -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"
}
}
```
diff --git a/composer.json b/composer.json
index 3dd5989..de9cc69 100644
--- a/composer.json
+++ b/composer.json
@@ -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",