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

Uri::addPort()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
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