From 1ef7bf36c8b00670c6e35181e467bcda4abf9be3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=93=AD=E6=98=95?= <715557344@qq.com> Date: Mon, 29 Apr 2024 21:04:23 +0800 Subject: [PATCH 1/3] Support required_if. --- src/ValidationRuleset.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ValidationRuleset.php b/src/ValidationRuleset.php index ad1a6b6..2cf442b 100644 --- a/src/ValidationRuleset.php +++ b/src/ValidationRuleset.php @@ -41,6 +41,7 @@ class ValidationRuleset protected const PRIORITY_MAP = [ 'required' => 50, + 'required_if' => 50, 'numeric' => 100, 'integer' => 100, 'string' => 100, @@ -111,6 +112,8 @@ protected function __construct(array $ruleMap) $rules[] = ValidationRule::make('required', static::getClosure('validateRequired' . static::fetchTypedRule($ruleMap))); } break; + case 'required_if': + break; case 'nullable': $flags |= static::FLAG_NULLABLE; break; From c4c3ba2d93b5e3dda687afc32db24b5eee82c641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=93=AD=E6=98=95?= <715557344@qq.com> Date: Mon, 29 Apr 2024 21:41:18 +0800 Subject: [PATCH 2/3] Support required_if --- src/ValidationRuleset.php | 76 ++++++++++++++++++++++++--------------- src/Validator.php | 2 +- 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/ValidationRuleset.php b/src/ValidationRuleset.php index 2cf442b..694d908 100644 --- a/src/ValidationRuleset.php +++ b/src/ValidationRuleset.php @@ -113,6 +113,11 @@ protected function __construct(array $ruleMap) } break; case 'required_if': + if (count($ruleArgs) !== 2) { + throw new InvalidArgumentException("Rule '{$rule}' require 2 parameter"); + } + $ruleArgs[] = 'validateRequired' . static::fetchTypedRule($ruleMap); + $rules[] = ValidationRule::make('required_if', static::getClosure('validateRequiredIf'), $ruleArgs); break; case 'nullable': $flags |= static::FLAG_NULLABLE; @@ -202,7 +207,7 @@ public function getRules(): array /** * @return string[] Error attribute names */ - public function check(mixed $data): array + public function check(mixed $data, array $attributes = []): array { if (($this->flags & static::FLAG_NULLABLE) && $data === null) { return []; @@ -212,7 +217,7 @@ public function check(mixed $data): array foreach ($this->rules as $rule) { $closure = $rule->closure; - $valid = $closure($data, ...$rule->args); + $valid = $closure($data, $attributes, ...$rule->args); if (!$valid) { $errors[] = $rule->name; /* Always bail here, for example: @@ -325,7 +330,7 @@ protected static function getClosure(string $method): Closure (static::$closureCache[$method] = Closure::fromCallable([static::class, $method])); } - protected static function validateRequired(mixed $value): bool + protected static function validateRequired(mixed $value, array $attributes): bool { if (is_null($value)) { return false; @@ -343,22 +348,33 @@ protected static function validateRequired(mixed $value): bool return true; } - protected static function validateRequiredString(mixed $value): bool + protected static function validateRequiredIf(mixed $value, array $attributes, string $key, mixed $keyValue, string $validator): bool + { + if (array_key_exists($key, $attributes)) { + if ($attributes[$key] == $keyValue) { + return self::$validator($value, $attributes); + } + } + + return true; + } + + protected static function validateRequiredString(mixed $value, array $attributes): bool { return $value !== '' && !ctype_space($value); } - protected static function validateRequiredArray(array $value): bool + protected static function validateRequiredArray(array $value, array $attributes): bool { return count($value) !== 0; } - protected static function validateRequiredFile(SplFileInfo $value): bool + protected static function validateRequiredFile(SplFileInfo $value, array $attributes): bool { return $value->getPath() !== ''; } - protected static function validateNumeric(mixed &$value): bool + protected static function validateNumeric(mixed &$value, array $attributes): bool { if (!is_numeric($value)) { return false; @@ -367,7 +383,7 @@ protected static function validateNumeric(mixed &$value): bool return true; } - protected static function validateInteger(mixed &$value): bool + protected static function validateInteger(mixed &$value, array $attributes): bool { if (filter_var($value, FILTER_VALIDATE_INT) === false) { return false; @@ -376,17 +392,17 @@ protected static function validateInteger(mixed &$value): bool return true; } - protected static function validateString(mixed $value): bool + protected static function validateString(mixed $value, array $attributes): bool { return is_string($value); } - protected static function validateArray(mixed $value): bool + protected static function validateArray(mixed $value, array $attributes): bool { return is_array($value); } - protected static function getLength(mixed $value): int + protected static function getLength(mixed $value, array $attributes): int { if (is_numeric($value)) { return $value + 0; @@ -403,49 +419,50 @@ protected static function getLength(mixed $value): int return mb_strlen((string) $value); } - protected static function validateMin(mixed $value, int|float $min): bool + protected static function validateMin(mixed $value, array $attributes, int|float $min): bool { // TODO: file min support b, kb, mb, gb ... return static::getLength($value) >= $min; } - protected static function validateMax(mixed $value, int|float $max): bool + protected static function validateMax(mixed $value, array $attributes, int|float $max): bool { // TODO: file max support b, kb, mb, gb ... return static::getLength($value) <= $max; } - protected static function validateMinInteger(int $value, int|float $min): bool + protected static function validateMinInteger(int $value, array $attributes, int|float $min): bool { return $value >= $min; } - protected static function validateMaxInteger(int $value, int|float $max): bool + protected static function validateMaxInteger(int $value, array $attributes, int|float $max): bool { return $value <= $max; } - protected static function validateMinNumeric(int|float $value, int|float $min): bool + protected static function validateMinNumeric(int|float $value, array $attributes, int|float $min): bool { return $value >= $min; } - protected static function validateMaxNumeric(int|float $value, int|float $max): bool + protected static function validateMaxNumeric(int|float $value, array $attributes, int|float $max): bool { return $value <= $max; } - protected static function validateMinString(string $value, int|float $min): bool + protected static function validateMinString(string $value, array $attributes, int|float $min): bool { return mb_strlen($value) >= $min; } - protected static function validateMaxString(string $value, int|float $max): bool + protected static function validateMaxString(string $value, array $attributes, int|float $max): bool { return mb_strlen($value) <= $max; } - #[Pure] protected static function validateInList(mixed $value, array $list): bool + #[Pure] + protected static function validateInList(mixed $value, array $attributes, array $list): bool { if (!is_array($value)) { return in_array((string) $value, $list, true); @@ -454,7 +471,7 @@ protected static function validateMaxString(string $value, int|float $max): bool } } - protected static function validateInListArray(array $value, array $list): bool + protected static function validateInListArray(array $value, array $attributes, array $list): bool { foreach ($value as $item) { if (is_array($item)) { @@ -467,7 +484,8 @@ protected static function validateInListArray(array $value, array $list): bool return true; } - #[Pure] protected static function validateInMap(mixed $value, array $map): bool + #[Pure] + protected static function validateInMap(mixed $value, array $attributes, array $map): bool { if (!is_array($value)) { return $map[(string) $value] ?? false; @@ -476,7 +494,7 @@ protected static function validateInListArray(array $value, array $list): bool } } - protected static function validateInMapArray(array $value, array $map): bool + protected static function validateInMapArray(array $value, array $attributes, array $map): bool { foreach ($value as $item) { if (is_array($item)) { @@ -489,32 +507,32 @@ protected static function validateInMapArray(array $value, array $map): bool return true; } - public static function validateAlpha(string $value): bool + public static function validateAlpha(string $value, array $attributes): bool { return preg_match('/^[\pL\pM]+$/u', $value); } - public static function validateAlphaNum(string $value): bool + public static function validateAlphaNum(string $value, array $attributes): bool { return preg_match('/^[\pL\pM\pN]+$/u', $value) > 0; } - public static function validateAlphaDash(string $value): bool + public static function validateAlphaDash(string $value, array $attributes): bool { return preg_match('/^[\pL\pM\pN_-]+$/u', $value) > 0; } - public static function validateIP(string $value): bool + public static function validateIP(string $value, array $attributes): bool { return filter_var($value, FILTER_VALIDATE_IP) !== false; } - public static function validateIPV4(string $value): bool + public static function validateIPV4(string $value, array $attributes): bool { return filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false; } - public static function validateIPV6(string $value): bool + public static function validateIPV6(string $value, array $attributes): bool { return filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false; } diff --git a/src/Validator.php b/src/Validator.php index 0d37d35..7cecd62 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -115,7 +115,7 @@ protected function validRecursive(array $data, array $validationPairs, array $cu continue; } $value = $data[$currentPatternPart]; - $errors = $ruleset->check($value); + $errors = $ruleset->check($value, $data); if ($errors) { $this->recordErrors($currentPatternPart, $errors); $invalid = true; From d5e68a047f4e3d2e45b65c9cb5fd7939dab26e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=93=AD=E6=98=95?= <715557344@qq.com> Date: Mon, 29 Apr 2024 22:59:03 +0800 Subject: [PATCH 3/3] Update --- src/ValidationRule.php | 9 +++++++++ src/ValidationRuleset.php | 17 +++++++++++++---- src/Validator.php | 6 ++++++ tests/HyperfValidatorTest.php | 12 ++++++++++++ 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/ValidationRule.php b/src/ValidationRule.php index b0f3486..a1caf2c 100644 --- a/src/ValidationRule.php +++ b/src/ValidationRule.php @@ -24,10 +24,19 @@ public static function make(string $name, Closure $closure, array $args = []): s return static::$pool[$hash] ?? (static::$pool[$hash] = new static($name, $closure, $args)); } + public string $rule; + protected function __construct( public string $name, public Closure $closure, public array $args = [] ) { + $this->rule = $this->name; + } + + public function setRule(string $rule): static + { + $this->rule = $rule; + return $this; } } diff --git a/src/ValidationRuleset.php b/src/ValidationRuleset.php index 694d908..67564be 100644 --- a/src/ValidationRuleset.php +++ b/src/ValidationRuleset.php @@ -3,6 +3,7 @@ namespace KK\Validation; use Closure; +use Hyperf\Validation\ValidationRuleParser; use InvalidArgumentException; use JetBrains\PhpStorm\Pure; use SplFileInfo; @@ -116,8 +117,9 @@ protected function __construct(array $ruleMap) if (count($ruleArgs) !== 2) { throw new InvalidArgumentException("Rule '{$rule}' require 2 parameter"); } + $name = "{$rule}:{$ruleArgs[0]},{$ruleArgs[1]}"; $ruleArgs[] = 'validateRequired' . static::fetchTypedRule($ruleMap); - $rules[] = ValidationRule::make('required_if', static::getClosure('validateRequiredIf'), $ruleArgs); + $rules[] = ValidationRule::make($name, static::getClosure('validateRequiredIf'), $ruleArgs)->setRule($rule); break; case 'nullable': $flags |= static::FLAG_NULLABLE; @@ -207,7 +209,7 @@ public function getRules(): array /** * @return string[] Error attribute names */ - public function check(mixed $data, array $attributes = []): array + public function check(mixed $data, array $attributes = [], ?string $ruleName = null): array { if (($this->flags & static::FLAG_NULLABLE) && $data === null) { return []; @@ -216,6 +218,10 @@ public function check(mixed $data, array $attributes = []): array $errors = []; foreach ($this->rules as $rule) { + if ($ruleName && $ruleName !== $rule->rule) { + continue; + } + $closure = $rule->closure; $valid = $closure($data, $attributes, ...$rule->args); if (!$valid) { @@ -352,6 +358,9 @@ protected static function validateRequiredIf(mixed $value, array $attributes, st { if (array_key_exists($key, $attributes)) { if ($attributes[$key] == $keyValue) { + if ($value === null) { + return false; + } return self::$validator($value, $attributes); } } @@ -422,13 +431,13 @@ protected static function getLength(mixed $value, array $attributes): int protected static function validateMin(mixed $value, array $attributes, int|float $min): bool { // TODO: file min support b, kb, mb, gb ... - return static::getLength($value) >= $min; + return static::getLength($value, $attributes) >= $min; } protected static function validateMax(mixed $value, array $attributes, int|float $max): bool { // TODO: file max support b, kb, mb, gb ... - return static::getLength($value) <= $max; + return static::getLength($value, $attributes) <= $max; } protected static function validateMinInteger(int $value, array $attributes, int|float $min): bool diff --git a/src/Validator.php b/src/Validator.php index 7cecd62..21b109c 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -112,6 +112,12 @@ protected function validRecursive(array $data, array $validationPairs, array $cu $this->recordError($currentPatternPart, 'required'); $invalid = true; } + + if($errors = $ruleset->check(null, $data, 'required_if')){ + $this->recordErrors($currentPatternPart, $errors); + $invalid = true; + } + continue; } $value = $data[$currentPatternPart]; diff --git a/tests/HyperfValidatorTest.php b/tests/HyperfValidatorTest.php index de60eac..64c7b4f 100644 --- a/tests/HyperfValidatorTest.php +++ b/tests/HyperfValidatorTest.php @@ -44,6 +44,18 @@ public function testFails() $this->assertFalse($validator->fails()); } + public function testRequiredIf() + { + $validator = $this->makeValidator(['type' => 1], ['id' => 'required_if:type,1', 'type' => 'required']); + $this->assertTrue($validator->fails()); + } + + public function testMax() + { + $validator = $this->makeValidator(['id' => 256], ['id' => 'max:255']); + $this->assertTrue($validator->fails()); + } + public function testGetMessageBag() { $data = [['id' => 256], ['id' => 'required|integer|max:255']];