Passed
Push — main ( 990aff...496765 )
by Stephen
01:20
created

Uri::fromString()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 29
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 7
eloc 15
c 2
b 0
f 0
nc 9
nop 1
dl 0
loc 29
rs 8.8333
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 string|null
22
     */
23
    private ?string $path = null;
24
25
    /**
26
     * @var ParameterBag
27
     */
28
    private ParameterBag $query;
29
30
    /**
31
     * @var string|null
32
     */
33
    private ?string $fragment = null;
34
35
    private function __construct()
36
    {
37
        $this->query = new ParameterBag([]);
38
    }
39
40
    /**
41
     * @return self
42
     */
43
    public static function build(): self
44
    {
45
        return new self();
46
    }
47
48
    /**
49
     * @param  string $uri
50
     * @return self
51
     */
52
    public static function fromString(string $uri): self
53
    {
54
        $original = $uri;
55
56
        $uri = parse_url($uri);
57
58
        if (! is_array($uri)) {
1 ignored issue
show
introduced by
The condition is_array($uri) is always true.
Loading history...
59
            throw new RuntimeException("URI failed to parse using parse_url, please ensure is valid URL.");
60
        }
61
62
        $url = self::build()
63
            ->addScheme($uri['scheme'] ?? null)
64
            ->addHost($uri['host'] ?? null);
65
66
        if (isset($uri['path'])) {
67
            $url->addPath($uri['path'] ?? null);
68
        }
69
70
        if (isset($uri['query'])) {
71
            $url->addQuery(isset($uri['query']) ? $uri['query'] : null);
72
        }
73
74
        $fragment = parse_url($original, PHP_URL_FRAGMENT);
75
76
        if (! is_null($fragment) && $fragment !== false) {
1 ignored issue
show
introduced by
The condition is_null($fragment) is always false.
Loading history...
77
            $url->addFragment($fragment);
78
        }
79
80
        return $url;
81
    }
82
83
    /**
84
     * @param  string|null $scheme
85
     * @return self
86
     */
87
    public function addScheme(?string $scheme): self
88
    {
89
        if (is_null($scheme)) {
90
            throw new RuntimeException("Cannot set scheme to a null value.");
91
        }
92
93
        $this->scheme = $scheme;
94
95
        return $this;
96
    }
97
98
    /**
99
     * @return string
100
     */
101
    public function scheme(): string
102
    {
103
        return $this->scheme;
104
    }
105
106
    /**
107
     * @param  string|null $host
108
     * @return self
109
     */
110
    public function addHost(?string $host): self
111
    {
112
        if (is_null($host)) {
113
            throw new RuntimeException("Cannot set host to a null value.");
114
        }
115
116
        $this->host = $host;
117
118
        return $this;
119
    }
120
121
    /**
122
     * @return string
123
     */
124
    public function host(): string
125
    {
126
        return $this->host;
127
    }
128
129
    /**
130
     * @param  string|null $path
131
     * @return self
132
     */
133
    public function addPath(?string $path = null): self
134
    {
135
        if (is_null($path)) {
136
            return $this;
137
        }
138
139
        $this->path = (substr($path, 0, 1) === '/') ? $path : "/{$path}";
140
141
        return $this;
142
    }
143
144
    /**
145
     * @return string|null
146
     */
147
    public function path():? string
148
    {
149
        return $this->path;
150
    }
151
152
    /**
153
     * @param  string|null $query
154
     * @return self
155
     */
156
    public function addQuery(?string $query = null): self
157
    {
158
        if (is_null($query)) {
159
            throw new RuntimeException("Cannot set query to a null value.");
160
        }
161
162
        $this->query = ParameterBag::fromString($query);
163
164
        return $this;
165
    }
166
167
    /**
168
     * @return ParameterBag
169
     */
170
    public function query(): ParameterBag
171
    {
172
        return $this->query;
173
    }
174
175
    /**
176
     * @param  string $key
177
     * @param  mixed  $value
178
     * @param  bool   $covertBoolToString
179
     * @return self
180
     */
181
    public function addQueryParam(string $key, $value, bool $covertBoolToString = false): self
182
    {
183
        if (is_array($value) || is_object($value)) {
184
            throw new RuntimeException("Cannot set Query Parameter to: array, object");
185
        }
186
187
        if ($covertBoolToString && is_bool($value)) {
188
            $value = ($value) ? 'true' : 'false';
189
        }
190
191
        $this->query->set($key, $value);
192
193
        return $this;
194
    }
195
196
    /**
197
     * @return array
198
     */
199
    public function queryParams(): array
200
    {
201
        return $this->query->all();
202
    }
203
204
    /**
205
     * @param  string $fragment
206
     * @return self
207
     */
208
    public function addFragment(string $fragment): self
209
    {
210
        if ($fragment === '') {
211
            return $this;
212
        }
213
214
        $this->fragment = (substr($fragment, 0, 1) === '#') ? $fragment : "#{$fragment}";
215
216
        return $this;
217
    }
218
219
    /**
220
     * @return string|null
221
     */
222
    public function fragment():? string
223
    {
224
        return $this->fragment;
225
    }
226
227
    /**
228
     * @return string
229
     */
230
    public function __toString(): string
231
    {
232
        return $this->toString();
233
    }
234
235
    /**
236
     * @return string
237
     */
238
    public function toString(): string
239
    {
240
        $url = "{$this->scheme}://{$this->host}";
241
242
        if (! is_null($this->path)) {
243
            $url .= "{$this->path}";
244
        }
245
246
        if (! empty($this->query->all())) {
247
            $collection = [];
248
            foreach ($this->query->all() as $key => $value) {
249
                $collection[] = "{$key}={$value}";
250
            }
251
252
            $url .= '?' . implode('&', $collection);
253
        }
254
255
        if (! is_null($this->fragment)) {
256
            $url .= "{$this->fragment}";
257
        }
258
259
        return $url;
260
    }
261
}
262