Passed
Push — master ( 05583d...7da3fd )
by Julián
05:51
created

AbstractEnum::getEnumerators()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
c 0
b 0
f 0
dl 0
loc 16
rs 10
cc 4
nc 2
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
     * Check enum value validity.
118
     *
119
     * @param mixed $value
120
     *
121
     * @throws InvalidEnumValueException
122
     */
123
    private function checkValue($value): void
124
    {
125
        if (!\in_array($value, static::getEnumerators(), true)) {
126
            throw new InvalidEnumValueException(\sprintf(
127
                '"%s" is not a valid value for enum "%s"',
128
                $value,
129
                static::class
130
            ));
131
        }
132
    }
133
134
    /**
135
     * Get list of enumerators.
136
     *
137
     * @return array<string, mixed>
138
     */
139
    private static function getEnumerators(): array
140
    {
141
        $class = static::class;
142
143
        if (!isset(static::$enumCacheMap[$class])) {
144
            $constants = [];
145
            foreach ((new \ReflectionClass($class))->getReflectionConstants() as $reflectionConstant) {
146
                if ($reflectionConstant->isPublic()) {
147
                    $constants[static::normalizeName($reflectionConstant->getName())] = $reflectionConstant->getValue();
148
                }
149
            }
150
151
            static::$enumCacheMap[$class] = $constants;
152
        }
153
154
        return static::$enumCacheMap[$class];
155
    }
156
157
    /**
158
     * Normalize name.
159
     *
160
     * @param string $name
161
     *
162
     * @return string
163
     */
164
    private static function normalizeName(string $name): string
165
    {
166
        return \strtoupper($name);
167
    }
168
169
    /**
170
     * {@inheritdoc}
171
     *
172
     * @return string[]
173
     */
174
    final protected function getAllowedInterfaces(): array
175
    {
176
        return [Enum::class];
177
    }
178
}
179