From 8bc49f030534f84db0e4573f01699ece0cd1c1f1 Mon Sep 17 00:00:00 2001 From: Peter Gribanov Date: Tue, 28 Mar 2017 13:44:29 +0300 Subject: [PATCH 001/104] test serializable --- tests/EnumTest.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/EnumTest.php b/tests/EnumTest.php index 72ec873..eea6fe2 100755 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -250,4 +250,23 @@ public function testEqualsConflictValues() { $this->assertFalse(EnumFixture::FOO()->equals(EnumConflict::FOO())); } + + public function testSerialize() + { + $this->assertEquals( + '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d46697874757265223a313a7b733a383a22002a0076616c7565223b733a333a22666f6f223b7d', + bin2hex(serialize(EnumFixture::FOO())) + ); + } + + public function testUnserialize() + { + /* @var $value EnumFixture */ + $value = unserialize(hex2bin( + '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d46697874757265223a313a7b733a383a22002a0076616c7565223b733a333a22666f6f223b7d' + )); + + $this->assertEquals(EnumFixture::FOO, $value->getValue()); + $this->assertTrue(EnumFixture::FOO()->equals($value)); + } } From 2b0cda86b3d6293643288da91f5746210656c37d Mon Sep 17 00:00:00 2001 From: Peter Gribanov Date: Tue, 28 Mar 2017 14:00:02 +0300 Subject: [PATCH 002/104] add compatibility for PHP 5.3 --- tests/EnumTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/EnumTest.php b/tests/EnumTest.php index eea6fe2..390cd0e 100755 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -262,7 +262,8 @@ public function testSerialize() public function testUnserialize() { /* @var $value EnumFixture */ - $value = unserialize(hex2bin( + $value = unserialize(pack( + 'H*', '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d46697874757265223a313a7b733a383a22002a0076616c7565223b733a333a22666f6f223b7d' )); From cedc9f738548a77bc61583234a41536df1168413 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Wed, 10 Jan 2018 14:30:29 +0100 Subject: [PATCH 003/104] Recommend using private constants --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d0c3001..6a08e0a 100644 --- a/README.md +++ b/README.md @@ -33,11 +33,12 @@ use MyCLabs\Enum\Enum; */ class Action extends Enum { - const VIEW = 'view'; - const EDIT = 'edit'; + private const VIEW = 'view'; + private const EDIT = 'edit'; } ``` +Note the `private` keyword requires PHP > 7.1, you can omit it on PHP 7.0. ## Usage @@ -80,8 +81,8 @@ Static methods: ```php class Action extends Enum { - const VIEW = 'view'; - const EDIT = 'edit'; + private const VIEW = 'view'; + private const EDIT = 'edit'; } // Static method: @@ -96,7 +97,7 @@ If you care about IDE autocompletion, you can either implement the static method ```php class Action extends Enum { - const VIEW = 'view'; + private const VIEW = 'view'; /** * @return Action @@ -116,8 +117,8 @@ or you can use phpdoc (this is supported in PhpStorm for example): */ class Action extends Enum { - const VIEW = 'view'; - const EDIT = 'edit'; + private const VIEW = 'view'; + private const EDIT = 'edit'; } ``` From cc4217b52bec852e8fecfaa237e42ab2b2d6146f Mon Sep 17 00:00:00 2001 From: Daan van Marsbergen Date: Thu, 3 May 2018 14:39:36 +0200 Subject: [PATCH 004/104] Drop support for PHP 5.3 --- .travis.yml | 2 +- composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 451832b..92822ee 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,12 @@ language: php php: - - 5.3 - 5.4 - 5.5 - 5.6 - 7.0 - 7.1 + - 7.2 - nightly - hhvm diff --git a/composer.json b/composer.json index e9769a3..1395658 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ } }, "require": { - "php": ">=5.3" + "php": ">=5.4" }, "require-dev": { "phpunit/phpunit": "^4.8.35|^5.7|^6.0", From feb4b6bf8b22cc9f419ca44f5837fdea1bc16605 Mon Sep 17 00:00:00 2001 From: Daan van Marsbergen Date: Thu, 3 May 2018 15:02:57 +0200 Subject: [PATCH 005/104] Implement the JsonSerializable interface --- src/Enum.php | 14 +++++++++++++- tests/EnumTest.php | 16 +++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Enum.php b/src/Enum.php index 140e722..5f4a12a 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -15,7 +15,7 @@ * @author Daniel Costa * @author Mirosław Filip */ -abstract class Enum +abstract class Enum implements \JsonSerializable { /** * Enum value @@ -183,4 +183,16 @@ public static function __callStatic($name, $arguments) throw new \BadMethodCallException("No static method or enum constant '$name' in class " . get_called_class()); } + + /** + * Specify data which should be serialized to JSON. This method returns data that can be serialized by json_encode() + * natively. + * + * @return mixed + * @link http://php.net/manual/en/jsonserializable.jsonserialize.php + */ + public function jsonSerialize() + { + return $this->getValue(); + } } diff --git a/tests/EnumTest.php b/tests/EnumTest.php index c468017..4b28038 100644 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -40,7 +40,7 @@ public function testGetKey() /** * @dataProvider invalidValueProvider - * @expectedException UnexpectedValueException + * @expectedException \UnexpectedValueException * @expectedExceptionMessage is not part of the enum MyCLabs\Tests\Enum\EnumFixture */ public function testCreatingEnumWithInvalidValue($value) @@ -247,4 +247,18 @@ public function testEqualsConflictValues() { $this->assertFalse(EnumFixture::FOO()->equals(EnumConflict::FOO())); } + + /** + * jsonSerialize() + */ + public function testJsonSerialize() + { + $this->assertJsonStringEqualsJsonString('"foo"', json_encode(new EnumFixture(EnumFixture::FOO))); + $this->assertJsonStringEqualsJsonString('"bar"', json_encode(new EnumFixture(EnumFixture::BAR))); + $this->assertJsonStringEqualsJsonString('42', json_encode(new EnumFixture(EnumFixture::NUMBER))); + $this->assertJsonStringEqualsJsonString('0', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_NUMBER))); + $this->assertJsonStringEqualsJsonString('null', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_NULL))); + $this->assertJsonStringEqualsJsonString('""', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_EMPTY_STRING))); + $this->assertJsonStringEqualsJsonString('false', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_BOOLEAN_FALSE))); + } } From df89d1f2009df7402caa167f937af02a3cb4468d Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Thu, 3 May 2018 21:17:28 +0200 Subject: [PATCH 006/104] Remove HHVM support --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 92822ee..4c59891 100755 --- a/.travis.yml +++ b/.travis.yml @@ -8,11 +8,6 @@ php: - 7.1 - 7.2 - nightly - - hhvm - -matrix: - allow_failures: - - php: hhvm before_script: - composer install --no-interaction From 4560a12e35e2a50c7f2f9a9d65c14e27ad742df3 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Thu, 3 May 2018 21:29:21 +0200 Subject: [PATCH 007/104] Update .travis.yml --- .travis.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4c59891..a175e29 100755 --- a/.travis.yml +++ b/.travis.yml @@ -9,18 +9,20 @@ php: - 7.2 - nightly +matrix: + fast_finish: true + +cache: + directories: + - $HOME/.composer/cache + before_script: - - composer install --no-interaction + - composer install -n script: - - vendor/bin/phpunit --coverage-clover=coverage.clover + - vendor/bin/phpunit - vendor/bin/phpcs --standard=PSR2 ./src/ -after_script: - - wget https://scrutinizer-ci.com/ocular.phar - - php ocular.phar code-coverage:upload --format=php-clover coverage.clover - # 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 - From 0f8763429fc07dec6448c3d751be753dd601689d Mon Sep 17 00:00:00 2001 From: Oleksandr Savchenko Date: Tue, 8 May 2018 10:33:48 +0300 Subject: [PATCH 008/104] allow null in equals --- src/Enum.php | 4 ++-- tests/EnumTest.php | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Enum.php b/src/Enum.php index 5f4a12a..f3aa212 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -80,9 +80,9 @@ public function __toString() * * @return bool True if Enums are equal, false if not equal */ - final public function equals(Enum $enum) + final public function equals(Enum $enum = null) { - return $this->getValue() === $enum->getValue() && get_called_class() == get_class($enum); + return $enum !== null && $this->getValue() === $enum->getValue() && get_called_class() == get_class($enum); } /** diff --git a/tests/EnumTest.php b/tests/EnumTest.php index 4b28038..ffb6583 100644 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -223,6 +223,7 @@ public function testEquals() $this->assertTrue($foo->equals($foo)); $this->assertFalse($foo->equals($number)); $this->assertTrue($foo->equals($anotherFoo)); + $this->assertFalse($foo->equals(null)); } /** From cad9c482a81cbb878f85685cb6825c0e6ec2e749 Mon Sep 17 00:00:00 2001 From: Willem Stuursma Date: Tue, 31 Jul 2018 17:28:02 +0200 Subject: [PATCH 009/104] Prefix all function calls with a backspace --- src/Enum.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Enum.php b/src/Enum.php index f3aa212..f26b6a9 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -41,7 +41,7 @@ abstract class Enum implements \JsonSerializable 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 " . \get_called_class()); } $this->value = $value; @@ -82,7 +82,7 @@ public function __toString() */ final public function equals(Enum $enum = null) { - return $enum !== null && $this->getValue() === $enum->getValue() && get_called_class() == get_class($enum); + return $enum !== null && $this->getValue() === $enum->getValue() && \get_called_class() === \get_class($enum); } /** @@ -92,7 +92,7 @@ final public function equals(Enum $enum = null) */ public static function keys() { - return array_keys(static::toArray()); + return \array_keys(static::toArray()); } /** @@ -118,8 +118,8 @@ public static function values() */ public static function toArray() { - $class = get_called_class(); - if (!array_key_exists($class, static::$cache)) { + $class = \get_called_class(); + if (!\array_key_exists($class, static::$cache)) { $reflection = new \ReflectionClass($class); static::$cache[$class] = $reflection->getConstants(); } @@ -136,7 +136,7 @@ public static function toArray() */ public static function isValid($value) { - return in_array($value, static::toArray(), true); + return \in_array($value, static::toArray(), true); } /** @@ -162,7 +162,7 @@ public static function isValidKey($key) */ public static function search($value) { - return array_search($value, static::toArray(), true); + return \array_search($value, static::toArray(), true); } /** @@ -181,7 +181,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 " . \get_called_class()); } /** From ec1d4fc213648a1c36ab1f619e3461069b0a7d76 Mon Sep 17 00:00:00 2001 From: Willem Stuursma Date: Tue, 31 Jul 2018 17:31:44 +0200 Subject: [PATCH 010/104] Replace function call with language construct (isset([]) evaluates to true) --- src/Enum.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index f26b6a9..7a105d1 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -119,7 +119,7 @@ public static function values() public static function toArray() { $class = \get_called_class(); - if (!\array_key_exists($class, static::$cache)) { + if (!isset(static::$cache[$class])) { $reflection = new \ReflectionClass($class); static::$cache[$class] = $reflection->getConstants(); } From ca4a0a004c5167a1ff86f423b805f28bff43c789 Mon Sep 17 00:00:00 2001 From: Willem Stuursma Date: Tue, 31 Jul 2018 17:32:53 +0200 Subject: [PATCH 011/104] Add travis_retry to overcome transport failures in composer install --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a175e29..a1bc09a 100755 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ cache: - $HOME/.composer/cache before_script: - - composer install -n + - travis_retry composer install -n script: - vendor/bin/phpunit From 5e044e6635653ab2888551501426ba44385f18d1 Mon Sep 17 00:00:00 2001 From: KartaviK Date: Thu, 25 Oct 2018 15:54:22 +0300 Subject: [PATCH 012/104] Set opportunity to create enum statically with null value --- src/Enum.php | 2 +- tests/EnumTest.php | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index 7a105d1..0b4c276 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -177,7 +177,7 @@ public static function search($value) public static function __callStatic($name, $arguments) { $array = static::toArray(); - if (isset($array[$name])) { + if (array_key_exists($name, $array)) { return new static($array[$name]); } diff --git a/tests/EnumTest.php b/tests/EnumTest.php index ffb6583..96d09c7 100644 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -262,4 +262,11 @@ public function testJsonSerialize() $this->assertJsonStringEqualsJsonString('""', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_EMPTY_STRING))); $this->assertJsonStringEqualsJsonString('false', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_BOOLEAN_FALSE))); } + + public function testNullableEnum() + { + $this->assertNull(EnumFixture::PROBLEMATIC_NULL()->getValue()); + $this->assertNull((new EnumFixture(EnumFixture::PROBLEMATIC_NULL))->getValue()); + $this->assertNull((new EnumFixture(EnumFixture::PROBLEMATIC_NULL))->jsonSerialize()); + } } From 0b720b9019ec8f0a85d255e2399103dd93ec07e9 Mon Sep 17 00:00:00 2001 From: Roman Varkuta Date: Thu, 25 Oct 2018 17:01:40 +0300 Subject: [PATCH 013/104] Use array_key_exists() as an extra check --- src/Enum.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index 0b4c276..957d3a8 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -177,7 +177,7 @@ public static function search($value) public static function __callStatic($name, $arguments) { $array = static::toArray(); - if (array_key_exists($name, $array)) { + if (isset($array[$name]) || array_key_exists($name, $array)) { return new static($array[$name]); } From 7c858b2986fc9590f3c4398d8c21a5b35b510fed Mon Sep 17 00:00:00 2001 From: Roman Varkuta Date: Thu, 25 Oct 2018 17:02:30 +0300 Subject: [PATCH 014/104] Add miss back slash --- src/Enum.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index 957d3a8..1ee2573 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -177,7 +177,7 @@ public static function search($value) public static function __callStatic($name, $arguments) { $array = static::toArray(); - if (isset($array[$name]) || array_key_exists($name, $array)) { + if (isset($array[$name]) || \array_key_exists($name, $array)) { return new static($array[$name]); } From f8c4a112b96e597d9cde99ce90987045dce3a08b Mon Sep 17 00:00:00 2001 From: KartaviK Date: Thu, 25 Oct 2018 17:15:53 +0300 Subject: [PATCH 015/104] Add tests for boolean enum --- tests/EnumTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/EnumTest.php b/tests/EnumTest.php index 96d09c7..4fd1000 100644 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -269,4 +269,10 @@ public function testNullableEnum() $this->assertNull((new EnumFixture(EnumFixture::PROBLEMATIC_NULL))->getValue()); $this->assertNull((new EnumFixture(EnumFixture::PROBLEMATIC_NULL))->jsonSerialize()); } + + public function testBooleanEnum() + { + $this->assertFalse(EnumFixture::PROBLEMATIC_BOOLEAN_FALSE()->getValue()); + $this->assertFalse((new EnumFixture(EnumFixture::PROBLEMATIC_BOOLEAN_FALSE))->jsonSerialize()); + } } From a690412cd57a74da13c87167a78fd56fdd699e4d Mon Sep 17 00:00:00 2001 From: KartaviK Date: Thu, 25 Oct 2018 17:19:49 +0300 Subject: [PATCH 016/104] Fix brackets by psr standart --- tests/EnumTest.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/EnumTest.php b/tests/EnumTest.php index ffb6583..2f518a6 100644 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -52,7 +52,8 @@ public function testCreatingEnumWithInvalidValue($value) * Contains values not existing in EnumFixture * @return array */ - public function invalidValueProvider() { + public function invalidValueProvider() + { return array( "string" => array('test'), "int" => array(1234), @@ -68,7 +69,8 @@ public function testToString($expected, $enumObject) $this->assertSame($expected, (string) $enumObject); } - public function toStringProvider() { + public function toStringProvider() + { return array( array(EnumFixture::FOO, new EnumFixture(EnumFixture::FOO)), array(EnumFixture::BAR, new EnumFixture(EnumFixture::BAR)), @@ -162,7 +164,8 @@ public function testIsValid($value, $isValid) $this->assertSame($isValid, EnumFixture::isValid($value)); } - public function isValidProvider() { + public function isValidProvider() + { return array( /** * Valid values @@ -177,7 +180,7 @@ public function isValidProvider() { * Invalid values */ array('baz', false) - ); + ); } /** @@ -199,7 +202,8 @@ public function testSearch($value, $expected) $this->assertSame($expected, EnumFixture::search($value)); } - public function searchProvider() { + public function searchProvider() + { return array( array('foo', 'FOO'), array(0, 'PROBLEMATIC_NUMBER'), From 89efd4f94820a7c9567c58e2e4f447cfda727721 Mon Sep 17 00:00:00 2001 From: KartaviK Date: Tue, 30 Oct 2018 15:20:06 +0200 Subject: [PATCH 017/104] Fix validating key with null value --- 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 1ee2573..00355df 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -150,7 +150,7 @@ public static function isValidKey($key) { $array = static::toArray(); - return isset($array[$key]); + return isset($array[$key]) || \array_key_exists($key, $array); } /** diff --git a/tests/EnumTest.php b/tests/EnumTest.php index 0e8ea8f..3349bd1 100644 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -190,6 +190,7 @@ public function testIsValidKey() { $this->assertTrue(EnumFixture::isValidKey('FOO')); $this->assertFalse(EnumFixture::isValidKey('BAZ')); + $this->assertTrue(EnumFixture::isValidKey('PROBLEMATIC_NULL')); } /** From 98709b26962d15ea35fe8368f03a7666124c280a Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Tue, 30 Oct 2018 14:51:22 +0100 Subject: [PATCH 018/104] Fix coding style --- tests/EnumTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/EnumTest.php b/tests/EnumTest.php index 3349bd1..c83f723 100644 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -261,10 +261,10 @@ public function testJsonSerialize() { $this->assertJsonStringEqualsJsonString('"foo"', json_encode(new EnumFixture(EnumFixture::FOO))); $this->assertJsonStringEqualsJsonString('"bar"', json_encode(new EnumFixture(EnumFixture::BAR))); - $this->assertJsonStringEqualsJsonString('42', json_encode(new EnumFixture(EnumFixture::NUMBER))); - $this->assertJsonStringEqualsJsonString('0', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_NUMBER))); - $this->assertJsonStringEqualsJsonString('null', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_NULL))); - $this->assertJsonStringEqualsJsonString('""', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_EMPTY_STRING))); + $this->assertJsonStringEqualsJsonString('42', json_encode(new EnumFixture(EnumFixture::NUMBER))); + $this->assertJsonStringEqualsJsonString('0', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_NUMBER))); + $this->assertJsonStringEqualsJsonString('null', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_NULL))); + $this->assertJsonStringEqualsJsonString('""', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_EMPTY_STRING))); $this->assertJsonStringEqualsJsonString('false', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_BOOLEAN_FALSE))); } From 1ac1a914eb36b17a098f9939b5d0ec0c9cf8936e Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Tue, 30 Oct 2018 14:54:02 +0100 Subject: [PATCH 019/104] Convert arrays to short arrays --- src/Enum.php | 2 +- tests/EnumTest.php | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Enum.php b/src/Enum.php index 00355df..d1bc516 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -29,7 +29,7 @@ abstract class Enum implements \JsonSerializable * * @var array */ - protected static $cache = array(); + protected static $cache = []; /** * Creates a new value of some type diff --git a/tests/EnumTest.php b/tests/EnumTest.php index c83f723..4dbcc80 100644 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -166,21 +166,21 @@ public function testIsValid($value, $isValid) public function isValidProvider() { - return array( + return [ /** * Valid values */ - array('foo', true), - array(42, true), - array(null, true), - array(0, true), - array('', true), - array(false, true), + ['foo', true], + [42, true], + [null, true], + [0, true], + ['', true], + [false, true], /** * Invalid values */ - array('baz', false) - ); + ['baz', false] + ]; } /** From 8a197f1ad73d02f0f46daa00dfbae0c06f9f6cdf Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Tue, 30 Oct 2018 14:56:39 +0100 Subject: [PATCH 020/104] Fix code style --- tests/EnumTest.php | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/tests/EnumTest.php b/tests/EnumTest.php index 4dbcc80..57f65a3 100644 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -259,13 +259,13 @@ public function testEqualsConflictValues() */ public function testJsonSerialize() { - $this->assertJsonStringEqualsJsonString('"foo"', json_encode(new EnumFixture(EnumFixture::FOO))); - $this->assertJsonStringEqualsJsonString('"bar"', json_encode(new EnumFixture(EnumFixture::BAR))); - $this->assertJsonStringEqualsJsonString('42', json_encode(new EnumFixture(EnumFixture::NUMBER))); - $this->assertJsonStringEqualsJsonString('0', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_NUMBER))); - $this->assertJsonStringEqualsJsonString('null', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_NULL))); - $this->assertJsonStringEqualsJsonString('""', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_EMPTY_STRING))); - $this->assertJsonStringEqualsJsonString('false', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_BOOLEAN_FALSE))); + $this->assertJsonEqualsJson('"foo"', json_encode(new EnumFixture(EnumFixture::FOO))); + $this->assertJsonEqualsJson('"bar"', json_encode(new EnumFixture(EnumFixture::BAR))); + $this->assertJsonEqualsJson('42', json_encode(new EnumFixture(EnumFixture::NUMBER))); + $this->assertJsonEqualsJson('0', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_NUMBER))); + $this->assertJsonEqualsJson('null', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_NULL))); + $this->assertJsonEqualsJson('""', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_EMPTY_STRING))); + $this->assertJsonEqualsJson('false', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_BOOLEAN_FALSE))); } public function testNullableEnum() @@ -280,4 +280,9 @@ public function testBooleanEnum() $this->assertFalse(EnumFixture::PROBLEMATIC_BOOLEAN_FALSE()->getValue()); $this->assertFalse((new EnumFixture(EnumFixture::PROBLEMATIC_BOOLEAN_FALSE))->jsonSerialize()); } + + private function assertJsonEqualsJson($json1, $json2) + { + $this->assertJsonStringEqualsJsonString($json1, $json2); + } } From d24462d356e0e20f0c99eea0797a96e8c940b80c Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Tue, 30 Oct 2018 14:57:10 +0100 Subject: [PATCH 021/104] Remove coding style from Travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a1bc09a..8f9e389 100755 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ php: - 7.0 - 7.1 - 7.2 + - 7.3 - nightly matrix: @@ -21,7 +22,6 @@ before_script: script: - vendor/bin/phpunit - - vendor/bin/phpcs --standard=PSR2 ./src/ # 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 5147e694f4253e7633e0df6d1bcf76bb5dff7b78 Mon Sep 17 00:00:00 2001 From: Kartvaik Date: Wed, 30 Jan 2019 16:07:46 +0200 Subject: [PATCH 022/104] Create instance of enum from same enum in constructor It will prevent incorrect semantic exception message --- src/Enum.php | 6 ++++++ tests/EnumTest.php | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/src/Enum.php b/src/Enum.php index d1bc516..aa36c42 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -40,6 +40,12 @@ abstract class Enum implements \JsonSerializable */ public function __construct($value) { + if ($value instanceof static) { + $this->value = $value->getValue(); + + return; + } + if (!$this->isValid($value)) { throw new \UnexpectedValueException("Value '$value' is not part of the enum " . \get_called_class()); } diff --git a/tests/EnumTest.php b/tests/EnumTest.php index 57f65a3..9591d73 100644 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -281,6 +281,15 @@ public function testBooleanEnum() $this->assertFalse((new EnumFixture(EnumFixture::PROBLEMATIC_BOOLEAN_FALSE))->jsonSerialize()); } + public function testConstructWithSameEnumArgument() + { + $enum = new EnumFixture(EnumFixture::FOO); + + $enveloped = new EnumFixture($enum); + + $this->assertEquals($enum, $enveloped); + } + private function assertJsonEqualsJson($json1, $json2) { $this->assertJsonStringEqualsJsonString($json1, $json2); From 521f5a32512ee211037c1d3d8de7b18b934ddfeb Mon Sep 17 00:00:00 2001 From: Kartvaik Date: Wed, 30 Jan 2019 17:00:20 +0200 Subject: [PATCH 023/104] Add ext-json to requirements for package --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 1395658..88bbe16 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ } }, "require": { - "php": ">=5.4" + "php": ">=5.4", + "ext-json": "*" }, "require-dev": { "phpunit/phpunit": "^4.8.35|^5.7|^6.0", From 094498380f381bb6435df9488d578a6b60c178c9 Mon Sep 17 00:00:00 2001 From: Andy Carter Date: Mon, 18 Feb 2019 10:56:47 +0000 Subject: [PATCH 024/104] Update PHP requirement for using private keyword "PHP > 7.1" implies you need a version above 7.1 whereas this syntax was added as part of PHP 7.1. I've modified the text to make this clearer in the readme. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6a08e0a..995f139 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ class Action extends Enum } ``` -Note the `private` keyword requires PHP > 7.1, you can omit it on PHP 7.0. +Note the `private` keyword requires PHP 7.1 or higher, you can omit it on PHP 7.0. ## Usage From aab502b7c734dcf44c7e9318df8298f5be77efa7 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Mon, 18 Feb 2019 14:05:37 +0100 Subject: [PATCH 025/104] Remove builds on nightly version of PHP The build is failing because of composer constraints. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8f9e389..ca8fea8 100755 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,6 @@ php: - 7.1 - 7.2 - 7.3 - - nightly matrix: fast_finish: true From 42dbbdeec24d5a5d6a8971626fd243d614fecd13 Mon Sep 17 00:00:00 2001 From: Peter Gribanov Date: Fri, 19 Apr 2019 16:05:29 +0300 Subject: [PATCH 026/104] split string for Pretty CI: "Line exceeds 120 characters" --- tests/EnumTest.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/EnumTest.php b/tests/EnumTest.php index d75a380..dff2069 100755 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -297,19 +297,21 @@ private function assertJsonEqualsJson($json1, $json2) public function testSerialize() { - $this->assertEquals( - '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d46697874757265223a313a7b733a383a22002a0076616c7565223b733a333a22666f6f223b7d', - bin2hex(serialize(EnumFixture::FOO())) - ); + // split string for Pretty CI: "Line exceeds 120 characters" + $bin = '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d4669787'. + '4757265223a313a7b733a383a22002a0076616c7565223b733a333a22666f6f223b7d'; + + $this->assertEquals($bin, bin2hex(serialize(EnumFixture::FOO()))); } public function testUnserialize() { + // split string for Pretty CI: "Line exceeds 120 characters" + $bin = '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d4669787'. + '4757265223a313a7b733a383a22002a0076616c7565223b733a333a22666f6f223b7d'; + /* @var $value EnumFixture */ - $value = unserialize(pack( - 'H*', - '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d46697874757265223a313a7b733a383a22002a0076616c7565223b733a333a22666f6f223b7d' - )); + $value = unserialize(pack('H*', $bin)); $this->assertEquals(EnumFixture::FOO, $value->getValue()); $this->assertTrue(EnumFixture::FOO()->equals($value)); From 7f285a3c010e70d03721cb25a4579c9b305cb102 Mon Sep 17 00:00:00 2001 From: "jacek.foremski" Date: Tue, 23 Apr 2019 12:31:45 +0200 Subject: [PATCH 027/104] Change "equals()" method to accept anything as a parameter --- src/Enum.php | 11 +++++++---- tests/EnumTest.php | 4 ++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Enum.php b/src/Enum.php index aa36c42..58b69b3 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -80,15 +80,18 @@ public function __toString() } /** - * Compares one Enum with another. + * Determines if Enum should be considered equal with the variable passed as a parameter. + * Returns false if an argument is an object of different class or not an object. * * This method is final, for more information read https://github.com/myclabs/php-enum/issues/4 * - * @return bool True if Enums are equal, false if not equal + * @return bool */ - final public function equals(Enum $enum = null) + final public function equals($variable = null) { - return $enum !== null && $this->getValue() === $enum->getValue() && \get_called_class() === \get_class($enum); + return $variable instanceof self + && $this->getValue() === $variable->getValue() + && \get_called_class() === \get_class($variable); } /** diff --git a/tests/EnumTest.php b/tests/EnumTest.php index dff2069..4253618 100755 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -224,11 +224,15 @@ public function testEquals() $foo = new EnumFixture(EnumFixture::FOO); $number = new EnumFixture(EnumFixture::NUMBER); $anotherFoo = new EnumFixture(EnumFixture::FOO); + $objectOfDifferentClass = new \stdClass(); + $notAnObject = 'foo'; $this->assertTrue($foo->equals($foo)); $this->assertFalse($foo->equals($number)); $this->assertTrue($foo->equals($anotherFoo)); $this->assertFalse($foo->equals(null)); + $this->assertFalse($foo->equals($objectOfDifferentClass)); + $this->assertFalse($foo->equals($notAnObject)); } /** From d631995a7b0fc574b97f6f5428f83fad29dfed13 Mon Sep 17 00:00:00 2001 From: "jacek.foremski" Date: Tue, 23 Apr 2019 13:52:47 +0200 Subject: [PATCH 028/104] Add return type declaration for "equals()" method --- .travis.yml | 5 ----- README.md | 2 -- composer.json | 2 +- src/Enum.php | 2 +- 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index ca8fea8..bfc13d1 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,6 @@ language: php php: - - 5.4 - - 5.5 - - 5.6 - - 7.0 - - 7.1 - 7.2 - 7.3 diff --git a/README.md b/README.md index 995f139..cbb48b3 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,6 @@ class Action extends Enum } ``` -Note the `private` keyword requires PHP 7.1 or higher, you can omit it on PHP 7.0. - ## Usage ```php diff --git a/composer.json b/composer.json index 88bbe16..3a10886 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ } }, "require": { - "php": ">=5.4", + "php": ">=7.2", "ext-json": "*" }, "require-dev": { diff --git a/src/Enum.php b/src/Enum.php index 58b69b3..2999d31 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -87,7 +87,7 @@ public function __toString() * * @return bool */ - final public function equals($variable = null) + final public function equals($variable = null): bool { return $variable instanceof self && $this->getValue() === $variable->getValue() From fa58f3efb151aaaefb6013e54a53cf8228bb4949 Mon Sep 17 00:00:00 2001 From: James Fenwick Date: Fri, 26 Apr 2019 15:15:11 +0100 Subject: [PATCH 029/104] Change minimum PHP version to 7.1 --- .travis.yml | 1 + composer.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bfc13d1..5ec1ca0 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: php php: + - 7.1 - 7.2 - 7.3 diff --git a/composer.json b/composer.json index 3a10886..871156d 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ } }, "require": { - "php": ">=7.2", + "php": ">=7.1", "ext-json": "*" }, "require-dev": { From d461d86661ee46ec6d9b776a1156c459b1134f79 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Tue, 30 Apr 2019 11:16:14 +0200 Subject: [PATCH 030/104] Add link to https://github.com/timeweb/phpstan-enum --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cbb48b3..35fa948 100644 --- a/README.md +++ b/README.md @@ -123,4 +123,5 @@ class Action extends Enum ## Related projects - [Doctrine enum mapping](https://github.com/acelaya/doctrine-enum-type) -- [Symfony 2/3 ParamConverter integration](https://github.com/Ex3v/MyCLabsEnumParamConverter) +- [Symfony ParamConverter integration](https://github.com/Ex3v/MyCLabsEnumParamConverter) +- [PHPStan integration](https://github.com/timeweb/phpstan-enum) From 960cdf1332e6049af5934c1be2e3b025bb81c5d0 Mon Sep 17 00:00:00 2001 From: Willem Stuursma Date: Thu, 2 May 2019 13:30:04 +0200 Subject: [PATCH 031/104] Add a comparator to help with writing tests --- src/PHPUnit/Comparator.php | 52 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/PHPUnit/Comparator.php diff --git a/src/PHPUnit/Comparator.php b/src/PHPUnit/Comparator.php new file mode 100644 index 0000000..9608833 --- /dev/null +++ b/src/PHPUnit/Comparator.php @@ -0,0 +1,52 @@ +register(new \MyCLabs\Enum\PHPUnit\Comparator()); + */ +final class Comparator extends \SebastianBergmann\Comparator\Comparator +{ + public function accepts($expected, $actual) + { + return $expected instanceof Enum && ( + $actual instanceof Enum || $actual === null + ); + } + + /** + * @param Enum $expected + * @param Enum|null $actual + */ + public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false) + { + if ($expected->equals($actual)) { + return; + } + + throw new ComparisonFailure( + $expected, + $actual, + $this->formatEnum($expected), + $this->formatEnum($actual), + false, + 'Failed asserting that two Enums are equal.' + ); + } + + private function formatEnum(Enum $enum = null) + { + if ($enum === null) { + return "null"; + } + + return get_class($enum)."::{$enum->getKey()}()"; + } +} \ No newline at end of file From 758bc39867bd19eaa786a62219cd8d5a1ebe39b3 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Thu, 2 May 2019 13:43:42 +0200 Subject: [PATCH 032/104] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 35fa948..94dae7f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ## Why? -First, and mainly, `SplEnum` is not integrated to PHP, you have to install it separately. +First, and mainly, `SplEnum` is not integrated to PHP, you have to install the extension separately. Using an enum instead of class constants provides the following advantages: From 2d72a4c51245d615c6cfef743fd4966ced8bc0a8 Mon Sep 17 00:00:00 2001 From: Willem Stuursma Date: Thu, 2 May 2019 14:38:47 +0200 Subject: [PATCH 033/104] Add newline to EOF --- src/PHPUnit/Comparator.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/PHPUnit/Comparator.php b/src/PHPUnit/Comparator.php index 9608833..302bf80 100644 --- a/src/PHPUnit/Comparator.php +++ b/src/PHPUnit/Comparator.php @@ -24,6 +24,8 @@ public function accepts($expected, $actual) /** * @param Enum $expected * @param Enum|null $actual + * + * @return void */ public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false) { @@ -49,4 +51,4 @@ private function formatEnum(Enum $enum = null) return get_class($enum)."::{$enum->getKey()}()"; } -} \ No newline at end of file +} From 3c33ff203ce42802ebc7796f91f1b5bbe587c996 Mon Sep 17 00:00:00 2001 From: Willem Stuursma Date: Thu, 2 May 2019 14:43:01 +0200 Subject: [PATCH 034/104] Use Comparator in internal tests --- phpunit.xml | 2 +- tests/bootstrap.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 tests/bootstrap.php diff --git a/phpunit.xml b/phpunit.xml index af5293b..67a61e1 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -11,7 +11,7 @@ processIsolation="false" stopOnFailure="false" syntaxCheck="false" - bootstrap="./vendor/autoload.php"> + bootstrap="./tests/bootstrap.php"> ./tests diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..d72b404 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,3 @@ +register(new \MyCLabs\Enum\PHPUnit\Comparator()); From 74662ebae19b1451bcb0fa87d0854e64d31b837a Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Tue, 30 Jul 2019 09:34:40 +0200 Subject: [PATCH 035/104] Fix license file so that it is detected as MIT --- LICENSE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index accd5a0..2a8cf22 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ -php-enum - PHP Enum implementation http://github.com/myclabs/php-enum +The MIT License (MIT) -Copyright (C) 2015 My C-Labs +Copyright (c) 2015 My C-Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, From de805197faba8f4abdbf82ec20241c525445c286 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Wed, 31 Jul 2019 12:46:28 +0200 Subject: [PATCH 036/104] Fix #91: documentation update --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 94dae7f..329b970 100644 --- a/README.md +++ b/README.md @@ -41,10 +41,12 @@ class Action extends Enum ## Usage ```php -$action = new Action(Action::VIEW); - -// or $action = Action::VIEW(); + +// or with a dynamic key: +$action = Action::$key(); +// or with a dynamic value: +$action = new Action($value); ``` As you can see, static methods are automatically implemented to provide quick access to an enum value. From f322c99782c25302919ae04bfc93f1ac28f0cbf4 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Fri, 9 Aug 2019 14:38:03 +0200 Subject: [PATCH 037/104] Create SECURITY.md --- SECURITY.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..84fd4e3 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,11 @@ +# Security Policy + +## Supported Versions + +Only the latest stable release is supported. + +## Reporting a Vulnerability + +To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). + +Tidelift will coordinate the fix and disclosure. From ecd04666d6ffc0f0cfc78f53991950c620528d80 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Fri, 9 Aug 2019 14:50:03 +0200 Subject: [PATCH 038/104] Create FUNDING.yml --- .github/FUNDING.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..d20d41a --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: "packagist/myclabs/php-enum" +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] From d4cb1c43714eda658ba5e51fecaee4eb24232b21 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Fri, 9 Aug 2019 14:52:58 +0200 Subject: [PATCH 039/104] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 329b970..7bdd4f8 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ [![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) +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). + ## Why? First, and mainly, `SplEnum` is not integrated to PHP, you have to install the extension separately. From 2fced2e324fe101c857102e5b144ac63a8360337 Mon Sep 17 00:00:00 2001 From: Roman Varkuta Date: Mon, 12 Aug 2019 14:28:52 +0300 Subject: [PATCH 040/104] Fix yaml array style and add php7.4-beta for tests --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5ec1ca0..99e7178 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,10 @@ language: php php: - - 7.1 - - 7.2 - - 7.3 + - '7.1' + - '7.2' + - '7.3' + - '7.4snapshot' matrix: fast_finish: true From 3359da89e0044b8e1e9a77af39868b7d402cf0aa Mon Sep 17 00:00:00 2001 From: user-rq Date: Mon, 12 Aug 2019 15:38:16 +0300 Subject: [PATCH 041/104] Resolve constructing base enum from inherited enum with invalid value --- src/Enum.php | 4 +--- tests/EnumTest.php | 11 +++++++++++ tests/InheritedEnumFixture.php | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 tests/InheritedEnumFixture.php diff --git a/src/Enum.php b/src/Enum.php index 2999d31..3bce0dc 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -41,9 +41,7 @@ abstract class Enum implements \JsonSerializable public function __construct($value) { if ($value instanceof static) { - $this->value = $value->getValue(); - - return; + $value = $value->getValue(); } if (!$this->isValid($value)) { diff --git a/tests/EnumTest.php b/tests/EnumTest.php index 4253618..9fe9022 100755 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -320,4 +320,15 @@ public function testUnserialize() $this->assertEquals(EnumFixture::FOO, $value->getValue()); $this->assertTrue(EnumFixture::FOO()->equals($value)); } + + /** + * @see https://github.com/myclabs/php-enum/issues/95 + */ + public function testEnumValuesInheritance() + { + $this->expectException(\UnexpectedValueException::class); + $this->expectExceptionMessage("Value 'value' is not part of the enum MyCLabs\Tests\Enum\EnumFixture"); + $inheritedEnumFixture = InheritedEnumFixture::VALUE(); + new EnumFixture($inheritedEnumFixture); + } } diff --git a/tests/InheritedEnumFixture.php b/tests/InheritedEnumFixture.php new file mode 100644 index 0000000..301f9bb --- /dev/null +++ b/tests/InheritedEnumFixture.php @@ -0,0 +1,14 @@ + Date: Thu, 15 Aug 2019 09:15:40 +0200 Subject: [PATCH 042/104] Update .gitattributes --- .gitattributes | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 50b8b8a..cd7364e 100755 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,9 @@ # Auto detect text files and perform LF normalization * text=auto +.gitattributes export-ignore +.github export-ignore +.gitignore export-ignore +.travis.yml export-ignore tests/ export-ignore phpunit.xml export-ignore -.travis.yml export-ignore From 18f3e186a6f0397dcf28d145346b44f3bd27e688 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Tue, 15 Oct 2019 09:27:08 +0200 Subject: [PATCH 043/104] Update FUNDING.yml --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index d20d41a..9b8c2d6 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,6 +1,6 @@ # These are supported funding model platforms -github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +github: mnapoli # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username 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 044/104] 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 045/104] 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 046/104] 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 047/104] 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 048/104] 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 049/104] 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 050/104] 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 051/104] 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 052/104] 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 053/104] 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 054/104] 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 055/104] 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 056/104] 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 057/104] 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 058/104] 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 059/104] 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 060/104] 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 061/104] 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 062/104] 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 063/104] 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 064/104] 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 065/104] 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 066/104] __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 067/104] 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 068/104] 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 069/104] 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 070/104] 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 071/104] 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 072/104] 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 073/104] 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 074/104] 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 075/104] 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 076/104] 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 077/104] 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 078/104] 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 079/104] 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 080/104] 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 081/104] 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 082/104] 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 083/104] 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 084/104] 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 085/104] 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 086/104] 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 087/104] 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 088/104] 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 089/104] 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 090/104] 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 091/104] 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 092/104] 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 093/104] 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 094/104] 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 095/104] 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 096/104] 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 097/104] 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 098/104] 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 099/104] 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 100/104] 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 101/104] 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 102/104] 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 103/104] 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 104/104] 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).