Completed
Push — master ( 8a6234...6e8ce6 )
by Peter
03:25
created

ReflectionEnum::__toString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
3
/**
4
 * GpsLab component.
5
 *
6
 * @author    Peter Gribanov <[email protected]>
7
 * @copyright Copyright (c) 2011, Peter Gribanov
8
 * @license   http://opensource.org/licenses/MIT
9
 */
10
11
namespace GpsLab\Component\Enum;
12
13
use GpsLab\Component\Enum\Exception\BadMethodCallException;
14
use GpsLab\Component\Enum\Exception\OutOfEnumException;
15
16
abstract class ReflectionEnum implements Enum, \Serializable
17
{
18
    /**
19
     * @var mixed
20
     */
21
    private $value = '';
22
23
    /**
24
     * @var Enum[]
25
     */
26
    private static $instances = [];
27
28
    /**
29
     * @var mixed[][]
30
     */
31
    private static $create_methods = [];
32
33
34
    /**
35
     * @var mixed[][]
36
     */
37
    private static $constants = [];
38
39
    /**
40
     * @var mixed[][]
41
     */
42
    private static $choices = [];
43
44
    /**
45
     * @var EnumEnum[]
46
     */
47
    private static $values = [];
48
49
    /**
50
     * @param mixed $value
51
     */
52
    final private function __construct($value)
53
    {
54
        $this->value = $value;
55
    }
56
57
    /**
58
     * @param mixed $value
59
     *
60
     * @return Enum
61
     */
62 23
    final public static function byValue($value)
63
    {
64 23
        $class = get_called_class();
65 23
        self::detectConstants($class);
66
67 23
        $method = array_search($value, self::$create_methods[$class], true);
68
69 23
        if ($method === false) {
70 23
            throw OutOfEnumException::create($value, $class);
71
        }
72
73
        // limitation of count object instances
74
        if (!isset(self::$instances[$class][$method])) {
75
            self::$instances[$class][$method] = new static($value);
76
        }
77
78
        return self::$instances[$class][$method];
79
    }
80
81
    /**
82
     * @return mixed
83
     */
84
    final public function value()
85
    {
86
        return $this->value;
87
    }
88
89
    /**
90
     * Available values.
91
     *
92
     * @return Enum[]
93
     */
94 3 View Code Duplication
    final public static function values()
95
    {
96 3
        $class = get_called_class();
97
98 3
        if (!isset(self::$values[$class])) {
99 3
            self::$values[$class] = [];
100 3
            foreach (self::constants() as $constant => $value) {
101
                self::$values[$class][$constant] = self::byValue($value);
102
            }
103
        }
104
105
        return self::$values[$class];
0 ignored issues
show
Bug Compatibility introduced by
The expression self::$values[$class]; of type GpsLab\Component\Enum\EnumEnum|array adds the type GpsLab\Component\Enum\EnumEnum to the return on line 105 which is incompatible with the return type declared by the interface GpsLab\Component\Enum\Enum::values of type array.
Loading history...
106
    }
107
108
    /**
109
     * @param Enum $enum
110
     *
111
     * @return bool
112
     */
113
    final public function equals(Enum $enum)
114
    {
115
        return $this === $enum || ($this->value() === $enum->value() && get_called_class() == get_class($enum));
116
    }
117
118
    /**
119
     * Is value supported.
120
     *
121
     * @param mixed $value
122
     *
123
     * @return bool
124
     */
125 10
    final public static function isValid($value)
126
    {
127 10
        return in_array($value, self::constants(), true);
128
    }
129
130
    /**
131
     * Get choices for radio group.
132
     *
133
     * <code>
134
     * {
135
     *   value1: 'Readable value 1',
136
     *   value2: 'Readable value 2',
137
     * }
138
     * </code>
139
     *
140
     * @return array
141
     */
142 3 View Code Duplication
    final public static function choices()
143
    {
144 3
        $class = get_called_class();
145
146 3
        if (!isset(self::$choices[$class])) {
147 3
            self::$choices[$class] = [];
148 3
            foreach (self::constants() as $value) {
149
                self::$choices[$class][$value] = (string) self::byValue($value);
150
            }
151
        }
152
153
        return self::$choices[$class];
154
    }
155
156
    /**
157
     * Return readable value.
158
     *
159
     * @return string
160
     */
161
    public function __toString()
162
    {
163
        return $this->constant();
164
    }
165
166
    final public function __clone()
167
    {
168
        throw new \LogicException('Enumerations are not cloneable');
169
    }
170
171
    /**
172
     * @return mixed
173
     */
174
    public function serialize()
175
    {
176
        return serialize($this->value);
177
    }
178
179
    /**
180
     * @param mixed $data
181
     */
182
    public function unserialize($data)
183
    {
184
        self::byValue($this->value = unserialize($data));
185
    }
186
187
    /**
188
     * @param string $class
189
     */
190 61
    private static function detectConstants($class)
191
    {
192 61
        if (!isset(self::$create_methods[$class])) {
193 3
            self::$create_methods[$class] = [];
194 3
            self::$is_methods[$class] = [];
195
            self::$constants[$class] = [];
196
197
            foreach (ConstantDetector::detect($class) as $constant => $constant_value) {
198
                self::$constants[$class][$constant] = $constant_value;
199
200
                // second parameter of ucwords() is not supported on HHVM
201
                $constant = str_replace(' ', '', ucwords(str_replace('_', ' ', strtolower($constant))));
202
203
                self::$is_methods[$class]['is'.$constant] = $constant_value;
204
                self::$create_methods[$class][lcfirst($constant)] = $constant_value;
205
            }
206
        }
207 58
    }
208
209
    /**
210
     * @return array
211
     */
212 16
    private static function constants()
213
    {
214 16
        $class = get_called_class();
215 16
        self::detectConstants($class);
216
217 13
        return self::$constants[$class];
218
    }
219
220
    /**
221
     * @return string
222
     */
223
    private function constant()
224
    {
225
        return array_search($this->value(), self::constants());
226
    }
227
228
    /**
229
     * @param string $method
230
     * @param array  $arguments
231
     *
232
     * @return bool
233
     */
234
    public function __call($method, array $arguments = [])
235
    {
236
        $class = get_called_class();
237
        self::detectConstants($class);
238
239
        if (!isset(self::$is_methods[$class][$method])) {
240
            throw BadMethodCallException::noMethod($method, $class);
241
        }
242
243
        return $this->value === self::$is_methods[$class][$method];
244
    }
245
246
    /**
247
     * @param string $method
248
     * @param array  $arguments
249
     *
250
     * @return Enum
251
     */
252 22
    public static function __callStatic($method, array $arguments = [])
253
    {
254 22
        $class = get_called_class();
255 22
        if (isset(self::$instances[$class][$method])) {
256
            return self::$instances[$class][$method];
257
        }
258
259 22
        self::detectConstants($class);
260
261 22
        if (!isset(self::$create_methods[$class][$method])) {
262 22
            throw BadMethodCallException::noStaticMethod($method, $class);
263
        }
264
265
        return self::$instances[$class][$method] = new static(self::$create_methods[$class][$method]);
266
    }
267
}
268