vendor/mongodb/mongodb/src/Client.php line 106

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