diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -6,3 +6,5 @@ * Ronald Ulysses Swanson aka Wes https://twitter.com/WesNetmo + +* Andrew Moore diff --git a/src/Strings/UUID.php b/src/Strings/UUID.php new file mode 100644 --- /dev/null +++ b/src/Strings/UUID.php @@ -0,0 +1,39 @@ +<?php +declare(strict_types=1); + +namespace Keruald\OmniTools\Strings; + +class UUID { + + /** + * @return string A RFC 4122 compliant v4 UUID + */ + public static function UUIDv4 () : string { + // Code by Andrew Moore + // See http://php.net/manual/en/function.uniqid.php#94959 + // https://www.ietf.org/rfc/rfc4122.txt + + return sprintf( + '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', + + // 32 bits for "time_low" + mt_rand(0, 0xffff), mt_rand(0, 0xffff), + + // 16 bits for "time_mid" + mt_rand(0, 0xffff), + + // 16 bits for "time_hi_and_version", + // four most significant bits holds version number 4 + mt_rand(0, 0x0fff) | 0x4000, + + // 16 bits, 8 bits for "clk_seq_hi_res", + // 8 bits for "clk_seq_low", + // two most significant bits holds zero and one for variant DCE1.1 + mt_rand(0, 0x3fff) | 0x8000, + + // 48 bits for "node" + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) + ); + } + +} diff --git a/tests/Strings/UUIDTest.php b/tests/Strings/UUIDTest.php new file mode 100644 --- /dev/null +++ b/tests/Strings/UUIDTest.php @@ -0,0 +1,27 @@ +<?php +declare(strict_types=1); + +namespace Keruald\OmniTools\Tests\Strings; + +use Keruald\OmniTools\Strings\UUID; +use Phpunit\Framework\TestCase; + +class UUIDTest extends TestCase { + + public function testUUIDv4 () : void { + $uuid = UUID::UUIDv4(); + + $this->assertEquals( + 36, strlen($uuid), + "UUID size must be 36 characters." + ); + + $re = "/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/"; + $this->assertRegExp($re, $uuid); + } + + public function testUUIDv4AreUnique () : void { + $this->assertNotEquals(UUID::UUIDv4(), UUID::UUIDv4()); + } + +}