Passed
Pull Request — master (#318)
by Christoffer
02:19
created

GraphQL::process()   B

Complexity

Conditions 9
Paths 7

Size

Total Lines 57
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 28
nc 7
nop 8
dl 0
loc 57
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\CallableMiddleware;
6
use Digia\GraphQL\Error\Handler\ErrorHandler;
7
use Digia\GraphQL\Error\Handler\ErrorHandlerInterface;
8
use Digia\GraphQL\Error\InvariantException;
9
use Digia\GraphQL\Execution\ExecutionInterface;
10
use Digia\GraphQL\Execution\ExecutionProvider;
11
use Digia\GraphQL\Execution\ExecutionResult;
12
use Digia\GraphQL\Language\LanguageProvider;
13
use Digia\GraphQL\Language\Node\DocumentNode;
14
use Digia\GraphQL\Language\Node\NodeInterface;
15
use Digia\GraphQL\Language\Node\TypeNodeInterface;
16
use Digia\GraphQL\Language\Node\ValueNodeInterface;
17
use Digia\GraphQL\Language\NodePrinterInterface;
18
use Digia\GraphQL\Language\ParserInterface;
19
use Digia\GraphQL\Language\Source;
20
use Digia\GraphQL\Language\SyntaxErrorException;
21
use Digia\GraphQL\Schema\Building\SchemaBuilderInterface;
22
use Digia\GraphQL\Schema\Building\SchemaBuildingProvider;
23
use Digia\GraphQL\Schema\Extension\SchemaExtenderInterface;
24
use Digia\GraphQL\Schema\Extension\SchemaExtensionProvider;
25
use Digia\GraphQL\Schema\Resolver\ResolverRegistry;
26
use Digia\GraphQL\Schema\Resolver\ResolverRegistryInterface;
27
use Digia\GraphQL\Schema\Schema;
28
use Digia\GraphQL\Schema\Validation\SchemaValidationProvider;
29
use Digia\GraphQL\Schema\Validation\SchemaValidatorInterface;
30
use Digia\GraphQL\Type\CoercerProvider;
31
use Digia\GraphQL\Type\DirectivesProvider;
32
use Digia\GraphQL\Type\IntrospectionProvider;
33
use Digia\GraphQL\Type\ScalarTypesProvider;
34
use Digia\GraphQL\Validation\RulesProvider;
35
use Digia\GraphQL\Validation\ValidationProvider;
36
use Digia\GraphQL\Validation\ValidatorInterface;
37
use League\Container\Container;
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 ExecutionResult
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
    ): ExecutionResult {
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 null                       $rootValue
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $rootValue is correct as it would always require null to be passed?
Loading history...
276
     * @param null                       $contextValue
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $contextValue is correct as it would always require null to be passed?
Loading history...
277
     * @param array                      $variableValues
278
     * @param null|string                $operationName
279
     * @param callable|null              $fieldResolver
280
     * @param ErrorHandlerInterface|null $errorHandler
281
     * @return ExecutionResult
282
     * @throws InvariantException
283
     * @throws SyntaxErrorException
284
     */
285
    public static function process(
286
        Schema $schema,
287
        string $source,
288
        $rootValue = null,
289
        $contextValue = null,
290
        array $variableValues = [],
291
        ?string $operationName = null,
292
        ?callable $fieldResolver = null,
293
        ?ErrorHandlerInterface $errorHandler = null
294
    ): ExecutionResult
295
    {
296
        $schemaValidationErrors = validateSchema($schema);
297
298
        if (!empty($schemaValidationErrors)) {
299
            if (null !== $errorHandler) {
300
                foreach ($schemaValidationErrors as $schemaValidationError) {
301
                    $errorHandler->handleError($schemaValidationError);
302
                }
303
            }
304
305
            return (new ExecutionResult(null, $schemaValidationErrors));
306
        }
307
308
        try {
309
            $document = parse($source);
310
        } catch (SyntaxErrorException $error) {
311
            if (null !== $errorHandler) {
312
                $errorHandler->handleError($error);
313
            }
314
315
            return (new ExecutionResult(null, [$error]));
316
        }
317
318
        $validationErrors = validate($schema, $document);
319
320
        if (!empty($validationErrors)) {
321
            if (null !== $errorHandler) {
322
                foreach ($validationErrors as $validationError) {
323
                    $errorHandler->handleError($validationError);
324
                }
325
            }
326
327
            return (new ExecutionResult(null, $validationErrors));
328
        }
329
330
        $result = execute(
331
            $schema,
332
            $document,
333
            $rootValue,
334
            $contextValue,
335
            $variableValues,
336
            $operationName,
337
            $fieldResolver,
338
            $errorHandler
339
        );
340
341
        return $result;
342
    }
343
344
    /**
345
     * @param NodeInterface $node
346
     * @return string
347
     */
348
    public static function print(NodeInterface $node): string
349
    {
350
        /** @var NodePrinterInterface $nodePrinter */
351
        $nodePrinter = static::make(NodePrinterInterface::class);
352
353
        return $nodePrinter->print($node);
354
    }
355
356
    /**
357
     * @return Container
358
     */
359
    public function getContainer(): Container
360
    {
361
        return $this->container;
362
    }
363
364
    /**
365
     * Registers the service provides with the container.
366
     *
367
     * @param Container $container
368
     */
369
    protected function registerProviders(Container $container): void
370
    {
371
        foreach (self::$providers as $className) {
372
            $container->addServiceProvider($className);
373
        }
374
    }
375
}
376