From e5c2a4072674117409e0eceef946d5d405cdda9c Mon Sep 17 00:00:00 2001 From: MallardDuck Date: Sat, 19 Sep 2020 20:37:36 -0400 Subject: [PATCH 1/3] Add an UnfilledIf validation rule to Validator --- .../Concerns/ReplacesAttributes.php | 15 +++++++++++++ .../Concerns/ValidatesAttributes.php | 21 +++++++++++++++++++ src/Illuminate/Validation/Validator.php | 1 + tests/Validation/ValidationValidatorTest.php | 18 ++++++++++++++++ 4 files changed, 55 insertions(+) diff --git a/src/Illuminate/Validation/Concerns/ReplacesAttributes.php b/src/Illuminate/Validation/Concerns/ReplacesAttributes.php index f5c3eb00c4e0..84b69aa9bab6 100644 --- a/src/Illuminate/Validation/Concerns/ReplacesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ReplacesAttributes.php @@ -505,4 +505,19 @@ protected function replaceStartsWith($message, $attribute, $rule, $parameters) return str_replace(':values', implode(', ', $parameters), $message); } + + + /** + * Replace all place-holders for the unfilled_if rule. + * + * @param string $message + * @param string $attribute + * @param string $rule + * @param array $parameters + * @return string + */ + protected function replaceUnfilledIf($message, $attribute, $rule, $parameters) + { + return $this->replaceRequiredIf($message, $attribute, $rule, $parameters); + } } diff --git a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php index fe394a2b0638..e0f197bb8b2f 100644 --- a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php @@ -1726,6 +1726,27 @@ public function validateTimezone($attribute, $value) return in_array($value, timezone_identifiers_list(), true); } + /** + * Validate the given attribute is unfilled if another field is present. + * + * @param string $attribute + * @param mixed $value + * @param mixed $parameters + * @return bool + */ + public function validateUnfilledIf($attribute, $value, $parameters) + { + $this->requireParameterCount(1, $parameters, 'unfilled_if'); + + [$values, $other] = $this->prepareValuesAndOther($parameters); + + if (!is_null($other)) { + return false; + } + + return true; + } + /** * Validate that an attribute is a valid URL. * diff --git a/src/Illuminate/Validation/Validator.php b/src/Illuminate/Validation/Validator.php index 86fbfc8769eb..17e7935818d6 100755 --- a/src/Illuminate/Validation/Validator.php +++ b/src/Illuminate/Validation/Validator.php @@ -221,6 +221,7 @@ class Validator implements ValidatorContract 'RequiredWithout', 'RequiredWithoutAll', 'Same', + 'UnfilledIf', 'Unique', ]; diff --git a/tests/Validation/ValidationValidatorTest.php b/tests/Validation/ValidationValidatorTest.php index 826aeef296c3..cfecda336005 100755 --- a/tests/Validation/ValidationValidatorTest.php +++ b/tests/Validation/ValidationValidatorTest.php @@ -5571,6 +5571,24 @@ public function testValidateFailsWithAsterisksAsDataKeys() $this->assertSame(['data.1.date' => ['validation.date'], 'data.*.date' => ['validation.date']], $validator->messages()->toArray()); } + public function testValidateUnfilledIf() + { + $v = new Validator($this->getIlluminateArrayTranslator(), [], ['name' => 'unfilled_if:first_name', 'first_name' => 'sometimes']); + $this->assertTrue($v->passes()); + + $v = new Validator($this->getIlluminateArrayTranslator(), ['name' => 'Ricky Bobby'], ['name' => 'unfilled_if:first_name', 'first_name' => 'sometimes']); + $this->assertTrue($v->passes()); + + $v = new Validator($this->getIlluminateArrayTranslator(), ['first_name' => 'Richard', 'last_name' => 'Robert'], ['name' => 'unfilled_if:first_name', 'first_name' => 'sometimes', 'last_name' => 'sometimes']); + $this->assertTrue($v->passes()); + + $v = new Validator($this->getIlluminateArrayTranslator(), ['name' => 'Ricky Bobby', 'first_name' => 'Richard', 'last_name' => 'Robert'], ['name' => 'unfilled_if:first_name', 'first_name' => 'sometimes']); + $this->assertTrue($v->fails()); + + $v = new Validator($this->getIlluminateArrayTranslator(), ['name' => 'Ricky Bobby', 'first_name' => 'Richard', 'last_name' => 'Robert'], ['name' => 'sometimes', 'first_name' => 'unfilled_if:name', 'last_name' => 'unfilled_if:name']); + $this->assertTrue($v->fails()); + } + protected function getTranslator() { return m::mock(TranslatorContract::class); From 86babcff14d6255fe884d20e86b49a9f9046f494 Mon Sep 17 00:00:00 2001 From: MallardDuck Date: Sun, 20 Sep 2020 13:39:39 -0400 Subject: [PATCH 2/3] Fix whitespace issue --- src/Illuminate/Validation/Concerns/ReplacesAttributes.php | 1 - src/Illuminate/Validation/Concerns/ValidatesAttributes.php | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Illuminate/Validation/Concerns/ReplacesAttributes.php b/src/Illuminate/Validation/Concerns/ReplacesAttributes.php index 84b69aa9bab6..b2c66f2b7df0 100644 --- a/src/Illuminate/Validation/Concerns/ReplacesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ReplacesAttributes.php @@ -506,7 +506,6 @@ protected function replaceStartsWith($message, $attribute, $rule, $parameters) return str_replace(':values', implode(', ', $parameters), $message); } - /** * Replace all place-holders for the unfilled_if rule. * diff --git a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php index e0f197bb8b2f..14cf22f11c2a 100644 --- a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php @@ -1740,7 +1740,7 @@ public function validateUnfilledIf($attribute, $value, $parameters) [$values, $other] = $this->prepareValuesAndOther($parameters); - if (!is_null($other)) { + if (! is_null($other)) { return false; } From bbcfbecc82affa5d404583e9596184e3e49d6acd Mon Sep 17 00:00:00 2001 From: MallardDuck Date: Sun, 20 Sep 2020 15:30:46 -0400 Subject: [PATCH 3/3] Update methods to match similar existing methods Make the unfilled_if match required_if, and implement unfilled_with method similar to original goal. --- .../Concerns/ReplacesAttributes.php | 14 ++++ .../Concerns/ValidatesAttributes.php | 25 ++++++- tests/Validation/ValidationValidatorTest.php | 66 +++++++++++++++++-- 3 files changed, 97 insertions(+), 8 deletions(-) diff --git a/src/Illuminate/Validation/Concerns/ReplacesAttributes.php b/src/Illuminate/Validation/Concerns/ReplacesAttributes.php index b2c66f2b7df0..414354c7c04f 100644 --- a/src/Illuminate/Validation/Concerns/ReplacesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ReplacesAttributes.php @@ -519,4 +519,18 @@ protected function replaceUnfilledIf($message, $attribute, $rule, $parameters) { return $this->replaceRequiredIf($message, $attribute, $rule, $parameters); } + + /** + * Replace all place-holders for the unfilled_with rule. + * + * @param string $message + * @param string $attribute + * @param string $rule + * @param array $parameters + * @return string + */ + protected function replaceUnfilledWith($message, $attribute, $rule, $parameters) + { + return $this->replaceRequiredWith($message, $attribute, $rule, $parameters); + } } diff --git a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php index 14cf22f11c2a..132a245bf572 100644 --- a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php @@ -1727,7 +1727,7 @@ public function validateTimezone($attribute, $value) } /** - * Validate the given attribute is unfilled if another field is present. + * Validate that an attribute is unfilled when another attribute has a given value. * * @param string $attribute * @param mixed $value @@ -1740,8 +1740,27 @@ public function validateUnfilledIf($attribute, $value, $parameters) [$values, $other] = $this->prepareValuesAndOther($parameters); - if (! is_null($other)) { - return false; + if (in_array($other, $values)) { + return ! $this->validateRequired($attribute, $value); + } + + return true; + } + + /** + * Validate that an attribute is unfilled when any other attribute exists. + * + * @param string $attribute + * @param mixed $value + * @param mixed $parameters + * @return bool + */ + public function validateUnfilledWith($attribute, $value, $parameters) + { + $this->requireParameterCount(1, $parameters, 'unfilled_with'); + + if (! $this->allFailingRequired($parameters)) { + return ! $this->validateRequired($attribute, $value); } return true; diff --git a/tests/Validation/ValidationValidatorTest.php b/tests/Validation/ValidationValidatorTest.php index cfecda336005..9f99269f29fa 100755 --- a/tests/Validation/ValidationValidatorTest.php +++ b/tests/Validation/ValidationValidatorTest.php @@ -5573,20 +5573,76 @@ public function testValidateFailsWithAsterisksAsDataKeys() public function testValidateUnfilledIf() { - $v = new Validator($this->getIlluminateArrayTranslator(), [], ['name' => 'unfilled_if:first_name', 'first_name' => 'sometimes']); + $basicUnfilledRules = [ + 'mode' => 'required', + 'full_name' => 'unfilled_if:mode,split', + 'first_name' => 'required_if:mode,split', + 'last_name' => 'required_if:mode,split', + ]; + $v = new Validator($this->getIlluminateArrayTranslator(), ['mode' => 'none'], $basicUnfilledRules); + $this->assertTrue($v->passes()); + + $v = new Validator($this->getIlluminateArrayTranslator(), [ + 'mode' => 'split', + 'first_name' => 'Richard', + 'last_name' => 'Bobby', + ], $basicUnfilledRules); + $this->assertTrue($v->passes()); + + $v = new Validator($this->getIlluminateArrayTranslator(), [ + 'mode' => 'split', + 'full_name' => 'Ricky Bobby', + 'first_name' => 'Richard', + 'last_name' => 'Bobby', + ], $basicUnfilledRules); + $this->assertTrue($v->fails()); + + $v = new Validator($this->getIlluminateArrayTranslator(), [ + 'mode' => 'split', + 'full_name' => 'Ricky Bobby', + 'last_name' => 'Bobby', + ], $basicUnfilledRules); + $this->assertTrue($v->fails()); + + $basicUnfilledRules = [ + 'mode' => 'required', + 'full_name' => 'required_if:mode,single', + 'first_name' => 'unfilled_if:mode,single', + 'last_name' => 'unfilled_if:mode,single', + ]; + $v = new Validator($this->getIlluminateArrayTranslator(), [ + 'mode' => 'single', + 'full_name' => 'Ricky Bobby', + ], $basicUnfilledRules); $this->assertTrue($v->passes()); - $v = new Validator($this->getIlluminateArrayTranslator(), ['name' => 'Ricky Bobby'], ['name' => 'unfilled_if:first_name', 'first_name' => 'sometimes']); + $v = new Validator($this->getIlluminateArrayTranslator(), [ + 'mode' => 'single', + 'full_name' => 'Ricky Bobby', + 'last_name' => 'Bobby', + ], $basicUnfilledRules); + $this->assertTrue($v->fails()); + } + + public function testValidateUnfilledWith() + { + $v = new Validator($this->getIlluminateArrayTranslator(), [], ['name' => 'unfilled_with:first_name', 'first_name' => 'sometimes']); $this->assertTrue($v->passes()); - $v = new Validator($this->getIlluminateArrayTranslator(), ['first_name' => 'Richard', 'last_name' => 'Robert'], ['name' => 'unfilled_if:first_name', 'first_name' => 'sometimes', 'last_name' => 'sometimes']); + $v = new Validator($this->getIlluminateArrayTranslator(), ['name' => 'Ricky Bobby'], ['name' => 'unfilled_with:first_name,last_name', 'first_name' => 'sometimes']); $this->assertTrue($v->passes()); - $v = new Validator($this->getIlluminateArrayTranslator(), ['name' => 'Ricky Bobby', 'first_name' => 'Richard', 'last_name' => 'Robert'], ['name' => 'unfilled_if:first_name', 'first_name' => 'sometimes']); + $v = new Validator($this->getIlluminateArrayTranslator(), ['name' => 'Ricky Bobby', 'first_name' => 'Richard', 'last_name' => 'Robertson'], ['name' => 'unfilled_with:first_name,last_name', 'first_name' => 'sometimes', 'last_name' => 'sometimes']); $this->assertTrue($v->fails()); - $v = new Validator($this->getIlluminateArrayTranslator(), ['name' => 'Ricky Bobby', 'first_name' => 'Richard', 'last_name' => 'Robert'], ['name' => 'sometimes', 'first_name' => 'unfilled_if:name', 'last_name' => 'unfilled_if:name']); + $v = new Validator($this->getIlluminateArrayTranslator(), ['name' => 'Ricky Bobby', 'last_name' => 'Robertson'], ['name' => 'unfilled_with:first_name,last_name', 'first_name' => 'sometimes']); $this->assertTrue($v->fails()); + + $v = new Validator($this->getIlluminateArrayTranslator(), ['name' => 'Ricky Bobby', 'first_name' => 'Richard', 'last_name' => 'Robert'], ['name' => 'sometimes', 'first_name' => 'unfilled_with:name', 'last_name' => 'unfilled_with:name']); + $this->assertTrue($v->fails()); + + $v = new Validator($this->getIlluminateArrayTranslator(), ['first_name' => 'Richard', 'last_name' => 'Robert'], ['name' => 'sometimes', 'first_name' => 'unfilled_with:name', 'last_name' => 'unfilled_with:name']); + $this->assertTrue($v->passes()); } protected function getTranslator()