Completed
Push — master ( 00e7ae...7b7009 )
by Tobias
03:17
created

DSN::isValid()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

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