Prechádzať zdrojové kódy

Merge pull request #16 from alcaeus/implement-mongodb-class

Implement missing methods in MongoDB class
Andreas 10 rokov pred
rodič
commit
afdeb9d1a1

+ 3 - 3
lib/Mongo/MongoCollection.php

@@ -150,7 +150,7 @@ class MongoCollection
 
         $command += $options;
 
-        return $this->db->command($command, [], $hash);
+        return $this->db->command($command);
     }
 
     /**
@@ -241,7 +241,7 @@ class MongoCollection
             'full'     => $scan_data,
         ];
 
-        return $this->db->command($command, [], $hash);
+        return $this->db->command($command);
     }
 
     /**
@@ -598,7 +598,7 @@ class MongoCollection
             $command['group']['finalize'] = $condition['finalize'];
         }
 
-        return $this->db->command($command, [], $hash);
+        return $this->db->command($command);
     }
 
     /**

+ 65 - 111
lib/Mongo/MongoDB.php

@@ -68,7 +68,7 @@ class MongoDB
 
     /**
      * @return \MongoDB\Database
-     * @internal
+     * @internal This method is not part of the ext-mongo API
      */
     public function getDb()
     {
@@ -77,6 +77,7 @@ class MongoDB
 
     /**
      * The name of this database
+     *
      * @link http://www.php.net/manual/en/mongodb.--tostring.php
      * @return string Returns this database's name.
      */
@@ -115,16 +116,16 @@ class MongoDB
     }
 
     /**
-     * (PECL mongo &gt;= 1.3.0)<br/>
-     * @link http://www.php.net/manual/en/mongodb.getcollectionnames.php
      * Get all collections from this database
-     * @return array Returns the names of the all the collections in the database as an
-     * {@link http://www.php.net/manual/en/language.types.array.php array}.
+     *
+     * @link http://www.php.net/manual/en/mongodb.getcollectionnames.php
+     * @return array Returns the names of the all the collections in the database as an array
      */
     public function getCollectionNames(array $options = [])
     {
-        if (is_bool($options)) {
-            $options = ['includeSystemCollections' => $options];
+        // The includeSystemCollections option is no longer supported
+        if (isset($options['includeSystemCollections'])) {
+            unset($options['includeSystemCollections']);
         }
 
         $collections = $this->db->listCollections($options);
@@ -133,7 +134,7 @@ class MongoDB
             return $collectionInfo->getName();
         };
 
-        return array_map($getCollectionName, (array) $collections);
+        return array_map($getCollectionName, (array)$collections);
     }
 
     /**
@@ -146,10 +147,10 @@ class MongoDB
     }
 
     /**
-     * (PECL mongo &gt;= 0.9.0)<br/>
      * Fetches toolkit for dealing with files stored in this database
+     *
      * @link http://www.php.net/manual/en/mongodb.getgridfs.php
-     * @param string $prefix [optional] The prefix for the files and chunks collections.
+     * @param string $prefix The prefix for the files and chunks collections.
      * @return MongoGridFS Returns a new gridfs object for this database.
      */
     public function getGridFS($prefix = "fs")
@@ -158,31 +159,35 @@ class MongoDB
     }
 
     /**
-     * (PECL mongo &gt;= 0.9.0)<br/>
      * Gets this database's profiling level
+     *
      * @link http://www.php.net/manual/en/mongodb.getprofilinglevel.php
      * @return int Returns the profiling level.
      */
     public function getProfilingLevel()
     {
-        return static::PROFILING_OFF;
+        $result = $this->command(['profile' => -1]);
+
+        return ($result['ok'] && isset($result['was'])) ? $result['was'] : 0;
     }
 
     /**
-     * (PECL mongo &gt;= 0.9.0)<br/>
      * Sets this database's profiling level
+     *
      * @link http://www.php.net/manual/en/mongodb.setprofilinglevel.php
      * @param int $level Profiling level.
      * @return int Returns the previous profiling level.
      */
     public function setProfilingLevel($level)
     {
-        return static::PROFILING_OFF;
+        $result = $this->command(['profile' => $level]);
+
+        return ($result['ok'] && isset($result['was'])) ? $result['was'] : 0;
     }
 
     /**
-     * (PECL mongo &gt;= 0.9.0)<br/>
      * Drops this database
+     *
      * @link http://www.php.net/manual/en/mongodb.drop.php
      * @return array Returns the database response.
      */
@@ -193,6 +198,7 @@ class MongoDB
 
     /**
      * Repairs and compacts this database
+     *
      * @link http://www.php.net/manual/en/mongodb.repair.php
      * @param bool $preserve_cloned_files [optional] <p>If cloned files should be kept if the repair fails.</p>
      * @param bool $backup_original_files [optional] <p>If original files should be backed up.</p>
@@ -204,14 +210,12 @@ class MongoDB
     }
 
     /**
-     * (PECL mongo &gt;= 0.9.0)<br/>
      * Gets a collection
+     *
      * @link http://www.php.net/manual/en/mongodb.selectcollection.php
      * @param string $name <b>The collection name.</b>
      * @throws Exception if the collection name is invalid.
-     * @return MongoCollection <p>
-     * Returns a new collection object.
-     * </p>
+     * @return MongoCollection Returns a new collection object.
      */
     public function selectCollection($name)
     {
@@ -220,37 +224,11 @@ class MongoDB
 
     /**
      * Creates a collection
+     *
      * @link http://www.php.net/manual/en/mongodb.createcollection.php
      * @param string $name The name of the collection.
-     * @param array $options [optional] <p>
-     * <p>
-     * An array containing options for the collections. Each option is its own
-     * element in the options array, with the option name listed below being
-     * the key of the element. The supported options depend on the MongoDB
-     * server version. At the moment, the following options are supported:
-     * </p>
-     * <p>
-     * <b>capped</b>
-     * <p>
-     * If the collection should be a fixed size.
-     * </p>
-     * </p>
-     * <p>
-     * <b>size</b>
-     * <p>
-     * If the collection is fixed size, its size in bytes.</p></p>
-     * <p><b>max</b>
-     * <p>If the collection is fixed size, the maximum number of elements to store in the collection.</p></p>
-     * <i>autoIndexId</i>
-     *
-     * <p>
-     * If capped is <b>TRUE</b> you can specify <b>FALSE</b> to disable the
-     * automatic index created on the <em>_id</em> field.
-     * Before MongoDB 2.2, the default value for
-     * <em>autoIndexId</em> was <b>FALSE</b>.
-     * </p>
-     * </p>
-     * @return MongoCollection <p>Returns a collection object representing the new collection.</p>
+     * @param array $options
+     * @return MongoCollection Returns a collection object representing the new collection.
      */
     public function createCollection($name, $options)
     {
@@ -259,23 +237,28 @@ class MongoDB
     }
 
     /**
-     * (PECL mongo &gt;= 0.9.0)<br/>
-     * @deprecated Use MongoCollection::drop() instead.
      * Drops a collection
+     *
      * @link http://www.php.net/manual/en/mongodb.dropcollection.php
      * @param MongoCollection|string $coll MongoCollection or name of collection to drop.
      * @return array Returns the database response.
+     *
+     * @deprecated Use MongoCollection::drop() instead.
      */
     public function dropCollection($coll)
     {
+        if ($coll instanceof MongoCollection) {
+            $coll = $coll->getName();
+        }
+
         return $this->db->dropCollection((string) $coll);
     }
 
     /**
-     * (PECL mongo &gt;= 0.9.0)<br/>
      * Get a list of collections in this database
+     *
      * @link http://www.php.net/manual/en/mongodb.listcollections.php
-     * @param bool $includeSystemCollections [optional] <p>Include system collections.</p>
+     * @param array $options
      * @return array Returns a list of MongoCollections.
      */
     public function listCollections(array $options = [])
@@ -284,26 +267,23 @@ class MongoDB
     }
 
     /**
-     * (PECL mongo &gt;= 0.9.0)<br/>
      * Creates a database reference
+     *
      * @link http://www.php.net/manual/en/mongodb.createdbref.php
      * @param string $collection The collection to which the database reference will point.
-     * @param mixed $document_or_id <p>
-     * If an array or object is given, its <em>_id</em> field will be
-     * used as the reference ID. If a {@see MongoId} or scalar
-     * is given, it will be used as the reference ID.
-     * </p>
-     * @return array <p>Returns a database reference array.</p>
-     * <p>
-     * If an array without an <em>_id</em> field was provided as the
-     * <em>document_or_id</em> parameter, <b>NULL</b> will be returned.
-     * </p>
+     * @param mixed $document_or_id
+     * @return array Returns a database reference array.
      */
     public function createDBRef($collection, $document_or_id)
     {
-        if (is_object($document_or_id)) {
-            $id = isset($document_or_id->_id) ? $document_or_id->_id : null;
-//            $id = $document_or_id->_id ?? null;
+        if ($document_or_id instanceof \MongoId) {
+            $id = $document_or_id;
+        } elseif (is_object($document_or_id)) {
+            if (! isset($document_or_id->_id)) {
+                return null;
+            }
+
+            $id = $document_or_id->_id;
         } elseif (is_array($document_or_id)) {
             if (! isset($document_or_id['_id'])) {
                 return null;
@@ -314,57 +294,44 @@ class MongoDB
             $id = $document_or_id;
         }
 
-        return [
-            '$ref' => $collection,
-            '$id' => $id,
-            '$db' => $this->name,
-        ];
+        return MongoDBRef::create($collection, $id, $this->name);
     }
 
 
     /**
-     * (PECL mongo &gt;= 0.9.0)<br/>
      * Fetches the document pointed to by a database reference
+     *
      * @link http://www.php.net/manual/en/mongodb.getdbref.php
      * @param array $ref A database reference.
      * @return array Returns the document pointed to by the reference.
      */
     public function getDBRef(array $ref)
     {
-        $this->notImplemented();
+        return MongoDBRef::get($this, $ref);
     }
 
     /**
-     * (PECL mongo &gt;= 0.9.3)<br/>
      * Runs JavaScript code on the database server.
+     *
      * @link http://www.php.net/manual/en/mongodb.execute.php
      * @param MongoCode|string $code Code to execute.
      * @param array $args [optional] Arguments to be passed to code.
      * @return array Returns the result of the evaluation.
      */
-    public function execute($code, array $args = array())
+    public function execute($code, array $args = [])
     {
-        $this->notImplemented();
+        return $this->command(['eval' => $code, 'args' => $args]);
     }
 
     /**
      * Execute a database command
+     *
      * @link http://www.php.net/manual/en/mongodb.command.php
      * @param array $data The query to send.
-     * @param array() $options [optional] <p>
-     * This parameter is an associative array of the form
-     * <em>array("optionname" =&gt; &lt;boolean&gt;, ...)</em>. Currently
-     * supported options are:
-     * </p><ul>
-     * <li><p><em>"timeout"</em></p><p>Deprecated alias for <em>"socketTimeoutMS"</em>.</p></li>
-     * </ul>
+     * @param array $options
      * @return array Returns database response.
-     * Every database response is always maximum one document,
-     * which means that the result of a database command can never exceed 16MB.
-     * The resulting document's structure depends on the command,
-     * but most results will have the ok field to indicate success or failure and results containing an array of each of the resulting documents.
      */
-    public function command(array $data, $options, &$hash)
+    public function command(array $data, $options = [], &$hash = null)
     {
         try {
             $cursor = new \MongoCommandCursor($this->connection, $this->name, $data);
@@ -381,69 +348,56 @@ class MongoDB
     }
 
     /**
-     * (PECL mongo &gt;= 0.9.5)<br/>
      * Check if there was an error on the most recent db operation performed
+     *
      * @link http://www.php.net/manual/en/mongodb.lasterror.php
      * @return array Returns the error, if there was one.
      */
     public function lastError()
     {
-        $this->notImplemented();
+        return $this->command(array('getLastError' => 1));
     }
 
     /**
-     * (PECL mongo &gt;= 0.9.5)<br/>
      * Checks for the last error thrown during a database operation
+     *
      * @link http://www.php.net/manual/en/mongodb.preverror.php
      * @return array Returns the error and the number of operations ago it occurred.
      */
     public function prevError()
     {
-        $this->notImplemented();
+        return $this->command(array('getPrevError' => 1));
     }
 
     /**
-     * (PECL mongo &gt;= 0.9.5)<br/>
      * Clears any flagged errors on the database
+     *
      * @link http://www.php.net/manual/en/mongodb.reseterror.php
      * @return array Returns the database response.
      */
     public function resetError()
     {
-        $this->notImplemented();
+        return $this->command(array('resetError' => 1));
     }
 
     /**
-     * (PECL mongo &gt;= 0.9.5)<br/>
      * Creates a database error
+     *
      * @link http://www.php.net/manual/en/mongodb.forceerror.php
      * @return boolean Returns the database response.
      */
     public function forceError()
     {
-        $this->notImplemented();
+        return $this->command(array('forceerror' => 1));
     }
 
     /**
-     * (PECL mongo &gt;= 1.0.1)<br/>
      * Log in to this database
+     *
      * @link http://www.php.net/manual/en/mongodb.authenticate.php
      * @param string $username The username.
      * @param string $password The password (in plaintext).
-     * @return array <p>Returns database response. If the login was successful, it will return 1.</p>
-     * <p>
-     * <span style="color: #0000BB">&lt;?php<br></span><span style="color: #007700">array(</span><span style="color: #DD0000">"ok"&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">);<br></span><span style="color: #0000BB">?&gt;</span>
-     * </span>
-     * </code></div>
-     * </div>
-     * </p>
-     * <p> If something went wrong, it will return </p>
-     * <p>
-     * <div class="example-contents">
-     * <div class="phpcode"><code><span style="color: #000000">
-     * <span style="color: #0000BB">&lt;?php<br></span><span style="color: #007700">array(</span><span style="color: #DD0000">"ok"&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">"errmsg"&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #DD0000">"auth&nbsp;fails"</span><span style="color: #007700">);<br></span><span style="color: #0000BB">?&gt;</span></p>
-     *         <p>("auth fails" could be another message, depending on database version and
-     *         what went wrong)</p>
+     * @return array Returns database response. If the login was successful, it will return 1.
      */
     public function authenticate($username, $password)
     {

+ 0 - 16
tests/Alcaeus/MongoDbAdapter/MongoClientTest.php

@@ -79,20 +79,4 @@ class MongoClientTest extends TestCase
         $this->assertTrue($client->setWriteConcern('majority', 100));
         $this->assertSame(['w' => 'majority', 'wtimeout' => 100], $client->getWriteConcern());
     }
-
-    /**
-     * @param array|null $options
-     * @return \MongoClient
-     */
-    protected function getClient($options = null)
-    {
-        $args = ['mongodb://localhost'];
-        if ($options !== null) {
-            $args[] = $options;
-        }
-
-        $reflection = new \ReflectionClass('MongoClient');
-
-        return $reflection->newInstanceArgs($args);
-    }
 }

+ 0 - 18
tests/Alcaeus/MongoDbAdapter/MongoCollectionTest.php

@@ -482,24 +482,6 @@ class MongoCollectionTest extends TestCase
     /**
      * @return \MongoCollection
      */
-    protected function getCollection($name = 'test')
-    {
-        return $this->getDatabase()->selectCollection($name);
-    }
-
-    /**
-     * @return \MongoDB
-     */
-    protected function getDatabase()
-    {
-        $client = new \MongoClient();
-
-        return $client->selectDB('mongo-php-adapter');
-    }
-
-    /**
-     * @return \MongoCollection
-     */
     protected function prepareData()
     {
         $collection = $this->getCollection();

+ 0 - 11
tests/Alcaeus/MongoDbAdapter/MongoCommandCursorTest.php

@@ -52,17 +52,6 @@ class MongoCommandCursorTest extends TestCase
     }
 
     /**
-     * @param string $name
-     * @return \MongoCollection
-     */
-    protected function getCollection($name = 'test')
-    {
-        $client = new \MongoClient();
-
-        return $client->selectCollection('mongo-php-adapter', $name);
-    }
-
-    /**
      * @return \MongoCollection
      */
     protected function prepareData()

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

@@ -248,17 +248,6 @@ class MongoCursorTest extends TestCase
     }
 
     /**
-     * @param string $name
-     * @return \MongoCollection
-     */
-    protected function getCollection($name = 'test')
-    {
-        $client = new \MongoClient();
-
-        return $client->selectCollection('mongo-php-adapter', $name);
-    }
-
-    /**
      * @return \PHPUnit_Framework_MockObject_MockObject
      */
     protected function getCollectionMock()

+ 44 - 6
tests/Alcaeus/MongoDbAdapter/MongoDBRefTest.php

@@ -22,6 +22,33 @@ class MongoDBRefTest extends TestCase
     }
 
     /**
+     * @dataProvider dataCreateThroughMongoDB
+     */
+    public function testCreateThroughMongoDB($expected, $document_or_id)
+    {
+        $ref = $this->getDatabase()->createDBRef('test', $document_or_id);
+
+        $this->assertEquals($expected, $ref);
+    }
+
+    public static function dataCreateThroughMongoDB()
+    {
+        $id = new \MongoId();
+        $validRef = ['$ref' => 'test', '$id' => $id, '$db' => 'mongo-php-adapter'];
+
+        $object = new \stdClass();
+        $object->_id = $id;
+
+        return [
+            'simpleId' => [$validRef, $id],
+            'arrayWithIdProperty' => [$validRef, ['_id' => $id]],
+            'objectWithIdProperty' => [$validRef, $object],
+            'arrayWithoutId' => [null, []],
+            'objectWithoutId' => [null, new \stdClass()],
+        ];
+    }
+
+    /**
      * @dataProvider dataIsRef
      */
     public function testIsRef($expected, $ref)
@@ -49,8 +76,7 @@ class MongoDBRefTest extends TestCase
     {
         $id = new \MongoId();
 
-        $client = new \MongoClient();
-        $db = $client->selectDB('mongo-php-adapter');
+        $db = $this->getDatabase();
 
         $document = ['_id' => $id, 'foo' => 'bar'];
         $db->selectCollection('test')->insert($document);
@@ -60,18 +86,30 @@ class MongoDBRefTest extends TestCase
         $this->assertEquals($document, $fetchedRef);
     }
 
+    public function testGetThroughMongoDB()
+    {
+        $id = new \MongoId();
+
+        $db = $this->getDatabase();
+
+        $document = ['_id' => $id, 'foo' => 'bar'];
+        $db->selectCollection('test')->insert($document);
+
+        $fetchedRef = $db->getDBRef(['$ref' => 'test', '$id' => $id]);
+        $this->assertInternalType('array', $fetchedRef);
+        $this->assertEquals($document, $fetchedRef);
+    }
+
     public function testGetWithNonExistingDocument()
     {
-        $client = new \MongoClient();
-        $db = $client->selectDB('mongo-php-adapter');
+        $db = $this->getDatabase();
 
         $this->assertNull(\MongoDBRef::get($db, ['$ref' => 'test', '$id' => 'foo']));
     }
 
     public function testGetWithInvalidRef()
     {
-        $client = new \MongoClient();
-        $db = $client->selectDB('mongo-php-adapter');
+        $db = $this->getDatabase();
 
         $this->assertNull(\MongoDBRef::get($db, []));
     }

+ 18 - 13
tests/Alcaeus/MongoDbAdapter/MongoDBTest.php

@@ -27,7 +27,7 @@ class MongoDBTest extends TestCase
     public function testCommand()
     {
         $db = $this->getDatabase();
-        $this->assertEquals(['ok' => 1], $db->command(['ping' => 1], [], $hash));
+        $this->assertEquals(['ok' => 1], $db->command(['ping' => 1]));
     }
 
     public function testCommandError()
@@ -39,7 +39,7 @@ class MongoDBTest extends TestCase
             'code' => 13,
         ];
 
-        $this->assertEquals($expected, $db->command(['listDatabases' => 1], [], $hash));
+        $this->assertEquals($expected, $db->command(['listDatabases' => 1]));
     }
 
     public function testReadPreference()
@@ -106,21 +106,26 @@ class MongoDBTest extends TestCase
         $this->assertSame(['w' => 'majority', 'wtimeout' => 100], $database->getWriteConcern());
     }
 
-    /**
-     * @return \MongoDB
-     */
-    protected function getDatabase()
+    public function testProfilingLevel()
     {
-        $client = $this->getClient();
+        $this->assertSame(\MongoDB::PROFILING_OFF, $this->getDatabase()->getProfilingLevel());
+        $this->assertSame(\MongoDB::PROFILING_OFF, $this->getDatabase()->setProfilingLevel(\MongoDB::PROFILING_SLOW));
 
-        return $client->selectDB('mongo-php-adapter');
+        $this->assertSame(\MongoDB::PROFILING_SLOW, $this->getDatabase()->getProfilingLevel());
+        $this->assertSame(\MongoDB::PROFILING_SLOW, $this->getDatabase()->setProfilingLevel(\MongoDB::PROFILING_ON));
+        $this->assertSame(\MongoDB::PROFILING_ON, $this->getDatabase()->getProfilingLevel());
     }
 
-    /**
-     * @return \MongoClient
-     */
-    protected function getClient()
+    public function testForceError()
     {
-        return new \MongoClient();
+        $result = $this->getDatabase()->forceError();
+        $this->assertSame(0, $result['ok']);
+    }
+
+    public function testExecute()
+    {
+        $db = $this->getDatabase();
+        $this->getCollection()->insert(['foo' => 'bar']);
+        $this->assertEquals(['ok' => 1, 'retval' => 1], $db->execute("return db.test.count();"));
     }
 }

+ 43 - 0
tests/Alcaeus/MongoDbAdapter/TestCase.php

@@ -19,4 +19,47 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
         $client = new Client('mongodb://localhost', ['connect' => true]);
         return $client->selectDatabase('mongo-php-adapter');
     }
+
+    /**
+     * @param array|null $options
+     * @return \MongoClient
+     */
+    protected function getClient($options = null)
+    {
+        $args = ['mongodb://localhost'];
+        if ($options !== null) {
+            $args[] = $options;
+        }
+
+        $reflection = new \ReflectionClass('MongoClient');
+
+        return $reflection->newInstanceArgs($args);
+    }
+
+    /**
+     * @param \MongoClient|null $client
+     * @return \MongoDB
+     */
+    protected function getDatabase(\MongoClient $client = null)
+    {
+        if ($client === null) {
+            $client = $this->getClient();
+        }
+
+        return $client->selectDB('mongo-php-adapter');
+    }
+
+    /**
+     * @param string $name
+     * @param \MongoDB|null $database
+     * @return \MongoCollection
+     */
+    protected function getCollection($name = 'test', \MongoDB $database = null)
+    {
+        if ($database === null) {
+            $database = $this->getDatabase();
+        }
+
+        return $database->selectCollection($name);
+    }
 }