Passed
Pull Request — master (#256)
by Sam
02:41
created

FieldsTrait::getFields()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Digia\GraphQL\Type\Definition;
4
5
use Digia\GraphQL\Error\InvariantException;
6
use function Digia\GraphQL\Type\isAssocArray;
7
use function Digia\GraphQL\Type\newField;
8
use function Digia\GraphQL\Type\resolveThunk;
9
use function Digia\GraphQL\Util\toString;
10
11
trait FieldsTrait
12
{
13
    /**
14
     * Fields can be defined either as an array or as a thunk.
15
     * Using thunks allows for cross-referencing of fields.
16
     *
17
     * @var array|callable
18
     */
19
    protected $rawFieldsOrThunk;
20
21
    /**
22
     * A key-value map over field names and their corresponding field instances.
23
     *
24
     * @var Field[]
25
     */
26
    protected $fieldMap;
27
28
    /**
29
     * @return null|string
30
     */
31
    abstract public function getName(): string;
32
33
    /**
34
     * @param string $fieldName
35
     * @return Field|null
36
     * @throws InvariantException
37
     */
38
    public function getField(string $fieldName): ?Field
39
    {
40
        return $this->getFields()[$fieldName] ?? null;
41
    }
42
43
    /**
44
     * @return Field[]
45
     * @throws InvariantException
46
     */
47
    public function getFields(): array
48
    {
49
        // Fields are built lazily to avoid concurrency issues.
50
        if (!isset($this->fieldMap)) {
51
            $this->fieldMap = $this->buildFieldMap($this->rawFieldsOrThunk);
52
        }
53
54
        return $this->fieldMap;
55
    }
56
57
    /**
58
     * @param array|callable $rawFieldsOrThunk
59
     * @return Field[]
60
     * @throws InvariantException
61
     */
62
    protected function buildFieldMap($rawFieldsOrThunk): array
63
    {
64
        $rawFields = resolveThunk($rawFieldsOrThunk);
65
66
        if (!isAssocArray($rawFields)) {
67
            throw new InvariantException(\sprintf(
68
                '%s fields must be an associative array with field names as keys or a ' .
69
                'callable which returns such an array.',
70
                $this->getName()
71
            ));
72
        }
73
74
        $fieldMap = [];
75
76
        foreach ($rawFields as $fieldName => $fieldConfig) {
77
            if (!\is_array($fieldConfig)) {
78
                throw new InvariantException(\sprintf('%s.%s field config must be an associative array.',
79
                    $this->getName(), $fieldName));
80
            }
81
82
            if (isset($fieldConfig['isDeprecated'])) {
83
                throw new InvariantException(\sprintf(
84
                    '%s.%s should provide "deprecationReason" instead of "isDeprecated".',
85
                    $this->getName(),
86
                    $fieldName
87
                ));
88
            }
89
90
            if (isset($fieldConfig['resolve']) && !\is_callable($fieldConfig['resolve'])) {
91
                throw new InvariantException(\sprintf(
92
                    '%s.%s field resolver must be a function if provided, but got: %s.',
93
                    $this->getName(),
94
                    $fieldName,
95
                    toString($fieldConfig['resolve'])
96
                ));
97
            }
98
99
            $fieldConfig['name']     = $fieldName;
100
            $fieldConfig['typeName'] = $this->getName();
101
102
            $fieldMap[$fieldName] = newField($fieldConfig);
103
        }
104
105
        return $fieldMap;
106
    }
107
}
108