Dsn::parseUds()   B
last analyzed

Complexity

Conditions 8
Paths 48

Size

Total Lines 30
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 18
c 1
b 0
f 0
nc 48
nop 1
dl 0
loc 30
rs 8.4444
ccs 18
cts 18
cp 1
crap 8
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
final class Dsn
17
{
18
    /** @var string|null */
19
    private $host;
20
21
    /** @var int|null */
22
    private $port;
23
24
    /** @var string|null */
25
    private $path;
26
27
    /** @var string */
28
    private $connectionUri;
29
30
    /** @var string|null */
31
    private $username;
32
33
    /** @var string|null */
34
    private $password;
35
36
    /** @var bool */
37
    private $isTcp = false;
38
39
    /**
40
     * @var array<string, string>
41
     * @psalm-suppress PropertyNotSetInConstructor
42
     */
43
    private $options;
44
45
    /**
46
     * @param string $connectionUri
47
     */
48 452
    private function __construct($connectionUri)
49
    {
50 452
        $this->connectionUri = $connectionUri;
51
    }
52
53 520
    public static function parse(string $dsn) : self
54
    {
55 520
        if (0 === \strpos($dsn, 'unix://') && isset($dsn[7])) {
56 156
            return self::parseUds($dsn);
57
        }
58
59 364
        if (false === $parsed = \parse_url($dsn)) {
60 12
            self::throwParseError($dsn);
61
        }
62 352
        if (!isset($parsed['scheme'], $parsed['host']) || 'tcp' !== $parsed['scheme']) {
63 44
            self::throwParseError($dsn);
64
        }
65 308
        if (isset($parsed['path']) && '/' !== $parsed['path']) {
66 4
            self::throwParseError($dsn);
67
        }
68
69 304
        $self = new self('tcp://'.$parsed['host'].':'.($parsed['port'] ?? '3301'));
70 304
        $self->host = $parsed['host'];
71 304
        $self->port = $parsed['port'] ?? 3301;
72 304
        $self->isTcp = true;
73
74 304
        if (isset($parsed['user'])) {
75 12
            $self->username = \rawurldecode($parsed['user']);
76 12
            $self->password = isset($parsed['pass']) ? \rawurldecode($parsed['pass']) : '';
77
        }
78
79 304
        if (isset($parsed['query'])) {
80 244
            \parse_str($parsed['query'], $self->options);
81
        }
82
83 304
        return $self;
84
    }
85
86 156
    private static function parseUds(string $dsn) : self
87
    {
88 156
        $parts = \explode('@', \substr($dsn, 7), 2);
89 156
        if (isset($parts[1])) {
90 16
            $parsed = \parse_url($parts[1]);
91 16
            $authority = \explode(':', $parts[0]);
92
        } else {
93 140
            $parsed = \parse_url($parts[0]);
94
        }
95
96 156
        if (false === $parsed) {
97 4
            self::throwParseError($dsn);
98
        }
99 152
        if (isset($parsed['host']) || !isset($parsed['path'])) {
100 4
            self::throwParseError($dsn);
101
        }
102
103 148
        $self = new self('unix://'.$parsed['path']);
104 148
        $self->path = \rawurldecode($parsed['path']);
105
106 148
        if (isset($authority)) {
107 16
            $self->username = \rawurldecode($authority[0]);
108 16
            $self->password = isset($authority[1]) ? \rawurldecode($authority[1]) : '';
109
        }
110
111 148
        if (isset($parsed['query'])) {
112 116
            \parse_str($parsed['query'], $self->options);
113
        }
114
115 148
        return $self;
116
    }
117
118 160
    public function getConnectionUri() : string
119
    {
120 160
        return $this->connectionUri;
121
    }
122
123 68
    public function getHost() : ?string
124
    {
125 68
        return $this->host;
126
    }
127
128 68
    public function getPort() : ?int
129
    {
130 68
        return $this->port;
131
    }
132
133 68
    public function getPath() : ?string
134
    {
135 68
        return $this->path;
136
    }
137
138 120
    public function getUsername() : ?string
139
    {
140 120
        return $this->username;
141
    }
142
143 28
    public function getPassword() : ?string
144
    {
145 28
        return $this->password;
146
    }
147
148 160
    public function isTcp() : bool
149
    {
150 160
        return $this->isTcp;
151
    }
152
153 60
    public function getString(string $name, ?string $default = null) : ?string
154
    {
155 60
        return $this->options[$name] ?? $default;
156
    }
157
158 196
    public function getBool(string $name, ?bool $default = null) : ?bool
159
    {
160 196
        if (!isset($this->options[$name])) {
161 120
            return $default;
162
        }
163
164 148
        if (null === $value = \filter_var($this->options[$name], \FILTER_VALIDATE_BOOLEAN, \FILTER_NULL_ON_FAILURE)) {
165 28
            throw new \TypeError(\sprintf('DSN option "%s" must be of type bool', $name));
166
        }
167
168 120
        return $value;
169
    }
170
171 160
    public function getInt(string $name, ?int $default = null) : ?int
172
    {
173 160
        if (!isset($this->options[$name])) {
174 100
            return $default;
175
        }
176
177 60
        if (false === $value = \filter_var($this->options[$name], \FILTER_VALIDATE_INT)) {
178 40
            throw new \TypeError(\sprintf('DSN option "%s" must be of type int', $name));
179
        }
180
181 20
        return $value;
182
    }
183
184 180
    public function getFloat(string $name, ?float $default = null) : ?float
185
    {
186 180
        if (!isset($this->options[$name])) {
187 128
            return $default;
188
        }
189
190 64
        if (false === $value = \filter_var($this->options[$name], \FILTER_VALIDATE_FLOAT)) {
191 32
            throw new \TypeError(\sprintf('DSN option "%s" must be of type float', $name));
192
        }
193
194 32
        return $value;
195
    }
196
197
    /**
198
     * @psalm-return never-returns
199
     */
200 68
    private static function throwParseError(string $dsn) : void
201
    {
202 68
        throw new \InvalidArgumentException(\sprintf('Unable to parse DSN "%s"', $dsn));
203
    }
204
}
205