diff --git a/src/Illuminate/Translation/lang/en/validation.php b/src/Illuminate/Translation/lang/en/validation.php index 4f8f726210fa..bd3eecd7d014 100644 --- a/src/Illuminate/Translation/lang/en/validation.php +++ b/src/Illuminate/Translation/lang/en/validation.php @@ -121,6 +121,10 @@ 'uncompromised' => 'The given :attribute has appeared in a data leak. Please choose a different :attribute.', ], 'present' => 'The :attribute field must be present.', + 'present_if' => 'The :attribute field must be present when :other is :value.', + 'present_unless' => 'The :attribute field must be present unless :other is :value.', + 'present_with' => 'The :attribute field must be present when :values is present.', + 'present_with_all' => 'The :attribute field must be present when :values are present.', 'prohibited' => 'The :attribute field is prohibited.', 'prohibited_if' => 'The :attribute field is prohibited when :other is :value.', 'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.', diff --git a/src/Illuminate/Validation/Concerns/ReplacesAttributes.php b/src/Illuminate/Validation/Concerns/ReplacesAttributes.php index 660818ed0d08..23efc2303115 100644 --- a/src/Illuminate/Validation/Concerns/ReplacesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ReplacesAttributes.php @@ -357,6 +357,68 @@ protected function replaceMimes($message, $attribute, $rule, $parameters) return str_replace(':values', implode(', ', $parameters), $message); } + /** + * Replace all place-holders for the present_if rule. + * + * @param string $message + * @param string $attribute + * @param string $rule + * @param array $parameters + * @return string + */ + protected function replacePresentIf($message, $attribute, $rule, $parameters) + { + $parameters[1] = $this->getDisplayableValue($parameters[0], Arr::get($this->data, $parameters[0])); + $parameters[0] = $this->getDisplayableAttribute($parameters[0]); + + return str_replace([':other', ':value'], $parameters, $message); + } + + /** + * Replace all place-holders for the present_unless rule. + * + * @param string $message + * @param string $attribute + * @param string $rule + * @param array $parameters + * @return string + */ + protected function replacePresentUnless($message, $attribute, $rule, $parameters) + { + return str_replace([':other', ':value'], [ + $this->getDisplayableAttribute($parameters[0]), + $this->getDisplayableValue($parameters[0], $parameters[1]), + ], $message); + } + + /** + * Replace all place-holders for the present_with rule. + * + * @param string $message + * @param string $attribute + * @param string $rule + * @param array $parameters + * @return string + */ + protected function replacePresentWith($message, $attribute, $rule, $parameters) + { + return str_replace(':values', implode(' / ', $this->getAttributeList($parameters)), $message); + } + + /** + * Replace all place-holders for the present_with_all rule. + * + * @param string $message + * @param string $attribute + * @param string $rule + * @param array $parameters + * @return string + */ + protected function replacePresentWithAll($message, $attribute, $rule, $parameters) + { + return $this->replacePresentWith($message, $attribute, $rule, $parameters); + } + /** * Replace all place-holders for the required_with rule. * diff --git a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php index 091681c34cb6..4b11c28f5e30 100644 --- a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php @@ -1728,6 +1728,86 @@ public function validatePresent($attribute, $value) return Arr::has($this->data, $attribute); } + /** + * Validate that an attribute is present when another attribute has a given value. + * + * @param string $attribute + * @param mixed $value + * @param array $parameters + * @return bool + */ + public function validatePresentIf($attribute, $value, $parameters) + { + $this->requireParameterCount(2, $parameters, 'present_if'); + + [$values, $other] = $this->parseDependentRuleParameters($parameters); + + if (in_array($other, $values, is_bool($other) || is_null($other))) { + return $this->validatePresent($attribute, $value, $parameters); + } + + return true; + } + + /** + * Validate that an attribute is present unless another attribute has a given value. + * + * @param string $attribute + * @param mixed $value + * @param array $parameters + * @return bool + */ + public function validatePresentUnless($attribute, $value, $parameters) + { + $this->requireParameterCount(2, $parameters, 'present_unless'); + + [$values, $other] = $this->parseDependentRuleParameters($parameters); + + if (! in_array($other, $values, is_bool($other) || is_null($other))) { + return $this->validatePresent($attribute, $value, $parameters); + } + + return true; + } + + /** + * Validate that an attribute is present when any given attribute is present. + * + * @param string $attribute + * @param mixed $value + * @param array $parameters + * @return bool + */ + public function validatePresentWith($attribute, $value, $parameters) + { + $this->requireParameterCount(1, $parameters, 'present_with'); + + if (Arr::hasAny($this->data, $parameters)) { + return $this->validatePresent($attribute, $value, $parameters); + } + + return true; + } + + /** + * Validate that an attribute is present when all given attributes are present. + * + * @param string $attribute + * @param mixed $value + * @param array $parameters + * @return bool + */ + public function validatePresentWithAll($attribute, $value, $parameters) + { + $this->requireParameterCount(1, $parameters, 'present_with_all'); + + if (Arr::has($this->data, $parameters)) { + return $this->validatePresent($attribute, $value, $parameters); + } + + return true; + } + /** * Validate that an attribute passes a regular expression check. * diff --git a/src/Illuminate/Validation/Validator.php b/src/Illuminate/Validation/Validator.php index 579e82135282..0629287d6e8a 100755 --- a/src/Illuminate/Validation/Validator.php +++ b/src/Illuminate/Validation/Validator.php @@ -213,6 +213,10 @@ class Validator implements ValidatorContract 'MissingWith', 'MissingWithAll', 'Present', + 'PresentIf', + 'PresentUnless', + 'PresentWith', + 'PresentWithAll', 'Required', 'RequiredIf', 'RequiredIfAccepted', diff --git a/tests/Validation/ValidationValidatorTest.php b/tests/Validation/ValidationValidatorTest.php index 51133741082d..925f463b7da6 100755 --- a/tests/Validation/ValidationValidatorTest.php +++ b/tests/Validation/ValidationValidatorTest.php @@ -1120,6 +1120,134 @@ public function testValidatePresent() $this->assertTrue($v->passes()); } + public function testValidatePresentIf() + { + $trans = $this->getIlluminateArrayTranslator(); + $trans->addLines(['validation.present_if' => 'The :attribute field must be present when :other is :value.'], 'en'); + + $v = new Validator($trans, ['bar' => 1], ['foo' => 'present_if:bar,1']); + $this->assertFalse($v->passes()); + $this->assertSame('The foo field must be present when bar is 1.', $v->errors()->first('foo')); + + $v = new Validator($trans, ['bar' => 1, 'foo' => null], ['foo' => 'present_if:bar,2']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['bar' => 1, 'foo' => ''], ['foo' => 'present_if:bar,1']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['bar' => 1, 'foo' => [['name' => 'a']]], ['foo.*.id' => 'present_if:bar,1']); + $this->assertFalse($v->passes()); + $this->assertSame('The foo.0.id field must be present when bar is 1.', $v->errors()->first('foo.0.id')); + + $v = new Validator($trans, ['bar' => 1, 'foo' => [['id' => '', 'name' => 'a']]], ['foo.*.id' => 'present_if:bar,1']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['bar' => 1, 'foo' => [['id' => null, 'name' => 'a']]], ['foo.*.id' => 'present_if:bar,1']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['bar' => 1, 'foo' => '2'], ['foo' => 'present_if:bar,1']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['bar' => 2], ['foo' => 'present_if:bar,1']); + $this->assertTrue($v->passes()); + } + + public function testValidatePresentUnless() + { + $trans = $this->getIlluminateArrayTranslator(); + $trans->addLines(['validation.present_unless' => 'The :attribute field must be present unless :other is :value.'], 'en'); + + $v = new Validator($trans, ['bar' => 2], ['foo' => 'present_unless:bar,1']); + $this->assertFalse($v->passes()); + $this->assertSame('The foo field must be present unless bar is 1.', $v->errors()->first('foo')); + + $v = new Validator($trans, ['bar' => 2, 'foo' => null], ['foo' => 'present_unless:bar,1']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['bar' => 2, 'foo' => ''], ['foo' => 'present_unless:bar,1']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['bar' => 2, 'foo' => [['name' => 'a']]], ['foo.*.id' => 'present_unless:bar,1']); + $this->assertFalse($v->passes()); + $this->assertSame('The foo.0.id field must be present unless bar is 1.', $v->errors()->first('foo.0.id')); + + $v = new Validator($trans, ['bar' => 2, 'foo' => [['id' => '', 'name' => 'a']]], ['foo.*.id' => 'present_unless:bar,1']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['bar' => 2, 'foo' => [['id' => null, 'name' => 'a']]], ['foo.*.id' => 'present_unless:bar,1']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['bar' => 2, 'foo' => '2'], ['foo' => 'present_unless:bar,1']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['bar' => 1], ['foo' => 'present_unless:bar,1']); + $this->assertTrue($v->passes()); + } + + public function testValidatePresentWith() + { + $trans = $this->getIlluminateArrayTranslator(); + $trans->addLines(['validation.present_with' => 'The :attribute field must be present when :values is present.'], 'en'); + + $v = new Validator($trans, ['foo' => 1, 'bar' => 2], ['foo' => 'present_with:bar']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['foo' => null, 'bar' => 2], ['foo' => 'present_with:bar']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['foo' => '', 'bar' => 2], ['foo' => 'present_with:bar']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['foo' => [['name' => 'a']], 'bar' => 2], ['foo.*.id' => 'present_with:bar']); + $this->assertFalse($v->passes()); + $this->assertSame('The foo.0.id field must be present when bar is present.', $v->errors()->first('foo.0.id')); + + $v = new Validator($trans, ['foo' => [['id' => '']], 'bar' => 2], ['foo.*.id' => 'present_with:bar']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['foo' => [['id' => null]], 'bar' => 2], ['foo.*.id' => 'present_with:bar']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['foo' => 1], ['foo' => 'present_with:bar']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['bar' => 2], ['foo' => 'present_with:bar']); + $this->assertFalse($v->passes()); + $this->assertSame('The foo field must be present when bar is present.', $v->errors()->first('foo')); + } + + public function testValidatePresentWithAll() + { + $trans = $this->getIlluminateArrayTranslator(); + $trans->addLines(['validation.present_with_all' => 'The :attribute field must be present when :values are present.'], 'en'); + + $v = new Validator($trans, ['foo' => 1, 'bar' => 2, 'baz' => 1], ['foo' => 'present_with_all:bar,baz']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['foo' => null, 'bar' => 2, 'baz' => 1], ['foo' => 'present_with_all:bar,baz']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['foo' => '', 'bar' => 2, 'baz' => 1], ['foo' => 'present_with_all:bar,baz']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['foo' => [['name' => 'a']], 'bar' => 2, 'baz' => 1], ['foo.*.id' => 'present_with_all:bar,baz']); + $this->assertFalse($v->passes()); + $this->assertSame('The foo.0.id field must be present when bar / baz are present.', $v->errors()->first('foo.0.id')); + + $v = new Validator($trans, ['foo' => [['id' => '']], 'bar' => 2, 'baz' => 1], ['foo.*.id' => 'present_with_all:bar,baz']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['foo' => [['id' => null]], 'bar' => 2, 'baz' => 1], ['foo.*.id' => 'present_with_all:bar,baz']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['foo' => 1, 'bar' => 2], ['foo' => 'present_with_all:bar,baz']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['bar' => 2, 'baz' => 1], ['foo' => 'present_with_all:bar,baz']); + $this->assertFalse($v->passes()); + $this->assertSame('The foo field must be present when bar / baz are present.', $v->errors()->first('foo')); + } + public function testValidateRequired() { $trans = $this->getIlluminateArrayTranslator();