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 25, 2019
1 parent 37822e6 commit bfadf03
Show file tree
Hide file tree
Showing 5 changed files with 437 additions and 48 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file based on the
* Elastica\Reindex does not return an Index anymore but a Response.
* Elastica\Reindex->run() does not refresh the new Index after completion anymore. Use `$reindex->setParam(Reindex::REFRESH, 'wait_for')` instead.
* `Elastica\Search->search()` and `Elastica\Search->count()` use request method `POST` by default. Same for `Elastica\Index`, `Elastica\Type\AbstractType`, `Elastica\Type`.
* Elastica\Client `$_config` field is now a `ClientConfiguration` instead of an array

### Bugfixes
* Always set the Guzzle `base_uri` to support connecting to multiple ES hosts. [#1618](https://github.com/ruflin/Elastica/pull/1618)
Expand All @@ -29,6 +30,8 @@ All notable changes to this project will be documented in this file based on the
* Added `AdjacencyMatrix` aggregation [#1642](https://github.com/ruflin/Elastica/pull/1642)
* Added request method parameter to `Elastica\SearchableInterface->search()` and `Elastica\SearchableInterface->count()`. Same for `Elastica\Search`[#1441](https://github.com/ruflin/Elastica/issues/1441)
* Added support for Field Collapsing (Issue: [#1392](https://github.com/ruflin/Elastica/issues/1392); PR: [#1653](https://github.com/ruflin/Elastica/pull/1653))
* Support string DSN in `\Elastica\Client` constructor for config argument [#1640](https://github.com/ruflin/Elastica/issues/1640)
* Move Client configuration in a dedicated class

### Improvements
* Added `native_function_invocation` CS rule [#1606](https://github.com/ruflin/Elastica/pull/1606)
Expand Down
83 changes: 36 additions & 47 deletions lib/Elastica/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,9 @@
class Client
{
/**
* Config with defaults.
*
* log: Set to true, to enable logging, set a string to log to a specific file
* retryOnConflict: Use in \Elastica\Client::updateDocument
* bigintConversion: Set to true to enable the JSON bigint to string conversion option (see issue #717)
*
* @var array
*/
protected $_config = [
'host' => null,
'port' => null,
'path' => null,
'url' => null,
'proxy' => null,
'transport' => null,
'persistent' => true,
'timeout' => null,
'connections' => [], // host, port, path, timeout, transport, compression, persistent, timeout, username, password, config -> (curl, headers, url)
'roundRobin' => false,
'log' => false,
'retryOnConflict' => 0,
'bigintConversion' => false,
'username' => null,
'password' => null,
];
* @var ClientConfiguration
*/
protected $_config;

/**
* @var callback
Expand Down Expand Up @@ -80,20 +58,30 @@ 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)) {
$configuration = ClientConfiguration::fromDsn($config);
} elseif (\is_array($config)) {
$configuration = ClientConfiguration::fromArray($config);
} else {
throw new InvalidException('Config parameter must be an array or a string.');
}

$this->_config = $configuration;
$this->_callback = $callback;

if (!$logger && isset($config['log']) && $config['log']) {
$logger = new Log($config['log']);
if (!$logger && $configuration->get('log')) {
$logger = new Log($configuration->get('log'));
}
$this->_logger = $logger ?: new NullLogger();

$this->setConfig($config);
$this->_initConnections();
}

Expand Down Expand Up @@ -124,8 +112,9 @@ protected function _initConnections()
$connections[] = Connection::create($this->_prepareConnectionParams($connection));
}

if (isset($this->_config['servers'])) {
foreach ($this->getConfig('servers') as $server) {
if ($this->_config->has('servers')) {
$servers = $this->_config->get('servers');
foreach ($servers as $server) {
$connections[] = Connection::create($this->_prepareConnectionParams($server));
}
}
Expand All @@ -135,7 +124,7 @@ protected function _initConnections()
$connections[] = Connection::create($this->_prepareConnectionParams($this->getConfig()));
}

if (!isset($this->_config['connectionStrategy'])) {
if (!$this->_config->has('connectionStrategy')) {
if (true === $this->getConfig('roundRobin')) {
$this->setConfigValue('connectionStrategy', 'RoundRobin');
} else {
Expand Down Expand Up @@ -180,7 +169,7 @@ protected function _prepareConnectionParams(array $config)
public function setConfig(array $config)
{
foreach ($config as $key => $value) {
$this->_config[$key] = $value;
$this->_config->set($key, $value);
}

return $this;
Expand All @@ -198,15 +187,7 @@ public function setConfig(array $config)
*/
public function getConfig($key = '')
{
if (empty($key)) {
return $this->_config;
}

if (!\array_key_exists($key, $this->_config)) {
throw new InvalidException('Config key is not set: '.$key);
}

return $this->_config[$key];
return $this->_config->get($key);
}

/**
Expand All @@ -230,7 +211,7 @@ public function setConfigValue($key, $value)
*/
public function getConfigValue($keys, $default = null)
{
$value = $this->_config;
$value = $this->_config->getAll();
foreach ((array) $keys as $key) {
if (isset($value[$key])) {
$value = $value[$key];
Expand Down Expand Up @@ -267,7 +248,13 @@ public function getIndex($name)
public function addHeader($header, $headerValue)
{
if (\is_string($header) && \is_string($headerValue)) {
$this->_config['headers'][$header] = $headerValue;
if ($this->_config->has('headers')) {
$headers = $this->_config->get('headers');
} else {
$headers = [];
}
$headers[$header] = $headerValue;
$this->_config->set('headers', $headers);
} else {
throw new InvalidException('Header must be a string');
}
Expand All @@ -287,8 +274,10 @@ public function addHeader($header, $headerValue)
public function removeHeader($header)
{
if (\is_string($header)) {
if (\array_key_exists($header, $this->_config['headers'])) {
unset($this->_config['headers'][$header]);
if ($this->_config->has('headers')) {
$headers = $this->_config->get('headers');
unset($headers[$header]);
$this->_config->set('headers', $headers);
}
} else {
throw new InvalidException('Header must be a string');
Expand Down
189 changes: 189 additions & 0 deletions lib/Elastica/ClientConfiguration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
<?php

namespace Elastica;

use Elastica\Exception\InvalidException;

/**
* Elastica client configuration.
*
* @author Antoine Lamirault <lamiraultantoine@gmail.com>
*/
class ClientConfiguration
{
/**
* Config with defaults.
*
* log: Set to true, to enable logging, set a string to log to a specific file
* retryOnConflict: Use in \Elastica\Client::updateDocument
* bigintConversion: Set to true to enable the JSON bigint to string conversion option (see issue #717)
*
* @var array
*/
protected $configuration = [
'host' => null,
'port' => null,
'path' => null,
'url' => null,
'proxy' => null,
'transport' => null,
'persistent' => true,
'timeout' => null,
'connections' => [], // host, port, path, timeout, transport, compression, persistent, timeout, username, password, config -> (curl, headers, url)
'roundRobin' => false,
'log' => false,
'retryOnConflict' => 0,
'bigintConversion' => false,
'username' => null,
'password' => null,
];

/**
* Create configuration.
*
* @param array $config Additional config
*
* @return ClientConfiguration
*/
public static function fromArray(array $config): self
{
$clientConfiguration = new self();
foreach ($config as $key => $value) {
$clientConfiguration->set($key, $value);
}

return $clientConfiguration;
}

/**
* Create configuration from Dsn string.
*
* @param string $dsn
*
* @return ClientConfiguration
*/
public static function fromDsn(string $dsn): self
{
if (false === $parsedDsn = \parse_url($dsn)) {
throw new InvalidException(\sprintf("DSN '%s' is invalid.", $dsn));
}

$clientConfiguration = new self();

if (isset($parsedDsn['scheme'])) {
$clientConfiguration->set('transport', $parsedDsn['scheme']);
}

if (isset($parsedDsn['host'])) {
$clientConfiguration->set('host', $parsedDsn['host']);
}

if (isset($parsedDsn['user'])) {
$clientConfiguration->set('username', \urldecode($parsedDsn['user']));
}

if (isset($parsedDsn['pass'])) {
$clientConfiguration->set('password', \urldecode($parsedDsn['pass']));
}

if (isset($parsedDsn['port'])) {
$clientConfiguration->set('port', $parsedDsn['port']);
}

if (isset($parsedDsn['path'])) {
$clientConfiguration->set('path', $parsedDsn['path']);
}

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

foreach ($options as $optionName => $optionValue) {
if ('false' === $optionValue) {
$optionValue = false;
} elseif ('true' === $optionValue) {
$optionValue = true;
} elseif (\is_numeric($optionValue)) {
$optionValue = (int) $optionValue;
}

$clientConfiguration->set($optionName, $optionValue);
}

return $clientConfiguration;
}

/**
* Returns a specific config key or the whole
* config array if not set.
*
* @param string $key Config key
*
* @throws \Elastica\Exception\InvalidException
*
* @return mixed Config value
*/
public function get(string $key)
{
if (empty($key)) {
return $this->configuration;
}

if (!$this->has($key)) {
throw new InvalidException('Config key is not set: '.$key);
}

return $this->configuration[$key];
}

/**
* Returns boolean indicates if configuration has key.
*
* @param string $key Key to check
*
* @return bool
*/
public function has(string $key): bool
{
return \array_key_exists($key, $this->configuration);
}

/**
* Return all configuration.
*
* @return array
*/
public function getAll(): array
{
return $this->configuration;
}

/**
* @param string $key Key to set
* @param mixed $value Value
*/
public function set(string $key, $value): void
{
$this->configuration[$key] = $value;
}

/**
* Add value to a key. If original value is not an array, value is wrapped.
*
* @param string $key Key to add
* @param mixed $value Value
*/
public function add(string $key, $value): void
{
if (!\array_key_exists($key, $this->configuration)) {
$this->configuration[$key] = [$value];
} else {
if (\is_array($this->configuration[$key])) {
$this->configuration[$key][] = $value;
} else {
$this->configuration[$key] = [$this->configuration[$key], $value];
}
}
}
}
Loading

0 comments on commit bfadf03

Please sign in to comment.