@@ -23,6 +23,12 @@ class Uuid extends AbstractUid
23
23
public const NAMESPACE_OID = '6ba7b812-9dad-11d1-80b4-00c04fd430c8 ' ;
24
24
public const NAMESPACE_X500 = '6ba7b814-9dad-11d1-80b4-00c04fd430c8 ' ;
25
25
26
+ public const FORMAT_BINARY = 1 ;
27
+ public const FORMAT_BASE_32 = 1 << 1 ;
28
+ public const FORMAT_BASE_58 = 1 << 2 ;
29
+ public const FORMAT_RFC_4122 = 1 << 3 ;
30
+ public const FORMAT_ALL = -1 ;
31
+
26
32
protected const TYPE = 0 ;
27
33
protected const NIL = '00000000-0000-0000-0000-000000000000 ' ;
28
34
protected const MAX = 'ffffffff-ffff-ffff-ffff-ffffffffffff ' ;
@@ -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,19 @@ 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
+ /**
125
+ * @param int-mask-of<Uuid::FORMAT_*> $format
126
+ */
127
+ public static function isValid (string $ uuid /*, int $format = self::FORMAT_RFC_4122 */ ): bool
134
128
{
129
+ $ format = 1 < \func_num_args () ? func_get_arg (1 ) : self ::FORMAT_RFC_4122 ;
130
+
131
+ if (36 === \strlen ($ uuid ) && !($ format & self ::FORMAT_RFC_4122 )) {
132
+ return false ;
133
+ }
134
+
135
+ $ uuid = self ::transformToRfc4122 ($ uuid , $ format );
136
+
135
137
if (self ::NIL === $ uuid && \in_array (static ::class, [__CLASS__ , NilUuid::class], true )) {
136
138
return true ;
137
139
}
@@ -182,4 +184,36 @@ private static function format(string $uuid, string $version): string
182
184
183
185
return substr_replace ($ uuid , '- ' , 23 , 0 );
184
186
}
187
+
188
+ /**
189
+ * Transforms a binary string, a base-32 string or a base-58 string to a RFC4122 string.
190
+ *
191
+ * @param int-mask-of<Uuid::FORMAT_*> $format
192
+ *
193
+ * @return non-empty-string
194
+ */
195
+ private static function transformToRfc4122 (string $ uuid , int $ format ): string
196
+ {
197
+ $ fromBase58 = false ;
198
+ if (22 === \strlen ($ uuid ) && 22 === strspn ($ uuid , BinaryUtil::BASE58 ['' ]) && $ format & self ::FORMAT_BASE_58 ) {
199
+ $ uuid = str_pad (BinaryUtil::fromBase ($ uuid , BinaryUtil::BASE58 ), 16 , "\0" , \STR_PAD_LEFT );
200
+ $ fromBase58 = true ;
201
+ }
202
+
203
+ // base-58 are always transformed to binary string, but they must only be valid when the format is FORMAT_BASE_58
204
+ if (16 === \strlen ($ uuid ) && $ format & self ::FORMAT_BINARY || $ fromBase58 && $ format & self ::FORMAT_BASE_58 ) {
205
+ // don't use uuid_unparse(), it's slower
206
+ $ uuid = bin2hex ($ uuid );
207
+ $ uuid = substr_replace ($ uuid , '- ' , 8 , 0 );
208
+ $ uuid = substr_replace ($ uuid , '- ' , 13 , 0 );
209
+ $ uuid = substr_replace ($ uuid , '- ' , 18 , 0 );
210
+ $ uuid = substr_replace ($ uuid , '- ' , 23 , 0 );
211
+ } elseif (26 === \strlen ($ uuid ) && Ulid::isValid ($ uuid ) && $ format & self ::FORMAT_BASE_32 ) {
212
+ $ ulid = new NilUlid ();
213
+ $ ulid ->uid = strtoupper ($ uuid );
214
+ $ uuid = $ ulid ->toRfc4122 ();
215
+ }
216
+
217
+ return $ uuid ;
218
+ }
185
219
}
0 commit comments