Skip to content

Commit

Permalink
Enable _ids to work when updating has many associations
Browse files Browse the repository at this point in the history
Previously the `_ids` key could only be used to update hasMany
associations if the association property *was not* populated. Now you
can use `_ids` to overwrite existing association data. This makes
hasMany associations consistent with belongs to many.

Refs #12373
  • Loading branch information
markstory committed Jul 26, 2018
1 parent 50d16b6 commit 74bf9d1
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/ORM/Marshaller.php
Expand Up @@ -753,6 +753,17 @@ protected function _mergeAssociation($original, $assoc, $value, $options)
return $marshaller->_mergeBelongsToMany($original, $assoc, $value, (array)$options);
}

if ($assoc->type() === Association::ONE_TO_MANY) {
$hasIds = array_key_exists('_ids', $value);
$onlyIds = array_key_exists('onlyIds', $options) && $options['onlyIds'];
if ($hasIds && is_array($value['_ids'])) {
return $this->_loadAssociatedByIds($assoc, $value['_ids']);
}
if ($hasIds || $onlyIds) {
return [];
}
}

return $marshaller->mergeMany($original, $value, (array)$options);
}

Expand Down
52 changes: 52 additions & 0 deletions tests/TestCase/ORM/MarshallerTest.php
Expand Up @@ -1731,6 +1731,57 @@ public function testMergeMultipleAssociations()
);
}

/**
* Tests that merging data to a hasMany association with _ids works.
*
* @return void
*/
public function testMergeHasManyEntitiesFromIds()
{
$entity = $this->articles->get(1, ['contain' => ['Comments']]);
$this->assertNotEmpty($entity->comments);

$marshall = new Marshaller($this->articles);
$data = ['comments' => ['_ids' => [1, 2, 3]]];
$result = $marshall->merge($entity, $data, ['associated' => ['Comments']]);

$this->assertCount(3, $result->comments);
$this->assertTrue($result->isDirty('comments'), 'Updated prop should be dirty');
$this->assertInstanceOf(Entity::class, $result->comments[0]);
$this->assertEquals(1, $result->comments[0]->id);
$this->assertInstanceOf(Entity::class, $result->comments[1]);
$this->assertEquals(2, $result->comments[1]->id);
$this->assertInstanceOf(Entity::class, $result->comments[2]);
$this->assertEquals(3, $result->comments[2]->id);
}

/**
* Tests that merging data to a hasMany association using onlyIds restricts operations.
*
* @return void
*/
public function testMergeHasManyEntitiesFromIdsOnlyIds()
{
$entity = $this->articles->get(1, ['contain' => ['Comments']]);
$this->assertNotEmpty($entity->comments);

$marshall = new Marshaller($this->articles);
$data = [
'comments' => [
'_ids' => [1],
[
'comment' => 'Nope'
]
]
];
$result = $marshall->merge($entity, $data, ['associated' => ['Comments' => ['onlyIds' => true]]]);

$this->assertCount(1, $result->comments);
$this->assertTrue($result->isDirty('comments'), 'Updated prop should be dirty');
$this->assertInstanceOf(Entity::class, $result->comments[0]);
$this->assertNotEquals('Nope', $result->comments[0]);
}

/**
* Tests that merging data to an entity containing belongsToMany and _ids
* will just overwrite the data
Expand Down Expand Up @@ -1765,6 +1816,7 @@ public function testMergeBelongsToManyEntitiesFromIds()
$this->assertInstanceOf('Cake\ORM\Entity', $result->tags[2]);
}


/**
* Tests that merging data to an entity containing belongsToMany and _ids
* will not generate conflicting queries when associations are automatically selected
Expand Down

0 comments on commit 74bf9d1

Please sign in to comment.