Completed
Pull Request — master (#134)
by Christoffer
02:23
created

EnumType::getValues()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
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\EnumValueNode;
8
use Digia\GraphQL\Language\Node\NodeAwareInterface;
9
use Digia\GraphQL\Language\Node\NodeInterface;
10
use Digia\GraphQL\Language\Node\NodeTrait;
11
use function Digia\GraphQL\Type\isAssocArray;
12
use function Digia\GraphQL\Util\invariant;
13
use function Digia\GraphQL\Util\toString;
14
15
/**
16
 * Enum Type Definition
17
 *
18
 * Some leaf values of requests and input values are Enums. GraphQL serializes
19
 * Enum values as strings, however internally Enums can be represented by any
20
 * kind of type, often integers.
21
 *
22
 * Example:
23
 *
24
 *     $RGBType = new GraphQLEnumType([
25
 *       'name'   => 'RGB',
26
 *       'values' => [
27
 *         'RED'   => ['value' => 0],
28
 *         'GREEN' => ['value' => 1],
29
 *         'BLUE'  => ['value' => 2]
30
 *       ]
31
 *     ]);
32
 *
33
 * Note: If a value is not provided in a definition, the name of the enum value
34
 * will be used as its internal value.
35
 */
36
class EnumType extends ConfigObject implements TypeInterface, NamedTypeInterface, InputTypeInterface,
37
    LeafTypeInterface, OutputTypeInterface, NodeAwareInterface
38
{
39
    use NameTrait;
40
    use DescriptionTrait;
41
    use NodeTrait;
42
43
    /**
44
     * @var array
45
     */
46
    protected $valueMap;
47
48
    /**
49
     * @var EnumValue[]
50
     */
51
    protected $values;
52
53
    /**
54
     * @inheritdoc
55
     */
56
    protected function afterConfig(): void
57
    {
58
        invariant(null !== $this->getName(), 'Must provide name.');
59
    }
60
61
    /**
62
     * @param $value
63
     * @return null|string
64
     * @throws InvariantException
65
     */
66
    public function serialize($value)
67
    {
68
        $enumValue = $this->getValueByValue($value);
69
70
        if ($enumValue) {
71
            return $enumValue->getName();
72
        }
73
74
        return null;
75
    }
76
77
    /**
78
     * @param $value
79
     * @return mixed|null
80
     * @throws InvariantException
81
     */
82
    public function parseValue($value)
83
    {
84
        if (\is_string($value)) {
85
            $enumValue = $this->getValueByName($value);
86
87
            if ($enumValue !== null) {
88
                return $enumValue->getValue();
89
            }
90
        }
91
92
        return null;
93
    }
94
95
    /**
96
     * @param NodeInterface $node
97
     * @return mixed|null
98
     * @throws InvariantException
99
     */
100
    public function parseLiteral(NodeInterface $node)
101
    {
102
        if ($node instanceof EnumValueNode) {
103
            $enumValue = $this->getValueByName($node->getValue());
104
105
            if ($enumValue !== null) {
106
                return $enumValue->getValue();
107
            }
108
        }
109
110
        return null;
111
    }
112
113
    /**
114
     * @param string $name
115
     * @return EnumValue|null
116
     * @throws InvariantException
117
     */
118
    public function getValue(string $name): ?EnumValue
119
    {
120
        return $this->getValueByName($name);
121
    }
122
123
    /**
124
     * @return EnumValue[]
125
     * @throws InvariantException
126
     */
127
    public function getValues(): array
128
    {
129
        if (!isset($this->values)) {
130
            $this->values = $this->buildValues($this->valueMap ?? []);
131
        }
132
        return $this->values;
133
    }
134
135
    /**
136
     * @param array $valueMap
137
     * @return $this
138
     */
139
    protected function setValues(array $valueMap): EnumType
140
    {
141
        $this->valueMap = $valueMap;
142
        return $this;
143
    }
144
145
    /**
146
     * @param string $name
147
     * @return EnumValue|null
148
     * @throws InvariantException
149
     */
150
    protected function getValueByName(string $name): ?EnumValue
151
    {
152
        foreach ($this->getValues() as $enumValue) {
153
            if ($enumValue->getName() === $name) {
154
                return $enumValue;
155
            }
156
        }
157
158
        return null;
159
    }
160
161
    /**
162
     * @param mixed $value
163
     * @return EnumValue|null
164
     * @throws InvariantException
165
     */
166
    protected function getValueByValue($value): ?EnumValue
167
    {
168
        foreach ($this->getValues() as $enumValue) {
169
            if ($enumValue->getValue() === $value) {
170
                return $enumValue;
171
            }
172
        }
173
174
        return null;
175
    }
176
177
    /**
178
     * @param array $valueMap
179
     * @return array
180
     * @throws InvariantException
181
     */
182
    protected function buildValues(array $valueMap): array
183
    {
184
        invariant(
185
            isAssocArray($valueMap),
186
            \sprintf('%s values must be an associative array with value names as keys.', $this->getName())
187
        );
188
189
        $values = [];
190
191
        foreach ($valueMap as $valueName => $valueConfig) {
192
            invariant(
193
                isAssocArray($valueConfig),
194
                \sprintf(
195
                    '%s.%s must refer to an object with a "value" key representing an internal value but got: %s',
196
                    $this->getName(),
197
                    $valueName,
198
                    toString($valueConfig)
199
                )
200
            );
201
202
            invariant(
203
                !isset($valueConfig['isDeprecated']),
204
                \sprintf(
205
                    '%s.%s should provided "deprecationReason" instead of "isDeprecated".',
206
                    $this->getName(),
207
                    $valueName
208
                )
209
            );
210
211
            $values[] = new EnumValue(\array_merge($valueConfig, ['name' => $valueName]));
212
        }
213
214
        return $values;
215
    }
216
}
217