From 1566c115af20a5933f0f8137467ae8286d152759 Mon Sep 17 00:00:00 2001 From: nath Date: Thu, 22 Apr 2021 15:56:26 +0200 Subject: [PATCH] Add prohibited_with and prohibited_without validation rules --- .../Concerns/ReplacesAttributes.php | 56 +++++ .../Concerns/ValidatesAttributes.php | 86 +++++++ src/Illuminate/Validation/Validator.php | 4 + tests/Validation/ValidationValidatorTest.php | 233 ++++++++++++++++++ 4 files changed, 379 insertions(+) diff --git a/src/Illuminate/Validation/Concerns/ReplacesAttributes.php b/src/Illuminate/Validation/Concerns/ReplacesAttributes.php index d4a47af146c4..fa6ebd2f679d 100644 --- a/src/Illuminate/Validation/Concerns/ReplacesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ReplacesAttributes.php @@ -248,6 +248,62 @@ protected function replaceRequiredWithoutAll($message, $attribute, $rule, $param return $this->replaceRequiredWith($message, $attribute, $rule, $parameters); } + /** + * Replace all place-holders for the prohibited_with rule. + * + * @param string $message + * @param string $attribute + * @param string $rule + * @param array $parameters + * @return string + */ + protected function replaceProhibitedWith($message, $attribute, $rule, $parameters) + { + return str_replace(':values', implode(' / ', $this->getAttributeList($parameters)), $message); + } + + /** + * Replace all place-holders for the prohibited_with_all rule. + * + * @param string $message + * @param string $attribute + * @param string $rule + * @param array $parameters + * @return string + */ + protected function replaceProhibitedWithAll($message, $attribute, $rule, $parameters) + { + return $this->replaceProhibitedWith($message, $attribute, $rule, $parameters); + } + + /** + * Replace all place-holders for the prohibited_without rule. + * + * @param string $message + * @param string $attribute + * @param string $rule + * @param array $parameters + * @return string + */ + protected function replaceProhibitedWithout($message, $attribute, $rule, $parameters) + { + return $this->replaceProhibitedWith($message, $attribute, $rule, $parameters); + } + + /** + * Replace all place-holders for the prohibited_without_all rule. + * + * @param string $message + * @param string $attribute + * @param string $rule + * @param array $parameters + * @return string + */ + protected function replaceProhibitedWithoutAll($message, $attribute, $rule, $parameters) + { + return $this->replaceProhibitedWith($message, $attribute, $rule, $parameters); + } + /** * Replace all place-holders for the size rule. * diff --git a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php index 454ddb70f1db..af542fd2566e 100644 --- a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php @@ -1489,6 +1489,58 @@ public function validateProhibitedUnless($attribute, $value, $parameters) return true; } + /** + * Validate that an attribute does not exist when any other attribute exists. + * + * @param string $attribute + * @param mixed $value + * @param mixed $parameters + * @return bool + */ + public function validateProhibitedWith($attribute, $value, $parameters) + { + return ! $this->anyPassingRequired($parameters); + } + + /** + * Validate that an attribute does not exist when all other attributes exist. + * + * @param string $attribute + * @param mixed $value + * @param mixed $parameters + * @return bool + */ + public function validateProhibitedWithAll($attribute, $value, $parameters) + { + return ! $this->allPassingRequired($parameters); + } + + /** + * Validate that an attribute does not exist when another attribute does not exist. + * + * @param string $attribute + * @param mixed $value + * @param mixed $parameters + * @return bool + */ + public function validateProhibitedWithout($attribute, $value, $parameters) + { + return ! $this->anyFailingRequired($parameters); + } + + /** + * Validate that an attribute does not exist when all other attributes do not exist. + * + * @param string $attribute + * @param mixed $value + * @param mixed $parameters + * @return bool + */ + public function validateProhibitedWithoutAll($attribute, $value, $parameters) + { + return $this->anyPassingRequired($parameters); + } + /** * Indicate that an attribute should be excluded when another attribute has a given value. * @@ -1729,6 +1781,40 @@ protected function allFailingRequired(array $attributes) return true; } + /** + * Determine if any of the given attributes pass the required test. + * + * @param array $attributes + * @return bool + */ + protected function anyPassingRequired(array $attributes) + { + foreach ($attributes as $key) { + if ($this->validateRequired($key, $this->getValue($key))) { + return true; + } + } + + return false; + } + + /** + * Determine if all of the given attributes pass the required test. + * + * @param array $attributes + * @return bool + */ + protected function allPassingRequired(array $attributes) + { + foreach ($attributes as $key) { + if (! $this->validateRequired($key, $this->getValue($key))) { + return false; + } + } + + return true; + } + /** * Validate that two attributes match. * diff --git a/src/Illuminate/Validation/Validator.php b/src/Illuminate/Validation/Validator.php index 70b8c17a6f3d..8a67c7e88c5d 100755 --- a/src/Illuminate/Validation/Validator.php +++ b/src/Illuminate/Validation/Validator.php @@ -231,6 +231,10 @@ class Validator implements ValidatorContract 'Prohibited', 'ProhibitedIf', 'ProhibitedUnless', + 'ProhibitedWith', + 'ProhibitedWithAll', + 'ProhibitedWithout', + 'ProhibitedWithoutAll', 'Same', 'Unique', ]; diff --git a/tests/Validation/ValidationValidatorTest.php b/tests/Validation/ValidationValidatorTest.php index 7d592324e47c..a007dac88758 100755 --- a/tests/Validation/ValidationValidatorTest.php +++ b/tests/Validation/ValidationValidatorTest.php @@ -1231,6 +1231,239 @@ public function testProhibited() $this->assertTrue($v->fails()); } + public function testValidateProhibitedWith() + { + $trans = $this->getIlluminateArrayTranslator(); + $v = new Validator($trans, ['first' => 'Taylor'], ['last' => 'prohibited_with:first']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['first' => 'Taylor', 'last' => ''], ['last' => 'prohibited_with:first']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['first' => ''], ['last' => 'prohibited_with:first']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, [], ['last' => 'prohibited_with:first']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['first' => 'Taylor', 'last' => 'Otwell'], ['last' => 'prohibited_with:first']); + $this->assertTrue($v->fails()); + + $file = new File('', false); + $v = new Validator($trans, ['file' => $file, 'foo' => ''], ['foo' => 'prohibited_with:file']); + $this->assertTrue($v->passes()); + + $file = new File(__FILE__, false); + $foo = new File(__FILE__, false); + $v = new Validator($trans, ['file' => $file, 'foo' => $foo], ['foo' => 'prohibited_with:file']); + $this->assertTrue($v->fails()); + + $file = new File('', false); + $foo = new File(__FILE__, false); + $v = new Validator($trans, ['file' => $file, 'foo' => $foo], ['foo' => 'prohibited_with:file']); + $this->assertTrue($v->passes()); + + $file = new File(__FILE__, false); + $foo = new File('', false); + $v = new Validator($trans, ['file' => $file, 'foo' => $foo], ['foo' => 'prohibited_with:file']); + $this->assertTrue($v->fails()); + } + + public function testProhibitedWithMultiple() + { + $trans = $this->getIlluminateArrayTranslator(); + + $rules = [ + 'f1' => 'prohibited_with:f2,f3', + 'f2' => 'prohibited_with:f1,f3', + 'f3' => 'prohibited_with:f1,f2', + ]; + + $v = new Validator($trans, [], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f1' => 'foo'], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f2' => 'foo'], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f3' => 'foo'], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f1' => 'foo', 'f2' => 'bar'], $rules); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['f1' => 'foo', 'f3' => 'bar'], $rules); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['f2' => 'foo', 'f3' => 'bar'], $rules); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['f1' => 'foo', 'f2' => 'bar', 'f3' => 'baz'], $rules); + $this->assertTrue($v->fails()); + } + + public function testProhibitedWithAll() + { + $trans = $this->getIlluminateArrayTranslator(); + + $rules = [ + 'f1' => 'prohibited_with_all:f2,f3', + 'f2' => 'prohibited_with_all:f1,f3', + 'f3' => 'prohibited_with_all:f1,f2', + + ]; + + $v = new Validator($trans, [], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f1' => 'foo'], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f2' => 'foo'], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f3' => 'foo'], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f1' => 'foo', 'f2' => 'bar'], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f1' => 'foo', 'f3' => 'bar'], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f2' => 'foo', 'f3' => 'bar'], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f1' => 'foo', 'f2' => 'bar', 'f3' => 'baz'], $rules); + $this->assertTrue($v->fails()); + } + + public function testValidateProhibitedWithout() + { + $trans = $this->getIlluminateArrayTranslator(); + $v = new Validator($trans, ['first' => 'Taylor'], ['last' => 'prohibited_without:first']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['first' => 'Taylor', 'last' => ''], ['last' => 'prohibited_without:first']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['first' => ''], ['last' => 'prohibited_without:first']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, [], ['last' => 'prohibited_without:first']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['first' => 'Taylor', 'last' => 'Otwell'], ['last' => 'prohibited_without:first']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['last' => 'Otwell'], ['last' => 'prohibited_without:first']); + $this->assertTrue($v->fails()); + + $file = new File('', false); + $v = new Validator($trans, ['file' => $file], ['foo' => 'prohibited_without:file']); + $this->assertTrue($v->passes()); + + $foo = new File('', false); + $v = new Validator($trans, ['foo' => $foo], ['foo' => 'prohibited_without:file']); + $this->assertTrue($v->fails()); + + $foo = new File(__FILE__, false); + $v = new Validator($trans, ['foo' => $foo], ['foo' => 'prohibited_without:file']); + $this->assertTrue($v->fails()); + + $file = new File(__FILE__, false); + $foo = new File(__FILE__, false); + $v = new Validator($trans, ['file' => $file, 'foo' => $foo], ['foo' => 'prohibited_without:file']); + $this->assertTrue($v->passes()); + + $file = new File(__FILE__, false); + $foo = new File('', false); + $v = new Validator($trans, ['file' => $file, 'foo' => $foo], ['foo' => 'prohibited_without:file']); + $this->assertTrue($v->passes()); + + $file = new File('', false); + $foo = new File(__FILE__, false); + $v = new Validator($trans, ['file' => $file, 'foo' => $foo], ['foo' => 'prohibited_without:file']); + $this->assertTrue($v->fails()); + + $file = new File('', false); + $foo = new File('', false); + $v = new Validator($trans, ['file' => $file, 'foo' => $foo], ['foo' => 'prohibited_without:file']); + $this->assertTrue($v->fails()); + } + + public function testProhibitedWithoutMultiple() + { + $trans = $this->getIlluminateArrayTranslator(); + + $rules = [ + 'f1' => 'prohibited_without:f2,f3', + 'f2' => 'prohibited_without:f1,f3', + 'f3' => 'prohibited_without:f1,f2', + ]; + + $v = new Validator($trans, [], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f1' => 'foo'], $rules); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['f2' => 'foo'], $rules); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['f3' => 'foo'], $rules); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['f1' => 'foo', 'f2' => 'bar'], $rules); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['f1' => 'foo', 'f3' => 'bar'], $rules); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['f2' => 'foo', 'f3' => 'bar'], $rules); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['f1' => 'foo', 'f2' => 'bar', 'f3' => 'baz'], $rules); + $this->assertTrue($v->passes()); + } + + public function testProhibitedWithoutAll() + { + $trans = $this->getIlluminateArrayTranslator(); + + $rules = [ + 'f1' => 'prohibited_without_all:f2,f3', + 'f2' => 'prohibited_without_all:f1,f3', + 'f3' => 'prohibited_without_all:f1,f2', + ]; + + $v = new Validator($trans, [], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f1' => 'foo'], $rules); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['f2' => 'foo'], $rules); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['f3' => 'foo'], $rules); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['f1' => 'foo', 'f2' => 'bar'], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f1' => 'foo', 'f3' => 'bar'], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f2' => 'foo', 'f3' => 'bar'], $rules); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['f1' => 'foo', 'f2' => 'bar', 'f3' => 'baz'], $rules); + $this->assertTrue($v->passes()); + } + public function testProhibitedIf() { $trans = $this->getIlluminateArrayTranslator();