Browse Source

Simplify loops by indexing data in separate loops.

By unrolling the nested loops we can have simpler code. I also added
another test case to help provide additional case coverage around
belongsToMany marshalling.

Refs #6512
Mark Story 11 years ago
parent
commit
04ed50026b
2 changed files with 63 additions and 19 deletions
  1. 18 14
      src/ORM/Marshaller.php
  2. 45 5
      tests/TestCase/ORM/MarshallerTest.php

+ 18 - 14
src/ORM/Marshaller.php

@@ -299,25 +299,29 @@ class Marshaller
         }
 
         if (isset($query)) {
-            $queryData = $query->toArray();
-            foreach ($queryData as $queryItem) {
-                foreach ($data as $i => $row) {
-                    $matchCount = 0;
-                    foreach ($primaryKey as $key => $value) {
-                        if (isset($row[$key]) && $row[$key] == $queryItem->$key) {
-                            $matchCount++;
-                        }
-                        if ($matchCount === count($primaryKey)) {
-                            $records[$i] = $queryItem;
-                            break 2;
-                        }
+            $keyFields = array_keys($primaryKey);
+
+            $existing = [];
+            foreach ($query as $row) {
+                $k = implode(';', $row->extract($keyFields));
+                $existing[$k] = $row;
+            }
+
+            foreach ($data as $i => $row) {
+                $key = [];
+                foreach ($keyFields as $k) {
+                    if (isset($row[$k])) {
+                        $key[] = $row[$k];
                     }
                 }
+                $key = implode(';', $key);
+                if (isset($existing[$key])) {
+                    $records[$i] = $existing[$key];
+                }
             }
         }
 
-        $joint = $assoc->junction();
-        $jointMarshaller = $joint->marshaller();
+        $jointMarshaller = $assoc->junction()->marshaller();
 
         $nested = [];
         if (isset($associated['_joinData'])) {

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

@@ -615,13 +615,9 @@ class MarshallerTest extends TestCase
                 ]
             ]
         ];
-
-        $articlesTags = TableRegistry::get('ArticlesTags');
-        $articlesTags->belongsTo('Users');
-
         $marshall = new Marshaller($this->articles);
 
-        $result = $marshall->one($data, ['associated' => ['Tags._joinData.Users']]);
+        $result = $marshall->one($data, ['associated' => ['Tags._joinData']]);
 
         $this->assertEquals($data['tags'][0]['id'], $result->tags[0]->id);
         $this->assertEquals($data['tags'][1]['name'], $result->tags[1]->name);
@@ -630,6 +626,50 @@ class MarshallerTest extends TestCase
     }
 
     /**
+     * Test belongsToMany association with mixed data and _joinData
+     *
+     * @return void
+     */
+    public function testBelongsToManyWithMixedJoinDataOutOfOrder()
+    {
+        $data = [
+            'title' => 'My title',
+            'body' => 'My content',
+            'author_id' => 1,
+            'tags' => [
+                [
+                    'name' => 'tag5',
+                    '_joinData' => [
+                        'active' => 1,
+                    ]
+                ],
+                [
+                    'id' => 1,
+                    '_joinData' => [
+                        'active' => 0,
+                    ]
+                ],
+                [
+                    'name' => 'tag3',
+                    '_joinData' => [
+                        'active' => 1,
+                    ]
+                ],
+            ]
+        ];
+        $marshall = new Marshaller($this->articles);
+        $result = $marshall->one($data, ['associated' => ['Tags._joinData']]);
+
+        $this->assertEquals($data['tags'][0]['name'], $result->tags[0]->name);
+        $this->assertEquals($data['tags'][1]['id'], $result->tags[1]->id);
+        $this->assertEquals($data['tags'][2]['name'], $result->tags[2]->name);
+
+        $this->assertEquals(1, $result->tags[0]->_joinData->active);
+        $this->assertEquals(0, $result->tags[1]->_joinData->active);
+        $this->assertEquals(1, $result->tags[2]->_joinData->active);
+    }
+
+    /**
      * Test belongsToMany association with mixed data array
      *
      * @return void