Completed
Push — master ( 970dd0...173ef8 )
by Julián
02:34
created

AbstractEnum::__clone()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 0
c 0
b 0
f 0
dl 0
loc 2
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
/*
4
 * enum (https://github.com/phpgears/enum).
5
 * Enum object for PHP.
6
 *
7
 * @license MIT
8
 * @link https://github.com/phpgears/enum
9
 * @author Julián Gutiérrez <[email protected]>
10
 */
11
12
declare(strict_types=1);
13
14
namespace Gears\Enum;
15
16
use Gears\Enum\Exception\EnumException;
17
use Gears\Enum\Exception\InvalidEnumNameException;
18
use Gears\Enum\Exception\InvalidEnumValueException;
19
use Gears\Immutability\ImmutabilityBehaviour;
20
21
/**
22
 * Base immutable enum class.
23
 */
24
abstract class AbstractEnum implements Enum
25
{
26
    use ImmutabilityBehaviour;
27
28
    /**
29
     * Enum class constants map.
30
     *
31
     * @var array
32
     */
33
    protected static $enumCacheMap = [];
34
35
    /**
36
     * Enum value.
37
     *
38
     * @var mixed
39
     */
40
    private $value;
41
42
    /**
43
     * AbstractEnum constructor.
44
     *
45
     * @param mixed $value
46
     *
47
     * @throws InvalidEnumValueException
48
     */
49
    final public function __construct($value)
50
    {
51
        $this->assertImmutable();
52
53
        $this->checkValue($value);
54
55
        $this->value = $value;
56
    }
57
58
    /**
59
     * Value based static constructor.
60
     *
61
     * @param string  $name
62
     * @param mixed[] $params
63
     *
64
     * @return self
65
     */
66
    final public static function __callStatic(string $name, array $params)
67
    {
68
        if (\count($params) !== 0) {
69
            throw new EnumException('Enum static constructor must be called with no parameters');
70
        }
71
72
        $enumerator = static::normalizeName($name);
73
        $enumerators = static::getEnumerators();
74
75
        if (!\array_key_exists($enumerator, $enumerators)) {
76
            throw new InvalidEnumNameException(\sprintf(
77
                '"%s" is not a valid enumerator for enum "%s"',
78
                $name,
79
                static::class
80
            ));
81
        }
82
83
        return new static($enumerators[$enumerator]);
84
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89
    final public function isEqualTo(Enum $enum): bool
90
    {
91
        return \get_class($enum) === static::class && $enum->getValue() === $this->value;
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97
    final public function isAnyOf(array $enums): bool
98
    {
99
        foreach ($enums as $enum) {
100
            if ($this->isEqualTo($enum)) {
101
                return true;
102
            }
103
        }
104
105
        return false;
106
    }
107
108
    /**
109
     * {@inheritdoc}
110
     */
111
    final public function getValue()
112
    {
113
        return $this->value;
114
    }
115
116
    /**
117
     * @return mixed[]
118
     */
119
    final public function __sleep(): array
120
    {
121
        throw new EnumException(\sprintf('Enum "%s" cannot be serialized', static::class));
122
    }
123
124
    final public function __wakeup(): void
125
    {
126
        throw new EnumException(\sprintf('Enum "%s" cannot be unserialized', static::class));
127
    }
128
129
    /**
130
     * @return mixed[]
131
     *
132
     * @SuppressWarnings(PHPMD.CamelCaseMethodName)
133
     */
134
    final public function __serialize(): array
135
    {
136
        throw new EnumException(\sprintf('Enum "%s" cannot be serialized', static::class));
137
    }
138
139
    /**
140
     * @SuppressWarnings(PHPMD.CamelCaseMethodName)
141
     */
142
    final public function __unserialize(): void
143
    {
144
        throw new EnumException(\sprintf('Enum "%s" cannot be unserialized', static::class));
145
    }
146
147
    final public function __clone()
148
    {
149
    }
150
151
    /**
152
     * Check enum value validity.
153
     *
154
     * @param mixed $value
155
     *
156
     * @throws InvalidEnumValueException
157
     */
158
    private function checkValue($value): void
159
    {
160
        if (!\in_array($value, static::getEnumerators(), true)) {
161
            throw new InvalidEnumValueException(\sprintf(
162
                '"%s" is not a valid value for enum "%s"',
163
                $value,
164
                static::class
165
            ));
166
        }
167
    }
168
169
    /**
170
     * Get list of enumerators.
171
     *
172
     * @return array<string, mixed>
173
     */
174
    private static function getEnumerators(): array
175
    {
176
        $class = static::class;
177
178
        if (!isset(static::$enumCacheMap[$class])) {
179
            $constants = [];
180
            foreach ((new \ReflectionClass($class))->getReflectionConstants() as $reflectionConstant) {
181
                if ($reflectionConstant->isPublic()) {
182
                    $constants[static::normalizeName($reflectionConstant->getName())] = $reflectionConstant->getValue();
183
                }
184
            }
185
186
            static::$enumCacheMap[$class] = $constants;
187
        }
188
189
        return static::$enumCacheMap[$class];
190
    }
191
192
    /**
193
     * Normalize name.
194
     *
195
     * @param string $name
196
     *
197
     * @return string
198
     */
199
    private static function normalizeName(string $name): string
200
    {
201
        return \strtoupper($name);
202
    }
203
204
    /**
205
     * {@inheritdoc}
206
     *
207
     * @return string[]
208
     */
209
    final protected function getAllowedInterfaces(): array
210
    {
211
        return [Enum::class];
212
    }
213
}
214