Commit 1c3e61ec by Qiang Xue

Fixes #4591: `yii\helpers\Url::to()` will no longer prefix relative URLs with the base URL

parent 0cfaa17b
......@@ -216,6 +216,7 @@ Yii Framework 2 Change Log
- Chg #4310: Removed `$data` from signature of `yii\rbac\ManagerInterface` (samdark)
- Chg #4318: `yii\helpers\Html::ul()` and `ol()` will return an empty list tag if an empty item array is given (qiangxue)
- Chg #4331: `yii\helpers\Url` now uses `UrlManager` to determine base URL when generating URLs (qiangxue)
- Chg #4591: `yii\helpers\Url::to()` will no longer prefix relative URLs with the base URL (qiangxue)
- Chg: Replaced `clearAll()` and `clearAllAssignments()` in `yii\rbac\ManagerInterface` with `removeAll()`, `removeAllRoles()`, `removeAllPermissions()`, `removeAllRules()` and `removeAllAssignments()` (qiangxue)
- Chg: Added `$user` as the first parameter of `yii\rbac\Rule::execute()` (qiangxue)
- Chg: `yii\grid\DataColumn::getDataCellValue()` visibility is now `public` to allow accessing the value from a GridView directly (cebe)
......
......@@ -174,6 +174,10 @@ new ones save the following code as `convert.php` that should be placed in the s
```
* Due to significant changes to security you need to upgrade your code to use `\yii\base\Security` component instead of
helper. If you have any data encrypted it should be re-encrypted. In order to do so you can use old security helper [as
explained by @docsolver at github](https://github.com/yiisoft/yii2/issues/4461#issuecomment-50237807).
helper. If you have any data encrypted it should be re-encrypted. In order to do so you can use old security helper
[as explained by @docsolver at github](https://github.com/yiisoft/yii2/issues/4461#issuecomment-50237807).
* [[yii\helpers\Url::to()]] will no longer prefix base URL to relative URLs. For example, `Url::to('images/logo.png')`
will return `images/logo.png` directly. If you want a relative URL to be prefix with base URL, you should make use
of the alias `@web`. For example, `Url::to('@web/images/logo.png')` will return `/BaseUrl/images/logo.png`.
......@@ -73,7 +73,7 @@ class BaseUrl
* @param boolean|string $scheme the URI scheme to use in the generated URL:
*
* - `false` (default): generating a relative URL.
* - `true`: generating an absolute URL whose scheme is the same as the current request.
* - `true`: returning an absolute base URL whose scheme is the same as that in [[\yii\web\UrlManager::hostInfo]].
* - string: generating an absolute URL with the specified scheme (either `http` or `https`).
*
* @return string the generated URL
......@@ -133,21 +133,20 @@ class BaseUrl
* Creates a URL based on the given parameters.
*
* This method is very similar to [[toRoute()]]. The only difference is that this method
* requires a route to be specified as an array only. If a string is given, it will be treated
* as a URL which will be prefixed with the base URL if it does not start with a slash.
* requires a route to be specified as an array only. If a string is given, it will be treated as a URL.
* In particular, if `$url` is
*
* - an array: [[toRoute()]] will be called to generate the URL. For example:
* `['site/index']`, `['post/index', 'page' => 2]`. Please refer to [[toRoute()]] for more details
* on how to specify a route.
* - a string with a leading `@`: it is treated as an alias and the corresponding aliased string
* will be subject to the following rules.
* - a string with a leading `@`: it is treated as an alias, and the corresponding aliased string
* will be returned.
* - an empty string: the currently requested URL will be returned;
* - a string without a leading slash: it will be prefixed with [[\yii\web\Request::baseUrl]].
* - a string with a leading slash: it will be returned as is.
* - a normal string: it will be returned as is.
*
* Note that in case `$scheme` is specified (either a string or true), an absolute URL with host info
* will be returned.
* When `$scheme` is specified (either a string or true), an absolute URL with host info (obtained from
* [[\yii\web\UrlManager::hostInfo]]) will be returned. If `$url` is already an absolute URL, its scheme
* will be replaced with the specified one.
*
* Below are some examples of using this method:
*
......@@ -162,13 +161,16 @@ class BaseUrl
* echo Url::to();
*
* // /images/logo.gif
* echo Url::to('@web/images/logo.gif');
*
* // images/logo.gif
* echo Url::to('images/logo.gif');
*
* // http://www.example.com/index.php?r=site/index
* echo Url::to(['site/index'], true);
* // http://www.example.com/images/logo.gif
* echo Url::to('@web/images/logo.gif', true);
*
* // https://www.example.com/index.php?r=site/index
* echo Url::to(['site/index'], 'https');
* // https://www.example.com/images/logo.gif
* echo Url::to('@web/images/logo.gif', 'https');
* ```
*
*
......@@ -176,7 +178,7 @@ class BaseUrl
* @param boolean|string $scheme the URI scheme to use in the generated URL:
*
* - `false` (default): generating a relative URL.
* - `true`: generating an absolute URL whose scheme is the same as the current request.
* - `true`: returning an absolute base URL whose scheme is the same as that in [[\yii\web\UrlManager::hostInfo]].
* - string: generating an absolute URL with the specified scheme (either `http` or `https`).
*
* @return string the generated URL
......@@ -188,26 +190,29 @@ class BaseUrl
return static::toRoute($url, $scheme);
}
$url = (string) Yii::getAlias($url);
$url = Yii::getAlias($url);
if ($url === '') {
$url = Yii::$app->getRequest()->getUrl();
} else {
$hasScheme = ($pos = strpos($url, ':')) > 0 && ctype_alpha(substr($url, 0, $pos));
$char = $url[0];
if ($char !== '/' && $char !== '#' && $char !== '.' && !$hasScheme) {
$url = Yii::$app->getUrlManager()->getBaseUrl() . '/' . $url;
}
if (!$scheme) {
return $url;
}
if ($scheme) {
if (empty($hasScheme)) {
if (strncmp($url, '//', 2) === 0) {
// e.g. //hostname/path/to/resource
return is_string($scheme) ? "$scheme:$url" : $url;
}
if (($pos = strpos($url, ':')) == false || !ctype_alpha(substr($url, 0, $pos))) {
// turn relative URL into absolute
$url = Yii::$app->getUrlManager()->getHostInfo() . '/' . ltrim($url, '/');
}
if (is_string($scheme) && ($pos = strpos($url, ':')) !== false) {
// replace the scheme with the specified one
$url = $scheme . substr($url, $pos);
}
}
return $url;
}
......@@ -217,7 +222,7 @@ class BaseUrl
* @param boolean|string $scheme the URI scheme to use in the returned base URL:
*
* - `false` (default): returning the base URL without host info.
* - `true`: returning an absolute base URL whose scheme is the same as the current request.
* - `true`: returning an absolute base URL whose scheme is the same as that in [[\yii\web\UrlManager::hostInfo]].
* - string: returning an absolute base URL with the specified scheme (either `http` or `https`).
* @return string
*/
......@@ -296,7 +301,7 @@ class BaseUrl
* @param boolean|string $scheme the URI scheme to use for the returned URL:
*
* - `false` (default): returning a relative URL.
* - `true`: returning an absolute URL whose scheme is the same as the current request.
* - `true`: returning an absolute base URL whose scheme is the same as that in [[\yii\web\UrlManager::hostInfo]].
* - string: returning an absolute URL with the specified scheme (either `http` or `https`).
*
* @return string home URL
......
......@@ -121,21 +121,22 @@ class UrlTest extends TestCase
\Yii::setAlias('@web4', '/test');
\Yii::setAlias('@web5', '#test');
$this->assertEquals('/base/test/me1', Url::to('test/me1'));
$this->assertEquals('test/me1', Url::to('test/me1'));
$this->assertEquals('javascript:test/me1', Url::to('javascript:test/me1'));
$this->assertEquals('/base/java/script:test/me1', Url::to('java/script:test/me1'));
$this->assertEquals('java/script:test/me1', Url::to('java/script:test/me1'));
$this->assertEquals('#test/me1', Url::to('#test/me1'));
$this->assertEquals('.test/me1', Url::to('.test/me1'));
$this->assertEquals('http://example.com/base/test/me1', Url::to('test/me1', true));
$this->assertEquals('https://example.com/base/test/me1', Url::to('test/me1', 'https'));
$this->assertEquals('http://example.com/test/me1', Url::to('test/me1', true));
$this->assertEquals('https://example.com/test/me1', Url::to('test/me1', 'https'));
$this->assertEquals('https://example.com/test/test/me1', Url::to('@web4/test/me1', 'https'));
$this->assertEquals('http://test.example.com/test/me1', Url::to('@web1'));
$this->assertEquals('http://test.example.com/test/me1', Url::to('@web1', true));
$this->assertEquals('https://test.example.com/test/me1', Url::to('@web1', 'https'));
$this->assertEquals('/base/test/me2', Url::to('@web2'));
$this->assertEquals('http://example.com/base/test/me2', Url::to('@web2', true));
$this->assertEquals('https://example.com/base/test/me2', Url::to('@web2', 'https'));
$this->assertEquals('test/me2', Url::to('@web2'));
$this->assertEquals('http://example.com/test/me2', Url::to('@web2', true));
$this->assertEquals('https://example.com/test/me2', Url::to('@web2', 'https'));
$this->assertEquals('/base/index.php&r=site%2Fcurrent&id=42', Url::to('@web3'));
$this->assertEquals('http://example.com/base/index.php&r=site%2Fcurrent&id=42', Url::to('@web3', true));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment