Bläddra i källkod

Merge pull request #34 from bashofmann/master

Fix iterator methods of MongoCursor
Andreas 10 år sedan
förälder
incheckning
ccb00883a3

+ 15 - 2
lib/Alcaeus/MongoDbAdapter/AbstractCursor.php

@@ -246,18 +246,31 @@ abstract class AbstractCursor
     }
 
     /**
-     * @return \IteratorIterator
+     * @return \Generator
      */
     protected function ensureIterator()
     {
         if ($this->iterator === null) {
-            $this->iterator = new \IteratorIterator($this->ensureCursor());
+            // MongoDB\Driver\Cursor needs to be wrapped into a \Generator so that a valid \Iterator with working implementations of
+            // next, current, valid, key and rewind is returned. These methods don't work if we wrap the Cursor inside an \IteratorIterator
+            $this->iterator = $this->wrapTraversable($this->ensureCursor());
         }
 
         return $this->iterator;
     }
 
     /**
+     * @param \Traversable $traversable
+     * @return \Generator
+     */
+    private function wrapTraversable(\Traversable $traversable)
+    {
+        foreach ($traversable as $key => $value) {
+            yield $key => $value;
+        }
+    }
+
+    /**
      * @throws \MongoCursorException
      */
     protected function errorIfOpened()

+ 34 - 0
tests/Alcaeus/MongoDbAdapter/MongoCursorTest.php

@@ -49,6 +49,40 @@ class MongoCursorTest extends TestCase
         $cursor->count();
     }
 
+    public function testIteratorInterface()
+    {
+        $this->prepareData();
+
+        $collection = $this->getCollection();
+        $cursor = $collection->find(['foo' => 'bar']);
+
+        $this->assertTrue($cursor->valid(), 'Cursor should be valid');
+
+        $item = $cursor->current();
+        $this->assertNotNull($item);
+        $this->assertInstanceOf('MongoId', $item['_id']);
+        $this->assertSame('bar', $item['foo']);
+
+        $cursor->next();
+
+        $item = $cursor->current();
+        $this->assertNotNull($item);
+        $this->assertInstanceOf('MongoId', $item['_id']);
+        $this->assertSame('bar', $item['foo']);
+
+        $cursor->next();
+
+        $this->assertNull($cursor->current(), 'Cursor should return null at the end');
+        $this->assertFalse($cursor->valid(), 'Cursor should be invalid');
+
+        $cursor->rewind();
+
+        $item = $cursor->current();
+        $this->assertNotNull($item);
+        $this->assertInstanceOf('MongoId', $item['_id']);
+        $this->assertSame('bar', $item['foo']);
+    }
+
     /**
      * @dataProvider getCursorOptions
      */