first commit
This commit is contained in:
176
vendor/symfony/uid/AbstractUid.php
vendored
Normal file
176
vendor/symfony/uid/AbstractUid.php
vendored
Normal file
@ -0,0 +1,176 @@
|
||||
<?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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 RFC4122 case insensitive string.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc4122#section-3
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
175
vendor/symfony/uid/BinaryUtil.php
vendored
Normal file
175
vendor/symfony/uid/BinaryUtil.php
vendored
Normal file
@ -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://tools.ietf.org/html/rfc4122#section-4.1.4
|
||||
// 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);
|
||||
}
|
||||
}
|
36
vendor/symfony/uid/CHANGELOG.md
vendored
Normal file
36
vendor/symfony/uid/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
6.2
|
||||
---
|
||||
|
||||
* Add `UuidV7` and `UuidV8`
|
||||
* Add `TimeBasedUidInterface` to describe UIDs that embed a timestamp
|
||||
* Add `MaxUuid` and `MaxUlid`
|
||||
|
||||
5.4
|
||||
---
|
||||
|
||||
* Add `NilUlid`
|
||||
|
||||
5.3
|
||||
---
|
||||
|
||||
* The component is not marked as `@experimental` anymore
|
||||
* Add `AbstractUid::fromBinary()`, `AbstractUid::fromBase58()`, `AbstractUid::fromBase32()` and `AbstractUid::fromRfc4122()`
|
||||
* [BC BREAK] Replace `UuidV1::getTime()`, `UuidV6::getTime()` and `Ulid::getTime()` by `UuidV1::getDateTime()`, `UuidV6::getDateTime()` and `Ulid::getDateTime()`
|
||||
* Add `Uuid::NAMESPACE_*` constants from RFC4122
|
||||
* Add `UlidFactory`, `UuidFactory`, `RandomBasedUuidFactory`, `TimeBasedUuidFactory` and `NameBasedUuidFactory`
|
||||
* Add commands to generate and inspect UUIDs and ULIDs
|
||||
|
||||
5.2.0
|
||||
-----
|
||||
|
||||
* made UUIDv6 always return truly random node fields to prevent leaking the MAC of the host
|
||||
|
||||
5.1.0
|
||||
-----
|
||||
|
||||
* added support for UUID
|
||||
* added support for ULID
|
||||
* added the component
|
119
vendor/symfony/uid/Command/GenerateUlidCommand.php
vendored
Normal file
119
vendor/symfony/uid/Command/GenerateUlidCommand.php
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
<?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\Command;
|
||||
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Completion\CompletionInput;
|
||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\Uid\Factory\UlidFactory;
|
||||
|
||||
#[AsCommand(name: 'ulid:generate', description: 'Generate a ULID')]
|
||||
class GenerateUlidCommand extends Command
|
||||
{
|
||||
private UlidFactory $factory;
|
||||
|
||||
public function __construct(?UlidFactory $factory = null)
|
||||
{
|
||||
$this->factory = $factory ?? new UlidFactory();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->setDefinition([
|
||||
new InputOption('time', null, InputOption::VALUE_REQUIRED, 'The ULID timestamp: a parsable date/time string'),
|
||||
new InputOption('count', 'c', InputOption::VALUE_REQUIRED, 'The number of ULID to generate', 1),
|
||||
new InputOption('format', 'f', InputOption::VALUE_REQUIRED, sprintf('The ULID output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'base32'),
|
||||
])
|
||||
->setHelp(<<<'EOF'
|
||||
The <info>%command.name%</info> command generates a ULID.
|
||||
|
||||
<info>php %command.full_name%</info>
|
||||
|
||||
To specify the timestamp:
|
||||
|
||||
<info>php %command.full_name% --time="2021-02-16 14:09:08"</info>
|
||||
|
||||
To generate several ULIDs:
|
||||
|
||||
<info>php %command.full_name% --count=10</info>
|
||||
|
||||
To output a specific format:
|
||||
|
||||
<info>php %command.full_name% --format=rfc4122</info>
|
||||
EOF
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
|
||||
|
||||
if (null !== $time = $input->getOption('time')) {
|
||||
try {
|
||||
$time = new \DateTimeImmutable($time);
|
||||
} catch (\Exception $e) {
|
||||
$io->error(sprintf('Invalid timestamp "%s": %s', $time, str_replace('DateTimeImmutable::__construct(): ', '', $e->getMessage())));
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
$formatOption = $input->getOption('format');
|
||||
|
||||
if (\in_array($formatOption, $this->getAvailableFormatOptions())) {
|
||||
$format = 'to'.ucfirst($formatOption);
|
||||
} else {
|
||||
$io->error(sprintf('Invalid format "%s", supported formats are "%s".', $formatOption, implode('", "', $this->getAvailableFormatOptions())));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$count = (int) $input->getOption('count');
|
||||
try {
|
||||
for ($i = 0; $i < $count; ++$i) {
|
||||
$output->writeln($this->factory->create($time)->$format());
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$io->error($e->getMessage());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
||||
{
|
||||
if ($input->mustSuggestOptionValuesFor('format')) {
|
||||
$suggestions->suggestValues($this->getAvailableFormatOptions());
|
||||
}
|
||||
}
|
||||
|
||||
private function getAvailableFormatOptions(): array
|
||||
{
|
||||
return [
|
||||
'base32',
|
||||
'base58',
|
||||
'rfc4122',
|
||||
];
|
||||
}
|
||||
}
|
208
vendor/symfony/uid/Command/GenerateUuidCommand.php
vendored
Normal file
208
vendor/symfony/uid/Command/GenerateUuidCommand.php
vendored
Normal file
@ -0,0 +1,208 @@
|
||||
<?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\Command;
|
||||
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Completion\CompletionInput;
|
||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\Uid\Factory\UuidFactory;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
|
||||
#[AsCommand(name: 'uuid:generate', description: 'Generate a UUID')]
|
||||
class GenerateUuidCommand extends Command
|
||||
{
|
||||
private UuidFactory $factory;
|
||||
|
||||
public function __construct(?UuidFactory $factory = null)
|
||||
{
|
||||
$this->factory = $factory ?? new UuidFactory();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->setDefinition([
|
||||
new InputOption('time-based', null, InputOption::VALUE_REQUIRED, 'The timestamp, to generate a time-based UUID: a parsable date/time string'),
|
||||
new InputOption('node', null, InputOption::VALUE_REQUIRED, 'The UUID whose node part should be used as the node of the generated UUID'),
|
||||
new InputOption('name-based', null, InputOption::VALUE_REQUIRED, 'The name, to generate a name-based UUID'),
|
||||
new InputOption('namespace', null, InputOption::VALUE_REQUIRED, 'The UUID to use at the namespace for named-based UUIDs, predefined namespaces keywords "dns", "url", "oid" and "x500" are accepted'),
|
||||
new InputOption('random-based', null, InputOption::VALUE_NONE, 'To generate a random-based UUID'),
|
||||
new InputOption('count', 'c', InputOption::VALUE_REQUIRED, 'The number of UUID to generate', 1),
|
||||
new InputOption('format', 'f', InputOption::VALUE_REQUIRED, sprintf('The UUID output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'rfc4122'),
|
||||
])
|
||||
->setHelp(<<<'EOF'
|
||||
The <info>%command.name%</info> generates a UUID.
|
||||
|
||||
<info>php %command.full_name%</info>
|
||||
|
||||
To generate a time-based UUID:
|
||||
|
||||
<info>php %command.full_name% --time-based=now</info>
|
||||
|
||||
To specify a time-based UUID's node:
|
||||
|
||||
<info>php %command.full_name% --time-based=@1613480254 --node=fb3502dc-137e-4849-8886-ac90d07f64a7</info>
|
||||
|
||||
To generate a name-based UUID:
|
||||
|
||||
<info>php %command.full_name% --name-based=foo</info>
|
||||
|
||||
To specify a name-based UUID's namespace:
|
||||
|
||||
<info>php %command.full_name% --name-based=bar --namespace=fb3502dc-137e-4849-8886-ac90d07f64a7</info>
|
||||
|
||||
To generate a random-based UUID:
|
||||
|
||||
<info>php %command.full_name% --random-based</info>
|
||||
|
||||
To generate several UUIDs:
|
||||
|
||||
<info>php %command.full_name% --count=10</info>
|
||||
|
||||
To output a specific format:
|
||||
|
||||
<info>php %command.full_name% --format=base58</info>
|
||||
EOF
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
|
||||
|
||||
$time = $input->getOption('time-based');
|
||||
$node = $input->getOption('node');
|
||||
$name = $input->getOption('name-based');
|
||||
$namespace = $input->getOption('namespace');
|
||||
$random = $input->getOption('random-based');
|
||||
|
||||
if (false !== ($time ?? $name ?? $random) && 1 < ((null !== $time) + (null !== $name) + $random)) {
|
||||
$io->error('Only one of "--time-based", "--name-based" or "--random-based" can be provided at a time.');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (null === $time && null !== $node) {
|
||||
$io->error('Option "--node" can only be used with "--time-based".');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (null === $name && null !== $namespace) {
|
||||
$io->error('Option "--namespace" can only be used with "--name-based".');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (true) {
|
||||
case null !== $time:
|
||||
if (null !== $node) {
|
||||
try {
|
||||
$node = Uuid::fromString($node);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$io->error(sprintf('Invalid node "%s": %s', $node, $e->getMessage()));
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
new \DateTimeImmutable($time);
|
||||
} catch (\Exception $e) {
|
||||
$io->error(sprintf('Invalid timestamp "%s": %s', $time, str_replace('DateTimeImmutable::__construct(): ', '', $e->getMessage())));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$create = fn (): Uuid => $this->factory->timeBased($node)->create(new \DateTimeImmutable($time));
|
||||
break;
|
||||
|
||||
case null !== $name:
|
||||
if ($namespace && !\in_array($namespace, ['dns', 'url', 'oid', 'x500'], true)) {
|
||||
try {
|
||||
$namespace = Uuid::fromString($namespace);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$io->error(sprintf('Invalid namespace "%s": %s', $namespace, $e->getMessage()));
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
$create = function () use ($namespace, $name): Uuid {
|
||||
try {
|
||||
$factory = $this->factory->nameBased($namespace);
|
||||
} catch (\LogicException) {
|
||||
throw new \InvalidArgumentException('Missing namespace: use the "--namespace" option or configure a default namespace in the underlying factory.');
|
||||
}
|
||||
|
||||
return $factory->create($name);
|
||||
};
|
||||
break;
|
||||
|
||||
case $random:
|
||||
$create = $this->factory->randomBased()->create(...);
|
||||
break;
|
||||
|
||||
default:
|
||||
$create = $this->factory->create(...);
|
||||
break;
|
||||
}
|
||||
|
||||
$formatOption = $input->getOption('format');
|
||||
|
||||
if (\in_array($formatOption, $this->getAvailableFormatOptions())) {
|
||||
$format = 'to'.ucfirst($formatOption);
|
||||
} else {
|
||||
$io->error(sprintf('Invalid format "%s", supported formats are "%s".', $formatOption, implode('", "', $this->getAvailableFormatOptions())));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$count = (int) $input->getOption('count');
|
||||
try {
|
||||
for ($i = 0; $i < $count; ++$i) {
|
||||
$output->writeln($create()->$format());
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$io->error($e->getMessage());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
||||
{
|
||||
if ($input->mustSuggestOptionValuesFor('format')) {
|
||||
$suggestions->suggestValues($this->getAvailableFormatOptions());
|
||||
}
|
||||
}
|
||||
|
||||
private function getAvailableFormatOptions(): array
|
||||
{
|
||||
return [
|
||||
'base32',
|
||||
'base58',
|
||||
'rfc4122',
|
||||
];
|
||||
}
|
||||
}
|
67
vendor/symfony/uid/Command/InspectUlidCommand.php
vendored
Normal file
67
vendor/symfony/uid/Command/InspectUlidCommand.php
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
<?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\Command;
|
||||
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\TableSeparator;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\Uid\Ulid;
|
||||
|
||||
#[AsCommand(name: 'ulid:inspect', description: 'Inspect a ULID')]
|
||||
class InspectUlidCommand extends Command
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->setDefinition([
|
||||
new InputArgument('ulid', InputArgument::REQUIRED, 'The ULID to inspect'),
|
||||
])
|
||||
->setHelp(<<<'EOF'
|
||||
The <info>%command.name%</info> displays information about a ULID.
|
||||
|
||||
<info>php %command.full_name% 01EWAKBCMWQ2C94EXNN60ZBS0Q</info>
|
||||
<info>php %command.full_name% 1BVdfLn3ERmbjYBLCdaaLW</info>
|
||||
<info>php %command.full_name% 01771535-b29c-b898-923b-b5a981f5e417</info>
|
||||
EOF
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
|
||||
|
||||
try {
|
||||
$ulid = Ulid::fromString($input->getArgument('ulid'));
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$io->error($e->getMessage());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$io->table(['Label', 'Value'], [
|
||||
['toBase32 (canonical)', (string) $ulid],
|
||||
['toBase58', $ulid->toBase58()],
|
||||
['toRfc4122', $ulid->toRfc4122()],
|
||||
['toHex', $ulid->toHex()],
|
||||
new TableSeparator(),
|
||||
['Time', $ulid->getDateTime()->format('Y-m-d H:i:s.v \U\T\C')],
|
||||
]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
85
vendor/symfony/uid/Command/InspectUuidCommand.php
vendored
Normal file
85
vendor/symfony/uid/Command/InspectUuidCommand.php
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
<?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\Command;
|
||||
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\TableSeparator;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\Uid\MaxUuid;
|
||||
use Symfony\Component\Uid\NilUuid;
|
||||
use Symfony\Component\Uid\TimeBasedUidInterface;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
|
||||
#[AsCommand(name: 'uuid:inspect', description: 'Inspect a UUID')]
|
||||
class InspectUuidCommand extends Command
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->setDefinition([
|
||||
new InputArgument('uuid', InputArgument::REQUIRED, 'The UUID to inspect'),
|
||||
])
|
||||
->setHelp(<<<'EOF'
|
||||
The <info>%command.name%</info> displays information about a UUID.
|
||||
|
||||
<info>php %command.full_name% a7613e0a-5986-11eb-a861-2bf05af69e52</info>
|
||||
<info>php %command.full_name% MfnmaUvvQ1h8B14vTwt6dX</info>
|
||||
<info>php %command.full_name% 57C4Z0MPC627NTGR9BY1DFD7JJ</info>
|
||||
EOF
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
|
||||
|
||||
try {
|
||||
/** @var Uuid $uuid */
|
||||
$uuid = Uuid::fromString($input->getArgument('uuid'));
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$io->error($e->getMessage());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (new NilUuid() == $uuid) {
|
||||
$version = 'nil';
|
||||
} elseif (new MaxUuid() == $uuid) {
|
||||
$version = 'max';
|
||||
} else {
|
||||
$version = uuid_type($uuid);
|
||||
}
|
||||
|
||||
$rows = [
|
||||
['Version', $version],
|
||||
['toRfc4122 (canonical)', (string) $uuid],
|
||||
['toBase58', $uuid->toBase58()],
|
||||
['toBase32', $uuid->toBase32()],
|
||||
['toHex', $uuid->toHex()],
|
||||
];
|
||||
|
||||
if ($uuid instanceof TimeBasedUidInterface) {
|
||||
$rows[] = new TableSeparator();
|
||||
$rows[] = ['Time', $uuid->getDateTime()->format('Y-m-d H:i:s.u \U\T\C')];
|
||||
}
|
||||
|
||||
$io->table(['Label', 'Value'], $rows);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
44
vendor/symfony/uid/Factory/NameBasedUuidFactory.php
vendored
Normal file
44
vendor/symfony/uid/Factory/NameBasedUuidFactory.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\Factory;
|
||||
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
use Symfony\Component\Uid\UuidV3;
|
||||
use Symfony\Component\Uid\UuidV5;
|
||||
|
||||
class NameBasedUuidFactory
|
||||
{
|
||||
private string $class;
|
||||
private Uuid $namespace;
|
||||
|
||||
public function __construct(string $class, Uuid $namespace)
|
||||
{
|
||||
$this->class = $class;
|
||||
$this->namespace = $namespace;
|
||||
}
|
||||
|
||||
public function create(string $name): UuidV5|UuidV3
|
||||
{
|
||||
switch ($class = $this->class) {
|
||||
case UuidV5::class: return Uuid::v5($this->namespace, $name);
|
||||
case UuidV3::class: return Uuid::v3($this->namespace, $name);
|
||||
}
|
||||
|
||||
if (is_subclass_of($class, UuidV5::class)) {
|
||||
$uuid = Uuid::v5($this->namespace, $name);
|
||||
} else {
|
||||
$uuid = Uuid::v3($this->namespace, $name);
|
||||
}
|
||||
|
||||
return new $class($uuid);
|
||||
}
|
||||
}
|
31
vendor/symfony/uid/Factory/RandomBasedUuidFactory.php
vendored
Normal file
31
vendor/symfony/uid/Factory/RandomBasedUuidFactory.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?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\Factory;
|
||||
|
||||
use Symfony\Component\Uid\UuidV4;
|
||||
|
||||
class RandomBasedUuidFactory
|
||||
{
|
||||
private string $class;
|
||||
|
||||
public function __construct(string $class)
|
||||
{
|
||||
$this->class = $class;
|
||||
}
|
||||
|
||||
public function create(): UuidV4
|
||||
{
|
||||
$class = $this->class;
|
||||
|
||||
return new $class();
|
||||
}
|
||||
}
|
44
vendor/symfony/uid/Factory/TimeBasedUuidFactory.php
vendored
Normal file
44
vendor/symfony/uid/Factory/TimeBasedUuidFactory.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\Factory;
|
||||
|
||||
use Symfony\Component\Uid\TimeBasedUidInterface;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
|
||||
class TimeBasedUuidFactory
|
||||
{
|
||||
/**
|
||||
* @var class-string<Uuid&TimeBasedUidInterface>
|
||||
*/
|
||||
private string $class;
|
||||
private ?Uuid $node;
|
||||
|
||||
/**
|
||||
* @param class-string<Uuid&TimeBasedUidInterface> $class
|
||||
*/
|
||||
public function __construct(string $class, ?Uuid $node = null)
|
||||
{
|
||||
$this->class = $class;
|
||||
$this->node = $node;
|
||||
}
|
||||
|
||||
public function create(?\DateTimeInterface $time = null): Uuid&TimeBasedUidInterface
|
||||
{
|
||||
$class = $this->class;
|
||||
|
||||
if (null === $time && null === $this->node) {
|
||||
return new $class();
|
||||
}
|
||||
|
||||
return new $class($class::generate($time, $this->node));
|
||||
}
|
||||
}
|
22
vendor/symfony/uid/Factory/UlidFactory.php
vendored
Normal file
22
vendor/symfony/uid/Factory/UlidFactory.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?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\Factory;
|
||||
|
||||
use Symfony\Component\Uid\Ulid;
|
||||
|
||||
class UlidFactory
|
||||
{
|
||||
public function create(?\DateTimeInterface $time = null): Ulid
|
||||
{
|
||||
return new Ulid(null === $time ? null : Ulid::generate($time));
|
||||
}
|
||||
}
|
95
vendor/symfony/uid/Factory/UuidFactory.php
vendored
Normal file
95
vendor/symfony/uid/Factory/UuidFactory.php
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
<?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\Factory;
|
||||
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
use Symfony\Component\Uid\UuidV1;
|
||||
use Symfony\Component\Uid\UuidV4;
|
||||
use Symfony\Component\Uid\UuidV5;
|
||||
use Symfony\Component\Uid\UuidV6;
|
||||
|
||||
class UuidFactory
|
||||
{
|
||||
private string $defaultClass;
|
||||
private string $timeBasedClass;
|
||||
private string $nameBasedClass;
|
||||
private string $randomBasedClass;
|
||||
private ?Uuid $timeBasedNode;
|
||||
private ?Uuid $nameBasedNamespace;
|
||||
|
||||
public function __construct(string|int $defaultClass = UuidV6::class, string|int $timeBasedClass = UuidV6::class, string|int $nameBasedClass = UuidV5::class, string|int $randomBasedClass = UuidV4::class, Uuid|string|null $timeBasedNode = null, Uuid|string|null $nameBasedNamespace = null)
|
||||
{
|
||||
if (null !== $timeBasedNode && !$timeBasedNode instanceof Uuid) {
|
||||
$timeBasedNode = Uuid::fromString($timeBasedNode);
|
||||
}
|
||||
|
||||
if (null !== $nameBasedNamespace) {
|
||||
$nameBasedNamespace = $this->getNamespace($nameBasedNamespace);
|
||||
}
|
||||
|
||||
$this->defaultClass = is_numeric($defaultClass) ? Uuid::class.'V'.$defaultClass : $defaultClass;
|
||||
$this->timeBasedClass = is_numeric($timeBasedClass) ? Uuid::class.'V'.$timeBasedClass : $timeBasedClass;
|
||||
$this->nameBasedClass = is_numeric($nameBasedClass) ? Uuid::class.'V'.$nameBasedClass : $nameBasedClass;
|
||||
$this->randomBasedClass = is_numeric($randomBasedClass) ? Uuid::class.'V'.$randomBasedClass : $randomBasedClass;
|
||||
$this->timeBasedNode = $timeBasedNode;
|
||||
$this->nameBasedNamespace = $nameBasedNamespace;
|
||||
}
|
||||
|
||||
public function create(): Uuid
|
||||
{
|
||||
$class = $this->defaultClass;
|
||||
|
||||
return new $class();
|
||||
}
|
||||
|
||||
public function randomBased(): RandomBasedUuidFactory
|
||||
{
|
||||
return new RandomBasedUuidFactory($this->randomBasedClass);
|
||||
}
|
||||
|
||||
public function timeBased(Uuid|string|null $node = null): TimeBasedUuidFactory
|
||||
{
|
||||
$node ??= $this->timeBasedNode;
|
||||
|
||||
if (null !== $node && !$node instanceof Uuid) {
|
||||
$node = Uuid::fromString($node);
|
||||
}
|
||||
|
||||
return new TimeBasedUuidFactory($this->timeBasedClass, $node);
|
||||
}
|
||||
|
||||
public function nameBased(Uuid|string|null $namespace = null): NameBasedUuidFactory
|
||||
{
|
||||
$namespace ??= $this->nameBasedNamespace;
|
||||
|
||||
if (null === $namespace) {
|
||||
throw new \LogicException(sprintf('A namespace should be defined when using "%s()".', __METHOD__));
|
||||
}
|
||||
|
||||
return new NameBasedUuidFactory($this->nameBasedClass, $this->getNamespace($namespace));
|
||||
}
|
||||
|
||||
private function getNamespace(Uuid|string $namespace): Uuid
|
||||
{
|
||||
if ($namespace instanceof Uuid) {
|
||||
return $namespace;
|
||||
}
|
||||
|
||||
return match ($namespace) {
|
||||
'dns' => new UuidV1(Uuid::NAMESPACE_DNS),
|
||||
'url' => new UuidV1(Uuid::NAMESPACE_URL),
|
||||
'oid' => new UuidV1(Uuid::NAMESPACE_OID),
|
||||
'x500' => new UuidV1(Uuid::NAMESPACE_X500),
|
||||
default => Uuid::fromString($namespace),
|
||||
};
|
||||
}
|
||||
}
|
19
vendor/symfony/uid/LICENSE
vendored
Normal file
19
vendor/symfony/uid/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2020-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
20
vendor/symfony/uid/MaxUlid.php
vendored
Normal file
20
vendor/symfony/uid/MaxUlid.php
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<?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;
|
||||
|
||||
class MaxUlid extends Ulid
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->uid = parent::MAX;
|
||||
}
|
||||
}
|
22
vendor/symfony/uid/MaxUuid.php
vendored
Normal file
22
vendor/symfony/uid/MaxUuid.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?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;
|
||||
|
||||
class MaxUuid extends Uuid
|
||||
{
|
||||
protected const TYPE = -1;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->uid = parent::MAX;
|
||||
}
|
||||
}
|
20
vendor/symfony/uid/NilUlid.php
vendored
Normal file
20
vendor/symfony/uid/NilUlid.php
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<?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;
|
||||
|
||||
class NilUlid extends Ulid
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->uid = parent::NIL;
|
||||
}
|
||||
}
|
25
vendor/symfony/uid/NilUuid.php
vendored
Normal file
25
vendor/symfony/uid/NilUuid.php
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
<?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>
|
||||
*/
|
||||
class NilUuid extends Uuid
|
||||
{
|
||||
protected const TYPE = -1;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->uid = parent::NIL;
|
||||
}
|
||||
}
|
16
vendor/symfony/uid/README.md
vendored
Normal file
16
vendor/symfony/uid/README.md
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
Uid Component
|
||||
=============
|
||||
|
||||
The UID component provides an object-oriented API to generate and represent UIDs.
|
||||
|
||||
It provides implementations that work on 32-bit and 64-bit CPUs
|
||||
for ULIDs and for UUIDs version 1 and versions 3 to 8.
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* [Documentation](https://symfony.com/doc/current/components/uid.html)
|
||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||
in the [main Symfony repository](https://github.com/symfony/symfony)
|
22
vendor/symfony/uid/TimeBasedUidInterface.php
vendored
Normal file
22
vendor/symfony/uid/TimeBasedUidInterface.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Interface to describe UIDs that contain a DateTimeImmutable as part of their behaviour.
|
||||
*
|
||||
* @author Barney Hanlon <barney.hanlon@cushon.co.uk>
|
||||
*/
|
||||
interface TimeBasedUidInterface
|
||||
{
|
||||
public function getDateTime(): \DateTimeImmutable;
|
||||
}
|
208
vendor/symfony/uid/Ulid.php
vendored
Normal file
208
vendor/symfony/uid/Ulid.php
vendored
Normal file
@ -0,0 +1,208 @@
|
||||
<?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 ULID is lexicographically sortable and contains a 48-bit timestamp and 80-bit of crypto-random entropy.
|
||||
*
|
||||
* @see https://github.com/ulid/spec
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class Ulid extends AbstractUid implements TimeBasedUidInterface
|
||||
{
|
||||
protected const NIL = '00000000000000000000000000';
|
||||
protected const MAX = '7ZZZZZZZZZZZZZZZZZZZZZZZZZ';
|
||||
|
||||
private static string $time = '';
|
||||
private static array $rand = [];
|
||||
|
||||
public function __construct(?string $ulid = null)
|
||||
{
|
||||
if (null === $ulid) {
|
||||
$this->uid = static::generate();
|
||||
} elseif (self::NIL === $ulid) {
|
||||
$this->uid = $ulid;
|
||||
} elseif (self::MAX === strtr($ulid, 'z', 'Z')) {
|
||||
$this->uid = $ulid;
|
||||
} else {
|
||||
if (!self::isValid($ulid)) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid ULID: "%s".', $ulid));
|
||||
}
|
||||
|
||||
$this->uid = strtoupper($ulid);
|
||||
}
|
||||
}
|
||||
|
||||
public static function isValid(string $ulid): bool
|
||||
{
|
||||
if (26 !== \strlen($ulid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (26 !== strspn($ulid, '0123456789ABCDEFGHJKMNPQRSTVWXYZabcdefghjkmnpqrstvwxyz')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $ulid[0] <= '7';
|
||||
}
|
||||
|
||||
public static function fromString(string $ulid): static
|
||||
{
|
||||
if (36 === \strlen($ulid) && preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di', $ulid)) {
|
||||
$ulid = uuid_parse($ulid);
|
||||
} elseif (22 === \strlen($ulid) && 22 === strspn($ulid, BinaryUtil::BASE58[''])) {
|
||||
$ulid = str_pad(BinaryUtil::fromBase($ulid, BinaryUtil::BASE58), 16, "\0", \STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
if (16 !== \strlen($ulid)) {
|
||||
return match (strtr($ulid, 'z', 'Z')) {
|
||||
self::NIL => new NilUlid(),
|
||||
self::MAX => new MaxUlid(),
|
||||
default => new static($ulid),
|
||||
};
|
||||
}
|
||||
|
||||
$ulid = bin2hex($ulid);
|
||||
$ulid = sprintf('%02s%04s%04s%04s%04s%04s%04s',
|
||||
base_convert(substr($ulid, 0, 2), 16, 32),
|
||||
base_convert(substr($ulid, 2, 5), 16, 32),
|
||||
base_convert(substr($ulid, 7, 5), 16, 32),
|
||||
base_convert(substr($ulid, 12, 5), 16, 32),
|
||||
base_convert(substr($ulid, 17, 5), 16, 32),
|
||||
base_convert(substr($ulid, 22, 5), 16, 32),
|
||||
base_convert(substr($ulid, 27, 5), 16, 32)
|
||||
);
|
||||
|
||||
if (self::NIL === $ulid) {
|
||||
return new NilUlid();
|
||||
}
|
||||
|
||||
if (self::MAX === $ulid = strtr($ulid, 'abcdefghijklmnopqrstuv', 'ABCDEFGHJKMNPQRSTVWXYZ')) {
|
||||
return new MaxUlid();
|
||||
}
|
||||
|
||||
$u = new static(self::NIL);
|
||||
$u->uid = $ulid;
|
||||
|
||||
return $u;
|
||||
}
|
||||
|
||||
public function toBinary(): string
|
||||
{
|
||||
$ulid = strtr($this->uid, 'ABCDEFGHJKMNPQRSTVWXYZ', 'abcdefghijklmnopqrstuv');
|
||||
|
||||
$ulid = sprintf('%02s%05s%05s%05s%05s%05s%05s',
|
||||
base_convert(substr($ulid, 0, 2), 32, 16),
|
||||
base_convert(substr($ulid, 2, 4), 32, 16),
|
||||
base_convert(substr($ulid, 6, 4), 32, 16),
|
||||
base_convert(substr($ulid, 10, 4), 32, 16),
|
||||
base_convert(substr($ulid, 14, 4), 32, 16),
|
||||
base_convert(substr($ulid, 18, 4), 32, 16),
|
||||
base_convert(substr($ulid, 22, 4), 32, 16)
|
||||
);
|
||||
|
||||
return hex2bin($ulid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
return $this->uid;
|
||||
}
|
||||
|
||||
public function getDateTime(): \DateTimeImmutable
|
||||
{
|
||||
$time = strtr(substr($this->uid, 0, 10), 'ABCDEFGHJKMNPQRSTVWXYZ', 'abcdefghijklmnopqrstuv');
|
||||
|
||||
if (\PHP_INT_SIZE >= 8) {
|
||||
$time = (string) hexdec(base_convert($time, 32, 16));
|
||||
} else {
|
||||
$time = sprintf('%02s%05s%05s',
|
||||
base_convert(substr($time, 0, 2), 32, 16),
|
||||
base_convert(substr($time, 2, 4), 32, 16),
|
||||
base_convert(substr($time, 6, 4), 32, 16)
|
||||
);
|
||||
$time = BinaryUtil::toBase(hex2bin($time), BinaryUtil::BASE10);
|
||||
}
|
||||
|
||||
if (4 > \strlen($time)) {
|
||||
$time = '000'.$time;
|
||||
}
|
||||
|
||||
return \DateTimeImmutable::createFromFormat('U.u', substr_replace($time, '.', -3, 0));
|
||||
}
|
||||
|
||||
public static function generate(?\DateTimeInterface $time = null): string
|
||||
{
|
||||
if (null === $mtime = $time) {
|
||||
$time = microtime(false);
|
||||
$time = substr($time, 11).substr($time, 2, 3);
|
||||
} elseif (0 > $time = $time->format('Uv')) {
|
||||
throw new \InvalidArgumentException('The timestamp must be positive.');
|
||||
}
|
||||
|
||||
if ($time > self::$time || (null !== $mtime && $time !== self::$time)) {
|
||||
randomize:
|
||||
$r = unpack('n*', random_bytes(10));
|
||||
$r[1] |= ($r[5] <<= 4) & 0xF0000;
|
||||
$r[2] |= ($r[5] <<= 4) & 0xF0000;
|
||||
$r[3] |= ($r[5] <<= 4) & 0xF0000;
|
||||
$r[4] |= ($r[5] <<= 4) & 0xF0000;
|
||||
unset($r[5]);
|
||||
self::$rand = $r;
|
||||
self::$time = $time;
|
||||
} elseif ([1 => 0xFFFFF, 0xFFFFF, 0xFFFFF, 0xFFFFF] === self::$rand) {
|
||||
if (\PHP_INT_SIZE >= 8 || 10 > \strlen($time = self::$time)) {
|
||||
$time = (string) (1 + $time);
|
||||
} elseif ('999999999' === $mtime = substr($time, -9)) {
|
||||
$time = (1 + substr($time, 0, -9)).'000000000';
|
||||
} else {
|
||||
$time = substr_replace($time, str_pad(++$mtime, 9, '0', \STR_PAD_LEFT), -9);
|
||||
}
|
||||
|
||||
goto randomize;
|
||||
} else {
|
||||
for ($i = 4; $i > 0 && 0xFFFFF === self::$rand[$i]; --$i) {
|
||||
self::$rand[$i] = 0;
|
||||
}
|
||||
|
||||
++self::$rand[$i];
|
||||
$time = self::$time;
|
||||
}
|
||||
|
||||
if (\PHP_INT_SIZE >= 8) {
|
||||
$time = base_convert($time, 10, 32);
|
||||
} else {
|
||||
$time = str_pad(bin2hex(BinaryUtil::fromBase($time, BinaryUtil::BASE10)), 12, '0', \STR_PAD_LEFT);
|
||||
$time = sprintf('%s%04s%04s',
|
||||
base_convert(substr($time, 0, 2), 16, 32),
|
||||
base_convert(substr($time, 2, 5), 16, 32),
|
||||
base_convert(substr($time, 7, 5), 16, 32)
|
||||
);
|
||||
}
|
||||
|
||||
return strtr(sprintf('%010s%04s%04s%04s%04s',
|
||||
$time,
|
||||
base_convert(self::$rand[1], 10, 32),
|
||||
base_convert(self::$rand[2], 10, 32),
|
||||
base_convert(self::$rand[3], 10, 32),
|
||||
base_convert(self::$rand[4], 10, 32)
|
||||
), 'abcdefghijklmnopqrstuv', 'ABCDEFGHJKMNPQRSTVWXYZ');
|
||||
}
|
||||
}
|
185
vendor/symfony/uid/Uuid.php
vendored
Normal file
185
vendor/symfony/uid/Uuid.php
vendored
Normal file
@ -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://tools.ietf.org/html/rfc4122#appendix-C 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 RFC4122 case insensitive string.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc4122#section-3
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
73
vendor/symfony/uid/UuidV1.php
vendored
Normal file
73
vendor/symfony/uid/UuidV1.php
vendored
Normal file
@ -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 = 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;
|
||||
}
|
||||
}
|
29
vendor/symfony/uid/UuidV3.php
vendored
Normal file
29
vendor/symfony/uid/UuidV3.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?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 v3 UUID contains an MD5 hash of another UUID and a name.
|
||||
*
|
||||
* Use Uuid::v3() to compute one.
|
||||
*
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
*/
|
||||
class UuidV3 extends Uuid
|
||||
{
|
||||
protected const TYPE = 3;
|
||||
|
||||
public function __construct(string $uuid)
|
||||
{
|
||||
parent::__construct($uuid, true);
|
||||
}
|
||||
}
|
36
vendor/symfony/uid/UuidV4.php
vendored
Normal file
36
vendor/symfony/uid/UuidV4.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?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 v4 UUID contains a 122-bit random number.
|
||||
*
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
*/
|
||||
class UuidV4 extends Uuid
|
||||
{
|
||||
protected const TYPE = 4;
|
||||
|
||||
public function __construct(?string $uuid = null)
|
||||
{
|
||||
if (null === $uuid) {
|
||||
$uuid = random_bytes(16);
|
||||
$uuid[6] = $uuid[6] & "\x0F" | "\x40";
|
||||
$uuid[8] = $uuid[8] & "\x3F" | "\x80";
|
||||
$uuid = bin2hex($uuid);
|
||||
|
||||
$this->uid = substr($uuid, 0, 8).'-'.substr($uuid, 8, 4).'-'.substr($uuid, 12, 4).'-'.substr($uuid, 16, 4).'-'.substr($uuid, 20, 12);
|
||||
} else {
|
||||
parent::__construct($uuid, true);
|
||||
}
|
||||
}
|
||||
}
|
29
vendor/symfony/uid/UuidV5.php
vendored
Normal file
29
vendor/symfony/uid/UuidV5.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?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 v5 UUID contains a SHA1 hash of another UUID and a name.
|
||||
*
|
||||
* Use Uuid::v5() to compute one.
|
||||
*
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
*/
|
||||
class UuidV5 extends Uuid
|
||||
{
|
||||
protected const TYPE = 5;
|
||||
|
||||
public function __construct(string $uuid)
|
||||
{
|
||||
parent::__construct($uuid, true);
|
||||
}
|
||||
}
|
66
vendor/symfony/uid/UuidV6.php
vendored
Normal file
66
vendor/symfony/uid/UuidV6.php
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
<?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 v6 UUID is lexicographically sortable and contains a 60-bit timestamp and 62 extra unique bits.
|
||||
*
|
||||
* Unlike UUIDv1, this implementation of UUIDv6 doesn't leak the MAC address of the host.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class UuidV6 extends Uuid implements TimeBasedUidInterface
|
||||
{
|
||||
protected const TYPE = 6;
|
||||
|
||||
private static string $node;
|
||||
|
||||
public function __construct(?string $uuid = null)
|
||||
{
|
||||
if (null === $uuid) {
|
||||
$this->uid = static::generate();
|
||||
} else {
|
||||
parent::__construct($uuid, true);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDateTime(): \DateTimeImmutable
|
||||
{
|
||||
return BinaryUtil::hexToDateTime('0'.substr($this->uid, 0, 8).substr($this->uid, 9, 4).substr($this->uid, 15, 3));
|
||||
}
|
||||
|
||||
public function getNode(): string
|
||||
{
|
||||
return substr($this->uid, 24);
|
||||
}
|
||||
|
||||
public static function generate(?\DateTimeInterface $time = null, ?Uuid $node = null): string
|
||||
{
|
||||
$uuidV1 = UuidV1::generate($time, $node);
|
||||
$uuid = substr($uuidV1, 15, 3).substr($uuidV1, 9, 4).$uuidV1[0].'-'.substr($uuidV1, 1, 4).'-6'.substr($uuidV1, 5, 3).substr($uuidV1, 18, 6);
|
||||
|
||||
if ($node) {
|
||||
return $uuid.substr($uuidV1, 24);
|
||||
}
|
||||
|
||||
// uuid_create() returns a stable "node" that can leak the MAC of the host, but
|
||||
// UUIDv6 prefers a truly random number here, let's XOR both to preserve the entropy
|
||||
|
||||
if (!isset(self::$node)) {
|
||||
$seed = [random_int(0, 0xFFFFFF), random_int(0, 0xFFFFFF)];
|
||||
$node = unpack('N2', hex2bin('00'.substr($uuidV1, 24, 6)).hex2bin('00'.substr($uuidV1, 30)));
|
||||
self::$node = sprintf('%06x%06x', ($seed[0] ^ $node[1]) | 0x010000, $seed[1] ^ $node[2]);
|
||||
}
|
||||
|
||||
return $uuid.self::$node;
|
||||
}
|
||||
}
|
125
vendor/symfony/uid/UuidV7.php
vendored
Normal file
125
vendor/symfony/uid/UuidV7.php
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
<?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 v7 UUID is lexicographically sortable and contains a 48-bit timestamp and 74 extra unique bits.
|
||||
*
|
||||
* Within the same millisecond, monotonicity is ensured by incrementing the random part by a random increment.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class UuidV7 extends Uuid implements TimeBasedUidInterface
|
||||
{
|
||||
protected const TYPE = 7;
|
||||
|
||||
private static string $time = '';
|
||||
private static array $rand = [];
|
||||
private static string $seed;
|
||||
private static array $seedParts;
|
||||
private static int $seedIndex = 0;
|
||||
|
||||
public function __construct(?string $uuid = null)
|
||||
{
|
||||
if (null === $uuid) {
|
||||
$this->uid = static::generate();
|
||||
} else {
|
||||
parent::__construct($uuid, true);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDateTime(): \DateTimeImmutable
|
||||
{
|
||||
$time = substr($this->uid, 0, 8).substr($this->uid, 9, 4);
|
||||
$time = \PHP_INT_SIZE >= 8 ? (string) hexdec($time) : BinaryUtil::toBase(hex2bin($time), BinaryUtil::BASE10);
|
||||
|
||||
if (4 > \strlen($time)) {
|
||||
$time = '000'.$time;
|
||||
}
|
||||
|
||||
return \DateTimeImmutable::createFromFormat('U.v', substr_replace($time, '.', -3, 0));
|
||||
}
|
||||
|
||||
public static function generate(?\DateTimeInterface $time = null): string
|
||||
{
|
||||
if (null === $mtime = $time) {
|
||||
$time = microtime(false);
|
||||
$time = substr($time, 11).substr($time, 2, 3);
|
||||
} elseif (0 > $time = $time->format('Uv')) {
|
||||
throw new \InvalidArgumentException('The timestamp must be positive.');
|
||||
}
|
||||
|
||||
if ($time > self::$time || (null !== $mtime && $time !== self::$time)) {
|
||||
randomize:
|
||||
self::$rand = unpack('n*', isset(self::$seed) ? random_bytes(10) : self::$seed = random_bytes(16));
|
||||
self::$rand[1] &= 0x03FF;
|
||||
self::$time = $time;
|
||||
} else {
|
||||
// Within the same ms, we increment the rand part by a random 24-bit number.
|
||||
// Instead of getting this number from random_bytes(), which is slow, we get
|
||||
// it by sha512-hashing self::$seed. This produces 64 bytes of entropy,
|
||||
// which we need to split in a list of 24-bit numbers. unpack() first splits
|
||||
// them into 16 x 32-bit numbers; we take the first byte of each of these
|
||||
// numbers to get 5 extra 24-bit numbers. Then, we consume those numbers
|
||||
// one-by-one and run this logic every 21 iterations.
|
||||
// self::$rand holds the random part of the UUID, split into 5 x 16-bit
|
||||
// numbers for x86 portability. We increment this random part by the next
|
||||
// 24-bit number in the self::$seedParts list and decrement self::$seedIndex.
|
||||
|
||||
if (!self::$seedIndex) {
|
||||
$s = unpack('l*', self::$seed = hash('sha512', self::$seed, true));
|
||||
$s[] = ($s[1] >> 8 & 0xFF0000) | ($s[2] >> 16 & 0xFF00) | ($s[3] >> 24 & 0xFF);
|
||||
$s[] = ($s[4] >> 8 & 0xFF0000) | ($s[5] >> 16 & 0xFF00) | ($s[6] >> 24 & 0xFF);
|
||||
$s[] = ($s[7] >> 8 & 0xFF0000) | ($s[8] >> 16 & 0xFF00) | ($s[9] >> 24 & 0xFF);
|
||||
$s[] = ($s[10] >> 8 & 0xFF0000) | ($s[11] >> 16 & 0xFF00) | ($s[12] >> 24 & 0xFF);
|
||||
$s[] = ($s[13] >> 8 & 0xFF0000) | ($s[14] >> 16 & 0xFF00) | ($s[15] >> 24 & 0xFF);
|
||||
self::$seedParts = $s;
|
||||
self::$seedIndex = 21;
|
||||
}
|
||||
|
||||
self::$rand[5] = 0xFFFF & $carry = self::$rand[5] + 1 + (self::$seedParts[self::$seedIndex--] & 0xFFFFFF);
|
||||
self::$rand[4] = 0xFFFF & $carry = self::$rand[4] + ($carry >> 16);
|
||||
self::$rand[3] = 0xFFFF & $carry = self::$rand[3] + ($carry >> 16);
|
||||
self::$rand[2] = 0xFFFF & $carry = self::$rand[2] + ($carry >> 16);
|
||||
self::$rand[1] += $carry >> 16;
|
||||
|
||||
if (0xFC00 & self::$rand[1]) {
|
||||
if (\PHP_INT_SIZE >= 8 || 10 > \strlen($time = self::$time)) {
|
||||
$time = (string) (1 + $time);
|
||||
} elseif ('999999999' === $mtime = substr($time, -9)) {
|
||||
$time = (1 + substr($time, 0, -9)).'000000000';
|
||||
} else {
|
||||
$time = substr_replace($time, str_pad(++$mtime, 9, '0', \STR_PAD_LEFT), -9);
|
||||
}
|
||||
|
||||
goto randomize;
|
||||
}
|
||||
|
||||
$time = self::$time;
|
||||
}
|
||||
|
||||
if (\PHP_INT_SIZE >= 8) {
|
||||
$time = dechex($time);
|
||||
} else {
|
||||
$time = bin2hex(BinaryUtil::fromBase($time, BinaryUtil::BASE10));
|
||||
}
|
||||
|
||||
return substr_replace(sprintf('%012s-%04x-%04x-%04x%04x%04x',
|
||||
$time,
|
||||
0x7000 | (self::$rand[1] << 2) | (self::$rand[2] >> 14),
|
||||
0x8000 | (self::$rand[2] & 0x3FFF),
|
||||
self::$rand[3],
|
||||
self::$rand[4],
|
||||
self::$rand[5],
|
||||
), '-', 8, 0);
|
||||
}
|
||||
}
|
27
vendor/symfony/uid/UuidV8.php
vendored
Normal file
27
vendor/symfony/uid/UuidV8.php
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
<?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 v8 UUID has no explicit requirements except embedding its version + variant bits.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class UuidV8 extends Uuid
|
||||
{
|
||||
protected const TYPE = 8;
|
||||
|
||||
public function __construct(string $uuid)
|
||||
{
|
||||
parent::__construct($uuid, true);
|
||||
}
|
||||
}
|
36
vendor/symfony/uid/composer.json
vendored
Normal file
36
vendor/symfony/uid/composer.json
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "symfony/uid",
|
||||
"type": "library",
|
||||
"description": "Provides an object-oriented API to generate and represent UIDs",
|
||||
"keywords": ["uid", "uuid", "ulid"],
|
||||
"homepage": "https://symfony.com",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Grégoire Pineau",
|
||||
"email": "lyrixx@lyrixx.info"
|
||||
},
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"symfony/polyfill-uuid": "^1.15"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/console": "^5.4|^6.0|^7.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Component\\Uid\\": "" },
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
Reference in New Issue
Block a user