Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Implemented merging of _joinData in the marshaller
  • Loading branch information
lorenzo committed Mar 2, 2014
1 parent f333550 commit ecbe408
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 1 deletion.
48 changes: 47 additions & 1 deletion src/ORM/Marshaller.php
Expand Up @@ -249,10 +249,16 @@ public function mergeMany($entities, array $data, $include = []) {
$output = [];

foreach ($entities as $entity) {
if (!($entity instanceof EntityInterface)) {
continue;
}

$key = $entity->get($primary[0]);

if ($key === null || !isset($indexed[$key])) {
continue;
}

$output[] = $this->merge($entity, $indexed[$key][0], $include);
unset($indexed[$key]);
}
Expand All @@ -276,9 +282,49 @@ protected function _mergeAssociation($original, $assoc, $value, $include) {
return $marshaller->merge($original, $value, (array)$include);
}
if ($assoc->type() === Association::MANY_TO_MANY) {
return $marshaller->_belongsToMany($assoc, $value, (array)$include);
return $marshaller->_mergeBelongsToMany($original, $assoc, $value, (array)$include);
}
return $marshaller->mergeMany($original, $value, (array)$include);
}

protected function _mergeBelongsToMany($original, $assoc, $data, $include) {
if (isset($data['_ids']) && is_array($data['_ids'])) {
return $this->_loadBelongsToMany($assoc, $data['_ids']);
}

if (!in_array('_joinData', $include) && !isset($include['_joinData'])) {
return $this->mergeMany($original, $data, $include);
}

$extra = [];
foreach ($original as $entity) {
$joinData = $entity->get('_joinData');
if ($joinData) {
$extra[spl_object_hash($entity)] = $joinData;
}
}

$joint = $assoc->junction();
$marshaller = $joint->marshaller();

$nested = [];
if (isset($include['_joinData']['associated'])) {
$nested = (array)$include['_joinData']['associated'];
}

$records = $this->mergeMany($original, $data, $include);
foreach ($records as $record) {
$hash = spl_object_hash($record);
$data = $record->get('_joinData');
if (isset($extra[$hash])) {
$record->set('_joinData', $marshaller->merge($extra[$hash], (array)$data));
} else {
$joinData = $marshaller->one($data, $nested);
$record->set('_joinData', $joinData);
}
}

return $records;
}

}
60 changes: 60 additions & 0 deletions tests/TestCase/ORM/MarshallerTest.php
Expand Up @@ -712,4 +712,64 @@ public function testMergeBelongsToManyEntitiesFromIds() {
$this->assertInstanceOf('Cake\ORM\Entity', $result->tags[2]);
}

/**
* Test merging the _joinData entity for belongstomany associations.
*
* @return void
*/
public function testMergeBelongsToManyJoinData() {
$data = [
'title' => 'My title',
'body' => 'My content',
'author_id' => 1,
'tags' => [
[
'id' => 1,
'tag' => 'news',
'_joinData' => [
'active' => 0
]
],
[
'id' => 2,
'tag' => 'cakephp',
'_joinData' => [
'active' => 0
]
],
],
];

$options = ['Tags' => ['associated' => ['_joinData']]];
$marshall = new Marshaller($this->articles);
$entity = $marshall->one($data, $options);
$entity->accessible('*', true);

$data = [
'title' => 'Haz data',
'tags' => [
['id' => 1, 'tag' => 'Cake', '_joinData' => ['foo' => 'bar']],
['tag' => 'new tag', '_joinData' => ['active' => 1, 'foo' => 'baz']]
]
];

$tag1 = $entity->tags[0];
$result = $marshall->merge($entity, $data, $options);
$this->assertEquals($data['title'], $result->title);
$this->assertEquals('My content', $result->body);
$this->assertSame($tag1, $entity->tags[0]);
$this->assertSame($tag1->_joinData, $entity->tags[0]->_joinData);
$this->assertSame(
['active' => 0, 'foo' => 'bar'],
$entity->tags[0]->_joinData->toArray()
);
$this->assertSame(
['active' => 1, 'foo' => 'baz'],
$entity->tags[1]->_joinData->toArray()
);
$this->assertEquals('new tag', $entity->tags[1]->tag);
$this->assertTrue($entity->tags[0]->dirty('_joinData'));
$this->assertTrue($entity->tags[1]->dirty('_joinData'));
}

}

0 comments on commit ecbe408

Please sign in to comment.