Completed
Pull Request — master (#1808)
by Tobias
04:15 queued 01:32
created

ClientConfiguration::fromDsn()   B

Complexity

Conditions 9
Paths 12

Size

Total Lines 37

Duplication

Lines 11
Ratio 29.73 %

Importance

Changes 0
Metric Value
dl 11
loc 37
rs 7.7724
c 0
b 0
f 0
cc 9
nc 12
nop 1
1
<?php
2
3
namespace Elastica;
4
5
use Elastica\Exception\InvalidException;
6
use Nyholm\Dsn\Configuration\Url;
7
use Nyholm\Dsn\DsnParser;
8
use Nyholm\Dsn\Exception\ExceptionInterface as DsnException;
9
use Nyholm\Dsn\Exception\FunctionNotSupportedException;
10
11
/**
12
 * Elastica client configuration.
13
 *
14
 * @author Antoine Lamirault <[email protected]>
15
 */
16
class ClientConfiguration
17
{
18
    /**
19
     * Config with defaults.
20
     *
21
     * retryOnConflict: Use in \Elastica\Client::updateDocument
22
     * bigintConversion: Set to true to enable the JSON bigint to string conversion option (see issue #717)
23
     *
24
     * @var array
25
     */
26
    protected $configuration = [
27
        'host' => null,
28
        'port' => null,
29
        'path' => null,
30
        'url' => null,
31
        'proxy' => null,
32
        'transport' => null,
33
        'persistent' => true,
34
        'timeout' => null,
35
        'connections' => [], // host, port, path, transport, compression, persistent, timeout, username, password, auth_type, config -> (curl, headers, url)
36
        'roundRobin' => false,
37
        'retryOnConflict' => 0,
38
        'bigintConversion' => false,
39
        'username' => null,
40
        'password' => null,
41
        'auth_type' => null, //basic, digest, gssnegotiate, ntlm
42
    ];
43
44
    /**
45
     * Create configuration.
46
     *
47
     * @param array $config Additional config
48
     *
49
     * @return ClientConfiguration
50
     */
51
    public static function fromArray(array $config): self
52
    {
53
        $clientConfiguration = new static();
54
        foreach ($config as $key => $value) {
55
            $clientConfiguration->set($key, $value);
56
        }
57
58
        return $clientConfiguration;
59
    }
60
61
    /**
62
     * Create configuration from Dsn string. Example of valid DSN strings:
63
     * - http://localhost
64
     * - http://foo:bar@localhost:1234?timeout=4&persistant=false
65
     * - pool(http://127.0.0.1 http://127.0.0.2/bar?timeout=4).
66
     *
67
     * @return ClientConfiguration
68
     */
69
    public static function fromDsn(string $dsnString): self
70
    {
71
        try {
72
            $func = DsnParser::parseFunc($dsnString);
73
        } catch (DsnException $e) {
74
            throw new InvalidException(\sprintf('DSN "%s" is invalid.', $dsnString), 0, $e);
75
        }
76
77
        if ('dsn' == $func->getName()) {
78
            /** @var Url $dsn */
79
            $dsn = $func->first();
80
            $clientConfiguration = self::fromArray(self::parseDsn($dsn));
81
        } elseif ('pool' == $func->getName()) {
82
            $connections = [];
83
            $clientConfiguration = new static();
84
            foreach ($func->getArguments() as $arg) {
85
                $connections[] = self::parseDsn($arg);
0 ignored issues
show
Documentation introduced by
$arg is of type object<Nyholm\Dsn\Config...\Dsn\Configuration\Dsn>, but the function expects a object<Nyholm\Dsn\Configuration\Url>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
86
            }
87
            $clientConfiguration->set('connections', $connections);
88
        } else {
89
            throw new FunctionNotSupportedException($dsnString, $func->getName());
90
        }
91
92 View Code Duplication
        foreach ($func->getParameters() as $optionName => $optionValue) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
93
            if ('false' === $optionValue) {
94
                $optionValue = false;
95
            } elseif ('true' === $optionValue) {
96
                $optionValue = true;
97
            } elseif (\is_numeric($optionValue)) {
98
                $optionValue = (int) $optionValue;
99
            }
100
101
            $clientConfiguration->set($optionName, $optionValue);
102
        }
103
104
        return $clientConfiguration;
105
    }
106
107
    /**
108
     * Returns a specific config key or the whole config array if not set.
109
     *
110
     * @throws InvalidException if the given key is not found in the configuration
111
     *
112
     * @return mixed Config value
113
     */
114
    public function get(string $key)
115
    {
116
        if (empty($key)) {
117
            return $this->configuration;
118
        }
119
120
        if (!$this->has($key)) {
121
            throw new InvalidException('Config key is not set: '.$key);
122
        }
123
124
        return $this->configuration[$key];
125
    }
126
127
    /**
128
     * Returns boolean indicates if configuration has key.
129
     */
130
    public function has(string $key): bool
131
    {
132
        return \array_key_exists($key, $this->configuration);
133
    }
134
135
    /**
136
     * Return all configuration.
137
     */
138
    public function getAll(): array
139
    {
140
        return $this->configuration;
141
    }
142
143
    /**
144
     * @param string $key   Key to set
145
     * @param mixed  $value Value
146
     */
147
    public function set(string $key, $value): void
148
    {
149
        $this->configuration[$key] = $value;
150
    }
151
152
    /**
153
     * Add value to a key. If original value is not an array, value is wrapped.
154
     *
155
     * @param string $key   Key to add
156
     * @param mixed  $value Value
157
     */
158
    public function add(string $key, $value): void
159
    {
160
        if (!\array_key_exists($key, $this->configuration)) {
161
            $this->configuration[$key] = [$value];
162
        } else {
163
            if (\is_array($this->configuration[$key])) {
164
                $this->configuration[$key][] = $value;
165
            } else {
166
                $this->configuration[$key] = [$this->configuration[$key], $value];
167
            }
168
        }
169
    }
170
171
    private static function parseDsn(Url $dsn): array
172
    {
173
        $data = ['host' => $dsn->getHost()];
174
175
        if (null !== $dsn->getScheme()) {
176
            $data['transport'] = $dsn->getScheme();
177
        }
178
179
        if (null !== $dsn->getUser()) {
180
            $data['username'] = $dsn->getUser();
181
        }
182
183
        if (null !== $dsn->getPassword()) {
184
            $data['password'] = $dsn->getPassword();
185
        }
186
187
        if (null !== $dsn->getUser() && null !== $dsn->getPassword()) {
188
            $data['auth_type'] = 'basic';
189
        }
190
191
        if (null !== $dsn->getPort()) {
192
            $data['port'] = $dsn->getPort();
193
        }
194
195
        if (null !== $dsn->getPath()) {
196
            $data['path'] = $dsn->getPath();
197
        }
198
199 View Code Duplication
        foreach ($dsn->getParameters() as $optionName => $optionValue) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
200
            if ('false' === $optionValue) {
201
                $optionValue = false;
202
            } elseif ('true' === $optionValue) {
203
                $optionValue = true;
204
            } elseif (\is_numeric($optionValue)) {
205
                $optionValue = (int) $optionValue;
206
            }
207
208
            $data[$optionName] = $optionValue;
209
        }
210
211
        return $data;
212
    }
213
}
214