Skip to content

Commit

Permalink
Merge pull request #4675 from MGatner/get-uri
Browse files Browse the repository at this point in the history
URL Functions
  • Loading branch information
MGatner authored May 13, 2021
2 parents 863079d + 307cfec commit 43e0e96
Show file tree
Hide file tree
Showing 11 changed files with 233 additions and 430 deletions.
167 changes: 93 additions & 74 deletions system/Helpers/url_helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* file that was distributed with this source code.
*/

use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\URI;
use CodeIgniter\Router\Exceptions\RouterException;
use Config\App;
Expand All @@ -18,105 +19,113 @@
* CodeIgniter URL Helpers
*/

if (! function_exists('site_url'))
if (! function_exists('_get_uri'))
{
/**
* Return a site URL to use in views
* Used by the other URL functions to build a
* framework-specific URI based on the App config.
*
* @param mixed $uri URI string or array of URI segments
* @param string|null $protocol
* @param App|null $altConfig Alternate configuration to use
* @internal Outside of the framework this should not be used directly.
*
* @return string
* @param string $relativePath May include queries or fragments
* @param App|null $config
*
* @return URI
*
* @throws InvalidArgumentException For invalid paths or config
*/
function site_url($uri = '', string $protocol = null, App $altConfig = null): string
function _get_uri(string $relativePath = '', App $config = null): URI
{
// convert segment array to string
if (is_array($uri))
$config = $config ?? config('App');

if ($config->baseURL === '')
{
$uri = implode('/', $uri);
throw new InvalidArgumentException('_get_uri() requires a valid baseURL.');
}

// use alternate config if provided, else default one
$config = $altConfig ?? config(App::class);

$fullPath = rtrim(base_url(), '/') . '/';

// Add index page, if so configured
if (! empty($config->indexPage))
// If a full URI was passed then convert it
if (is_int(strpos($relativePath, '://')))
{
$fullPath .= rtrim($config->indexPage, '/');
$full = new URI($relativePath);
$relativePath = URI::createURIString(null, null, $full->getPath(), $full->getQuery(), $full->getFragment());
}
if ($uri !== '')

$relativePath = URI::removeDotSegments($relativePath);

// Build the full URL based on $config and $relativePath
$url = rtrim($config->baseURL, '/ ') . '/';

// Check for an index page
if ($config->indexPage !== '')
{
$fullPath .= '/' . $uri;
$url .= $config->indexPage;

// Check if we need a separator
if ($relativePath !== '' && $relativePath[0] !== '/' && $relativePath[0] !== '?')
{
$url .= '/';
}
}

$url = new URI($fullPath);
$url .= $relativePath;

$uri = new URI($url);

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

return (string) $url;
return $uri;
}
}

//--------------------------------------------------------------------

if (! function_exists('base_url'))
if (! function_exists('site_url'))
{
/**
* Return the base URL to use in views
* Returns a site URL as defined by the App config.
*
* @param mixed $relativePath URI string or array of URI segments
* @param string|null $scheme
* @param App|null $config Alternate configuration to use
*
* @param mixed $uri URI string or array of URI segments
* @param string $protocol
* @return string
*/
function base_url($uri = '', string $protocol = null): string
function site_url($relativePath = '', string $scheme = null, App $config = null): string
{
// convert segment array to string
if (is_array($uri))
// Convert array of segments to a string
if (is_array($relativePath))
{
$uri = implode('/', $uri);
$relativePath = implode('/', $relativePath);
}
$uri = trim($uri, '/');

// We should be using the configured baseURL that the user set;
// otherwise get rid of the path, because we have
// no way of knowing the intent...
$config = Services::request()->config;

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

$url = new URI($baseUrl);
unset($config);

// Merge in the path set by the user, if any
if ($uri !== '')
{
$url = $url->resolveRelativeURI($uri);
}
return URI::createURIString($scheme ?? $uri->getScheme(), $uri->getAuthority(), $uri->getPath(), $uri->getQuery(), $uri->getFragment());
}
}

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

if (! empty($protocol))
{
$url->setScheme($protocol);
}
if (! function_exists('base_url'))
{
/**
* Returns the base URL as defined by the App config.
* Base URLs are trimmed site URLs without the index page.
*
* @param mixed $relativePath URI string or array of URI segments
* @param string $scheme
* @return string
*/
function base_url($relativePath = '', string $scheme = null): string
{
$config = clone config('App');
$config->indexPage = '';

return rtrim((string) $url, '/ ');
return rtrim(site_url($relativePath, $scheme, $config), '/');
}
}

Expand All @@ -125,22 +134,32 @@ function base_url($uri = '', string $protocol = null): string
if (! function_exists('current_url'))
{
/**
* Current URL
*
* Returns the full URL (including segments) of the page where this
* function is placed
* Returns the current full URL based on the IncomingRequest.
* String returns ignore query and fragment parts.
*
* @param boolean $returnObject True to return an object instead of a strong
* @param boolean $returnObject True to return an object instead of a string
* @param IncomingRequest|null $request A request to use when retrieving the path
*
* @return string|URI
*/
function current_url(bool $returnObject = false)
function current_url(bool $returnObject = false, IncomingRequest $request = null)
{
$uri = clone Services::request()->uri;
$request = $request ?? Services::request();
$path = $request->getPath();

// Append queries and fragments
if ($query = $request->getUri()->getQuery())
{
$path .= '?' . $query;
}
if ($fragment = $request->getUri()->getFragment())
{
$path .= '#' . $fragment;
}

$uri = _get_uri($path);

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

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

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

if ($title === '')
Expand Down
6 changes: 3 additions & 3 deletions tests/system/HTTP/ResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,23 +176,23 @@ public function testSetLink()
$response->setLink($pager);

$this->assertEquals(
'<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"',
'<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"',
$response->header('Link')->getValue()
);

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

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

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

$this->assertEquals(
'<http://example.com/test/?page=1>; rel="first",<http://example.com/test/?page=19>; rel="prev"',
'<http://example.com/test/index.php?page=1>; rel="first",<http://example.com/test/index.php?page=19>; rel="prev"',
$response->header('Link')->getValue()
);
}
Expand Down
3 changes: 3 additions & 0 deletions tests/system/HTTP/URITest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
use CodeIgniter\Test\CIUnitTestCase;
use Config\App;

/**
* @backupGlobals enabled
*/
class URITest extends CIUnitTestCase
{

Expand Down
4 changes: 2 additions & 2 deletions tests/system/Helpers/FormHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,15 @@ public function testFormOpenWithoutAction()
$Value = csrf_hash();
$Name = csrf_token();
$expected = <<<EOH
<form action="http://example.com/" name="form" id="form" method="POST" accept-charset="utf-8">
<form action="http://example.com/index.php" name="form" id="form" method="POST" accept-charset="utf-8">
<input type="hidden" name="$Name" value="$Value" style="display:none;" />
EOH;
}
else
{
$expected = <<<EOH
<form action="http://example.com/" name="form" id="form" method="POST" accept-charset="utf-8">
<form action="http://example.com/index.php" name="form" id="form" method="POST" accept-charset="utf-8">
EOH;
}
Expand Down
Loading

0 comments on commit 43e0e96

Please sign in to comment.