diff --git a/src/Illuminate/Validation/Rule.php b/src/Illuminate/Validation/Rule.php index 170f4d04a1ea..57e5bc52d4a9 100644 --- a/src/Illuminate/Validation/Rule.php +++ b/src/Illuminate/Validation/Rule.php @@ -260,6 +260,21 @@ public static function anyOf($rules) return new AnyOf($rules); } + /** + * Get a contains rule builder instance. + * + * @param \Illuminate\Contracts\Support\Arrayable|\BackedEnum|\UnitEnum|array|string $values + * @return \Illuminate\Validation\Rules\Contains + */ + public static function contains($values) + { + if ($values instanceof Arrayable) { + $values = $values->toArray(); + } + + return new Rules\Contains(is_array($values) ? $values : func_get_args()); + } + /** * Compile a set of rules for an attribute. * diff --git a/src/Illuminate/Validation/Rules/Contains.php b/src/Illuminate/Validation/Rules/Contains.php new file mode 100644 index 000000000000..c42b9b474250 --- /dev/null +++ b/src/Illuminate/Validation/Rules/Contains.php @@ -0,0 +1,49 @@ +toArray(); + } + + $this->values = is_array($values) ? $values : func_get_args(); + } + + /** + * Convert the rule to a validation string. + * + * @return string + */ + public function __toString() + { + $values = array_map(function ($value) { + $value = enum_value($value); + + return '"'.str_replace('"', '""', $value).'"'; + }, $this->values); + + return 'contains:'.implode(',', $values); + } +} diff --git a/tests/Validation/ValidationRuleContainsTest.php b/tests/Validation/ValidationRuleContainsTest.php new file mode 100644 index 000000000000..9b3009d1bff5 --- /dev/null +++ b/tests/Validation/ValidationRuleContainsTest.php @@ -0,0 +1,89 @@ +assertSame('contains:"Taylor"', (string) $rule); + + $rule = Rule::contains('Taylor', 'Abigail'); + $this->assertSame('contains:"Taylor","Abigail"', (string) $rule); + + $rule = Rule::contains(['Taylor', 'Abigail']); + $this->assertSame('contains:"Taylor","Abigail"', (string) $rule); + + $rule = Rule::contains(collect(['Taylor', 'Abigail'])); + $this->assertSame('contains:"Taylor","Abigail"', (string) $rule); + + $rule = Rule::contains([ArrayKeys::key_1, ArrayKeys::key_2]); + $this->assertSame('contains:"key_1","key_2"', (string) $rule); + + $rule = Rule::contains([ArrayKeysBacked::key_1, ArrayKeysBacked::key_2]); + $this->assertSame('contains:"key_1","key_2"', (string) $rule); + + $rule = Rule::contains(['Taylor', 'Taylor']); + $this->assertSame('contains:"Taylor","Taylor"', (string) $rule); + + $rule = Rule::contains([1, 2, 3]); + $this->assertSame('contains:"1","2","3"', (string) $rule); + + $rule = Rule::contains(['"foo"', '"bar"', '"baz"']); + $this->assertSame('contains:"""foo""","""bar""","""baz"""', (string) $rule); + } + + public function testContainsValidation() + { + $trans = new Translator(new ArrayLoader, 'en'); + + // Test fails when value is string + $v = new Validator($trans, ['roles' => 'admin'], ['roles' => Rule::contains('editor')]); + $this->assertTrue($v->fails()); + + // Test passes when array contains the value + $v = new Validator($trans, ['roles' => ['admin', 'user']], ['roles' => Rule::contains('admin')]); + $this->assertTrue($v->passes()); + + // Test fails when array doesn't contain all the values + $v = new Validator($trans, ['roles' => ['admin', 'user']], ['roles' => Rule::contains(['admin', 'editor'])]); + $this->assertTrue($v->fails()); + + // Test fails when array doesn't contain all the values (using multiple arguments) + $v = new Validator($trans, ['roles' => ['admin', 'user']], ['roles' => Rule::contains('admin', 'editor')]); + $this->assertTrue($v->fails()); + + // Test passes when array contains all the values + $v = new Validator($trans, ['roles' => ['admin', 'user', 'editor']], ['roles' => Rule::contains(['admin', 'editor'])]); + $this->assertTrue($v->passes()); + + // Test passes when array contains all the values (using multiple arguments) + $v = new Validator($trans, ['roles' => ['admin', 'user', 'editor']], ['roles' => Rule::contains('admin', 'editor')]); + $this->assertTrue($v->passes()); + + // Test fails when array doesn't contain the value + $v = new Validator($trans, ['roles' => ['admin', 'user']], ['roles' => Rule::contains('editor')]); + $this->assertTrue($v->fails()); + + // Test fails when array doesn't contain any of the values + $v = new Validator($trans, ['roles' => ['admin', 'user']], ['roles' => Rule::contains(['editor', 'manager'])]); + $this->assertTrue($v->fails()); + + // Test with empty array + $v = new Validator($trans, ['roles' => []], ['roles' => Rule::contains('admin')]); + $this->assertTrue($v->fails()); + + // Test with nullable field + $v = new Validator($trans, ['roles' => null], ['roles' => ['nullable', Rule::contains('admin')]]); + $this->assertTrue($v->passes()); + } +}