Commit 842e7eb5 by Alexander Makarov

Added tests, final Url helper adjustments

parent bddad528
...@@ -48,13 +48,18 @@ class BaseUrl ...@@ -48,13 +48,18 @@ class BaseUrl
public static function toRoute($route, $schema = false) public static function toRoute($route, $schema = false)
{ {
$route = (array)$route; $route = (array)$route;
if (!isset($route[0])) {
throw new InvalidParamException('$route should contain at least one element.');
}
if (Yii::$app->controller instanceof \yii\web\Controller) { if (Yii::$app->controller instanceof \yii\web\Controller) {
$route[0] = static::getNormalizedRoute($route[0]); $route[0] = static::getNormalizedRoute($route[0]);
} }
return $schema ? Yii::$app->getUrlManager()->createAbsoluteUrl($route, $schema) : Yii::$app->getUrlManager()->createUrl($route); if ($schema) {
if ($schema === true) {
$schema = null;
}
$url = Yii::$app->getUrlManager()->createAbsoluteUrl($route, $schema);
} else {
$url = Yii::$app->getUrlManager()->createUrl($route);
}
return $url;
} }
/** /**
...@@ -90,13 +95,13 @@ class BaseUrl ...@@ -90,13 +95,13 @@ class BaseUrl
* If the input parameter * If the input parameter
* *
* - is an array: the first array element is considered a route, while the rest of the name-value * - is an array: the first array element is considered a route, while the rest of the name-value
* pairs are treated as the parameters to be used for URL creation using [[\yii\web\Controller::createUrl()]]. * pairs are treated as the parameters to be used for URL creation using [[toRoute]].
* For example: `['post/index', 'page' => 2]`, `['index']`. * For example: `['post/index', 'page' => 2]`, `['index']`.
* In case there is no controller, [[\yii\web\UrlManager::createUrl()]] will be used. * In case there is no controller, [[\yii\web\UrlManager::createUrl()]] will be used.
* - is an empty string: the currently requested URL will be returned; * - is an empty string: the currently requested URL will be returned;
* - is a non-empty string: it will first be processed by [[Yii::getAlias()]]. If the result * - is a non-empty string: it will first be processed by [[Yii::getAlias()]]. If the result
* is an absolute URL, it will be returned without any change further; Otherwise, the result * is an absolute URL, it will be returned either without any change or, if schema was specified, with schema
* will be prefixed with [[\yii\web\Request::baseUrl]] and returned. * replaced; Otherwise, the result will be prefixed with [[\yii\web\Request::baseUrl]] and returned.
* *
* @param array|string $url the parameter to be used to generate a valid URL * @param array|string $url the parameter to be used to generate a valid URL
...@@ -115,37 +120,25 @@ class BaseUrl ...@@ -115,37 +120,25 @@ class BaseUrl
return static::toRoute($url, $schema); return static::toRoute($url, $schema);
} elseif ($url === '') { } elseif ($url === '') {
if ($schema) { if ($schema) {
$url = Yii::$app->request->getAbsoluteUrl(); $url = Yii::$app->getRequest()->getAbsoluteUrl();
if ($schema !== true) {
$pos = strpos($url, '://');
$url = $schema . substr($url, $pos);
}
} else { } else {
$url = Yii::$app->request->getUrl(); $url = Yii::$app->getRequest()->getUrl();
} }
} else { } else {
$url = Yii::getAlias($url); $url = Yii::getAlias($url);
$pos = strpos($url, '://'); if (strpos($url, '://') === false) {
if ($pos !== null) {
// URI is already absolute, adjust schema if specified
if ($schema && $schema !== true) {
$url = $schema . substr($url, $pos);
}
} else {
// URI is relative
if ($url === '' || ($url[0] !== '/' && $url[0] !== '#' && strncmp($url, './', 2))) { if ($url === '' || ($url[0] !== '/' && $url[0] !== '#' && strncmp($url, './', 2))) {
// URL is relative need to adjust it to be absolute
$url = Yii::$app->getRequest()->getBaseUrl() . '/' . $url; $url = Yii::$app->getRequest()->getBaseUrl() . '/' . $url;
} }
if ($schema) { if ($schema) {
$url = Yii::$app->getRequest()->getHostInfo() . $url; $url = Yii::$app->getRequest()->getHostInfo() . $url;
if ($schema !== true) {
$pos = strpos($url, '://');
if ($pos !== null) {
$url = $schema . substr($url, $pos);
} }
} }
} }
if ($schema && $schema !== true) {
$pos = strpos($url, '://');
if ($pos !== false) {
$url = $schema . substr($url, $pos);
} }
} }
return $url; return $url;
......
<?php
namespace yiiunit\framework\helpers;
use yii\base\Action;
use yii\base\Module;
use yii\helpers\Url;
use yii\web\Controller;
use yiiunit\TestCase;
/**
* UrlTest
*/
class UrlTest extends TestCase
{
protected function setUp()
{
parent::setUp();
$this->mockApplication([
'components' => [
'request' => [
'class' => 'yii\web\Request',
'scriptUrl' => '/base/index.php',
'hostInfo' => 'http://example.com/',
'url' => '/base/index.php&r=site/current&id=42'
],
'user' => [
'class' => 'yii\web\User',
'identityClass' => 'stdObject',
],
],
], '\yii\web\Application');
}
/**
* Mocks controller action with parameters
*
* @param string $controllerId
* @param string $actionId
* @param string $moduleID
* @param array $params
*/
protected function mockAction($controllerId, $actionId, $moduleID = null, $params = [])
{
\Yii::$app->controller = $controller = new Controller($controllerId, \Yii::$app);
$controller->actionParams = $params;
$controller->action = new Action($actionId, $controller);
if ($moduleID !== null) {
$controller->module = new Module($moduleID);
}
}
protected function removeMockedAction()
{
\Yii::$app->controller = null;
}
public function testToRoute()
{
$this->mockAction('page', 'view', null, ['id' => 10]);
// If the route is an empty string, the current route will be used;
$this->assertEquals('/base/index.php?r=page/view', Url::toRoute(''));
$this->assertEquals('http://example.com/base/index.php?r=page/view', Url::toRoute('', true));
$this->assertEquals('https://example.com/base/index.php?r=page/view', Url::toRoute('', 'https'));
// If the route contains no slashes at all, it is considered to be an action ID of the current controller and
// will be prepended with uniqueId;
$this->assertEquals('/base/index.php?r=page/edit', Url::toRoute('edit'));
$this->assertEquals('/base/index.php?r=page/edit&id=20', Url::toRoute(['edit', 'id' => 20]));
$this->assertEquals('http://example.com/base/index.php?r=page/edit&id=20', Url::toRoute(['edit', 'id' => 20], true));
$this->assertEquals('https://example.com/base/index.php?r=page/edit&id=20', Url::toRoute(['edit', 'id' => 20], 'https'));
// If the route has no leading slash, it is considered to be a route relative
// to the current module and will be prepended with the module's uniqueId.
$this->mockAction('default', 'index', 'stats');
$this->assertEquals('/base/index.php?r=stats/user/view', Url::toRoute('user/view'));
$this->assertEquals('/base/index.php?r=stats/user/view&id=42', Url::toRoute(['user/view', 'id' => 42]));
$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.
$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]));
}
public function testTo()
{
// is an array: the first array element is considered a route, while the rest of the name-value
// pairs are treated as the parameters to be used for URL creation using Url::toRoute.
$this->mockAction('page', 'view', null, ['id' => 10]);
$this->assertEquals('/base/index.php?r=page/edit&id=20', Url::to(['edit', 'id' => 20]));
$this->assertEquals('/base/index.php?r=page/edit', Url::to(['edit']));
$this->assertEquals('/base/index.php?r=page/view', Url::to(['']));
$this->assertEquals('http://example.com/base/index.php?r=page/edit&id=20', Url::to(['edit', 'id' => 20], true));
$this->assertEquals('http://example.com/base/index.php?r=page/edit', Url::to(['edit'], true));
$this->assertEquals('http://example.com/base/index.php?r=page/view', Url::to([''], true));
$this->assertEquals('https://example.com/base/index.php?r=page/edit&id=20', Url::to(['edit', 'id' => 20], 'https'));
$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
// replaced; Otherwise, the result will be prefixed with [[\yii\web\Request::baseUrl]] and returned.
\Yii::setAlias('@web1', 'http://test.example.com/test/me1');
\Yii::setAlias('@web2', 'test/me2');
\Yii::setAlias('@web3', '');
\Yii::setAlias('@web4', '/test');
\Yii::setAlias('@web5', '#test');
$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('/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('/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'));
}
public function testHome()
{
$this->assertEquals('/base/index.php', Url::home());
$this->assertEquals('http://example.com/base/index.php', Url::home(true));
$this->assertEquals('https://example.com/base/index.php', Url::home('https'));
}
public function testCanonical()
{
$this->mockAction('page', 'view', null, ['id' => 10]);
$this->assertEquals('http://example.com/base/index.php?r=page/view&id=10', Url::canonical());
$this->removeMockedAction();
}
}
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