Skip to content

Commit

Permalink
Fix BelongsToMany saving incorrectly when _joinData is used.
Browse files Browse the repository at this point in the history
When the `_joinData` has not been fully marshalled, BelongsToMany
associations will not save the joinData correctly. This can cause data
to go 'missing' when associations with conditions are involved.

Refs #7808
  • Loading branch information
markstory committed Jan 7, 2016
1 parent 5a9ba35 commit b5a9068
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/ORM/Association/BelongsToMany.php
Expand Up @@ -622,11 +622,13 @@ protected function _saveLinks(EntityInterface $sourceEntity, $targetEntities, $o
$junctionAlias = $junction->alias();

foreach ($targetEntities as $e) {
$joint = $e->get($jointProperty);
$joint = $jointVal = $e->get($jointProperty);
if (!$joint || !($joint instanceof EntityInterface)) {
$joint = new $entityClass([], ['markNew' => true, 'source' => $junctionAlias]);
if (is_array($jointVal)) {
$joint->set($jointVal);
}
}

$sourceKeys = array_combine($foreignKey, $sourceEntity->extract($bindingKey));
$targetKeys = array_combine($assocForeignKey, $e->extract($targetPrimaryKey));

Expand Down
32 changes: 32 additions & 0 deletions tests/TestCase/ORM/Association/BelongsToManyTest.php
Expand Up @@ -656,6 +656,38 @@ public function testReplaceLinkWithConditions()
$this->assertSame(1, $jointCount, 'Non matching joint record should remain.');
}

/**
* Tests that replaceLinks will apply _joinData when it has not been converted
* to an entity if that data is an array.
*
* @return void
*/
public function testReplaceLinkJoinDataHandling()
{
$joint = TableRegistry::get('SpecialTags');
$articles = TableRegistry::get('Articles');

$assoc = $articles->belongsToMany('Tags', [
'through' => 'SpecialTags',
'conditions' => ['SpecialTags.highlighted' => true]
]);
$id = 2;
$entity = $articles->get($id, ['contain' => 'Tags']);

// New tag
$tagData = [
new Entity(['id' => 2, '_joinData' => ['highlighted' => true]]),
];

$assoc->replaceLinks($entity, $tagData);
$this->assertSame($tagData, $entity->tags, 'Tags should match replaced objects');
$this->assertFalse($entity->dirty('tags'), 'Should be clean');

$jointRecords = $joint->find()->where(['article_id' => $id])->toArray();
$this->assertCount(1, $jointRecords);
$this->assertTrue($jointRecords[0]->highlighted, 'joinData should be set.');
}

/**
* Provider for empty values
*
Expand Down

0 comments on commit b5a9068

Please sign in to comment.