Passed
Pull Request — master (#106)
by Christoffer
02:26
created

GraphQLException::getExtensions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Digia\GraphQL\Error;
4
5
use Digia\GraphQL\Language\Node\NodeInterface;
6
use Digia\GraphQL\Language\Source;
7
use Digia\GraphQL\Language\SourceLocation;
8
9
/**
10
 * An GraphQLException describes an exception thrown during the execute
11
 * phase of performing a GraphQL operation. In addition to a message
12
 * and stack trace, it also includes information about the locations in a
13
 * GraphQL document and/or execution result that correspond to the Error.
14
 */
15
class GraphQLException extends AbstractException
16
{
17
18
    /**
19
     * An array of { line, column } locations within the source GraphQL document
20
     * which correspond to this error.
21
     *
22
     * Errors during validation often contain multiple locations, for example to
23
     * point out two things with the same name. Errors during execution include a
24
     * single location, the field which produced the error.
25
     *
26
     * @var array|null
27
     */
28
    protected $locations;
29
30
    /**
31
     * An array describing the JSON-path into the execution response which
32
     * corresponds to this error. Only included for errors during execution.
33
     *
34
     * @var string[]|null
35
     */
36
    protected $path;
37
38
    /**
39
     * An array of GraphQL AST Nodes corresponding to this error.
40
     *
41
     * @var NodeInterface[]|null
42
     */
43
    protected $nodes;
44
45
    /**
46
     * The source GraphQL document for the first location of this error.
47
     *
48
     * Note that if this Error represents more than one node, the source may not
49
     * represent nodes after the first node.
50
     *
51
     * @var Source|null
52
     */
53
    protected $source;
54
55
    /**
56
     * An array of character offsets within the source GraphQL document
57
     * which correspond to this error.
58
     *
59
     * @var int[]|null
60
     */
61
    protected $positions;
62
63
    /**
64
     * Extension fields to add to the formatted error.
65
     *
66
     * @var \Exception|null
67
     */
68
    protected $originalException;
69
70
    /**
71
     * ExecutionException constructor.
72
     *
73
     * @param string          $message
74
     * @param array|null      $nodes
75
     * @param Source|null     $source
76
     * @param array|null      $positions
77
     * @param array|null      $path
78
     * @param \Exception|null $originalException
79
     */
80
    public function __construct(
81
        string $message,
82
        ?array $nodes = null,
83
        ?Source $source = null,
84
        ?array $positions = null,
85
        ?array $path = null,
86
        ?\Exception $originalException = null
87
    ) {
88
        parent::__construct($message);
89
90
        $this->resolveNodes($nodes);
91
        $this->resolveSource($source);
92
        $this->resolvePositions($positions);
93
        $this->resolveLocations($positions, $source);
94
95
        $this->path              = $path;
96
        $this->originalException = $originalException;
97
    }
98
99
    /**
100
     * @return NodeInterface[]
101
     */
102
    public function getNodes(): ?array
103
    {
104
        return $this->nodes;
105
    }
106
107
    /**
108
     * @return bool
109
     */
110
    public function hasSource(): bool
111
    {
112
        return null !== $this->source;
113
    }
114
115
    /**
116
     * @return Source|null
117
     */
118
    public function getSource(): ?Source
119
    {
120
        return $this->source;
121
    }
122
123
    /**
124
     * @return int[]|null
125
     */
126
    public function getPositions(): ?array
127
    {
128
        return $this->positions;
129
    }
130
131
    /**
132
     * @return bool
133
     */
134
    public function hasLocations(): bool
135
    {
136
        return !empty($this->locations);
137
    }
138
139
    /**
140
     * @return array|null
141
     */
142
    public function getLocations(): ?array
143
    {
144
        return $this->locations;
145
    }
146
147
    /**
148
     * @return array|null
149
     */
150
    public function getLocationsAsArray(): ?array
151
    {
152
        return !empty($this->locations) ? array_map(function (SourceLocation $location) {
153
            return $location->toArray();
154
        }, $this->locations) : null;
155
    }
156
157
    /**
158
     * @return array|null
159
     */
160
    public function getPath(): ?array
161
    {
162
        return $this->path;
163
    }
164
165
    /**
166
     * @return \Exception|null
167
     */
168
    public function getOriginalException(): ?\Exception
169
    {
170
        return $this->originalException;
171
    }
172
173
    /**
174
     * @return null|string
175
     */
176
    public function getOriginalErrorMessage(): ?string
177
    {
178
        return null !== $this->originalException ? $this->originalException->getMessage() : null;
179
    }
180
181
    /**
182
     * @param array|null $nodes
183
     * @return $this
184
     */
185
    protected function resolveNodes(?array $nodes)
186
    {
187
        $this->nodes = is_array($nodes)
188
            ? (!empty($nodes) ? $nodes : null)
189
            : (null !== $nodes ? [$nodes] : null);
0 ignored issues
show
introduced by
The condition null !== $nodes is always false.
Loading history...
190
191
        return $this;
192
    }
193
194
    /**
195
     * @param Source|null $source
196
     * @return $this
197
     */
198
    protected function resolveSource(?Source $source)
199
    {
200
        if (null === $source && !empty($this->nodes)) {
201
            $firstNode = $this->nodes[0];
202
            $location  = null !== $firstNode ? $firstNode->getLocation() : null;
203
            $source    = null !== $location ? $location->getSource() : null;
204
        }
205
206
        $this->source = $source;
207
208
        return $this;
209
    }
210
211
    /**
212
     * @param array|null $positions
213
     * @return $this
214
     */
215
    protected function resolvePositions(?array $positions)
216
    {
217
        if (null === $positions && !empty($this->nodes)) {
218
            $positions = array_reduce($this->nodes, function (array $list, NodeInterface $node) {
219
                $location = $node->getLocation();
220
                if (null !== $location) {
221
                    $list[] = $location->getStart();
222
                }
223
                return $list;
224
            }, []);
225
        }
226
227
        if (null !== $positions && empty($positions)) {
228
            $positions = null;
229
        }
230
231
        $this->positions = $positions;
232
233
        return $this;
234
    }
235
236
    /**
237
     * @param array|null  $positions
238
     * @param Source|null $source
239
     * @return $this
240
     */
241
    protected function resolveLocations(?array $positions, ?Source $source)
242
    {
243
        if (null !== $positions && null !== $source) {
244
            $locations = array_map(function ($position) use ($source) {
245
                return SourceLocation::fromSource($source, $position);
246
            }, $positions);
247
        } elseif (!empty($this->nodes)) {
248
            $locations = array_reduce($this->nodes, function (array $list, NodeInterface $node) {
249
                $location = $node->getLocation();
250
                if (null !== $location) {
251
                    $list[] = SourceLocation::fromSource($location->getSource(), $location->getStart());
252
                }
253
                return $list;
254
            }, []);
255
        }
256
257
        if (isset($locations)) {
258
            $this->locations = $locations;
259
        }
260
261
        return $this;
262
    }
263
264
    /**
265
     * @inheritdoc
266
     */
267
    public function __toString(): string
268
    {
269
        return printError($this);
270
    }
271
}
272