Passed
Pull Request — master (#539)
by Benedikt
03:07
created

Introspection   B

Complexity

Total Complexity 51

Size/Duplication

Total Lines 794
Duplicated Lines 0 %

Test Coverage

Coverage 50%

Importance

Changes 5
Bugs 0 Features 0
Metric Value
wmc 51
eloc 441
c 5
b 0
f 0
dl 0
loc 794
ccs 152
cts 304
cp 0.5
rs 7.92

15 Methods

Rating   Name   Duplication   Size   Complexity  
A isIntrospectionType() 0 3 1
A getTypes() 0 11 1
A getIntrospectionQuery() 0 70 4
A _schema() 0 54 2
A typeNameMetaFieldDef() 0 20 2
A fromSchema() 0 8 1
A typeMetaFieldDef() 0 17 2
A schemaMetaFieldDef() 0 20 2
A _enumValue() 0 40 2
A _directive() 0 44 3
B _directiveLocation() 0 92 2
A _field() 0 53 3
A _typeKind() 0 45 2
D _type() 0 149 20
A _inputValue() 0 60 4

How to fix   Complexity   

Complex Class

Complex classes like Introspection often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Introspection, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQL\Type;
6
7
use Exception;
8
use GraphQL\GraphQL;
9
use GraphQL\Language\DirectiveLocation;
10
use GraphQL\Language\Printer;
11
use GraphQL\Type\Definition\Directive;
12
use GraphQL\Type\Definition\EnumType;
13
use GraphQL\Type\Definition\FieldArgument;
14
use GraphQL\Type\Definition\FieldDefinition;
15
use GraphQL\Type\Definition\InputObjectField;
16
use GraphQL\Type\Definition\InputObjectType;
17
use GraphQL\Type\Definition\InterfaceType;
18
use GraphQL\Type\Definition\ListOfType;
19
use GraphQL\Type\Definition\NonNull;
20
use GraphQL\Type\Definition\ObjectType;
21
use GraphQL\Type\Definition\ResolveInfo;
22
use GraphQL\Type\Definition\ScalarType;
23
use GraphQL\Type\Definition\Type;
24
use GraphQL\Type\Definition\UnionType;
25
use GraphQL\Type\Definition\WrappingType;
26
use GraphQL\Utils\AST;
27
use GraphQL\Utils\Utils;
28
use function array_filter;
29
use function array_key_exists;
30
use function array_values;
31
use function is_bool;
32
use function method_exists;
33
use function trigger_error;
34
use const E_USER_DEPRECATED;
35
36
class Introspection
37
{
38
    const SCHEMA_FIELD_NAME    = '__schema';
39
    const TYPE_FIELD_NAME      = '__type';
40
    const TYPE_NAME_FIELD_NAME = '__typename';
41
42
    /** @var array<string, mixed> */
43
    private static $map = [];
44
45
    /**
46
     * Options:
47
     *   - descriptions
48
     *     Whether to include descriptions in the introspection result.
49
     *     Default: true
50
     *
51
     * @param bool[]|bool $options
52
     *
53
     * @return string
54 5
     */
55
    public static function getIntrospectionQuery($options = [])
56 5
    {
57
        if (is_bool($options)) {
58
            trigger_error(
59
                'Calling Introspection::getIntrospectionQuery(boolean) is deprecated. ' .
60
                'Please use Introspection::getIntrospectionQuery(["descriptions" => boolean]).',
61
                E_USER_DEPRECATED
62
            );
63
            $descriptions = $options;
64 5
        } else {
65
            $descriptions = ! array_key_exists('descriptions', $options) || $options['descriptions'] === true;
66 5
        }
67
        $descriptionField = $descriptions ? 'description' : '';
68
69
        return <<<EOD
70
  query IntrospectionQuery {
71
    __schema {
72
      queryType { name }
73
      mutationType { name }
74
      subscriptionType { name }
75
      types {
76
        ...FullType
77
      }
78
      directives {
79 5
        name
80
        {$descriptionField}
81
        locations
82
        args {
83
          ...InputValue
84
        }
85
      }
86
    }
87
  }
88
89
  fragment FullType on __Type {
90
    kind
91 5
    name
92
    {$descriptionField}
93
    fields(includeDeprecated: true) {
94 5
      name
95
      {$descriptionField}
96
      args {
97
        ...InputValue
98
      }
99
      type {
100
        ...TypeRef
101
      }
102
      isDeprecated
103
      deprecationReason
104
    }
105
    inputFields {
106
      ...InputValue
107
    }
108
    interfaces {
109
      ...TypeRef
110
    }
111
    enumValues(includeDeprecated: true) {
112 5
      name
113
      {$descriptionField}
114
      isDeprecated
115
      deprecationReason
116
    }
117
    possibleTypes {
118
      ...TypeRef
119
    }
120
  }
121
122
  fragment InputValue on __InputValue {
123 5
    name
124
    {$descriptionField}
125
    type { ...TypeRef }
126
    defaultValue
127
  }
128
129
  fragment TypeRef on __Type {
130
    kind
131
    name
132
    ofType {
133
      kind
134
      name
135
      ofType {
136
        kind
137
        name
138
        ofType {
139
          kind
140
          name
141
          ofType {
142
            kind
143
            name
144
            ofType {
145
              kind
146
              name
147
              ofType {
148
                kind
149
                name
150
                ofType {
151
                  kind
152
                  name
153
                }
154
              }
155
            }
156
          }
157
        }
158
      }
159
    }
160
  }
161
EOD;
162
    }
163
164
    /**
165
     * @param Type $type
166
     *
167
     * @return bool
168 138
     */
169
    public static function isIntrospectionType($type)
170 138
    {
171
        return array_key_exists($type->name, self::getTypes());
172
    }
173 889
174
    public static function getTypes()
175
    {
176 889
        return [
177 889
            '__Schema'            => self::_schema(),
178 889
            '__Type'              => self::_type(),
179 889
            '__Directive'         => self::_directive(),
180 889
            '__Field'             => self::_field(),
181 889
            '__InputValue'        => self::_inputValue(),
182 889
            '__EnumValue'         => self::_enumValue(),
183 889
            '__TypeKind'          => self::_typeKind(),
184
            '__DirectiveLocation' => self::_directiveLocation(),
185
        ];
186
    }
187 889
188
    /**
189 889
     * Build an introspection query from a Schema
190
     *
191
     * Introspection is useful for utilities that care about type and field
192
     * relationships, but do not need to traverse through those relationships.
193
     *
194
     * This is the inverse of BuildClientSchema::build(). The primary use case is outside
195
     * of the server context, for instance when doing schema comparisons.
196
     *
197
     * Options:
198
     *   - descriptions
199
     *     Whether to include descriptions in the introspection result.
200
     *     Default: true
201
     *
202
     * @param array<string, bool> $options
203 4
     *
204
     * @return array<string, mixed[]>|null
205
     */
206
    public static function fromSchema(Schema $schema, array $options = []) : ?array
207
    {
208
        $result = GraphQL::executeQuery(
209
            $schema,
210 5
            self::getIntrospectionQuery($options)
211
        );
212
213
        return $result->data;
214
    }
215
216
    public static function _schema()
217
    {
218
        if (! isset(self::$map['__Schema'])) {
219 3
            self::$map['__Schema'] = new ObjectType([
220
                'name'            => '__Schema',
221
                'isIntrospection' => true,
222
                'description'     =>
223
                    'A GraphQL Schema defines the capabilities of a GraphQL ' .
224
                    'server. It exposes all available types and directives on ' .
225
                    'the server, as well as the entry points for query, mutation, and ' .
226 3
                    'subscription operations.',
227
                'fields'          => [
228
                    'types'            => [
229
                        'description' => 'A list of all types supported by this server.',
230
                        'type'        => new NonNull(new ListOfType(new NonNull(self::_type()))),
231
                        'resolve'     => static function (Schema $schema) {
232
                            return array_values($schema->getTypeMap());
233 3
                        },
234
                    ],
235
                    'queryType'        => [
236
                        'description' => 'The type that query operations will be rooted at.',
237
                        'type'        => new NonNull(self::_type()),
238
                        'resolve'     => static function (Schema $schema) {
239
                            return $schema->getQueryType();
240 889
                        },
241
                    ],
242
                    'mutationType'     => [
243 889
                        'description' =>
244
                            'If this server supports mutation, the type that ' .
245 889
                            'mutation operations will be rooted at.',
246
                        'type'        => self::_type(),
247
                        'resolve'     => static function (Schema $schema) {
248
                            return $schema->getMutationType();
249
                        },
250
                    ],
251
                    'subscriptionType' => [
252
                        'description' => 'If this server support subscription, the type that subscription operations will be rooted at.',
253
                        'type'        => self::_type(),
254
                        'resolve'     => static function (Schema $schema) {
255
                            return $schema->getSubscriptionType();
256
                        },
257
                    ],
258
                    'directives'       => [
259
                        'description' => 'A list of all directives supported by this server.',
260
                        'type'        => Type::nonNull(Type::listOf(Type::nonNull(self::_directive()))),
261
                        'resolve'     => static function (Schema $schema) {
262
                            return $schema->getDirectives();
263
                        },
264
                    ],
265 10
                ],
266 6
            ]);
267 10
        }
268 6
269 10
        return self::$map['__Schema'];
270 7
    }
271 9
272 4
    public static function _type()
273 8
    {
274 5
        if (! isset(self::$map['__Type'])) {
275 4
            self::$map['__Type'] = new ObjectType([
276 1
                'name'            => '__Type',
277 3
                'isIntrospection' => true,
278 3
                'description'     =>
279 1
                    'The fundamental unit of any GraphQL Schema is the type. There are ' .
280 1
                    'many kinds of types in GraphQL as represented by the `__TypeKind` enum.' .
281
                    "\n\n" .
282
                    'Depending on the kind of a type, certain fields describe ' .
283
                    'information about that type. Scalar types provide no information ' .
284
                    'beyond a name and description, while Enum types provide their values. ' .
285
                    'Object and Interface types provide the fields they describe. Abstract ' .
286
                    'types, Union and Interface, provide the Object types possible ' .
287
                    'at runtime. List and NonNull types compose other types.',
288
                'fields'          => static function () {
289 21
                    return [
290
                        'kind'          => [
291
                            'type'    => Type::nonNull(self::_typeKind()),
292
                            'resolve' => static function (Type $type) {
293
                                switch (true) {
294
                                    case $type instanceof ListOfType:
295 5
                                        return TypeKind::LIST;
296
                                    case $type instanceof NonNull:
297
                                        return TypeKind::NON_NULL;
298
                                    case $type instanceof ScalarType:
299
                                        return TypeKind::SCALAR;
300
                                    case $type instanceof ObjectType:
301
                                        return TypeKind::OBJECT;
302
                                    case $type instanceof EnumType:
303
                                        return TypeKind::ENUM;
304 10
                                    case $type instanceof InputObjectType:
305 10
                                        return TypeKind::INPUT_OBJECT;
306
                                    case $type instanceof InterfaceType:
307 10
                                        return TypeKind::INTERFACE;
308 6
                                    case $type instanceof UnionType:
309 6
                                        return TypeKind::UNION;
310
                                    default:
311 6
                                        throw new Exception('Unknown kind of type: ' . Utils::printSafe($type));
312 6
                                }
313
                            },
314
                        ],
315
                        'name'          => [
316 10
                            'type' => Type::string(),
317
                            'resolve' => static function ($obj) {
318
                                return $obj->name;
319 4
                            },
320
                        ],
321
                        'description'   => [
322
                            'type' => Type::string(),
323
                            'resolve' => static function ($obj) {
324
                                return $obj->description;
325 4
                            },
326 3
                        ],
327
                        'fields'        => [
328
                            'type'    => Type::listOf(Type::nonNull(self::_field())),
329 4
                            'args'    => [
330
                                'includeDeprecated' => ['type' => Type::boolean(), 'defaultValue' => false],
331
                            ],
332
                            'resolve' => static function (Type $type, $args) {
333
                                if ($type instanceof ObjectType || $type instanceof InterfaceType) {
334
                                    $fields = $type->getFields();
335 4
336 1
                                    if (empty($args['includeDeprecated'])) {
337
                                        $fields = array_filter(
338
                                            $fields,
339 3
                                            static function (FieldDefinition $field) {
340
                                                return ! $field->deprecationReason;
341
                                            }
342
                                        );
343
                                    }
344
345
                                    return array_values($fields);
346
                                }
347
348 7
                                return null;
349 6
                            },
350
                        ],
351 6
                        'interfaces'    => [
352 2
                            'type'    => Type::listOf(Type::nonNull(self::_type())),
353 2
                            'resolve' => static function ($type) {
354
                                if ($type instanceof ObjectType) {
355 2
                                    return $type->getInterfaces();
356 2
                                }
357
358
                                return null;
359
                            },
360 6
                        ],
361
                        'possibleTypes' => [
362
                            'type'    => Type::listOf(Type::nonNull(self::_type())),
363 4
                            'resolve' => static function ($type, $args, $context, ResolveInfo $info) {
364
                                if ($type instanceof InterfaceType || $type instanceof UnionType) {
365
                                    return $info->schema->getPossibleTypes($type);
366
                                }
367
368
                                return null;
369 5
                            },
370 1
                        ],
371
                        'enumValues'    => [
372
                            'type'    => Type::listOf(Type::nonNull(self::_enumValue())),
373 4
                            'args'    => [
374
                                'includeDeprecated' => ['type' => Type::boolean(), 'defaultValue' => false],
375
                            ],
376
                            'resolve' => static function ($type, $args) {
377
                                if ($type instanceof EnumType) {
378
                                    $values = array_values($type->getValues());
379 6
380 6
                                    if (empty($args['includeDeprecated'])) {
381
                                        $values = array_filter(
382
                                            $values,
383 6
                                            static function ($value) {
384
                                                return ! $value->deprecationReason;
385
                                            }
386
                                        );
387
                                    }
388
389
                                    return $values;
390
                                }
391 889
392
                                return null;
393
                            },
394 889
                        ],
395
                        'inputFields'   => [
396 889
                            'type'    => Type::listOf(Type::nonNull(self::_inputValue())),
397
                            'resolve' => static function ($type) {
398
                                if ($type instanceof InputObjectType) {
399
                                    return array_values($type->getFields());
400
                                }
401
402
                                return null;
403
                            },
404
                        ],
405
                        'ofType'        => [
406
                            'type'    => self::_type(),
407
                            'resolve' => static function ($type) {
408
                                if ($type instanceof WrappingType) {
409
                                    return $type->getWrappedType();
410
                                }
411
412
                                return null;
413
                            },
414
                        ],
415
                    ];
416
                },
417
            ]);
418
        }
419
420
        return self::$map['__Type'];
421
    }
422
423
    public static function _typeKind()
424
    {
425
        if (! isset(self::$map['__TypeKind'])) {
426
            self::$map['__TypeKind'] = new EnumType([
427
                'name'            => '__TypeKind',
428
                'isIntrospection' => true,
429
                'description'     => 'An enum describing what kind of type a given `__Type` is.',
430
                'values'          => [
431
                    'SCALAR'       => [
432
                        'value'       => TypeKind::SCALAR,
433
                        'description' => 'Indicates this type is a scalar.',
434
                    ],
435
                    'OBJECT'       => [
436
                        'value'       => TypeKind::OBJECT,
437
                        'description' => 'Indicates this type is an object. `fields` and `interfaces` are valid fields.',
438 889
                    ],
439
                    'INTERFACE'    => [
440
                        'value'       => TypeKind::INTERFACE,
441 889
                        'description' => 'Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.',
442
                    ],
443 889
                    'UNION'        => [
444
                        'value'       => TypeKind::UNION,
445
                        'description' => 'Indicates this type is a union. `possibleTypes` is a valid field.',
446
                    ],
447
                    'ENUM'         => [
448
                        'value'       => TypeKind::ENUM,
449
                        'description' => 'Indicates this type is an enum. `enumValues` is a valid field.',
450
                    ],
451
                    'INPUT_OBJECT' => [
452
                        'value'       => TypeKind::INPUT_OBJECT,
453
                        'description' => 'Indicates this type is an input object. `inputFields` is a valid field.',
454
                    ],
455 10
                    'LIST'         => [
456
                        'value'       => TypeKind::LIST,
457
                        'description' => 'Indicates this type is a list. `ofType` is a valid field.',
458
                    ],
459
                    'NON_NULL'     => [
460
                        'value'       => TypeKind::NON_NULL,
461 3
                        'description' => 'Indicates this type is a non-null. `ofType` is a valid field.',
462
                    ],
463
                ],
464
            ]);
465
        }
466
467 4
        return self::$map['__TypeKind'];
468
    }
469
470
    public static function _field()
471
    {
472
        if (! isset(self::$map['__Field'])) {
473 5
            self::$map['__Field'] = new ObjectType([
474
                'name'            => '__Field',
475
                'isIntrospection' => true,
476
                'description'     =>
477
                    'Object and Interface types are described by a list of Fields, each of ' .
478
                    'which has a name, potentially a list of arguments, and a return type.',
479 4
                'fields'          => static function () {
480
                    return [
481
                        'name'              => [
482
                            'type' => Type::nonNull(Type::string()),
483
                            'resolve' => static function (FieldDefinition $field) {
484
                                return $field->name;
485 4
                            },
486
                        ],
487
                        'description'       => [
488
                            'type' => Type::string(),
489
                            'resolve' => static function (FieldDefinition $field) {
490
                                return $field->description;
491
                            },
492
                        ],
493 889
                        'args'              => [
494
                            'type'    => Type::nonNull(Type::listOf(Type::nonNull(self::_inputValue()))),
495
                            'resolve' => static function (FieldDefinition $field) {
496 889
                                return empty($field->args) ? [] : $field->args;
497
                            },
498 889
                        ],
499
                        'type'              => [
500
                            'type'    => Type::nonNull(self::_type()),
501
                            'resolve' => static function (FieldDefinition $field) {
502
                                return $field->getType();
503
                            },
504
                        ],
505
                        'isDeprecated'      => [
506
                            'type'    => Type::nonNull(Type::boolean()),
507
                            'resolve' => static function (FieldDefinition $field) {
508
                                return (bool) $field->deprecationReason;
509
                            },
510
                        ],
511
                        'deprecationReason' => [
512 5
                            'type'    => Type::string(),
513
                            'resolve' => static function (FieldDefinition $field) {
514 5
                                return $field->deprecationReason;
515
                            },
516
                        ],
517
                    ];
518
                },
519
            ]);
520
        }
521 3
522
        return self::$map['__Field'];
523 3
    }
524
525
    public static function _inputValue()
526
    {
527
        if (! isset(self::$map['__InputValue'])) {
528
            self::$map['__InputValue'] = new ObjectType([
529 5
                'name'            => '__InputValue',
530 5
                'isIntrospection' => true,
531 5
                'description'     =>
532
                    'Arguments provided to Fields or Directives and the input fields of an ' .
533
                    'InputObject are represented as Input Values which describe their type ' .
534
                    'and optionally a default value.',
535
                'fields'          => static function () {
536
                    return [
537
                        'name'         => [
538
                            'type' => Type::nonNull(Type::string()),
539
                            'resolve' => static function ($inputValue) {
540 5
                                /** @var FieldArgument|InputObjectField $inputValue */
541
                                $inputValue = $inputValue;
542 5
543 5
                                return $inputValue->name;
544 4
                            },
545 4
                        ],
546 5
                        'description'  => [
547
                            'type' => Type::string(),
548
                            'resolve' => static function ($inputValue) {
549
                                /** @var FieldArgument|InputObjectField $inputValue */
550
                                $inputValue = $inputValue;
551
552
                                return $inputValue->description;
553
                            },
554
                        ],
555 889
                        'type'         => [
556
                            'type'    => Type::nonNull(self::_type()),
557
                            'resolve' => static function ($value) {
558 889
                                return method_exists($value, 'getType')
559
                                    ? $value->getType()
560 889
                                    : $value->type;
561
                            },
562
                        ],
563
                        'defaultValue' => [
564
                            'type'        => Type::string(),
565
                            'description' =>
566
                                'A GraphQL-formatted string representing the default value for this input value.',
567
                            'resolve'     => static function ($inputValue) {
568
                                /** @var FieldArgument|InputObjectField $inputValue */
569
                                $inputValue = $inputValue;
570
571
                                return ! $inputValue->defaultValueExists()
572 6
                                    ? null
573
                                    : Printer::doPrint(AST::astFromValue(
574
                                        $inputValue->defaultValue,
575
                                        $inputValue->getType()
0 ignored issues
show
Bug introduced by
$inputValue->getType() of type GraphQL\Type\Definition\Type is incompatible with the type GraphQL\Type\Definition\InputType expected by parameter $type of GraphQL\Utils\AST::astFromValue(). ( Ignorable by Annotation )

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

575
                                        /** @scrutinizer ignore-type */ $inputValue->getType()
Loading history...
576
                                    ));
577
                            },
578 3
                        ],
579
                    ];
580
                },
581
            ]);
582
        }
583
584 4
        return self::$map['__InputValue'];
585
    }
586
587
    public static function _enumValue()
588
    {
589
        if (! isset(self::$map['__EnumValue'])) {
590 4
            self::$map['__EnumValue'] = new ObjectType([
591
                'name'            => '__EnumValue',
592
                'isIntrospection' => true,
593
                'description'     =>
594
                    'One possible value for a given Enum. Enum values are unique values, not ' .
595
                    'a placeholder for a string or numeric value. However an Enum value is ' .
596
                    'returned in a JSON response as a string.',
597 889
                'fields'          => [
598
                    'name'              => [
599
                        'type' => Type::nonNull(Type::string()),
600 889
                        'resolve' => static function ($enumValue) {
601
                            return $enumValue->name;
602 889
                        },
603
                    ],
604
                    'description'       => [
605
                        'type' => Type::string(),
606
                        'resolve' => static function ($enumValue) {
607
                            return $enumValue->description;
608
                        },
609
                    ],
610
                    'isDeprecated'      => [
611
                        'type'    => Type::nonNull(Type::boolean()),
612
                        'resolve' => static function ($enumValue) {
613
                            return (bool) $enumValue->deprecationReason;
614
                        },
615
                    ],
616 3
                    'deprecationReason' => [
617
                        'type' => Type::string(),
618
                        'resolve' => static function ($enumValue) {
619
                            return $enumValue->deprecationReason;
620
                        },
621
                    ],
622 2
                ],
623
            ]);
624
        }
625
626
        return self::$map['__EnumValue'];
627
    }
628
629
    public static function _directive()
630 3
    {
631
        if (! isset(self::$map['__Directive'])) {
632
            self::$map['__Directive'] = new ObjectType([
633
                'name'            => '__Directive',
634
                'isIntrospection' => true,
635
                'description'     => 'A Directive provides a way to describe alternate runtime execution and ' .
636 3
                    'type validation behavior in a GraphQL document.' .
637
                    "\n\nIn some cases, you need to provide options to alter GraphQL's " .
638
                    'execution behavior in ways field arguments will not suffice, such as ' .
639
                    'conditionally including or skipping a field. Directives provide this by ' .
640
                    'describing additional information to the executor.',
641
                'fields'          => [
642
                    'name'        => [
643 889
                        'type'    => Type::nonNull(Type::string()),
644
                        'resolve' => static function ($obj) {
645
                            return $obj->name;
646 889
                        },
647
                    ],
648 889
                    'description' => [
649
                        'type' => Type::string(),
650
                        'resolve' => static function ($obj) {
651
                            return $obj->description;
652
                        },
653
                    ],
654
                    'locations'   => [
655
                        'type' => Type::nonNull(Type::listOf(Type::nonNull(
656
                            self::_directiveLocation()
657
                        ))),
658
                        'resolve' => static function ($obj) {
659
                            return $obj->locations;
660
                        },
661
                    ],
662
                    'args'        => [
663
                        'type'    => Type::nonNull(Type::listOf(Type::nonNull(self::_inputValue()))),
664
                        'resolve' => static function (Directive $directive) {
665
                            return $directive->args ?: [];
666
                        },
667
                    ],
668
                ],
669
            ]);
670
        }
671
672
        return self::$map['__Directive'];
673
    }
674
675
    public static function _directiveLocation()
676
    {
677
        if (! isset(self::$map['__DirectiveLocation'])) {
678
            self::$map['__DirectiveLocation'] = new EnumType([
679
                'name'            => '__DirectiveLocation',
680
                'isIntrospection' => true,
681
                'description'     =>
682
                    'A Directive can be adjacent to many parts of the GraphQL language, a ' .
683
                    '__DirectiveLocation describes one such possible adjacencies.',
684
                'values'          => [
685
                    'QUERY'                  => [
686
                        'value'       => DirectiveLocation::QUERY,
687
                        'description' => 'Location adjacent to a query operation.',
688
                    ],
689
                    'MUTATION'               => [
690
                        'value'       => DirectiveLocation::MUTATION,
691
                        'description' => 'Location adjacent to a mutation operation.',
692
                    ],
693
                    'SUBSCRIPTION'           => [
694
                        'value'       => DirectiveLocation::SUBSCRIPTION,
695
                        'description' => 'Location adjacent to a subscription operation.',
696
                    ],
697
                    'FIELD'                  => [
698
                        'value'       => DirectiveLocation::FIELD,
699
                        'description' => 'Location adjacent to a field.',
700
                    ],
701
                    'FRAGMENT_DEFINITION'    => [
702
                        'value'       => DirectiveLocation::FRAGMENT_DEFINITION,
703
                        'description' => 'Location adjacent to a fragment definition.',
704
                    ],
705
                    'FRAGMENT_SPREAD'        => [
706
                        'value'       => DirectiveLocation::FRAGMENT_SPREAD,
707
                        'description' => 'Location adjacent to a fragment spread.',
708
                    ],
709
                    'INLINE_FRAGMENT'        => [
710
                        'value'       => DirectiveLocation::INLINE_FRAGMENT,
711
                        'description' => 'Location adjacent to an inline fragment.',
712
                    ],
713
                    'VARIABLE_DEFINITION'    => [
714
                        'value'       => DirectiveLocation::VARIABLE_DEFINITION,
715
                        'description' => 'Location adjacent to a variable definition.',
716
                    ],
717
                    'SCHEMA'                 => [
718
                        'value'       => DirectiveLocation::SCHEMA,
719
                        'description' => 'Location adjacent to a schema definition.',
720
                    ],
721
                    'SCALAR'                 => [
722
                        'value'       => DirectiveLocation::SCALAR,
723
                        'description' => 'Location adjacent to a scalar definition.',
724
                    ],
725
                    'OBJECT'                 => [
726
                        'value'       => DirectiveLocation::OBJECT,
727
                        'description' => 'Location adjacent to an object type definition.',
728
                    ],
729
                    'FIELD_DEFINITION'       => [
730
                        'value'       => DirectiveLocation::FIELD_DEFINITION,
731
                        'description' => 'Location adjacent to a field definition.',
732
                    ],
733
                    'ARGUMENT_DEFINITION'    => [
734
                        'value'       => DirectiveLocation::ARGUMENT_DEFINITION,
735
                        'description' => 'Location adjacent to an argument definition.',
736
                    ],
737 889
                    'INTERFACE'              => [
738
                        'value'       => DirectiveLocation::IFACE,
739
                        'description' => 'Location adjacent to an interface definition.',
740 476
                    ],
741
                    'UNION'                  => [
742 476
                        'value'       => DirectiveLocation::UNION,
743 1
                        'description' => 'Location adjacent to a union definition.',
744 1
                    ],
745 1
                    'ENUM'                   => [
746 1
                        'value'       => DirectiveLocation::ENUM,
747
                        'description' => 'Location adjacent to an enum definition.',
748
                    ],
749
                    'ENUM_VALUE'             => [
750
                        'value'       => DirectiveLocation::ENUM_VALUE,
751
                        'description' => 'Location adjacent to an enum value definition.',
752
                    ],
753
                    'INPUT_OBJECT'           => [
754 6
                        'value'       => DirectiveLocation::INPUT_OBJECT,
755 1
                        'description' => 'Location adjacent to an input object type definition.',
756
                    ],
757
                    'INPUT_FIELD_DEFINITION' => [
758
                        'value'       => DirectiveLocation::INPUT_FIELD_DEFINITION,
759 476
                        'description' => 'Location adjacent to an input object field definition.',
760
                    ],
761
762 477
                ],
763
            ]);
764 477
        }
765 1
766 1
        return self::$map['__DirectiveLocation'];
767 1
    }
768 1
769
    public static function schemaMetaFieldDef() : FieldDefinition
770 1
    {
771
        if (! isset(self::$map[self::SCHEMA_FIELD_NAME])) {
772
            self::$map[self::SCHEMA_FIELD_NAME] = FieldDefinition::create([
773 15
                'name'        => self::SCHEMA_FIELD_NAME,
774 1
                'type'        => Type::nonNull(self::_schema()),
775
                'description' => 'Access the current type schema of this server.',
776
                'args'        => [],
777
                'resolve'     => static function (
778 477
                    $source,
779
                    $args,
780
                    $context,
781 481
                    ResolveInfo $info
782
                ) {
783 481
                    return $info->schema;
784 1
                },
785 1
            ]);
786 1
        }
787 1
788
        return self::$map[self::SCHEMA_FIELD_NAME];
789
    }
790
791
    public static function typeMetaFieldDef() : FieldDefinition
792
    {
793
        if (! isset(self::$map[self::TYPE_FIELD_NAME])) {
794
            self::$map[self::TYPE_FIELD_NAME] = FieldDefinition::create([
795 7
                'name'        => self::TYPE_FIELD_NAME,
796 1
                'type'        => self::_type(),
797
                'description' => 'Request the type information of a single type.',
798
                'args'        => [
799
                    ['name' => 'name', 'type' => Type::nonNull(Type::string())],
800 481
                ],
801
                'resolve'     => static function ($source, $args, $context, ResolveInfo $info) {
802
                    return $info->schema->getType($args['name']);
803
                },
804
            ]);
805
        }
806
807
        return self::$map[self::TYPE_FIELD_NAME];
808
    }
809
810
    public static function typeNameMetaFieldDef() : FieldDefinition
811
    {
812
        if (! isset(self::$map[self::TYPE_NAME_FIELD_NAME])) {
813
            self::$map[self::TYPE_NAME_FIELD_NAME] = FieldDefinition::create([
814
                'name'        => self::TYPE_NAME_FIELD_NAME,
815
                'type'        => Type::nonNull(Type::string()),
816
                'description' => 'The name of the current Object type at runtime.',
817
                'args'        => [],
818
                'resolve'     => static function (
819
                    $source,
820
                    $args,
821
                    $context,
822
                    ResolveInfo $info
823
                ) {
824
                    return $info->parentType->name;
825
                },
826
            ]);
827
        }
828
829
        return self::$map[self::TYPE_NAME_FIELD_NAME];
830
    }
831
}
832