Passed
Pull Request — master (#132)
by Christoffer
04:13 queued 01:55
created

EnumType::serialize()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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