Skip to content

Commit

Permalink
Use association conditions when replacing belongToMany links.
Browse files Browse the repository at this point in the history
This is necessary especially for polymorphic belongsToMany to ensure links for
other models are not deleted.
  • Loading branch information
ADmad committed Jun 27, 2015
1 parent d658891 commit d245bea
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/ORM/Association/BelongsToMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,11 @@ function () use ($sourceEntity, $targetEntities, $primaryValue, $options) {
$existing = $hasMany->find('all')
->where(array_combine($foreignKey, $primaryValue));

$associationConditions = $this->conditions();
if ($associationConditions) {
$existing->andWhere($associationConditions);
}

$jointEntities = $this->_collectJointEntities($sourceEntity, $targetEntities);
$inserts = $this->_diffLinks($existing, $jointEntities, $targetEntities);

Expand Down
52 changes: 52 additions & 0 deletions tests/Fixture/PolymorphicTaggedFixture.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 3.0.8
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Test\Fixture;

use Cake\TestSuite\Fixture\TestFixture;

class PolymorphicTaggedFixture extends TestFixture
{

/**
* table property
*
* @var string
*/
public $table = 'polymorphic_tagged';

/**
* fields property
*
* @var array
*/
public $fields = [
'id' => ['type' => 'integer'],
'tag_id' => ['type' => 'integer'],
'foreign_key' => ['type' => 'integer'],
'foreign_model' => ['type' => 'string'],
'position' => ['type' => 'integer', 'null' => true],
'_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id']]]
];

/**
* records property
*
* @var array
*/
public $records = [
['tag_id' => 1, 'foreign_key' => 1, 'foreign_model' => 'Posts', 'position' => 1],
['tag_id' => 1, 'foreign_key' => 1, 'foreign_model' => 'Articles', 'position' => 1],
];
}
75 changes: 75 additions & 0 deletions tests/TestCase/ORM/TableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class TableTest extends TestCase
'core.members',
'core.groups',
'core.groups_members',
'core.polymorphic_tagged',
];

/**
Expand Down Expand Up @@ -3286,6 +3287,80 @@ public function testSaveBelongsToManyJoinData()
$this->assertSame($result, $article);
}

/**
* Test to check that association condition are used when fetching existing
* records to decide which records to unlink.
*
* @return void
*/
public function testPolymorphicBelongsToManySave()
{
$articles = TableRegistry::get('Articles');
$articles->belongsToMany('Tags', [
'through' => 'PolymorphicTagged',
'foreignKey' => 'foreign_key',
'conditions' => [
'PolymorphicTagged.foreign_model' => 'Articles'
],
'sort' => ['PolymorphicTagged.position' => 'ASC']
]);

$articles->Tags->junction()->belongsTo('Tags');

$entity = $articles->get(1, ['contain' => ['Tags']]);
$data = [
'id' => 1,
'tags' => [
[
'id' => 1,
'_joinData' => [
'id' => 2,
'foreign_model' => 'Articles',
'position' => 2
]
],
[
'id' => 2,
'_joinData' => [
'foreign_model' => 'Articles',
'position' => 1
]
]
]
];
$entity = $articles->patchEntity($entity, $data, ['associated' => ['Tags._joinData']]);
$entity = $articles->save($entity);

$expected = [
[
'id' => 1,
'tag_id' => 1,
'foreign_key' => 1,
'foreign_model' => 'Posts',
'position' => 1
],
[
'id' => 2,
'tag_id' => 1,
'foreign_key' => 1,
'foreign_model' => 'Articles',
'position' => 2
],
[
'id' => 3,
'tag_id' => 2,
'foreign_key' => 1,
'foreign_model' => 'Articles',
'position' => 1
]
];
$result = TableRegistry::get('PolymorphicTagged')
->find('all', ['sort' => ['id' => 'DESC']])
->hydrate(false)
->toArray();
$this->assertEquals($expected, $result);
}

/**
* Tests saving belongsToMany records can delete all links.
*
Expand Down

0 comments on commit d245bea

Please sign in to comment.