Skip to content

Commit ec52893

Browse files
committed
Refactor Serializer to improve readability
1 parent b791f39 commit ec52893

1 file changed

Lines changed: 131 additions & 103 deletions

File tree

src/Serializer.php

Lines changed: 131 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
use Closure;
66
use RuntimeException;
7-
use Tobyz\JsonApiServer\Endpoint\ProvidesResourceLinks;
87
use Tobyz\JsonApiServer\Schema\Field\Field;
98
use Tobyz\JsonApiServer\Schema\Field\Relationship;
109

@@ -48,90 +47,11 @@ private function addToMap(Context $context): array
4847

4948
$key = $this->key($type = $resource->type(), $id = $context->id($resource, $model));
5049

51-
if (!isset($this->map[$key])) {
52-
$this->map[$key] = [
53-
'type' => $type,
54-
'id' => $id,
55-
];
56-
57-
static $linkFieldsCache = [];
58-
59-
if (!isset($linkFieldsCache[$type])) {
60-
foreach ($context->api->getResourceCollections($type) as $collection) {
61-
$collectionContext = $context->withCollection($collection);
62-
63-
foreach ($context->endpoints($collection) as $endpoint) {
64-
if ($endpoint instanceof ProvidesResourceLinks) {
65-
foreach ($endpoint->resourceLinks($collectionContext) as $field) {
66-
$linkFieldsCache[$type][$field->name] ??= [$field, $collection];
67-
}
68-
}
69-
}
70-
}
71-
}
72-
73-
foreach ($linkFieldsCache[$type] ?? [] as [$field, $collection]) {
74-
$linkContext = $context->withCollection($collection)->withField($field);
75-
76-
if (!$field->isVisible($linkContext)) {
77-
continue;
78-
}
79-
80-
$value = $field->getValue($linkContext);
81-
82-
$this->resolveLinkValue($key, $field, $linkContext, $value);
83-
}
84-
}
85-
86-
foreach ($context->sparseFields($resource) as $field) {
87-
if (in_array($field, $this->processedFields[$key] ?? [])) {
88-
continue;
89-
}
90-
91-
$this->processedFields[$key][] = $field;
92-
93-
$fieldContext = $context
94-
->withField($field)
95-
->withInclude($context->include[$field->name] ?? null);
96-
97-
if (!$field->isVisible($fieldContext)) {
98-
continue;
99-
}
100-
101-
$value = $field->getValue($fieldContext);
102-
103-
$this->resolveFieldValue($key, $field, $fieldContext, $value);
104-
}
105-
106-
foreach ($context->meta($resource) as $field) {
107-
if (
108-
array_key_exists($field->name, $this->map[$key]['meta'] ?? []) ||
109-
!$field->isVisible($metaContext = $context->withField($field))
110-
) {
111-
continue;
112-
}
113-
114-
$value = $field->getValue($metaContext);
115-
116-
$this->resolveMetaValue($key, $field, $metaContext, $value);
117-
}
118-
119-
foreach ($context->resourceMeta[$model] ?? [] as $k => $v) {
120-
$this->map[$key]['meta'][$k] = $v;
121-
}
122-
123-
foreach ($context->links($resource) as $link) {
124-
if (
125-
array_key_exists($link->name, $this->map[$key]['links'] ?? []) ||
126-
!$link->isVisible($linkContext = $context->withField($link))
127-
) {
128-
continue;
129-
}
130-
131-
$value = $link->getValue($linkContext);
132-
133-
$this->resolveLinkValue($key, $link, $linkContext, $value);
134-
}
50+
$this->initializeResource($key, $type, $id, $context);
51+
$this->serializeFields($key, $context);
52+
$this->serializeMeta($key, $context);
53+
$this->mergeResourceMeta($key, $context);
54+
$this->serializeLinks($key, $context);
13555

13656
return $this->map[$key];
13757
}
@@ -147,14 +67,7 @@ private function resolveFieldValue(
14767
Context $context,
14868
mixed $value,
14969
): void {
150-
if ($value instanceof Closure) {
151-
$this->deferred[] = fn() => $this->resolveFieldValue($key, $field, $context, $value());
152-
} elseif (
153-
($value = $field->serializeValue($value, $context)) ||
154-
!$field instanceof Relationship
155-
) {
156-
set_value($this->map[$key], $field, $value);
157-
}
70+
$this->resolveValue($value, fn($value) => $this->writeFieldValue($key, $field, $context, $value));
15871
}
15972

16073
private function resolveMetaValue(
@@ -163,11 +76,10 @@ private function resolveMetaValue(
16376
Context $context,
16477
mixed $value,
16578
): void {
166-
if ($value instanceof Closure) {
167-
$this->deferred[] = fn() => $this->resolveMetaValue($key, $field, $context, $value());
168-
} else {
169-
$this->map[$key]['meta'][$field->name] = $field->serializeValue($value, $context);
170-
}
79+
$this->resolveValue(
80+
$value,
81+
fn($value) => $this->map[$key]['meta'][$field->name] = $field->serializeValue($value, $context),
82+
);
17183
}
17284

17385
private function resolveLinkValue(
@@ -176,11 +88,10 @@ private function resolveLinkValue(
17688
Context $context,
17789
mixed $value,
17890
): void {
179-
if ($value instanceof Closure) {
180-
$this->deferred[] = fn() => $this->resolveLinkValue($key, $field, $context, $value());
181-
} else {
182-
$this->map[$key]['links'][$field->name] = $field->serializeValue($value, $context);
183-
}
91+
$this->resolveValue(
92+
$value,
93+
fn($value) => $this->map[$key]['links'][$field->name] = $field->serializeValue($value, $context),
94+
);
18495
}
18596

18697
/**
@@ -207,6 +118,102 @@ public function addIncluded(Context $context): array
207118
];
208119
}
209120

121+
private function initializeResource(
122+
string $key,
123+
string $type,
124+
string $id,
125+
Context $context,
126+
): void {
127+
if (isset($this->map[$key])) {
128+
return;
129+
}
130+
131+
$this->map[$key] = [
132+
'type' => $type,
133+
'id' => $id,
134+
];
135+
136+
foreach ($context->resourceLinkDefinitions() as [$field, $collection]) {
137+
$linkContext = $context->withCollection($collection)->withField($field);
138+
139+
if (!$field->isVisible($linkContext)) {
140+
continue;
141+
}
142+
143+
$this->resolveLinkValue($key, $field, $linkContext, $field->getValue($linkContext));
144+
}
145+
}
146+
147+
private function serializeFields(string $key, Context $context): void
148+
{
149+
foreach ($context->sparseFields($context->resource) as $field) {
150+
if ($this->fieldProcessed($key, $field)) {
151+
continue;
152+
}
153+
154+
$fieldContext = $context
155+
->withField($field)
156+
->withInclude($context->include[$field->name] ?? null);
157+
158+
if (!$field->isVisible($fieldContext)) {
159+
continue;
160+
}
161+
162+
$this->resolveFieldValue($key, $field, $fieldContext, $field->getValue($fieldContext));
163+
}
164+
}
165+
166+
private function serializeMeta(string $key, Context $context): void
167+
{
168+
foreach ($context->meta($context->resource) as $field) {
169+
if (array_key_exists($field->name, $this->map[$key]['meta'] ?? [])) {
170+
continue;
171+
}
172+
173+
$metaContext = $context->withField($field);
174+
175+
if (!$field->isVisible($metaContext)) {
176+
continue;
177+
}
178+
179+
$this->resolveMetaValue($key, $field, $metaContext, $field->getValue($metaContext));
180+
}
181+
}
182+
183+
private function mergeResourceMeta(string $key, Context $context): void
184+
{
185+
foreach ($context->resourceMeta[$context->model] ?? [] as $name => $value) {
186+
$this->map[$key]['meta'][$name] = $value;
187+
}
188+
}
189+
190+
private function serializeLinks(string $key, Context $context): void
191+
{
192+
foreach ($context->links($context->resource) as $field) {
193+
if (array_key_exists($field->name, $this->map[$key]['links'] ?? [])) {
194+
continue;
195+
}
196+
197+
$linkContext = $context->withField($field);
198+
199+
if (!$field->isVisible($linkContext)) {
200+
continue;
201+
}
202+
203+
$this->resolveLinkValue($key, $field, $linkContext, $field->getValue($linkContext));
204+
}
205+
}
206+
207+
private function fieldProcessed(string $key, Field $field): bool
208+
{
209+
if (in_array($field, $this->processedFields[$key] ?? [])) {
210+
return true;
211+
}
212+
213+
$this->processedFields[$key][] = $field;
214+
215+
return false;
216+
}
210217
private function resolveDeferred(): void
211218
{
212219
$i = 0;
@@ -221,4 +228,25 @@ private function resolveDeferred(): void
221228
}
222229
}
223230
}
231+
232+
private function resolveValue(mixed $value, callable $resolve): void
233+
{
234+
if ($value instanceof Closure) {
235+
$this->deferred[] = fn() => $resolve($value());
236+
return;
237+
}
238+
239+
$resolve($value);
240+
}
241+
242+
private function writeFieldValue(
243+
string $key,
244+
Field $field,
245+
Context $context,
246+
mixed $value,
247+
): void {
248+
if (($value = $field->serializeValue($value, $context)) || !$field instanceof Relationship) {
249+
set_value($this->map[$key], $field, $value);
250+
}
251+
}
224252
}

0 commit comments

Comments
 (0)