mirror of
https://github.com/retailcrm/NelmioApiDocBundle.git
synced 2025-02-09 02:59:27 +03:00
Read discriminator mapping from file configuration (#2034)
* Read discriminator mapping from file configuration * Use more realistic test data
This commit is contained in:
parent
18425863b7
commit
f808eafbe4
@ -144,7 +144,7 @@ final class NelmioApiDocExtension extends Extension implements PrependExtensionI
|
||||
));
|
||||
|
||||
$container->getDefinition('nelmio_api_doc.model_describers.object')
|
||||
->setArgument(3, $config['media_types']);
|
||||
->setArgument(4, $config['media_types']);
|
||||
|
||||
// Add autoconfiguration for model describer
|
||||
$container->registerForAutoconfiguration(ModelDescriberInterface::class)
|
||||
|
@ -23,7 +23,7 @@ use OpenApi\Annotations as OA;
|
||||
use OpenApi\Generator;
|
||||
use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
|
||||
use Symfony\Component\PropertyInfo\Type;
|
||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
|
||||
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
|
||||
|
||||
class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwareInterface
|
||||
@ -33,6 +33,8 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
|
||||
|
||||
/** @var PropertyInfoExtractorInterface */
|
||||
private $propertyInfo;
|
||||
/** @var ClassMetadataFactoryInterface */
|
||||
private $classMetadataFactory;
|
||||
/** @var Reader */
|
||||
private $doctrineReader;
|
||||
/** @var PropertyDescriberInterface[] */
|
||||
@ -46,6 +48,7 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
|
||||
|
||||
public function __construct(
|
||||
PropertyInfoExtractorInterface $propertyInfo,
|
||||
ClassMetadataFactoryInterface $classMetadataFactory,
|
||||
Reader $reader,
|
||||
iterable $propertyDescribers,
|
||||
array $mediaTypes,
|
||||
@ -53,6 +56,7 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
|
||||
bool $useValidationGroups = false
|
||||
) {
|
||||
$this->propertyInfo = $propertyInfo;
|
||||
$this->classMetadataFactory = $classMetadataFactory;
|
||||
$this->doctrineReader = $reader;
|
||||
$this->propertyDescribers = $propertyDescribers;
|
||||
$this->mediaTypes = $mediaTypes;
|
||||
@ -85,14 +89,17 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
|
||||
|
||||
$schema->type = 'object';
|
||||
|
||||
$discriminatorMap = $this->getAnnotation($reflClass, DiscriminatorMap::class);
|
||||
if ($discriminatorMap && Generator::UNDEFINED === $schema->discriminator) {
|
||||
$mapping = $this->classMetadataFactory
|
||||
->getMetadataFor($class)
|
||||
->getClassDiscriminatorMapping();
|
||||
|
||||
if ($mapping && Generator::UNDEFINED === $schema->discriminator) {
|
||||
$this->applyOpenApiDiscriminator(
|
||||
$model,
|
||||
$schema,
|
||||
$this->modelRegistry,
|
||||
$discriminatorMap->getTypeProperty(),
|
||||
$discriminatorMap->getMapping()
|
||||
$mapping->getTypeProperty(),
|
||||
$mapping->getTypesMapping()
|
||||
);
|
||||
}
|
||||
|
||||
@ -196,23 +203,6 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
|
||||
throw new \Exception(sprintf('Type "%s" is not supported in %s::$%s. You may use the `@OA\Property(type="")` annotation to specify it manually.', $types[0]->getBuiltinType(), $model->getType()->getClassName(), $propertyName));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
private function getAnnotation(\ReflectionClass $reflection, string $className)
|
||||
{
|
||||
if (false === class_exists($className)) {
|
||||
return null;
|
||||
}
|
||||
if (\PHP_VERSION_ID >= 80000) {
|
||||
if (null !== $attribute = $reflection->getAttributes($className, \ReflectionAttribute::IS_INSTANCEOF)[0] ?? null) {
|
||||
return $attribute->newInstance();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->doctrineReader->getClassAnnotation($reflection, $className);
|
||||
}
|
||||
|
||||
public function supports(Model $model): bool
|
||||
{
|
||||
return Type::BUILTIN_TYPE_OBJECT === $model->getType()->getBuiltinType()
|
||||
|
@ -71,6 +71,7 @@
|
||||
<!-- Model Describers -->
|
||||
<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="serializer.mapping.class_metadata_factory" />
|
||||
<argument type="service" id="annotations.reader" />
|
||||
<argument type="tagged" tag="nelmio_api_doc.object_model.property_describer" />
|
||||
<argument />
|
||||
|
@ -24,6 +24,7 @@ use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithRef;
|
||||
use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraints;
|
||||
use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraintsWithValidationGroups;
|
||||
use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminator;
|
||||
use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminatorFileMapping;
|
||||
use Nelmio\ApiDocBundle\Tests\Functional\Entity\User;
|
||||
use Nelmio\ApiDocBundle\Tests\Functional\Form\DummyType;
|
||||
use Nelmio\ApiDocBundle\Tests\Functional\Form\FormWithAlternateSchemaType;
|
||||
@ -277,6 +278,15 @@ class ApiController80
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/discriminator-mapping-configured-with-file", methods={"GET", "POST"})
|
||||
*
|
||||
* @OA\Response(response=200, description="Worked well!", @Model(type=SymfonyDiscriminatorFileMapping::class))
|
||||
*/
|
||||
public function discriminatorMappingConfiguredWithFileAction()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/named_route-operation-id", name="named_route_operation_id", methods={"GET", "POST"})
|
||||
*
|
||||
|
16
Tests/Functional/Entity/SymfonyDiscriminatorFileMapping.php
Normal file
16
Tests/Functional/Entity/SymfonyDiscriminatorFileMapping.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?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;
|
||||
|
||||
interface SymfonyDiscriminatorFileMapping
|
||||
{
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
|
||||
namespace Nelmio\ApiDocBundle\Tests\Functional\Entity;
|
||||
|
||||
class SymfonyDiscriminatorOne extends SymfonyDiscriminator
|
||||
class SymfonyDiscriminatorOne extends SymfonyDiscriminator implements SymfonyDiscriminatorFileMapping
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
namespace Nelmio\ApiDocBundle\Tests\Functional\Entity;
|
||||
|
||||
class SymfonyDiscriminatorTwo extends SymfonyDiscriminator
|
||||
class SymfonyDiscriminatorTwo extends SymfonyDiscriminator implements SymfonyDiscriminatorFileMapping
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
|
@ -622,6 +622,19 @@ class FunctionalTest extends WebTestCase
|
||||
$this->assertCount(2, $model->oneOf);
|
||||
}
|
||||
|
||||
public function testModelsWithDiscriminatorMapAreLoadedWithOpenApiPolymorphismWhenUsingFileConfiguration()
|
||||
{
|
||||
$model = $this->getModel('SymfonyDiscriminatorFileMapping');
|
||||
|
||||
$this->assertInstanceOf(OA\Discriminator::class, $model->discriminator);
|
||||
$this->assertSame('type', $model->discriminator->propertyName);
|
||||
$this->assertCount(2, $model->discriminator->mapping);
|
||||
$this->assertArrayHasKey('one', $model->discriminator->mapping);
|
||||
$this->assertArrayHasKey('two', $model->discriminator->mapping);
|
||||
$this->assertNotSame(Generator::UNDEFINED, $model->oneOf);
|
||||
$this->assertCount(2, $model->oneOf);
|
||||
}
|
||||
|
||||
public function testDiscriminatorMapLoadsChildrenModels()
|
||||
{
|
||||
// get model does its own assertions
|
||||
|
6
Tests/Functional/Resources/serializer/discriminator.yaml
Normal file
6
Tests/Functional/Resources/serializer/discriminator.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminatorFileMapping:
|
||||
discriminator_map:
|
||||
type_property: type
|
||||
mapping:
|
||||
one: Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminatorOne
|
||||
two: Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminatorTwo
|
@ -131,7 +131,12 @@ class TestKernel extends Kernel
|
||||
'test' => null,
|
||||
'validation' => null,
|
||||
'form' => null,
|
||||
'serializer' => ['enable_annotations' => true],
|
||||
'serializer' => [
|
||||
'enable_annotations' => true,
|
||||
'mapping' => [
|
||||
'paths' => [__DIR__.'/Resources/serializer/'],
|
||||
],
|
||||
],
|
||||
'property_access' => true,
|
||||
];
|
||||
// Support symfony/framework-bundle < 5.4
|
||||
|
Loading…
x
Reference in New Issue
Block a user