Browse Source

Rewinding only once the iterator for Collection::nest()

This solves problems with iterators having side effects when they
are rewound at the expense of having an extra map() call.

Fixes #5982
Jose Lorenzo Rodriguez 11 years ago
parent
commit
84bb942180

+ 10 - 9
src/Collection/CollectionTrait.php

@@ -371,7 +371,7 @@ trait CollectionTrait
         $parents = [];
         $idPath = $this->_propertyExtractor($idPath);
         $parentPath = $this->_propertyExtractor($parentPath);
-        $isObject = !is_array((new Collection($this))->first());
+        $isObject = true;
 
         $mapper = function ($row, $key, $mapReduce) use (&$parents, $idPath, $parentPath) {
             $row['children'] = [];
@@ -381,7 +381,12 @@ trait CollectionTrait
             $mapReduce->emitIntermediate($id, $parentId);
         };
 
-        $reducer = function ($values, $key, $mapReduce) use (&$parents, $isObject) {
+        $reducer = function ($values, $key, $mapReduce) use (&$parents, &$isObject) {
+            static $foundOutType = false;
+            if (!$foundOutType) {
+                $isObject = is_object(current($parents));
+                $foundOutType = true;
+            }
             if (empty($key) || !isset($parents[$key])) {
                 foreach ($values as $id) {
                     $parents[$id] = $isObject ? $parents[$id] : new ArrayIterator($parents[$id], 1);
@@ -397,14 +402,10 @@ trait CollectionTrait
             $parents[$key]['children'] = $children;
         };
 
-        $collection = new MapReduce($this, $mapper, $reducer);
-        if (!$isObject) {
-            $collection = (new Collection($collection))->map(function ($value) {
-                return $value->getArrayCopy();
+        return (new Collection(new MapReduce($this->_unwrap(), $mapper, $reducer)))
+            ->map(function ($value) use (&$isObject) {
+                return $isObject ? $value : $value->getArrayCopy();
             });
-        }
-
-        return new Collection($collection);
     }
 
     /**

+ 2 - 1
tests/TestCase/ORM/Behavior/BehaviorRegressionTest.php

@@ -49,7 +49,8 @@ class BehaviorRegressionTest extends TestCase
      * @see https://github.com/cakephp/cakephp/issues/5982
      * @return void
      */
-    public function testTreeAndTranslateIntegration() {
+    public function testTreeAndTranslateIntegration()
+    {
         $table = TableRegistry::get('NumberTrees');
         $table->primaryKey(['id']);
         $table->addBehavior('Tree');