diff --git a/admin-dev/tabs/AdminMeta.php b/admin-dev/tabs/AdminMeta.php index 6b1f3fb0a..30ef7a9d0 100644 --- a/admin-dev/tabs/AdminMeta.php +++ b/admin-dev/tabs/AdminMeta.php @@ -52,24 +52,59 @@ class AdminMeta extends AdminTab ); // Display route options only if friendly URL is activated + $this->_fieldsRoutes = array(); if (Configuration::get('PS_REWRITING_SETTINGS')) { - $this->_fieldsOptions += array( - 'PS_ROUTE_product_rule' => array('title' => $this->l('Route to products'), 'desc' => $this->l('Select URL pattern if friendly url is activated'), 'validation' => 'isString', 'type' => 'text', 'size' => 50, 'defaultValue' => Dispatcher::getInstance()->defaultRoutes['product_rule']['rule']), - 'PS_ROUTE_product_rule2' => array('title' => $this->l('Route to products with category'), 'desc' => $this->l('Select URL pattern if friendly url is activated'), 'validation' => 'isString', 'type' => 'text', 'size' => 50, 'defaultValue' => Dispatcher::getInstance()->defaultRoutes['product_rule2']['rule']), - 'PS_ROUTE_category_rule' => array('title' => $this->l('Route to category'), 'desc' => $this->l('Select URL pattern if friendly url is activated'), 'validation' => 'isString', 'type' => 'text', 'size' => 50, 'defaultValue' => Dispatcher::getInstance()->defaultRoutes['category_rule']['rule']), - 'PS_ROUTE_supplier_rule' => array('title' => $this->l('Route to supplier'), 'desc' => $this->l('Select URL pattern if friendly url is activated'), 'validation' => 'isString', 'type' => 'text', 'size' => 50, 'defaultValue' => Dispatcher::getInstance()->defaultRoutes['supplier_rule']['rule']), - 'PS_ROUTE_manufacturer_rule' => array('title' => $this->l('Route to manufacturer'), 'desc' => $this->l('Select URL pattern if friendly url is activated'), 'validation' => 'isString', 'type' => 'text', 'size' => 50, 'defaultValue' => Dispatcher::getInstance()->defaultRoutes['manufacturer_rule']['rule']), - 'PS_ROUTE_cms_rule' => array('title' => $this->l('Route to CMS page'), 'desc' => $this->l('Select URL pattern if friendly url is activated'), 'validation' => 'isString', 'type' => 'text', 'size' => 50, 'defaultValue' => Dispatcher::getInstance()->defaultRoutes['cms_rule']['rule']), - 'PS_ROUTE_cms_category_rule' => array('title' => $this->l('Route to CMS category'), 'desc' => $this->l('Select URL pattern if friendly url is activated'), 'validation' => 'isString', 'type' => 'text', 'size' => 50, 'defaultValue' => Dispatcher::getInstance()->defaultRoutes['cms_category_rule']['rule']), - ); + $this->addFieldRoute('product_rule', $this->l('Route to products')); + $this->addFieldRoute('category_rule', $this->l('Route to category')); + $this->addFieldRoute('supplier_rule', $this->l('Route to supplier')); + $this->addFieldRoute('manufacturer_rule', $this->l('Route to manufacturer')); + $this->addFieldRoute('cms_rule', $this->l('Route to CMS page')); + $this->addFieldRoute('cms_category_rule', $this->l('Route to CMS category')); } } - - public function display() + + public function addFieldRoute($routeID, $title) { - $this->warnDomainName(); - parent::display(); + $keywords = array(); + foreach (Dispatcher::getInstance()->defaultRoutes[$routeID]['keywords'] as $keyword => $data) + $keywords[] = ((isset($data['param'])) ? ''.$keyword.'*' : $keyword); + + $this->_fieldsRoutes['PS_ROUTE_'.$routeID] = array( + 'title' => $title, + 'desc' => sprintf($this->l('Keywords: %s'), implode(', ', $keywords)), + 'validation' => 'isString', + 'type' => 'text', + 'size' => 70, + 'defaultValue' => Dispatcher::getInstance()->defaultRoutes[$routeID]['rule'], + ); + } + + protected function updateOptions($token) + { + if ($this->tabAccess['edit'] === '1') + { + $this->submitConfiguration($this->_fieldsRoutes); + parent::updateOptions($token); + } + else + $this->_errors[] = Tools::displayError('You do not have permission to edit here.'); + } + + public function displayOptionsList($fieldsOptions = null, $optionTitle = null, $optionDescription = null) + { + // Desactivate
, we want to add our own tags + $this->formOptions = false; + + $tab = Tab::getTab($this->context->language->id, $this->id); + echo ''; + parent::displayOptionsList(); + if ($this->_fieldsRoutes) + { + $desc = $this->l('You can change here the pattern of your links. There are some available keywords for each route listed below, keywords with * are required. To add a keyword in URL use {keyword} syntax. You can add some text before or after the keyword IF the keyword is not empty with syntax {prepend:keyword:append}, for example {-hey-:meta_title} will add "-hey-my-title" in URL if meta title is set, or nothing. Friendly URL and rewriting Apache option must be activated on your web server to use this functionality.'); + parent::displayOptionsList($this->_fieldsRoutes, $this->l('Schema of URLs'), $desc); + } + echo '
'; } public function displayForm($isMainTab = true) @@ -215,49 +250,47 @@ class AdminMeta extends AdminTab $rule = Tools::getValue('PS_ROUTE_'.$routeID); if (!$rule || $rule == $defaultRoutes[$routeID]['rule']) + { + Configuration::updateValue('PS_ROUTE_'.$routeID, ''); return ; + } $errors = array(); if (!Dispatcher::getInstance()->validateRoute($routeID, $rule, $errors)) { foreach ($errors as $error) - $this->_errors[] = sprintf('Keyword "%1$s" required for route "%2$s" (rule: "%3$s")', $error, $routeID, htmlspecialchars($rule)); + $this->_errors[] = sprintf('Keyword "{%1$s}" required for route "%2$s" (rule: "%3$s")', $error, $routeID, htmlspecialchars($rule)); } else Configuration::updateValue('PS_ROUTE_'.$routeID, $rule); } - public function updateOptionPsDispatcherRouteProductRule() + public function updateOptionPsRouteProductRule() { $this->checkAndUpdateRoute('product_rule'); } - - public function updateOptionPsDispatcherRouteProductRule2() - { - $this->checkAndUpdateRoute('product_rule2'); - } - - public function updateOptionPsDispatcherRouteCategoryRule() + + public function updateOptionPsRouteCategoryRule() { $this->checkAndUpdateRoute('category_rule'); } - public function updateOptionPsDispatcherRouteSupplierRule() + public function updateOptionPsRouteSupplierRule() { $this->checkAndUpdateRoute('supplier_rule'); } - public function updateOptionPsDispatcherRouteManufacturerRule() + public function updateOptionPsRouteManufacturerRule() { $this->checkAndUpdateRoute('manufacturer_rule'); } - public function updateOptionPsDispatcherRouteCmsRule() + public function updateOptionPsRouteCmsRule() { $this->checkAndUpdateRoute('cms_rule'); } - public function updateOptionPsDispatcherRouteCmsCategoryRule() + public function updateOptionPsRouteCmsCategoryRule() { $this->checkAndUpdateRoute('cms_category_rule'); } diff --git a/classes/AdminTab.php b/classes/AdminTab.php index 097318984..76c9f4fbb 100644 --- a/classes/AdminTab.php +++ b/classes/AdminTab.php @@ -149,6 +149,9 @@ abstract class AdminTabCore /** @var bool Redirect or not ater a creation */ protected $_redirect = true; + + /** @var bool If false, don't add form tags in options forms */ + protected $formOptions = true; protected $_languages = NULL; protected $_defaultFormLanguage = NULL; @@ -1666,28 +1669,39 @@ abstract class AdminTabCore /** * Options lists + * + * @param array $fieldsOptions Since 1.5.0 + * @param string $optionTitle Since 1.5.0 */ - public function displayOptionsList() + public function displayOptionsList($fieldsOptions = null, $optionTitle = null, $optionDescription = null) { - if (!isset($this->_fieldsOptions) OR !sizeof($this->_fieldsOptions)) + if (is_null($fieldsOptions)) + $fieldsOptions = $this->_fieldsOptions; + + if (is_null($optionTitle)) + $optionTitle = $this->optionTitle; + + if (!isset($fieldsOptions) OR !sizeof($fieldsOptions)) return false; $defaultLanguage = (int)$this->context->language->id; $this->_languages = Language::getLanguages(false); $tab = Tab::getTab($defaultLanguage, $this->id); echo '

'; - echo (isset($this->optionTitle) ? '

'.$this->optionTitle.'

' : ''); + echo (isset($optionTitle) ? '

'.$optionTitle.'

' : ''); echo ' -
+ '.(($this->formOptions) ? '' : '').'
'; - echo (isset($this->optionTitle) ? ' + echo (isset($optionTitle) ? ' ' - .$this->optionTitle.'' : ''); + .$optionTitle.'' : ''); + if ($optionDescription) + echo '

'.$optionDescription.'

'; - foreach ($this->_fieldsOptions AS $key => $field) + foreach ($fieldsOptions AS $key => $field) { $val = Tools::getValue($key, Configuration::get($key)); if ($field['type'] != 'textLang') @@ -1767,8 +1781,9 @@ abstract class AdminTabCore
- -
'; + '; + if ($this->formOptions) + echo ''; } /** diff --git a/classes/Dispatcher.php b/classes/Dispatcher.php index c8c212e4f..dc0188fe0 100644 --- a/classes/Dispatcher.php +++ b/classes/Dispatcher.php @@ -43,31 +43,70 @@ class DispatcherCore public $defaultRoutes = array( 'product_rule' => array( 'controller' => 'product', - 'rule' => '{number:id_product}-{text}.html', + 'rule' => '{category:/}{id}-{rewrite}{-:ean13}.html', + 'keywords' => array( + 'id' => array('regexp' => '[0-9]+', 'param' => 'id_product'), + 'rewrite' => array('regexp' => '[a-zA-Z0-9-]*'), + 'ean13' => array('regexp' => '[a-zA-Z0-9-]*'), + 'category' => array('regexp' => '[a-zA-Z0-9-]*'), + 'reference' => array('regexp' => '[a-zA-Z0-9-]*'), + 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-]*'), + 'meta_title' => array('regexp' => '[a-zA-Z0-9-]*'), + 'manufacturer' => array('regexp' => '[a-zA-Z0-9-]*'), + 'supplier' => array('regexp' => '[a-zA-Z0-9-]*'), + 'price' => array('regexp' => '[0-9\.,]*'), + 'tags' => array('regexp' => '[a-zA-Z0-9-]*'), + ), ), 'category_rule' => array( 'controller' => 'category', - 'rule' => '{number:id_category}-{text}', - ), - 'product_rule2' => array( - 'controller' => 'product', - 'rule' => '{text1}/{number:id_product}-{text2}.html', + 'rule' => '{id}-{rewrite}', + 'keywords' => array( + 'id' => array('regexp' => '[0-9]+', 'param' => 'id_category'), + 'rewrite' => array('regexp' => '[a-zA-Z0-9-]*'), + 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-]*'), + 'meta_title' => array('regexp' => '[a-zA-Z0-9-]*'), + ), ), 'supplier_rule' => array( 'controller' => 'supplier', - 'rule' => '{number:id_supplier}__{text}', + 'rule' => '{id}__{rewrite}', + 'keywords' => array( + 'id' => array('regexp' => '[0-9]+', 'param' => 'id_supplier'), + 'rewrite' => array('regexp' => '[a-zA-Z0-9-]*'), + 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-]*'), + 'meta_title' => array('regexp' => '[a-zA-Z0-9-]*'), + ), ), 'manufacturer_rule' => array( 'controller' => 'manufacturer', - 'rule' => '{number:id_manufacturer}_{text}', + 'rule' => '{id}_{rewrite}', + 'keywords' => array( + 'id' => array('regexp' => '[0-9]+', 'param' => 'id_manufacturer'), + 'rewrite' => array('regexp' => '[a-zA-Z0-9-]*'), + 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-]*'), + 'meta_title' => array('regexp' => '[a-zA-Z0-9-]*'), + ), ), 'cms_rule' => array( 'controller' => 'cms', - 'rule' => 'content/{number:id_cms}-{text}', + 'rule' => 'content/{id}-{rewrite}', + 'keywords' => array( + 'id' => array('regexp' => '[0-9]+', 'param' => 'id_cms'), + 'rewrite' => array('regexp' => '[a-zA-Z0-9-]*'), + 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-]*'), + 'meta_title' => array('regexp' => '[a-zA-Z0-9-]*'), + ), ), 'cms_category_rule' => array( 'controller' => 'cms', - 'rule' => 'content/category/{number:id_cms_category}-{text}', + 'rule' => 'content/category/{id}-{rewrite}', + 'keywords' => array( + 'id' => array('regexp' => '[0-9]+', 'param' => 'id_cms_category'), + 'rewrite' => array('regexp' => '[a-zA-Z0-9-]*'), + 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-]*'), + 'meta_title' => array('regexp' => '[a-zA-Z0-9-]*'), + ), ), ); @@ -85,16 +124,6 @@ class DispatcherCore */ protected $routes = array(); - /** - * List of allowed keywords in routes - * - * @var array - */ - protected $keywords = array( - 'number' => '[0-9]+', - 'text' => '[a-zA-Z0-9-]*', - ); - /** * Current controller name * @@ -173,7 +202,7 @@ class DispatcherCore { $context = Context::getContext(); foreach ($this->defaultRoutes as $id => $route) - $this->addRoute($id, $route['rule'], $route['controller']); + $this->addRoute($id, $route['rule'], $route['controller'], $route['keywords']); if ($this->useRoutes) { @@ -198,7 +227,7 @@ class DispatcherCore // Load custom routes foreach ($this->defaultRoutes as $routeID => $routeData) if ($customRoute = Configuration::get('PS_ROUTE_'.$routeID)) - $this->addRoute($routeID, $customRoute, $routeData['controller']); + $this->addRoute($routeID, $customRoute, $routeData['controller'], $routeData['keywords']); } } @@ -208,44 +237,74 @@ class DispatcherCore * @param string $rule Url rule * @param string $controller Controller to call if request uri match the rule */ - public function addRoute($routeID, $rule, $controller) - { + public function addRoute($routeID, $rule, $controller, $keywords = array()) + { $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]) + if ($keywords) + { + $transformKeywords = array(); + preg_match_all('#\\\{(([^{}]+)\\\:)?('.implode('|', array_keys($keywords)).')(\\\:([^{}]+))?\\\}#', $regexp, $m); + for ($i = 0, $total = count($m[0]); $i < $total; $i++) { - $regexp = str_replace($m[0][$i], '(?P<'.$m[3][$i].'>'.$this->keywords[$m[1][$i]].')', $regexp); - $required[$m[3][$i]] = $m[1][$i]; + $prepend = $m[2][$i]; + $keyword = $m[3][$i]; + $append = $m[5][$i]; + $transformKeywords[$keyword] = array( + 'required' => isset($keywords[$keyword]['param']), + 'prepend' => stripslashes($prepend), + 'append' => stripslashes($append), + ); + + if (isset($keywords[$keyword]['param'])) + $regexp = str_replace($m[0][$i], (($prepend) ? '('.$prepend.')?' : '').'(?P<'.$keywords[$keyword]['param'].'>'.$keywords[$keyword]['regexp'].')'.(($append) ? '('.$append.')?' : ''), $regexp); + else + $regexp = str_replace($m[0][$i], (($prepend) ? '('.$prepend.')?' : '').'('.$keywords[$keyword]['regexp'].')'.(($append) ? '('.$append.')?' : ''), $regexp); + } - else - $regexp = str_replace($m[0][$i], '('.$this->keywords[$m[1][$i]].')', $regexp); + $keywords = $transformKeywords; + } $regexp = '#^/'.$regexp.'#'; $this->routes[$routeID] = array( 'rule' => $rule, 'regexp' => $regexp, 'controller' => $controller, - 'required' => $required, + 'keywords' => $keywords, ); } - + + /** + * Check if a keyword is written in a route rule + * + * @param string $routeID + * @param string $keyword + * @return bool + */ + public function hasKeyword($routeID, $keyword) + { + if (!isset($this->routes[$routeID])) + return false; + + return preg_match('#\{([^{}]+:)?'.preg_quote($keyword, '#').'(:[^{}])?\}#', $this->routes[$routeID]['rule']); + } + + /** + * Check if a route rule contain all required keywords of default route definition + * + * @param string $routeID + * @param string $rule Rule to verify + * @param array $errors List of missing keywords + */ public function validateRoute($routeID, $rule, &$errors = array()) { $errors = array(); if (!isset($this->defaultRoutes[$routeID])) return false; - $required = array(); - preg_match_all('#\{('.implode('|', array_keys($this->keywords)).')[0-9]*:([a-z0-9_]+)\}#', $this->defaultRoutes[$routeID]['rule'], $m); - for ($i = 0, $total = count($m[0]); $i < $total; $i++) - $required[] = $m[2][$i]; - - foreach ($required as $requiredKey) - if (!preg_match('#\{('.implode('|', array_keys($this->keywords)).')[0-9]*:'.$requiredKey.'\}#', $rule)) - $errors[] = $requiredKey; - + foreach ($this->defaultRoutes[$routeID]['keywords'] as $keyword => $data) + if (isset($data['param']) && !preg_match('#\{([^{}]+:)?'.$keyword.'(:[^{}])?\}#', $rule)) + $errors[] = $keyword; + return (count($errors)) ? false : true; } @@ -267,13 +326,16 @@ class DispatcherCore return 'index.php?controller='.$routeID.(($query) ? '&'.$query : ''); } $route = $this->routes[$routeID]; - + // Check required fields $queryParams = array(); - foreach (array_keys($route['required']) as $key) + foreach ($route['keywords'] as $key => $data) { + if (!$data['required']) + continue; + if (!array_key_exists($key, $params)) - die("Dispatcher::createUrl() miss required parameter '$key'"); + die("Dispatcher::createUrl() miss required parameter '$key' for route '$routeID'"); $queryParams[$key] = $params[$key]; } @@ -282,11 +344,17 @@ class DispatcherCore { $url = $route['rule']; foreach ($params as $key => $value) - if (isset($route['required'][$key])) - $url = str_replace('{'.$route['required'][$key].':'.$key.'}', $params[$key], $url); + { + if (!isset($route['keywords'][$key])) + continue; + $data = $route['keywords'][$key]; + if ($params[$key]) + $replace = $route['keywords'][$key]['prepend'].$params[$key].$route['keywords'][$key]['append']; else - $url = str_replace('{'.$key.'}', $value, $url); - $url = preg_replace('#\{[a-z0-9]+(:[a-z0-9_]+)?\}#', '', $url); + $replace = ''; + $url = preg_replace('#\{([^{}]+:)?'.$key.'(:[^{}])?\}#', $replace, $url); + } + $url = preg_replace('#\{([^{}]+:)?[a-z0-9_]+?(:[^{}])?\}#', '', $url); } // Build a classic url index.php?controller=foo&... else @@ -336,7 +404,6 @@ class DispatcherCore $_GET[$k] = $v; break; } - $this->controller = $controller; } // Default mode, take controller from url diff --git a/classes/Link.php b/classes/Link.php index 4ccc1f3ab..055a674ae 100644 --- a/classes/Link.php +++ b/classes/Link.php @@ -62,98 +62,113 @@ class LinkCore /** * Create a link to a product * - * @param mixed $id_product ID of the product OR a Product object - * @param string $alias If $id_product is not a object, this argument is same as obj->link_rewrite - * @param string $category If $id_product is not a object, name of the product category - * @param string $ean13 + * @param mixed $product Product object (can be an ID product, but deprecated) + * @param string $alias Deprecated + * @param string $category Deprecated + * @param string $ean13 Deprecated * @param int $id_lang * @param int $id_shop (since 1.5.0) ID shop need to be used when we generate a product link for a product in a cart * @return string */ - public function getProductLink($id_product, $alias = null, $category = null, $ean13 = null, $id_lang = null, $id_shop = null) + public function getProductLink($product, $alias = null, $category = null, $ean13 = null, $id_lang = null, $id_shop = null) { + $dispatcher = Dispatcher::getInstance(); $url = _PS_BASE_URL_.__PS_BASE_URI__; + + if (!$id_lang) + $id_lang = Context::getContext()->language->id; // @todo use specific method ? if ($id_shop && ($shop = Shop::getShop($id_shop))) $url = 'http://'.$shop['domain'].'/'.$shop['uri']; $url .= $this->getLangLink($id_lang); + + if (!is_object($product)) + $product = new Product($product, false, $id_lang); - if (is_object($id_product)) - { - $product = clone($id_product); - $id_product = $product->id; - $category = $product->category; - $alias = $product->link_rewrite; - $ean13 = $product->ean13; - } + // Set available keywords + $params = array(); + $params['id'] = $product->id; + $params['rewrite'] = $product->link_rewrite; + $params['ean13'] = $product->ean13; + $params['category'] = $product->category; + $params['meta_keywords'] = Tools::str2url($product->meta_keywords); + $params['meta_title'] = Tools::str2url($product->meta_title); - if ($category AND $category != 'home') - return $url.Dispatcher::getInstance()->createUrl('product_rule2', array( - 'id_product' => $id_product, - 'text1' => $category, - 'text2' => $alias.(($ean13) ? '-'.$ean13 : ''), - ), ($alias && $this->allow)); - else - return $url.Dispatcher::getInstance()->createUrl('product_rule', array( - 'id_product' => $id_product, - 'text' => (($alias) ? $alias : '').(($ean13) ? '-'.$ean13 : ''), - ), ($alias && $this->allow)); + if ($dispatcher->hasKeyword('product_rule', 'manufacturer')) + $params['manufacturer'] = Tools::str2url($product->isFullyLoaded ? $product->manufacturer_name : Manufacturer::getNameById($product->id_manufacturer)); + + if ($dispatcher->hasKeyword('product_rule', 'supplier')) + $params['supplier'] = Tools::str2url($product->isFullyLoaded ? $product->supplier_name : Supplier::getNameById($product->id_supplier)); + + if ($dispatcher->hasKeyword('product_rule', 'price')) + $params['supplier'] = $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')) + $params['tags'] = Tools::str2url($product->getTags($id_lang)); + + return $url.$dispatcher->createUrl('product_rule', $params, $this->allow); } /** * Create a link to a category * - * @param mixed $id_category ID of the category OR a Category object - * @param string $alias If $id_category is not a object, this argument is same as obj->link_rewrite + * @param mixed $category Category object (can be an ID category, but deprecated) + * @param string $alias Deprecated * @param int $id_lang * @return string */ - public function getCategoryLink($id_category, $alias = NULL, $id_lang = NULL) + public function getCategoryLink($category, $alias = NULL, $id_lang = NULL) { $url = _PS_BASE_URL_.__PS_BASE_URI__.$this->getLangLink($id_lang); - if (is_object($id_category)) - { - $category = clone($id_category); - $id_category = $category->id; - $alias = $category->link_rewrite; - } + if (!$id_lang) + $id_lang = Context::getContext()->language->id; - return $url.Dispatcher::getInstance()->createUrl('category_rule', array( - 'id_category' => $id_category, - 'text' => ($alias) ? $alias : '', - ), ($alias && $this->allow)); + if (!is_object($category)) + $category = new Category($category, $id_lang); + + // Set available keywords + $params = array(); + $params['id'] = $category->id; + $params['rewrite'] = $category->link_rewrite; + $params['meta_keywords'] = Tools::str2url($category->meta_keywords); + $params['meta_title'] = Tools::str2url($category->meta_title); + + return $url.Dispatcher::getInstance()->createUrl('category_rule', $params, $this->allow); } /** * Create a link to a CMS category * - * @param mixed $id_category ID of the category OR a CmsCategory object - * @param string $alias If $id_category is not a object, this argument is same as obj->link_rewrite + * @param mixed $category CMSCategory object (can be an ID category, but deprecated) + * @param string $alias Deprecated * @param int $id_lang * @return string */ - public function getCMSCategoryLink($id_category, $alias = NULL, $id_lang = NULL) + public function getCMSCategoryLink($category, $alias = NULL, $id_lang = NULL) { $url = _PS_BASE_URL_.__PS_BASE_URI__.$this->getLangLink($id_lang); - if (is_object($id_category)) - { - $category = clone($id_category); - $id_category = $category->id; - $alias = $category->link_rewrite; - } + if (!$id_lang) + $id_lang = Context::getContext()->language->id; - return $url.Dispatcher::getInstance()->createUrl('cms_category_rule', array( - 'id_cms_category' => $id_category, - 'text' => ($alias) ? $alias : '', - ), ($alias && $this->allow)); + if (!is_object($category)) + $category = new CMSCategory($category, $id_lang); + + // Set available keywords + $params = array(); + $params['id'] = $category->id; + $params['rewrite'] = $category->link_rewrite; + $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); } /** * Create a link to a CMS page * - * @param mixed $cms ID of the CMS page OR a Cms object - * @param string $alias If $cms is not a object, this argument is same as obj->link_rewrite + * @param mixed $cms CMS object (can be an ID CMS, but deprecated) + * @param string $alias Deprecated * @param bool $ssl * @param int $id_lang * @return string @@ -162,67 +177,74 @@ class LinkCore { $base = (($ssl AND Configuration::get('PS_SSL_ENABLED')) ? Tools::getShopDomainSsl(true) : Tools::getShopDomain(true)); $url = $base.__PS_BASE_URI__.$this->getLangLink($id_lang); + if (!$id_lang) + $id_lang = Context::getContext()->language->id; - if (is_object($cms)) - { - $id_cms = $cms->id; - $alias = $cms->link_rewrite; - } - else - $id_cms = $cms; + if (!is_object($cms)) + $cms = new CMS($cms, $id_lang); - return $url.Dispatcher::getInstance()->createUrl('cms_rule', array( - 'id_cms' => $id_cms, - 'text' => ($alias) ? $alias : '', - ), ($alias && $this->allow)); + // Set available keywords + $params = array(); + $params['id'] = $cms->id; + $params['rewrite'] = $cms->link_rewrite; + $params['meta_keywords'] = Tools::str2url($cms->meta_keywords); + $params['meta_title'] = Tools::str2url($cms->meta_title); + + return $url.Dispatcher::getInstance()->createUrl('cms_rule', $params, $this->allow); } /** * Create a link to a supplier * - * @param mixed $id_supplier ID of the supplier page OR a Supplier object - * @param string $alias If $id_supplier is not a object, this argument is same as obj->link_rewrite + * @param mixed $supplier Supplier object (can be an ID supplier, but deprecated) + * @param string $alias Deprecated * @param int $id_lang * @return string */ - public function getSupplierLink($id_supplier, $alias = NULL, $id_lang = NULL) + public function getSupplierLink($supplier, $alias = NULL, $id_lang = NULL) { $url = _PS_BASE_URL_.__PS_BASE_URI__.$this->getLangLink($id_lang); - if (is_object($id_supplier)) - { - $supplier = clone($id_supplier); - $id_supplier = $supplier->id; - $alias = $supplier->link_rewrite; - } + if (!$id_lang) + $id_lang = Context::getContext()->language->id; - return $url.Dispatcher::getInstance()->createUrl('supplier_rule', array( - 'id_supplier' => $id_supplier, - 'text' => ($alias) ? $alias : '', - ), ($alias && $this->allow)); + if (!is_object($supplier)) + $supplier = new Supplier($supplier, $id_lang); + + // Set available keywords + $params = array(); + $params['id'] = $supplier->id; + $params['rewrite'] = $supplier->link_rewrite; + $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); } /** * Create a link to a manufacturer * - * @param mixed $id_manufacturer ID of the manufacturer page OR a Supplier object - * @param string $alias If $id_manufacturer is not a object, this argument is same as obj->link_rewrite + * @param mixed $manufacturer Manufacturer object (can be an ID supplier, but deprecated) + * @param string $alias Deprecated * @param int $id_lang * @return string */ - public function getManufacturerLink($id_manufacturer, $alias = NULL, $id_lang = NULL) + public function getManufacturerLink($manufacturer, $alias = NULL, $id_lang = NULL) { $url = _PS_BASE_URL_.__PS_BASE_URI__.$this->getLangLink($id_lang); - if (is_object($id_manufacturer)) - { - $manufacturer = clone($id_manufacturer); - $id_manufacturer = $manufacturer->id; - $alias = $manufacturer->link_rewrite; - } + if (!$id_lang) + $id_lang = Context::getContext()->language->id; - return $url.Dispatcher::getInstance()->createUrl('manufacturer_rule', array( - 'id_manufacturer' => $id_manufacturer, - 'text' => ($alias) ? $alias : '', - ), ($alias && $this->allow)); + if (!is_object($manufacturer)) + $manufacturer = new Manufacturer($manufacturer, $id_lang); + + // Set available keywords + $params = array(); + $params['id'] = $manufacturer->id; + $params['rewrite'] = $manufacturer->link_rewrite; + $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); } /** @@ -279,6 +301,7 @@ class LinkCore if (!$id_lang) $id_lang = (int)Context::getContext()->language->id; + if (is_array($request)) { unset($request['controller']); diff --git a/classes/Product.php b/classes/Product.php index e54b38b2f..16755cda6 100644 --- a/classes/Product.php +++ b/classes/Product.php @@ -184,6 +184,8 @@ class ProductCore extends ObjectModel /*** @var array Tags */ public $tags; + + public $isFullyLoaded = false; protected $langMultiShop = true; @@ -300,6 +302,7 @@ class ProductCore extends ObjectModel if ($full AND $this->id) { + $this->isFullyLoaded = $full; $this->tax_name = 'deprecated'; // The applicable tax may be BOTH the product one AND the state one (moreover this variable is some deadcode) $this->manufacturer_name = Manufacturer::getNameById((int)$this->id_manufacturer); $this->supplier_name = Supplier::getNameById((int)$this->id_supplier); @@ -2691,8 +2694,12 @@ class ProductCore extends ObjectModel public function getTags($id_lang) { + if (!$this->isFullyLoaded && is_null($this->tags)) + $this->tags = Tag::getProductTags($this->id); + if (!($this->tags AND key_exists($id_lang, $this->tags))) return ''; + $result = ''; foreach ($this->tags[$id_lang] AS $tagName) $result .= $tagName.', '; diff --git a/css/admin.css b/css/admin.css index eca53405d..b5b4e31e7 100644 --- a/css/admin.css +++ b/css/admin.css @@ -1593,4 +1593,15 @@ a.action_module_delete { .select_theme_choice{ background-color: #FAEEC2; border: 1px dotted #000000; +} + +fieldset .optionsDescription +{ + background: url("../img/admin/help2.png") no-repeat scroll 6px center #DDE9F7; + border: 1px solid #50B0EC; + color: #7F7F7F; + font-family: Arial,Verdana,Helvetica,sans-serif; + font-size: 0.85em; + margin-bottom: 15px; + padding: 5px 5px 5px 40px; } \ No newline at end of file diff --git a/translations/fr/admin.php b/translations/fr/admin.php index 96ef8ebd8..b58bccb80 100644 --- a/translations/fr/admin.php +++ b/translations/fr/admin.php @@ -915,8 +915,6 @@ $_LANGADM['AdminGenerator1dec4f55522b828fe5dacf8478021a9e'] = 'URLs simplifiées $_LANGADM['AdminGenerator223cf855cfa657eeb99550e1acd8eaa3'] = 'N\'activez cette option que si le mode rewrite est activé sur votre serveur.'; $_LANGADM['AdminGeneratoracaa02ab1d800ce9a0b3df2e4ab8909a'] = 'Désactiver l\'option apache multivues'; $_LANGADM['AdminGenerator7dc12aaf3ebf9e01ef5b2ec91761c26a'] = 'N\'activez cette option que si vous rencontrez des problèmes avec la redirection d\'url de certaines pages.'; -$_LANGADM['AdminGenerator8b1fa347125449d64bb72e2c723cd8bf'] = 'Configuration spécifique'; -$_LANGADM['AdminGeneratord59b3e143646e3f3e28005adccdb36a3'] = 'Ajouter ici les directives spécifiques de votre hébergement (SetEnv PHP_VER 5, AddType x-mapp-php5 .php...).'; $_LANGADM['AdminGeneratorb696dfaf5a833f70d71d26d052c6eaa3'] = 'Générer le fichier \".htaccess\" en cliquant sur le bouton suivant :'; $_LANGADM['AdminGenerator3c108dd1d7338dcc6a9face1824db1dd'] = 'Générer le fichier .htaccess'; $_LANGADM['AdminGenerator067b367b527d0a275f99b9071dd69e28'] = 'Cela va écraser votre'; @@ -1479,13 +1477,20 @@ $_LANGADM['AdminMeta193cfc9be3b995831c6af2fea6650e60'] = 'Page'; $_LANGADM['AdminMetab78a3223503896721cca1303f776159b'] = 'Titre'; $_LANGADM['AdminMeta1dec4f55522b828fe5dacf8478021a9e'] = 'URL simplifiée :'; $_LANGADM['AdminMetabc5d446bc10f94f2132fa898d11a423a'] = 'Configuration des URLs'; -$_LANGADM['AdminMeta1b4b359df85800a253dd935f48ef9806'] = 'Page d\'accueil'; -$_LANGADM['AdminMeta01511869cfaa1653ead50840cd612e70'] = 'Habituellement \"index.php\", mais peut être différent sur certaines configurations.'; $_LANGADM['AdminMetada82a2002384409477655085d5c4136e'] = 'N\'activez cette option que si votre serveur autorise la réécriture d\'URLs (recommandé).'; $_LANGADM['AdminMeta34d6a3e98f1b347c4f1df6257cd793c5'] = 'Si vous activez cette fonctionnalité, vous devez'; $_LANGADM['AdminMeta3cf5f5fe88091d2e57f5597b184b5959'] = 'générer un nouveau fichier .htaccess'; $_LANGADM['AdminMeta44bc5350d0a72d6f348aaeebb4004d8e'] = 'Rediriger automatiquement vers l\'url canonique'; $_LANGADM['AdminMetae73d8e659020c1acff040a3a3eaf9d21'] = 'Recommandé mais votre thème doit être conforme'; +$_LANGADM['AdminMeta5575f8bf467eba7499f22e78db6f3f56'] = 'Route vers les produits'; +$_LANGADM['AdminMeta1092637069f4ebf1bee2b02fd280888b'] = 'Route vers les catégories'; +$_LANGADM['AdminMeta08a551b84112995247355daf3b5d72ba'] = 'Route vers les fournisseurs'; +$_LANGADM['AdminMeta8f815100fbc9398e9441b28d219e0ca4'] = 'Route vers les fabricants'; +$_LANGADM['AdminMeta8eee2883d683841b6ab08c1bb6d13fb7'] = 'Route vers les pages CMS'; +$_LANGADM['AdminMeta83495f05c4aa5f326f23b6d58d0da5e6'] = 'Route vers les catégories CMS'; +$_LANGADM['AdminMeta9ca94e67feafa7c087ed70257d54ce53'] = 'Mots clefs : %s'; +$_LANGADM['AdminMeta2979a7ecfaf65f58d0adcf78e2948c8d'] = 'Vous pouvez changer ici le format de vos liens. Il y a plusieurs mots clefs disponibles pour chaque route, listés ci dessous. Les mots clefs avec * sont obligatoires. Pour ajouter un mot clef dans l\'URL, utilisez la syntaxe {motclef}. Vous pouvez ajouter du texte avant ou après le mot clef qui s\'affichera si le contenu du mot clef n\'est pas vide, avec la syntaxe {avant:motclef:apres}. Par exemple {-bonjour-:meta_title} ajoutera \"-bonjour-mon-titre\" dans l\'URL si le méta titre est rempli, autrement il n\'affichera rien. Les URL simplifiées et le module rewrite Apache doivent être activés sur votre serveur pour pouvoir utiliser cette option.'; +$_LANGADM['AdminMeta0d3ed57f8fd83cc2e9cf265a18663c0a'] = 'Format des liens'; $_LANGADM['AdminMeta0af89096135210f23a49637e3d9f3a60'] = 'Méta-Tags'; $_LANGADM['AdminMetadbb5f11eab5c5c375c4c5face47ddf1e'] = 'Page :'; $_LANGADM['AdminMetae1a7478962f9872f0765922496b26851'] = 'Il n\'y a pas de page disponible !'; @@ -2587,10 +2592,12 @@ $_LANGADM['AdminShopf5d52e166d3891c911dc7ac910387df6'] = 'La boutique par défau $_LANGADM['AdminShop7e5bf0b306c8d4608fcddb53ce9b1169'] = 'Vous ne pouvez pas changer le groupe de boutiques lorsque vous avez plus d\'une boutique'; $_LANGADM['AdminShope93c33bd1341ab74195430daeb63db13'] = 'Nom de la boutique'; $_LANGADM['AdminShop1379a6b19242372c1f23cc9adedfcdd6'] = 'Catégorie parente'; -$_LANGADM['AdminShopd721757161f7f70c5b0949fdb6ec2c30'] = 'Thème'; $_LANGADM['AdminShop24a23d787190f2c4812ff9ab11847a72'] = 'Statut:'; $_LANGADM['AdminShopb9f5c797ebbf55adccdd8539a65a0241'] = 'Désactivé'; $_LANGADM['AdminShop37c0e2b9736bc4cc2005f7be3fd66fe5'] = 'Activer ou désactiver la boutique'; +$_LANGADM['AdminShopd721757161f7f70c5b0949fdb6ec2c30'] = 'Thème'; +$_LANGADM['AdminShop38fb7d24e0d60a048f540ecb18e13376'] = 'Enregistrer'; +$_LANGADM['AdminShop19f823c6453c2b1ffd09cb715214813d'] = 'Champ obligatoire'; $_LANGADM['AdminShop1d6af794b2599c1407a83029a09d1ecf'] = 'Transporteurs'; $_LANGADM['AdminShop622f3c75de9f3481ffc58c1f292c1c2b'] = 'Page CMS'; $_LANGADM['AdminShopbbaff12800505b22a853e8b7f4eb6a22'] = 'Contact'; @@ -2611,11 +2618,7 @@ $_LANGADM['AdminShop511e7adbb96dafc5569e4be09da8dc93'] = 'Langue des produits'; $_LANGADM['AdminShop27ce7f8b5623b2e2df568d64cf051607'] = 'Stock'; $_LANGADM['AdminShop821b8ee6937cec96c30fdafbfe836d68'] = 'Magasins'; $_LANGADM['AdminShopdad1f8d794ee0dd7753fe75e73b78f31'] = 'Zones'; -$_LANGADM['AdminShop75581ca0bd0adf51a757a454503c191d'] = 'Importation de données'; -$_LANGADM['AdminShop746e1cf754a476e8c249b306a8caf162'] = 'Dupliquer les données à partir de'; $_LANGADM['AdminShopff8be7dc0dfd076e494b88721b257237'] = 'Utilisez cette option pour associer les données (produits, modules etc) de la même façon que la boutique sélectionnée'; -$_LANGADM['AdminShop38fb7d24e0d60a048f540ecb18e13376'] = 'Enregistrer'; -$_LANGADM['AdminShop19f823c6453c2b1ffd09cb715214813d'] = 'Champ obligatoire'; $_LANGADM['AdminShop652342e19bf26f8d1b350e60aad3e3bf'] = 'Ajouter une nouvelle boutique'; $_LANGADM['AdminShopUrlb718adec73e04ce3ec720dd11a06a308'] = 'ID'; $_LANGADM['AdminShopUrleae639a70006feff484a39363c977e24'] = 'Domaine'; @@ -2926,9 +2929,7 @@ $_LANGADM['AdminThemes5bcdec816ad8c7bb1e7ef04f7ae9350d'] = 'Apparaîtra sur le l $_LANGADM['AdminThemes60e53443dbca990bf3f314b2fa38e839'] = 'Taille suggérée : 30x30, GIF transparent'; $_LANGADM['AdminThemes93af5f35c247e0e814bd676249f60b62'] = 'Caractère de séparation :'; $_LANGADM['AdminThemesf2284dabeee8efb9617fbb0f05883adb'] = 'Utilisé pour le chemin de navigation dans les catégories et les produits'; -$_LANGADM['AdminThemesd721757161f7f70c5b0949fdb6ec2c30'] = 'Thème'; $_LANGADM['AdminThemesa1c58e94227389415de133efdf78ea6e'] = 'Apparence'; -$_LANGADM['AdminThemes83915d1254927f41241e8630890bec6e'] = 'Thèmes'; $_LANGADM['AdminThemesbbb572a770006c9e0e57c9e5d4bcda90'] = 'En direct de Prestashop Addons !'; $_LANGADM['AdminThemes0ac3a6bb56ca9b829859b5c12040e3a0'] = 'Trouvez de nouveaux thèmes sur Prestashop Addons !'; $_LANGADM['AdminTools442824e37ecd2fe5b938869e10e85d79'] = 'Outils de la boutique'; @@ -3333,7 +3334,6 @@ $_LANGADM['index13348442cc6a27032d2b4aa28b75a5d3'] = 'Recherche'; $_LANGADM['index4f32a32dea642737580dd71cdfd8d3c0'] = 'Accès rapide'; $_LANGADM['index891cea3363eb13a9ed383ae32f0b48d8'] = 'Selectionnez votre boutique :'; $_LANGADM['index53cd939ae14e33855274e17a3c411fdd'] = 'Pour des raisons de sécurité, vous devez :'; -$_LANGADM['index362b56674d07160fab60725a927bbf13'] = 'supprimer le dossier /install'; $_LANGADM['index7286baef44d09300636a4b99c533523c'] = 'Temps de chargement :'; $_LANGADM['indexbbaff12800505b22a853e8b7f4eb6a22'] = 'Contact'; $_LANGADM['index3e937d04c1c83492260a33d926ca587c'] = 'Bug Tracker';