Browse Source

Merge pull request #6099 from cakephp/issue-6097

Fix #6097
José Lorenzo Rodríguez 11 years ago
parent
commit
7a5bd8e3cd
2 changed files with 79 additions and 21 deletions
  1. 17 16
      src/ORM/Marshaller.php
  2. 62 5
      tests/TestCase/ORM/MarshallerTest.php

+ 17 - 16
src/ORM/Marshaller.php

@@ -106,21 +106,6 @@ class Marshaller
 
         $schema = $this->_table->schema();
         $primaryKey = $schema->primaryKey();
-
-        if (array_intersect($primaryKey, array_keys($data)) == $primaryKey) {
-            $tableName = $this->_table->alias();
-            $record = $this->_table->find('all');
-            foreach ($primaryKey as $pkey) {
-                $record->where(["$tableName.$pkey" => $data[$pkey]]);
-            }
-
-            $record = $record->first();
-
-            if ($record) {
-                return $record;
-            }
-        }
-
         $entityClass = $this->_table->entityClass();
         $entity = new $entityClass();
         $entity->source($this->_table->registryAlias());
@@ -277,6 +262,7 @@ class Marshaller
      */
     protected function _belongsToMany(Association $assoc, array $data, $options = [])
     {
+        // Accept _ids = [1, 2]
         $associated = isset($options['associated']) ? $options['associated'] : [];
         $hasIds = array_key_exists('_ids', $data);
         if ($hasIds && is_array($data['_ids'])) {
@@ -286,7 +272,22 @@ class Marshaller
             return [];
         }
 
-        $records = $this->many($data, $options);
+        // Accept [ [id => 1], [id = 2] ] style.
+        $primaryKey = array_flip($assoc->target()->schema()->primaryKey());
+        if (array_intersect_key($primaryKey, current($data)) === $primaryKey) {
+            $primaryCount = count($primaryKey);
+            $query = $assoc->find();
+            foreach ($data as $row) {
+                $keys = array_intersect_key($row, $primaryKey);
+                if (count($keys) === $primaryCount) {
+                    $query->orWhere($keys);
+                }
+            }
+            $records = $query->toArray();
+        } else {
+            $records = $this->many($data, $options);
+        }
+
         $joint = $assoc->junction();
         $jointMarshaller = $joint->marshaller();
 

+ 62 - 5
tests/TestCase/ORM/MarshallerTest.php

@@ -524,10 +524,11 @@ class MarshallerTest extends TestCase
         ];
 
         $articlesTags = TableRegistry::get('ArticlesTags');
-        $Tags = TableRegistry::get('Tags');
-        $t1 = $Tags->find('all')->where(['id' => 1])->first();
-        $t2 = $Tags->find('all')->where(['id' => 2])->first();
+        $tags = TableRegistry::get('Tags');
+        $t1 = $tags->find('all')->where(['id' => 1])->first();
+        $t2 = $tags->find('all')->where(['id' => 2])->first();
         $articlesTags->belongsTo('Users');
+
         $marshall = new Marshaller($this->articles);
         $result = $marshall->one($data, ['associated' => ['Tags._joinData.Users']]);
         $this->assertInstanceOf(
@@ -548,8 +549,8 @@ class MarshallerTest extends TestCase
             'Cake\ORM\Entity',
             $result->tags[1]->_joinData->user
         );
-        $this->assertFalse($result->tags[0]->isNew());
-        $this->assertFalse($result->tags[1]->isNew());
+        $this->assertFalse($result->tags[0]->isNew(), 'Should not be new, as id is in db.');
+        $this->assertFalse($result->tags[1]->isNew(), 'Should not be new, as id is in db.');
         $this->assertEquals($t1->tag, $result->tags[0]->tag);
         $this->assertEquals($t2->tag, $result->tags[1]->tag);
         $this->assertEquals($data['tags'][0]['_joinData']['user']['username'], $result->tags[0]->_joinData->user->username);
@@ -1155,6 +1156,62 @@ class MarshallerTest extends TestCase
     }
 
     /**
+     * Test merging belongsToMany data doesn't create 'new' entities.
+     *
+     * @return void
+     */
+    public function testMergeBelongsToManyJoinDataAssociatedWithIds()
+    {
+        $data = [
+            'title' => 'My title',
+            'tags' => [
+                [
+                    'id' => 1,
+                    '_joinData' => [
+                        'active' => 1,
+                        'user' => ['username' => 'MyLux'],
+                    ]
+                ],
+                [
+                    'id' => 2,
+                    '_joinData' => [
+                        'active' => 0,
+                        'user' => ['username' => 'IronFall'],
+                    ]
+                ],
+            ],
+        ];
+        $articlesTags = TableRegistry::get('ArticlesTags');
+        $articlesTags->belongsTo('Users');
+
+        $marshall = new Marshaller($this->articles);
+        $article = $this->articles->get(1, ['associated' => 'Tags']);
+        $result = $marshall->merge($article, $data, ['associated' => ['Tags._joinData.Users']]);
+
+        $this->assertInstanceOf('Cake\ORM\Entity', $result->tags[0]);
+        $this->assertInstanceOf('Cake\ORM\Entity', $result->tags[1]);
+        $this->assertInstanceOf('Cake\ORM\Entity', $result->tags[0]->_joinData->user);
+
+        $this->assertInstanceOf('Cake\ORM\Entity', $result->tags[1]->_joinData->user);
+        $this->assertFalse($result->tags[0]->isNew(), 'Should not be new, as id is in db.');
+        $this->assertFalse($result->tags[1]->isNew(), 'Should not be new, as id is in db.');
+        $this->assertEquals(1, $result->tags[0]->id);
+        $this->assertEquals(2, $result->tags[1]->id);
+
+        $this->assertEquals(1, $result->tags[0]->_joinData->active);
+        $this->assertEquals(0, $result->tags[1]->_joinData->active);
+
+        $this->assertEquals(
+            $data['tags'][0]['_joinData']['user']['username'],
+            $result->tags[0]->_joinData->user->username
+        );
+        $this->assertEquals(
+            $data['tags'][1]['_joinData']['user']['username'],
+            $result->tags[1]->_joinData->user->username
+        );
+    }
+
+    /**
      * Test merging the _joinData entity for belongstomany associations.
      *
      * @return void