Allow model describers on jms custom types (#1495)

* allow model describers on jms custom types

* add fallback describer

* test custom type def

* remove object_fallback describer from the container when jms is not active
This commit is contained in:
Asmir Mustafic 2019-04-16 12:13:33 +02:00 committed by Guilhem N
parent 258dd2f69f
commit d6ea99420e
9 changed files with 109 additions and 6 deletions

View File

@ -173,6 +173,8 @@ final class NelmioApiDocExtension extends Extension implements PrependExtensionI
new Reference('nelmio_api_doc.model_describers.jms.inner'), new Reference('nelmio_api_doc.model_describers.jms.inner'),
]); ]);
} }
} else {
$container->removeDefinition('nelmio_api_doc.model_describers.object_fallback');
} }
// Import the base configuration // Import the base configuration

View File

@ -0,0 +1,28 @@
<?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 Nelmio\ApiDocBundle\Model\Model;
use Symfony\Component\PropertyInfo\Type;
class FallbackObjectModelDescriber implements ModelDescriberInterface
{
public function describe(Model $model, Schema $schema)
{
}
public function supports(Model $model): bool
{
return Type::BUILTIN_TYPE_OBJECT === $model->getType()->getBuiltinType();
}
}

View File

@ -177,11 +177,6 @@ class JMSModelDescriber implements ModelDescriberInterface, ModelRegistryAwareIn
$property->setType('string'); $property->setType('string');
$property->setFormat('date-time'); $property->setFormat('date-time');
} else { } else {
// we can use property type also for custom handlers, then we don't have here real class name
if (!class_exists($type['name'])) {
return null;
}
$model = new Model(new Type(Type::BUILTIN_TYPE_OBJECT, false, $type['name']), $groups); $model = new Model(new Type(Type::BUILTIN_TYPE_OBJECT, false, $type['name']), $groups);
$property->setRef($this->modelRegistry->register($model)); $property->setRef($this->modelRegistry->register($model));

View File

@ -124,6 +124,6 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
public function supports(Model $model): bool public function supports(Model $model): bool
{ {
return Type::BUILTIN_TYPE_OBJECT === $model->getType()->getBuiltinType(); return Type::BUILTIN_TYPE_OBJECT === $model->getType()->getBuiltinType() && class_exists($model->getType()->getClassName());
} }
} }

View File

@ -46,6 +46,10 @@
<tag name="nelmio_api_doc.model_describer" /> <tag name="nelmio_api_doc.model_describer" />
</service> </service>
<service id="nelmio_api_doc.model_describers.object_fallback" class="Nelmio\ApiDocBundle\ModelDescriber\FallbackObjectModelDescriber" public="false">
<tag name="nelmio_api_doc.model_describer" priority="-1000" />
</service>
<!-- Form Type Extensions --> <!-- Form Type Extensions -->
<service id="nelmio_api_doc.form.documentation_extension" class="Nelmio\ApiDocBundle\Form\Extension\DocumentationExtension"> <service id="nelmio_api_doc.form.documentation_extension" class="Nelmio\ApiDocBundle\Form\Extension\DocumentationExtension">

View File

@ -126,6 +126,24 @@ class JMSUser
*/ */
private $status; private $status;
/**
* JMS custom types handled via Custom Type Handlers.
*
* @var string
* @Serializer\Type("VirtualTypeClassDoesNotExistsHandlerDefined")
* @Serializer\Expose
*/
private $virtualType1;
/**
* JMS custom types handled via Custom Type Handlers.
*
* @var string
* @Serializer\Type("VirtualTypeClassDoesNotExistsHandlerNotDefined")
* @Serializer\Expose
*/
private $virtualType2;
/** /**
* @Serializer\Type("array<array<float>>") * @Serializer\Type("array<array<float>>")
* @Serializer\Expose * @Serializer\Expose

View File

@ -121,6 +121,12 @@ class JMSFunctionalTest extends WebTestCase
'description' => 'Only enabled users may be used in actions.', 'description' => 'Only enabled users may be used in actions.',
'enum' => ['disabled', 'enabled'], 'enum' => ['disabled', 'enabled'],
], ],
'virtual_type1' => [
'$ref' => '#/definitions/VirtualTypeClassDoesNotExistsHandlerDefined',
],
'virtual_type2' => [
'$ref' => '#/definitions/VirtualTypeClassDoesNotExistsHandlerNotDefined',
],
'last_update' => [ 'last_update' => [
'type' => 'date', 'type' => 'date',
], ],
@ -174,6 +180,18 @@ class JMSFunctionalTest extends WebTestCase
], ],
], ],
], $this->getModel('JMSUser')->toArray()); ], $this->getModel('JMSUser')->toArray());
$this->assertEquals([
], $this->getModel('VirtualTypeClassDoesNotExistsHandlerNotDefined')->toArray());
$this->assertEquals([
'type' => 'object',
'properties' => [
'custom_prop' => [
'type' => 'string',
],
],
], $this->getModel('VirtualTypeClassDoesNotExistsHandlerDefined')->toArray());
} }
public function testModelComplexDualDocumentation() public function testModelComplexDualDocumentation()

View File

@ -0,0 +1,32 @@
<?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\ModelDescriber;
use EXSyst\Component\Swagger\Schema;
use Nelmio\ApiDocBundle\Model\Model;
use Nelmio\ApiDocBundle\ModelDescriber\ModelDescriberInterface;
use Symfony\Component\PropertyInfo\Type;
class VirtualTypeClassDoesNotExistsHandlerDefinedDescriber implements ModelDescriberInterface
{
public function describe(Model $model, Schema $schema)
{
$schema->setType('object');
$schema->getProperties()->get('custom_prop')->setType('string');
}
public function supports(Model $model): bool
{
return Type::BUILTIN_TYPE_OBJECT === $model->getType()->getBuiltinType()
&& 'VirtualTypeClassDoesNotExistsHandlerDefined' === $model->getType()->getClassName();
}
}

View File

@ -16,12 +16,14 @@ use Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle;
use FOS\RestBundle\FOSRestBundle; use FOS\RestBundle\FOSRestBundle;
use JMS\SerializerBundle\JMSSerializerBundle; use JMS\SerializerBundle\JMSSerializerBundle;
use Nelmio\ApiDocBundle\NelmioApiDocBundle; use Nelmio\ApiDocBundle\NelmioApiDocBundle;
use Nelmio\ApiDocBundle\Tests\Functional\ModelDescriber\VirtualTypeClassDoesNotExistsHandlerDefinedDescriber;
use Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle; use Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Bundle\TwigBundle\TwigBundle; use Symfony\Bundle\TwigBundle\TwigBundle;
use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\RouteCollectionBuilder; use Symfony\Component\Routing\RouteCollectionBuilder;
@ -163,6 +165,10 @@ class TestKernel extends Kernel
], ],
], ],
]); ]);
$def = new Definition(VirtualTypeClassDoesNotExistsHandlerDefinedDescriber::class);
$def->addTag('nelmio_api_doc.model_describer');
$c->setDefinition('nelmio.test.jms.virtual_type.describer', $def);
} }
/** /**