PHPLIB-516: Append PHPLIB version information to handshake data

parent 68879deb
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
"php": "^7.0", "php": "^7.0",
"ext-hash": "*", "ext-hash": "*",
"ext-json": "*", "ext-json": "*",
"ext-mongodb": "^1.8" "ext-mongodb": "^1.8",
"jean85/pretty-package-versions": "^1.2"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.4 || ^8.3", "phpunit/phpunit": "^6.4 || ^8.3",
......
...@@ -142,6 +142,34 @@ description: | ...@@ -142,6 +142,34 @@ description: |
For the ``keyVaultClient`` option, you may pass a :phpclass:`MongoDB\\Client` For the ``keyVaultClient`` option, you may pass a :phpclass:`MongoDB\\Client`
instance, which will be unwrapped to provide a :php:`MongoDB\\Driver\\Manager <class.mongodb-driver-manager>` instance, which will be unwrapped to provide a :php:`MongoDB\\Driver\\Manager <class.mongodb-driver-manager>`
to the extension. to the extension.
.. versionadded:: 1.6
interface: phpmethod
operation: ~
optional: true
---
arg_name: option
name: driver
type: array
description: |
Additional driver metadata to be passed on to the server handshake. This is an
array containing ``name``, ``version``, and ``platform`` fields:
.. code-block:: php
[
'name' => 'my-driver',
'version' => '1.2.3-dev',
'platform' => 'some-platform',
]
.. note::
This feature is primarily designed for custom drivers and ODMs, which may
want to identify themselves to the server for diagnostic purposes.
Applications should use the ``appName`` URI option instead of driver
metadata.
.. versionadded:: 1.7
interface: phpmethod interface: phpmethod
operation: ~ operation: ~
optional: true optional: true
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
namespace MongoDB; namespace MongoDB;
use Jean85\PrettyVersions;
use MongoDB\Driver\ClientEncryption; use MongoDB\Driver\ClientEncryption;
use MongoDB\Driver\Exception\InvalidArgumentException as DriverInvalidArgumentException; use MongoDB\Driver\Exception\InvalidArgumentException as DriverInvalidArgumentException;
use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException; use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
...@@ -34,7 +35,9 @@ use MongoDB\Model\DatabaseInfoIterator; ...@@ -34,7 +35,9 @@ use MongoDB\Model\DatabaseInfoIterator;
use MongoDB\Operation\DropDatabase; use MongoDB\Operation\DropDatabase;
use MongoDB\Operation\ListDatabases; use MongoDB\Operation\ListDatabases;
use MongoDB\Operation\Watch; use MongoDB\Operation\Watch;
use Throwable;
use function is_array; use function is_array;
use function is_string;
class Client class Client
{ {
...@@ -51,6 +54,12 @@ class Client ...@@ -51,6 +54,12 @@ class Client
/** @var integer */ /** @var integer */
private static $wireVersionForWritableCommandWriteConcern = 5; private static $wireVersionForWritableCommandWriteConcern = 5;
/** @var string */
private static $handshakeSeparator = ' / ';
/** @var string|null */
private static $version;
/** @var Manager */ /** @var Manager */
private $manager; private $manager;
...@@ -108,6 +117,8 @@ class Client ...@@ -108,6 +117,8 @@ class Client
} }
} }
$driverOptions['driver'] = $this->mergeDriverInfo($driverOptions['driver'] ?? []);
$this->uri = (string) $uri; $this->uri = (string) $uri;
$this->typeMap = $driverOptions['typeMap'] ?? null; $this->typeMap = $driverOptions['typeMap'] ?? null;
...@@ -354,4 +365,47 @@ class Client ...@@ -354,4 +365,47 @@ class Client
return $operation->execute($server); return $operation->execute($server);
} }
private static function getVersion() : string
{
if (self::$version === null) {
try {
self::$version = PrettyVersions::getVersion('mongodb/mongodb')->getPrettyVersion();
} catch (Throwable $t) {
return 'unknown';
}
}
return self::$version;
}
private function mergeDriverInfo(array $driver) : array
{
$mergedDriver = [
'name' => 'PHPLIB',
'version' => self::getVersion(),
];
if (isset($driver['name'])) {
if (! is_string($driver['name'])) {
throw InvalidArgumentException::invalidType('"name" handshake option', $driver['name'], 'string');
}
$mergedDriver['name'] .= self::$handshakeSeparator . $driver['name'];
}
if (isset($driver['version'])) {
if (! is_string($driver['version'])) {
throw InvalidArgumentException::invalidType('"version" handshake option', $driver['version'], 'string');
}
$mergedDriver['version'] .= self::$handshakeSeparator . $driver['version'];
}
if (isset($driver['platform'])) {
$mergedDriver['platform'] = $driver['platform'];
}
return $mergedDriver;
}
} }
...@@ -4,6 +4,7 @@ namespace MongoDB\Tests; ...@@ -4,6 +4,7 @@ namespace MongoDB\Tests;
use MongoDB\Client; use MongoDB\Client;
use MongoDB\Driver\ClientEncryption; use MongoDB\Driver\ClientEncryption;
use MongoDB\Driver\Exception\InvalidArgumentException as DriverInvalidArgumentException;
use MongoDB\Driver\ReadConcern; use MongoDB\Driver\ReadConcern;
use MongoDB\Driver\ReadPreference; use MongoDB\Driver\ReadPreference;
use MongoDB\Driver\WriteConcern; use MongoDB\Driver\WriteConcern;
...@@ -38,9 +39,9 @@ class ClientTest extends TestCase ...@@ -38,9 +39,9 @@ class ClientTest extends TestCase
/** /**
* @dataProvider provideInvalidConstructorDriverOptions * @dataProvider provideInvalidConstructorDriverOptions
*/ */
public function testConstructorDriverOptionTypeChecks(array $driverOptions) public function testConstructorDriverOptionTypeChecks(array $driverOptions, string $exception = InvalidArgumentException::class)
{ {
$this->expectException(InvalidArgumentException::class); $this->expectException($exception);
new Client(static::getUri(), [], $driverOptions); new Client(static::getUri(), [], $driverOptions);
} }
...@@ -54,6 +55,21 @@ class ClientTest extends TestCase ...@@ -54,6 +55,21 @@ class ClientTest extends TestCase
$options[][] = ['autoEncryption' => ['keyVaultClient' => 'foo']]; $options[][] = ['autoEncryption' => ['keyVaultClient' => 'foo']];
foreach ($this->getInvalidStringValues() as $value) {
$options[][] = ['driver' => ['name' => $value]];
}
foreach ($this->getInvalidStringValues() as $value) {
$options[][] = ['driver' => ['version' => $value]];
}
foreach ($this->getInvalidStringValues() as $value) {
$options[] = [
'driverOptions' => ['driver' => ['platform' => $value]],
'exception' => DriverInvalidArgumentException::class,
];
}
return $options; return $options;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment