Passed
Push — master ( 68b04b...f7f8f7 )
by Eugene
02:12
created

Client::fromOptions()   C

Complexity

Conditions 10
Paths 256

Size

Total Lines 33
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 10

Importance

Changes 0
Metric Value
cc 10
eloc 21
nc 256
nop 2
dl 0
loc 33
ccs 22
cts 22
cp 1
crap 10
rs 6.1333
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file is part of the tarantool/client package.
5
 *
6
 * (c) Eugene Leonovich <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Tarantool\Client;
15
16
use Tarantool\Client\Connection\StreamConnection;
17
use Tarantool\Client\Exception\RequestFailed;
18
use Tarantool\Client\Handler\DefaultHandler;
19
use Tarantool\Client\Handler\Handler;
20
use Tarantool\Client\Handler\MiddlewareHandler;
21
use Tarantool\Client\Middleware\AuthenticationMiddleware;
22
use Tarantool\Client\Middleware\Middleware;
23
use Tarantool\Client\Middleware\RetryMiddleware;
24
use Tarantool\Client\Packer\Packer;
25
use Tarantool\Client\Packer\PackerFactory;
26
use Tarantool\Client\Request\CallRequest;
27
use Tarantool\Client\Request\EvaluateRequest;
28
use Tarantool\Client\Request\ExecuteRequest;
29
use Tarantool\Client\Request\PingRequest;
30
use Tarantool\Client\Request\PrepareRequest;
31
use Tarantool\Client\Schema\Criteria;
32
use Tarantool\Client\Schema\Space;
33
34
final class Client
35
{
36
    /** @var Handler */
37
    private $handler;
38
39
    /** @var array<array-key, Space> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, Space> at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, Space>.
Loading history...
40
    private $spaces = [];
41
42 577
    public function __construct(Handler $handler)
43
    {
44 577
        $this->handler = $handler;
45 577
    }
46
47 3
    public static function fromDefaults() : self
48
    {
49 3
        return new self(new DefaultHandler(
50 3
            StreamConnection::createTcp(),
51 3
            PackerFactory::create()
52
        ));
53
    }
54
55 60
    public static function fromOptions(array $options, ?Packer $packer = null) : self
56
    {
57 60
        $connectionOptions = [];
58 60
        if (isset($options['connect_timeout'])) {
59 6
            $connectionOptions['connect_timeout'] = $options['connect_timeout'];
60
        }
61 60
        if (isset($options['socket_timeout'])) {
62 6
            $connectionOptions['socket_timeout'] = $options['socket_timeout'];
63
        }
64 60
        if (isset($options['tcp_nodelay'])) {
65 6
            $connectionOptions['tcp_nodelay'] = $options['tcp_nodelay'];
66
        }
67 60
        if (isset($options['persistent'])) {
68 6
            $connectionOptions['persistent'] = $options['persistent'];
69
        }
70
71 60
        $middleware = [];
72 60
        if (isset($options['max_retries']) && 0 !== $options['max_retries']) {
73 12
            $middleware[] = RetryMiddleware::linear($options['max_retries']);
74
        }
75 51
        if (isset($options['username'])) {
76 15
            $middleware[] = new AuthenticationMiddleware($options['username'], $options['password'] ?? '');
77
        }
78
79 39
        $connection = isset($options['uri'])
80 15
            ? StreamConnection::create($options['uri'], $connectionOptions)
81 33
            : StreamConnection::createTcp(StreamConnection::DEFAULT_TCP_URI, $connectionOptions);
82
83 9
        $handler = new DefaultHandler($connection, $packer ?? PackerFactory::create());
84
85 9
        return $middleware
86 3
            ? new self(MiddlewareHandler::create($handler, $middleware))
87 9
            : new self($handler);
88
    }
89
90 27
    public static function fromDsn(string $dsn, ?Packer $packer = null) : self
91
    {
92 27
        $dsn = Dsn::parse($dsn);
93
94 27
        $connectionOptions = [];
95 27
        if (null !== $timeout = $dsn->getFloat('connect_timeout')) {
96
            $connectionOptions['connect_timeout'] = $timeout;
97
        }
98 24
        if (null !== $timeout = $dsn->getFloat('socket_timeout')) {
99
            $connectionOptions['socket_timeout'] = $timeout;
100
        }
101 21
        if (null !== $tcpNoDelay = $dsn->getBool('tcp_nodelay')) {
102
            $connectionOptions['tcp_nodelay'] = $tcpNoDelay;
103
        }
104 18
        if (null !== $persistent = $dsn->getBool('persistent')) {
105
            $connectionOptions['persistent'] = $persistent;
106
        }
107
108 12
        $middleware = [];
109 12
        if ($maxRetries = $dsn->getInt('max_retries')) {
110
            $middleware[] = RetryMiddleware::linear($maxRetries);
111
        }
112 6
        if ($username = $dsn->getUsername()) {
113
            $middleware[] = new AuthenticationMiddleware($username, $dsn->getPassword() ?? '');
114
        }
115
116 6
        $connection = $dsn->isTcp()
117 6
            ? StreamConnection::createTcp($dsn->getConnectionUri(), $connectionOptions)
118 6
            : StreamConnection::createUds($dsn->getConnectionUri(), $connectionOptions);
119
120 6
        $handler = new DefaultHandler($connection, $packer ?? PackerFactory::create());
121
122 6
        return $middleware
123
            ? new self(MiddlewareHandler::create($handler, $middleware))
124 6
            : new self($handler);
125
    }
126
127 27
    public function withMiddleware(Middleware ...$middleware) : self
128
    {
129 27
        $new = clone $this;
130 27
        $new->handler = MiddlewareHandler::create($new->handler, $middleware);
131
132 27
        return $new;
133
    }
134
135 3
    public function withPrependedMiddleware(Middleware ...$middleware) : self
136
    {
137 3
        $new = clone $this;
138 3
        $new->handler = MiddlewareHandler::create($new->handler, $middleware, true);
139
140 3
        return $new;
141
    }
142
143 96
    public function getHandler() : Handler
144
    {
145 96
        return $this->handler;
146
    }
147
148 176
    public function getSpace(string $spaceName) : Space
149
    {
150 176
        if (isset($this->spaces[$spaceName])) {
151 3
            return $this->spaces[$spaceName];
152
        }
153
154 176
        $spaceId = $this->getSpaceIdByName($spaceName);
155
156 170
        return $this->spaces[$spaceName] = $this->spaces[$spaceId] = new Space($this->handler, $spaceId);
157
    }
158
159 188
    public function getSpaceById(int $spaceId) : Space
160
    {
161 188
        if (isset($this->spaces[$spaceId])) {
162
            return $this->spaces[$spaceId];
163
        }
164
165 188
        return $this->spaces[$spaceId] = new Space($this->handler, $spaceId);
166
    }
167
168 102
    public function ping() : void
169
    {
170 102
        $this->handler->handle(new PingRequest());
171 22
    }
172
173
    /**
174
     * @param mixed ...$args
175
     */
176 30
    public function call(string $funcName, ...$args) : array
177
    {
178 30
        return $this->handler->handle(new CallRequest($funcName, $args))
179 30
            ->getBodyField(Keys::DATA);
180
    }
181
182
    /**
183
     * @param mixed ...$args
184
     */
185 262
    public function evaluate(string $expr, ...$args) : array
186
    {
187 262
        return $this->handler->handle(new EvaluateRequest($expr, $args))
188 247
            ->getBodyField(Keys::DATA);
189
    }
190
191
    /**
192
     * @param mixed ...$params
193
     */
194 9
    public function execute(string $sql, ...$params) : Response
195
    {
196 9
        return $this->handler->handle(ExecuteRequest::fromSql($sql, $params));
197
    }
198
199
    /**
200
     * @param mixed ...$params
201
     */
202 30
    public function executeQuery(string $sql, ...$params) : SqlQueryResult
203
    {
204 30
        $response = $this->handler->handle(ExecuteRequest::fromSql($sql, $params));
205
206 30
        return new SqlQueryResult(
207 30
            $response->getBodyField(Keys::DATA),
208 30
            $response->getBodyField(Keys::METADATA)
209
        );
210
    }
211
212
    /**
213
     * @param mixed ...$params
214
     */
215 18
    public function executeUpdate(string $sql, ...$params) : SqlUpdateResult
216
    {
217 18
        $response = $this->handler->handle(ExecuteRequest::fromSql($sql, $params));
218
219 18
        return new SqlUpdateResult($response->getBodyField(Keys::SQL_INFO));
220
    }
221
222 15
    public function prepare(string $sql) : PreparedStatement
223
    {
224 15
        $response = $this->handler->handle(PrepareRequest::fromSql($sql));
225
226 15
        return new PreparedStatement(
227 15
            $this->handler,
228 15
            $response->getBodyField(Keys::STMT_ID),
229 15
            $response->getBodyField(Keys::BIND_COUNT),
230 15
            $response->getBodyField(Keys::BIND_METADATA),
231 15
            $response->tryGetBodyField(Keys::METADATA, [])
232
        );
233
    }
234
235 6
    public function flushSpaces() : void
236
    {
237 6
        $this->spaces = [];
238 6
    }
239
240 30
    public function __clone()
241
    {
242 30
        $this->spaces = [];
243 30
    }
244
245 176
    private function getSpaceIdByName(string $spaceName) : int
246
    {
247 176
        $schema = $this->getSpaceById(Space::VSPACE_ID);
248 176
        $data = $schema->select(Criteria::key([$spaceName])->andIndex(Space::VSPACE_NAME_INDEX));
249
250 176
        if ($data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
251 170
            return $data[0][0];
252
        }
253
254 6
        throw RequestFailed::unknownSpace($spaceName);
255
    }
256
}
257