Skip to content

Commit 81f3e96

Browse files
committed
Adds Url, UrlQuery objects.
1 parent e443081 commit 81f3e96

2 files changed

Lines changed: 462 additions & 0 deletions

File tree

src/Object/Internet/Url.php

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
<?php
2+
/**
3+
* Url.php.
4+
*/
5+
6+
namespace DevCoding\Object\Internet;
7+
8+
use DevCoding\Object\Type\StringLiteral;
9+
10+
/**
11+
* Immutable Object representing an Url.
12+
*
13+
* @author AMJones <am@jonesiscoding.com>
14+
* @license https://github.com/deviscoding/objection/blob/main/LICENSE
15+
* @package DevCoding\Object\Internet
16+
*/
17+
class Url
18+
{
19+
/** @var string */
20+
protected $raw;
21+
/** @var array */
22+
protected $parts;
23+
/** @var UrlQuery */
24+
protected $query;
25+
26+
// region //////////////////////////////////////////////// Object Instantiation Methods
27+
28+
/**
29+
* @param string $raw
30+
*/
31+
public function __construct($raw)
32+
{
33+
$this->raw = $raw;
34+
}
35+
36+
// endregion ///////////////////////////////////////////// End Object Instantiation Methods
37+
38+
// region //////////////////////////////////////////////// Public Getters
39+
40+
/**
41+
* Determines if the given value is equal to this URL by performing a comparison of the string form of this object.
42+
*
43+
* If the given value is a string, it is converted to an Url object for comparison.
44+
*
45+
* @param Url|StringLiteral|string $value
46+
*/
47+
public function equals($value): bool
48+
{
49+
if ($value instanceof Url || $value instanceof StringLiteral)
50+
{
51+
$str = $value->toNative();
52+
}
53+
elseif (is_string($value))
54+
{
55+
$str = (new Url($value))->__toString();
56+
}
57+
else
58+
{
59+
return false;
60+
}
61+
62+
return $str === $this->__toString();
63+
}
64+
65+
/**
66+
* Returns any URL fragment (the portion after the #) as a StringLiteral.
67+
*
68+
* @return StringLiteral|null
69+
*/
70+
public function getFragment()
71+
{
72+
if (empty($this->parts))
73+
{
74+
$this->doParse($this->raw);
75+
}
76+
77+
return isset($this->parts[PHP_URL_FRAGMENT]) ? new StringLiteral($this->parts[PHP_URL_FRAGMENT]) : null;
78+
}
79+
80+
/**
81+
* Returns any URL host as a StringLiteral.
82+
*
83+
* @return StringLiteral|null
84+
*/
85+
public function getHost()
86+
{
87+
if (empty($this->parts))
88+
{
89+
$this->doParse($this->raw);
90+
}
91+
92+
return isset($this->parts[PHP_URL_HOST]) ? new StringLiteral($this->parts[PHP_URL_HOST]) : null;
93+
}
94+
95+
/**
96+
* Returns any password embedded in the URL.
97+
*
98+
* @return string|null
99+
*/
100+
public function getPass()
101+
{
102+
if (empty($this->parts))
103+
{
104+
$this->doParse($this->raw);
105+
}
106+
107+
return $this->parts[PHP_URL_PASS];
108+
}
109+
110+
/**
111+
* Returns the path from the URL as a StringLiteral object. A File object was not used here because the File class
112+
* strips the trailing slash from /app_dev.php/.
113+
*
114+
* @return StringLiteral|null
115+
*/
116+
public function getPath()
117+
{
118+
if (empty($this->parts))
119+
{
120+
$this->doParse($this->raw);
121+
}
122+
123+
return isset($this->parts[PHP_URL_PATH]) ? new StringLiteral($this->parts[PHP_URL_PATH]) : null;
124+
}
125+
126+
/**
127+
* Returns any port referenced in the URL. Defaults to null if no port is present.
128+
*
129+
* @return int|null
130+
*/
131+
public function getPort()
132+
{
133+
if (empty($this->parts))
134+
{
135+
$this->doParse($this->raw);
136+
}
137+
138+
return $this->parts[PHP_URL_PORT];
139+
}
140+
141+
/**
142+
* Returns the UrlQuery from the URL.
143+
*
144+
* @return UrlQuery|null
145+
*/
146+
public function getQuery()
147+
{
148+
if (empty($this->query))
149+
{
150+
if (empty($this->parts))
151+
{
152+
$this->doParse($this->raw);
153+
}
154+
155+
if (isset($this->parts[PHP_URL_QUERY]))
156+
{
157+
$this->query = new UrlQuery($this->parts[PHP_URL_QUERY]);
158+
}
159+
}
160+
161+
return $this->query;
162+
}
163+
164+
/**
165+
* Returns the scheme referenced in the URL as a StringLiteral, or null if no scheme was specified.
166+
*
167+
* @return StringLiteral|null
168+
*/
169+
public function getScheme()
170+
{
171+
if (empty($this->parts))
172+
{
173+
$this->doParse($this->raw);
174+
}
175+
176+
return isset($this->parts[PHP_URL_SCHEME]) ? new StringLiteral($this->parts[PHP_URL_SCHEME]) : null;
177+
}
178+
179+
/**
180+
* Returns any username in the URL as a StringLiteral, or null if no user was specified.
181+
*
182+
* @return StringLiteral|null
183+
*/
184+
public function getUser()
185+
{
186+
if (empty($this->parts))
187+
{
188+
$this->doParse($this->raw);
189+
}
190+
191+
return isset($this->parts[PHP_URL_USER]) ? new StringLiteral($this->parts[PHP_URL_USER]) : null;
192+
}
193+
194+
/**
195+
* Returns this Url object as a string by compiling the parts together. If an exception is thrown, the raw string
196+
* from object creation is returned.
197+
*/
198+
public function __toString(): string
199+
{
200+
try
201+
{
202+
$url = '';
203+
if ($scheme = $this->getScheme())
204+
{
205+
$url .= $scheme.'://';
206+
}
207+
208+
if ($user = $this->getUser())
209+
{
210+
$pass = ($pw = $this->getPass()) ? ':'.$pw : '';
211+
$url .= $user.$pass.'@';
212+
}
213+
214+
if ($host = $this->getHost())
215+
{
216+
$url .= $host;
217+
}
218+
219+
if ($port = $this->getPort())
220+
{
221+
$url .= ':'.$port;
222+
}
223+
224+
if ($path = $this->getPath())
225+
{
226+
$url .= $path;
227+
}
228+
229+
if ($query = $this->getQuery())
230+
{
231+
$url .= '?'.$query;
232+
}
233+
234+
if ($frag = $this->getFragment())
235+
{
236+
$url .= '#'.$frag;
237+
}
238+
239+
return $url;
240+
}
241+
catch (\Exception $e)
242+
{
243+
return $this->raw;
244+
}
245+
}
246+
247+
// endregion ///////////////////////////////////////////// End Public Getters
248+
249+
// region //////////////////////////////////////////////// Helper Methods
250+
251+
/**
252+
* Parses the given string into it's parts, populating this object.
253+
*
254+
* @param string $string
255+
*
256+
* @return $this
257+
*/
258+
protected function doParse($string)
259+
{
260+
$parsed = parse_url($string);
261+
262+
$this->parts = [
263+
PHP_URL_SCHEME => $parsed['scheme'] ?? null,
264+
PHP_URL_HOST => $parsed['host'] ?? null,
265+
PHP_URL_PORT => isset($parsed['port']) ? (int) $parsed['port'] : null,
266+
PHP_URL_USER => $parsed['user'] ?? null,
267+
PHP_URL_PASS => $parsed['pass'] ?? null,
268+
PHP_URL_PATH => $parsed['path'] ?? null,
269+
PHP_URL_QUERY => $parsed['query'] ?? null,
270+
PHP_URL_FRAGMENT => $parsed['fragment'] ?? null,
271+
];
272+
273+
return $this;
274+
}
275+
276+
// endregion ///////////////////////////////////////////// End Helper Methods
277+
}

0 commit comments

Comments
 (0)