diff --git a/docs/installation.rst b/docs/installation.rst deleted file mode 100644 index 886f092..0000000 --- a/docs/installation.rst +++ /dev/null @@ -1,37 +0,0 @@ -.. _installation: - -====================== -Installing ramsey/uuid -====================== - -Requirements -############ - -ramsey/uuid |version| requires PHP 7.2. Using the latest version of PHP is -highly recommended. - -ramsey/uuid requires the `json `_ -extension, which is normally enabled by default. - -ramsey/uuid also requires the -`pcre `_ -and `spl `_ -extensions. These standard extensions are enabled by default and cannot be -disabled without patching PHP's build system and/or C sources. - -ramsey/uuid recommends installing the -`ctype `_, -`gmp `_, -or `bcmath `_ extensions. -While not required, these extensions improve the performance of ramsey/uuid. - -Composer -######## - -The only supported installation method for ramsey/uuid is -`Composer `_. Use the following command to add -ramsey/uuid to your project dependencies: - -.. code-block:: bash - - composer require ramsey/uuid diff --git a/src/Type/Decimal.php b/src/Type/Decimal.php index a561a45..982e0f5 100644 --- a/src/Type/Decimal.php +++ b/src/Type/Decimal.php @@ -73,4 +73,26 @@ final class Decimal implements NumberInterface { return $this->toString(); } + + public function jsonSerialize(): string + { + return $this->toString(); + } + + public function serialize(): string + { + return $this->toString(); + } + + /** + * Constructs the object from a serialized string representation + * + * @param string $serialized The serialized string representation of the object + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + */ + public function unserialize($serialized): void + { + $this->__construct($serialized); + } } diff --git a/src/Type/Hexadecimal.php b/src/Type/Hexadecimal.php index 7e508f9..1145018 100644 --- a/src/Type/Hexadecimal.php +++ b/src/Type/Hexadecimal.php @@ -66,4 +66,26 @@ final class Hexadecimal implements TypeInterface { return $this->toString(); } + + public function jsonSerialize(): string + { + return $this->toString(); + } + + public function serialize(): string + { + return $this->toString(); + } + + /** + * Constructs the object from a serialized string representation + * + * @param string $serialized The serialized string representation of the object + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + */ + public function unserialize($serialized): void + { + $this->__construct($serialized); + } } diff --git a/src/Type/Integer.php b/src/Type/Integer.php index a8ff1d8..0be97a7 100644 --- a/src/Type/Integer.php +++ b/src/Type/Integer.php @@ -86,4 +86,26 @@ final class Integer implements NumberInterface { return $this->toString(); } + + public function jsonSerialize(): string + { + return $this->toString(); + } + + public function serialize(): string + { + return $this->toString(); + } + + /** + * Constructs the object from a serialized string representation + * + * @param string $serialized The serialized string representation of the object + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + */ + public function unserialize($serialized): void + { + $this->__construct($serialized); + } } diff --git a/src/Type/Time.php b/src/Type/Time.php index b4996fc..7e9715e 100644 --- a/src/Type/Time.php +++ b/src/Type/Time.php @@ -14,7 +14,12 @@ declare(strict_types=1); namespace Ramsey\Uuid\Type; +use Ramsey\Uuid\Exception\UnsupportedOperationException; use Ramsey\Uuid\Type\Integer as IntegerObject; +use stdClass; + +use function json_decode; +use function json_encode; /** * A value object representing a timestamp @@ -66,4 +71,41 @@ final class Time implements TypeInterface { return $this->toString(); } + + /** + * @return string[] + */ + public function jsonSerialize(): array + { + return [ + 'seconds' => $this->getSeconds()->toString(), + 'microseconds' => $this->getMicroSeconds()->toString(), + ]; + } + + public function serialize(): string + { + return (string) json_encode($this); + } + + /** + * Constructs the object from a serialized string representation + * + * @param string $serialized The serialized string representation of the object + * + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + */ + public function unserialize($serialized): void + { + /** @var stdClass $time */ + $time = json_decode($serialized); + + if (!isset($time->seconds) || !isset($time->microseconds)) { + throw new UnsupportedOperationException( + 'Attempted to unserialize an invalid value' + ); + } + + $this->__construct($time->seconds, $time->microseconds); + } } diff --git a/src/Type/TypeInterface.php b/src/Type/TypeInterface.php index afa1e5b..da2d8b2 100644 --- a/src/Type/TypeInterface.php +++ b/src/Type/TypeInterface.php @@ -14,12 +14,15 @@ declare(strict_types=1); namespace Ramsey\Uuid\Type; +use JsonSerializable; +use Serializable; + /** * TypeInterface ensures consistency in typed values returned by ramsey/uuid * * @psalm-immutable */ -interface TypeInterface +interface TypeInterface extends JsonSerializable, Serializable { public function toString(): string; diff --git a/tests/Type/DecimalTest.php b/tests/Type/DecimalTest.php index 491d5c2..09c0a6c 100644 --- a/tests/Type/DecimalTest.php +++ b/tests/Type/DecimalTest.php @@ -8,6 +8,11 @@ use Ramsey\Uuid\Exception\InvalidArgumentException; use Ramsey\Uuid\Test\TestCase; use Ramsey\Uuid\Type\Decimal; +use function json_encode; +use function serialize; +use function sprintf; +use function unserialize; + class DecimalTest extends TestCase { /** @@ -226,4 +231,31 @@ class DecimalTest extends TestCase ['-0012.a'], ]; } + + /** + * @param mixed $value + * + * @dataProvider provideDecimal + */ + public function testSerializeUnserializeDecimal($value, string $expected): void + { + $decimal = new Decimal($value); + $serializedDecimal = serialize($decimal); + $unserializedDecimal = unserialize($serializedDecimal); + + $this->assertSame($expected, $unserializedDecimal->toString()); + } + + /** + * @param mixed $value + * + * @dataProvider provideDecimal + */ + public function testJsonSerialize($value, string $expected): void + { + $decimal = new Decimal($value); + $expectedJson = sprintf('"%s"', $expected); + + $this->assertSame($expectedJson, json_encode($decimal)); + } } diff --git a/tests/Type/HexadecimalTest.php b/tests/Type/HexadecimalTest.php index 01b8033..2a3112c 100644 --- a/tests/Type/HexadecimalTest.php +++ b/tests/Type/HexadecimalTest.php @@ -8,6 +8,11 @@ use Ramsey\Uuid\Exception\InvalidArgumentException; use Ramsey\Uuid\Test\TestCase; use Ramsey\Uuid\Type\Hexadecimal; +use function json_encode; +use function serialize; +use function sprintf; +use function unserialize; + class HexadecimalTest extends TestCase { /** @@ -67,4 +72,31 @@ class HexadecimalTest extends TestCase ['0xfoobar'], ]; } + + /** + * @param mixed $value + * + * @dataProvider provideHex + */ + public function testSerializeUnserializeHexadecimal($value, string $expected): void + { + $hexadecimal = new Hexadecimal($value); + $serializedHexadecimal = serialize($hexadecimal); + $unserializedHexadecimal = unserialize($serializedHexadecimal); + + $this->assertSame($expected, $unserializedHexadecimal->toString()); + } + + /** + * @param mixed $value + * + * @dataProvider provideHex + */ + public function testJsonSerialize($value, string $expected): void + { + $hexadecimal = new Hexadecimal($value); + $expectedJson = sprintf('"%s"', $expected); + + $this->assertSame($expectedJson, json_encode($hexadecimal)); + } } diff --git a/tests/Type/IntegerTest.php b/tests/Type/IntegerTest.php index 3c4dac7..d2c2cbb 100644 --- a/tests/Type/IntegerTest.php +++ b/tests/Type/IntegerTest.php @@ -8,6 +8,11 @@ use Ramsey\Uuid\Exception\InvalidArgumentException; use Ramsey\Uuid\Test\TestCase; use Ramsey\Uuid\Type\Integer as IntegerObject; +use function json_encode; +use function serialize; +use function sprintf; +use function unserialize; + class IntegerTest extends TestCase { /** @@ -163,4 +168,31 @@ class IntegerTest extends TestCase ['foobar'], ]; } + + /** + * @param mixed $value + * + * @dataProvider provideInteger + */ + public function testSerializeUnserializeInteger($value, string $expected): void + { + $integer = new IntegerObject($value); + $serializedInteger = serialize($integer); + $unserializedInteger = unserialize($serializedInteger); + + $this->assertSame($expected, $unserializedInteger->toString()); + } + + /** + * @param mixed $value + * + * @dataProvider provideInteger + */ + public function testJsonSerialize($value, string $expected): void + { + $integer = new IntegerObject($value); + $expectedJson = sprintf('"%s"', $expected); + + $this->assertSame($expectedJson, json_encode($integer)); + } } diff --git a/tests/Type/TimeTest.php b/tests/Type/TimeTest.php index ee8fb97..3fbba6e 100644 --- a/tests/Type/TimeTest.php +++ b/tests/Type/TimeTest.php @@ -4,9 +4,14 @@ declare(strict_types=1); namespace Ramsey\Uuid\Test\Type; +use Ramsey\Uuid\Exception\UnsupportedOperationException; use Ramsey\Uuid\Test\TestCase; use Ramsey\Uuid\Type\Time; +use function json_encode; +use function serialize; +use function unserialize; + class TimeTest extends TestCase { /** @@ -55,4 +60,64 @@ class TimeTest extends TestCase ], ]; } + + /** + * @param int|float|string $seconds + * @param int|float|string|null $microSeconds + * + * @dataProvider provideTimeValues + */ + public function testSerializeUnserializeTime($seconds, $microSeconds): void + { + $params = [$seconds]; + if ($microSeconds !== null) { + $params[] = $microSeconds; + } + + $time = new Time(...$params); + $serializedTime = serialize($time); + $unserializedTime = unserialize($serializedTime); + + $this->assertSame((string) $seconds, $unserializedTime->getSeconds()->toString()); + + $this->assertSame( + (string) $microSeconds ?: '0', + $unserializedTime->getMicroSeconds()->toString() + ); + } + + public function testUnserializeOfInvalidValueException(): void + { + $invalidSerialization = 'C:21:"Ramsey\\Uuid\\Type\\Time":13:{{"foo":"bar"}}'; + + $this->expectException(UnsupportedOperationException::class); + $this->expectExceptionMessage('Attempted to unserialize an invalid value'); + + unserialize($invalidSerialization); + } + + /** + * @param int|float|string $seconds + * @param int|float|string|null $microSeconds + * + * @dataProvider provideTimeValues + */ + public function testJsonSerialize($seconds, $microSeconds): void + { + $time = [ + 'seconds' => (string) $seconds, + 'microseconds' => (string) $microSeconds ?: '0', + ]; + + $expectedJson = json_encode($time); + + $params = [$seconds]; + if ($microSeconds !== null) { + $params[] = $microSeconds; + } + + $time = new Time(...$params); + + $this->assertSame($expectedJson, json_encode($time)); + } }