[-] 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();
// 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;
+24 -26
View File
@@ -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)
+16 -1
View File
@@ -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));
}
}
}
+19 -10
View File
@@ -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<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('Cache-Control: no-cache');
Tools::redirectLink($canonical_url.$str_params);
Tools::redirectLink($final_url);
}
}