ExtendedUriTrait   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 217
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 43
c 1
b 0
f 0
dl 0
loc 217
rs 10
wmc 20

10 Methods

Rating   Name   Duplication   Size   Complexity  
A getQueryParameters() 0 5 2
A withPathSegments() 0 4 1
A getPathSegments() 0 5 1
A getPassword() 0 5 2
A getStandardPort() 0 9 2
A getTopLevelDomain() 0 15 4
A getIpAddress() 0 12 3
A withQueryParameters() 0 3 1
A getPathExtension() 0 11 2
A getUsername() 0 6 2
1
<?php
2
3
namespace Riimu\Kit\UrlParser;
4
5
/**
6
 * Provides convenience methods for accessing the standard URI interface.
7
 *
8
 * ExtendedUriTrait provides additional methods for common use cases that build
9
 * on top the standard URI interface. Note that due to RFC 3986 compliance, the
10
 * methods do not treat the plus sign as a space character.
11
 *
12
 * @author Riikka Kalliomäki <[email protected]>
13
 * @copyright Copyright (c) 2015-2017 Riikka Kalliomäki
14
 * @license http://opensource.org/licenses/mit-license.php MIT License
15
 */
16
trait ExtendedUriTrait
17
{
18
    /** @var array<string,int> List of known ports for different schemes */
19
    private static $standardPorts = [
20
        'ftp' => 21,
21
        'http' => 80,
22
        'https' => 443,
23
    ];
24
25
    /**
26
     * Returns the scheme component of the URI.
27
     * @return string The URI scheme
28
     */
29
    abstract public function getScheme();
30
31
    /**
32
     * Returns the standard port for the current scheme.
33
     *
34
     * The known ports are:
35
     *
36
     * - ftp : 21
37
     * - http : 80
38
     * - https : 443
39
     *
40
     * @return int|null The standard port for the current scheme or null if not known
41
     */
42
    public function getStandardPort()
43
    {
44
        $scheme = $this->getScheme();
45
46
        if (isset(self::$standardPorts[$scheme])) {
47
            return self::$standardPorts[$scheme];
48
        }
49
50
        return null;
51
    }
52
53
    /**
54
     * Returns the user information component of the URI.
55
     * @return string The URI user information
56
     */
57
    abstract public function getUserInfo();
58
59
    /**
60
     * Returns the decoded username from the URI.
61
     * @return string The decoded username
62
     */
63
    public function getUsername()
64
    {
65
        $info = $this->getUserInfo();
66
        $username = strstr($info, ':', true);
67
68
        return rawurldecode($username === false ? $info : $username);
69
    }
70
71
    /**
72
     * Returns the decoded password from the URI.
73
     * @return string The decoded password
74
     */
75
    public function getPassword()
76
    {
77
        $password = strstr($this->getUserInfo(), ':');
78
79
        return $password === false ? '' : rawurldecode(substr($password, 1));
80
    }
81
82
    /**
83
     * Returns the host component of the URI.
84
     * @return string The URI host
85
     */
86
    abstract public function getHost();
87
88
    /**
89
     * Returns the IP address from the host component.
90
     * @return string|null IP address from the host or null if the host is not an IP address
91
     */
92
    public function getIpAddress()
93
    {
94
        $pattern = new UriPattern();
95
        $pattern->matchHost($this->getHost(), $match);
96
97
        if (isset($match['IPv4address'])) {
98
            return $match['IPv4address'];
99
        } elseif (isset($match['IP_literal'])) {
100
            return preg_replace('/^\\[(v[^.]+\\.)?([^\\]]+)\\]$/', '$2', $match['IP_literal']);
101
        }
102
103
        return null;
104
    }
105
106
    /**
107
     * Returns the top level domain from the host component.
108
     *
109
     * Note that if the host component represents an IP address, an empty string
110
     * will be returned instead. Additionally, if the host component ends in a
111
     * period, the section prior that period will be returned instead. If no
112
     * period is present in the host component, the entire host component will
113
     * be returned.
114
     *
115
     * @return string The top level domain or an empty string, if no TLD is present
116
     */
117
    public function getTopLevelDomain()
118
    {
119
        if ($this->getIpAddress() !== null) {
120
            return '';
121
        }
122
123
        $host = rawurldecode($this->getHost());
124
        $tld = strrchr($host, '.');
125
126
        if ($tld === '.') {
127
            $host = substr($host, 0, -1);
128
            $tld = strrchr($host, '.');
129
        }
130
131
        return $tld === false ? $host : substr($tld, 1);
132
    }
133
134
    /**
135
     * Returns the path component of the URI.
136
     * @return string The URI path
137
     */
138
    abstract public function getPath();
139
140
    /**
141
     * Returns the decoded path segments from the path component.
142
     * @return string[] The decoded non empty path segments
143
     */
144
    public function getPathSegments()
145
    {
146
        return array_values(array_map(
147
            'rawurldecode',
148
            array_filter(explode('/', $this->getPath()), 'strlen')
149
        ));
150
    }
151
152
    /**
153
     * Returns the file extension for the last segment in the path.
154
     * @return string The file extension from the last non empty segment
155
     */
156
    public function getPathExtension()
157
    {
158
        $segments = $this->getPathSegments();
159
        $filename = array_pop($segments);
160
        $extension = strrchr((string) $filename, '.');
161
162
        if ($extension === false) {
163
            return '';
164
        }
165
166
        return substr($extension, 1);
167
    }
168
169
    /**
170
     * Returns the query string of the URI.
171
     * @return string The URI query string
172
     */
173
    abstract public function getQuery();
174
175
    /**
176
     * Returns the decoded parameters parsed from the query component.
177
     * @return array The decoded parameters parsed from the query
178
     */
179
    public function getQueryParameters()
180
    {
181
        parse_str(str_replace('+', '%2B', $this->getQuery()), $parameters);
182
183
        return $parameters ? $parameters : [];
184
    }
185
186
    /**
187
     * Returns a URI instance with the specified path.
188
     * @param string $path The path to use with the new instance
189
     * @return static A new instance with the specified path
190
     */
191
    abstract public function withPath($path);
192
193
    /**
194
     * Returns a URI instance with path constructed from given path segments.
195
     *
196
     * Note that all the segments are assumed to be decoded. Thus any percent
197
     * encoded characters in the segments will be double encoded. Due to
198
     * aggressive encoding, this method will encode even the forward slashes in
199
     * the provided segments.
200
     *
201
     * @param string[] $segments Path segments for the new path
202
     * @return static A new instance with the specified path
203
     */
204
    public function withPathSegments(array $segments)
205
    {
206
        return $this->withPath(
207
            implode('/', array_map('rawurlencode', array_filter($segments, 'strlen')))
208
        );
209
    }
210
211
    /**
212
     * Returns a URI instance with the specified query string.
213
     * @param string $query The query string to use with the new instance
214
     * @return static A new instance with the specified query string
215
     */
216
    abstract public function withQuery($query);
217
218
    /**
219
     * Returns a URI instance with the query constructed from the given parameters.
220
     *
221
     * The provided associative array will be used to construct the query
222
     * string. Even characters such as the ampersand and equal sign will be
223
     * encoded in resulting string. Note the any percent encoded characters will
224
     * be double encoded, since this method assumes that all the values are
225
     * unencoded.
226
     *
227
     * @param array $parameters Parameters for the query
228
     * @return static A new instance with the specified query string
229
     */
230
    public function withQueryParameters(array $parameters)
231
    {
232
        return $this->withQuery(http_build_query($parameters, '', '&', PHP_QUERY_RFC3986));
233
    }
234
}
235