Passed
Pull Request — master (#201)
by Christoffer
02:16
created

InputObjectType::afterConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
1
<?php
2
3
namespace Digia\GraphQL\Type\Definition;
4
5
use Digia\GraphQL\Error\InvariantException;
6
use Digia\GraphQL\Language\Node\ASTNodeAwareInterface;
7
use Digia\GraphQL\Language\Node\ASTNodeTrait;
8
use Digia\GraphQL\Language\Node\InputObjectTypeDefinitionNode;
9
use function Digia\GraphQL\Type\isAssocArray;
10
use function Digia\GraphQL\Type\resolveThunk;
11
use function Digia\GraphQL\Util\invariant;
12
13
/**
14
 * Input Object Type Definition
15
 *
16
 * An input object defines a structured collection of fields which may be
17
 * supplied to a field argument.
18
 *
19
 * Using `NonNull` will ensure that a value must be provided by the query
20
 *
21
 * Example:
22
 *
23
 *     $GeoPoint = newInputObjectType([
24
 *       'name': 'GeoPoint',
25
 *       'fields': [
26
 *         'lat': ['type' => newNonNull(Float())],
27
 *         'lon': ['type' => newNonNull(Float())],
28
 *         'alt': ['type' => Float(), 'defaultValue' => 0],
29
 *       ]
30
 *     ]);
31
 */
32
class InputObjectType implements TypeInterface, NamedTypeInterface, InputTypeInterface, ASTNodeAwareInterface
33
{
34
    use NameTrait;
35
    use DescriptionTrait;
36
    use ASTNodeTrait;
37
38
    /**
39
     * Fields can be defined either as an array or as a thunk.
40
     * Using thunks allows for cross-referencing of fields.
41
     *
42
     * @var array|callable
43
     */
44
    protected $fieldsOrThunk;
45
46
    /**
47
     * A key-value map over field names and their corresponding field instances.
48
     *
49
     * @var null|InputField[]
50
     */
51
    protected $fieldMap;
52
53
    /**
54
     * InputObjectType constructor.
55
     *
56
     * @param string                             $name
57
     * @param null|string                        $description
58
     * @param array|callable                     $fieldsOrThunk
59
     * @param InputObjectTypeDefinitionNode|null $astNode
60
     * @throws InvariantException
61
     */
62
    public function __construct(
63
        string $name,
64
        ?string $description,
65
        $fieldsOrThunk,
66
        ?InputObjectTypeDefinitionNode $astNode
67
    ) {
68
        $this->name          = $name;
69
        $this->description   = $description;
70
        $this->fieldsOrThunk = $fieldsOrThunk;
71
        $this->astNode       = $astNode;
72
73
        invariant(null !== $this->getName(), 'Must provide name.');
74
    }
75
76
    /**
77
     * @return InputField[]
78
     * @throws InvariantException
79
     */
80
    public function getFields(): array
81
    {
82
        if (!isset($this->fieldMap)) {
83
            $this->fieldMap = $this->buildFieldMap($this->fieldsOrThunk);
84
        }
85
86
        return $this->fieldMap;
87
    }
88
89
    /**
90
     * @param array|callable $fieldsOrThunk
91
     * @return array
92
     * @throws InvariantException
93
     */
94
    protected function buildFieldMap($fieldsOrThunk): array
95
    {
96
        $fields = resolveThunk($fieldsOrThunk);
97
98
        invariant(
99
            isAssocArray($fields),
100
            \sprintf(
101
                '%s fields must be an associative array with field names as keys or a function which returns such an array.',
102
                $this->name
103
            )
104
        );
105
106
        $fieldMap = [];
107
108
        foreach ($fields as $fieldName => $fieldConfig) {
109
            invariant(
110
                !isset($fieldConfig['resolve']),
111
                \sprintf(
112
                    '%s.%s field type has a resolve property, but Input Types cannot define resolvers.',
113
                    $this->name,
114
                    $fieldName
115
                )
116
            );
117
118
            $fieldMap[$fieldName] = new InputField(
119
                $fieldName,
120
                $fieldConfig['type'] ?? null,
121
                $fieldConfig['defaultValue'] ?? null,
122
                $fieldConfig['description'] ?? null,
123
                $fieldConfig['astNode'] ?? null
124
            );
125
        }
126
127
        return $fieldMap;
128
    }
129
}
130