mirror of
https://gitlab.com/signalytic/client-external/streamline/streamline-emr.git
synced 2026-09-12 03:01:32 +00:00
resolved conflicts
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Uid;
|
||||
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
abstract class AbstractUid implements \JsonSerializable, \Stringable
|
||||
{
|
||||
/**
|
||||
* The identifier in its canonic representation.
|
||||
*/
|
||||
protected $uid;
|
||||
|
||||
/**
|
||||
* Whether the passed value is valid for the constructor of the current class.
|
||||
*/
|
||||
abstract public static function isValid(string $uid): bool;
|
||||
|
||||
/**
|
||||
* Creates an AbstractUid from an identifier represented in any of the supported formats.
|
||||
*
|
||||
* @throws \InvalidArgumentException When the passed value is not valid
|
||||
*/
|
||||
abstract public static function fromString(string $uid): static;
|
||||
|
||||
/**
|
||||
* @throws \InvalidArgumentException When the passed value is not valid
|
||||
*/
|
||||
public static function fromBinary(string $uid): static
|
||||
{
|
||||
if (16 !== \strlen($uid)) {
|
||||
throw new \InvalidArgumentException('Invalid binary uid provided.');
|
||||
}
|
||||
|
||||
return static::fromString($uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \InvalidArgumentException When the passed value is not valid
|
||||
*/
|
||||
public static function fromBase58(string $uid): static
|
||||
{
|
||||
if (22 !== \strlen($uid)) {
|
||||
throw new \InvalidArgumentException('Invalid base-58 uid provided.');
|
||||
}
|
||||
|
||||
return static::fromString($uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \InvalidArgumentException When the passed value is not valid
|
||||
*/
|
||||
public static function fromBase32(string $uid): static
|
||||
{
|
||||
if (26 !== \strlen($uid)) {
|
||||
throw new \InvalidArgumentException('Invalid base-32 uid provided.');
|
||||
}
|
||||
|
||||
return static::fromString($uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uid A valid RFC 9562/4122 uid
|
||||
*
|
||||
* @throws \InvalidArgumentException When the passed value is not valid
|
||||
*/
|
||||
public static function fromRfc4122(string $uid): static
|
||||
{
|
||||
if (36 !== \strlen($uid)) {
|
||||
throw new \InvalidArgumentException('Invalid RFC4122 uid provided.');
|
||||
}
|
||||
|
||||
return static::fromString($uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier as a raw binary string.
|
||||
*/
|
||||
abstract public function toBinary(): string;
|
||||
|
||||
/**
|
||||
* Returns the identifier as a base58 case sensitive string.
|
||||
*
|
||||
* @example 2AifFTC3zXgZzK5fPrrprL (len=22)
|
||||
*/
|
||||
public function toBase58(): string
|
||||
{
|
||||
return strtr(sprintf('%022s', BinaryUtil::toBase($this->toBinary(), BinaryUtil::BASE58)), '0', '1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier as a base32 case insensitive string.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc4648#section-6
|
||||
*
|
||||
* @example 09EJ0S614A9FXVG9C5537Q9ZE1 (len=26)
|
||||
*/
|
||||
public function toBase32(): string
|
||||
{
|
||||
$uid = bin2hex($this->toBinary());
|
||||
$uid = sprintf('%02s%04s%04s%04s%04s%04s%04s',
|
||||
base_convert(substr($uid, 0, 2), 16, 32),
|
||||
base_convert(substr($uid, 2, 5), 16, 32),
|
||||
base_convert(substr($uid, 7, 5), 16, 32),
|
||||
base_convert(substr($uid, 12, 5), 16, 32),
|
||||
base_convert(substr($uid, 17, 5), 16, 32),
|
||||
base_convert(substr($uid, 22, 5), 16, 32),
|
||||
base_convert(substr($uid, 27, 5), 16, 32)
|
||||
);
|
||||
|
||||
return strtr($uid, 'abcdefghijklmnopqrstuv', 'ABCDEFGHJKMNPQRSTVWXYZ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier as a RFC 9562/4122 case insensitive string.
|
||||
*
|
||||
* @see https://datatracker.ietf.org/doc/html/rfc9562/#section-4
|
||||
*
|
||||
* @example 09748193-048a-4bfb-b825-8528cf74fdc1 (len=36)
|
||||
*/
|
||||
public function toRfc4122(): string
|
||||
{
|
||||
// don't use uuid_unparse(), it's slower
|
||||
$uuid = bin2hex($this->toBinary());
|
||||
$uuid = substr_replace($uuid, '-', 8, 0);
|
||||
$uuid = substr_replace($uuid, '-', 13, 0);
|
||||
$uuid = substr_replace($uuid, '-', 18, 0);
|
||||
|
||||
return substr_replace($uuid, '-', 23, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier as a prefixed hexadecimal case insensitive string.
|
||||
*
|
||||
* @example 0x09748193048a4bfbb8258528cf74fdc1 (len=34)
|
||||
*/
|
||||
public function toHex(): string
|
||||
{
|
||||
return '0x'.bin2hex($this->toBinary());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the argument is an AbstractUid and contains the same value as the current instance.
|
||||
*/
|
||||
public function equals(mixed $other): bool
|
||||
{
|
||||
if (!$other instanceof self) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->uid === $other->uid;
|
||||
}
|
||||
|
||||
public function compare(self $other): int
|
||||
{
|
||||
return (\strlen($this->uid) - \strlen($other->uid)) ?: ($this->uid <=> $other->uid);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->uid;
|
||||
}
|
||||
|
||||
public function jsonSerialize(): string
|
||||
{
|
||||
return $this->uid;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Uid;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class BinaryUtil
|
||||
{
|
||||
public const BASE10 = [
|
||||
'' => '0123456789',
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
];
|
||||
|
||||
public const BASE58 = [
|
||||
'' => '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz',
|
||||
1 => 0, 1, 2, 3, 4, 5, 6, 7, 8, 'A' => 9,
|
||||
'B' => 10, 'C' => 11, 'D' => 12, 'E' => 13, 'F' => 14, 'G' => 15,
|
||||
'H' => 16, 'J' => 17, 'K' => 18, 'L' => 19, 'M' => 20, 'N' => 21,
|
||||
'P' => 22, 'Q' => 23, 'R' => 24, 'S' => 25, 'T' => 26, 'U' => 27,
|
||||
'V' => 28, 'W' => 29, 'X' => 30, 'Y' => 31, 'Z' => 32, 'a' => 33,
|
||||
'b' => 34, 'c' => 35, 'd' => 36, 'e' => 37, 'f' => 38, 'g' => 39,
|
||||
'h' => 40, 'i' => 41, 'j' => 42, 'k' => 43, 'm' => 44, 'n' => 45,
|
||||
'o' => 46, 'p' => 47, 'q' => 48, 'r' => 49, 's' => 50, 't' => 51,
|
||||
'u' => 52, 'v' => 53, 'w' => 54, 'x' => 55, 'y' => 56, 'z' => 57,
|
||||
];
|
||||
|
||||
// https://datatracker.ietf.org/doc/html/rfc9562#section-5.1
|
||||
// 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.
|
||||
private const TIME_OFFSET_INT = 0x01B21DD213814000;
|
||||
private const TIME_OFFSET_BIN = "\x01\xb2\x1d\xd2\x13\x81\x40\x00";
|
||||
private const TIME_OFFSET_COM1 = "\xfe\x4d\xe2\x2d\xec\x7e\xbf\xff";
|
||||
private const TIME_OFFSET_COM2 = "\xfe\x4d\xe2\x2d\xec\x7e\xc0\x00";
|
||||
|
||||
public static function toBase(string $bytes, array $map): string
|
||||
{
|
||||
$base = \strlen($alphabet = $map['']);
|
||||
$bytes = array_values(unpack(\PHP_INT_SIZE >= 8 ? 'n*' : 'C*', $bytes));
|
||||
$digits = '';
|
||||
|
||||
while ($count = \count($bytes)) {
|
||||
$quotient = [];
|
||||
$remainder = 0;
|
||||
|
||||
for ($i = 0; $i !== $count; ++$i) {
|
||||
$carry = $bytes[$i] + ($remainder << (\PHP_INT_SIZE >= 8 ? 16 : 8));
|
||||
$digit = intdiv($carry, $base);
|
||||
$remainder = $carry % $base;
|
||||
|
||||
if ($digit || $quotient) {
|
||||
$quotient[] = $digit;
|
||||
}
|
||||
}
|
||||
|
||||
$digits = $alphabet[$remainder].$digits;
|
||||
$bytes = $quotient;
|
||||
}
|
||||
|
||||
return $digits;
|
||||
}
|
||||
|
||||
public static function fromBase(string $digits, array $map): string
|
||||
{
|
||||
$base = \strlen($map['']);
|
||||
$count = \strlen($digits);
|
||||
$bytes = [];
|
||||
|
||||
while ($count) {
|
||||
$quotient = [];
|
||||
$remainder = 0;
|
||||
|
||||
for ($i = 0; $i !== $count; ++$i) {
|
||||
$carry = ($bytes ? $digits[$i] : $map[$digits[$i]]) + $remainder * $base;
|
||||
|
||||
if (\PHP_INT_SIZE >= 8) {
|
||||
$digit = $carry >> 16;
|
||||
$remainder = $carry & 0xFFFF;
|
||||
} else {
|
||||
$digit = $carry >> 8;
|
||||
$remainder = $carry & 0xFF;
|
||||
}
|
||||
|
||||
if ($digit || $quotient) {
|
||||
$quotient[] = $digit;
|
||||
}
|
||||
}
|
||||
|
||||
$bytes[] = $remainder;
|
||||
$count = \count($digits = $quotient);
|
||||
}
|
||||
|
||||
return pack(\PHP_INT_SIZE >= 8 ? 'n*' : 'C*', ...array_reverse($bytes));
|
||||
}
|
||||
|
||||
public static function add(string $a, string $b): string
|
||||
{
|
||||
$carry = 0;
|
||||
for ($i = 7; 0 <= $i; --$i) {
|
||||
$carry += \ord($a[$i]) + \ord($b[$i]);
|
||||
$a[$i] = \chr($carry & 0xFF);
|
||||
$carry >>= 8;
|
||||
}
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $time Count of 100-nanosecond intervals since the UUID epoch 1582-10-15 00:00:00 in hexadecimal
|
||||
*/
|
||||
public static function hexToDateTime(string $time): \DateTimeImmutable
|
||||
{
|
||||
if (\PHP_INT_SIZE >= 8) {
|
||||
$time = (string) (hexdec($time) - self::TIME_OFFSET_INT);
|
||||
} else {
|
||||
$time = str_pad(hex2bin($time), 8, "\0", \STR_PAD_LEFT);
|
||||
|
||||
if (self::TIME_OFFSET_BIN <= $time) {
|
||||
$time = self::add($time, self::TIME_OFFSET_COM2);
|
||||
$time[0] = $time[0] & "\x7F";
|
||||
$time = self::toBase($time, self::BASE10);
|
||||
} else {
|
||||
$time = self::add($time, self::TIME_OFFSET_COM1);
|
||||
$time = '-'.self::toBase($time ^ "\xff\xff\xff\xff\xff\xff\xff\xff", self::BASE10);
|
||||
}
|
||||
}
|
||||
|
||||
if (9 > \strlen($time)) {
|
||||
$time = '-' === $time[0] ? '-'.str_pad(substr($time, 1), 8, '0', \STR_PAD_LEFT) : str_pad($time, 8, '0', \STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
return \DateTimeImmutable::createFromFormat('U.u?', substr_replace($time, '.', -7, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string Count of 100-nanosecond intervals since the UUID epoch 1582-10-15 00:00:00 in hexadecimal
|
||||
*/
|
||||
public static function dateTimeToHex(\DateTimeInterface $time): string
|
||||
{
|
||||
if (\PHP_INT_SIZE >= 8) {
|
||||
if (-self::TIME_OFFSET_INT > $time = (int) $time->format('Uu0')) {
|
||||
throw new \InvalidArgumentException('The given UUID date cannot be earlier than 1582-10-15.');
|
||||
}
|
||||
|
||||
return str_pad(dechex(self::TIME_OFFSET_INT + $time), 16, '0', \STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
$time = $time->format('Uu0');
|
||||
$negative = '-' === $time[0];
|
||||
if ($negative && self::TIME_OFFSET_INT < $time = substr($time, 1)) {
|
||||
throw new \InvalidArgumentException('The given UUID date cannot be earlier than 1582-10-15.');
|
||||
}
|
||||
$time = self::fromBase($time, self::BASE10);
|
||||
$time = str_pad($time, 8, "\0", \STR_PAD_LEFT);
|
||||
|
||||
if ($negative) {
|
||||
$time = self::add($time, self::TIME_OFFSET_COM1) ^ "\xff\xff\xff\xff\xff\xff\xff\xff";
|
||||
} else {
|
||||
$time = self::add($time, self::TIME_OFFSET_BIN);
|
||||
}
|
||||
|
||||
return bin2hex($time);
|
||||
}
|
||||
}
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Uid;
|
||||
|
||||
/**
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
*
|
||||
* @see https://datatracker.ietf.org/doc/html/rfc9562/#section-6.6 for details about namespaces
|
||||
*/
|
||||
class Uuid extends AbstractUid
|
||||
{
|
||||
public const NAMESPACE_DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
|
||||
public const NAMESPACE_URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
|
||||
public const NAMESPACE_OID = '6ba7b812-9dad-11d1-80b4-00c04fd430c8';
|
||||
public const NAMESPACE_X500 = '6ba7b814-9dad-11d1-80b4-00c04fd430c8';
|
||||
|
||||
protected const TYPE = 0;
|
||||
protected const NIL = '00000000-0000-0000-0000-000000000000';
|
||||
protected const MAX = 'ffffffff-ffff-ffff-ffff-ffffffffffff';
|
||||
|
||||
public function __construct(string $uuid, bool $checkVariant = false)
|
||||
{
|
||||
$type = preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di', $uuid) ? (int) $uuid[14] : false;
|
||||
|
||||
if (false === $type || (static::TYPE ?: $type) !== $type) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid UUID%s: "%s".', static::TYPE ? 'v'.static::TYPE : '', $uuid));
|
||||
}
|
||||
|
||||
$this->uid = strtolower($uuid);
|
||||
|
||||
if ($checkVariant && !\in_array($this->uid[19], ['8', '9', 'a', 'b'], true)) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid UUID%s: "%s".', static::TYPE ? 'v'.static::TYPE : '', $uuid));
|
||||
}
|
||||
}
|
||||
|
||||
public static function fromString(string $uuid): static
|
||||
{
|
||||
if (22 === \strlen($uuid) && 22 === strspn($uuid, BinaryUtil::BASE58[''])) {
|
||||
$uuid = str_pad(BinaryUtil::fromBase($uuid, BinaryUtil::BASE58), 16, "\0", \STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
if (16 === \strlen($uuid)) {
|
||||
// don't use uuid_unparse(), it's slower
|
||||
$uuid = bin2hex($uuid);
|
||||
$uuid = substr_replace($uuid, '-', 8, 0);
|
||||
$uuid = substr_replace($uuid, '-', 13, 0);
|
||||
$uuid = substr_replace($uuid, '-', 18, 0);
|
||||
$uuid = substr_replace($uuid, '-', 23, 0);
|
||||
} elseif (26 === \strlen($uuid) && Ulid::isValid($uuid)) {
|
||||
$ulid = new NilUlid();
|
||||
$ulid->uid = strtoupper($uuid);
|
||||
$uuid = $ulid->toRfc4122();
|
||||
}
|
||||
|
||||
if (__CLASS__ !== static::class || 36 !== \strlen($uuid)) {
|
||||
return new static($uuid);
|
||||
}
|
||||
|
||||
if (self::NIL === $uuid) {
|
||||
return new NilUuid();
|
||||
}
|
||||
|
||||
if (self::MAX === $uuid = strtr($uuid, 'F', 'f')) {
|
||||
return new MaxUuid();
|
||||
}
|
||||
|
||||
if (!\in_array($uuid[19], ['8', '9', 'a', 'b', 'A', 'B'], true)) {
|
||||
return new self($uuid);
|
||||
}
|
||||
|
||||
return match ((int) $uuid[14]) {
|
||||
UuidV1::TYPE => new UuidV1($uuid),
|
||||
UuidV3::TYPE => new UuidV3($uuid),
|
||||
UuidV4::TYPE => new UuidV4($uuid),
|
||||
UuidV5::TYPE => new UuidV5($uuid),
|
||||
UuidV6::TYPE => new UuidV6($uuid),
|
||||
UuidV7::TYPE => new UuidV7($uuid),
|
||||
UuidV8::TYPE => new UuidV8($uuid),
|
||||
default => new self($uuid),
|
||||
};
|
||||
}
|
||||
|
||||
final public static function v1(): UuidV1
|
||||
{
|
||||
return new UuidV1();
|
||||
}
|
||||
|
||||
final public static function v3(self $namespace, string $name): UuidV3
|
||||
{
|
||||
// don't use uuid_generate_md5(), some versions are buggy
|
||||
$uuid = md5(hex2bin(str_replace('-', '', $namespace->uid)).$name, true);
|
||||
|
||||
return new UuidV3(self::format($uuid, '-3'));
|
||||
}
|
||||
|
||||
final public static function v4(): UuidV4
|
||||
{
|
||||
return new UuidV4();
|
||||
}
|
||||
|
||||
final public static function v5(self $namespace, string $name): UuidV5
|
||||
{
|
||||
// don't use uuid_generate_sha1(), some versions are buggy
|
||||
$uuid = substr(sha1(hex2bin(str_replace('-', '', $namespace->uid)).$name, true), 0, 16);
|
||||
|
||||
return new UuidV5(self::format($uuid, '-5'));
|
||||
}
|
||||
|
||||
final public static function v6(): UuidV6
|
||||
{
|
||||
return new UuidV6();
|
||||
}
|
||||
|
||||
final public static function v7(): UuidV7
|
||||
{
|
||||
return new UuidV7();
|
||||
}
|
||||
|
||||
final public static function v8(string $uuid): UuidV8
|
||||
{
|
||||
return new UuidV8($uuid);
|
||||
}
|
||||
|
||||
public static function isValid(string $uuid): bool
|
||||
{
|
||||
if (self::NIL === $uuid && \in_array(static::class, [__CLASS__, NilUuid::class], true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (self::MAX === strtr($uuid, 'F', 'f') && \in_array(static::class, [__CLASS__, MaxUuid::class], true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){2}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$}Di', $uuid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return __CLASS__ === static::class || static::TYPE === (int) $uuid[14];
|
||||
}
|
||||
|
||||
public function toBinary(): string
|
||||
{
|
||||
return uuid_parse($this->uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier as a RFC 9562/4122 case insensitive string.
|
||||
*
|
||||
* @see https://datatracker.ietf.org/doc/html/rfc9562/#section-4
|
||||
*
|
||||
* @example 09748193-048a-4bfb-b825-8528cf74fdc1 (len=36)
|
||||
*/
|
||||
public function toRfc4122(): string
|
||||
{
|
||||
return $this->uid;
|
||||
}
|
||||
|
||||
public function compare(AbstractUid $other): int
|
||||
{
|
||||
if (false !== $cmp = uuid_compare($this->uid, $other->uid)) {
|
||||
return $cmp;
|
||||
}
|
||||
|
||||
return parent::compare($other);
|
||||
}
|
||||
|
||||
private static function format(string $uuid, string $version): string
|
||||
{
|
||||
$uuid[8] = $uuid[8] & "\x3F" | "\x80";
|
||||
$uuid = substr_replace(bin2hex($uuid), '-', 8, 0);
|
||||
$uuid = substr_replace($uuid, $version, 13, 1);
|
||||
$uuid = substr_replace($uuid, '-', 18, 0);
|
||||
|
||||
return substr_replace($uuid, '-', 23, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Uid;
|
||||
|
||||
/**
|
||||
* A v1 UUID contains a 60-bit timestamp and 62 extra unique bits.
|
||||
*
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
*/
|
||||
class UuidV1 extends Uuid implements TimeBasedUidInterface
|
||||
{
|
||||
protected const TYPE = 1;
|
||||
|
||||
private static string $clockSeq;
|
||||
|
||||
public function __construct(?string $uuid = null)
|
||||
{
|
||||
if (null === $uuid) {
|
||||
$this->uid = strtolower(uuid_create(static::TYPE));
|
||||
} else {
|
||||
parent::__construct($uuid, true);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDateTime(): \DateTimeImmutable
|
||||
{
|
||||
return BinaryUtil::hexToDateTime('0'.substr($this->uid, 15, 3).substr($this->uid, 9, 4).substr($this->uid, 0, 8));
|
||||
}
|
||||
|
||||
public function getNode(): string
|
||||
{
|
||||
return uuid_mac($this->uid);
|
||||
}
|
||||
|
||||
public static function generate(?\DateTimeInterface $time = null, ?Uuid $node = null): string
|
||||
{
|
||||
$uuid = !$time || !$node ? uuid_create(static::TYPE) : parent::NIL;
|
||||
|
||||
if ($time) {
|
||||
if ($node) {
|
||||
// use clock_seq from the node
|
||||
$seq = substr($node->uid, 19, 4);
|
||||
} elseif (!$seq = self::$clockSeq ?? '') {
|
||||
// generate a static random clock_seq to prevent any collisions with the real one
|
||||
$seq = substr($uuid, 19, 4);
|
||||
|
||||
do {
|
||||
self::$clockSeq = sprintf('%04x', random_int(0, 0x3FFF) | 0x8000);
|
||||
} while ($seq === self::$clockSeq);
|
||||
|
||||
$seq = self::$clockSeq;
|
||||
}
|
||||
|
||||
$time = BinaryUtil::dateTimeToHex($time);
|
||||
$uuid = substr($time, 8).'-'.substr($time, 4, 4).'-1'.substr($time, 1, 3).'-'.$seq.substr($uuid, 23);
|
||||
}
|
||||
|
||||
if ($node) {
|
||||
$uuid = substr($uuid, 0, 24).substr($node->uid, 24);
|
||||
}
|
||||
|
||||
return $uuid;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user