Désactiver les accents dans les url sous prestashop 1.5

Vous avez sûrement constaté comme beaucoup d’autres que l’équipe de développeurs de Prestashop avait jugé bon  d’inclure les accents dans les urls. Cette idée plutôt étrange génère bien des problèmes (essayez de faire un copié collé de vos liens avec chrome par exemple). Voici la solution pour rendre les accents désactivable.

Remplacez le contenu du fichier « controllers/admin/AdminMetaController.php » par celui-ci


<?php
/*
* 2007-2012 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
*  @author PrestaShop SA <contact@prestashop.com>
*  @copyright  2007-2012 PrestaShop SA
*  @version  Release: $Revision: 7445 $
*  @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
*  International Registered Trademark & Property of PrestaShop SA
*/

class AdminMetaControllerCore extends AdminController
{
	public $table = 'meta';
	public $className = 'Meta';
	public $lang = true;
	protected $toolbar_scroll = false;

	public function __construct()
	{
		parent::__construct();

		$this->ht_file = _PS_ROOT_DIR_.'/.htaccess';
		$this->rb_file = _PS_ROOT_DIR_.'/robots.txt';
		$this->sm_file = _PS_ROOT_DIR_.'/sitemap.xml';
		$this->rb_data = $this->getRobotsContent();

		$this->explicitSelect = true;
		$this->addRowAction('edit');
		$this->addRowAction('delete');
		$this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?')));

		$this->fields_list = array(
			'id_meta' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25),
			'page' => array('title' => $this->l('Page'), 'width' => 120),
			'title' => array('title' => $this->l('Title'), 'width' => 120),
			'url_rewrite' => array('title' => $this->l('Friendly URL'), 'width' => 120)
		);
		$this->_group = 'GROUP BY a.id_meta';

		// Options to generate friendly urls
		$mod_rewrite = Tools::modRewriteActive();
		$general_fields = array(
			'PS_REWRITING_SETTINGS' => array(
				'title' => $this->l('Friendly URL'),
				'desc' => ($mod_rewrite ? $this->l('Enable only if your server allows URL rewriting (recommended)') : ''),
				'validation' => 'isBool',
				'cast' => 'intval',
				'type' => 'rewriting_settings',
				'mod_rewrite' => $mod_rewrite
			),
			'PS_CANONICAL_REDIRECT' => array(
				'title' => $this->l('Automatically redirect to Canonical URL'),
				'desc' => $this->l('Recommended, but your theme must be compliant'),
				'validation' => 'isBool',
				'cast' => 'intval',
				'type' => 'bool'
			),
			/*** patch ***/
			'PS_REWRITING_ACCEPT_ACCENTS' => array(
				'title' => $this->l('Accept accents in url rewriting'),
				'desc' => $this->l('Recommended, but your webserver must be compliant'),
				'validation' => 'isBool',
				'cast' => 'intval',
				'type' => 'bool'
			),
			/** **/
		);

		$url_description = '';
		if ($this->checkConfiguration($this->ht_file))
			$general_fields['PS_HTACCESS_DISABLE_MULTIVIEWS'] = array(
				'title' => $this->l('Disable apache multiviews'),
				'desc' => $this->l('Enable this option only if you have problems with URL rewriting on some pages.'),
				'validation' => 'isBool',
				'cast' => 'intval',
				'type' => 'bool',
			);
		else
		{
			$url_description = $this->l('Before being able to use this tool, you need to:');
			$url_description .= '<br />- '.$this->l('create a blank .htaccess in your root directory');
			$url_description .= '<br />- '.$this->l('give it write permissions (CHMOD 666 on Unix system)');
		}

		// Options to generate robot.txt
		$robots_description = $this->l('Your robots.txt file MUST be in your website\'s root directory and nowhere else (e.g. http://www.yoursite.com/robots.txt).');
		if ($this->checkConfiguration($this->rb_file))
		{
			$robots_description .= '<br />'.$this->l('Generate your "robots.txt" file by clicking on the following button (this will erase your old robots.txt file):');
			$robots_submit = array('name' => 'submitRobots', 'title' => $this->l('Generate robots.txt file'));
		}
		else
		{
			$robots_description .= '<br />'.$this->l('Before being able to use this tool, you need to:');
			$robots_description .= '<br />- '.$this->l('create a blank robots.txt file in your root directory');
			$robots_description .= '<br />- '.$this->l('give it write permissions (CHMOD 666 on Unix system)');
		}

		$robots_options = array(
			'title' => $this->l('Robots file generation'),
			'description' => $robots_description,
		);

		if (isset($robots_submit))
			$robots_options['submit'] = $robots_submit;

		// Options for shop URL if multishop is disabled
		$shop_url_options = array(
			'title' => $this->l('Set shop URL'),
			'fields' => array(),
		);

		if (!Shop::isFeatureActive())
		{
			$this->url = ShopUrl::getShopUrls($this->context->shop->id)->where('main', '=', 1)->getFirst();
			if ($this->url)
			{
				$shop_url_options['description'] = $this->l('You can set here the URL for your shop. If you migrate your shop to a new URL, remember to change the values bellow.');
				$shop_url_options['fields'] = array(
					'domain' => array(
						'title' =>	$this->l('Shop domain'),
						'validation' => 'isString',
						'type' => 'text',
						'size' => 70,
						'defaultValue' => $this->url->domain,
					),
					'domain_ssl' => array(
						'title' =>	$this->l('SSL domain'),
						'validation' => 'isString',
						'type' => 'text',
						'size' => 70,
						'defaultValue' => $this->url->domain_ssl,
					),
					'uri' => array(
						'title' =>	$this->l('Base URI'),
						'validation' => 'isString',
						'type' => 'text',
						'size' => 70,
						'defaultValue' => $this->url->physical_uri,
					),
				);
			}
		}
		else
			$shop_url_options['description'] = $this->l('Multistore option is enabled, if you want to change the URL of your shop you have to go to "Multistore" page under the "Advanced Parameters"  menu.');

		// List of options
		$this->fields_options = array(
			'general' => array(
				'title' =>	$this->l('Set up URLs'),
				'description' => $url_description,
				'fields' =>	$general_fields,
				'submit' => array()
			),
			'shop_url' => $shop_url_options
		);

		// Add display route options to options form
		if (Configuration::get('PS_REWRITING_SETTINGS'))
		{
			$this->fields_options['routes'] = array(
				'title' =>	$this->l('Schema of URLs'),
				'description' => $this->l('Change the pattern of your links. There are some available keywords for each route listed below, keywords with * are required. To add a keyword in your 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.'),
				'fields' => array()
			);
			$this->addAllRouteFields();
		}

		$this->fields_options['robots'] = $robots_options;
	}

	public function initProcess()
	{
		parent::initProcess();
		// This is a composite page, we don't want the "options" display mode
		if ($this->display == 'options')
			$this->display = '';
	}

	public function setMedia()
	{
		parent::setMedia();
		$this->addJqueryUi('ui.widget');
		$this->addJqueryPlugin('tagify');
	}

	public function addFieldRoute($route_id, $title)
	{
		$keywords = array();
		foreach (Dispatcher::getInstance()->default_routes[$route_id]['keywords'] as $keyword => $data)
			$keywords[] = ((isset($data['param'])) ? '<span class="red">'.$keyword.'*</span>' : $keyword);

		$this->fields_options['routes']['fields']['PS_ROUTE_'.$route_id] = array(
			'title' =>	$title,
			'desc' => sprintf($this->l('Keywords: %s'), implode(', ', $keywords)),
			'validation' => 'isString',
			'type' => 'text',
			'size' => 70,
			'defaultValue' => Dispatcher::getInstance()->default_routes[$route_id]['rule'],
		);
	}

	public function renderForm()
	{
		$files = Meta::getPages(true, ($this->object->page ? $this->object->page : false));
		$pages = array(
			'common' => array(
				'name' => $this->l('Default pages'),
				'query' => array(),
			),
			'module' => array(
				'name' => $this->l('Modules pages'),
				'query' => array(),
			),
		);

		foreach ($files as $name => $file)
		{
			$k = (preg_match('#^module-#', $file)) ? 'module' : 'common';
			$pages[$k]['query'][] = array(
				'id' => $file,
				'page' => $name,
			);
		}

 		$this->fields_form = array(
			'legend' => array(
				'title' => $this->l('Meta-Tags'),
				'image' => '../img/admin/metatags.gif'
			),
			'input' => array(
				array(
					'type' => 'hidden',
					'name' => 'id_meta',
				),
				array(
					'type' => 'select',
					'label' => $this->l('Page:'),
					'name' => 'page',

					'options' => array(
						'optiongroup' => array(
							'label' => 'name',
							'query' => $pages,
						),
						'options' => array(
							'id' => 'id',
							'name' => 'page',
							'query' => 'query',
						),
					),
					'desc' => $this->l('Name of the related page'),
					'required' => true,
					'empty_message' => '<p>'.$this->l('There is no page available!').'</p>',
				),
				array(
					'type' => 'text',
					'label' => $this->l('Page title:'),
					'name' => 'title',
					'lang' => true,
					'hint' => $this->l('Invalid characters:').' <>;=#{}',
					'desc' => $this->l('Title of this page'),
					'size' => 30
				),
				array(
					'type' => 'text',
					'label' => $this->l('Meta description:'),
					'name' => 'description',
					'lang' => true,
					'hint' => $this->l('Invalid characters:').' <>;=#{}',
					'desc' => $this->l('A short description of your shop'),
					'size' => 50
				),
				array(
					'type' => 'tags',
					'label' => $this->l('Meta keywords:'),
					'name' => 'keywords',
					'lang' => true,
					'hint' => $this->l('Invalid characters:').' <>;=#{}',
					'desc' => $this->l('List of keywords for search engines').' '.$this->l('To add "tags" click in the field, write something, then press "Enter"'),
					'size' => 50
				),
				array(
					'type' => 'text',
					'label' => $this->l('Rewritten URL:'),
					'name' => 'url_rewrite',
					'lang' => true,
					'required' => true,
					'hint' => $this->l('Only letters and the minus (-) character are allowed'),
					'desc' => $this->l('e.g. "contacts" for http://mysite.com/shop/contacts to redirect to http://mysite.com/shop/contact-form.php'),
					'size' => 50
				),
			),
			'submit' => array(
				'title' => $this->l('   Save   '),
				'class' => 'button'
			)
		);
		return parent::renderForm();
	}

	public function postProcess()
	{
		if (Tools::isSubmit('submitAddmeta'))
		{
			$langs = Language::getLanguages(false);

			$default_language = Configuration::get('PS_LANG_DEFAULT');
			if (Tools::getValue('page') != 'index')
			{
				$defaultLangIsValidated = Validate::isLinkRewrite(Tools::getValue('url_rewrite_'.$default_language));
				$englishLangIsValidated = Validate::isLinkRewrite(Tools::getValue('url_rewrite_1'));
			}
			else
			{	// index.php can have empty rewrite rule
				$defaultLangIsValidated = !Tools::getValue('url_rewrite_'.$default_language) || Validate::isLinkRewrite(Tools::getValue('url_rewrite_'.$default_language));
				$englishLangIsValidated = !Tools::getValue('url_rewrite_1') || Validate::isLinkRewrite(Tools::getValue('url_rewrite_1'));
			}

			if (!$defaultLangIsValidated && !$englishLangIsValidated)
			{
				$this->errors[] = Tools::displayError('URL rewrite field must be filled at least in default or English language.');
				return false;
			}

			foreach ($langs as $lang)
			{
				$current = Tools::getValue('url_rewrite_'.$lang['id_lang']);
				if (strlen($current) == 0)
					// Prioritize default language first
					if ($defaultLangIsValidated)
						$_POST['url_rewrite_'.$lang['id_lang']] = Tools::getValue('url_rewrite_'.$default_language);
					else
						$_POST['url_rewrite_'.$lang['id_lang']] = Tools::getValue('url_rewrite_1');
			}

			Hook::exec('actionAdminMetaSave');
		}
		else if (Tools::isSubmit('submitRobots'))
			$this->generateRobotsFile();

		return parent::postProcess();
	}

	public function generateRobotsFile()
	{
		if (!$write_fd = @fopen($this->rb_file, 'w'))
			$this->errors[] = sprintf(Tools::displayError('Cannot write into file: %s. Please check write permissions.'), $this->rb_file);
		else
		{
			// PS Comments
			fwrite($write_fd, "# robots.txt automaticaly generated by PrestaShop e-commerce open-source solution\n");
			fwrite($write_fd, "# http://www.prestashop.com - http://www.prestashop.com/forums\n");
			fwrite($write_fd, "# This file is to prevent the crawling and indexing of certain parts\n");
			fwrite($write_fd, "# of your site by web crawlers and spiders run by sites like Yahoo!\n");
			fwrite($write_fd, "# and Google. By telling these \"robots\" where not to go on your site,\n");
			fwrite($write_fd, "# you save bandwidth and server resources.\n");
			fwrite($write_fd, "# For more information about the robots.txt standard, see:\n");
			fwrite($write_fd, "# http://www.robotstxt.org/wc/robots.html\n");

			// User-Agent
			fwrite($write_fd, "User-agent: *\n");

			// Private pages
			if (count($this->rb_data['GB']))
			{
				fwrite($write_fd, "# Private pages\n");
				foreach ($this->rb_data['GB'] as $gb)
					fwrite($write_fd, 'Disallow: /*'.$gb."\n");
			}

			// Directories
			if (count($this->rb_data['Directories']))
			{
				fwrite($write_fd, "# Directories\n");
				foreach ($this->rb_data['Directories'] as $dir)
					fwrite($write_fd, 'Disallow: /*'.$dir."\n");
			}

			// Files
			if (count($this->rb_data['Files']))
			{
				fwrite($write_fd, "# Files\n");
				foreach ($this->rb_data['Files'] as $iso_code => $files)
					foreach ($files as $file)
						fwrite($write_fd, 'Disallow: /*'.$iso_code.'/'.$file."\n");
			}

			// Sitemap
			if (file_exists($this->sm_file) && filesize($this->sm_file))
			{
				fwrite($write_fd, "# Sitemap\n");
				fwrite($write_fd, 'Sitemap: '.(Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://').$_SERVER['SERVER_NAME'].__PS_BASE_URI__.'sitemap.xml'."\n");
			}

			fclose($write_fd);

			$this->redirect_after = self::$currentIndex.'&conf=4&token='.$this->token;
		}
	}

	public function getList($id_lang, $orderBy = null, $orderWay = null, $start = 0, $limit = null, $id_lang_shop = false)
	{
		parent::getList($id_lang, $orderBy, $orderWay, $start, $limit, Context::getContext()->shop->id);
	}

	public function renderList()
	{
		if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP)
			$this->displayInformation($this->l('You can only display the page list in a shop context.'));
		else
			return parent::renderList();
	}

	/**
	 * Validate route syntax and save it in configuration
	 *
	 * @param string $route_id
	 */
	public function checkAndUpdateRoute($route_id)
	{
		$default_routes = Dispatcher::getInstance()->default_routes;
		if (!isset($default_routes[$route_id]))
			return;

		$rule = Tools::getValue('PS_ROUTE_'.$route_id);
		if (!$rule || $rule == $default_routes[$route_id]['rule'])
		{
			Configuration::updateValue('PS_ROUTE_'.$route_id, '');
			return;
		}

		$errors = array();
		if (!Dispatcher::getInstance()->validateRoute($route_id, $rule, $errors))
		{
			foreach ($errors as $error)
				$this->errors[] = sprintf('Keyword "{%1$s}" required for route "%2$s" (rule: "%3$s")', $error, $route_id, htmlspecialchars($rule));
		}
		else
			Configuration::updateValue('PS_ROUTE_'.$route_id, $rule);
	}

	/**
	 * Called when PS_REWRITING_SETTINGS option is saved
	 */
	public function updateOptionPsRewritingSettings()
	{
		Configuration::updateValue('PS_REWRITING_SETTINGS', (int)Tools::getValue('PS_REWRITING_SETTINGS'));
		Tools::generateHtaccess($this->ht_file, null, null, '', Tools::getValue('PS_HTACCESS_DISABLE_MULTIVIEWS'));

		Tools::enableCache();
		Tools::clearCache($this->context->smarty);
		Tools::restoreCacheSettings();
	}

	public function updateOptionPsRouteProductRule()
	{
		$this->checkAndUpdateRoute('product_rule');
	}

	public function updateOptionPsRouteCategoryRule()
	{
		$this->checkAndUpdateRoute('category_rule');
	}

	public function updateOptionPsRouteLayeredRule()
	{
		$this->checkAndUpdateRoute('layered_rule');
	}

	public function updateOptionPsRouteSupplierRule()
	{
		$this->checkAndUpdateRoute('supplier_rule');
	}

	public function updateOptionPsRouteManufacturerRule()
	{
		$this->checkAndUpdateRoute('manufacturer_rule');
	}

	public function updateOptionPsRouteCmsRule()
	{
		$this->checkAndUpdateRoute('cms_rule');
	}

	public function updateOptionPsRouteCmsCategoryRule()
	{
		$this->checkAndUpdateRoute('cms_category_rule');
	}

	/**
	 * Update shop domain (for mono shop)
	 */
	public function updateOptionDomain($value)
	{
		if (!Shop::isFeatureActive() && $this->url && $this->url->domain != $value)
		{
			if (Validate::isCleanHtml($value))
			{
				$this->url->domain = $value;
				$this->url->update();
			}
			else
				$this->errors[] = Tools::displayError('Domain is not valid');
		}
	}

	/**
	 * Update shop SSL domain (for mono shop)
	 */
	public function updateOptionDomainSsl($value)
	{
		if (!Shop::isFeatureActive() && $this->url && $this->url->domain_ssl != $value)
		{
			if (Validate::isCleanHtml($value))
			{
				$this->url->domain_ssl = $value;
				$this->url->update();
			}
			else
				$this->errors[] = Tools::displayError('SSL Domain is not valid');
		}
	}

	/**
	 * Update shop physical uri for mono shop)
	 */
	public function updateOptionUri($value)
	{
		if (!Shop::isFeatureActive() && $this->url && $this->url->physical_uri != $value)
		{
			$this->url->physical_uri = $value;
			$this->url->update();
		}
	}

	/**
	 * Function used to render the options for this controller
	 */
	public function renderOptions()
	{
		// If friendly url is not active, do not display custom routes form
		if (Configuration::get('PS_REWRITING_SETTINGS'))
			$this->addAllRouteFields();

		if ($this->fields_options && is_array($this->fields_options))
		{
			$helper = new HelperOptions($this);
			$this->setHelperDisplay($helper);
			$helper->toolbar_scroll = true;
			$helper->toolbar_btn = array('save' => array(
								'href' => '#',
								'desc' => $this->l('Save')
							));
			$helper->id = $this->id;
			$helper->tpl_vars = $this->tpl_option_vars;
			$options = $helper->generateOptions($this->fields_options);

			return $options;
		}
	}

	/**
	 * Add all custom route fields to the options form
	 */
	public function addAllRouteFields()
	{
		$this->addFieldRoute('product_rule', $this->l('Route to products'));
		$this->addFieldRoute('category_rule', $this->l('Route to category'));
		$this->addFieldRoute('layered_rule', $this->l('Route to category with attribute selected_filter for the module block layered'));
		$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'));
		$this->addFieldRoute('module', $this->l('Route to modules'));
	}

	/**
	 * Check if a file is writable
	 *
	 * @param string $file
	 * @return bool
	 */
	public function checkConfiguration($file)
	{
		if (file_exists($file))
			return is_writable($file);
		return is_writable(dirname($file));
	}

	public function getRobotsContent()
	{
		$tab = array();

		// Directories
		$tab['Directories'] = array('classes/', 'config/', 'download/', 'mails/', 'modules/', 'translations/', 'tools/');

		// Files
		$disallow_controllers = array(
			'addresses', 'address', 'authentication', 'cart', 'discount', 'footer',
			'get-file', 'header', 'history', 'identity', 'images.inc', 'init', 'my-account', 'order', 'order-opc',
			'order-slip', 'order-detail', 'order-follow', 'order-return', 'order-confirmation', 'pagination', 'password',
			'pdf-invoice', 'pdf-order-return', 'pdf-order-slip', 'product-sort', 'search', 'statistics','attachment', 'guest-tracking'
		);

		// Rewrite files
		$tab['Files'] = array();
		if (Configuration::get('PS_REWRITING_SETTINGS'))
		{
			$sql = 'SELECT ml.url_rewrite, l.iso_code
					FROM '._DB_PREFIX_.'meta m
					INNER JOIN '._DB_PREFIX_.'meta_lang ml ON ml.id_meta = m.id_meta
					INNER JOIN '._DB_PREFIX_.'lang l ON l.id_lang = ml.id_lang
					WHERE l.active = 1 AND m.page IN (\''.implode('\', \'', $disallow_controllers).'\')';
			if ($results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql))
				foreach ($results as $row)
					$tab['Files'][$row['iso_code']][] = $row['url_rewrite'];
		}

		$tab['GB'] = array(
			'orderby=','orderway=','tag=','id_currency=','search_query=','back=','utm_source=','utm_medium=','utm_campaign=','n='
		);

		foreach ($disallow_controllers as $controller)
			$tab['GB'][] = 'controller='.$controller;

		return $tab;
	}
}


Remplacez ensuite le contenu du fichier « classes/link.php » par celui-ci:


<?php
/*
* 2007-2012 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
*  @author PrestaShop SA <contact@prestashop.com>
*  @copyright  2007-2012 PrestaShop SA
*  @version  Release: $Revision: 7465 $
*  @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
*  International Registered Trademark & Property of PrestaShop SA
*/

class LinkCore
{
	/** @var boolean Rewriting activation */
	protected $allow;
	protected $url;
	public static $cache = array('page' => array());

	public $protocol_link;
	public $protocol_content;

	protected $ssl_enable;

	/**
	  * Constructor (initialization only)
	  */
	public function __construct($protocol_link = null, $protocol_content = null)
	{
		$this->allow = (int)Configuration::get('PS_REWRITING_SETTINGS');
		/*** patch ***/
		//This check because if patched without loading and setting the value in admin/SEO pannel (which sets the PS_REWRITING_ACCEPT_ACCENTS in the database),
		//we should continue with the old behavior (ie: with accents)
		$this->allow_accents = !is_bool(Configuration::get('PS_REWRITING_ACCEPT_ACCENTS')) ? (int)Configuration::get('PS_REWRITING_ACCEPT_ACCENTS') : 1;
		/*** patch ***/
		$this->url = $_SERVER['SCRIPT_NAME'];
		$this->protocol_link = $protocol_link;
		$this->protocol_content = $protocol_content;

		if (!defined('_PS_BASE_URL_'))
			define('_PS_BASE_URL_', Tools::getShopDomain(true));
		if (!defined('_PS_BASE_URL_SSL_'))
			define('_PS_BASE_URL_SSL_', Tools::getShopDomainSsl(true));

		$this->ssl_enable = Configuration::get('PS_SSL_ENABLED');
	}

	/**
	 * Create a link to delete a product
	 *
	 * @param mixed $product ID of the product OR a Product object
	 * @param int $id_picture ID of the picture to delete
	 * @return string
	 */
	public function getProductDeletePictureLink($product, $id_picture)
	{
		$url = $this->getProductLink($product);
		return $url.((strpos($url, '?')) ? '&' : '?').'&deletePicture='.$id_picture;
	}

	/**
	 * Create a link to a product
	 *
	 * @param mixed $product Product object (can be an ID product, but deprecated)
	 * @param string $alias
	 * @param string $category
	 * @param string $ean13
	 * @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
	 * @param int $ipa ID product attribute
	 * @return string
	 */
	public function getProductLink($product, $alias = null, $category = null, $ean13 = null, $id_lang = null, $id_shop = null, $ipa = 0, $force_routes = false)
	{
		$dispatcher = Dispatcher::getInstance();

		if (!$id_lang)
			$id_lang = Context::getContext()->language->id;

		if (!$id_shop)
			$shop = Context::getContext()->shop;
		else
			$shop = new Shop($id_shop);

		$url = 'http://'.$shop->domain.$shop->getBaseURI().$this->getLangLink($id_lang);

		if (!is_object($product))
		{
			if (is_array($product) && isset($product['id_product']))
					$product = new Product($product['id_product'], false, $id_lang);
			else if (is_numeric($product) || !$product)
				$product = new Product($product, false, $id_lang);
			else
				throw new PrestaShopException('Invalid product vars');
		}

		// Set available keywords
		$params = array();
		$params['id'] = $product->id;

		/*** patch ***/
		//$params['rewrite'] = (!$alias) ? $product->getFieldByLang('link_rewrite') : $alias;
		if(!$this->allow_accents)
		$params['rewrite'] = (!$alias) ? Tools::replaceAccentedChars($product->getFieldByLang('link_rewrite')) : Tools::replaceAccentedChars($alias);
		else
		$params['rewrite'] = (!$alias) ? $product->getFieldByLang('link_rewrite') : $alias;
		/*** ***/

		$params['ean13'] = (!$ean13) ? $product->ean13 : $ean13;
		$params['meta_keywords'] =	Tools::str2url($product->getFieldByLang('meta_keywords'));
		$params['meta_title'] = Tools::str2url($product->getFieldByLang('meta_title'));

		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', $id_lang, 'supplier'))
			$params['supplier'] = Tools::str2url($product->isFullyLoaded ? $product->supplier_name : Supplier::getNameById($product->id_supplier));

		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', $id_lang, 'tags'))
			$params['tags'] = Tools::str2url($product->getTags($id_lang));

		if ($dispatcher->hasKeyword('product_rule', $id_lang, 'reference'))
			$params['reference'] = Tools::str2url($product->reference);

		if ($dispatcher->hasKeyword('product_rule', $id_lang, 'categories'))
		{
			$params['category'] = (!$category) ? $product->category : $category;
			$cats = array();
			/*** patch ***/
			/*foreach ($product->getParentCategories() as $cat)
				$cats[] = $cat['link_rewrite'];*/
			foreach ($product->getParentCategories() as $cat){
				$link_rewrite = $cat['link_rewrite'];
				if(!$this->allow_accents)
					$link_rewrite = Tools::replaceAccentedChars($link_rewrite);
				$cats[] = $link_rewrite;
			}
			/*** ***/
			$params['categories'] = implode('/', $cats);
		}
		$anchor = $ipa ? $product->getAnchor($ipa) : '';

		return $url.$dispatcher->createUrl('product_rule', $id_lang, $params, $force_routes, $anchor);
	}

	/**
	 * Create a link to a category
	 *
	 * @param mixed $category Category object (can be an ID category, but deprecated)
	 * @param string $alias
	 * @param int $id_lang
	 * @param string $selected_filters Url parameter to autocheck filters of the module blocklayered
	 * @return string
	 */
	public function getCategoryLink($category, $alias = null, $id_lang = null, $selected_filters = null)
	{
		if (!$id_lang)
			$id_lang = Context::getContext()->language->id;
		$url = _PS_BASE_URL_.__PS_BASE_URI__.$this->getLangLink($id_lang);

		if (!is_object($category))
			$category = new Category($category, $id_lang);

		// Set available keywords
		$params = array();
		$params['id'] = $category->id;
		/** patch **/
		//$params['rewrite'] = (!$alias) ? $category->link_rewrite : $alias;
		if(!$this->allow_accents)
			$params['rewrite'] = (!$alias) ? Tools::replaceAccentedChars($category->link_rewrite) : Tools::replaceAccentedChars($alias);
		else
			$params['rewrite'] = (!$alias) ? $category->link_rewrite : $alias;
		/** **/
		$params['meta_keywords'] =	Tools::str2url($category->meta_keywords);
		$params['meta_title'] = Tools::str2url($category->meta_title);

		// Selected filters is used by the module blocklayered
		$selected_filters = is_null($selected_filters) ? Tools::getValue('selected_filters') : $selected_filters;

		if (empty($selected_filters))
			$rule = 'category_rule';
		else
		{
			$rule = 'layered_rule';
			$params['selected_filters'] = $selected_filters;
		}

		return $url.Dispatcher::getInstance()->createUrl($rule, $id_lang, $params, $this->allow);
	}

	/**
	 * Create a link to a CMS category
	 *
	 * @param mixed $category CMSCategory object (can be an ID category, but deprecated)
	 * @param string $alias
	 * @param int $id_lang
	 * @return string
	 */
	public function getCMSCategoryLink($category, $alias = null, $id_lang = null)
	{
		if (!$id_lang)
			$id_lang = Context::getContext()->language->id;
		$url = _PS_BASE_URL_.__PS_BASE_URI__.$this->getLangLink($id_lang);

		if (!is_object($category))
			$category = new CMSCategory($category, $id_lang);

		// Set available keywords
		$params = array();
		$params['id'] = $category->id;
		/*** patch ***/
		//$params['rewrite'] = (!$alias) ? $category->link_rewrite : $alias;
		if(!$this->allow_accents)
			$params['rewrite'] = (!$alias) ? Tools::replaceAccentedChars($category->link_rewrite) : Tools::replaceAccentedChars($alias);
		else
			$params['rewrite'] = (!$alias) ? $category->link_rewrite : $alias;
		/*** ***/
		$params['meta_keywords'] =	Tools::str2url($category->meta_keywords);
		$params['meta_title'] = Tools::str2url($category->meta_title);

		return $url.Dispatcher::getInstance()->createUrl('cms_category_rule', $id_lang, $params, $this->allow);
	}

	/**
	 * Create a link to a CMS page
	 *
	 * @param mixed $cms CMS object (can be an ID CMS, but deprecated)
	 * @param string $alias
	 * @param bool $ssl
	 * @param int $id_lang
	 * @return string
	 */
	public function getCMSLink($cms, $alias = null, $ssl = false, $id_lang = null)
	{
		$base = (($ssl && $this->ssl_enable) ? _PS_BASE_URL_SSL_ : _PS_BASE_URL_);

		if (!$id_lang)
			$id_lang = Context::getContext()->language->id;
		$url = $base.__PS_BASE_URI__.$this->getLangLink($id_lang);

		if (!is_object($cms))
			$cms = new CMS($cms, $id_lang);

		// Set available keywords
		$params = array();
		$params['id'] = $cms->id;
		/*** patch ***/
		//$params['rewrite'] = (!$alias) ? (is_array($cms->link_rewrite) ? $cms->link_rewrite[(int)$id_lang] : $cms->link_rewrite) : $alias;
		if(!$this->allow_accents)
			$params['rewrite'] = (!$alias) ? (is_array($cms->link_rewrite) ? Tools::replaceAccentedChars($cms->link_rewrite[(int)$id_lang]) : Tools::replaceAccentedChars($cms->link_rewrite)) : Tools::replaceAccentedChars($alias);
		else
			$params['rewrite'] = (!$alias) ? (is_array($cms->link_rewrite) ? $cms->link_rewrite[(int)$id_lang] : $cms->link_rewrite) : $alias;
		/*** ***/
		if (isset($cms->meta_keywords) && !empty($cms->meta_keywords))
			$params['meta_keywords'] = is_array($cms->meta_keywords) ?  Tools::str2url($cms->meta_keywords[(int)$id_lang]) :  Tools::str2url($cms->meta_keywords);
		else
			$params['meta_keywords'] = '';

		if (isset($cms->meta_title) && !empty($cms->meta_title))
			$params['meta_title'] = is_array($cms->meta_title) ? Tools::str2url($cms->meta_title[(int)$id_lang]) : Tools::str2url($cms->meta_title);
		else
			$params['meta_title'] = '';

		return $url.Dispatcher::getInstance()->createUrl('cms_rule', $id_lang, $params, $this->allow);
	}

	/**
	 * Create a link to a supplier
	 *
	 * @param mixed $supplier Supplier object (can be an ID supplier, but deprecated)
	 * @param string $alias
	 * @param int $id_lang
	 * @return string
	 */
	public function getSupplierLink($supplier, $alias = null, $id_lang = null)
	{
		if (!$id_lang)
			$id_lang = Context::getContext()->language->id;
		$url = _PS_BASE_URL_.__PS_BASE_URI__.$this->getLangLink($id_lang);

		if (!is_object($supplier))
			$supplier = new Supplier($supplier, $id_lang);

		// Set available keywords
		$params = array();
		$params['id'] = $supplier->id;
		/*** patch ***/
		//$params['rewrite'] = (!$alias) ? $supplier->link_rewrite : $alias;
		if(!$this->allow_accents)
			$params['rewrite'] = (!$alias) ? Tools::replaceAccentedChars($supplier->link_rewrite) : Tools::replaceAccentedChars($alias);
		else
			$params['rewrite'] = (!$alias) ? $supplier->link_rewrite : $alias;
		/*** ***/
		$params['meta_keywords'] =	Tools::str2url($supplier->meta_keywords);
		$params['meta_title'] = Tools::str2url($supplier->meta_title);

		return $url.Dispatcher::getInstance()->createUrl('supplier_rule', $id_lang, $params, $this->allow);
	}

	/**
	 * Create a link to a manufacturer
	 *
	 * @param mixed $manufacturer Manufacturer object (can be an ID supplier, but deprecated)
	 * @param string $alias
	 * @param int $id_lang
	 * @return string
	 */
	public function getManufacturerLink($manufacturer, $alias = null, $id_lang = null)
	{
		if (!$id_lang)
			$id_lang = Context::getContext()->language->id;
		$url = _PS_BASE_URL_.__PS_BASE_URI__.$this->getLangLink($id_lang);

		if (!is_object($manufacturer))
			$manufacturer = new Manufacturer($manufacturer, $id_lang);

		// Set available keywords
		$params = array();
		$params['id'] = $manufacturer->id;
		/*** patch ***/
		//$params['rewrite'] = (!$alias) ? $manufacturer->link_rewrite : $alias;
		if(!$this->allow_accents)
			$params['rewrite'] = (!$alias) ? Tools::replaceAccentedChars($manufacturer->link_rewrite) : Tools::replaceAccentedChars($alias);
		else
			$params['rewrite'] = (!$alias) ? $manufacturer->link_rewrite : $alias;
		/*** ***/
		$params['meta_keywords'] =	Tools::str2url($manufacturer->meta_keywords);
		$params['meta_title'] = Tools::str2url($manufacturer->meta_title);

		return $url.Dispatcher::getInstance()->createUrl('manufacturer_rule', $id_lang, $params, $this->allow);
	}

	/**
	 * Create a link to a module
	 *
	 * @since 1.5.0
	 * @param string $module Module name
	 * @param string $process Action name
	 * @param int $id_lang
	 * @return string
	 */
	public function getModuleLink($module, $controller = 'default', array $params = array(), $ssl = false, $id_lang = null)
	{
		$base = (($ssl && $this->ssl_enable) ? _PS_BASE_URL_SSL_ : _PS_BASE_URL_);

		if (!$id_lang)
			$id_lang = Context::getContext()->language->id;
		$url = $base.__PS_BASE_URI__.$this->getLangLink($id_lang);

		// Set available keywords
		$params['module'] = $module;
		$params['controller'] = $controller ? $controller : 'default';

		// If the module has its own route ... just use it !
		if (Dispatcher::getInstance()->hasRoute('module-'.$module.'-'.$controller, $id_lang))
			return $this->getPageLink('module-'.$module.'-'.$controller, $ssl, $id_lang, $params);
		else
			return $url.Dispatcher::getInstance()->createUrl('module', $id_lang, $params, $this->allow);
	}

	/**
	 * Use controller name to create a link
	 *
	 * @param string $controller
	 * @param boolean $with_token include or not the token in the url
	 * @return controller url
	 */
	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, $id_lang, $params, false);
	}

	/**
	 * Returns a link to a product image for display
	 * Note: the new image filesystem stores product images in subdirectories of img/p/
	 *
	 * @param string $name rewrite link of the image
	 * @param string $ids id part of the image filename - can be "id_product-id_image" (legacy support, recommended) or "id_image" (new)
	 * @param string $type
	 */
	public function getImageLink($name, $ids, $type = null)
	{
		if(!$this->allow_accents)
			$name = Tools::replaceAccentedChars($name);
		// legacy mode or default image
		$theme = ((Shop::isFeatureActive() && file_exists(_PS_PROD_IMG_DIR_.$ids.($type ? '-'.$type : '').'-'.(int)Context::getContext()->shop->id_theme.'.jpg')) ? '-'.Context::getContext()->shop->id_theme : '');
		if ((Configuration::get('PS_LEGACY_IMAGES')
			&& (file_exists(_PS_PROD_IMG_DIR_.$ids.($type ? '-'.$type : '').$theme.'.jpg')))
			|| ($not_default = strpos($ids, 'default') !== false))
		{
			if ($this->allow == 1 && !$not_default)
				$uri_path = __PS_BASE_URI__.$ids.($type ? '-'.$type : '').$theme.'/'.$name.'.jpg';
			else
				$uri_path = _THEME_PROD_DIR_.$ids.($type ? '-'.$type : '').$theme.'.jpg';
		}
		else
		{
			// if ids if of the form id_product-id_image, we want to extract the id_image part
			$split_ids = explode('-', $ids);
			$id_image = (isset($split_ids[1]) ? $split_ids[1] : $split_ids[0]);
			$theme = ((Shop::isFeatureActive() && file_exists(_PS_PROD_IMG_DIR_.Image::getImgFolderStatic($id_image).$id_image.($type ? '-'.$type : '').'-'.(int)Context::getContext()->shop->id_theme.'.jpg')) ? '-'.Context::getContext()->shop->id_theme : '');
			if ($this->allow == 1)
				$uri_path = __PS_BASE_URI__.$id_image.($type ? '-'.$type : '').$theme.'/'.$name.'.jpg';
			else
				$uri_path = _THEME_PROD_DIR_.Image::getImgFolderStatic($id_image).$id_image.($type ? '-'.$type : '').$theme.'.jpg';
		}

		return $this->protocol_content.Tools::getMediaServer($uri_path).$uri_path;
	}

	public function getMediaLink($filepath)
	{
		return Tools::getProtocol().Tools::getMediaServer($filepath).$filepath;
	}

	/**
	 * Create a simple link
	 *
	 * @param string $controller
	 * @param bool $ssl
	 * @param int $id_lang
	 * @param string|array $request
	 * @param bool $request_url_encode Use URL encode
	 *
	 * @return string Page link
	 */
	public function getPageLink($controller, $ssl = false, $id_lang = null, $request = null, $request_url_encode = false)
	{
		$controller = Tools::strReplaceFirst('.php', '', $controller);

		if (!$id_lang)
			$id_lang = (int)Context::getContext()->language->id;

		if (!is_array($request))
		{
			// @FIXME html_entity_decode has been added due to '&' => '%3B' ...
			$request = html_entity_decode($request);
			if ($request_url_encode)
				$request = urlencode($request);
			parse_str($request, $request);
		}
		unset($request['controller'], $request['module']);

		$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, '/');

		return $url;
	}

	public function getCatImageLink($name, $id_category, $type = null)
	{
		return ($this->allow == 1) ? (__PS_BASE_URI__.'c/'.$id_category.($type ? '-'.$type : '').'/'.$name.'.jpg') : (_THEME_CAT_DIR_.$id_category.($type ? '-'.$type : '').'.jpg');
	}

	/**
	 * Create link after language change, for the change language block
	 *
	 * @param integer $id_lang Language ID
	 * @return string link
	 */
	public function getLanguageLink($id_lang, Context $context = null)
	{
		if (!$context)
			$context = Context::getContext();

		$params = $_GET;
		unset($params['isolang'], $params['controller']);

		if (!$this->allow)
			$params['id_lang'] = $id_lang;
		else
			unset($params['id_lang']);

		$controller = Dispatcher::getInstance()->getController();
		if (!empty(Context::getContext()->controller->php_self))
			$controller = Context::getContext()->controller->php_self;

		if ($controller == 'product' && isset($params['id_product']))
			return $this->getProductLink((int)$params['id_product'], null, null, null, (int)$id_lang);
		elseif ($controller == 'category' && isset($params['id_category']))
			return $this->getCategoryLink((int)$params['id_category'], null, (int)$id_lang);
		elseif ($controller == 'supplier' && isset($params['id_supplier']))
			return $this->getSupplierLink((int)$params['id_supplier'], null, (int)$id_lang);
		elseif ($controller == 'manufacturer' && isset($params['id_manufacturer']))
			return $this->getManufacturerLink((int)$params['id_manufacturer'], null, (int)$id_lang);
		elseif ($controller == 'cms' && isset($params['id_cms']))
			return $this->getCMSLink((int)$params['id_cms'], null, false, (int)$id_lang);
		elseif ($controller == 'cms' && isset($params['id_cms_category']))
			return $this->getCMSCategoryLink((int)$params['id_cms_category'], null, (int)$id_lang);

		return $this->getPageLink($controller, false, $id_lang, $params);
	}

	public function goPage($url, $p)
	{
		return $url.($p == 1 ? '' : (!strstr($url, '?') ? '?' : '&').'p='.(int)$p);
	}

	/**
	 * Get pagination link
	 *
	 * @param string $type Controller name
	 * @param int $id_object
	 * @param boolean $nb Show nb element per page attribute
	 * @param boolean $sort Show sort attribute
	 * @param boolean $pagination Show page number attribute
	 * @param boolean $array If false return an url, if true return an array
	 */
	public function getPaginationLink($type, $id_object, $nb = false, $sort = false, $pagination = false, $array = false)
	{
		// If no parameter $type, try to get it by using the controller name
		if (!$type && !$id_object)
		{
			$method_name = 'get'.Dispatcher::getInstance()->getController().'Link';
			if (method_exists($this, $method_name) && isset($_GET['id_'.Dispatcher::getInstance()->getController()]))
			{
				$type = Dispatcher::getInstance()->getController();
				$id_object = $_GET['id_'.$type];
			}
		}

		if ($type && $id_object)
			$url = $this->{'get'.$type.'Link'}($id_object, null);
		else
		{
			if (isset(Context::getContext()->controller->php_self))
				$name = Context::getContext()->controller->php_self;
			else
				$name = Dispatcher::getInstance()->getController();
			$url = $this->getPageLink($name);
		}

		$vars = array();
		$vars_nb = array('n', 'search_query');
		$vars_sort = array('orderby', 'orderway');
		$vars_pagination = array('p');

		foreach ($_GET as $k => $value)
		{
			if ($k != 'id_'.$type && $k != 'controller')
			{
				if (Configuration::get('PS_REWRITING_SETTINGS') && ($k == 'isolang' || $k == 'id_lang'))
					continue;
				$if_nb = (!$nb || ($nb && !in_array($k, $vars_nb)));
				$if_sort = (!$sort || ($sort && !in_array($k, $vars_sort)));
				$if_pagination = (!$pagination || ($pagination && !in_array($k, $vars_pagination)));
				if ($if_nb && $if_sort && $if_pagination)
				{
					if (!is_array($value))
						$vars[urlencode($k)] = $value;
					else
					{
						foreach (explode('&', http_build_query(array($k => $value), '', '&')) as $key => $val)
						{
							$data = explode('=', $val);
							$vars[urldecode($data[0])] = $data[1];
						}
					}
				}
			}
		}

		if (!$array)
			return $url.(($this->allow == 1 || $url == $this->url) ? '?' : '&').http_build_query($vars, '', '&');
		$vars['requestUrl'] = $url;

		if ($type && $id_object)
			$vars['id_'.$type] = (is_object($id_object) ? (int)$id_object->id : (int)$id_object);

		if (!$this->allow == 1)
			$vars['controller'] = Dispatcher::getInstance()->getController();
		return $vars;
	}

	public function addSortDetails($url, $orderby, $orderway)
	{
		return $url.(!strstr($url, '?') ? '?' : '&').'orderby='.urlencode($orderby).'&orderway='.urlencode($orderway);
	}

	protected function getLangLink($id_lang = null, Context $context = null)
	{
		if (!$context)
			$context = Context::getContext();

		if (!$this->allow || !Language::isMultiLanguageActivated())
			return '';

		if (!$id_lang)
			$id_lang = $context->language->id;

		return Language::getIsoById($id_lang).'/';
	}
}


Ensuite vous n’avez plus qu’à vous rendre dans « preferences/seo&urls » et modifier le réglage: « Accept accents in url rewriting »

Un grand merci à Gehasia qui a posté ce patch sur le forum officiel.

ps: dans la rubrique « référencement » de votre fiche produit vous constaterez que l’url généré utilise toujours les accents mais rassurez-vous en front office ce ne sera plus le cas.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *