From 698393c6db1d3e2706f0d1905bf1756ff360129b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=A4drich?= <11225821+shaedrich@users.noreply.github.com> Date: Thu, 31 Oct 2024 23:56:45 +0100 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20support=20for=20U?= =?UTF-8?q?UID=20v2=20and=20max=20UUID=20validation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Illuminate/Support/Str.php | 35 ++++++++++++------- .../Concerns/ValidatesAttributes.php | 14 ++++++-- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/Illuminate/Support/Str.php b/src/Illuminate/Support/Str.php index 0d23c49597e1..185e0c638148 100644 --- a/src/Illuminate/Support/Str.php +++ b/src/Illuminate/Support/Str.php @@ -603,7 +603,7 @@ public static function isUrl($value, array $protocols = []) * Determine if a given value is a valid UUID. * * @param mixed $value - * @param int<-1, 8>|null $version + * @param int<0, 8>|'max'|null $version * @return bool */ public static function isUuid($value, $version = null) @@ -615,19 +615,28 @@ public static function isUuid($value, $version = null) if ($version === null) { return preg_match('/^[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}$/D', $value) > 0; } + + $factory = new UuidFactory(); + try { + $factoryUuid = $factory->fromString($value); + } catch (InvalidUuidStringException $ex) { + return false; + } + $fields = $factoryUuid->getFields(); - return match ($version) { - -1, 0 => NilUuid::isValid($value), - 1 => UuidV1::isValid($value), - // 2 => UuidV2::isValid($value), // Symfony/uid doesn't implement version 2 - 3 => UuidV3::isValid($value), - 4 => UuidV4::isValid($value), - 5 => UuidV5::isValid($value), - 6 => UuidV6::isValid($value), - 7 => UuidV7::isValid($value), - 8 => UuidV8::isValid($value), - default => false, - }; + if (!($fields instanceof FieldsInterface)) { + return false; + } + + if ($version === 0 || $version === 'nil') { + return $fields->isNil(); + } + + if ($version === 'max') { + return $fields->isMax(); + } + + return $fields->getVersion() === $version; } /** diff --git a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php index e26c5300797f..607c7b840716 100644 --- a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php @@ -2550,12 +2550,22 @@ public function validateUlid($attribute, $value) * * @param string $attribute * @param mixed $value - * @param array> $parameters + * @param array|'max'> $parameters * @return bool */ public function validateUuid($attribute, $value, $parameters) { - return Str::isUuid($value, $parameters !== null && count($parameters) === 1 ? (int) $parameters[0] : null); + $version = null; + + if ($parameters !== null && count($parameters) === 1) { + $version = $parameters[0]; + + if ($version !== 'max') { + $version = (int) $parameters[0]; + } + } + + return Str::isUuid($value, $version); } /** From 2c94539b0b6d917f1d29a876d13db50b5a056ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=A4drich?= <11225821+shaedrich@users.noreply.github.com> Date: Thu, 31 Oct 2024 23:56:56 +0100 Subject: [PATCH 2/8] =?UTF-8?q?test:=20=E2=9C=85=20Add=20cases=20for=20eve?= =?UTF-8?q?ry=20supported=20UUID=20version=20to=20data=20provider=20of=20U?= =?UTF-8?q?UID=20validation=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Support/SupportStrTest.php | 44 ++++++++++++++++++-- tests/Validation/ValidationValidatorTest.php | 40 ++++++++++++++++-- 2 files changed, 76 insertions(+), 8 deletions(-) diff --git a/tests/Support/SupportStrTest.php b/tests/Support/SupportStrTest.php index fed5d2c57c4d..f85719e6bde3 100755 --- a/tests/Support/SupportStrTest.php +++ b/tests/Support/SupportStrTest.php @@ -1315,14 +1315,50 @@ public static function invalidUuidList() public static function uuidVersionList() { return [ - ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', null, true], - ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 1, false], - ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 4, true], - ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 42, false], + ['00000000-0000-0000-0000-000000000000', null, true], + ['00000000-0000-0000-0000-000000000000', 0, true], + ['00000000-0000-0000-0000-000000000000', 1, false], + ['00000000-0000-0000-0000-000000000000', 42, false], ['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', null, true], ['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', 1, true], ['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', 4, false], ['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', 42, false], + ['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', null, true], + ['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', 1, false], + ['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', 2, true], + ['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', 42, false], + ['76a4ba72-cc4e-3e1d-b52d-856382f408c3', null, true], + ['76a4ba72-cc4e-3e1d-b52d-856382f408c3', 1, false], + ['76a4ba72-cc4e-3e1d-b52d-856382f408c3', 3, true], + ['76a4ba72-cc4e-3e1d-b52d-856382f408c3', 42, false], + ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', null, true], + ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 1, false], + ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 4, true], + ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 42, false], + ['d3b2b5a9-d433-5c58-b038-4fa13696e357', null, true], + ['d3b2b5a9-d433-5c58-b038-4fa13696e357', 1, false], + ['d3b2b5a9-d433-5c58-b038-4fa13696e357', 5, true], + ['d3b2b5a9-d433-5c58-b038-4fa13696e357', 42, false], + ['1ef97d97-b5ab-67d8-9f12-5600051f1387', null, true], + ['1ef97d97-b5ab-67d8-9f12-5600051f1387', 1, false], + ['1ef97d97-b5ab-67d8-9f12-5600051f1387', 6, true], + ['1ef97d97-b5ab-67d8-9f12-5600051f1387', 42, false], + ['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', null, true], + ['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', 1, false], + ['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', 7, true], + ['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', 42, false], + ['07e80a1f-1629-831f-811f-c595103c91b5', null, true], + ['07e80a1f-1629-831f-811f-c595103c91b5', 1, false], + ['07e80a1f-1629-831f-811f-c595103c91b5', 8, true], + ['07e80a1f-1629-831f-811f-c595103c91b5', 42, false], + ['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', null, true], + ['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', 1, false], + ['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', 42, false], + ['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', 'max', true], + ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', null, true], + ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 1, false], + ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 4, true], + ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 42, false], ['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', null, false], ['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 1, false], ['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 4, false], diff --git a/tests/Validation/ValidationValidatorTest.php b/tests/Validation/ValidationValidatorTest.php index 99814b4d481c..06b163fcf43c 100755 --- a/tests/Validation/ValidationValidatorTest.php +++ b/tests/Validation/ValidationValidatorTest.php @@ -8488,14 +8488,46 @@ public static function invalidUuidList() public static function uuidVersionList() { return [ - ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 'uuid', true], - ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 'uuid:1', false], - ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 'uuid:4', true], - ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 'uuid:42', false], + ['00000000-0000-0000-0000-000000000000', 'uuid', true], + ['00000000-0000-0000-0000-000000000000', 'uuid:0', true], + ['00000000-0000-0000-0000-000000000000', 'uuid:1', false], + ['00000000-0000-0000-0000-000000000000', 'uuid:42', false], ['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', 'uuid', true], ['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', 'uuid:1', true], ['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', 'uuid:4', false], ['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', 'uuid:42', false], + ['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', 'uuid', true], + ['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', 'uuid:1', false], + ['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', 'uuid:2', true], + ['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', 'uuid:42', false], + ['76a4ba72-cc4e-3e1d-b52d-856382f408c3', 'uuid', true], + ['76a4ba72-cc4e-3e1d-b52d-856382f408c3', 'uuid:1', false], + ['76a4ba72-cc4e-3e1d-b52d-856382f408c3', 'uuid:3', true], + ['76a4ba72-cc4e-3e1d-b52d-856382f408c3', 'uuid:42', false], + ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 'uuid', true], + ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 'uuid:1', false], + ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 'uuid:4', true], + ['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 'uuid:42', false], + ['d3b2b5a9-d433-5c58-b038-4fa13696e357', 'uuid', true], + ['d3b2b5a9-d433-5c58-b038-4fa13696e357', 'uuid:1', false], + ['d3b2b5a9-d433-5c58-b038-4fa13696e357', 'uuid:5', true], + ['d3b2b5a9-d433-5c58-b038-4fa13696e357', 'uuid:42', false], + ['1ef97d97-b5ab-67d8-9f12-5600051f1387', 'uuid', true], + ['1ef97d97-b5ab-67d8-9f12-5600051f1387', 'uuid:1', false], + ['1ef97d97-b5ab-67d8-9f12-5600051f1387', 'uuid:6', true], + ['1ef97d97-b5ab-67d8-9f12-5600051f1387', 'uuid:42', false], + ['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', 'uuid', true], + ['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', 'uuid:1', false], + ['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', 'uuid:7', true], + ['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', 'uuid:42', false], + ['07e80a1f-1629-831f-811f-c595103c91b5', 'uuid', true], + ['07e80a1f-1629-831f-811f-c595103c91b5', 'uuid:1', false], + ['07e80a1f-1629-831f-811f-c595103c91b5', 'uuid:8', true], + ['07e80a1f-1629-831f-811f-c595103c91b5', 'uuid:42', false], + ['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', 'uuid', true], + ['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', 'uuid:1', false], + ['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', 'uuid:42', false], + ['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', 'uuid:max', true], ['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 'uuid', false], ['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 'uuid:1', false], ['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 'uuid:4', false], From abb53e9fee242db597e378e0777653a819da16ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=A4drich?= <11225821+shaedrich@users.noreply.github.com> Date: Fri, 1 Nov 2024 00:05:59 +0100 Subject: [PATCH 3/8] =?UTF-8?q?style:=20=F0=9F=8E=A8=20Fix=20StyleCI=20err?= =?UTF-8?q?ors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit – Remove unused imports – Spacing improves: #53341 --- src/Illuminate/Support/Str.php | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Illuminate/Support/Str.php b/src/Illuminate/Support/Str.php index 185e0c638148..54a68f168a76 100644 --- a/src/Illuminate/Support/Str.php +++ b/src/Illuminate/Support/Str.php @@ -14,15 +14,7 @@ use Ramsey\Uuid\Generator\CombGenerator; use Ramsey\Uuid\Uuid; use Ramsey\Uuid\UuidFactory; -use Symfony\Component\Uid\NilUuid; use Symfony\Component\Uid\Ulid; -use Symfony\Component\Uid\UuidV1; -use Symfony\Component\Uid\UuidV3; -use Symfony\Component\Uid\UuidV4; -use Symfony\Component\Uid\UuidV5; -use Symfony\Component\Uid\UuidV6; -use Symfony\Component\Uid\UuidV7; -use Symfony\Component\Uid\UuidV8; use Throwable; use Traversable; use voku\helper\ASCII; @@ -617,6 +609,7 @@ public static function isUuid($value, $version = null) } $factory = new UuidFactory(); + try { $factoryUuid = $factory->fromString($value); } catch (InvalidUuidStringException $ex) { @@ -624,7 +617,7 @@ public static function isUuid($value, $version = null) } $fields = $factoryUuid->getFields(); - if (!($fields instanceof FieldsInterface)) { + if (! ($fields instanceof FieldsInterface)) { return false; } From c5eb2f1794135dfcef121e48e9f450e0f2e3edd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=A4drich?= <11225821+shaedrich@users.noreply.github.com> Date: Fri, 1 Nov 2024 00:08:37 +0100 Subject: [PATCH 4/8] Add missing import --- src/Illuminate/Support/Str.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Illuminate/Support/Str.php b/src/Illuminate/Support/Str.php index 54a68f168a76..09fb71a81a7a 100644 --- a/src/Illuminate/Support/Str.php +++ b/src/Illuminate/Support/Str.php @@ -11,7 +11,9 @@ use League\CommonMark\GithubFlavoredMarkdownConverter; use League\CommonMark\MarkdownConverter; use Ramsey\Uuid\Codec\TimestampFirstCombCodec; +use Ramsey\Uuid\Exception\InvalidUuidStringException; use Ramsey\Uuid\Generator\CombGenerator; +use Ramsey\Uuid\Rfc4122\FieldsInterface; use Ramsey\Uuid\Uuid; use Ramsey\Uuid\UuidFactory; use Symfony\Component\Uid\Ulid; From 8600efe002c3f7c7bb1e629d2bad264a31284fc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=A4drich?= <11225821+shaedrich@users.noreply.github.com> Date: Fri, 1 Nov 2024 00:10:02 +0100 Subject: [PATCH 5/8] =?UTF-8?q?style:=20=F0=9F=8E=A8=20Remove=20indent=20f?= =?UTF-8?q?rom=20blank=20line?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Illuminate/Support/Str.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Support/Str.php b/src/Illuminate/Support/Str.php index 09fb71a81a7a..b16ccedcfecb 100644 --- a/src/Illuminate/Support/Str.php +++ b/src/Illuminate/Support/Str.php @@ -609,7 +609,7 @@ public static function isUuid($value, $version = null) if ($version === null) { return preg_match('/^[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}$/D', $value) > 0; } - + $factory = new UuidFactory(); try { From 98b7f0726ad7f36847498667a72d8cb8185f2908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=A4drich?= <11225821+shaedrich@users.noreply.github.com> Date: Fri, 1 Nov 2024 13:27:42 +0100 Subject: [PATCH 6/8] Add ramsey/uuid to composer suggestions to be able to use it for UUID version constraint validation --- src/Illuminate/Validation/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Validation/composer.json b/src/Illuminate/Validation/composer.json index 74e7c1e61c17..0aae94ee07fb 100755 --- a/src/Illuminate/Validation/composer.json +++ b/src/Illuminate/Validation/composer.json @@ -39,7 +39,8 @@ } }, "suggest": { - "illuminate/database": "Required to use the database presence verifier (^12.0)." + "illuminate/database": "Required to use the database presence verifier (^12.0).", + "ramsey/uuid": "Required to use Validator::validateUuid() (^4.7)." }, "config": { "sort-packages": true From 4367dc82271018db04c6aee8549b31467b23cc0e Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 1 Nov 2024 08:31:00 -0500 Subject: [PATCH 7/8] Update Str.php --- src/Illuminate/Support/Str.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Illuminate/Support/Str.php b/src/Illuminate/Support/Str.php index b16ccedcfecb..1ab0b578c703 100644 --- a/src/Illuminate/Support/Str.php +++ b/src/Illuminate/Support/Str.php @@ -617,6 +617,7 @@ public static function isUuid($value, $version = null) } catch (InvalidUuidStringException $ex) { return false; } + $fields = $factoryUuid->getFields(); if (! ($fields instanceof FieldsInterface)) { From c5fe7aece5aa0255308fdc5f8f7178f25e249070 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 1 Nov 2024 08:31:24 -0500 Subject: [PATCH 8/8] Update Str.php --- src/Illuminate/Support/Str.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Support/Str.php b/src/Illuminate/Support/Str.php index 1ab0b578c703..cda1f7c7fc67 100644 --- a/src/Illuminate/Support/Str.php +++ b/src/Illuminate/Support/Str.php @@ -610,7 +610,7 @@ public static function isUuid($value, $version = null) return preg_match('/^[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}$/D', $value) > 0; } - $factory = new UuidFactory(); + $factory = new UuidFactory; try { $factoryUuid = $factory->fromString($value);