From 70712e733f9a001e37d6a9033e3d61485dde1291 Mon Sep 17 00:00:00 2001 From: uzdevid Date: Thu, 12 Dec 2024 16:54:14 +0500 Subject: [PATCH 1/4] Add UUID validation rule, and test --- src/Rule/Uuid.php | 65 +++++++++++++++++++++++++++++++++++++ src/Rule/UuidHandler.php | 49 ++++++++++++++++++++++++++++ tests/Rule/UuidTest.php | 70 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 src/Rule/Uuid.php create mode 100644 src/Rule/UuidHandler.php create mode 100644 tests/Rule/UuidTest.php diff --git a/src/Rule/Uuid.php b/src/Rule/Uuid.php new file mode 100644 index 00000000..60b976f1 --- /dev/null +++ b/src/Rule/Uuid.php @@ -0,0 +1,65 @@ +message; + } + + /** + * @return string + */ + public function getName(): string { + return self::class; + } + + /** + * @return array + */ + public function getOptions(): array { + return []; + } + + /** + * @return string + */ + public function getHandler(): string { + return UuidHandler::class; + } +} diff --git a/src/Rule/UuidHandler.php b/src/Rule/UuidHandler.php new file mode 100644 index 00000000..ee42e41b --- /dev/null +++ b/src/Rule/UuidHandler.php @@ -0,0 +1,49 @@ +validateUuid($value)) { + return $result; + } + + return $result->addError($rule->getMessage(), [ + 'property' => $context->getTranslatedProperty(), + 'Property' => $context->getCapitalizedTranslatedProperty(), + ]); + } + + /** + * @param string $uuid + * @return bool + */ + protected function validateUuid(string $uuid): bool { + $uuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid); + + return $uuid === self::NIL || preg_match('/' . self::PATTERN . '/Dms', $uuid); + } +} diff --git a/tests/Rule/UuidTest.php b/tests/Rule/UuidTest.php new file mode 100644 index 00000000..96639218 --- /dev/null +++ b/tests/Rule/UuidTest.php @@ -0,0 +1,70 @@ +assertSame(Uuid::class, $rule->getName()); + } + + /** + * @return string[] + */ + protected function getDifferentRuleInHandlerItems(): array { + return [Uuid::class, UuidHandler::class]; + } + + /** + * @return array[] + */ + public function dataValidationPassed(): array { + return [ + ['0193ba64-5ef5-7ba3-90c1-2915349a60d3', [new Uuid()]], + ['89ffcfc5-d452-4eb9-8949-d35fb577f09d', [new Uuid()]], + + ['289cef4c-b873-11ef-9cd2-0242ac120002', [new Uuid()]], + ]; + } + + public function dataValidationFailed(): array { + $errors = ['' => ['The value of value does not conform to the UUID format.']]; + + return [ + ['not uuid value', [new Uuid()], $errors], + ['ea20aba6-1fb2-45de-8582-6ed15f94501', [new Uuid()], $errors], + ]; + } + + public function dataOptions(): array { + return [ + [new Uuid(), []], + ]; + } + + public function testSkipOnError(): void { + $this->testSkipOnErrorInternal(new Url(), new Url(skipOnError: true)); + } + + /** + * @return void + */ + public function testWhen(): void { + $when = static fn(mixed $value): bool => $value !== null; + $this->testWhenInternal(new Uuid(), new Uuid(when: $when)); + } +} From aa42c98a1fefefe2ebd2f8810fb912bed50efe65 Mon Sep 17 00:00:00 2001 From: uzdevid Date: Fri, 13 Dec 2024 18:46:33 +0500 Subject: [PATCH 2/4] Add implementation of SkipOnEmptyInterface --- src/Rule/Uuid.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Rule/Uuid.php b/src/Rule/Uuid.php index 60b976f1..33007f14 100644 --- a/src/Rule/Uuid.php +++ b/src/Rule/Uuid.php @@ -7,13 +7,16 @@ use Attribute; use Closure; use Yiisoft\Validator\DumpedRuleInterface; +use Yiisoft\Validator\Rule\Trait\SkipOnEmptyTrait; use Yiisoft\Validator\Rule\Trait\SkipOnErrorTrait; use Yiisoft\Validator\Rule\Trait\WhenTrait; +use Yiisoft\Validator\SkipOnEmptyInterface; use Yiisoft\Validator\SkipOnErrorInterface; use Yiisoft\Validator\WhenInterface; #[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)] -class Uuid implements DumpedRuleInterface, SkipOnErrorInterface, WhenInterface { +class Uuid implements DumpedRuleInterface, SkipOnEmptyInterface, SkipOnErrorInterface, WhenInterface { + use SkipOnEmptyTrait; use SkipOnErrorTrait; use WhenTrait; From ff5d46f7b67f0a3dbf4ee1096e6f28941be219bb Mon Sep 17 00:00:00 2001 From: uzdevid Date: Fri, 13 Dec 2024 18:46:44 +0500 Subject: [PATCH 3/4] Change regex pattern --- src/Rule/UuidHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rule/UuidHandler.php b/src/Rule/UuidHandler.php index ee42e41b..92553b8b 100644 --- a/src/Rule/UuidHandler.php +++ b/src/Rule/UuidHandler.php @@ -11,7 +11,7 @@ use Yiisoft\Validator\ValidationContext; class UuidHandler implements RuleHandlerInterface { - private const PATTERN = '\A[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\z'; + private const PATTERN = '/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i'; private const NIL = '00000000-0000-0000-0000-000000000000'; /** From 754bd348aada7879bebdd1419199252ab82df416 Mon Sep 17 00:00:00 2001 From: uzdevid Date: Fri, 13 Dec 2024 18:52:19 +0500 Subject: [PATCH 4/4] Added a parameter that enables character replacement --- src/Rule/Uuid.php | 9 +++++++++ src/Rule/UuidHandler.php | 9 ++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Rule/Uuid.php b/src/Rule/Uuid.php index 33007f14..4730dd49 100644 --- a/src/Rule/Uuid.php +++ b/src/Rule/Uuid.php @@ -21,12 +21,14 @@ class Uuid implements DumpedRuleInterface, SkipOnEmptyInterface, SkipOnErrorInte use WhenTrait; /** + * @param bool $replaceChars * @param string $message * @param string $notPassedMessage * @param bool $skipOnError * @param Closure|null $when */ public function __construct( + private bool $replaceChars = false, private string $message = 'The value of {property} does not conform to the UUID format.', private string $notPassedMessage = '{Property} not passed.', private bool $skipOnError = false, @@ -34,6 +36,13 @@ public function __construct( ) { } + /** + * @return bool + */ + public function getReplaceChars(): bool { + return $this->replaceChars; + } + /** * Gets error message used when validation fails because the validated value is empty. * diff --git a/src/Rule/UuidHandler.php b/src/Rule/UuidHandler.php index 92553b8b..8678cd35 100644 --- a/src/Rule/UuidHandler.php +++ b/src/Rule/UuidHandler.php @@ -27,7 +27,7 @@ public function validate(mixed $value, RuleInterface $rule, ValidationContext $c $result = new Result(); - if ($this->validateUuid($value)) { + if ($this->validateUuid($value, $rule->getReplaceChars())) { return $result; } @@ -39,10 +39,13 @@ public function validate(mixed $value, RuleInterface $rule, ValidationContext $c /** * @param string $uuid + * @param bool $replaceChars * @return bool */ - protected function validateUuid(string $uuid): bool { - $uuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid); + protected function validateUuid(string $uuid, bool $replaceChars): bool { + if ($replaceChars) { + $uuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid); + } return $uuid === self::NIL || preg_match('/' . self::PATTERN . '/Dms', $uuid); }