Skip to content

Commit d9cf112

Browse files
committed
feat(serializer): remove pagination attributes when explicitly disabled
1 parent 44f2271 commit d9cf112

File tree

7 files changed

+559
-137
lines changed

7 files changed

+559
-137
lines changed

src/Hal/JsonSchema/SchemaFactory.php

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ final class SchemaFactory implements SchemaFactoryInterface, SchemaFactoryAwareI
3535
use SchemaUriPrefixTrait;
3636

3737
private const COLLECTION_BASE_SCHEMA_NAME = 'HalCollectionBaseSchema';
38+
private const COLLECTION_BASE_SCHEMA_NAME_NO_PAGINATION = 'HalCollectionBaseSchemaNoPagination';
3839

3940
private const HREF_PROP = [
4041
'href' => [
@@ -122,10 +123,14 @@ public function buildSchema(string $className, string $format = 'jsonhal', strin
122123
}
123124

124125
if (($schema['type'] ?? '') === 'array') {
125-
if (!isset($definitions[self::COLLECTION_BASE_SCHEMA_NAME])) {
126-
$definitions[self::COLLECTION_BASE_SCHEMA_NAME] = [
126+
if (!isset($definitions[self::COLLECTION_BASE_SCHEMA_NAME_NO_PAGINATION])) {
127+
$definitions[self::COLLECTION_BASE_SCHEMA_NAME_NO_PAGINATION] = [
127128
'type' => 'object',
128129
'properties' => [
130+
'totalItems' => [
131+
'type' => 'integer',
132+
'minimum' => 0,
133+
],
129134
'_embedded' => [
130135
'anyOf' => [
131136
[
@@ -139,41 +144,52 @@ public function buildSchema(string $className, string $format = 'jsonhal', strin
139144
['type' => 'object'],
140145
],
141146
],
142-
'totalItems' => [
143-
'type' => 'integer',
144-
'minimum' => 0,
145-
],
146-
'itemsPerPage' => [
147-
'type' => 'integer',
148-
'minimum' => 0,
149-
],
150147
'_links' => [
151148
'type' => 'object',
152149
'properties' => [
153150
'self' => [
154151
'type' => 'object',
155152
'properties' => self::HREF_PROP,
156153
],
157-
'first' => [
158-
'type' => 'object',
159-
'properties' => self::HREF_PROP,
160-
],
161-
'last' => [
162-
'type' => 'object',
163-
'properties' => self::HREF_PROP,
164-
],
165-
'next' => [
166-
'type' => 'object',
167-
'properties' => self::HREF_PROP,
154+
],
155+
],
156+
],
157+
'required' => ['_links', '_embedded'],
158+
];
159+
160+
$definitions[self::COLLECTION_BASE_SCHEMA_NAME] = [
161+
'allOf' => [
162+
['$ref' => $prefix.self::COLLECTION_BASE_SCHEMA_NAME_NO_PAGINATION],
163+
[
164+
'type' => 'object',
165+
'properties' => [
166+
'itemsPerPage' => [
167+
'type' => 'integer',
168+
'minimum' => 0,
168169
],
169-
'previous' => [
170-
'type' => 'object',
171-
'properties' => self::HREF_PROP,
170+
'_links' => [
171+
'properties' => [
172+
'first' => [
173+
'type' => 'object',
174+
'properties' => self::HREF_PROP,
175+
],
176+
'last' => [
177+
'type' => 'object',
178+
'properties' => self::HREF_PROP,
179+
],
180+
'next' => [
181+
'type' => 'object',
182+
'properties' => self::HREF_PROP,
183+
],
184+
'previous' => [
185+
'type' => 'object',
186+
'properties' => self::HREF_PROP,
187+
],
188+
],
172189
],
173190
],
174191
],
175192
],
176-
'required' => ['_links', '_embedded'],
177193
];
178194
}
179195

@@ -182,7 +198,7 @@ public function buildSchema(string $className, string $format = 'jsonhal', strin
182198

183199
$schema['description'] = "$definitionName collection.";
184200
$schema['allOf'] = [
185-
['$ref' => $prefix.self::COLLECTION_BASE_SCHEMA_NAME],
201+
['$ref' => $prefix.(false === $operation->getPaginationEnabled() ? self::COLLECTION_BASE_SCHEMA_NAME_NO_PAGINATION : self::COLLECTION_BASE_SCHEMA_NAME)],
186202
[
187203
'type' => 'object',
188204
'properties' => [

src/Hydra/JsonSchema/SchemaFactory.php

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ final class SchemaFactory implements SchemaFactoryInterface, SchemaFactoryAwareI
3838

3939
private const ITEM_BASE_SCHEMA_NAME = 'HydraItemBaseSchema';
4040
private const ITEM_WITHOUT_ID_BASE_SCHEMA_NAME = 'HydraItemBaseSchemaWithoutId';
41+
private const COLLECTION_BASE_SCHEMA_NAME_NO_PAGINATION = 'HydraCollectionBaseSchemaNoPagination';
4142
private const COLLECTION_BASE_SCHEMA_NAME = 'HydraCollectionBaseSchema';
4243

4344
private const BASE_PROP = [
@@ -155,7 +156,7 @@ public function buildSchema(string $className, string $format = 'jsonld', string
155156

156157
$hydraPrefix = $this->getHydraPrefix($serializerContext + $this->defaultContext);
157158

158-
if (!isset($definitions[self::COLLECTION_BASE_SCHEMA_NAME])) {
159+
if (!isset($definitions[self::COLLECTION_BASE_SCHEMA_NAME_NO_PAGINATION])) {
159160
switch ($schema->getVersion()) {
160161
// JSON Schema + OpenAPI 3.1
161162
case Schema::VERSION_OPENAPI:
@@ -168,49 +169,13 @@ public function buildSchema(string $className, string $format = 'jsonld', string
168169
break;
169170
}
170171

171-
$definitions[self::COLLECTION_BASE_SCHEMA_NAME] = [
172+
$definitions[self::COLLECTION_BASE_SCHEMA_NAME_NO_PAGINATION] = [
172173
'type' => 'object',
173174
'properties' => [
174175
$hydraPrefix.'totalItems' => [
175176
'type' => 'integer',
176177
'minimum' => 0,
177178
],
178-
$hydraPrefix.'view' => [
179-
'type' => 'object',
180-
'properties' => [
181-
'@id' => [
182-
'type' => 'string',
183-
'format' => 'iri-reference',
184-
],
185-
'@type' => [
186-
'type' => 'string',
187-
],
188-
$hydraPrefix.'first' => [
189-
'type' => 'string',
190-
'format' => 'iri-reference',
191-
],
192-
$hydraPrefix.'last' => [
193-
'type' => 'string',
194-
'format' => 'iri-reference',
195-
],
196-
$hydraPrefix.'previous' => [
197-
'type' => 'string',
198-
'format' => 'iri-reference',
199-
],
200-
$hydraPrefix.'next' => [
201-
'type' => 'string',
202-
'format' => 'iri-reference',
203-
],
204-
],
205-
'example' => [
206-
'@id' => 'string',
207-
'type' => 'string',
208-
$hydraPrefix.'first' => 'string',
209-
$hydraPrefix.'last' => 'string',
210-
$hydraPrefix.'previous' => 'string',
211-
$hydraPrefix.'next' => 'string',
212-
],
213-
],
214179
$hydraPrefix.'search' => [
215180
'type' => 'object',
216181
'properties' => [
@@ -233,13 +198,60 @@ public function buildSchema(string $className, string $format = 'jsonld', string
233198
],
234199
],
235200
];
201+
202+
$definitions[self::COLLECTION_BASE_SCHEMA_NAME] = [
203+
'allOf' => [
204+
['$ref' => $prefix.self::COLLECTION_BASE_SCHEMA_NAME_NO_PAGINATION],
205+
[
206+
'type' => 'object',
207+
'properties' => [
208+
$hydraPrefix.'view' => [
209+
'type' => 'object',
210+
'properties' => [
211+
'@id' => [
212+
'type' => 'string',
213+
'format' => 'iri-reference',
214+
],
215+
'@type' => [
216+
'type' => 'string',
217+
],
218+
$hydraPrefix.'first' => [
219+
'type' => 'string',
220+
'format' => 'iri-reference',
221+
],
222+
$hydraPrefix.'last' => [
223+
'type' => 'string',
224+
'format' => 'iri-reference',
225+
],
226+
$hydraPrefix.'previous' => [
227+
'type' => 'string',
228+
'format' => 'iri-reference',
229+
],
230+
$hydraPrefix.'next' => [
231+
'type' => 'string',
232+
'format' => 'iri-reference',
233+
],
234+
],
235+
'example' => [
236+
'@id' => 'string',
237+
'type' => 'string',
238+
$hydraPrefix.'first' => 'string',
239+
$hydraPrefix.'last' => 'string',
240+
$hydraPrefix.'previous' => 'string',
241+
$hydraPrefix.'next' => 'string',
242+
],
243+
],
244+
],
245+
],
246+
],
247+
];
236248
}
237249

238250
$definitionName = $this->definitionNameFactory->create($className, $format, $inputOrOutputClass, $operation, $serializerContext);
239251
$schema['type'] = 'object';
240252
$schema['description'] = "$definitionName collection.";
241253
$schema['allOf'] = [
242-
['$ref' => $prefix.self::COLLECTION_BASE_SCHEMA_NAME],
254+
['$ref' => $prefix.(false === $operation->getPaginationEnabled() ? self::COLLECTION_BASE_SCHEMA_NAME_NO_PAGINATION : self::COLLECTION_BASE_SCHEMA_NAME)],
243255
[
244256
'type' => 'object',
245257
'required' => [

src/Hydra/Tests/JsonSchema/SchemaFactoryTest.php

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,18 @@ public function testSchemaTypeBuildSchema(): void
130130
{
131131
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class, 'jsonld', Schema::TYPE_OUTPUT, new GetCollection());
132132
$this->assertNull($resultSchema->getRootDefinitionKey());
133-
$hydraCollectionSchema = $resultSchema['definitions']['HydraCollectionBaseSchema'];
134-
$properties = $hydraCollectionSchema['properties'];
133+
$hydraCollectionSchemaNoPagination = $resultSchema['definitions']['HydraCollectionBaseSchemaNoPagination'];
134+
$properties = $hydraCollectionSchemaNoPagination['properties'];
135135
$this->assertArrayHasKey('hydra:totalItems', $properties);
136-
$this->assertArrayHasKey('hydra:view', $properties);
137136
$this->assertArrayHasKey('hydra:search', $properties);
137+
138+
$hydraCollectionSchema = $resultSchema['definitions']['HydraCollectionBaseSchema'];
139+
$this->assertArrayHasKey('allOf', $hydraCollectionSchema);
140+
$this->assertSame([
141+
'$ref' => '#/definitions/HydraCollectionBaseSchemaNoPagination',
142+
], $hydraCollectionSchema['allOf'][0]);
143+
$properties = $hydraCollectionSchema['allOf'][1]['properties'];
144+
$this->assertArrayHasKey('hydra:view', $properties);
138145
$this->assertArrayNotHasKey('@context', $properties);
139146

140147
$this->assertTrue(isset($properties['hydra:view']));
@@ -152,10 +159,16 @@ public function testSchemaTypeBuildSchemaWithoutPrefix(): void
152159
{
153160
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class, 'jsonld', Schema::TYPE_OUTPUT, new GetCollection(), null, [ContextBuilder::HYDRA_CONTEXT_HAS_PREFIX => false]);
154161
$this->assertNull($resultSchema->getRootDefinitionKey());
155-
$hydraCollectionSchema = $resultSchema['definitions']['HydraCollectionBaseSchema'];
156-
$properties = $hydraCollectionSchema['properties'];
162+
$hydraCollectionSchemaNoPagination = $resultSchema['definitions']['HydraCollectionBaseSchemaNoPagination'];
163+
$properties = $hydraCollectionSchemaNoPagination['properties'];
157164
$this->assertArrayHasKey('totalItems', $properties);
158-
$this->assertArrayHasKey('view', $properties);
159165
$this->assertArrayHasKey('search', $properties);
166+
167+
$hydraCollectionSchema = $resultSchema['definitions']['HydraCollectionBaseSchema'];
168+
$this->assertSame([
169+
'$ref' => '#/definitions/HydraCollectionBaseSchemaNoPagination',
170+
], $hydraCollectionSchema['allOf'][0]);
171+
$properties = $hydraCollectionSchema['allOf'][1]['properties'];
172+
$this->assertArrayHasKey('view', $properties);
160173
}
161174
}

0 commit comments

Comments
 (0)