Browse Source

Use association conditions when replacing belongToMany links.

This is necessary especially for polymorphic belongsToMany to ensure links for
other models are not deleted.
ADmad 10 years ago
parent
commit
d245beaa65

+ 5 - 0
src/ORM/Association/BelongsToMany.php

@@ -733,6 +733,11 @@ class BelongsToMany extends Association
                 $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);
 

+ 52 - 0
tests/Fixture/PolymorphicTaggedFixture.php

@@ -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 - 0
tests/TestCase/ORM/TableTest.php

@@ -59,6 +59,7 @@ class TableTest extends TestCase
         'core.members',
         'core.groups',
         'core.groups_members',
+        'core.polymorphic_tagged',
     ];
 
     /**
@@ -3287,6 +3288,80 @@ class TableTest extends TestCase
     }
 
     /**
+     * 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.
      *
      * @group save