HttpsImmutable::setAuthority()   B
last analyzed

Complexity

Conditions 7
Paths 24

Size

Total Lines 28
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 16
nc 24
nop 1
dl 0
loc 28
rs 8.8333
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Keppler\Url\Scheme\Schemes\Https;
5
6
use Keppler\Url\Interfaces\Immutable\ImmutableSchemeInterface;
7
use Keppler\Url\Scheme\Schemes\AbstractImmutable;
8
use Keppler\Url\Scheme\Schemes\Https\Bags\HttpsImmutablePath;
9
use Keppler\Url\Scheme\Schemes\Https\Bags\HttpsImmutableQuery;
10
11
/**
12
 * Note that the following class makes no assumption regarding url encoding
13
 * the https url is taken AS IS and will not be decoded or encoded
14
 * url encoded strings WILL result in errors
15
 *
16
 *  userinfo     host        port
17
 * ┌─┴────┐ ┌────┴────────┐ ┌┴┐
18
 *  https://[email protected]:123/forum/questions/?tag=networking&order=newest#top
19
 *  └─┬─┘ └───────┬────────────────────┘└─┬─────────────┘└──┬───────────────────────┘└┬─┘
20
 * scheme     authority                 path              query                      fragment
21
 *
22
 * @see https://tools.ietf.org/html/rfc3986#page-16
23
 *
24
 *
25
 * Class HttpsImmutable
26
 *
27
 * @package Keppler\Url\Schemes\HttpsImmutable
28
 */
29
class HttpsImmutable extends AbstractImmutable implements ImmutableSchemeInterface
30
{
31
    /**
32
     * The default scheme for this class
33
     *
34
     * @var string
35
     */
36
    const SCHEME = 'https';
37
38
    /**
39
     * authority = [ userinfo "@" ] host [ ":" port ]
40
     *
41
     * -- An optional authority component preceded by two slashes (//), comprising:
42
     *
43
     *   - An optional userinfo subcomponent that may consist of a user name and an optional password preceded
44
     *  by a colon (:), followed by an at symbol (@). Use of the format username:password in the userinfo
45
     *  subcomponent is deprecated for security reasons. Applications should not render as clear text any data
46
     *  after the first colon (:) found within a userinfo subcomponent unless the data after the colon
47
     *  is the empty string (indicating no password).
48
     *
49
     *  - An optional host subcomponent, consisting of either a registered name (including but not limited to a hostname),
50
     *  or an IP address. IPv4 addresses must be in dot-decimal notation, and IPv6 addresses must be enclosed in brackets ([]).[10][c]
51
     *
52
     *   - An optional port subcomponent preceded by a colon (:).
53
     *
54
     * @var string
55
     */
56
    private $authority = '';
57
58
    /**
59
     * userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
60
     *
61
     * @var string
62
     */
63
    private $user = '';
64
65
    /**
66
     * Usage is highly discouraged
67
     *
68
     * @var string
69
     */
70
    private $password = '';
71
72
    /**
73
     * host = IP-literal / IPv4address / reg-name
74
     *
75
     * @var string
76
     */
77
    private $host = '';
78
79
    /**
80
     * port = *DIGIT
81
     *
82
     * Ports can't be negative, -1 should be considered the default value and ignored
83
     *
84
     * INVALID-PORT
85
     *  Either the local or foreign port was improperly
86
     *  specified.  This should be returned if either or
87
     *  both of the port ids were out of range (TCP port
88
     *  numbers are from 1-65535), negative integers, reals or
89
     *  in any fashion not recognized as a non-negative integer.
90
     *
91
     * @see https://www.ietf.org/rfc/rfc1413.txt
92
     * @var int
93
     */
94
    private $port = -1;
95
96
    /**
97
     * fragment = *( pchar / "/" / "?" )
98
     *
99
     * @var string
100
     */
101
    private $fragment = '';
102
103
    /**
104
     * @var HttpsImmutableQuery
105
     */
106
    private $queryBag;
107
108
    /**
109
     * @var HttpsImmutablePath
110
     */
111
    private $pathBag;
112
113
    /**
114
     * @var string
115
     */
116
    private $raw = '';
117
118
    /**
119
     * HttpsImmutable constructor.
120
     * @param $url
121
     */
122
    public function __construct(string $url)
123
    {
124
        $this->raw = $url;
125
126
        $parsedUrl = parse_url($url);
127
128
        $this->setAuthority($parsedUrl);
129
130
        if (isset($parsedUrl['fragment'])) {
131
            if (false !== strpos($parsedUrl['fragment'], '#')) {
132
                // get only the first fragment
133
                $this->fragment = explode('#', $parsedUrl['fragment'])[0];
134
            } else {
135
                $this->fragment = $parsedUrl['fragment'];
136
            }
137
        }
138
139
        if (isset($parsedUrl['query']) && !empty($parsedUrl['query'])) {
140
            $this->queryBag = new HttpsImmutableQuery($parsedUrl['query']);
141
        } else {
142
            $this->queryBag = new HttpsImmutableQuery();
143
        }
144
145
        if (isset($parsedUrl['path']) && !empty($parsedUrl['path'])) {
146
            $this->pathBag = new HttpsImmutablePath($parsedUrl['path']);
147
        } else {
148
            $this->pathBag = new HttpsImmutablePath();
149
        }
150
    }
151
152
///////////////////////////
153
/// PRIVATE FUNCTIONS  ///
154
/////////////////////////
155
156
    /**
157
     * @param array $parsedUrl
158
     */
159
    private function setAuthority(array $parsedUrl)
160
    {
161
        $authority = '';
162
163
        if (isset($parsedUrl['user'])) {
164
            $authority .= $parsedUrl['user'];
165
            $this->user = $parsedUrl['user'];
166
        }
167
168
        if (isset($parsedUrl['pass'])) {
169
            $authority .= ':'.$parsedUrl['pass'];
170
            $this->password = $parsedUrl['pass'];
171
        }
172
173
        if (isset($parsedUrl['host'])) {
174
            if (!empty($this->user) || !empty($this->password)) {
175
                $authority .= '@';
176
            }
177
            $authority .= $parsedUrl['host'];
178
            $this->host = $parsedUrl['host'];
179
        }
180
181
        if (isset($parsedUrl['port'])) {
182
            $authority .= ':'.$parsedUrl['port'];
183
            $this->port = $parsedUrl['port'];
184
        }
185
186
        $this->authority = $authority;
187
    }
188
189
//////////////////////////
190
/// GETTER FUNCTIONS  ///
191
////////////////////////
192
193
    /**
194
     * @return string
195
     */
196
    public function getAuthority(): string
197
    {
198
        return $this->authority;
199
    }
200
201
    /**
202
     * @return string
203
     */
204
    public function getUser(): string
205
    {
206
        return $this->user;
207
    }
208
209
    /**
210
     * @return string
211
     */
212
    public function getPassword(): string
213
    {
214
        return $this->password;
215
    }
216
217
    /**
218
     * @return string
219
     */
220
    public function getHost(): string
221
    {
222
        return $this->host;
223
    }
224
225
    /**
226
     * @return int|null
227
     */
228
    public function getPort(): ?int
229
    {
230
        return -1 === $this->port ? null : $this->port;
231
    }
232
233
    /**
234
     * @return string
235
     */
236
    public function getFragment(): string
237
    {
238
        return $this->fragment;
239
    }
240
241
    /**
242
     * @return HttpsImmutableQuery
243
     */
244
    public function getQueryBag(): HttpsImmutableQuery
245
    {
246
        return $this->queryBag;
247
    }
248
249
    /**
250
     * @return HttpsImmutablePath
251
     */
252
    public function getPathBag(): HttpsImmutablePath
253
    {
254
        return $this->pathBag;
255
    }
256
257
/////////////////////////////////
258
/// INTERFACE IMPLEMENTATION  ///
259
/////////////////////////////////
260
261
    /**
262
     * Returns all the components of the scheme including
263
     *  any bags in the form of an array
264
     *
265
     * @return array
266
     */
267
    public function all(): array
268
    {
269
        return [
270
            'scheme' => self::SCHEME,
271
            'authority' => $this->authority,
272
            'user' => $this->user,
273
            'password' => $this->password,
274
            'host' => $this->host,
275
            'port' => $this->port === -1 ? null : $this->port,
276
            'query' => $this->queryBag->all(),
277
            'path' => $this->pathBag->all(),
278
            'fragment' => $this->fragment,
279
        ];
280
    }
281
282
    /**
283
     * Return the raw unaltered url
284
     *
285
     * @return string
286
     */
287
    public function raw(): string
288
    {
289
        return $this->raw;
290
    }
291
292
    /**
293
     * Returns the scheme associated with the class
294
     *
295
     * @return string
296
     */
297
    public function getScheme(): string
298
    {
299
        return self::SCHEME;
300
    }
301
}
302