Completed
Push — master ( b645fc...1a7521 )
by Charis
03:32
created

Uri::__construct()   A

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
c 0
b 0
f 0
rs 9.4285
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
        $path = '/' . ltrim($path, '/');
272
273
        return ($scheme ? $scheme . ':' : '')
274
            . ($authority ? '//' . $authority : '')
275
            . $path
276
            . ($query ? '?' . $query : '')
277
            . ($fragment ? '#' . $fragment : '');
278
    }
279
280
    /*
281
        END OF UriInterface Implementation
282
    */
283
284
    /**
285
     * filter scheme given to only allow certain scheme, no file:// or ftp:// or other scheme because its http message uri interface
286
     *
287
     * @access protected
288
     * @param string $scheme
289
     * @return string $scheme
290
     * @throws InvalidArgumentException if not corret scheme is present
291
     */
292
    protected function filterScheme(string $scheme)
293
    {
294
        static $valid = [
295
            '' => true,
296
            'https' => true,
297
            'http' => true,
298
        ];
299
300
        $scheme = str_replace('://', '', strtolower($scheme));
301
        if (!isset($valid[$scheme])) {
302
            throw new InvalidArgumentException('Uri scheme must be one of: "", "https", "http"');
303
        }
304
305
        return $scheme;
306
    }
307
308
309
    /**
310
     * Filter allowable port to minimize risk
311
     *
312
     * @access protected
313
     * @param integer|null $port
314
     * @return null|integer $port
315
     * @throws InvalidArgumentException for incorrect port assigned
316
     */
317
    protected function filterPort($port)
318
    {
319
        if (is_null($port) || (is_integer($port) && ($port >= 1 && $port <= 65535))) {
320
            return $port;
321
        }
322
323
        throw new InvalidArgumentException('Uri port must be null or an integer between 1 and 65535 (inclusive)');
324
    }
325
326
    /**
327
     * Path allowed chars filter, no weird path on uri yes?.
328
     *
329
     * @access protected
330
     * @param string $path
331
     * @return string of cleared path
332
     */
333
    protected function filterPath($path)
334
    {
335
        return preg_replace_callback(
336
            '/(?:[^a-zA-Z0-9_\-\.~:@&=\+\$,\/;%]+|%(?![A-Fa-f0-9]{2}))/',
337
            function ($match) {
338
                return rawurlencode($match[0]);
339
            },
340
            $path
341
        );
342
    }
343
344
    /**
345
     * replace query to clear not allowed chars
346
     *
347
     * @access protected
348
     * @param string $query
349
     * @return string of replaced query
350
     */
351
    protected function filterQuery($query)
352
    {
353
        return preg_replace_callback(
354
            '/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/',
355
            function ($match) {
356
                return rawurlencode($match[0]);
357
            },
358
            $query
359
        );
360
    }
361
362
    /**
363
     * cek if current uri scheme use standard port
364
     *
365
     * @access protected
366
     * @return boolean
367
     */
368
    protected function hasStandardPort()
369
    {
370
        return ($this->scheme === 'http' && $this->port === 80) || ($this->scheme === 'https' && $this->port === 443);
371
    }
372
373
    /**
374
     * get Base Url
375
     *
376
     * @access public
377
     * @return string
378
     */
379
    public function getBaseUrl()
380
    {
381
        $scheme = $this->getScheme();
382
        $authority = $this->getAuthority();
383
384
        return ($scheme ? $scheme . ':' : '')
385
            . ($authority ? '//' . $authority : '');
386
    }
387
}
388