Passed
Push — master ( ac7426...a8ebef )
by Sebastian
01:33
created

Uri::getPort()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 17
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 2
nop 0
dl 0
loc 17
ccs 8
cts 8
cp 1
crap 3
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Linna Psr7
5
 *
6
 * @author Sebastian Rapetti <[email protected]>
7
 * @copyright (c) 2017, Sebastian Rapetti
8
 * @license http://opensource.org/licenses/MIT MIT License
9
 *
10
 */
11
12
namespace Linna\Psr7;
13
14
use InvalidArgumentException;
15
use Psr\Http\Message\UriInterface;
16
17
18
/**
19
 * Psr7 Uri Implementation
20
 */
21
class Uri implements UriInterface
22
{
23
    use UriTrait;
24
    
25
    /**
26
     * @var array Standard schemes
27
     */
28
    protected $standardSchemes = [
29
        'http'  => 80,
30
        'https' => 443,
31
    ];
32
    
33
    /**
34
     * @var array Url description
35
     */
36
    protected $url = [
37
        'scheme' => '',
38
        'host' => '',
39
        'port' => 0,
40
        'user' => '',
41
        'pass' => '',
42
        'path' => '',
43
        'query' => '',
44
        'fragment' => ''
45
    ];
46
    
47
    /**
48
     * Constructor.
49
     * 
50
     * @param string $uri
51
     * @throws InvalidArgumentException
52
     */
53 82
    public function __construct(string $uri)
54
    {
55 82
        if (($parsedUrl = parse_url($uri)) === false) {
56 1
            throw new InvalidArgumentException(__CLASS__.': Bad URI provided for '.__METHOD__);
57
        }
58
        
59 81
        $this->url = array_merge($this->url, $parsedUrl);
60 81
    }
61
    
62
    /**
63
     * {@inheritdoc}
64
     */
65 2
    public function getScheme() : string
66
    {
67 2
        return strtolower($this->url['scheme']);
68
    }
69
70
    /**
71
     * {@inheritdoc}
72
     */
73 26
    public function getAuthority() : string
74
    {
75 26
        if ($this->url['host'] === '') {
76 5
            return '';
77
        }
78
        
79 21
        $authority = $this->url['host'];
80
        
81 21
        if ($this->url['user'] !== '') {
82 18
            $authority = $this->getUserInfo() . '@' . $authority;
83
        }
84
        
85 21
        if ($this->url['port'] !== 0) {
86 16
            $authority .= ':' . $this->url['port'];
87
        }
88
        
89 21
        return $authority;
90
    }
91
92
    /**
93
     * {@inheritdoc}
94
     */
95 21
    public function getUserInfo() : string
96
    {
97 21
        $user = $this->url['user'];
98
        
99 21
        if ($this->url['pass'] !== '' && $this->url['pass'] !== null) {
100 17
            $user .= ':' . $this->url['pass'];
101
        }
102
        
103 21
        return ($user !== '') ? $user : '';
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109 2
    public function getHost() : string
110
    {
111 2
        return strtolower($this->url['host']);
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     */
117 8
    public function getPort() : int
118
    {
119 8
        $scheme = $this->url['scheme'];
120 8
        $port = $this->url['port'];
121
        
122 8
        $standardPort = $this->checkStandardPortForCurretScheme($scheme, $port, $this->standardSchemes);
123 8
        $standardScheme = array_key_exists($scheme, $this->standardSchemes);
124
        
125
        //scheme present and port standard - return 0
126
        //scheme present and port non standard - return port
127 8
        if ($standardPort && $standardScheme) {
128 1
            return $this->getPortForStandardScheme($standardPort, $port);
0 ignored issues
show
Bug introduced by
$standardPort of type true is incompatible with the type integer expected by parameter $standardPort of Linna\Psr7\Uri::getPortForStandardScheme(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

128
            return $this->getPortForStandardScheme(/** @scrutinizer ignore-type */ $standardPort, $port);
Loading history...
129
        }
130
        
131
        //scheme present and standard, port non present - return port
132
        //scheme non standard, port present - return port
133 7
        return $this->getNonStandardPort($port, $scheme, $standardScheme, $this->standardSchemes);
0 ignored issues
show
Bug introduced by
$standardScheme of type boolean is incompatible with the type string expected by parameter $standardScheme of Linna\Psr7\Uri::getNonStandardPort(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

133
        return $this->getNonStandardPort($port, $scheme, /** @scrutinizer ignore-type */ $standardScheme, $this->standardSchemes);
Loading history...
134
    }
135
    
136
    /**
137
     * {@inheritdoc}
138
     */
139 20
    public function getPath() : string
140
    {
141 20
        return $this->url['path'];
142
    }
143
144
    /**
145
     * {@inheritdoc}
146
     */
147 4
    public function getQuery() : string
148
    {
149 4
        return $this->url['query'];
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155 4
    public function getFragment() : string
156
    {
157 4
        return $this->url['fragment'];
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163 2
    public function withScheme(string $scheme) : UriInterface
164
    {
165 2
        if (!array_key_exists($scheme, $this->standardSchemes)) {
166 1
            throw new InvalidArgumentException(__CLASS__.': Invalid or unsupported scheme provided for '.__METHOD__);
167
        }
168
        
169 1
        $new = clone $this;
170 1
        $new->url['scheme'] = $scheme;
171
        
172 1
        return $new;
173
    }
174
    
175
    /**
176
     * {@inheritdoc}
177
     */
178 3
    public function withUserInfo(string $user, string $password = '') : UriInterface
179
    {
180 3
        $new = clone $this;
181 3
        $new->url['user'] = $user;
182 3
        $new->url['pass'] = $password;
183
        
184 3
        return $new;
185
    }
186
187
    /**
188
     * {@inheritdoc}
189
     */
190 2
    public function withHost(string $host) : UriInterface
191
    {
192 2
        if (filter_var($host, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) === false){
0 ignored issues
show
Bug introduced by
The constant Linna\Psr7\FILTER_FLAG_HOSTNAME was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant Linna\Psr7\FILTER_VALIDATE_DOMAIN was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
193 1
            throw new InvalidArgumentException(__CLASS__.': Invalid host provided for '.__METHOD__);
194
        }
195
        
196 1
        $new = clone $this;
197 1
        $new->url['host'] = $host;
198
        
199 1
        return $new;
200
    }
201
    
202
    /**
203
     * {@inheritdoc}
204
     */
205 4
    public function withPort(int $port = 0) : UriInterface
206
    {
207 4
        if ($port !== 0 && ($port < 1 || $port > 65535)) {
208 2
            throw new \InvalidArgumentException(__CLASS__.': Invalid port ('.$port.') number provided for '.__METHOD__);
209
        }
210
        
211 2
        $new = clone $this;
212 2
        $new->url['port'] = $port;
213
        
214 2
        return $new;
215
    }
216
    
217
    /**
218
     * {@inheritdoc}
219
     */
220 3 View Code Duplication
    public function withPath(string $path) : UriInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
221
    {
222 3
        if (strpos($path, '?') !== false) {
223 1
            throw new \InvalidArgumentException(__CLASS__.': Invalid path provided; must not contain a query string');
224
        }
225
        
226 2
        if (strpos($path, '#') !== false) {
227 1
            throw new \InvalidArgumentException(__CLASS__.': Invalid path provided; must not contain a URI fragment');
228
        }
229
        
230 1
        $new = clone $this;
231 1
        $new->url['path'] = $path;
232
        
233 1
        return $new;
234
    }
235
236
    /**
237
     * {@inheritdoc}
238
     */
239 4 View Code Duplication
    public function withQuery(string $query) : UriInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
240
    {
241 4
        if (strpos($query, '#') !== false) {
242 1
            throw new \InvalidArgumentException(__CLASS__.': Query string must not include a URI fragment');
243
        }
244
        
245 3
        $new = clone $this;
246 3
        $new->url['query'] = (strpos($query, '?') !== false) ? substr($query, 1) : $query;
247
        
248 3
        return $new;
249
    }
250
251
    /**
252
     * {@inheritdoc}
253
     */
254 3
    public function withFragment(string $fragment) : UriInterface
255
    {
256 3
        $new = clone $this;
257 3
        $new->url['fragment'] = (strpos($fragment, '#') !== false) ? substr($fragment, 1) : $fragment;
258
        
259 3
        return $new;
260
    }
261
262
    /**
263
     * {@inheritdoc}
264
     */
265 19
    public function __toString() : string
266
    {
267 19
        $scheme = $this->url['scheme'];
268 19
        $query = $this->url['query'];
269 19
        $fragment = $this->url['fragment'];
270
        
271 19
        return $this->createUriString(($scheme !== '') ? $scheme.'://' : '',
272 19
               $this->getAuthority(),
273 19
               $this->getPath(),
274 19
               ($query !== '') ? '?'.$query : '',
275 19
               ($fragment !== '') ? '#'. $fragment : '');
276
    }
277
}
278