Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[6.x] Fix nullable values for required_if #37128

Merged
merged 2 commits into from
Apr 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/Illuminate/Validation/Concerns/FormatsMessages.php
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,10 @@ public function getDisplayableValue($attribute, $value)
return $value ? 'true' : 'false';
}

if (is_null($value)) {
return 'empty';
}

driesvints marked this conversation as resolved.
Show resolved Hide resolved
return $value;
}

Expand Down
82 changes: 65 additions & 17 deletions src/Illuminate/Validation/Concerns/ValidatesAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -1420,9 +1420,13 @@ public function validateRequiredIf($attribute, $value, $parameters)
{
$this->requireParameterCount(2, $parameters, 'required_if');

if (! Arr::has($this->data, $parameters[0])) {
return true;
}

[$values, $other] = $this->prepareValuesAndOther($parameters);

if (in_array($other, $values, is_bool($other))) {
if (in_array($other, $values, is_bool($other) || is_null($other))) {
return $this->validateRequired($attribute, $value);
}

Expand All @@ -1441,9 +1445,13 @@ public function validateExcludeIf($attribute, $value, $parameters)
{
$this->requireParameterCount(2, $parameters, 'exclude_if');

if (! Arr::has($this->data, $parameters[0])) {
return true;
}

[$values, $other] = $this->prepareValuesAndOther($parameters);

return ! in_array($other, $values, is_bool($other));
return ! in_array($other, $values, is_bool($other) || is_null($other));
}

/**
Expand All @@ -1458,9 +1466,38 @@ public function validateExcludeUnless($attribute, $value, $parameters)
{
$this->requireParameterCount(2, $parameters, 'exclude_unless');

if (! Arr::has($this->data, $parameters[0])) {
return true;
}

[$values, $other] = $this->prepareValuesAndOther($parameters);

return in_array($other, $values, is_bool($other));
return in_array($other, $values, is_bool($other) || is_null($other));
}

/**
* Validate that an attribute exists when another attribute does not have a given value.
*
* @param string $attribute
* @param mixed $value
* @param mixed $parameters
* @return bool
*/
public function validateRequiredUnless($attribute, $value, $parameters)
{
$this->requireParameterCount(2, $parameters, 'required_unless');

if (! Arr::has($this->data, $parameters[0])) {
return true;
}

[$values, $other] = $this->prepareValuesAndOther($parameters);

if (! in_array($other, $values, is_bool($other) || is_null($other))) {
return $this->validateRequired($attribute, $value);
}

return true;
}

/**
Expand All @@ -1479,6 +1516,10 @@ protected function prepareValuesAndOther($parameters)
$values = $this->convertValuesToBoolean($values);
}

if ($this->shouldConvertToNull($parameters[0]) || is_null($other)) {
$values = $this->convertValuesToNull($values);
}

return [$values, $other];
}

Expand All @@ -1493,6 +1534,17 @@ protected function shouldConvertToBoolean($parameter)
return in_array('boolean', Arr::get($this->rules, $parameter, []));
}

/**
* Check if parameter should be converted to null.
*
* @param string $parameter
* @return bool
*/
protected function shouldConvertToNull($parameter)
{
return in_array('nullable', Arr::get($this->rules, $parameter, []));
}

/**
* Convert the given values to boolean if they are string "true" / "false".
*
Expand All @@ -1513,24 +1565,20 @@ protected function convertValuesToBoolean($values)
}

/**
* Validate that an attribute exists when another attribute does not have a given value.
* Convert the given values to null if they are string "null".
*
* @param string $attribute
* @param mixed $value
* @param mixed $parameters
* @return bool
* @param array $values
* @return array
*/
public function validateRequiredUnless($attribute, $value, $parameters)
protected function convertValuesToNull($values)
{
$this->requireParameterCount(2, $parameters, 'required_unless');

[$values, $other] = $this->prepareValuesAndOther($parameters);

if (! in_array($other, $values, is_bool($other))) {
return $this->validateRequired($attribute, $value);
}
return array_map(function ($value) {
if ($value === 'null') {
return null;
}

return true;
return $value;
}, $values);
}

/**
Expand Down
33 changes: 32 additions & 1 deletion tests/Validation/ValidationValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1094,13 +1094,44 @@ public function testRequiredIf()
$trans = $this->getIlluminateArrayTranslator();
$trans->addLines(['validation.required_if' => 'The :attribute field is required when :other is :value.'], 'en');
$v = new Validator($trans, ['foo' => 0], [
'foo' => 'required|boolean',
'foo' => 'nullable|required|boolean',
'bar' => 'required_if:foo,true',
'baz' => 'required_if:foo,false',
]);
$this->assertTrue($v->fails());
$this->assertCount(1, $v->messages());
$this->assertSame('The baz field is required when foo is 0.', $v->messages()->first('baz'));

$trans = $this->getIlluminateArrayTranslator();
$v = new Validator($trans, [], [
'foo' => 'nullable|boolean',
'baz' => 'nullable|required_if:foo,false',
]);
$this->assertTrue($v->passes());

$trans = $this->getIlluminateArrayTranslator();
$v = new Validator($trans, ['foo' => null], [
'foo' => 'nullable|boolean',
'baz' => 'nullable|required_if:foo,false',
]);
$this->assertTrue($v->passes());

$trans = $this->getIlluminateArrayTranslator();
$v = new Validator($trans, [], [
'foo' => 'nullable|boolean',
'baz' => 'nullable|required_if:foo,null',
]);
$this->assertTrue($v->passes());

$trans = $this->getIlluminateArrayTranslator();
$trans->addLines(['validation.required_if' => 'The :attribute field is required when :other is :value.'], 'en');
$v = new Validator($trans, ['foo' => null], [
'foo' => 'nullable|boolean',
'baz' => 'nullable|required_if:foo,null',
]);
$this->assertTrue($v->fails());
$this->assertCount(1, $v->messages());
$this->assertSame('The baz field is required when foo is empty.', $v->messages()->first('baz'));
}

public function testRequiredUnless()
Expand Down