-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Uid] Add support for binary, base-32 and base-58 representations in Uuid::isValid()
#57940
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,12 @@ | |
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_ALL = -1; | ||
|
||
protected const TYPE = 0; | ||
protected const NIL = '00000000-0000-0000-0000-000000000000'; | ||
protected const MAX = 'ffffffff-ffff-ffff-ffff-ffffffffffff'; | ||
|
@@ -44,22 +50,7 @@ | |
|
||
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::transformToRfc4122($uuid, self::FORMAT_ALL); | ||
|
||
if (__CLASS__ !== static::class || 36 !== \strlen($uuid)) { | ||
return new static($uuid); | ||
|
@@ -130,8 +121,19 @@ | |
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_4122 */): bool | ||
Check failure on line 127 in src/Symfony/Component/Uid/Uuid.php
|
||
{ | ||
$format = 1 < \func_num_args() ? func_get_arg(1) : self::FORMAT_RFC_4122; | ||
|
||
if (36 === \strlen($uuid) && !($format & self::FORMAT_RFC_4122)) { | ||
return false; | ||
} | ||
|
||
$uuid = self::transformToRfc4122($uuid, $format); | ||
|
||
Comment on lines
+131
to
+136
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @alexandre-daubois sorry to dig this up, but while 7.2 is not release.. I find this early condition non "optimal", as default case will be in fact $format = FORMAT_RFC_4122.. What if we did something like this here (before? instead?), avoiding the regexp if the string is not 36 chars long ? if (($format & self::FORMAT_RFC_4122) && 36 !== \strlen($uuid)) {
return false;
} What do you think ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (before line 131, i messed up my selection 😅 ) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did try a few things but it would require some refactoring because of how the control flow is currently. I'm not sure it would worth it and if performances would greatly improve 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep that is very true! |
||
if (self::NIL === $uuid && \in_array(static::class, [__CLASS__, NilUuid::class], true)) { | ||
return true; | ||
} | ||
|
@@ -182,4 +184,36 @@ | |
|
||
return substr_replace($uuid, '-', 23, 0); | ||
} | ||
|
||
/** | ||
* Transforms a binary string, a base-32 string or a base-58 string to a RFC4122 string. | ||
* | ||
* @param int-mask-of<Uuid::FORMAT_*> $format | ||
* | ||
* @return non-empty-string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @alexandre-daubois this is currently not true, afaik ... should we enforce it (or remove it) ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed, but more than that, it's a bit confusing. I proposed this update: #58089 |
||
*/ | ||
private static function transformToRfc4122(string $uuid, int $format): string | ||
{ | ||
$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(); | ||
} | ||
|
||
return $uuid; | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.