Skip to content

Commit 83b2508

Browse files
committed
Optimized Enum::getConstants()
1 parent 548a4c4 commit 83b2508

File tree

2 files changed

+59
-72
lines changed

2 files changed

+59
-72
lines changed

src/Enum.php

Lines changed: 54 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,10 @@ final public function getName()
130130
final public function getOrdinal()
131131
{
132132
if ($this->ordinal === null) {
133-
$ordinal = 0;
134-
$value = $this->value;
135-
foreach (self::detectConstants(static::class) as $constValue) {
133+
$ordinal = 0;
134+
$value = $this->value;
135+
$constants = self::$constants[static::class] ?? static::getConstants();
136+
foreach ($constants as $constValue) {
136137
if ($value === $constValue) {
137138
break;
138139
}
@@ -189,8 +190,7 @@ final public static function get($enumerator)
189190
*/
190191
final public static function byValue($value)
191192
{
192-
$constants = self::$constants[static::class]
193-
?? self::detectConstants(static::class);
193+
$constants = self::$constants[static::class] ?? static::getConstants();
194194

195195
$name = \array_search($value, $constants, true);
196196
if ($name === false) {
@@ -239,7 +239,7 @@ final public static function byName(string $name)
239239
*/
240240
final public static function byOrdinal(int $ordinal)
241241
{
242-
$constants = self::$constants[static::class] ?? self::detectConstants(static::class);
242+
$constants = self::$constants[static::class] ?? static::getConstants();
243243

244244
if (!isset(self::$names[static::class][$ordinal])) {
245245
throw new InvalidArgumentException(\sprintf(
@@ -262,7 +262,7 @@ final public static function byOrdinal(int $ordinal)
262262
final public static function getEnumerators()
263263
{
264264
if (!isset(self::$names[static::class])) {
265-
self::detectConstants(static::class);
265+
static::getConstants();
266266
}
267267
return \array_map([static::class, 'byName'], self::$names[static::class]);
268268
}
@@ -274,7 +274,7 @@ final public static function getEnumerators()
274274
*/
275275
final public static function getValues()
276276
{
277-
return \array_values(self::detectConstants(static::class));
277+
return \array_values(self::$constants[static::class] ?? static::getConstants());
278278
}
279279

280280
/**
@@ -285,7 +285,7 @@ final public static function getValues()
285285
final public static function getNames()
286286
{
287287
if (!isset(self::$names[static::class])) {
288-
self::detectConstants(static::class);
288+
static::getConstants();
289289
}
290290
return self::$names[static::class];
291291
}
@@ -297,7 +297,7 @@ final public static function getNames()
297297
*/
298298
final public static function getOrdinals()
299299
{
300-
$count = \count(self::detectConstants(static::class));
300+
$count = \count(self::$constants[static::class] ?? static::getConstants());
301301
return $count ? \range(0, $count - 1) : [];
302302
}
303303

@@ -309,7 +309,49 @@ final public static function getOrdinals()
309309
*/
310310
final public static function getConstants()
311311
{
312-
return self::detectConstants(static::class);
312+
if (isset(self::$constants[static::class])) {
313+
return self::$constants[static::class];
314+
}
315+
316+
$reflection = new ReflectionClass(static::class);
317+
$constants = [];
318+
319+
do {
320+
$scopeConstants = [];
321+
// Enumerators must be defined as public class constants
322+
foreach ($reflection->getReflectionConstants() as $reflConstant) {
323+
if ($reflConstant->isPublic()) {
324+
$scopeConstants[ $reflConstant->getName() ] = $reflConstant->getValue();
325+
}
326+
}
327+
328+
$constants = $scopeConstants + $constants;
329+
} while (($reflection = $reflection->getParentClass()) && $reflection->name !== __CLASS__);
330+
331+
assert(
332+
self::noAmbiguousValues($constants),
333+
'Ambiguous enumerator values detected for ' . static::class
334+
);
335+
336+
self::$names[static::class] = \array_keys($constants);
337+
return self::$constants[static::class] = $constants;
338+
}
339+
340+
/**
341+
* Test that the given constants does not contain ambiguous values
342+
* @param array $constants
343+
* @return bool
344+
*/
345+
private static function noAmbiguousValues($constants)
346+
{
347+
foreach ($constants as $value) {
348+
$names = \array_keys($constants, $value, true);
349+
if (\count($names) > 1) {
350+
return false;
351+
}
352+
}
353+
354+
return true;
313355
}
314356

315357
/**
@@ -332,8 +374,7 @@ final public static function has($enumerator)
332374
*/
333375
final public static function hasValue($value)
334376
{
335-
$constants = self::detectConstants(static::class);
336-
return \in_array($value, $constants, true);
377+
return \in_array($value, self::$constants[static::class] ?? static::getConstants(), true);
337378
}
338379

339380
/**
@@ -347,59 +388,6 @@ final public static function hasName(string $name)
347388
return \defined("static::{$name}");
348389
}
349390

350-
/**
351-
* Detect all public available constants of given enumeration class
352-
*
353-
* @param string $class
354-
* @return array
355-
*/
356-
private static function detectConstants($class)
357-
{
358-
if (!isset(self::$constants[$class])) {
359-
$reflection = new ReflectionClass($class);
360-
$constants = [];
361-
362-
do {
363-
$scopeConstants = [];
364-
// Enumerators must be defined as public class constants
365-
foreach ($reflection->getReflectionConstants() as $reflConstant) {
366-
if ($reflConstant->isPublic()) {
367-
$scopeConstants[ $reflConstant->getName() ] = $reflConstant->getValue();
368-
}
369-
}
370-
371-
$constants = $scopeConstants + $constants;
372-
} while (($reflection = $reflection->getParentClass()) && $reflection->name !== __CLASS__);
373-
374-
assert(
375-
self::noAmbiguousValues($constants),
376-
"Ambiguous enumerator values detected for {$class}"
377-
);
378-
379-
self::$constants[$class] = $constants;
380-
self::$names[$class] = \array_keys($constants);
381-
}
382-
383-
return self::$constants[$class];
384-
}
385-
386-
/**
387-
* Test that the given constants does not contain ambiguous values
388-
* @param array $constants
389-
* @return bool
390-
*/
391-
private static function noAmbiguousValues($constants)
392-
{
393-
foreach ($constants as $value) {
394-
$names = \array_keys($constants, $value, true);
395-
if (\count($names) > 1) {
396-
return false;
397-
}
398-
}
399-
400-
return true;
401-
}
402-
403391
/**
404392
* Get an enumerator instance by the given name.
405393
*

tests/MabeEnumTest/EnumSerializableTraitTest.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use MabeEnumTest\TestAsset\SerializableEnum;
99
use PHPUnit\Framework\TestCase;
1010
use ReflectionClass;
11+
use ReflectionProperty;
1112
use RuntimeException;
1213

1314
/**
@@ -89,11 +90,9 @@ private function clearEnumeration($enumeration)
8990
$reflClass = $reflClass->getParentClass();
9091
}
9192

92-
$reflPropInstances = $reflClass->getProperty('instances');
93-
$reflPropInstances->setAccessible(true);
94-
$reflPropInstances->setValue(null, array());
95-
$reflPropConstants = $reflClass->getProperty('constants');
96-
$reflPropConstants->setAccessible(true);
97-
$reflPropConstants->setValue(null, array());
93+
foreach ($reflClass->getProperties(ReflectionProperty::IS_STATIC) as $reflProp) {
94+
$reflProp->setAccessible(true);;
95+
$reflProp->setValue(null, []);
96+
}
9897
}
9998
}

0 commit comments

Comments
 (0)