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

Dsn::getFloat()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

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