ReflectionEnum::values()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 9.9666
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 2
1
<?php
2
3
/**
4
 * GpsLab component.
5
 *
6
 * @author    Peter Gribanov <[email protected]>
7
 * @copyright Copyright (c) 2017, Peter Gribanov
8
 * @license   http://opensource.org/licenses/MIT
9
 */
10
11
namespace GpsLab\Component\Enum;
12
13
use GpsLab\Component\Enum\Exception\OutOfEnumException;
14
15
abstract class ReflectionEnum implements Enum, \Serializable
16
{
17
    /**
18
     * @var mixed
19
     */
20
    private $value;
21
22
    /**
23
     * @var self[]
24
     */
25
    private static $instances = [];
26
27
    /**
28
     * @var array
29
     */
30
    private static $constants = [];
31
32
    /**
33
     * @param mixed $value
34
     */
35 6
    final private function __construct($value)
36
    {
37 6
        $this->value = $value;
38 6
    }
39
40
    /**
41
     * @param mixed $value
42
     *
43
     * @return self
44
     */
45 47
    final public static function byValue($value)
46
    {
47 47
        $class = get_called_class();
48 47
        self::constants();
49
50 47
        $constant = array_search($value, self::$constants[$class], true);
51
52 47
        if ($constant === false) {
53 3
            throw OutOfEnumException::invalidValue($value, $class);
54
        }
55
56
        // limitation of count object instances
57 44
        if (!isset(self::$instances[$class][$constant])) {
58 3
            self::$instances[$class][$constant] = new static($value);
59
        }
60
61 44
        return self::$instances[$class][$constant];
62
    }
63
64
    /**
65
     * @param string $name
66
     *
67
     * @return self
68
     */
69 30
    final public static function byName($name)
70
    {
71 30
        $class = get_called_class();
72 30
        if (isset(self::$instances[$class][$name])) {
73 21
            return self::$instances[$class][$name];
74
        }
75
76 9
        self::constants();
77
78 9
        if (!isset(self::$constants[$class][$name])) {
79 6
            throw OutOfEnumException::undefinedConstant($class.'::'.$name);
80
        }
81
82 3
        return self::$instances[$class][$name] = new static(self::$constants[$class][$name]);
83
    }
84
85
    /**
86
     * @return mixed
87
     */
88 42
    final public function value()
89
    {
90 42
        return $this->value;
91
    }
92
93
    /**
94
     * Available values.
95
     *
96
     * @return self[]
97
     */
98 3
    final public static function values()
99
    {
100 3
        $values = [];
101 3
        foreach (self::constants() as $constant => $value) {
102 3
            $values[$constant] = self::byValue($value);
103
        }
104
105 3
        return $values;
106
    }
107
108
    /**
109
     * @return string
110
     */
111 21
    final public function name()
112
    {
113 21
        return array_search($this->value(), self::constants(), true);
114
    }
115
116
    /**
117
     * @param Enum $enum
118
     *
119
     * @return bool
120
     */
121 20
    final public function equals(Enum $enum)
122
    {
123 20
        return $this === $enum || ($this->value() === $enum->value() && get_called_class() === get_class($enum));
124
    }
125
126
    /**
127
     * Get choices for radio group.
128
     *
129
     * <code>
130
     * {
131
     *   value1: 'Readable value 1',
132
     *   value2: 'Readable value 2',
133
     * }
134
     * </code>
135
     *
136
     * @return array
137
     */
138 3
    final public static function choices()
139
    {
140 3
        $choices = [];
141 3
        foreach (self::constants() as $value) {
142 3
            $choices[$value] = (string) self::byValue($value);
143
        }
144
145 3
        return $choices;
146
    }
147
148
    /**
149
     * Return readable value.
150
     *
151
     * @return string
152
     */
153 13
    public function __toString()
154
    {
155 13
        return $this->name();
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression $this->name(); of type false|integer|string adds false to the return on line 155 which is incompatible with the return type declared by the interface GpsLab\Component\Enum\Enum::__toString of type string. It seems like you forgot to handle an error condition.
Loading history...
156
    }
157
158 3
    final public function __clone()
159
    {
160 3
        throw new \LogicException('Enumerations are not cloneable');
161
    }
162
163
    /**
164
     * @return mixed
165
     */
166 10
    public function serialize()
167
    {
168 10
        return serialize($this->value);
169
    }
170
171
    /**
172
     * @param mixed $data
173
     */
174 10
    public function unserialize($data)
175
    {
176 10
        self::byValue($this->value = unserialize($data));
177 10
    }
178
179
    /**
180
     * @return array
181
     */
182 56
    private static function constants()
183
    {
184 56
        $class = get_called_class();
185 56
        if (!isset(self::$constants[$class])) {
186 3
            self::$constants[$class] = ConstantDetector::detect($class);
187
        }
188
189 56
        return self::$constants[$class];
190
    }
191
192
    /**
193
     * @param string $method
194
     * @param array  $arguments
195
     *
196
     * @return self
197
     */
198 19
    public static function __callStatic($method, array $arguments = [])
199
    {
200 19
        return self::byName($method);
201
    }
202
}
203