Passed
Pull Request — master (#207)
by Christoffer
02:26
created

newSchema()   B

Complexity

Conditions 5
Paths 2

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 15
nc 2
nop 1
dl 0
loc 22
rs 8.6737
c 0
b 0
f 0
1
<?php
2
3
namespace Digia\GraphQL\Type;
4
5
use Digia\GraphQL\Error\InvalidTypeException;
6
use Digia\GraphQL\Error\InvariantException;
7
use Digia\GraphQL\Schema\Schema;
8
use Digia\GraphQL\Type\Definition\AbstractTypeInterface;
9
use Digia\GraphQL\Type\Definition\Argument;
10
use Digia\GraphQL\Type\Definition\CompositeTypeInterface;
11
use Digia\GraphQL\Type\Definition\Directive;
12
use Digia\GraphQL\Type\Definition\EnumType;
13
use Digia\GraphQL\Type\Definition\EnumValue;
14
use Digia\GraphQL\Type\Definition\Field;
15
use Digia\GraphQL\Type\Definition\InputField;
16
use Digia\GraphQL\Type\Definition\InputObjectType;
17
use Digia\GraphQL\Type\Definition\InputTypeInterface;
18
use Digia\GraphQL\Type\Definition\InterfaceType;
19
use Digia\GraphQL\Type\Definition\LeafTypeInterface;
20
use Digia\GraphQL\Type\Definition\ListType;
21
use Digia\GraphQL\Type\Definition\NamedTypeInterface;
22
use Digia\GraphQL\Type\Definition\NonNullType;
23
use Digia\GraphQL\Type\Definition\ObjectType;
24
use Digia\GraphQL\Type\Definition\OutputTypeInterface;
25
use Digia\GraphQL\Type\Definition\ScalarType;
26
use Digia\GraphQL\Type\Definition\TypeInterface;
27
use Digia\GraphQL\Type\Definition\UnionType;
28
use Digia\GraphQL\Type\Definition\WrappingTypeInterface;
29
use function Digia\GraphQL\Util\invariant;
30
use function Digia\GraphQL\Util\toString;
31
32
/**
33
 * @param $maybeThunk
34
 * @return mixed
35
 */
36
function resolveThunk($maybeThunk)
37
{
38
    return \is_callable($maybeThunk) ? $maybeThunk() : $maybeThunk;
39
}
40
41
/**
42
 * @param mixed $value
43
 * @return bool
44
 */
45
function isAssocArray($value): bool
46
{
47
    if (!\is_array($value)) {
48
        return false;
49
    }
50
    if (empty($value)) {
51
        return true;
52
    }
53
    $keys = \array_keys($value);
54
    return $keys !== \array_keys($keys);
55
}
56
57
/**
58
 * @param $type
59
 * @throws InvariantException
60
 */
61
function assertType($type)
62
{
63
    invariant(
64
        $type instanceof TypeInterface,
65
        \sprintf('Expected %s to be a GraphQL type.', toString($type))
66
    );
67
}
68
69
/**
70
 * @param mixed $type
71
 * @throws InvariantException
72
 */
73
function assertScalarType($type)
74
{
75
    invariant(
76
        $type instanceof ScalarType,
77
        \sprintf('Expected %s to be a GraphQL Scalar type.', toString($type))
78
    );
79
}
80
81
/**
82
 * @param mixed $type
83
 * @throws InvariantException
84
 */
85
function assertObjectType($type)
86
{
87
    invariant(
88
        $type instanceof ObjectType,
89
        \sprintf('Expected %s to be a GraphQL Object type.', toString($type))
90
    );
91
}
92
93
/**
94
 * @param mixed $type
95
 * @throws InvariantException
96
 */
97
function assertInterfaceType($type)
98
{
99
    invariant(
100
        $type instanceof InterfaceType,
101
        \sprintf('Expected %s to be a GraphQL Interface type.', toString($type))
102
    );
103
}
104
105
/**
106
 * @param mixed $type
107
 * @throws InvariantException
108
 */
109
function assertUnionType($type)
110
{
111
    invariant(
112
        $type instanceof UnionType,
113
        \sprintf('Expected %s to be a GraphQL Union type.', toString($type))
114
    );
115
}
116
117
/**
118
 * @param mixed $type
119
 * @throws InvariantException
120
 */
121
function assertEnumType($type)
122
{
123
    invariant(
124
        $type instanceof EnumType,
125
        \sprintf('Expected %s to be a GraphQL Enum type.', toString($type))
126
    );
127
}
128
129
/**
130
 * @param mixed $type
131
 * @throws InvariantException
132
 */
133
function assertInputObjectType($type)
134
{
135
    invariant(
136
        $type instanceof InputObjectType,
137
        \sprintf('Expected %s to be a GraphQL InputObject type.', toString($type))
138
    );
139
}
140
141
/**
142
 * @param mixed $type
143
 * @throws InvariantException
144
 */
145
function assertListType($type)
146
{
147
    invariant(
148
        $type instanceof ListType,
149
        \sprintf('Expected %s to be a GraphQL List type.', toString($type))
150
    );
151
}
152
153
/**
154
 * @param mixed $type
155
 * @throws InvariantException
156
 */
157
function assertNonNullType($type)
158
{
159
    invariant(
160
        $type instanceof NonNullType,
161
        \sprintf('Expected %s to be a GraphQL NonNull type.', toString($type))
162
    );
163
}
164
165
/**
166
 * Whether a type is an input type cannot be determined with `instanceof`
167
 * because lists and non-nulls can also be output types if the wrapped type is an output type.
168
 *
169
 * @param TypeInterface|null $type
170
 * @return bool
171
 */
172
function isInputType(?TypeInterface $type): bool
173
{
174
    return null !== $type &&
175
        ($type instanceof InputTypeInterface ||
176
            ($type instanceof WrappingTypeInterface && isInputType($type->getOfType())));
177
}
178
179
/**
180
 * @param mixed $type
181
 * @throws InvariantException
182
 */
183
function assertInputType($type)
184
{
185
    invariant(
186
        isInputType($type),
187
        \sprintf('Expected %s to be a GraphQL input type.', toString($type))
188
    );
189
}
190
191
/**
192
 * Whether a type is an output type cannot be determined with `instanceof`
193
 * because lists and non-nulls can also be output types if the wrapped type is an output type.
194
 *
195
 * @param TypeInterface|null $type
196
 * @return bool
197
 */
198
function isOutputType(?TypeInterface $type): bool
199
{
200
    return null !== $type &&
201
        ($type instanceof OutputTypeInterface ||
202
            ($type instanceof WrappingTypeInterface && isOutputType($type->getOfType())));
203
}
204
205
/**
206
 * @param mixed $type
207
 * @throws InvariantException
208
 */
209
function assertOutputType($type)
210
{
211
    invariant(
212
        isOutputType($type),
213
        \sprintf('Expected %s to be a GraphQL output type.', toString($type))
214
    );
215
}
216
217
/**
218
 * @param mixed $type
219
 * @throws InvariantException
220
 */
221
function assertLeafType($type)
222
{
223
    invariant(
224
        $type instanceof LeafTypeInterface,
225
        \sprintf('Expected %s to be a GraphQL leaf type.', toString($type))
226
    );
227
}
228
229
/**
230
 * @param mixed $type
231
 * @throws InvariantException
232
 */
233
function assertCompositeType($type)
234
{
235
    invariant(
236
        $type instanceof CompositeTypeInterface,
237
        \sprintf('Expected %s to be a GraphQL composite type.', toString($type))
238
    );
239
}
240
241
/**
242
 * @param mixed $type
243
 * @throws InvariantException
244
 */
245
function assertAbstractType($type)
246
{
247
    invariant(
248
        $type instanceof AbstractTypeInterface,
249
        \sprintf('Expected %s to be a GraphQL abstract type.', toString($type))
250
    );
251
}
252
253
/**
254
 * @param mixed $type
255
 * @throws InvariantException
256
 */
257
function assertWrappingType($type)
258
{
259
    invariant(
260
        $type instanceof WrappingTypeInterface,
261
        \sprintf('Expected %s to be a GraphQL wrapping type.', toString($type))
262
    );
263
}
264
265
/**
266
 * @param mixed $type
267
 * @return bool
268
 */
269
function isNullableType($type): bool
270
{
271
    return !($type instanceof NonNullType);
272
}
273
274
/**
275
 * @param mixed $type
276
 * @return TypeInterface
277
 * @throws InvariantException
278
 */
279
function assertNullableType($type): TypeInterface
280
{
281
    invariant(
282
        isNullableType($type),
283
        \sprintf('Expected %s to be a GraphQL nullable type.', toString($type))
284
    );
285
286
    return $type;
287
}
288
289
/**
290
 * @param TypeInterface|null $type
291
 * @return TypeInterface|null
292
 */
293
function getNullableType(?TypeInterface $type): ?TypeInterface
294
{
295
    if (null === $type) {
296
        return null;
297
    }
298
299
    return $type instanceof NonNullType ? $type->getOfType() : $type;
300
}
301
302
/**
303
 * @param mixed $type
304
 * @throws InvariantException
305
 */
306
function assertNamedType($type)
307
{
308
    invariant(
309
        $type instanceof NamedTypeInterface,
310
        \sprintf('Expected %s to be a GraphQL named type.', toString($type))
311
    );
312
}
313
314
/**
315
 * @param TypeInterface|null $type
316
 * @return NamedTypeInterface|null
317
 */
318
function getNamedType(?TypeInterface $type): ?NamedTypeInterface
319
{
320
    if (!$type) {
321
        return null;
322
    }
323
324
    $unwrappedType = $type;
325
326
    while ($unwrappedType instanceof WrappingTypeInterface) {
327
        $unwrappedType = $unwrappedType->getOfType();
328
    }
329
330
    return $unwrappedType;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $unwrappedType returns the type Digia\GraphQL\Type\Definition\TypeInterface which is incompatible with the type-hinted return null|Digia\GraphQL\Type\...tion\NamedTypeInterface.
Loading history...
331
}
332
333
/**
334
 * @param array $config
335
 * @return ScalarType
336
 * @throws InvariantException
337
 */
338
function newScalarType(array $config = []): ScalarType
339
{
340
    invariant(isset($config['name']), 'Must provide name.');
341
342
    invariant(
343
        isset($config['serialize']) && \is_callable($config['serialize']),
344
        \sprintf(
345
            '%s must provide "serialize" function. If this custom Scalar ' .
346
            'is also used as an input type, ensure "parseValue" and "parseLiteral" ' .
347
            'functions are also provided.',
348
            $config['name']
349
        )
350
    );
351
352
    if (isset($config['parseValue']) || isset($config['parseLiteral'])) {
353
        invariant(
354
            (isset($config['parseValue']) && \is_callable($config['parseValue'])) &&
355
            (isset($config['parseLiteral']) && \is_callable($config['parseLiteral'])),
356
            \sprintf('%s must provide both "parseValue" and "parseLiteral" functions.', $config['name'])
357
        );
358
    }
359
360
    return new ScalarType(
361
        $config['name'],
362
        $config['description'] ?? null,
363
        $config['serialize'],
364
        $config['parseValue'] ?? null,
365
        $config['parseLiteral'] ?? null,
366
        $config['astNode'] ?? null
367
    );
368
}
369
370
/**
371
 * @param array $config
372
 * @return EnumType
373
 * @throws InvariantException
374
 */
375
function newEnumType(array $config = []): EnumType
376
{
377
    invariant(isset($config['name']), 'Must provide name.');
378
379
    return new EnumType(
380
        $config['name'],
381
        $config['description'] ?? null,
382
        $config['values'] ?? [],
383
        $config['astNode'] ?? null
384
    );
385
}
386
387
/**
388
 * @param array $config
389
 * @return EnumValue
390
 * @throws InvariantException
391
 */
392
function newEnumValue(array $config = []): EnumValue
393
{
394
    invariant(isset($config['name']), 'Must provide name.');
395
396
    return new EnumValue(
397
        $config['name'],
398
        $config['description'] ?? null,
399
        $config['deprecationReason'] ?? null,
400
        $config['astNode'] ?? null,
401
        $config['value'] ?? null
402
    );
403
}
404
405
/**
406
 * @param array $config
407
 * @return InputObjectType
408
 * @throws InvariantException
409
 */
410
function newInputObjectType(array $config = []): InputObjectType
411
{
412
    invariant(isset($config['name']), 'Must provide name.');
413
414
    return new InputObjectType(
415
        $config['name'],
416
        $config['description'] ?? null,
417
        $config['fields'] ?? [],
418
        $config['astNode'] ?? null
419
    );
420
}
421
422
/**
423
 * @param array $config
424
 * @return InputField
425
 * @throws InvariantException
426
 */
427
function newInputField(array $config = []): InputField
428
{
429
    invariant(isset($config['name']), 'Must provide name.');
430
431
    return new InputField(
432
        $config['name'],
433
        $config['description'] ?? null,
434
        $config['type'] ?? null,
435
        $config['defaultValue'] ?? null,
436
        $config['astNode'] ?? null
437
    );
438
}
439
440
/**
441
 * @param array $config
442
 * @return InterfaceType
443
 * @throws InvariantException
444
 */
445
function newInterfaceType(array $config = []): InterfaceType
446
{
447
    invariant(isset($config['name']), 'Must provide name.');
448
449
    invariant(
450
        !isset($config['resolveType']) || null === $config['resolveType'] || \is_callable($config['resolveType']),
451
        \sprintf('%s must provide "resolveType" as a function.', $config['name'])
452
    );
453
454
    return new InterfaceType(
455
        $config['name'],
456
        $config['description'] ?? null,
457
        $config['fields'] ?? [],
458
        $config['resolveType'] ?? null,
459
        $config['astNode'] ?? null,
460
        $config['extensionASTNodes'] ?? []
461
    );
462
}
463
464
/**
465
 * @param array $config
466
 * @return ObjectType
467
 * @throws InvariantException
468
 */
469
function newObjectType(array $config = []): ObjectType
470
{
471
    invariant(isset($config['name']), 'Must provide name.');
472
473
    if (isset($config['isTypeOf'])) {
474
        invariant(
475
            \is_callable($config['isTypeOf']),
476
            \sprintf('%s must provide "isTypeOf" as a function.', $config['name'])
477
        );
478
    }
479
480
    return new ObjectType(
481
        $config['name'],
482
        $config['description'] ?? null,
483
        $config['fields'] ?? [],
484
        $config['interfaces'] ?? [],
485
        $config['isTypeOf'] ?? null,
486
        $config['astNode'] ?? null,
487
        $config['extensionASTNodes'] ?? []
488
    );
489
}
490
491
/**
492
 * @param array $config
493
 * @return Field
494
 * @throws InvariantException
495
 */
496
function newField(array $config = []): Field
497
{
498
    invariant(isset($config['name']), 'Must provide name.');
499
500
    return new Field(
501
        $config['name'],
502
        $config['description'] ?? null,
503
        $config['type'] ?? null,
504
        $config['args'] ?? [],
505
        $config['resolve'] ?? null,
506
        $config['subscribe'] ?? null,
507
        $config['deprecationReason'] ?? null,
508
        $config['astNode'] ?? null,
509
        $config['typeName'] ?? ''
510
    );
511
}
512
513
/**
514
 * @param array $config
515
 * @return Argument
516
 * @throws InvariantException
517
 */
518
function newArgument(array $config = []): Argument
519
{
520
    invariant(isset($config['name']), 'Must provide name.');
521
522
    return new Argument(
523
        $config['name'],
524
        $config['description'] ?? null,
525
        $config['type'] ?? null,
526
        $config['defaultValue'] ?? null,
527
        $config['astNode'] ?? null
528
    );
529
}
530
531
/**
532
 * @param array $config
533
 * @return UnionType
534
 * @throws InvariantException
535
 */
536
function newUnionType(array $config = []): UnionType
537
{
538
    invariant(isset($config['name']), 'Must provide name.');
539
540
    if (isset($config['resolveType'])) {
541
        invariant(
542
            \is_callable($config['resolveType']),
543
            \sprintf('%s must provide "resolveType" as a function.', $config['name'])
544
        );
545
    }
546
547
    return new UnionType(
548
        $config['name'],
549
        $config['description'] ?? null,
550
        $config['types'] ?? [],
551
        $config['resolveType'] ?? null,
552
        $config['astNode'] ?? null
553
    );
554
}
555
556
/**
557
 * @param array $config
558
 * @return Schema
559
 * @throws InvariantException
560
 */
561
function newSchema(array $config = []): Schema
562
{
563
    if (!isset($config['assumeValid']) || !$config['assumeValid']) {
564
        invariant(
565
            !isset($config['types']) || \is_array($config['types']),
566
            \sprintf('"types" must be Array if provided but got: %s.', toString($config['types']))
567
        );
568
569
        invariant(
570
            !isset($config['directives']) || \is_array($config['directives']),
571
            \sprintf('"directives" must be Array if provided but got: %s.', toString($config['directives']))
572
        );
573
    }
574
575
    return new Schema(
576
        $config['query'] ?? null,
577
        $config['mutation'] ?? null,
578
        $config['subscription'] ?? null,
579
        $config['types'] ?? [],
580
        $config['directives'] ?? [],
581
        $config['assumeValid'] ?? false,
582
        $config['astNode'] ?? null
583
    );
584
}
585
586
/**
587
 * @param array $config
588
 * @return Directive
589
 * @throws InvariantException
590
 */
591
function newDirective(array $config = []): Directive
592
{
593
    invariant(isset($config['name']), 'Must provide name.');
594
595
    invariant(
596
        isset($config['locations']) && \is_array($config['locations']),
597
        'Must provide locations for directive.'
598
    );
599
600
    return new Directive(
601
        $config['name'] ?? null,
0 ignored issues
show
Bug introduced by
It seems like $config['name'] ?? null can also be of type null; however, parameter $name of Digia\GraphQL\Type\Defin...irective::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

601
        /** @scrutinizer ignore-type */ $config['name'] ?? null,
Loading history...
602
        $config['description'] ?? null,
603
        $config['locations'],
604
        $config['args'] ?? [],
605
        $config['astNode'] ?? null,
606
        $config['typeName'] ?? ''
607
    );
608
}
609
610
/**
611
 * @param mixed $ofType
612
 * @return ListType
613
 * @throws InvariantException
614
 */
615
function newList($ofType): ListType
616
{
617
    assertType($ofType);
618
619
    return new ListType($ofType);
620
}
621
622
/**
623
 * @param mixed $ofType
624
 * @return NonNullType
625
 * @throws InvariantException
626
 */
627
function newNonNull($ofType): NonNullType
628
{
629
    assertNullableType($ofType);
630
631
    return new NonNullType($ofType);
632
}
633