Blame | Letzte Änderung | Log anzeigen | RSS feed
<?php/*** This file is part of the ramsey/uuid library** For the full copyright and license information, please view the LICENSE* file that was distributed with this source code.** @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>* @license http://opensource.org/licenses/MIT MIT*/declare(strict_types=1);namespace Ramsey\Uuid;use DateTimeInterface;use Ramsey\Uuid\Builder\UuidBuilderInterface;use Ramsey\Uuid\Codec\CodecInterface;use Ramsey\Uuid\Converter\NumberConverterInterface;use Ramsey\Uuid\Converter\TimeConverterInterface;use Ramsey\Uuid\Generator\DceSecurityGeneratorInterface;use Ramsey\Uuid\Generator\DefaultTimeGenerator;use Ramsey\Uuid\Generator\NameGeneratorInterface;use Ramsey\Uuid\Generator\RandomGeneratorInterface;use Ramsey\Uuid\Generator\TimeGeneratorInterface;use Ramsey\Uuid\Generator\UnixTimeGenerator;use Ramsey\Uuid\Lazy\LazyUuidFromString;use Ramsey\Uuid\Provider\NodeProviderInterface;use Ramsey\Uuid\Provider\Time\FixedTimeProvider;use Ramsey\Uuid\Type\Hexadecimal;use Ramsey\Uuid\Type\Integer as IntegerObject;use Ramsey\Uuid\Type\Time;use Ramsey\Uuid\Validator\ValidatorInterface;use function bin2hex;use function hex2bin;use function pack;use function str_pad;use function strtolower;use function substr;use function substr_replace;use function unpack;use const STR_PAD_LEFT;class UuidFactory implements UuidFactoryInterface{private CodecInterface $codec;private DceSecurityGeneratorInterface $dceSecurityGenerator;private NameGeneratorInterface $nameGenerator;private NodeProviderInterface $nodeProvider;private NumberConverterInterface $numberConverter;private RandomGeneratorInterface $randomGenerator;private TimeConverterInterface $timeConverter;private TimeGeneratorInterface $timeGenerator;private TimeGeneratorInterface $unixTimeGenerator;private UuidBuilderInterface $uuidBuilder;private ValidatorInterface $validator;/*** @var bool whether the feature set was provided from outside, or we can* operate under "default" assumptions*/private bool $isDefaultFeatureSet;/*** @param FeatureSet|null $features A set of available features in the current environment*/public function __construct(?FeatureSet $features = null){$this->isDefaultFeatureSet = $features === null;$features = $features ?: new FeatureSet();$this->codec = $features->getCodec();$this->dceSecurityGenerator = $features->getDceSecurityGenerator();$this->nameGenerator = $features->getNameGenerator();$this->nodeProvider = $features->getNodeProvider();$this->numberConverter = $features->getNumberConverter();$this->randomGenerator = $features->getRandomGenerator();$this->timeConverter = $features->getTimeConverter();$this->timeGenerator = $features->getTimeGenerator();$this->uuidBuilder = $features->getBuilder();$this->validator = $features->getValidator();$this->unixTimeGenerator = $features->getUnixTimeGenerator();}/*** Returns the codec used by this factory*/public function getCodec(): CodecInterface{return $this->codec;}/*** Sets the codec to use for this factory** @param CodecInterface $codec A UUID encoder-decoder*/public function setCodec(CodecInterface $codec): void{$this->isDefaultFeatureSet = false;$this->codec = $codec;}/*** Returns the name generator used by this factory*/public function getNameGenerator(): NameGeneratorInterface{return $this->nameGenerator;}/*** Sets the name generator to use for this factory** @param NameGeneratorInterface $nameGenerator A generator to generate* binary data, based on a namespace and name*/public function setNameGenerator(NameGeneratorInterface $nameGenerator): void{$this->isDefaultFeatureSet = false;$this->nameGenerator = $nameGenerator;}/*** Returns the node provider used by this factory*/public function getNodeProvider(): NodeProviderInterface{return $this->nodeProvider;}/*** Returns the random generator used by this factory*/public function getRandomGenerator(): RandomGeneratorInterface{return $this->randomGenerator;}/*** Returns the time generator used by this factory*/public function getTimeGenerator(): TimeGeneratorInterface{return $this->timeGenerator;}/*** Sets the time generator to use for this factory** @param TimeGeneratorInterface $generator A generator to generate binary* data, based on the time*/public function setTimeGenerator(TimeGeneratorInterface $generator): void{$this->isDefaultFeatureSet = false;$this->timeGenerator = $generator;}/*** Returns the DCE Security generator used by this factory*/public function getDceSecurityGenerator(): DceSecurityGeneratorInterface{return $this->dceSecurityGenerator;}/*** Sets the DCE Security generator to use for this factory** @param DceSecurityGeneratorInterface $generator A generator to generate* binary data, based on a local domain and local identifier*/public function setDceSecurityGenerator(DceSecurityGeneratorInterface $generator): void{$this->isDefaultFeatureSet = false;$this->dceSecurityGenerator = $generator;}/*** Returns the number converter used by this factory*/public function getNumberConverter(): NumberConverterInterface{return $this->numberConverter;}/*** Sets the random generator to use for this factory** @param RandomGeneratorInterface $generator A generator to generate binary* data, based on some random input*/public function setRandomGenerator(RandomGeneratorInterface $generator): void{$this->isDefaultFeatureSet = false;$this->randomGenerator = $generator;}/*** Sets the number converter to use for this factory** @param NumberConverterInterface $converter A converter to use for working* with large integers (i.e. integers greater than PHP_INT_MAX)*/public function setNumberConverter(NumberConverterInterface $converter): void{$this->isDefaultFeatureSet = false;$this->numberConverter = $converter;}/*** Returns the UUID builder used by this factory*/public function getUuidBuilder(): UuidBuilderInterface{return $this->uuidBuilder;}/*** Sets the UUID builder to use for this factory** @param UuidBuilderInterface $builder A builder for constructing instances* of UuidInterface*/public function setUuidBuilder(UuidBuilderInterface $builder): void{$this->isDefaultFeatureSet = false;$this->uuidBuilder = $builder;}/*** @psalm-mutation-free*/public function getValidator(): ValidatorInterface{return $this->validator;}/*** Sets the validator to use for this factory** @param ValidatorInterface $validator A validator to use for validating* whether a string is a valid UUID*/public function setValidator(ValidatorInterface $validator): void{$this->isDefaultFeatureSet = false;$this->validator = $validator;}/*** @psalm-pure*/public function fromBytes(string $bytes): UuidInterface{return $this->codec->decodeBytes($bytes);}/*** @psalm-pure*/public function fromString(string $uuid): UuidInterface{$uuid = strtolower($uuid);return $this->codec->decode($uuid);}/*** @psalm-pure*/public function fromInteger(string $integer): UuidInterface{$hex = $this->numberConverter->toHex($integer);$hex = str_pad($hex, 32, '0', STR_PAD_LEFT);return $this->fromString($hex);}public function fromDateTime(DateTimeInterface $dateTime,?Hexadecimal $node = null,?int $clockSeq = null): UuidInterface {$timeProvider = new FixedTimeProvider(new Time($dateTime->format('U'), $dateTime->format('u')));$timeGenerator = new DefaultTimeGenerator($this->nodeProvider,$this->timeConverter,$timeProvider);$nodeHex = $node ? $node->toString() : null;$bytes = $timeGenerator->generate($nodeHex, $clockSeq);return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_TIME);}/*** @psalm-pure*/public function fromHexadecimal(Hexadecimal $hex): UuidInterface{return $this->codec->decode($hex->__toString());}/*** @inheritDoc*/public function uuid1($node = null, ?int $clockSeq = null): UuidInterface{$bytes = $this->timeGenerator->generate($node, $clockSeq);return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_TIME);}public function uuid2(int $localDomain,?IntegerObject $localIdentifier = null,?Hexadecimal $node = null,?int $clockSeq = null): UuidInterface {$bytes = $this->dceSecurityGenerator->generate($localDomain,$localIdentifier,$node,$clockSeq);return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_DCE_SECURITY);}/*** @inheritDoc* @psalm-pure*/public function uuid3($ns, string $name): UuidInterface{return $this->uuidFromNsAndName($ns, $name, Uuid::UUID_TYPE_HASH_MD5, 'md5');}public function uuid4(): UuidInterface{$bytes = $this->randomGenerator->generate(16);return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_RANDOM);}/*** @inheritDoc* @psalm-pure*/public function uuid5($ns, string $name): UuidInterface{return $this->uuidFromNsAndName($ns, $name, Uuid::UUID_TYPE_HASH_SHA1, 'sha1');}public function uuid6(?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface{$nodeHex = $node ? $node->toString() : null;$bytes = $this->timeGenerator->generate($nodeHex, $clockSeq);// Rearrange the bytes, according to the UUID version 6 specification.$v6 = $bytes[6] . $bytes[7] . $bytes[4] . $bytes[5]. $bytes[0] . $bytes[1] . $bytes[2] . $bytes[3];$v6 = bin2hex($v6);// Drop the first four bits, while adding an empty four bits for the// version field. This allows us to reconstruct the correct time from// the bytes of this UUID.$v6Bytes = hex2bin(substr($v6, 1, 12) . '0' . substr($v6, -3));$v6Bytes .= substr($bytes, 8);return $this->uuidFromBytesAndVersion($v6Bytes, Uuid::UUID_TYPE_REORDERED_TIME);}/*** Returns a version 7 (Unix Epoch time) UUID** @param DateTimeInterface|null $dateTime An optional date/time from which* to create the version 7 UUID. If not provided, the UUID is generated* using the current date/time.** @return UuidInterface A UuidInterface instance that represents a* version 7 UUID*/public function uuid7(?DateTimeInterface $dateTime = null): UuidInterface{assert($this->unixTimeGenerator instanceof UnixTimeGenerator);$bytes = $this->unixTimeGenerator->generate(null, null, $dateTime);return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_UNIX_TIME);}/*** Returns a version 8 (Custom) UUID** The bytes provided may contain any value according to your application's* needs. Be aware, however, that other applications may not understand the* semantics of the value.** @param string $bytes A 16-byte octet string. This is an open blob* of data that you may fill with 128 bits of information. Be aware,* however, bits 48 through 51 will be replaced with the UUID version* field, and bits 64 and 65 will be replaced with the UUID variant. You* MUST NOT rely on these bits for your application needs.** @return UuidInterface A UuidInterface instance that represents a* version 8 UUID*/public function uuid8(string $bytes): UuidInterface{return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_CUSTOM);}/*** Returns a Uuid created from the provided byte string** Uses the configured builder and codec and the provided byte string to* construct a Uuid object.** @param string $bytes The byte string from which to construct a UUID** @return UuidInterface An instance of UuidInterface, created from the* provided bytes** @psalm-pure*/public function uuid(string $bytes): UuidInterface{/** @psalm-suppress ImpurePropertyFetch */return $this->uuidBuilder->build($this->codec, $bytes);}/*** Returns a version 3 or 5 namespaced Uuid** @param string|UuidInterface $ns The namespace (must be a valid UUID)* @param string $name The name to hash together with the namespace* @param int $version The version of UUID to create (3 or 5)* @param string $hashAlgorithm The hashing algorithm to use when hashing* together the namespace and name** @return UuidInterface An instance of UuidInterface, created by hashing* together the provided namespace and name** @psalm-pure*/private function uuidFromNsAndName(UuidInterface | string $ns,string $name,int $version,string $hashAlgorithm): UuidInterface {if (!($ns instanceof UuidInterface)) {$ns = $this->fromString($ns);}$bytes = $this->nameGenerator->generate($ns, $name, $hashAlgorithm);return $this->uuidFromBytesAndVersion(substr($bytes, 0, 16), $version);}/*** Returns an RFC 4122 variant Uuid, created from the provided bytes and version** @param string $bytes The byte string to convert to a UUID* @param int $version The RFC 4122 version to apply to the UUID** @return UuidInterface An instance of UuidInterface, created from the* byte string and version** @psalm-pure*/private function uuidFromBytesAndVersion(string $bytes, int $version): UuidInterface{/** @var array $unpackedTime */$unpackedTime = unpack('n*', substr($bytes, 6, 2));$timeHi = (int) $unpackedTime[1];$timeHiAndVersion = pack('n*', BinaryUtils::applyVersion($timeHi, $version));/** @var array $unpackedClockSeq */$unpackedClockSeq = unpack('n*', substr($bytes, 8, 2));$clockSeqHi = (int) $unpackedClockSeq[1];$clockSeqHiAndReserved = pack('n*', BinaryUtils::applyVariant($clockSeqHi));$bytes = substr_replace($bytes, $timeHiAndVersion, 6, 2);$bytes = substr_replace($bytes, $clockSeqHiAndReserved, 8, 2);if ($this->isDefaultFeatureSet) {return LazyUuidFromString::fromBytes($bytes);}/** @psalm-suppress ImpureVariable */return $this->uuid($bytes);}}