From 771e36aecb184fff7e1792342f8aba1c61ca5883 Mon Sep 17 00:00:00 2001 From: rMalie Date: Mon, 25 Jul 2011 17:33:46 +0000 Subject: [PATCH] // Routes for dispatcher (part 1) git-svn-id: http://dev.prestashop.com/svn/v1/branches/1.5.x@7727 b9a71923-0436-4b27-9f14-aed3839534dd --- classes/Dispatcher.php | 215 +++++++++++++++++++++++++++++++++++++++-- classes/Tools.php | 46 ++++----- index.php | 3 +- 3 files changed, 229 insertions(+), 35 deletions(-) diff --git a/classes/Dispatcher.php b/classes/Dispatcher.php index bfc08ec77..6e68c510b 100644 --- a/classes/Dispatcher.php +++ b/classes/Dispatcher.php @@ -2,14 +2,95 @@ class DispatcherCore { + /** + * @var Dispatcher + */ + public static $instance = null; + + /** + * @var array + */ + protected $defaultRoutes = array( + 'product' => array( + 'controller' => 'product', + 'rule' => '{number:id_product}-{word}.html', + ), + 'category' => array( + 'controller' => 'category', + 'rule' => '{number:id_category}-{word}', + ), + 'product_alt' => array( + 'controller' => 'product', + 'rule' => '{word1}/{number:id_product}-{word2}.html', + ), + 'supplier' => array( + 'controller' => 'supplier', + 'rule' => '{number:id_supplier}__{word}', + ), + 'manufacturer' => array( + 'controller' => 'manufacturer', + 'rule' => '{number:id_manufacturer}_{word}', + ), + 'cms' => array( + 'controller' => 'cms', + 'rule' => 'content/{number:id_cms}-{word}', + ), + 'cms_category' => array( + 'controller' => 'cms', + 'rule' => 'content/category/{number:id_cms_category}-{word}', + ), + ); + + /** + * @var $useRoutes bool + */ + protected $useRoutes = false; + + /** + * @var $routes array + */ + protected $routes = array(); + + /** + * @var array + */ + protected $keywords = array( + 'number' => '[0-9]+', + 'word' => '[a-zA-Z0-9-]*', + ); + public static $controllers = array(); public static $controller; - function __construct() + /** + * Get current instance of dispatcher (singleton) + * + * @return Dispatcher + */ + public static function getInstance() { - $this->loadControllers(); + if (!self::$instance) + self::$instance = new Dispatcher(); + return self::$instance; } + /** + * Need to be instancied from getInstance() method + */ + protected function __construct() + { + $this->useRoutes = (bool)Configuration::get('PS_REWRITING_SETTINGS'); + $this->loadControllers(); + + // Load default routes + if ($this->useRoutes) + foreach ($this->defaultRoutes as $id => $route) + $this->addRoute($id, $route['rule'], $route['controller']); + } + + /** + * "main" method of dispatcher, call the controller + */ public function dispatch() { self::$controller = $this->getController(); @@ -19,7 +100,86 @@ class DispatcherCore self::$controller = 'index'; ControllerFactory::getController(self::$controllers[self::$controller])->run(); } + + /** + * + * @param string $id Name of the route (need to be uniq, a second route with same name will override the first) + * @param string $rule URL rule + * @param string $controller Controller to call if request uri match the rule + */ + public function addRoute($routeID, $rule, $controller) + { + $regexp = preg_quote($rule, '#'); + $required = array(); + preg_match_all('#\\\{('.implode('|', array_keys($this->keywords)).')[0-9]*(\\\:([a-z0-9_]+))?\\\}#', $regexp, $m); + for ($i = 0, $total = count($m[0]); $i < $total; $i++) + if ($m[3][$i]) + { + $regexp = str_replace($m[0][$i], '(?P<'.$m[3][$i].'>'.$this->keywords[$m[1][$i]].')', $regexp); + $required[$m[3][$i]] = $m[1][$i]; + } + else + $regexp = str_replace($m[0][$i], '('.$this->keywords[$m[1][$i]].')', $regexp); + $regexp = '#^/'.$regexp.'#'; + $this->routes[$routeID] = array( + 'rule' => $rule, + 'regexp' => $regexp, + 'controller' => $controller, + 'required' => $required, + ); + } + + /** + * + * + * @param string $routeID Name the route + * @param array $params + */ + public function createUrl($routeID, $params = array()) + { + if (!is_array($params)) + die('Dispatcher::createURL() $params must be an array'); + + if (!isset($this->routes[$routeID])) + return ''; + $route = $this->routes[$routeID]; + + // Get required parameters + $queryParams = array(); + foreach (array_keys($route['required']) as $key) + { + if (!array_key_exists($key, $params)) + die("Dispatcher::createURL() miss required parameter '$key'"); + $queryParams[$key] = $params[$key]; + } + + // Build an URL which match a route + if ($this->useRoutes) + { + $url = $route['rule']; + + // Replace required parameters + foreach ($route['required'] as $key => $keyword) + { + $url = str_replace('{'.$keyword.':'.$key.'}', $params[$key], $url); + unset($params[$key]); + } + + // Replace other parameters + foreach ($params as $key => $value) + $url = str_replace('{'.$key.'}', $value, $url); + } + // Build a classic URL index.php?controller=foo&... + else + $url = 'index.php?controller='.$route['controller'].(($queryParams) ? '&'.http_build_query($queryParams) : ''); + + return $url; + } + + /** + * Load list of available controllers + */ public static function loadControllers() { $controller_files = scandir(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.'controllers'); @@ -35,17 +195,52 @@ class DispatcherCore self::$controllers['productscomparison'] = self::$controllers['compare']; } + /** + * Retrieve the controller from URL or request URI if routes are activated + * + * @return string + */ public function getController() { - $controller = Tools::getValue('controller'); - if (isset($controller) && preg_match('/^([0-9a-z_-]+)\?(.*)=(.*)$/Ui', $controller, $controller_string)) + // Use routes ? (for URL rewriting) + if ($this->useRoutes) { - $controller = $controller_string[1]; - if (isset($_GET['controller'])) - $_GET[$controller_string[2]] = $controller_string[3]; - elseif (isset($_POST['controller'])) - $_POST[$controller_string[2]] = $controller_string[3]; + // Get request URI (HTTP_X_REWRITE_URL is used by IIS) + if (isset($_SERVER['REQUEST_URI'])) + $request = $_SERVER['REQUEST_URI']; + else if (isset($_SERVER['HTTP_X_REWRITE_URL'])) + $request = $_SERVER['HTTP_X_REWRITE_URL']; + else + return 'index'; + + $controller = 'index'; + foreach ($this->routes as $route) + if (preg_match($route['regexp'], $request, $m)) + { + // Route found ! Now fill $_GET with parameters of URI + $controller = $route['controller']; + foreach ($m as $k => $v) + if (!is_numeric($k)) + $_GET[$k] = $v; + break; + } + + $_GET['controller'] = $controller; + return $controller; + } + // Default mode, take controller from URL + else + { + $controller = Tools::getValue('controller'); + if (isset($controller) && preg_match('/^([0-9a-z_-]+)\?(.*)=(.*)$/Ui', $controller, $m)) + { + $controller = $m[1]; + if (isset($_GET['controller'])) + $_GET[$m[2]] = $m[3]; + else if (isset($_POST['controller'])) + $_POST[$m[2]] = $m[3]; + } + return (!empty($controller)) ? $controller : 'index'; } - return (!empty($controller)) ? $controller : 'index'; } } diff --git a/classes/Tools.php b/classes/Tools.php index 166cf3292..9b582b922 100644 --- a/classes/Tools.php +++ b/classes/Tools.php @@ -551,9 +551,9 @@ class ToolsCore */ public static function dieObject($object, $kill = true) { - echo '
';
+		echo '';
 		print_r($object);
-		echo '</pre><br />';
+		echo '
'; if ($kill) die('END'); return $object; @@ -1634,23 +1634,23 @@ class ToolsCore $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])(\-[_a-zA-Z0-9-]*)?/[_a-zA-Z0-9-]*\.jpg$'] = _PS_PROD_IMG_.'$1/$2/$3/$4/$5/$6/$7/$8/$1$2$3$4$5$6$7$8$9.jpg [L]'; $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'c/([0-9]+)(\-[_a-zA-Z0-9-]*)/[_a-zA-Z0-9-]*\.jpg$'] = 'img/c/$1$2.jpg [L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)\-[a-zA-Z0-9-]*\.html'] = 'index.php?controller=product&id_product=$1 [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)\-[a-zA-Z0-9-]*'] = 'index.php?controller=category&id_category=$1 [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'[a-zA-Z0-9-]*/([0-9]+)\-[a-zA-Z0-9-]*\.html'] = 'index.php?controller=product&id_product=$1 [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)__([a-zA-Z0-9-]*)'] = 'index.php?controller=supplier&id_supplier=$1 [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)_([a-zA-Z0-9-]*)'] = 'index.php?controller=manufacturer&id_manufacturer=$1 [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'content/([0-9]+)\-([a-zA-Z0-9-]*)'] = 'index.php?controller=cms&id_cms=$1 [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'content/category/([0-9]+)\-([a-zA-Z0-9-]*)'] = 'index.php?controller=cms&id_cms_category=$1 [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)\-[a-zA-Z0-9-]*\.html'] = 'index.php?controller=product&id_product=$1 [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)\-[a-zA-Z0-9-]*'] = 'index.php?controller=category&id_category=$1 [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'[a-zA-Z0-9-]*/([0-9]+)\-[a-zA-Z0-9-]*\.html'] = 'index.php?controller=product&id_product=$1 [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)__([a-zA-Z0-9-]*)'] = 'index.php?controller=supplier&id_supplier=$1 [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)_([a-zA-Z0-9-]*)'] = 'index.php?controller=manufacturer&id_manufacturer=$1 [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'content/([0-9]+)\-([a-zA-Z0-9-]*)'] = 'index.php?controller=cms&id_cms=$1 [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'content/category/([0-9]+)\-([a-zA-Z0-9-]*)'] = 'index.php?controller=cms&id_cms_category=$1 [QSA,L]'; if ($multilang) { - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([a-z]{2})/[a-zA-Z0-9-]*/([0-9]+)\-[a-zA-Z0-9-]*\.html'] = 'index.php?controller=product&id_product=$2&isolang=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([a-z]{2})/([0-9]+)\-[a-zA-Z0-9-]*\.html'] = 'index.php?controller=product&id_product=$2&isolang=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([a-z]{2})/([0-9]+)\-[a-zA-Z0-9-]*'] = 'index.php?controller=category&id_category=$2&isolang=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([a-z]{2})/content/([0-9]+)\-[a-zA-Z0-9-]*'] = 'index.php?controller=cms&isolang=$1&id_cms=$2&id_shop='.$uri['id_shop'].' [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([a-z]{2})/content/category/([0-9]+)\-[a-zA-Z0-9-]*'] = 'index.php?controller=cms&isolang=$1&id_cms_category=$2&id_shop='.$uri['id_shop'].' [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([a-z]{2})/([0-9]+)__[a-zA-Z0-9-]*'] = 'index.php?controller=supplier&isolang=$1&id_supplier=$2&id_shop='.$uri['id_shop'].' [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([a-z]{2})/([0-9]+)_[a-zA-Z0-9-]*'] = 'index.php?controller=manufacturer&isolang=$1&id_manufacturer=$2&id_shop='.$uri['id_shop'].' [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([a-z]{2})/[a-zA-Z0-9-]*/([0-9]+)\-[a-zA-Z0-9-]*\.html'] = 'index.php?controller=product&id_product=$2&isolang=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([a-z]{2})/([0-9]+)\-[a-zA-Z0-9-]*\.html'] = 'index.php?controller=product&id_product=$2&isolang=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([a-z]{2})/([0-9]+)\-[a-zA-Z0-9-]*'] = 'index.php?controller=category&id_category=$2&isolang=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([a-z]{2})/content/([0-9]+)\-[a-zA-Z0-9-]*'] = 'index.php?controller=cms&isolang=$1&id_cms=$2&id_shop='.$uri['id_shop'].' [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([a-z]{2})/content/category/([0-9]+)\-[a-zA-Z0-9-]*'] = 'index.php?controller=cms&isolang=$1&id_cms_category=$2&id_shop='.$uri['id_shop'].' [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([a-z]{2})/([0-9]+)__[a-zA-Z0-9-]*'] = 'index.php?controller=supplier&isolang=$1&id_supplier=$2&id_shop='.$uri['id_shop'].' [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([a-z]{2})/([0-9]+)_[a-zA-Z0-9-]*'] = 'index.php?controller=manufacturer&isolang=$1&id_manufacturer=$2&id_shop='.$uri['id_shop'].' [QSA,L]'; } // PS BASE URI automaticaly prepend the string, do not use PS defines for the image directories @@ -1658,13 +1658,13 @@ class ToolsCore $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)\-([0-9]+)/[_a-zA-Z0-9-]*\.jpg$'] = _PS_PROD_IMG_.'$1-$2.jpg [L]'; $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)(\-[_a-zA-Z0-9-]*)/[_a-zA-Z0-9-]*\.jpg$'] = 'img/c/$1$2.jpg [L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)\-[a-zA-Z0-9-]*\.html'] = 'index.php?controller=product&id_product=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'[a-zA-Z0-9-]*/([0-9]+)\-[a-zA-Z0-9-]*\.html'] = 'index.php?controller=product&id_product=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)\-[a-zA-Z0-9-]*'] = 'index.php?controller=category&id_category=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)__([a-zA-Z0-9-]*)'] = 'index.php?controller=supplier&id_supplier=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)_([a-zA-Z0-9-]*)'] = 'index.php?controller=manufacturer&id_manufacturer=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'content/([0-9]+)\-([a-zA-Z0-9-]*)'] = 'index.php?controller=cms&id_cms=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; - $tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'content/category/([0-9]+)\-([a-zA-Z0-9-]*)'] = 'index.php?controller=cms&id_cms_category=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)\-[a-zA-Z0-9-]*\.html'] = 'index.php?controller=product&id_product=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'[a-zA-Z0-9-]*/([0-9]+)\-[a-zA-Z0-9-]*\.html'] = 'index.php?controller=product&id_product=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)\-[a-zA-Z0-9-]*'] = 'index.php?controller=category&id_category=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)__([a-zA-Z0-9-]*)'] = 'index.php?controller=supplier&id_supplier=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'([0-9]+)_([a-zA-Z0-9-]*)'] = 'index.php?controller=manufacturer&id_manufacturer=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'content/([0-9]+)\-([a-zA-Z0-9-]*)'] = 'index.php?controller=cms&id_cms=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; + //$tab['RewriteRule'][$domain]['content']['^'.ltrim($uri['uri'], '/').'content/category/([0-9]+)\-([a-zA-Z0-9-]*)'] = 'index.php?controller=cms&id_cms_category=$1&id_shop='.$uri['id_shop'].' [QSA,L]'; Language::loadLanguages(); $default_meta = Meta::getMetasByIdLang((int)Configuration::get('PS_LANG_DEFAULT'), new Shop($uri['id_shop'])); diff --git a/index.php b/index.php index 4057bdc9e..bb4a9a351 100644 --- a/index.php +++ b/index.php @@ -26,5 +26,4 @@ */ require(dirname(__FILE__).'/config/config.inc.php'); -$dispatcher = new Dispatcher(); -$dispatcher->dispatch(); +Dispatcher::getInstance()->dispatch();