From adc31c54c2cf1701dd1837d20d2811d5fcfef3fb Mon Sep 17 00:00:00 2001 From: Igor Markin Date: Fri, 7 Jun 2024 17:37:31 +0300 Subject: [PATCH] Add tryFromString method --- src/Uuid.php | 28 ++++++++++++++++++++++++++++ tests/ExpectedBehaviorTest.php | 25 +++++++++++++++++++++++++ tests/UuidTest.php | 25 ++++++++++++++++++++++++- 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/Uuid.php b/src/Uuid.php index cce99438..0b61e97a 100644 --- a/src/Uuid.php +++ b/src/Uuid.php @@ -497,6 +497,34 @@ public static function fromString(string $uuid): UuidInterface return self::getFactory()->fromString($uuid); } + /** + * Creates a UUID from the string standard representation if it is not empty + * + * @param ?string $uuid A hexadecimal string or null + * + * @return ?UuidInterface A UuidInterface instance created from a hexadecimal + * string representation or null from invalid string + * + * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants, + * but under constant factory setups, this method operates in functionally pure manners + * @psalm-suppress ImpureStaticProperty we know that the factory being replaced can lead to massive + * havoc across all consumers: that should never happen, and + * is generally to be discouraged. Until the factory is kept + * un-replaced, this method is effectively pure. + */ + public static function tryFromString(?string $uuid): ?UuidInterface + { + if ($uuid === null || $uuid === '') { + return null; + } + + try { + return self::fromString($uuid); + } catch (InvalidArgumentException) { + return null; + } + } + /** * Creates a UUID from a DateTimeInterface instance * diff --git a/tests/ExpectedBehaviorTest.php b/tests/ExpectedBehaviorTest.php index 804239c2..b901d269 100644 --- a/tests/ExpectedBehaviorTest.php +++ b/tests/ExpectedBehaviorTest.php @@ -377,6 +377,31 @@ public function testFromString($string, $version, $variant, $integer) $this->assertSame($bytes, $uuid->getBytes()); } + /** + * @dataProvider provideFromStringInteger + */ + public function testTryFromString($string, $version, $variant, $integer) + { + $bytes = hex2bin(str_replace('-', '', $string)); + + $uuid = Uuid::tryFromString($string); + + $this->assertInstanceOf('Ramsey\Uuid\UuidInterface', $uuid); + $this->assertSame($string, $uuid->toString()); + $this->assertSame($version, $uuid->getVersion()); + $this->assertSame($variant, $uuid->getVariant()); + + $components = explode('-', $string); + + $this->assertSame($components[0], $uuid->getTimeLowHex()); + $this->assertSame($components[1], $uuid->getTimeMidHex()); + $this->assertSame($components[2], $uuid->getTimeHiAndVersionHex()); + $this->assertSame($components[3], $uuid->getClockSeqHiAndReservedHex() . $uuid->getClockSeqLowHex()); + $this->assertSame($components[4], $uuid->getNodeHex()); + $this->assertSame($integer, (string) $uuid->getInteger()); + $this->assertSame($bytes, $uuid->getBytes()); + } + public function provideFromStringInteger() { return [ diff --git a/tests/UuidTest.php b/tests/UuidTest.php index feea5a04..a06c33a4 100644 --- a/tests/UuidTest.php +++ b/tests/UuidTest.php @@ -204,6 +204,29 @@ public function testFromStringWithMaxUuid(): void $this->assertTrue($fields->isMax()); } + public function testTryFromString(): void + { + $this->assertSame( + 'ff6f8cb0-c57d-11e1-9b21-0800200c9a66', + Uuid::tryFromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66')?->toString() + ); + } + + public function testTryFromStringNull(): void + { + $this->assertNull(Uuid::tryFromString(null)); + } + + public function testTryFromStringEmptyString(): void + { + $this->assertNull(Uuid::tryFromString('')); + } + + public function testTryFromStringInvalidString(): void + { + $this->assertNull(Uuid::tryFromString('invalid-string')); + } + public function testGetBytes(): void { $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); @@ -1727,7 +1750,7 @@ public function providePythonTests(): array } /** - * @covers Ramsey\Uuid\Uuid::jsonSerialize + * @covers \Ramsey\Uuid\Uuid::jsonSerialize */ public function testJsonSerialize(): void {