Commit 12fbb0f7 by Qiang Xue

url WIP

parent f65a0bd9
......@@ -27,7 +27,7 @@ class UrlManager extends Component
* @var string the URL suffix used when in 'path' format.
* For example, ".html" can be used so that the URL looks like pointing to a static HTML page. Defaults to empty.
*/
public $urlSuffix = '';
public $suffix;
/**
* @var boolean whether to show entry script name in the constructed URL. Defaults to true.
*/
......@@ -122,7 +122,7 @@ class UrlManager extends Component
/** @var $rule UrlRule */
foreach ($this->rules as $rule) {
if (($url = $rule->createUrl($route, $params)) !== false) {
if (($url = $rule->createUrl($this, $route, $params)) !== false) {
return $this->getBaseUrl() . $url . $anchor;
}
}
......@@ -144,4 +144,20 @@ class UrlManager extends Component
{
$this->_baseUrl = trim($value, '/');
}
/**
* Removes the URL suffix from path info.
* @param string $pathInfo path info part in the URL
* @param string $suffix the URL suffix to be removed
* @return string path info with URL suffix removed.
*/
public function removeSuffix($pathInfo, $suffix)
{
$n = strlen($suffix);
if ($n > 0 && substr($pathInfo, -$n) === $suffix) {
return substr($pathInfo, 0, -$n);
} else {
return $pathInfo;
}
}
}
......@@ -20,6 +20,15 @@ use yii\base\Object;
class UrlRule extends Object
{
/**
* Set [[mode]] with this value to mark that this rule is for URL parsing only
*/
const PARSING_ONLY = 1;
/**
* Set [[mode]] with this value to mark that this rule is for URL creation only
*/
const CREATION_ONLY = 2;
/**
* @var string regular expression used to parse a URL
*/
public $pattern;
......@@ -34,11 +43,6 @@ class UrlRule extends Object
*/
public $defaults = array();
/**
* @var boolean whether this rule is only used for request parsing.
* Defaults to false, meaning the rule is used for both URL parsing and creation.
*/
public $parsingOnly = false;
/**
* @var string the URL suffix used for this rule.
* For example, ".html" can be used so that the URL looks like pointing to a static HTML page.
* If not, the value of [[UrlManager::suffix]] will be used.
......@@ -49,7 +53,6 @@ class UrlRule extends Object
* Use array to represent multiple verbs that this rule may match.
* If this property is not set, the rule can match any verb.
* Note that this property is only used when parsing a request. It is ignored for URL creation.
* @see parsingOnly
*/
public $verb;
/**
......@@ -57,6 +60,14 @@ class UrlRule extends Object
* If not set, it means the host info is ignored.
*/
public $hostInfo;
/**
* @var integer a value indicating if this rule should be used for both URL parsing and creation,
* parsing only, or creation only.
* If not set, it means the rule is both URL parsing and creation.
* If it is [[PARSING_ONLY]], the rule is for URL parsing only.
* If it is [[CREATION_ONLY]], the rule is for URL creation only.
*/
public $mode;
/**
* @var string the template for generating a new URL. This is derived from [[pattern]] and is used in generating URL.
......@@ -138,12 +149,38 @@ class UrlRule extends Object
}
}
public function parseUrl($pathInfo)
/**
* Parses the given path info and returns the corresponding route and parameters.
* @param UrlManager $manager the URL manager
* @param string $pathInfo the path info to be parsed. It should not have slashes at the beginning or the end.
* @return array|boolean the parsing result. The route and the parameters are returned as an array.
* If false, it means this rule cannot be used to parse this path info.
*/
public function parseUrl($manager, $pathInfo)
{
if ($this->mode === self::CREATION_ONLY) {
return false;
}
if ($this->verb !== null && !in_array(\Yii::$app->getRequest()->verb, $this->verb, true)) {
return false;
}
$suffix = (string)($this->suffix === null ? $manager->suffix : $this->suffix);
if ($suffix !== '' && $pathInfo !== '') {
$n = strlen($suffix);
if (substr($pathInfo, -$n) === $suffix) {
$pathInfo = substr($pathInfo, 0, -$n);
if ($pathInfo === '') {
// suffix alone is not allowed
return false;
}
} elseif ($suffix !== '/') {
// we allow the ending '/' to be optional if it is a suffix
return false;
}
}
if (!preg_match($this->pattern, $pathInfo, $matches)) {
return false;
}
......@@ -170,9 +207,16 @@ class UrlRule extends Object
return array($route, $params);
}
public function createUrl($route, $params)
/**
* Creates a URL according to the given route and parameters.
* @param UrlManager $manager the URL manager
* @param string $route the route. It should not have slashes at the beginning or the end.
* @param array $params the parameters
* @return string|boolean the created URL, or false if this rule cannot be used for creating this URL.
*/
public function createUrl($manager, $route, $params)
{
if ($this->parsingOnly) {
if ($this->mode === self::PARSING_ONLY) {
return false;
}
......@@ -225,6 +269,11 @@ class UrlRule extends Object
if (strpos($url, '//') !== false) {
$url = preg_replace('#/+#', '/', $url);
}
if ($url !== '') {
$url .= ($this->suffix === null ? $manager->suffix : $this->suffix);
}
if ($params !== array()) {
$url .= '?' . http_build_query($params);
}
......
......@@ -2,19 +2,21 @@
namespace yiiunit\framework\web;
use yii\web\UrlManager;
use yii\web\UrlRule;
class UrlRuleTest extends \yiiunit\TestCase
{
public function testCreateUrl()
{
$manager = new UrlManager;
$suites = $this->getTestsForCreateUrl();
foreach ($suites as $i => $suite) {
list ($name, $config, $tests) = $suite;
$rule = new UrlRule($config);
foreach ($tests as $j => $test) {
list ($route, $params, $expected) = $test;
$url = $rule->createUrl($route, $params);
$url = $rule->createUrl($manager, $route, $params);
$this->assertEquals($expected, $url, "Test#$i-$j: $name");
}
}
......@@ -22,6 +24,7 @@ class UrlRuleTest extends \yiiunit\TestCase
public function testParseUrl()
{
$manager = new UrlManager;
$suites = $this->getTestsForParseUrl();
foreach ($suites as $i => $suite) {
list ($name, $config, $tests) = $suite;
......@@ -30,7 +33,7 @@ class UrlRuleTest extends \yiiunit\TestCase
$pathInfo = $test[0];
$route = $test[1];
$params = isset($test[2]) ? $test[2] : array();
$result = $rule->parseUrl($pathInfo);
$result = $rule->parseUrl($manager, $pathInfo);
if ($route === false) {
$this->assertFalse($result, "Test#$i-$j: $name");
} else {
......@@ -75,6 +78,17 @@ class UrlRuleTest extends \yiiunit\TestCase
),
),
array(
'parsing only',
array(
'pattern' => 'posts',
'route' => 'post/index',
'mode' => UrlRule::PARSING_ONLY,
),
array(
array('post/index', array(), false),
),
),
array(
'with param',
array(
'pattern' => 'post/<page>',
......@@ -259,6 +273,58 @@ class UrlRuleTest extends \yiiunit\TestCase
array('post/index', array('page' => 1), 'post?page=1'),
),
),
array(
'empty pattern with suffix',
array(
'pattern' => '',
'route' => 'post/index',
'suffix' => '.html',
),
array(
array('post/index', array(), ''),
array('comment/index', array(), false),
array('post/index', array('page' => 1), '?page=1'),
),
),
array(
'regular pattern with suffix',
array(
'pattern' => 'posts',
'route' => 'post/index',
'suffix' => '.html',
),
array(
array('post/index', array(), 'posts.html'),
array('comment/index', array(), false),
array('post/index', array('page' => 1), 'posts.html?page=1'),
),
),
array(
'empty pattern with slash suffix',
array(
'pattern' => '',
'route' => 'post/index',
'suffix' => '/',
),
array(
array('post/index', array(), ''),
array('comment/index', array(), false),
array('post/index', array('page' => 1), '?page=1'),
),
),
array(
'regular pattern with slash suffix',
array(
'pattern' => 'posts',
'route' => 'post/index',
'suffix' => '/',
),
array(
array('post/index', array(), 'posts/'),
array('comment/index', array(), false),
array('post/index', array('page' => 1), 'posts/?page=1'),
),
),
);
}
......@@ -295,6 +361,17 @@ class UrlRuleTest extends \yiiunit\TestCase
),
),
array(
'creation only',
array(
'pattern' => 'posts',
'route' => 'post/index',
'mode' => UrlRule::CREATION_ONLY,
),
array(
array('posts', false),
),
),
array(
'with param',
array(
'pattern' => 'post/<page>',
......@@ -479,6 +556,58 @@ class UrlRuleTest extends \yiiunit\TestCase
array('index', false),
),
),
array(
'empty pattern with suffix',
array(
'pattern' => '',
'route' => 'post/index',
'suffix' => '.html',
),
array(
array('', 'post/index'),
array('.html', false),
array('a.html', false),
),
),
array(
'regular pattern with suffix',
array(
'pattern' => 'posts',
'route' => 'post/index',
'suffix' => '.html',
),
array(
array('posts.html', 'post/index'),
array('posts', false),
array('posts.HTML', false),
array('a.html', false),
array('a', false),
),
),
array(
'empty pattern with slash suffix',
array(
'pattern' => '',
'route' => 'post/index',
'suffix' => '/',
),
array(
array('', 'post/index'),
array('a', false),
),
),
array(
'regular pattern with slash suffix',
array(
'pattern' => 'posts',
'route' => 'post/index',
'suffix' => '/',
),
array(
array('posts', 'post/index'),
array('a', false),
),
),
);
}
}
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