From c2e7ef4c183c040caa0541345f9fa19cd5948531 Mon Sep 17 00:00:00 2001 From: fredericbarthelet Date: Mon, 19 Aug 2019 17:34:00 +0200 Subject: [PATCH] Add default, min, max specification in pagination parameter API docs --- .../Serializer/DocumentationNormalizer.php | 19 +- .../DocumentationNormalizerV3Test.php | 177 +++++++++++++++++- 2 files changed, 186 insertions(+), 10 deletions(-) diff --git a/src/Swagger/Serializer/DocumentationNormalizer.php b/src/Swagger/Serializer/DocumentationNormalizer.php index 29adb4007b8..ddde8e3e154 100644 --- a/src/Swagger/Serializer/DocumentationNormalizer.php +++ b/src/Swagger/Serializer/DocumentationNormalizer.php @@ -357,7 +357,10 @@ private function addPaginationParameters(bool $v3, ResourceMetadata $resourceMet 'required' => false, 'description' => 'The collection page number', ]; - $v3 ? $paginationParameter['schema'] = ['type' => 'integer'] : $paginationParameter['type'] = 'integer'; + $v3 ? $paginationParameter['schema'] = [ + 'type' => 'integer', + 'default' => 1, + ] : $paginationParameter['type'] = 'integer'; $pathOperation['parameters'][] = $paginationParameter; if ($resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_items_per_page', $this->clientItemsPerPage, true)) { @@ -367,7 +370,19 @@ private function addPaginationParameters(bool $v3, ResourceMetadata $resourceMet 'required' => false, 'description' => 'The number of items per page', ]; - $v3 ? $itemPerPageParameter['schema'] = ['type' => 'integer'] : $itemPerPageParameter['type'] = 'integer'; + if ($v3) { + $itemPerPageParameter['schema'] = [ + 'type' => 'integer', + 'default' => $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_items_per_page', 30, true), + 'minimum' => 0, + ]; + + if ($maximumItemPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'maximum_items_per_page', false, true)) { + $itemPerPageParameter['schema']['maximum'] = $maximumItemPerPage; + } + } else { + $itemPerPageParameter['type'] = 'integer'; + } $pathOperation['parameters'][] = $itemPerPageParameter; } diff --git a/tests/Swagger/Serializer/DocumentationNormalizerV3Test.php b/tests/Swagger/Serializer/DocumentationNormalizerV3Test.php index 02f442f728e..9b5c2286b73 100644 --- a/tests/Swagger/Serializer/DocumentationNormalizerV3Test.php +++ b/tests/Swagger/Serializer/DocumentationNormalizerV3Test.php @@ -165,6 +165,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth 'required' => false, 'schema' => [ 'type' => 'integer', + 'default' => 1, ], 'description' => 'The collection page number', ], @@ -174,6 +175,8 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth 'required' => false, 'schema' => [ 'type' => 'integer', + 'default' => 30, + 'minimum' => 0, ], 'description' => 'The number of items per page', ], @@ -294,14 +297,21 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth 'name' => 'page', 'in' => 'query', 'required' => false, - 'schema' => ['type' => 'integer'], + 'schema' => [ + 'type' => 'integer', + 'default' => 1, + ], 'description' => 'The collection page number', ], [ 'name' => 'itemsPerPage', 'in' => 'query', 'required' => false, - 'schema' => ['type' => 'integer'], + 'schema' => [ + 'type' => 'integer', + 'default' => 30, + 'minimum' => 0, + ], 'description' => 'The number of items per page', ], ], @@ -772,7 +782,10 @@ public function testNormalizeWithOnlyNormalizationGroups(): void 'name' => 'page', 'in' => 'query', 'required' => false, - 'schema' => ['type' => 'integer'], + 'schema' => [ + 'type' => 'integer', + 'default' => 1, + ], 'description' => 'The collection page number', ], ], @@ -1103,7 +1116,10 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void 'name' => 'page', 'in' => 'query', 'required' => false, - 'schema' => ['type' => 'integer'], + 'schema' => [ + 'type' => 'integer', + 'default' => 1, + ], 'description' => 'The collection page number', ], ], @@ -1321,7 +1337,10 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void 'name' => 'page', 'in' => 'query', 'required' => false, - 'schema' => ['type' => 'integer'], + 'schema' => [ + 'type' => 'integer', + 'default' => 1, + ], 'description' => 'The collection page number', ], ], @@ -1825,7 +1844,10 @@ public function testNormalizeWithNestedNormalizationGroups(): void 'name' => 'page', 'in' => 'query', 'required' => false, - 'schema' => ['type' => 'integer'], + 'schema' => [ + 'type' => 'integer', + 'default' => 1, + ], 'description' => 'The collection page number', ], ], @@ -2079,7 +2101,10 @@ private function normalizeWithFilters($filterLocator): void 'name' => 'page', 'in' => 'query', 'required' => false, - 'schema' => ['type' => 'integer'], + 'schema' => [ + 'type' => 'integer', + 'default' => 1, + ], 'description' => 'The collection page number', ], ], @@ -2476,7 +2501,10 @@ public function testNormalizeWithPaginationClientEnabled(): void 'name' => 'page', 'in' => 'query', 'required' => false, - 'schema' => ['type' => 'integer'], + 'schema' => [ + 'type' => 'integer', + 'default' => 1, + ], 'description' => 'The collection page number', ], [ @@ -2530,6 +2558,139 @@ public function testNormalizeWithPaginationClientEnabled(): void $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); } + public function testNormalizeWithPaginationCustomDefaultAndMaxItemsPerPage(): void + { + $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); + + $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'] + self::OPERATION_FORMATS], + ['pagination_client_items_per_page' => true, 'pagination_items_per_page' => 20, 'maximum_items_per_page' => 80] + ); + $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, ['openapi_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); + + $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); + + $normalizer = new DocumentationNormalizer( + $resourceMetadataFactoryProphecy->reveal(), + $propertyNameCollectionFactoryProphecy->reveal(), + $propertyMetadataFactoryProphecy->reveal(), + null, + null, + $operationPathResolver, + null, + null, + null, + false, + '', + '', + '', + '', + [], + [], + null, + true, + 'page', + false, + 'itemsPerPage', + [], + false, + 'pagination', + ['spec_version' => 3] + ); + + $expected = [ + 'openapi' => '3.0.2', + 'servers' => [['url' => '/app_dev.php/']], + 'info' => [ + 'title' => 'Test API', + 'description' => 'This is a test API.', + 'version' => '1.2.3', + ], + 'paths' => new \ArrayObject([ + '/dummies' => [ + 'get' => new \ArrayObject([ + 'tags' => ['Dummy'], + 'operationId' => 'getDummyCollection', + 'summary' => 'Retrieves the collection of Dummy resources.', + 'parameters' => [ + [ + 'name' => 'page', + 'in' => 'query', + 'required' => false, + 'schema' => [ + 'type' => 'integer', + 'default' => 1, + ], + 'description' => 'The collection page number', + ], + [ + 'name' => 'itemsPerPage', + 'in' => 'query', + 'required' => false, + 'schema' => [ + 'type' => 'integer', + 'default' => 20, + 'minimum' => 0, + 'maximum' => 80, + ], + 'description' => 'The number of items per page', + ], + ], + 'responses' => [ + '200' => [ + 'description' => 'Dummy collection response', + 'content' => [ + 'application/ld+json' => [ + 'schema' => [ + 'type' => 'array', + 'items' => ['$ref' => '#/components/schemas/Dummy'], + ], + ], + ], + ], + ], + ]), + ], + ]), + 'components' => [ + 'schemas' => 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/'])); + } + public function testNormalizeWithCustomFormatsDefinedAtOperationLevel(): void { $this->doNormalizeWithCustomFormatsDefinedAtOperationLevel();