Passed
Pull Request — master (#351)
by Kirill
02:28
created

InputObjectType::hasField()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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