Browse Source

Merge pull request #145 from alcaeus/fix-gridfs-find-projection

Convert legacy projection syntax before applying
Andreas 9 years ago
parent
commit
20995f52c5

+ 20 - 0
lib/Alcaeus/MongoDbAdapter/TypeConverter.php

@@ -88,6 +88,26 @@ class TypeConverter
     }
 
     /**
+     * Converts a projection used in find queries.
+     *
+     * This method handles conversion from the legacy syntax (e.g. ['x', 'y', 'z'])
+     * to the new syntax (e.g. ['x' => true, 'y' => true, 'z' => true]). While
+     * this was never documented, the legacy driver applied the same conversion.
+     *
+     * @param array $fields
+     * @return array
+     */
+    public static function convertProjection($fields)
+    {
+        if (! is_array($fields) || $fields === []) {
+            return [];
+        }
+
+        $projection = TypeConverter::isNumericArray($fields) ? array_fill_keys($fields, true) : $fields;
+        return TypeConverter::fromLegacy($projection);
+    }
+
+    /**
      * Helper method to find out if an array has numerical indexes
      *
      * For performance reason, this method checks the first array index only.

+ 2 - 2
lib/Mongo/MongoCollection.php

@@ -514,7 +514,7 @@ class MongoCollection
                     unset($options['new']);
                 }
 
-                $options['projection'] = is_array($fields) ? TypeConverter::fromLegacy($fields) : [];
+                $options['projection'] = TypeConverter::convertProjection($fields);
 
                 if (! \MongoDB\is_first_key_operator($update)) {
                     $document = $this->collection->findOneAndReplace($query, $update, $options);
@@ -552,7 +552,7 @@ class MongoCollection
             return;
         }
 
-        $options = ['projection' => TypeConverter::fromLegacy($fields)] + $options;
+        $options = ['projection' => TypeConverter::convertProjection($fields)] + $options;
         try {
             $document = $this->collection->findOne(TypeConverter::fromLegacy($query), $options);
         } catch (\MongoDB\Driver\Exception\Exception $e) {

+ 1 - 1
lib/Mongo/MongoCursor.php

@@ -431,7 +431,7 @@ class MongoCursor extends AbstractCursor implements Iterator
      */
     protected function convertProjection()
     {
-        return TypeConverter::fromLegacy($this->projection);
+        return TypeConverter::convertProjection($this->projection);
     }
 
     /**

+ 49 - 2
tests/Alcaeus/MongoDbAdapter/Mongo/MongoCollectionTest.php

@@ -429,6 +429,35 @@ class MongoCollectionTest extends TestCase
         $this->assertInstanceOf('MongoCursor', $collection->find());
     }
 
+    public function testFindWithProjection()
+    {
+        $document = ['foo' => 'foo', 'bar' => 'bar'];
+        $this->getCollection()->insert($document);
+        unset($document['_id']);
+        $this->getCollection()->insert($document);
+
+        $cursor = $this->getCollection()->find(['foo' => 'foo'], ['bar' => true]);
+        foreach ($cursor as $document) {
+            $this->assertCount(2, $document);
+            $this->assertArraySubset(['bar' => 'bar'], $document);
+        }
+    }
+
+    public function testFindWithLegacyProjection()
+    {
+        $document = ['foo' => 'foo', 'bar' => 'bar'];
+        $this->getCollection()->insert($document);
+        unset($document['_id']);
+        $this->getCollection()->insert($document);
+
+        $cursor = $this->getCollection()->find(['foo' => 'foo'], ['bar']);
+        foreach ($cursor as $document) {
+            $this->assertCount(2, $document);
+            $this->assertArraySubset(['bar' => 'bar'], $document);
+        }
+    }
+
+
     public function testCount()
     {
         $this->prepareData();
@@ -510,6 +539,26 @@ class MongoCollectionTest extends TestCase
         $this->assertSame(['foo' => 'foo'], $document);
     }
 
+    public function testFindOneWithProjection()
+    {
+        $document = ['foo' => 'foo', 'bar' => 'bar'];
+        $this->getCollection()->insert($document);
+
+        $document = $this->getCollection()->findOne(['foo' => 'foo'], ['bar' => true]);
+        $this->assertCount(2, $document);
+        $this->assertArraySubset(['bar' => 'bar'], $document);
+    }
+
+    public function testFindOneWithLegacyProjection()
+    {
+        $document = ['foo' => 'foo', 'bar' => 'bar'];
+        $this->getCollection()->insert($document);
+
+        $document = $this->getCollection()->findOne(['foo' => 'foo'], ['bar']);
+        $this->assertCount(2, $document);
+        $this->assertArraySubset(['bar' => 'bar'], $document);
+    }
+
     public function testFindOneNotFound()
     {
         $document = $this->getCollection()->findOne(['foo' => 'foo'], ['_id' => false]);
@@ -1510,8 +1559,6 @@ class MongoCollectionTest extends TestCase
                 'keysPerIndex' => ['mongo-php-adapter.test.$_id_' => 1],
                 'valid' => true,
                 'errors' => [],
-                'warning' => 'Some checks omitted for speed. use {full:true} option to do more thorough scan.',
-                'ok'  => 1.0
             ],
             $result
         );

+ 12 - 0
tests/Alcaeus/MongoDbAdapter/Mongo/MongoGridFSTest.php

@@ -287,6 +287,18 @@ class MongoGridFSTest extends TestCase
         $this->assertInstanceOf('MongoGridFSFile', $result);
     }
 
+    public function testFindOneWithLegacyProjectionReturnsFile()
+    {
+        $collection = $this->getGridFS();
+        $this->prepareFile('abcd', ['date' => new \MongoDate()]);
+
+        $result = $collection->findOne([], ['date']);
+
+        $this->assertInstanceOf('MongoGridFSFile', $result);
+        $this->assertCount(2, $result->file);
+        $this->assertArrayHasKey('date', $result->file);
+    }
+
     public function testFindOneWithFilenameReturnsFile()
     {
         $collection = $this->getGridFS();