Skip to content

Commit 3c98fdb

Browse files
authored
Merge pull request #3002 from fredericbarthelet/improve-pagination-generated-doc
Add default, min, max specification in pagination parameter API docs
2 parents 849fd28 + c2e7ef4 commit 3c98fdb

File tree

2 files changed

+186
-10
lines changed

2 files changed

+186
-10
lines changed

src/Swagger/Serializer/DocumentationNormalizer.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,10 @@ private function addPaginationParameters(bool $v3, ResourceMetadata $resourceMet
357357
'required' => false,
358358
'description' => 'The collection page number',
359359
];
360-
$v3 ? $paginationParameter['schema'] = ['type' => 'integer'] : $paginationParameter['type'] = 'integer';
360+
$v3 ? $paginationParameter['schema'] = [
361+
'type' => 'integer',
362+
'default' => 1,
363+
] : $paginationParameter['type'] = 'integer';
361364
$pathOperation['parameters'][] = $paginationParameter;
362365

363366
if ($resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_items_per_page', $this->clientItemsPerPage, true)) {
@@ -367,7 +370,19 @@ private function addPaginationParameters(bool $v3, ResourceMetadata $resourceMet
367370
'required' => false,
368371
'description' => 'The number of items per page',
369372
];
370-
$v3 ? $itemPerPageParameter['schema'] = ['type' => 'integer'] : $itemPerPageParameter['type'] = 'integer';
373+
if ($v3) {
374+
$itemPerPageParameter['schema'] = [
375+
'type' => 'integer',
376+
'default' => $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_items_per_page', 30, true),
377+
'minimum' => 0,
378+
];
379+
380+
if ($maximumItemPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'maximum_items_per_page', false, true)) {
381+
$itemPerPageParameter['schema']['maximum'] = $maximumItemPerPage;
382+
}
383+
} else {
384+
$itemPerPageParameter['type'] = 'integer';
385+
}
371386

372387
$pathOperation['parameters'][] = $itemPerPageParameter;
373388
}

tests/Swagger/Serializer/DocumentationNormalizerV3Test.php

Lines changed: 169 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth
165165
'required' => false,
166166
'schema' => [
167167
'type' => 'integer',
168+
'default' => 1,
168169
],
169170
'description' => 'The collection page number',
170171
],
@@ -174,6 +175,8 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth
174175
'required' => false,
175176
'schema' => [
176177
'type' => 'integer',
178+
'default' => 30,
179+
'minimum' => 0,
177180
],
178181
'description' => 'The number of items per page',
179182
],
@@ -294,14 +297,21 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth
294297
'name' => 'page',
295298
'in' => 'query',
296299
'required' => false,
297-
'schema' => ['type' => 'integer'],
300+
'schema' => [
301+
'type' => 'integer',
302+
'default' => 1,
303+
],
298304
'description' => 'The collection page number',
299305
],
300306
[
301307
'name' => 'itemsPerPage',
302308
'in' => 'query',
303309
'required' => false,
304-
'schema' => ['type' => 'integer'],
310+
'schema' => [
311+
'type' => 'integer',
312+
'default' => 30,
313+
'minimum' => 0,
314+
],
305315
'description' => 'The number of items per page',
306316
],
307317
],
@@ -772,7 +782,10 @@ public function testNormalizeWithOnlyNormalizationGroups(): void
772782
'name' => 'page',
773783
'in' => 'query',
774784
'required' => false,
775-
'schema' => ['type' => 'integer'],
785+
'schema' => [
786+
'type' => 'integer',
787+
'default' => 1,
788+
],
776789
'description' => 'The collection page number',
777790
],
778791
],
@@ -1103,7 +1116,10 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void
11031116
'name' => 'page',
11041117
'in' => 'query',
11051118
'required' => false,
1106-
'schema' => ['type' => 'integer'],
1119+
'schema' => [
1120+
'type' => 'integer',
1121+
'default' => 1,
1122+
],
11071123
'description' => 'The collection page number',
11081124
],
11091125
],
@@ -1321,7 +1337,10 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void
13211337
'name' => 'page',
13221338
'in' => 'query',
13231339
'required' => false,
1324-
'schema' => ['type' => 'integer'],
1340+
'schema' => [
1341+
'type' => 'integer',
1342+
'default' => 1,
1343+
],
13251344
'description' => 'The collection page number',
13261345
],
13271346
],
@@ -1825,7 +1844,10 @@ public function testNormalizeWithNestedNormalizationGroups(): void
18251844
'name' => 'page',
18261845
'in' => 'query',
18271846
'required' => false,
1828-
'schema' => ['type' => 'integer'],
1847+
'schema' => [
1848+
'type' => 'integer',
1849+
'default' => 1,
1850+
],
18291851
'description' => 'The collection page number',
18301852
],
18311853
],
@@ -2079,7 +2101,10 @@ private function normalizeWithFilters($filterLocator): void
20792101
'name' => 'page',
20802102
'in' => 'query',
20812103
'required' => false,
2082-
'schema' => ['type' => 'integer'],
2104+
'schema' => [
2105+
'type' => 'integer',
2106+
'default' => 1,
2107+
],
20832108
'description' => 'The collection page number',
20842109
],
20852110
],
@@ -2476,7 +2501,10 @@ public function testNormalizeWithPaginationClientEnabled(): void
24762501
'name' => 'page',
24772502
'in' => 'query',
24782503
'required' => false,
2479-
'schema' => ['type' => 'integer'],
2504+
'schema' => [
2505+
'type' => 'integer',
2506+
'default' => 1,
2507+
],
24802508
'description' => 'The collection page number',
24812509
],
24822510
[
@@ -2530,6 +2558,139 @@ public function testNormalizeWithPaginationClientEnabled(): void
25302558
$this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/']));
25312559
}
25322560

2561+
public function testNormalizeWithPaginationCustomDefaultAndMaxItemsPerPage(): void
2562+
{
2563+
$documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3');
2564+
2565+
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
2566+
$propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['id', 'name']));
2567+
2568+
$dummyMetadata = new ResourceMetadata(
2569+
'Dummy',
2570+
'This is a dummy.',
2571+
'http://schema.example.com/Dummy',
2572+
[],
2573+
['get' => ['method' => 'GET'] + self::OPERATION_FORMATS],
2574+
['pagination_client_items_per_page' => true, 'pagination_items_per_page' => 20, 'maximum_items_per_page' => 80]
2575+
);
2576+
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
2577+
$resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata);
2578+
2579+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
2580+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'id')->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false));
2581+
$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']]));
2582+
2583+
$operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()));
2584+
2585+
$normalizer = new DocumentationNormalizer(
2586+
$resourceMetadataFactoryProphecy->reveal(),
2587+
$propertyNameCollectionFactoryProphecy->reveal(),
2588+
$propertyMetadataFactoryProphecy->reveal(),
2589+
null,
2590+
null,
2591+
$operationPathResolver,
2592+
null,
2593+
null,
2594+
null,
2595+
false,
2596+
'',
2597+
'',
2598+
'',
2599+
'',
2600+
[],
2601+
[],
2602+
null,
2603+
true,
2604+
'page',
2605+
false,
2606+
'itemsPerPage',
2607+
[],
2608+
false,
2609+
'pagination',
2610+
['spec_version' => 3]
2611+
);
2612+
2613+
$expected = [
2614+
'openapi' => '3.0.2',
2615+
'servers' => [['url' => '/app_dev.php/']],
2616+
'info' => [
2617+
'title' => 'Test API',
2618+
'description' => 'This is a test API.',
2619+
'version' => '1.2.3',
2620+
],
2621+
'paths' => new \ArrayObject([
2622+
'/dummies' => [
2623+
'get' => new \ArrayObject([
2624+
'tags' => ['Dummy'],
2625+
'operationId' => 'getDummyCollection',
2626+
'summary' => 'Retrieves the collection of Dummy resources.',
2627+
'parameters' => [
2628+
[
2629+
'name' => 'page',
2630+
'in' => 'query',
2631+
'required' => false,
2632+
'schema' => [
2633+
'type' => 'integer',
2634+
'default' => 1,
2635+
],
2636+
'description' => 'The collection page number',
2637+
],
2638+
[
2639+
'name' => 'itemsPerPage',
2640+
'in' => 'query',
2641+
'required' => false,
2642+
'schema' => [
2643+
'type' => 'integer',
2644+
'default' => 20,
2645+
'minimum' => 0,
2646+
'maximum' => 80,
2647+
],
2648+
'description' => 'The number of items per page',
2649+
],
2650+
],
2651+
'responses' => [
2652+
'200' => [
2653+
'description' => 'Dummy collection response',
2654+
'content' => [
2655+
'application/ld+json' => [
2656+
'schema' => [
2657+
'type' => 'array',
2658+
'items' => ['$ref' => '#/components/schemas/Dummy'],
2659+
],
2660+
],
2661+
],
2662+
],
2663+
],
2664+
]),
2665+
],
2666+
]),
2667+
'components' => [
2668+
'schemas' => new \ArrayObject([
2669+
'Dummy' => new \ArrayObject([
2670+
'type' => 'object',
2671+
'description' => 'This is a dummy.',
2672+
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
2673+
'properties' => [
2674+
'id' => new \ArrayObject([
2675+
'type' => 'integer',
2676+
'description' => 'This is an id.',
2677+
'readOnly' => true,
2678+
]),
2679+
'name' => new \ArrayObject([
2680+
'type' => 'string',
2681+
'description' => 'This is a name.',
2682+
'enum' => ['one', 'two'],
2683+
'example' => 'one',
2684+
]),
2685+
],
2686+
]),
2687+
]),
2688+
],
2689+
];
2690+
2691+
$this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/']));
2692+
}
2693+
25332694
public function testNormalizeWithCustomFormatsDefinedAtOperationLevel(): void
25342695
{
25352696
$this->doNormalizeWithCustomFormatsDefinedAtOperationLevel();

0 commit comments

Comments
 (0)