/** * Constructs a count command. * * Supported options: * * * hint (string|document): The index to use. If a document, it will be * interpretted as an index specification and a name will be generated. * * * limit (integer): The maximum number of documents to count. * * * maxTimeMS (integer): The maximum amount of time to allow the query to * run. * * * readConcern (MongoDB\Driver\ReadConcern): Read concern. * * For servers < 3.2, this option is ignored as read concern is not * available. * * * readPreference (MongoDB\Driver\ReadPreference): Read preference. * * * skip (integer): The number of documents to skip before returning the * documents. * * @param string $databaseName Database name * @param string $collectionName Collection name * @param array|object $filter Query by which to filter documents * @param array $options Command options * @throws InvalidArgumentException */ public function __construct($databaseName, $collectionName, $filter = [], array $options = []) { if (!is_array($filter) && !is_object($filter)) { throw InvalidArgumentException::invalidType('$filter', $filter, 'array or object'); } if (isset($options['hint'])) { if (is_array($options['hint']) || is_object($options['hint'])) { $options['hint'] = \MongoDB\generate_index_name($options['hint']); } if (!is_string($options['hint'])) { throw InvalidArgumentException::invalidType('"hint" option', $options['hint'], 'string or array or object'); } } if (isset($options['limit']) && !is_integer($options['limit'])) { throw InvalidArgumentException::invalidType('"limit" option', $options['limit'], 'integer'); } if (isset($options['maxTimeMS']) && !is_integer($options['maxTimeMS'])) { throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); } if (isset($options['readConcern']) && !$options['readConcern'] instanceof ReadConcern) { throw InvalidArgumentException::invalidType('"readConcern" option', $options['readConcern'], 'MongoDB\\Driver\\ReadConcern'); } if (isset($options['readPreference']) && !$options['readPreference'] instanceof ReadPreference) { throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], 'MongoDB\\Driver\\ReadPreference'); } if (isset($options['skip']) && !is_integer($options['skip'])) { throw InvalidArgumentException::invalidType('"skip" option', $options['skip'], 'integer'); } $this->databaseName = (string) $databaseName; $this->collectionName = (string) $collectionName; $this->filter = $filter; $this->options = $options; }
/** * 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'] = \MongoDB\generate_index_name($index['key']); } if (!is_string($index['name'])) { throw InvalidArgumentException::invalidType('"name" option', $index['name'], 'string'); } $this->index = $index; }
/** * Constructs a findAndModify command for replacing 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 RETURN_DOCUMENT_BEFORE or * RETURN_DOCUMENT_AFTER. The default is 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 $replacement Replacement document * @param array $options Command options * @throws InvalidArgumentException */ public function __construct($databaseName, $collectionName, $filter, $replacement, array $options = []) { if (!is_array($filter) && !is_object($filter)) { throw InvalidArgumentException::invalidType('$filter', $filter, 'array or object'); } if (!is_array($replacement) && !is_object($replacement)) { throw InvalidArgumentException::invalidType('$replacement', $replacement, 'array or object'); } if (\MongoDB\is_first_key_operator($replacement)) { throw new InvalidArgumentException('First key in $replacement argument is 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' => $replacement] + $options); }
/** * Constructs a update command. * * Supported options: * * * bypassDocumentValidation (boolean): If true, allows the write to opt * out of document level validation. * * * multi (boolean): When true, updates all documents matching the query. * This option cannot be true if the $update argument is a replacement * document (i.e. contains no update operators). The default is false. * * * 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 delete documents * @param array|object $update Update to apply to the matched * document(s) or a replacement 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', $filter, 'array or object'); } $options += ['multi' => false, 'upsert' => false]; if (isset($options['bypassDocumentValidation']) && !is_bool($options['bypassDocumentValidation'])) { throw InvalidArgumentException::invalidType('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean'); } if (!is_bool($options['multi'])) { throw InvalidArgumentException::invalidType('"multi" option', $options['multi'], 'boolean'); } if ($options['multi'] && !\MongoDB\is_first_key_operator($update)) { throw new InvalidArgumentException('"multi" option cannot be true if $update is a replacement document'); } if (!is_bool($options['upsert'])) { throw InvalidArgumentException::invalidType('"upsert" option', $options['upsert'], 'boolean'); } if (isset($options['writeConcern']) && !$options['writeConcern'] instanceof WriteConcern) { throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], 'MongoDB\\Driver\\WriteConcern'); } $this->databaseName = (string) $databaseName; $this->collectionName = (string) $collectionName; $this->filter = $filter; $this->update = $update; $this->options = $options; }
/** * Constructs an insert command. * * Supported options: * * * bypassDocumentValidation (boolean): If true, allows the write to opt * out of document level validation. * * * ordered (boolean): If true, when an insert fails, return without * performing the remaining writes. If false, when a write fails, * continue with the remaining writes, if any. The default is true. * * * writeConcern (MongoDB\Driver\WriteConcern): Write concern. * * @param string $databaseName Database name * @param string $collectionName Collection name * @param array[]|object[] $documents List of documents to insert * @param array $options Command options * @throws InvalidArgumentException */ public function __construct($databaseName, $collectionName, array $documents, array $options = []) { if (empty($documents)) { throw new InvalidArgumentException('$documents is empty'); } $expectedIndex = 0; foreach ($documents as $i => $document) { if ($i !== $expectedIndex) { throw new InvalidArgumentException(sprintf('$documents is not a list (unexpected index: "%s")', $i)); } if (!is_array($document) && !is_object($document)) { throw InvalidArgumentException::invalidType(sprintf('$documents[%d]', $i), $document, 'array or object'); } $expectedIndex += 1; } $options += ['ordered' => true]; if (isset($options['bypassDocumentValidation']) && !is_bool($options['bypassDocumentValidation'])) { throw InvalidArgumentException::invalidType('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean'); } if (!is_bool($options['ordered'])) { throw InvalidArgumentException::invalidType('"ordered" option', $options['ordered'], 'boolean'); } if (isset($options['writeConcern']) && !$options['writeConcern'] instanceof WriteConcern) { throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], 'MongoDB\\Driver\\WriteConcern'); } $this->databaseName = (string) $databaseName; $this->collectionName = (string) $collectionName; $this->documents = $documents; $this->options = $options; }
/** * Constructs a listDatabases command. * * Supported options: * * * maxTimeMS (integer): The maximum amount of time to allow the query to * run. * * @param array $options Command options * @throws InvalidArgumentException */ public function __construct(array $options = []) { if (isset($options['maxTimeMS']) && !is_integer($options['maxTimeMS'])) { throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); } $this->options = $options; }
/** * Constructs a dropDatabase command. * * Supported options: * * * typeMap (array): Type map for BSON deserialization. This will be used * for the returned command result document. * * @param string $databaseName Database name * @param array $options Command options */ public function __construct($databaseName, array $options = []) { if (isset($options['typeMap']) && !is_array($options['typeMap'])) { throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); } $this->databaseName = (string) $databaseName; $this->options = $options; }
/** * Constructs a listIndexes command. * * Supported options: * * * maxTimeMS (integer): The maximum amount of time to allow the query to * run. * * @param string $databaseName Database name * @param string $collectionName Collection name * @param array $options Command options * @throws InvalidArgumentException */ public function __construct($databaseName, $collectionName, array $options = []) { if (isset($options['maxTimeMS']) && !is_integer($options['maxTimeMS'])) { throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); } $this->databaseName = (string) $databaseName; $this->collectionName = (string) $collectionName; $this->options = $options; }
/** * 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 $replacement Replacement document * @param array $options Command options * @throws InvalidArgumentException */ public function __construct($databaseName, $collectionName, $filter, $replacement, array $options = []) { if (!is_array($replacement) && !is_object($replacement)) { throw InvalidArgumentException::invalidType('$replacement', $replacement, 'array or object'); } if (\MongoDB\is_first_key_operator($replacement)) { throw new InvalidArgumentException('First key in $replacement argument is an update operator'); } $this->update = new Update($databaseName, $collectionName, $filter, $replacement, ['multi' => false] + $options); }
/** * 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 documents * @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 (!\MongoDB\is_first_key_operator($update)) { throw new InvalidArgumentException('First key in $update argument is not an update operator'); } $this->update = new Update($databaseName, $collectionName, $filter, $update, ['multi' => true] + $options); }
/** * Constructs a new Client instance. * * This is the preferred class for connecting to a MongoDB server or * cluster of servers. It serves as a gateway for accessing individual * databases and collections. * * Supported driver-specific options: * * * typeMap (array): Default type map for cursors and BSON documents. * * Other options are documented in MongoDB\Driver\Manager::__construct(). * * @see http://docs.mongodb.org/manual/reference/connection-string/ * @see http://php.net/manual/en/mongodb-driver-manager.construct.php * @see http://php.net/manual/en/mongodb.persistence.php#mongodb.persistence.typemaps * @param string $uri MongoDB connection string * @param array $uriOptions Additional connection string options * @param array $driverOptions Driver-specific options * @throws InvalidArgumentException */ public function __construct($uri = 'mongodb://localhost:27017', array $uriOptions = [], array $driverOptions = []) { $driverOptions += ['typeMap' => self::$defaultTypeMap]; if (isset($driverOptions['typeMap']) && !is_array($driverOptions['typeMap'])) { throw InvalidArgumentException::invalidType('"typeMap" driver option', $driverOptions['typeMap'], 'array'); } $this->manager = new Manager($uri, $uriOptions, $driverOptions); $this->uri = (string) $uri; $this->typeMap = isset($driverOptions['typeMap']) ? $driverOptions['typeMap'] : null; }
/** * Return whether the first key in the document starts with a "$" character. * * This is used for differentiating update and replacement documents. * * @internal * @param array|object $document Update or replacement document * @return boolean * @throws InvalidArgumentException */ function is_first_key_operator($document) { if (is_object($document)) { $document = get_object_vars($document); } if (!is_array($document)) { throw InvalidArgumentException::invalidType('$document', $document, 'array or object'); } $firstKey = (string) key($document); return isset($firstKey[0]) && $firstKey[0] == '$'; }
/** * Constructs a dropIndexes command. * * @param string $databaseName Database name * @param string $collectionName Collection name * @param string $indexName Index name (use "*" to drop all indexes) * @param array $options Command options * @throws InvalidArgumentException */ public function __construct($databaseName, $collectionName, $indexName, array $options = []) { $indexName = (string) $indexName; if ($indexName === '') { throw new InvalidArgumentException('$indexName cannot be empty'); } if (isset($options['typeMap']) && !is_array($options['typeMap'])) { throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); } $this->databaseName = (string) $databaseName; $this->collectionName = (string) $collectionName; $this->indexName = $indexName; $this->options = $options; }
/** * Constructs a findAndModify command for deleting a document. * * Supported options: * * * maxTimeMS (integer): The maximum amount of time to allow the query to * run. * * * projection (document): Limits the fields to return for the matching * document. * * * sort (document): Determines which document the operation modifies if * the query selects multiple documents. * * * 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 $options Command options * @throws InvalidArgumentException */ public function __construct($databaseName, $collectionName, $filter, array $options = []) { if (!is_array($filter) && !is_object($filter)) { throw InvalidArgumentException::invalidType('$filter', $filter, 'array or object'); } if (isset($options['projection']) && !is_array($options['projection']) && !is_object($options['projection'])) { throw InvalidArgumentException::invalidType('"projection" option', $options['projection'], 'array or object'); } if (isset($options['projection'])) { $options['fields'] = $options['projection']; } unset($options['projection']); $this->findAndModify = new FindAndModify($databaseName, $collectionName, ['query' => $filter, 'remove' => true] + $options); }
/** * Constructs a command. * * Supported options: * * * readPreference (MongoDB\Driver\ReadPreference): The read preference to * use when executing the command. This may be used when issuing the * command to a replica set or mongos node to ensure that the driver sets * the wire protocol accordingly or adds the read preference to the * command document, respectively. * * * typeMap (array): Type map for BSON deserialization. This will be * applied to the returned Cursor (it is not sent to the server). * * @param string $databaseName Database name * @param array|object $command Command document * @param array $options Options for command execution * @throws InvalidArgumentException */ public function __construct($databaseName, $command, array $options = []) { if (!is_array($command) && !is_object($command)) { throw InvalidArgumentException::invalidType('$command', $command, 'array or object'); } if (isset($options['readPreference']) && !$options['readPreference'] instanceof ReadPreference) { throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], 'MongoDB\\Driver\\ReadPreference'); } if (isset($options['typeMap']) && !is_array($options['typeMap'])) { throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); } $this->databaseName = (string) $databaseName; $this->command = $command instanceof Command ? $command : new Command($command); $this->options = $options; }
/** * Constructs an insert command. * * Supported options: * * * bypassDocumentValidation (boolean): If true, allows the write to opt * out of document level validation. * * * writeConcern (MongoDB\Driver\WriteConcern): Write concern. * * @param string $databaseName Database name * @param string $collectionName Collection name * @param array|object $document Document to insert * @param array $options Command options * @throws InvalidArgumentException */ public function __construct($databaseName, $collectionName, $document, array $options = []) { if (!is_array($document) && !is_object($document)) { throw InvalidArgumentException::invalidType('$document', $document, 'array or object'); } if (isset($options['bypassDocumentValidation']) && !is_bool($options['bypassDocumentValidation'])) { throw InvalidArgumentException::invalidType('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean'); } if (isset($options['writeConcern']) && !$options['writeConcern'] instanceof WriteConcern) { throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], 'MongoDB\\Driver\\WriteConcern'); } $this->databaseName = (string) $databaseName; $this->collectionName = (string) $collectionName; $this->document = $document; $this->options = $options; }
/** * Constructs a delete command. * * Supported options: * * * writeConcern (MongoDB\Driver\WriteConcern): Write concern. * * @param string $databaseName Database name * @param string $collectionName Collection name * @param array|object $filter Query by which to delete documents * @param integer $limit The number of matching documents to * delete. Must be 0 or 1, for all or a * single document, respectively. * @param array $options Command options * @throws InvalidArgumentException */ public function __construct($databaseName, $collectionName, $filter, $limit, array $options = []) { if (!is_array($filter) && !is_object($filter)) { throw InvalidArgumentException::invalidType('$filter', $filter, 'array or object'); } if ($limit !== 0 && $limit !== 1) { throw new InvalidArgumentException('$limit must be 0 or 1'); } if (isset($options['writeConcern']) && !$options['writeConcern'] instanceof WriteConcern) { throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], 'MongoDB\\Driver\\WriteConcern'); } $this->databaseName = (string) $databaseName; $this->collectionName = (string) $collectionName; $this->filter = $filter; $this->limit = $limit; $this->options = $options; }
/** * 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']) && !\MongoDB\is_string_array($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]); }
/** * Constructs a GridFS bucket. * * Supported options: * * * bucketName (string): The bucket name, which will be used as a prefix * for the files and chunks collections. Defaults to "fs". * * * chunkSizeBytes (integer): The chunk size in bytes. Defaults to * 261120 (i.e. 255 KiB). * * * readPreference (MongoDB\Driver\ReadPreference): Read preference. * * * writeConcern (MongoDB\Driver\WriteConcern): Write concern. * * @param Manager $manager Manager instance from the driver * @param string $databaseName Database name * @param array $options Bucket options * @throws InvalidArgumentException */ public function __construct(Manager $manager, $databaseName, array $options = []) { $options += ['bucketName' => 'fs', 'chunkSizeBytes' => 261120]; if (isset($options['bucketName']) && !is_string($options['bucketName'])) { throw InvalidArgumentException::invalidType('"bucketName" option', $options['bucketName'], 'string'); } if (isset($options['chunkSizeBytes']) && !is_integer($options['chunkSizeBytes'])) { throw InvalidArgumentException::invalidType('"chunkSizeBytes" option', $options['chunkSizeBytes'], 'integer'); } if (isset($options['readPreference']) && !$options['readPreference'] instanceof ReadPreference) { throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], 'MongoDB\\Driver\\ReadPreference'); } if (isset($options['writeConcern']) && !$options['writeConcern'] instanceof WriteConcern) { throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], 'MongoDB\\Driver\\WriteConcern'); } $this->databaseName = (string) $databaseName; $this->options = $options; $collectionOptions = array_intersect_key($options, ['readPreference' => 1, 'writeConcern' => 1]); $this->collectionsWrapper = new GridFSCollectionsWrapper($manager, $databaseName, $options['bucketName'], $collectionOptions); $this->registerStreamWrapper($manager); }
/** * Constructs a createIndexes command. * * @param string $databaseName Database name * @param string $collectionName Collection name * @param array[] $indexes List of index specifications * @throws InvalidArgumentException */ public function __construct($databaseName, $collectionName, array $indexes) { if (empty($indexes)) { throw new InvalidArgumentException('$indexes is empty'); } $expectedIndex = 0; foreach ($indexes as $i => $index) { if ($i !== $expectedIndex) { throw new InvalidArgumentException(sprintf('$indexes is not a list (unexpected index: "%s")', $i)); } if (!is_array($index)) { throw InvalidArgumentException::invalidType(sprintf('$index[%d]', $i), $index, 'array'); } if (!isset($index['ns'])) { $index['ns'] = $databaseName . '.' . $collectionName; } $this->indexes[] = new IndexInput($index); $expectedIndex += 1; } $this->databaseName = (string) $databaseName; $this->collectionName = (string) $collectionName; }
/** * Constructs new Database instance. * * This class provides methods for database-specific operations and serves * as a gateway for accessing collections. * * Supported options: * * * readConcern (MongoDB\Driver\ReadConcern): The default read concern to * use for database operations and selected collections. Defaults to the * Manager's read concern. * * * readPreference (MongoDB\Driver\ReadPreference): The default read * preference to use for database operations and selected collections. * Defaults to the Manager's read preference. * * * typeMap (array): Default type map for cursors and BSON documents. * * * writeConcern (MongoDB\Driver\WriteConcern): The default write concern * to use for database operations and selected collections. Defaults to * the Manager's write concern. * * @param Manager $manager Manager instance from the driver * @param string $databaseName Database name * @param array $options Database options * @throws InvalidArgumentException */ public function __construct(Manager $manager, $databaseName, array $options = []) { if (strlen($databaseName) < 1) { throw new InvalidArgumentException('$databaseName is invalid: ' . $databaseName); } if (isset($options['readConcern']) && !$options['readConcern'] instanceof ReadConcern) { throw InvalidArgumentException::invalidType('"readConcern" option', $options['readConcern'], 'MongoDB\\Driver\\ReadConcern'); } if (isset($options['readPreference']) && !$options['readPreference'] instanceof ReadPreference) { throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], 'MongoDB\\Driver\\ReadPreference'); } if (isset($options['typeMap']) && !is_array($options['typeMap'])) { throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); } if (isset($options['writeConcern']) && !$options['writeConcern'] instanceof WriteConcern) { throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], 'MongoDB\\Driver\\WriteConcern'); } $this->manager = $manager; $this->databaseName = (string) $databaseName; $this->readConcern = isset($options['readConcern']) ? $options['readConcern'] : $this->manager->getReadConcern(); $this->readPreference = isset($options['readPreference']) ? $options['readPreference'] : $this->manager->getReadPreference(); $this->typeMap = isset($options['typeMap']) ? $options['typeMap'] : self::$defaultTypeMap; $this->writeConcern = isset($options['writeConcern']) ? $options['writeConcern'] : $this->manager->getWriteConcern(); }
/** * Constructs a findAndModify command. * * Supported options: * * * bypassDocumentValidation (boolean): If true, allows the write to opt * out of document level validation. * * * fields (document): Limits the fields to return for the matching * document. * * * maxTimeMS (integer): The maximum amount of time to allow the query to * run. * * * new (boolean): When true, returns the modified document rather than * the original. This option is ignored for remove operations. The * The default is false. * * * query (document): Query by which to filter documents. * * * remove (boolean): When true, removes the matched document. This option * cannot be true if the update option is set. The default is false. * * * sort (document): Determines which document the operation modifies if * the query selects multiple documents. * * * update (document): Update or replacement to apply to the matched * document. This option cannot be set if the remove option is true. * * * upsert (boolean): When true, a new document is created if no document * matches the query. This option is ignored for remove operations. 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 $options Command options * @throws InvalidArgumentException */ public function __construct($databaseName, $collectionName, array $options) { $options += ['new' => false, 'remove' => false, 'upsert' => false]; if (isset($options['bypassDocumentValidation']) && !is_bool($options['bypassDocumentValidation'])) { throw InvalidArgumentException::invalidType('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean'); } if (isset($options['fields']) && !is_array($options['fields']) && !is_object($options['fields'])) { throw InvalidArgumentException::invalidType('"fields" option', $options['fields'], 'array or object'); } if (isset($options['maxTimeMS']) && !is_integer($options['maxTimeMS'])) { throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); } if (!is_bool($options['new'])) { throw InvalidArgumentException::invalidType('"new" option', $options['new'], 'boolean'); } if (isset($options['query']) && !is_array($options['query']) && !is_object($options['query'])) { throw InvalidArgumentException::invalidType('"query" option', $options['query'], 'array or object'); } if (!is_bool($options['remove'])) { throw InvalidArgumentException::invalidType('"remove" option', $options['remove'], 'boolean'); } if (isset($options['sort']) && !is_array($options['sort']) && !is_object($options['sort'])) { throw InvalidArgumentException::invalidType('"sort" option', $options['sort'], 'array or object'); } if (isset($options['update']) && !is_array($options['update']) && !is_object($options['update'])) { throw InvalidArgumentException::invalidType('"update" option', $options['update'], 'array or object'); } if (isset($options['writeConcern']) && !$options['writeConcern'] instanceof WriteConcern) { throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], 'MongoDB\\Driver\\WriteConcern'); } if (!is_bool($options['upsert'])) { throw InvalidArgumentException::invalidType('"upsert" option', $options['upsert'], 'boolean'); } if (!(isset($options['update']) xor $options['remove'])) { throw new InvalidArgumentException('The "remove" option must be true or an "update" document must be specified, but not both'); } $this->databaseName = (string) $databaseName; $this->collectionName = (string) $collectionName; $this->options = $options; }
/** * Constructs a find command. * * Supported options: * * * allowPartialResults (boolean): Get partial results from a mongos if * some shards are inaccessible (instead of throwing an error). * * * batchSize (integer): The number of documents to return per batch. * * * comment (string): Attaches a comment to the query. If "$comment" also * exists in the modifiers document, this option will take precedence. * * * cursorType (enum): Indicates the type of cursor to use. Must be either * NON_TAILABLE, TAILABLE, or TAILABLE_AWAIT. The default is * NON_TAILABLE. * * * limit (integer): The maximum number of documents to return. * * * maxTimeMS (integer): The maximum amount of time to allow the query to * run. If "$maxTimeMS" also exists in the modifiers document, this * option will take precedence. * * * modifiers (document): Meta-operators modifying the output or behavior * of a query. * * * noCursorTimeout (boolean): The server normally times out idle cursors * after an inactivity period (10 minutes) to prevent excess memory use. * Set this option to prevent that. * * * oplogReplay (boolean): Internal replication use only. The driver * should not set this. * * * projection (document): Limits the fields to return for the matching * document. * * * readConcern (MongoDB\Driver\ReadConcern): Read concern. * * For servers < 3.2, this option is ignored as read concern is not * available. * * * readPreference (MongoDB\Driver\ReadPreference): Read preference. * * * skip (integer): The number of documents to skip before returning. * * * sort (document): The order in which to return matching documents. If * "$orderby" also exists in the modifiers document, this option will * take precedence. * * * typeMap (array): Type map for BSON deserialization. This will be * applied to the returned Cursor (it is not sent to the server). * * @param string $databaseName Database name * @param string $collectionName Collection name * @param array|object $filter Query by which to filter documents * @param array $options Command options * @throws InvalidArgumentException */ public function __construct($databaseName, $collectionName, $filter, array $options = []) { if (!is_array($filter) && !is_object($filter)) { throw InvalidArgumentException::invalidType('$filter', $filter, 'array or object'); } if (isset($options['allowPartialResults']) && !is_bool($options['allowPartialResults'])) { throw InvalidArgumentException::invalidType('"allowPartialResults" option', $options['allowPartialResults'], 'boolean'); } if (isset($options['batchSize']) && !is_integer($options['batchSize'])) { throw InvalidArgumentException::invalidType('"batchSize" option', $options['batchSize'], 'integer'); } if (isset($options['comment']) && !is_string($options['comment'])) { throw InvalidArgumentException::invalidType('"comment" option', $options['comment'], 'comment'); } if (isset($options['cursorType'])) { if (!is_integer($options['cursorType'])) { throw InvalidArgumentException::invalidType('"cursorType" option', $options['cursorType'], 'integer'); } if ($options['cursorType'] !== self::NON_TAILABLE && $options['cursorType'] !== self::TAILABLE && $options['cursorType'] !== self::TAILABLE_AWAIT) { throw new InvalidArgumentException('Invalid value for "cursorType" option: ' . $options['cursorType']); } } if (isset($options['limit']) && !is_integer($options['limit'])) { throw InvalidArgumentException::invalidType('"limit" option', $options['limit'], 'integer'); } if (isset($options['maxTimeMS']) && !is_integer($options['maxTimeMS'])) { throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); } if (isset($options['modifiers']) && !is_array($options['modifiers']) && !is_object($options['modifiers'])) { throw InvalidArgumentException::invalidType('"modifiers" option', $options['modifiers'], 'array or object'); } if (isset($options['noCursorTimeout']) && !is_bool($options['noCursorTimeout'])) { throw InvalidArgumentException::invalidType('"noCursorTimeout" option', $options['noCursorTimeout'], 'boolean'); } if (isset($options['oplogReplay']) && !is_bool($options['oplogReplay'])) { throw InvalidArgumentException::invalidType('"oplogReplay" option', $options['oplogReplay'], 'boolean'); } if (isset($options['projection']) && !is_array($options['projection']) && !is_object($options['projection'])) { throw InvalidArgumentException::invalidType('"projection" option', $options['projection'], 'array or object'); } if (isset($options['readConcern']) && !$options['readConcern'] instanceof ReadConcern) { throw InvalidArgumentException::invalidType('"readConcern" option', $options['readConcern'], 'MongoDB\\Driver\\ReadConcern'); } if (isset($options['readPreference']) && !$options['readPreference'] instanceof ReadPreference) { throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], 'MongoDB\\Driver\\ReadPreference'); } if (isset($options['skip']) && !is_integer($options['skip'])) { throw InvalidArgumentException::invalidType('"skip" option', $options['skip'], 'integer'); } if (isset($options['sort']) && !is_array($options['sort']) && !is_object($options['sort'])) { throw InvalidArgumentException::invalidType('"sort" option', $options['sort'], 'array or object'); } if (isset($options['typeMap']) && !is_array($options['typeMap'])) { throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); } $this->databaseName = (string) $databaseName; $this->collectionName = (string) $collectionName; $this->filter = $filter; $this->options = $options; }
/** * Constructs a create command. * * Supported options: * * * autoIndexId (boolean): Specify false to disable the automatic creation * of an index on the _id field. For replica sets, this option cannot be * false. The default is true. * * * capped (boolean): Specify true to create a capped collection. If set, * the size option must also be specified. The default is false. * * * flags (integer): Options for the MMAPv1 storage engine only. Must be a * bitwise combination CreateCollection::USE_POWER_OF_2_SIZES and * CreateCollection::NO_PADDING. The default is * CreateCollection::USE_POWER_OF_2_SIZES. * * * indexOptionDefaults (document): Default configuration for indexes when * creating the collection. * * * max (integer): The maximum number of documents allowed in the capped * collection. The size option takes precedence over this limit. * * * maxTimeMS (integer): The maximum amount of time to allow the query to * run. * * * size (integer): The maximum number of bytes for a capped collection. * * * storageEngine (document): Storage engine options. * * * typeMap (array): Type map for BSON deserialization. This will only be * used for the returned command result document. * * * validationAction (string): Validation action. * * * validationLevel (string): Validation level. * * * validator (document): Validation rules or expressions. * * @see http://source.wiredtiger.com/2.4.1/struct_w_t___s_e_s_s_i_o_n.html#a358ca4141d59c345f401c58501276bbb * @see https://docs.mongodb.org/manual/core/document-validation/ * @param string $databaseName Database name * @param string $collectionName Collection name * @param array $options Command options * @throws InvalidArgumentException */ public function __construct($databaseName, $collectionName, array $options = []) { if (isset($options['autoIndexId']) && !is_bool($options['autoIndexId'])) { throw InvalidArgumentException::invalidType('"autoIndexId" option', $options['autoIndexId'], 'boolean'); } if (isset($options['capped']) && !is_bool($options['capped'])) { throw InvalidArgumentException::invalidType('"capped" option', $options['capped'], 'boolean'); } if (isset($options['flags']) && !is_integer($options['flags'])) { throw InvalidArgumentException::invalidType('"flags" option', $options['flags'], 'integer'); } if (isset($options['indexOptionDefaults']) && !is_array($options['indexOptionDefaults']) && !is_object($options['indexOptionDefaults'])) { throw InvalidArgumentException::invalidType('"indexOptionDefaults" option', $options['indexOptionDefaults'], 'array or object'); } if (isset($options['max']) && !is_integer($options['max'])) { throw InvalidArgumentException::invalidType('"max" option', $options['max'], 'integer'); } if (isset($options['maxTimeMS']) && !is_integer($options['maxTimeMS'])) { throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); } if (isset($options['size']) && !is_integer($options['size'])) { throw InvalidArgumentException::invalidType('"size" option', $options['size'], 'integer'); } if (isset($options['storageEngine']) && !is_array($options['storageEngine']) && !is_object($options['storageEngine'])) { throw InvalidArgumentException::invalidType('"storageEngine" option', $options['storageEngine'], 'array or object'); } if (isset($options['typeMap']) && !is_array($options['typeMap'])) { throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); } if (isset($options['validationAction']) && !is_string($options['validationAction'])) { throw InvalidArgumentException::invalidType('"validationAction" option', $options['validationAction'], 'string'); } if (isset($options['validationLevel']) && !is_string($options['validationLevel'])) { throw InvalidArgumentException::invalidType('"validationLevel" option', $options['validationLevel'], 'string'); } if (isset($options['validator']) && !is_array($options['validator']) && !is_object($options['validator'])) { throw InvalidArgumentException::invalidType('"validator" option', $options['validator'], 'array or object'); } $this->databaseName = (string) $databaseName; $this->collectionName = (string) $collectionName; $this->options = $options; }
/** * Constructs an aggregate command. * * Supported options: * * * allowDiskUse (boolean): Enables writing to temporary files. When set * to true, aggregation stages can write data to the _tmp sub-directory * in the dbPath directory. The default is false. * * * batchSize (integer): The number of documents to return per batch. * * * bypassDocumentValidation (boolean): If true, allows the write to opt * out of document level validation. This only applies when the $out * stage is specified. * * For servers < 3.2, this option is ignored as document level validation * is not available. * * * maxTimeMS (integer): The maximum amount of time to allow the query to * run. * * * readConcern (MongoDB\Driver\ReadConcern): Read concern. Note that a * "majority" read concern is not compatible with the $out stage. * * For servers < 3.2, this option is ignored as read concern is not * available. * * * readPreference (MongoDB\Driver\ReadPreference): Read preference. * * * typeMap (array): Type map for BSON deserialization. This will be * applied to the returned Cursor (it is not sent to the server). * * This is not supported for inline aggregation results (i.e. useCursor * option is false or the server versions < 2.6). * * * useCursor (boolean): Indicates whether the command will request that * the server provide results using a cursor. The default is true. * * For servers < 2.6, this option is ignored as aggregation cursors are * not available. * * For servers >= 2.6, this option allows users to turn off cursors if * necessary to aid in mongod/mongos upgrades. * * @param string $databaseName Database name * @param string $collectionName Collection name * @param array $pipeline List of pipeline operations * @param array $options Command options * @throws InvalidArgumentException */ public function __construct($databaseName, $collectionName, array $pipeline, array $options = []) { if (empty($pipeline)) { throw new InvalidArgumentException('$pipeline is empty'); } $expectedIndex = 0; foreach ($pipeline as $i => $operation) { if ($i !== $expectedIndex) { throw new InvalidArgumentException(sprintf('$pipeline is not a list (unexpected index: "%s")', $i)); } if (!is_array($operation) && !is_object($operation)) { throw InvalidArgumentException::invalidType(sprintf('$pipeline[%d]', $i), $operation, 'array or object'); } $expectedIndex += 1; } $options += ['allowDiskUse' => false, 'useCursor' => true]; if (!is_bool($options['allowDiskUse'])) { throw InvalidArgumentException::invalidType('"allowDiskUse" option', $options['allowDiskUse'], 'boolean'); } if (isset($options['batchSize']) && !is_integer($options['batchSize'])) { throw InvalidArgumentException::invalidType('"batchSize" option', $options['batchSize'], 'integer'); } if (isset($options['bypassDocumentValidation']) && !is_bool($options['bypassDocumentValidation'])) { throw InvalidArgumentException::invalidType('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean'); } if (isset($options['maxTimeMS']) && !is_integer($options['maxTimeMS'])) { throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); } if (isset($options['readConcern']) && !$options['readConcern'] instanceof ReadConcern) { throw InvalidArgumentException::invalidType('"readConcern" option', $options['readConcern'], 'MongoDB\\Driver\\ReadConcern'); } if (isset($options['readPreference']) && !$options['readPreference'] instanceof ReadPreference) { throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], 'MongoDB\\Driver\\ReadPreference'); } if (isset($options['typeMap']) && !is_array($options['typeMap'])) { throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); } if (!is_bool($options['useCursor'])) { throw InvalidArgumentException::invalidType('"useCursor" option', $options['useCursor'], 'boolean'); } if (isset($options['batchSize']) && !$options['useCursor']) { throw new InvalidArgumentException('"batchSize" option should not be used if "useCursor" is false'); } if (isset($options['typeMap']) && !$options['useCursor']) { throw new InvalidArgumentException('"typeMap" option should not be used if "useCursor" is false'); } $this->databaseName = (string) $databaseName; $this->collectionName = (string) $collectionName; $this->pipeline = $pipeline; $this->options = $options; }
/** * Returns information for all collections in this database by querying the * "system.namespaces" collection (MongoDB <3.0). * * @param Server $server * @return CollectionInfoLegacyIterator * @throws InvalidArgumentException if filter.name is not a string. */ private function executeLegacy(Server $server) { $filter = empty($this->options['filter']) ? [] : (array) $this->options['filter']; if (array_key_exists('name', $filter)) { if (!is_string($filter['name'])) { throw InvalidArgumentException::invalidType('filter name for MongoDB <3.0', $filter['name'], 'string'); } $filter['name'] = $this->databaseName . '.' . $filter['name']; } $options = isset($this->options['maxTimeMS']) ? ['modifiers' => ['$maxTimeMS' => $this->options['maxTimeMS']]] : []; $cursor = $server->executeQuery($this->databaseName . '.system.namespaces', new Query($filter, $options)); $cursor->setTypeMap(['root' => 'array', 'document' => 'array']); return new CollectionInfoLegacyIterator($cursor); }
/** * Writes the contents of a readable stream to a GridFS file. * * Supported options: * * * _id (mixed): File document identifier. Defaults to a new ObjectId. * * * chunkSizeBytes (integer): The chunk size in bytes. Defaults to the * bucket's chunk size. * * * metadata (document): User data for the "metadata" field of the files * collection document. * * @param string $filename Filename * @param resource $source Readable stream * @param array $options Stream options * @return ObjectId ID of the newly created GridFS file * @throws InvalidArgumentException if $source is not a stream */ public function uploadFromStream($filename, $source, array $options = []) { if (!is_resource($source) || get_resource_type($source) != "stream") { throw InvalidArgumentException::invalidType('$source', $source, 'resource'); } $destination = $this->openUploadStream($filename, $options); stream_copy_to_stream($source, $destination); return $this->getIdFromStream($destination); }
/** * Constructs a bulk write operation. * * Example array structure for all supported operation types: * * [ * [ 'deleteOne' => [ $filter ] ], * [ 'deleteMany' => [ $filter ] ], * [ 'insertOne' => [ $document ] ], * [ 'replaceOne' => [ $filter, $replacement, $options ] ], * [ 'updateMany' => [ $filter, $update, $options ] ], * [ 'updateOne' => [ $filter, $update, $options ] ], * ] * * Arguments correspond to the respective Operation classes; however, the * writeConcern option is specified for the top-level bulk write operation * instead of each individual operations. * * Supported options for replaceOne, updateMany, and updateOne operations: * * * upsert (boolean): When true, a new document is created if no document * matches the query. The default is false. * * Supported options for the bulk write operation: * * * bypassDocumentValidation (boolean): If true, allows the write to opt * out of document level validation. * * * ordered (boolean): If true, when an insert fails, return without * performing the remaining writes. If false, when a write fails, * continue with the remaining writes, if any. The default is true. * * * writeConcern (MongoDB\Driver\WriteConcern): Write concern. * * @param string $databaseName Database name * @param string $collectionName Collection name * @param array[] $operations List of write operations * @param array $options Command options * @throws InvalidArgumentException */ public function __construct($databaseName, $collectionName, array $operations, array $options = []) { if (empty($operations)) { throw new InvalidArgumentException('$operations is empty'); } $expectedIndex = 0; foreach ($operations as $i => $operation) { if ($i !== $expectedIndex) { throw new InvalidArgumentException(sprintf('$operations is not a list (unexpected index: "%s")', $i)); } if (!is_array($operation)) { throw InvalidArgumentException::invalidType(sprintf('$operations[%d]', $i), $operation, 'array'); } if (count($operation) !== 1) { throw new InvalidArgumentException(sprintf('Expected one element in $operation[%d], actually: %d', $i, count($operation))); } $type = key($operation); $args = current($operation); if (!isset($args[0]) && !array_key_exists(0, $args)) { throw new InvalidArgumentException(sprintf('Missing first argument for $operations[%d]["%s"]', $i, $type)); } if (!is_array($args[0]) && !is_object($args[0])) { throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][0]', $i, $type), $args[0], 'array or object'); } switch ($type) { case self::INSERT_ONE: break; case self::DELETE_MANY: case self::DELETE_ONE: $operations[$i][$type][1] = ['limit' => $type === self::DELETE_ONE ? 1 : 0]; break; case self::REPLACE_ONE: if (!isset($args[1]) && !array_key_exists(1, $args)) { throw new InvalidArgumentException(sprintf('Missing second argument for $operations[%d]["%s"]', $i, $type)); } if (!is_array($args[1]) && !is_object($args[1])) { throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][1]', $i, $type), $args[1], 'array or object'); } if (\MongoDB\is_first_key_operator($args[1])) { throw new InvalidArgumentException(sprintf('First key in $operations[%d]["%s"][1] is an update operator', $i, $type)); } if (!isset($args[2])) { $args[2] = []; } if (!is_array($args[2])) { throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][2]', $i, $type), $args[2], 'array'); } $args[2]['multi'] = false; $args[2] += ['upsert' => false]; if (!is_bool($args[2]['upsert'])) { throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][2]["upsert"]', $i, $type), $args[2]['upsert'], 'boolean'); } $operations[$i][$type][2] = $args[2]; break; case self::UPDATE_MANY: case self::UPDATE_ONE: if (!isset($args[1]) && !array_key_exists(1, $args)) { throw new InvalidArgumentException(sprintf('Missing second argument for $operations[%d]["%s"]', $i, $type)); } if (!is_array($args[1]) && !is_object($args[1])) { throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][1]', $i, $type), $args[1], 'array or object'); } if (!\MongoDB\is_first_key_operator($args[1])) { throw new InvalidArgumentException(sprintf('First key in $operations[%d]["%s"][1] is not an update operator', $i, $type)); } if (!isset($args[2])) { $args[2] = []; } if (!is_array($args[2])) { throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][2]', $i, $type), $args[2], 'array'); } $args[2]['multi'] = $type === self::UPDATE_MANY; $args[2] += ['upsert' => false]; if (!is_bool($args[2]['upsert'])) { throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][2]["upsert"]', $i, $type), $args[2]['upsert'], 'boolean'); } $operations[$i][$type][2] = $args[2]; break; default: throw new InvalidArgumentException(sprintf('Unknown operation type "%s" in $operations[%d]', $type, $i)); } $expectedIndex += 1; } $options += ['ordered' => true]; if (isset($options['bypassDocumentValidation']) && !is_bool($options['bypassDocumentValidation'])) { throw InvalidArgumentException::invalidType('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean'); } if (!is_bool($options['ordered'])) { throw InvalidArgumentException::invalidType('"ordered" option', $options['ordered'], 'boolean'); } if (isset($options['writeConcern']) && !$options['writeConcern'] instanceof WriteConcern) { throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], 'MongoDB\\Driver\\WriteConcern'); } $this->databaseName = (string) $databaseName; $this->collectionName = (string) $collectionName; $this->operations = $operations; $this->options = $options; }