From 540bf0d59afe41276e250b85c6b499561511fe86 Mon Sep 17 00:00:00 2001 From: Ilya Tregubov Date: Thu, 9 Dec 2021 16:11:14 +0200 Subject: [PATCH] MDL-71723 core: Upgrade php-enum to 1.8.3 --- lib/php-enum/src/Enum.php | 86 +++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 9 deletions(-) diff --git a/lib/php-enum/src/Enum.php b/lib/php-enum/src/Enum.php index b8b93277e2c..89064eba743 100644 --- a/lib/php-enum/src/Enum.php +++ b/lib/php-enum/src/Enum.php @@ -17,6 +17,7 @@ namespace MyCLabs\Enum; * * @psalm-template T * @psalm-immutable + * @psalm-consistent-constructor */ abstract class Enum implements \JsonSerializable { @@ -28,6 +29,13 @@ abstract class Enum implements \JsonSerializable */ protected $value; + /** + * Enum key, the constant name + * + * @var string + */ + private $key; + /** * Store existing constants in a static cache per object. * @@ -51,7 +59,7 @@ abstract class Enum implements \JsonSerializable * @psalm-pure * @param mixed $value * - * @psalm-param static|T $value + * @psalm-param T $value * @throws \UnexpectedValueException if incompatible type is given. */ public function __construct($value) @@ -61,15 +69,40 @@ abstract class Enum implements \JsonSerializable $value = $value->getValue(); } - if (!$this->isValid($value)) { - /** @psalm-suppress InvalidCast */ - throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class); - } + /** @psalm-suppress ImplicitToStringCast assertValidValueReturningKey returns always a string but psalm has currently an issue here */ + $this->key = static::assertValidValueReturningKey($value); /** @psalm-var T */ $this->value = $value; } + /** + * This method exists only for the compatibility reason when deserializing a previously serialized version + * that didn't had the key property + */ + public function __wakeup() + { + /** @psalm-suppress DocblockTypeContradiction key can be null when deserializing an enum without the key */ + if ($this->key === null) { + /** + * @psalm-suppress InaccessibleProperty key is not readonly as marked by psalm + * @psalm-suppress PossiblyFalsePropertyAssignmentValue deserializing a case that was removed + */ + $this->key = static::search($this->value); + } + } + + /** + * @param mixed $value + * @return static + */ + public static function from($value): self + { + $key = static::assertValidValueReturningKey($value); + + return self::__callStatic($key, []); + } + /** * @psalm-pure * @return mixed @@ -84,11 +117,11 @@ abstract class Enum implements \JsonSerializable * Returns the enum key (i.e. the constant name). * * @psalm-pure - * @return mixed + * @return string */ public function getKey() { - return static::search($this->value); + return $this->key; } /** @@ -163,7 +196,9 @@ abstract class Enum implements \JsonSerializable $class = static::class; if (!isset(static::$cache[$class])) { + /** @psalm-suppress ImpureMethodCall this reflection API usage has no side-effects here */ $reflection = new \ReflectionClass($class); + /** @psalm-suppress ImpureMethodCall this reflection API usage has no side-effects here */ static::$cache[$class] = $reflection->getConstants(); } @@ -176,6 +211,7 @@ abstract class Enum implements \JsonSerializable * @param $value * @psalm-param mixed $value * @psalm-pure + * @psalm-assert-if-true T $value * @return bool */ public static function isValid($value) @@ -183,6 +219,35 @@ abstract class Enum implements \JsonSerializable return \in_array($value, static::toArray(), true); } + /** + * Asserts valid enum value + * + * @psalm-pure + * @psalm-assert T $value + * @param mixed $value + */ + public static function assertValidValue($value): void + { + self::assertValidValueReturningKey($value); + } + + /** + * Asserts valid enum value + * + * @psalm-pure + * @psalm-assert T $value + * @param mixed $value + * @return string + */ + private static function assertValidValueReturningKey($value): string + { + if (false === ($key = static::search($value))) { + throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class); + } + + return $key; + } + /** * Check if is valid enum key * @@ -201,11 +266,11 @@ abstract class Enum implements \JsonSerializable /** * Return key for value * - * @param $value + * @param mixed $value * * @psalm-param mixed $value * @psalm-pure - * @return mixed + * @return string|false */ public static function search($value) { @@ -220,6 +285,8 @@ abstract class Enum implements \JsonSerializable * * @return static * @throws \BadMethodCallException + * + * @psalm-pure */ public static function __callStatic($name, $arguments) { @@ -243,6 +310,7 @@ abstract class Enum implements \JsonSerializable * @link http://php.net/manual/en/jsonserializable.jsonserialize.php * @psalm-pure */ + #[\ReturnTypeWillChange] public function jsonSerialize() { return $this->getValue();