Completed
Pull Request — master (#37)
by Eugene
03:16
created

Client::authenticate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 9
cts 9
cp 1
rs 9.7998
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Tarantool Client package.
7
 *
8
 * (c) Eugene Leonovich <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Tarantool\Client;
15
16
use Tarantool\Client\Connection\Connection;
17
use Tarantool\Client\Exception\RequestFailed;
18
use Tarantool\Client\Packer\Packer;
19
use Tarantool\Client\Request\Authenticate;
20
use Tarantool\Client\Request\Call;
21
use Tarantool\Client\Request\Evaluate;
22
use Tarantool\Client\Request\Execute;
23
use Tarantool\Client\Request\Ping;
24
use Tarantool\Client\Request\Request;
25
use Tarantool\Client\Schema\Index;
26
use Tarantool\Client\Schema\Space;
27
28
final class Client
29
{
30
    private $connection;
31
    private $packer;
32
    private $salt;
33
    private $username;
34
    private $password;
35
    private $spaces = [];
36
37 131
    public function __construct(Connection $connection, Packer $packer)
38
    {
39 131
        $this->connection = $connection;
40 131
        $this->packer = $packer;
41 131
    }
42
43 2
    public function getConnection() : Connection
44
    {
45 2
        return $this->connection;
46
    }
47
48 2
    public function getPacker() : Packer
49
    {
50 2
        return $this->packer;
51
    }
52
53 125
    public function connect() : void
54
    {
55 125
        $this->salt = $this->connection->open();
56
57 104
        if ($this->username) {
58 2
            $this->authenticate($this->username, $this->password);
59
        }
60 104
    }
61
62 2
    public function disconnect() : void
63
    {
64 2
        $this->connection->close();
65 2
        $this->salt = null;
66 2
    }
67
68 6
    public function isDisconnected() : bool
69
    {
70 6
        return $this->connection->isClosed() || !$this->salt;
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->salt of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
71
    }
72
73 6
    public function authenticate(string $username, string $password = '') : void
74
    {
75 6
        if ($this->isDisconnected()) {
76 4
            $this->salt = $this->connection->open();
77
        }
78
79 6
        $request = new Authenticate($this->salt, $username, $password);
80 6
        $this->sendRequest($request);
81
82 3
        $this->username = $username;
83 3
        $this->password = $password;
84
85 3
        $this->flushSpaces();
86 3
    }
87
88 6
    public function ping() : void
89
    {
90 6
        $request = new Ping();
91
92 6
        $this->sendRequest($request);
93
    }
94
95 61
    public function getSpace(string $spaceName) : Space
96
    {
97 61
        if (isset($this->spaces[$spaceName])) {
98 3
            return $this->spaces[$spaceName];
99
        }
100
101 61
        $spaceId = $this->getSpaceIdByName($spaceName);
102
103 59
        return $this->spaces[$spaceName] = $this->spaces[$spaceId] = new Space($this, $spaceId);
104
    }
105
106 64
    public function getSpaceById(int $spaceId) : Space
107
    {
108 64
        if (isset($this->spaces[$spaceId])) {
109 2
            return $this->spaces[$spaceId];
110
        }
111
112 64
        return $this->spaces[$spaceId] = new Space($this, $spaceId);
113
    }
114
115 5
    public function call(string $funcName, ...$args) : array
116
    {
117 5
        $request = new Call($funcName, $args);
118
119 5
        return $this->sendRequest($request)->getBodyField(IProto::DATA);
120
    }
121
122 4
    public function executeQuery(string $sql, array $params = []) : SqlQueryResult
123
    {
124 4
        $request = new Execute($sql, $params);
125 4
        $response = $this->sendRequest($request);
126
127 4
        return new SqlQueryResult(
128 4
            $response->getBodyField(IProto::DATA),
129 4
            $response->getBodyField(IProto::METADATA)
130
        );
131
    }
132
133 4
    public function executeUpdate(string $sql, array $params = []) : int
134
    {
135 4
        $request = new Execute($sql, $params);
136
137 4
        return $this->sendRequest($request)->getBodyField(IProto::SQL_INFO)[0];
138
    }
139
140 28
    public function evaluate(string $expr, array $args = []) : array
141
    {
142 28
        $request = new Evaluate($expr, $args);
143
144 28
        return $this->sendRequest($request)->getBodyField(IProto::DATA);
145
    }
146
147 5
    public function flushSpaces() : void
148
    {
149 5
        $this->spaces = [];
150 5
    }
151
152 108
    public function sendRequest(Request $request) : Response
153
    {
154 108
        if ($this->connection->isClosed()) {
155 106
            $this->connect();
156
        }
157
158 106
        $data = $this->packer->pack($request);
159 106
        $data = $this->connection->send($data);
160
161 102
        $response = $this->packer->unpack($data);
162 102
        if (!$response->isError()) {
163 98
            return $response;
164
        }
165
166 20
        throw RequestFailed::fromErrorResponse($response);
167
    }
168
169 61
    private function getSpaceIdByName(string $spaceName) : int
170
    {
171 61
        $schema = $this->getSpaceById(Space::VSPACE_ID);
172 61
        $data = $schema->select([$spaceName], Index::SPACE_NAME);
173
174 61
        if (empty($data)) {
175 3
            throw RequestFailed::unknownSpace($spaceName);
176
        }
177
178 59
        return $data[0][0];
179
    }
180
}
181