1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the League\Fractal package. |
5
|
|
|
* |
6
|
|
|
* (c) Phil Sturgeon <[email protected]> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace League\Fractal\Serializer; |
13
|
|
|
|
14
|
|
|
use InvalidArgumentException; |
15
|
|
|
use League\Fractal\Pagination\PaginatorInterface; |
16
|
|
|
use League\Fractal\Resource\ResourceInterface; |
17
|
|
|
|
18
|
|
|
class JsonApiSerializer extends ArraySerializer |
19
|
|
|
{ |
20
|
|
|
/** @var string|null */ |
21
|
|
|
protected $baseUrl; |
22
|
|
|
|
23
|
|
|
/** @var array */ |
24
|
|
|
protected $rootObjects; |
25
|
|
|
|
26
|
37 |
|
public function __construct(string $baseUrl = null) |
27
|
|
|
{ |
28
|
37 |
|
$this->baseUrl = $baseUrl; |
29
|
37 |
|
$this->rootObjects = []; |
30
|
37 |
|
} |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Serialize a collection. |
34
|
|
|
* |
35
|
|
|
* @param string $resourceKey |
36
|
|
|
* @param array $data |
37
|
|
|
* |
38
|
|
|
* @return array |
39
|
|
|
*/ |
40
|
24 |
|
public function collection($resourceKey, array $data): array |
41
|
|
|
{ |
42
|
24 |
|
$resources = []; |
43
|
|
|
|
44
|
24 |
|
foreach ($data as $resource) { |
45
|
23 |
|
$resources[] = $this->item($resourceKey, $resource)['data']; |
46
|
|
|
} |
47
|
|
|
|
48
|
24 |
|
return ['data' => $resources]; |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Serialize an item. |
53
|
|
|
* |
54
|
|
|
* @param string $resourceKey |
55
|
|
|
* @param array $data |
56
|
|
|
* |
57
|
|
|
* @return array |
58
|
|
|
*/ |
59
|
37 |
|
public function item($resourceKey, array $data): array |
60
|
|
|
{ |
61
|
37 |
|
$id = $this->getIdFromData($data); |
62
|
|
|
|
63
|
|
|
$resource = [ |
64
|
|
|
'data' => [ |
65
|
36 |
|
'type' => $resourceKey, |
66
|
36 |
|
'id' => "$id", |
67
|
36 |
|
'attributes' => $data, |
68
|
|
|
], |
69
|
|
|
]; |
70
|
|
|
|
71
|
36 |
|
unset($resource['data']['attributes']['id']); |
72
|
|
|
|
73
|
|
|
|
74
|
36 |
|
if ($this->areResourceLinksSet($resource)) { |
75
|
1 |
|
$custom_links = $data['links']; |
76
|
1 |
|
unset($resource['data']['attributes']['links']); |
77
|
|
|
} |
78
|
|
|
|
79
|
36 |
|
if ($this->isResourceMetaSet($resource)) { |
80
|
2 |
|
$resource['data']['meta'] = $data['meta']; |
81
|
2 |
|
unset($resource['data']['attributes']['meta']); |
82
|
|
|
} |
83
|
|
|
|
84
|
36 |
|
if ($this->isDataAttributesEmpty($resource)) { |
85
|
3 |
|
$resource['data']['attributes'] = (object) []; |
86
|
|
|
} |
87
|
|
|
|
88
|
36 |
|
if ($this->shouldIncludeLinks()) { |
89
|
11 |
|
$resource['data']['links'] = [ |
90
|
11 |
|
'self' => "{$this->baseUrl}/$resourceKey/$id", |
91
|
|
|
]; |
92
|
11 |
|
if (isset($custom_links)) { |
93
|
1 |
|
$resource['data']['links'] = array_merge($resource['data']['links'], $custom_links); |
94
|
|
|
} |
95
|
|
|
} |
96
|
|
|
|
97
|
36 |
|
return $resource; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Serialize the paginator. |
102
|
|
|
* |
103
|
|
|
* @param PaginatorInterface $paginator |
104
|
|
|
* |
105
|
|
|
* @return array |
106
|
|
|
*/ |
107
|
3 |
|
public function paginator(PaginatorInterface $paginator): array |
108
|
|
|
{ |
109
|
3 |
|
$currentPage = (int)$paginator->getCurrentPage(); |
110
|
3 |
|
$lastPage = (int)$paginator->getLastPage(); |
111
|
|
|
|
112
|
|
|
$pagination = [ |
113
|
3 |
|
'total' => (int)$paginator->getTotal(), |
114
|
3 |
|
'count' => (int)$paginator->getCount(), |
115
|
3 |
|
'per_page' => (int)$paginator->getPerPage(), |
116
|
3 |
|
'current_page' => $currentPage, |
117
|
3 |
|
'total_pages' => $lastPage, |
118
|
|
|
]; |
119
|
|
|
|
120
|
3 |
|
$pagination['links'] = []; |
121
|
|
|
|
122
|
3 |
|
$pagination['links']['self'] = $paginator->getUrl($currentPage); |
123
|
3 |
|
$pagination['links']['first'] = $paginator->getUrl(1); |
124
|
|
|
|
125
|
3 |
|
if ($currentPage > 1) { |
126
|
2 |
|
$pagination['links']['prev'] = $paginator->getUrl($currentPage - 1); |
127
|
|
|
} |
128
|
|
|
|
129
|
3 |
|
if ($currentPage < $lastPage) { |
130
|
2 |
|
$pagination['links']['next'] = $paginator->getUrl($currentPage + 1); |
131
|
|
|
} |
132
|
|
|
|
133
|
3 |
|
$pagination['links']['last'] = $paginator->getUrl($lastPage); |
134
|
|
|
|
135
|
3 |
|
return ['pagination' => $pagination]; |
136
|
|
|
} |
137
|
|
|
|
138
|
36 |
|
public function meta(array $meta): array |
139
|
|
|
{ |
140
|
36 |
|
$result = []; |
141
|
|
|
|
142
|
36 |
|
if (empty($meta)) { |
143
|
30 |
|
return []; |
144
|
|
|
} |
145
|
|
|
|
146
|
7 |
|
$result['meta'] = $meta; |
147
|
|
|
|
148
|
7 |
|
if (array_key_exists('pagination', $result['meta'])) { |
149
|
3 |
|
$result['links'] = $result['meta']['pagination']['links']; |
150
|
3 |
|
unset($result['meta']['pagination']['links']); |
151
|
|
|
} |
152
|
|
|
|
153
|
7 |
|
return $result; |
154
|
|
|
} |
155
|
|
|
|
156
|
2 |
|
public function null(): array |
157
|
|
|
{ |
158
|
|
|
return [ |
159
|
2 |
|
'data' => null, |
160
|
|
|
]; |
161
|
|
|
} |
162
|
|
|
|
163
|
36 |
|
public function includedData(ResourceInterface $resource, array $data): array |
164
|
|
|
{ |
165
|
36 |
|
list($serializedData, $linkedIds) = $this->pullOutNestedIncludedData($data); |
166
|
|
|
|
167
|
36 |
|
foreach ($data as $value) { |
168
|
36 |
|
foreach ($value as $includeObject) { |
169
|
22 |
|
if ($this->isNull($includeObject) || $this->isEmpty($includeObject)) { |
170
|
4 |
|
continue; |
171
|
|
|
} |
172
|
|
|
|
173
|
20 |
|
$includeObjects = $this->createIncludeObjects($includeObject); |
174
|
20 |
|
list($serializedData, $linkedIds) = $this->serializeIncludedObjectsWithCacheKey($includeObjects, $linkedIds, $serializedData); |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
178
|
36 |
|
return empty($serializedData) ? [] : ['included' => $serializedData]; |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
/** |
182
|
|
|
* Indicates if includes should be side-loaded. |
183
|
|
|
* |
184
|
|
|
* @return bool |
185
|
|
|
*/ |
186
|
37 |
|
public function sideloadIncludes() |
187
|
|
|
{ |
188
|
37 |
|
return true; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* @param array $data |
193
|
|
|
* @param array $includedData |
194
|
|
|
* |
195
|
|
|
* @return array |
196
|
|
|
*/ |
197
|
36 |
|
public function injectData($data, $includedData): array |
198
|
|
|
{ |
199
|
36 |
|
$relationships = $this->parseRelationships($includedData); |
200
|
|
|
|
201
|
36 |
|
if (!empty($relationships)) { |
202
|
22 |
|
$data = $this->fillRelationships($data, $relationships); |
203
|
|
|
} |
204
|
|
|
|
205
|
36 |
|
return $data; |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* Hook to manipulate the final sideloaded includes. |
210
|
|
|
* The JSON API specification does not allow the root object to be included |
211
|
|
|
* into the sideloaded `included`-array. We have to make sure it is |
212
|
|
|
* filtered out, in case some object links to the root object in a |
213
|
|
|
* relationship. |
214
|
|
|
* |
215
|
|
|
* @param array $includedData |
216
|
|
|
* @param array $data |
217
|
|
|
* |
218
|
|
|
* @return array |
219
|
|
|
*/ |
220
|
36 |
|
public function filterIncludes($includedData, $data): array |
221
|
|
|
{ |
222
|
36 |
|
if (!isset($includedData['included'])) { |
223
|
18 |
|
return $includedData; |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
// Create the RootObjects |
227
|
18 |
|
$this->createRootObjects($data); |
228
|
|
|
|
229
|
|
|
// Filter out the root objects |
230
|
18 |
|
$filteredIncludes = array_filter($includedData['included'], [$this, 'filterRootObject']); |
231
|
|
|
|
232
|
|
|
// Reset array indices |
233
|
18 |
|
$includedData['included'] = array_merge([], $filteredIncludes); |
234
|
|
|
|
235
|
18 |
|
return $includedData; |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
/** |
239
|
|
|
* Get the mandatory fields for the serializer |
240
|
|
|
* |
241
|
|
|
* @return array |
242
|
|
|
*/ |
243
|
4 |
|
public function getMandatoryFields() : array |
244
|
|
|
{ |
245
|
4 |
|
return ['id']; |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
/** |
249
|
|
|
* Filter function to delete root objects from array. |
250
|
|
|
* |
251
|
|
|
* @param array $object |
252
|
|
|
* |
253
|
|
|
* @return bool |
254
|
|
|
*/ |
255
|
18 |
|
protected function filterRootObject($object): bool |
256
|
|
|
{ |
257
|
18 |
|
return !$this->isRootObject($object); |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
/** |
261
|
|
|
* Set the root objects of the JSON API tree. |
262
|
|
|
* |
263
|
|
|
* @param array $objects |
264
|
|
|
*/ |
265
|
18 |
|
protected function setRootObjects(array $objects = []): void |
266
|
|
|
{ |
267
|
|
|
$this->rootObjects = array_map(function ($object) { |
268
|
18 |
|
return "{$object['type']}:{$object['id']}"; |
269
|
18 |
|
}, $objects); |
270
|
18 |
|
} |
271
|
|
|
|
272
|
|
|
/** |
273
|
|
|
* Determines whether an object is a root object of the JSON API tree. |
274
|
|
|
* |
275
|
|
|
* @param array $object |
276
|
|
|
* |
277
|
|
|
* @return bool |
278
|
|
|
*/ |
279
|
18 |
|
protected function isRootObject($object): bool |
280
|
|
|
{ |
281
|
18 |
|
$objectKey = "{$object['type']}:{$object['id']}"; |
282
|
18 |
|
return in_array($objectKey, $this->rootObjects); |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
/** |
286
|
|
|
* @param array|null $data |
287
|
|
|
* |
288
|
|
|
* @return bool |
289
|
|
|
*/ |
290
|
29 |
View Code Duplication |
protected function isCollection($data): bool |
|
|
|
|
291
|
|
|
{ |
292
|
29 |
|
if ($data === null) { |
293
|
|
|
return false; |
294
|
|
|
} |
295
|
|
|
|
296
|
29 |
|
return array_key_exists('data', $data) && |
297
|
29 |
|
array_key_exists(0, $data['data']); |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
/** |
301
|
|
|
* @param array|null $data |
302
|
|
|
* |
303
|
|
|
* @return bool |
304
|
|
|
*/ |
305
|
22 |
View Code Duplication |
protected function isNull($data): bool |
|
|
|
|
306
|
|
|
{ |
307
|
22 |
|
if ($data === null) { |
308
|
|
|
return true; |
309
|
|
|
} |
310
|
|
|
|
311
|
22 |
|
return array_key_exists('data', $data) && $data['data'] === null; |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* @param array|null $data |
316
|
|
|
* |
317
|
|
|
* @return bool |
318
|
|
|
*/ |
319
|
21 |
View Code Duplication |
protected function isEmpty($data): bool |
|
|
|
|
320
|
|
|
{ |
321
|
21 |
|
if ($data === null) { |
322
|
|
|
return true; |
323
|
|
|
} |
324
|
|
|
|
325
|
21 |
|
return array_key_exists('data', $data) && $data['data'] === []; |
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
/** |
329
|
|
|
* @param array $data |
330
|
|
|
* @param array $relationships |
331
|
|
|
* |
332
|
|
|
* @return array |
333
|
|
|
*/ |
334
|
22 |
|
protected function fillRelationships($data, $relationships): array |
335
|
|
|
{ |
336
|
22 |
|
if ($this->isCollection($data)) { |
337
|
9 |
|
foreach ($relationships as $key => $relationship) { |
338
|
9 |
|
$data = $this->fillRelationshipAsCollection($data, $relationship, $key); |
339
|
|
|
} |
340
|
|
|
} else { // Single resource |
341
|
15 |
|
foreach ($relationships as $key => $relationship) { |
342
|
15 |
|
$data = $this->fillRelationshipAsSingleResource($data, $relationship, $key); |
343
|
|
|
} |
344
|
|
|
} |
345
|
|
|
|
346
|
22 |
|
return $data; |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
/** |
350
|
|
|
* @param array $includedData |
351
|
|
|
* |
352
|
|
|
* @return array |
353
|
|
|
*/ |
354
|
36 |
|
protected function parseRelationships($includedData): array |
355
|
|
|
{ |
356
|
36 |
|
$relationships = []; |
357
|
|
|
|
358
|
36 |
|
foreach ($includedData as $key => $inclusion) { |
359
|
36 |
|
foreach ($inclusion as $includeKey => $includeObject) { |
360
|
22 |
|
$relationships = $this->buildRelationships($includeKey, $relationships, $includeObject, $key); |
361
|
22 |
|
if (isset($includedData[0][$includeKey]['meta'])) { |
362
|
1 |
|
$relationships[$includeKey][0]['meta'] = $includedData[0][$includeKey]['meta']; |
363
|
|
|
} |
364
|
|
|
} |
365
|
|
|
} |
366
|
|
|
|
367
|
36 |
|
return $relationships; |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
/** |
371
|
|
|
* @param array $data |
372
|
|
|
* |
373
|
|
|
* @return integer |
374
|
|
|
*/ |
375
|
37 |
|
protected function getIdFromData(array $data): int |
376
|
|
|
{ |
377
|
37 |
|
if (!array_key_exists('id', $data)) { |
378
|
1 |
|
throw new InvalidArgumentException( |
379
|
1 |
|
'JSON API resource objects MUST have a valid id' |
380
|
|
|
); |
381
|
|
|
} |
382
|
36 |
|
return $data['id']; |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* Keep all sideloaded inclusion data on the top level. |
387
|
|
|
* |
388
|
|
|
* @param array $data |
389
|
|
|
* |
390
|
|
|
* @return array |
391
|
|
|
*/ |
392
|
36 |
|
protected function pullOutNestedIncludedData(array $data): array |
393
|
|
|
{ |
394
|
36 |
|
$includedData = []; |
395
|
36 |
|
$linkedIds = []; |
396
|
|
|
|
397
|
36 |
|
foreach ($data as $value) { |
398
|
36 |
|
foreach ($value as $includeObject) { |
399
|
22 |
|
if (isset($includeObject['included'])) { |
400
|
4 |
|
list($includedData, $linkedIds) = $this->serializeIncludedObjectsWithCacheKey($includeObject['included'], $linkedIds, $includedData); |
401
|
|
|
} |
402
|
|
|
} |
403
|
|
|
} |
404
|
|
|
|
405
|
36 |
|
return [$includedData, $linkedIds]; |
406
|
|
|
} |
407
|
|
|
|
408
|
|
|
/** |
409
|
|
|
* Whether or not the serializer should include `links` for resource objects. |
410
|
|
|
* |
411
|
|
|
* @return bool |
412
|
|
|
*/ |
413
|
36 |
|
protected function shouldIncludeLinks(): bool |
414
|
|
|
{ |
415
|
36 |
|
return $this->baseUrl !== null; |
416
|
|
|
} |
417
|
|
|
|
418
|
|
|
/** |
419
|
|
|
* Check if the objects are part of a collection or not |
420
|
|
|
* |
421
|
|
|
* @param array $includeObject |
422
|
|
|
* |
423
|
|
|
* @return array |
424
|
|
|
*/ |
425
|
20 |
|
private function createIncludeObjects($includeObject): array |
426
|
|
|
{ |
427
|
20 |
|
if ($this->isCollection($includeObject)) { |
428
|
11 |
|
$includeObjects = $includeObject['data']; |
429
|
|
|
|
430
|
11 |
|
return $includeObjects; |
431
|
|
|
} else { |
432
|
13 |
|
$includeObjects = [$includeObject['data']]; |
433
|
|
|
|
434
|
13 |
|
return $includeObjects; |
435
|
|
|
} |
436
|
|
|
} |
437
|
|
|
|
438
|
|
|
/** |
439
|
|
|
* Sets the RootObjects, either as collection or not. |
440
|
|
|
* |
441
|
|
|
* @param array $data |
442
|
|
|
*/ |
443
|
18 |
|
private function createRootObjects(array $data): void |
444
|
|
|
{ |
445
|
18 |
|
if ($this->isCollection($data)) { |
446
|
8 |
|
$this->setRootObjects($data['data']); |
447
|
|
|
} else { |
448
|
10 |
|
$this->setRootObjects([$data['data']]); |
449
|
|
|
} |
450
|
18 |
|
} |
451
|
|
|
|
452
|
9 |
|
private function fillRelationshipAsCollection($data, $relationship, $key): array |
453
|
|
|
{ |
454
|
9 |
|
foreach ($relationship as $index => $relationshipData) { |
455
|
9 |
|
$data['data'][$index]['relationships'][$key] = $relationshipData; |
456
|
|
|
} |
457
|
|
|
|
458
|
9 |
|
return $data; |
459
|
|
|
} |
460
|
|
|
|
461
|
15 |
|
private function fillRelationshipAsSingleResource($data, $relationship, $key): array |
462
|
|
|
{ |
463
|
15 |
|
$data['data']['relationships'][$key] = $relationship[0]; |
464
|
|
|
|
465
|
15 |
|
return $data; |
466
|
|
|
} |
467
|
|
|
|
468
|
22 |
|
private function buildRelationships(string $includeKey, array $relationships, array $includeObject, string $key): array |
469
|
|
|
{ |
470
|
22 |
|
$relationships = $this->addIncludeKeyToRelationsIfNotSet($includeKey, $relationships); |
471
|
|
|
|
472
|
22 |
|
if ($this->isNull($includeObject)) { |
473
|
2 |
|
$relationship = $this->null(); |
474
|
21 |
|
} elseif ($this->isEmpty($includeObject)) { |
475
|
|
|
$relationship = [ |
476
|
2 |
|
'data' => [], |
477
|
|
|
]; |
478
|
20 |
|
} elseif (! empty($includeObject) && $this->isCollection($includeObject)) { |
479
|
11 |
|
$relationship = ['data' => []]; |
480
|
11 |
|
$relationship = $this->addIncludedDataToRelationship($includeObject, $relationship); |
481
|
|
|
} else { |
482
|
|
|
$relationship = [ |
483
|
|
|
'data' => [ |
484
|
13 |
|
'type' => $includeObject['data']['type'], |
485
|
13 |
|
'id' => $includeObject['data']['id'], |
486
|
|
|
], |
487
|
|
|
]; |
488
|
|
|
} |
489
|
|
|
|
490
|
22 |
|
$relationships[$includeKey][$key] = $relationship; |
491
|
|
|
|
492
|
22 |
|
return $relationships; |
493
|
|
|
} |
494
|
|
|
|
495
|
22 |
|
private function addIncludeKeyToRelationsIfNotSet(string $includeKey, array $relationships): array |
496
|
|
|
{ |
497
|
22 |
|
if (!array_key_exists($includeKey, $relationships)) { |
498
|
22 |
|
$relationships[$includeKey] = []; |
499
|
22 |
|
return $relationships; |
500
|
|
|
} |
501
|
|
|
|
502
|
9 |
|
return $relationships; |
503
|
|
|
} |
504
|
|
|
|
505
|
|
|
/** |
506
|
|
|
* @param array $includeObject |
507
|
|
|
* @param array $relationship |
508
|
|
|
* |
509
|
|
|
* @return array |
510
|
|
|
*/ |
511
|
11 |
|
private function addIncludedDataToRelationship(array $includeObject, array $relationship) : array |
512
|
|
|
{ |
513
|
11 |
|
foreach ($includeObject['data'] as $object) { |
514
|
11 |
|
$relationship['data'][] = [ |
515
|
11 |
|
'type' => $object['type'], |
516
|
11 |
|
'id' => $object['id'], |
517
|
|
|
]; |
518
|
|
|
} |
519
|
|
|
|
520
|
11 |
|
return $relationship; |
521
|
|
|
} |
522
|
|
|
|
523
|
35 |
|
public function injectAvailableIncludeData($data, $availableIncludes): array |
524
|
|
|
{ |
525
|
35 |
|
if (!$this->shouldIncludeLinks()) { |
526
|
24 |
|
return $data; |
527
|
|
|
} |
528
|
|
|
|
529
|
11 |
|
if ($this->isCollection($data)) { |
530
|
|
|
$data['data'] = array_map(function ($resource) use ($availableIncludes) { |
531
|
7 |
|
foreach ($availableIncludes as $relationshipKey) { |
532
|
7 |
|
$resource = $this->addRelationshipLinks($resource, $relationshipKey); |
533
|
|
|
} |
534
|
7 |
|
return $resource; |
535
|
7 |
|
}, $data['data']); |
536
|
|
|
} else { |
537
|
6 |
|
foreach ($availableIncludes as $relationshipKey) { |
538
|
6 |
|
$data['data'] = $this->addRelationshipLinks($data['data'], $relationshipKey); |
539
|
|
|
} |
540
|
|
|
} |
541
|
|
|
|
542
|
11 |
|
return $data; |
543
|
|
|
} |
544
|
|
|
|
545
|
11 |
|
private function addRelationshipLinks(array $resource, string $relationshipKey): array |
546
|
|
|
{ |
547
|
11 |
|
if (!isset($resource['relationships']) || !isset($resource['relationships'][$relationshipKey])) { |
548
|
11 |
|
$resource['relationships'][$relationshipKey] = []; |
549
|
|
|
} |
550
|
|
|
|
551
|
11 |
|
$resource['relationships'][$relationshipKey] = array_merge( |
552
|
|
|
[ |
553
|
|
|
'links' => [ |
554
|
11 |
|
'self' => "{$this->baseUrl}/{$resource['type']}/{$resource['id']}/relationships/{$relationshipKey}", |
555
|
11 |
|
'related' => "{$this->baseUrl}/{$resource['type']}/{$resource['id']}/{$relationshipKey}", |
556
|
|
|
] |
557
|
|
|
], |
558
|
11 |
|
$resource['relationships'][$relationshipKey] |
559
|
|
|
); |
560
|
|
|
|
561
|
11 |
|
return $resource; |
562
|
|
|
} |
563
|
|
|
|
564
|
20 |
|
private function serializeIncludedObjectsWithCacheKey(array $includeObjects, array $linkedIds, array $serializedData): array |
565
|
|
|
{ |
566
|
20 |
|
foreach ($includeObjects as $object) { |
567
|
20 |
|
$includeType = $object['type']; |
568
|
20 |
|
$includeId = $object['id']; |
569
|
20 |
|
$cacheKey = "$includeType:$includeId"; |
570
|
20 |
|
if (!array_key_exists($cacheKey, $linkedIds)) { |
571
|
20 |
|
$serializedData[] = $object; |
572
|
20 |
|
$linkedIds[$cacheKey] = $object; |
573
|
|
|
} |
574
|
|
|
} |
575
|
20 |
|
return [$serializedData, $linkedIds]; |
576
|
|
|
} |
577
|
|
|
|
578
|
36 |
|
private function areResourceLinksSet($resource): bool |
579
|
|
|
{ |
580
|
36 |
|
return isset($resource['data']['attributes']['links'])?: false; |
581
|
|
|
} |
582
|
|
|
|
583
|
36 |
|
private function isResourceMetaSet($resource): bool |
584
|
|
|
{ |
585
|
36 |
|
return isset($resource['data']['attributes']['meta'])?: false; |
586
|
|
|
} |
587
|
|
|
|
588
|
36 |
|
private function isDataAttributesEmpty($resource) : bool |
589
|
|
|
{ |
590
|
36 |
|
return empty($resource['data']['attributes'])?: false; |
591
|
|
|
} |
592
|
|
|
} |
593
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.