Skip to content

Commit

Permalink
Merge data into existing belongsToMany associations.
Browse files Browse the repository at this point in the history
When creating a new entity that is linked to existing belongsToMany
records, we should merge request data into the existing entities.
Failing to do so makes it hard to create a new record, link it to an
existing record and update the existing record and its associations at
the same time.

Refs #8082
  • Loading branch information
markstory committed Jan 24, 2016
1 parent 69ad2b6 commit d7e0bde
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 5 deletions.
7 changes: 4 additions & 3 deletions src/ORM/Marshaller.php
Expand Up @@ -318,9 +318,7 @@ protected function _belongsToMany(Association $assoc, array $data, $options = []
$query->andWhere(function ($exp) use ($conditions) {
return $exp->or_($conditions);
});
}

if (isset($query)) {
$keyFields = array_keys($primaryKey);

$existing = [];
Expand All @@ -337,8 +335,10 @@ protected function _belongsToMany(Association $assoc, array $data, $options = []
}
}
$key = implode(';', $key);

// Update existing record and child associations
if (isset($existing[$key])) {
$records[$i] = $existing[$key];
$records[$i] = $this->merge($existing[$key], $data[$i], $options);
}
}
}
Expand All @@ -351,6 +351,7 @@ protected function _belongsToMany(Association $assoc, array $data, $options = []
}

foreach ($records as $i => $record) {
// Update junction table data in _joinData.
if (isset($data[$i]['_joinData'])) {
$joinData = $jointMarshaller->one($data[$i]['_joinData'], $nested);
$record->set('_joinData', $joinData);
Expand Down
46 changes: 44 additions & 2 deletions tests/TestCase/ORM/MarshallerTest.php
Expand Up @@ -115,7 +115,9 @@ public function setUp()
{
parent::setUp();
$articles = TableRegistry::get('Articles');
$articles->belongsTo('Users');
$articles->belongsTo('Users', [
'foreignKey' => 'author_id'
]);
$articles->hasMany('Comments');
$articles->belongsToMany('Tags');

Expand Down Expand Up @@ -652,7 +654,7 @@ public function testOneBelongsToManyJoinDataAssociatedWithIds()
*
* @return void
*/
public function testBelongsToManyWithMixedJoinData()
public function testOneBelongsToManyWithMixedJoinData()
{
$data = [
'title' => 'My title',
Expand Down Expand Up @@ -683,6 +685,46 @@ public function testBelongsToManyWithMixedJoinData()
$this->assertEquals(1, $result->tags[1]->_joinData->active);
}

public function testOneBelongsToManyWithNestedAssociations()
{
$this->tags->belongsToMany('Articles');
$data = [
'name' => 'new tag',
'articles' => [
// This nested article exists, and we want to update it.
[
'id' => 1,
'title' => 'New tagged article',
'body' => 'New tagged article',
'user' => [
'id' => 1,
'username' => 'newuser'
],
'comments' => [
['comment' => 'New comment', 'user_id' => 1],
['comment' => 'Second comment', 'user_id' => 1],
]
]
]
];
$marshaller = new Marshaller($this->tags);
$tag = $marshaller->one($data, ['associated' => ['Articles.Users', 'Articles.Comments']]);

$this->assertNotEmpty($tag->articles);
$this->assertCount(1, $tag->articles);
$this->assertInstanceOf('Cake\ORM\Entity', $tag->articles[0]);
$this->assertSame('New tagged article', $tag->articles[0]->title);

$this->assertNotEmpty($tag->articles[0]->user);
$this->assertInstanceOf('Cake\ORM\Entity', $tag->articles[0]->user);
$this->assertSame('newuser', $tag->articles[0]->user->username);

$this->assertNotEmpty($tag->articles[0]->comments);
$this->assertCount(2, $tag->articles[0]->comments);
$this->assertInstanceOf('Cake\ORM\Entity', $tag->articles[0]->comments[0]);
$this->assertInstanceOf('Cake\ORM\Entity', $tag->articles[0]->comments[1]);
}

/**
* Test belongsToMany association with mixed data and _joinData
*
Expand Down

0 comments on commit d7e0bde

Please sign in to comment.