Skip to content

Commit

Permalink
fix saveAll deep option, when associated data is empty, or has deeper…
Browse files Browse the repository at this point in the history
… associated model data as first key in array
  • Loading branch information
ceeram committed Mar 21, 2012
1 parent 01e035f commit 4dfbfe9
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 8 deletions.
22 changes: 17 additions & 5 deletions lib/Cake/Model/Model.php
Expand Up @@ -2042,6 +2042,7 @@ public function saveMany($data = null, $options = array()) {
if ((!$validates && $options['atomic']) || (!$options['atomic'] && in_array(false, $validates, true))) {
return $validates;
}
$options['validate'] = true;
}

if ($options['atomic']) {
Expand Down Expand Up @@ -2172,6 +2173,7 @@ public function saveAssociated($data = null, $options = array()) {
if ((!$validates && $options['atomic']) || (!$options['atomic'] && in_array(false, $validates, true))) {
return $validates;
}
$options['validate'] = true;
}
if ($options['atomic']) {
$db = $this->getDataSource();
Expand All @@ -2193,10 +2195,11 @@ public function saveAssociated($data = null, $options = array()) {
$validates = ($saved === true || (is_array($saved) && !in_array(false, $saved, true)));
}
if ($validates) {
if (!empty($data[$this->alias])) {
$data[$this->alias][$this->belongsTo[$association]['foreignKey']] = $this->{$association}->id;
$key = $this->belongsTo[$association]['foreignKey'];
if (isset($data[$this->alias])) {
$data[$this->alias][$key] = $this->{$association}->id;
} else {
$data[$this->belongsTo[$association]['foreignKey']] = $this->{$association}->id;
$data = array_merge(array($key => $this->{$association}->id), $data, array($key => $this->{$association}->id));
}
} else {
$validationErrors[$association] = $this->{$association}->validationErrors;
Expand All @@ -2216,9 +2219,14 @@ public function saveAssociated($data = null, $options = array()) {
}
if (isset($associations[$association])) {
$type = $associations[$association];
$key = $this->{$type}[$association]['foreignKey'];
switch ($type) {
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;
$saved = false;
if ($validates) {
Expand All @@ -2236,7 +2244,11 @@ public function saveAssociated($data = null, $options = array()) {
break;
case 'hasMany':
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)));
if (in_array(false, $_return, true)) {
Expand Down
60 changes: 57 additions & 3 deletions lib/Cake/Test/Case/Model/ModelWriteTest.php
Expand Up @@ -6567,7 +6567,7 @@ public function testSaveAllDeepHasManyBelongsTo() {
$this->db->truncate(new Comment());

$result = $TestModel->saveAll(array(
'Article' => array('id' => 2, 'title' => 'I will not save'),
'Article' => array('id' => 2, 'title' => 'The title'),
'Comment' => array(
array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
array(
Expand Down Expand Up @@ -6613,7 +6613,7 @@ public function testSaveAllDeepHasManyBelongsTo() {
public function testSaveAllDeepHasManyHasMany() {
$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
$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->bindModel(array('hasMany' => array('Attachment')), false);

Expand All @@ -6622,7 +6622,7 @@ public function testSaveAllDeepHasManyHasMany() {
$this->db->truncate(new Attachment());

$result = $TestModel->saveAll(array(
'Article' => array('id' => 2, 'title' => 'I will not save'),
'Article' => array('id' => 2, 'title' => 'The title'),
'Comment' => array(
array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
array(
Expand Down Expand Up @@ -6661,6 +6661,60 @@ public function testSaveAllDeepHasManyHasMany() {
$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
*
Expand Down

0 comments on commit 4dfbfe9

Please sign in to comment.