Passed
Push — master ( e86c97...dfc587 )
by Christoffer
02:07
created

newScalarType()   C

Complexity

Conditions 7
Paths 2

Size

Total Lines 29
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 20
nc 2
nop 1
dl 0
loc 29
rs 6.7272
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
 * Returns a new Scalar type after ensuring that its state is valid.
335
 *
336
 * @param array $config
337
 * @return ScalarType
338
 * @throws InvariantException
339
 */
340
function newScalarType(array $config = []): ScalarType
341
{
342
    invariant(isset($config['name']), 'Must provide name.');
343
344
    invariant(
345
        isset($config['serialize']) && \is_callable($config['serialize']),
346
        \sprintf(
347
            '%s must provide "serialize" function. If this custom Scalar ' .
348
            'is also used as an input type, ensure "parseValue" and "parseLiteral" ' .
349
            'functions are also provided.',
350
            $config['name']
351
        )
352
    );
353
354
    if (isset($config['parseValue']) || isset($config['parseLiteral'])) {
355
        invariant(
356
            (isset($config['parseValue']) && \is_callable($config['parseValue'])) &&
357
            (isset($config['parseLiteral']) && \is_callable($config['parseLiteral'])),
358
            \sprintf('%s must provide both "parseValue" and "parseLiteral" functions.', $config['name'])
359
        );
360
    }
361
362
    return new ScalarType(
363
        $config['name'],
364
        $config['description'] ?? null,
365
        $config['serialize'],
366
        $config['parseValue'] ?? null,
367
        $config['parseLiteral'] ?? null,
368
        $config['astNode'] ?? null
369
    );
370
}
371
372
/**
373
 * Returns a new Enum type after ensuring that its state is valid.
374
 *
375
 * @param array $config
376
 * @return EnumType
377
 * @throws InvariantException
378
 */
379
function newEnumType(array $config = []): EnumType
380
{
381
    invariant(isset($config['name']), 'Must provide name.');
382
383
    return new EnumType(
384
        $config['name'],
385
        $config['description'] ?? null,
386
        $config['values'] ?? [],
387
        $config['astNode'] ?? null
388
    );
389
}
390
391
/**
392
 * Returns a new Enum value after ensuring that its state is valid.
393
 *
394
 * @param array $config
395
 * @return EnumValue
396
 * @throws InvariantException
397
 */
398
function newEnumValue(array $config = []): EnumValue
399
{
400
    invariant(isset($config['name']), 'Must provide name.');
401
402
    return new EnumValue(
403
        $config['name'],
404
        $config['description'] ?? null,
405
        $config['deprecationReason'] ?? null,
406
        $config['astNode'] ?? null,
407
        $config['value'] ?? null
408
    );
409
}
410
411
/**
412
 * Returns a new Input Object type after ensuring that its state is valid.
413
 *
414
 * @param array $config
415
 * @return InputObjectType
416
 * @throws InvariantException
417
 */
418
function newInputObjectType(array $config = []): InputObjectType
419
{
420
    invariant(isset($config['name']), 'Must provide name.');
421
422
    return new InputObjectType(
423
        $config['name'],
424
        $config['description'] ?? null,
425
        $config['fields'] ?? [],
426
        $config['astNode'] ?? null
427
    );
428
}
429
430
/**
431
 * Returns a new Input field after ensuring that its state is valid.
432
 *
433
 * @param array $config
434
 * @return InputField
435
 * @throws InvariantException
436
 */
437
function newInputField(array $config = []): InputField
438
{
439
    invariant(isset($config['name']), 'Must provide name.');
440
441
    return new InputField(
442
        $config['name'],
443
        $config['description'] ?? null,
444
        $config['type'] ?? null,
445
        $config['defaultValue'] ?? null,
446
        $config['astNode'] ?? null
447
    );
448
}
449
450
/**
451
 * Returns a new Interface type after ensuring that its state is valid.
452
 *
453
 * @param array $config
454
 * @return InterfaceType
455
 * @throws InvariantException
456
 */
457
function newInterfaceType(array $config = []): InterfaceType
458
{
459
    invariant(isset($config['name']), 'Must provide name.');
460
461
    invariant(
462
        !isset($config['resolveType']) || null === $config['resolveType'] || \is_callable($config['resolveType']),
463
        \sprintf('%s must provide "resolveType" as a function.', $config['name'])
464
    );
465
466
    return new InterfaceType(
467
        $config['name'],
468
        $config['description'] ?? null,
469
        $config['fields'] ?? [],
470
        $config['resolveType'] ?? null,
471
        $config['astNode'] ?? null,
472
        $config['extensionASTNodes'] ?? []
473
    );
474
}
475
476
/**
477
 * Returns a new Object type after ensuring that its state is valid.
478
 *
479
 * @param array $config
480
 * @return ObjectType
481
 * @throws InvariantException
482
 */
483
function newObjectType(array $config = []): ObjectType
484
{
485
    invariant(isset($config['name']), 'Must provide name.');
486
487
    if (isset($config['isTypeOf'])) {
488
        invariant(
489
            \is_callable($config['isTypeOf']),
490
            \sprintf('%s must provide "isTypeOf" as a function.', $config['name'])
491
        );
492
    }
493
494
    return new ObjectType(
495
        $config['name'],
496
        $config['description'] ?? null,
497
        $config['fields'] ?? [],
498
        $config['interfaces'] ?? [],
499
        $config['isTypeOf'] ?? null,
500
        $config['astNode'] ?? null,
501
        $config['extensionASTNodes'] ?? []
502
    );
503
}
504
505
/**
506
 * Returns a new Field after ensuring that its state is valid.
507
 *
508
 * @param array $config
509
 * @return Field
510
 * @throws InvariantException
511
 */
512
function newField(array $config = []): Field
513
{
514
    invariant(isset($config['name']), 'Must provide name.');
515
516
    return new Field(
517
        $config['name'],
518
        $config['description'] ?? null,
519
        $config['type'] ?? null,
520
        $config['args'] ?? [],
521
        $config['resolve'] ?? null,
522
        $config['subscribe'] ?? null,
523
        $config['deprecationReason'] ?? null,
524
        $config['astNode'] ?? null,
525
        $config['typeName'] ?? ''
526
    );
527
}
528
529
/**
530
 * Returns a new Argument after ensuring that its state is valid.
531
 *
532
 * @param array $config
533
 * @return Argument
534
 * @throws InvariantException
535
 */
536
function newArgument(array $config = []): Argument
537
{
538
    invariant(isset($config['name']), 'Must provide name.');
539
540
    return new Argument(
541
        $config['name'],
542
        $config['description'] ?? null,
543
        $config['type'] ?? null,
544
        $config['defaultValue'] ?? null,
545
        $config['astNode'] ?? null
546
    );
547
}
548
549
/**
550
 * Returns a new Union type after ensuring that its state is valid.
551
 *
552
 * @param array $config
553
 * @return UnionType
554
 * @throws InvariantException
555
 */
556
function newUnionType(array $config = []): UnionType
557
{
558
    invariant(isset($config['name']), 'Must provide name.');
559
560
    if (isset($config['resolveType'])) {
561
        invariant(
562
            \is_callable($config['resolveType']),
563
            \sprintf('%s must provide "resolveType" as a function.', $config['name'])
564
        );
565
    }
566
567
    return new UnionType(
568
        $config['name'],
569
        $config['description'] ?? null,
570
        $config['types'] ?? [],
571
        $config['resolveType'] ?? null,
572
        $config['astNode'] ?? null
573
    );
574
}
575
576
/**
577
 * Returns a new Schema after ensuring that its state is valid.
578
 *
579
 * @param array $config
580
 * @return Schema
581
 * @throws InvariantException
582
 */
583
function newSchema(array $config = []): Schema
584
{
585
    if (!isset($config['assumeValid']) || !$config['assumeValid']) {
586
        if (isset($config['types'])) {
587
            invariant(
588
                \is_array($config['types']),
589
                \sprintf('"types" must be Array if provided but got: %s.', toString($config['types']))
590
            );
591
        }
592
593
        if (isset($config['directives'])) {
594
            invariant(
595
                \is_array($config['directives']),
596
                \sprintf('"directives" must be Array if provided but got: %s.', toString($config['directives']))
597
            );
598
        }
599
    }
600
601
    return new Schema(
602
        $config['query'] ?? null,
603
        $config['mutation'] ?? null,
604
        $config['subscription'] ?? null,
605
        $config['types'] ?? [],
606
        $config['directives'] ?? [],
607
        $config['assumeValid'] ?? false,
608
        $config['astNode'] ?? null
609
    );
610
}
611
612
/**
613
 * Returns a new Directive after ensuring that its state is valid.
614
 *
615
 * @param array $config
616
 * @return Directive
617
 * @throws InvariantException
618
 */
619
function newDirective(array $config = []): Directive
620
{
621
    invariant(isset($config['name']), 'Must provide name.');
622
623
    invariant(
624
        isset($config['locations']) && \is_array($config['locations']),
625
        'Must provide locations for directive.'
626
    );
627
628
    return new Directive(
629
        $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

629
        /** @scrutinizer ignore-type */ $config['name'] ?? null,
Loading history...
630
        $config['description'] ?? null,
631
        $config['locations'],
632
        $config['args'] ?? [],
633
        $config['astNode'] ?? null,
634
        $config['typeName'] ?? ''
635
    );
636
}
637
638
/**
639
 * Returns a new List type after ensuring that its state is valid.
640
 *
641
 * @param mixed $ofType
642
 * @return ListType
643
 * @throws InvariantException
644
 */
645
function newList($ofType): ListType
646
{
647
    assertType($ofType);
648
649
    return new ListType($ofType);
650
}
651
652
/**
653
 * Returns a new Non-null type after ensuring that its state is valid.
654
 *
655
 * @param mixed $ofType
656
 * @return NonNullType
657
 * @throws InvariantException
658
 */
659
function newNonNull($ofType): NonNullType
660
{
661
    assertNullableType($ofType);
662
663
    return new NonNullType($ofType);
664
}
665