Skip to content

Commit

Permalink
Replace ChoiceEnumTrait & SimpleChoiceEnum by AutoDiscoveredReadables…
Browse files Browse the repository at this point in the history
…Trait
  • Loading branch information
ogizanagi committed Apr 9, 2018
1 parent 5a75fe9 commit 9153b70
Show file tree
Hide file tree
Showing 13 changed files with 189 additions and 387 deletions.
89 changes: 89 additions & 0 deletions src/AutoDiscoveredReadablesTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

/*
* This file is part of the "elao/enum" package.
*
* Copyright (C) Elao
*
* @author Elao <contact@elao.com>
*/

namespace Elao\Enum;

use Elao\Enum\Exception\LogicException;

/**
* Auto-discover enumerated readable values from public constants.
*
* Meant to be used within a {@link \Elao\Enum\ReadableEnumInterface} implementation.
*/
trait AutoDiscoveredReadablesTrait
{
use AutoDiscoveredValuesTrait {
AutoDiscoveredValuesTrait::values as autodiscoveredValues;
}

/** @internal */
private static $guessedReadables = [];

/** @internal */
private static $called = 0;

/**
* @see ReadableEnumInterface::readables()
*
* @return string[] labels indexed by enumerated value
*/
public static function readables(): array
{
static::checkForChoiceEnumTraitMisuses();

return static::autodiscoveredReadables();
}

/**
* @internal
*/
private static function autodiscoveredReadables(): array
{
$enumType = static::class;

++self::$called;
/**
* The {@link AutoDiscoveredReadablesTrait::$called} property and the following is required
* in order to preserve BC, especially for the FlaggedEnum.
* It ensures overriding the {@link \Elao\Enum\ReadableEnum::values} method is taken into account
* and prevents an infinite loop otherwise.
* However, it's still a BC break in case of any parent::values call...
*
* @see \Elao\Enum\Tests\Unit\FlaggedEnumTest::testWithSpecifiedValues
*/
$values = self::$called > 1 ? static::autodiscoveredValues() : static::values();
self::$called = 0;

if (!isset(self::$guessedReadables[$enumType])) {
$constants = (new \ReflectionClass($enumType))->getConstants();
foreach ($values as $value) {
$constantName = array_search($value, $constants, true);
self::$guessedReadables[$enumType][$value] = ucfirst(strtolower(str_replace('_', ' ', $constantName)));
}
}

return self::$guessedReadables[$enumType];
}

/**
* @internal
*/
private static function checkForChoiceEnumTraitMisuses()
{
if (!is_a(static::class, ReadableEnumInterface::class, true)) {
throw new LogicException(sprintf(
'The "%s" trait is meant to be used by "%s" implementations, but "%s" does not implement it.',
self::class,
ReadableEnumInterface::class,
static::class
));
}
}
}
50 changes: 1 addition & 49 deletions src/AutoDiscoveredValuesTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,50 +10,20 @@

namespace Elao\Enum;

use Elao\Enum\Exception\LogicException;

/**
* Auto-discover enumerated values from public constants.
*/
trait AutoDiscoveredValuesTrait
{
/** @var array */
/** @internal */
private static $guessedValues = [];

/** @var array */
private static $guessedReadables = [];

/**
* @see EnumInterface::values()
*
* @return int[]|string[]
*/
public static function values(): array
{
return static::autodiscoveredValues();
}

/**
* @see ChoiceEnumTrait::choices()
*/
protected static function choices(): array
{
if (!in_array(ChoiceEnumTrait::class, class_uses(self::class, false), true)) {
throw new LogicException(sprintf(
'Method "%s" is only meant to be used when using the "%s" trait which is not used in "%s"',
__METHOD__,
ChoiceEnumTrait::class,
static::class
));
}

return static::autodiscoveredReadables();
}

/**
* @internal
*/
private static function autodiscoveredValues(): array
{
$enumType = static::class;

Expand All @@ -78,22 +48,4 @@ private static function autodiscoveredValues(): array

return self::$guessedValues[$enumType];
}

/**
* @internal
*/
private static function autodiscoveredReadables(): array
{
$enumType = static::class;

if (!isset(self::$guessedReadables[$enumType])) {
$constants = (new \ReflectionClass($enumType))->getConstants();
foreach (static::autodiscoveredValues() as $value) {
$constantName = array_search($value, $constants, true);
self::$guessedReadables[$enumType][$value] = ucfirst(strtolower(str_replace('_', ' ', $constantName)));
}
}

return self::$guessedReadables[$enumType];
}
}
76 changes: 0 additions & 76 deletions src/ChoiceEnumTrait.php

This file was deleted.

21 changes: 6 additions & 15 deletions src/FlaggedEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,13 @@

abstract class FlaggedEnum extends ReadableEnum
{
use AutoDiscoveredReadablesTrait;

const NONE = 0;

/** @var array */
private static $masks = [];

/** @var array */
private static $readables = [];

/** @var int[] */
protected $flags;

Expand All @@ -45,19 +44,11 @@ public static function accepts($value): bool
/**
* {@inheritdoc}
*/
public static function readables(): array
public static function values(): array
{
$enumType = static::class;

if (!isset(self::$readables[$enumType])) {
$constants = (new \ReflectionClass($enumType))->getConstants();
foreach (static::values() as $value) {
$constantName = array_search($value, $constants, true);
self::$readables[$enumType][$value] = ucfirst(strtolower(str_replace('_', ' ', $constantName)));
}
}

return self::$readables[$enumType];
return array_values(array_filter(parent::values(), function (int $v): bool {
return 0 === ($v & $v - 1);
}));
}

/**
Expand Down
13 changes: 10 additions & 3 deletions src/ReadableEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@

abstract class ReadableEnum extends Enum implements ReadableEnumInterface
{
/**
* {@inheritdoc}
*/
public static function values(): array
{
return array_keys(static::readables());
}

/**
* {@inheritdoc}
*/
Expand All @@ -22,9 +30,8 @@ public static function readableFor($value): string
if (!static::accepts($value)) {
throw new InvalidValueException($value, static::class);
}
$humanRepresentations = static::readables();

return $humanRepresentations[$value];
return static::readables()[$value];
}

/**
Expand All @@ -40,6 +47,6 @@ public function getReadable(): string
*/
public function __toString()
{
return (string) $this->getReadable();
return $this->getReadable();
}
}
25 changes: 0 additions & 25 deletions src/SimpleChoiceEnum.php

This file was deleted.

23 changes: 0 additions & 23 deletions tests/Fixtures/Enum/AlarmScheduleType.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,4 @@ final class AlarmScheduleType extends FlaggedEnum
const SATURDAY_AFTERNOON = 1 << 11;
const SUNDAY_MORNING = 1 << 12;
const SUNDAY_AFTERNOON = 1 << 13;

/**
* {@inheritdoc}
*/
public static function values(): array
{
return [
static::MONDAY_MORNING,
static::MONDAY_AFTERNOON,
static::TUESDAY_MORNING,
static::TUESDAY_AFTERNOON,
static::WEDNESDAY_MORNING,
static::WEDNESDAY_AFTERNOON,
static::THURSDAY_MORNING,
static::THURSDAY_AFTERNOON,
static::FRIDAY_MORNING,
static::FRIDAY_AFTERNOON,
static::SATURDAY_MORNING,
static::SATURDAY_AFTERNOON,
static::SUNDAY_MORNING,
static::SUNDAY_AFTERNOON,
];
}
}
9 changes: 0 additions & 9 deletions tests/Fixtures/Enum/Permissions.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,6 @@ final class Permissions extends FlaggedEnum

const ALL = self::EXECUTE | self::WRITE | self::READ;

public static function values(): array
{
return [
static::EXECUTE,
static::WRITE,
static::READ,
];
}

public static function readables(): array
{
return [
Expand Down
Loading

0 comments on commit 9153b70

Please sign in to comment.