Fix Model::isUnique() not working as a validator.

While it *did* work for single fields, isUnique could not be used to
validate the uniqueness across multiple fields as documented. Because
validation methods pass arguments in an order the validator did not
expect the validation method would not work correctly.

Fixes #4571
This commit is contained in:
mark_story 2014-10-09 22:49:17 -04:00
parent 0ff9545e5a
commit 39011cd9d8
2 changed files with 53 additions and 1 deletions

View file

@ -3293,11 +3293,19 @@ class Model extends Object implements CakeEventListener {
/**
* Returns false if any fields passed match any (by default, all if $or = false) of their matching values.
*
* Can be used as a validation method. When used as a validation method, the `$or` parameter
* contains an array of fields to be validated.
*
* @param array $fields Field/value pairs to search (if no values specified, they are pulled from $this->data)
* @param bool $or If false, all fields specified must match in order for a false return value
* @param bool|array $or If false, all fields specified must match in order for a false return value
* @return bool False if any records matching any fields are found
*/
public function isUnique($fields, $or = true) {
if (is_array($or)) {
$args = func_get_args();
$fields = $args[1];
$or = isset($args[2]) ? $args[2] : true;
}
if (!is_array($fields)) {
$fields = func_get_args();
if (is_bool($fields[count($fields) - 1])) {

View file

@ -2405,6 +2405,50 @@ class ModelValidationTest extends BaseModelTest {
$this->assertEquals($expected, $result);
}
/**
* Test the isUnique method when used as a validator for multiple fields.
*
* @return void
*/
public function testIsUniqueValidator() {
$this->loadFixtures('Article');
$Article = ClassRegistry::init('Article');
$Article->validate = array(
'user_id' => array(
'duplicate' => array(
'rule' => array('isUnique', array('user_id', 'title'), false)
)
)
);
$data = array(
'user_id' => 1,
'title' => 'First Article',
);
$Article->create($data);
$this->assertFalse($Article->validates(), 'Contains a dupe');
$data = array(
'user_id' => 1,
'title' => 'Unique Article',
);
$Article->create($data);
$this->assertTrue($Article->validates(), 'Should pass');
$Article->validate = array(
'user_id' => array(
'duplicate' => array(
'rule' => array('isUnique', array('user_id', 'title'))
)
)
);
$data = array(
'user_id' => 1,
'title' => 'Unique Article',
);
$Article->create($data);
$this->assertFalse($Article->validates(), 'Should fail, conditions are combined with or');
}
}
/**