update patch 1

This commit is contained in:
fiqhpratama
2024-12-02 01:18:34 +07:00
parent 453d9bb470
commit 25026b0a85
3380 changed files with 103529 additions and 363623 deletions
+8 -3
View File
@@ -14,7 +14,7 @@ namespace Symfony\Component\Uid;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
abstract class AbstractUid implements \JsonSerializable, \Stringable
abstract class AbstractUid implements \JsonSerializable, \Stringable, HashableInterface
{
/**
* The identifier in its canonic representation.
@@ -95,7 +95,7 @@ abstract class AbstractUid implements \JsonSerializable, \Stringable
*/
public function toBase58(): string
{
return strtr(sprintf('%022s', BinaryUtil::toBase($this->toBinary(), BinaryUtil::BASE58)), '0', '1');
return strtr(\sprintf('%022s', BinaryUtil::toBase($this->toBinary(), BinaryUtil::BASE58)), '0', '1');
}
/**
@@ -108,7 +108,7 @@ abstract class AbstractUid implements \JsonSerializable, \Stringable
public function toBase32(): string
{
$uid = bin2hex($this->toBinary());
$uid = sprintf('%02s%04s%04s%04s%04s%04s%04s',
$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),
@@ -161,6 +161,11 @@ abstract class AbstractUid implements \JsonSerializable, \Stringable
return $this->uid === $other->uid;
}
public function hash(): string
{
return $this->uid;
}
public function compare(self $other): int
{
return (\strlen($this->uid) - \strlen($other->uid)) ?: ($this->uid <=> $other->uid);
+7
View File
@@ -1,6 +1,13 @@
CHANGELOG
=========
7.2
---
* Make `AbstractUid` implement `Ds\Hashable` if available
* Add support for binary, base-32 and base-58 representations in `Uuid::isValid()`
* Add the `Uuid::FORMAT_RFC_9562` constant to validate UUIDs in the RFC 9562 format
7.1
---
+4 -3
View File
@@ -37,7 +37,7 @@ class GenerateUlidCommand extends Command
->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'),
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.
@@ -68,7 +68,7 @@ EOF
try {
$time = new \DateTimeImmutable($time);
} catch (\Exception $e) {
$io->error(sprintf('Invalid timestamp "%s": %s', $time, str_replace('DateTimeImmutable::__construct(): ', '', $e->getMessage())));
$io->error(\sprintf('Invalid timestamp "%s": %s', $time, str_replace('DateTimeImmutable::__construct(): ', '', $e->getMessage())));
return 1;
}
@@ -79,7 +79,7 @@ EOF
if (\in_array($formatOption, $this->getAvailableFormatOptions(), true)) {
$format = 'to'.ucfirst($formatOption);
} else {
$io->error(sprintf('Invalid format "%s", supported formats are "%s".', $formatOption, implode('", "', $this->getAvailableFormatOptions())));
$io->error(\sprintf('Invalid format "%s", supported formats are "%s".', $formatOption, implode('", "', $this->getAvailableFormatOptions())));
return 1;
}
@@ -105,6 +105,7 @@ EOF
}
}
/** @return string[] */
private function getAvailableFormatOptions(): array
{
return [
+6 -5
View File
@@ -42,7 +42,7 @@ class GenerateUuidCommand extends Command
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'),
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.
@@ -115,7 +115,7 @@ EOF
try {
$node = Uuid::fromString($node);
} catch (\InvalidArgumentException $e) {
$io->error(sprintf('Invalid node "%s": %s', $node, $e->getMessage()));
$io->error(\sprintf('Invalid node "%s": %s', $node, $e->getMessage()));
return 1;
}
@@ -124,7 +124,7 @@ EOF
try {
new \DateTimeImmutable($time);
} catch (\Exception $e) {
$io->error(sprintf('Invalid timestamp "%s": %s', $time, str_replace('DateTimeImmutable::__construct(): ', '', $e->getMessage())));
$io->error(\sprintf('Invalid timestamp "%s": %s', $time, str_replace('DateTimeImmutable::__construct(): ', '', $e->getMessage())));
return 1;
}
@@ -137,7 +137,7 @@ EOF
try {
$namespace = Uuid::fromString($namespace);
} catch (\InvalidArgumentException $e) {
$io->error(sprintf('Invalid namespace "%s": %s', $namespace, $e->getMessage()));
$io->error(\sprintf('Invalid namespace "%s": %s', $namespace, $e->getMessage()));
return 1;
}
@@ -168,7 +168,7 @@ EOF
if (\in_array($formatOption, $this->getAvailableFormatOptions(), true)) {
$format = 'to'.ucfirst($formatOption);
} else {
$io->error(sprintf('Invalid format "%s", supported formats are "%s".', $formatOption, implode('", "', $this->getAvailableFormatOptions())));
$io->error(\sprintf('Invalid format "%s", supported formats are "%s".', $formatOption, implode('", "', $this->getAvailableFormatOptions())));
return 1;
}
@@ -194,6 +194,7 @@ EOF
}
}
/** @return string[] */
private function getAvailableFormatOptions(): array
{
return [
+1 -1
View File
@@ -72,7 +72,7 @@ class UuidFactory
$namespace ??= $this->nameBasedNamespace;
if (null === $namespace) {
throw new \LogicException(sprintf('A namespace should be defined when using "%s()".', __METHOD__));
throw new \LogicException(\sprintf('A namespace should be defined when using "%s()".', __METHOD__));
}
return new NameBasedUuidFactory($this->nameBasedClass, $this->getNamespace($namespace));
+6 -6
View File
@@ -36,7 +36,7 @@ class Ulid extends AbstractUid implements TimeBasedUidInterface
$this->uid = $ulid;
} else {
if (!self::isValid($ulid)) {
throw new \InvalidArgumentException(sprintf('Invalid ULID: "%s".', $ulid));
throw new \InvalidArgumentException(\sprintf('Invalid ULID: "%s".', $ulid));
}
$this->uid = strtoupper($ulid);
@@ -73,7 +73,7 @@ class Ulid extends AbstractUid implements TimeBasedUidInterface
}
$ulid = bin2hex($ulid);
$ulid = sprintf('%02s%04s%04s%04s%04s%04s%04s',
$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),
@@ -101,7 +101,7 @@ class Ulid extends AbstractUid implements TimeBasedUidInterface
{
$ulid = strtr($this->uid, 'ABCDEFGHJKMNPQRSTVWXYZ', 'abcdefghijklmnopqrstuv');
$ulid = sprintf('%02s%05s%05s%05s%05s%05s%05s',
$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),
@@ -133,7 +133,7 @@ class Ulid extends AbstractUid implements TimeBasedUidInterface
if (\PHP_INT_SIZE >= 8) {
$time = (string) hexdec(base_convert($time, 32, 16));
} else {
$time = sprintf('%02s%05s%05s',
$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)
@@ -190,14 +190,14 @@ class Ulid extends AbstractUid implements TimeBasedUidInterface
$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',
$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',
return strtr(\sprintf('%010s%04s%04s%04s%04s',
$time,
base_convert(self::$rand[1], 10, 32),
base_convert(self::$rand[2], 10, 32),
+62 -19
View File
@@ -23,6 +23,13 @@ class Uuid extends AbstractUid
public const NAMESPACE_OID = '6ba7b812-9dad-11d1-80b4-00c04fd430c8';
public const NAMESPACE_X500 = '6ba7b814-9dad-11d1-80b4-00c04fd430c8';
public const FORMAT_BINARY = 1;
public const FORMAT_BASE_32 = 1 << 1;
public const FORMAT_BASE_58 = 1 << 2;
public const FORMAT_RFC_4122 = 1 << 3;
public const FORMAT_RFC_9562 = self::FORMAT_RFC_4122;
public const FORMAT_ALL = -1;
protected const TYPE = 0;
protected const NIL = '00000000-0000-0000-0000-000000000000';
protected const MAX = 'ffffffff-ffff-ffff-ffff-ffffffffffff';
@@ -32,34 +39,19 @@ class Uuid extends AbstractUid
$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));
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));
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();
}
$uuid = self::transformToRfc9562($uuid, self::FORMAT_ALL);
if (__CLASS__ !== static::class || 36 !== \strlen($uuid)) {
return new static($uuid);
@@ -130,8 +122,21 @@ class Uuid extends AbstractUid
return new UuidV8($uuid);
}
public static function isValid(string $uuid): bool
/**
* @param int-mask-of<Uuid::FORMAT_*> $format
*/
public static function isValid(string $uuid /* , int $format = self::FORMAT_RFC_9562 */): bool
{
$format = 1 < \func_num_args() ? func_get_arg(1) : self::FORMAT_RFC_9562;
if (36 === \strlen($uuid) && !($format & self::FORMAT_RFC_9562)) {
return false;
}
if (false === $uuid = self::transformToRfc9562($uuid, $format)) {
return false;
}
if (self::NIL === $uuid && \in_array(static::class, [__CLASS__, NilUuid::class], true)) {
return true;
}
@@ -182,4 +187,42 @@ class Uuid extends AbstractUid
return substr_replace($uuid, '-', 23, 0);
}
/**
* Transforms a binary string, a base-32 string or a base-58 string to a RFC9562 string.
*
* @param int-mask-of<Uuid::FORMAT_*> $format
*
* @return string|false The RFC9562 string or false if the format doesn't match the input
*/
private static function transformToRfc9562(string $uuid, int $format): string|false
{
$inputUuid = $uuid;
$fromBase58 = false;
if (22 === \strlen($uuid) && 22 === strspn($uuid, BinaryUtil::BASE58['']) && $format & self::FORMAT_BASE_58) {
$uuid = str_pad(BinaryUtil::fromBase($uuid, BinaryUtil::BASE58), 16, "\0", \STR_PAD_LEFT);
$fromBase58 = true;
}
// base-58 are always transformed to binary string, but they must only be valid when the format is FORMAT_BASE_58
if (16 === \strlen($uuid) && $format & self::FORMAT_BINARY || $fromBase58 && $format & self::FORMAT_BASE_58) {
// 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) && $format & self::FORMAT_BASE_32) {
$ulid = new NilUlid();
$ulid->uid = strtoupper($uuid);
$uuid = $ulid->toRfc4122();
}
if ($inputUuid === $uuid && !($format & self::FORMAT_RFC_9562)) {
// input format doesn't match the input string
return false;
}
return $uuid;
}
}
+1 -1
View File
@@ -66,7 +66,7 @@ class UuidV1 extends Uuid implements TimeBasedUidInterface
$seq = substr($uuid, 19, 4);
do {
self::$clockSeq = sprintf('%04x', random_int(0, 0x3FFF) | 0x8000);
self::$clockSeq = \sprintf('%04x', random_int(0, 0x3FFF) | 0x8000);
} while ($seq === self::$clockSeq);
$seq = self::$clockSeq;
+2 -2
View File
@@ -59,7 +59,7 @@ class UuidV6 extends Uuid implements TimeBasedUidInterface
$time = substr($time, 1);
}
return new UuidV7(substr_replace(sprintf(
return new UuidV7(substr_replace(\sprintf(
'%012s-7%s-%s%s-%s%06s',
\PHP_INT_SIZE >= 8 ? dechex($ms) : bin2hex(BinaryUtil::fromBase($ms, BinaryUtil::BASE10)),
substr($uuid, -6, 3),
@@ -85,7 +85,7 @@ class UuidV6 extends Uuid implements TimeBasedUidInterface
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]);
self::$node = \sprintf('%06x%06x', ($seed[0] ^ $node[1]) | 0x010000, $seed[1] ^ $node[2]);
}
return $uuid.self::$node;
+1 -1
View File
@@ -113,7 +113,7 @@ class UuidV7 extends Uuid implements TimeBasedUidInterface
$time = bin2hex(BinaryUtil::fromBase($time, BinaryUtil::BASE10));
}
return substr_replace(sprintf('%012s-%04x-%04x-%04x%04x%04x',
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),