DSN::parseHosts()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
ccs 10
cts 10
cp 1
cc 3
nc 3
nop 1
crap 3
1
<?php
2
3
/*
4
 * This file is part of php-cache organization.
5
 *
6
 * (c) 2015 Aaron Scherer <[email protected]>, Tobias Nyholm <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace Cache\AdapterBundle;
13
14
/**
15
 * @author Aaron Scherer <[email protected]>
16
 *
17
 * @see    https://github.com/snc/SncRedisBundle/blob/master/DependencyInjection/Configuration/RedisDsn.php
18
 */
19
final class DSN
20
{
21
    private static $PORTS = [
22
        'redis' => 6379,
23
        'mongodb' => 27017,
24
        'tcp' => 6379,
25
    ];
26
27
    /**
28
     * @var string
29
     */
30
    protected $dsn;
31
32
    /**
33
     * @var string
34
     */
35
    protected $protocol;
36
37
    /**
38
     * @var array
39
     */
40
    protected $authentication;
41
42
    /**
43
     * @var array
44
     */
45
    protected $hosts;
46
47
    /**
48
     * @var int
49
     */
50
    protected $database;
51
52
    /**
53
     * @var array
54
     */
55
    protected $parameters = [];
56
57
    /**
58
     * Constructor.
59
     *
60
     * @param string $dsn
61
     */
62 92
    public function __construct($dsn)
63
    {
64 92
        $this->dsn = $dsn;
65 92
        $this->parseDsn($dsn);
66 92
    }
67
68
    /**
69
     * @return string
70
     */
71 16
    public function getDsn()
72
    {
73 16
        return $this->dsn;
74
    }
75
76
    /**
77
     * @return string
78
     */
79 92
    public function getProtocol()
80
    {
81 92
        return $this->protocol;
82
    }
83
84
    /**
85
     * @return int|null
86
     */
87 18
    public function getDatabase()
88
    {
89 18
        return $this->database;
90
    }
91
92
    /**
93
     * @return array
94
     */
95 14
    public function getHosts()
96
    {
97 14
        return $this->hosts;
98
    }
99
100
    /**
101
     * @return null|string
102
     */
103 15
    public function getFirstHost()
104
    {
105 15
        return $this->hosts[0]['host'];
106
    }
107
108
    /**
109
     * @return null|int
110
     */
111 16
    public function getFirstPort()
112
    {
113 16
        return $this->hosts[0]['port'];
114
    }
115
116
    /**
117
     * @return array
118
     */
119
    public function getAuthentication()
120
    {
121
        return $this->authentication;
122
    }
123
124 5
    public function getUsername()
125
    {
126 5
        return $this->authentication['username'];
127
    }
128
129 17
    public function getPassword()
130
    {
131 17
        return $this->authentication['password'];
132
    }
133
134
    /**
135
     * @return array
136
     */
137 8
    public function getParameters()
138
    {
139 8
        return $this->parameters;
140
    }
141
142
    /**
143
     * @return bool
144
     */
145 16
    public function isValid()
146
    {
147 16
        if (null === $this->getProtocol()) {
148 4
            return false;
149
        }
150
151 12
        if (!in_array($this->getProtocol(), ['redis', 'mongodb', 'tcp'])) {
152
            return false;
153
        }
154
155 12
        if (empty($this->getHosts())) {
156
            return false;
157
        }
158
159 12
        return true;
160
    }
161
162 92
    private function parseProtocol($dsn)
163
    {
164 92
        $regex = '/^(\w+):\/\//i';
165
166 92
        preg_match($regex, $dsn, $matches);
167
168 92
        if (isset($matches[1])) {
169 89
            $protocol = $matches[1];
170 89
            if (!in_array($protocol, ['redis', 'mongodb', 'tcp'])) {
171 1
                return false;
172
            }
173
174 88
            $this->protocol = $protocol;
175
        }
176 91
    }
177
178
    /**
179
     * @param string $dsn
180
     */
181 92
    private function parseDsn($dsn)
182
    {
183 92
        $this->parseProtocol($dsn);
184 92
        if (null === $this->getProtocol()) {
185 4
            return;
186
        }
187
188
        // Remove the protocol
189 88
        $dsn = str_replace($this->protocol.'://', '', $dsn);
190
191
        // Parse and remove auth if they exist
192 88
        if (false !== $pos = strrpos($dsn, '@')) {
193 39
            $temp = explode(':', str_replace('\@', '@', substr($dsn, 0, $pos)));
194 39
            $dsn = substr($dsn, $pos + 1);
195
196 39
            $auth = [];
197 39
            if (2 === count($temp)) {
198 23
                $auth['username'] = $temp[0];
199 23
                $auth['password'] = $temp[1];
200
            } else {
201 16
                $auth['password'] = $temp[0];
202
            }
203
204 39
            $this->authentication = $auth;
205
        }
206
207 88
        if (false !== strpos($dsn, '?')) {
208 8
            if (false === strpos($dsn, '/')) {
209 2
                $dsn = str_replace('?', '/?', $dsn);
210
            }
211
        }
212
213 88
        $temp = explode('/', $dsn);
214 88
        $this->parseHosts($temp[0]);
215
216 88
        if (isset($temp[1])) {
217 51
            $params = $temp[1];
218 51
            $temp = explode('?', $params);
219 51
            $this->database = empty($temp[0]) ? null : $temp[0];
220 51
            if (isset($temp[1])) {
221 8
                $this->parseParameters($temp[1]);
222
            }
223
        }
224 88
    }
225
226 88
    private function parseHosts($hostString)
227
    {
228 88
        preg_match_all('/(?P<host>[\w\-._]+)(?::(?P<port>\d+))?/mi', $hostString, $matches);
229
230 88
        $hosts = [];
231 88
        foreach ($matches['host'] as $index => $match) {
232 88
            $port = !empty($matches['port'][$index])
233 46
                ? (int) $matches['port'][$index]
234 88
                : self::$PORTS[$this->protocol];
235 88
            $hosts[] = ['host' => $match, 'port' => $port];
236
        }
237
238 88
        $this->hosts = $hosts;
239 88
    }
240
241
    /**
242
     * @param string $params
243
     *
244
     * @return string
245
     */
246 8
    protected function parseParameters($params)
247
    {
248 8
        $parameters = explode('&', $params);
249
250 8
        foreach ($parameters as $parameter) {
251 8
            $kv = explode('=', $parameter, 2);
252 8
            $this->parameters[$kv[0]] = isset($kv[1]) ? $kv[1] : null;
253
        }
254
255 8
        return '';
256
    }
257
}
258