<?php
 namespace MongoDB;
 use MongoDB\Driver\Cursor;
 use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
 use MongoDB\Driver\Manager;
 use MongoDB\Driver\ReadConcern;
 use MongoDB\Driver\ReadPreference;
 use MongoDB\Driver\WriteConcern;
 use MongoDB\Exception\InvalidArgumentException;
 use MongoDB\Exception\UnexpectedValueException;
 use MongoDB\Exception\UnsupportedException;
 use MongoDB\GridFS\Bucket;
 use MongoDB\Model\BSONArray;
 use MongoDB\Model\BSONDocument;
 use MongoDB\Model\CollectionInfoIterator;
 use MongoDB\Operation\Aggregate;
 use MongoDB\Operation\CreateCollection;
 use MongoDB\Operation\DatabaseCommand;
 use MongoDB\Operation\DropCollection;
 use MongoDB\Operation\DropDatabase;
 use MongoDB\Operation\ListCollections;
 use MongoDB\Operation\ModifyCollection;
 use MongoDB\Operation\Watch;
 use Traversable;
 use function is_array;
 use function strlen;
 class Database {
 private static $defaultTypeMap = [ 'array' => BSONArray::class, 'document' => BSONDocument::class, 'root' => BSONDocument::class, ];
 private static $wireVersionForReadConcern = 4;
 private static $wireVersionForWritableCommandWriteConcern = 5;
 private static $wireVersionForReadConcernWithWriteStage = 8;
 private $databaseName;
 private $manager;
 private $readConcern;
 private $readPreference;
 private $typeMap;
 private $writeConcern;
 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'], ReadConcern::class);
 }
 if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) {
 throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], ReadPreference::class);
 }
 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'], WriteConcern::class);
 }
 $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();
 }
 public function __debugInfo() {
 return [ 'databaseName' => $this->databaseName, 'manager' => $this->manager, 'readConcern' => $this->readConcern, 'readPreference' => $this->readPreference, 'typeMap' => $this->typeMap, 'writeConcern' => $this->writeConcern, ];
 }
 public function __get($collectionName) {
 return $this->selectCollection($collectionName);
 }
 public function __toString() {
 return $this->databaseName;
 }
 public function aggregate(array $pipeline, array $options = []) {
 $hasWriteStage = is_last_pipeline_operator_write($pipeline);
 if (! isset($options['readPreference']) && ! is_in_transaction($options)) {
 $options['readPreference'] = $this->readPreference;
 }
 if ($hasWriteStage) {
 $options['readPreference'] = new ReadPreference(ReadPreference::RP_PRIMARY);
 }
 $server = select_server($this->manager, $options);
 if (! isset($options['readConcern']) && server_supports_feature($server, self::$wireVersionForReadConcern) && ! is_in_transaction($options) && ( ! $hasWriteStage || server_supports_feature($server, self::$wireVersionForReadConcernWithWriteStage)) ) {
 $options['readConcern'] = $this->readConcern;
 }
 if (! isset($options['typeMap'])) {
 $options['typeMap'] = $this->typeMap;
 }
 if ($hasWriteStage && ! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
 $options['writeConcern'] = $this->writeConcern;
 }
 $operation = new Aggregate($this->databaseName, null, $pipeline, $options);
 return $operation->execute($server);
 }
 public function command($command, array $options = []) {
 if (! isset($options['readPreference']) && ! is_in_transaction($options)) {
 $options['readPreference'] = $this->readPreference;
 }
 if (! isset($options['typeMap'])) {
 $options['typeMap'] = $this->typeMap;
 }
 $operation = new DatabaseCommand($this->databaseName, $command, $options);
 $server = select_server($this->manager, $options);
 return $operation->execute($server);
 }
 public function createCollection($collectionName, array $options = []) {
 if (! isset($options['typeMap'])) {
 $options['typeMap'] = $this->typeMap;
 }
 $server = select_server($this->manager, $options);
 if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
 $options['writeConcern'] = $this->writeConcern;
 }
 $operation = new CreateCollection($this->databaseName, $collectionName, $options);
 return $operation->execute($server);
 }
 public function drop(array $options = []) {
 if (! isset($options['typeMap'])) {
 $options['typeMap'] = $this->typeMap;
 }
 $server = select_server($this->manager, $options);
 if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
 $options['writeConcern'] = $this->writeConcern;
 }
 $operation = new DropDatabase($this->databaseName, $options);
 return $operation->execute($server);
 }
 public function dropCollection($collectionName, array $options = []) {
 if (! isset($options['typeMap'])) {
 $options['typeMap'] = $this->typeMap;
 }
 $server = select_server($this->manager, $options);
 if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
 $options['writeConcern'] = $this->writeConcern;
 }
 $operation = new DropCollection($this->databaseName, $collectionName, $options);
 return $operation->execute($server);
 }
 public function getDatabaseName() {
 return $this->databaseName;
 }
 public function getManager() {
 return $this->manager;
 }
 public function getReadConcern() {
 return $this->readConcern;
 }
 public function getReadPreference() {
 return $this->readPreference;
 }
 public function getTypeMap() {
 return $this->typeMap;
 }
 public function getWriteConcern() {
 return $this->writeConcern;
 }
 public function listCollections(array $options = []) {
 $operation = new ListCollections($this->databaseName, $options);
 $server = select_server($this->manager, $options);
 return $operation->execute($server);
 }
 public function modifyCollection($collectionName, array $collectionOptions, array $options = []) {
 if (! isset($options['typeMap'])) {
 $options['typeMap'] = $this->typeMap;
 }
 $server = select_server($this->manager, $options);
 if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
 $options['writeConcern'] = $this->writeConcern;
 }
 $operation = new ModifyCollection($this->databaseName, $collectionName, $collectionOptions, $options);
 return $operation->execute($server);
 }
 public function selectCollection($collectionName, array $options = []) {
 $options += [ 'readConcern' => $this->readConcern, 'readPreference' => $this->readPreference, 'typeMap' => $this->typeMap, 'writeConcern' => $this->writeConcern, ];
 return new Collection($this->manager, $this->databaseName, $collectionName, $options);
 }
 public function selectGridFSBucket(array $options = []) {
 $options += [ 'readConcern' => $this->readConcern, 'readPreference' => $this->readPreference, 'typeMap' => $this->typeMap, 'writeConcern' => $this->writeConcern, ];
 return new Bucket($this->manager, $this->databaseName, $options);
 }
 public function watch(array $pipeline = [], array $options = []) {
 if (! isset($options['readPreference']) && ! is_in_transaction($options)) {
 $options['readPreference'] = $this->readPreference;
 }
 $server = select_server($this->manager, $options);
 if (! isset($options['readConcern']) && server_supports_feature($server, self::$wireVersionForReadConcern) && ! is_in_transaction($options)) {
 $options['readConcern'] = $this->readConcern;
 }
 if (! isset($options['typeMap'])) {
 $options['typeMap'] = $this->typeMap;
 }
 $operation = new Watch($this->manager, $this->databaseName, null, $pipeline, $options);
 return $operation->execute($server);
 }
 public function withOptions(array $options = []) {
 $options += [ 'readConcern' => $this->readConcern, 'readPreference' => $this->readPreference, 'typeMap' => $this->typeMap, 'writeConcern' => $this->writeConcern, ];
 return new Database($this->manager, $this->databaseName, $options);
 }
 }
 