MDL-54592 cachestore_mongodb: MongoDB cache store use new driver.
[moodle.git] / cache / stores / mongodb / lib.php
index 0f1d352..302828f 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
+require_once('MongoDB/functions.php');
+
 /**
  * The MongoDB Cache store.
  *
- * This cache store uses the MongoDB Native Driver.
+ * This cache store uses the MongoDB Native Driver and the MongoDB PHP Library.
  * For installation instructions have a look at the following two links:
- *  - {@link http://www.php.net/manual/en/mongo.installation.php}
- *  - {@link http://www.mongodb.org/display/DOCS/PHP+Language+Center}
+ *  - {@link http://php.net/manual/en/set.mongodb.php}
+ *  - {@link https://docs.mongodb.com/ecosystem/drivers/php/}
  *
  * @copyright  2012 Sam Hemelryk
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@@ -65,19 +67,19 @@ class cachestore_mongodb extends cache_store implements cache_is_configurable {
 
     /**
      * The Connection object
-     * @var Mongo
+     * @var MongoDB/Client
      */
     protected $connection = false;
 
     /**
      * The Database Object
-     * @var MongoDB
+     * @var MongoDB/Database
      */
     protected $database;
 
     /**
      * The Collection object
-     * @var MongoCollection
+     * @var MongoDB/Collection
      */
     protected $collection;
 
@@ -105,14 +107,6 @@ class cachestore_mongodb extends cache_store implements cache_is_configurable {
      */
     protected $isready = false;
 
-    /**
-     * Set to true if the Mongo extension is < version 1.3.
-     * If this is the case we must use the legacy Mongo class instead of MongoClient.
-     * Mongo is backwards compatible, although obviously deprecated.
-     * @var bool
-     */
-    protected $legacymongo = false;
-
     /**
      * Constructs a new instance of the Mongo store.
      *
@@ -148,16 +142,11 @@ class cachestore_mongodb extends cache_store implements cache_is_configurable {
             $this->extendedmode = $configuration['extendedmode'];
         }
 
-        // Test if the MongoClient class exists, if not we need to switch to legacy classes.
-        $this->legacymongo = (!class_exists('MongoClient'));
-
-        // MongoClient from Mongo 1.3 onwards. Mongo for earlier versions.
-        $class = ($this->legacymongo) ? 'Mongo' : 'MongoClient';
         try {
-            $this->connection = new $class($this->server, $this->options);
+            $this->connection = new MongoDB\Client($this->server, $this->options);
             $this->isready = true;
-        } catch (MongoConnectionException $e) {
-            // We only want to catch MongoConnectionExceptions here.
+        } catch (MongoDB\Driver\Exception\RuntimeException $e) {
+            // We only want to catch RuntimeException here.
         }
     }
 
@@ -166,7 +155,7 @@ class cachestore_mongodb extends cache_store implements cache_is_configurable {
      * @return bool
      */
     public static function are_requirements_met() {
-        return class_exists('MongoClient') || class_exists('Mongo');
+        return version_compare(phpversion('mongodb'), '1.5', 'ge');
     }
 
     /**
@@ -203,17 +192,18 @@ class cachestore_mongodb extends cache_store implements cache_is_configurable {
         if ($this->is_initialised()) {
             throw new coding_exception('This mongodb instance has already been initialised.');
         }
-        $this->database = $this->connection->selectDB($this->databasename);
+        $this->database = $this->connection->selectDatabase($this->databasename);
         $this->definitionhash = 'm'.$definition->generate_definition_hash();
         $this->collection = $this->database->selectCollection($this->definitionhash);
 
         $options = array('name' => 'idx_key');
-        if ($this->legacymongo) {
-            $options['safe'] = $this->usesafe;
-        } else {
-            $options['w'] = $this->usesafe ? 1 : 0;
-        }
-        $this->collection->ensureIndex(array('key' => 1), $options);
+
+        $w = $this->usesafe ? 1 : 0;
+        $wc = new MongoDB\Driver\WriteConcern($w);
+
+        $options['writeConcern'] = $wc;
+
+        $this->collection->createIndex(array('key' => 1), $options);
     }
 
     /**
@@ -221,7 +211,7 @@ class cachestore_mongodb extends cache_store implements cache_is_configurable {
      * @return bool
      */
     public function is_initialised() {
-        return ($this->database instanceof MongoDB);
+        return ($this->database instanceof MongoDB\Database);
     }
 
     /**
@@ -319,24 +309,20 @@ class cachestore_mongodb extends cache_store implements cache_is_configurable {
         }
         $record['data'] = serialize($data);
         $options = array('upsert' => true);
-        if ($this->legacymongo) {
-            $options['safe'] = $this->usesafe;
-        } else {
-            $options['w'] = $this->usesafe ? 1 : 0;
-        }
+
+        $w = $this->usesafe ? 1 : 0;
+        $wc = new MongoDB\Driver\WriteConcern($w);
+
+        $options['writeConcern'] = $wc;
+
         $this->delete($key);
-        $result = $this->collection->insert($record, $options);
-        if ($result === true) {
-            // Safe mode is off.
-            return true;
-        } else if (is_array($result)) {
-            if (empty($result['ok']) || isset($result['err'])) {
-                return false;
-            }
-            return true;
+        try {
+            $this->collection->insertOne($record, $options);
+        } catch (MongoDB\Exception\Exception $e) {
+            return false;
         }
-        // Who knows?
-        return false;
+
+        return true;
     }
 
     /**
@@ -373,27 +359,23 @@ class cachestore_mongodb extends cache_store implements cache_is_configurable {
             $criteria = $key;
         }
         $options = array('justOne' => false);
-        if ($this->legacymongo) {
-            $options['safe'] = $this->usesafe;
-        } else {
-            $options['w'] = $this->usesafe ? 1 : 0;
-        }
-        $result = $this->collection->remove($criteria, $options);
-
-        if ($result === true) {
-            // Safe mode.
-            return true;
-        } else if (is_array($result)) {
-            if (empty($result['ok']) || isset($result['err'])) {
-                return false;
-            } else if (empty($result['n'])) {
-                // Nothing was removed.
-                return false;
-            }
-            return true;
+
+        $w = $this->usesafe ? 1 : 0;
+        $wc = new MongoDB\Driver\WriteConcern($w);
+
+        $options['writeConcern'] = $wc;
+
+        try {
+            $result = $this->collection->deleteOne($criteria, $options);
+        } catch (\MongoDB\Exception $e) {
+            return false;
+        }
+
+        if (empty($result->getDeletedCount())) {
+            return false;
         }
-        // Who knows?
-        return false;
+
+        return true;
     }
 
     /**
@@ -502,16 +484,14 @@ class cachestore_mongodb extends cache_store implements cache_is_configurable {
             $connection = $this->connection;
         } else {
             try {
-                // MongoClient from Mongo 1.3 onwards. Mongo for earlier versions.
-                $class = ($this->legacymongo) ? 'Mongo' : 'MongoClient';
-                $connection = new $class($this->server, $this->options);
-            } catch (MongoConnectionException $e) {
-                // We only want to catch MongoConnectionExceptions here.
+                $connection = new MongoDB\Client($this->server, $this->options);
+            } catch (MongoDB\Driver\Exception\RuntimeException $e) {
+                // We only want to catch RuntimeException here.
                 // If the server cannot be connected to we cannot clean it.
                 return;
             }
         }
-        $database = $connection->selectDB($this->databasename);
+        $database = $connection->selectDatabase($this->databasename);
         $database->drop();
         $connection = null;
         $database = null;
@@ -564,7 +544,6 @@ class cachestore_mongodb extends cache_store implements cache_is_configurable {
         return $store;
     }
 
-
     /**
      * Generates an instance of the cache store that can be used for testing.
      *
@@ -577,7 +556,7 @@ class cachestore_mongodb extends cache_store implements cache_is_configurable {
 
         // If the configuration is not defined correctly, return only the configuration know about.
         if (defined('TEST_CACHESTORE_MONGODB_TESTSERVER')) {
-            $configuration['servers'] = explode("\n", TEST_CACHESTORE_MONGODB_TESTSERVER);
+            $configuration['server'] = TEST_CACHESTORE_MONGODB_TESTSERVER;
         }
 
         return $configuration;