From cd0a342282b07f0fb822fd54a1a66b42e821d60a Mon Sep 17 00:00:00 2001 From: Peter Fox Date: Sat, 15 Feb 2025 19:16:11 +0000 Subject: [PATCH 1/3] Stops validation if a custom rule specifies it formatting formatting --- .../Contracts/Validation/StopUponFailure.php | 13 ++++++ src/Illuminate/Validation/Validator.php | 11 ++++- .../ValidationStopOnFailureTest.php | 42 +++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/Illuminate/Contracts/Validation/StopUponFailure.php create mode 100644 tests/Validation/ValidationStopOnFailureTest.php diff --git a/src/Illuminate/Contracts/Validation/StopUponFailure.php b/src/Illuminate/Contracts/Validation/StopUponFailure.php new file mode 100644 index 000000000000..39d46bd20589 --- /dev/null +++ b/src/Illuminate/Contracts/Validation/StopUponFailure.php @@ -0,0 +1,13 @@ +shouldStopValidating($attribute)) { + if ($this->shouldStopValidating($attribute, $rule)) { break; } } @@ -909,9 +911,10 @@ protected function validateUsingCustomRule($attribute, $value, $rule) * Check if we should stop further validations on a given attribute. * * @param string $attribute + * @param string|ValidationRule * @return bool */ - protected function shouldStopValidating($attribute) + protected function shouldStopValidating($attribute, $rule) { $cleanedAttribute = $this->replacePlaceholderInString($attribute); @@ -919,6 +922,10 @@ protected function shouldStopValidating($attribute) return $this->messages->has($cleanedAttribute); } + if ($rule instanceof InvokableValidationRule && $rule->invokable() instanceof StopUponFailure) { + return $rule->invokable()->shouldStop(); + } + if (isset($this->failedRules[$cleanedAttribute]) && array_key_exists('uploaded', $this->failedRules[$cleanedAttribute])) { return true; diff --git a/tests/Validation/ValidationStopOnFailureTest.php b/tests/Validation/ValidationStopOnFailureTest.php new file mode 100644 index 000000000000..bd20286e6768 --- /dev/null +++ b/tests/Validation/ValidationStopOnFailureTest.php @@ -0,0 +1,42 @@ + 'foobar'], + ['foo' => [new StoppingValidationRule(), 'numeric']], + ); + $this->assertFalse($v->passes()); + $this->assertEquals( + ['foo' => ['Illuminate\Tests\Validation\StoppingValidationRule' => []]], + $v->failed() + ); + } +} + +class StoppingValidationRule implements ValidationRule, StopUponFailure +{ + public function shouldStop(): bool + { + return true; + } + + public function validate(string $attribute, mixed $value, Closure $fail): void + { + $fail('failed'); + } +} From 362f5749579304d8d87b43566d057ee56ecea61a Mon Sep 17 00:00:00 2001 From: Peter Fox Date: Tue, 25 Feb 2025 01:43:31 +0000 Subject: [PATCH 2/3] Change to Bailable contract --- src/Illuminate/Contracts/Validation/Bailable.php | 5 +++++ .../Contracts/Validation/StopUponFailure.php | 13 ------------- src/Illuminate/Validation/Validator.php | 6 +++--- ...est.php => ValidationRuleWithBailableTest.php} | 15 +++++---------- 4 files changed, 13 insertions(+), 26 deletions(-) create mode 100644 src/Illuminate/Contracts/Validation/Bailable.php delete mode 100644 src/Illuminate/Contracts/Validation/StopUponFailure.php rename tests/Validation/{ValidationStopOnFailureTest.php => ValidationRuleWithBailableTest.php} (66%) diff --git a/src/Illuminate/Contracts/Validation/Bailable.php b/src/Illuminate/Contracts/Validation/Bailable.php new file mode 100644 index 000000000000..503b9cb0aac9 --- /dev/null +++ b/src/Illuminate/Contracts/Validation/Bailable.php @@ -0,0 +1,5 @@ +messages->has($cleanedAttribute); } - if ($rule instanceof InvokableValidationRule && $rule->invokable() instanceof StopUponFailure) { - return $rule->invokable()->shouldStop(); + if ($rule instanceof InvokableValidationRule && $rule->invokable() instanceof Bailable) { + return true; } if (isset($this->failedRules[$cleanedAttribute]) && diff --git a/tests/Validation/ValidationStopOnFailureTest.php b/tests/Validation/ValidationRuleWithBailableTest.php similarity index 66% rename from tests/Validation/ValidationStopOnFailureTest.php rename to tests/Validation/ValidationRuleWithBailableTest.php index bd20286e6768..bc95c420222b 100644 --- a/tests/Validation/ValidationStopOnFailureTest.php +++ b/tests/Validation/ValidationRuleWithBailableTest.php @@ -3,14 +3,14 @@ namespace Illuminate\Tests\Validation; use Closure; -use Illuminate\Contracts\Validation\StopUponFailure; +use Illuminate\Contracts\Validation\Bailable; use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Translation\ArrayLoader; use Illuminate\Translation\Translator; use Illuminate\Validation\Validator; use PHPUnit\Framework\TestCase; -class ValidationStopOnFailureTest extends TestCase +class ValidationRuleWithBailableTest extends TestCase { public function testFailingStopsFurtherValidation() { @@ -18,23 +18,18 @@ public function testFailingStopsFurtherValidation() $v = new Validator( $trans, ['foo' => 'foobar'], - ['foo' => [new StoppingValidationRule(), 'numeric']], + ['foo' => [new BailableValidationRule(), 'numeric']], ); $this->assertFalse($v->passes()); $this->assertEquals( - ['foo' => ['Illuminate\Tests\Validation\StoppingValidationRule' => []]], + ['foo' => ['Illuminate\Tests\Validation\BailableValidationRule' => []]], $v->failed() ); } } -class StoppingValidationRule implements ValidationRule, StopUponFailure +class BailableValidationRule implements ValidationRule, Bailable { - public function shouldStop(): bool - { - return true; - } - public function validate(string $attribute, mixed $value, Closure $fail): void { $fail('failed'); From ecd7b448d98a43e04055d5c1ca1f1ef7d44166df Mon Sep 17 00:00:00 2001 From: Peter Fox Date: Tue, 25 Feb 2025 01:56:05 +0000 Subject: [PATCH 3/3] cs fixes --- src/Illuminate/Contracts/Validation/Bailable.php | 4 +++- src/Illuminate/Validation/Validator.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Contracts/Validation/Bailable.php b/src/Illuminate/Contracts/Validation/Bailable.php index 503b9cb0aac9..6c5bbe515ce2 100644 --- a/src/Illuminate/Contracts/Validation/Bailable.php +++ b/src/Illuminate/Contracts/Validation/Bailable.php @@ -2,4 +2,6 @@ namespace Illuminate\Contracts\Validation; -interface Bailable {} +interface Bailable +{ +} diff --git a/src/Illuminate/Validation/Validator.php b/src/Illuminate/Validation/Validator.php index 946a80bf8692..7b022b29fcca 100755 --- a/src/Illuminate/Validation/Validator.php +++ b/src/Illuminate/Validation/Validator.php @@ -5,10 +5,10 @@ use BadMethodCallException; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Translation\Translator; +use Illuminate\Contracts\Validation\Bailable; use Illuminate\Contracts\Validation\DataAwareRule; use Illuminate\Contracts\Validation\ImplicitRule; use Illuminate\Contracts\Validation\Rule as RuleContract; -use Illuminate\Contracts\Validation\Bailable; use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Contracts\Validation\Validator as ValidatorContract; use Illuminate\Contracts\Validation\ValidatorAwareRule;