Commit 6e8c4602 by Qiang Xue

Fixes #2724: consistent use of absolute and relative routes.

parent 300c5a54
......@@ -9,6 +9,7 @@ namespace yii\debug;
use Yii;
use yii\base\Application;
use yii\helpers\Url;
use yii\web\View;
use yii\web\ForbiddenHttpException;
......@@ -124,7 +125,7 @@ class Module extends \yii\base\Module
if (!$this->checkAccess() || Yii::$app->getRequest()->getIsAjax()) {
return;
}
$url = Yii::$app->getUrlManager()->createUrl([$this->id . '/default/toolbar',
$url = Url::toRoute(['/' . $this->id . '/default/toolbar',
'tag' => $this->logTarget->tag,
]);
echo '<div id="yii-debug-toolbar" data-url="' . $url . '" style="display:none"></div>';
......
......@@ -9,6 +9,7 @@ namespace yii\debug;
use Yii;
use yii\base\Component;
use yii\helpers\Url;
/**
* Panel is a base class for debugger panel classes. It defines how data should be collected,
......@@ -88,7 +89,7 @@ class Panel extends Component
*/
public function getUrl()
{
return Yii::$app->getUrlManager()->createUrl([$this->module->id . '/default/view',
return Url::toRoute(['/' . $this->module->id . '/default/view',
'panel' => $this->id,
'tag' => $this->tag,
]);
......
......@@ -35,8 +35,9 @@ use yii\widgets\InputWidget;
class Captcha extends InputWidget
{
/**
* @var string the route of the action that generates the CAPTCHA images.
* @var string|array the route of the action that generates the CAPTCHA images.
* The action represented by this route must be an action of [[CaptchaAction]].
* Please refer to [[\yii\helpers\Url::toRoute()]] for acceptable formats.
*/
public $captchaAction = 'site/captcha';
/**
......@@ -81,8 +82,13 @@ class Captcha extends InputWidget
} else {
$input = Html::textInput($this->name, $this->value, $this->options);
}
$url = Yii::$app->getUrlManager()->createUrl([$this->captchaAction, 'v' => uniqid()]);
$image = Html::img($url, $this->imageOptions);
$route = $this->captchaAction;
if (is_array($route)) {
$route['v'] = uniqid();
} else {
$route = [$route, 'v' => uniqid()];
}
$image = Html::img($route, $this->imageOptions);
echo strtr($this->template, [
'{input}' => $input,
'{image}' => $image,
......
......@@ -184,7 +184,7 @@ class UrlManager extends Component
/**
* Parses the user request.
* @param Request $request the request component
* @param Request $request the request component
* @return array|boolean the route and the associated parameters. The latter is always empty
* if [[enablePrettyUrl]] is false. False is returned if the current request cannot be successfully parsed.
*/
......@@ -205,7 +205,7 @@ class UrlManager extends Component
Yii::trace('No matching URL rules. Using default URL parsing logic.', __METHOD__);
$suffix = (string) $this->suffix;
$suffix = (string)$this->suffix;
if ($suffix !== '' && $pathInfo !== '') {
$n = strlen($this->suffix);
if (substr($pathInfo, -$n) === $this->suffix) {
......@@ -228,19 +228,42 @@ class UrlManager extends Component
$route = '';
}
return [(string) $route, []];
return [(string)$route, []];
}
}
/**
* Creates a URL using the given route and parameters.
* Creates a URL using the given route and query parameters.
*
* You may specify the route as a string, e.g., `site/index`. You may also use an array
* if you want to specify additional query parameters for the URL being created. The
* array format must be:
*
* ```php
* // generates: /index.php?r=site/index&param1=value1&param2=value2
* ['site/index', 'param1' => 'value1', 'param2' => 'value2']
* ```
*
* If you want to create a URL with an anchor, you can use the array format with a `#` parameter.
* For example,
*
* ```php
* // generates: /index.php?r=site/index&param1=value1#name
* ['site/index', 'param1' => 'value1', '#' => 'name']
* ```
*
* The URL created is a relative one. Use [[createAbsoluteUrl()]] to create an absolute URL.
* @param string|array $params route as a string or route and parameters in form of ['route', 'param1' => 'value1', 'param2' => 'value2']
* @return string the created URL
*
* Note that unlike [[\yii\helpers\Url::toRoute()]], this method always treats the given route
* as an absolute route.
*
* @param string|array $params use a string to represent a route (e.g. `site/index`),
* or an array to represent a route with query parameters (e.g. `['site/index', 'param1' => 'value1']`).
* @return string the created URL
*/
public function createUrl($params)
{
$params = (array) $params;
$params = (array)$params;
$anchor = isset($params['#']) ? '#' . $params['#'] : '';
unset($params['#'], $params[$this->routeParam]);
......@@ -283,23 +306,29 @@ class UrlManager extends Component
}
/**
* Creates an absolute URL using the given route and parameters.
* Creates an absolute URL using the given route and query parameters.
*
* This method prepends the URL created by [[createUrl()]] with the [[hostInfo]].
* @param string|array $params route as a string or route and parameters in form of ['route', 'param1' => 'value1', 'param2' => 'value2']
* @param string $schema the schema to use for the url. e.g. 'http' or 'https'. If not specified
* the schema of the current request will be used.
* @return string the created URL
*
* Note that unlike [[\yii\helpers\Url::toRoute()]], this method always treats the given route
* as an absolute route.
*
* @param string|array $params use a string to represent a route (e.g. `site/index`),
* or an array to represent a route with query parameters (e.g. `['site/index', 'param1' => 'value1']`).
* @param string $scheme the scheme to use for the url (either `http` or `https`). If not specified
* the scheme of the current request will be used.
* @return string the created URL
* @see createUrl()
*/
public function createAbsoluteUrl($params, $schema = null)
public function createAbsoluteUrl($params, $scheme = null)
{
$params = (array) $params;
$params = (array)$params;
$url = $this->createUrl($params);
if (strpos($url, '://') === false) {
$url = $this->getHostInfo() . $url;
}
if ($schema && ($pos = strpos($url, '://')) !== false) {
$url = $schema . substr($url, $pos);
if (is_string($scheme) && ($pos = strpos($url, '://')) !== false) {
$url = $scheme . substr($url, $pos);
}
return $url;
......
......@@ -75,13 +75,11 @@ class UrlTest extends TestCase
$this->assertEquals('http://example.com/base/index.php?r=stats/user/view&id=42', Url::toRoute(['user/view', 'id' => 42], true));
$this->assertEquals('https://example.com/base/index.php?r=stats/user/view&id=42', Url::toRoute(['user/view', 'id' => 42], 'https'));
// In case there is no controller, [[\yii\web\UrlManager::createUrl()]] will be used.
// In case there is no controller, an exception should be thrown for relative route
$this->removeMockedAction();
$this->assertEquals('/base/index.php?r=site/view', Url::toRoute('site/view'));
$this->assertEquals('http://example.com/base/index.php?r=site/view', Url::toRoute('site/view', true));
$this->assertEquals('https://example.com/base/index.php?r=site/view', Url::toRoute('site/view', 'https'));
$this->assertEquals('/base/index.php?r=site/view&id=37', Url::toRoute(['site/view', 'id' => 37]));
$this->setExpectedException('yii\base\InvalidParamException');
Url::toRoute('site/view');
}
public function testTo()
......@@ -101,27 +99,11 @@ class UrlTest extends TestCase
$this->assertEquals('https://example.com/base/index.php?r=page/edit', Url::to(['edit'], 'https'));
$this->assertEquals('https://example.com/base/index.php?r=page/view', Url::to([''], 'https'));
//In case there is no controller, [[\yii\web\UrlManager::createUrl()]] will be used.
$this->removeMockedAction();
$this->assertEquals('/base/index.php?r=edit&id=20', Url::to(['edit', 'id' => 20]));
$this->assertEquals('/base/index.php?r=edit', Url::to(['edit']));
$this->assertEquals('/base/index.php?r=', Url::to(['']));
$this->assertEquals('http://example.com/base/index.php?r=edit&id=20', Url::to(['edit', 'id' => 20], true));
$this->assertEquals('http://example.com/base/index.php?r=edit', Url::to(['edit'], true));
$this->assertEquals('http://example.com/base/index.php?r=', Url::to([''], true));
$this->assertEquals('https://example.com/base/index.php?r=edit&id=20', Url::to(['edit', 'id' => 20], 'https'));
$this->assertEquals('https://example.com/base/index.php?r=edit', Url::to(['edit'], 'https'));
$this->assertEquals('https://example.com/base/index.php?r=', Url::to([''], 'https'));
// is an empty string: the currently requested URL will be returned;
$this->mockAction('page', 'view', null, ['id' => 10]);
$this->assertEquals('/base/index.php&r=site/current&id=42', Url::to(''));
$this->assertEquals('http://example.com/base/index.php&r=site/current&id=42', Url::to('', true));
$this->assertEquals('https://example.com/base/index.php&r=site/current&id=42', Url::to('', 'https'));
$this->removeMockedAction();
// is a non-empty string: it will first be processed by [[Yii::getAlias()]]. If the result
// is an absolute URL, it will be returned either without any change or, if schema was specified, with schema
......@@ -140,17 +122,31 @@ class UrlTest extends TestCase
$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('/base/', Url::to('@web3'));
$this->assertEquals('http://example.com/base/', Url::to('@web3', true));
$this->assertEquals('https://example.com/base/', Url::to('@web3', 'https'));
$this->assertEquals('/base/index.php&r=site/current&id=42', Url::to('@web3'));
$this->assertEquals('http://example.com/base/index.php&r=site/current&id=42', Url::to('@web3', true));
$this->assertEquals('https://example.com/base/index.php&r=site/current&id=42', Url::to('@web3', 'https'));
$this->assertEquals('/test', Url::to('@web4'));
$this->assertEquals('http://example.com/test', Url::to('@web4', true));
$this->assertEquals('https://example.com/test', Url::to('@web4', 'https'));
$this->assertEquals('#test', Url::to('@web5'));
$this->assertEquals('http://example.com#test', Url::to('@web5', true));
$this->assertEquals('https://example.com#test', Url::to('@web5', 'https'));
$this->assertEquals('http://example.com/#test', Url::to('@web5', true));
$this->assertEquals('https://example.com/#test', Url::to('@web5', 'https'));
//In case there is no controller, throw an exception
$this->removeMockedAction();
$this->setExpectedException('yii\base\InvalidParamException');
Url::to(['site/view']);
}
public function testBase()
{
$this->mockAction('page', 'view', null, ['id' => 10]);
$this->assertEquals('/base', Url::base());
$this->assertEquals('http://example.com/base', Url::base(true));
$this->assertEquals('https://example.com/base', Url::base('https'));
}
public function testHome()
......
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