Skip to content

Commit

Permalink
Updated enum to last PMMP changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
matcracker committed Jun 4, 2020
1 parent 1c4eef5 commit 8fda6d3
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 130 deletions.
93 changes: 35 additions & 58 deletions src/matcracker/BedcoreProtect/enums/EnumTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,21 @@ trait EnumTrait
{
use RegistryTrait;

/** @var int|null */
private static $nextId = null;
/** @var string */
private $enumName;
/** @var int */
private $runtimeId;

/**
* @param string $enumName
* Registers the given object as an enum member.
*
* @throws InvalidArgumentException
*/
private function __construct(string $enumName)
protected static function register(self $member): void
{
static $pattern = '/^\D[A-Za-z\d_]+$/u';
if (preg_match($pattern, $enumName, $matches) === 0) {
throw new InvalidArgumentException("Invalid enum member name \"$enumName\", should only contain letters, numbers and underscores, and must not start with a number");
}
$this->enumName = $enumName;
if (self::$nextId === null) {
self::$nextId = getmypid(); //this provides enough base entropy to prevent hardcoding
self::_registryRegister($member->name(), $member);
}

protected static function registerAll(self ...$members): void
{
foreach ($members as $member) {
self::register($member);
}
$this->runtimeId = self::$nextId++;
}

/**
Expand All @@ -63,62 +56,50 @@ private function __construct(string $enumName)
*/
public static function getAll(): array
{
return self::_registryGetAll();
//phpstan doesn't support generic traits yet :(
/** @var self[] $result */
$result = self::_registryGetAll();
return $result;
}

/**
* Returns the enum member matching the given name.
* This is overridden to change the return typehint.
*
* @param string $name
*
* @return self
* @throws InvalidArgumentException if no member matches.
*/
public static function fromString(string $name): self
{
return self::_registryFromString($name);
//phpstan doesn't support generic traits yet :(
/** @var self $result */
$result = self::_registryFromString($name);
return $result;
}

/**
* @throws InvalidArgumentException
* @internal Lazy-inits the enum if necessary.
*
*/
protected static function checkInit(): void
{
if (self::$members === null) {
self::$members = [];
foreach (self::setup() as $item) {
self::register($item);
}
}
}
/** @var int|null */
private static $nextId = null;

/**
* Returns an array of enum members to be registered.
*
* (This ought to be private, but traits suck too much for that.)
*
* @return self[]|iterable
*/
abstract protected static function setup(): iterable;
/** @var string */
private $enumName;
/** @var int */
private $runtimeId;

/**
* Registers the given object as an enum member.
*
* @param self $member
*
* @throws InvalidArgumentException
*/
protected static function register(self $member): void
private function __construct(string $enumName)
{
self::_registryRegister($member->name(), $member);
static $pattern = '/^\D[A-Za-z\d_]+$/u';
if (preg_match($pattern, $enumName, $matches) === 0) {
throw new InvalidArgumentException("Invalid enum member name \"$enumName\", should only contain letters, numbers and underscores, and must not start with a number");
}
$this->enumName = $enumName;
if (self::$nextId === null) {
self::$nextId = getmypid(); //this provides enough base entropy to prevent hardcoding
}
$this->runtimeId = self::$nextId++;
}

/**
* @return string
*/
public function name(): string
{
return $this->enumName;
Expand All @@ -128,8 +109,6 @@ public function name(): string
* Returns a runtime-only identifier for this enum member. This will be different with each run, so don't try to
* hardcode it.
* This can be useful for switches or array indexing.
*
* @return int
*/
public function id(): int
{
Expand All @@ -138,9 +117,7 @@ public function id(): int

/**
* Returns whether the two objects are equivalent.
*
* @param self $other
*
* @param EnumTrait $other
* @return bool
*/
public function equals(self $other): bool
Expand Down
141 changes: 69 additions & 72 deletions src/matcracker/BedcoreProtect/enums/RegistryTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
use Error;
use InvalidArgumentException;
use ReflectionClass;
use ReflectionException;
use ReflectionMethod;
use function array_map;
use function count;
use function get_class;
use function implode;
Expand All @@ -43,28 +43,90 @@ trait RegistryTrait
/** @var object[] */
private static $members = null;

/**
* Adds the given object to the registry.
*
* @throws InvalidArgumentException
*/
private static function _registryRegister(string $name, object $member): void
{
$name = strtoupper($name);
if (isset(self::$members[$name])) {
throw new InvalidArgumentException("\"$name\" is already reserved");
}
self::$members[strtoupper($name)] = $member;
}

/**
* Inserts default entries into the registry.
*
* (This ought to be private, but traits suck too much for that.)
*/
abstract protected static function setup(): void;

/**
* @throws InvalidArgumentException
* @internal Lazy-inits the enum if necessary.
*
*/
protected static function checkInit(): void
{
if (self::$members === null) {
self::$members = [];
self::setup();
}
}

/**
* @throws InvalidArgumentException
*/
private static function _registryFromString(string $name): object
{
self::checkInit();
$name = strtoupper($name);
if (!isset(self::$members[$name])) {
throw new InvalidArgumentException("No such registry member: " . self::class . "::" . $name);
}
return self::preprocessMember(self::$members[$name]);
}

protected static function preprocessMember(object $member): object
{
return $member;
}

/**
* @param string $name
* @param array $arguments
* @param mixed[] $arguments
* @phpstan-param list<mixed> $arguments
*
* @return object
*/
public static function __callStatic($name, $arguments)
{
if (!empty($arguments)) {
if (count($arguments) > 0) {
throw new ArgumentCountError("Expected exactly 0 arguments, " . count($arguments) . " passed");
}
try {
return self::fromString($name);
return self::_registryFromString($name);
} catch (InvalidArgumentException $e) {
throw new Error($e->getMessage(), 0, $e);
}
}

/**
* @return object[]
*/
private static function _registryGetAll(): array
{
self::checkInit();
return array_map(function (object $o): object {
return self::preprocessMember($o);
}, self::$members);
}

/**
* Generates code for static methods for all known registry members.
*
* @return string
*/
public static function _generateGetters(): string
{
Expand All @@ -83,9 +145,6 @@ public static function %1$s() : %2$s{

/**
* Generates a block of @ method annotations for accessors for this registry's known members.
*
* @return string
* @throws ReflectionException
*/
public static function _generateMethodAnnotations(): string
{
Expand Down Expand Up @@ -118,66 +177,4 @@ public static function _generateMethodAnnotations(): string
$lines[] = " */\n";
return implode("\n", $lines);
}

/**
* Adds the given object to the registry.
*
* @param string $name
* @param object $member
*
* @throws InvalidArgumentException
*/
private static function _registryRegister(string $name, object $member): void
{
$name = strtoupper($name);
if (isset(self::$members[$name])) {
throw new InvalidArgumentException("\"$name\" is already reserved");
}
self::$members[strtoupper($name)] = $member;
}

/**
* @param string $name
*
* @return object
* @throws InvalidArgumentException
*/
private static function _registryFromString(string $name): object
{
self::checkInit();
$name = strtoupper($name);
if (!isset(self::$members[$name])) {
throw new InvalidArgumentException("No such registry member: " . self::class . "::" . $name);
}
return self::$members[$name];
}

/**
* @throws InvalidArgumentException
* @internal Lazy-inits the enum if necessary.
*
*/
protected static function checkInit(): void
{
if (self::$members === null) {
self::$members = [];
self::setup();
}
}

/**
* Inserts default entries into the registry.
*
* (This ought to be private, but traits suck too much for that.)
*/
abstract protected static function setup(): void;

/**
* @return object[]
*/
private static function _registryGetAll(): array
{
self::checkInit();
return self::$members;
}
}
}

0 comments on commit 8fda6d3

Please sign in to comment.