Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /**
- * Guid - class generating/verifying project-wide unique identifiers to be used as IDs in the database
- *
- * @package tools
- * @author Dave Broome <daveb@finda.co.nz>
- * @author Jakub Nesetril <jakub@finda.co.nz>
- * @todo Store guids as integers internally and only display them in URLs as base31
- * @copyright APN Finda, Ltd., 15 December, 2006
- **/
- class Guid {
- /**
- * @var Array List of vowels to be stripped from a GUID
- **/
- protected static $vowels = array('a','e','i','o','u');
- /**
- * @var Array List of consonants replacing vowels
- **/
- protected static $consonants = array('v','w','x','y','z');
- /**
- * @var int Configuration to set up the block of guids fetched at once from DB into memcache
- **/
- protected static $guid_block = 10000;
- /**
- * @var int The wait interval for concurrent synchronisation
- **/
- protected static $wait_interval = 200000;
- /**
- * @return string Base-31 number to be converted to decimal
- * @author Dave Broome <daveb@finda.co.nz>
- * @author Jakub Nesetril <jakub@finda.co.nz>
- * @param int $decimal
- **/
- protected static function decimal_to_modified_base_31($decimal) {
- return str_replace(self::$vowels, self::$consonants, base_convert($decimal, 10, 31));
- }
- /**
- * @return int
- * @author Dave Broome <daveb@finda.co.nz>
- * @author Jakub Nesetril <jakub@finda.co.nz>
- * @param string $base_31 Base-31 number to be converted to decimal
- **/
- protected static function modified_base_31_to_decimal($base_31) {
- return base_convert(str_replace(self::$consonants, self::$vowels, $base_31), 31, 10);
- }
- /**
- * Reserves a block of guids from database and sets up cache records
- *
- * @return int Returns the current valid Guid
- * @author Jakub Nesetril <jakub@finda.co.nz>
- * @todo implement a mutex on the DB fetching, so that two processes don't allocate two blocks
- * @global adodb_distributor $db
- **/
- protected static function seedCache()
- {
- global $db;
- $db->execute("START TRANSACTION");
- $guid_decimal = $db->getOne("SELECT value FROM constant WHERE name = 'next-guid-decimal' FOR UPDATE");
- $db->execute("UPDATE constant SET value = value + ".self::$guid_block." WHERE name = 'next-guid-decimal'");
- $db->execute("COMMIT");
- Cache::set('Guid_maximum', $guid_decimal+self::$guid_block-1, 'Guid');
- Cache::set('Guid_current', $guid_decimal, 'Guid');
- return $guid_decimal;
- }
- /**
- * Verify if a provided value is a valid GUID
- *
- * Checks if candidate contains only allowed alfanumeric characters (no vowels), if it's smaller
- * then the current maximum GUID and if it's bigger then the starting guid (1708)
- *
- * @return bool
- * @author Dave Broome <daveb@finda.co.nz>
- * @author Jakub Nesetril <jakub@finda.co.nz>
- * @param string $spec
- **/
- public static function isGuid($spec) {
- $start = '31';
- // invalid chars
- if (!preg_match('/[0-9b-df-hj-np-tv-z]+/', $spec)) {
- return false;
- }
- $next_guid_decimal = (Cache::exists('Guid_current')) ? Cache::get('Guid_current') : self::seedCache();
- // if proposed guid is more than highest guid or less then lowest guid
- if (self::modified_base_31_to_decimal($spec) > $next_guid_decimal || self::modified_base_31_to_decimal($spec) < $start)
- {
- return false;
- }
- else return true;
- }
- /**
- * Return a freshly generated unique ID
- *
- * @return string
- * @author Dave Broome <daveb@finda.co.nz>
- * @author Jakub Nesetril <jakub@finda.co.nz>
- **/
- public static function getGuid() {
- // find out what the current guid is
- $current = (Cache::exists('Guid_current')) ? Cache::increment('Guid_current') : self::seedCache();
- $maximum = Cache::get('Guid_maximum');
- // if current allocation block of guids has been exhausted, delete the cache
- if ($current >= $maximum) Cache::delete('Guid_current');
- if ($current > $maximum) // if due to some bizzare concurency issue, we have exceeded our maximum and cannot return an overlapping guid
- {
- usleep(self::$wait_interval); // sleep for 0.2 second
- return self::getGuid();
- }
- return self::decimal_to_modified_base_31($current);
- }
- /**
- * Return a unique ID in decimal format
- *
- * @return int
- * @author Jakub Nesetril <jakub@finda.co.nz>
- **/
- public static function getGuidDecimal()
- {
- return self::modified_base_31_to_decimal(self::getGuid());
- }
- }
- ?>
Add Comment
Please, Sign In to add comment