Skip to content

Commit 98ba69e

Browse files
committed
[Swagger] Added support for customizing the Definition key
1 parent 337ffdf commit 98ba69e

File tree

4 files changed

+108
-2
lines changed

4 files changed

+108
-2
lines changed

src/Serializer/SerializerContextBuilder.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use ApiPlatform\Core\Api\OperationType;
1717
use ApiPlatform\Core\Exception\RuntimeException;
1818
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
19+
use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer;
1920
use ApiPlatform\Core\Util\RequestAttributesExtractor;
2021
use Symfony\Component\HttpFoundation\Request;
2122

@@ -92,6 +93,8 @@ public function createFromRequest(Request $request, bool $normalization, array $
9293
$context['subresource_resource_class'] = $attributes['subresource_resource_class'] ?? null;
9394
}
9495

96+
unset($context[DocumentationNormalizer::SWAGGER_DEFINITION_NAME]);
97+
9598
return $context;
9699
}
97100
}

src/Swagger/Serializer/DocumentationNormalizer.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ final class DocumentationNormalizer implements NormalizerInterface
4646

4747
const SWAGGER_VERSION = '2.0';
4848
const FORMAT = 'json';
49+
const SWAGGER_DEFINITION_NAME = 'swagger_definition_name';
4950

5051
private $resourceMetadataFactory;
5152
private $propertyNameCollectionFactory;
@@ -445,7 +446,11 @@ private function updateDeleteOperation(\ArrayObject $pathOperation, string $reso
445446
*/
446447
private function getDefinition(\ArrayObject $definitions, ResourceMetadata $resourceMetadata, string $resourceClass, array $serializerContext = null): string
447448
{
448-
$definitionKey = $this->getDefinitionKey($resourceMetadata->getShortName(), (array) ($serializerContext[AbstractNormalizer::GROUPS] ?? []));
449+
if (isset($serializerContext[self::SWAGGER_DEFINITION_NAME])) {
450+
$definitionKey = sprintf('%s-%s', $resourceMetadata->getShortName(), $serializerContext[self::SWAGGER_DEFINITION_NAME]);
451+
} else {
452+
$definitionKey = $this->getDefinitionKey($resourceMetadata->getShortName(), (array) ($serializerContext[AbstractNormalizer::GROUPS] ?? []));
453+
}
449454

450455
if (!isset($definitions[$definitionKey])) {
451456
$definitions[$definitionKey] = []; // Initialize first to prevent infinite loop

tests/Serializer/SerializerContextBuilderTest.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
1717
use ApiPlatform\Core\Metadata\Resource\ResourceMetadata;
1818
use ApiPlatform\Core\Serializer\SerializerContextBuilder;
19+
use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer;
1920
use PHPUnit\Framework\TestCase;
2021
use Symfony\Component\HttpFoundation\Request;
2122

@@ -37,7 +38,10 @@ protected function setUp()
3738
null,
3839
[],
3940
[],
40-
['normalization_context' => ['foo' => 'bar'], 'denormalization_context' => ['bar' => 'baz']]
41+
[
42+
'normalization_context' => ['foo' => 'bar', DocumentationNormalizer::SWAGGER_DEFINITION_NAME => 'MyDefinition'],
43+
'denormalization_context' => ['bar' => 'baz'],
44+
]
4145
);
4246

4347
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);

tests/Swagger/Serializer/DocumentationNormalizerTest.php

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,100 @@ public function testNormalizeWithOnlyNormalizationGroups()
732732
$this->assertEquals($expected, $normalizer->normalize($documentation));
733733
}
734734

735+
public function testNormalizeWithSwaggerDefinitionName()
736+
{
737+
$documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3', ['jsonld' => ['application/ld+json']]);
738+
739+
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
740+
$propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['id']));
741+
742+
$dummyMetadata = new ResourceMetadata(
743+
'Dummy',
744+
'This is a dummy.',
745+
'http://schema.example.com/Dummy',
746+
[
747+
'get' => [
748+
'method' => 'GET',
749+
'normalization_context' => [
750+
DocumentationNormalizer::SWAGGER_DEFINITION_NAME => 'Read',
751+
],
752+
],
753+
]
754+
);
755+
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
756+
$resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata);
757+
758+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
759+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'id')->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false));
760+
$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
761+
$resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true);
762+
763+
$operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class);
764+
$operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'get')->shouldBeCalled()->willReturn('GET');
765+
766+
$operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()));
767+
768+
$normalizer = new DocumentationNormalizer(
769+
$resourceMetadataFactoryProphecy->reveal(),
770+
$propertyNameCollectionFactoryProphecy->reveal(),
771+
$propertyMetadataFactoryProphecy->reveal(),
772+
$resourceClassResolverProphecy->reveal(),
773+
$operationMethodResolverProphecy->reveal(),
774+
$operationPathResolver
775+
);
776+
777+
$expected = [
778+
'swagger' => '2.0',
779+
'basePath' => '/app_dev.php/',
780+
'info' => [
781+
'title' => 'Test API',
782+
'description' => 'This is a test API.',
783+
'version' => '1.2.3',
784+
],
785+
'paths' => new \ArrayObject([
786+
'/dummies/{id}' => [
787+
'get' => new \ArrayObject([
788+
'tags' => ['Dummy'],
789+
'operationId' => 'getDummyItem',
790+
'produces' => ['application/ld+json'],
791+
'summary' => 'Retrieves a Dummy resource.',
792+
'parameters' => [
793+
[
794+
'name' => 'id',
795+
'in' => 'path',
796+
'type' => 'string',
797+
'required' => true,
798+
],
799+
],
800+
'responses' => [
801+
200 => [
802+
'description' => 'Dummy resource response',
803+
'schema' => ['$ref' => '#/definitions/Dummy-Read'],
804+
],
805+
404 => ['description' => 'Resource not found'],
806+
],
807+
]),
808+
],
809+
]),
810+
'definitions' => new \ArrayObject([
811+
'Dummy-Read' => new \ArrayObject([
812+
'type' => 'object',
813+
'description' => 'This is a dummy.',
814+
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
815+
'properties' => [
816+
'id' => new \ArrayObject([
817+
'type' => 'integer',
818+
'description' => 'This is an id.',
819+
'readOnly' => true,
820+
]),
821+
],
822+
]),
823+
]),
824+
];
825+
826+
$this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/']));
827+
}
828+
735829
public function testNormalizeWithOnlyDenormalizationGroups()
736830
{
737831
$title = 'Test API';

0 commit comments

Comments
 (0)