Skip to content

Commit 4ad72ad

Browse files
committed
Fix joinData being lost when belongsToMany is marshalled by id.
When patching belongsToMany records by id, the existing joinData record should be retained and not replaced. Refs #8159
1 parent 4d8a51f commit 4ad72ad

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

src/ORM/Marshaller.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -704,19 +704,27 @@ protected function _mergeJoinData($original, $assoc, $value, $options)
704704
}
705705

706706
$options['accessibleFields'] = ['_joinData' => true];
707+
707708
$records = $this->mergeMany($original, $value, $options);
708709
foreach ($records as $record) {
709710
$hash = spl_object_hash($record);
710711
$value = $record->get('_joinData');
711712

713+
// Already an entity, no further marshalling required.
714+
if ($value instanceof EntityInterface) {
715+
continue;
716+
}
717+
718+
// Scalar data can't be handled
712719
if (!is_array($value)) {
713720
$record->unsetProperty('_joinData');
714721
continue;
715722
}
716723

724+
// Marshal data into the old object, or make a new joinData object.
717725
if (isset($extra[$hash])) {
718726
$record->set('_joinData', $marshaller->merge($extra[$hash], $value, $nested));
719-
} else {
727+
} elseif (is_array($value)) {
720728
$joinData = $marshaller->one($value, $nested);
721729
$record->set('_joinData', $joinData);
722730
}

tests/TestCase/ORM/MarshallerTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2003,6 +2003,36 @@ public function testMergeJoinDataAssociations()
20032003
$this->assertEquals('ber', $entity->tags[1]->_joinData->user->username);
20042004
}
20052005

2006+
/**
2007+
* Tests that merging belongsToMany association doesn't erase _joinData
2008+
* on existing objects.
2009+
*
2010+
* @return void
2011+
*/
2012+
public function testMergeBelongsToManyIdsRetainJoinData()
2013+
{
2014+
$this->articles->belongsToMany('Tags');
2015+
$entity = $this->articles->get(1, ['contain' => ['Tags']]);
2016+
$entity->accessible('*', true);
2017+
$original = $entity->tags[0]->_joinData;
2018+
2019+
$this->assertInstanceOf('Cake\ORM\Entity', $entity->tags[0]->_joinData);
2020+
2021+
$data = [
2022+
'title' => 'Haz moar tags',
2023+
'tags' => [
2024+
['id' => 1],
2025+
]
2026+
];
2027+
$marshall = new Marshaller($this->articles);
2028+
$result = $marshall->merge($entity, $data, ['associated' => ['Tags']]);
2029+
2030+
$this->assertCount(1, $result->tags);
2031+
$this->assertInstanceOf('Cake\ORM\Entity', $result->tags[0]);
2032+
$this->assertInstanceOf('Cake\ORM\Entity', $result->tags[0]->_joinData);
2033+
$this->assertSame($original, $result->tags[0]->_joinData, 'Should be same object');
2034+
}
2035+
20062036
/**
20072037
* Test mergeMany() with a simple set of data.
20082038
*

0 commit comments

Comments
 (0)