Differences Between: [Versions 310 and 400] [Versions 39 and 400] [Versions 400 and 401]
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; 19 20 use Iterator; 21 use Jean85\PrettyVersions; 22 use MongoDB\Driver\ClientEncryption; 23 use MongoDB\Driver\Exception\InvalidArgumentException as DriverInvalidArgumentException; 24 use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException; 25 use MongoDB\Driver\Manager; 26 use MongoDB\Driver\ReadConcern; 27 use MongoDB\Driver\ReadPreference; 28 use MongoDB\Driver\Session; 29 use MongoDB\Driver\WriteConcern; 30 use MongoDB\Exception\InvalidArgumentException; 31 use MongoDB\Exception\UnexpectedValueException; 32 use MongoDB\Exception\UnsupportedException; 33 use MongoDB\Model\BSONArray; 34 use MongoDB\Model\BSONDocument; 35 use MongoDB\Model\DatabaseInfoIterator; 36 use MongoDB\Operation\DropDatabase; 37 use MongoDB\Operation\ListDatabaseNames; 38 use MongoDB\Operation\ListDatabases; 39 use MongoDB\Operation\Watch; 40 use Throwable; 41 use function is_array; 42 use function is_string; 43 44 class Client 45 { 46 /** @var array */ 47 private static $defaultTypeMap = [ 48 'array' => BSONArray::class, 49 'document' => BSONDocument::class, 50 'root' => BSONDocument::class, 51 ]; 52 53 /** @var integer */ 54 private static $wireVersionForReadConcern = 4; 55 56 /** @var integer */ 57 private static $wireVersionForWritableCommandWriteConcern = 5; 58 59 /** @var string */ 60 private static $handshakeSeparator = ' / '; 61 62 /** @var string|null */ 63 private static $version; 64 65 /** @var Manager */ 66 private $manager; 67 68 /** @var ReadConcern */ 69 private $readConcern; 70 71 /** @var ReadPreference */ 72 private $readPreference; 73 74 /** @var string */ 75 private $uri; 76 77 /** @var array */ 78 private $typeMap; 79 80 /** @var WriteConcern */ 81 private $writeConcern; 82 83 /** 84 * Constructs a new Client instance. 85 * 86 * This is the preferred class for connecting to a MongoDB server or 87 * cluster of servers. It serves as a gateway for accessing individual 88 * databases and collections. 89 * 90 * Supported driver-specific options: 91 * 92 * * typeMap (array): Default type map for cursors and BSON documents. 93 * 94 * Other options are documented in MongoDB\Driver\Manager::__construct(). 95 * 96 * @see http://docs.mongodb.org/manual/reference/connection-string/ 97 * @see http://php.net/manual/en/mongodb-driver-manager.construct.php 98 * @see http://php.net/manual/en/mongodb.persistence.php#mongodb.persistence.typemaps 99 * @param string $uri MongoDB connection string 100 * @param array $uriOptions Additional connection string options 101 * @param array $driverOptions Driver-specific options 102 * @throws InvalidArgumentException for parameter/option parsing errors 103 * @throws DriverInvalidArgumentException for parameter/option parsing errors in the driver 104 * @throws DriverRuntimeException for other driver errors (e.g. connection errors) 105 */ 106 public function __construct($uri = 'mongodb://127.0.0.1/', array $uriOptions = [], array $driverOptions = []) 107 { 108 $driverOptions += ['typeMap' => self::$defaultTypeMap]; 109 110 if (! is_array($driverOptions['typeMap'])) { 111 throw InvalidArgumentException::invalidType('"typeMap" driver option', $driverOptions['typeMap'], 'array'); 112 } 113 114 if (isset($driverOptions['autoEncryption']['keyVaultClient'])) { 115 if ($driverOptions['autoEncryption']['keyVaultClient'] instanceof self) { 116 $driverOptions['autoEncryption']['keyVaultClient'] = $driverOptions['autoEncryption']['keyVaultClient']->manager; 117 } elseif (! $driverOptions['autoEncryption']['keyVaultClient'] instanceof Manager) { 118 throw InvalidArgumentException::invalidType('"keyVaultClient" autoEncryption option', $driverOptions['autoEncryption']['keyVaultClient'], [self::class, Manager::class]); 119 } 120 } 121 122 $driverOptions['driver'] = $this->mergeDriverInfo($driverOptions['driver'] ?? []); 123 124 $this->uri = (string) $uri; 125 $this->typeMap = $driverOptions['typeMap'] ?? null; 126 127 unset($driverOptions['typeMap']); 128 129 $this->manager = new Manager($uri, $uriOptions, $driverOptions); 130 $this->readConcern = $this->manager->getReadConcern(); 131 $this->readPreference = $this->manager->getReadPreference(); 132 $this->writeConcern = $this->manager->getWriteConcern(); 133 } 134 135 /** 136 * Return internal properties for debugging purposes. 137 * 138 * @see http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.debuginfo 139 * @return array 140 */ 141 public function __debugInfo() 142 { 143 return [ 144 'manager' => $this->manager, 145 'uri' => $this->uri, 146 'typeMap' => $this->typeMap, 147 'writeConcern' => $this->writeConcern, 148 ]; 149 } 150 151 /** 152 * Select a database. 153 * 154 * Note: databases whose names contain special characters (e.g. "-") may 155 * be selected with complex syntax (e.g. $client->{"that-database"}) or 156 * {@link selectDatabase()}. 157 * 158 * @see http://php.net/oop5.overloading#object.get 159 * @see http://php.net/types.string#language.types.string.parsing.complex 160 * @param string $databaseName Name of the database to select 161 * @return Database 162 */ 163 public function __get($databaseName) 164 { 165 return $this->selectDatabase($databaseName); 166 } 167 168 /** 169 * Return the connection string (i.e. URI). 170 * 171 * @return string 172 */ 173 public function __toString() 174 { 175 return $this->uri; 176 } 177 178 /** 179 * Returns a ClientEncryption instance for explicit encryption and decryption 180 * 181 * @param array $options Encryption options 182 * 183 * @return ClientEncryption 184 */ 185 public function createClientEncryption(array $options) 186 { 187 if (isset($options['keyVaultClient'])) { 188 if ($options['keyVaultClient'] instanceof self) { 189 $options['keyVaultClient'] = $options['keyVaultClient']->manager; 190 } elseif (! $options['keyVaultClient'] instanceof Manager) { 191 throw InvalidArgumentException::invalidType('"keyVaultClient" option', $options['keyVaultClient'], [self::class, Manager::class]); 192 } 193 } 194 195 return $this->manager->createClientEncryption($options); 196 } 197 198 /** 199 * Drop a database. 200 * 201 * @see DropDatabase::__construct() for supported options 202 * @param string $databaseName Database name 203 * @param array $options Additional options 204 * @return array|object Command result document 205 * @throws UnsupportedException if options are unsupported on the selected server 206 * @throws InvalidArgumentException for parameter/option parsing errors 207 * @throws DriverRuntimeException for other driver errors (e.g. connection errors) 208 */ 209 public function dropDatabase($databaseName, array $options = []) 210 { 211 if (! isset($options['typeMap'])) { 212 $options['typeMap'] = $this->typeMap; 213 } 214 215 $server = select_server($this->manager, $options); 216 217 if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) { 218 $options['writeConcern'] = $this->writeConcern; 219 } 220 221 $operation = new DropDatabase($databaseName, $options); 222 223 return $operation->execute($server); 224 } 225 226 /** 227 * Return the Manager. 228 * 229 * @return Manager 230 */ 231 public function getManager() 232 { 233 return $this->manager; 234 } 235 236 /** 237 * Return the read concern for this client. 238 * 239 * @see http://php.net/manual/en/mongodb-driver-readconcern.isdefault.php 240 * @return ReadConcern 241 */ 242 public function getReadConcern() 243 { 244 return $this->readConcern; 245 } 246 247 /** 248 * Return the read preference for this client. 249 * 250 * @return ReadPreference 251 */ 252 public function getReadPreference() 253 { 254 return $this->readPreference; 255 } 256 257 /** 258 * Return the type map for this client. 259 * 260 * @return array 261 */ 262 public function getTypeMap() 263 { 264 return $this->typeMap; 265 } 266 267 /** 268 * Return the write concern for this client. 269 * 270 * @see http://php.net/manual/en/mongodb-driver-writeconcern.isdefault.php 271 * @return WriteConcern 272 */ 273 public function getWriteConcern() 274 { 275 return $this->writeConcern; 276 } 277 278 /** 279 * List database names. 280 * 281 * @see ListDatabaseNames::__construct() for supported options 282 * @throws UnexpectedValueException if the command response was malformed 283 * @throws InvalidArgumentException for parameter/option parsing errors 284 * @throws DriverRuntimeException for other driver errors (e.g. connection errors) 285 */ 286 public function listDatabaseNames(array $options = []) : Iterator 287 { 288 $operation = new ListDatabaseNames($options); 289 $server = select_server($this->manager, $options); 290 291 return $operation->execute($server); 292 } 293 294 /** 295 * List databases. 296 * 297 * @see ListDatabases::__construct() for supported options 298 * @param array $options 299 * @return DatabaseInfoIterator 300 * @throws UnexpectedValueException if the command response was malformed 301 * @throws InvalidArgumentException for parameter/option parsing errors 302 * @throws DriverRuntimeException for other driver errors (e.g. connection errors) 303 */ 304 public function listDatabases(array $options = []) 305 { 306 $operation = new ListDatabases($options); 307 $server = select_server($this->manager, $options); 308 309 return $operation->execute($server); 310 } 311 312 /** 313 * Select a collection. 314 * 315 * @see Collection::__construct() for supported options 316 * @param string $databaseName Name of the database containing the collection 317 * @param string $collectionName Name of the collection to select 318 * @param array $options Collection constructor options 319 * @return Collection 320 * @throws InvalidArgumentException for parameter/option parsing errors 321 */ 322 public function selectCollection($databaseName, $collectionName, array $options = []) 323 { 324 $options += ['typeMap' => $this->typeMap]; 325 326 return new Collection($this->manager, $databaseName, $collectionName, $options); 327 } 328 329 /** 330 * Select a database. 331 * 332 * @see Database::__construct() for supported options 333 * @param string $databaseName Name of the database to select 334 * @param array $options Database constructor options 335 * @return Database 336 * @throws InvalidArgumentException for parameter/option parsing errors 337 */ 338 public function selectDatabase($databaseName, array $options = []) 339 { 340 $options += ['typeMap' => $this->typeMap]; 341 342 return new Database($this->manager, $databaseName, $options); 343 } 344 345 /** 346 * Start a new client session. 347 * 348 * @see http://php.net/manual/en/mongodb-driver-manager.startsession.php 349 * @param array $options Session options 350 * @return Session 351 */ 352 public function startSession(array $options = []) 353 { 354 return $this->manager->startSession($options); 355 } 356 357 /** 358 * Create a change stream for watching changes to the cluster. 359 * 360 * @see Watch::__construct() for supported options 361 * @param array $pipeline List of pipeline operations 362 * @param array $options Command options 363 * @return ChangeStream 364 * @throws InvalidArgumentException for parameter/option parsing errors 365 */ 366 public function watch(array $pipeline = [], array $options = []) 367 { 368 if (! isset($options['readPreference']) && ! is_in_transaction($options)) { 369 $options['readPreference'] = $this->readPreference; 370 } 371 372 $server = select_server($this->manager, $options); 373 374 if (! isset($options['readConcern']) && server_supports_feature($server, self::$wireVersionForReadConcern) && ! is_in_transaction($options)) { 375 $options['readConcern'] = $this->readConcern; 376 } 377 378 if (! isset($options['typeMap'])) { 379 $options['typeMap'] = $this->typeMap; 380 } 381 382 $operation = new Watch($this->manager, null, null, $pipeline, $options); 383 384 return $operation->execute($server); 385 } 386 387 private static function getVersion() : string 388 { 389 if (self::$version === null) { 390 try { 391 self::$version = PrettyVersions::getVersion('mongodb/mongodb')->getPrettyVersion(); 392 } catch (Throwable $t) { 393 return 'unknown'; 394 } 395 } 396 397 return self::$version; 398 } 399 400 private function mergeDriverInfo(array $driver) : array 401 { 402 $mergedDriver = [ 403 'name' => 'PHPLIB', 404 'version' => self::getVersion(), 405 ]; 406 407 if (isset($driver['name'])) { 408 if (! is_string($driver['name'])) { 409 throw InvalidArgumentException::invalidType('"name" handshake option', $driver['name'], 'string'); 410 } 411 412 $mergedDriver['name'] .= self::$handshakeSeparator . $driver['name']; 413 } 414 415 if (isset($driver['version'])) { 416 if (! is_string($driver['version'])) { 417 throw InvalidArgumentException::invalidType('"version" handshake option', $driver['version'], 'string'); 418 } 419 420 $mergedDriver['version'] .= self::$handshakeSeparator . $driver['version']; 421 } 422 423 if (isset($driver['platform'])) { 424 $mergedDriver['platform'] = $driver['platform']; 425 } 426 427 return $mergedDriver; 428 } 429 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body