diff --git a/src/Builder/DefaultUuidBuilder.php b/src/Builder/DefaultUuidBuilder.php new file mode 100644 index 0000000..449e68b --- /dev/null +++ b/src/Builder/DefaultUuidBuilder.php @@ -0,0 +1,24 @@ +converter = $converter; + } + + public function build(Codec $codec, array $fields) + { + return new Uuid($fields, $this->converter, $codec); + } +} diff --git a/src/Builder/DegradedUuidBuilder.php b/src/Builder/DegradedUuidBuilder.php new file mode 100644 index 0000000..8de0218 --- /dev/null +++ b/src/Builder/DegradedUuidBuilder.php @@ -0,0 +1,24 @@ +converter = $converter; + } + + public function build(Codec $codec, array $fields) + { + return new DegradedUuid($fields, $this->converter, $codec); + } +} diff --git a/src/Codec.php b/src/Codec.php index b88db75..9912851 100644 --- a/src/Codec.php +++ b/src/Codec.php @@ -8,7 +8,7 @@ interface Codec public function encodeBinary(UuidInterface $uuid); - public function decode(BigNumberConverter $converter, $encodedUuid); + public function decode($encodedUuid); - public function decodeBytes(BigNumberConverter $converter, $bytes); + public function decodeBytes($bytes); } diff --git a/src/Codec/GuidStringCodec.php b/src/Codec/GuidStringCodec.php index 9da1b47..e290b03 100644 --- a/src/Codec/GuidStringCodec.php +++ b/src/Codec/GuidStringCodec.php @@ -8,15 +8,19 @@ use Rhumsaa\Uuid\UuidInterface; use Rhumsaa\Uuid\Uuid; use Rhumsaa\Uuid\BigNumberConverter; use Rhumsaa\Uuid\UuidFactory; +use Rhumsaa\Uuid\UuidBuilder; class GuidStringCodec implements Codec { - private $factory; + private $builder; - public function __construct(UuidFactory $factory) + private $uuidCodec; + + public function __construct(UuidBuilder $builder, Codec $uuidCodec) { - $this->factory = $factory; + $this->builder = $builder; + $this->uuidCodec = $uuidCodec; } public function encode(UuidInterface $uuid) @@ -39,17 +43,17 @@ class GuidStringCodec implements Codec public function encodeBinary(UuidInterface $uuid) { - $reversed = $this->_decode($uuid->getConverter(), $this->encode($uuid), false); + $reversed = $this->_decode($this->encode($uuid), false); - return (new StringCodec())->encodeBinary($reversed); + return $this->uuidCodec->encodeBinary($reversed); } - public function decode(BigNumberConverter $converter, $encodedUuid) + public function decode($encodedUuid) { - return $this->_decode($converter, $encodedUuid, true); + return $this->_decode($encodedUuid, true); } - public function decodeBytes(BigNumberConverter $converter, $bytes) + public function decodeBytes($bytes) { if (strlen($bytes) !== 16) { throw new InvalidArgumentException('$bytes string should contain 16 characters.'); @@ -57,10 +61,10 @@ class GuidStringCodec implements Codec $hexUuid = unpack('H*', $bytes); - return $this->_decode($converter, $hexUuid[1], false); + return $this->_decode($hexUuid[1], false); } - private function _decode(BigNumberConverter $converter, $hex, $swap) + private function _decode($hex, $swap) { $nameParsed = str_replace(array( 'urn:', @@ -105,6 +109,6 @@ class GuidStringCodec implements Codec 'node' => sprintf('%012s', $components[4]) ); - return $this->factory->uuid($fields, $this); + return $this->builder->build($this, $fields); } } diff --git a/src/Codec/StringCodec.php b/src/Codec/StringCodec.php index 5e9fd43..ce451de 100644 --- a/src/Codec/StringCodec.php +++ b/src/Codec/StringCodec.php @@ -8,15 +8,16 @@ use Rhumsaa\Uuid\UuidInterface; use Rhumsaa\Uuid\Uuid; use Rhumsaa\Uuid\BigNumberConverter; use Rhumsaa\Uuid\UuidFactory; +use Rhumsaa\Uuid\UuidBuilder; class StringCodec implements Codec { - private $factory; + private $builder; - public function __construct(UuidFactory $factory) + public function __construct(UuidBuilder $builder) { - $this->factory = $factory; + $this->builder = $builder; } public function encode(UuidInterface $uuid) @@ -40,7 +41,7 @@ class StringCodec implements Codec return $bytes; } - public function decode(BigNumberConverter $converter, $encodedUuid) + public function decode($encodedUuid) { $nameParsed = str_replace(array( 'urn:', @@ -76,10 +77,10 @@ class StringCodec implements Codec 'node' => sprintf('%012s', $components[4]) ); - return $this->factory->uuid($fields, $this); + return $this->builder->build($this, $fields); } - public function decodeBytes(BigNumberConverter $converter, $bytes) + public function decodeBytes($bytes) { if (strlen($bytes) !== 16) { throw new InvalidArgumentException('$bytes string should contain 16 characters.'); @@ -87,6 +88,6 @@ class StringCodec implements Codec $hexUuid = unpack('H*', $bytes); - return $this->decode($converter, $hexUuid[1]); + return $this->decode($hexUuid[1]); } } diff --git a/src/FeatureSet.php b/src/FeatureSet.php new file mode 100644 index 0000000..7709ad1 --- /dev/null +++ b/src/FeatureSet.php @@ -0,0 +1,171 @@ +disableBigNumber = $forceNoBigNumber; + $this->disable64Bit = $force32Bit; + $this->ignoreSystemNode = $ignoreSystemNode; + + $this->numberConverter = $this->buildNumberConverter(); + $this->builder = $this->buildUuidBuilder(); + $this->codec = $this->buildCodec($useGuids); + $this->nodeProvider = $this->buildNodeProvider(); + $this->randomGenerator = $this->buildRandomGenerator(); + $this->timeConverter = $this->buildTimeConverter(); + $this->timeProvider = new SystemTimeProvider(); + } + + public function getBuilder() + { + return $this->builder; + } + + public function getCodec() + { + return $this->codec; + } + + public function getNodeProvider() + { + return $this->nodeProvider; + } + + public function getNumberConverter() + { + return $this->numberConverter; + } + + public function getRandomGenerator() + { + return $this->randomGenerator; + } + + public function getTimeConverter() + { + return $this->timeConverter; + } + + public function getTimeProvider() + { + return $this->timeProvider; + } + + protected function buildCodec($useGuids = false) + { + if ($useGuids) { + return new GuidStringCodec($this->builder, $this->buildCodec(false)); + } + + return new StringCodec($this->builder); + } + + protected function buildNodeProvider() + { + if ($this->ignoreSystemNode) { + return new RandomNodeProvider(); + } + + return new FallbackNodeProvider([ + new SystemNodeProvider(), + new RandomNodeProvider() + ]); + } + + protected function buildNumberConverter() + { + if ($this->hasBigNumber()) { + return new BigNumberConverter(); + } + + return new DegradedNumberConverter(); + } + + protected function buildRandomGenerator() + { + return (new RandomGeneratorFactory())->getGenerator(); + } + + protected function buildTimeConverter() + { + if ($this->is64BitSystem()) { + return new PhpTimeConverter(); + } + elseif ($this->hasBigNumber()) { + return new BigNumberTimeConverter(); + } + + return new DegradedTimeConverter(); + } + + protected function buildUuidBuilder() + { + if ($this->is64BitSystem()) { + return new DefaultUuidBuilder($this->numberConverter); + } + + return new DegradedUuidBuilder($this->numberConverter); + } + + /** + * Returns true if the system has Moontoast\Math\BigNumber + * + * @return bool + */ + protected function hasBigNumber() + { + return class_exists('Moontoast\Math\BigNumber') && ! $this->disableBigNumber; + } + + /** + * Returns true if the system is 64-bit, false otherwise + * + * @return bool + */ + protected function is64BitSystem() + { + return PHP_INT_SIZE == 8 && ! $this->disable64Bit; + } +} diff --git a/src/Generator/RandomLibAdapter.php b/src/Generator/RandomLibAdapter.php new file mode 100644 index 0000000..8dac106 --- /dev/null +++ b/src/Generator/RandomLibAdapter.php @@ -0,0 +1,27 @@ +generator = $generator; + + if ($this->generator == null) { + $factory = new Factory(); + + $this->generator = $factory->getLowStrengthGenerator(); + } + } + + public function generate($length) + { + return $this->generator->generate($length); + } +} diff --git a/src/Node/FallbackNodeProvider.php b/src/Node/FallbackNodeProvider.php new file mode 100644 index 0000000..947ca9a --- /dev/null +++ b/src/Node/FallbackNodeProvider.php @@ -0,0 +1,26 @@ +nodeProviders = $providers; + } + + public function getNode() + { + foreach ($this->nodeProviders as $provider) { + if ($node = $provider->getNode()) { + return $node; + } + } + + return null; + } +} diff --git a/src/Node/RandomNodeProvider.php b/src/Node/RandomNodeProvider.php new file mode 100644 index 0000000..1c4195c --- /dev/null +++ b/src/Node/RandomNodeProvider.php @@ -0,0 +1,15 @@ +getIfconfig(), $matches, PREG_PATTERN_ORDER)) { + $node = $matches[1][0]; + $node = str_replace(':', '', $node); + $node = str_replace('-', '', $node); + } + + return $node; + } + + /** + * Returns the network interface configuration for the system + * + * @todo Needs evaluation and possibly modification to ensure this works + * well across multiple platforms. + * @codeCoverageIgnore + */ + protected function getIfconfig() + { + switch (strtoupper(substr(php_uname('a'), 0, 3))) { + case 'WIN': + $ifconfig = `ipconfig /all 2>&1`; + break; + case 'DAR': + $ifconfig = `ifconfig 2>&1`; + break; + case 'LIN': + default: + $ifconfig = `netstat -ie 2>&1`; + break; + } + + return $ifconfig; + } +} diff --git a/src/NodeProvider.php b/src/NodeProvider.php new file mode 100644 index 0000000..70f58d2 --- /dev/null +++ b/src/NodeProvider.php @@ -0,0 +1,8 @@ +multiply('10000000'); + + $usec = new \Moontoast\Math\BigNumber($microSeconds); + $usec->multiply('10'); + + $uuidTime->add($sec) + ->add($usec) + ->add('122192928000000000'); + + $uuidTimeHex = sprintf('%016s', $uuidTime->convertToBase(16)); + + return array( + 'low' => substr($uuidTimeHex, 8), + 'mid' => substr($uuidTimeHex, 4, 4), + 'hi' => substr($uuidTimeHex, 0, 4), + ); + } +} diff --git a/src/Time/DegradedTimeConverter.php b/src/Time/DegradedTimeConverter.php new file mode 100644 index 0000000..f64ee30 --- /dev/null +++ b/src/Time/DegradedTimeConverter.php @@ -0,0 +1,18 @@ +fixedTime = $timestamp; + } + + public function setUsec($value) + { + $this->fixedTime['usec'] = $value; + } + + public function setSec($value) + { + $this->fixedTime['sec'] = $value; + } + + public function currentTime() + { + return $this->fixedTime; + } +} diff --git a/src/Time/PhpTimeConverter.php b/src/Time/PhpTimeConverter.php new file mode 100644 index 0000000..5e40540 --- /dev/null +++ b/src/Time/PhpTimeConverter.php @@ -0,0 +1,21 @@ + sprintf('%08x', $uuidTime & 0xffffffff), + 'mid' => sprintf('%04x', ($uuidTime >> 32) & 0xffff), + 'hi' => sprintf('%04x', ($uuidTime >> 48) & 0x0fff), + ); + } +} diff --git a/src/Time/SystemTimeProvider.php b/src/Time/SystemTimeProvider.php new file mode 100644 index 0000000..068ecc9 --- /dev/null +++ b/src/Time/SystemTimeProvider.php @@ -0,0 +1,13 @@ +fromBytes($bytes); } - public static function fromGuidBytes($bytes) - { - return self::getFactory()->fromGuidBytes($bytes); - } - /** * Creates a UUID from the string standard representation as described * in the toString() method. @@ -763,11 +758,6 @@ class Uuid implements UuidInterface, \JsonSerializable return self::getFactory()->fromString($name); } - public static function fromGuidString($name) - { - return self::getFactory()->fromGuidString($name); - } - /** * Creates a UUID from either the UUID as a 128-bit integer string or a Moontoast\Math\BigNumber object. * diff --git a/src/UuidBuilder.php b/src/UuidBuilder.php new file mode 100644 index 0000000..6f777be --- /dev/null +++ b/src/UuidBuilder.php @@ -0,0 +1,8 @@ + sprintf('%08x', $uuidTime & 0xffffffff), - 'mid' => sprintf('%04x', ($uuidTime >> 32) & 0xffff), - 'hi' => sprintf('%04x', ($uuidTime >> 48) & 0x0fff), - ); - } - - if (self::hasBigNumber()) { - - $uuidTime = new \Moontoast\Math\BigNumber('0'); - - $sec = new \Moontoast\Math\BigNumber($sec); - $sec->multiply('10000000'); - - $usec = new \Moontoast\Math\BigNumber($usec); - $usec->multiply('10'); - - $uuidTime->add($sec) - ->add($usec) - ->add('122192928000000000'); - - $uuidTimeHex = sprintf('%016s', $uuidTime->convertToBase(16)); - - return array( - 'low' => substr($uuidTimeHex, 8), - 'mid' => substr($uuidTimeHex, 4, 4), - 'hi' => substr($uuidTimeHex, 0, 4), - ); - } - - throw new Exception\UnsatisfiedDependencyException( - 'When calling ' . __METHOD__ . ' on a 32-bit system, ' - . 'Moontoast\Math\BigNumber must be present in order ' - . 'to generate version 1 UUIDs' - ); - } + private $timeConverter = null; /** - * Get the hardware address as a 48-bit positive integer. If all attempts to - * obtain the hardware address fail, we choose a random 48-bit number with - * its eighth bit set to 1 as recommended in RFC 4122. "Hardware address" - * means the MAC address of a network interface, and on a machine with - * multiple network interfaces the MAC address of any one of them may be - * returned. * - * @return string + * @var TimeProvider */ - protected static function getNodeFromSystem() - { - $node = null; - $pattern = '/[^:]([0-9A-Fa-f]{2}([:-])[0-9A-Fa-f]{2}(\2[0-9A-Fa-f]{2}){4})[^:]/'; - $matches = array(); - - // Search the ifconfig output for all MAC addresses and return - // the first one found - if (preg_match_all($pattern, self::getIfconfig(), $matches, PREG_PATTERN_ORDER)) { - $node = $matches[1][0]; - $node = str_replace(':', '', $node); - $node = str_replace('-', '', $node); - } - - return $node; - } + private $timeProvider = null; /** - * Returns the network interface configuration for the system * - * @todo Needs evaluation and possibly modification to ensure this works - * well across multiple platforms. - * @codeCoverageIgnore + * @var UuidBuilder */ - protected static function getIfconfig() - { - switch (strtoupper(substr(php_uname('a'), 0, 3))) { - case 'WIN': - $ifconfig = `ipconfig /all 2>&1`; - break; - case 'DAR': - $ifconfig = `ifconfig 2>&1`; - break; - case 'LIN': - default: - $ifconfig = `netstat -ie 2>&1`; - break; - } - - return $ifconfig; - } + private $uuidBuilder = null; /** - * Returns true if the system has Moontoast\Math\BigNumber + * Create a new a instance * - * @return bool */ - protected static function hasBigNumber() + public function __construct(FeatureSet $features = null) { - return (class_exists('Moontoast\Math\BigNumber') && !self::$forceNoBigNumber); + $features = $features ?: new FeatureSet(); + + $this->codec = $features->getCodec(); + $this->nodeProvider = $features->getNodeProvider(); + $this->numberConverter = $features->getNumberConverter(); + $this->randomGenerator = $features->getRandomGenerator(); + $this->timeConverter = $features->getTimeConverter(); + $this->timeProvider = $features->getTimeProvider(); + $this->uuidBuilder = $features->getBuilder(); } - /** - * Returns true if the system is 64-bit, false otherwise - * - * @return bool - */ - protected static function is64BitSystem() + public function setTimeConverter(TimeConverter $converter) { - return (PHP_INT_SIZE == 8 && !self::$force32Bit); + $this->timeConverter = $converter; } - - /** - * Generates random bytes for use in version 4 UUIDs - * - * @param int $length - * @return string - */ - private static function generateBytes($length) + public function setTimeProvider(TimeProvider $provider) { - if (! self::$prng) { - self::$prng = (new RandomGeneratorFactory())->getGenerator(); - } - - return self::$prng->generate($length); + $this->timeProvider = $provider; } - private $codec = null; - - public function __construct(Codec $uuidCodec = null, Codec $guidCodec = null) + public function setRandomGenerator(RandomGenerator $generator) { - $this->codec = $uuidCodec ?: new StringCodec($this); - $this->guidCodec = $guidCodec ?: new GuidStringCodec($this); + $this->randomGenerator = $generator; + } + + public function setNodeProvider(NodeProvider $provider) + { + $this->nodeProvider = $provider; + } + + public function setNumberConverter(BigNumberConverter $converter) + { + $this->numberConverter = $converter; + } + + public function setUuidBuilder(UuidBuilder $builder) + { + $this->uuidBuilder = $builder; } /** @@ -203,12 +118,7 @@ class UuidFactory */ public function fromBytes($bytes) { - return $this->codec->decodeBytes($this->getConverter(), $bytes); - } - - public function fromGuidBytes($bytes) - { - return $this->guidCodec->decodeBytes($this->getConverter(), $bytes); + return $this->codec->decodeBytes($bytes); } /** @@ -222,33 +132,17 @@ class UuidFactory */ public function fromString($name) { - return $this->codec->decode($this->getConverter(), $name); - } - - public function fromGuidString($name) - { - return $this->guidCodec->decode($this->getConverter(), $name); + return $this->codec->decode($name); } public function fromInteger($integer) { - $hex = $this->getConverter()->toHex($integer); + $hex = $this->numberConverter->toHex($integer); $hex = str_pad($hex, 32, '0', STR_PAD_LEFT); return $this->fromString($hex); } - public function getConverter() - { - $converter = new BigNumberConverter(); - - if (! self::hasBigNumber()) { - $converter = new DegradedNumberConverter(); - } - - return $converter; - } - /** * Generate a version 1 UUID from a host ID, sequence number, and the current time. * If $node is not given, we will attempt to obtain the local hardware @@ -266,14 +160,8 @@ class UuidFactory */ public function uuid1($node = null, $clockSeq = null) { - if ($node === null && !self::$ignoreSystemNode) { - $node = self::getNodeFromSystem(); - } - - // if $node is still null (couldn't get from system), randomly generate - // a node value, according to RFC 4122, Section 4.5 if ($node === null) { - $node = sprintf('%06x%06x', mt_rand(0, 1 << 24), mt_rand(0, 1 << 24)); + $node = $this->nodeProvider->getNode(); } // Convert the node to hex, if it is still an integer @@ -281,12 +169,12 @@ class UuidFactory $node = sprintf('%012x', $node); } - if (ctype_xdigit($node) && strlen($node) <= 12) { - $node = strtolower(sprintf('%012s', $node)); - } else { + if (! ctype_xdigit($node) || strlen($node) > 12) { throw new \InvalidArgumentException('Invalid node value'); } + $node = strtolower(sprintf('%012s', $node)); + if ($clockSeq === null) { // Not using "stable storage"; see RFC 4122, Section 4.2.1.1 $clockSeq = mt_rand(0, 1 << 14); @@ -294,13 +182,8 @@ class UuidFactory // Create a 60-bit time value as a count of 100-nanosecond intervals // since 00:00:00.00, 15 October 1582 - if (self::$timeOfDayTest === null) { - $timeOfDay = gettimeofday(); - } else { - $timeOfDay = self::$timeOfDayTest; - } - - $uuidTime = self::calculateUuidTime($timeOfDay['sec'], $timeOfDay['usec']); + $timeOfDay = $this->timeProvider->currentTime(); + $uuidTime = $this->timeConverter->calculateTime($timeOfDay['sec'], $timeOfDay['usec']); // Set the version number to 1 $timeHi = hexdec($uuidTime['hi']) & 0x0fff; @@ -336,7 +219,7 @@ class UuidFactory public function uuid3($ns, $name) { if (!($ns instanceof UuidInterface)) { - $ns = $this->codec->decode($this->getConverter(), $ns); + $ns = $this->codec->decode($ns); } $hash = md5($ns->getBytes() . $name); @@ -351,12 +234,13 @@ class UuidFactory */ public function uuid4() { - $bytes = self::generateBytes(16); + $bytes = $this->randomGenerator->generate(16); // When converting the bytes to hex, it turns into a 32-character // hexadecimal string that looks a lot like an MD5 hash, so at this // point, we can just pass it to uuidFromHashedName. $hex = bin2hex($bytes); + return $this->uuidFromHashedName($hex, 4); } @@ -371,7 +255,7 @@ class UuidFactory public function uuid5($ns, $name) { if (!($ns instanceof Uuid)) { - $ns = $this->codec->decode($this->getConverter(), $ns); + $ns = $this->codec->decode($ns); } $hash = sha1($ns->getBytes() . $name); @@ -379,15 +263,9 @@ class UuidFactory return $this->uuidFromHashedName($hash, 5); } - public function uuid(array $fields, Codec $codec = null) + public function uuid(array $fields) { - $codec = $codec ?: $this->codec; - - if (! self::is64BitSystem()) { - return new DegradedUuid($fields, $this->getConverter(), $codec); - } - - return new Uuid($fields, $this->getConverter(), $codec); + return $this->uuidBuilder->build($this->codec, $fields); } /** diff --git a/tests/UuidBcTag1_1_2Test.php b/tests/UuidBcTag1_1_2Test.php index fde737c..60966f1 100644 --- a/tests/UuidBcTag1_1_2Test.php +++ b/tests/UuidBcTag1_1_2Test.php @@ -12,6 +12,8 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase { protected function setUp() { + Uuid::setFactory(new UuidFactory()); + // Skip these tests if run on a 32-bit build of PHP if (PHP_INT_SIZE == 4) { $this->markTestSkipped( @@ -375,7 +377,7 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase */ public function testUuid1WithRandomNode() { - UuidFactory::$ignoreSystemNode = true; + Uuid::setFactory(new UuidFactory(new FeatureSet(false, false, false, true))); $uuid = Uuid::uuid1(); $this->assertInstanceOf('\Rhumsaa\Uuid\Uuid', $uuid); diff --git a/tests/UuidFactoryTest.php b/tests/UuidFactoryTest.php index c53d757..b5ca218 100644 --- a/tests/UuidFactoryTest.php +++ b/tests/UuidFactoryTest.php @@ -15,9 +15,9 @@ class UuidFactoryTest extends TestCase public function testParsesGuidCorrectly() { - $factory = new UuidFactory(); + $factory = new UuidFactory(new FeatureSet(true)); - $uuid = $factory->fromGuidString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); + $uuid = $factory->fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); $this->assertEquals('ff6f8cb0-c57d-11e1-9b21-0800200c9a66', $uuid->toString()); } diff --git a/tests/UuidTest.php b/tests/UuidTest.php index 7858abb..c2f0d6d 100644 --- a/tests/UuidTest.php +++ b/tests/UuidTest.php @@ -2,15 +2,14 @@ namespace Rhumsaa\Uuid; +use Rhumsaa\Uuid\Time\SystemTimeProvider; +use Rhumsaa\Uuid\Time\FixedTimeProvider; + class UuidTest extends TestCase { protected function setUp() { - UuidFactory::$forceNoBigNumber = false; - - UuidFactory::$timeOfDayTest = null; - UuidFactory::$force32Bit = false; - UuidFactory::$ignoreSystemNode = false; + Uuid::setFactory(new UuidFactory()); RandomGeneratorFactory::$forceNoOpensslRandomPseudoBytes = false; } @@ -29,7 +28,10 @@ class UuidTest extends TestCase public function testFromLittleEndianString() { $uuid = Uuid::fromString('b08c6fff-7dc5-e111-9b21-0800200c9a66'); - $guid = Uuid::fromGuidString('b08c6fff-7dc5-e111-9b21-0800200c9a66'); + + Uuid::setFactory(new UuidFactory(new FeatureSet(true))); + + $guid = Uuid::fromString('b08c6fff-7dc5-e111-9b21-0800200c9a66'); $this->assertInstanceOf('\Rhumsaa\Uuid\Uuid', $guid); // UUID's and GUID's share the same textual representation @@ -152,7 +154,7 @@ class UuidTest extends TestCase public function testGetDateTime32Bit() { $this->skipIfNoMoontoastMath(); - UuidFactory::$force32Bit = true; + Uuid::setFactory(new UuidFactory(new FeatureSet(false, true))); // Check a recent date $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); @@ -180,8 +182,7 @@ class UuidTest extends TestCase */ public function testGetDateTimeThrownException() { - UuidFactory::$force32Bit = true; - UuidFactory::$forceNoBigNumber = true; + Uuid::setFactory(new UuidFactory(new FeatureSet(false, true, true))); $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); @@ -227,7 +228,8 @@ class UuidTest extends TestCase */ public function testGetFields32Bit() { - UuidFactory::$force32Bit = true; + Uuid::setFactory(new UuidFactory(new FeatureSet(false, true))); + $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); $fields = $uuid->getFields(); } @@ -266,7 +268,8 @@ class UuidTest extends TestCase */ public function testGetLeastSignificantBitsException() { - UuidFactory::$forceNoBigNumber = true; + Uuid::setFactory(new UuidFactory(new FeatureSet(false, false, true))); + $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); $bn = $uuid->getLeastSignificantBits(); } @@ -295,7 +298,8 @@ class UuidTest extends TestCase */ public function testGetMostSignificantBitsException() { - UuidFactory::$forceNoBigNumber = true; + Uuid::setFactory(new UuidFactory(new FeatureSet(false, false, true))); + $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); $bn = $uuid->getMostSignificantBits(); } @@ -323,7 +327,8 @@ class UuidTest extends TestCase */ public function testGetNode32Bit() { - UuidFactory::$force32Bit = true; + Uuid::setFactory(new UuidFactory(new FeatureSet(false, true))); + $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); $node = $uuid->getNode(); } @@ -367,7 +372,8 @@ class UuidTest extends TestCase */ public function testGetTimeLow32Bit() { - UuidFactory::$force32Bit = true; + Uuid::setFactory(new UuidFactory(new FeatureSet(false, true))); + $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); $timeLow = $uuid->getTimeLow(); } @@ -451,7 +457,8 @@ class UuidTest extends TestCase */ public function testGetTimestamp32Bit() { - UuidFactory::$force32Bit = true; + Uuid::setFactory(new UuidFactory(new FeatureSet(false, true))); + $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); $ts = $uuid->getTimestamp(); } @@ -695,7 +702,7 @@ class UuidTest extends TestCase public function testUuid1WithRandomNode() { - UuidFactory::$ignoreSystemNode = true; + Uuid::setFactory(new UuidFactory(new FeatureSet(false, false, false, true))); $uuid = Uuid::uuid1(); $this->assertInstanceOf('\Rhumsaa\Uuid\Uuid', $uuid); @@ -877,15 +884,15 @@ class UuidTest extends TestCase */ public function testCalculateUuidTime() { - $timeOfDay = array( + $timeOfDay = new FixedTimeProvider(array( 'sec' => 1348845514, 'usec' => 277885, 'minuteswest' => 0, 'dsttime' => 0, - ); + )); // For usec = 277885 - UuidFactory::$timeOfDayTest = $timeOfDay; + Uuid::getFactory()->setTimeProvider($timeOfDay); $uuidA = Uuid::uuid1(0x00007ffffffe, 0x1669); $this->assertEquals('c4dbe7e2-097f-11e2-9669-00007ffffffe', (string) $uuidA); @@ -894,7 +901,7 @@ class UuidTest extends TestCase $this->assertEquals('11e2', $uuidA->getTimeHiAndVersionHex()); // For usec = 0 - UuidFactory::$timeOfDayTest['usec'] = 0; + $timeOfDay->setUsec(0); $uuidB = Uuid::uuid1(0x00007ffffffe, 0x1669); $this->assertEquals('c4b18100-097f-11e2-9669-00007ffffffe', (string) $uuidB); @@ -903,7 +910,7 @@ class UuidTest extends TestCase $this->assertEquals('11e2', $uuidB->getTimeHiAndVersionHex()); // For usec = 999999 - UuidFactory::$timeOfDayTest['usec'] = 999999; + $timeOfDay->setUsec(999999); $uuidC = Uuid::uuid1(0x00007ffffffe, 0x1669); $this->assertEquals('c54a1776-097f-11e2-9669-00007ffffffe', (string) $uuidC); @@ -917,17 +924,17 @@ class UuidTest extends TestCase public function testCalculateUuidTimeForce32BitPath() { $this->skipIfNoMoontoastMath(); - UuidFactory::$force32Bit = true; + Uuid::setFactory(new UuidFactory(new FeatureSet(false, true))); - $timeOfDay = array( + $timeOfDay = new FixedTimeProvider(array( 'sec' => 1348845514, 'usec' => 277885, 'minuteswest' => 0, 'dsttime' => 0, - ); + )); // For usec = 277885 - UuidFactory::$timeOfDayTest = $timeOfDay; + Uuid::getFactory()->setTimeProvider($timeOfDay); $uuidA = Uuid::uuid1(0x00007ffffffe, 0x1669); $this->assertEquals('c4dbe7e2-097f-11e2-9669-00007ffffffe', (string) $uuidA); @@ -936,7 +943,7 @@ class UuidTest extends TestCase $this->assertEquals('11e2', $uuidA->getTimeHiAndVersionHex()); // For usec = 0 - UuidFactory::$timeOfDayTest['usec'] = 0; + $timeOfDay->setUsec(0); $uuidB = Uuid::uuid1(0x00007ffffffe, 0x1669); $this->assertEquals('c4b18100-097f-11e2-9669-00007ffffffe', (string) $uuidB); @@ -945,7 +952,7 @@ class UuidTest extends TestCase $this->assertEquals('11e2', $uuidB->getTimeHiAndVersionHex()); // For usec = 999999 - UuidFactory::$timeOfDayTest['usec'] = 999999; + $timeOfDay->setUsec(999999); $uuidC = Uuid::uuid1(0x00007ffffffe, 0x1669); $this->assertEquals('c54a1776-097f-11e2-9669-00007ffffffe', (string) $uuidC); @@ -961,14 +968,14 @@ class UuidTest extends TestCase $this->skip64BitTest(); // 5235-03-31T21:20:59+00:00 - $timeOfDay = array( + $timeOfDay = new FixedTimeProvider(array( 'sec' => 103072857659, 'usec' => 999999, 'minuteswest' => 0, 'dsttime' => 0, - ); + )); - UuidFactory::$timeOfDayTest = $timeOfDay; + Uuid::getFactory()->setTimeProvider($timeOfDay); $uuidA = Uuid::uuid1(0x00007ffffffe, 0x1669); $this->assertEquals('ff9785f6-ffff-1fff-9669-00007ffffffe', (string) $uuidA); @@ -977,14 +984,14 @@ class UuidTest extends TestCase $this->assertEquals('1fff', $uuidA->getTimeHiAndVersionHex()); // 1582-10-15T00:00:00+00:00 - $timeOfDay = array( + $timeOfDay = new FixedTimeProvider(array( 'sec' => -12219292800, 'usec' => 0, 'minuteswest' => 0, 'dsttime' => 0, - ); + )); - UuidFactory::$timeOfDayTest = $timeOfDay; + Uuid::getFactory()->setTimeProvider($timeOfDay); $uuidB = Uuid::uuid1(0x00007ffffffe, 0x1669); $this->assertEquals('00000000-0000-1000-9669-00007ffffffe', (string) $uuidB); @@ -1003,17 +1010,17 @@ class UuidTest extends TestCase $this->skipIfNoMoontoastMath(); $this->skip64BitTest(); - UuidFactory::$force32Bit = true; + Uuid::setFactory(new UuidFactory(new FeatureSet(false, true))); // 5235-03-31T21:20:59+00:00 - $timeOfDay = array( + $timeOfDay = new FixedTimeProvider(array( 'sec' => 103072857659, 'usec' => 999999, 'minuteswest' => 0, 'dsttime' => 0, - ); + )); - UuidFactory::$timeOfDayTest = $timeOfDay; + Uuid::getFactory()->setTimeProvider($timeOfDay); $uuidA = Uuid::uuid1(0x00007ffffffe, 0x1669); $this->assertEquals('ff9785f6-ffff-1fff-9669-00007ffffffe', (string) $uuidA); @@ -1022,14 +1029,14 @@ class UuidTest extends TestCase $this->assertEquals('1fff', $uuidA->getTimeHiAndVersionHex()); // 1582-10-15T00:00:00+00:00 - $timeOfDay = array( + $timeOfDay = new FixedTimeProvider(array( 'sec' => -12219292800, 'usec' => 0, 'minuteswest' => 0, 'dsttime' => 0, - ); + )); - UuidFactory::$timeOfDayTest = $timeOfDay; + Uuid::getFactory()->setTimeProvider($timeOfDay); $uuidB = Uuid::uuid1(0x00007ffffffe, 0x1669); $this->assertEquals('00000000-0000-1000-9669-00007ffffffe', (string) $uuidB); @@ -1043,17 +1050,17 @@ class UuidTest extends TestCase public function testCalculateUuidTimeUpperLowerBounds32Bit() { $this->skipIfNoMoontoastMath(); - UuidFactory::$force32Bit = true; + Uuid::setFactory(new UuidFactory(new FeatureSet(false, true))); // 2038-01-19T03:14:07+00:00 - $timeOfDay = array( + $timeOfDay = new FixedTimeProvider(array( 'sec' => 2147483647, 'usec' => 999999, 'minuteswest' => 0, 'dsttime' => 0, - ); + )); - UuidFactory::$timeOfDayTest = $timeOfDay; + Uuid::getFactory()->setTimeProvider($timeOfDay); $uuidA = Uuid::uuid1(0x00007ffffffe, 0x1669); $this->assertEquals('13813ff6-6912-11fe-9669-00007ffffffe', (string) $uuidA); @@ -1062,14 +1069,14 @@ class UuidTest extends TestCase $this->assertEquals('11fe', $uuidA->getTimeHiAndVersionHex()); // 1901-12-13T20:45:53+00:00 - $timeOfDay = array( + $timeOfDay = new FixedTimeProvider(array( 'sec' => -2147483647, 'usec' => 0, 'minuteswest' => 0, 'dsttime' => 0, - ); + )); - UuidFactory::$timeOfDayTest = $timeOfDay; + Uuid::getFactory()->setTimeProvider($timeOfDay); $uuidB = Uuid::uuid1(0x00007ffffffe, 0x1669); $this->assertEquals('1419d680-d292-1165-9669-00007ffffffe', (string) $uuidB); @@ -1088,14 +1095,14 @@ class UuidTest extends TestCase $this->skip64BitTest(); // 2038-01-19T03:14:07+00:00 - $timeOfDay = array( + $timeOfDay = new FixedTimeProvider(array( 'sec' => 2147483647, 'usec' => 999999, 'minuteswest' => 0, 'dsttime' => 0, - ); + )); - UuidFactory::$timeOfDayTest = $timeOfDay; + Uuid::getFactory()->setTimeProvider($timeOfDay); $uuidA = Uuid::uuid1(0x00007ffffffe, 0x1669); $this->assertEquals('13813ff6-6912-11fe-9669-00007ffffffe', (string) $uuidA); @@ -1104,14 +1111,14 @@ class UuidTest extends TestCase $this->assertEquals('11fe', $uuidA->getTimeHiAndVersionHex()); // 1901-12-13T20:45:53+00:00 - $timeOfDay = array( + $timeOfDay = new FixedTimeProvider(array( 'sec' => -2147483647, 'usec' => 0, 'minuteswest' => 0, 'dsttime' => 0, - ); + )); - UuidFactory::$timeOfDayTest = $timeOfDay; + Uuid::getFactory()->setTimeProvider($timeOfDay); $uuidB = Uuid::uuid1(0x00007ffffffe, 0x1669); $this->assertEquals('1419d680-d292-1165-9669-00007ffffffe', (string) $uuidB); @@ -1132,24 +1139,25 @@ class UuidTest extends TestCase $currentTime = strtotime('2012-12-11T00:00:00+00:00'); $endTime = $currentTime + 3600; + $factory = new UuidFactory(); + $smallIntFactory = new UuidFactory(new FeatureSet(false, true)); + while ($currentTime <= $endTime) { foreach (array(0, 50000, 250000, 500000, 750000, 999999) as $usec) { - $timeOfDay = array( + $timeOfDay = new FixedTimeProvider(array( 'sec' => $currentTime, 'usec' => $usec, 'minuteswest' => 0, 'dsttime' => 0, - ); + )); - UuidFactory::$timeOfDayTest = $timeOfDay; + $factory->setTimeProvider($timeOfDay); + $smallIntFactory->setTimeProvider($timeOfDay); - UuidFactory::$force32Bit = true; - $uuid32 = Uuid::uuid1(0x00007ffffffe, 0x1669); - - UuidFactory::$force32Bit = false; - $uuid64 = Uuid::uuid1(0x00007ffffffe, 0x1669); + $uuid32 = $smallIntFactory->uuid1(0x00007ffffffe, 0x1669); + $uuid64 = $factory->uuid1(0x00007ffffffe, 0x1669); $this->assertTrue( $uuid32->equals($uuid64), @@ -1171,8 +1179,7 @@ class UuidTest extends TestCase */ public function testCalculateUuidTimeThrownException() { - UuidFactory::$force32Bit = true; - UuidFactory::$forceNoBigNumber = true; + Uuid::setFactory(new UuidFactory(new FeatureSet(false, true, true))); $uuid = Uuid::uuid1(0x00007ffffffe, 0x1669); } @@ -1291,16 +1298,18 @@ class UuidTest extends TestCase $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); $bytes = $uuid->getBytes(); - $guid = Uuid::fromGuidBytes($bytes); + Uuid::setFactory(new UuidFactory(new FeatureSet(true))); + + $guid = Uuid::fromBytes($bytes); // First three fields should be reversed $this->assertEquals('b08c6fff-7dc5-e111-9b21-0800200c9a66', $guid->toString()); // Check that parsing LE bytes as LE preserves fields - $guid = Uuid::fromGuidString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); + $guid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); $bytes = $guid->getBytes(); - $parsedGuid = Uuid::fromGuidBytes($bytes); + $parsedGuid = Uuid::fromBytes($bytes); $this->assertEquals($guid->toString(), $parsedGuid->toString()); } @@ -1679,7 +1688,7 @@ class UuidTest extends TestCase */ public function testGetInteger() { - UuidFactory::$forceNoBigNumber = true; + Uuid::setFactory(new UuidFactory(new FeatureSet(false, false, true))); $uuid = Uuid::uuid1(); $uuid->getInteger();