Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

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

   1  <?php
   2  /*
   3   * Copyright 2015-2017 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\DeleteResult;
  21  use MongoDB\Driver\BulkWrite as Bulk;
  22  use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
  23  use MongoDB\Driver\Server;
  24  use MongoDB\Driver\Session;
  25  use MongoDB\Driver\WriteConcern;
  26  use MongoDB\Exception\InvalidArgumentException;
  27  use MongoDB\Exception\UnsupportedException;
  28  use function is_array;
  29  use function is_object;
  30  use function is_string;
  31  use function MongoDB\server_supports_feature;
  32  
  33  /**
  34   * Operation for the delete command.
  35   *
  36   * This class is used internally by the DeleteMany and DeleteOne operation
  37   * classes.
  38   *
  39   * @internal
  40   * @see http://docs.mongodb.org/manual/reference/command/delete/
  41   */
  42  class Delete implements Executable, Explainable
  43  {
  44      /** @var integer */
  45      private static $wireVersionForCollation = 5;
  46  
  47      /** @var int */
  48      private static $wireVersionForHintServerSideError = 5;
  49  
  50      /** @var string */
  51      private $databaseName;
  52  
  53      /** @var string */
  54      private $collectionName;
  55  
  56      /** @var array|object */
  57      private $filter;
  58  
  59      /** @var integer */
  60      private $limit;
  61  
  62      /** @var array */
  63      private $options;
  64  
  65      /**
  66       * Constructs a delete command.
  67       *
  68       * Supported options:
  69       *
  70       *  * collation (document): Collation specification.
  71       *
  72       *    This is not supported for server versions < 3.4 and will result in an
  73       *    exception at execution time if used.
  74       *
  75       *  * hint (string|document): The index to use. Specify either the index
  76       *    name as a string or the index key pattern as a document. If specified,
  77       *    then the query system will only consider plans using the hinted index.
  78       *
  79       *    This is not supported for server versions < 4.4 and will result in an
  80       *    exception at execution time if used.
  81       *
  82       *  * session (MongoDB\Driver\Session): Client session.
  83       *
  84       *    Sessions are not supported for server versions < 3.6.
  85       *
  86       *  * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
  87       *
  88       * @param string       $databaseName   Database name
  89       * @param string       $collectionName Collection name
  90       * @param array|object $filter         Query by which to delete documents
  91       * @param integer      $limit          The number of matching documents to
  92       *                                     delete. Must be 0 or 1, for all or a
  93       *                                     single document, respectively.
  94       * @param array        $options        Command options
  95       * @throws InvalidArgumentException for parameter/option parsing errors
  96       */
  97      public function __construct($databaseName, $collectionName, $filter, $limit, array $options = [])
  98      {
  99          if (! is_array($filter) && ! is_object($filter)) {
 100              throw InvalidArgumentException::invalidType('$filter', $filter, 'array or object');
 101          }
 102  
 103          if ($limit !== 0 && $limit !== 1) {
 104              throw new InvalidArgumentException('$limit must be 0 or 1');
 105          }
 106  
 107          if (isset($options['collation']) && ! is_array($options['collation']) && ! is_object($options['collation'])) {
 108              throw InvalidArgumentException::invalidType('"collation" option', $options['collation'], 'array or object');
 109          }
 110  
 111          if (isset($options['hint']) && ! is_string($options['hint']) && ! is_array($options['hint']) && ! is_object($options['hint'])) {
 112              throw InvalidArgumentException::invalidType('"hint" option', $options['hint'], ['string', 'array', 'object']);
 113          }
 114  
 115          if (isset($options['session']) && ! $options['session'] instanceof Session) {
 116              throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class);
 117          }
 118  
 119          if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) {
 120              throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class);
 121          }
 122  
 123          if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) {
 124              unset($options['writeConcern']);
 125          }
 126  
 127          $this->databaseName = (string) $databaseName;
 128          $this->collectionName = (string) $collectionName;
 129          $this->filter = $filter;
 130          $this->limit = $limit;
 131          $this->options = $options;
 132      }
 133  
 134      /**
 135       * Execute the operation.
 136       *
 137       * @see Executable::execute()
 138       * @param Server $server
 139       * @return DeleteResult
 140       * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
 141       */
 142      public function execute(Server $server)
 143      {
 144          if (isset($this->options['collation']) && ! server_supports_feature($server, self::$wireVersionForCollation)) {
 145              throw UnsupportedException::collationNotSupported();
 146          }
 147  
 148          /* Server versions >= 3.4.0 raise errors for unknown update
 149           * options. For previous versions, the CRUD spec requires a client-side
 150           * error. */
 151          if (isset($this->options['hint']) && ! server_supports_feature($server, self::$wireVersionForHintServerSideError)) {
 152              throw UnsupportedException::hintNotSupported();
 153          }
 154  
 155          $inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction();
 156          if ($inTransaction && isset($this->options['writeConcern'])) {
 157              throw UnsupportedException::writeConcernNotSupportedInTransaction();
 158          }
 159  
 160          $bulk = new Bulk();
 161          $bulk->delete($this->filter, $this->createDeleteOptions());
 162  
 163          $writeResult = $server->executeBulkWrite($this->databaseName . '.' . $this->collectionName, $bulk, $this->createExecuteOptions());
 164  
 165          return new DeleteResult($writeResult);
 166      }
 167  
 168      public function getCommandDocument(Server $server)
 169      {
 170          $cmd = ['delete' => $this->collectionName, 'deletes' => [['q' => $this->filter] + $this->createDeleteOptions()]];
 171  
 172          if (isset($this->options['writeConcern'])) {
 173              $cmd['writeConcern'] = $this->options['writeConcern'];
 174          }
 175  
 176          return $cmd;
 177      }
 178  
 179      /**
 180       * Create options for the delete command.
 181       *
 182       * Note that these options are different from the bulk write options, which
 183       * are created in createExecuteOptions().
 184       *
 185       * @return array
 186       */
 187      private function createDeleteOptions()
 188      {
 189          $deleteOptions = ['limit' => $this->limit];
 190  
 191          if (isset($this->options['collation'])) {
 192              $deleteOptions['collation'] = (object) $this->options['collation'];
 193          }
 194  
 195          if (isset($this->options['hint'])) {
 196              $deleteOptions['hint'] = $this->options['hint'];
 197          }
 198  
 199          return $deleteOptions;
 200      }
 201  
 202      /**
 203       * Create options for executing the bulk write.
 204       *
 205       * @see http://php.net/manual/en/mongodb-driver-server.executebulkwrite.php
 206       * @return array
 207       */
 208      private function createExecuteOptions()
 209      {
 210          $options = [];
 211  
 212          if (isset($this->options['session'])) {
 213              $options['session'] = $this->options['session'];
 214          }
 215  
 216          if (isset($this->options['writeConcern'])) {
 217              $options['writeConcern'] = $this->options['writeConcern'];
 218          }
 219  
 220          return $options;
 221      }
 222  }