@@ -27,6 +27,12 @@ class Uuid extends AbstractUid
27
27
protected const NIL = '00000000-0000-0000-0000-000000000000 ' ;
28
28
protected const MAX = 'ffffffff-ffff-ffff-ffff-ffffffffffff ' ;
29
29
30
+ public const FORMAT_BINARY = 1 ;
31
+ public const FORMAT_BASE_32 = 1 << 1 ;
32
+ public const FORMAT_BASE_58 = 1 << 2 ;
33
+ public const FORMAT_RFC_4122 = 1 << 3 ;
34
+ public const FORMAT_ALL = self ::FORMAT_BINARY | self ::FORMAT_BASE_32 | self ::FORMAT_BASE_58 | self ::FORMAT_RFC_4122 ;
35
+
30
36
public function __construct (string $ uuid , bool $ checkVariant = false )
31
37
{
32
38
$ type = preg_match ('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di ' , $ uuid ) ? (int ) $ uuid [14 ] : false ;
@@ -44,22 +50,7 @@ public function __construct(string $uuid, bool $checkVariant = false)
44
50
45
51
public static function fromString (string $ uuid ): static
46
52
{
47
- if (22 === \strlen ($ uuid ) && 22 === strspn ($ uuid , BinaryUtil::BASE58 ['' ])) {
48
- $ uuid = str_pad (BinaryUtil::fromBase ($ uuid , BinaryUtil::BASE58 ), 16 , "\0" , \STR_PAD_LEFT );
49
- }
50
-
51
- if (16 === \strlen ($ uuid )) {
52
- // don't use uuid_unparse(), it's slower
53
- $ uuid = bin2hex ($ uuid );
54
- $ uuid = substr_replace ($ uuid , '- ' , 8 , 0 );
55
- $ uuid = substr_replace ($ uuid , '- ' , 13 , 0 );
56
- $ uuid = substr_replace ($ uuid , '- ' , 18 , 0 );
57
- $ uuid = substr_replace ($ uuid , '- ' , 23 , 0 );
58
- } elseif (26 === \strlen ($ uuid ) && Ulid::isValid ($ uuid )) {
59
- $ ulid = new NilUlid ();
60
- $ ulid ->uid = strtoupper ($ uuid );
61
- $ uuid = $ ulid ->toRfc4122 ();
62
- }
53
+ $ uuid = self ::transformToRfc4122 ($ uuid , self ::FORMAT_ALL );
63
54
64
55
if (__CLASS__ !== static ::class || 36 !== \strlen ($ uuid )) {
65
56
return new static ($ uuid );
@@ -130,8 +121,14 @@ final public static function v8(string $uuid): UuidV8
130
121
return new UuidV8 ($ uuid );
131
122
}
132
123
133
- public static function isValid (string $ uuid ): bool
124
+ public static function isValid (string $ uuid, int $ format = self :: FORMAT_RFC_4122 ): bool
134
125
{
126
+ if (36 === \strlen ($ uuid ) && !($ format & self ::FORMAT_RFC_4122 )) {
127
+ return false ;
128
+ }
129
+
130
+ $ uuid = self ::transformToRfc4122 ($ uuid , $ format );
131
+
135
132
if (self ::NIL === $ uuid && \in_array (static ::class, [__CLASS__ , NilUuid::class], true )) {
136
133
return true ;
137
134
}
@@ -182,4 +179,34 @@ private static function format(string $uuid, string $version): string
182
179
183
180
return substr_replace ($ uuid , '- ' , 23 , 0 );
184
181
}
182
+
183
+ /**
184
+ * Transforms a binary string, a base-32 string or a base-58 string to a RFC4122 string.
185
+ *
186
+ * @return non-empty-string
187
+ */
188
+ private static function transformToRfc4122 (string $ uuid , int $ format = self ::FORMAT_RFC_4122 ): string
189
+ {
190
+ $ fromBase58 = false ;
191
+ if (22 === \strlen ($ uuid ) && 22 === strspn ($ uuid , BinaryUtil::BASE58 ['' ]) && $ format & self ::FORMAT_BASE_58 ) {
192
+ $ uuid = str_pad (BinaryUtil::fromBase ($ uuid , BinaryUtil::BASE58 ), 16 , "\0" , \STR_PAD_LEFT );
193
+ $ fromBase58 = true ;
194
+ }
195
+
196
+ // base-58 are always transformed to binary string, but they must only be valid when the format is FORMAT_BASE_58
197
+ if (16 === \strlen ($ uuid ) && $ format & self ::FORMAT_BINARY || $ fromBase58 && $ format & self ::FORMAT_BASE_58 ) {
198
+ // don't use uuid_unparse(), it's slower
199
+ $ uuid = bin2hex ($ uuid );
200
+ $ uuid = substr_replace ($ uuid , '- ' , 8 , 0 );
201
+ $ uuid = substr_replace ($ uuid , '- ' , 13 , 0 );
202
+ $ uuid = substr_replace ($ uuid , '- ' , 18 , 0 );
203
+ $ uuid = substr_replace ($ uuid , '- ' , 23 , 0 );
204
+ } elseif (26 === \strlen ($ uuid ) && Ulid::isValid ($ uuid ) && $ format & self ::FORMAT_BASE_32 ) {
205
+ $ ulid = new NilUlid ();
206
+ $ ulid ->uid = strtoupper ($ uuid );
207
+ $ uuid = $ ulid ->toRfc4122 ();
208
+ }
209
+
210
+ return $ uuid ;
211
+ }
185
212
}
0 commit comments