Skip to content

Commit 996e5b3

Browse files
committed
using strict comparison
1 parent e2f45c8 commit 996e5b3

File tree

4 files changed

+89
-57
lines changed

4 files changed

+89
-57
lines changed

src/MabeEnum/Enum.php

Lines changed: 37 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -122,33 +122,22 @@ final public function getOrdinal()
122122
*/
123123
final static public function get($value)
124124
{
125-
$class = get_called_class();
126-
if (isset(self::$instances[$class][$value])) {
127-
return self::$instances[$class][$value];
128-
}
129-
130-
// find the real value
125+
$class = get_called_class();
131126
$constants = self::detectConstants($class);
132-
$name = array_search($value, $constants, true); // use strict, see next lines
127+
$name = array_search($value, $constants, true);
133128
if ($name === false) {
134-
// Bnumeration values have to be unique by their string representation.
135-
// Because array_search searches in strict mode or in non-strict mode only
136-
// we have to search for a value of the same string our self.
137-
// (see issue #26)
138-
$valueStr = (string) $value;
139-
$found = false;
140-
foreach ($constants as $name => $constValue) {
141-
if ($valueStr === (string) $constValue) {
142-
$found = true;
143-
break;
144-
}
145-
}
146-
if (!$found) {
147-
throw new InvalidArgumentException("Unknown value '{$value}'");
129+
if (is_scalar($value)) {
130+
throw new InvalidArgumentException('Unknown value ' . var_export($value, true));
131+
} else {
132+
throw new InvalidArgumentException('Invalid value of type ' . gettype($value));
148133
}
149134
}
150135

151-
return self::$instances[$class][$value] = new $class($constants[$name]);
136+
if (!isset(self::$instances[$class][$name])) {
137+
self::$instances[$class][$name] = new $class($constants[$name]);
138+
}
139+
140+
return self::$instances[$class][$name];
152141
}
153142

154143
/**
@@ -161,18 +150,18 @@ final static public function get($value)
161150
*/
162151
final public static function getByName($name)
163152
{
153+
$name = (string) $name;
164154
$class = get_called_class();
155+
if (isset(self::$instances[$class][$name])) {
156+
return self::$instances[$class][$name];
157+
}
158+
165159
$const = $class . '::' . $name;
166160
if (!defined($const)) {
167161
throw new InvalidArgumentException($const . ' not defined');
168162
}
169163

170-
$value = constant($const);
171-
if (isset(self::$instances[$class][$value])) {
172-
return self::$instances[$class][$value];
173-
}
174-
175-
return self::$instances[$class][$value] = new $class($value);
164+
return self::$instances[$class][$name] = new $class(constant($const));
176165
}
177166

178167
/**
@@ -196,12 +185,12 @@ final public static function getByOrdinal($ordinal)
196185
));
197186
}
198187

199-
$value = current($item);
200-
if (isset(self::$instances[$class][$value])) {
201-
return self::$instances[$class][$value];
188+
$name = key($item);
189+
if (isset(self::$instances[$class][$name])) {
190+
return self::$instances[$class][$name];
202191
}
203192

204-
return self::$instances[$class][$value] = new $class($value, $ordinal);
193+
return self::$instances[$class][$name] = new $class(current($item), $ordinal);
205194
}
206195

207196
/**
@@ -240,19 +229,25 @@ static private function detectConstants($class)
240229
$reflection = new ReflectionClass($class);
241230
$constants = $reflection->getConstants();
242231

243-
// Constant values needs to be unique
244-
if (max(array_count_values($constants)) > 1) {
245-
$ambiguous = array_map(function ($v) use ($constants) {
246-
return implode('/', array_keys($constants, $v)) . '=' . $v;
247-
}, array_unique(array_diff_assoc($constants, array_unique($constants))));
248-
throw new LogicException(sprintf(
249-
'All possible values needs to be unique. The following are ambiguous: %s',
250-
implode(', ', $ambiguous)
251-
));
232+
// values needs to be unique
233+
$ambiguous = array();
234+
foreach ($constants as $value) {
235+
$names = array_keys($constants, $value, true);
236+
if (count($names) > 1) {
237+
$ambiguous[var_export($value, true)] = $names;
238+
}
239+
}
240+
if ($ambiguous) {
241+
throw new LogicException(
242+
'All possible values needs to be unique. The following are ambiguous: '
243+
. implode(', ', array_map(function ($names) use ($constants) {
244+
return implode('/', $names) . '=' . var_export($constants[$names[0]], true);
245+
}, $ambiguous))
246+
);
252247
}
253248

254249
// This is required to make sure that constants of base classes will be the first
255-
while (($reflection = $reflection->getParentClass()) && $reflection->name != 'MabeEnum\Enum') {
250+
while (($reflection = $reflection->getParentClass()) && $reflection->name != __CLASS__) {
256251
$constants = $reflection->getConstants() + $constants;
257252
}
258253

tests/MabeEnumTest/EnumTest.php

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,20 @@ public function testEnumInheritance()
4949
'EIGHT' => 8,
5050
'NINE' => 9,
5151
'ZERO' => 0,
52-
'INHERITANCE' => 'Inheritance'
52+
'FLOATING_POINT_NUMBER' => 0.123,
53+
'STR' => 'str',
54+
'STR_EMPTY' => '',
55+
'NIL' => null,
56+
'BOOLEAN_TRUE' => true,
57+
'BOOLEAN_FALSE' => false,
58+
'INHERITANCE' => 'Inheritance',
5359
), $enum::getConstants());
5460
$this->assertSame(EnumInheritance::ONE, $enum->getValue());
5561
$this->assertSame(0, $enum->getOrdinal());
5662

5763
$enum = EnumInheritance::get(EnumInheritance::INHERITANCE);
5864
$this->assertSame(EnumInheritance::INHERITANCE, $enum->getValue());
59-
$this->assertSame(10, $enum->getOrdinal());
65+
$this->assertSame(16, $enum->getOrdinal());
6066
}
6167

6268
public function testGetWithStrictValue()
@@ -66,11 +72,10 @@ public function testGetWithStrictValue()
6672
$this->assertSame(0, $enum->getOrdinal());
6773
}
6874

69-
public function testGetWithNonStrictValue()
75+
public function testGetWithNonStrictValueThrowsInvalidArgumentException()
7076
{
71-
$enum = EnumBasic::get((string)EnumBasic::TWO);
72-
$this->assertSame(2, $enum->getValue());
73-
$this->assertSame(1, $enum->getOrdinal());
77+
$this->setExpectedException('InvalidArgumentException');
78+
EnumBasic::get((string)EnumBasic::TWO);
7479
}
7580

7681
public function testGetWithInvalidValueThrowsInvalidArgumentException()
@@ -79,6 +84,22 @@ public function testGetWithInvalidValueThrowsInvalidArgumentException()
7984
EnumBasic::get('unknown');
8085
}
8186

87+
public function testGetWithInvalidTypeOfValueThrowsInvalidArgumentException()
88+
{
89+
$this->setExpectedException('InvalidArgumentException');
90+
EnumBasic::get(array());
91+
}
92+
93+
public function testGetAllValues()
94+
{
95+
$constants = EnumBasic::getConstants();
96+
foreach ($constants as $name => $value) {
97+
$enum = EnumBasic::get($value);
98+
$this->assertSame($value, $enum->getValue());
99+
$this->assertSame($name, $enum->getName());
100+
}
101+
}
102+
82103
public function testCallingGetOrdinalTwoTimesWillResultTheSameValue()
83104
{
84105
$enum = EnumBasic::get(EnumBasic::TWO);
@@ -88,15 +109,15 @@ public function testCallingGetOrdinalTwoTimesWillResultTheSameValue()
88109

89110
public function testInstantiateUsingOrdinalNumber()
90111
{
91-
$enum = EnumInheritance::getByOrdinal(10);
92-
$this->assertSame(10, $enum->getOrdinal());
112+
$enum = EnumInheritance::getByOrdinal(16);
113+
$this->assertSame(16, $enum->getOrdinal());
93114
$this->assertSame('INHERITANCE', $enum->getName());
94115
}
95116

96117
public function testInstantiateUsingInvalidOrdinalNumberThrowsInvalidArgumentException()
97118
{
98119
$this->setExpectedException('InvalidArgumentException');
99-
EnumInheritance::getByOrdinal(11);
120+
EnumInheritance::getByOrdinal(17);
100121
}
101122

102123
public function testInstantiateByName()
@@ -122,7 +143,7 @@ public function testInstantiateUsingMagicMethod()
122143
public function testAmbuguousConstantsThrowsLogicException()
123144
{
124145
$this->setExpectedException('LogicException');
125-
EnumAmbiguous::get(EnumAmbiguous::AMBIGUOUS1);
146+
EnumAmbiguous::get('unknown');
126147
}
127148

128149
public function testSingleton()

tests/MabeEnumTest/TestAsset/EnumAmbiguous.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,18 @@
1313
*/
1414
class EnumAmbiguous extends Enum
1515
{
16-
const UNIQUE1 = 'unique1';
17-
const AMBIGUOUS1 = 1;
18-
const UNIQUE2 = 'unique2';
19-
const AMBIGUOUS2 = '1';
20-
const UNIQUE3 = 'unique3';
16+
const UNIQUE1 = 'unique1';
17+
const AMBIGUOUS_INT1 = 1;
18+
const UNIQUE2 = 'unique2';
19+
const AMBIGUOUS_INT2 = 1;
20+
const UNIQUE3 = 'unique3';
21+
22+
const AMBIGUOUS_STR1 = '1';
23+
const AMBIGUOUS_STR2 = '1';
24+
25+
const AMBIGUOUS_NULL1 = null;
26+
const AMBIGUOUS_NULL2 = null;
27+
28+
const AMBIGUOUS_FALSE1 = false;
29+
const AMBIGUOUS_FALSE2 = false;
2130
}

tests/MabeEnumTest/TestAsset/EnumBasic.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,11 @@ class EnumBasic extends Enum
2323
const EIGHT = 8;
2424
const NINE = 9;
2525
const ZERO = 0;
26+
27+
const FLOATING_POINT_NUMBER = 0.123;
28+
const STR = 'str';
29+
const STR_EMPTY = '';
30+
const NIL = null;
31+
const BOOLEAN_TRUE = true;
32+
const BOOLEAN_FALSE = false;
2633
}

0 commit comments

Comments
 (0)