Uri::__construct()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 17
nc 2
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Resilient\Http;
4
5
use InvalidArgumentException;
6
use \Psr\Http\Message\UriInterface;
7
8
class Uri implements UriInterface
9
{
10
    /**
11
     * Uri scheme (without "://" suffix)
12
     *
13
     * @var string
14
     */
15
    protected $scheme = '';
16
17
    /**
18
     * Uri user
19
     *
20
     * @var string
21
     */
22
    protected $user = '';
23
24
    /**
25
     * Uri password
26
     *
27
     * @var string
28
     */
29
    protected $password = '';
30
31
    /**
32
     * Uri host
33
     *
34
     * @var string
35
     */
36
    protected $host = '';
37
38
    /**
39
     * Uri port number
40
     *
41
     * @var null|int
42
     */
43
    protected $port;
44
45
    /**
46
     * Uri path
47
     *
48
     * @var string
49
     */
50
    protected $path = '';
51
52
    /**
53
     * Uri query string (without "?" prefix)
54
     *
55
     * @var string
56
     */
57
    protected $query = '';
58
59
    /**
60
     * Uri fragment string (without "#" prefix)
61
     *
62
     * @var string
63
     */
64
    protected $fragment = '';
65
66
    /**
67
     * Instance new Uri.
68
     *
69
     * @param string $scheme   Uri scheme.
70
     * @param string $host     Uri host.
71
     * @param int    $port     Uri port number.
72
     * @param string $path     Uri path.
73
     * @param string $query    Uri query string.
74
     * @param string $fragment Uri fragment.
75
     * @param string $user     Uri user.
76
     * @param string $password Uri password.
77
     */
78
    public function __construct (
79
        $scheme,
80
        $host,
81
        $port = null,
82
        $path = '/',
83
        $query = '',
84
        $fragment = '',
85
        $user = '',
86
        $password = ''
87
    ) {
88
        $this->scheme = $this->filterScheme($scheme);
89
        $this->host = $host;
90
        $this->port = $this->filterPort($port);
91
        $this->path = empty($path) ? '/' : $this->filterPath($path);
92
        $this->query = $this->filterQuery($query);
93
        $this->fragment = $this->filterQuery($fragment);
94
        $this->user = $user;
95
        $this->password = $password;
96
    }
97
98
    /**
99
     * {@inheritdoc}
100
     */
101
    public function getScheme ()
102
    {
103
        return $this->scheme;
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109
    public function getAuthority ()
110
    {
111
        $userInfo = $this->getUserInfo();
112
        $host = $this->getHost();
113
        $port = $this->getPort();
114
115
        return ($userInfo ? $userInfo . '@' : '') . $host . ($port !== null ? ':' . $port : '');
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121
    public function getUserInfo ()
122
    {
123
        return $this->user . ($this->password ? ':' . $this->password : '');
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129
    public function getHost ()
130
    {
131
        return $this->host;
132
    }
133
134
    /**
135
     * {@inheritdoc}
136
     */
137
    public function getPort ()
138
    {
139
        return $this->port !== null && !$this->hasStandardPort() ? $this->port : null;
140
    }
141
142
    /**
143
     * {@inheritdoc}
144
     */
145
    public function getPath ()
146
    {
147
        return $this->path;
148
    }
149
150
    /**
151
     * {@inheritdoc}
152
     */
153
    public function getQuery ()
154
    {
155
        return $this->query;
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161
    public function getFragment ()
162
    {
163
        return $this->fragment;
164
    }
165
166
    /**
167
     * {@inheritdoc}
168
     */
169
    public function withScheme ($scheme)
170
    {
171
        $scheme = $this->filterScheme($scheme);
172
        $clone = clone $this;
173
        $clone->scheme = $scheme;
174
175
        return $clone;
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     */
181
    public function withUserInfo ($user, $password = null)
182
    {
183
        $clone = clone $this;
184
        $clone->user = $user;
185
        $clone->password = $password ? $password : '';
186
187
        return $clone;
188
    }
189
190
    /**
191
     * {@inheritdoc}
192
     */
193
    public function withHost ($host)
194
    {
195
        $clone = clone $this;
196
        $clone->host = $host;
197
198
        return $clone;
199
    }
200
201
    /**
202
     * {@inheritdoc}
203
     */
204
    public function withPort ($port)
205
    {
206
        $port = $this->filterPort($port);
207
        $clone = clone $this;
208
        $clone->port = $port;
209
210
        return $clone;
211
    }
212
213
    /**
214
     * {@inheritdoc}
215
     */
216
    public function withPath ($path)
217
    {
218
        $clone = clone $this;
219
        $clone->path = $this->filterPath($path);
220
221
        return $clone;
222
    }
223
224
    /**
225
     * {@inheritdoc}
226
     */
227
    public function withQuery ($query)
228
    {
229
        return $this->withString($query);
230
    }
231
232
    /**
233
     * {@inheritdoc}
234
     */
235
    public function withFragment ($fragment)
236
    {
237
        return $this->withString($fragment, 'fragment');
238
    }
239
240
    /**
241
     * withString function.
242
     *
243
     * @access protected
244
     * @param string $string
245
     * @param string $name (default: 'query')
246
     * @return Uri
247
     */
248
    protected function withString ($string, $name = 'query')
249
    {
250
        if (!is_string($string) && !method_exists($string, '__toString')) {
251
            throw new InvalidArgumentException('Uri fragment must be a string');
252
        }
253
        $string = ltrim((string) $string, '#');
254
        $clone = clone $this;
255
        $clone->$name = $this->filterQuery($string);
256
257
        return $clone;
258
    }
259
260
    /**
261
     * {@inheritdoc}
262
     */
263
    public function __toString ()
264
    {
265
        $scheme = $this->getScheme();
266
        $authority = $this->getAuthority();
267
        $path = $this->getPath();
268
        $query = $this->getQuery();
269
        $fragment = $this->getFragment();
270
271
        return ($scheme ? $scheme . ':' : '')
272
            . ($authority ? '//' . $authority : '')
273
            . $path
274
            . ($query ? '?' . $query : '')
275
            . ($fragment ? '#' . $fragment : '');
276
    }
277
278
    /*
279
        END OF UriInterface Implementation
280
    */
281
282
    /**
283
     * filter scheme given to only allow certain scheme, no file:// or ftp:// or other scheme because its http message uri interface
284
     *
285
     * @access protected
286
     * @param string $scheme
287
     * @return string $scheme
288
     * @throws InvalidArgumentException if not corret scheme is present
289
     */
290
    protected function filterScheme (string $scheme)
291
    {
292
        static $valid = [
293
            '' => true,
294
            'https' => true,
295
            'http' => true,
296
        ];
297
298
        $scheme = str_replace('://', '', strtolower($scheme));
299
        if (!isset($valid[$scheme])) {
300
            throw new InvalidArgumentException('Uri scheme must be one of: "", "https", "http"');
301
        }
302
303
        return $scheme;
304
    }
305
306
307
    /**
308
     * Filter allowable port to minimize risk
309
     *
310
     * @access protected
311
     * @param integer|null $port
312
     * @return null|integer $port
313
     * @throws InvalidArgumentException for incorrect port assigned
314
     */
315
    protected function filterPort ($port)
316
    {
317
        if ((integer) $port >= 0 && (integer) $port <= 65535) {
318
            return $port;
319
        }
320
321
        throw new InvalidArgumentException('Uri port must be null or an integer between 1 and 65535 (inclusive)');
322
    }
323
324
    /**
325
     * Path allowed chars filter, no weird path on uri yes?.
326
     *
327
     * @access protected
328
     * @param string $path
329
     * @return string of cleared path
330
     */
331
    protected function filterPath ($path)
332
    {
333
        return preg_replace_callback(
334
            '/(?:[^a-zA-Z0-9_\-\.~:@&=\+\$,\/;%]+|%(?![A-Fa-f0-9]{2}))/',
335
            function($match) {
336
                return rawurlencode($match[0]);
337
            },
338
            $path
339
        );
340
    }
341
342
    /**
343
     * replace query to clear not allowed chars
344
     *
345
     * @access protected
346
     * @param string $query
347
     * @return string of replaced query
348
     */
349
    protected function filterQuery ($query)
350
    {
351
        return preg_replace_callback(
352
            '/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/',
353
            function($match) {
354
                return rawurlencode($match[0]);
355
            },
356
            $query
357
        );
358
    }
359
360
    /**
361
     * cek if current uri scheme use standard port
362
     *
363
     * @access protected
364
     * @return boolean
365
     */
366
    protected function hasStandardPort ()
367
    {
368
        return ($this->scheme === 'http' && $this->port === 80) || ($this->scheme === 'https' && $this->port === 443);
369
    }
370
371
    /**
372
     * get Base Url
373
     *
374
     * @access public
375
     * @return string
376
     */
377
    public function getBaseUrl ()
378
    {
379
        $scheme = $this->getScheme();
380
        $authority = $this->getAuthority();
381
382
        return ($scheme ? $scheme . ':' : '')
383
            . ($authority ? '//' . $authority : '');
384
    }
385
}
386