Skip to content

Commit 42a60ce

Browse files
committed
Add URL class
1 parent 1472864 commit 42a60ce

File tree

2 files changed

+541
-0
lines changed

2 files changed

+541
-0
lines changed

system/HTTP/URL.php

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the CodeIgniter 4 framework.
5+
*
6+
* (c) CodeIgniter Foundation <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace CodeIgniter\HTTP;
13+
14+
use CodeIgniter\HTTP\IncomingRequest;
15+
use Config\App;
16+
use Config\Services;
17+
use InvalidArgumentException;
18+
19+
/**
20+
* URI wrapper to work with complete project URLs.
21+
* This class creates immutable instances.
22+
*/
23+
class URL
24+
{
25+
/**
26+
* Underlying URI instance
27+
*
28+
* @var URI
29+
*/
30+
private $uri;
31+
32+
/**
33+
* Path relative to baseURL
34+
*
35+
* @var string
36+
*/
37+
protected $relativePath;
38+
39+
//--------------------------------------------------------------------
40+
41+
/**
42+
* Returns an instance representing the current URL.
43+
*
44+
* @return static
45+
*/
46+
final public static function base()
47+
{
48+
return new static('');
49+
}
50+
51+
/**
52+
* Returns an instance representing the current URL.
53+
*
54+
* @param string $uri
55+
*
56+
* @return static
57+
*/
58+
final public static function to(string $uri)
59+
{
60+
// Check for a named or reverse-route
61+
if ($route = Services::routes()->reverseRoute($uri))
62+
{
63+
return new static($route);
64+
}
65+
66+
return new static($uri);
67+
}
68+
69+
/**
70+
* Returns an instance representing the current URL.
71+
*
72+
* @return static
73+
*/
74+
final public static function current()
75+
{
76+
return static::fromRequest(Services::request());
77+
}
78+
79+
/**
80+
* Returns an instance representing the URL from
81+
* an Incoming Request (as defined by Config\App).
82+
*
83+
* @param IncomingRequest $request
84+
*
85+
* @return static
86+
*/
87+
final public static function fromRequest(IncomingRequest $request)
88+
{
89+
$path = $request->detectPath($request->config->uriProtocol);
90+
$query = isset($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : '';
91+
92+
return new static($path . $query, $request->config);
93+
}
94+
95+
//--------------------------------------------------------------------
96+
97+
/**
98+
* Store the App configuration and create the URI
99+
* instance from the relative path.
100+
*
101+
* @param string $relativePath
102+
* @param App|null $config
103+
*/
104+
final public function __construct(string $relativePath = '', App $config = null)
105+
{
106+
$config = $config ?? config('App');
107+
108+
if ($config->baseURL === '')
109+
{
110+
throw new InvalidArgumentException('URL class requires a valid baseURL.');
111+
}
112+
if (is_int(strpos($relativePath, '://')))
113+
{
114+
throw new InvalidArgumentException('URL class only accepts relative paths.');
115+
}
116+
117+
$this->relativePath = ltrim(URI::removeDotSegments($relativePath), '/');
118+
119+
// Build the full URL based on $config and $relativePath
120+
$url = rtrim($config->baseURL, '/ ') . '/';
121+
122+
// Check for an index page
123+
if ($config->indexPage !== '')
124+
{
125+
$url .= $config->indexPage;
126+
127+
// If the relative path has anything other than ? (for query) we need a separator
128+
if ($this->relativePath !== '' && strncmp($this->relativePath, '?', 1) !== 0)
129+
{
130+
$url .= '/';
131+
}
132+
}
133+
134+
$url .= $this->relativePath;
135+
136+
$this->uri = new URI($url);
137+
138+
// Check if the baseURL scheme needs to be coerced into its secure version
139+
if ($config->forceGlobalSecureRequests && $this->uri->getScheme() === 'http')
140+
{
141+
$this->uri->setScheme('https');
142+
}
143+
}
144+
145+
/**
146+
* Returns the path relative to baseUrl, loosely
147+
* what was passed to the constructor.
148+
*
149+
* @return string
150+
*/
151+
public function getPath(): string
152+
{
153+
return $this->relativePath;
154+
}
155+
156+
/**
157+
* Returns the underlying URI instance.
158+
* In order for this instance to remain
159+
* immutable a clone is returned.
160+
*
161+
* @return URI
162+
*/
163+
public function getUri(): URI
164+
{
165+
return clone $this->uri;
166+
}
167+
168+
/**
169+
* Returns this URL as a string.
170+
*
171+
* @return string
172+
*/
173+
public function __toString(): string
174+
{
175+
return (string) $this->uri;
176+
}
177+
}

0 commit comments

Comments
 (0)