diff --git a/classes/Dispatcher.php b/classes/Dispatcher.php index 04b3b038e..264cf8d9f 100644 --- a/classes/Dispatcher.php +++ b/classes/Dispatcher.php @@ -221,6 +221,9 @@ class DispatcherCore $this->setRequestUri(); + // Switch language if needed + Tools::switchLanguage(); + $this->loadRoutes(); } @@ -368,19 +371,23 @@ class DispatcherCore } /** - * Load default routes + * Load default routes group by languages */ protected function loadRoutes() { $context = Context::getContext(); - foreach ($this->default_routes as $id => $route) - $this->addRoute( - $id, - $route['rule'], - $route['controller'], - $route['keywords'], - isset($route['params']) ? $route['params'] : array() - ); + + // Set default routes + foreach (Language::getLanguages() as $lang) + foreach ($this->default_routes as $id => $route) + $this->addRoute( + $id, + $route['rule'], + $route['controller'], + $lang['id_lang'], + $route['keywords'], + isset($route['params']) ? $route['params'] : array() + ); if ($this->use_routes) { @@ -391,16 +398,15 @@ class DispatcherCore $id_lang = Language::getIdByIso($iso_lang); // Load routes from meta table - $sql = 'SELECT m.page, ml.url_rewrite + $sql = 'SELECT m.page, ml.url_rewrite, ml.id_lang FROM `'._DB_PREFIX_.'meta` m LEFT JOIN `'._DB_PREFIX_.'meta_lang` ml ON (m.id_meta = ml.id_meta'.Shop::addSqlRestrictionOnLang('ml').') - WHERE id_lang = '.(int)$id_lang.' ORDER BY LENGTH(ml.url_rewrite) DESC'; if ($results = Db::getInstance()->executeS($sql)) foreach ($results as $row) { if ($row['url_rewrite']) - $this->addRoute($row['page'], $row['url_rewrite'], $row['page']); + $this->addRoute($row['page'], $row['url_rewrite'], $row['page'], $row['id_lang']); else $this->empty_route = array( 'routeID' => $row['page'], @@ -420,24 +426,30 @@ class DispatcherCore // Load custom routes foreach ($this->default_routes as $route_id => $route_data) if ($custom_route = Configuration::get('PS_ROUTE_'.$route_id)) - $this->addRoute( - $route_id, - $custom_route, - $route_data['controller'], - $route_data['keywords'], - isset($route_data['params']) ? $route_data['params'] : array() - ); + foreach (Language::getLanguages() as $lang) + $this->addRoute( + $route_id, + $custom_route, + $route_data['controller'], + $lang['id_lang'], + $route_data['keywords'], + isset($route_data['params']) ? $route_data['params'] : array() + ); } } /** * - * @param string $id Name of the route (need to be uniq, a second route with same name will override the first) + * @param string $route_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 + * @param int $id_lang */ - public function addRoute($route_id, $rule, $controller, array $keywords = array(), array $params = array()) + public function addRoute($route_id, $rule, $controller, $id_lang = null, array $keywords = array(), array $params = array()) { + if (is_null($id_lang)) + $id_lang = Context::getContext()->language->id; + $regexp = preg_quote($rule, '#'); if ($keywords) { @@ -471,7 +483,10 @@ class DispatcherCore } $regexp = '#^/'.$regexp.'(\?.*)?$#u'; - $this->routes[$route_id] = array( + if (!isset($this->routes[$id_lang])) + $this->routes[$id_lang] = array(); + + $this->routes[$id_lang][$route_id] = array( 'rule' => $rule, 'regexp' => $regexp, 'controller' => $controller, @@ -484,26 +499,31 @@ class DispatcherCore * Check if a route exists * * @param string $route_id + * @param int $id_lang * @return bool */ - public function hasRoute($route_id) + public function hasRoute($route_id, $id_lang = null) { - return isset($this->routes[$route_id]); + if (is_null($id_lang)) + $id_lang = Context::getContext()->language->id; + + return isset($this->routes[$id_lang]) && isset($this->routes[$id_lang][$route_id]); } /** * Check if a keyword is written in a route rule * * @param string $route_id + * @param int $id_lang * @param string $keyword * @return bool */ - public function hasKeyword($route_id, $keyword) + public function hasKeyword($route_id, $id_lang, $keyword) { - if (!isset($this->routes[$route_id])) + if (!isset($this->routes[$id_lang]) && !isset($this->routes[$id_lang][$route_id])) return false; - return preg_match('#\{([^{}]+:)?'.preg_quote($keyword, '#').'(:[^{}])?\}#', $this->routes[$route_id]['rule']); + return preg_match('#\{([^{}]+:)?'.preg_quote($keyword, '#').'(:[^{}])?\}#', $this->routes[$id_lang][$route_id]['rule']); } /** @@ -530,19 +550,23 @@ class DispatcherCore * Create an url from * * @param string $route_id Name the route + * @param int $id_lang * @param array $params * @param bool $use_routes If false, don't use to create this url * @param string $anchor Optional anchor to add at the end of this url */ - public function createUrl($route_id, array $params = array(), $force_routes = false, $anchor = '') + public function createUrl($route_id, $id_lang = null, array $params = array(), $force_routes = false, $anchor = '') { - if (!isset($this->routes[$route_id])) + if (!$id_lang) + $id_lang = Context::getContext()->language->id; + + if (!isset($this->routes[$id_lang][$route_id])) { $query = http_build_query($params, '', '&'); $index_link = Configuration::get('PS_REWRITING_SETTINGS') ? '' : 'index.php'; return ($route_id == 'index') ? $index_link.(($query) ? '?'.$query : '') : 'index.php?controller='.$route_id.(($query) ? '&'.$query : '').$anchor; } - $route = $this->routes[$route_id]; + $route = $this->routes[$id_lang][$route_id]; // Check required fields $query_params = isset($route['params']) ? $route['params'] : array(); @@ -630,34 +654,35 @@ class DispatcherCore // Add empty route as last route to prevent this greedy regexp to match request uri before right time if ($this->empty_route) - $this->addRoute($this->empty_route['routeID'], $this->empty_route['rule'], $this->empty_route['controller']); + $this->addRoute($this->empty_route['routeID'], $this->empty_route['rule'], $this->empty_route['controller'], Context::getContext()->language->id); - foreach ($this->routes as $route) - if (preg_match($route['regexp'], $this->request_uri, $m)) - { - // Route found ! Now fill $_GET with parameters of uri - foreach ($m as $k => $v) - if (!is_numeric($k)) - $_GET[$k] = $v; - - $controller = $route['controller'] ? $route['controller'] : $_GET['controller']; - if (!empty($route['params'])) - foreach ($route['params'] as $k => $v) - $_GET[$k] = $v; - - // A patch for module friendly urls - if (preg_match('#module-([a-z0-9_-]+)-([a-z0-9]+)$#i', $controller, $m)) + if (isset($this->routes[Context::getContext()->language->id])) + foreach ($this->routes[Context::getContext()->language->id] as $route) + if (preg_match($route['regexp'], $this->request_uri, $m)) { - $_GET['module'] = $m[1]; - $_GET['fc'] = 'module'; - $controller = $m[2]; + // Route found ! Now fill $_GET with parameters of uri + foreach ($m as $k => $v) + if (!is_numeric($k)) + $_GET[$k] = $v; + + $controller = $route['controller'] ? $route['controller'] : $_GET['controller']; + if (!empty($route['params'])) + foreach ($route['params'] as $k => $v) + $_GET[$k] = $v; + + // A patch for module friendly urls + if (preg_match('#module-([a-z0-9_-]+)-([a-z0-9]+)$#i', $controller, $m)) + { + $_GET['module'] = $m[1]; + $_GET['fc'] = 'module'; + $controller = $m[2]; + } + + if (isset($_GET['fc']) && $_GET['fc'] == 'module') + $this->front_controller = self::FC_MODULE; + break; } - if (isset($_GET['fc']) && $_GET['fc'] == 'module') - $this->front_controller = self::FC_MODULE; - break; - } - if ($controller == 'index' || $this->request_uri == '/index.php') $controller = $this->default_controller; $this->controller = $controller; diff --git a/classes/Link.php b/classes/Link.php index fefb51eb1..25853b103 100644 --- a/classes/Link.php +++ b/classes/Link.php @@ -112,19 +112,19 @@ class LinkCore $params['meta_keywords'] = Tools::str2url($product->getFieldByLang('meta_keywords')); $params['meta_title'] = Tools::str2url($product->getFieldByLang('meta_title')); - if ($dispatcher->hasKeyword('product_rule', 'manufacturer')) + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'manufacturer')) $params['manufacturer'] = Tools::str2url($product->isFullyLoaded ? $product->manufacturer_name : Manufacturer::getNameById($product->id_manufacturer)); - if ($dispatcher->hasKeyword('product_rule', 'supplier')) + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'supplier')) $params['supplier'] = Tools::str2url($product->isFullyLoaded ? $product->supplier_name : Supplier::getNameById($product->id_supplier)); - if ($dispatcher->hasKeyword('product_rule', 'price')) + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'price')) $params['price'] = $product->isFullyLoaded ? $product->price : Product::getPriceStatic($product->id, false, null, 6, null, false, true, 1, false, null, null, null, $product->specificPrice); - if ($dispatcher->hasKeyword('product_rule', 'tags')) + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'tags')) $params['tags'] = Tools::str2url($product->getTags($id_lang)); - if ($dispatcher->hasKeyword('product_rule', 'categories')) + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'categories')) { $cats = array(); foreach ($product->getParentCategories() as $cat) @@ -133,7 +133,7 @@ class LinkCore } $anchor = $ipa ? $product->getAnchor($ipa) : ''; - return $url.$dispatcher->createUrl('product_rule', $params, $force_routes, $anchor); + return $url.$dispatcher->createUrl('product_rule', $id_lang, $params, $force_routes, $anchor); } /** @@ -172,7 +172,7 @@ class LinkCore $params['selected_filters'] = $selected_filters; } - return $url.Dispatcher::getInstance()->createUrl($rule, $params, $this->allow); + return $url.Dispatcher::getInstance()->createUrl($rule, $id_lang, $params, $this->allow); } /** @@ -199,7 +199,7 @@ class LinkCore $params['meta_keywords'] = Tools::str2url($category->meta_keywords); $params['meta_title'] = Tools::str2url($category->meta_title); - return $url.Dispatcher::getInstance()->createUrl('cms_category_rule', $params, $this->allow); + return $url.Dispatcher::getInstance()->createUrl('cms_category_rule', $id_lang, $params, $this->allow); } /** @@ -237,7 +237,7 @@ class LinkCore else $params['meta_title'] = ''; - return $url.Dispatcher::getInstance()->createUrl('cms_rule', $params, $this->allow); + return $url.Dispatcher::getInstance()->createUrl('cms_rule', $id_lang, $params, $this->allow); } /** @@ -264,7 +264,7 @@ class LinkCore $params['meta_keywords'] = Tools::str2url($supplier->meta_keywords); $params['meta_title'] = Tools::str2url($supplier->meta_title); - return $url.Dispatcher::getInstance()->createUrl('supplier_rule', $params, $this->allow); + return $url.Dispatcher::getInstance()->createUrl('supplier_rule', $id_lang, $params, $this->allow); } /** @@ -291,7 +291,7 @@ class LinkCore $params['meta_keywords'] = Tools::str2url($manufacturer->meta_keywords); $params['meta_title'] = Tools::str2url($manufacturer->meta_title); - return $url.Dispatcher::getInstance()->createUrl('manufacturer_rule', $params, $this->allow); + return $url.Dispatcher::getInstance()->createUrl('manufacturer_rule', $id_lang, $params, $this->allow); } /** @@ -316,10 +316,10 @@ class LinkCore $params['controller'] = $controller ? $controller : 'default'; // If the module has its own route ... just use it ! - if (Dispatcher::getInstance()->hasRoute('module-'.$module.'-'.$controller)) + if (Dispatcher::getInstance()->hasRoute('module-'.$module.'-'.$controller, $id_lang)) return $this->getPageLink('module-'.$module.'-'.$controller, $params); else - return $url.Dispatcher::getInstance()->createUrl('module', $params, $this->allow); + return $url.Dispatcher::getInstance()->createUrl('module', $id_lang, $params, $this->allow); } /** @@ -331,8 +331,10 @@ class LinkCore */ public function getAdminLink($controller, $with_token = true) { + $id_lang = Context::getContext()->language->id; + $params = $with_token ? array('token' => Tools::getAdminTokenLite($controller)) : array(); - return Dispatcher::getInstance()->createUrl($controller, $params, false); + return Dispatcher::getInstance()->createUrl($controller, $id_lang, $params, false); } /** @@ -404,7 +406,7 @@ class LinkCore } unset($request['controller']); - $uri_path = Dispatcher::getInstance()->createUrl($controller, $request); + $uri_path = Dispatcher::getInstance()->createUrl($controller, $id_lang, $request); $url = ($ssl && $this->ssl_enable) ? Tools::getShopDomainSsl(true) : Tools::getShopDomain(true); $url .= __PS_BASE_URI__.$this->getLangLink($id_lang).ltrim($uri_path, '/'); @@ -426,24 +428,20 @@ class LinkCore { if (!$context) $context = Context::getContext(); - $matches = array(); - $request = $_SERVER['REQUEST_URI']; - preg_match('#^/([a-z]{2})/([^\?]*).*$#', $request, $matches); - if ($matches) - { - $current_iso = $matches[1]; - $rewrite = $matches[2]; - $url_rewrite = Meta::getEquivalentUrlRewrite($id_lang, Language::getIdByIso($current_iso), $rewrite); - $request = str_replace($rewrite, $url_rewrite, $request); - } $params = $_GET; unset($params['isolang'], $params['controller']); if (!$this->allow) $params['id_lang'] = $id_lang; + else + unset($params['id_lang']); - return $this->getPageLink(Dispatcher::getInstance()->getController(), false, $id_lang, $params); + $controller = Dispatcher::getInstance()->getController(); + if (!empty(Context::getContext()->controller->php_self)) + $controller = Context::getContext()->controller->php_self; + + return $this->getPageLink($controller, false, $id_lang, $params); } public function goPage($url, $p) diff --git a/classes/Tools.php b/classes/Tools.php index ec6fc07e9..50d0beabf 100644 --- a/classes/Tools.php +++ b/classes/Tools.php @@ -378,6 +378,9 @@ class ToolsCore if (!$context) $context = Context::getContext(); + if (($iso = Tools::getValue('isolang')) && Validate::isLanguageIsoCode($iso) && ($id_lang = (int)Language::getIdByIso($iso))) + $_GET['id_lang'] = $id_lang; + // update language only if new id is different from old id // or if default language changed $cookie_id_lang = $context->cookie->id_lang; @@ -392,7 +395,19 @@ class ToolsCore $params = $_GET; unset($params['id_lang']); - Tools::redirect('index.php?'.http_build_query($params)); + + if (!Configuration::get('PS_REWRITING_SETTINGS')) + { + if (empty($params['controller'])) + unset($params['controller']); + elseif (!empty(Context::getContext()->controller->php_self)) + $params['controller'] = Context::getContext()->controller->php_self; + + if (empty($params)) + Tools::redirect('index.php'); + else + Tools::redirect('index.php?'.http_build_query($params)); + } } } diff --git a/classes/controller/FrontController.php b/classes/controller/FrontController.php index c418a6730..d5e4834c6 100755 --- a/classes/controller/FrontController.php +++ b/classes/controller/FrontController.php @@ -145,12 +145,10 @@ class FrontControllerCore extends Controller ob_start(); - // Switch language if needed and init cookie language - if (($iso = Tools::getValue('isolang')) && Validate::isLanguageIsoCode($iso) && ($id_lang = (int)Language::getIdByIso($iso))) - $_GET['id_lang'] = $id_lang; - - Tools::switchLanguage(); + // Init cookie language + // @TODO This method must be moved into switchLanguage Tools::setCookieLanguage($this->context->cookie); + $currency = Tools::setCurrency($this->context->cookie); $protocol_link = (Configuration::get('PS_SSL_ENABLED') || Tools::usingSecureMode()) ? 'https://' : 'http://'; @@ -525,7 +523,7 @@ class FrontControllerCore extends Controller if (Tools::isSubmit('live_edit')) $this->context->smarty->assign('live_edit', $this->getLiveEditFooter()); - $layout = $this->getLayout(); + $layout = $this->getLayout(); if ($layout) { if ($this->template) @@ -608,15 +606,26 @@ class FrontControllerCore extends Controller $params[$key] = $value; $str_params = ''; - if ($params) - $str_params = ((strpos($canonical_url, '?') === false) ? '?' : '&').http_build_query($params, '', '&'); + $url_details = parse_url($canonical_url); + if (!empty($url_details['query'])) + { + parse_str($url_details['query'], $query); + foreach ($query as $key => $value) + $params[$key] = $value; + } + + $str_params = http_build_query($params, '', '&'); + if (!empty($str_params)) + $final_url = preg_replace('/^([^?]*)?.*$/', '$1', $canonical_url).'?'.Tools::safeOutput($str_params); + else + $final_url = preg_replace('/^([^?]*)?.*$/', '$1', $canonical_url); if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_ && $_SERVER['REQUEST_URI'] != __PS_BASE_URI__) - die('[Debug] This page has moved
Please use the following URL instead: '.$canonical_url.Tools::safeOutput($str_params).''); + die('[Debug] This page has moved
Please use the following URL instead: '.$final_url.''); header('HTTP/1.0 301 Moved'); header('Cache-Control: no-cache'); - Tools::redirectLink($canonical_url.$str_params); + Tools::redirectLink($final_url); } }