Browse Source

Merge pull request #11396 from cakephp/fix-collections

Fix collections when iterating over certain classes
José Lorenzo Rodríguez 8 years ago
parent
commit
e7a15f8438

+ 1 - 0
phpstan.neon

@@ -22,6 +22,7 @@ parameters:
         - '#Access to an undefined property Exception::\$queryString#'
         - '#Access to an undefined property PHPUnit\\Framework\\Test::\$fixtureManager#'
         - '#Method Redis::#'
+        - '#Call to an undefined method Traversable::getArrayCopy().#'
     earlyTerminatingMethodCalls:
         Cake\Shell\Shell:
             - abort

+ 1 - 1
src/Collection/CollectionTrait.php

@@ -819,7 +819,7 @@ trait CollectionTrait
     {
         $iterator = $this->unwrap();
 
-        if ($iterator instanceof ArrayIterator) {
+        if (get_class($iterator) === ArrayIterator::class) {
             $iterator = $iterator->getArrayCopy();
         }
 

+ 1 - 1
src/Collection/Iterator/ExtractIterator.php

@@ -88,7 +88,7 @@ class ExtractIterator extends Collection
             $iterator = $iterator->unwrap();
         }
 
-        if (!$iterator instanceof ArrayIterator) {
+        if (get_class($iterator) !== ArrayIterator::class) {
             return $this;
         }
 

+ 1 - 1
src/Collection/Iterator/FilterIterator.php

@@ -74,7 +74,7 @@ class FilterIterator extends Collection
             $iterator = $iterator->unwrap();
         }
 
-        if (!$iterator instanceof ArrayIterator) {
+        if (get_class($iterator) !== ArrayIterator::class) {
             return $filter;
         }
 

+ 1 - 1
src/Collection/Iterator/ReplaceIterator.php

@@ -86,7 +86,7 @@ class ReplaceIterator extends Collection
             $iterator = $iterator->unwrap();
         }
 
-        if (!$iterator instanceof ArrayIterator) {
+        if (get_class($iterator) !== ArrayIterator::class) {
             return $this;
         }
 

+ 1 - 1
src/Collection/Iterator/StoppableIterator.php

@@ -97,7 +97,7 @@ class StoppableIterator extends Collection
             $iterator = $iterator->unwrap();
         }
 
-        if (!$iterator instanceof ArrayIterator) {
+        if (get_class($iterator) !== ArrayIterator::class) {
             return $this;
         }
 

+ 48 - 0
tests/TestCase/Collection/CollectionTest.php

@@ -42,6 +42,28 @@ class TestCollection extends \IteratorIterator implements CollectionInterface
 }
 
 /**
+ * Special class to test that extending \ArrayIterator works as expected
+ */
+class TestIterator extends ArrayIterator
+{
+    use CollectionTrait;
+
+    public $data = [];
+
+    public function __construct($data)
+    {
+        $this->data = $data;
+
+        parent::__construct($data);
+    }
+
+    public function checkValues()
+    {
+        return true;
+    }
+}
+
+/**
  * CollectionTest
  */
 class CollectionTest extends TestCase
@@ -2512,4 +2534,30 @@ class CollectionTest extends TestCase
     {
         return new \DatePeriod(new \DateTime($start), new \DateInterval('P1D'), new \DateTime($end));
     }
+
+    /**
+     * Tests to ensure that collection classes extending ArrayIterator work as expected.
+     *
+     * @return void
+     */
+    public function testArrayIteratorExtend()
+    {
+        $iterator = new TestIterator(range(0, 10));
+
+        $this->assertTrue(method_exists($iterator, 'checkValues'));
+        $this->assertTrue($iterator->checkValues());
+
+        //We need to perform at least two collection operation to trigger the issue.
+        $newIterator = $iterator
+            ->filter(function ($item) {
+                return $item < 5;
+            })
+            ->reject(function ($item) {
+                return $item > 2;
+            });
+
+        $this->assertTrue(method_exists($newIterator, 'checkValues'), 'Our method has gone missing!');
+        $this->assertTrue($newIterator->checkValues());
+        $this->assertCount(3, $newIterator->toArray());
+    }
 }