Skip to content
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
1 change: 1 addition & 0 deletions src/Illuminate/Translation/lang/en/validation.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
'image' => 'The :attribute field must be an image.',
'in' => 'The selected :attribute is invalid.',
'in_array' => 'The :attribute field must exist in :other.',
'in_array_keys' => 'The :attribute field must contain at least one of the following keys: :values.',
'integer' => 'The :attribute field must be an integer.',
'ip' => 'The :attribute field must be a valid IP address.',
'ipv4' => 'The :attribute field must be a valid IPv4 address.',
Expand Down
18 changes: 18 additions & 0 deletions src/Illuminate/Validation/Concerns/ReplacesAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,24 @@ protected function replaceInArray($message, $attribute, $rule, $parameters)
return str_replace(':other', $this->getDisplayableAttribute($parameters[0]), $message);
}

/**
* Replace all place-holders for the in_array_keys rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array<int,string> $parameters
* @return string
*/
protected function replaceInArrayKeys($message, $attribute, $rule, $parameters)
{
foreach ($parameters as &$parameter) {
$parameter = $this->getDisplayableValue($attribute, $parameter);
}

return str_replace(':values', implode(', ', $parameters), $message);
}

/**
* Replace all place-holders for the required_array_keys rule.
*
Expand Down
27 changes: 27 additions & 0 deletions src/Illuminate/Validation/Concerns/ValidatesAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -1450,6 +1450,33 @@ public function validateInArray($attribute, $value, $parameters)
return in_array($value, $otherValues);
}

/**
* Validate that an array has at least one of the given keys.
*
* @param string $attribute
* @param mixed $value
* @param array<int, int|string> $parameters
* @return bool
*/
public function validateInArrayKeys($attribute, $value, $parameters)
{
if (! is_array($value)) {
return false;
}

if (empty($parameters)) {
return false;
}

foreach ($parameters as $param) {
if (Arr::exists($value, $param)) {
return true;
}
}

return false;
}

/**
* Validate that an attribute is an integer.
*
Expand Down
80 changes: 80 additions & 0 deletions tests/Validation/ValidationInArrayKeysTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

namespace Illuminate\Tests\Validation;

use Illuminate\Translation\ArrayLoader;
use Illuminate\Translation\Translator;
use Illuminate\Validation\Validator;
use PHPUnit\Framework\TestCase;

class ValidationInArrayKeysTest extends TestCase
{
public function testInArrayKeysValidation()
{
$trans = $this->getIlluminateArrayTranslator();

// Test passes when array has at least one of the specified keys
$v = new Validator($trans, ['foo' => ['first_key' => 'bar', 'second_key' => 'baz']], ['foo' => 'in_array_keys:first_key,third_key']);
$this->assertTrue($v->passes());

// Test passes when array has multiple of the specified keys
$v = new Validator($trans, ['foo' => ['first_key' => 'bar', 'second_key' => 'baz']], ['foo' => 'in_array_keys:first_key,second_key']);
$this->assertTrue($v->passes());

// Test fails when array doesn't have any of the specified keys
$v = new Validator($trans, ['foo' => ['first_key' => 'bar', 'second_key' => 'baz']], ['foo' => 'in_array_keys:third_key,fourth_key']);
$this->assertTrue($v->fails());

// Test fails when value is not an array
$v = new Validator($trans, ['foo' => 'not-an-array'], ['foo' => 'in_array_keys:first_key']);
$this->assertTrue($v->fails());

// Test fails when no keys are specified
$v = new Validator($trans, ['foo' => ['first_key' => 'bar']], ['foo' => 'in_array_keys:']);
$this->assertTrue($v->fails());
}

public function testInArrayKeysValidationWithNestedArrays()
{
$trans = $this->getIlluminateArrayTranslator();

// Test passes with nested arrays
$v = new Validator($trans, [
'foo' => [
'first_key' => ['nested' => 'value'],
'second_key' => 'baz',
],
], ['foo' => 'in_array_keys:first_key,third_key']);
$this->assertTrue($v->passes());

// Test with dot notation for nested arrays
$v = new Validator($trans, [
'foo' => [
'first' => [
'nested_key' => 'value',
],
],
], ['foo.first' => 'in_array_keys:nested_key']);
$this->assertTrue($v->passes());
}

public function testInArrayKeysValidationErrorMessage()
{
$trans = $this->getIlluminateArrayTranslator();
$trans->addLines([
'validation.in_array_keys' => 'The :attribute field must contain at least one of the following keys: :values.',
], 'en');

$v = new Validator($trans, ['foo' => ['wrong_key' => 'bar']], ['foo' => 'in_array_keys:first_key,second_key']);
$this->assertFalse($v->passes());
$this->assertEquals(
'The foo field must contain at least one of the following keys: first_key, second_key.',
$v->messages()->first('foo')
);
}

protected function getIlluminateArrayTranslator()
{
return new Translator(new ArrayLoader, 'en');
}
}