diff --git a/includes/uuid.inc b/includes/uuid.inc new file mode 100644 index 0000000..4caf2a4 --- /dev/null +++ b/includes/uuid.inc @@ -0,0 +1,111 @@ +plugin = new $class(); + } + + /** + * Generates an universally unique identifier. + * + * @see UuidInterface::generate() + */ + public function generate() { + return $this->plugin->generate(); + } + + /** + * Check that a string appears to be in the format of an uuid. + * + * Plugins should not implement validation, since UUIDs should be in a + * consistent format across all plugins. + * + * @param $uuid + * The string to test. + * @return + * TRUE if the string is well formed. + */ + public function isValid($uuid) { + return preg_match("/^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/", $uuid); + } +} + +/** + * UUID implementation using the PECL extension. + */ +class UuidPecl implements UuidInterface { + public function generate() { + return uuid_create(UUID_TYPE_DEFAULT); + } +} + +/** + * UUID implementation using the Windows internal GUID extension. + * + * @see http://php.net/com_create_guid + */ +class UuidCom implements UuidInterface { + public function generate() { + // Remove {} wrapper and make lower case to keep result consistent. + return drupal_strtolower(trim(com_create_guid(), '{}')); + } +} + +/** + * Generates an uuid v4 using PHP code. + * + * @see http://php.net/uniqid + */ +class UuidPhp implements UuidInterface { + public function generate() { + // The field names refer to RFC 4122 section 4.1.2. + return sprintf('%04x%04x-%04x-%03x4-%04x-%04x%04x%04x', + // 32 bits for "time_low". + mt_rand(0, 65535), mt_rand(0, 65535), + // 16 bits for "time_mid". + mt_rand(0, 65535), + // 12 bits before the 0100 of (version) 4 for + // "time_hi_and_version". + mt_rand(0, 4095), + bindec(substr_replace(sprintf('%016b', mt_rand(0, 65535)), '01', 6, 2)), + // 8 bits, the last two of which (positions 6 and 7) are 01, for + // "clk_seq_hi_res" (hence, the 2nd hex digit after the 3rd hyphen can + // only be 1, 5, 9 or d) 8 bits for "clk_seq_low" 48 bits for "node". + mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535) + ); + } +} diff --git a/modules/system/system.test b/modules/system/system.test index 9944619..0e293bc 100644 --- a/modules/system/system.test +++ b/modules/system/system.test @@ -2466,3 +2466,43 @@ class SystemIndexPhpTest extends DrupalWebTestCase { } } +/** + * Tests uuid.inc and related functions. + */ +class UuidTestCase extends DrupalWebTestCase { + public static function getInfo() { + return array( + 'name' => 'UUID handling', + 'description' => "Test the handling of universally unique identifiers.", + 'group' => 'System', + ); + } + + /** + * Test UUID handling. + */ + function testUuidHandling() { + // Initiate the generator. This will lazy-load uuid.inc. + $uuid = new Uuid(); + + // This is a valid UUID, we know that. + $valid_uuid = '0ab26e6b-f074-4e44-9da6-1205fa0e9761'; + $invalid_uuid1 = '0ab26e6b-f074-4e44-9da6-1205fa0e976'; + $invalid_uuid2 = '0ab26e6b-f074-4e44-9da-1205fa0e9761'; + // Test the uuid_is_valid() function. + $test = ( + $uuid->isValid($valid_uuid) + && !$uuid->isValid($invalid_uuid1) + && !$uuid->isValid($invalid_uuid2) + ); + $this->assertTrue($test, 'UUID validation works.'); + + // Test generating an uuid. + $uuid1 = $uuid->generate(); + $this->assertTrue($uuid->isValid($uuid1), 'UUID generation works.'); + + // Just to demonstrate the purpose of the UUID functionality. + $uuid2 = $uuid->generate(); + $this->assertNotEqual($uuid1, $uuid2, 'Same UUID was not generated twice.'); + } +}