Commit b0f5bd3b authored by Jan Kuchař's avatar Jan Kuchař

cleanup & docs

parent 5a86003f
......@@ -2,9 +2,12 @@
namespace Grifart\Enum;
/**
* Allows you to use you defined constants automatically as enum value.
* Without explicitly implementing each enum value.
*/
trait AutoInstances
{
// todo: better define this interface
abstract protected static function getConstantToScalar(): array;
/** @param string|int $scalar */
......@@ -13,8 +16,8 @@ trait AutoInstances
protected static function provideInstances(): array
{
$instances = [];
foreach (static::getConstantToScalar() as $constantName => $primitiveValue) {
$instances[] = new static($primitiveValue);
foreach (static::getConstantToScalar() as $scalarValue) {
$instances[] = new static($scalarValue);
}
return $instances;
}
......
......@@ -6,12 +6,13 @@ use Grifart\Enum\Internal\InstanceRegister;
use Grifart\Enum\Internal\Meta;
/**
* Enum
* Enumeration class with support for strong-typing support and behaviour-rich values.
*
* Three concepts:
* - constant name = used to refer to enum value
* - value = the enum instance
* - scalar value = scalar value of enum, must be unique, used for serialization
* Three basic concepts:
* - **value** = the enum instance
* - **scalar** = scalar identifier of enum value; typically used in persistence layer to refer to particular value
* - **constant** = each value has associated class constant, which is used to refer to value from code.
* Constant name is used to generate static method for each of them. Constants are therefore usually not public.
*/
abstract class Enum
{
......@@ -74,10 +75,10 @@ abstract class Enum
private static function getMeta(): Meta
{
return InstanceRegister::get(
static::getEnumClassName(),
function (): Meta {
$rootClass = static::getEnumRootClass(),
function () use ($rootClass): Meta {
return Meta::from(
static::getEnumClassName(),
$rootClass,
static::getConstantToScalar(),
static::provideInstances()
);
......@@ -85,7 +86,7 @@ abstract class Enum
);
}
private static function getEnumClassName(): string
private static function getEnumRootClass(): string
{
try {
$ref = new \ReflectionClass(static::class);
......
......@@ -4,18 +4,21 @@ namespace Grifart\Enum\Internal;
use Grifart\Enum\UsageException;
/**
* Checks if registering enum does not contain error.
*/
final class ConsistencyChecker
{
public static function checkAnnotations(Meta $enumMeta): void
{
$enumReflection = new \ReflectionClass($enumMeta->getClass());
self::checkCallStaticAnnotations($enumMeta, $enumReflection);
self::checkAllInstancesProvided($enumMeta, $enumReflection->getName());
self::checkCallStaticAnnotations($enumMeta);
self::checkAllInstancesProvided($enumMeta);
}
private static function checkCallStaticAnnotations(Meta $enumMeta, \ReflectionClass $enumReflection): void
private static function checkCallStaticAnnotations(Meta $enumMeta): void
{
$enumReflection = $enumMeta->getClassReflection();
$docBlock = $enumReflection->getDocComment();
$className = $enumReflection->getShortName();
if ($docBlock === false) {
......@@ -37,7 +40,7 @@ final class ConsistencyChecker
// todo: @method annotations without constants
}
private static function checkAllInstancesProvided(Meta $enumMeta, string $className): void
private static function checkAllInstancesProvided(Meta $enumMeta): void
{
// todo: instances without constants
......
......@@ -13,13 +13,15 @@ final class InstanceRegister
public static function get(string $enumClass, callable $registrar): Meta
{
if (!isset(self::$instances[$enumClass])) {
self::register($registrar());
self::register($enumClass, $registrar());
}
return self::$instances[$enumClass];
}
public static function register(Meta $meta): void
public static function register(string $className, Meta $meta): void
{
\assert($meta->getClass() === $className, 'Provided Meta object is for different enum class that was originally registered.');
// check consistency of enum when assertions are enabled (typically non-production code)
assert(
(function () use ($meta): bool {
......@@ -27,6 +29,6 @@ final class InstanceRegister
return true;
})()
);
self::$instances[$meta->getClass()] = $meta;
self::$instances[$className] = $meta;
}
}
......@@ -4,6 +4,7 @@ namespace Grifart\Enum\Internal;
use Grifart\Enum\Enum;
use Grifart\Enum\MissingValueDeclarationException;
use Grifart\Enum\ReflectionFailedException;
use Grifart\Enum\UsageException;
final class Meta
......@@ -78,6 +79,15 @@ final class Meta
return $this->class;
}
public function getClassReflection(): \ReflectionClass
{
try {
return new \ReflectionClass($this->getClass());
} catch (\ReflectionException $e) {
throw new ReflectionFailedException($e);
}
}
/**
* @return string[]
*/
......
......@@ -4,8 +4,8 @@
* Contains all exceptions used in project.
*
* - Usage exceptions: leads directly to fix by programmer. They are never caught and should never happen on production.
* - Runtime exception: they represent valid case in domain logic. They should be handled at runtime and caught.
* Therefore every error should have separate exception type.
* - Runtime exception: they represent valid case in domain logic. They should be handled at runtime and caught by user.
* Therefore every error should have separate exception type (they can create inheritance tree)
*/
namespace Grifart\Enum;
......
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