determinePlugin(); $this->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 a 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); } /** * Determines the optimal implementation to use for generating UUIDs. * * The selection is made based on the enabled PHP extensions with the * most performant available option chosen. * * @return * The class name for the optimal UUID generator. */ protected function determinePlugin() { static $plugin; if (!empty($plugin)) { return $plugin; } $plugin = 'UuidPhp'; // Debian/Ubuntu uses the (broken) OSSP extension as their UUID // implementation. The OSSP implementation is not compatible with the // PECL functions. if (function_exists('uuid_create') && !function_exists('uuid_make')) { $plugin = 'UuidPecl'; } // Try to use the COM implementation for Windows users. elseif (function_exists('com_create_guid')) { $plugin = 'UuidCom'; } return $plugin; } } /** * 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. * * Loosely based on Ruby's UUIDTools generate_random logic. * * @see http://uuidtools.rubyforge.org/api/classes/UUIDTools/UUID.html */ class UuidPhp implements UuidInterface { public function generate() { $hex = substr(hash('sha256', drupal_random_bytes(16)), 0, 32); // The field names refer to RFC 4122 section 4.1.2. $time_low = substr($hex, 0, 8); $time_mid = substr($hex, 8, 4); $time_hi_and_version = base_convert(substr($hex, 12, 4), 16, 10); $time_hi_and_version &= 0x0FFF; $time_hi_and_version |= (4 << 12); $clock_seq_hi_and_reserved = base_convert(substr($hex, 16, 4), 16, 10); $clock_seq_hi_and_reserved &= 0x3F; $clock_seq_hi_and_reserved |= 0x80; $clock_seq_low = substr($hex, 20, 2); $nodes = substr($hex, 20); $uuid = sprintf('%s-%s-%04x-%02x%02x-%s', $time_low, $time_mid, $time_hi_and_version, $clock_seq_hi_and_reserved, $clock_seq_low, $nodes); return $uuid; } }