Failed Conditions
Pull Request — master (#342)
by Šimon
03:38
created

GraphQL   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 277
Duplicated Lines 0 %

Test Coverage

Coverage 47.73%

Importance

Changes 0
Metric Value
wmc 19
eloc 80
dl 0
loc 277
ccs 42
cts 88
cp 0.4773
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A setPromiseAdapter() 0 3 1
A getInternalDirectives() 0 3 1
A getStandardTypes() 0 3 1
A getStandardValidationRules() 0 3 1
A executeQuery() 0 25 1
B promiseToExecute() 0 54 8
A execute() 0 33 2
A executeAndReturnResult() 0 29 2
A setDefaultFieldResolver() 0 3 1
A getStandardDirectives() 0 3 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\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
     * @api
68
     * @param string|DocumentNode $source
69
     * @param mixed               $rootValue
70
     * @param mixed               $context
71
     * @param mixed[]|null        $variableValues
72
     * @param ValidationRule[]    $validationRules
73
     */
74 74
    public static function executeQuery(
75
        SchemaType $schema,
76
        $source,
77
        $rootValue = null,
78
        $context = null,
79
        $variableValues = null,
80
        ?string $operationName = null,
81
        ?callable $fieldResolver = null,
82
        ?array $validationRules = null
83
    ) : ExecutionResult {
84 74
        $promiseAdapter = new SyncPromiseAdapter();
85
86 74
        $promise = self::promiseToExecute(
87 74
            $promiseAdapter,
88 74
            $schema,
89 74
            $source,
90 74
            $rootValue,
91 74
            $context,
92 74
            $variableValues,
93 74
            $operationName,
94 74
            $fieldResolver,
95 74
            $validationRules
96
        );
97
98 74
        return $promiseAdapter->wait($promise);
99
    }
100
101
    /**
102
     * Same as executeQuery(), but requires PromiseAdapter and always returns a Promise.
103
     * Useful for Async PHP platforms.
104
     *
105
     * @api
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 97
    public static function promiseToExecute(
113
        PromiseAdapter $promiseAdapter,
114
        SchemaType $schema,
115
        $source,
116
        $rootValue = null,
117
        $context = null,
118
        $variableValues = null,
119
        ?string $operationName = null,
120
        ?callable $fieldResolver = null,
121
        ?array $validationRules = null
122
    ) : Promise {
123
        try {
124 97
            if ($source instanceof DocumentNode) {
125 21
                $documentNode = $source;
126
            } else {
127 76
                $documentNode = Parser::parse(new Source($source ?: '', 'GraphQL'));
128
            }
129
130
            // FIXME
131 96
            if (empty($validationRules)) {
132
                /** @var QueryComplexity $queryComplexity */
133 95
                $queryComplexity = DocumentValidator::getRule(QueryComplexity::class);
134 95
                $queryComplexity->setRawVariableValues($variableValues);
135
            } else {
136 3
                foreach ($validationRules as $rule) {
137 3
                    if (! ($rule instanceof QueryComplexity)) {
138 3
                        continue;
139
                    }
140
141 2
                    $rule->setRawVariableValues($variableValues);
142
                }
143
            }
144
145 96
            $validationErrors = DocumentValidator::validate($schema, $documentNode, $validationRules);
146
147 96
            if (! empty($validationErrors)) {
148 14
                return $promiseAdapter->createFulfilled(
149 14
                    new ExecutionResult(null, $validationErrors)
150
                );
151
            }
152
153 86
            return Executor::promiseToExecute(
154 86
                $promiseAdapter,
155 86
                $schema,
156 86
                $documentNode,
157 86
                $rootValue,
158 86
                $context,
159 86
                $variableValues,
160 86
                $operationName,
161 86
                $fieldResolver
162
            );
163 1
        } catch (Error $e) {
164 1
            return $promiseAdapter->createFulfilled(
165 1
                new ExecutionResult(null, [$e])
166
            );
167
        }
168
    }
169
170
    /**
171
     * @deprecated Use executeQuery()->toArray() instead
172
     *
173
     * @param string|DocumentNode $source
174
     * @param mixed               $rootValue
175
     * @param mixed               $contextValue
176
     * @param mixed[]|null        $variableValues
177
     * @return Promise|mixed[]
178
     */
179
    public static function execute(
180
        SchemaType $schema,
181
        $source,
182
        $rootValue = null,
183
        $contextValue = null,
184
        $variableValues = null,
185
        ?string $operationName = null
186
    ) {
187
        trigger_error(
188
            __METHOD__ . ' is deprecated, use GraphQL::executeQuery()->toArray() as a quick replacement',
189
            E_USER_DEPRECATED
190
        );
191
192
        $promiseAdapter = Executor::getPromiseAdapter();
193
        $result         = self::promiseToExecute(
194
            $promiseAdapter,
195
            $schema,
196
            $source,
197
            $rootValue,
198
            $contextValue,
199
            $variableValues,
200
            $operationName
201
        );
202
203
        if ($promiseAdapter instanceof SyncPromiseAdapter) {
204
            $result = $promiseAdapter->wait($result)->toArray();
205
        } else {
206
            $result = $result->then(function (ExecutionResult $r) {
207
                return $r->toArray();
208
            });
209
        }
210
211
        return $result;
212
    }
213
214
    /**
215
     * @deprecated renamed to executeQuery()
216
     *
217
     * @param string|DocumentNode $source
218
     * @param mixed               $rootValue
219
     * @param mixed               $contextValue
220
     * @param mixed[]|null        $variableValues
221
     *
222
     * @return ExecutionResult|Promise
223
     */
224
    public static function executeAndReturnResult(
225
        SchemaType $schema,
226
        $source,
227
        $rootValue = null,
228
        $contextValue = null,
229
        $variableValues = null,
230
        ?string $operationName = null
231
    ) {
232
        trigger_error(
233
            __METHOD__ . ' is deprecated, use GraphQL::executeQuery() as a quick replacement',
234
            E_USER_DEPRECATED
235
        );
236
237
        $promiseAdapter = Executor::getPromiseAdapter();
238
        $result         = self::promiseToExecute(
239
            $promiseAdapter,
240
            $schema,
241
            $source,
242
            $rootValue,
243
            $contextValue,
244
            $variableValues,
245
            $operationName
246
        );
247
248
        if ($promiseAdapter instanceof SyncPromiseAdapter) {
249
            $result = $promiseAdapter->wait($result);
250
        }
251
252
        return $result;
253
    }
254
255
    /**
256
     * Returns directives defined in GraphQL spec
257
     *
258
     * @api
259
     * @return Directive[]
260
     */
261 340
    public static function getStandardDirectives() : array
262
    {
263 340
        return array_values(Directive::getInternalDirectives());
264
    }
265
266
    /**
267
     * Returns types defined in GraphQL spec
268
     *
269
     * @api
270
     * @return Type[]
271
     */
272
    public static function getStandardTypes() : array
273
    {
274
        return array_values(Type::getInternalTypes());
275
    }
276
277
    /**
278
     * Returns standard validation rules implementing GraphQL spec
279
     *
280
     * @api
281
     * @return ValidationRule[]
282
     */
283
    public static function getStandardValidationRules() : array
284
    {
285
        return array_values(DocumentValidator::defaultRules());
286
    }
287
288
    public static function setDefaultFieldResolver(callable $fn) : void
289
    {
290
        Executor::setDefaultFieldResolver($fn);
291
    }
292
293
    public static function setPromiseAdapter(?PromiseAdapter $promiseAdapter = null) : void
294
    {
295
        Executor::setPromiseAdapter($promiseAdapter);
296
    }
297
298
    /**
299
     * Returns directives defined in GraphQL spec
300
     *
301
     * @deprecated Renamed to getStandardDirectives
302
     * @return Directive[]
303
     */
304
    public static function getInternalDirectives() : array
305
    {
306
        return self::getStandardDirectives();
307
    }
308
}
309