Skip to content

Commit 87c90ca

Browse files
committed
feat: add SiteURI class
1 parent 40be63e commit 87c90ca

File tree

3 files changed

+559
-0
lines changed

3 files changed

+559
-0
lines changed

system/HTTP/SiteURI.php

Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
<?php
2+
3+
/**
4+
* This file is part of CodeIgniter 4 framework.
5+
*
6+
* (c) CodeIgniter Foundation <[email protected]>
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*/
11+
12+
namespace CodeIgniter\HTTP;
13+
14+
use BadMethodCallException;
15+
use CodeIgniter\HTTP\Exceptions\HTTPException;
16+
use Config\App;
17+
18+
/**
19+
* URI for the application site
20+
*/
21+
class SiteURI extends URI
22+
{
23+
/**
24+
* The baseURL.
25+
*/
26+
private string $baseURL;
27+
28+
/**
29+
* The Index File.
30+
*/
31+
private string $indexPage;
32+
33+
/**
34+
* List of URI segments in baseURL and indexPage.
35+
*
36+
* If the URI is "http://localhost:8888/ci431/public/index.php/test?a=b",
37+
* and the baseUR is "http://localhost:8888/ci431/public/", then:
38+
* $baseSegments = [
39+
* 0 => 'ci431',
40+
* 1 => 'public',
41+
* 2 => 'index.php',
42+
* ];
43+
*/
44+
private array $baseSegments;
45+
46+
/**
47+
* List of URI segments after indexPage.
48+
*
49+
* The word "URI Segments" originally means only the URI path part relative
50+
* to the baseURL.
51+
*
52+
* If the URI is "http://localhost:8888/ci431/public/index.php/test?a=b",
53+
* and the baseUR is "http://localhost:8888/ci431/public/", then:
54+
* $segments = [
55+
* 0 => 'test',
56+
* ];
57+
*
58+
* @var array
59+
*
60+
* @deprecated This property will be private.
61+
*/
62+
protected $segments;
63+
64+
/**
65+
* URI path relative to baseURL.
66+
*
67+
* If the baseURL contains sub folders, this value will be different from
68+
* the current URI path.
69+
*/
70+
private string $routePath;
71+
72+
public function __construct(App $configApp)
73+
{
74+
// It's possible the user forgot a trailing slash on their
75+
// baseURL, so let's help them out.
76+
$baseURL = rtrim($configApp->baseURL, '/ ') . '/';
77+
78+
$this->baseURL = $baseURL;
79+
$this->indexPage = $configApp->indexPage;
80+
81+
$this->setBaseSeegments();
82+
83+
// Check for an index page
84+
$indexPage = '';
85+
if ($configApp->indexPage !== '') {
86+
$indexPage = $configApp->indexPage . '/';
87+
}
88+
89+
$tempUri = $this->baseURL . $indexPage;
90+
$uri = new URI($tempUri);
91+
92+
if ($configApp->forceGlobalSecureRequests) {
93+
$uri->setScheme('https');
94+
}
95+
96+
$parts = parse_url((string) $uri);
97+
if ($parts === false) {
98+
throw HTTPException::forUnableToParseURI($uri);
99+
}
100+
$this->applyParts($parts);
101+
102+
$this->setPath('/');
103+
}
104+
105+
/**
106+
* Sets baseSegments.
107+
*/
108+
private function setBaseSeegments(): void
109+
{
110+
$basePath = (new URI($this->baseURL))->getPath();
111+
$this->baseSegments = $this->convertToSegments($basePath);
112+
113+
if ($this->indexPage) {
114+
$this->baseSegments[] = $this->indexPage;
115+
}
116+
}
117+
118+
public function setURI(?string $uri = null)
119+
{
120+
throw new BadMethodCallException('Cannot use this method.');
121+
}
122+
123+
/**
124+
* Returns the URI path relative to baseURL.
125+
*
126+
* @return string The Route path.
127+
*/
128+
public function getRoutePath(): string
129+
{
130+
return $this->routePath;
131+
}
132+
133+
/**
134+
* Returns the URI segments of the path as an array.
135+
*/
136+
public function getSegments(): array
137+
{
138+
return $this->segments;
139+
}
140+
141+
/**
142+
* Returns the value of a specific segment of the URI path relative to baseURL.
143+
*
144+
* @param int $number Segment number
145+
* @param string $default Default value
146+
*
147+
* @return string The value of the segment. If no segment is found,
148+
* throws HTTPException
149+
*/
150+
public function getSegment(int $number, string $default = ''): string
151+
{
152+
if ($number < 1) {
153+
throw HTTPException::forURISegmentOutOfRange($number);
154+
}
155+
156+
if ($number > count($this->segments) && ! $this->silent) {
157+
throw HTTPException::forURISegmentOutOfRange($number);
158+
}
159+
160+
// The segment should treat the array as 1-based for the user
161+
// but we still have to deal with a zero-based array.
162+
$number--;
163+
164+
return $this->segments[$number] ?? $default;
165+
}
166+
167+
/**
168+
* Set the value of a specific segment of the URI path relative to baseURL.
169+
* Allows to set only existing segments or add new one.
170+
*
171+
* @param int $number The segment number. Starting with 1.
172+
* @param string $value The segment value.
173+
*
174+
* @return $this
175+
*/
176+
public function setSegment(int $number, $value)
177+
{
178+
if ($number < 1) {
179+
throw HTTPException::forURISegmentOutOfRange($number);
180+
}
181+
182+
if ($number > count($this->segments) + 1) {
183+
if ($this->silent) {
184+
return $this;
185+
}
186+
187+
throw HTTPException::forURISegmentOutOfRange($number);
188+
}
189+
190+
// The segment should treat the array as 1-based for the user,
191+
// but we still have to deal with a zero-based array.
192+
$number--;
193+
194+
$this->segments[$number] = $value;
195+
196+
$this->refreshPath();
197+
198+
return $this;
199+
}
200+
201+
/**
202+
* Returns the total number of segments.
203+
*/
204+
public function getTotalSegments(): int
205+
{
206+
return count($this->segments);
207+
}
208+
209+
/**
210+
* Formats the URI as a string.
211+
*/
212+
public function __toString(): string
213+
{
214+
return static::createURIString(
215+
$this->getScheme(),
216+
$this->getAuthority(),
217+
$this->getPath(), // Absolute URIs should use a "/" for an empty path
218+
$this->getQuery(),
219+
$this->getFragment()
220+
);
221+
}
222+
223+
/**
224+
* Sets the route path (and segments).
225+
*
226+
* @return $this
227+
*/
228+
public function setPath(string $path)
229+
{
230+
$this->routePath = $this->filterPath($path);
231+
232+
$this->segments = $this->convertToSegments($this->routePath);
233+
234+
$this->refreshPath();
235+
236+
return $this;
237+
}
238+
239+
/**
240+
* Converts path to segments
241+
*/
242+
private function convertToSegments(string $path): array
243+
{
244+
$tempPath = trim($path, '/');
245+
246+
return ($tempPath === '') ? [] : explode('/', $tempPath);
247+
}
248+
249+
/**
250+
* Sets the path portion of the URI based on segments.
251+
*
252+
* @return $this
253+
*
254+
* @deprecated This method will be private.
255+
*/
256+
public function refreshPath()
257+
{
258+
$allSegments = array_merge($this->baseSegments, $this->segments);
259+
$this->path = '/' . $this->filterPath(implode('/', $allSegments));
260+
261+
$this->routePath = $this->filterPath(implode('/', $this->segments));
262+
263+
if ($this->routePath === '') {
264+
$this->routePath = '/';
265+
266+
if ($this->indexPage !== '') {
267+
$this->path .= '/';
268+
}
269+
}
270+
271+
return $this;
272+
}
273+
274+
/**
275+
* Saves our parts from a parse_url() call.
276+
*/
277+
protected function applyParts(array $parts)
278+
{
279+
if (! empty($parts['host'])) {
280+
$this->host = $parts['host'];
281+
}
282+
if (! empty($parts['user'])) {
283+
$this->user = $parts['user'];
284+
}
285+
if (isset($parts['path']) && $parts['path'] !== '') {
286+
$this->path = $this->filterPath($parts['path']);
287+
}
288+
if (! empty($parts['query'])) {
289+
$this->setQuery($parts['query']);
290+
}
291+
if (! empty($parts['fragment'])) {
292+
$this->fragment = $parts['fragment'];
293+
}
294+
295+
// Scheme
296+
if (isset($parts['scheme'])) {
297+
$this->setScheme(rtrim($parts['scheme'], ':/'));
298+
} else {
299+
$this->setScheme('http');
300+
}
301+
302+
// Port
303+
if (isset($parts['port']) && $parts['port'] !== null) {
304+
// Valid port numbers are enforced by earlier parse_url() or setPort()
305+
$this->port = $parts['port'];
306+
}
307+
308+
if (isset($parts['pass'])) {
309+
$this->password = $parts['pass'];
310+
}
311+
}
312+
}

system/HTTP/URI.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,8 @@ public function getBaseURL(): string
785785
* Sets the path portion of the URI based on segments.
786786
*
787787
* @return $this
788+
*
789+
* @deprecated This method will be private.
788790
*/
789791
public function refreshPath()
790792
{

0 commit comments

Comments
 (0)