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