diff --git a/src/Swagger/Serializer/DocumentationNormalizer.php b/src/Swagger/Serializer/DocumentationNormalizer.php index f31169195bd..c455ac41722 100644 --- a/src/Swagger/Serializer/DocumentationNormalizer.php +++ b/src/Swagger/Serializer/DocumentationNormalizer.php @@ -521,6 +521,11 @@ private function getPropertySchema(PropertyMetadata $propertyMetadata, \ArrayObj return $propertySchema; } + $attributeSchema = []; + if (null !== $attributes = $propertyMetadata->getAttributes()) { + $attributeSchema = $this->getPropertyAttributes($attributes); + } + $isCollection = $type->isCollection(); if (null === $valueType = $isCollection ? $type->getCollectionValueType() : $type) { $builtinType = 'string'; @@ -532,7 +537,21 @@ private function getPropertySchema(PropertyMetadata $propertyMetadata, \ArrayObj $valueSchema = $this->getType($builtinType, $isCollection, $className, $propertyMetadata->isReadableLink(), $definitions, $serializerContext); - return new \ArrayObject((array) $propertySchema + $valueSchema); + return new \ArrayObject((array) $propertySchema + $valueSchema + $attributeSchema); + } + + /** + * @param array $attributes + * @return array + */ + private function getPropertyAttributes(array $attributes): array + { + $attributeSchema = []; + if (isset($attributes['swagger_context'])) { + $attributeSchema = array_merge($attributeSchema, $attributes['swagger_context']); + } + + return $attributeSchema; } /** diff --git a/tests/Swagger/Serializer/DocumentationNormalizerTest.php b/tests/Swagger/Serializer/DocumentationNormalizerTest.php index 1fff4f220cf..b43eb4c90d8 100644 --- a/tests/Swagger/Serializer/DocumentationNormalizerTest.php +++ b/tests/Swagger/Serializer/DocumentationNormalizerTest.php @@ -1785,4 +1785,93 @@ public function testNormalizeWithSubResource() $this->assertEquals($expected, $normalizer->normalize($documentation)); } + + public function testNormalizeWithPropertySwaggerContext() + { + $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3', ['jsonld' => ['application/ld+json']]); + + $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); + $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['id', 'name'])); + + $dummyMetadata = new ResourceMetadata('Dummy', 'This is a dummy.', 'http://schema.example.com/Dummy', ['get' => ['method' => 'GET']]); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata); + + $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'id')->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'name')->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, ['swagger_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); + $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); + $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); + + $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); + $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'get')->shouldBeCalled()->willReturn('GET'); + + $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); + + $normalizer = new DocumentationNormalizer( + $resourceMetadataFactoryProphecy->reveal(), + $propertyNameCollectionFactoryProphecy->reveal(), + $propertyMetadataFactoryProphecy->reveal(), + $resourceClassResolverProphecy->reveal(), + $operationMethodResolverProphecy->reveal(), + $operationPathResolver + ); + + $expected = [ + 'swagger' => '2.0', + 'basePath' => '/app_dev.php/', + 'info' => [ + 'title' => 'Test API', + 'description' => 'This is a test API.', + 'version' => '1.2.3', + ], + 'paths' => new \ArrayObject([ + '/dummies/{id}' => [ + 'get' => new \ArrayObject([ + 'tags' => ['Dummy'], + 'operationId' => 'getDummyItem', + 'produces' => ['application/ld+json'], + 'summary' => 'Retrieves a Dummy resource.', + 'parameters' => [ + [ + 'name' => 'id', + 'in' => 'path', + 'type' => 'string', + 'required' => true, + ], + ], + 'responses' => [ + 200 => [ + 'description' => 'Dummy resource response', + 'schema' => ['$ref' => '#/definitions/Dummy'], + ], + 404 => ['description' => 'Resource not found'], + ], + ]), + ], + ]), + 'definitions' => new \ArrayObject([ + 'Dummy' => new \ArrayObject([ + 'type' => 'object', + 'description' => 'This is a dummy.', + 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], + 'properties' => [ + 'id' => new \ArrayObject([ + 'type' => 'integer', + 'description' => 'This is an id.', + 'readOnly' => true, + ]), + 'name' => new \ArrayObject([ + 'type' => 'string', + 'description' => 'This is a name.', + 'enum' => ['one', 'two'], + 'example' => 'one', + ]), + ], + ]), + ]), + ]; + + $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); + } }