Completed
Push — master ( cba8c1...0e1bf9 )
by Ivannis Suárez
03:36
created

Enum::name()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
/*
4
 * This file is part of the Cubiche package.
5
 *
6
 * Copyright (c) Cubiche
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Cubiche\Core\Enum;
13
14
use Cubiche\Core\Equatable\EquatableInterface;
15
use Cubiche\Core\Hashable\HashCoder;
16
17
/**
18
 * Enum class based on http://github.com/myclabs/php-enum.
19
 *
20
 * @method static static __DEFAULT()
21
 *
22
 * @author Karel Osorio Ramírez <[email protected]>
23
 */
24
abstract class Enum implements EquatableInterface
25
{
26
    /**
27
     * @var mixed
28
     */
29
    protected $value;
30
31
    /**
32
     * @var array
33
     */
34
    protected static $cache = array();
35
36
    /**
37
     * @var array
38
     */
39
    protected static $defaultCache = array();
40
41
    /**
42
     * @param string $name
43
     * @param array  $arguments
44
     *
45
     * @return static
46
     *
47
     * @throws \BadMethodCallException
48
     */
49
    public static function __callStatic($name, $arguments)
50
    {
51
        $array = static::toArray();
52
        if (\strtoupper($name) === '__DEFAULT' && isset(static::$defaultCache[static::class])) {
53
            return new static(static::$defaultCache[static::class]);
54
        }
55
56
        if (isset($array[$name])) {
57
            return new static($array[$name]);
58
        }
59
60
        throw new \BadMethodCallException(
61
            \sprintf('No static method or enum constant %S in class %s', $name, static::class)
62
        );
63
    }
64
65
    /**
66
     * Creates a new value of some type.
67
     *
68
     * @param mixed $value
69
     *
70
     * @throws \UnexpectedValueException if incompatible type is given.
71
     */
72
    public function __construct($value)
73
    {
74
        if (!$this->isValid($value)) {
75
            throw new \UnexpectedValueException(
76
                \sprintf('Value %s is not part of the enum %s.', $value, static::class)
77
            );
78
        }
79
80
        $this->value = $value;
81
    }
82
83
    /**
84
     * @return mixed
85
     */
86
    public function value()
87
    {
88
        return $this->value;
89
    }
90
91
    /**
92
     * @return string
93
     */
94
    public function name()
95
    {
96
        return static::search($this->value);
97
    }
98
99
    /**
100
     * @param mixed $value
101
     *
102
     * @return bool
103
     */
104
    public function is($value)
105
    {
106
        return $this->value === $value;
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     */
112
    public function equals($other)
113
    {
114
        return $other instanceof static && $this->is($other->value());
115
    }
116
117
    /**
118
     * {@inheritdoc}
119
     */
120
    public function hashCode()
121
    {
122
        return HashCoder::defaultHashCoder()->hashCode($this->value());
123
    }
124
125
    /**
126
     * @return string
127
     */
128
    public function __toString()
129
    {
130
        return (string) $this->value;
131
    }
132
133
    /**
134
     * @param $value
135
     *
136
     * @return bool
137
     */
138
    public static function isValid($value)
139
    {
140
        return \in_array($value, static::toArray(), true);
141
    }
142
143
    /**
144
     * @param $name
145
     *
146
     * @return bool
147
     */
148
    public static function isValidName($name)
149
    {
150
        $array = static::toArray();
151
152
        return isset($array[$name]);
153
    }
154
155
    /**
156
     * @return array
157
     */
158
    public static function names()
159
    {
160
        return \array_keys(static::toArray());
161
    }
162
163
    /**
164
     * @return static[]
165
     */
166
    public static function values()
167
    {
168
        $values = array();
169
        foreach (static::toArray() as $key => $value) {
170
            $values[$key] = new static($value);
171
        }
172
173
        return $values;
174
    }
175
176
    /**
177
     * @return array
178
     */
179
    public static function toArray()
180
    {
181
        if (!isset(static::$cache[static::class])) {
182
            static::$cache[static::class] = self::constants(static::class);
183
            if (!isset(static::$defaultCache[static::class]) && !empty(static::$cache[static::class])) {
184
                static::$defaultCache[static::class] = \array_values(static::$cache[static::class])[0];
185
            }
186
        }
187
188
        return static::$cache[static::class];
189
    }
190
191
    /**
192
     * @param Enum $enum
193
     * @param Enum $default
194
     *
195
     * @throws \InvalidArgumentException
196
     *
197
     * @return static
198
     */
199
    public static function ensure(Enum $enum = null, Enum $default = null)
200
    {
201
        if ($enum instanceof static) {
202
            return $enum;
203
        }
204
        if ($enum === null) {
205
            return $default === null ? static::__DEFAULT() : static::ensure($default);
206
        }
207
208
        throw new \InvalidArgumentException(\sprintf('The enum parameter must be a %s instance', static::class));
209
    }
210
211
    /**
212
     * @param $value
213
     *
214
     * @return mixed
215
     */
216
    protected static function search($value)
217
    {
218
        return \array_search($value, static::toArray(), true);
219
    }
220
221
    /**
222
     * @param string $class
223
     *
224
     * @return array
225
     */
226
    private static function constants($class)
227
    {
228
        $reflection = new \ReflectionClass($class);
229
        $constants = $reflection->getConstants();
230
        foreach ($constants as $name => $value) {
231
            if (\strtoupper($name) === '__DEFAULT') {
232
                static::$defaultCache[$class] = $value;
233
                unset($constants[$name]);
234
            }
235
        }
236
237
        return $constants;
238
    }
239
}
240