Exemple #1
0
 /**
  * Constructor.
  *
  * @param array $index Index specification
  *
  * @throws InvalidArgumentException
  */
 public function __construct(array $index)
 {
     if (!isset($index['key'])) {
         throw new InvalidArgumentException('Required "key" document is missing from index specification');
     }
     if (!is_array($index['key']) && !is_object($index['key'])) {
         throw InvalidArgumentException::invalidType('"key" option', $index['key'], 'array or object');
     }
     foreach ($index['key'] as $fieldName => $order) {
         if (!is_int($order) && !is_float($order) && !is_string($order)) {
             throw InvalidArgumentException::invalidType(sprintf('order value for "%s" field within "key" option', $fieldName), $order, 'numeric or string');
         }
     }
     if (!isset($index['ns'])) {
         throw new InvalidArgumentException('Required "ns" option is missing from index specification');
     }
     if (!is_string($index['ns'])) {
         throw InvalidArgumentException::invalidType('"ns" option', $index['ns'], 'string');
     }
     if (!isset($index['name'])) {
         $index['name'] = Functions::generateIndexName($index['key']);
     }
     if (!is_string($index['name'])) {
         throw InvalidArgumentException::invalidType('"name" option', $index['name'], 'string');
     }
     $this->index = $index;
 }
 /**
  * Constructs a findAndModify command for updating a document.
  *
  * Supported options:
  *
  *  * bypassDocumentValidation (boolean): If true, allows the write to opt
  *    out of document level validation.
  *
  *  * maxTimeMS (integer): The maximum amount of time to allow the query to
  *    run.
  *
  *  * projection (document): Limits the fields to return for the matching
  *    document.
  *
  *  * returnDocument (enum): Whether to return the document before or after
  *    the update is applied. Must be either
  *    FindOneAndUpdate::RETURN_DOCUMENT_BEFORE or
  *    FindOneAndUpdate::RETURN_DOCUMENT_AFTER. The default is
  *    FindOneAndUpdate::RETURN_DOCUMENT_BEFORE.
  *
  *  * sort (document): Determines which document the operation modifies if
  *    the query selects multiple documents.
  *
  *  * upsert (boolean): When true, a new document is created if no document
  *    matches the query. The default is false.
  *
  *  * writeConcern (MongoDB\Driver\WriteConcern): Write concern. This option
  *    is only supported for server versions >= 3.2.
  *
  * @param string       $databaseName Database name
  * @param string       $collectionName Collection name
  * @param array|object $filter Query by which to filter documents
  * @param array|object $update Update to apply to the matched document
  * @param array        $options Command options
  *
  * @throws InvalidArgumentException
  */
 public function __construct($databaseName, $collectionName, $filter, $update, array $options = [])
 {
     if (!is_array($filter) && !is_object($filter)) {
         throw InvalidArgumentException::invalidType('$filter', $filter, 'array or object');
     }
     if (!is_array($update) && !is_object($update)) {
         throw InvalidArgumentException::invalidType('$update', $update, 'array or object');
     }
     if (!Functions::isFirstKeyOperator($update)) {
         throw new InvalidArgumentException('First key in $update argument is not an update operator');
     }
     $options += ['returnDocument' => self::RETURN_DOCUMENT_BEFORE, 'upsert' => false];
     if (isset($options['projection']) && !is_array($options['projection']) && !is_object($options['projection'])) {
         throw InvalidArgumentException::invalidType('"projection" option', $options['projection'], 'array or object');
     }
     if (!is_integer($options['returnDocument'])) {
         throw InvalidArgumentException::invalidType('"returnDocument" option', $options['returnDocument'], 'integer');
     }
     if ($options['returnDocument'] !== self::RETURN_DOCUMENT_AFTER && $options['returnDocument'] !== self::RETURN_DOCUMENT_BEFORE) {
         throw new InvalidArgumentException('Invalid value for "returnDocument" option: ' . $options['returnDocument']);
     }
     if (isset($options['projection'])) {
         $options['fields'] = $options['projection'];
     }
     $options['new'] = $options['returnDocument'] === self::RETURN_DOCUMENT_AFTER;
     unset($options['projection'], $options['returnDocument']);
     $this->findAndModify = new FindAndModify($databaseName, $collectionName, ['query' => $filter, 'update' => $update] + $options);
 }
Exemple #3
0
 /**
  * Constructs an update command.
  *
  * Supported options:
  *
  *  * bypassDocumentValidation (boolean): If true, allows the write to opt
  *    out of document level validation.
  *
  *  * upsert (boolean): When true, a new document is created if no document
  *    matches the query. The default is false.
  *
  *  * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
  *
  * @param string       $databaseName Database name
  * @param string       $collectionName Collection name
  * @param array|object $filter Query by which to filter documents
  * @param array|object $update Update to apply to the matched document
  * @param array        $options Command options
  *
  * @throws InvalidArgumentException
  */
 public function __construct($databaseName, $collectionName, $filter, $update, array $options = [])
 {
     if (!is_array($update) && !is_object($update)) {
         throw InvalidArgumentException::invalidType('$update', $update, 'array or object');
     }
     if (!Functions::isFirstKeyOperator($update)) {
         throw new InvalidArgumentException('First key in $update argument is not an update operator');
     }
     $this->update = new Update($databaseName, $collectionName, $filter, $update, ['multi' => false] + $options);
 }
Exemple #4
0
 /**
  * Execute the operation.
  *
  * For servers < 2.6, this will actually perform an insert operation on the
  * database's "system.indexes" collection.
  *
  * @see Executable::execute()
  *
  * @param Server $server
  *
  * @return string[] The names of the created indexes
  */
 public function execute(Server $server)
 {
     if (Functions::serverSupportsFeature($server, self::$wireVersionForCommand)) {
         $this->executeCommand($server);
     } else {
         $this->executeLegacy($server);
     }
     return array_map(function (IndexInput $index) {
         return (string) $index;
     }, $this->indexes);
 }
Exemple #5
0
 /**
  * Execute the operation.
  *
  * @see Executable::execute()
  *
  * @param Server $server
  *
  * @return InsertOneResult
  */
 public function execute(Server $server)
 {
     $options = [];
     if (isset($this->options['bypassDocumentValidation']) && Functions::serverSupportsFeature($server, self::$wireVersionForDocumentLevelValidation)) {
         $options['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
     }
     $bulk = new Bulk($options);
     $insertedId = $bulk->insert($this->document);
     if ($insertedId === null) {
         $insertedId = Functions::extractIdFromInsertedDocument($this->document);
     }
     $writeConcern = isset($this->options['writeConcern']) ? $this->options['writeConcern'] : null;
     $writeResult = $server->executeBulkWrite($this->databaseName . '.' . $this->collectionName, $bulk, $writeConcern);
     return new InsertOneResult($writeResult, $insertedId);
 }
Exemple #6
0
 /**
  * Constructs a writable GridFS stream.
  *
  * Supported options:
  *
  *  * _id (mixed): File document identifier. Defaults to a new ObjectId.
  *
  *  * aliases (array of strings): DEPRECATED An array of aliases.
  *    Applications wishing to store aliases should add an aliases field to
  *    the metadata document instead.
  *
  *  * chunkSizeBytes (integer): The chunk size in bytes. Defaults to
  *    261120 (i.e. 255 KiB).
  *
  *  * contentType (string): DEPRECATED content type to be stored with the
  *    file. This information should now be added to the metadata.
  *
  *  * metadata (document): User data for the "metadata" field of the files
  *    collection document.
  *
  * @param CollectionWrapper $collectionWrapper GridFS collection wrapper
  * @param string            $filename Filename
  * @param array             $options Upload options
  *
  * @throws InvalidArgumentException
  */
 public function __construct(CollectionWrapper $collectionWrapper, $filename, array $options = [])
 {
     $options += ['_id' => new ObjectId(), 'chunkSizeBytes' => self::$defaultChunkSizeBytes];
     if (isset($options['aliases']) && !Functions::isStringArray($options['aliases'])) {
         throw InvalidArgumentException::invalidType('"aliases" option', $options['aliases'], 'array of strings');
     }
     if (isset($options['chunkSizeBytes']) && !is_integer($options['chunkSizeBytes'])) {
         throw InvalidArgumentException::invalidType('"chunkSizeBytes" option', $options['chunkSizeBytes'], 'integer');
     }
     if (isset($options['contentType']) && !is_string($options['contentType'])) {
         throw InvalidArgumentException::invalidType('"contentType" option', $options['contentType'], 'string');
     }
     if (isset($options['metadata']) && !is_array($options['metadata']) && !is_object($options['metadata'])) {
         throw InvalidArgumentException::invalidType('"metadata" option', $options['metadata'], 'array or object');
     }
     $this->chunkSize = $options['chunkSizeBytes'];
     $this->collectionWrapper = $collectionWrapper;
     $this->buffer = fopen('php://temp', 'w+');
     $this->ctx = hash_init('md5');
     $this->file = ['_id' => $options['_id'], 'chunkSize' => $this->chunkSize, 'filename' => (string) $filename, 'uploadDate' => new UTCDateTime(floor(microtime(true) * 1000))] + array_intersect_key($options, ['aliases' => 1, 'contentType' => 1, 'metadata' => 1]);
 }
 /**
  * Execute the operation.
  *
  * @see Executable::execute()
  *
  * @param Server $server
  *
  * @return CollectionInfoIterator
  */
 public function execute(Server $server)
 {
     return Functions::serverSupportsFeature($server, self::$wireVersionForCommand) ? $this->executeCommand($server) : $this->executeLegacy($server);
 }
Exemple #8
0
 /**
  * Finds a single document and updates it, returning either the original or
  * the updated document.
  *
  * The document to return may be null if no document matched the filter. By
  * default, the original document is returned. Specify
  * FindOneAndUpdate::RETURN_DOCUMENT_AFTER for the "returnDocument" option
  * to return the updated document.
  *
  * Note: BSON deserialization of the returned document does not yet support
  * a custom type map (depends on: https://jira.mongodb.org/browse/PHPC-314).
  *
  * @see FindOneAndReplace::__construct() for supported options
  * @see http://docs.mongodb.org/manual/reference/command/findAndModify/
  *
  * @param array|object $filter Query by which to filter documents
  * @param array|object $update Update to apply to the matched document
  * @param array        $options Command options
  *
  * @return object|null
  */
 public function findOneAndUpdate($filter, $update, array $options = [])
 {
     $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
     if (!isset($options['writeConcern']) && Functions::serverSupportsFeature($server, self::$wireVersionForFindAndModifyWriteConcern)) {
         $options['writeConcern'] = $this->writeConcern;
     }
     $operation = new FindOneAndUpdate($this->databaseName, $this->collectionName, $filter, $update, $options);
     return $operation->execute($server);
 }
Exemple #9
0
 /**
  * Create the distinct command.
  *
  * @param Server $server
  *
  * @return Command
  */
 private function createCommand(Server $server)
 {
     $cmd = ['distinct' => $this->collectionName, 'key' => $this->fieldName];
     if (!empty($this->filter)) {
         $cmd['query'] = (object) $this->filter;
     }
     if (isset($this->options['maxTimeMS'])) {
         $cmd['maxTimeMS'] = $this->options['maxTimeMS'];
     }
     if (isset($this->options['readConcern']) && Functions::serverSupportsFeature($server, self::$wireVersionForReadConcern)) {
         $cmd['readConcern'] = Functions::readConcernAsDocument($this->options['readConcern']);
     }
     return new Command($cmd);
 }
Exemple #10
0
 /**
  * Create the count command.
  *
  * @param Server $server
  *
  * @return Command
  */
 private function createCommand(Server $server)
 {
     $cmd = ['count' => $this->collectionName];
     if (!empty($this->filter)) {
         $cmd['query'] = (object) $this->filter;
     }
     foreach (['hint', 'limit', 'maxTimeMS', 'skip'] as $option) {
         if (isset($this->options[$option])) {
             $cmd[$option] = $this->options[$option];
         }
     }
     if (isset($this->options['readConcern']) && Functions::serverSupportsFeature($server, self::$wireVersionForReadConcern)) {
         $cmd['readConcern'] = Functions::readConcernAsDocument($this->options['readConcern']);
     }
     return new Command($cmd);
 }
Exemple #11
0
 /**
  * Execute the operation.
  *
  * @see Executable::execute()
  *
  * @param Server $server
  *
  * @return UpdateResult
  */
 public function execute(Server $server)
 {
     $updateOptions = ['multi' => $this->options['multi'], 'upsert' => $this->options['upsert']];
     $bulkOptions = [];
     if (isset($this->options['bypassDocumentValidation']) && Functions::serverSupportsFeature($server, self::$wireVersionForDocumentLevelValidation)) {
         $bulkOptions['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
     }
     $bulk = new Bulk($bulkOptions);
     $bulk->update($this->filter, $this->update, $updateOptions);
     $writeConcern = isset($this->options['writeConcern']) ? $this->options['writeConcern'] : null;
     $writeResult = $server->executeBulkWrite($this->databaseName . '.' . $this->collectionName, $bulk, $writeConcern);
     return new UpdateResult($writeResult);
 }
Exemple #12
0
 /**
  * Execute the operation.
  *
  * @see Executable::execute()
  *
  * @param Server $server
  *
  * @return BulkWriteResult
  */
 public function execute(Server $server)
 {
     $options = ['ordered' => $this->options['ordered']];
     if (isset($this->options['bypassDocumentValidation']) && Functions::serverSupportsFeature($server, self::$wireVersionForDocumentLevelValidation)) {
         $options['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
     }
     $bulk = new Bulk($options);
     $insertedIds = [];
     foreach ($this->operations as $i => $operation) {
         $type = key($operation);
         $args = current($operation);
         switch ($type) {
             case self::DELETE_MANY:
             case self::DELETE_ONE:
                 $bulk->delete($args[0], $args[1]);
                 break;
             case self::INSERT_ONE:
                 $insertedId = $bulk->insert($args[0]);
                 if ($insertedId !== null) {
                     $insertedIds[$i] = $insertedId;
                 } else {
                     $insertedIds[$i] = Functions::extractIdFromInsertedDocument($args[0]);
                 }
                 break;
             case self::REPLACE_ONE:
             case self::UPDATE_MANY:
             case self::UPDATE_ONE:
                 $bulk->update($args[0], $args[1], $args[2]);
         }
     }
     $writeConcern = isset($this->options['writeConcern']) ? $this->options['writeConcern'] : null;
     $writeResult = $server->executeBulkWrite($this->databaseName . '.' . $this->collectionName, $bulk, $writeConcern);
     return new BulkWriteResult($writeResult, $insertedIds);
 }
Exemple #13
0
 /**
  * Create the aggregate command.
  *
  * @param Server  $server
  * @param boolean $isCursorSupported
  *
  * @return Command
  */
 private function createCommand(Server $server, $isCursorSupported)
 {
     $cmd = ['aggregate' => $this->collectionName, 'pipeline' => $this->pipeline];
     // Servers < 2.6 do not support any command options
     if (!$isCursorSupported) {
         return new Command($cmd);
     }
     $cmd['allowDiskUse'] = $this->options['allowDiskUse'];
     if (isset($this->options['bypassDocumentValidation']) && Functions::serverSupportsFeature($server, self::$wireVersionForDocumentLevelValidation)) {
         $cmd['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
     }
     if (isset($this->options['maxTimeMS'])) {
         $cmd['maxTimeMS'] = $this->options['maxTimeMS'];
     }
     if (isset($this->options['readConcern']) && Functions::serverSupportsFeature($server, self::$wireVersionForReadConcern)) {
         $cmd['readConcern'] = Functions::readConcernAsDocument($this->options['readConcern']);
     }
     if ($this->options['useCursor']) {
         $cmd['cursor'] = isset($this->options["batchSize"]) ? ['batchSize' => $this->options["batchSize"]] : new stdClass();
     }
     return new Command($cmd);
 }
Exemple #14
0
 /**
  * Create the findAndModify command.
  *
  * @param Server $server
  *
  * @return Command
  */
 private function createCommand(Server $server)
 {
     $cmd = ['findAndModify' => $this->collectionName];
     if ($this->options['remove']) {
         $cmd['remove'] = true;
     } else {
         $cmd['new'] = $this->options['new'];
         $cmd['upsert'] = $this->options['upsert'];
     }
     foreach (['fields', 'query', 'sort', 'update'] as $option) {
         if (isset($this->options[$option])) {
             $cmd[$option] = (object) $this->options[$option];
         }
     }
     if (isset($this->options['maxTimeMS'])) {
         $cmd['maxTimeMS'] = $this->options['maxTimeMS'];
     }
     if (isset($this->options['bypassDocumentValidation']) && Functions::serverSupportsFeature($server, self::$wireVersionForDocumentLevelValidation)) {
         $cmd['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
     }
     if (isset($this->options['writeConcern']) && Functions::serverSupportsFeature($server, self::$wireVersionForWriteConcern)) {
         $cmd['writeConcern'] = $this->options['writeConcern'];
     }
     return new Command($cmd);
 }