Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401]

   1  <?php
   2  /*
   3   * Copyright 2018 MongoDB, Inc.
   4   *
   5   * Licensed under the Apache License, Version 2.0 (the "License");
   6   * you may not use this file except in compliance with the License.
   7   * You may obtain a copy of the License at
   8   *
   9   *   http://www.apache.org/licenses/LICENSE-2.0
  10   *
  11   * Unless required by applicable law or agreed to in writing, software
  12   * distributed under the License is distributed on an "AS IS" BASIS,
  13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14   * See the License for the specific language governing permissions and
  15   * limitations under the License.
  16   */
  17  
  18  namespace MongoDB\Operation;
  19  
  20  use MongoDB\Driver\Command;
  21  use MongoDB\Driver\ReadPreference;
  22  use MongoDB\Driver\Server;
  23  use MongoDB\Driver\Session;
  24  use MongoDB\Exception\InvalidArgumentException;
  25  use MongoDB\Exception\UnsupportedException;
  26  use function current;
  27  use function is_array;
  28  use function is_string;
  29  use function MongoDB\server_supports_feature;
  30  
  31  /**
  32   * Operation for the explain command.
  33   *
  34   * @api
  35   * @see \MongoDB\Collection::explain()
  36   * @see http://docs.mongodb.org/manual/reference/command/explain/
  37   */
  38  class Explain implements Executable
  39  {
  40      const VERBOSITY_ALL_PLANS = 'allPlansExecution';
  41      const VERBOSITY_EXEC_STATS = 'executionStats';
  42      const VERBOSITY_QUERY = 'queryPlanner';
  43  
  44      /** @var integer */
  45      private static $wireVersionForDistinct = 4;
  46  
  47      /** @var integer */
  48      private static $wireVersionForFindAndModify = 4;
  49  
  50      /** @var string */
  51      private $databaseName;
  52  
  53      /** @var Explainable */
  54      private $explainable;
  55  
  56      /** @var array */
  57      private $options;
  58  
  59      /**
  60       * Constructs an explain command for explainable operations.
  61       *
  62       * Supported options:
  63       *
  64       *  * readPreference (MongoDB\Driver\ReadPreference): Read preference.
  65       *
  66       *  * session (MongoDB\Driver\Session): Client session.
  67       *
  68       *  * typeMap (array): Type map for BSON deserialization. This will be used
  69       *    used for the returned command result document.
  70       *
  71       *  * verbosity (string): The mode in which the explain command will be run.
  72       *
  73       * @param string      $databaseName Database name
  74       * @param Explainable $explainable  Operation to explain
  75       * @param array       $options      Command options
  76       * @throws InvalidArgumentException for parameter/option parsing errors
  77       */
  78      public function __construct($databaseName, Explainable $explainable, array $options = [])
  79      {
  80          if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) {
  81              throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], ReadPreference::class);
  82          }
  83  
  84          if (isset($options['session']) && ! $options['session'] instanceof Session) {
  85              throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class);
  86          }
  87  
  88          if (isset($options['typeMap']) && ! is_array($options['typeMap'])) {
  89              throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array');
  90          }
  91  
  92          if (isset($options['verbosity']) && ! is_string($options['verbosity'])) {
  93              throw InvalidArgumentException::invalidType('"verbosity" option', $options['verbosity'], 'string');
  94          }
  95  
  96          $this->databaseName = $databaseName;
  97          $this->explainable = $explainable;
  98          $this->options = $options;
  99      }
 100  
 101      public function execute(Server $server)
 102      {
 103          if ($this->explainable instanceof Distinct && ! server_supports_feature($server, self::$wireVersionForDistinct)) {
 104              throw UnsupportedException::explainNotSupported();
 105          }
 106  
 107          if ($this->isFindAndModify($this->explainable) && ! server_supports_feature($server, self::$wireVersionForFindAndModify)) {
 108              throw UnsupportedException::explainNotSupported();
 109          }
 110  
 111          $cmd = ['explain' => $this->explainable->getCommandDocument($server)];
 112  
 113          if (isset($this->options['verbosity'])) {
 114              $cmd['verbosity'] = $this->options['verbosity'];
 115          }
 116  
 117          $cursor = $server->executeCommand($this->databaseName, new Command($cmd), $this->createOptions());
 118  
 119          if (isset($this->options['typeMap'])) {
 120              $cursor->setTypeMap($this->options['typeMap']);
 121          }
 122  
 123          return current($cursor->toArray());
 124      }
 125  
 126      /**
 127       * Create options for executing the command.
 128       *
 129       * @see http://php.net/manual/en/mongodb-driver-server.executecommand.php
 130       * @return array
 131       */
 132      private function createOptions()
 133      {
 134          $options = [];
 135  
 136          if (isset($this->options['readPreference'])) {
 137              $options['readPreference'] = $this->options['readPreference'];
 138          }
 139  
 140          if (isset($this->options['session'])) {
 141              $options['session'] = $this->options['session'];
 142          }
 143  
 144          return $options;
 145      }
 146  
 147      private function isFindAndModify($explainable)
 148      {
 149          if ($explainable instanceof FindAndModify || $explainable instanceof FindOneAndDelete || $explainable instanceof FindOneAndReplace || $explainable instanceof FindOneAndUpdate) {
 150              return true;
 151          }
 152  
 153          return false;
 154      }
 155  }