Skip to content

Commit 43e0e96

Browse files
authored
Merge pull request #4675 from MGatner/get-uri
URL Functions
2 parents 863079d + 307cfec commit 43e0e96

11 files changed

Lines changed: 233 additions & 430 deletions

File tree

system/Helpers/url_helper.php

Lines changed: 93 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* file that was distributed with this source code.
1010
*/
1111

12+
use CodeIgniter\HTTP\IncomingRequest;
1213
use CodeIgniter\HTTP\URI;
1314
use CodeIgniter\Router\Exceptions\RouterException;
1415
use Config\App;
@@ -18,105 +19,113 @@
1819
* CodeIgniter URL Helpers
1920
*/
2021

21-
if (! function_exists('site_url'))
22+
if (! function_exists('_get_uri'))
2223
{
2324
/**
24-
* Return a site URL to use in views
25+
* Used by the other URL functions to build a
26+
* framework-specific URI based on the App config.
2527
*
26-
* @param mixed $uri URI string or array of URI segments
27-
* @param string|null $protocol
28-
* @param App|null $altConfig Alternate configuration to use
28+
* @internal Outside of the framework this should not be used directly.
2929
*
30-
* @return string
30+
* @param string $relativePath May include queries or fragments
31+
* @param App|null $config
32+
*
33+
* @return URI
34+
*
35+
* @throws InvalidArgumentException For invalid paths or config
3136
*/
32-
function site_url($uri = '', string $protocol = null, App $altConfig = null): string
37+
function _get_uri(string $relativePath = '', App $config = null): URI
3338
{
34-
// convert segment array to string
35-
if (is_array($uri))
39+
$config = $config ?? config('App');
40+
41+
if ($config->baseURL === '')
3642
{
37-
$uri = implode('/', $uri);
43+
throw new InvalidArgumentException('_get_uri() requires a valid baseURL.');
3844
}
3945

40-
// use alternate config if provided, else default one
41-
$config = $altConfig ?? config(App::class);
42-
43-
$fullPath = rtrim(base_url(), '/') . '/';
44-
45-
// Add index page, if so configured
46-
if (! empty($config->indexPage))
46+
// If a full URI was passed then convert it
47+
if (is_int(strpos($relativePath, '://')))
4748
{
48-
$fullPath .= rtrim($config->indexPage, '/');
49+
$full = new URI($relativePath);
50+
$relativePath = URI::createURIString(null, null, $full->getPath(), $full->getQuery(), $full->getFragment());
4951
}
50-
if ($uri !== '')
52+
53+
$relativePath = URI::removeDotSegments($relativePath);
54+
55+
// Build the full URL based on $config and $relativePath
56+
$url = rtrim($config->baseURL, '/ ') . '/';
57+
58+
// Check for an index page
59+
if ($config->indexPage !== '')
5160
{
52-
$fullPath .= '/' . $uri;
61+
$url .= $config->indexPage;
62+
63+
// Check if we need a separator
64+
if ($relativePath !== '' && $relativePath[0] !== '/' && $relativePath[0] !== '?')
65+
{
66+
$url .= '/';
67+
}
5368
}
5469

55-
$url = new URI($fullPath);
70+
$url .= $relativePath;
71+
72+
$uri = new URI($url);
5673

57-
// allow the scheme to be over-ridden; else, use default
58-
if (! empty($protocol))
74+
// Check if the baseURL scheme needs to be coerced into its secure version
75+
if ($config->forceGlobalSecureRequests && $uri->getScheme() === 'http')
5976
{
60-
$url->setScheme($protocol);
77+
$uri->setScheme('https');
6178
}
6279

63-
return (string) $url;
80+
return $uri;
6481
}
6582
}
6683

6784
//--------------------------------------------------------------------
6885

69-
if (! function_exists('base_url'))
86+
if (! function_exists('site_url'))
7087
{
7188
/**
72-
* Return the base URL to use in views
89+
* Returns a site URL as defined by the App config.
90+
*
91+
* @param mixed $relativePath URI string or array of URI segments
92+
* @param string|null $scheme
93+
* @param App|null $config Alternate configuration to use
7394
*
74-
* @param mixed $uri URI string or array of URI segments
75-
* @param string $protocol
7695
* @return string
7796
*/
78-
function base_url($uri = '', string $protocol = null): string
97+
function site_url($relativePath = '', string $scheme = null, App $config = null): string
7998
{
80-
// convert segment array to string
81-
if (is_array($uri))
99+
// Convert array of segments to a string
100+
if (is_array($relativePath))
82101
{
83-
$uri = implode('/', $uri);
102+
$relativePath = implode('/', $relativePath);
84103
}
85-
$uri = trim($uri, '/');
86-
87-
// We should be using the configured baseURL that the user set;
88-
// otherwise get rid of the path, because we have
89-
// no way of knowing the intent...
90-
$config = Services::request()->config;
91104

92-
// If baseUrl does not have a trailing slash it won't resolve
93-
// correctly for users hosting in a subfolder.
94-
$baseUrl = ! empty($config->baseURL) && $config->baseURL !== '/'
95-
? rtrim($config->baseURL, '/ ') . '/'
96-
: $config->baseURL;
105+
$uri = _get_uri($relativePath, $config);
97106

98-
$url = new URI($baseUrl);
99-
unset($config);
100-
101-
// Merge in the path set by the user, if any
102-
if ($uri !== '')
103-
{
104-
$url = $url->resolveRelativeURI($uri);
105-
}
107+
return URI::createURIString($scheme ?? $uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(), $uri->getFragment());
108+
}
109+
}
106110

107-
// If the scheme wasn't provided, check to
108-
// see if it was a secure request
109-
if (empty($protocol) && Services::request()->isSecure())
110-
{
111-
$protocol = 'https';
112-
}
111+
//--------------------------------------------------------------------
113112

114-
if (! empty($protocol))
115-
{
116-
$url->setScheme($protocol);
117-
}
113+
if (! function_exists('base_url'))
114+
{
115+
/**
116+
* Returns the base URL as defined by the App config.
117+
* Base URLs are trimmed site URLs without the index page.
118+
*
119+
* @param mixed $relativePath URI string or array of URI segments
120+
* @param string $scheme
121+
* @return string
122+
*/
123+
function base_url($relativePath = '', string $scheme = null): string
124+
{
125+
$config = clone config('App');
126+
$config->indexPage = '';
118127

119-
return rtrim((string) $url, '/ ');
128+
return rtrim(site_url($relativePath, $scheme, $config), '/');
120129
}
121130
}
122131

@@ -125,22 +134,32 @@ function base_url($uri = '', string $protocol = null): string
125134
if (! function_exists('current_url'))
126135
{
127136
/**
128-
* Current URL
129-
*
130-
* Returns the full URL (including segments) of the page where this
131-
* function is placed
137+
* Returns the current full URL based on the IncomingRequest.
138+
* String returns ignore query and fragment parts.
132139
*
133-
* @param boolean $returnObject True to return an object instead of a strong
140+
* @param boolean $returnObject True to return an object instead of a string
141+
* @param IncomingRequest|null $request A request to use when retrieving the path
134142
*
135143
* @return string|URI
136144
*/
137-
function current_url(bool $returnObject = false)
145+
function current_url(bool $returnObject = false, IncomingRequest $request = null)
138146
{
139-
$uri = clone Services::request()->uri;
147+
$request = $request ?? Services::request();
148+
$path = $request->getPath();
149+
150+
// Append queries and fragments
151+
if ($query = $request->getUri()->getQuery())
152+
{
153+
$path .= '?' . $query;
154+
}
155+
if ($fragment = $request->getUri()->getFragment())
156+
{
157+
$path .= '#' . $fragment;
158+
}
159+
160+
$uri = _get_uri($path);
140161

141-
// Since we're basing off of the IncomingRequest URI,
142-
// we are guaranteed to have a host based on our own configs.
143-
return $returnObject ? $uri : (string) $uri->setQuery('');
162+
return $returnObject ? $uri : URI::createURIString($uri->getScheme(), $uri->getAuthority(), $uri->getPath());
144163
}
145164
}
146165

@@ -285,7 +304,7 @@ function anchor_popup($uri = '', string $title = '', $attributes = false, App $a
285304
// use alternate config if provided, else default one
286305
$config = $altConfig ?? config(App::class);
287306

288-
$siteUrl = preg_match('#^(\w+:)?//#i', $uri) ? $uri : site_url($uri, '', $config);
307+
$siteUrl = preg_match('#^(\w+:)?//#i', $uri) ? $uri : site_url($uri, null, $config);
289308
$siteUrl = rtrim($siteUrl, '/');
290309

291310
if ($title === '')

tests/system/HTTP/ResponseTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,23 +176,23 @@ public function testSetLink()
176176
$response->setLink($pager);
177177

178178
$this->assertEquals(
179-
'<http://example.com/test/?page=1>; rel="first",<http://example.com/test/?page=2>; rel="prev",<http://example.com/test/?page=4>; rel="next",<http://example.com/test/?page=20>; rel="last"',
179+
'<http://example.com/test/index.php?page=1>; rel="first",<http://example.com/test/index.php?page=2>; rel="prev",<http://example.com/test/index.php?page=4>; rel="next",<http://example.com/test/index.php?page=20>; rel="last"',
180180
$response->header('Link')->getValue()
181181
);
182182

183183
$pager->store('default', 1, 10, 200);
184184
$response->setLink($pager);
185185

186186
$this->assertEquals(
187-
'<http://example.com/test/?page=2>; rel="next",<http://example.com/test/?page=20>; rel="last"',
187+
'<http://example.com/test/index.php?page=2>; rel="next",<http://example.com/test/index.php?page=20>; rel="last"',
188188
$response->header('Link')->getValue()
189189
);
190190

191191
$pager->store('default', 20, 10, 200);
192192
$response->setLink($pager);
193193

194194
$this->assertEquals(
195-
'<http://example.com/test/?page=1>; rel="first",<http://example.com/test/?page=19>; rel="prev"',
195+
'<http://example.com/test/index.php?page=1>; rel="first",<http://example.com/test/index.php?page=19>; rel="prev"',
196196
$response->header('Link')->getValue()
197197
);
198198
}

tests/system/HTTP/URITest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
use CodeIgniter\Test\CIUnitTestCase;
99
use Config\App;
1010

11+
/**
12+
* @backupGlobals enabled
13+
*/
1114
class URITest extends CIUnitTestCase
1215
{
1316

tests/system/Helpers/FormHelperTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,15 @@ public function testFormOpenWithoutAction()
9696
$Value = csrf_hash();
9797
$Name = csrf_token();
9898
$expected = <<<EOH
99-
<form action="http://example.com/" name="form" id="form" method="POST" accept-charset="utf-8">
99+
<form action="http://example.com/index.php" name="form" id="form" method="POST" accept-charset="utf-8">
100100
<input type="hidden" name="$Name" value="$Value" style="display:none;" />
101101
102102
EOH;
103103
}
104104
else
105105
{
106106
$expected = <<<EOH
107-
<form action="http://example.com/" name="form" id="form" method="POST" accept-charset="utf-8">
107+
<form action="http://example.com/index.php" name="form" id="form" method="POST" accept-charset="utf-8">
108108
109109
EOH;
110110
}

0 commit comments

Comments
 (0)