1 <?php # vim:ts=2:sw=2:noet:
2 /* For licensing and copyright terms, see the file named LICENSE */
3 /* Copyright (c) 2007, OmniTI Computer Consulting, Inc.
8 * A class for working with RFC 4122 UUIDs
10 class OmniTI_Util_UUID {
13 function __construct($src = null) {
15 switch (strlen($src)) {
16 case 36: /* with -'s */
17 $src = str_replace('-', '', $src);
18 case 32: /* with -'s stripped */
19 $this->binary = pack('H*', $src);
21 case 16: /* binary string */
24 case 24: /* base64 encoded binary */
25 $this->binary = base64_decode(
40 * returns a 32-bit integer that identifies this host.
41 * The node identifier needs to be unique among nodes
42 * in a cluster for a given application in order to
43 * avoid collisions between generated identifiers.
44 * You may extend and override this method if you
45 * want to substitute an alternative means of determining
46 * the node identifier */
47 protected function getNodeId() {
48 if (isset($_SERVER['SERVER_ADDR'])) {
49 $node = ip2long($_SERVER['SERVER_ADDR']);
51 /* running from the CLI most likely;
52 * inspect the environment to see if we can
53 * deduce the hostname, and from there, the
55 static $names = array('HOSTNAME', 'HOST');
56 foreach ($names as $name) {
57 if (isset($_ENV[$name])) {
60 $host = getenv($name);
62 if (strlen($host)) break;
66 $node = ip2long('127.0.0.1');
68 $ip = gethostbyname($host);
81 * returns a process identifier.
82 * In multi-process servers, this should be the system process ID.
83 * In multi-threaded servers, this should be some unique ID to
84 * prevent two threads from generating precisely the same UUID
87 protected function getLockId() {
88 if (function_exists('zend_thread_id')) {
89 return zend_thread_id();
95 * generate an RFC 4122 UUID.
96 * This is psuedo-random UUID influenced by the system clock, IP
97 * address and process ID.
99 * The intended use is to generate an identifier that can uniquely
100 * identify user generated posts, comments etc. made to a website.
101 * This generation process should be sufficient to avoid collisions
102 * between nodes in a cluster, and between apache children on the
106 function generate() {
107 $node = $this->getNodeId();
108 $pid = $this->getLockId();
110 list($time_mid, $time_lo) = explode(' ', microtime());
111 $time_lo = (int)$time_lo;
112 $time_mid = (int)substr($time_mid, 2);
114 $time_hi = mt_rand(0, 0xfff);
118 $clock_lo = mt_rand(0, 0xff);
121 /* type is psuedo-random */
122 $clock_hi = mt_rand(0, 0x3f);
125 $this->binary = pack('NnnCCnN',
126 $time_lo, $time_mid & 0xffff, $time_hi,
127 $clock_hi, $clock_lo, $node_lo, $node);
131 * render the UUID as an RFC4122 standard string representation
132 * of the binary bits.
134 function toRFC4122String($dashes = true) {
135 $uuid = unpack('Ntl/ntm/nth/Cch/Ccl/nnl/Nn', $this->binary);
137 "%08x-%04x-%04x-%02x%02x-%04x%08x" :
138 "%08x%04x%04x%02x%02x%04x%08x";
140 $uuid['tl'], $uuid['tm'], $uuid['th'],
141 $uuid['ch'], $uuid['cl'], $uuid['nl'], $uuid['n']);
145 * render the UUID using a modified base64 representation
146 * of the binary bits. This string is shorter than the standard
147 * representation, but is not part of any standard specification.
149 function toShortString() {
151 array('=', '/', '+'),
152 array('@', '-', '_'),
153 base64_encode($this->binary));