From eb1063eefc9a68f4166bd683f83e420b5657bee6 Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Fri, 6 Dec 2024 09:37:57 +0100 Subject: [PATCH 1/3] feat: allow validating missing keys --- .../package-manager/src/AllValidatorRules.php | 31 ------------------- .../src/ConfigureAuthValidator.php | 2 +- .../src/ConfigureComposerValidator.php | 2 +- .../core/src/Foundation/AbstractValidator.php | 26 +++++++++++++--- 4 files changed, 24 insertions(+), 37 deletions(-) delete mode 100644 extensions/package-manager/src/AllValidatorRules.php diff --git a/extensions/package-manager/src/AllValidatorRules.php b/extensions/package-manager/src/AllValidatorRules.php deleted file mode 100644 index e2d8757e75..0000000000 --- a/extensions/package-manager/src/AllValidatorRules.php +++ /dev/null @@ -1,31 +0,0 @@ -getRules(); - - $validator = $this->validator->make($attributes, $rules, $this->getMessages()); - - foreach ($this->configuration as $callable) { - $callable($this, $validator); - } - - return $validator; - } -} diff --git a/extensions/package-manager/src/ConfigureAuthValidator.php b/extensions/package-manager/src/ConfigureAuthValidator.php index 14a9a03ed4..528a12c403 100644 --- a/extensions/package-manager/src/ConfigureAuthValidator.php +++ b/extensions/package-manager/src/ConfigureAuthValidator.php @@ -13,7 +13,7 @@ class ConfigureAuthValidator extends AbstractValidator { - use AllValidatorRules; + protected bool $validateMissingKeys = true; protected array $rules = [ 'github-oauth' => ['sometimes', 'array'], diff --git a/extensions/package-manager/src/ConfigureComposerValidator.php b/extensions/package-manager/src/ConfigureComposerValidator.php index 6292e5539c..a58a172d08 100644 --- a/extensions/package-manager/src/ConfigureComposerValidator.php +++ b/extensions/package-manager/src/ConfigureComposerValidator.php @@ -13,7 +13,7 @@ class ConfigureComposerValidator extends AbstractValidator { - use AllValidatorRules; + protected bool $validateMissingKeys = true; protected array $rules = [ 'minimum-stability' => ['sometimes', 'in:stable,RC,beta,alpha,dev'], diff --git a/framework/core/src/Foundation/AbstractValidator.php b/framework/core/src/Foundation/AbstractValidator.php index 788b85a7c0..12eafcd59d 100644 --- a/framework/core/src/Foundation/AbstractValidator.php +++ b/framework/core/src/Foundation/AbstractValidator.php @@ -22,13 +22,12 @@ abstract class AbstractValidator */ protected array $configuration = []; - /** - * @var array - */ protected array $rules = []; protected ?Validator $laravelValidator = null; + protected bool $validateMissingKeys = false; + public function __construct( protected Factory $validator, protected TranslatorInterface $translator @@ -54,6 +53,16 @@ public function assertValid(array $attributes): void } } + /** + * Whether to validate missing keys or to only validate provided data keys. + */ + public function validateMissingKeys(bool $validateMissingKeys = true): static + { + $this->validateMissingKeys = $validateMissingKeys; + + return $this; + } + public function prepare(array $attributes): static { $this->laravelValidator ??= $this->makeValidator($attributes); @@ -71,6 +80,15 @@ protected function getRules(): array return $this->rules; } + protected function getActiveRules(array $attributes): array + { + $rules = $this->getRules(); + + return $this->validateMissingKeys + ? $rules + : Arr::only($rules, array_keys($attributes)); + } + protected function getMessages(): array { return []; @@ -78,7 +96,7 @@ protected function getMessages(): array protected function makeValidator(array $attributes): Validator { - $rules = Arr::only($this->getRules(), array_keys($attributes)); + $rules = $this->getActiveRules($attributes); $validator = $this->validator->make($attributes, $rules, $this->getMessages()); From b0a34737d69e13de33240e5b54f01e570ab63050 Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Fri, 6 Dec 2024 10:03:51 +0100 Subject: [PATCH 2/3] fixes #3612 --- .../core/src/Foundation/AbstractValidator.php | 20 ++++++- .../integration/extenders/ValidatorTest.php | 59 ++++++++++++++++++- 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/framework/core/src/Foundation/AbstractValidator.php b/framework/core/src/Foundation/AbstractValidator.php index 12eafcd59d..a43be822c8 100644 --- a/framework/core/src/Foundation/AbstractValidator.php +++ b/framework/core/src/Foundation/AbstractValidator.php @@ -11,6 +11,8 @@ use Flarum\Locale\TranslatorInterface; use Illuminate\Support\Arr; +use Illuminate\Support\Collection; +use Illuminate\Support\Str; use Illuminate\Validation\Factory; use Illuminate\Validation\ValidationException; use Illuminate\Validation\Validator; @@ -84,9 +86,21 @@ protected function getActiveRules(array $attributes): array { $rules = $this->getRules(); - return $this->validateMissingKeys - ? $rules - : Arr::only($rules, array_keys($attributes)); + if ($this->validateMissingKeys) { + return $rules; + } + + return Collection::make($rules) + ->filter(function (mixed $rule, string $key) use ($attributes) { + foreach ($attributes as $attributeKey => $attributeValue) { + if ($attributeKey === $key || Str::startsWith($key, $attributeKey . '.')) { + return true; + } + } + + return false; + }) + ->all(); } protected function getMessages(): array diff --git a/framework/core/tests/integration/extenders/ValidatorTest.php b/framework/core/tests/integration/extenders/ValidatorTest.php index eafaf4dae0..01bf94e6cd 100644 --- a/framework/core/tests/integration/extenders/ValidatorTest.php +++ b/framework/core/tests/integration/extenders/ValidatorTest.php @@ -18,7 +18,7 @@ class ValidatorTest extends TestCase { - private function extendToRequireLongPassword() + private function extendToRequireLongPassword(): void { $this->extend((new Extend\Validator(CustomUserValidator::class))->configure(function ($flarumValidator, $validator) { $validator->setRules([ @@ -30,7 +30,7 @@ private function extendToRequireLongPassword() })); } - private function extendToRequireLongPasswordViaInvokableClass() + private function extendToRequireLongPasswordViaInvokableClass(): void { $this->extend((new Extend\Validator(CustomUserValidator::class))->configure(CustomValidatorClass::class)); } @@ -74,6 +74,51 @@ public function custom_validation_rule_doesnt_affect_other_validators() // If we have gotten this far, no validation exception has been thrown, so the test is successful. $this->assertTrue(true); } + + #[Test] + public function validator_only_validates_provided_data_by_default() + { + /** @var SecondCustomValidator $validator */ + $validator = $this->app()->getContainer()->make(SecondCustomValidator::class); + + $validator->assertValid([ + 'my_key' => 'value', + ]); + + // If we have gotten this far, no validation exception has been thrown, so the test is successful. + $this->assertTrue(true); + } + + #[Test] + public function validator_includes_path_based_rules() + { + /** @var SecondCustomValidator $validator */ + $validator = $this->app()->getContainer()->make(SecondCustomValidator::class); + + $this->expectException(ValidationException::class); + + $validator->assertValid([ + 'my_key' => 'value', + 'my_third_key' => [null], + ]); + } + + #[Test] + public function validator_can_validate_missing_keys() + { + /** @var SecondCustomValidator $validator */ + $validator = $this->app()->getContainer()->make(SecondCustomValidator::class)->validateMissingKeys(); + + $this->expectException(ValidationException::class); + + $validator->validateMissingKeys()->assertValid([ + 'my_key' => 'value', + 'my_third_key' => [ + '2021-01-01 00:00:00', + '2021-01-02 00:00:00' + ] + ]); + } } class CustomValidatorClass @@ -142,3 +187,13 @@ class CustomValidator extends AbstractValidator 'name_plural' => ['required'] ]; } + +class SecondCustomValidator extends AbstractValidator +{ + protected array $rules = [ + 'my_key' => ['required'], + 'my_other_key' => ['required'], + 'my_third_key' => ['required', 'array'], + 'my_third_key.*' => ['required', 'date'] + ]; +} From 99cb01e93fac811102eb681fe23a55dc68f2933b Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Fri, 6 Dec 2024 09:04:09 +0000 Subject: [PATCH 3/3] Apply fixes from StyleCI --- framework/core/src/Foundation/AbstractValidator.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/core/src/Foundation/AbstractValidator.php b/framework/core/src/Foundation/AbstractValidator.php index a43be822c8..0e4048827a 100644 --- a/framework/core/src/Foundation/AbstractValidator.php +++ b/framework/core/src/Foundation/AbstractValidator.php @@ -10,7 +10,6 @@ namespace Flarum\Foundation; use Flarum\Locale\TranslatorInterface; -use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Str; use Illuminate\Validation\Factory; @@ -93,7 +92,7 @@ protected function getActiveRules(array $attributes): array return Collection::make($rules) ->filter(function (mixed $rule, string $key) use ($attributes) { foreach ($attributes as $attributeKey => $attributeValue) { - if ($attributeKey === $key || Str::startsWith($key, $attributeKey . '.')) { + if ($attributeKey === $key || Str::startsWith($key, $attributeKey.'.')) { return true; } }