Commit 31ca7dd1 authored by Jan Kuchař's avatar Jan Kuchař

properly handled cases when values are non-anonymous classes

parent b0f5bd3b
......@@ -72,10 +72,18 @@ abstract class Enum
return $value;
}
private static function getMeta(): Meta
private static function getMeta(bool $checkIfAccessingRootDirectly = true): Meta
{
$rootClass = static::getRootClass();
if ($checkIfAccessingRootDirectly && $rootClass !== static::class) {
throw new UsageException(
'You have accessed static enum method on non-root class '
. "('$rootClass' is a root class)"
);
}
return InstanceRegister::get(
$rootClass = static::getEnumRootClass(),
$rootClass,
function () use ($rootClass): Meta {
return Meta::from(
$rootClass,
......@@ -86,18 +94,17 @@ abstract class Enum
);
}
private static function getEnumRootClass(): string
private static function getRootClass(): string
{
try {
$ref = new \ReflectionClass(static::class);
if ($ref->isAnonymous()) { // anonymous objects are used for values
$ref = $ref->getMethod('provideInstances')->getDeclaringClass();
}
return (new \ReflectionClass(static::class))
->getMethod('provideInstances')
->getDeclaringClass()
->getName();
} catch (\ReflectionException $e) {
throw new ReflectionFailedException($e);
}
return $ref->getName();
}
......@@ -140,7 +147,7 @@ abstract class Enum
*/
public function getConstantName(): string
{
return self::getMeta()->getConstantNameForScalar(
return $this::getMeta(FALSE)->getConstantNameForScalar(
$this->toScalar()
);
}
......
<?php declare(strict_types=1);
namespace TestFullClasses;
use Grifart\Enum\UsageException;
use Tester\Assert;
require __DIR__ . '/../bootstrap.php';
/**
* @method static FullClassesAsValuesEnum VALUE1()
* @method static FullClassesAsValuesEnum VALUE2()
*/
abstract class FullClassesAsValuesEnum extends \Grifart\Enum\Enum
{
private const VALUE1 = 1;
private const VALUE2 = 2;
protected static function provideInstances(): array
{
return [
new Value1(self::VALUE1),
new Value2(self::VALUE2),
];
}
}
final class Value1 extends FullClassesAsValuesEnum { }
class Value2 extends FullClassesAsValuesEnum { }
// Standard APIs:
Assert::equal(FullClassesAsValuesEnum::VALUE1()->toScalar(), 1);
Assert::equal(FullClassesAsValuesEnum::VALUE2()->toScalar(), 2);
Assert::type(Value1::class, FullClassesAsValuesEnum::VALUE1());
Assert::type(Value2::class, FullClassesAsValuesEnum::VALUE2());
Assert::same(
[
FullClassesAsValuesEnum::VALUE1(),
FullClassesAsValuesEnum::VALUE2()
],
FullClassesAsValuesEnum::getAvailableValues()
);
Assert::same(FullClassesAsValuesEnum::VALUE1(), FullClassesAsValuesEnum::fromScalar(1));
// ## Wrong usage & edge-cases
// wrong usage:
$expectNonRootAccess = function(callable $fn) {
Assert::exception(
$fn,
UsageException::class,
"You have accessed static enum method on non-root class ('TestFullClasses\\FullClassesAsValuesEnum' is a root class)"
);
};
$expectNonRootAccess(function () {
Value1::getAvailableValues();
});
$expectNonRootAccess(function () {
Value1::fromScalar('1');
});
$expectNonRootAccess(function () {
Value1::VALUE1();
});
$expectNonRootAccess(function () {
Value1::VALUE2();
});
// valid edge case: this is valid and accesses registers the same way as calls above
Assert::same(
'VALUE1',
FullClassesAsValuesEnum::VALUE1()
->getConstantName()
);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment