Completed
Push — master ( 439e92...54d259 )
by Peter
08:34
created

ReflectionEnum   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 188
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 188
c 0
b 0
f 0
wmc 23
lcom 1
cbo 3
ccs 53
cts 53
cp 1
rs 10

14 Methods

Rating   Name   Duplication   Size   Complexity  
A value() 0 4 1
A __construct() 0 4 1
A byValue() 0 18 3
A byName() 0 15 3
A values() 0 9 2
A name() 0 4 1
A equals() 0 4 3
A choices() 0 9 2
A __toString() 0 4 1
A __clone() 0 4 1
A serialize() 0 4 1
A unserialize() 0 4 1
A constants() 0 9 2
A __callStatic() 0 4 1
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\OutOfEnumException;
14
15
abstract class ReflectionEnum implements Enum, \Serializable
16
{
17
    /**
18
     * @var mixed
19
     */
20
    private $value = '';
21
22
    /**
23
     * @var Enum[]
24
     */
25
    private static $instances = [];
26
27
    /**
28
     * @var array
29
     */
30
    private static $constants = [];
31
32
    /**
33
     * @param mixed $value
34
     */
35
    final private function __construct($value)
36
    {
37
        $this->value = $value;
38
    }
39
40
    /**
41
     * @param mixed $value
42
     *
43
     * @return Enum
44
     */
45
    final public static function byValue($value)
46
    {
47
        $class = get_called_class();
48
        self::constants();
49
50
        $constant = array_search($value, self::$constants[$class], true);
51
52
        if ($constant === false) {
53
            throw OutOfEnumException::invalidValue($value, $class);
54
        }
55
56 4
        // limitation of count object instances
57
        if (!isset(self::$instances[$class][$constant])) {
58 4
            self::$instances[$class][$constant] = new static($value);
59 4
        }
60
61
        return self::$instances[$class][$constant];
62
    }
63
64
    /**
65
     * @param string $name
66 30
     *
67
     * @return Enum
68 30
     */
69 30
    final public static function byName($name)
70
    {
71 30
        $class = get_called_class();
72
        if (isset(self::$instances[$class][$name])) {
73 30
            return self::$instances[$class][$name];
74 2
        }
75
76
        self::constants();
77
78 28
        if (!isset(self::$constants[$class][$name])) {
79 2
            throw OutOfEnumException::undefinedConstant($class . '::' . $name);
80 2
        }
81
82 28
        return self::$instances[$class][$name] = new static(self::$constants[$class][$name]);
83
    }
84
85
    /**
86
     * @return mixed
87
     */
88 20
    final public function value()
89
    {
90 20
        return $this->value;
91
    }
92
93
    /**
94
     * Available values.
95
     *
96
     * @return Enum[]
97
     */
98 2
    final public static function values()
99
    {
100 2
        $values = [];
101
        foreach (self::constants() as $constant => $value) {
102 2
            $values[$constant] = self::byValue($value);
103 2
        }
104 2
105 2
        return $values;
106 2
    }
107 2
108
    /**
109 2
     * @return string
110
     */
111
    final public function name()
112
    {
113
        return array_search($this->value(), self::constants());
114
    }
115
116
    /**
117 8
     * @param Enum $enum
118
     *
119 8
     * @return bool
120
     */
121
    final public function equals(Enum $enum)
122
    {
123
        return $this === $enum || ($this->value() === $enum->value() && get_called_class() == get_class($enum));
124
    }
125
126
    /**
127
     * Get choices for radio group.
128
     *
129 8
     * <code>
130
     * {
131 8
     *   value1: 'Readable value 1',
132
     *   value2: 'Readable value 2',
133
     * }
134
     * </code>
135
     *
136
     * @return array
137
     */
138
    final public static function choices()
139
    {
140
        $choices = [];
141
        foreach (self::constants() as $value) {
142
            $choices[$value] = (string) self::byValue($value);
143
        }
144
145
        return $choices;
146 2
    }
147
148 2
    /**
149
     * Return readable value.
150 2
     *
151 2
     * @return string
152 2
     */
153 2
    public function __toString()
154 2
    {
155 2
        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 2
158
    final public function __clone()
159
    {
160
        throw new \LogicException('Enumerations are not cloneable');
161
    }
162
163
    /**
164
     * @return mixed
165 10
     */
166
    public function serialize()
167 10
    {
168
        return serialize($this->value);
169
    }
170 2
171
    /**
172 2
     * @param mixed $data
173
     */
174
    public function unserialize($data)
175
    {
176
        self::byValue($this->value = unserialize($data));
177
    }
178 8
179
    /**
180 8
     * @return array
181
     */
182
    private static function constants()
183
    {
184
        $class = get_called_class();
185
        if (!isset(self::$constants[$class])) {
186 8
            self::$constants[$class] = ConstantDetector::detect($class);
187
        }
188 8
189 8
        return self::$constants[$class];
190
    }
191
192
    /**
193
     * @param string $method
194 44
     * @param array  $arguments
195
     *
196 44
     * @return Enum
197 2
     */
198 2
    public static function __callStatic($method, array $arguments = [])
199 2
    {
200
        return self::byName($method);
201 2
    }
202
}
203