-
-
Notifications
You must be signed in to change notification settings - Fork 963
Expand file tree
/
Copy pathCollectionNormalizer.php
More file actions
124 lines (104 loc) · 4.87 KB
/
CollectionNormalizer.php
File metadata and controls
124 lines (104 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<?php
/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace ApiPlatform\Hydra\Serializer;
use ApiPlatform\JsonLd\ContextBuilderInterface;
use ApiPlatform\JsonLd\Serializer\HydraPrefixTrait;
use ApiPlatform\JsonLd\Serializer\JsonLdContextTrait;
use ApiPlatform\Metadata\IriConverterInterface;
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
use ApiPlatform\Metadata\ResourceClassResolverInterface;
use ApiPlatform\Metadata\UrlGeneratorInterface;
use ApiPlatform\Serializer\AbstractCollectionNormalizer;
use ApiPlatform\State\Pagination\PaginatorInterface;
use ApiPlatform\State\Pagination\PartialPaginatorInterface;
/**
* This normalizer handles collections.
*
* @author Kevin Dunglas <dunglas@gmail.com>
* @author Samuel ROZE <samuel.roze@gmail.com>
*/
final class CollectionNormalizer extends AbstractCollectionNormalizer
{
use HydraOperationsTrait;
use HydraPrefixTrait;
use JsonLdContextTrait;
public const FORMAT = 'jsonld';
public const IRI_ONLY = 'iri_only';
public const PRESERVE_COLLECTION_KEYS = 'preserve_collection_keys';
private array $defaultContext = [
self::IRI_ONLY => false,
self::PRESERVE_COLLECTION_KEYS => false,
];
public function __construct(private readonly ContextBuilderInterface $contextBuilder, ResourceClassResolverInterface $resourceClassResolver, private readonly IriConverterInterface $iriConverter, array $defaultContext = [], private readonly ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null)
{
$this->defaultContext = array_merge($this->defaultContext, $defaultContext);
parent::__construct($resourceClassResolver, '');
}
/**
* Gets the pagination data.
*/
protected function getPaginationData(iterable $object, array $context = []): array
{
$resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class']);
$hydraPrefix = $this->getHydraPrefix($context + $this->defaultContext);
// This adds "jsonld_has_context" by reference, we moved the code to this class.
// To follow a note I wrote in the ItemNormalizer, we need to change the JSON-LD context generation as it is more complicated then it should.
$data = $this->addJsonLdContext($this->contextBuilder, $resourceClass, $context);
$data['@id'] = $this->iriConverter->getIriFromResource($resourceClass, UrlGeneratorInterface::ABS_PATH, $context['operation'] ?? null, $context);
$data['@type'] = $hydraPrefix.'Collection';
if ($object instanceof PaginatorInterface) {
$data[$hydraPrefix.'totalItems'] = $object->getTotalItems();
}
if (\is_array($object) || ($object instanceof \Countable && !$object instanceof PartialPaginatorInterface)) {
$data[$hydraPrefix.'totalItems'] = \count($object);
}
if (null !== $this->resourceMetadataCollectionFactory && ($context['hydra_operations'] ?? $this->defaultContext['hydra_operations'] ?? false)) {
$allHydraOperations = $this->getHydraOperationsFromResourceMetadatas(
$resourceClass,
true,
$hydraPrefix
);
if (!empty($allHydraOperations)) {
$data[$hydraPrefix.'operation'] = $allHydraOperations;
}
}
return $data;
}
/**
* Gets items data.
*/
protected function getItemsData(iterable $object, ?string $format = null, array $context = []): array
{
$hydraPrefix = $this->getHydraPrefix($context + $this->defaultContext);
$data = [$hydraPrefix.'member' => []];
$iriOnly = $context[self::IRI_ONLY] ?? $this->defaultContext[self::IRI_ONLY];
$preserveCollectionKey = $context[self::PRESERVE_COLLECTION_KEYS] ?? $this->defaultContext[self::PRESERVE_COLLECTION_KEYS];
foreach ($object as $key => $obj) {
if ($iriOnly) {
$normalizedItem = $this->iriConverter->getIriFromResource($obj, UrlGeneratorInterface::ABS_PATH, null, $context);
} else {
$normalizedItem = $this->normalizer->normalize($obj, $format, $context + ['jsonld_has_context' => true]);
}
if ($preserveCollectionKey) {
$data[$hydraPrefix.'member'][$key] = $normalizedItem;
} else {
$data[$hydraPrefix.'member'][] = $normalizedItem;
}
}
return $data;
}
protected function initContext(string $resourceClass, array $context): array
{
$context = parent::initContext($resourceClass, $context);
$context['api_collection_sub_level'] = true;
return $context;
}
}