fix saveAll deep option, when associated data is empty, or has deeper associated model data as first key in array

This commit is contained in:
Ceeram 2012-03-21 10:38:04 +01:00
parent 01e035f726
commit 4dfbfe9c8b
2 changed files with 74 additions and 8 deletions

View file

@ -2042,6 +2042,7 @@ class Model extends Object implements CakeEventListener {
if ((!$validates && $options['atomic']) || (!$options['atomic'] && in_array(false, $validates, true))) { if ((!$validates && $options['atomic']) || (!$options['atomic'] && in_array(false, $validates, true))) {
return $validates; return $validates;
} }
$options['validate'] = true;
} }
if ($options['atomic']) { if ($options['atomic']) {
@ -2172,6 +2173,7 @@ class Model extends Object implements CakeEventListener {
if ((!$validates && $options['atomic']) || (!$options['atomic'] && in_array(false, $validates, true))) { if ((!$validates && $options['atomic']) || (!$options['atomic'] && in_array(false, $validates, true))) {
return $validates; return $validates;
} }
$options['validate'] = true;
} }
if ($options['atomic']) { if ($options['atomic']) {
$db = $this->getDataSource(); $db = $this->getDataSource();
@ -2193,10 +2195,11 @@ class Model extends Object implements CakeEventListener {
$validates = ($saved === true || (is_array($saved) && !in_array(false, $saved, true))); $validates = ($saved === true || (is_array($saved) && !in_array(false, $saved, true)));
} }
if ($validates) { if ($validates) {
if (!empty($data[$this->alias])) { $key = $this->belongsTo[$association]['foreignKey'];
$data[$this->alias][$this->belongsTo[$association]['foreignKey']] = $this->{$association}->id; if (isset($data[$this->alias])) {
$data[$this->alias][$key] = $this->{$association}->id;
} else { } else {
$data[$this->belongsTo[$association]['foreignKey']] = $this->{$association}->id; $data = array_merge(array($key => $this->{$association}->id), $data, array($key => $this->{$association}->id));
} }
} else { } else {
$validationErrors[$association] = $this->{$association}->validationErrors; $validationErrors[$association] = $this->{$association}->validationErrors;
@ -2216,9 +2219,14 @@ class Model extends Object implements CakeEventListener {
} }
if (isset($associations[$association])) { if (isset($associations[$association])) {
$type = $associations[$association]; $type = $associations[$association];
$key = $this->{$type}[$association]['foreignKey'];
switch ($type) { switch ($type) {
case 'hasOne': case 'hasOne':
$values[$this->{$type}[$association]['foreignKey']] = $this->id; if (isset($values[$association])) {
$values[$association][$key] = $this->id;
} else {
$values = array_merge(array($key => $this->id), $values, array($key => $this->id));
}
$validates = $this->{$association}->create(null) !== null; $validates = $this->{$association}->create(null) !== null;
$saved = false; $saved = false;
if ($validates) { if ($validates) {
@ -2236,7 +2244,11 @@ class Model extends Object implements CakeEventListener {
break; break;
case 'hasMany': case 'hasMany':
foreach ($values as $i => $value) { foreach ($values as $i => $value) {
$values[$i][$this->{$type}[$association]['foreignKey']] = $this->id; if (isset($values[$i][$association])) {
$values[$i][$association][$key] = $this->id;
} else {
$values[$i] = array_merge(array($key => $this->id), $value, array($key => $this->id));
}
} }
$_return = $this->{$association}->saveMany($values, array_merge($options, array('atomic' => false))); $_return = $this->{$association}->saveMany($values, array_merge($options, array('atomic' => false)));
if (in_array(false, $_return, true)) { if (in_array(false, $_return, true)) {

View file

@ -6567,7 +6567,7 @@ class ModelWriteTest extends BaseModelTest {
$this->db->truncate(new Comment()); $this->db->truncate(new Comment());
$result = $TestModel->saveAll(array( $result = $TestModel->saveAll(array(
'Article' => array('id' => 2, 'title' => 'I will not save'), 'Article' => array('id' => 2, 'title' => 'The title'),
'Comment' => array( 'Comment' => array(
array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1), array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
array( array(
@ -6613,7 +6613,7 @@ class ModelWriteTest extends BaseModelTest {
public function testSaveAllDeepHasManyHasMany() { public function testSaveAllDeepHasManyHasMany() {
$this->loadFixtures('Article', 'Comment', 'User', 'Attachment'); $this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
$TestModel = new Article(); $TestModel = new Article();
$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array(); $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = $TestModel->Comment->belongsTo = array();
$TestModel->Comment->unbindModel(array('hasOne' => array('Attachment')), false); $TestModel->Comment->unbindModel(array('hasOne' => array('Attachment')), false);
$TestModel->Comment->bindModel(array('hasMany' => array('Attachment')), false); $TestModel->Comment->bindModel(array('hasMany' => array('Attachment')), false);
@ -6622,7 +6622,7 @@ class ModelWriteTest extends BaseModelTest {
$this->db->truncate(new Attachment()); $this->db->truncate(new Attachment());
$result = $TestModel->saveAll(array( $result = $TestModel->saveAll(array(
'Article' => array('id' => 2, 'title' => 'I will not save'), 'Article' => array('id' => 2, 'title' => 'The title'),
'Comment' => array( 'Comment' => array(
array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1), array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
array( array(
@ -6661,6 +6661,60 @@ class ModelWriteTest extends BaseModelTest {
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);
} }
/**
* testSaveAllDeepEmptyHasManyHasMany method
*
* return @void
*/
public function testSaveAllDeepEmptyHasManyHasMany() {
$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
$TestModel = new Article();
$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = $TestModel->Comment->belongsTo = array();
$TestModel->Comment->unbindModel(array('hasOne' => array('Attachment')), false);
$TestModel->Comment->bindModel(array('hasMany' => array('Attachment')), false);
$this->db->truncate($TestModel);
$this->db->truncate(new Comment());
$this->db->truncate(new Attachment());
$result = $TestModel->saveAll(array(
'Article' => array('id' => 2, 'title' => 'Comment has its data after Attachment'),
'Comment' => array(
array(
'Attachment' => array(
array('attachment' => 'attachment should be created with comment_id'),
array('attachment' => 'comment should be created with article_id'),
),
'comment' => 'after associated data'
)
)
), array('deep' => true));
$result = $TestModel->Comment->find('first', array(
'conditions' => array('Comment.article_id' => 2),
));
$this->assertEquals(2, $result['Comment']['article_id']);
$this->assertEquals(2, count($result['Attachment']));
$result = $TestModel->saveAll(array(
'Article' => array('id' => 3, 'title' => 'Comment has no data'),
'Comment' => array(
array(
'Attachment' => array(
array('attachment' => 'attachment should be created with comment_id'),
array('attachment' => 'comment should be created with article_id'),
),
)
)
), array('deep' => true));
$result = $TestModel->Comment->find('first', array(
'conditions' => array('Comment.article_id' => 3),
));
$this->assertEquals(3, $result['Comment']['article_id']);
$this->assertEquals(2, count($result['Attachment']));
}
/** /**
* testUpdateAllBoolean * testUpdateAllBoolean
* *