Passed
Pull Request — master (#20)
by Christoffer
02:08
created

FieldsTrait   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 129
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 129
rs 10
c 0
b 0
f 0
wmc 11

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getFields() 0 5 1
A addField() 0 5 1
B defineFieldMap() 0 45 4
A setFields() 0 5 1
A defineFieldMapIfNecessary() 0 7 2
A addFields() 0 7 2
1
<?php
2
3
namespace Digia\GraphQL\Type\Definition;
4
5
use function Digia\GraphQL\Type\isAssocArray;
6
use function Digia\GraphQL\Type\isValidResolver;
7
use function Digia\GraphQL\Type\resolveThunk;
8
use function Digia\GraphQL\Util\invariant;
9
use function Digia\GraphQL\Util\toString;
10
11
trait FieldsTrait
12
{
13
14
    /**
15
     * @var array|callable
16
     */
17
    private $_fieldsThunk;
18
19
    /**
20
     * @var Field[]
21
     */
22
    private $_fieldMap = [];
23
24
    /**
25
     * @var bool
26
     */
27
    private $_isFieldMapDefined = false;
28
29
    /**
30
     * @param Field $field
31
     * @return $this
32
     * @throws \Exception
33
     */
34
    public function addField(Field $field)
35
    {
36
        $this->_fieldMap[$field->getName()] = $field;
37
38
        return $this;
39
    }
40
41
    /**
42
     * @param array $fields
43
     * @return $this
44
     * @throws \Exception
45
     */
46
    public function addFields(array $fields)
47
    {
48
        foreach ($fields as $field) {
49
            $this->addField($field);
50
        }
51
52
        return $this;
53
    }
54
55
    /**
56
     * @return Field[]
57
     * @throws \Exception
58
     */
59
    public function getFields(): array
60
    {
61
        $this->defineFieldMapIfNecessary();
62
63
        return $this->_fieldMap;
64
    }
65
66
    /**
67
     * @throws \Exception
68
     */
69
    protected function defineFieldMapIfNecessary(): void
70
    {
71
        // Fields are built lazily to avoid concurrency issues.
72
        if (!$this->_isFieldMapDefined) {
73
            $this->_fieldMap = array_merge($this->defineFieldMap($this->_fieldsThunk), $this->_fieldMap);
74
75
            $this->_isFieldMapDefined = true;
76
        }
77
    }
78
79
    /**
80
     * @param array|callable $fieldsThunk
81
     * @return $this
82
     */
83
    protected function setFields($fieldsThunk)
84
    {
85
        $this->_fieldsThunk = $fieldsThunk;
86
87
        return $this;
88
    }
89
90
    /**
91
     * @param mixed $fieldsThunk
92
     * @return array
93
     * @throws \Exception
94
     */
95
    protected function defineFieldMap($fieldsThunk): array
96
    {
97
        $fields = resolveThunk($fieldsThunk) ?: [];
98
99
        invariant(
100
            isAssocArray($fields),
101
            sprintf(
102
                '%s fields must be an associative array with field names as key or a callable which returns such an array.',
103
                $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

103
                $this->/** @scrutinizer ignore-call */ 
104
                       getName()
Loading history...
104
            )
105
        );
106
107
        $fieldMap = [];
108
109
        foreach ($fields as $fieldName => $fieldConfig) {
110
            invariant(
111
                is_array($fieldConfig),
112
                sprintf('%s.%s field config must be an array', $this->getName(), $fieldName)
113
            );
114
115
            invariant(
116
                !isset($fieldConfig['isDeprecated']),
117
                sprintf(
118
                    '%s.%s should provide "deprecationReason" instead of "isDeprecated".',
119
                    $this->getName(),
120
                    $fieldName
121
                )
122
            );
123
124
            if (isset($fieldConfig['resolve'])) {
125
                invariant(
126
                    isValidResolver($fieldConfig['resolve']),
127
                    sprintf(
128
                        '%s.%s field resolver must be a function if provided, but got: %s',
129
                        $this->getName(),
130
                        $fieldName,
131
                        toString($fieldConfig['resolve'])
132
                    )
133
                );
134
            }
135
136
            $fieldMap[$fieldName] = new Field(array_merge($fieldConfig, ['name' => $fieldName]));
137
        }
138
139
        return $fieldMap;
140
    }
141
142
}
143