Failed Conditions
Push — master ( bdbb30...e1b4d4 )
by Vladimir
05:50
created

GraphQL::overrideStandardTypes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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