| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 | 
							- <?php
 
- declare(strict_types = 1);
 
- namespace DASPRiD\Enum;
 
- use DASPRiD\Enum\Exception\CloneNotSupportedException;
 
- use DASPRiD\Enum\Exception\IllegalArgumentException;
 
- use DASPRiD\Enum\Exception\MismatchException;
 
- use DASPRiD\Enum\Exception\SerializeNotSupportedException;
 
- use DASPRiD\Enum\Exception\UnserializeNotSupportedException;
 
- use ReflectionClass;
 
- abstract class AbstractEnum
 
- {
 
-     /**
 
-      * @var string
 
-      */
 
-     private $name;
 
-     /**
 
-      * @var int
 
-      */
 
-     private $ordinal;
 
-     /**
 
-      * @var array<string, array<string, static>>
 
-      */
 
-     private static $values = [];
 
-     /**
 
-      * @var array<string, bool>
 
-      */
 
-     private static $allValuesLoaded = [];
 
-     /**
 
-      * @var array<string, array>
 
-      */
 
-     private static $constants = [];
 
-     /**
 
-      * The constructor is private by default to avoid arbitrary enum creation.
 
-      *
 
-      * When creating your own constructor for a parameterized enum, make sure to declare it as protected, so that
 
-      * the static methods are able to construct it. Avoid making it public, as that would allow creation of
 
-      * non-singleton enum instances.
 
-      */
 
-     private function __construct()
 
-     {
 
-     }
 
-     /**
 
-      * Magic getter which forwards all calls to {@see self::valueOf()}.
 
-      *
 
-      * @return static
 
-      */
 
-     final public static function __callStatic(string $name, array $arguments) : self
 
-     {
 
-         return static::valueOf($name);
 
-     }
 
-     /**
 
-      * Returns an enum with the specified name.
 
-      *
 
-      * The name must match exactly an identifier used to declare an enum in this type (extraneous whitespace characters
 
-      * are not permitted).
 
-      *
 
-      * @return static
 
-      * @throws IllegalArgumentException if the enum has no constant with the specified name
 
-      */
 
-     final public static function valueOf(string $name) : self
 
-     {
 
-         if (isset(self::$values[static::class][$name])) {
 
-             return self::$values[static::class][$name];
 
-         }
 
-         $constants = self::constants();
 
-         if (array_key_exists($name, $constants)) {
 
-             return self::createValue($name, $constants[$name][0], $constants[$name][1]);
 
-         }
 
-         throw new IllegalArgumentException(sprintf('No enum constant %s::%s', static::class, $name));
 
-     }
 
-     /**
 
-      * @return static
 
-      */
 
-     final private static function createValue(string $name, int $ordinal, array $arguments) : self
 
-     {
 
-         $instance = new static(...$arguments);
 
-         $instance->name = $name;
 
-         $instance->ordinal = $ordinal;
 
-         self::$values[static::class][$name] = $instance;
 
-         return $instance;
 
-     }
 
-     /**
 
-      * Obtains all possible types defined by this enum.
 
-      *
 
-      * @return static[]
 
-      */
 
-     final public static function values() : array
 
-     {
 
-         if (isset(self::$allValuesLoaded[static::class])) {
 
-             return self::$values[static::class];
 
-         }
 
-         if (! isset(self::$values[static::class])) {
 
-             self::$values[static::class] = [];
 
-         }
 
-         foreach (self::constants() as $name => $constant) {
 
-             if (array_key_exists($name, self::$values[static::class])) {
 
-                 continue;
 
-             }
 
-             static::createValue($name, $constant[0], $constant[1]);
 
-         }
 
-         uasort(self::$values[static::class], function (self $a, self $b) {
 
-             return $a->ordinal() <=> $b->ordinal();
 
-         });
 
-         self::$allValuesLoaded[static::class] = true;
 
-         return self::$values[static::class];
 
-     }
 
-     final private static function constants() : array
 
-     {
 
-         if (isset(self::$constants[static::class])) {
 
-             return self::$constants[static::class];
 
-         }
 
-         self::$constants[static::class] = [];
 
-         $reflectionClass = new ReflectionClass(static::class);
 
-         $ordinal = -1;
 
-         foreach ($reflectionClass->getReflectionConstants() as $reflectionConstant) {
 
-             if (! $reflectionConstant->isProtected()) {
 
-                 continue;
 
-             }
 
-             $value = $reflectionConstant->getValue();
 
-             self::$constants[static::class][$reflectionConstant->name] = [
 
-                 ++$ordinal,
 
-                 is_array($value) ? $value : []
 
-             ];
 
-         }
 
-         return self::$constants[static::class];
 
-     }
 
-     /**
 
-      * Returns the name of this enum constant, exactly as declared in its enum declaration.
 
-      *
 
-      * Most programmers should use the {@see self::__toString()} method in preference to this one, as the toString
 
-      * method may return a more user-friendly name. This method is designed primarily for use in specialized situations
 
-      * where correctness depends on getting the exact name, which will not vary from release to release.
 
-      */
 
-     final public function name() : string
 
-     {
 
-         return $this->name;
 
-     }
 
-     /**
 
-      * Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial
 
-      * constant is assigned an ordinal of zero).
 
-      *
 
-      * Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data
 
-      * structures.
 
-      */
 
-     final public function ordinal() : int
 
-     {
 
-         return $this->ordinal;
 
-     }
 
-     /**
 
-      * Compares this enum with the specified object for order.
 
-      *
 
-      * Returns negative integer, zero or positive integer as this object is less than, equal to or greater than the
 
-      * specified object.
 
-      *
 
-      * Enums are only comparable to other enums of the same type. The natural order implemented by this method is the
 
-      * order in which the constants are declared.
 
-      *
 
-      * @throws MismatchException if the passed enum is not of the same type
 
-      */
 
-     final public function compareTo(self $other) : int
 
-     {
 
-         if (! $other instanceof static) {
 
-             throw new MismatchException(sprintf(
 
-                 'The passed enum %s is not of the same type as %s',
 
-                 get_class($other),
 
-                 static::class
 
-             ));
 
-         }
 
-         return $this->ordinal - $other->ordinal;
 
-     }
 
-     /**
 
-      * Forbid cloning enums.
 
-      *
 
-      * @throws CloneNotSupportedException
 
-      */
 
-     final public function __clone()
 
-     {
 
-         throw new CloneNotSupportedException();
 
-     }
 
-     /**
 
-      * Forbid serializing enums.
 
-      *
 
-      * @throws SerializeNotSupportedException
 
-      */
 
-     final public function __sleep() : void
 
-     {
 
-         throw new SerializeNotSupportedException();
 
-     }
 
-     /**
 
-      * Forbid unserializing enums.
 
-      *
 
-      * @throws UnserializeNotSupportedException
 
-      */
 
-     final public function __wakeup() : void
 
-     {
 
-         throw new UnserializeNotSupportedException();
 
-     }
 
-     /**
 
-      * Turns the enum into a string representation.
 
-      *
 
-      * You may override this method to give a more user-friendly version.
 
-      */
 
-     public function __toString() : string
 
-     {
 
-         return $this->name;
 
-     }
 
- }
 
 
  |