Skip to content

Commit

Permalink
Support DSN in Client constructor for config argument (ruflin#1640)
Browse files Browse the repository at this point in the history
  • Loading branch information
alamirault committed Aug 17, 2019
1 parent 5f71248 commit 638bbed
Show file tree
Hide file tree
Showing 5 changed files with 334 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ All notable changes to this project will be documented in this file based on the
* Added `ParentAggregation` [#1616](https://github.com/ruflin/Elastica/pull/1616)
* Elastica\Reindex missing options (script, remote, wait_for_completion, scroll...)
* Added `AdjacencyMatrix` aggregation [#1642](https://github.com/ruflin/Elastica/pull/1642)
* Support DSN in `\Elastica\Client` constructor for config argument [#1640](https://github.com/ruflin/Elastica/issues/1640)

### Improvements
* Added `native_function_invocation` CS rule [#1606](https://github.com/ruflin/Elastica/pull/1606)
Expand Down
14 changes: 12 additions & 2 deletions lib/Elastica/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,22 @@ class Client
/**
* Creates a new Elastica client.
*
* @param array $config OPTIONAL Additional config options
* @param array|string $config OPTIONAL Additional config or DSN of options
* @param callback $callback OPTIONAL Callback function which can be used to be notified about errors (for example connection down)
* @param LoggerInterface $logger
*
* @throws \Elastica\Exception\InvalidException
*/
public function __construct(array $config = [], $callback = null, LoggerInterface $logger = null)
public function __construct($config = [], $callback = null, LoggerInterface $logger = null)
{
if (\is_string($config)) {
$config = Dsn::fromString($config)->getConfiguration();
}

if (!\is_array($config)) {
throw new InvalidException('Config parameter must be an array or a string.');
}

$this->_callback = $callback;

if (!$logger && isset($config['log']) && $config['log']) {
Expand Down
222 changes: 222 additions & 0 deletions lib/Elastica/Dsn.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
<?php

namespace Elastica;

use Elastica\Exception\InvalidException;

/**
* Dns parser and configuration exporter to Elastica Client.
*
* @author Antoine Lamirault <lamiraultantoine@gmail.com>
*/
class Dsn
{
/**
* @var string|null
*/
private $host;

/**
* @var string|null
*/
private $port;

/**
* @var string|null
*/
private $url;

/**
* @var string|null
*/
private $path;

/**
* @var string|null
*/
private $proxy;

/**
* @var string|null
*/
private $transport;

/**
* @var bool
*/
private $persistent;

/**
* @var int|null
*/
private $timeout;

/**
* @var array
*/
private $connections;

/**
* @var bool
*/
private $roundRobin;

/**
* @var bool
*/
private $log;

/**
* @var int
*/
private $retryOnConflict;

/**
* @var bool
*/
private $bigintConversion;

/**
* @var string|null
*/
private $username;

/**
* @var string|null
*/
private $password;

/**
* Dsn constructor.
*
* @param string|null $host
* @param string|null $port
* @param string|null $url
* @param string|null $path
* @param string|null $proxy
* @param string|null $transport
* @param bool $persistent
* @param int|null $timeout
* @param array $connections
* @param bool $roundRobin
* @param bool $log
* @param int $retryOnConflict
* @param bool $bigintConversion
* @param string|null $username
* @param string|null $password
*/
public function __construct(?string $host, ?string $port, ?string $url, ?string $path, ?string $proxy,
?string $transport, bool $persistent, ?int $timeout, array $connections,
bool $roundRobin, bool $log, int $retryOnConflict, bool $bigintConversion,
?string $username, ?string $password)
{
$this->host = $host;
$this->port = $port;
$this->url = $url;
$this->path = $path;
$this->proxy = $proxy;
$this->transport = $transport;
$this->persistent = $persistent;
$this->timeout = $timeout;
$this->connections = $connections;
$this->roundRobin = $roundRobin;
$this->log = $log;
$this->retryOnConflict = $retryOnConflict;
$this->bigintConversion = $bigintConversion;
$this->username = $username;
$this->password = $password;
}

public static function fromString(string $dsn): self
{
if (false === $parsedDsn = \parse_url($dsn)) {
throw new InvalidException(\sprintf("DSN '%s' is invalid.", $dsn));
}

$transport = $parsedDsn['scheme'] ?? null;
$host = $parsedDsn['host'] ?? null;
$username = isset($parsedDsn['user']) ? \urldecode($parsedDsn['user']) : null;
$password = isset($parsedDsn['pass']) ? \urldecode($parsedDsn['pass']) : null;
$port = $parsedDsn['port'] ?? null;
$path = $parsedDsn['path'] ?? null;

$options = [];
if (isset($parsedDsn['query'])) {
\parse_str($parsedDsn['query'], $options);
}

$proxy = null;
if (isset($options['proxy'])) {
$proxy = $options['proxy'];
}

$persistent = true;
if (isset($options['persistent']) && ('false' === $options['persistent'])) {
$persistent = false;
}

$timeout = null;
if (isset($options['timeout'])) {
$timeout = (int) $options['timeout'];
}

$roundRobin = false;
if (isset($options['roundRobin']) && ('true' === $options['roundRobin'])) {
$roundRobin = true;
}

$log = false;
if (isset($options['log']) && ('true' === $options['log'])) {
$log = true;
}

$retryOnConflict = 0;
if (isset($options['retryOnConflict'])) {
$retryOnConflict = (int) $options['retryOnConflict'];
}

$bigintConversion = false;
if (isset($options['bigintConversion']) && ('true' === $options['bigintConversion'])) {
$bigintConversion = true;
}

return new self(
$host,
$port,
null,
$path,
$proxy,
$transport,
$persistent,
$timeout,
[],
$roundRobin,
$log,
$retryOnConflict,
$bigintConversion,
$username,
$password
);
}

public function getConfiguration(): array
{
return [
'host' => $this->host,
'port' => $this->port,
'path' => $this->path,
'url' => $this->url,
'proxy' => $this->proxy,
'transport' => $this->transport,
'persistent' => $this->persistent,
'timeout' => $this->timeout,
'connections' => $this->connections,
'roundRobin' => $this->roundRobin,
'log' => $this->log,
'retryOnConflict' => $this->retryOnConflict,
'bigintConversion' => $this->bigintConversion,
'username' => $this->username,
'password' => $this->password,
];
}
}
30 changes: 30 additions & 0 deletions test/Elastica/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,36 @@ public function testConstruct()
$this->assertCount(1, $client->getConnections());
}

/**
* @group unit
*/
public function testConstructWithDsn()
{
$client = new Client('https://user:p4ss@foo.com:9200?persistent=false&retryOnConflict=2');
$this->assertCount(1, $client->getConnections());

$expected = [
'host' => 'foo.com',
'port' => '9200',
'path' => null,
'url' => null,
'proxy' => null,
'transport' => 'https',
'persistent' => false,
'timeout' => null,
'connections' => [],
'roundRobin' => false,
'log' => false,
'retryOnConflict' => 2,
'bigintConversion' => false,
'username' => 'user',
'password' => 'p4ss',
'connectionStrategy' => 'Simple',
];

$this->assertEquals($expected, $client->getConfig());
}

/**
* @group functional
*/
Expand Down
69 changes: 69 additions & 0 deletions test/Elastica/DsnTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace Elastica\Test;

use Elastica\Dsn;
use PHPUnit\Framework\TestCase;

/**
* @group unit
*/
class DsnTest extends TestCase
{
public function testInvalidDsn()
{
$this->expectException(\Elastica\Exception\InvalidException::class);
$this->expectExceptionMessage("DSN 'test:0' is invalid.");

Dsn::fromString('test:0');
}

public function testSimpleDsn()
{
$dsn = Dsn::fromString('192.168.1.1:9201');

$expected = [
'host' => '192.168.1.1',
'port' => '9201',
'path' => null,
'url' => null,
'proxy' => null,
'transport' => null,
'persistent' => true,
'timeout' => null,
'connections' => [],
'roundRobin' => false,
'log' => false,
'retryOnConflict' => 0,
'bigintConversion' => false,
'username' => null,
'password' => null,
];

$this->assertEquals($expected, $dsn->getConfiguration());
}

public function testDsnWithParameters()
{
$dsn = Dsn::fromString('https://user:p4ss@foo.com:9201/my-path?proxy=https://proxy.com&persistent=false&timeout=45&roundRobin=true&log=true&retryOnConflict=2&bigintConversion=true');
$expected = [
'host' => 'foo.com',
'port' => '9201',
'path' => '/my-path',
'url' => null,
'proxy' => 'https://proxy.com',
'transport' => 'https',
'persistent' => false,
'timeout' => 45,
'connections' => [],
'roundRobin' => true,
'log' => true,
'retryOnConflict' => 2,
'bigintConversion' => true,
'username' => 'user',
'password' => 'p4ss',
];

$this->assertEquals($expected, $dsn->getConfiguration());
}
}

0 comments on commit 638bbed

Please sign in to comment.