Passed
Pull Request — master (#351)
by Kirill
02:55
created

FieldsTrait   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 100
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 33
dl 0
loc 100
rs 10
c 2
b 0
f 0
wmc 11

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getFields() 0 8 2
A hasField() 0 3 1
B buildFieldMap() 0 44 7
A getField() 0 3 1
1
<?php
2
3
namespace Digia\GraphQL\Type\Definition;
4
5
use Digia\GraphQL\Error\InvariantException;
6
use GraphQL\Contracts\TypeSystem\FieldInterface;
7
use function Digia\GraphQL\Type\isAssocArray;
8
use function Digia\GraphQL\Type\newField;
9
use function Digia\GraphQL\Type\resolveThunk;
10
use function Digia\GraphQL\Util\toString;
11
12
/**
13
 * @mixin FieldsAwareInterface
14
 */
15
trait FieldsTrait
16
{
17
    /**
18
     * Fields can be defined either as an array or as a thunk.
19
     * Using thunks allows for cross-referencing of fields.
20
     *
21
     * @var array|callable
22
     */
23
    protected $rawFieldsOrThunk;
24
25
    /**
26
     * A key-value map over field names and their corresponding field instances.
27
     *
28
     * @var Field[]
29
     */
30
    protected $fieldMap;
31
32
    /**
33
     * @param string $fieldName
34
     * @return Field|FieldInterface|null
35
     * @throws InvariantException
36
     */
37
    public function getField(string $fieldName): ?FieldInterface
38
    {
39
        return $this->getFields()[$fieldName] ?? null;
40
    }
41
42
    /**
43
     * @param string $fieldName
44
     * @return bool
45
     * @throws InvariantException
46
     */
47
    public function hasField(string $fieldName): bool
48
    {
49
        return $this->getField($fieldName) !== null;
50
    }
51
52
    /**
53
     * @return Field[]
54
     * @throws InvariantException
55
     */
56
    public function getFields(): array
57
    {
58
        // Fields are built lazily to avoid concurrency issues.
59
        if (!isset($this->fieldMap)) {
60
            $this->fieldMap = $this->buildFieldMap($this->rawFieldsOrThunk);
61
        }
62
63
        return $this->fieldMap;
64
    }
65
66
    /**
67
     * @param array|callable $rawFieldsOrThunk
68
     * @return Field[]
69
     * @throws InvariantException
70
     */
71
    protected function buildFieldMap($rawFieldsOrThunk): array
72
    {
73
        $rawFields = resolveThunk($rawFieldsOrThunk);
74
75
        if (!isAssocArray($rawFields)) {
76
            throw new InvariantException(\sprintf(
77
                '%s fields must be an associative array with field names as keys or a ' .
78
                'callable which returns such an array.',
79
                $this->getName()
0 ignored issues
show
Bug introduced by
It seems like getName() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

79
                $this->/** @scrutinizer ignore-call */ 
80
                       getName()
Loading history...
80
            ));
81
        }
82
83
        $fieldMap = [];
84
85
        foreach ($rawFields as $fieldName => $fieldConfig) {
86
            if (!\is_array($fieldConfig)) {
87
                throw new InvariantException(\sprintf('%s.%s field config must be an associative array.',
88
                    $this->getName(), $fieldName));
89
            }
90
91
            if (isset($fieldConfig['isDeprecated'])) {
92
                throw new InvariantException(\sprintf(
93
                    '%s.%s should provide "deprecationReason" instead of "isDeprecated".',
94
                    $this->getName(),
95
                    $fieldName
96
                ));
97
            }
98
99
            if (isset($fieldConfig['resolve']) && !\is_callable($fieldConfig['resolve'])) {
100
                throw new InvariantException(\sprintf(
101
                    '%s.%s field resolver must be a function if provided, but got: %s.',
102
                    $this->getName(),
103
                    $fieldName,
104
                    toString($fieldConfig['resolve'])
105
                ));
106
            }
107
108
            $fieldConfig['name']     = $fieldName;
109
            $fieldConfig['typeName'] = $this->getName();
110
111
            $fieldMap[$fieldName] = newField($fieldConfig);
112
        }
113
114
        return $fieldMap;
115
    }
116
}
117