From c08c2e8b727031248a820b682070b7a5afa8ba36 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Sun, 17 Feb 2013 12:50:03 -0500 Subject: [PATCH] url wip --- framework/caching/Cache.php | 2 +- framework/web/UrlManager.php | 151 +++++++++++++++++++++++++------------------ framework/web/UrlRule.php | 5 -- 3 files changed, 88 insertions(+), 70 deletions(-) diff --git a/framework/caching/Cache.php b/framework/caching/Cache.php index a35785c..1c5765c 100644 --- a/framework/caching/Cache.php +++ b/framework/caching/Cache.php @@ -95,7 +95,7 @@ abstract class Cache extends Component implements \ArrayAccess return (string)$key; } else { $params = func_get_args(); - return md5(serialize($params)); + return md5(json_encode($params)); } } diff --git a/framework/web/UrlManager.php b/framework/web/UrlManager.php index 8f927e8..a69385c 100644 --- a/framework/web/UrlManager.php +++ b/framework/web/UrlManager.php @@ -9,6 +9,7 @@ namespace yii\web; +use Yii; use \yii\base\Component; /** @@ -20,69 +21,43 @@ use \yii\base\Component; class UrlManager extends Component { /** - * @var array the URL rules (pattern=>route). + * @var boolean whether to enable pretty URLs. + */ + public $enablePrettyUrl = false; + /** + * @var array the rules for creating and parsing URLs when [[enablePrettyUrl]] is true. + * This property is used only if [[enablePrettyUrl]] is true. Each element in the array + * is the configuration of creating a single URL rule whose class by default is [[defaultRuleClass]]. + * If you modify this property after the UrlManager object is created, make sure + * populate the array with the rule objects instead of configurations. */ public $rules = array(); /** * @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. + * For example, ".html" can be used so that the URL looks like pointing to a static HTML page. + * This property is used only if [[enablePrettyUrl]] is true. */ public $suffix; /** * @var boolean whether to show entry script name in the constructed URL. Defaults to true. + * This property is used only if [[enablePrettyUrl]] is true. */ public $showScriptName = true; /** - * @var boolean whether to append GET parameters to the path info part. Defaults to true. - * This property is only effective when {@link urlFormat} is 'path' and is mainly used when - * creating URLs. When it is true, GET parameters will be appended to the path info and - * separate from each other using slashes. If this is false, GET parameters will be in query part. - */ - public $appendParams = true; - /** * @var string the GET variable name for route. Defaults to 'r'. */ public $routeVar = 'r'; /** - * @var boolean whether routes are case-sensitive. Defaults to true. By setting this to false, - * the route in the incoming request will be turned to lower case first before further processing. - * As a result, you should follow the convention that you use lower case when specifying - * controller mapping ({@link CWebApplication::controllerMap}) and action mapping - * ({@link CController::actions}). Also, the directory names for organizing controllers should - * be in lower case. - */ - public $caseSensitive = true; - /** - * @var boolean whether the GET parameter values should match the corresponding - * sub-patterns in a rule before using it to create a URL. Defaults to false, meaning - * a rule will be used for creating a URL only if its route and parameter names match the given ones. - * If this property is set true, then the given parameter values must also match the corresponding - * parameter sub-patterns. Note that setting this property to true will degrade performance. - * @since 1.1.0 - */ - public $matchValue = false; - /** - * @var string the ID of the cache application component that is used to cache the parsed URL rules. - * Defaults to 'cache' which refers to the primary cache application component. + * @var string the ID of the cache component that is used to cache the parsed URL rules. + * Defaults to 'cache' which refers to the primary cache component registered with the application. * Set this property to false if you want to disable caching URL rules. */ public $cacheID = 'cache'; /** - * @var boolean whether to enable strict URL parsing. - * This property is only effective when {@link urlFormat} is 'path'. - * If it is set true, then an incoming URL must match one of the {@link rules URL rules}. - * Otherwise, it will be treated as an invalid request and trigger a 404 HTTP exception. - * Defaults to false. + * @var string the class name or configuration for URL rule instances. + * This will be passed to [[\Yii::createObject()]] to create the URL rule instances. */ - public $useStrictParsing = false; - /** - * @var string the class name or path alias for the URL rule instances. Defaults to 'CUrlRule'. - * If you change this to something else, please make sure that the new class must extend from - * {@link CBaseUrlRule} and have the same constructor signature as {@link CUrlRule}. - * It must also be serializable and autoloadable. - * @since 1.1.8 - */ - public $urlRuleClass = 'CUrlRule'; + public $defaultRuleClass = 'yii\web\UrlRule'; /** * Initializes the application component. @@ -90,29 +65,67 @@ class UrlManager extends Component public function init() { parent::init(); - $this->processRules(); - } - /** - * Processes the URL rules. - */ - protected function processRules() - { - foreach ($this->rules as $i => $rule) { - if (!isset($rule['class'])) { - $rule['class'] = 'yii\web\UrlRule'; + if ($this->enablePrettyUrl && $this->rules !== array()) { + /** + * @var $cache \yii\caching\Cache + */ + if ($this->cacheID !== false && ($cache = Yii::$app->getComponent($this->cacheID)) !== null) { + $key = $cache->buildKey(__CLASS__); + $hash = md5(json_encode($this->rules)); + if (($data = $cache->get($key)) !== false && isset($data[1]) && $data[1] === $hash) { + $this->rules = $data[0]; + return; + } + } + + foreach ($this->rules as $i => $rule) { + if (!isset($rule['class'])) { + $rule['class'] = $this->defaultRuleClass; + } + $this->rules[$i] = Yii::createObject($rule); + } + + if (isset($cache)) { + $cache->set($key, array($this->rules, $hash)); } - $this->rules[$i] = \Yii::createObject($rule); } } /** * Parses the user request. - * @param Request $request the request application component - * @return string the route (controllerID/actionID) and perhaps GET parameters in path format. + * @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. */ public function parseUrl($request) { + if ($this->enablePrettyUrl) { + $pathInfo = $request->pathInfo; + /** @var $rule UrlRule */ + foreach ($this->rules as $rule) { + if (($result = $rule->parseUrl($this, $pathInfo)) !== false) { + return $result; + } + } + + $suffix = (string)$this->suffix; + if ($suffix !== '' && $suffix !== '/' && $pathInfo !== '') { + $n = strlen($this->suffix); + if (substr($pathInfo, -$n) === $this->suffix) { + $pathInfo = substr($pathInfo, 0, -$n); + if ($pathInfo === '') { + // suffix alone is not allowed + return false; + } + } + } + + return array($pathInfo, array()); + } else { + $route = (string)$request->getParam($this->routeVar); + return array($route, array()); + } } public function createUrl($route, $params = array()) @@ -120,17 +133,27 @@ class UrlManager extends Component $anchor = isset($params['#']) ? '#' . $params['#'] : ''; unset($anchor['#']); - /** @var $rule UrlRule */ - foreach ($this->rules as $rule) { - if (($url = $rule->createUrl($this, $route, $params)) !== false) { - return $this->getBaseUrl() . $url . $anchor; + $route = trim($route, '/'); + + if ($this->enablePrettyUrl) { + /** @var $rule UrlRule */ + foreach ($this->rules as $rule) { + if (($url = $rule->createUrl($this, $route, $params)) !== false) { + return $this->getBaseUrl() . $url . $anchor; + } } - } - if ($params !== array()) { - $route .= '?' . http_build_query($params); + if ($this->suffix !== null) { + $route .= $this->suffix; + } + if ($params !== array()) { + $route .= '?' . http_build_query($params); + } + return $this->getBaseUrl() . '/' . $route . $anchor; + } else { + $params[$this->routeVar] = $route; + return $this->getBaseUrl() . '?' . http_build_query($params) . $anchor; } - return $this->getBaseUrl() . '/' . $route . $anchor; } private $_baseUrl; diff --git a/framework/web/UrlRule.php b/framework/web/UrlRule.php index 471712b..97214c9 100644 --- a/framework/web/UrlRule.php +++ b/framework/web/UrlRule.php @@ -56,11 +56,6 @@ class UrlRule extends Object */ public $verb; /** - * @var string the host info (e.g. `http://www.example.com`) that this rule should match. - * 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.