diff --git a/src/Validation/Validator.php b/src/Validation/Validator.php index 96fb6ee0259..6f61e2e3922 100644 --- a/src/Validation/Validator.php +++ b/src/Validation/Validator.php @@ -1319,6 +1319,56 @@ public function multipleOptions($field, array $options = [], $message = null, $w ]); } + /** + * Add a validation rule to ensure that a field is an array containing at least + * the specified amount of elements + * + * @param string $field The field you want to apply the rule to. + * @param int $count The number of elements the array should at least have + * @param string|null $message The error message when the rule fails. + * @param string|callable|null $when Either 'create' or 'update' or a callable that returns + * true when the validation rule should be applied. + * @see \Cake\Validation\Validation::numElements() + * @return $this + */ + public function hasAtLeast($field, $count, $message = null, $when = null) + { + $extra = array_filter(['on' => $when, 'message' => $message]); + return $this->add($field, 'hasAtLeast', $extra + [ + 'rule' => function ($value) use ($count) { + if (is_array($value) && isset($value['_ids'])) { + $value = $value['_ids']; + } + return Validation::numElements($value, '>=', $count); + } + ]); + } + + /** + * Add a validation rule to ensure that a field is an array containing at most + * the specified amount of elements + * + * @param string $field The field you want to apply the rule to. + * @param int $count The number maximim amount of elements the field should have + * @param string|null $message The error message when the rule fails. + * @param string|callable|null $when Either 'create' or 'update' or a callable that returns + * true when the validation rule should be applied. + * @see \Cake\Validation\Validation::numElements() + * @return $this + */ + public function hasAtMost($field, $count, $message = null, $when = null) + { + $extra = array_filter(['on' => $when, 'message' => $message]); + return $this->add($field, 'hasAtMost', $extra + [ + 'rule' => function ($value) use ($count) { + if (is_array($value) && isset($value['_ids'])) { + $value = $value['_ids']; + } + return Validation::numElements($value, '<=', $count); + } + ]); + } + /** * Returns whether or not a field can be left empty for a new or already existing * record. diff --git a/tests/TestCase/Validation/ValidatorTest.php b/tests/TestCase/Validation/ValidatorTest.php index 2b9901d1c41..1bf5f100f5a 100644 --- a/tests/TestCase/Validation/ValidatorTest.php +++ b/tests/TestCase/Validation/ValidatorTest.php @@ -1545,6 +1545,46 @@ public function testMultiple() $this->assertNotEmpty($validator->errors(['username' => ''])); } + /** + * Tests the hasAtLeast method + * + * @return void + */ + public function testHasAtLeast() + { + $validator = new Validator(); + $validator->hasAtLeast('things', 3); + $this->assertEmpty($validator->errors(['things' => [1, 2, 3]])); + $this->assertEmpty($validator->errors(['things' => [1, 2, 3, 4]])); + $this->assertNotEmpty($validator->errors(['things' => [1, 2]])); + $this->assertNotEmpty($validator->errors(['things' => []])); + $this->assertNotEmpty($validator->errors(['things' => 'string'])); + + $this->assertEmpty($validator->errors(['things' => ['_ids' => [1, 2, 3]]])); + $this->assertEmpty($validator->errors(['things' => ['_ids' => [1, 2, 3, 4]]])); + $this->assertNotEmpty($validator->errors(['things' => ['_ids' => [1, 2]]])); + $this->assertNotEmpty($validator->errors(['things' => ['_ids' => []]])); + $this->assertNotEmpty($validator->errors(['things' => ['_ids' => 'string']])); + } + + /** + * Tests the hasAtMost method + * + * @return void + */ + public function testHasAtMost() + { + $validator = new Validator(); + $validator->hasAtMost('things', 3); + $this->assertEmpty($validator->errors(['things' => [1, 2, 3]])); + $this->assertEmpty($validator->errors(['things' => [1]])); + $this->assertNotEmpty($validator->errors(['things' => [1, 2, 3, 4]])); + + $this->assertEmpty($validator->errors(['things' => ['_ids' => [1, 2, 3]]])); + $this->assertEmpty($validator->errors(['things' => ['_ids' => [1, 2]]])); + $this->assertNotEmpty($validator->errors(['things' => ['_ids' => [1, 2, 3, 4]]])); + } + protected function assertProxyMethod($validator, $method, $extra = null, $pass = [], $name = null) { $name = $name ?: $method;