Passed
Pull Request — master (#345)
by
unknown
02:49
created

GraphQL::processAsync()   B

Complexity

Conditions 9
Paths 7

Size

Total Lines 53
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 27
nc 7
nop 8
dl 0
loc 53
rs 8.0555
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
namespace Digia\GraphQL;
4
5
use Digia\GraphQL\Error\Handler\ErrorHandlerInterface;
6
use Digia\GraphQL\Error\InvariantException;
7
use Digia\GraphQL\Execution\ExecutionInterface;
8
use Digia\GraphQL\Execution\ExecutionProvider;
9
use Digia\GraphQL\Execution\ExecutionResult;
10
use Digia\GraphQL\Execution\PromisedExecutionInterface;
0 ignored issues
show
Bug introduced by
The type Digia\GraphQL\Execution\PromisedExecutionInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use Digia\GraphQL\Language\LanguageProvider;
12
use Digia\GraphQL\Language\Node\DocumentNode;
13
use Digia\GraphQL\Language\Node\NodeInterface;
14
use Digia\GraphQL\Language\Node\TypeNodeInterface;
15
use Digia\GraphQL\Language\Node\ValueNodeInterface;
16
use Digia\GraphQL\Language\NodePrinterInterface;
17
use Digia\GraphQL\Language\ParserInterface;
18
use Digia\GraphQL\Language\Source;
19
use Digia\GraphQL\Language\SyntaxErrorException;
20
use Digia\GraphQL\Schema\Building\SchemaBuilderInterface;
21
use Digia\GraphQL\Schema\Building\SchemaBuildingProvider;
22
use Digia\GraphQL\Schema\Extension\SchemaExtenderInterface;
23
use Digia\GraphQL\Schema\Extension\SchemaExtensionProvider;
24
use Digia\GraphQL\Schema\Resolver\ResolverRegistry;
25
use Digia\GraphQL\Schema\Resolver\ResolverRegistryInterface;
26
use Digia\GraphQL\Schema\Schema;
27
use Digia\GraphQL\Schema\Validation\SchemaValidationProvider;
28
use Digia\GraphQL\Schema\Validation\SchemaValidatorInterface;
29
use Digia\GraphQL\Type\CoercerProvider;
30
use Digia\GraphQL\Type\DirectivesProvider;
31
use Digia\GraphQL\Type\IntrospectionProvider;
32
use Digia\GraphQL\Type\ScalarTypesProvider;
33
use Digia\GraphQL\Validation\RulesProvider;
34
use Digia\GraphQL\Validation\ValidationProvider;
35
use Digia\GraphQL\Validation\ValidatorInterface;
36
use League\Container\Container;
37
use React\Promise\PromiseInterface;
38
use function React\Promise\resolve;
39
40
class GraphQL
41
{
42
    public const BOOLEAN = 'GraphQLBoolean';
43
    public const FLOAT   = 'GraphQLFloat';
44
    public const INT     = 'GraphQLInt';
45
    public const ID      = 'GraphQLID';
46
    public const STRING  = 'GraphQLString';
47
48
    public const DEPRECATED_DIRECTIVE = 'GraphQLDeprecatedDirective';
49
    public const INCLUDE_DIRECTIVE    = 'GraphQLIncludeDirective';
50
    public const SKIP_DIRECTIVE       = 'GraphQLSkipDirective';
51
52
    public const SCHEMA_INTROSPECTION             = '__Schema';
53
    public const DIRECTIVE_INTROSPECTION          = '__Directive';
54
    public const DIRECTIVE_LOCATION_INTROSPECTION = '__DirectiveLocation';
55
    public const TYPE_INTROSPECTION               = '__Type';
56
    public const FIELD_INTROSPECTION              = '__Field';
57
    public const INPUT_VALUE_INTROSPECTION        = '__InputValue';
58
    public const ENUM_VALUE_INTROSPECTION         = '__EnumValue';
59
    public const TYPE_KIND_INTROSPECTION          = '__TypeKind';
60
61
    public const SCHEMA_META_FIELD_DEFINITION    = 'SchemaMetaFieldDefinition';
62
    public const TYPE_META_FIELD_DEFINITION      = 'TypeMetaFieldDefinition';
63
    public const TYPE_NAME_META_FIELD_DEFINITION = 'TypeNameMetaFieldDefinition';
64
65
    /**
66
     * @var array
67
     */
68
    private static $providers = [
69
        LanguageProvider::class,
70
        SchemaBuildingProvider::class,
71
        SchemaExtensionProvider::class,
72
        SchemaValidationProvider::class,
73
        CoercerProvider::class,
74
        IntrospectionProvider::class,
75
        ScalarTypesProvider::class,
76
        DirectivesProvider::class,
77
        RulesProvider::class,
78
        ValidationProvider::class,
79
        ExecutionProvider::class,
80
    ];
81
82
    /**
83
     * @var GraphQL
84
     */
85
    private static $instance;
86
87
    /**
88
     * @var Container
89
     */
90
    protected $container;
91
92
    /**
93
     * GraphQL constructor.
94
     */
95
    private function __construct()
96
    {
97
        $container = new Container();
98
99
        $this->registerProviders($container);
100
101
        $this->container = $container;
102
    }
103
104
    /**
105
     * @return GraphQL
106
     */
107
    public static function getInstance(): self
108
    {
109
        if (null === self::$instance) {
110
            self::$instance = new self();
111
        }
112
113
        return self::$instance;
114
    }
115
116
    /**
117
     * @param string $id
118
     * @return mixed
119
     */
120
    public static function make(string $id)
121
    {
122
        return static::getInstance()
123
            ->getContainer()
124
            ->get($id);
125
    }
126
127
    /**
128
     * @param Source                          $source
129
     * @param array|ResolverRegistryInterface $resolverRegistry
130
     * @param array                           $options
131
     * @return Schema
132
     */
133
    public static function buildSchema(Source $source, $resolverRegistry, array $options = []): Schema
134
    {
135
        /** @var SchemaBuilderInterface $schemaBuilder */
136
        $schemaBuilder = static::make(SchemaBuilderInterface::class);
137
138
        return $schemaBuilder->build(
139
            static::parse($source, $options),
140
            $resolverRegistry instanceof ResolverRegistryInterface
141
                ? $resolverRegistry
142
                : new ResolverRegistry($resolverRegistry),
143
            $options
144
        );
145
    }
146
147
    /**
148
     * @param Schema                          $schema
149
     * @param Source                          $source
150
     * @param array|ResolverRegistryInterface $resolverRegistry
151
     * @param array                           $options
152
     * @return Schema
153
     */
154
    public static function extendSchema(
155
        Schema $schema,
156
        Source $source,
157
        $resolverRegistry,
158
        array $options = []
159
    ): Schema {
160
        /** @var SchemaExtenderInterface $schemaExtender */
161
        $schemaExtender = static::make(SchemaExtenderInterface::class);
162
163
        return $schemaExtender->extend(
164
            $schema,
165
            static::parse($source, $options),
166
            $resolverRegistry instanceof ResolverRegistryInterface
167
                ? $resolverRegistry
168
                : new ResolverRegistry($resolverRegistry),
169
            $options
170
        );
171
    }
172
173
    /**
174
     * @param Schema $schema
175
     * @return array
176
     */
177
    public static function validateSchema(Schema $schema): array
178
    {
179
        /** @var SchemaValidatorInterface $schemaValidator */
180
        $schemaValidator = static::make(SchemaValidatorInterface::class);
181
182
        return $schemaValidator->validate($schema);
183
    }
184
185
    /**
186
     * @param Source $source
187
     * @param array  $options
188
     * @return DocumentNode
189
     */
190
    public static function parse(Source $source, array $options = []): DocumentNode
191
    {
192
        /** @var ParserInterface $parser */
193
        $parser = static::make(ParserInterface::class);
194
195
        return $parser->parse($source, $options);
196
    }
197
198
    /**
199
     * @param Source $source
200
     * @param array  $options
201
     * @return ValueNodeInterface
202
     */
203
    public static function parseValue(Source $source, array $options = []): ValueNodeInterface
204
    {
205
        /** @var ParserInterface $parser */
206
        $parser = static::make(ParserInterface::class);
207
208
        return $parser->parseValue($source, $options);
0 ignored issues
show
Bug introduced by
The method parseValue() does not exist on Digia\GraphQL\Language\ParserInterface. Did you maybe mean parse()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

208
        return $parser->/** @scrutinizer ignore-call */ parseValue($source, $options);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
209
    }
210
211
    /**
212
     * @param Source $source
213
     * @param array  $options
214
     * @return TypeNodeInterface
215
     */
216
    public static function parseType(Source $source, array $options = []): TypeNodeInterface
217
    {
218
        /** @var ParserInterface $parser */
219
        $parser = static::make(ParserInterface::class);
220
221
        return $parser->parseType($source, $options);
0 ignored issues
show
Bug introduced by
The method parseType() does not exist on Digia\GraphQL\Language\ParserInterface. Did you maybe mean parse()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

221
        return $parser->/** @scrutinizer ignore-call */ parseType($source, $options);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
222
    }
223
224
    /**
225
     * @param Schema       $schema
226
     * @param DocumentNode $document
227
     * @return array
228
     */
229
    public static function validate(Schema $schema, DocumentNode $document): array
230
    {
231
        /** @var ValidatorInterface $validator */
232
        $validator = static::make(ValidatorInterface::class);
233
234
        return $validator->validate($schema, $document);
235
    }
236
237
    /**
238
     * @param Schema                     $schema
239
     * @param DocumentNode               $document
240
     * @param mixed                      $rootValue
241
     * @param mixed                      $contextValue
242
     * @param array                      $variableValues
243
     * @param string|null                $operationName
244
     * @param callable|null              $fieldResolver
245
     * @param ErrorHandlerInterface|null $errorHandler
246
     * @return ExecutionResult
247
     */
248
    public static function execute(
249
        Schema $schema,
250
        DocumentNode $document,
251
        $rootValue = null,
252
        $contextValue = null,
253
        array $variableValues = [],
254
        $operationName = null,
255
        callable $fieldResolver = null,
256
        ?ErrorHandlerInterface $errorHandler = null
257
    ): ExecutionResult {
258
        /** @var ExecutionInterface $execution */
259
        $execution = static::make(ExecutionInterface::class);
260
261
        return $execution->execute(
262
            $schema,
263
            $document,
264
            $rootValue,
265
            $contextValue,
266
            $variableValues,
267
            $operationName,
268
            $fieldResolver,
269
            $errorHandler
270
        );
271
    }
272
273
    /**
274
     * @param Schema                     $schema
275
     * @param DocumentNode               $document
276
     * @param mixed                      $rootValue
277
     * @param mixed                      $contextValue
278
     * @param array                      $variableValues
279
     * @param string|null                $operationName
280
     * @param callable|null              $fieldResolver
281
     * @param ErrorHandlerInterface|null $errorHandler
282
     * @return PromiseInterface<ExecutionResult>
283
     */
284
    public static function promiseExecute(
285
        Schema $schema,
286
        DocumentNode $document,
287
        $rootValue = null,
288
        $contextValue = null,
289
        array $variableValues = [],
290
        $operationName = null,
291
        callable $fieldResolver = null,
292
        ?ErrorHandlerInterface $errorHandler = null
293
    ): PromiseInterface {
294
        /** @var PromisedExecutionInterface $execution */
295
        $execution = static::make(ExecutionInterface::class);
296
297
        return $execution->promiseExecute(
298
            $schema,
299
            $document,
300
            $rootValue,
301
            $contextValue,
302
            $variableValues,
303
            $operationName,
304
            $fieldResolver,
305
            $errorHandler
306
        );
307
    }
308
309
    /**
310
     * @param Schema                     $schema
311
     * @param string                     $source
312
     * @param mixed                      $rootValue
313
     * @param mixed                      $contextValue
314
     * @param array                      $variableValues
315
     * @param null|string                $operationName
316
     * @param callable|null              $fieldResolver
317
     * @param ErrorHandlerInterface|null $errorHandler
318
     * @return ExecutionResult
319
     * @throws InvariantException
320
     * @throws SyntaxErrorException
321
     */
322
    public static function process(
323
        Schema $schema,
324
        string $source,
325
        $rootValue = null,
326
        $contextValue = null,
327
        array $variableValues = [],
328
        ?string $operationName = null,
329
        ?callable $fieldResolver = null,
330
        ?ErrorHandlerInterface $errorHandler = null
331
    ): ExecutionResult {
332
        $schemaValidationErrors = validateSchema($schema);
333
334
        if (!empty($schemaValidationErrors)) {
335
            if (null !== $errorHandler) {
336
                foreach ($schemaValidationErrors as $schemaValidationError) {
337
                    $errorHandler->handleError($schemaValidationError);
338
                }
339
            }
340
341
            return new ExecutionResult(null, $schemaValidationErrors);
342
        }
343
344
        try {
345
            $document = parse($source);
346
        } catch (SyntaxErrorException $error) {
347
            if (null !== $errorHandler) {
348
                $errorHandler->handleError($error);
349
            }
350
351
            return new ExecutionResult(null, [$error]);
352
        }
353
354
        $validationErrors = validate($schema, $document);
355
356
        if (!empty($validationErrors)) {
357
            if (null !== $errorHandler) {
358
                foreach ($validationErrors as $validationError) {
359
                    $errorHandler->handleError($validationError);
360
                }
361
            }
362
363
            return new ExecutionResult(null, $validationErrors);
364
        }
365
366
        return execute(
367
            $schema,
368
            $document,
369
            $rootValue,
370
            $contextValue,
371
            $variableValues,
372
            $operationName,
373
            $fieldResolver,
374
            $errorHandler
375
        );
376
    }
377
378
    /**
379
     * @param Schema                     $schema
380
     * @param string                     $source
381
     * @param mixed                      $rootValue
382
     * @param mixed                      $contextValue
383
     * @param array                      $variableValues
384
     * @param null|string                $operationName
385
     * @param callable|null              $fieldResolver
386
     * @param ErrorHandlerInterface|null $errorHandler
387
     * @return PromiseInterface<ExecutionResult>
388
     * @throws InvariantException
389
     * @throws SyntaxErrorException
390
     */
391
    public static function processAsync(
392
        Schema $schema,
393
        string $source,
394
        $rootValue = null,
395
        $contextValue = null,
396
        array $variableValues = [],
397
        ?string $operationName = null,
398
        ?callable $fieldResolver = null,
399
        ?ErrorHandlerInterface $errorHandler = null
400
    ): PromiseInterface {
401
        $schemaValidationErrors = validateSchema($schema);
402
403
        if (!empty($schemaValidationErrors)) {
404
            if (null !== $errorHandler) {
405
                foreach ($schemaValidationErrors as $schemaValidationError) {
406
                    $errorHandler->handleError($schemaValidationError);
407
                }
408
            }
409
410
            return resolve(new ExecutionResult(null, $schemaValidationErrors));
411
        }
412
413
        try {
414
            $document = parse($source);
415
        } catch (SyntaxErrorException $error) {
416
            if (null !== $errorHandler) {
417
                $errorHandler->handleError($error);
418
            }
419
420
            return resolve(new ExecutionResult(null, [$error]));
421
        }
422
423
        $validationErrors = validate($schema, $document);
424
425
        if (!empty($validationErrors)) {
426
            if (null !== $errorHandler) {
427
                foreach ($validationErrors as $validationError) {
428
                    $errorHandler->handleError($validationError);
429
                }
430
            }
431
432
            return resolve(new ExecutionResult(null, $validationErrors));
433
        }
434
435
        return promiseExecute(
436
            $schema,
437
            $document,
438
            $rootValue,
439
            $contextValue,
440
            $variableValues,
441
            $operationName,
442
            $fieldResolver,
443
            $errorHandler
444
        );
445
    }
446
447
    /**
448
     * @param NodeInterface $node
449
     * @return string
450
     */
451
    public static function print(NodeInterface $node): string
452
    {
453
        /** @var NodePrinterInterface $nodePrinter */
454
        $nodePrinter = static::make(NodePrinterInterface::class);
455
456
        return $nodePrinter->print($node);
457
    }
458
459
    /**
460
     * @return Container
461
     */
462
    public function getContainer(): Container
463
    {
464
        return $this->container;
465
    }
466
467
    /**
468
     * Registers the service provides with the container.
469
     *
470
     * @param Container $container
471
     */
472
    protected function registerProviders(Container $container): void
473
    {
474
        foreach (self::$providers as $className) {
475
            $container->addServiceProvider($className);
476
        }
477
    }
478
}
479