Failed Conditions
Push — master ( e1b4d4...c45fa1 )
by Vladimir
05:53
created

GraphQL::getStandardDirectives()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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