Passed
Push — main ( 73fb8f...1ab7b5 )
by Stephen
06:35
created

Uri   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 295
Duplicated Lines 0 %

Importance

Changes 9
Bugs 0 Features 1
Metric Value
eloc 80
dl 0
loc 295
rs 8.8
c 9
b 0
f 1
wmc 45

19 Methods

Rating   Name   Duplication   Size   Complexity  
A addQueryParam() 0 13 6
A addPort() 0 9 2
A __construct() 0 3 1
A host() 0 3 1
B fromString() 0 33 8
A queryParams() 0 3 1
A addPath() 0 9 3
B toString() 0 32 7
A path() 0 3 1
A addHost() 0 9 2
A __toString() 0 3 1
A addFragment() 0 9 3
A build() 0 3 1
A scheme() 0 3 1
A addQuery() 0 9 2
A fragment() 0 3 1
A query() 0 3 1
A port() 0 3 1
A addScheme() 0 9 2

How to fix   Complexity   

Complex Class

Complex classes like Uri often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Uri, and based on these observations, apply Extract Interface, too.

1
<?php declare(strict_types=1);
2
3
namespace JustSteveKing\UriBuilder;
4
5
use JustSteveKing\ParameterBag\ParameterBag;
6
use RuntimeException;
7
8
class Uri
9
{
10
    /**
11
     * @var string
12
     */
13
    private string $scheme = '';
14
15
    /**
16
     * @var string
17
     */
18
    private string $host = '';
19
20
    /**
21
     * @var int|null
22
     */
23
    private ?int $port = null;
24
25
    /**
26
     * @var string|null
27
     */
28
    private ?string $path = null;
29
30
    /**
31
     * @var ParameterBag
32
     */
33
    private ParameterBag $query;
34
35
    /**
36
     * @var string|null
37
     */
38
    private ?string $fragment = null;
39
40
    private function __construct()
41
    {
42
        $this->query = new ParameterBag([]);
43
    }
44
45
    /**
46
     * @return self
47
     */
48
    public static function build(): self
49
    {
50
        return new self();
51
    }
52
53
    /**
54
     * @param  string $uri
55
     * @return self
56
     */
57
    public static function fromString(string $uri): self
58
    {
59
        $original = $uri;
60
61
        $uri = parse_url($uri);
62
63
        if (! is_array($uri)) {
64
            throw new RuntimeException("URI failed to parse using parse_url, please ensure is valid URL.");
65
        }
66
67
        $url = self::build()
68
            ->addScheme($uri['scheme'] ?? null)
69
            ->addHost($uri['host'] ?? null);
70
71
        if (isset($uri['port'])) {
72
            $url->addPort($uri['port']);
73
        }
74
75
        if (isset($uri['path'])) {
76
            $url->addPath($uri['path'] ?? null);
77
        }
78
79
        if (isset($uri['query'])) {
80
            $url->addQuery(isset($uri['query']) ? $uri['query'] : null);
81
        }
82
83
        $fragment = parse_url($original, PHP_URL_FRAGMENT);
84
85
        if (! is_null($fragment) && $fragment !== false) {
86
            $url->addFragment($fragment);
87
        }
88
89
        return $url;
90
    }
91
92
    /**
93
     * @param  string|null $scheme
94
     * @return self
95
     */
96
    public function addScheme(?string $scheme): self
97
    {
98
        if (is_null($scheme)) {
99
            throw new RuntimeException("Cannot set scheme to a null value.");
100
        }
101
102
        $this->scheme = $scheme;
103
104
        return $this;
105
    }
106
107
    /**
108
     * @return string
109
     */
110
    public function scheme(): string
111
    {
112
        return $this->scheme;
113
    }
114
115
    /**
116
     * @param  string|null $host
117
     * @return self
118
     */
119
    public function addHost(?string $host): self
120
    {
121
        if (is_null($host)) {
122
            throw new RuntimeException("Cannot set host to a null value.");
123
        }
124
125
        $this->host = $host;
126
127
        return $this;
128
    }
129
130
    /**
131
     * @return string
132
     */
133
    public function host(): string
134
    {
135
        return $this->host;
136
    }
137
138
    /**
139
     * @param int|null $port
140
     * @return $this
141
     */
142
    public function addPort(?int $port): self
143
    {
144
        if (is_null($port)) {
145
            throw new RuntimeException("Cannot set port to a null value.");
146
        }
147
148
        $this->port = $port;
149
150
        return $this;
151
    }
152
153
    /**
154
     * @return int|null
155
     */
156
    public function port():? int
157
    {
158
        return $this->port;
159
    }
160
161
    /**
162
     * @param  string|null $path
163
     * @return self
164
     */
165
    public function addPath(?string $path = null): self
166
    {
167
        if (is_null($path)) {
168
            return $this;
169
        }
170
171
        $this->path = (substr($path, 0, 1) === '/') ? $path : "/{$path}";
172
173
        return $this;
174
    }
175
176
    /**
177
     * @return string|null
178
     */
179
    public function path():? string
180
    {
181
        return $this->path;
182
    }
183
184
    /**
185
     * @param  string|null $query
186
     * @return self
187
     */
188
    public function addQuery(?string $query = null): self
189
    {
190
        if (is_null($query)) {
191
            throw new RuntimeException("Cannot set query to a null value.");
192
        }
193
194
        $this->query = ParameterBag::fromString($query);
195
196
        return $this;
197
    }
198
199
    /**
200
     * @return ParameterBag
201
     */
202
    public function query(): ParameterBag
203
    {
204
        return $this->query;
205
    }
206
207
    /**
208
     * @param  string $key
209
     * @param  mixed  $value
210
     * @param  bool   $covertBoolToString
211
     * @return self
212
     */
213
    public function addQueryParam(string $key, $value, bool $covertBoolToString = false): self
214
    {
215
        if (is_array($value) || is_object($value)) {
216
            throw new RuntimeException("Cannot set Query Parameter to: array, object");
217
        }
218
219
        if ($covertBoolToString && is_bool($value)) {
220
            $value = ($value) ? 'true' : 'false';
221
        }
222
223
        $this->query->set($key, $value);
224
225
        return $this;
226
    }
227
228
    /**
229
     * @return array
230
     */
231
    public function queryParams(): array
232
    {
233
        return $this->query->all();
234
    }
235
236
    /**
237
     * @param  string $fragment
238
     * @return self
239
     */
240
    public function addFragment(string $fragment): self
241
    {
242
        if ($fragment === '') {
243
            return $this;
244
        }
245
246
        $this->fragment = (substr($fragment, 0, 1) === '#') ? $fragment : "#{$fragment}";
247
248
        return $this;
249
    }
250
251
    /**
252
     * @return string|null
253
     */
254
    public function fragment():? string
255
    {
256
        return $this->fragment;
257
    }
258
259
    /**
260
     * @return string
261
     */
262
    public function __toString(): string
263
    {
264
        return $this->toString();
265
    }
266
267
    /**
268
     * @param bool $encode
269
     * @return string
270
     */
271
    public function toString(bool $encode = false): string
272
    {
273
        $url = "{$this->scheme}://{$this->host}";
274
275
        if (! is_null($this->port)) {
276
            $url .= ":{$this->port}";
277
        }
278
279
        if (! is_null($this->path)) {
280
            $url .= "{$this->path}";
281
        }
282
283
        if (! empty($this->query->all())) {
284
            $collection = [];
285
            foreach ($this->query->all() as $key => $value) {
286
                $collection[] = "{$key}={$value}";
287
            }
288
289
            $queryParamString = implode('&', $collection);
290
291
            if ($encode) {
292
                $queryParamString = urlencode($queryParamString);
293
            }
294
295
            $url .= "?{$queryParamString}";
296
        }
297
298
        if (! is_null($this->fragment)) {
299
            $url .= "{$this->fragment}";
300
        }
301
302
        return $url;
303
    }
304
}
305