Fix multi-model validators with deep & atomic.

Apply patch from 'Christian Buffin' to fix validateMany() and
validateAssociated() when atomic=false & deep=true are used in
conjunction. Using Hash to flatten the nested set of validation results
yields the correct results.

Fixes #3352
This commit is contained in:
mark_story 2012-11-28 21:26:40 -05:00
parent 966c69cb98
commit f250592fee
2 changed files with 122 additions and 2 deletions

View file

@ -156,7 +156,7 @@ class ModelValidator implements ArrayAccess, IteratorAggregate, Countable {
$data[$association] = $model->{$association}->data[$model->{$association}->alias];
}
if (is_array($validates)) {
if (in_array(false, $validates, true)) {
if (in_array(false, Hash::flatten($validates), true)) {
$validates = false;
} else {
$validates = true;
@ -220,7 +220,7 @@ class ModelValidator implements ArrayAccess, IteratorAggregate, Countable {
$validates = $model->set($record) && $model->validates($options);
$data[$key] = $model->data;
}
if ($validates === false || (is_array($validates) && in_array(false, $validates, true))) {
if ($validates === false || (is_array($validates) && in_array(false, Hash::flatten($validates), true))) {
$validationErrors[$key] = $model->validationErrors;
$validates = false;
} else {

View file

@ -2227,4 +2227,124 @@ class ModelValidationTest extends BaseModelTest {
$this->assertFalse($model->validates());
}
/**
* Test validateAssociated with atomic=false & deep=true
*
* @return void
*/
public function testValidateAssociatedAtomicFalseDeepTrueWithErrors() {
$this->loadFixtures('Comment', 'Article', 'User', 'Attachment');
$Attachment = ClassRegistry::init('Attachment');
$Attachment->Comment->validator()->add('comment', array(
array('rule' => 'notEmpty')
));
$Attachment->Comment->User->bindModel(array(
'hasMany' => array(
'Article',
'Comment'
)),
false
);
$data = array(
'Attachment' => array(
'attachment' => 'text',
'Comment' => array(
'comment' => '',
'published' => 'N',
'User' => array(
'user' => 'Foo',
'password' => 'mypassword',
'Comment' => array(
array(
'comment' => ''
)
)
)
)
)
);
$result = $Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true));
$result = $Attachment->validationErrors;
$expected = array(
'Comment' => array(
'comment' => array(
0 => 'This field cannot be left blank',
),
'User' => array(
'Comment' => array(
0 => array(
'comment' => array(
0 => 'This field cannot be left blank',
),
),
),
),
),
);
$this->assertEquals($result, $expected);
}
/**
* Test validateMany with atomic=false & deep=true
*
* @return void
*/
public function testValidateManyAtomicFalseDeepTrueWithErrors() {
$this->loadFixtures('Comment', 'Article', 'User');
$Article = ClassRegistry::init('Article');
$Article->Comment->validator()->add('comment', array(
array('rule' => 'notEmpty')
));
$data = array(
array(
'Article' => array(
'user_id' => 1,
'title' => 'Foo',
'body' => 'text',
'published' => 'N'
),
'Comment' => array(
array(
'user_id' => 1,
'comment' => 'Baz',
'published' => 'N',
)
),
),
array(
'Article' => array(
'user_id' => 1,
'title' => 'Bar',
'body' => 'text',
'published' => 'N'
),
'Comment' => array(
array(
'user_id' => 1,
'comment' => '',
'published' => 'N',
)
),
),
);
$Article->validateMany($data, array('atomic' => false, 'deep' => true));
$result = $Article->validationErrors;
$expected = array(
1 => array(
'Comment' => array(
0 => array(
'comment' => array(
0 => 'This field cannot be left blank',
),
),
),
),
);
$this->assertEquals($result, $expected);
}
}