Merge pull request #39 from aztech-digital/refactoring

Refactoring for new 3.0 architecture
This commit is contained in:
Ben Ramsey
2014-12-03 08:22:06 -06:00
50 changed files with 1891 additions and 865 deletions
+1
View File
@@ -3,4 +3,5 @@
/.travis.yml export-ignore
/tests export-ignore
/phpunit.xml.dist export-ignore
/phpcs.xml export-ignore
/apigen.neon export-ignore
+3 -1
View File
@@ -10,6 +10,8 @@ before_script:
- composer self-update
- composer install --dev --prefer-source
script: ./vendor/bin/phpunit --coverage-text --coverage-clover ./build/logs/clover.xml
script:
- ./vendor/bin/phpunit --coverage-text --coverage-clover ./build/logs/clover.xml
- ./vendor/bin/phpcs --standard=phpcs.xml ./
after_script: php vendor/bin/coveralls
+3
View File
@@ -24,14 +24,17 @@
},
"require-dev": {
"moontoast/math": "~1.1",
"ircmaxell/random-lib": "~1.0",
"symfony/console": "~2.3",
"doctrine/dbal": ">=2.3",
"phpunit/phpunit": "~4.1",
"squizlabs/php_codesniffer": "2.0.0RC4",
"satooshi/php-coveralls": "~0.6"
},
"bin": ["bin/uuid"],
"suggest": {
"moontoast/math": "Support for converting UUID to 128-bit integer (in string form).",
"ircmaxell/random-lib": "Provides RandomLib to use with the RandomLibAdapter",
"symfony/console": "Support for use of the bin/uuid command line tool.",
"doctrine/dbal": "Allow the use of a UUID as doctrine field type."
},
+15
View File
@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<ruleset name="Rhumsaa\Uuid Standard">
<description>Coding standard rules for Rhumsaa\Uuid</description>
<exclude-pattern>*/build/*</exclude-pattern>
<exclude-pattern>*/tests/*</exclude-pattern>
<exclude-pattern>*/vendor/*</exclude-pattern>
<arg name="extensions" value="php"/>
<arg value="p"/>
<rule ref="PSR2"/>
</ruleset>
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace Rhumsaa\Uuid\Builder;
use Rhumsaa\Uuid\Converter\NumberConverterInterface;
use Rhumsaa\Uuid\CodecInterface;
use Rhumsaa\Uuid\Uuid;
use Rhumsaa\Uuid\UuidBuilder;
class DefaultUuidBuilder implements UuidBuilder
{
private $converter;
public function __construct(NumberConverterInterface $converter)
{
$this->converter = $converter;
}
public function build(CodecInterface $codec, array $fields)
{
return new Uuid($fields, $this->converter, $codec);
}
}
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace Rhumsaa\Uuid\Builder;
use Rhumsaa\Uuid\UuidBuilder;
use Rhumsaa\Uuid\CodecInterface;
use Rhumsaa\Uuid\DegradedUuid;
use Rhumsaa\Uuid\Converter\NumberConverterInterface;
class DegradedUuidBuilder implements UuidBuilder
{
private $converter;
public function __construct(NumberConverterInterface $converter)
{
$this->converter = $converter;
}
public function build(CodecInterface $codec, array $fields)
{
return new DegradedUuid($fields, $this->converter, $codec);
}
}
+55
View File
@@ -0,0 +1,55 @@
<?php
namespace Rhumsaa\Uuid\Codec;
use Rhumsaa\Uuid\UuidInterface;
use Rhumsaa\Uuid\Uuid;
use Rhumsaa\Uuid\CodecInterface;
class GuidStringCodec extends StringCodec
{
public function encode(UuidInterface $uuid)
{
$components = array_values($uuid->getFieldsHex());
// Swap byte-order on the first three fields
$this->swapFields($components);
return vsprintf(
'%08s-%04s-%04s-%02s%02s-%012s',
$components
);
}
public function encodeBinary(UuidInterface $uuid)
{
$components = array_values($uuid->getFieldsHex());
return hex2bin(implode('', $components));
}
public function decode($encodedUuid)
{
$components = $this->extractComponents($encodedUuid);
$this->swapFields($components);
return $this->getBuilder()->build($this, $this->getFields($components));
}
public function decodeBytes($bytes)
{
return parent::decode(bin2hex($bytes));
}
protected function swapFields(array & $components)
{
$hex = unpack('H*', pack('V', hexdec($components[0])));
$components[0] = $hex[1];
$hex = unpack('H*', pack('v', hexdec($components[1])));
$components[1] = $hex[1];
$hex = unpack('H*', pack('v', hexdec($components[2])));
$components[2] = $hex[1];
}
}
+101
View File
@@ -0,0 +1,101 @@
<?php
namespace Rhumsaa\Uuid\Codec;
use InvalidArgumentException;
use Rhumsaa\Uuid\CodecInterface;
use Rhumsaa\Uuid\Uuid;
use Rhumsaa\Uuid\UuidBuilder;
use Rhumsaa\Uuid\UuidInterface;
class StringCodec implements CodecInterface
{
private $builder;
public function __construct(UuidBuilder $builder)
{
$this->builder = $builder;
}
public function encode(UuidInterface $uuid)
{
$fields = array_values($uuid->getFieldsHex());
return vsprintf(
'%08s-%04s-%04s-%02s%02s-%012s',
$fields
);
}
public function encodeBinary(UuidInterface $uuid)
{
return hex2bin($uuid->getHex());
}
public function decode($encodedUuid)
{
$components = $this->extractComponents($encodedUuid);
$fields = $this->getFields($components);
return $this->builder->build($this, $fields);
}
public function decodeBytes($bytes)
{
if (strlen($bytes) !== 16) {
throw new InvalidArgumentException('$bytes string should contain 16 characters.');
}
$hexUuid = unpack('H*', $bytes);
return $this->decode($hexUuid[1]);
}
protected function getBuilder()
{
return $this->builder;
}
protected function extractComponents($encodedUuid)
{
$nameParsed = str_replace(array(
'urn:',
'uuid:',
'{',
'}',
'-'
), '', $encodedUuid);
// We have stripped out the dashes and are breaking up the string using
// substr(). In this way, we can accept a full hex value that doesn't
// contain dashes.
$components = array(
substr($nameParsed, 0, 8),
substr($nameParsed, 8, 4),
substr($nameParsed, 12, 4),
substr($nameParsed, 16, 4),
substr($nameParsed, 20)
);
$nameParsed = implode('-', $components);
if (! Uuid::isValid($nameParsed)) {
throw new InvalidArgumentException('Invalid UUID string: ' . $encodedUuid);
}
return $components;
}
protected function getFields(array $components)
{
return array(
'time_low' => sprintf('%08s', $components[0]),
'time_mid' => sprintf('%04s', $components[1]),
'time_hi_and_version' => sprintf('%04s', $components[2]),
'clock_seq_hi_and_reserved' => sprintf('%02s', substr($components[3], 0, 2)),
'clock_seq_low' => sprintf('%02s', substr($components[3], 2)),
'node' => sprintf('%012s', $components[4])
);
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace Rhumsaa\Uuid;
interface CodecInterface
{
/**
* @return string
*/
public function encode(UuidInterface $uuid);
/**
* @return string
*/
public function encodeBinary(UuidInterface $uuid);
/**
* @return UuidInterface
*/
public function decode($encodedUuid);
/**
* @param string $bytes
* @return UuidInterface
*/
public function decodeBytes($bytes);
}
+3 -61
View File
@@ -15,10 +15,11 @@ use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\TableHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Rhumsaa\Uuid\Console\Exception;
use Rhumsaa\Uuid\Uuid;
use Rhumsaa\Uuid\Console\Util\UuidFormatter;
use Symfony\Component\Console\Helper\Table;
/**
* Provides the console command to decode UUIDs and dump information about them
@@ -58,66 +59,7 @@ class DecodeCommand extends Command
$table = $this->getHelperSet()->get('table');
$table->setLayout(TableHelper::LAYOUT_BORDERLESS);
$table->addRows(array(
array('encode:', 'STR:', (string) $uuid),
array('', 'INT:', (string) $uuid->getInteger()),
));
if ($uuid->getVariant() != Uuid::RFC_4122) {
$table->addRows(array(
array('decode:', 'variant:', 'Not an RFC 4122 UUID'),
));
$table->render($output);
return;
}
switch ($uuid->getVersion()) {
case 1:
$version = '1 (time and node based)';
break;
case 2:
$version = '2 (DCE security based)';
break;
case 3:
$version = '3 (name based, MD5)';
break;
case 4:
$version = '4 (random data based)';
break;
case 5:
$version = '5 (name based, SHA-1)';
break;
}
$table->addRows(array(
array('decode:', 'variant:', 'RFC 4122'),
array('', 'version:', $version),
));
if ($uuid->getVersion() == 1) {
$table->addRows(array(
array('', 'content:', 'time: ' . $uuid->getDateTime()->format('c')),
array('', '', 'clock: ' . $uuid->getClockSequence() . ' (usually random)'),
array('', '', 'node: ' . substr(chunk_split($uuid->getNodeHex(), 2, ':'), 0, -1)),
));
}
if ($uuid->getVersion() == 4) {
$table->addRows(array(
array('', 'content:', substr(chunk_split($uuid->getHex(), 2, ':'), 0, -1)),
array('', '', '(no semantics: random data only)'),
));
}
if ($uuid->getVersion() == 3 || $uuid->getVersion() == 5) {
$table->addRows(array(
array('', 'content:', substr(chunk_split($uuid->getHex(), 2, ':'), 0, -1)),
array('', '', '(not decipherable: MD5 message digest only)'),
));
}
(new UuidFormatter())->write($table, $uuid);
$table->render($output);
}
+4 -2
View File
@@ -159,9 +159,11 @@ class GenerateCommand extends Command
return $namespace;
}
throw new Exception('Invalid namespace. '
throw new Exception(
'Invalid namespace. '
. 'May be either a UUID in string representation or an identifier '
. 'for internally pre-defined namespace UUIDs (currently known '
. 'are "ns:DNS", "ns:URL", "ns:OID", and "ns:X500").');
. 'are "ns:DNS", "ns:URL", "ns:OID", and "ns:X500").'
);
}
}
@@ -0,0 +1,19 @@
<?php
namespace Rhumsaa\Uuid\Console\Util\Formatter;
use Rhumsaa\Uuid\Console\Util\UuidFormatter;
use Rhumsaa\Uuid\UuidInterface;
use Rhumsaa\Uuid\Console\Util\UuidContentFormatterInterface;
class V1Formatter implements UuidContentFormatterInterface
{
public function getContent(UuidInterface $uuid)
{
return array(
array('', 'content:', 'time: ' . $uuid->getDateTime()->format('c')),
array('', '', 'clock: ' . $uuid->getClockSequence() . ' (usually random)'),
array('', '', 'node: ' . substr(chunk_split($uuid->getNodeHex(), 2, ':'), 0, -1)),
);
}
}
@@ -0,0 +1,15 @@
<?php
namespace Rhumsaa\Uuid\Console\Util\Formatter;
use Rhumsaa\Uuid\Console\Util\UuidFormatter;
use Rhumsaa\Uuid\UuidInterface;
use Rhumsaa\Uuid\Console\Util\UuidContentFormatterInterface;
class V2Formatter implements UuidContentFormatterInterface
{
public function getContent(UuidInterface $uuid)
{
return array();
}
}
@@ -0,0 +1,18 @@
<?php
namespace Rhumsaa\Uuid\Console\Util\Formatter;
use Rhumsaa\Uuid\Console\Util\UuidFormatter;
use Rhumsaa\Uuid\UuidInterface;
use Rhumsaa\Uuid\Console\Util\UuidContentFormatterInterface;
class V3Formatter implements UuidContentFormatterInterface
{
public function getContent(UuidInterface $uuid)
{
return array(
array('', 'content:', substr(chunk_split($uuid->getHex(), 2, ':'), 0, -1)),
array('', '', '(not decipherable: MD5 message digest only)'),
);
}
}
@@ -0,0 +1,18 @@
<?php
namespace Rhumsaa\Uuid\Console\Util\Formatter;
use Rhumsaa\Uuid\Console\Util\UuidFormatter;
use Rhumsaa\Uuid\UuidInterface;
use Rhumsaa\Uuid\Console\Util\UuidContentFormatterInterface;
class V4Formatter implements UuidContentFormatterInterface
{
public function getContent(UuidInterface $uuid)
{
return array(
array('', 'content:', substr(chunk_split($uuid->getHex(), 2, ':'), 0, -1)),
array('', '', '(no semantics: random data only)'),
);
}
}
@@ -0,0 +1,18 @@
<?php
namespace Rhumsaa\Uuid\Console\Util\Formatter;
use Rhumsaa\Uuid\Console\Util\UuidFormatter;
use Rhumsaa\Uuid\UuidInterface;
use Rhumsaa\Uuid\Console\Util\UuidContentFormatterInterface;
class V5Formatter implements UuidContentFormatterInterface
{
public function getContent(UuidInterface $uuid)
{
return array(
array('', 'content:', substr(chunk_split($uuid->getHex(), 2, ':'), 0, -1)),
array('', '', '(not decipherable: SHA1 message digest only)'),
);
}
}
@@ -0,0 +1,10 @@
<?php
namespace Rhumsaa\Uuid\Console\Util;
use Rhumsaa\Uuid\UuidInterface;
interface UuidContentFormatterInterface
{
public function getContent(UuidInterface $uuid);
}
+87
View File
@@ -0,0 +1,87 @@
<?php
namespace Rhumsaa\Uuid\Console\Util;
use Rhumsaa\Uuid\Uuid;
use Rhumsaa\Uuid\UuidInterface;
use Rhumsaa\Uuid\Console\Util\Formatter\V1Formatter;
use Rhumsaa\Uuid\Console\Util\Formatter\V2Formatter;
use Rhumsaa\Uuid\Console\Util\Formatter\V3Formatter;
use Rhumsaa\Uuid\Console\Util\Formatter\V4Formatter;
use Rhumsaa\Uuid\Console\Util\Formatter\V5Formatter;
use Symfony\Component\Console\Helper\TableHelper;
class UuidFormatter
{
private static $versionMap = [
1 => '1 (time and node based)',
2 => '2 (DCE security based)',
3 => '3 (name based, MD5)',
4 => '4 (random data based)',
5 => '5 (name based, SHA-1)'
];
private static $variantMap = [
Uuid::RESERVED_NCS => 'Reserved',
Uuid::RFC_4122 => 'RFC 4122',
Uuid::RESERVED_MICROSOFT => 'Reserved for Microsoft use.',
Uuid::RESERVED_FUTURE => 'Reserved for future use.'
];
private static $formatters;
public function __construct()
{
if (self::$formatters == null) {
self::$formatters = [
1 => new V1Formatter(),
2 => new V2Formatter(),
3 => new V3Formatter(),
4 => new V4Formatter(),
5 => new V5Formatter()
];
}
}
public function write(TableHelper $table, UuidInterface $uuid)
{
$table->addRows(array(
array('encode:', 'STR:', (string) $uuid),
array('', 'INT:', (string) $uuid->getInteger()),
));
if ($uuid->getVariant() == Uuid::RFC_4122) {
$table->addRows(array(
array('decode:', 'variant:',$this->getFormattedVariant($uuid)),
array('', 'version:', $this->getFormattedVersion($uuid)),
));
$table->addRows($this->getContent($uuid));
} else {
$table->addRows(array(
array('decode:', 'variant:', 'Not an RFC 4122 UUID'),
));
}
}
public function getFormattedVersion(UuidInterface $uuid)
{
return self::$versionMap[$uuid->getVersion()];
}
public function getFormattedVariant(UuidInterface $uuid)
{
return self::$variantMap[$uuid->getVariant()];
}
/**
* Returns content as an array of rows, each row being an array containing column values.
*/
public function getContent(UuidInterface $uuid)
{
$formatter = self::$formatters[$uuid->getVersion()];
return $formatter->getContent($uuid);
}
}
@@ -0,0 +1,27 @@
<?php
namespace Rhumsaa\Uuid\Converter\Number;
use Rhumsaa\Uuid\Converter\NumberConverterInterface;
class BigNumberConverter implements NumberConverterInterface
{
/**
* @param string $hex
*/
public function fromHex($hex)
{
$number = \Moontoast\Math\BigNumber::baseConvert($hex, 16, 10);
return new \Moontoast\Math\BigNumber($number);
}
public function toHex($integer)
{
if (!$integer instanceof \Moontoast\Math\BigNumber) {
$integer = new \Moontoast\Math\BigNumber($integer);
}
return \Moontoast\Math\BigNumber::baseConvert($integer, 10, 16);
}
}
@@ -0,0 +1,28 @@
<?php
namespace Rhumsaa\Uuid\Converter\Number;
use Rhumsaa\Uuid\Exception\UnsatisfiedDependencyException;
use Rhumsaa\Uuid\Converter\NumberConverterInterface;
class DegradedNumberConverter implements NumberConverterInterface
{
public function fromHex($hex)
{
throw new UnsatisfiedDependencyException(
'Cannot call ' . __METHOD__ . ' without support for large '
. 'integers, since integer is an unsigned '
. '128-bit integer; Moontoast\Math\BigNumber is required.'
. '; consider calling an hex based method instead'
);
}
public function toHex($integer)
{
throw new UnsatisfiedDependencyException(
'Cannot call ' . __METHOD__ . ' without support for large '
. 'integers, since integer is an unsigned '
. '128-bit integer; Moontoast\Math\BigNumber is required. '
);
}
}
@@ -0,0 +1,10 @@
<?php
namespace Rhumsaa\Uuid\Converter;
interface NumberConverterInterface
{
public function fromHex($hex);
public function toHex($integer);
}
@@ -0,0 +1,31 @@
<?php
namespace Rhumsaa\Uuid\Converter\Time;
use Rhumsaa\Uuid\Converter\TimeConverterInterface;
class BigNumberTimeConverter implements TimeConverterInterface
{
public function calculateTime($seconds, $microSeconds)
{
$uuidTime = new \Moontoast\Math\BigNumber('0');
$sec = new \Moontoast\Math\BigNumber($seconds);
$sec->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),
);
}
}
@@ -0,0 +1,18 @@
<?php
namespace Rhumsaa\Uuid\Converter\Time;
use Rhumsaa\Uuid\Converter\TimeConverterInterface;
use Rhumsaa\Uuid\Exception\UnsatisfiedDependencyException;
class DegradedTimeConverter implements TimeConverterInterface
{
public function calculateTime($seconds, $microSeconds)
{
throw new UnsatisfiedDependencyException(
'When calling ' . __METHOD__ . ' on a 32-bit system, '
. 'Moontoast\Math\BigNumber must be present in order '
. 'to generate version 1 UUIDs'
);
}
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace Rhumsaa\Uuid\Converter\Time;
use Rhumsaa\Uuid\Converter\TimeConverterInterface;
class PhpTimeConverter implements TimeConverterInterface
{
public function calculateTime($seconds, $microSeconds)
{
// 0x01b21dd213814000 is the number of 100-ns intervals between the
// UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
$uuidTime = ($seconds * 10000000) + ($microSeconds * 10) + 0x01b21dd213814000;
return array(
'low' => sprintf('%08x', $uuidTime & 0xffffffff),
'mid' => sprintf('%04x', ($uuidTime >> 32) & 0xffff),
'hi' => sprintf('%04x', ($uuidTime >> 48) & 0x0fff),
);
}
}
+16
View File
@@ -0,0 +1,16 @@
<?php
namespace Rhumsaa\Uuid\Converter;
interface TimeConverterInterface
{
/**
* Calculates low, mid, high time array.
*
* @param string $seconds
* @param string $microSeconds
* @return string[] An array guaranteed to contain 'low', 'mid', and 'high' keys.
*/
public function calculateTime($seconds, $microSeconds);
}
+154
View File
@@ -0,0 +1,154 @@
<?php
namespace Rhumsaa\Uuid;
use Rhumsaa\Uuid\Converter\NumberConverterInterface;
class DegradedUuid extends Uuid
{
public function __construct(array $fields, NumberConverterInterface $converter, CodecInterface $codec)
{
parent::__construct($fields, $converter, $codec);
}
/**
* Returns a PHP DateTime object representing the timestamp associated
* with this UUID.
*
* The timestamp value is only meaningful in a time-based UUID, which
* has version type 1. If this UUID is not a time-based UUID then
* this method throws UnsupportedOperationException.
*
* @return \DateTime A PHP DateTime representation of the date
* @throws Exception\UnsupportedOperationException If this UUID is not a version 1 UUID
* @throws Exception\UnsatisfiedDependencyException if called on a 32-bit system and
* Moontoast\Math\BigNumber is not present
*/
public function getDateTime()
{
if ($this->getVersion() != 1) {
throw new Exception\UnsupportedOperationException('Not a time-based UUID');
}
$time = $this->converter->fromHex($this->getTimestampHex());
$ts = new \Moontoast\Math\BigNumber($time, 20);
$ts->subtract('122192928000000000');
$ts->divide('10000000.0');
$ts->round();
$unixTime = $ts->getValue();
return new \DateTime("@{$unixTime}");
}
/**
* Returns an array of the fields of this UUID, with keys named according
* to the RFC 4122 names for the fields.
*
* * **time_low**: The low field of the timestamp, an unsigned 32-bit integer
* * **time_mid**: The middle field of the timestamp, an unsigned 16-bit integer
* * **time_hi_and_version**: The high field of the timestamp multiplexed with
* the version number, an unsigned 16-bit integer
* * **clock_seq_hi_and_reserved**: The high field of the clock sequence
* multiplexed with the variant, an unsigned 8-bit integer
* * **clock_seq_low**: The low field of the clock sequence, an unsigned
* 8-bit integer
* * **node**: The spatially unique node identifier, an unsigned 48-bit
* integer
*
* @return array The UUID fields represented as integer values
* @throws Exception\UnsatisfiedDependencyException if called on a 32-bit system
* @link http://tools.ietf.org/html/rfc4122#section-4.1.2
*/
public function getFields()
{
throw new Exception\UnsatisfiedDependencyException(
'Cannot call ' . __METHOD__ . ' on a 32-bit system, since some '
. 'values overflow the system max integer value'
. '; consider calling getFieldsHex instead'
);
}
/**
* Returns the node value associated with this UUID
*
* For UUID version 1, the node field consists of an IEEE 802 MAC
* address, usually the host address. For systems with multiple IEEE
* 802 addresses, any available one can be used. The lowest addressed
* octet (octet number 10) contains the global/local bit and the
* unicast/multicast bit, and is the first octet of the address
* transmitted on an 802.3 LAN.
*
* For systems with no IEEE address, a randomly or pseudo-randomly
* generated value may be used; see RFC 4122, Section 4.5. The
* multicast bit must be set in such addresses, in order that they
* will never conflict with addresses obtained from network cards.
*
* For UUID version 3 or 5, the node field is a 48-bit value constructed
* from a name as described in RFC 4122, Section 4.3.
*
* For UUID version 4, the node field is a randomly or pseudo-randomly
* generated 48-bit value as described in RFC 4122, Section 4.4.
*
* @return int Unsigned 48-bit integer value of node
* @link http://tools.ietf.org/html/rfc4122#section-4.1.6
* @throws Exception\UnsatisfiedDependencyException if called on a 32-bit system
*/
public function getNode()
{
throw new Exception\UnsatisfiedDependencyException(
'Cannot call ' . __METHOD__ . ' on a 32-bit system, since node '
. 'is an unsigned 48-bit integer and can overflow the system '
. 'max integer value'
. '; consider calling getNodeHex instead'
);
}
/**
* Returns the low field of the timestamp (the first 32 bits of the UUID).
*
* @return int Unsigned 32-bit integer value of time_low
* @throws Exception\UnsatisfiedDependencyException if called on a 32-bit system
*/
public function getTimeLow()
{
throw new Exception\UnsatisfiedDependencyException(
'Cannot call ' . __METHOD__ . ' on a 32-bit system, since time_low '
. 'is an unsigned 32-bit integer and can overflow the system '
. 'max integer value'
. '; consider calling getTimeLowHex instead'
);
}
/**
* The timestamp value associated with this UUID
*
* The 60 bit timestamp value is constructed from the time_low,
* time_mid, and time_hi fields of this UUID. The resulting
* timestamp is measured in 100-nanosecond units since midnight,
* October 15, 1582 UTC.
*
* The timestamp value is only meaningful in a time-based UUID, which
* has version type 1. If this UUID is not a time-based UUID then
* this method throws UnsupportedOperationException.
*
* @return int Unsigned 60-bit integer value of the timestamp
* @throws Exception\UnsupportedOperationException If this UUID is not a version 1 UUID
* @throws Exception\UnsatisfiedDependencyException if called on a 32-bit system
* @link http://tools.ietf.org/html/rfc4122#section-4.1.4
*/
public function getTimestamp()
{
if ($this->getVersion() != 1) {
throw new Exception\UnsupportedOperationException('Not a time-based UUID');
}
throw new Exception\UnsatisfiedDependencyException(
'Cannot call ' . __METHOD__ . ' on a 32-bit system, since timestamp '
. 'is an unsigned 60-bit integer and can overflow the system '
. 'max integer value'
. '; consider calling getTimestampHex instead'
);
}
}
+176
View File
@@ -0,0 +1,176 @@
<?php
namespace Rhumsaa\Uuid;
use Rhumsaa\Uuid\Provider\Node\FallbackNodeProvider;
use Rhumsaa\Uuid\Provider\Node\RandomNodeProvider;
use Rhumsaa\Uuid\Provider\Node\SystemNodeProvider;
use Rhumsaa\Uuid\Converter\Number\BigNumberConverter;
use Rhumsaa\Uuid\Converter\Number\DegradedNumberConverter;
use Rhumsaa\Uuid\Converter\Time\BigNumberTimeConverter;
use Rhumsaa\Uuid\Converter\Time\DegradedTimeConverter;
use Rhumsaa\Uuid\Converter\Time\PhpTimeConverter;
use Rhumsaa\Uuid\Provider\Time\SystemTimeProvider;
use Rhumsaa\Uuid\Builder\DefaultUuidBuilder;
use Rhumsaa\Uuid\Codec\StringCodec;
use Rhumsaa\Uuid\Codec\GuidStringCodec;
use Rhumsaa\Uuid\Builder\DegradedUuidBuilder;
/**
* Detects and exposes available features in current environment (32 or 64 bit, available dependencies...)
*
* @author thibaud
*
*/
class FeatureSet
{
private $disableBigNumber = false;
private $disable64Bit = false;
private $ignoreSystemNode = false;
private $builder;
private $codec;
private $nodeProvider;
private $numberConverter;
private $randomGenerator;
private $timeConverter;
private $timeProvider;
public function __construct(
$useGuids = false,
$force32Bit = false,
$forceNoBigNumber = false,
$ignoreSystemNode = false
) {
$this->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);
}
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;
}
}
+19
View File
@@ -0,0 +1,19 @@
<?php
namespace Rhumsaa\Uuid\Generator;
use Rhumsaa\Uuid\RandomGeneratorInterface;
class MtRandGenerator implements RandomGeneratorInterface
{
public function generate($length)
{
$bytes = '';
for ($i = 1; $i <= $length; $i++) {
$bytes = chr(mt_rand(0, 255)) . $bytes;
}
return $bytes;
}
}
+14
View File
@@ -0,0 +1,14 @@
<?php
namespace Rhumsaa\Uuid\Generator;
use Rhumsaa\Uuid\RandomGeneratorInterface;
class OpenSslGenerator implements RandomGeneratorInterface
{
public function generate($length)
{
return openssl_random_pseudo_bytes($length);
}
}
+28
View File
@@ -0,0 +1,28 @@
<?php
namespace Rhumsaa\Uuid\Generator;
use RandomLib\Generator;
use RandomLib\Factory;
use Rhumsaa\Uuid\RandomGeneratorInterface;
class RandomLibAdapter implements RandomGeneratorInterface
{
private $generator;
public function __construct(Generator $generator = null)
{
$this->generator = $generator;
if ($this->generator == null) {
$factory = new Factory();
$this->generator = $factory->getLowStrengthGenerator();
}
}
public function generate($length)
{
return $this->generator->generate($length);
}
}
@@ -0,0 +1,26 @@
<?php
namespace Rhumsaa\Uuid\Provider\Node;
use Rhumsaa\Uuid\Provider\NodeProviderInterface;
class FallbackNodeProvider implements NodeProviderInterface
{
private $nodeProviders;
public function __construct(array $providers)
{
$this->nodeProviders = $providers;
}
public function getNode()
{
foreach ($this->nodeProviders as $provider) {
if ($node = $provider->getNode()) {
return $node;
}
}
return null;
}
}
+15
View File
@@ -0,0 +1,15 @@
<?php
namespace Rhumsaa\Uuid\Provider\Node;
use Rhumsaa\Uuid\Provider\NodeProviderInterface;
class RandomNodeProvider implements NodeProviderInterface
{
public function getNode()
{
// if $node is still null (couldn't get from system), randomly generate
// a node value, according to RFC 4122, Section 4.5
return sprintf('%06x%06x', mt_rand(0, 1 << 24), mt_rand(0, 1 << 24));
}
}
+51
View File
@@ -0,0 +1,51 @@
<?php
namespace Rhumsaa\Uuid\Provider\Node;
use Rhumsaa\Uuid\Provider\NodeProviderInterface;
class SystemNodeProvider implements NodeProviderInterface
{
public function getNode()
{
$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, $this->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
* @return string
*/
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;
}
}
+8
View File
@@ -0,0 +1,8 @@
<?php
namespace Rhumsaa\Uuid\Provider;
interface NodeProviderInterface
{
public function getNode();
}
+34
View File
@@ -0,0 +1,34 @@
<?php
namespace Rhumsaa\Uuid\Provider\Time;
use Rhumsaa\Uuid\Provider\TimeProviderInterface;
class FixedTimeProvider implements TimeProviderInterface
{
private $fixedTime;
public function __construct(array $timestamp)
{
if (! array_key_exists('sec', $timestamp) || ! array_key_exists('usec', $timestamp)) {
throw new \InvalidArgumentException('Array must contain sec and usec keys.');
}
$this->fixedTime = $timestamp;
}
public function setUsec($value)
{
$this->fixedTime['usec'] = $value;
}
public function setSec($value)
{
$this->fixedTime['sec'] = $value;
}
public function currentTime()
{
return $this->fixedTime;
}
}
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace Rhumsaa\Uuid\Provider\Time;
use Rhumsaa\Uuid\Provider\TimeProviderInterface;
class SystemTimeProvider implements TimeProviderInterface
{
public function currentTime()
{
return gettimeofday();
}
}
+11
View File
@@ -0,0 +1,11 @@
<?php
namespace Rhumsaa\Uuid\Provider;
interface TimeProviderInterface
{
/**
* @return string[] Array guaranteed to contain "sec" and "usec" components of current timestamp.
*/
public function currentTime();
}
+36
View File
@@ -0,0 +1,36 @@
<?php
namespace Rhumsaa\Uuid;
use Rhumsaa\Uuid\Generator\OpenSslGenerator;
use Rhumsaa\Uuid\Generator\MtRandGenerator;
class RandomGeneratorFactory
{
/**
* For testing, openssl_random_pseudo_bytes() override; if true, treat as
* if openssl_random_pseudo_bytes() is not available
*
* @var bool
*/
public static $forceNoOpensslRandomPseudoBytes = false;
/**
* Returns true if the system has openssl_random_pseudo_bytes()
*
* @return bool
*/
protected static function hasOpensslRandomPseudoBytes()
{
return (function_exists('openssl_random_pseudo_bytes') && !self::$forceNoOpensslRandomPseudoBytes);
}
public static function getGenerator()
{
if (self::hasOpensslRandomPseudoBytes()) {
return new OpenSslGenerator();
}
return new MtRandGenerator();
}
}
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace Rhumsaa\Uuid;
interface RandomGeneratorInterface
{
/**
* @param integer $length
*
* @return string
*/
public function generate($length);
}
+54 -482
View File
@@ -12,6 +12,7 @@
namespace Rhumsaa\Uuid;
use InvalidArgumentException;
use Rhumsaa\Uuid\Converter\NumberConverterInterface;
/**
* Represents a universally unique identifier (UUID), according to RFC 4122
@@ -29,7 +30,8 @@ use InvalidArgumentException;
* @link http://docs.python.org/3/library/uuid.html
* @link http://docs.oracle.com/javase/6/docs/api/java/util/UUID.html
*/
class Uuid implements \JsonSerializable
class Uuid implements UuidInterface, \JsonSerializable
{
/**
* When this namespace is specified, the name string is a fully-qualified domain name.
@@ -96,41 +98,16 @@ class Uuid implements \JsonSerializable
const VERSION = '3.0.x-dev';
/**
* For testing, 64-bit system override; if true, treat the system as 32-bit
*
* @var bool
* @var UuidFactory
*/
public static $force32Bit = false;
private static $factory = null;
/**
* For testing, Moontoast\Math\BigNumber override; if true, treat as if
* BigNumber is not available
*
* @var bool
* String codec
* @var CodecInterface
*/
public static $forceNoBigNumber = false;
/**
* For testing, openssl_random_pseudo_bytes() override; if true, treat as
* if openssl_random_pseudo_bytes() is not available
*
* @var bool
*/
public static $forceNoOpensslRandomPseudoBytes = false;
/**
* For testing, sets time of day to a static, known value
*
* @var array
*/
public static $timeOfDayTest;
/**
* For testing, system override to ignore generating node from hardware
*
* @var bool
*/
public static $ignoreSystemNode = false;
protected $codec;
/**
* The fields that make up this UUID
@@ -149,6 +126,8 @@ class Uuid implements \JsonSerializable
'node' => '000000000000',
);
protected $converter;
/**
* Creates a universally unique identifier (UUID) from an array of fields.
*
@@ -156,11 +135,14 @@ class Uuid implements \JsonSerializable
* UUIDs.
*
* @param array $fields
* @param CodecInterface $codec String codec
* @link Rhumsaa.Uuid.Uuid.html#method_getFields
*/
protected function __construct(array $fields)
public function __construct(array $fields, NumberConverterInterface $converter, CodecInterface $codec)
{
$this->fields = $fields;
$this->codec = $codec;
$this->converter = $converter;
}
/**
@@ -201,9 +183,9 @@ class Uuid implements \JsonSerializable
* @param Uuid $uuid UUID to which this UUID is to be compared
* @return int -1, 0 or 1 as this UUID is less than, equal to, or greater than $uuid
*/
public function compareTo(Uuid $uuid)
public function compareTo(UuidInterface $uuid)
{
$comparison = null;
$comparison = 0;
if ($this->getMostSignificantBitsHex() < $uuid->getMostSignificantBitsHex()) {
$comparison = -1;
@@ -213,8 +195,6 @@ class Uuid implements \JsonSerializable
$comparison = -1;
} elseif ($this->getLeastSignificantBitsHex() > $uuid->getLeastSignificantBitsHex()) {
$comparison = 1;
} else {
$comparison = 0;
}
return $comparison;
@@ -247,13 +227,7 @@ class Uuid implements \JsonSerializable
*/
public function getBytes()
{
$bytes = '';
foreach (range(-2, -32, 2) as $step) {
$bytes = chr(hexdec(substr($this->getHex(), $step, 2))) . $bytes;
}
return $bytes;
return $this->codec->encodeBinary($this);
}
/**
@@ -330,6 +304,11 @@ class Uuid implements \JsonSerializable
return sprintf('%04x', $this->getClockSequence());
}
public function getNumberConverter()
{
return $this->converter;
}
/**
* Returns a PHP DateTime object representing the timestamp associated
* with this UUID.
@@ -340,7 +319,8 @@ class Uuid implements \JsonSerializable
*
* @return \DateTime A PHP DateTime representation of the date
* @throws Exception\UnsupportedOperationException If this UUID is not a version 1 UUID
* @throws Exception\UnsatisfiedDependencyException if called on a 32-bit system and Moontoast\Math\BigNumber is not present
* @throws Exception\UnsatisfiedDependencyException if called on a 32-bit system and
* Moontoast\Math\BigNumber is not present
*/
public function getDateTime()
{
@@ -348,31 +328,8 @@ class Uuid implements \JsonSerializable
throw new Exception\UnsupportedOperationException('Not a time-based UUID');
}
if (self::is64BitSystem()) {
$unixTime = ($this->getTimestamp() - 0x01b21dd213814000) / 1e7;
$unixTime = number_format($unixTime, 0, '', '');
} elseif (self::hasBigNumber()) {
$time = \Moontoast\Math\BigNumber::baseConvert($this->getTimestampHex(), 16, 10);
$ts = new \Moontoast\Math\BigNumber($time, 20);
$ts->subtract('122192928000000000');
$ts->divide('10000000.0');
$ts->round();
$unixTime = $ts->getValue();
} else {
throw new Exception\UnsatisfiedDependencyException(
'When calling ' . __METHOD__ . ' on a 32-bit system, '
. 'Moontoast\Math\BigNumber must be present in order '
. 'to extract DateTime from version 1 UUIDs'
);
}
$unixTime = ($this->getTimestamp() - 0x01b21dd213814000) / 1e7;
$unixTime = number_format($unixTime, 0, '', '');
return new \DateTime("@{$unixTime}");
}
@@ -398,14 +355,6 @@ class Uuid implements \JsonSerializable
*/
public function getFields()
{
if (!self::is64BitSystem()) {
throw new Exception\UnsatisfiedDependencyException(
'Cannot call ' . __METHOD__ . ' on a 32-bit system, since some '
. 'values overflow the system max integer value'
. '; consider calling getFieldsHex instead'
);
}
return array(
'time_low' => $this->getTimeLow(),
'time_mid' => $this->getTimeMid(),
@@ -456,22 +405,7 @@ class Uuid implements \JsonSerializable
*/
public function getInteger()
{
if (!self::hasBigNumber()) {
throw new Exception\UnsatisfiedDependencyException(
'Cannot call ' . __METHOD__ . ' without support for large '
. 'integers, since integer is an unsigned '
. '128-bit integer; Moontoast\Math\BigNumber is required'
. '; consider calling getMostSignificantBitsHex instead'
);
}
$number = \Moontoast\Math\BigNumber::baseConvert(
$this->getHex(),
16,
10
);
return new \Moontoast\Math\BigNumber($number);
return $this->converter->fromHex($this->getHex());
}
/**
@@ -482,22 +416,7 @@ class Uuid implements \JsonSerializable
*/
public function getLeastSignificantBits()
{
if (!self::hasBigNumber()) {
throw new Exception\UnsatisfiedDependencyException(
'Cannot call ' . __METHOD__ . ' without support for large '
. 'integers, since least significant bits is an unsigned '
. '64-bit integer; Moontoast\Math\BigNumber is required'
. '; consider calling getLeastSignificantBitsHex instead'
);
}
$number = \Moontoast\Math\BigNumber::baseConvert(
$this->getLeastSignificantBitsHex(),
16,
10
);
return new \Moontoast\Math\BigNumber($number);
return $this->converter->fromHex($this->getLeastSignificantBitsHex());
}
/**
@@ -523,22 +442,7 @@ class Uuid implements \JsonSerializable
*/
public function getMostSignificantBits()
{
if (!self::hasBigNumber()) {
throw new Exception\UnsatisfiedDependencyException(
'Cannot call ' . __METHOD__ . ' without support for large '
. 'integers, since most significant bits is an unsigned '
. '64-bit integer; Moontoast\Math\BigNumber is required'
. '; consider calling getMostSignificantBitsHex instead'
);
}
$number = \Moontoast\Math\BigNumber::baseConvert(
$this->getMostSignificantBitsHex(),
16,
10
);
return new \Moontoast\Math\BigNumber($number);
return $this->converter->fromHex($this->getMostSignificantBitsHex());
}
/**
@@ -583,15 +487,6 @@ class Uuid implements \JsonSerializable
*/
public function getNode()
{
if (!self::is64BitSystem()) {
throw new Exception\UnsatisfiedDependencyException(
'Cannot call ' . __METHOD__ . ' on a 32-bit system, since node '
. 'is an unsigned 48-bit integer and can overflow the system '
. 'max integer value'
. '; consider calling getNodeHex instead'
);
}
return hexdec($this->getNodeHex());
}
@@ -654,15 +549,6 @@ class Uuid implements \JsonSerializable
*/
public function getTimeLow()
{
if (!self::is64BitSystem()) {
throw new Exception\UnsatisfiedDependencyException(
'Cannot call ' . __METHOD__ . ' on a 32-bit system, since time_low '
. 'is an unsigned 32-bit integer and can overflow the system '
. 'max integer value'
. '; consider calling getTimeLowHex instead'
);
}
return hexdec($this->getTimeLowHex());
}
@@ -719,15 +605,6 @@ class Uuid implements \JsonSerializable
throw new Exception\UnsupportedOperationException('Not a time-based UUID');
}
if (!self::is64BitSystem()) {
throw new Exception\UnsatisfiedDependencyException(
'Cannot call ' . __METHOD__ . ' on a 32-bit system, since timestamp '
. 'is an unsigned 60-bit integer and can overflow the system '
. 'max integer value'
. '; consider calling getTimestampHex instead'
);
}
return hexdec($this->getTimestampHex());
}
@@ -836,10 +713,21 @@ class Uuid implements \JsonSerializable
*/
public function toString()
{
return vsprintf(
'%08s-%04s-%04s-%02s%02s-%012s',
$this->fields
);
return $this->codec->encode($this);
}
public static function getFactory()
{
if (! self::$factory) {
self::$factory = new UuidFactory();
}
return self::$factory;
}
public static function setFactory(UuidFactory $factory)
{
self::$factory = $factory;
}
/**
@@ -851,20 +739,7 @@ class Uuid implements \JsonSerializable
*/
public static function fromBytes($bytes)
{
if (strlen($bytes) !== 16) {
throw new InvalidArgumentException('$bytes string should contain 16 characters.');
}
$uuid = '';
foreach (range(0, 15) as $step) {
$uuid .= sprintf('%02x', ord($bytes[$step]));
if (in_array($step, array(3, 5, 7, 9))) {
$uuid .= '-';
}
}
return Uuid::fromString($uuid);
return self::getFactory()->fromBytes($bytes);
}
/**
@@ -877,34 +752,7 @@ class Uuid implements \JsonSerializable
*/
public static function fromString($name)
{
$nameParsed = str_replace(array('urn:', 'uuid:', '{', '}', '-'), '', $name);
// We have stripped out the dashes and are breaking up the string using
// substr(). In this way, we can accept a full hex value that doesn't
// contain dashes.
$components = array(
substr($nameParsed, 0, 8),
substr($nameParsed, 8, 4),
substr($nameParsed, 12, 4),
substr($nameParsed, 16, 4),
substr($nameParsed, 20),
);
$nameParsed = implode('-', $components);
if (!self::isValid($nameParsed)) {
throw new InvalidArgumentException('Invalid UUID string: ' . $name);
}
$fields = array(
'time_low' => sprintf('%08s', $components[0]),
'time_mid' => sprintf('%04s', $components[1]),
'time_hi_and_version' => sprintf('%04s', $components[2]),
'clock_seq_hi_and_reserved' => sprintf('%02s', substr($components[3], 0, 2)),
'clock_seq_low' => sprintf('%02s', substr($components[3], 2)),
'node' => sprintf('%012s', $components[4]),
);
return new self($fields);
return self::getFactory()->fromString($name);
}
/**
@@ -916,22 +764,7 @@ class Uuid implements \JsonSerializable
*/
public static function fromInteger($integer)
{
if (!self::hasBigNumber()) {
throw new Exception\UnsatisfiedDependencyException(
'Cannot call ' . __METHOD__ . ' without support for large '
. 'integers, since integer is an unsigned '
. '128-bit integer; Moontoast\Math\BigNumber is required. '
);
}
if (!$integer instanceof \Moontoast\Math\BigNumber) {
$integer = new \Moontoast\Math\BigNumber($integer);
}
$hex = \Moontoast\Math\BigNumber::baseConvert($integer, 10, 16);
$hex = str_pad($hex, 32, '0', STR_PAD_LEFT);
return self::fromString($hex);
return self::getFactory()->fromInteger($integer);
}
/**
@@ -951,6 +784,7 @@ class Uuid implements \JsonSerializable
if (!preg_match('/' . self::VALID_PATTERN . '/', $uuid)) {
return false;
}
return true;
}
@@ -971,80 +805,20 @@ class Uuid implements \JsonSerializable
*/
public static 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));
}
// Convert the node to hex, if it is still an integer
if (is_int($node)) {
$node = sprintf('%012x', $node);
}
if (ctype_xdigit($node) && strlen($node) <= 12) {
$node = strtolower(sprintf('%012s', $node));
} else {
throw new InvalidArgumentException('Invalid node value');
}
if ($clockSeq === null) {
// Not using "stable storage"; see RFC 4122, Section 4.2.1.1
$clockSeq = mt_rand(0, 1 << 14);
}
// 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']);
// Set the version number to 1
$timeHi = hexdec($uuidTime['hi']) & 0x0fff;
$timeHi &= ~(0xf000);
$timeHi |= 1 << 12;
// Set the variant to RFC 4122
$clockSeqHi = ($clockSeq >> 8) & 0x3f;
$clockSeqHi &= ~(0xc0);
$clockSeqHi |= 0x80;
$fields = array(
'time_low' => $uuidTime['low'],
'time_mid' => $uuidTime['mid'],
'time_hi_and_version' => sprintf('%04x', $timeHi),
'clock_seq_hi_and_reserved' => sprintf('%02x', $clockSeqHi),
'clock_seq_low' => sprintf('%02x', $clockSeq & 0xff),
'node' => $node,
);
return new self($fields);
return self::getFactory()->uuid1($node, $clockSeq);
}
/**
* Generate a version 3 UUID based on the MD5 hash of a namespace identifier (which
* is a UUID) and a name (which is a string).
*
* @param Uuid|string $ns The UUID namespace in which to create the named UUID
* @param string $ns The UUID namespace in which to create the named UUID
* @param string $name The name to create a UUID for
* @return Uuid
*/
public static function uuid3($ns, $name)
{
if (!($ns instanceof Uuid)) {
$ns = self::fromString($ns);
}
$hash = md5($ns->getBytes() . $name);
return self::uuidFromHashedName($hash, 3);
return self::getFactory()->uuid3($ns, $name);
}
/**
@@ -1054,221 +828,19 @@ class Uuid implements \JsonSerializable
*/
public static function uuid4()
{
$bytes = self::generateBytes(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 self::uuidFromHashedName($hex, 4);
return self::getFactory()->uuid4();
}
/**
* Generate a version 5 UUID based on the SHA-1 hash of a namespace identifier (which
* is a UUID) and a name (which is a string).
*
* @param Uuid|string $ns The UUID namespace in which to create the named UUID
* @param string $ns The UUID namespace in which to create the named UUID
* @param string $name The name to create a UUID for
* @return Uuid
*/
public static function uuid5($ns, $name)
{
if (!($ns instanceof Uuid)) {
$ns = self::fromString($ns);
}
$hash = sha1($ns->getBytes() . $name);
return self::uuidFromHashedName($hash, 5);
}
/**
* Calculates the UUID time fields from a UNIX timestamp
*
* UUID time is a 60-bit time value as a count of 100-nanosecond intervals
* since 00:00:00.00, 15 October 1582.
*
* @param int $sec Seconds since the Unix Epoch
* @param int $usec Microseconds
* @return array
* @throws Exception\UnsatisfiedDependencyException if called on a 32-bit system and Moontoast\Math\BigNumber is not present
*/
protected static function calculateUuidTime($sec, $usec)
{
if (self::is64BitSystem()) {
// 0x01b21dd213814000 is the number of 100-ns intervals between the
// UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
$uuidTime = ($sec * 10000000) + ($usec * 10) + 0x01b21dd213814000;
return array(
'low' => 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'
);
}
/**
* Returns the network interface configuration for the system
*
* @todo Needs evaluation and possibly modification to ensure this works
* well across multiple platforms.
* @codeCoverageIgnore
*/
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;
}
/**
* 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
*/
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;
}
/**
* Returns true if the system has Moontoast\Math\BigNumber
*
* @return bool
*/
protected static function hasBigNumber()
{
return (class_exists('Moontoast\Math\BigNumber') && !self::$forceNoBigNumber);
}
/**
* Returns true if the system has openssl_random_pseudo_bytes()
*
* @return bool
*/
protected static function hasOpensslRandomPseudoBytes()
{
return (function_exists('openssl_random_pseudo_bytes') && !self::$forceNoOpensslRandomPseudoBytes);
}
/**
* Returns true if the system is 64-bit, false otherwise
*
* @return bool
*/
protected static function is64BitSystem()
{
return (PHP_INT_SIZE == 8 && !self::$force32Bit);
}
/**
* Returns a version 3 or 5 UUID based on the hash (md5 or sha1) of a
* namespace identifier (which is a UUID) and a name (which is a string)
*
* @param string $hash The hash to use when creating the UUID
* @param int $version The UUID version to be generated
* @return Uuid
*/
protected static function uuidFromHashedName($hash, $version)
{
// Set the version number
$timeHi = hexdec(substr($hash, 12, 4)) & 0x0fff;
$timeHi &= ~(0xf000);
$timeHi |= $version << 12;
// Set the variant to RFC 4122
$clockSeqHi = hexdec(substr($hash, 16, 2)) & 0x3f;
$clockSeqHi &= ~(0xc0);
$clockSeqHi |= 0x80;
$fields = array(
'time_low' => substr($hash, 0, 8),
'time_mid' => substr($hash, 8, 4),
'time_hi_and_version' => sprintf('%04x', $timeHi),
'clock_seq_hi_and_reserved' => sprintf('%02x', $clockSeqHi),
'clock_seq_low' => substr($hash, 18, 2),
'node' => substr($hash, 20, 12),
);
return new self($fields);
}
/**
* Generates random bytes for use in version 4 UUIDs
*
* @param int $length
* @return string
*/
private static function generateBytes($length)
{
if (self::hasOpensslRandomPseudoBytes()) {
return openssl_random_pseudo_bytes($length);
}
$bytes = '';
for ($i = 1; $i <= $length; $i++) {
$bytes = chr(mt_rand(0, 255)) . $bytes;
}
return $bytes;
return self::getFactory()->uuid5($ns, $name);
}
}
+11
View File
@@ -0,0 +1,11 @@
<?php
namespace Rhumsaa\Uuid;
interface UuidBuilder
{
/**
* @return Uuid
*/
public function build(CodecInterface $codec, array $fields);
}
+314
View File
@@ -0,0 +1,314 @@
<?php
namespace Rhumsaa\Uuid;
use InvalidArgumentException;
use Rhumsaa\Uuid\Converter\NumberConverterInterface;
use Rhumsaa\Uuid\Converter\TimeConverterInterface;
use Rhumsaa\Uuid\Provider\NodeProviderInterface;
use Rhumsaa\Uuid\Provider\TimeProviderInterface;
class UuidFactory
{
/**
*
* @var CodecInterface
*/
private $codec = null;
/**
*
* @var NodeProviderInterface
*/
private $nodeProvider = null;
/**
*
* @var NumberConverterInterface
*/
private $numberConverter = null;
/**
* @var RandomGeneratorInterface
*/
private $randomGenerator = null;
/**
*
* @var TimeConverterInterface
*/
private $timeConverter = null;
/**
*
* @var TimeProviderInterface
*/
private $timeProvider = null;
/**
*
* @var UuidBuilder
*/
private $uuidBuilder = null;
/**
* Create a new a instance
*
*/
public function __construct(FeatureSet $features = null)
{
$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();
}
public function getCodec()
{
return $this->codec;
}
public function setTimeConverter(TimeConverterInterface $converter)
{
$this->timeConverter = $converter;
}
public function setTimeProvider(TimeProviderInterface $provider)
{
$this->timeProvider = $provider;
}
public function setRandomGenerator(RandomGeneratorInterface $generator)
{
$this->randomGenerator = $generator;
}
public function setNodeProvider(NodeProviderInterface $provider)
{
$this->nodeProvider = $provider;
}
public function setNumberConverter(NumberConverterInterface $converter)
{
$this->numberConverter = $converter;
}
public function setUuidBuilder(UuidBuilder $builder)
{
$this->uuidBuilder = $builder;
}
/**
* Creates a UUID from a byte string.
*
* @param string $bytes
* @return Uuid
* @throws InvalidArgumentException If the $bytes string does not contain 16 characters
*/
public function fromBytes($bytes)
{
return $this->codec->decodeBytes($bytes);
}
/**
* Creates a UUID from the string standard representation as described
* in the toString() method.
*
* @param string $name A string that specifies a UUID
* @return Uuid
* @throws InvalidArgumentException If the $name isn't a valid UUID
*/
public function fromString($name)
{
return $this->codec->decode($name);
}
public function fromInteger($integer)
{
$hex = $this->numberConverter->toHex($integer);
$hex = str_pad($hex, 32, '0', STR_PAD_LEFT);
return $this->fromString($hex);
}
/**
* 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
* address. If $clockSeq is given, it is used as the sequence number;
* otherwise a random 14-bit sequence number is chosen.
*
* @param int|string $node A 48-bit number representing the hardware
* address. This number may be represented as
* an integer or a hexadecimal string.
* @param int $clockSeq A 14-bit number used to help avoid duplicates that
* could arise when the clock is set backwards in time
* or if the node ID changes.
* @return Uuid
* @throws InvalidArgumentException if the $node is invalid
*/
public function uuid1($node = null, $clockSeq = null)
{
$node = $this->getValidNode($node);
if ($clockSeq === null) {
// Not using "stable storage"; see RFC 4122, Section 4.2.1.1
$clockSeq = mt_rand(0, 1 << 14);
}
// Create a 60-bit time value as a count of 100-nanosecond intervals
// since 00:00:00.00, 15 October 1582
$timeOfDay = $this->timeProvider->currentTime();
$uuidTime = $this->timeConverter->calculateTime($timeOfDay['sec'], $timeOfDay['usec']);
$timeHi = $this->applyVersion($uuidTime['hi'], 1);
$clockSeqHi = $this->applyVariant($clockSeq >> 8);
$fields = array(
'time_low' => $uuidTime['low'],
'time_mid' => $uuidTime['mid'],
'time_hi_and_version' => sprintf('%04x', $timeHi),
'clock_seq_hi_and_reserved' => sprintf('%02x', $clockSeqHi),
'clock_seq_low' => sprintf('%02x', $clockSeq & 0xff),
'node' => $node,
);
return $this->uuid($fields);
}
/**
* Generate a version 3 UUID based on the MD5 hash of a namespace identifier (which
* is a UUID) and a name (which is a string).
*
* @param Uuid|string $ns The UUID namespace in which to create the named UUID
* @param string $name The name to create a UUID for
* @return Uuid
*/
public function uuid3($ns, $name)
{
return $this->uuidFromNsAndName($ns, $name, 3, 'md5');
}
/**
* Generate a version 4 (random) UUID.
*
* @return Uuid
*/
public function uuid4()
{
$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);
}
/**
* Generate a version 5 UUID based on the SHA-1 hash of a namespace identifier (which
* is a UUID) and a name (which is a string).
*
* @param Uuid|string $ns The UUID namespace in which to create the named UUID
* @param string $name The name to create a UUID for
* @return Uuid
*/
public function uuid5($ns, $name)
{
return $this->uuidFromNsAndName($ns, $name, 5, 'sha1');
}
public function uuid(array $fields)
{
return $this->uuidBuilder->build($this->codec, $fields);
}
protected function applyVariant($clockSeqHi)
{
// Set the variant to RFC 4122
$clockSeqHi = $clockSeqHi & 0x3f;
$clockSeqHi &= ~(0xc0);
$clockSeqHi |= 0x80;
return $clockSeqHi;
}
/**
* @param string $timeHi
* @param integer $version
*/
protected function applyVersion($timeHi, $version)
{
$timeHi = hexdec($timeHi) & 0x0fff;
$timeHi &= ~(0xf000);
$timeHi |= $version << 12;
return $timeHi;
}
/**
* @param string $name
* @param integer $version
* @param string $hashFunction
*/
protected function uuidFromNsAndName($ns, $name, $version, $hashFunction)
{
if (!($ns instanceof Uuid)) {
$ns = $this->codec->decode($ns);
}
$hash = call_user_func($hashFunction, ($ns->getBytes() . $name));
return $this->uuidFromHashedName($hash, $version);
}
/**
* Returns a version 3 or 5 UUID based on the hash (md5 or sha1) of a
* namespace identifier (which is a UUID) and a name (which is a string)
*
* @param string $hash The hash to use when creating the UUID
* @param int $version The UUID version to be generated
* @return Uuid
*/
protected function uuidFromHashedName($hash, $version)
{
$timeHi = $this->applyVersion(substr($hash, 12, 4), $version);
$clockSeqHi = $this->applyVariant(hexdec(substr($hash, 16, 2)));
$fields = array(
'time_low' => substr($hash, 0, 8),
'time_mid' => substr($hash, 8, 4),
'time_hi_and_version' => sprintf('%04x', $timeHi),
'clock_seq_hi_and_reserved' => sprintf('%02x', $clockSeqHi),
'clock_seq_low' => substr($hash, 18, 2),
'node' => substr($hash, 20, 12),
);
return $this->uuid($fields);
}
protected function getValidNode($node)
{
if ($node === null) {
$node = $this->nodeProvider->getNode();
}
// Convert the node to hex, if it is still an integer
if (is_int($node)) {
$node = sprintf('%012x', $node);
}
if (! ctype_xdigit($node) || strlen($node) > 12) {
throw new \InvalidArgumentException('Invalid node value');
}
return strtolower(sprintf('%012s', $node));
}
}
+111
View File
@@ -0,0 +1,111 @@
<?php
namespace Rhumsaa\Uuid;
use Rhumsaa\Uuid\Converter\NumberConverterInterface;
interface UuidInterface
{
/**
* @return integer
*/
public function compareTo(UuidInterface $other);
/**
* @return boolean
*/
public function equals($other);
/**
* @return NumberConverterInterface
*/
public function getNumberConverter();
/**
* @return string
*/
public function getHex();
public function getFieldsHex();
/**
* @return string
*/
public function getClockSeqHiAndReservedHex();
/**
* @return string
*/
public function getClockSeqLowHex();
/**
* @return string
*/
public function getClockSequenceHex();
/**
* @return \DateTime
*/
public function getDateTime();
/**
* @return \Moontoast\Math\BigNumber
*/
public function getInteger();
/**
* @return string
*/
public function getLeastSignificantBitsHex();
/**
* @return string
*/
public function getMostSignificantBitsHex();
/**
* @return string
*/
public function getNodeHex();
/**
* @return string
*/
public function getTimeHiAndVersionHex();
/**
* @return string
*/
public function getTimeLowHex();
/**
* @return string
*/
public function getTimeMidHex();
/**
* @return string
*/
public function getTimestampHex();
/**
* @return string
*/
public function getUrn();
/**
* @return integer
*/
public function getVariant();
/**
* @return integer|null
*/
public function getVersion();
/**
* @return string
*/
public function toString();
}
@@ -0,0 +1,28 @@
<?php
namespace Rhumsaa\Uuid\Converter\Number;
use Rhumsaa\Uuid\TestCase;
class DegradedNumberConverterTest extends TestCase
{
/**
* @expectedException Rhumsaa\Uuid\Exception\UnsatisfiedDependencyException
*/
public function testConvertingFromHexThrowsException()
{
$converter = new DegradedNumberConverter();
$converter->fromHex('ffff');
}
/**
* @expectedException Rhumsaa\Uuid\Exception\UnsatisfiedDependencyException
*/
public function testConvertingToHexThrowsException()
{
$converter = new DegradedNumberConverter();
$converter->toHex(0);
}
}
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace Rhumsaa\Uuid;
class RandomGeneratorFactoryTest extends TestCase
{
public function testFactoryReturnsNonOpenSslGeneratorWithForceNoOpenSsl()
{
RandomGeneratorFactory::$forceNoOpensslRandomPseudoBytes = true;
$generator = RandomGeneratorFactory::getGenerator();
$this->assertNotInstanceOf('\Rhumsaa\Uuid\Generator\OpenSslGenerator', $generator);
}
public function testFactoryReturnsOpenSslGeneratorIfAvailable()
{
RandomGeneratorFactory::$forceNoOpensslRandomPseudoBytes = false;
$generator = RandomGeneratorFactory::getGenerator();
$this->assertInstanceOf('\Rhumsaa\Uuid\Generator\OpenSslGenerator', $generator);
}
}
+3 -51
View File
@@ -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(
@@ -21,8 +23,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::fromString
* @covers Rhumsaa\Uuid\Uuid::__construct
*/
public function testFromString()
{
@@ -32,7 +32,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::fromString
*/
public function testFromStringWithCurlyBraces()
{
@@ -42,7 +41,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::fromString
* @expectedException InvalidArgumentException
* @expectedExceptionMessage Invalid UUID string:
*/
@@ -52,7 +50,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::fromString
*/
public function testFromStringWithUrn()
{
@@ -62,7 +59,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getBytes
*/
public function testGetBytes()
{
@@ -71,7 +67,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getClockSeqHiAndReserved
*/
public function testGetClockSeqHiAndReserved()
{
@@ -80,7 +75,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getClockSeqLow
*/
public function testGetClockSeqLow()
{
@@ -89,7 +83,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getClockSequence
*/
public function testGetClockSequence()
{
@@ -98,7 +91,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getDateTime
*/
public function testGetDateTime()
{
@@ -114,8 +106,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getDateTime
* @covers Rhumsaa\Uuid\Exception\UnsupportedOperationException
* @expectedException Rhumsaa\Uuid\Exception\UnsupportedOperationException
* @expectedExceptionMessage Not a time-based UUID
*/
@@ -127,7 +117,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getFields
*/
public function testGetFields()
{
@@ -141,7 +130,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getLeastSignificantBits
*/
public function testGetLeastSignificantBits()
{
@@ -158,7 +146,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getMostSignificantBits
*/
public function testGetMostSignificantBits()
{
@@ -175,7 +162,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getNode
*/
public function testGetNode()
{
@@ -184,7 +170,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getTimeHiAndVersion
*/
public function testGetTimeHiAndVersion()
{
@@ -193,7 +178,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getTimeLow
*/
public function testGetTimeLow()
{
@@ -202,7 +186,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getTimeMid
*/
public function testGetTimeMid()
{
@@ -211,7 +194,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getTimestamp
*/
public function testGetTimestamp()
{
@@ -225,8 +207,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getTimestamp
* @covers Rhumsaa\Uuid\Exception\UnsupportedOperationException
* @expectedException Rhumsaa\Uuid\Exception\UnsupportedOperationException
* @expectedExceptionMessage Not a time-based UUID
*/
@@ -238,7 +218,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getUrn
*/
public function testGetUrn()
{
@@ -247,7 +226,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getVariant
*/
public function testGetVariantForReservedNcs()
{
@@ -277,7 +255,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getVariant
*/
public function testGetVariantForRfc4122()
{
@@ -295,7 +272,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getVariant
*/
public function testGetVariantForReservedMicrosoft()
{
@@ -307,7 +283,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getVariant
*/
public function testGetVariantForReservedFuture()
{
@@ -319,7 +294,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getVersion
*/
public function testGetVersionForVersion1()
{
@@ -328,7 +302,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getVersion
*/
public function testGetVersionForVersion2()
{
@@ -337,7 +310,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getVersion
*/
public function testGetVersionForVersion3()
{
@@ -346,7 +318,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getVersion
*/
public function testGetVersionForVersion4()
{
@@ -355,7 +326,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::getVersion
*/
public function testGetVersionForVersion5()
{
@@ -364,8 +334,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::toString
* @covers Rhumsaa\Uuid\Uuid::__toString
*/
public function testToString()
{
@@ -381,8 +349,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::uuid1
* @covers Rhumsaa\Uuid\Uuid::getNodeFromSystem
*/
public function testUuid1()
{
@@ -394,7 +360,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::uuid1
*/
public function testUuid1WithNodeAndClockSequence()
{
@@ -409,11 +374,10 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::uuid1
*/
public function testUuid1WithRandomNode()
{
Uuid::$ignoreSystemNode = true;
Uuid::setFactory(new UuidFactory(new FeatureSet(false, false, false, true)));
$uuid = Uuid::uuid1();
$this->assertInstanceOf('\Rhumsaa\Uuid\Uuid', $uuid);
@@ -427,8 +391,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
* library generates a matching UUID for the same name.
* @see http://docs.python.org/library/uuid.html
*
* @covers Rhumsaa\Uuid\Uuid::uuid3
* @covers Rhumsaa\Uuid\Uuid::uuidFromHashedName
*/
public function testUuid3WithNamespaceAsUuidObject()
{
@@ -444,8 +406,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
* library generates a matching UUID for the same name.
* @see http://docs.python.org/library/uuid.html
*
* @covers Rhumsaa\Uuid\Uuid::uuid3
* @covers Rhumsaa\Uuid\Uuid::uuidFromHashedName
*/
public function testUuid3WithNamespaceAsUuidString()
{
@@ -456,8 +416,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::uuid4
* @covers Rhumsaa\Uuid\Uuid::uuidFromHashedName
*/
public function testUuid4()
{
@@ -472,8 +430,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
* library generates a matching UUID for the same name.
* @see http://docs.python.org/library/uuid.html
*
* @covers Rhumsaa\Uuid\Uuid::uuid5
* @covers Rhumsaa\Uuid\Uuid::uuidFromHashedName
*/
public function testUuid5WithNamespaceAsUuidObject()
{
@@ -489,8 +445,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
* library generates a matching UUID for the same name.
* @see http://docs.python.org/library/uuid.html
*
* @covers Rhumsaa\Uuid\Uuid::uuid5
* @covers Rhumsaa\Uuid\Uuid::uuidFromHashedName
*/
public function testUuid5WithNamespaceAsUuidString()
{
@@ -501,7 +455,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::compareTo
*/
public function testCompareTo()
{
@@ -530,7 +483,6 @@ class UuidBcTag1_1_2Test extends \PHPUnit_Framework_TestCase
}
/**
* @covers Rhumsaa\Uuid\Uuid::equals
*/
public function testEquals()
{
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace Rhumsaa\Uuid;
class UuidFactoryTest extends TestCase
{
public function testParsesUuidCorrectly()
{
$factory = new UuidFactory();
$uuid = $factory->fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66');
$this->assertEquals('ff6f8cb0-c57d-11e1-9b21-0800200c9a66', $uuid->toString());
}
public function testParsesGuidCorrectly()
{
$factory = new UuidFactory(new FeatureSet(true));
$uuid = $factory->fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66');
$this->assertEquals('ff6f8cb0-c57d-11e1-9b21-0800200c9a66', $uuid->toString());
}
}
+124 -267
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -9,6 +9,9 @@ if (!file_exists(dirname(__DIR__) . '/vendor/autoload.php')) {
. "See http://getcomposer.org for help with installing composer\n");
}
// Set a default timezone for HHVM tests
date_default_timezone_set('UTC');
// Include the Composer autoloader
$loader = include realpath(dirname(__FILE__) . '/../vendor/autoload.php');
@@ -4,5 +4,5 @@
decode: variant: RFC 4122
version: 5 (name based, SHA-1)
content: 88:63:13:e1:3b:8a:53:72:9b:90:0c:9a:ee:19:9e:5d
(not decipherable: MD5 message digest only)
(not decipherable: SHA1 message digest only)
========= ========== =================================================