Skip to content

Commit a4ee6c8

Browse files
committed
Use serializedName in Swagger UI Links section
1 parent 4af03d0 commit a4ee6c8

File tree

6 files changed

+186
-2
lines changed

6 files changed

+186
-2
lines changed

src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ public function create(string $resourceClass, string $property, array $options =
6161
return $propertyMetadata;
6262
}
6363

64+
$serializerMetadataAttributes = $this->serializerClassMetadataFactory->getMetadataFor($resourceClass)->getAttributesMetadata();
65+
if (!empty($serializerMetadataAttributes[$property]) && null !== ($serializedName = $serializerMetadataAttributes[$property]->getSerializedName())) {
66+
$propertyMetadata = $propertyMetadata->withSerializedName($serializedName);
67+
}
68+
6469
$propertyMetadata = $this->transformReadWrite($propertyMetadata, $resourceClass, $property, $normalizationGroups, $denormalizationGroups);
6570

6671
return $this->transformLinkStatus($propertyMetadata, $normalizationGroups, $denormalizationGroups);

src/Metadata/Property/PropertyMetadata.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ final class PropertyMetadata
3535
private $attributes;
3636
private $subresource;
3737
private $initializable;
38+
private $serializedName;
3839

39-
public function __construct(Type $type = null, string $description = null, bool $readable = null, bool $writable = null, bool $readableLink = null, bool $writableLink = null, bool $required = null, bool $identifier = null, string $iri = null, $childInherited = null, array $attributes = null, SubresourceMetadata $subresource = null, bool $initializable = null)
40+
public function __construct(Type $type = null, string $description = null, bool $readable = null, bool $writable = null, bool $readableLink = null, bool $writableLink = null, bool $required = null, bool $identifier = null, string $iri = null, $childInherited = null, array $attributes = null, SubresourceMetadata $subresource = null, bool $initializable = null, string $serializedName = null)
4041
{
4142
$this->type = $type;
4243
$this->description = $description;
@@ -51,6 +52,7 @@ public function __construct(Type $type = null, string $description = null, bool
5152
$this->attributes = $attributes;
5253
$this->subresource = $subresource;
5354
$this->initializable = $initializable;
55+
$this->serializedName = $serializedName;
5456
}
5557

5658
/**
@@ -343,4 +345,23 @@ public function withInitializable(bool $initializable): self
343345

344346
return $metadata;
345347
}
348+
349+
/**
350+
* Gets custom serialized name of this property.
351+
*/
352+
public function getSerializedName(): ?string
353+
{
354+
return $this->serializedName;
355+
}
356+
357+
/**
358+
* Returns a new instance with the given serialized name.
359+
*/
360+
public function withSerializedName(string $serializedName = null): self
361+
{
362+
$metadata = clone $this;
363+
$metadata->serializedName = $serializedName;
364+
365+
return $metadata;
366+
}
346367
}

src/Swagger/Serializer/DocumentationNormalizer.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,7 @@ private function getLinkObject(string $resourceClass, string $operationId, strin
793793
continue;
794794
}
795795

796+
$propertyName = $propertyMetadata->getSerializedName() ?? $propertyName;
796797
$linkObject['parameters'][$propertyName] = sprintf('$response.body#/%s', $propertyName);
797798
$identifiers[] = $propertyName;
798799
}
@@ -801,7 +802,7 @@ private function getLinkObject(string $resourceClass, string $operationId, strin
801802
return [];
802803
}
803804
$linkObject['operationId'] = $operationId;
804-
$linkObject['description'] = 1 === \count($identifiers) ? sprintf('The `%1$s` value returned in the response can be used as the `%1$s` parameter in `GET %2$s`.', $identifiers[0], $path) : sprintf('The values returned in the response can be used in `GET %s`.', $path);
805+
$linkObject['description'] = 1 === \count($identifiers) ? sprintf('The `%1$s` value returned in the response can be used as the `id` parameter in `GET %2$s`.', $identifiers[0], $path) : sprintf('The values returned in the response can be used in `GET %s`.', $path);
805806

806807
return $linkObject;
807808
}

tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ public function testCreate($readGroups, $writeGroups)
8383
$dummySerializerClassMetadata->addAttributeMetadata($relatedDummySerializerAttributeMetadata);
8484
$nameConvertedSerializerAttributeMetadata = new SerializerAttributeMetadata('nameConverted');
8585
$dummySerializerClassMetadata->addAttributeMetadata($nameConvertedSerializerAttributeMetadata);
86+
$nameSerializedSerializerAttributeMetadata = new SerializerAttributeMetadata('nameSerialized');
87+
$nameSerializedSerializerAttributeMetadata->setSerializedName('name_serialized');
88+
$dummySerializerClassMetadata->addAttributeMetadata($nameSerializedSerializerAttributeMetadata);
8689
$serializerClassMetadataFactoryProphecy->getMetadataFor(Dummy::class)->willReturn($dummySerializerClassMetadata);
8790
$relatedDummySerializerClassMetadata = new SerializerClassMetadata(RelatedDummy::class);
8891
$idSerializerAttributeMetadata = new SerializerAttributeMetadata('id');
@@ -105,6 +108,9 @@ public function testCreate($readGroups, $writeGroups)
105108
$nameConvertedPropertyMetadata = (new PropertyMetadata())
106109
->withType(new Type(Type::BUILTIN_TYPE_STRING, true));
107110
$decoratedProphecy->create(Dummy::class, 'nameConverted', [])->willReturn($nameConvertedPropertyMetadata);
111+
$nameSerializedPropertyMetadata = (new PropertyMetadata())
112+
->withType(new Type(Type::BUILTIN_TYPE_STRING, true));
113+
$decoratedProphecy->create(Dummy::class, 'nameSerialized', [])->willReturn($nameSerializedPropertyMetadata);
108114

109115
$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
110116
$resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true);
@@ -116,6 +122,7 @@ public function testCreate($readGroups, $writeGroups)
116122
$actual[] = $serializerPropertyMetadataFactory->create(Dummy::class, 'foo');
117123
$actual[] = $serializerPropertyMetadataFactory->create(Dummy::class, 'relatedDummy');
118124
$actual[] = $serializerPropertyMetadataFactory->create(Dummy::class, 'nameConverted');
125+
$actual[] = $serializerPropertyMetadataFactory->create(Dummy::class, 'nameSerialized');
119126

120127
$this->assertInstanceOf(PropertyMetadata::class, $actual[0]);
121128
$this->assertFalse($actual[0]->isReadable());
@@ -130,6 +137,9 @@ public function testCreate($readGroups, $writeGroups)
130137
$this->assertInstanceOf(PropertyMetadata::class, $actual[2]);
131138
$this->assertFalse($actual[2]->isReadable());
132139
$this->assertFalse($actual[2]->isWritable());
140+
141+
$this->assertInstanceOf(PropertyMetadata::class, $actual[3]);
142+
$this->assertEquals($actual[3]->getSerializedName(), 'name_serialized');
133143
}
134144

135145
public function groupsProvider(): array

tests/Metadata/Property/PropertyMetadataTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ public function testValueObject()
8282
$newMetadata = $metadata->withInitializable(true);
8383
$this->assertNotSame($metadata, $newMetadata);
8484
$this->assertTrue($newMetadata->isInitializable());
85+
86+
$newMetadata = $metadata->withSerializedName('foo');
87+
$this->assertNotSame($metadata, $newMetadata);
88+
$this->assertEquals('foo', $newMetadata->getSerializedName());
8589
}
8690

8791
public function testShouldReturnRequiredFalseWhenRequiredTrueIsSetButMaskedByWritableFalse()

tests/Swagger/Serializer/DocumentationNormalizerV3Test.php

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3131,4 +3131,147 @@ private function doTestNormalizeWithCustomFormatsDefinedAtOperationLevel(Operati
31313131

31323132
$this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/']));
31333133
}
3134+
3135+
public function testNormalizeWithCustomSerializedName(): void
3136+
{
3137+
$documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3');
3138+
3139+
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
3140+
$propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['id']));
3141+
3142+
$dummyMetadata = new ResourceMetadata(
3143+
'Dummy',
3144+
'This is a dummy.',
3145+
'http://schema.example.com/Dummy',
3146+
[
3147+
'get' => ['method' => 'GET'] + self::OPERATION_FORMATS,
3148+
],
3149+
[
3150+
'post' => ['method' => 'POST'] + self::OPERATION_FORMATS,
3151+
]
3152+
);
3153+
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
3154+
$resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata);
3155+
3156+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
3157+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false, null, null, null, true, null, null, [], null, null, 'code'));
3158+
3159+
$operationPathResolver = new OperationPathResolver(new UnderscorePathSegmentNameGenerator());
3160+
3161+
$normalizer = new DocumentationNormalizer(
3162+
$resourceMetadataFactoryProphecy->reveal(),
3163+
$propertyNameCollectionFactoryProphecy->reveal(),
3164+
$propertyMetadataFactoryProphecy->reveal(),
3165+
null,
3166+
null,
3167+
$operationPathResolver,
3168+
null,
3169+
null,
3170+
null, false,
3171+
'',
3172+
'',
3173+
'',
3174+
'',
3175+
[],
3176+
[],
3177+
null,
3178+
false,
3179+
'page',
3180+
false,
3181+
'itemsPerPage',
3182+
[],
3183+
false,
3184+
'pagination',
3185+
['spec_version' => 3]
3186+
);
3187+
3188+
$expected = [
3189+
'openapi' => '3.0.2',
3190+
'info' => [
3191+
'title' => 'Test API',
3192+
'description' => 'This is a test API.',
3193+
'version' => '1.2.3',
3194+
],
3195+
'paths' => new \ArrayObject([
3196+
'/dummies' => [
3197+
'post' => new \ArrayObject([
3198+
'tags' => ['Dummy'],
3199+
'operationId' => 'postDummyCollection',
3200+
'summary' => 'Creates a Dummy resource.',
3201+
'requestBody' => [
3202+
'content' => [
3203+
'application/ld+json' => [
3204+
'schema' => ['$ref' => '#/components/schemas/Dummy'],
3205+
],
3206+
],
3207+
'description' => 'The new Dummy resource',
3208+
],
3209+
'responses' => [
3210+
201 => [
3211+
'description' => 'Dummy resource created',
3212+
'content' => [
3213+
'application/ld+json' => [
3214+
'schema' => ['$ref' => '#/components/schemas/Dummy'],
3215+
],
3216+
],
3217+
'links' => [
3218+
'GetDummyItem' => [
3219+
'operationId' => 'getDummyItem',
3220+
'parameters' => ['code' => '$response.body#/code'],
3221+
'description' => 'The `code` value returned in the response can be used as the `id` parameter in `GET /dummies/{id}`.',
3222+
],
3223+
],
3224+
],
3225+
400 => ['description' => 'Invalid input'],
3226+
404 => ['description' => 'Resource not found'],
3227+
],
3228+
]),
3229+
],
3230+
'/dummies/{id}' => [
3231+
'get' => new \ArrayObject([
3232+
'tags' => ['Dummy'],
3233+
'operationId' => 'getDummyItem',
3234+
'summary' => 'Retrieves a Dummy resource.',
3235+
'parameters' => [
3236+
[
3237+
'name' => 'id',
3238+
'in' => 'path',
3239+
'schema' => ['type' => 'string'],
3240+
'required' => true,
3241+
],
3242+
],
3243+
'responses' => [
3244+
'200' => [
3245+
'description' => 'Dummy resource response',
3246+
'content' => [
3247+
'application/ld+json' => [
3248+
'schema' => ['$ref' => '#/components/schemas/Dummy'],
3249+
],
3250+
],
3251+
],
3252+
'404' => ['description' => 'Resource not found'],
3253+
],
3254+
]),
3255+
],
3256+
]),
3257+
'components' => [
3258+
'schemas' => new \ArrayObject([
3259+
'Dummy' => new \ArrayObject([
3260+
'type' => 'object',
3261+
'description' => 'This is a dummy.',
3262+
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
3263+
'properties' => [
3264+
'id' => new \ArrayObject([
3265+
'type' => 'integer',
3266+
'description' => 'This is an id.',
3267+
'readOnly' => true,
3268+
]),
3269+
],
3270+
]),
3271+
]),
3272+
],
3273+
];
3274+
3275+
$this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/']));
3276+
}
31343277
}

0 commit comments

Comments
 (0)