[-] FO : #PSCFV-2951 - Fix bug with dispatcher and route rule with multilanguage

This commit is contained in:
mDeflotte
2012-07-02 14:16:47 +00:00
parent 1e9e36ffd7
commit 3db6a38f1e
4 changed files with 138 additions and 91 deletions
+79 -54
View File
@@ -221,6 +221,9 @@ class DispatcherCore
$this->setRequestUri(); $this->setRequestUri();
// Switch language if needed
Tools::switchLanguage();
$this->loadRoutes(); $this->loadRoutes();
} }
@@ -368,19 +371,23 @@ class DispatcherCore
} }
/** /**
* Load default routes * Load default routes group by languages
*/ */
protected function loadRoutes() protected function loadRoutes()
{ {
$context = Context::getContext(); $context = Context::getContext();
foreach ($this->default_routes as $id => $route)
$this->addRoute( // Set default routes
$id, foreach (Language::getLanguages() as $lang)
$route['rule'], foreach ($this->default_routes as $id => $route)
$route['controller'], $this->addRoute(
$route['keywords'], $id,
isset($route['params']) ? $route['params'] : array() $route['rule'],
); $route['controller'],
$lang['id_lang'],
$route['keywords'],
isset($route['params']) ? $route['params'] : array()
);
if ($this->use_routes) if ($this->use_routes)
{ {
@@ -391,16 +398,15 @@ class DispatcherCore
$id_lang = Language::getIdByIso($iso_lang); $id_lang = Language::getIdByIso($iso_lang);
// Load routes from meta table // 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 FROM `'._DB_PREFIX_.'meta` m
LEFT JOIN `'._DB_PREFIX_.'meta_lang` ml ON (m.id_meta = ml.id_meta'.Shop::addSqlRestrictionOnLang('ml').') 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'; ORDER BY LENGTH(ml.url_rewrite) DESC';
if ($results = Db::getInstance()->executeS($sql)) if ($results = Db::getInstance()->executeS($sql))
foreach ($results as $row) foreach ($results as $row)
{ {
if ($row['url_rewrite']) 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 else
$this->empty_route = array( $this->empty_route = array(
'routeID' => $row['page'], 'routeID' => $row['page'],
@@ -420,24 +426,30 @@ class DispatcherCore
// Load custom routes // Load custom routes
foreach ($this->default_routes as $route_id => $route_data) foreach ($this->default_routes as $route_id => $route_data)
if ($custom_route = Configuration::get('PS_ROUTE_'.$route_id)) if ($custom_route = Configuration::get('PS_ROUTE_'.$route_id))
$this->addRoute( foreach (Language::getLanguages() as $lang)
$route_id, $this->addRoute(
$custom_route, $route_id,
$route_data['controller'], $custom_route,
$route_data['keywords'], $route_data['controller'],
isset($route_data['params']) ? $route_data['params'] : array() $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 $rule Url rule
* @param string $controller Controller to call if request uri match the 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, '#'); $regexp = preg_quote($rule, '#');
if ($keywords) if ($keywords)
{ {
@@ -471,7 +483,10 @@ class DispatcherCore
} }
$regexp = '#^/'.$regexp.'(\?.*)?$#u'; $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, 'rule' => $rule,
'regexp' => $regexp, 'regexp' => $regexp,
'controller' => $controller, 'controller' => $controller,
@@ -484,26 +499,31 @@ class DispatcherCore
* Check if a route exists * Check if a route exists
* *
* @param string $route_id * @param string $route_id
* @param int $id_lang
* @return bool * @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 * Check if a keyword is written in a route rule
* *
* @param string $route_id * @param string $route_id
* @param int $id_lang
* @param string $keyword * @param string $keyword
* @return bool * @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 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 * Create an url from
* *
* @param string $route_id Name the route * @param string $route_id Name the route
* @param int $id_lang
* @param array $params * @param array $params
* @param bool $use_routes If false, don't use to create this url * @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 * @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, '', '&'); $query = http_build_query($params, '', '&');
$index_link = Configuration::get('PS_REWRITING_SETTINGS') ? '' : 'index.php'; $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; 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 // Check required fields
$query_params = isset($route['params']) ? $route['params'] : array(); $query_params = isset($route['params']) ? $route['params'] : array();
@@ -630,33 +654,34 @@ class DispatcherCore
// Add empty route as last route to prevent this greedy regexp to match request uri before right time // Add empty route as last route to prevent this greedy regexp to match request uri before right time
if ($this->empty_route) 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 (isset($this->routes[Context::getContext()->language->id]))
if (preg_match($route['regexp'], $this->request_uri, $m)) foreach ($this->routes[Context::getContext()->language->id] 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))
{ {
$_GET['module'] = $m[1]; // Route found ! Now fill $_GET with parameters of uri
$_GET['fc'] = 'module'; foreach ($m as $k => $v)
$controller = $m[2]; if (!is_numeric($k))
} $_GET[$k] = $v;
if (isset($_GET['fc']) && $_GET['fc'] == 'module') $controller = $route['controller'] ? $route['controller'] : $_GET['controller'];
$this->front_controller = self::FC_MODULE; if (!empty($route['params']))
break; 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 ($controller == 'index' || $this->request_uri == '/index.php') if ($controller == 'index' || $this->request_uri == '/index.php')
$controller = $this->default_controller; $controller = $this->default_controller;
+24 -26
View File
@@ -112,19 +112,19 @@ class LinkCore
$params['meta_keywords'] = Tools::str2url($product->getFieldByLang('meta_keywords')); $params['meta_keywords'] = Tools::str2url($product->getFieldByLang('meta_keywords'));
$params['meta_title'] = Tools::str2url($product->getFieldByLang('meta_title')); $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)); $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)); $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); $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)); $params['tags'] = Tools::str2url($product->getTags($id_lang));
if ($dispatcher->hasKeyword('product_rule', 'categories')) if ($dispatcher->hasKeyword('product_rule', $id_lang, 'categories'))
{ {
$cats = array(); $cats = array();
foreach ($product->getParentCategories() as $cat) foreach ($product->getParentCategories() as $cat)
@@ -133,7 +133,7 @@ class LinkCore
} }
$anchor = $ipa ? $product->getAnchor($ipa) : ''; $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; $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_keywords'] = Tools::str2url($category->meta_keywords);
$params['meta_title'] = Tools::str2url($category->meta_title); $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 else
$params['meta_title'] = ''; $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_keywords'] = Tools::str2url($supplier->meta_keywords);
$params['meta_title'] = Tools::str2url($supplier->meta_title); $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_keywords'] = Tools::str2url($manufacturer->meta_keywords);
$params['meta_title'] = Tools::str2url($manufacturer->meta_title); $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'; $params['controller'] = $controller ? $controller : 'default';
// If the module has its own route ... just use it ! // 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); return $this->getPageLink('module-'.$module.'-'.$controller, $params);
else 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) public function getAdminLink($controller, $with_token = true)
{ {
$id_lang = Context::getContext()->language->id;
$params = $with_token ? array('token' => Tools::getAdminTokenLite($controller)) : array(); $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']); 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 = ($ssl && $this->ssl_enable) ? Tools::getShopDomainSsl(true) : Tools::getShopDomain(true);
$url .= __PS_BASE_URI__.$this->getLangLink($id_lang).ltrim($uri_path, '/'); $url .= __PS_BASE_URI__.$this->getLangLink($id_lang).ltrim($uri_path, '/');
@@ -426,24 +428,20 @@ class LinkCore
{ {
if (!$context) if (!$context)
$context = Context::getContext(); $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; $params = $_GET;
unset($params['isolang'], $params['controller']); unset($params['isolang'], $params['controller']);
if (!$this->allow) if (!$this->allow)
$params['id_lang'] = $id_lang; $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) public function goPage($url, $p)
+16 -1
View File
@@ -378,6 +378,9 @@ class ToolsCore
if (!$context) if (!$context)
$context = Context::getContext(); $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 // update language only if new id is different from old id
// or if default language changed // or if default language changed
$cookie_id_lang = $context->cookie->id_lang; $cookie_id_lang = $context->cookie->id_lang;
@@ -392,7 +395,19 @@ class ToolsCore
$params = $_GET; $params = $_GET;
unset($params['id_lang']); 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));
}
} }
} }
+19 -10
View File
@@ -145,12 +145,10 @@ class FrontControllerCore extends Controller
ob_start(); ob_start();
// Switch language if needed and init cookie language // Init cookie language
if (($iso = Tools::getValue('isolang')) && Validate::isLanguageIsoCode($iso) && ($id_lang = (int)Language::getIdByIso($iso))) // @TODO This method must be moved into switchLanguage
$_GET['id_lang'] = $id_lang;
Tools::switchLanguage();
Tools::setCookieLanguage($this->context->cookie); Tools::setCookieLanguage($this->context->cookie);
$currency = Tools::setCurrency($this->context->cookie); $currency = Tools::setCurrency($this->context->cookie);
$protocol_link = (Configuration::get('PS_SSL_ENABLED') || Tools::usingSecureMode()) ? 'https://' : 'http://'; $protocol_link = (Configuration::get('PS_SSL_ENABLED') || Tools::usingSecureMode()) ? 'https://' : 'http://';
@@ -525,7 +523,7 @@ class FrontControllerCore extends Controller
if (Tools::isSubmit('live_edit')) if (Tools::isSubmit('live_edit'))
$this->context->smarty->assign('live_edit', $this->getLiveEditFooter()); $this->context->smarty->assign('live_edit', $this->getLiveEditFooter());
$layout = $this->getLayout(); $layout = $this->getLayout();
if ($layout) if ($layout)
{ {
if ($this->template) if ($this->template)
@@ -608,15 +606,26 @@ class FrontControllerCore extends Controller
$params[$key] = $value; $params[$key] = $value;
$str_params = ''; $str_params = '';
if ($params) $url_details = parse_url($canonical_url);
$str_params = ((strpos($canonical_url, '?') === false) ? '?' : '&').http_build_query($params, '', '&'); 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__) if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_ && $_SERVER['REQUEST_URI'] != __PS_BASE_URI__)
die('[Debug] This page has moved<br />Please use the following URL instead: <a href="'.$canonical_url.Tools::safeOutput($str_params).'">'.$canonical_url.Tools::safeOutput($str_params).'</a>'); die('[Debug] This page has moved<br />Please use the following URL instead: <a href="'.$final_url.'">'.$final_url.'</a>');
header('HTTP/1.0 301 Moved'); header('HTTP/1.0 301 Moved');
header('Cache-Control: no-cache'); header('Cache-Control: no-cache');
Tools::redirectLink($canonical_url.$str_params); Tools::redirectLink($final_url);
} }
} }