diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 828be306fc..15a85d98f0 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -47,6 +47,7 @@ Yii Framework 2 Change Log - Bug #3817: `yii\rbac\PhpManager::getChildren()` returns null instead of expected empty array (qiangxue) - Bug #3843: Fixed Menu bug when using `template` with `encodeLabel` => false (creocoder, umneeq) - Bug #3863: Fixed incorrect js selector for `\yii\widgets\ActiveForm::errorSummaryCssClass` when it contains multiple classes (creocoder, umneeq) +- Bug #3909: `Html::to()` should not prefix base URL to URLs that already contain scheme (qiangxue) - Bug: Fixed inconsistent return of `\yii\console\Application::runAction()` (samdark) - Bug: URL encoding for the route parameter added to `\yii\web\UrlManager` (klimov-paul) - Bug: Fixed the bug that requesting protected or private action methods would cause 500 error instead of 404 (qiangxue) diff --git a/framework/helpers/BaseUrl.php b/framework/helpers/BaseUrl.php index 1d0ca37a4e..e31c89d575 100644 --- a/framework/helpers/BaseUrl.php +++ b/framework/helpers/BaseUrl.php @@ -192,15 +192,19 @@ class BaseUrl if ($url === '') { $url = Yii::$app->getRequest()->getUrl(); - } elseif ($url[0] !== '/' && $url[0] !== '#' && $url[0] !== '.' && strpos($url, '://') === false) { - $url = Yii::$app->getRequest()->getBaseUrl() . '/' . $url; + } else { + $hasScheme = ($pos = strpos($url, ':')) > 0 && ctype_alpha(substr($url, 0, $pos)); + $char = $url[0]; + if ($char !== '/' && $char !== '#' && $char !== '.' && !$hasScheme) { + $url = Yii::$app->getRequest()->getBaseUrl() . '/' . $url; + } } if ($scheme) { - if (strpos($url, '://') === false) { + if (empty($hasScheme)) { $url = Yii::$app->getRequest()->getHostInfo() . '/' . ltrim($url, '/'); } - if (is_string($scheme) && ($pos = strpos($url, '://')) !== false) { + if (is_string($scheme) && ($pos = strpos($url, ':')) !== false) { $url = $scheme . substr($url, $pos); } } diff --git a/tests/unit/framework/helpers/UrlTest.php b/tests/unit/framework/helpers/UrlTest.php index a528c160b6..c98227ec04 100644 --- a/tests/unit/framework/helpers/UrlTest.php +++ b/tests/unit/framework/helpers/UrlTest.php @@ -115,6 +115,14 @@ class UrlTest extends TestCase \Yii::setAlias('@web4', '/test'); \Yii::setAlias('@web5', '#test'); + $this->assertEquals('/base/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('#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://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'));