From b2e7f7d41101eeb90f179574eec07d0398b256fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Make=C5=A1?= Date: Sun, 15 Dec 2019 14:02:43 +0100 Subject: [PATCH 01/61] Changed PHP from 7.4 beta to stable in TravisCI --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 99e7178..a9f9cd8 100755 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ php: - '7.1' - '7.2' - '7.3' - - '7.4snapshot' + - '7.4' matrix: fast_finish: true From 0f7ae5f21f8bc776815891f9b0d7530f7b735513 Mon Sep 17 00:00:00 2001 From: Jarred Stelfox Date: Thu, 6 Feb 2020 16:41:46 -0800 Subject: [PATCH 02/61] PHPUnit: Update to a modern version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 871156d..86a3de3 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ "ext-json": "*" }, "require-dev": { - "phpunit/phpunit": "^4.8.35|^5.7|^6.0", + "phpunit/phpunit": "^7", "squizlabs/php_codesniffer": "1.*" } } From 4c20d3f4d0bd9037be67650fd81f3f5e3551c6c1 Mon Sep 17 00:00:00 2001 From: Jarred Stelfox Date: Thu, 6 Feb 2020 16:42:31 -0800 Subject: [PATCH 03/61] Psalm: Add to allow type checking --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 86a3de3..1c7ba1c 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,8 @@ }, "require": { "php": ">=7.1", - "ext-json": "*" + "ext-json": "*", + "vimeo/psalm": "^3.8" }, "require-dev": { "phpunit/phpunit": "^7", From d81fc4fde33aa9536435febeb9f81d6fcd132865 Mon Sep 17 00:00:00 2001 From: Jarred Stelfox Date: Thu, 6 Feb 2020 16:44:12 -0800 Subject: [PATCH 04/61] Psalm: Set up to be the most strict settings --- psalm.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 psalm.xml diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000..b07e929 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + From 3116aff3398745dfb569d43d1fa65689a1b9a1d9 Mon Sep 17 00:00:00 2001 From: Jarred Stelfox Date: Thu, 6 Feb 2020 16:46:33 -0800 Subject: [PATCH 05/61] Psalm: Add psalm types to remove most psalm errors --- src/Enum.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/Enum.php b/src/Enum.php index 3bce0dc..d750289 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -14,6 +14,9 @@ * @author Matthieu Napoli * @author Daniel Costa * @author Mirosław Filip + * + * @template T + * @psalm-immutable */ abstract class Enum implements \JsonSerializable { @@ -21,6 +24,7 @@ abstract class Enum implements \JsonSerializable * Enum value * * @var mixed + * @psalm-var T */ protected $value; @@ -28,6 +32,7 @@ abstract class Enum implements \JsonSerializable * Store existing constants in a static cache per object. * * @var array + * @psalm-var array> */ protected static $cache = []; @@ -36,6 +41,8 @@ abstract class Enum implements \JsonSerializable * * @param mixed $value * + * @psalm-param T $value + * @psalm-suppress InvalidCast * @throws \UnexpectedValueException if incompatible type is given. */ public function __construct($value) @@ -53,6 +60,7 @@ public function __construct($value) /** * @return mixed + * @psalm-return T */ public function getValue() { @@ -62,6 +70,7 @@ public function getValue() /** * Returns the enum key (i.e. the constant name). * + * @psalm-pure * @return mixed */ public function getKey() @@ -70,6 +79,7 @@ public function getKey() } /** + * @psalm-suppress InvalidCast * @return string */ public function __toString() @@ -83,6 +93,7 @@ public function __toString() * * This method is final, for more information read https://github.com/myclabs/php-enum/issues/4 * + * @psalm-param mixed $variable * @return bool */ final public function equals($variable = null): bool @@ -121,6 +132,8 @@ public static function values() /** * Returns all possible values as an array * + * @psalm-pure + * @psalm-return array * @return array Constant name in key, constant value in value */ public static function toArray() @@ -138,6 +151,7 @@ public static function toArray() * Check if is valid enum value * * @param $value + * @psalm-param mixed $value * * @return bool */ @@ -150,6 +164,7 @@ public static function isValid($value) * Check if is valid enum key * * @param $key + * @psalm-param string $key * * @return bool */ @@ -165,6 +180,8 @@ public static function isValidKey($key) * * @param $value * + * @psalm-param mixed $value + * @psalm-pure * @return mixed */ public static function search($value) From efff03a72c4454d9019616f486c04b84354f2049 Mon Sep 17 00:00:00 2001 From: Jarred Stelfox Date: Thu, 6 Feb 2020 16:49:46 -0800 Subject: [PATCH 06/61] Psalm: Make happy inside an immutable class For some reason psalm doesnt like get_called_class even when I tried to stub it to explain to psalm this method was pure (immutable) Instead lets use another valid method for getting the late static bond class name --- src/Enum.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Enum.php b/src/Enum.php index d750289..5c15251 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -52,7 +52,7 @@ public function __construct($value) } if (!$this->isValid($value)) { - throw new \UnexpectedValueException("Value '$value' is not part of the enum " . \get_called_class()); + throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class); } $this->value = $value; @@ -100,7 +100,7 @@ final public function equals($variable = null): bool { return $variable instanceof self && $this->getValue() === $variable->getValue() - && \get_called_class() === \get_class($variable); + && static::class === \get_class($variable); } /** @@ -138,7 +138,8 @@ public static function values() */ public static function toArray() { - $class = \get_called_class(); + $class = static::class; + if (!isset(static::$cache[$class])) { $reflection = new \ReflectionClass($class); static::$cache[$class] = $reflection->getConstants(); @@ -205,7 +206,7 @@ public static function __callStatic($name, $arguments) return new static($array[$name]); } - throw new \BadMethodCallException("No static method or enum constant '$name' in class " . \get_called_class()); + throw new \BadMethodCallException("No static method or enum constant '$name' in class " . static::class); } /** From 0fd28e9ed4f2e92793b151526c41f68a4aaee622 Mon Sep 17 00:00:00 2001 From: Jarred Stelfox Date: Thu, 6 Feb 2020 16:52:13 -0800 Subject: [PATCH 07/61] Psalm: Add to travis Lets static type check all pulls --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a9f9cd8..c6ac198 100755 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,7 @@ before_script: script: - vendor/bin/phpunit + - vendor/bin/psalm --shepherd # Use Travis' new container-based infrastructure. # See http://docs.travis-ci.com/user/migrating-from-legacy/#How-can-I-use-container-based-infrastructure%3F From cb27bc182b08826828e9bbd620f22526d78c3286 Mon Sep 17 00:00:00 2001 From: Jarred Stelfox Date: Thu, 6 Feb 2020 16:56:20 -0800 Subject: [PATCH 08/61] Readme: Add Type checking badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7bdd4f8..6065f49 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![Build Status](https://travis-ci.org/myclabs/php-enum.png?branch=master)](https://travis-ci.org/myclabs/php-enum) [![Latest Stable Version](https://poser.pugx.org/myclabs/php-enum/version.png)](https://packagist.org/packages/myclabs/php-enum) [![Total Downloads](https://poser.pugx.org/myclabs/php-enum/downloads.png)](https://packagist.org/packages/myclabs/php-enum) +[![psalm](https://shepherd.dev/github/myclabs/php-enum/coverage.svg)](https://shepherd.dev/github/myclabs/php-enum) Maintenance for this project is [supported via Tidelift](https://tidelift.com/subscription/pkg/packagist-myclabs-php-enum?utm_source=packagist-myclabs-php-enum&utm_medium=referral&utm_campaign=readme). From c3f3b36602748871098069f4f2f8224ca34df899 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Fri, 7 Feb 2020 09:35:07 +0100 Subject: [PATCH 09/61] Move psalm to require-dev --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 1c7ba1c..6861a5c 100644 --- a/composer.json +++ b/composer.json @@ -23,11 +23,11 @@ }, "require": { "php": ">=7.1", - "ext-json": "*", - "vimeo/psalm": "^3.8" + "ext-json": "*" }, "require-dev": { "phpunit/phpunit": "^7", - "squizlabs/php_codesniffer": "1.*" + "squizlabs/php_codesniffer": "1.*", + "vimeo/psalm": "^3.8" } } From f69348a23f014f5d9ceaa44ed71368fab16eb470 Mon Sep 17 00:00:00 2001 From: Andrew Gilbert Date: Mon, 10 Feb 2020 12:53:39 -0700 Subject: [PATCH 10/61] Be more specific about where to suppress `InvalidCast` --- src/Enum.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index 5c15251..c07454b 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -42,7 +42,6 @@ abstract class Enum implements \JsonSerializable * @param mixed $value * * @psalm-param T $value - * @psalm-suppress InvalidCast * @throws \UnexpectedValueException if incompatible type is given. */ public function __construct($value) @@ -52,6 +51,7 @@ public function __construct($value) } if (!$this->isValid($value)) { + /** @psalm-suppress InvalidCast */ throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class); } From 396357fbc4b25c131ff85ca5fb3e42063e96b871 Mon Sep 17 00:00:00 2001 From: Andrew Gilbert Date: Mon, 10 Feb 2020 12:56:20 -0700 Subject: [PATCH 11/61] Mark static methods as `external-mutation-free` They all modify the cache, so they can't be `mutation-free`, and they rely on the object state, so they're not `pure`. --- src/Enum.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Enum.php b/src/Enum.php index c07454b..39796eb 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -70,7 +70,7 @@ public function getValue() /** * Returns the enum key (i.e. the constant name). * - * @psalm-pure + * @psalm-external-mutation-free * @return mixed */ public function getKey() @@ -106,6 +106,7 @@ final public function equals($variable = null): bool /** * Returns the names (keys) of all constants in the Enum class * + * @psalm-external-mutation-free * @return array */ public static function keys() @@ -116,6 +117,7 @@ public static function keys() /** * Returns instances of the Enum class of all Enum constants * + * @psalm-external-mutation-free * @return static[] Constant name in key, Enum instance in value */ public static function values() @@ -132,7 +134,7 @@ public static function values() /** * Returns all possible values as an array * - * @psalm-pure + * @psalm-external-mutation-free * @psalm-return array * @return array Constant name in key, constant value in value */ @@ -153,7 +155,7 @@ public static function toArray() * * @param $value * @psalm-param mixed $value - * + * @psalm-external-mutation-free * @return bool */ public static function isValid($value) @@ -166,7 +168,7 @@ public static function isValid($value) * * @param $key * @psalm-param string $key - * + * @psalm-external-mutation-free * @return bool */ public static function isValidKey($key) @@ -182,7 +184,7 @@ public static function isValidKey($key) * @param $value * * @psalm-param mixed $value - * @psalm-pure + * @psalm-external-mutation-free * @return mixed */ public static function search($value) @@ -197,6 +199,7 @@ public static function search($value) * @param array $arguments * * @return static + * @psalm-external-mutation-free * @throws \BadMethodCallException */ public static function __callStatic($name, $arguments) From e58f812b736b4dcc0c0c279b89ad9a4b60158f64 Mon Sep 17 00:00:00 2001 From: Andrew Gilbert Date: Mon, 10 Feb 2020 12:57:21 -0700 Subject: [PATCH 12/61] Explain construction typing to Psalm This makes it so Psalm doesn't think we're passing `mixed` values around. We're either constructing using an instance of ourselves, or using a value which we're going to wrap. --- src/Enum.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index 39796eb..6605538 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -41,12 +41,13 @@ abstract class Enum implements \JsonSerializable * * @param mixed $value * - * @psalm-param T $value + * @psalm-param static|T $value * @throws \UnexpectedValueException if incompatible type is given. */ public function __construct($value) { if ($value instanceof static) { + /** @psalm-var T */ $value = $value->getValue(); } @@ -55,6 +56,7 @@ public function __construct($value) throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class); } + /** @psalm-var T */ $this->value = $value; } From 967787b5d216f480f1fea1ab7f3e519b8bfcbcd9 Mon Sep 17 00:00:00 2001 From: Andrew Gilbert Date: Mon, 10 Feb 2020 12:58:20 -0700 Subject: [PATCH 13/61] Add more-specific Psalm return types Might as well be more precise about this, as Psalm supports doing so. --- src/Enum.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Enum.php b/src/Enum.php index 6605538..1dec57e 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -109,6 +109,7 @@ final public function equals($variable = null): bool * Returns the names (keys) of all constants in the Enum class * * @psalm-external-mutation-free + * @psalm-return list * @return array */ public static function keys() @@ -120,6 +121,7 @@ public static function keys() * Returns instances of the Enum class of all Enum constants * * @psalm-external-mutation-free + * @psalm-return array * @return static[] Constant name in key, Enum instance in value */ public static function values() From 27aa6b1c43cb0898f1582fc07ff673fc20e953c7 Mon Sep 17 00:00:00 2001 From: Andrew Gilbert Date: Mon, 10 Feb 2020 12:58:49 -0700 Subject: [PATCH 14/61] Explain loop typing to Psalm This makes it clear that we're not passing `mixed` values around. --- src/Enum.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Enum.php b/src/Enum.php index 1dec57e..9f5e974 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -128,6 +128,7 @@ public static function values() { $values = array(); + /** @psalm-var T $value */ foreach (static::toArray() as $key => $value) { $values[$key] = new static($value); } From 3d5c198dc031d468d865e9c5695f7cb28aa3ab91 Mon Sep 17 00:00:00 2001 From: Jarred Stelfox Date: Wed, 12 Feb 2020 09:31:15 -0800 Subject: [PATCH 15/61] Mark all methods as pure This means every function can be called from an immutable / pure context Note: ToArray will fail psalm on this commit as (rightfully) there is an impure psalm issue This commit is a bit of a lie to psalm: Psalm is correct that our object is not actually immutable / pure. But is if you remove caching. This lie seems tolerable (despite how bad a practice overriding the typechecker is) because the mutation is entirely memoization. --- src/Enum.php | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/Enum.php b/src/Enum.php index 9f5e974..b502c34 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -31,6 +31,8 @@ abstract class Enum implements \JsonSerializable /** * Store existing constants in a static cache per object. * + * @psalm-pure + * * @var array * @psalm-var array> */ @@ -39,6 +41,7 @@ abstract class Enum implements \JsonSerializable /** * Creates a new value of some type * + * @psalm-pure * @param mixed $value * * @psalm-param static|T $value @@ -61,6 +64,7 @@ public function __construct($value) } /** + * @psalm-pure * @return mixed * @psalm-return T */ @@ -72,7 +76,7 @@ public function getValue() /** * Returns the enum key (i.e. the constant name). * - * @psalm-external-mutation-free + * @psalm-pure * @return mixed */ public function getKey() @@ -81,6 +85,7 @@ public function getKey() } /** + * @psalm-pure * @psalm-suppress InvalidCast * @return string */ @@ -95,6 +100,7 @@ public function __toString() * * This method is final, for more information read https://github.com/myclabs/php-enum/issues/4 * + * @psalm-pure * @psalm-param mixed $variable * @return bool */ @@ -108,7 +114,7 @@ final public function equals($variable = null): bool /** * Returns the names (keys) of all constants in the Enum class * - * @psalm-external-mutation-free + * @psalm-pure * @psalm-return list * @return array */ @@ -120,7 +126,7 @@ public static function keys() /** * Returns instances of the Enum class of all Enum constants * - * @psalm-external-mutation-free + * @psalm-pure * @psalm-return array * @return static[] Constant name in key, Enum instance in value */ @@ -139,7 +145,8 @@ public static function values() /** * Returns all possible values as an array * - * @psalm-external-mutation-free + * @psalm-pure + * * @psalm-return array * @return array Constant name in key, constant value in value */ @@ -160,7 +167,7 @@ public static function toArray() * * @param $value * @psalm-param mixed $value - * @psalm-external-mutation-free + * @psalm-pure * @return bool */ public static function isValid($value) @@ -173,7 +180,7 @@ public static function isValid($value) * * @param $key * @psalm-param string $key - * @psalm-external-mutation-free + * @psalm-pure * @return bool */ public static function isValidKey($key) @@ -189,7 +196,7 @@ public static function isValidKey($key) * @param $value * * @psalm-param mixed $value - * @psalm-external-mutation-free + * @psalm-pure * @return mixed */ public static function search($value) @@ -204,7 +211,7 @@ public static function search($value) * @param array $arguments * * @return static - * @psalm-external-mutation-free + * @psalm-pure * @throws \BadMethodCallException */ public static function __callStatic($name, $arguments) @@ -223,6 +230,7 @@ public static function __callStatic($name, $arguments) * * @return mixed * @link http://php.net/manual/en/jsonserializable.jsonserialize.php + * @psalm-pure */ public function jsonSerialize() { From 2e58f99a02d251e58b87d78ca20ced5db142151f Mon Sep 17 00:00:00 2001 From: Jarred Stelfox Date: Wed, 12 Feb 2020 09:34:01 -0800 Subject: [PATCH 16/61] Force psalm to accept toArray as pure See previous commit. Psalm isn't actually wrong here, but we are willing to lie to psalm since the impurity is just an internal cache. --- src/Enum.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Enum.php b/src/Enum.php index b502c34..0527356 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -146,6 +146,7 @@ public static function values() * Returns all possible values as an array * * @psalm-pure + * @psalm-suppress ImpureStaticProperty * * @psalm-return array * @return array Constant name in key, constant value in value From fdb1bd56df293631d94dcbb8abd7c8db685d9f8b Mon Sep 17 00:00:00 2001 From: Jarred Stelfox Date: Wed, 12 Feb 2020 09:37:43 -0800 Subject: [PATCH 17/61] Cut: Properties can not be pure This happened due to a bad find replace --- src/Enum.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index 0527356..2d2e114 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -31,7 +31,6 @@ abstract class Enum implements \JsonSerializable /** * Store existing constants in a static cache per object. * - * @psalm-pure * * @var array * @psalm-var array> From 61c12d18b5a77fbc6d7aea67038b5bb6b801d23e Mon Sep 17 00:00:00 2001 From: Jarred Stelfox Date: Thu, 13 Feb 2020 08:13:26 -0800 Subject: [PATCH 18/61] Psalm: do not collide with doctine templates --- src/Enum.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index 2d2e114..f5a5940 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -15,7 +15,7 @@ * @author Daniel Costa * @author Mirosław Filip * - * @template T + * @psalm-template T * @psalm-immutable */ abstract class Enum implements \JsonSerializable From d3ccffe21ce2153414291f2fa5fea2fb8ce5b132 Mon Sep 17 00:00:00 2001 From: Danack Date: Mon, 15 Jun 2020 10:26:05 +0100 Subject: [PATCH 19/61] fix legacy use of words. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6065f49..024c4df 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,8 @@ First, and mainly, `SplEnum` is not integrated to PHP, you have to install the e Using an enum instead of class constants provides the following advantages: -- You can type-hint: `function setAction(Action $action) {` +- You can use an enum as a parameter type: `function setAction(Action $action) {` +- You can use an enum as a return type: `function getAction() : Action {` - You can enrich the enum with methods (e.g. `format`, `parse`, …) - You can extend the enum to add new values (make your enum `final` to prevent it) - You can get a list of all the possible values (see below) @@ -54,7 +55,7 @@ $action = new Action($value); As you can see, static methods are automatically implemented to provide quick access to an enum value. -One advantage over using class constants is to be able to type-hint enum values: +One advantage over using class constants is to be able to use enum as a paramter type: ```php function setAction(Action $action) { From 7c4836a6ec7476e4aad0f6044ee2581357c8237a Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Mon, 15 Jun 2020 18:00:00 +0200 Subject: [PATCH 20/61] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 024c4df..7d09e87 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ $action = new Action($value); As you can see, static methods are automatically implemented to provide quick access to an enum value. -One advantage over using class constants is to be able to use enum as a paramter type: +One advantage over using class constants is to be able to use an enum as a parameter type: ```php function setAction(Action $action) { From 30afedaea1eec8a5fe9e32990184a682970bc167 Mon Sep 17 00:00:00 2001 From: Roman Varkuta Date: Fri, 17 Jul 2020 21:24:32 +0300 Subject: [PATCH 21/61] Add yii2-enum package to docs --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7d09e87..bf1c91d 100644 --- a/README.md +++ b/README.md @@ -131,3 +131,4 @@ class Action extends Enum - [Doctrine enum mapping](https://github.com/acelaya/doctrine-enum-type) - [Symfony ParamConverter integration](https://github.com/Ex3v/MyCLabsEnumParamConverter) - [PHPStan integration](https://github.com/timeweb/phpstan-enum) +- [Yii2 enum mapping](https://github.com/KartaviK/yii2-enum) From 86949d6e7c3f0e4c10a36ac07e147dfe77cf482b Mon Sep 17 00:00:00 2001 From: Simon Podlipsky Date: Wed, 19 Aug 2020 08:59:17 +0200 Subject: [PATCH 22/61] Add getKey() return type as string --- src/Enum.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Enum.php b/src/Enum.php index f5a5940..e239d5b 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -76,9 +76,8 @@ public function getValue() * Returns the enum key (i.e. the constant name). * * @psalm-pure - * @return mixed */ - public function getKey() + public function getKey(): string { return static::search($this->value); } @@ -193,11 +192,11 @@ public static function isValidKey($key) /** * 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) { From 82ec4acb757679ddc164f7b27b1fc527b079cde3 Mon Sep 17 00:00:00 2001 From: Daniel Beardsley Date: Wed, 28 Oct 2020 15:29:33 -0700 Subject: [PATCH 23/61] __callStatic: cache created Enum instances Instead of creating a new one each time, cache them. This only matters if you're creating thousands of these objects. I've used a small test script: > + */ + protected static $instances = []; + /** * Creates a new value of some type * @@ -211,17 +219,19 @@ public static function search($value) * @param array $arguments * * @return static - * @psalm-pure * @throws \BadMethodCallException */ public static function __callStatic($name, $arguments) { - $array = static::toArray(); - if (isset($array[$name]) || \array_key_exists($name, $array)) { - return new static($array[$name]); + $class = static::class; + if (!isset(self::$instances[$class][$name])) { + $array = static::toArray(); + if (!isset($array[$name]) && !\array_key_exists($name, $array)) { + throw new \BadMethodCallException("No static method or enum constant '$name' in class " . static::class); + } + return self::$instances[$class][$name] = new static($array[$name]); } - - throw new \BadMethodCallException("No static method or enum constant '$name' in class " . static::class); + return self::$instances[$class][$name]; } /** From facf0bfcb5944e299259aebddf50f4eb4dcf053d Mon Sep 17 00:00:00 2001 From: Daniel Beardsley Date: Thu, 29 Oct 2020 09:34:42 -0700 Subject: [PATCH 24/61] Code formatting --- src/Enum.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index c6b6ffc..4b7b5fc 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -227,7 +227,8 @@ public static function __callStatic($name, $arguments) if (!isset(self::$instances[$class][$name])) { $array = static::toArray(); if (!isset($array[$name]) && !\array_key_exists($name, $array)) { - throw new \BadMethodCallException("No static method or enum constant '$name' in class " . static::class); + $message = "No static method or enum constant '$name' in class " . static::class; + throw new \BadMethodCallException($message); } return self::$instances[$class][$name] = new static($array[$name]); } From 14edb7bd4b5219d99c3a8bc4789eef96bd006739 Mon Sep 17 00:00:00 2001 From: Daniel Beardsley Date: Fri, 30 Oct 2020 13:09:24 -0700 Subject: [PATCH 25/61] Enum::CONST(): never return same instance Enums shouldn't be compared with ===, but static accessors are now cached so === was working. Let's return a clone each time so === won't be true for values retrieved from these accessors. Note: this actually had no impact on the performance gains from a few commits ago. --- src/Enum.php | 2 +- tests/EnumTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index 4b7b5fc..b8b9327 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -232,7 +232,7 @@ public static function __callStatic($name, $arguments) } return self::$instances[$class][$name] = new static($array[$name]); } - return self::$instances[$class][$name]; + return clone self::$instances[$class][$name]; } /** diff --git a/tests/EnumTest.php b/tests/EnumTest.php index 9fe9022..cb08d29 100755 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -143,6 +143,7 @@ public function testStaticAccess() $this->assertEquals(new EnumFixture(EnumFixture::FOO), EnumFixture::FOO()); $this->assertEquals(new EnumFixture(EnumFixture::BAR), EnumFixture::BAR()); $this->assertEquals(new EnumFixture(EnumFixture::NUMBER), EnumFixture::NUMBER()); + $this->assertNotSame(EnumFixture::NUMBER(), EnumFixture::NUMBER()); } /** From 21d62a63921b72a905756b40ecbe5263af21fb21 Mon Sep 17 00:00:00 2001 From: Gregor Harlan Date: Fri, 13 Nov 2020 11:32:27 +0100 Subject: [PATCH 26/61] Remove unused psalm-suppress --- src/Enum.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index f5a5940..9b07191 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -54,7 +54,6 @@ public function __construct($value) } if (!$this->isValid($value)) { - /** @psalm-suppress InvalidCast */ throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class); } From bd92d06729d5c979f4bf5fe601c1f39e0b0ae918 Mon Sep 17 00:00:00 2001 From: Michael Petri Date: Tue, 9 Feb 2021 22:10:02 +0100 Subject: [PATCH 27/61] Added new named constructor to create enum from mixed The current implementation of Enum requires to pass a valid enum value to class constructor. With this new named constructor we can just pass any value to enum and get an instance or unexpected value exception. --- src/Enum.php | 30 +++++++++++++++++++++++++++--- tests/EnumTest.php | 27 +++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/Enum.php b/src/Enum.php index 92a42a4..3790f6e 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -61,14 +61,24 @@ public function __construct($value) $value = $value->getValue(); } - if (!$this->isValid($value)) { - throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class); - } + static::assertValidValue($value); /** @psalm-var T */ $this->value = $value; } + /** + * @param mixed $value + * @return static + * @psalm-return static + */ + public static function from($value): self + { + static::assertValidValue($value); + + return new static($value); + } + /** * @psalm-pure * @return mixed @@ -175,6 +185,7 @@ public static function toArray() * @param $value * @psalm-param mixed $value * @psalm-pure + * @psalm-assert-if-true T $value * @return bool */ public static function isValid($value) @@ -182,6 +193,19 @@ public static function isValid($value) return \in_array($value, static::toArray(), true); } + /** + * Asserts valid enum value + * + * @psalm-pure + * @psalm-assert T $value + */ + public static function assertValidValue($value): void + { + if (!static::isValid($value)) { + throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class); + } + } + /** * Check if is valid enum key * diff --git a/tests/EnumTest.php b/tests/EnumTest.php index cb08d29..674b977 100755 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -48,6 +48,18 @@ public function testCreatingEnumWithInvalidValue($value) new EnumFixture($value); } + /** + * @dataProvider invalidValueProvider + * @param mixed $value + */ + public function testFailToCreateEnumWithInvalidValueThroughNamedConstructor($value): void + { + $this->expectException(\UnexpectedValueException::class); + $this->expectExceptionMessage('is not part of the enum MyCLabs\Tests\Enum\EnumFixture'); + + EnumFixture::from($value); + } + /** * Contains values not existing in EnumFixture * @return array @@ -332,4 +344,19 @@ public function testEnumValuesInheritance() $inheritedEnumFixture = InheritedEnumFixture::VALUE(); new EnumFixture($inheritedEnumFixture); } + + /** + * @dataProvider isValidProvider + */ + public function testAssertValidValue($value, $isValid): void + { + if (!$isValid) { + $this->expectException(\UnexpectedValueException::class); + $this->expectExceptionMessage("Value '$value' is not part of the enum " . EnumFixture::class); + } + + EnumFixture::assertValidValue($value); + + self::assertTrue(EnumFixture::isValid($value)); + } } From db6a2a87422dcde7a13d023d61178be238badeea Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Fri, 12 Feb 2021 16:01:52 +0100 Subject: [PATCH 28/61] Fix #134 by marking `Enum::__callStatic` as `@psalm-pure` To achieve proper static analysis coverage: * `vimeo/psalm` has been updated * a new `static-analysis` dir has been added (to test static analysis properties **only**) * impure `$this` usages in `Enum` have been ignored in static analysis checks * PHP version support has been upgraded from `>=7.1` to `^7.3 || ^8.0` * PHPUnit version has been upgraded to its latest and greatest Fixes #134 --- .gitattributes | 1 + .travis.yml | 3 +-- composer.json | 6 +++--- phpunit.xml | 19 ++++++------------- psalm.xml | 15 +++++++++++++++ src/Enum.php | 7 ++++++- static-analysis/EnumIsPure.php | 33 +++++++++++++++++++++++++++++++++ tests/EnumTest.php | 17 +++++++---------- 8 files changed, 72 insertions(+), 29 deletions(-) create mode 100644 static-analysis/EnumIsPure.php diff --git a/.gitattributes b/.gitattributes index cd7364e..c821984 100755 --- a/.gitattributes +++ b/.gitattributes @@ -7,3 +7,4 @@ .travis.yml export-ignore tests/ export-ignore phpunit.xml export-ignore +static-analysis/ export-ignore diff --git a/.travis.yml b/.travis.yml index c6ac198..92affbf 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,9 @@ language: php php: - - '7.1' - - '7.2' - '7.3' - '7.4' + - '8.0' matrix: fast_finish: true diff --git a/composer.json b/composer.json index 6861a5c..73caf14 100644 --- a/composer.json +++ b/composer.json @@ -22,12 +22,12 @@ } }, "require": { - "php": ">=7.1", + "php": "^7.3 || ^8.0", "ext-json": "*" }, "require-dev": { - "phpunit/phpunit": "^7", + "phpunit/phpunit": "^9.5", "squizlabs/php_codesniffer": "1.*", - "vimeo/psalm": "^3.8" + "vimeo/psalm": "^4.5.1" } } diff --git a/phpunit.xml b/phpunit.xml index 67a61e1..bd714f1 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,17 +1,10 @@ - - + ./tests diff --git a/psalm.xml b/psalm.xml index b07e929..ff06b66 100644 --- a/psalm.xml +++ b/psalm.xml @@ -8,6 +8,7 @@ > + @@ -16,5 +17,19 @@ + + + + + + + + + + + + + + diff --git a/src/Enum.php b/src/Enum.php index 92a42a4..dc9fd51 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -17,6 +17,7 @@ * * @psalm-template T * @psalm-immutable + * @psalm-consistent-constructor */ abstract class Enum implements \JsonSerializable { @@ -51,7 +52,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) @@ -162,7 +163,9 @@ public static function toArray() $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(); } @@ -219,6 +222,8 @@ public static function search($value) * * @return static * @throws \BadMethodCallException + * + * @psalm-pure */ public static function __callStatic($name, $arguments) { diff --git a/static-analysis/EnumIsPure.php b/static-analysis/EnumIsPure.php new file mode 100644 index 0000000..5875fd8 --- /dev/null +++ b/static-analysis/EnumIsPure.php @@ -0,0 +1,33 @@ + + */ +final class PureEnum extends Enum +{ + const A = 'A'; + const C = 'C'; +} + +/** @psalm-pure */ +function enumFetchViaMagicMethodIsPure(): PureEnum +{ + return PureEnum::A(); +} + +/** @psalm-pure */ +function enumFetchViaExplicitMagicCallIsPure(): PureEnum +{ + return PureEnum::__callStatic('A', []); +} diff --git a/tests/EnumTest.php b/tests/EnumTest.php index cb08d29..90caa48 100755 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -38,13 +38,12 @@ public function testGetKey() $this->assertNotEquals('BA', $value->getKey()); } - /** - * @dataProvider invalidValueProvider - * @expectedException \UnexpectedValueException - * @expectedExceptionMessage is not part of the enum MyCLabs\Tests\Enum\EnumFixture - */ + /** @dataProvider invalidValueProvider */ public function testCreatingEnumWithInvalidValue($value) { + $this->expectException(\UnexpectedValueException::class); + $this->expectExceptionMessage('is not part of the enum ' . EnumFixture::class); + new EnumFixture($value); } @@ -146,13 +145,11 @@ public function testStaticAccess() $this->assertNotSame(EnumFixture::NUMBER(), EnumFixture::NUMBER()); } - /** - * @expectedException \BadMethodCallException - * @expectedExceptionMessage No static method or enum constant 'UNKNOWN' in class - * UnitTest\MyCLabs\Enum\Enum\EnumFixture - */ public function testBadStaticAccess() { + $this->expectException(\BadMethodCallException::class); + $this->expectExceptionMessage('No static method or enum constant \'UNKNOWN\' in class ' . EnumFixture::class); + EnumFixture::UNKNOWN(); } From 0ad4363522ecad3ff2a3f4c46a967c8f3f30be56 Mon Sep 17 00:00:00 2001 From: Alexandru Patranescu Date: Mon, 15 Feb 2021 00:04:55 +0200 Subject: [PATCH 29/61] make assertValidValue private as it's not valuable to extend the API. One can programatically call `isValid()` returning bool or just create a new instance with `from()` throwing exception --- src/Enum.php | 2 +- tests/EnumTest.php | 23 ++++++++--------------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/Enum.php b/src/Enum.php index 19318b9..cfb4bd8 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -198,7 +198,7 @@ public static function isValid($value) * @psalm-pure * @psalm-assert T $value */ - public static function assertValidValue($value): void + private static function assertValidValue($value): void { if (!static::isValid($value)) { throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class); diff --git a/tests/EnumTest.php b/tests/EnumTest.php index 674b977..8ad82ea 100755 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -60,6 +60,14 @@ public function testFailToCreateEnumWithInvalidValueThroughNamedConstructor($val EnumFixture::from($value); } + public function testFailToCreateEnumWithEnumItselfThroughNamedConstructor(): void + { + $this->expectException(\UnexpectedValueException::class); + $this->expectExceptionMessage("Value 'foo' is not part of the enum " . EnumFixture::class); + + EnumFixture::from(EnumFixture::FOO()); + } + /** * Contains values not existing in EnumFixture * @return array @@ -344,19 +352,4 @@ public function testEnumValuesInheritance() $inheritedEnumFixture = InheritedEnumFixture::VALUE(); new EnumFixture($inheritedEnumFixture); } - - /** - * @dataProvider isValidProvider - */ - public function testAssertValidValue($value, $isValid): void - { - if (!$isValid) { - $this->expectException(\UnexpectedValueException::class); - $this->expectExceptionMessage("Value '$value' is not part of the enum " . EnumFixture::class); - } - - EnumFixture::assertValidValue($value); - - self::assertTrue(EnumFixture::isValid($value)); - } } From edcc10dce18980607f07b46b0539cb306053fb5e Mon Sep 17 00:00:00 2001 From: Alexandru Patranescu Date: Mon, 15 Feb 2021 00:22:01 +0200 Subject: [PATCH 30/61] cache the key value at construct changing from in_array to array_search --- src/Enum.php | 19 ++++++++++++++----- tests/EnumTest.php | 3 ++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/Enum.php b/src/Enum.php index cfb4bd8..ca6aef0 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -28,6 +28,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. * @@ -61,7 +68,7 @@ public function __construct($value) $value = $value->getValue(); } - static::assertValidValue($value); + $this->key = static::assertValidValue($value); /** @psalm-var T */ $this->value = $value; @@ -94,9 +101,9 @@ public function getValue() * * @psalm-pure */ - public function getKey(): string + public function getKey() { - return static::search($this->value); + return $this->key ?? ($this->key = static::search($this->value)); } /** @@ -198,11 +205,13 @@ public static function isValid($value) * @psalm-pure * @psalm-assert T $value */ - private static function assertValidValue($value): void + private static function assertValidValue($value): string { - if (!static::isValid($value)) { + if (false === ($key = static::search($value))) { throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class); } + + return $key; } /** diff --git a/tests/EnumTest.php b/tests/EnumTest.php index 8ad82ea..bbe848a 100755 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -324,7 +324,8 @@ public function testSerialize() { // split string for Pretty CI: "Line exceeds 120 characters" $bin = '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d4669787'. - '4757265223a313a7b733a383a22002a0076616c7565223b733a333a22666f6f223b7d'; + '4757265223a323a7b733a383a22002a0076616c7565223b733a333a22666f6f223b73'. + '3a32323a22004d79434c6162735c456e756d5c456e756d006b6579223b733a333a22464f4f223b7d'; $this->assertEquals($bin, bin2hex(serialize(EnumFixture::FOO()))); } From 4f2c5723a0b08d73215afa1a28bbb711216fcd00 Mon Sep 17 00:00:00 2001 From: Alexandru Patranescu Date: Mon, 15 Feb 2021 09:57:55 +0200 Subject: [PATCH 31/61] move key property initialization in __wakeup in case an old version is unserialized --- src/Enum.php | 10 +++++++++- tests/EnumTest.php | 18 +++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/Enum.php b/src/Enum.php index ca6aef0..9b845c2 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -74,6 +74,13 @@ public function __construct($value) $this->value = $value; } + public function __wakeup() + { + if ($this->key === null) { + $this->key = static::search($this->value); + } + } + /** * @param mixed $value * @return static @@ -100,10 +107,11 @@ public function getValue() * Returns the enum key (i.e. the constant name). * * @psalm-pure + * @return string */ public function getKey() { - return $this->key ?? ($this->key = static::search($this->value)); + return $this->key; } /** diff --git a/tests/EnumTest.php b/tests/EnumTest.php index bbe848a..cdf472d 100755 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -330,7 +330,7 @@ public function testSerialize() $this->assertEquals($bin, bin2hex(serialize(EnumFixture::FOO()))); } - public function testUnserialize() + public function testUnserializeVersionWithoutKey() { // split string for Pretty CI: "Line exceeds 120 characters" $bin = '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d4669787'. @@ -341,6 +341,22 @@ public function testUnserialize() $this->assertEquals(EnumFixture::FOO, $value->getValue()); $this->assertTrue(EnumFixture::FOO()->equals($value)); + $this->assertTrue(EnumFixture::FOO() == $value); + } + + public function testUnserialize() + { + // split string for Pretty CI: "Line exceeds 120 characters" + $bin = '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d4669787'. + '4757265223a323a7b733a383a22002a0076616c7565223b733a333a22666f6f223b73'. + '3a32323a22004d79434c6162735c456e756d5c456e756d006b6579223b733a333a22464f4f223b7d'; + + /* @var $value EnumFixture */ + $value = unserialize(pack('H*', $bin)); + + $this->assertEquals(EnumFixture::FOO, $value->getValue()); + $this->assertTrue(EnumFixture::FOO()->equals($value)); + $this->assertTrue(EnumFixture::FOO() == $value); } /** From 2525fe0f94f179cbd2f6bc06b38b341ac995b3f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandru=20P=C4=83tr=C4=83nescu?= Date: Mon, 15 Feb 2021 10:17:17 +0200 Subject: [PATCH 32/61] add final to example classes and add note about from() static method --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index bf1c91d..1456bd9 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ use MyCLabs\Enum\Enum; /** * Action enum */ -class Action extends Enum +final class Action extends Enum { private const VIEW = 'view'; private const EDIT = 'edit'; @@ -50,7 +50,7 @@ $action = Action::VIEW(); // or with a dynamic key: $action = Action::$key(); // or with a dynamic value: -$action = new Action($value); +$action = Action::from($value); ``` As you can see, static methods are automatically implemented to provide quick access to an enum value. @@ -73,6 +73,7 @@ function setAction(Action $action) { Static methods: +- `from()` Creates an Enum instance, checking that the value exist in the enum - `toArray()` method Returns all possible values as an array (constant name in key, constant value in value) - `keys()` Returns the names (keys) of all constants in the Enum class - `values()` Returns instances of the Enum class of all Enum constants (constant name in key, Enum instance in value) @@ -83,7 +84,7 @@ Static methods: ### Static methods ```php -class Action extends Enum +final class Action extends Enum { private const VIEW = 'view'; private const EDIT = 'edit'; @@ -99,7 +100,7 @@ Static method helpers are implemented using [`__callStatic()`](http://www.php.ne If you care about IDE autocompletion, you can either implement the static methods yourself: ```php -class Action extends Enum +final class Action extends Enum { private const VIEW = 'view'; @@ -119,7 +120,7 @@ or you can use phpdoc (this is supported in PhpStorm for example): * @method static Action VIEW() * @method static Action EDIT() */ -class Action extends Enum +final class Action extends Enum { private const VIEW = 'view'; private const EDIT = 'edit'; From e620c08f6a6e3c8407dd1d6dbee680ca11b1a5b1 Mon Sep 17 00:00:00 2001 From: Alexandru Patranescu Date: Mon, 15 Feb 2021 10:20:07 +0200 Subject: [PATCH 33/61] re-add the constructor example --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 1456bd9..dfcd491 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ $action = Action::VIEW(); $action = Action::$key(); // or with a dynamic value: $action = Action::from($value); +// or +$action = new Action($value); ``` As you can see, static methods are automatically implemented to provide quick access to an enum value. From b072dc299510ab06b3472b541f1b5f342ae7beb4 Mon Sep 17 00:00:00 2001 From: Alexandru Patranescu Date: Mon, 15 Feb 2021 11:17:08 +0200 Subject: [PATCH 34/61] re-add the public static method assertValidValue --- src/Enum.php | 15 +++++++++++++-- tests/EnumTest.php | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Enum.php b/src/Enum.php index 9b845c2..19cc275 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -68,7 +68,7 @@ public function __construct($value) $value = $value->getValue(); } - $this->key = static::assertValidValue($value); + $this->key = static::assertValidValueReturningKey($value); /** @psalm-var T */ $this->value = $value; @@ -213,7 +213,18 @@ public static function isValid($value) * @psalm-pure * @psalm-assert T $value */ - private static function assertValidValue($value): string + public static function assertValidValue($value): void + { + self::assertValidValueReturningKey($value); + } + + /** + * Asserts valid enum value + * + * @psalm-pure + * @psalm-assert T $value + */ + 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); diff --git a/tests/EnumTest.php b/tests/EnumTest.php index cdf472d..154b8ba 100755 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -369,4 +369,19 @@ public function testEnumValuesInheritance() $inheritedEnumFixture = InheritedEnumFixture::VALUE(); new EnumFixture($inheritedEnumFixture); } + + /** + * @dataProvider isValidProvider + */ + public function testAssertValidValue($value, $isValid): void + { + if (!$isValid) { + $this->expectException(\UnexpectedValueException::class); + $this->expectExceptionMessage("Value '$value' is not part of the enum " . EnumFixture::class); + } + + EnumFixture::assertValidValue($value); + + self::assertTrue(EnumFixture::isValid($value)); + } } From be02f8d94563890bd3ec094db5fbb8da24b0f95c Mon Sep 17 00:00:00 2001 From: Alexandru Patranescu Date: Mon, 15 Feb 2021 11:26:04 +0200 Subject: [PATCH 35/61] optimize the from named constructor to have only one array full scan without calling the constructor again --- src/Enum.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Enum.php b/src/Enum.php index 19cc275..b665b0c 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -88,9 +88,9 @@ public function __wakeup() */ public static function from($value): self { - static::assertValidValue($value); + $key = static::assertValidValueReturningKey($value); - return new static($value); + return self::__callStatic($key, []); } /** From b50f4add068433c033f6e6be40e68a57dbda5cfe Mon Sep 17 00:00:00 2001 From: Alexandru Patranescu Date: Mon, 15 Feb 2021 12:58:34 +0200 Subject: [PATCH 36/61] add also mention in documentation for assertValidValue --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index dfcd491..1e4d1ff 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ Static methods: - `values()` Returns instances of the Enum class of all Enum constants (constant name in key, Enum instance in value) - `isValid()` Check if tested value is valid on enum set - `isValidKey()` Check if tested key is valid on enum set +- `assertValidValue()` Assert the value is valid on enum set, throwing exception otherwise - `search()` Return key for searched value ### Static methods From c55aa7fc6a76317aed4f2639cc6917431cb6d76f Mon Sep 17 00:00:00 2001 From: Alexandru Patranescu Date: Sat, 27 Feb 2021 08:55:05 +0200 Subject: [PATCH 37/61] suppress some psalm errors that are actually bugs in current psalm implementation or are related to deserialization workaround --- composer.json | 2 +- src/Enum.php | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 73caf14..924f924 100644 --- a/composer.json +++ b/composer.json @@ -28,6 +28,6 @@ "require-dev": { "phpunit/phpunit": "^9.5", "squizlabs/php_codesniffer": "1.*", - "vimeo/psalm": "^4.5.1" + "vimeo/psalm": "^4.6.2" } } diff --git a/src/Enum.php b/src/Enum.php index a16aa23..6967ab5 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -69,15 +69,25 @@ public function __construct($value) $value = $value->getValue(); } + /** @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); } } @@ -215,6 +225,7 @@ public static function isValid($value) * * @psalm-pure * @psalm-assert T $value + * @param mixed $value */ public static function assertValidValue($value): void { @@ -226,6 +237,8 @@ public static function assertValidValue($value): void * * @psalm-pure * @psalm-assert T $value + * @param mixed $value + * @return string */ private static function assertValidValueReturningKey($value): string { From 195eee4e114790d5bcf30cda0b97bd9aa731d40d Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Mon, 28 Jun 2021 15:12:55 +0200 Subject: [PATCH 38/61] PHP 8.1: silence the deprecation notice about jsonSerialize() return type --- src/Enum.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Enum.php b/src/Enum.php index 6967ab5..20df959 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -311,6 +311,7 @@ public static function __callStatic($name, $arguments) * @link http://php.net/manual/en/jsonserializable.jsonserialize.php * @psalm-pure */ + #[ReturnTypeWillChange] public function jsonSerialize() { return $this->getValue(); From 4651dd3a6242d7f315f4e85ce94de9558e5b6ab8 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Mon, 28 Jun 2021 15:19:59 +0200 Subject: [PATCH 39/61] PHP 8.1: silence the deprecation notice about jsonSerialize() return type --- src/Enum.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index 20df959..382e1c4 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -311,7 +311,7 @@ public static function __callStatic($name, $arguments) * @link http://php.net/manual/en/jsonserializable.jsonserialize.php * @psalm-pure */ - #[ReturnTypeWillChange] + #[\ReturnTypeWillChange] public function jsonSerialize() { return $this->getValue(); From a128308839cf931057943f833a91e8ae2fab84ba Mon Sep 17 00:00:00 2001 From: Alexander Kurilo Date: Sun, 4 Jul 2021 18:42:12 +0300 Subject: [PATCH 40/61] Fix psalm annotation on Enum::from --- src/Enum.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index 382e1c4..687a9cc 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -94,8 +94,8 @@ public function __wakeup() /** * @param mixed $value + * @psalm-param T $value * @return static - * @psalm-return static */ public static function from($value): self { From 97b70b0eaa15ededa5c62d10148974b6167fe31c Mon Sep 17 00:00:00 2001 From: Alexander Kurilo Date: Sun, 4 Jul 2021 23:26:14 +0300 Subject: [PATCH 41/61] Remove psalm template from static method `from` Accoring to vimeo/psalm#2571, psalm doesn't support it --- src/Enum.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index 687a9cc..89064eb 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -94,7 +94,6 @@ public function __wakeup() /** * @param mixed $value - * @psalm-param T $value * @return static */ public static function from($value): self From dbc04b767c4d81661d9bdff0cea8ae0acf8c00b1 Mon Sep 17 00:00:00 2001 From: Simon Podlipsky Date: Sun, 8 Aug 2021 11:43:08 +0200 Subject: [PATCH 42/61] Do not export psalm.xml in dist --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index c821984..c118fb2 100755 --- a/.gitattributes +++ b/.gitattributes @@ -7,4 +7,5 @@ .travis.yml export-ignore tests/ export-ignore phpunit.xml export-ignore +psalm.xml export-ignore static-analysis/ export-ignore From 812cfbbe863396e8ca44e0e2165467194d4191e4 Mon Sep 17 00:00:00 2001 From: Simon Podlipsky Date: Sat, 21 Aug 2021 13:17:47 +0200 Subject: [PATCH 43/61] Add Github Actions CI - drop Travis --- .gitattributes | 1 - .github/workflows/ci.yaml | 53 ++++++++++++++++++++++++++ .github/workflows/static-analysis.yaml | 31 +++++++++++++++ .travis.yml | 24 ------------ README.md | 13 ++++++- phpunit.xml | 6 +++ 6 files changed, 101 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/ci.yaml create mode 100644 .github/workflows/static-analysis.yaml delete mode 100755 .travis.yml diff --git a/.gitattributes b/.gitattributes index c118fb2..2140930 100755 --- a/.gitattributes +++ b/.gitattributes @@ -4,7 +4,6 @@ .gitattributes export-ignore .github export-ignore .gitignore export-ignore -.travis.yml export-ignore tests/ export-ignore phpunit.xml export-ignore psalm.xml export-ignore diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..e3b6e64 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,53 @@ +name: "CI" + +on: + pull_request: + push: + branches: + - "master" + schedule: + - cron: "42 3 * * *" + +jobs: + phpunit: + name: "PHPUnit" + runs-on: "ubuntu-20.04" + + strategy: + matrix: + php-version: + - "7.3" + - "7.4" + - "8.0" + dependencies: + - "highest" + include: + - dependencies: "lowest" + php-version: "7.3" + + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + with: + fetch-depth: 2 + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: "${{ matrix.php-version }}" + coverage: "pcov" + ini-values: "zend.assertions=1" + + - name: "Install dependencies with Composer" + uses: "ramsey/composer-install@v1" + with: + dependency-versions: "${{ matrix.dependencies }}" + + - name: "Run PHPUnit" + run: "vendor/bin/phpunit --coverage-clover=coverage.xml" + + - name: "Upload coverage file" + uses: "actions/upload-artifact@v2" + with: + name: "phpunit-${{ matrix.deps }}-${{ matrix.php-version }}.coverage" + path: "coverage.xml" diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml new file mode 100644 index 0000000..358b8c6 --- /dev/null +++ b/.github/workflows/static-analysis.yaml @@ -0,0 +1,31 @@ +name: "Static Analysis" + +on: + pull_request: + push: + branches: + - "master" + +jobs: + static-analysis-psalm: + name: "Static Analysis with Psalm" + runs-on: "ubuntu-20.04" + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Psalm + uses: docker://vimeo/psalm-github-actions:4.9.3 + with: + args: --shepherd + composer_ignore_platform_reqs: true + composer_require_dev: true + security_analysis: true + report_file: results.sarif + env: + CHECK_PLATFORM_REQUIREMENTS: "false" + - name: Upload Security Analysis results to GitHub + uses: github/codeql-action/upload-sarif@v1 + with: + sarif_file: results.sarif diff --git a/.travis.yml b/.travis.yml deleted file mode 100755 index 92affbf..0000000 --- a/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -language: php - -php: - - '7.3' - - '7.4' - - '8.0' - -matrix: - fast_finish: true - -cache: - directories: - - $HOME/.composer/cache - -before_script: - - travis_retry composer install -n - -script: - - vendor/bin/phpunit - - vendor/bin/psalm --shepherd - -# Use Travis' new container-based infrastructure. -# See http://docs.travis-ci.com/user/migrating-from-legacy/#How-can-I-use-container-based-infrastructure%3F -sudo: false diff --git a/README.md b/README.md index 1e4d1ff..eaac7e5 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # PHP Enum implementation inspired from SplEnum -[![Build Status](https://travis-ci.org/myclabs/php-enum.png?branch=master)](https://travis-ci.org/myclabs/php-enum) +[![GitHub Actions][GA Image]][GA Link] [![Latest Stable Version](https://poser.pugx.org/myclabs/php-enum/version.png)](https://packagist.org/packages/myclabs/php-enum) [![Total Downloads](https://poser.pugx.org/myclabs/php-enum/downloads.png)](https://packagist.org/packages/myclabs/php-enum) -[![psalm](https://shepherd.dev/github/myclabs/php-enum/coverage.svg)](https://shepherd.dev/github/myclabs/php-enum) +[![Psalm Shepherd][Psalm Shepherd Image]][Psalm Shepherd Link] Maintenance for this project is [supported via Tidelift](https://tidelift.com/subscription/pkg/packagist-myclabs-php-enum?utm_source=packagist-myclabs-php-enum&utm_medium=referral&utm_campaign=readme). @@ -136,3 +136,12 @@ final class Action extends Enum - [Symfony ParamConverter integration](https://github.com/Ex3v/MyCLabsEnumParamConverter) - [PHPStan integration](https://github.com/timeweb/phpstan-enum) - [Yii2 enum mapping](https://github.com/KartaviK/yii2-enum) + + +[GA Image]: https://github.com/myclabs/php-enum/workflows/CI/badge.svg + +[GA Link]: https://github.com/myclabs/php-enum/actions?query=workflow%3A%22CI%22+branch%3Amaster + +[Shepherd Image]: https://shepherd.dev/github/myclabs/php-enum/coverage.svg + +[Shepherd Link]: https://shepherd.dev/github/myclabs/php-enum diff --git a/phpunit.xml b/phpunit.xml index bd714f1..33b8f67 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -10,4 +10,10 @@ ./tests + + + + src + + From 92662add78eda4eea2fedf051d068d553aa96d05 Mon Sep 17 00:00:00 2001 From: Alexandru Patranescu Date: Tue, 7 Dec 2021 19:19:27 +0200 Subject: [PATCH 44/61] document how migration to native php enums will work --- README.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/README.md b/README.md index 1e4d1ff..23a3b12 100644 --- a/README.md +++ b/README.md @@ -130,8 +130,56 @@ final class Action extends Enum } ``` +## Native enums and migration +Native enum arrived to PHP in version 8.1: https://www.php.net/enumerations +If your project is running PHP 8.1+ or your library have it as a minimum requirement you should use it instead of this library. + +When migrating from `myclabs/php-enum`, the effort should be small if the usage was in the recommended way: +- private constants +- final class without extending the enum class +- no static method overridden + +Changes for migration: +- Class definition should be changed from +```php +/** + * @method static Action VIEW() + * @method static Action EDIT() + */ +final class Action extends Enum +{ + private const VIEW = 'view'; + private const EDIT = 'edit'; +} +``` + to +```php +enum Action: string +{ + case VIEW = 'view'; + case EDIT = 'edit'; +} +``` +All places where the class was used as a type will continue to work. + +Usages and the change needed: + +| Operation | myclabs/php-enum | native enum | +|----------------------------------------------------------------|----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Obtain an instance will change from | `$enumCase = Action::VIEW()` | `$enumCase = Action::VIEW` | +| Create an enum from a backed value | `$enumCase = new Action('view')` | `$enumCase = Action::from('view')` | +| Get the backed value of the enum instance | `$enumCase->getValue()` | `$enumCase->value` | +| Compare two enum instances | `$enumCase1 == $enumCase2`
or
`$enumCase1->equals($enumCase2)` | `$enumCase1 === $enumCase2` | +| Get the key/name of the enum instance | `$enumCase->getKey()` | `$enumCase->name` | +| Get a list of all the possible instances of the enum | `Action::values()` | `Action::cases()` | +| Get a map of possible instances of the enum mapped by name | `Action::values()` | `array_combine(array_map(fn($case) => $case->name, Action::cases()), Action::cases())`
or
`(new ReflectionEnum(Action::class))->getConstants()` | +| Get a list of all possible names of the enum | `Action::keys()` | `array_map(fn($case) => $case->name, Action::cases())` | +| Get a list of all possible backed values of the enum | `Action::toArray()` | `array_map(fn($case) => $case->value, Action::cases())` | +| Get a map of possible backed values of the enum mapped by name | `Action::toArray()` | `array_combine(array_map(fn($case) => $case->name, Action::cases()), array_map(fn($case) => $case->value, Action::cases()))`
or
`array_map(fn($case) => $case->value, (new ReflectionEnum(Action::class))->getConstants()))` | + ## Related projects +- [PHP 8.1+ native enum](https://www.php.net/enumerations) - [Doctrine enum mapping](https://github.com/acelaya/doctrine-enum-type) - [Symfony ParamConverter integration](https://github.com/Ex3v/MyCLabsEnumParamConverter) - [PHPStan integration](https://github.com/timeweb/phpstan-enum) From e53bae149bd75c14e2a7bcb240974915794050b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandru=20P=C4=83tr=C4=83nescu?= Date: Wed, 8 Dec 2021 08:20:44 +0200 Subject: [PATCH 45/61] fix the verb conjugation Co-authored-by: Jacob Dreesen --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 23a3b12..910275a 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ final class Action extends Enum ## Native enums and migration Native enum arrived to PHP in version 8.1: https://www.php.net/enumerations -If your project is running PHP 8.1+ or your library have it as a minimum requirement you should use it instead of this library. +If your project is running PHP 8.1+ or your library has it as a minimum requirement you should use it instead of this library. When migrating from `myclabs/php-enum`, the effort should be small if the usage was in the recommended way: - private constants From f3f9aa67d2b0204807c498314a01af7838ff4552 Mon Sep 17 00:00:00 2001 From: Alexandru Patranescu Date: Wed, 8 Dec 2021 15:32:27 +0200 Subject: [PATCH 46/61] reduce the unnecessary details --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 910275a..cd813b1 100644 --- a/README.md +++ b/README.md @@ -136,8 +136,8 @@ If your project is running PHP 8.1+ or your library has it as a minimum requirem When migrating from `myclabs/php-enum`, the effort should be small if the usage was in the recommended way: - private constants -- final class without extending the enum class -- no static method overridden +- final classes +- no method overridden Changes for migration: - Class definition should be changed from From eb6410282801fa4511855de001c2c1deb6e4bf50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20DECOOL?= Date: Sat, 16 Apr 2022 09:39:34 +0200 Subject: [PATCH 47/61] Implement Stringable interface on Enum --- composer.json | 5 ++++- src/Enum.php | 2 +- stubs/Stringable.php | 11 +++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 stubs/Stringable.php diff --git a/composer.json b/composer.json index 924f924..978cb19 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,10 @@ "autoload": { "psr-4": { "MyCLabs\\Enum\\": "src/" - } + }, + "classmap": [ + "stubs/Stringable.php" + ] }, "autoload-dev": { "psr-4": { diff --git a/src/Enum.php b/src/Enum.php index 89064eb..4c94cf6 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -19,7 +19,7 @@ * @psalm-immutable * @psalm-consistent-constructor */ -abstract class Enum implements \JsonSerializable +abstract class Enum implements \JsonSerializable, \Stringable { /** * Enum value diff --git a/stubs/Stringable.php b/stubs/Stringable.php new file mode 100644 index 0000000..4811af7 --- /dev/null +++ b/stubs/Stringable.php @@ -0,0 +1,11 @@ + Date: Sat, 14 May 2022 16:24:51 +0200 Subject: [PATCH 48/61] Added PHP 8.1 to CI configuration --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e3b6e64..25b3372 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -19,6 +19,7 @@ jobs: - "7.3" - "7.4" - "8.0" + - "8.1" dependencies: - "highest" include: From 0a08c9f24718cb765c6eadf14fb0ca146b934068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Mon, 16 May 2022 02:29:22 +0000 Subject: [PATCH 49/61] Fix Shepherd link in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d72323f..d874efb 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![GitHub Actions][GA Image]][GA Link] [![Latest Stable Version](https://poser.pugx.org/myclabs/php-enum/version.png)](https://packagist.org/packages/myclabs/php-enum) [![Total Downloads](https://poser.pugx.org/myclabs/php-enum/downloads.png)](https://packagist.org/packages/myclabs/php-enum) -[![Psalm Shepherd][Psalm Shepherd Image]][Psalm Shepherd Link] +[![Psalm Shepherd][Shepherd Image]][Shepherd Link] Maintenance for this project is [supported via Tidelift](https://tidelift.com/subscription/pkg/packagist-myclabs-php-enum?utm_source=packagist-myclabs-php-enum&utm_medium=referral&utm_campaign=readme). From 99a5bf3fa504ffd6e496748532222a04db67fedb Mon Sep 17 00:00:00 2001 From: Roman Varkuta Date: Fri, 17 Jun 2022 14:24:21 +0300 Subject: [PATCH 50/61] yii2-enum is abandoned and not supporting anymore --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index d874efb..681d55e 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,6 @@ Usages and the change needed: - [Doctrine enum mapping](https://github.com/acelaya/doctrine-enum-type) - [Symfony ParamConverter integration](https://github.com/Ex3v/MyCLabsEnumParamConverter) - [PHPStan integration](https://github.com/timeweb/phpstan-enum) -- [Yii2 enum mapping](https://github.com/KartaviK/yii2-enum) [GA Image]: https://github.com/myclabs/php-enum/workflows/CI/badge.svg From 5d1e09ef0c4bef8b9491f03c56d6ee4759e5e68f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1chym=20Tou=C5=A1ek?= Date: Fri, 28 Oct 2022 08:42:37 +0200 Subject: [PATCH 51/61] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 681d55e..948f374 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,8 @@ use MyCLabs\Enum\Enum; /** * Action enum + * + * @extends Enum */ final class Action extends Enum { From 85a33645c5b5dd4edfada1381bd818485f2ccded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roger=20Vil=C3=A0?= Date: Tue, 13 Dec 2022 11:13:58 +0100 Subject: [PATCH 52/61] Upgrade to Psalm 5 --- composer.json | 2 +- src/Enum.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 978cb19..67612d0 100644 --- a/composer.json +++ b/composer.json @@ -31,6 +31,6 @@ "require-dev": { "phpunit/phpunit": "^9.5", "squizlabs/php_codesniffer": "1.*", - "vimeo/psalm": "^4.6.2" + "vimeo/psalm": "^5.2" } } diff --git a/src/Enum.php b/src/Enum.php index 4c94cf6..1bd5592 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -176,6 +176,7 @@ public static function values() /** @psalm-var T $value */ foreach (static::toArray() as $key => $value) { + /** @psalm-suppress UnsafeGenericInstantiation */ $values[$key] = new static($value); } @@ -297,6 +298,7 @@ public static function __callStatic($name, $arguments) $message = "No static method or enum constant '$name' in class " . static::class; throw new \BadMethodCallException($message); } + /** @psalm-suppress UnsafeGenericInstantiation */ return self::$instances[$class][$name] = new static($array[$name]); } return clone self::$instances[$class][$name]; @@ -308,7 +310,6 @@ public static function __callStatic($name, $arguments) * * @return mixed * @link http://php.net/manual/en/jsonserializable.jsonserialize.php - * @psalm-pure */ #[\ReturnTypeWillChange] public function jsonSerialize() From f9a24befc55270c323167cc8266f59b3dfd3c51e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roger=20Vil=C3=A0?= Date: Tue, 13 Dec 2022 11:43:12 +0100 Subject: [PATCH 53/61] Support Psalm v4 and v5 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 67612d0..2513db7 100644 --- a/composer.json +++ b/composer.json @@ -31,6 +31,6 @@ "require-dev": { "phpunit/phpunit": "^9.5", "squizlabs/php_codesniffer": "1.*", - "vimeo/psalm": "^5.2" + "vimeo/psalm": "^4.6.2 || ^5.2" } } From 9394a8eda18e9e0de7bb80575ca5b4e1fc6c192b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roger=20Vil=C3=A0?= Date: Tue, 13 Dec 2022 12:22:32 +0100 Subject: [PATCH 54/61] PHP 8.2 CI Support --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 25b3372..de91a2c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -20,6 +20,7 @@ jobs: - "7.4" - "8.0" - "8.1" + - "8.2" dependencies: - "highest" include: From 35b96941f167bd289f8c1811dc8585e73432f815 Mon Sep 17 00:00:00 2001 From: Giorgio Scalvini <139172449+g-scalvini@users.noreply.github.com> Date: Thu, 15 Feb 2024 13:56:24 +0100 Subject: [PATCH 55/61] HTTP to HTTPS for homepage link in composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 2513db7..eab6263 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "type": "library", "description": "PHP Enum implementation", "keywords": ["enum"], - "homepage": "http://github.com/myclabs/php-enum", + "homepage": "https://github.com/myclabs/php-enum", "license": "MIT", "authors": [ { From ae3fb27dbc8bebb7ad678e5d9131d84e6eb456d2 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Fri, 13 Sep 2024 19:39:16 +0200 Subject: [PATCH 56/61] Update ci.yaml --- .github/workflows/ci.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index de91a2c..a75731e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -5,8 +5,6 @@ on: push: branches: - "master" - schedule: - - cron: "42 3 * * *" jobs: phpunit: From a1c7bcfdfeb054b4f1bba0f5c2d1bec382898eaa Mon Sep 17 00:00:00 2001 From: "M. Vugteveen" Date: Mon, 13 Jan 2025 19:54:14 +0100 Subject: [PATCH 57/61] fix php8.4 deprecated --- src/PHPUnit/Comparator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PHPUnit/Comparator.php b/src/PHPUnit/Comparator.php index 302bf80..7c65e4e 100644 --- a/src/PHPUnit/Comparator.php +++ b/src/PHPUnit/Comparator.php @@ -43,7 +43,7 @@ public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = f ); } - private function formatEnum(Enum $enum = null) + private function formatEnum(?Enum $enum = null) { if ($enum === null) { return "null"; From ada961a2824c5d709be48d6b108ae714fe2662e2 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Tue, 14 Jan 2025 09:59:51 +0100 Subject: [PATCH 58/61] Update ci.yaml --- .github/workflows/ci.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a75731e..cf8037c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -27,7 +27,7 @@ jobs: steps: - name: "Checkout" - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" with: fetch-depth: 2 @@ -47,7 +47,7 @@ jobs: run: "vendor/bin/phpunit --coverage-clover=coverage.xml" - name: "Upload coverage file" - uses: "actions/upload-artifact@v2" + uses: "actions/upload-artifact@v4" with: name: "phpunit-${{ matrix.deps }}-${{ matrix.php-version }}.coverage" path: "coverage.xml" From a462e42ba36b2bff85695e616f3b6b086f2d4aeb Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Tue, 14 Jan 2025 10:00:05 +0100 Subject: [PATCH 59/61] Update static-analysis.yaml --- .github/workflows/static-analysis.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index 358b8c6..017d4a6 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -13,7 +13,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Psalm uses: docker://vimeo/psalm-github-actions:4.9.3 From 347013faaba789a283d46a55581958f2ba469bdb Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Tue, 14 Jan 2025 10:09:47 +0100 Subject: [PATCH 60/61] Update ci.yaml --- .github/workflows/ci.yaml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index cf8037c..7863acf 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -35,7 +35,6 @@ jobs: uses: "shivammathur/setup-php@v2" with: php-version: "${{ matrix.php-version }}" - coverage: "pcov" ini-values: "zend.assertions=1" - name: "Install dependencies with Composer" @@ -44,10 +43,4 @@ jobs: dependency-versions: "${{ matrix.dependencies }}" - name: "Run PHPUnit" - run: "vendor/bin/phpunit --coverage-clover=coverage.xml" - - - name: "Upload coverage file" - uses: "actions/upload-artifact@v4" - with: - name: "phpunit-${{ matrix.deps }}-${{ matrix.php-version }}.coverage" - path: "coverage.xml" + run: "vendor/bin/phpunit" From eb3eefdf91307a002b9e3ce4f6d25034c94265a7 Mon Sep 17 00:00:00 2001 From: Danny van der Sluijs Date: Thu, 20 Feb 2025 10:36:09 +0100 Subject: [PATCH 61/61] Correct pugx badges This replaces the extension no the pugx badges for version and total downloads. The current png version is failing due to request redirection combined with [GitHub Camo](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-anonymized-urls) as mentioned in https://github.com/PUGX/badge-poser/issues/1195 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 948f374..2bf98cd 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # PHP Enum implementation inspired from SplEnum [![GitHub Actions][GA Image]][GA Link] -[![Latest Stable Version](https://poser.pugx.org/myclabs/php-enum/version.png)](https://packagist.org/packages/myclabs/php-enum) -[![Total Downloads](https://poser.pugx.org/myclabs/php-enum/downloads.png)](https://packagist.org/packages/myclabs/php-enum) +[![Latest Stable Version](https://poser.pugx.org/myclabs/php-enum/version.svg)](https://packagist.org/packages/myclabs/php-enum) +[![Total Downloads](https://poser.pugx.org/myclabs/php-enum/downloads.svg)](https://packagist.org/packages/myclabs/php-enum) [![Psalm Shepherd][Shepherd Image]][Shepherd Link] Maintenance for this project is [supported via Tidelift](https://tidelift.com/subscription/pkg/packagist-myclabs-php-enum?utm_source=packagist-myclabs-php-enum&utm_medium=referral&utm_campaign=readme).