From 0997de99a2a2ce27f6b5a913dcb26442ab61a6c8 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sun, 5 Sep 2021 12:41:13 +0100 Subject: [PATCH 1/3] Add support for PHP 8.1 --- .github/workflows/continuous-integration.yml | 5 +-- composer.json | 3 +- phpstan.neon.dist | 4 +++ psalm-baseline.xml | 35 +++++++++++++++++++- src/Fields/SerializableFieldsTrait.php | 23 +++++++++++++ src/Lazy/LazyUuidFromString.php | 26 +++++++++++++++ src/Type/Decimal.php | 22 ++++++++++++ src/Type/Hexadecimal.php | 22 ++++++++++++ src/Type/Integer.php | 22 ++++++++++++ src/Type/Time.php | 25 ++++++++++++++ src/Uuid.php | 22 ++++++++++++ 11 files changed, 203 insertions(+), 6 deletions(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index cdd15f3b..5c8a0b8b 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -66,6 +66,7 @@ jobs: - "7.3" - "7.4" - "8.0" + - "8.1" steps: - name: "Checkout repository" @@ -114,7 +115,6 @@ jobs: unit-tests: name: "Unit Tests" runs-on: "ubuntu-latest" - continue-on-error: ${{ matrix.experimental }} strategy: fail-fast: false @@ -124,11 +124,8 @@ jobs: - "7.3" - "7.4" - "8.0" - experimental: - - false include: - php-version: "8.1" - experimental: true composer-options: "--ignore-platform-req=php" steps: diff --git a/composer.json b/composer.json index a29d483c..a2f1014f 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,8 @@ "ext-json": "*", "brick/math": "^0.8 || ^0.9", "ramsey/collection": "^1.0", - "symfony/polyfill-ctype": "^1.8" + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php80": "^1.14" }, "replace": { "rhumsaa/uuid": "self.version" diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 131212f6..1382f73f 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -29,3 +29,7 @@ parameters: message: '#^Call to an undefined method Ramsey\\Uuid\\Fields\\FieldsInterface::get.*$#' count: 9 path: ./src/Lazy/LazyUuidFromString.php + - + message: '#^Result of \|\| is always false\.$#' + count: 1 + path: ./src/Type/Time.php diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 2744786c..402c2ac5 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,5 +1,5 @@ - + DegradedUuid @@ -48,6 +48,11 @@ $timeProvider + + + unserialize + + uuid_generate_md5 @@ -62,6 +67,11 @@ $this + + + unserialize + + $this @@ -108,6 +118,26 @@ $this + + + unserialize + + + + + unserialize + + + + + unserialize + + + + + __construct + + getFactory @@ -117,6 +147,9 @@ getFactory getFactory + + unserialize + diff --git a/src/Fields/SerializableFieldsTrait.php b/src/Fields/SerializableFieldsTrait.php index a076568c..96c8baf8 100644 --- a/src/Fields/SerializableFieldsTrait.php +++ b/src/Fields/SerializableFieldsTrait.php @@ -14,7 +14,10 @@ namespace Ramsey\Uuid\Fields; +use ValueError; + use function base64_decode; +use function sprintf; use function strlen; /** @@ -42,6 +45,14 @@ public function serialize(): string return $this->getBytes(); } + /** + * @return array{bytes: string} + */ + public function __serialize(): array + { + return ['bytes' => $this->getBytes()]; + } + /** * Constructs the object from a serialized string representation * @@ -58,4 +69,16 @@ public function unserialize($serialized): void $this->__construct(base64_decode($serialized)); } } + + /** + * @param array{bytes: string} $data + */ + public function __unserialize(array $data): void + { + if (!isset($data['bytes'])) { + throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); + } + + $this->unserialize($data['bytes']); + } } diff --git a/src/Lazy/LazyUuidFromString.php b/src/Lazy/LazyUuidFromString.php index 82c156c0..093cd526 100644 --- a/src/Lazy/LazyUuidFromString.php +++ b/src/Lazy/LazyUuidFromString.php @@ -24,10 +24,12 @@ use Ramsey\Uuid\Type\Integer as IntegerObject; use Ramsey\Uuid\UuidFactory; use Ramsey\Uuid\UuidInterface; +use ValueError; use function assert; use function bin2hex; use function hex2bin; +use function sprintf; use function str_replace; use function substr; @@ -90,6 +92,16 @@ public function serialize(): string return $this->uuid; } + /** + * @return array{string: string} + * + * @psalm-return array{string: non-empty-string} + */ + public function __serialize(): array + { + return ['string' => $this->uuid]; + } + /** * {@inheritDoc} * @@ -102,6 +114,20 @@ public function unserialize($serialized): void $this->uuid = $serialized; } + /** + * @param array{string: string} $data + * + * @psalm-param array{string: non-empty-string} $data + */ + public function __unserialize(array $data): void + { + if (!isset($data['string'])) { + throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); + } + + $this->unserialize($data['string']); + } + /** @psalm-suppress DeprecatedMethod */ public function getNumberConverter(): NumberConverterInterface { diff --git a/src/Type/Decimal.php b/src/Type/Decimal.php index 042fc160..6eb3623b 100644 --- a/src/Type/Decimal.php +++ b/src/Type/Decimal.php @@ -15,8 +15,10 @@ namespace Ramsey\Uuid\Type; use Ramsey\Uuid\Exception\InvalidArgumentException; +use ValueError; use function is_numeric; +use function sprintf; /** * A value object representing a decimal @@ -98,6 +100,14 @@ public function serialize(): string return $this->toString(); } + /** + * @return array{string: string} + */ + public function __serialize(): array + { + return ['string' => $this->toString()]; + } + /** * Constructs the object from a serialized string representation * @@ -110,4 +120,16 @@ public function unserialize($serialized): void { $this->__construct($serialized); } + + /** + * @param array{string: string} $data + */ + public function __unserialize(array $data): void + { + if (!isset($data['string'])) { + throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); + } + + $this->unserialize($data['string']); + } } diff --git a/src/Type/Hexadecimal.php b/src/Type/Hexadecimal.php index 7de2f82c..57cb631c 100644 --- a/src/Type/Hexadecimal.php +++ b/src/Type/Hexadecimal.php @@ -15,8 +15,10 @@ namespace Ramsey\Uuid\Type; use Ramsey\Uuid\Exception\InvalidArgumentException; +use ValueError; use function ctype_xdigit; +use function sprintf; use function strpos; use function strtolower; use function substr; @@ -77,6 +79,14 @@ public function serialize(): string return $this->toString(); } + /** + * @return array{string: string} + */ + public function __serialize(): array + { + return ['string' => $this->toString()]; + } + /** * Constructs the object from a serialized string representation * @@ -89,4 +99,16 @@ public function unserialize($serialized): void { $this->__construct($serialized); } + + /** + * @param array{string: string} $data + */ + public function __unserialize(array $data): void + { + if (!isset($data['string'])) { + throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); + } + + $this->unserialize($data['string']); + } } diff --git a/src/Type/Integer.php b/src/Type/Integer.php index fabe5eb9..42a471d2 100644 --- a/src/Type/Integer.php +++ b/src/Type/Integer.php @@ -15,9 +15,11 @@ namespace Ramsey\Uuid\Type; use Ramsey\Uuid\Exception\InvalidArgumentException; +use ValueError; use function ctype_digit; use function ltrim; +use function sprintf; use function strpos; use function substr; @@ -114,6 +116,14 @@ public function serialize(): string return $this->toString(); } + /** + * @return array{string: string} + */ + public function __serialize(): array + { + return ['string' => $this->toString()]; + } + /** * Constructs the object from a serialized string representation * @@ -126,4 +136,16 @@ public function unserialize($serialized): void { $this->__construct($serialized); } + + /** + * @param array{string: string} $data + */ + public function __unserialize(array $data): void + { + if (!isset($data['string'])) { + throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); + } + + $this->unserialize($data['string']); + } } diff --git a/src/Type/Time.php b/src/Type/Time.php index abceddf4..55f03585 100644 --- a/src/Type/Time.php +++ b/src/Type/Time.php @@ -16,10 +16,12 @@ use Ramsey\Uuid\Exception\UnsupportedOperationException; use Ramsey\Uuid\Type\Integer as IntegerObject; +use ValueError; use stdClass; use function json_decode; use function json_encode; +use function sprintf; /** * A value object representing a timestamp @@ -88,6 +90,17 @@ public function serialize(): string return (string) json_encode($this); } + /** + * @return array{seconds: string, microseconds: string} + */ + public function __serialize(): array + { + return [ + 'seconds' => $this->getSeconds()->toString(), + 'microseconds' => $this->getMicroseconds()->toString(), + ]; + } + /** * Constructs the object from a serialized string representation * @@ -109,4 +122,16 @@ public function unserialize($serialized): void $this->__construct($time->seconds, $time->microseconds); } + + /** + * @param array{seconds: string, microseconds: string} $data + */ + public function __unserialize(array $data): void + { + if (!isset($data['seconds']) || !isset($data['microseconds'])) { + throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); + } + + $this->__construct($data['seconds'], $data['microseconds']); + } } diff --git a/src/Uuid.php b/src/Uuid.php index d80fd57a..f2dab135 100644 --- a/src/Uuid.php +++ b/src/Uuid.php @@ -23,10 +23,12 @@ use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; use Ramsey\Uuid\Type\Hexadecimal; use Ramsey\Uuid\Type\Integer as IntegerObject; +use ValueError; use function assert; use function bin2hex; use function preg_match; +use function sprintf; use function str_replace; use function strcmp; use function strlen; @@ -289,6 +291,14 @@ public function serialize(): string return $this->getFields()->getBytes(); } + /** + * @return array{bytes: string} + */ + public function __serialize(): array + { + return ['bytes' => $this->serialize()]; + } + /** * Re-constructs the object from its serialized form * @@ -313,6 +323,18 @@ public function unserialize($serialized): void $this->timeConverter = $uuid->timeConverter; } + /** + * @param array{bytes: string} $data + */ + public function __unserialize(array $data): void + { + if (!isset($data['bytes'])) { + throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); + } + + $this->unserialize($data['bytes']); + } + public function compareTo(UuidInterface $other): int { $compare = strcmp($this->toString(), $other->toString()); From 2ed177534efcf0dadbf91e316d60b5c860bdfe55 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sun, 5 Sep 2021 14:03:47 +0100 Subject: [PATCH 2/3] Ignore serialization shape checking for code coverage purposes --- src/Fields/SerializableFieldsTrait.php | 2 ++ src/Lazy/LazyUuidFromString.php | 2 ++ src/Type/Decimal.php | 2 ++ src/Type/Hexadecimal.php | 2 ++ src/Type/Integer.php | 2 ++ src/Type/Time.php | 2 ++ src/Uuid.php | 2 ++ 7 files changed, 14 insertions(+) diff --git a/src/Fields/SerializableFieldsTrait.php b/src/Fields/SerializableFieldsTrait.php index 96c8baf8..16e6525d 100644 --- a/src/Fields/SerializableFieldsTrait.php +++ b/src/Fields/SerializableFieldsTrait.php @@ -75,9 +75,11 @@ public function unserialize($serialized): void */ public function __unserialize(array $data): void { + // @codeCoverageIgnoreStart if (!isset($data['bytes'])) { throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); } + // @codeCoverageIgnoreEnd $this->unserialize($data['bytes']); } diff --git a/src/Lazy/LazyUuidFromString.php b/src/Lazy/LazyUuidFromString.php index 093cd526..8ba75796 100644 --- a/src/Lazy/LazyUuidFromString.php +++ b/src/Lazy/LazyUuidFromString.php @@ -121,9 +121,11 @@ public function unserialize($serialized): void */ public function __unserialize(array $data): void { + // @codeCoverageIgnoreStart if (!isset($data['string'])) { throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); } + // @codeCoverageIgnoreEnd $this->unserialize($data['string']); } diff --git a/src/Type/Decimal.php b/src/Type/Decimal.php index 6eb3623b..10f93845 100644 --- a/src/Type/Decimal.php +++ b/src/Type/Decimal.php @@ -126,9 +126,11 @@ public function unserialize($serialized): void */ public function __unserialize(array $data): void { + // @codeCoverageIgnoreStart if (!isset($data['string'])) { throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); } + // @codeCoverageIgnoreEnd $this->unserialize($data['string']); } diff --git a/src/Type/Hexadecimal.php b/src/Type/Hexadecimal.php index 57cb631c..88adc2e7 100644 --- a/src/Type/Hexadecimal.php +++ b/src/Type/Hexadecimal.php @@ -105,9 +105,11 @@ public function unserialize($serialized): void */ public function __unserialize(array $data): void { + // @codeCoverageIgnoreStart if (!isset($data['string'])) { throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); } + // @codeCoverageIgnoreEnd $this->unserialize($data['string']); } diff --git a/src/Type/Integer.php b/src/Type/Integer.php index 42a471d2..7690f6cd 100644 --- a/src/Type/Integer.php +++ b/src/Type/Integer.php @@ -142,9 +142,11 @@ public function unserialize($serialized): void */ public function __unserialize(array $data): void { + // @codeCoverageIgnoreStart if (!isset($data['string'])) { throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); } + // @codeCoverageIgnoreEnd $this->unserialize($data['string']); } diff --git a/src/Type/Time.php b/src/Type/Time.php index 55f03585..dd1b8bc2 100644 --- a/src/Type/Time.php +++ b/src/Type/Time.php @@ -128,9 +128,11 @@ public function unserialize($serialized): void */ public function __unserialize(array $data): void { + // @codeCoverageIgnoreStart if (!isset($data['seconds']) || !isset($data['microseconds'])) { throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); } + // @codeCoverageIgnoreEnd $this->__construct($data['seconds'], $data['microseconds']); } diff --git a/src/Uuid.php b/src/Uuid.php index f2dab135..945480ba 100644 --- a/src/Uuid.php +++ b/src/Uuid.php @@ -328,9 +328,11 @@ public function unserialize($serialized): void */ public function __unserialize(array $data): void { + // @codeCoverageIgnoreStart if (!isset($data['bytes'])) { throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__)); } + // @codeCoverageIgnoreEnd $this->unserialize($data['bytes']); } From d86822196f34ef2083d18dd70ccdd29163006b44 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sun, 5 Sep 2021 14:14:15 +0100 Subject: [PATCH 3/3] Update continuous-integration.yml --- .github/workflows/continuous-integration.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 5c8a0b8b..37ba9e42 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -66,7 +66,9 @@ jobs: - "7.3" - "7.4" - "8.0" - - "8.1" + include: + - php-version: "8.1" + composer-options: "--ignore-platform-req=php" steps: - name: "Checkout repository" @@ -89,6 +91,14 @@ jobs: code-coverage: name: "Code coverage" runs-on: "ubuntu-latest" + + strategy: + fail-fast: false + matrix: + php-version: + - "7.2" + - "8.0" + steps: - name: "Checkout repository" uses: "actions/checkout@v2"