Skip to content

Commit

Permalink
Url: Consider urls with a leading slash as absolute..
Browse files Browse the repository at this point in the history
..and make it possible to have a url without a base.

refs #5600
  • Loading branch information
Johannes Meyer committed Sep 22, 2015
1 parent 57e08e9 commit 7321d67
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 31 deletions.
97 changes: 69 additions & 28 deletions library/Icinga/Web/Url.php
Expand Up @@ -46,12 +46,11 @@ class Url
protected $path = '';

/**
* The baseUrl that will be appended to @see Url::$path in order to
* create an absolute Url
* The baseUrl that will be appended to @see Url::$path
*
* @var string
*/
protected $baseUrl = '/';
protected $baseUrl = '';

protected function __construct()
{
Expand Down Expand Up @@ -156,17 +155,24 @@ public static function fromPath($url, array $params = array(), $request = null)
$baseUrl = $urlParts['host'] . (isset($urlParts['port']) ? (':' . $urlParts['port']) : '');
$urlObject->setIsExternal();
} else {
$baseUrl = $request->getBaseUrl();
$baseUrl = '';
}

$urlObject->setBaseUrl($baseUrl);

if (isset($urlParts['path'])) {
if ($baseUrl && !$urlObject->isExternal() && strpos($urlParts['path'], $baseUrl) === 0) {
$urlObject->setPath(substr($urlParts['path'], strlen($baseUrl)));
$urlPath = $urlParts['path'];
if ($urlPath && $urlPath[0] === '/') {
$baseUrl = '';
} elseif (! $baseUrl) {
$baseUrl = $request->getBaseUrl();
}

if ($baseUrl && !$urlObject->isExternal() && strpos($urlPath, $baseUrl) === 0) {
$urlObject->setPath(substr($urlPath, strlen($baseUrl)));
} else {
$urlObject->setPath($urlParts['path']);
$urlObject->setPath($urlPath);
}
} elseif (! $baseUrl) {
$baseUrl = $request->getBaseUrl();
}

// TODO: This has been used by former filter implementation, remove it:
Expand All @@ -178,6 +184,7 @@ public static function fromPath($url, array $params = array(), $request = null)
$urlObject->setAnchor($urlParts['fragment']);
}

$urlObject->setBaseUrl($baseUrl);
$urlObject->setParams($params);
return $urlObject;
}
Expand Down Expand Up @@ -205,19 +212,13 @@ public static function urlAddFilterOptional($url, $filter, $optional)
/**
* Overwrite the baseUrl
*
* If an empty Url is given '/' is used as the base
*
* @param string $baseUrl The url path to use as the Url Base
*
* @return $this
*/
public function setBaseUrl($baseUrl)
{
if (($baseUrl = rtrim($baseUrl, '/ ')) === '') {
$baseUrl = '/';
}

$this->baseUrl = $baseUrl;
$this->baseUrl = rtrim($baseUrl, '/ ');
return $this;
}

Expand Down Expand Up @@ -280,17 +281,42 @@ public function isExternal()
}

/**
* Return the relative url with query parameters as a string
* Return the relative url
*
* @return string
*
* @throws ProgrammingError In case no relative url path is set or it is absolute
*/
public function getRelativeUrl($separator = '&')
{
if ($this->params->isEmpty()) {
return $this->path . $this->anchor;
} else {
return $this->path . '?' . $this->params->toString($separator) . $this->anchor;
$path = $this->getPath();
if (! $path) {
throw new ProgrammingError('Unable to provide a relative URL. No path set');
} elseif ($path[0] === '/') {
throw new ProgrammingError('Cannot provide a relative URL. Path is absolute');
}

return $this->buildPathQueryAndFragment($separator);
}

/**
* Return this url's path with its query parameters and fragment as string
*
* @return string
*/
protected function buildPathQueryAndFragment($querySeparator)
{
$anchor = $this->getAnchor();
if ($anchor) {
$anchor = '#' . $anchor;
}

$query = $this->getQueryString($querySeparator);
if ($query) {
$query = '?' . $query;
}

return $this->getPath() . $query . $anchor;
}

public function setQueryString($queryString)
Expand All @@ -299,9 +325,9 @@ public function setQueryString($queryString)
return $this;
}

public function getQueryString()
public function getQueryString($separator = null)
{
return (string) $this->params;
return $this->params->toString($separator);
}

/**
Expand All @@ -311,12 +337,17 @@ public function getQueryString()
*/
public function getAbsoluteUrl($separator = '&')
{
$relativeUrl = $this->getRelativeUrl($separator);
if ($relativeUrl === '#') {
return $relativeUrl;
$path = $this->buildPathQueryAndFragment($separator);
if ($path && ($path === '#' || $path[0] === '/')) {
return $path;
}

return $this->baseUrl . ($this->baseUrl !== '/' && $relativeUrl ? '/' : '') . $relativeUrl;
$baseUrl = $this->getBaseUrl();
if (! $baseUrl) {
$baseUrl = '/';
}

return $baseUrl . ($baseUrl !== '/' && $path ? '/' : '') . $path;
}

/**
Expand Down Expand Up @@ -434,10 +465,20 @@ public function setParam($param, $value = true)
*/
public function setAnchor($anchor)
{
$this->anchor = '#' . $anchor;
$this->anchor = $anchor;
return $this;
}

/**
* Return the url anchor-part
*
* @return string The site's anchor string without the '#'
*/
public function getAnchor()
{
return $this->anchor;
}

/**
* Remove provided key (if string) or keys (if array of string) from the query parameter array
*
Expand Down
6 changes: 3 additions & 3 deletions test/php/library/Icinga/Web/UrlTest.php
Expand Up @@ -82,13 +82,13 @@ public function testWhetherFromPathProperlyParsesUrlsWithoutQuery()
$url = Url::fromPath('/my/test/url.html');

$this->assertEquals(
'/',
'',
$url->getBaseUrl(),
'Url::fromPath does not recognize the correct base url'
);
$this->assertEquals(
'my/test/url.html',
$url->getPath(),
'/my/test/url.html',
$url->getAbsoluteUrl(),
'Url::fromPath does not recognize the correct url path'
);
}
Expand Down

0 comments on commit 7321d67

Please sign in to comment.