GraphQL::execute()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 10
c 1
b 0
f 0
nc 1
nop 8
dl 0
loc 22
rs 9.9332

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

207
        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...
208
    }
209
210
    /**
211
     * @param Source $source
212
     * @param array  $options
213
     * @return TypeNodeInterface
214
     */
215
    public static function parseType(Source $source, array $options = []): TypeNodeInterface
216
    {
217
        /** @var ParserInterface $parser */
218
        $parser = static::make(ParserInterface::class);
219
220
        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

220
        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...
221
    }
222
223
    /**
224
     * @param Schema       $schema
225
     * @param DocumentNode $document
226
     * @return array
227
     */
228
    public static function validate(Schema $schema, DocumentNode $document): array
229
    {
230
        /** @var ValidatorInterface $validator */
231
        $validator = static::make(ValidatorInterface::class);
232
233
        return $validator->validate($schema, $document);
234
    }
235
236
    /**
237
     * @param Schema                     $schema
238
     * @param DocumentNode               $document
239
     * @param mixed                      $rootValue
240
     * @param mixed                      $contextValue
241
     * @param array                      $variableValues
242
     * @param string|null                $operationName
243
     * @param callable|null              $fieldResolver
244
     * @param ErrorHandlerInterface|null $errorHandler
245
     * @return PromiseInterface
246
     */
247
    public static function execute(
248
        Schema $schema,
249
        DocumentNode $document,
250
        $rootValue = null,
251
        $contextValue = null,
252
        array $variableValues = [],
253
        $operationName = null,
254
        callable $fieldResolver = null,
255
        ?ErrorHandlerInterface $errorHandler = null
256
    ): PromiseInterface {
257
        /** @var ExecutionInterface $execution */
258
        $execution = static::make(ExecutionInterface::class);
259
260
        return $execution->execute(
261
            $schema,
262
            $document,
263
            $rootValue,
264
            $contextValue,
265
            $variableValues,
266
            $operationName,
267
            $fieldResolver,
268
            $errorHandler
269
        );
270
    }
271
272
    /**
273
     * @param Schema                     $schema
274
     * @param string                     $source
275
     * @param mixed                      $rootValue
276
     * @param mixed                      $contextValue
277
     * @param array                      $variableValues
278
     * @param null|string                $operationName
279
     * @param callable|null              $fieldResolver
280
     * @param ErrorHandlerInterface|null $errorHandler
281
     * @return PromiseInterface
282
     * @throws InvariantException
283
     */
284
    public static function process(
285
        Schema $schema,
286
        string $source,
287
        $rootValue = null,
288
        $contextValue = null,
289
        array $variableValues = [],
290
        ?string $operationName = null,
291
        ?callable $fieldResolver = null,
292
        ?ErrorHandlerInterface $errorHandler = null
293
    ): PromiseInterface {
294
        $schemaValidationErrors = validateSchema($schema);
295
296
        if (!empty($schemaValidationErrors)) {
297
            if (null !== $errorHandler) {
298
                foreach ($schemaValidationErrors as $schemaValidationError) {
299
                    $errorHandler->handleError($schemaValidationError);
300
                }
301
            }
302
303
            return resolve(new ExecutionResult(null, $schemaValidationErrors));
304
        }
305
306
        try {
307
            $document = parse($source);
308
        } catch (SyntaxErrorException $error) {
309
            if (null !== $errorHandler) {
310
                $errorHandler->handleError($error);
311
            }
312
313
            return resolve(new ExecutionResult(null, [$error]));
314
        }
315
316
        $validationErrors = validate($schema, $document);
317
318
        if (!empty($validationErrors)) {
319
            if (null !== $errorHandler) {
320
                foreach ($validationErrors as $validationError) {
321
                    $errorHandler->handleError($validationError);
322
                }
323
            }
324
325
            return resolve(new ExecutionResult(null, $validationErrors));
326
        }
327
328
        return executeAsync(
329
            $schema,
330
            $document,
331
            $rootValue,
332
            $contextValue,
333
            $variableValues,
334
            $operationName,
335
            $fieldResolver,
336
            $errorHandler
337
        );
338
    }
339
340
    /**
341
     * @param NodeInterface $node
342
     * @return string
343
     */
344
    public static function print(NodeInterface $node): string
345
    {
346
        /** @var NodePrinterInterface $nodePrinter */
347
        $nodePrinter = static::make(NodePrinterInterface::class);
348
349
        return $nodePrinter->print($node);
350
    }
351
352
    /**
353
     * @return Container
354
     */
355
    public function getContainer(): Container
356
    {
357
        return $this->container;
358
    }
359
360
    /**
361
     * Registers the service provides with the container.
362
     *
363
     * @param Container $container
364
     */
365
    protected function registerProviders(Container $container): void
366
    {
367
        foreach (self::$providers as $className) {
368
            $container->addServiceProvider($className);
369
        }
370
    }
371
}
372