Passed
Push — master ( 7cc72b...baad32 )
by Vladimir
10:39
created

GraphQL::executeQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 12
c 1
b 0
f 0
dl 0
loc 25
rs 9.8666
ccs 13
cts 13
cp 1
cc 1
nc 1
nop 8
crap 1

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQL;
6
7
use GraphQL\Error\Error;
8
use GraphQL\Executor\ExecutionResult;
9
use GraphQL\Executor\Executor;
10
use GraphQL\Executor\Promise\Adapter\SyncPromiseAdapter;
11
use GraphQL\Executor\Promise\Promise;
12
use GraphQL\Executor\Promise\PromiseAdapter;
13
use GraphQL\Executor\ReferenceExecutor;
14
use GraphQL\Experimental\Executor\CoroutineExecutor;
15
use GraphQL\Language\AST\DocumentNode;
16
use GraphQL\Language\Parser;
17
use GraphQL\Language\Source;
18
use GraphQL\Type\Definition\Directive;
19
use GraphQL\Type\Definition\ScalarType;
20
use GraphQL\Type\Definition\Type;
21
use GraphQL\Type\Schema as SchemaType;
22
use GraphQL\Validator\DocumentValidator;
23
use GraphQL\Validator\Rules\QueryComplexity;
24
use GraphQL\Validator\Rules\ValidationRule;
25
use function array_values;
26
use function trigger_error;
27
use const E_USER_DEPRECATED;
28
29
/**
30
 * This is the primary facade for fulfilling GraphQL operations.
31
 * See [related documentation](executing-queries.md).
32
 */
33
class GraphQL
34
{
35
    /**
36
     * Executes graphql query.
37
     *
38
     * More sophisticated GraphQL servers, such as those which persist queries,
39
     * may wish to separate the validation and execution phases to a static time
40
     * tooling step, and a server runtime step.
41
     *
42
     * Available options:
43
     *
44
     * schema:
45
     *    The GraphQL type system to use when validating and executing a query.
46
     * source:
47
     *    A GraphQL language formatted string representing the requested operation.
48
     * rootValue:
49
     *    The value provided as the first argument to resolver functions on the top
50
     *    level type (e.g. the query object type).
51
     * contextValue:
52
     *    The context value is provided as an argument to resolver functions after
53
     *    field arguments. It is used to pass shared information useful at any point
54
     *    during executing this query, for example the currently logged in user and
55
     *    connections to databases or other services.
56
     * variableValues:
57
     *    A mapping of variable name to runtime value to use for all variables
58
     *    defined in the requestString.
59
     * operationName:
60
     *    The name of the operation to use if requestString contains multiple
61
     *    possible operations. Can be omitted if requestString contains only
62
     *    one operation.
63
     * fieldResolver:
64
     *    A resolver function to use when one is not provided by the schema.
65
     *    If not provided, the default field resolver is used (which looks for a
66
     *    value on the source value with the field's name).
67
     * validationRules:
68
     *    A set of rules for query validation step. Default value is all available rules.
69
     *    Empty array would allow to skip query validation (may be convenient for persisted
70
     *    queries which are validated before persisting and assumed valid during execution)
71
     *
72
     * @param string|DocumentNode $source
73
     * @param mixed               $rootValue
74
     * @param mixed               $contextValue
75
     * @param mixed[]|null        $variableValues
76
     * @param ValidationRule[]    $validationRules
77
     *
78
     * @api
79
     */
80 86
    public static function executeQuery(
81
        SchemaType $schema,
82
        $source,
83
        $rootValue = null,
84
        $contextValue = null,
85
        $variableValues = null,
86
        ?string $operationName = null,
87
        ?callable $fieldResolver = null,
88
        ?array $validationRules = null
89
    ) : ExecutionResult {
90 86
        $promiseAdapter = new SyncPromiseAdapter();
91
92 86
        $promise = self::promiseToExecute(
93 86
            $promiseAdapter,
94 86
            $schema,
95 86
            $source,
96 86
            $rootValue,
97 86
            $contextValue,
98 86
            $variableValues,
99 86
            $operationName,
100 86
            $fieldResolver,
101 86
            $validationRules
102
        );
103
104 86
        return $promiseAdapter->wait($promise);
105
    }
106
107
    /**
108
     * Same as executeQuery(), but requires PromiseAdapter and always returns a Promise.
109
     * Useful for Async PHP platforms.
110
     *
111
     * @param string|DocumentNode   $source
112
     * @param mixed                 $rootValue
113
     * @param mixed                 $context
114
     * @param mixed[]|null          $variableValues
115
     * @param ValidationRule[]|null $validationRules
116
     *
117
     * @api
118
     */
119 111
    public static function promiseToExecute(
120
        PromiseAdapter $promiseAdapter,
121
        SchemaType $schema,
122
        $source,
123
        $rootValue = null,
124
        $context = null,
125
        $variableValues = null,
126
        ?string $operationName = null,
127
        ?callable $fieldResolver = null,
128
        ?array $validationRules = null
129
    ) : Promise {
130
        try {
131 111
            if ($source instanceof DocumentNode) {
132 22
                $documentNode = $source;
133
            } else {
134 89
                $documentNode = Parser::parse(new Source($source ?: '', 'GraphQL'));
135
            }
136
137
            // FIXME
138 110
            if (empty($validationRules)) {
139
                /** @var QueryComplexity $queryComplexity */
140 109
                $queryComplexity = DocumentValidator::getRule(QueryComplexity::class);
141 109
                $queryComplexity->setRawVariableValues($variableValues);
142
            } else {
143 3
                foreach ($validationRules as $rule) {
144 3
                    if (! ($rule instanceof QueryComplexity)) {
145 3
                        continue;
146
                    }
147
148 2
                    $rule->setRawVariableValues($variableValues);
149
                }
150
            }
151
152 110
            $validationErrors = DocumentValidator::validate($schema, $documentNode, $validationRules);
153
154 110
            if (! empty($validationErrors)) {
155 14
                return $promiseAdapter->createFulfilled(
156 14
                    new ExecutionResult(null, $validationErrors)
157
                );
158
            }
159
160 100
            return Executor::promiseToExecute(
161 100
                $promiseAdapter,
162 100
                $schema,
163 100
                $documentNode,
164 100
                $rootValue,
165 100
                $context,
166 100
                $variableValues,
167 100
                $operationName,
168 100
                $fieldResolver
169
            );
170 1
        } catch (Error $e) {
171 1
            return $promiseAdapter->createFulfilled(
172 1
                new ExecutionResult(null, [$e])
173
            );
174
        }
175
    }
176
177
    /**
178
     * @deprecated Use executeQuery()->toArray() instead
179
     *
180
     * @param string|DocumentNode $source
181
     * @param mixed               $rootValue
182
     * @param mixed               $contextValue
183
     * @param mixed[]|null        $variableValues
184
     *
185
     * @return Promise|mixed[]
186
     *
187
     * @codeCoverageIgnore
188
     */
189
    public static function execute(
190
        SchemaType $schema,
191
        $source,
192
        $rootValue = null,
193
        $contextValue = null,
194
        $variableValues = null,
195
        ?string $operationName = null
196
    ) {
197
        trigger_error(
198
            __METHOD__ . ' is deprecated, use GraphQL::executeQuery()->toArray() as a quick replacement',
199
            E_USER_DEPRECATED
200
        );
201
202
        $promiseAdapter = Executor::getPromiseAdapter();
203
        $result         = self::promiseToExecute(
204
            $promiseAdapter,
205
            $schema,
206
            $source,
207
            $rootValue,
208
            $contextValue,
209
            $variableValues,
210
            $operationName
211
        );
212
213
        if ($promiseAdapter instanceof SyncPromiseAdapter) {
214
            $result = $promiseAdapter->wait($result)->toArray();
215
        } else {
216
            $result = $result->then(static function (ExecutionResult $r) {
217
                return $r->toArray();
218
            });
219
        }
220
221
        return $result;
222
    }
223
224
    /**
225
     * @deprecated renamed to executeQuery()
226
     *
227
     * @param string|DocumentNode $source
228
     * @param mixed               $rootValue
229
     * @param mixed               $contextValue
230
     * @param mixed[]|null        $variableValues
231
     *
232
     * @return ExecutionResult|Promise
233
     *
234
     * @codeCoverageIgnore
235
     */
236
    public static function executeAndReturnResult(
237
        SchemaType $schema,
238
        $source,
239
        $rootValue = null,
240
        $contextValue = null,
241
        $variableValues = null,
242
        ?string $operationName = null
243
    ) {
244
        trigger_error(
245
            __METHOD__ . ' is deprecated, use GraphQL::executeQuery() as a quick replacement',
246
            E_USER_DEPRECATED
247
        );
248
249
        $promiseAdapter = Executor::getPromiseAdapter();
250
        $result         = self::promiseToExecute(
251
            $promiseAdapter,
252
            $schema,
253
            $source,
254
            $rootValue,
255
            $contextValue,
256
            $variableValues,
257
            $operationName
258
        );
259
260
        if ($promiseAdapter instanceof SyncPromiseAdapter) {
261
            $result = $promiseAdapter->wait($result);
262
        }
263
264
        return $result;
265
    }
266
267
    /**
268
     * Returns directives defined in GraphQL spec
269
     *
270
     * @return Directive[]
271
     *
272
     * @api
273
     */
274 407
    public static function getStandardDirectives() : array
275
    {
276 407
        return array_values(Directive::getInternalDirectives());
277
    }
278
279
    /**
280
     * Returns types defined in GraphQL spec
281
     *
282
     * @return Type[]
283
     *
284
     * @api
285
     */
286
    public static function getStandardTypes() : array
287
    {
288
        return array_values(Type::getStandardTypes());
289
    }
290
291
    /**
292
     * Replaces standard types with types from this list (matching by name)
293
     * Standard types not listed here remain untouched.
294
     *
295
     * @param array<string, ScalarType> $types
296
     *
297
     * @api
298
     */
299
    public static function overrideStandardTypes(array $types)
300
    {
301
        Type::overrideStandardTypes($types);
302
    }
303
304
    /**
305
     * Returns standard validation rules implementing GraphQL spec
306
     *
307
     * @return ValidationRule[]
308
     *
309
     * @api
310
     */
311
    public static function getStandardValidationRules() : array
312
    {
313
        return array_values(DocumentValidator::defaultRules());
314
    }
315
316
    /**
317
     * Set default resolver implementation
318
     *
319
     * @api
320
     */
321
    public static function setDefaultFieldResolver(callable $fn) : void
322
    {
323
        Executor::setDefaultFieldResolver($fn);
324
    }
325
326
    public static function setPromiseAdapter(?PromiseAdapter $promiseAdapter = null) : void
327
    {
328
        Executor::setPromiseAdapter($promiseAdapter);
329
    }
330
331
    /**
332
     * Experimental: Switch to the new executor
333
     */
334
    public static function useExperimentalExecutor()
335
    {
336
        Executor::setImplementationFactory([CoroutineExecutor::class, 'create']);
337
    }
338
339
    /**
340
     * Experimental: Switch back to the default executor
341
     */
342
    public static function useReferenceExecutor()
343
    {
344
        Executor::setImplementationFactory([ReferenceExecutor::class, 'create']);
345
    }
346
347
    /**
348
     * Returns directives defined in GraphQL spec
349
     *
350
     * @deprecated Renamed to getStandardDirectives
351
     *
352
     * @return Directive[]
353
     *
354
     * @codeCoverageIgnore
355
     */
356
    public static function getInternalDirectives() : array
357
    {
358
        return self::getStandardDirectives();
359
    }
360
}
361