diff --git a/.travis.yml b/.travis.yml index 7de708c..e3b64fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,4 +8,4 @@ before_script: - curl -s http://getcomposer.org/installer | php -- --quiet - php composer.phar install -script: phpunit -c phpunit.dist.xml +script: phpunit -c phpunit.xml.dist diff --git a/README.md b/README.md index 33925c1..ee152f0 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,22 @@ A PHP 5.3+ library for generating and working with [RFC 4122][rfc4122] version Much inspiration for this library came from the [Java][javauuid] and [Python][pyuuid] UUID libraries. +## Requirements + +*Rhumsaa\Uuid works on __64-bit builds__ of PHP 5.3.3+.* + +This library deals with large integers, so you will need to run it on a +64-bit system with a 64-bit compiled version of PHP. + +**Warning:** The [Windows binaries located on PHP.net][phpwin] are 32-bit +versions of PHP. Even if you run them on a 64-bit version of Windows, this +library will not work. You will need to compile PHP on Windows yourself to +build a 64-bit version. + ## Examples ```php $compareTo($uuid2)) { + case -1: + echo "$uuid1 is less than $uuid2"; + break; + case 1: + echo "$uuid1 is greater than $uuid2"; + break; + case 0: + default: + echo "$uuid1 is equal to $uuid2"; + } + +bool **equals($obj)** +Compares this UUID to the specified object and returns `true` if they are equal. + +string **getBytes()** +Returns the UUID as a 16-byte string. + +int **getClockSeqHiAndReserved()** +Returns the high field of the clock sequence multiplexed with the variant +(bits 65-72 of the UUID). + +int **getClockSeqLow()** +Returns the low field of the clock sequence (bits 73-80 of the UUID). + +int **getClockSequence()** +Returns the full clock sequence, including the high and low fields. + +\DateTime **getDateTime()** +For version 1 UUIDs, this returns a PHP DateTime object representing the date +and time used to create the UUID. + +array **getFields()** +Returns an array of the fields of the UUID, with keys named according to the +RFC 4122 names for the fields. + +| Field | Meaning | +| -------------------------- | ------------------------------- | +| time_low | the first 32 bits of the UUID | +| time_mid | the next 16 bits of the UUID | +| time_hi_and_version | the next 16 bits of the UUID | +| clock_seq_hi_and_reserved | the next 8 bits of the UUID | +| clock_seq_low | the next 8 bits of the UUID | +| node | the last 48 bits of the UUID | + +int **getLeastSignificantBits()** +Returns the least significant 64 bits of this UUID's 128 bit value. + +int **getMostSignificantBits()** +Returns the most significant 64 bits of this UUID's 128 bit value. + +int **getNode()** +Returns the node value associated with this UUID. + +int **getTimeHiAndVersion()** +Returns the high field of the timestamp multiplexed with the version number +(bits 49-64 of the UUID). + +int **getTimeLow()** +Returns the low field of the timestamp (the first 32 bits of the UUID). + +int **getTimeMid()** +Returns the middle field of the timestamp (bits 33-48 of the UUID). + +int **getTimestamp()** +For version 1 UUIDs, this returns the 60 bit timestamp value used to create +this UUID. The timestamp is measured in 100-nanosecond units since midnight, +October 15, 1582, UTC. It is not a Unix timestamp. + +string **getUrn()** +Returns the string representation of the UUID as a URN. + +int **getVariant()** +Returns the variant number associated with this UUID. + +The variant number has the following meaning: + +* 0 - Reserved for NCS backward compatibility +* 2 - The RFC 4122 variant (used by this class +* 6 - Reserved, Microsoft Corporation backward compatibility +* 7 - Reserved for future definition + +int **getVersion()** +The version number associated with this UUID. The version number describes how +this UUID was generated. + +The version number has the following meaning: + +* 1 - Time-based UUID +* 2 - DCE security UUID +* 3 - Name-based UUID hashed with MD5 +* 4 - Randomly generated UUID +* 5 - Name-based UUID hashed with SHA-1 + +string **toString()** +Converts this UUID into a string representation. This class also implements +__toString(), which will convert this object to a string when it is used in +any string context. + ## Installation @@ -51,4 +204,5 @@ and install the latest version of the Uuid library into your project: [rfc4122]: http://tools.ietf.org/html/rfc4122 [javauuid]: http://docs.oracle.com/javase/6/docs/api/java/util/UUID.html [pyuuid]: http://docs.python.org/library/uuid.html +[phpwin]: http://windows.php.net/download/ [packagist]: http://packagist.org/ diff --git a/composer.json b/composer.json index 90bc282..24ef289 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "rhumsaa/uuid", - "description": "A PHP 5.3+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", + "description": "A PHP 5.3+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID). Requires a 64-bit build of PHP.", "type": "library", "keywords": ["uuid", "identifier", "guid"], "homepage": "https://github.com/ramsey/uuid", @@ -18,7 +18,14 @@ "require": { "php": ">=5.3.3" }, + "require-dev": { + "doctrine/dbal": ">=2.3" + }, + "suggest": { + "doctrine/dbal": "Allow the use of a UUID as doctrine field type." + }, "autoload": { "psr-0": {"Rhumsaa\\Uuid": "src/"} - } + }, + "minimum-stability": "dev" } diff --git a/phpunit.dist.xml b/phpunit.xml.dist similarity index 100% rename from phpunit.dist.xml rename to phpunit.xml.dist diff --git a/src/Rhumsaa/Uuid/Doctrine/UuidType.php b/src/Rhumsaa/Uuid/Doctrine/UuidType.php new file mode 100644 index 0000000..4c1fc5f --- /dev/null +++ b/src/Rhumsaa/Uuid/Doctrine/UuidType.php @@ -0,0 +1,85 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +namespace Rhumsaa\Uuid\Doctrine; + +use InvalidArgumentException; +use Rhumsaa\Uuid\Uuid; +use Doctrine\DBAL\Types\ConversionException; +use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Field type mapping for the Doctrine Database Abstraction Layer (DBAL). + * + * UUID fields will be stored as a string in the database and converted back to + * the Uuid value object when querying. + */ +class UuidType extends Type +{ + /** + * @var string + */ + const NAME = 'uuid'; + + /** + * @param array $fieldDeclaration + * @param Doctrine\DBAL\Platforms\AbstractPlatform $platform + */ + public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getGuidTypeDeclartionSQL($fieldDeclaration); + } + + /** + * @param string|null $value + * @param Doctrine\DBAL\Platforms\AbstractPlatform $platform + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if (null === $value) { + return null; + } + + try { + $uuid = Uuid::fromString($value); + } catch (InvalidArgumentException $e) { + throw ConversionException::conversionFailed($value, self::NAME); + } + + return $uuid; + } + + /** + * @param Uuid\Uuid|null $value + * @param Doctrine\DBAL\Platforms\AbstractPlatform $platform + */ + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + if (empty($value)) { + return null; + } + + if ($value instanceof Uuid) { + return (string) $value; + } + + throw ConversionException::conversionFailed($value, self::NAME); + } + + /** + * @return string + */ + public function getName() + { + return self::NAME; + } +} diff --git a/src/Rhumsaa/Uuid/Uuid.php b/src/Rhumsaa/Uuid/Uuid.php index 1565842..84815b3 100644 --- a/src/Rhumsaa/Uuid/Uuid.php +++ b/src/Rhumsaa/Uuid/Uuid.php @@ -97,6 +97,13 @@ final class Uuid */ protected function __construct($msb, $lsb) { + if (PHP_INT_SIZE == 4) { + throw new \OverflowException( + 'Attempting to create a UUID on a 32-bit build of PHP. This ' + . 'library requires a 64-bit build of PHP.' + ); + } + $this->msb = $msb; $this->lsb = $lsb; } diff --git a/tests/Rhumsaa/Uuid/Doctrine/UuidTypeTest.php b/tests/Rhumsaa/Uuid/Doctrine/UuidTypeTest.php new file mode 100644 index 0000000..5a67b5c --- /dev/null +++ b/tests/Rhumsaa/Uuid/Doctrine/UuidTypeTest.php @@ -0,0 +1,51 @@ +platform = new MockPlatform(); + $this->type = Type::getType('uuid'); + } + + public function testUuidConvertsToDatabaseValue() + { + $uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66'); + + $expected = $uuid->toString(); + $actual = $this->type->convertToDatabaseValue($uuid, $this->platform); + + $this->assertEquals($expected, $actual); + } + + public function testUuidConvertsToPHPValue() + { + $uuid = $this->type->convertToPHPValue('ff6f8cb0-c57d-11e1-9b21-0800200c9a66', $this->platform); + $this->assertInstanceOf('Rhumsaa\Uuid\Uuid', $uuid); + $this->assertEquals('ff6f8cb0-c57d-11e1-9b21-0800200c9a66', $uuid->toString()); + } + + public function testInvalidUuidConversion() + { + $this->setExpectedException('Doctrine\DBAL\Types\ConversionException'); + $this->type->convertToPHPValue('abcdefg', $this->platform); + } + + public function testNullConversion() + { + $this->assertNull($this->type->convertToPHPValue(null, $this->platform)); + } +} diff --git a/tests/Rhumsaa/Uuid/EnvironmentTest.php b/tests/Rhumsaa/Uuid/EnvironmentTest.php new file mode 100644 index 0000000..f562b5d --- /dev/null +++ b/tests/Rhumsaa/Uuid/EnvironmentTest.php @@ -0,0 +1,30 @@ +setExpectedException( + 'OverflowException', + 'Attempting to create a UUID on a 32-bit build of PHP. This library requires a 64-bit build of PHP.' + ); + + $uuid = Uuid::uuid1(); + + } else { + + $this->markTestSkipped('This test is only applicable on a 32-bit system.'); + + } + } +} diff --git a/tests/Rhumsaa/Uuid/UuidTest.php b/tests/Rhumsaa/Uuid/UuidTest.php index 83e2e0d..0b22a3a 100644 --- a/tests/Rhumsaa/Uuid/UuidTest.php +++ b/tests/Rhumsaa/Uuid/UuidTest.php @@ -3,6 +3,16 @@ namespace Rhumsaa\Uuid; class UuidTest extends \PHPUnit_Framework_TestCase { + protected function setUp() + { + // Skip these tests if run on a 32-bit build of PHP + if (PHP_INT_SIZE == 4) { + $this->markTestSkipped( + 'Running tests on a 32-bit build of PHP; 64-bit build required.' + ); + } + } + /** * @covers Rhumsaa\Uuid\Uuid::fromString * @covers Rhumsaa\Uuid\Uuid::__construct @@ -497,10 +507,10 @@ class UuidTest extends \PHPUnit_Framework_TestCase // The next three UUIDs are used for comparing msb and lsb in // the compareTo() method - // msb are greater than $uuid4, lsb are greater than $uuid5 + // msb are less than $uuid4, lsb are greater than $uuid5 $uuid3 = Uuid::fromString('44cca71e-d13d-11e1-a959-c8bcc8a476f4'); - // msb are less than in $uuid3, lsb are equal to those in $uuid3 + // msb are greater than $uuid3, lsb are equal to those in $uuid3 $uuid4 = Uuid::fromString('44cca71e-d13d-11e2-a959-c8bcc8a476f4'); // msb are equal to those in $uuid3, lsb are less than in $uuid3 diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 19834b8..447d18b 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -9,5 +9,6 @@ if (!file_exists(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'composer.lock')) { } // Include the Composer autoloader -include realpath(dirname(__FILE__) . '/../vendor/autoload.php'); +$loader = include realpath(dirname(__FILE__) . '/../vendor/autoload.php'); +$loader->add("Doctrine\Tests\DBAL", __DIR__."/../vendor/doctrine/dbal/tests");