Completed
Pull Request — master (#134)
by Christoffer
02:23
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\Config\ConfigObject;
6
use Digia\GraphQL\Error\InvariantException;
7
use Digia\GraphQL\Language\Node\NodeAwareInterface;
8
use Digia\GraphQL\Language\Node\NodeTrait;
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 = GraphQLInputObjectType([
24
 *       'name': 'GeoPoint',
25
 *       'fields': [
26
 *         'lat': ['type' => GraphQLNonNull(GraphQLFloat())],
27
 *         'lon': ['type' => GraphQLNonNull(GraphQLFloat())],
28
 *         'alt': ['type' => GraphQLFloat(), 'defaultValue' => 0],
29
 *       ]
30
 *     ]);
31
 */
32
class InputObjectType extends ConfigObject implements TypeInterface, NamedTypeInterface, InputTypeInterface, NodeAwareInterface
33
{
34
    use NameTrait;
35
    use DescriptionTrait;
36
    use NodeTrait;
37
38
    /**
39
     * @var array|callable
40
     */
41
    protected $fieldsOrThunk;
42
43
    /**
44
     * @var null|InputField[]
45
     */
46
    protected $fieldMap;
47
48
    /**
49
     * @inheritdoc
50
     */
51
    protected function afterConfig(): void
52
    {
53
        invariant(null !== $this->getName(), 'Must provide name.');
54
    }
55
56
    /**
57
     * @return InputField[]
58
     * @throws InvariantException
59
     */
60
    public function getFields(): array
61
    {
62
        if (!isset($this->fieldMap)) {
63
            $this->fieldMap = $this->buildFieldMap($this->fieldsOrThunk ?? []);
64
        }
65
        return $this->fieldMap;
66
    }
67
68
    /**
69
     * Input fields are created using the `ConfigAwareTrait` constructor which will automatically
70
     * call this method when setting arguments from `$config['fields']`.
71
     *
72
     * @param array|callable $fieldsOrThunk
73
     * @return $this
74
     */
75
    protected function setFields($fieldsOrThunk)
76
    {
77
        $this->fieldsOrThunk = $fieldsOrThunk;
78
        return $this;
79
    }
80
81
    /**
82
     * @param array|callable $fieldsOrThunk
83
     * @return array
84
     * @throws InvariantException
85
     */
86
    protected function buildFieldMap($fieldsOrThunk): array
87
    {
88
        $fields = resolveThunk($fieldsOrThunk) ?? [];
89
90
        invariant(
91
            isAssocArray($fields),
92
            \sprintf(
93
                '%s fields must be an associative array with field names as keys or a function which returns such an array.',
94
                $this->getName()
95
            )
96
        );
97
98
        $fieldMap = [];
99
100
        foreach ($fields as $fieldName => $fieldConfig) {
101
            invariant(
102
                !isset($fieldConfig['resolve']),
103
                \sprintf(
104
                    '%s.%s field type has a resolve property, but Input Types cannot define resolvers.',
105
                    $this->getName(),
106
                    $fieldName
107
                )
108
            );
109
110
            $fieldConfig['name'] = $fieldName;
111
            $fieldMap[$fieldName] = new InputField($fieldConfig);
112
        }
113
114
        return $fieldMap;
115
    }
116
}
117