Passed
Pull Request — master (#2959)
by Alan
04:10
created

SerializerContextBuilder::replaceIdKeys()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 7
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 12
rs 10
1
<?php
2
3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <[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
declare(strict_types=1);
13
14
namespace ApiPlatform\Core\GraphQl\Serializer;
15
16
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
17
use ApiPlatform\Core\Metadata\Resource\ResourceMetadata;
18
use GraphQL\Type\Definition\ResolveInfo;
19
20
/**
21
 * Builds the context used by the Symfony Serializer.
22
 *
23
 * @experimental
24
 *
25
 * @author Alan Poulain <[email protected]>
26
 */
27
final class SerializerContextBuilder implements SerializerContextBuilderInterface
28
{
29
    private $resourceMetadataFactory;
30
31
    public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory)
32
    {
33
        $this->resourceMetadataFactory = $resourceMetadataFactory;
34
    }
35
36
    public function create(?string $resourceClass, string $operationName, array $resolverContext): array
37
    {
38
        $resourceMetadata = $resourceClass ? $this->resourceMetadataFactory->create($resourceClass) : null;
39
40
        $normalizationContext = [
41
            'resource_class' => $resourceClass,
42
            'attributes' => $this->fieldsToAttributes($resourceMetadata, $resolverContext),
43
        ];
44
45
        if ($resourceMetadata) {
0 ignored issues
show
introduced by
$resourceMetadata is of type ApiPlatform\Core\Metadat...source\ResourceMetadata, thus it always evaluated to true.
Loading history...
46
            $normalizationContext = array_merge($resourceMetadata->getGraphqlAttribute($operationName, 'normalization_context', [], true), $normalizationContext);
47
        }
48
49
        return $normalizationContext;
50
    }
51
52
    /**
53
     * Retrieves fields, recursively replaces the "_id" key (the raw id) by "id" (the name of the property expected by the Serializer) and flattens edge and node structures (pagination).
54
     */
55
    private function fieldsToAttributes(?ResourceMetadata $resourceMetadata, array $context): array
56
    {
57
        /** @var ResolveInfo $info */
58
        $info = $context['info'];
59
        $fields = $info->getFieldSelection(PHP_INT_MAX);
60
61
        $attributes = $this->replaceIdKeys($fields['edges']['node'] ?? $fields);
62
63
        if ($context['is_mutation']) {
64
            if (!$resourceMetadata) {
65
                throw new \LogicException('ResourceMetadata should always exist for a mutation.');
66
            }
67
68
            $wrapFieldName = lcfirst($resourceMetadata->getShortName());
69
70
            return $attributes[$wrapFieldName] ?? [];
71
        }
72
73
        return $attributes;
74
    }
75
76
    private function replaceIdKeys(array $fields): array
77
    {
78
        foreach ($fields as $key => $value) {
79
            if ('_id' === $key) {
80
                $fields['id'] = $fields['_id'];
81
                unset($fields['_id']);
82
            } elseif (\is_array($fields[$key])) {
83
                $fields[$key] = $this->replaceIdKeys($fields[$key]);
84
            }
85
        }
86
87
        return $fields;
88
    }
89
}
90