Enum::keys()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
nc 1
cc 1
eloc 2
nop 0
crap 1
1
<?php
2
3
namespace Atrapalo\PHPTools\Enum;
4
5
/**
6
 * Class Enum
7
 * @package Atrapalo\PHPTools\Enum
8
 *
9
 * @author Guillermo González <[email protected]>
10
 */
11
abstract class Enum
12
{
13
    /**
14
     * @var mixed
15
     */
16
    protected $value;
17
18
    /**
19
     * @var array
20
     */
21
    protected static $cache = array();
22
23
    /**
24
     * @param mixed $value
25
     * @throws \Exception
26
     */
27 17
    public function __construct($value)
28
    {
29 17
        if (!$this->isValid($value)) {
30 5
            throw static::customInvalidValueException($value);
31
        }
32
33 12
        $this->value = $value;
34 12
    }
35
36
    /**
37
     * @return mixed
38
     */
39 5
    public function value()
40
    {
41 5
        return $this->value;
42
    }
43
44
    /**
45
     * @return mixed
46
     */
47 2
    public function key()
48
    {
49 2
        return static::search($this->value);
50
    }
51
52
    /**
53
     * @return string
54
     */
55 3
    public function __toString(): string
56
    {
57 3
        return (string) $this->value;
58
    }
59
60
    /**
61
     * @param Enum $enum
62
     * @return bool True if Enums are equal, false if not equal
63
     */
64 2
    public function equals(Enum $enum): bool
65
    {
66 2
        return $this->value() === $enum->value() && static::class === get_class($enum);
67
    }
68
69
    /**
70
     * @return array
71
     */
72 1
    public static function keys(): array
73
    {
74 1
        return array_keys(static::toArray());
75
    }
76
77
    /**
78
     * @return static[] Constant name in key, Enum instance in value
79
     */
80 1
    public static function values(): array
81
    {
82 1
        $values = array();
83
84 1
        foreach (static::toArray() as $key => $value) {
85 1
            $values[$key] = new static($value);
86
        }
87
88 1
        return $values;
89
    }
90
91
    /**
92
     * @return array Constant name in key, constant value in value
93
     */
94 37
    public static function toArray(): array
95
    {
96 37
        $class = get_called_class();
97 37
        if (!array_key_exists($class, static::$cache)) {
98 2
            $reflection            = new \ReflectionClass($class);
99 2
            static::$cache[$class] = $reflection->getConstants();
100
        }
101
102 37
        return static::$cache[$class];
103
    }
104
105
    /**
106
     * @param $value
107
     * @return bool
108
     */
109 24
    public static function isValid($value): bool
110
    {
111 24
        return in_array($value, static::toArray(), true);
112
    }
113
114
    /**
115
     * @param $key
116
     * @return bool
117
     */
118 1
    public static function isValidKey($key): bool
119
    {
120 1
        $array = static::toArray();
121
122 1
        return isset($array[$key]);
123
    }
124
125
    /**
126
     * @param $value
127
     * @return mixed
128
     */
129 9
    public static function search($value)
130
    {
131 9
        return array_search($value, static::toArray(), true);
132
    }
133
134
    /**
135
     * Returns a value when called statically like so: MyEnum::someValue() given SOME_VALUE is a class constant
136
     * @example MyEnum::someValue()
137
     *
138
     * @param string $name
139
     * @param array  $arguments
140
     * @return static
141
     * @throws \Exception
142
     */
143 5
    public static function __callStatic($name, $arguments)
144
    {
145 5
        $key = self::toSnakeCase($name);
146 5
        $array = static::toArray();
147 5
        if (array_key_exists($key, $array)) {
148 2
            return new static($array[$key]);
149
        }
150
151 3
        throw static::customUnknownStaticMethodException($name);
152
    }
153
154
155
    /**
156
     * Check if a given key is selected using the "isKey" syntax.
157
     * @example $myEnum->isSomeValue()
158
     *
159
     * @param string $method
160
     * @param        $arguments
161
     * @return bool
162
     * @throws \Exception
163
     */
164 5
    public function __call($method, $arguments): bool
165
    {
166 5
        if (substr($method, 0, 2) === 'is')  {
167 4
            $key = $this->toSnakeCase(substr($method, 2));
168 4
            $array = static::toArray();
169 4
            if (array_key_exists($key, $array)) {
170 2
                return $this->value() === $array[$key];
171
            }
172
        }
173
174 3
        throw static::customUnknownMethodException($method);
175
    }
176
177
    /**
178
     * @param string $string
179
     * @return string
180
     */
181 9
    private static function toSnakeCase(string $string): string
182
    {
183 9
        return strtoupper(preg_replace(
184 9
            '/(?<=\d)(?=[A-Za-z])|(?<=[A-Za-z])(?=\d)|(?<=[a-z])(?=[A-Z])/',
185 9
            '_',
186 9
            $string
187
        ));
188
    }
189
190
    /**
191
     * @param string $value
192
     * @return \Exception
193
     */
194 3
    public static function customInvalidValueException(string $value): \Exception
195
    {
196 3
        return new \UnexpectedValueException("Value '$value' is not part of the enum " . get_called_class());
197
    }
198
199
    /**
200
     * @param string $method
201
     * @return \Exception
202
     */
203 2
    public static function customUnknownStaticMethodException(string $method): \Exception
204
    {
205 2
        return new \BadMethodCallException("No static method or enum constant '$method' in class " . get_called_class());
206
    }
207
208
    /**
209
     * @param string $method
210
     * @return \Exception
211
     */
212 2
    public static function customUnknownMethodException(string $method): \Exception
213
    {
214 2
        return new \BadMethodCallException(sprintf('The method "%s" is not defined.', $method));
215
    }
216
}