diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..ba7a233
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,9 @@
+; top-most EditorConfig file
+root = true
+
+[*]
+end_of_line = LF
+insert_final_newline = true
+trim_trailing_whitespace = true
+indent_style = space
+indent_size = 4
diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index 412eeda..0000000
--- a/.gitattributes
+++ /dev/null
@@ -1,22 +0,0 @@
-# Auto detect text files and perform LF normalization
-* text=auto
-
-# Custom for Visual Studio
-*.cs diff=csharp
-*.sln merge=union
-*.csproj merge=union
-*.vbproj merge=union
-*.fsproj merge=union
-*.dbproj merge=union
-
-# Standard to msysgit
-*.doc diff=astextplain
-*.DOC diff=astextplain
-*.docx diff=astextplain
-*.DOCX diff=astextplain
-*.dot diff=astextplain
-*.DOT diff=astextplain
-*.pdf diff=astextplain
-*.PDF diff=astextplain
-*.rtf diff=astextplain
-*.RTF diff=astextplain
diff --git a/.gitignore b/.gitignore
index b9d6bd9..fe98dfa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,215 +1,5 @@
-#################
-## Eclipse
-#################
-
-*.pydevproject
-.project
-.metadata
+vendor/
bin/
-tmp/
-*.tmp
-*.bak
-*.swp
-*~.nib
-local.properties
-.classpath
-.settings/
-.loadpath
-
-# External tool builders
-.externalToolBuilders/
-
-# Locally stored "Eclipse launch configurations"
-*.launch
-
-# CDT-specific
-.cproject
-
-# PDT-specific
-.buildpath
-
-
-#################
-## Visual Studio
-#################
-
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-
-# User-specific files
-*.suo
-*.user
-*.sln.docstates
-
-# Build results
-
-[Dd]ebug/
-[Rr]elease/
-x64/
-build/
-[Bb]in/
-[Oo]bj/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-*_i.c
-*_p.c
-*.ilk
-*.meta
-*.obj
-*.pch
-*.pdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.log
-*.scc
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opensdf
-*.sdf
-*.cachefile
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# NCrunch
-*.ncrunch*
-.*crunch*.local.xml
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.Publish.xml
-*.pubxml
-
-# NuGet Packages Directory
-## TODO: If you have NuGet Package Restore enabled, uncomment the next line
-#packages/
-
-# Windows Azure Build Output
-csx
-*.build.csdef
-
-# Windows Store app package directory
-AppPackages/
-
-# Others
-sql/
-*.Cache
-ClientBin/
-[Ss]tyle[Cc]op.*
-~$*
-*~
-*.dbmdl
-*.[Pp]ublish.xml
-*.pfx
-*.publishsettings
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file to a newer
-# Visual Studio version. Backup files are not needed, because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-
-# SQL Server files
-App_Data/*.mdf
-App_Data/*.ldf
-
-#############
-## Windows detritus
-#############
-
-# Windows image file caches
-Thumbs.db
-ehthumbs.db
-
-# Folder config file
-Desktop.ini
-
-# Recycle Bin used on file shares
-$RECYCLE.BIN/
-
-# Mac crap
-.DS_Store
-
-
-#############
-## Python
-#############
-
-*.py[co]
-
-# Packages
-*.egg
-*.egg-info
-dist/
-build/
-eggs/
-parts/
-var/
-sdist/
-develop-eggs/
-.installed.cfg
-
-# Installer logs
-pip-log.txt
-
-# Unit test / coverage reports
-.coverage
-.tox
-
-#Translations
-*.mo
-
-#Mr Developer
-.mr.developer.cfg
+.php_cs.cache
+config_*.xml
+*.zip
diff --git a/.php_cs b/.php_cs
new file mode 100644
index 0000000..e1764dc
--- /dev/null
+++ b/.php_cs
@@ -0,0 +1,39 @@
+
+@license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+@source https://github.com/faktiva/prestashop-clean-urls
+EOF;
+
+Symfony\CS\Fixer\Contrib\HeaderCommentFixer::setHeader($header);
+
+$finder = Symfony\CS\Finder::create()
+ ->in(__DIR__.'/faktiva_clean_urls');
+
+return Symfony\CS\Config\Config::create()
+ ->setUsingCache(true)
+ ->level(Symfony\CS\FixerInterface::SYMFONY_LEVEL)
+ ->fixers(array(
+ 'header_comment',
+ 'empty_return',
+ 'long_array_syntax',
+ 'newline_after_open_tag',
+ 'short_echo_tag',
+ ))
+ ->finder($finder)
+;
+
+// vim:ft=php
diff --git a/.sensiolabs.yml b/.sensiolabs.yml
new file mode 100644
index 0000000..ec19085
--- /dev/null
+++ b/.sensiolabs.yml
@@ -0,0 +1,17 @@
+global_exclude_dirs:
+ - translations
+ - upgrade
+
+exclude_patterns:
+ - tools/debug.php
+
+rules:
+ php.absolute_path_present:
+ enabled: true
+ allowed_paths: []
+ php.method_too_long:
+ enabled: true
+ max_length: 50
+ threshold: 15
+ php.psr1:
+ enabled: false
diff --git a/README.md b/README.md
index 4f38b77..0fee7d4 100644
--- a/README.md
+++ b/README.md
@@ -1,42 +1,93 @@
-README
-======
+[](https://insight.sensiolabs.com/projects/58d1de4f-45fc-4f63-aeb3-7ddc51d4a64e)
+[PrestaShop module "Clean URLs"](https://github.com/faktiva/prestashop-seo-tk)
+===
+[](https://github.com/faktiva/prestashop-clean-urls/releases/latest)
+[](http://opensource.box.com/badges)
+[](http://isitmaintained.com/project/faktiva/prestashop-clean-urls "Percentage of issues still open")
+[](http://isitmaintained.com/project/faktiva/prestashop-clean-urls "Average time to resolve an issue")
+[](https://packagist.org/packages/faktiva/prestashop-clean-urls)
+[](https://libraries.io/github/faktiva/prestashop-clean-urls)
+[](https://creativecommons.org/licenses/by-sa/4.0/)
-ABOUT
---------
+[](https://gitter.im/faktiva/prestashop-clean-urls)
+[](https://twitter.com/intent/tweet?text=Fantastic @PrestaShop module "#Faktiva Clean URLs"&url=https://github.com/faktiva/prestashop-clean-urls)
-This PrestaShop 1.5 module/override allows removal of number ID's from all URLs.
+____
+**Makes possible to have URLs with no IDs in PrestaShop.**
-INSTALLATION
---------
+> If you fork, please make every change the way we can pull, don't reinvent the wheel .. make every custom change on a private branch, so you can merge your own changes to the community mantained branch every time a new release is out.
+>
+> - For production use the **latest stable [release](https://github.com/faktiva/prestashop-clean-urls/releases/latest)**
+> - For developing or Pull Request please use only the "**[dev](https://github.com/faktiva/prestashop-clean-urls/tree/dev)**" branch
+>
+> It has been reported to work on **PS 1.5.6 - 1.6.1.x** but will install on PS >= 1.5 too.
+> **If you succesfully use this module on some older version please report**
-Install the module from the Backoffice (administration panel)
-In the modules tab, click on add a new module. Click on Browse to open the dialogue box letting you search your computer, select the file then validate the dialogue box. Finally click on Upload this module.
+# INSTALLATION
+## from _PS administration panel_
-UNINSTALLATION
---------
+Go in the back office of your shop and follow these steps:
+ - download the [lastest release](https://github.com/faktiva/prestashop-clean-urls/releases/latest) **_ZIP_ file** (**_`faktiva_clean_urls.zip`_**) as it already contains the right folder name (`faktiva_clean_urls`, **not** `faktiva-prestashop-clean-urls-version_x.y.z` !)
+ - in the modules tab, click on **`add a new module`**
+ - click on **"`Browse`"** to open the dialogue box letting you search your computer
+ - select the ZIP file you downloaded and validate the dialogue box
+ - click on "**`Upload this module`**"
+ - once uploaded, you could have to search the module among the others (_tip: filter by author "**`faktiva`**"_) and click on the **`install`** button
-Go to modules -> Find and uninstall "CleanURL".
+# Configuration & Checks
-Open folder /override/classes/
--> Remove "Link.php"
--> Remove "Dispatcher.php"
+**Make sure your _`SEO and URL`_ settings are as follows:**
-Open folder /override/controllers/front/
--> Remove "CategoryController.php"
--> Remove "CmsController.php"
--> Remove "ManufacturerController.php"
--> Remove "ProductController.php"
--> Remove "SupplierController.php"
+This is **MANDATORY**
+ - products: {category:/}{rewrite} (you **can** add .html at the end)
+ - categories: {categories:/}{rewrite}**/**
+ - manufacturers: manufactures/{rewrite}
+ - suppliers: suppliers/{rewrite}
+ - CMS page: info/{rewrite} (you **can** add .html at the end)
+ - CMS category: info/{rewrite}**/**
+ - modules: modules/{module}{/:controller}
-Open folder /cache/
--> Remove "class_index.php"
+_You can replace words such as "info", "suppliers", etc with whatever you want, given that it does not conflicts with a category name_
+
+**Remember to**
+ - clear the **browser cache**
+ - clear **PS cache** (under smarty -> cache and smarty -> compile)
+
+# UNINSTALLATION
+
+* Go to modules -> Find and uninstall "**faktiva_clean_urls**"
+
+**It should suffice!**
+
+
+If something goes wrong do the following:
+ - Open folder **`/override/classes/`**
+ - Remove **`Link.php`**
+ - Remove **`Dispatcher.php`**
+ - Open folder **`/override/controllers/front/`**
+ - Remove **`CategoryController.php`**
+ - Remove **`CmsController.php`**
+ - Remove **`ManufacturerController.php`**
+ - Remove **`ProductController.php`**
+ - Remove **`SupplierController.php`**
+ - Open folder **`/cache/`**
+ - Remove **`class_index.php`**
+ - Go to **`back office`** -> **`Preferences`** -> **`SEO and URLs`** -> Set **`userfriendly URL`** off -> **`Save`**
+ - Go to **`back office`** -> **`Preferences`** -> **`SEO and URLs`** -> Set **`userfriendly URL`** on -> **`Save`**
-Go to back office -> Preferences -> SEO and URLs -> Set userfriendly URL off -> Save
-Go to back office -> Preferences -> SEO and URLs -> Set userfriendly URL on -> Save
If you got any other override modules, you should now go to you back office, uninstall them, and reinstall them again to work correctly.
+# License
+
+
+
+
+**[PrestaShop Clean URLs](https://github.com/faktiva/prestashop-clean-urls)** by [Faktiva](https://github.com/faktiva) is licensed under a **Creative Commons [Attribution-ShareAlike](http://creativecommons.org/licenses/by-sa/4.0/) 4.0 International License**.
+
+Permissions beyond the scope of this license may be available contacting us at info@faktiva.com.
+
diff --git a/cleanurls/PRTSC_Preferences_SEO_URLs.png b/cleanurls/PRTSC_Preferences_SEO_URLs.png
deleted file mode 100644
index 9cb8dfc..0000000
Binary files a/cleanurls/PRTSC_Preferences_SEO_URLs.png and /dev/null differ
diff --git a/cleanurls/cleanurls.php b/cleanurls/cleanurls.php
deleted file mode 100644
index 96df801..0000000
--- a/cleanurls/cleanurls.php
+++ /dev/null
@@ -1,120 +0,0 @@
-
-* @copyright 2012-2013 Ha!*!*y
-* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
-* @code sorce: http://prestashop.com
-*/
-
-class cleanurls extends Module
-{
- public function __construct()
- {
- $this->name = 'cleanurls';
- $this->tab = 'seo';
- $this->version = '0.42.1';
- $this->need_instance = 0;
- $this->author = 'ha!*!*y';
-
- parent::__construct();
-
- $this->displayName = $this->l('Clean URLs');
- $this->description = $this->l('This override-Module allows you to remove URL ID\'s.');
- }
-
- public function getContent()
- {
- $output = '';
-
- $output .= '
- On some versions you have to disable Cache save than open your shop home page than go back and enable it.
- Advanced Parameters > Performance > Clear Smarty cache
- Go to back office -> Preferences -> SEO and URLs -> Set userfriendly URL off -> Save
- Go to back office -> Preferences -> SEO and URLs -> Set userfriendly URL on -> Save
-
';
-
- $sql = 'SELECT * FROM `'._DB_PREFIX_.'product_lang`
- WHERE `link_rewrite`
- IN (SELECT `link_rewrite` FROM `'._DB_PREFIX_.'product_lang`
- GROUP BY `link_rewrite`, `id_lang`
- HAVING count(`link_rewrite`) > 1)';
-
- if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP)
- {
- $sql .= ' AND `id_shop` = '.(int)Shop::getContextShopID();
- }
-
- if ($results = (int)Db::getInstance()->ExecuteS($sql))
- {
- $output .= 'You need to fix duplicate URL entries
';
- foreach ($results AS $row)
- {
- $language_info = $this->context->language->getLanguage($row['id_lang']);
- $output .= $row['name'].' ('.$row['id_product'] .') - '. $row['link_rewrite'].'
';
- $shop_info = $this->context->shop->getShop($language_info['id_shop']);
- $output .= 'Language:'. $language_info['name'] . '
Shop:' . $shop_info['name'].'
';
- }
- }
- else
- {
- $output .= 'Nice you don\'t have any duplicate URL entries.';
- }
-
- return $output;
- }
-
- function checkWritable($directories)
- {
- foreach ($directories as $dir) {
- if (!file_exists(_PS_ROOT_DIR_ . "/" . $dir) &&
- strpos($dir, "override/", 0) === 0 &&
- !copy(_PS_ROOT_DIR_ ."/modules/cleanurls/empty_".$dir, _PS_ROOT_DIR_ . "/" . $dir))
- return false;
- if (!is_writable(_PS_ROOT_DIR_ . "/" . $dir))
- return false;
- }
- return true;
- }
-
- public function install()
- {
-
- if (!$this->checkWritable(array("override/classes/Dispatcher.php", "override/classes/Link.php",
- "override/controllers/front/CategoryController.php", "override/controllers/front/CmsController.php", "override/controllers/front/ManufacturerController.php","override/controllers/front/ProductController.php"),"override/controllers/front/SupplierController.php")
- ) {
- $this->_errors[] = $this->l('Files in /override folder are not writable, these files need to be writable: classes: Dispatcher.php, Link.php; controllers/front: CategoryController.php, CmsController.php, ManufacturerController.php, ProductController.php, SupplierController.php');
- return false;
- }
- // add link_rewrite as index to improve search
- $table_list = array('category_lang','cms_category_lang','cms_lang','product_lang');
- foreach($table_list as $table)
- {
- if(!Db::getInstance()->ExecuteS('SHOW INDEX FROM `'._DB_PREFIX_.$table.'` WHERE Key_name = \'link_rewrite\''))
- Db::getInstance()->Execute('ALTER TABLE `'._DB_PREFIX_.$table.'` ADD INDEX ( `link_rewrite` )');
- }
-
- if (!parent::install())
- return false;
- return true;
- }
-
- public function uninstall()
- {
- copy(_PS_ROOT_DIR_ ."/modules/cleanurls/empty_override/classes/Dispatcher.php", _PS_ROOT_DIR_ . "/override/classes/Dispatcher.php");
- if (!parent::uninstall())
- return false;
- return true;
- }
-}
diff --git a/cleanurls/config.xml b/cleanurls/config.xml
deleted file mode 100644
index 4e546bc..0000000
--- a/cleanurls/config.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- cleanurls
-
-
-
-
-
- 1
- 0
-
-
\ No newline at end of file
diff --git a/cleanurls/empty_override/classes/Dispatcher.php b/cleanurls/empty_override/classes/Dispatcher.php
deleted file mode 100644
index 4cd11a4..0000000
--- a/cleanurls/empty_override/classes/Dispatcher.php
+++ /dev/null
@@ -1,4 +0,0 @@
-
-* @copyright 2012-2013 Ha!*!*y
-* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
-* @code sorce: http://prestashop.com
-*/
-
-header("Expires: Fri, 31 Dec 1999 23:59:59 GMT");
-header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
-
-header("Cache-Control: no-store, no-cache, must-revalidate");
-header("Cache-Control: post-check=0, pre-check=0", false);
-header("Pragma: no-cache");
-
-header("Location: ../");
-exit;
\ No newline at end of file
diff --git a/cleanurls/logo.gif b/cleanurls/logo.gif
deleted file mode 100644
index 9ea90ff..0000000
Binary files a/cleanurls/logo.gif and /dev/null differ
diff --git a/cleanurls/logo.png b/cleanurls/logo.png
deleted file mode 100644
index b0c35b5..0000000
Binary files a/cleanurls/logo.png and /dev/null differ
diff --git a/cleanurls/override/classes/Dispatcher.php b/cleanurls/override/classes/Dispatcher.php
deleted file mode 100644
index 8dc83a4..0000000
--- a/cleanurls/override/classes/Dispatcher.php
+++ /dev/null
@@ -1,387 +0,0 @@
- array(
- 'controller' => 'supplier',
- 'rule' => 'supplier/{rewrite}/',
- 'keywords' => array(
- 'id' => array('regexp' => '[0-9]+'),
- 'rewrite' => array('regexp' => '[_a-zA-Z0-9-\pL]*', 'param' => 'supplier_rewrite'),
- 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- ),
- ),
- 'manufacturer_rule' => array(
- 'controller' => 'manufacturer',
- 'rule' => 'manufacturer/{rewrite}/',
- 'keywords' => array(
- 'id' => array('regexp' => '[0-9]+'),
- 'rewrite' => array('regexp' => '[_a-zA-Z0-9-\pL]*', 'param' => 'manufacturer_rewrite'),
- 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- ),
- ),
- 'cms_rule' => array(
- 'controller' => 'cms',
- 'rule' => 'info/{rewrite}',
- 'keywords' => array(
- 'id' => array('regexp' => '[0-9]+'),
- 'rewrite' => array('regexp' => '[_a-zA-Z0-9-\pL]*', 'param' => 'cms_rewrite'),
- 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- ),
- ),
- 'cms_category_rule' => array(
- 'controller' => 'cms',
- 'rule' => 'info/{rewrite}/',
- 'keywords' => array(
- 'id' => array('regexp' => '[0-9]+'),
- 'rewrite' => array('regexp' => '[_a-zA-Z0-9-\pL]*', 'param' => 'cms_category_rewrite'),
- 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- ),
- ),
- 'module' => array(
- 'controller' => null,
- 'rule' => 'module/{module}{/:controller}',
- 'keywords' => array(
- 'module' => array('regexp' => '[_a-zA-Z0-9_-]+', 'param' => 'module'),
- 'controller' => array('regexp' => '[_a-zA-Z0-9_-]+', 'param' => 'controller'),
- ),
- 'params' => array(
- 'fc' => 'module',
- ),
- ),
- 'product_rule' => array(
- 'controller' => 'product',
- 'rule' => '{category:/}{rewrite}.html',
- 'keywords' => array(
- 'id' => array('regexp' => '[0-9]+'),
- 'rewrite' => array('regexp' => '[_a-zA-Z0-9-\pL]*', 'param' => 'product_rewrite'),
- 'ean13' => array('regexp' => '[0-9\pL]*'),
- 'category' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- 'categories' => array('regexp' => '[/_a-zA-Z0-9-\pL]*'),
- 'reference' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- 'manufacturer' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- 'supplier' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- 'price' => array('regexp' => '[0-9\.,]*'),
- 'tags' => array('regexp' => '[a-zA-Z0-9-\pL]*'),
- ),
- ),
- 'layered_rule' => array(
- 'controller' => 'category',
- 'rule' => '{rewrite}/filter{selected_filters}',
- 'keywords' => array(
- 'id' => array('regexp' => '[0-9]+'),
- /* Selected filters is used by the module blocklayered */
- 'selected_filters' => array('regexp' => '.*', 'param' => 'selected_filters'),
- 'rewrite' => array('regexp' => '[_a-zA-Z0-9-\pL]*', 'param' => 'category_rewrite'),
- 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- ),
- ),
- 'category_rule' => array(
- 'controller' => 'category',
- 'rule' => '{parent_categories:/}{rewrite}/',
- 'keywords' => array(
- 'id' => array('regexp' => '[0-9]+'),
- 'rewrite' => array('regexp' => '[_a-zA-Z0-9-\pL]*', 'param' => 'category_rewrite'),
- 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
- 'parent_categories' => array('regexp' => '[/_a-zA-Z0-9-\pL]*'),
- ),
- ),
- );
-
- /**
- * Check if $short_link is a Product Link
- *
- * @param string $short_link: requested url without '?' part and without '/' on begining
- * @return bool true: it's a link to product, false: it isn't
- */
- public static function isProductLink($short_link)
- {
- $sql = 'SELECT `id_product`
- FROM `'._DB_PREFIX_.'product_lang`
- WHERE `link_rewrite` = \''.$short_link.'\' AND `id_lang` = '. Context::getContext()->language->id;
-
- if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP)
- {
- $sql .= ' AND `id_shop` = '.(int)Shop::getContextShopID();
- }
-
- $id_product = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
-
- return ($id_product > 0) ? true : false;
- }
-
- /**
- * Check if $short_link is a Category Link
- *
- * @param string $short_link: requested url without '?' part and without '/' on begining
- * @return bool true: it's a link to category, false: it isn't
- */
- public static function isCategoryLink($short_link)
- {
- // check if parent categories
- $categories = explode("/", $short_link);
-
- $sql = 'SELECT `id_category` FROM `'._DB_PREFIX_.'category_lang`
- WHERE `link_rewrite` = \''.$categories[0].'\' AND `id_lang` = '. Context::getContext()->language->id;
-
- if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP)
- {
- $sql .= ' AND `id_shop` = '.(int)Shop::getContextShopID();
- }
-
- $id_category = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
-
- return ($id_category > 0) ? true : false;
- }
-
- /**
- * Check if $short_link is a Cms Link
- *
- * @param string $short_link: requested url without '?' part and without '/' on begining
- * @return bool true: it's a link to cms page, false: it isn't
- */
- public static function isCmsLink($short_link)
- {
- $sql = 'SELECT l.`id_cms`
- FROM `'._DB_PREFIX_.'cms_lang` l
- LEFT JOIN `'._DB_PREFIX_.'cms_shop` s ON (l.`id_cms` = s.`id_cms`)
- WHERE l.`link_rewrite` = \''.$short_link.'\'';
-
- if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP)
- {
- $sql .= ' AND s.`id_shop` = '.(int)Shop::getContextShopID();
- }
-
- $id_cms = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
-
- return ($id_cms > 0) ? true : false;
- }
-
- /**
- * Check if $short_link is a Manufacturer Link
- *
- * @param string $short_link: requested url without '?' part and without '/' on begining
- * @return bool true: it's a link to manufacturer, false: it isn't
- */
- public static function isManufacturerLink($short_link)
- {
- $name_manufacturer = str_replace('-', '%', $short_link);
-
- $sql = 'SELECT m.`id_manufacturer`
- FROM `'._DB_PREFIX_.'manufacturer` m
- LEFT JOIN `'._DB_PREFIX_.'manufacturer_shop` s ON (m.`id_manufacturer` = s.`id_manufacturer`)
- WHERE m.`name` LIKE \''.$name_manufacturer.'\'';
-
- if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP)
- {
- $sql .= ' AND s.`id_shop` = '.(int)Shop::getContextShopID();
- }
-
- $id_manufacturer = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
-
- return ($id_manufacturer > 0) ? true : false;
- }
-
- /**
- * Check if $short_link is a Supplier Link
- *
- * @param string $short_link: requested url without '?' part and without '/' on begining
- * @return bool true: it's a link to supplier, false: it isn't
- */
- public static function isSupplierLink($short_link)
- {
- $name_supplier = str_replace('-', '%', $short_link);
-
- $sql = 'SELECT sp.`id_supplier`
- FROM `'._DB_PREFIX_.'supplier` sp
- LEFT JOIN `'._DB_PREFIX_.'supplier_shop` s ON (sp.`id_supplier` = s.`id_supplier`)
- WHERE sp.`name` LIKE \''.$name_supplier.'\'';
-
- if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP)
- {
- $sql .= ' AND s.`id_shop` = '.(int)Shop::getContextShopID();
- }
-
- $id_supplier = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
-
- return ($id_supplier > 0) ? true : false;
- }
-
- /**
- * Retrieve the controller from url or request uri if routes are activated
- *
- * @return string
- */
- public function getController($id_shop = null)
- {
- if (defined('_PS_ADMIN_DIR_'))
- $_GET['controllerUri'] = Tools::getvalue('controller');
- if ($this->controller)
- {
- $_GET['controller'] = $this->controller;
- return $this->controller;
- }
-
- if ($id_shop === null)
- $id_shop = (int)Context::getContext()->shop->id;
-
- $controller = Tools::getValue('controller');
-
- if (isset($controller) && is_string($controller) && preg_match('/^([0-9a-z_-]+)\?(.*)=(.*)$/Ui', $controller, $m))
- {
- $controller = $m[1];
- if (isset($_GET['controller']))
- $_GET[$m[2]] = $m[3];
- else if (isset($_POST['controller']))
- $_POST[$m[2]] = $m[3];
- }
-
- if (!Validate::isControllerName($controller))
- $controller = false;
-
- // Use routes ? (for url rewriting)
- if ($this->use_routes && !$controller && !defined('_PS_ADMIN_DIR_'))
- {
- if (!$this->request_uri)
- return strtolower($this->controller_not_found);
- $controller = $this->controller_not_found;
-
- // If the request_uri matches a static file, then there is no need to check the routes, we keep "controller_not_found" (a static file should not go through the dispatcher)
- if (!preg_match('/\.(gif|jpe?g|png|css|js|ico)$/i', $this->request_uri))
- {
- // 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'], Context::getContext()->language->id, array(), array(), $id_shop);
-
- if (isset($this->routes[$id_shop][Context::getContext()->language->id]))
- {
-// $firephp = FirePHP::getInstance(true);
- $findRoute = array();
-
- // check, whether request_uri is template or not
- foreach ($this->routes[$id_shop][Context::getContext()->language->id] as $route)
- {
-// $firephp->log($route['rule'], 'Rule');
-
- if (preg_match($route['regexp'], $this->request_uri, $m))
- {
-// $firephp->log('RegExp Pass!');
-
- $isTemplate = false;
-
- switch($route['controller'])
- {
- case 'supplier':
- case 'manufacturer':
- // these two can be processed in normal way and also as template
- if(strpos($route['rule'], '{') !== false)
- {
- $isTemplate = true;
- }
- break;
-
- case 'cms':
- case 'product':
- $isTemplate = true;
- break;
- case 'category':
- // category can be processed in two ways
- if(strpos($route['rule'], 'selected_filters') === false)
- {
- $isTemplate = true;
- }
- break;
- }
-
-// $firephp->log((int)$isTemplate, 'Template');
-
- if($isTemplate == false)
- {
- $findRoute = $route;
- break;
- }
- }
- }
-
- // if route is not found, we have to find rewrite link in database
- if(empty($findRoute))
- {
- $req_url = substr($this->request_uri, 1); // remove '/' from begining
- $req_url = explode("?", $req_url); // remove all after '?'
- $short_link = $req_url[0];
-
-// $firephp->log($short_link, 'Short Link');
-
- if(!Dispatcher::isProductLink($short_link))
- if(!Dispatcher::isCategoryLink($short_link))
- if(!Dispatcher::isCmsLink($short_link))
- if(!Dispatcher::isManufacturerLink($short_link))
- if(!Dispatcher::isSupplierLink($short_link))
- {}
- else
- $findRoute = $this->routes[$id_shop][Context::getContext()->language->id]['supplier_rule'];
- else
- $findRoute = $this->routes[$id_shop][Context::getContext()->language->id]['manufacturer_rule'];
- else
- $findRoute = $this->routes[$id_shop][Context::getContext()->language->id]['cms_rule'];
- else
- $findRoute = $this->routes[$id_shop][Context::getContext()->language->id]['category_rule'];
- else
- $findRoute = $this->routes[$id_shop][Context::getContext()->language->id]['product_rule'];
- }
-
- if(!empty($findRoute))
- {
-// $firephp->log($findRoute['rule'], 'Find Route Template');
-
- if (preg_match($findRoute['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 = $findRoute['controller'] ? $findRoute['controller'] : $_GET['controller'];
- if (!empty($findRoute['params']))
- foreach ($findRoute['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;
- }
- }
- }
- }
-
- if ($controller == 'index' || $this->request_uri == '/index.php')
- $controller = $this->default_controller;
- $this->controller = $controller;
- }
- // Default mode, take controller from url
- else
- $this->controller = $controller;
-
- $this->controller = str_replace('-', '', $this->controller);
- $_GET['controller'] = $this->controller;
- return $this->controller;
- }
-}
\ No newline at end of file
diff --git a/cleanurls/override/classes/Link.php b/cleanurls/override/classes/Link.php
deleted file mode 100644
index 830fd4b..0000000
--- a/cleanurls/override/classes/Link.php
+++ /dev/null
@@ -1,142 +0,0 @@
-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;
- $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) ? '' : $selected_filters;
-
- if (empty($selected_filters))
- $rule = 'category_rule';
- else
- {
- $rule = 'layered_rule';
- $params['selected_filters'] = $selected_filters;
- }
-
-
-
- if ($dispatcher->hasKeyword('category_rule', $id_lang, 'parent_categories'))
- {
- //RETRIEVING ALL THE PARENT CATEGORIES
- $cats = array();
- foreach ($category->getParentsCategories() as $cat)
- if (!in_array($cat['id_category'], array(1, 2, $category->id)))//remove root, home and current category from the URL
- $cats[] = $cat['link_rewrite']; //THE CATEGORIES ARE BEING ASSIGNED IN THE WRONG ORDER (?)
- $params['parent_categories'] = implode('/', array_reverse($cats));//ADD THE URL SLASHES TO THE CATEGORIES IN REVERSE ORDER
- }
-
- return $url.Dispatcher::getInstance()->createUrl($rule, $id_lang, $params, $this->allow);
-
- }
-
-
- /**
- * 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)
- {
- // Ha!*!*y strip var like category_rewrite from url
- if ($k != 'id_'.$type && $k != $type.'_rewrite' && $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)
- if (count($vars))
- return $url.(($this->allow == 1 || $url == $this->url) ? '?' : '&').http_build_query($vars, '', '&');
- else
- return $url;
-
- $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;
- }
-
-}
diff --git a/cleanurls/override/classes/index.php b/cleanurls/override/classes/index.php
deleted file mode 100644
index 1f943d3..0000000
--- a/cleanurls/override/classes/index.php
+++ /dev/null
@@ -1,29 +0,0 @@
-
-* @copyright 2012-2013 Ha!*!*y
-* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
-* @code sorce: http://prestashop.com
-*/
-
-header("Expires: Fri, 31 Dec 1999 23:59:59 GMT");
-header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
-
-header("Cache-Control: no-store, no-cache, must-revalidate");
-header("Cache-Control: post-check=0, pre-check=0", false);
-header("Pragma: no-cache");
-
-header("Location: ../");
-exit;
\ No newline at end of file
diff --git a/cleanurls/override/controllers/front/CategoryController.php b/cleanurls/override/controllers/front/CategoryController.php
deleted file mode 100644
index 1bb1f51..0000000
--- a/cleanurls/override/controllers/front/CategoryController.php
+++ /dev/null
@@ -1,36 +0,0 @@
-language->id;
-
- if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP)
- {
- $sql .= ' AND `id_shop` = '.(int)Shop::getContextShopID();
- }
-
- $id_category = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
-
- if($id_category > 0)
- {
- $_GET['id_category'] = $id_category;
- }
- else
- {
- //TODO: Do we need to send 404?
- header('HTTP/1.1 404 Not Found');
- header('Status: 404 Not Found');
- }
- }
-
- parent::init();
- }
-}
diff --git a/cleanurls/override/controllers/front/CmsController.php b/cleanurls/override/controllers/front/CmsController.php
deleted file mode 100644
index 6061525..0000000
--- a/cleanurls/override/controllers/front/CmsController.php
+++ /dev/null
@@ -1,62 +0,0 @@
-getValue($sql);
-
- if($id_cms > 0)
- {
- $_GET['id_cms'] = $id_cms;
- }
- else
- {
- //TODO: Do we need to send 404?
- header('HTTP/1.1 404 Not Found');
- header('Status: 404 Not Found');
- }
- }
- else if (Tools::getValue('cms_category_rewrite'))
- {
- $rewrite_url = Tools::getValue('cms_category_rewrite');
-
- $sql = 'SELECT `id_cms_category`
- FROM `'._DB_PREFIX_.'cms_category_lang`
- WHERE `link_rewrite` = \''.$rewrite_url.'\'';
-
- if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP)
- {
- $sql .= ' AND s.`id_shop` = '.(int)Shop::getContextShopID();
- }
-
- $id_cms_category = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
-
- if($id_cms_category > 0)
- {
- $_GET['id_cms_category'] = $id_cms_category;
- }
- else
- {
- //TODO: Do we need to send 404?
- header('HTTP/1.1 404 Not Found');
- header('Status: 404 Not Found');
- }
- }
- parent::init();
- }
-}
diff --git a/cleanurls/override/controllers/front/ManufacturerController.php b/cleanurls/override/controllers/front/ManufacturerController.php
deleted file mode 100644
index 0cde4fe..0000000
--- a/cleanurls/override/controllers/front/ManufacturerController.php
+++ /dev/null
@@ -1,42 +0,0 @@
-getValue($sql);
-
- if($id_manufacturer > 0)
- {
- $_GET['id_manufacturer'] = $id_manufacturer;
- $_GET['noredirect'] = 1;
- }
- else
- {
- //TODO: Do we need to send 404?
- header('HTTP/1.1 404 Not Found');
- header('Status: 404 Not Found');
- }
- }
- parent::init();
- }
-}
diff --git a/cleanurls/override/controllers/front/ProductController.php b/cleanurls/override/controllers/front/ProductController.php
deleted file mode 100644
index 17e4dea..0000000
--- a/cleanurls/override/controllers/front/ProductController.php
+++ /dev/null
@@ -1,63 +0,0 @@
-language->id;
-
- if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP)
- {
- $sql .= ' AND `id_shop` = '.(int)Shop::getContextShopID();
- }
-
- $id_product = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
-
- if($id_product > 0)
- {
- $_GET['id_product'] = $id_product;
- }
- else if(preg_match($url_id_pattern, $_SERVER['REQUEST_URI'], $url_split))
- {
- $url_id_product = $url_split[1];
-
- $sql = 'SELECT `id_product`
- FROM `'._DB_PREFIX_.'product_lang`
- WHERE `id_product` = \''.$url_id_product.'\' AND `id_lang` = '. Context::getContext()->language->id;
-
- if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP)
- {
- $sql .= ' AND `id_shop` = '.(int)Shop::getContextShopID();
- }
-
- $id_product = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
-
- if($id_product > 0)
- {
- $_GET['id_product'] = $id_product;
- }
- else
- {
- //TODO: Do we need to send 404?
- header('HTTP/1.1 404 Not Found');
- header('Status: 404 Not Found');
- }
- }
- else
- {
- //TODO: Do we need to send 404?
- header('HTTP/1.1 404 Not Found');
- header('Status: 404 Not Found');
- }
- }
- parent::init();
- }
-}
diff --git a/cleanurls/override/controllers/front/SupplierController.php b/cleanurls/override/controllers/front/SupplierController.php
deleted file mode 100644
index cfdfbaf..0000000
--- a/cleanurls/override/controllers/front/SupplierController.php
+++ /dev/null
@@ -1,42 +0,0 @@
-getValue($sql);
-
- if($id_supplier > 0)
- {
- $_GET['id_supplier'] = $id_supplier;
- }
- else
- {
- //TODO: Do we need to send 404?
- header('HTTP/1.1 404 Not Found');
- header('Status: 404 Not Found');
- }
- }
-
- parent::init();
- }
-}
diff --git a/cleanurls/override/controllers/front/index.php b/cleanurls/override/controllers/front/index.php
deleted file mode 100644
index 1f943d3..0000000
--- a/cleanurls/override/controllers/front/index.php
+++ /dev/null
@@ -1,29 +0,0 @@
-
-* @copyright 2012-2013 Ha!*!*y
-* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
-* @code sorce: http://prestashop.com
-*/
-
-header("Expires: Fri, 31 Dec 1999 23:59:59 GMT");
-header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
-
-header("Cache-Control: no-store, no-cache, must-revalidate");
-header("Cache-Control: post-check=0, pre-check=0", false);
-header("Pragma: no-cache");
-
-header("Location: ../");
-exit;
\ No newline at end of file
diff --git a/cleanurls/override/controllers/index.php b/cleanurls/override/controllers/index.php
deleted file mode 100644
index 1f943d3..0000000
--- a/cleanurls/override/controllers/index.php
+++ /dev/null
@@ -1,29 +0,0 @@
-
-* @copyright 2012-2013 Ha!*!*y
-* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
-* @code sorce: http://prestashop.com
-*/
-
-header("Expires: Fri, 31 Dec 1999 23:59:59 GMT");
-header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
-
-header("Cache-Control: no-store, no-cache, must-revalidate");
-header("Cache-Control: post-check=0, pre-check=0", false);
-header("Pragma: no-cache");
-
-header("Location: ../");
-exit;
\ No newline at end of file
diff --git a/cleanurls/override/index.php b/cleanurls/override/index.php
deleted file mode 100644
index 1f943d3..0000000
--- a/cleanurls/override/index.php
+++ /dev/null
@@ -1,29 +0,0 @@
-
-* @copyright 2012-2013 Ha!*!*y
-* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
-* @code sorce: http://prestashop.com
-*/
-
-header("Expires: Fri, 31 Dec 1999 23:59:59 GMT");
-header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
-
-header("Cache-Control: no-store, no-cache, must-revalidate");
-header("Cache-Control: post-check=0, pre-check=0", false);
-header("Pragma: no-cache");
-
-header("Location: ../");
-exit;
\ No newline at end of file
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..a92ee85
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,56 @@
+{
+ "name": "faktiva/prestashop-clean-urls",
+ "description": "Prestashop\"Clean URLs\" module. It removes objects' IDs from URLs.",
+ "homepage": "https://github.com/faktiva/prestashop-clean-urls",
+ "license": "CC-BY-SA-4.0",
+ "type": "prestashop-module",
+ "authors": [
+ {
+ "name": "AlberT",
+ "email": "albert@faktiva.com"
+ }
+ ],
+
+ "minimum-stability": "stable",
+ "config": {
+ "bin-dir": "bin",
+ "github-protocols": ["https"],
+ "archive-format": "zip",
+ "preferred-install": "dist",
+ "optimize-autoloader": true
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^1.12",
+ "symfony/var-dumper": "^2.8||^3.0",
+ "symfony/debug": "^2.8||^3.0",
+ "sensiolabs/security-checker": "^4.0"
+ },
+ "require": {
+ "php": ">=5.2"
+ },
+ "replace": {
+ "zizuu-store/zzcleanurls": "*"
+ },
+ "scripts": {
+ "chk-cs": [
+ "php-cs-fixer -vvv fix --dry-run"
+ ],
+ "chk-sec": [
+ "php bin/security-checker -vv security:check"
+ ],
+ "check": [
+ "@chk-cs",
+ "@chk-sec"
+ ],
+ "fix-cs": [
+ "php-cs-fixer -vvv fix ; exit 0"
+ ],
+ "zip": [
+ "@composer archive -vvv -f zip",
+ "php -r 'rename(@array_shift(glob(\"faktiva-prestashop-clean-urls-*.zip\")), \"faktiva_clean_urls.zip\");'"
+ ]
+ },
+ "archive": {
+ "exclude": [".*", "/composer.*", "/vendor", "*.zip", "*.tar", "*.md", "/*.jpg" ]
+ }
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..286ac60
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,718 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+ "This file is @generated automatically"
+ ],
+ "hash": "1b802d7b0d5a0eb4106ef15c86c5d046",
+ "content-hash": "07bff411abf84b026b6f0fb44b00a343",
+ "packages": [],
+ "packages-dev": [
+ {
+ "name": "friendsofphp/php-cs-fixer",
+ "version": "v1.12.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
+ "reference": "baa7112bef3b86c65fcfaae9a7a50436e3902b41"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/baa7112bef3b86c65fcfaae9a7a50436e3902b41",
+ "reference": "baa7112bef3b86c65fcfaae9a7a50436e3902b41",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "php": "^5.3.6 || >=7.0 <7.2",
+ "sebastian/diff": "^1.1",
+ "symfony/console": "^2.3 || ^3.0",
+ "symfony/event-dispatcher": "^2.1 || ^3.0",
+ "symfony/filesystem": "^2.1 || ^3.0",
+ "symfony/finder": "^2.1 || ^3.0",
+ "symfony/process": "^2.3 || ^3.0",
+ "symfony/stopwatch": "^2.5 || ^3.0"
+ },
+ "conflict": {
+ "hhvm": "<3.9"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.5|^5",
+ "satooshi/php-coveralls": "^1.0"
+ },
+ "bin": [
+ "php-cs-fixer"
+ ],
+ "type": "application",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\CS\\": "Symfony/CS/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Dariusz RumiĆski",
+ "email": "dariusz.ruminski@gmail.com"
+ },
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "description": "A tool to automatically fix PHP code style",
+ "time": "2016-09-27 07:57:59"
+ },
+ {
+ "name": "psr/log",
+ "version": "1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "time": "2016-10-10 12:19:37"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "1.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
+ "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "https://github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff"
+ ],
+ "time": "2015-12-08 07:14:41"
+ },
+ {
+ "name": "sensiolabs/security-checker",
+ "version": "v4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sensiolabs/security-checker.git",
+ "reference": "116027b57b568ed61b7b1c80eeb4f6ee9e8c599c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sensiolabs/security-checker/zipball/116027b57b568ed61b7b1c80eeb4f6ee9e8c599c",
+ "reference": "116027b57b568ed61b7b1c80eeb4f6ee9e8c599c",
+ "shasum": ""
+ },
+ "require": {
+ "symfony/console": "~2.7|~3.0"
+ },
+ "bin": [
+ "security-checker"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "SensioLabs\\Security": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien.potencier@gmail.com"
+ }
+ ],
+ "description": "A security checker for your composer.lock",
+ "time": "2016-09-23 18:09:57"
+ },
+ {
+ "name": "symfony/console",
+ "version": "v3.1.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/console.git",
+ "reference": "6cb0872fb57b38b3b09ff213c21ed693956b9eb0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/console/zipball/6cb0872fb57b38b3b09ff213c21ed693956b9eb0",
+ "reference": "6cb0872fb57b38b3b09ff213c21ed693956b9eb0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.9",
+ "symfony/debug": "~2.8|~3.0",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/event-dispatcher": "~2.8|~3.0",
+ "symfony/process": "~2.8|~3.0"
+ },
+ "suggest": {
+ "psr/log": "For using the console logger",
+ "symfony/event-dispatcher": "",
+ "symfony/process": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Console\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Console Component",
+ "homepage": "https://symfony.com",
+ "time": "2016-09-28 00:11:12"
+ },
+ {
+ "name": "symfony/debug",
+ "version": "v3.1.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/debug.git",
+ "reference": "e2b3f74a67fc928adc3c1b9027f73e1bc01190a8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/e2b3f74a67fc928adc3c1b9027f73e1bc01190a8",
+ "reference": "e2b3f74a67fc928adc3c1b9027f73e1bc01190a8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.9",
+ "psr/log": "~1.0"
+ },
+ "conflict": {
+ "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
+ },
+ "require-dev": {
+ "symfony/class-loader": "~2.8|~3.0",
+ "symfony/http-kernel": "~2.8|~3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Debug\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Debug Component",
+ "homepage": "https://symfony.com",
+ "time": "2016-09-06 11:02:40"
+ },
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "v3.1.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher.git",
+ "reference": "c0c00c80b3a69132c4e55c3e7db32b4a387615e5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c0c00c80b3a69132c4e55c3e7db32b4a387615e5",
+ "reference": "c0c00c80b3a69132c4e55c3e7db32b4a387615e5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.9"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/config": "~2.8|~3.0",
+ "symfony/dependency-injection": "~2.8|~3.0",
+ "symfony/expression-language": "~2.8|~3.0",
+ "symfony/stopwatch": "~2.8|~3.0"
+ },
+ "suggest": {
+ "symfony/dependency-injection": "",
+ "symfony/http-kernel": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\EventDispatcher\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony EventDispatcher Component",
+ "homepage": "https://symfony.com",
+ "time": "2016-07-19 10:45:57"
+ },
+ {
+ "name": "symfony/filesystem",
+ "version": "v3.1.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/filesystem.git",
+ "reference": "682fd8fdb3135fdf05fc496a01579ccf6c85c0e5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/682fd8fdb3135fdf05fc496a01579ccf6c85c0e5",
+ "reference": "682fd8fdb3135fdf05fc496a01579ccf6c85c0e5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Filesystem\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Filesystem Component",
+ "homepage": "https://symfony.com",
+ "time": "2016-09-14 00:18:46"
+ },
+ {
+ "name": "symfony/finder",
+ "version": "v3.1.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/finder.git",
+ "reference": "205b5ffbb518a98ba2ae60a52656c4a31ab00c6f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/205b5ffbb518a98ba2ae60a52656c4a31ab00c6f",
+ "reference": "205b5ffbb518a98ba2ae60a52656c4a31ab00c6f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Finder\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Finder Component",
+ "homepage": "https://symfony.com",
+ "time": "2016-09-28 00:11:12"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "dff51f72b0706335131b00a7f49606168c582594"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594",
+ "reference": "dff51f72b0706335131b00a7f49606168c582594",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "time": "2016-05-18 14:26:46"
+ },
+ {
+ "name": "symfony/process",
+ "version": "v3.1.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/process.git",
+ "reference": "66de154ae86b1a07001da9fbffd620206e4faf94"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/process/zipball/66de154ae86b1a07001da9fbffd620206e4faf94",
+ "reference": "66de154ae86b1a07001da9fbffd620206e4faf94",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Process\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Process Component",
+ "homepage": "https://symfony.com",
+ "time": "2016-09-29 14:13:09"
+ },
+ {
+ "name": "symfony/stopwatch",
+ "version": "v3.1.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/stopwatch.git",
+ "reference": "bb42806b12c5f89db4ebf64af6741afe6d8457e1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/stopwatch/zipball/bb42806b12c5f89db4ebf64af6741afe6d8457e1",
+ "reference": "bb42806b12c5f89db4ebf64af6741afe6d8457e1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Stopwatch\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Stopwatch Component",
+ "homepage": "https://symfony.com",
+ "time": "2016-06-29 05:41:56"
+ },
+ {
+ "name": "symfony/var-dumper",
+ "version": "v3.1.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/var-dumper.git",
+ "reference": "70bfe927b86ba9999aeebd829715b0bb2cd39a10"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/70bfe927b86ba9999aeebd829715b0bb2cd39a10",
+ "reference": "70bfe927b86ba9999aeebd829715b0bb2cd39a10",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.9",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "require-dev": {
+ "twig/twig": "~1.20|~2.0"
+ },
+ "suggest": {
+ "ext-symfony_debug": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "Resources/functions/dump.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\VarDumper\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony mechanism for exploring and dumping PHP variables",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "debug",
+ "dump"
+ ],
+ "time": "2016-09-29 14:13:09"
+ }
+ ],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": {
+ "php": ">=5.2"
+ },
+ "platform-dev": []
+}
diff --git a/faktiva_clean_urls/config.xml b/faktiva_clean_urls/config.xml
new file mode 100644
index 0000000..8ea9912
--- /dev/null
+++ b/faktiva_clean_urls/config.xml
@@ -0,0 +1,13 @@
+
+
+ faktiva_clean_urls
+
+
+
+
+
+
+ 1
+ 0
+
+
diff --git a/faktiva_clean_urls/faktiva_clean_urls.php b/faktiva_clean_urls/faktiva_clean_urls.php
new file mode 100644
index 0000000..95d6b04
--- /dev/null
+++ b/faktiva_clean_urls/faktiva_clean_urls.php
@@ -0,0 +1,111 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+if (!defined('_PS_VERSION_')) {
+ return;
+}
+
+// Set true to enable debugging
+define('FKV_DEBUG', false);
+
+if (version_compare(phpversion(), '5.3.0', '>=')) { // Namespaces support is required
+ include_once __DIR__.'/tools/debug.php';
+}
+
+class faktiva_clean_urls extends Module
+{
+ public function __construct()
+ {
+ $this->name = 'faktiva_clean_urls';
+ $this->tab = 'seo';
+ $this->version = '1.1.1';
+ $this->author = 'Faktiva';
+ $this->need_instance = 0;
+ $this->ps_versions_compliancy = array('min' => '1.5', 'max' => _PS_VERSION_);
+ $this->bootstrap = true;
+
+ parent::__construct();
+
+ $this->displayName = $this->l('Faktiva Clean URLs');
+ $this->description = $this->l('This override-Module allows you to remove URL ID\'s.');
+
+ $this->confirmUninstall = $this->l('Are you sure you want to uninstall "Faktiva Clean URLs" module?');
+ }
+
+ public function getContent()
+ {
+ $output = ''
+ .$this->l('On some versions you could have to disable Cache, save, open your shop home page, than go back and enable it:').'
'
+ .sprintf('%s -> %s -> %s', $this->l('Advanced Parameters'), $this->l('Performance'), $this->l('Clear Smarty cache')).'
'
+ .sprintf('%s -> %s -> %s -> %s', $this->l('Preferences'), $this->l('SEO and URLs'), $this->l('Set userfriendly URL off'), $this->l('Save')).'
'
+ .sprintf('%s -> %s -> %s -> %s', $this->l('Preferences'), $this->l('SEO and URLs'), $this->l('Set userfriendly URL on'), $this->l('Save')).'
'
+ .'
';
+
+ $sql = 'SELECT * FROM `'._DB_PREFIX_.'product_lang`
+ WHERE `link_rewrite`
+ IN (SELECT `link_rewrite` FROM `'._DB_PREFIX_.'product_lang`
+ GROUP BY `link_rewrite`, `id_lang`
+ HAVING count(`link_rewrite`) > 1)';
+ if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) {
+ $sql .= ' AND `id_shop` = '.(int) Shop::getContextShopID();
+ }
+
+ if ($res = Db::getInstance()->ExecuteS($sql)) {
+ $err = $this->l('You need to fix duplicate URL entries:').'
';
+ foreach ($res as $row) {
+ $lang = $this->context->language->getLanguage($row['id_lang']);
+ $err .= $row['name'].' ('.$row['id_product'].') - '.$row['link_rewrite'].'
';
+
+ $shop = $this->context->shop->getShop($lang['id_shop']);
+ $err .= $this->l('Language: ').$lang['name'].'
'.$this->l('Shop: ').$shop['name'].'
';
+ }
+ $output .= $this->displayWarning($err);
+ } else {
+ $output .= $this->displayConfirmation($this->l('Nice. You have no duplicate URL entry.'));
+ }
+
+ return ''.$output.'
';
+ }
+
+ public function install()
+ {
+ // add link_rewrite as index to improve search
+ foreach (array('category_lang', 'cms_category_lang', 'cms_lang', 'product_lang') as $tab) {
+ if (!Db::getInstance()->ExecuteS('SHOW INDEX FROM `'._DB_PREFIX_.$tab.'` WHERE Key_name = \'link_rewrite\'')) {
+ Db::getInstance()->Execute('ALTER TABLE `'._DB_PREFIX_.$tab.'` ADD INDEX ( `link_rewrite` )');
+ }
+ }
+
+ if (!parent::install()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public function uninstall()
+ {
+ if (!parent::uninstall()) {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/faktiva_clean_urls/index.php b/faktiva_clean_urls/index.php
new file mode 100644
index 0000000..5bbd579
--- /dev/null
+++ b/faktiva_clean_urls/index.php
@@ -0,0 +1,30 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+header('Expires: Fri, 31 Dec 1999 23:59:59 GMT');
+header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
+
+header('Cache-Control: no-store, no-cache, must-revalidate');
+header('Cache-Control: post-check=0, pre-check=0', false);
+header('Pragma: no-cache');
+
+header('Location: ../');
+
+return;
diff --git a/faktiva_clean_urls/logo.gif b/faktiva_clean_urls/logo.gif
new file mode 100644
index 0000000..54b3a2c
Binary files /dev/null and b/faktiva_clean_urls/logo.gif differ
diff --git a/faktiva_clean_urls/logo.png b/faktiva_clean_urls/logo.png
new file mode 100644
index 0000000..696efd1
Binary files /dev/null and b/faktiva_clean_urls/logo.png differ
diff --git a/faktiva_clean_urls/override/classes/Dispatcher.php b/faktiva_clean_urls/override/classes/Dispatcher.php
new file mode 100644
index 0000000..ab08f95
--- /dev/null
+++ b/faktiva_clean_urls/override/classes/Dispatcher.php
@@ -0,0 +1,554 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+class Dispatcher extends DispatcherCore
+{
+ /**
+ * Load default routes group by languages.
+ */
+ protected function loadRoutes($id_shop = null)
+ {
+ /*
+ * @var array List of default routes
+ */
+ $this->default_routes = array(
+ 'category_rule' => array(
+ 'controller' => 'category',
+ 'rule' => '{rewrite}/',
+ 'keywords' => array(
+ 'id' => array('regexp' => '[0-9]+'),
+ 'categories' => array('regexp' => '[/_a-zA-Z0-9\pL\pS-]*'),
+ 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*', 'param' => 'category_rewrite'),
+ 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ 'meta_title' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ ),
+ ),
+ 'supplier_rule' => array(
+ 'controller' => 'supplier',
+ 'rule' => 'supplier/{rewrite}',
+ 'keywords' => array(
+ 'id' => array('regexp' => '[0-9]+'),
+ 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*', 'param' => 'supplier_rewrite'),
+ 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ 'meta_title' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ ),
+ ),
+ 'manufacturer_rule' => array(
+ 'controller' => 'manufacturer',
+ 'rule' => 'manufacturer/{rewrite}',
+ 'keywords' => array(
+ 'id' => array('regexp' => '[0-9]+'),
+ 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*', 'param' => 'manufacturer_rewrite'),
+ 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ 'meta_title' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ ),
+ ),
+ 'cms_rule' => array(
+ 'controller' => 'cms',
+ 'rule' => 'info/{rewrite}',
+ 'keywords' => array(
+ 'id' => array('regexp' => '[0-9]+'),
+ 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*', 'param' => 'cms_rewrite'),
+ 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ 'meta_title' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ ),
+ ),
+ 'cms_category_rule' => array(
+ 'controller' => 'cms',
+ 'rule' => 'info/{rewrite}/',
+ 'keywords' => array(
+ 'id' => array('regexp' => '[0-9]+'),
+ 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*', 'param' => 'cms_category_rewrite'),
+ 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ 'meta_title' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ ),
+ ),
+ 'module' => array(
+ 'controller' => null,
+ 'rule' => 'module/{module}/{controller}',
+ 'keywords' => array(
+ 'module' => array('regexp' => '[_a-zA-Z0-9-]+', 'param' => 'module'),
+ 'controller' => array('regexp' => '[_a-zA-Z0-9-]+', 'param' => 'controller'),
+ ),
+ 'params' => array(
+ 'fc' => 'module',
+ ),
+ ),
+ 'product_rule' => array(
+ 'controller' => 'product',
+ 'rule' => '{category:/}{rewrite}',
+ 'keywords' => array(
+ 'id' => array('regexp' => '[0-9]+'),
+ 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*', 'param' => 'product_rewrite'),
+ 'ean13' => array('regexp' => '[0-9]{8,17}'),
+ 'category' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ 'categories' => array('regexp' => '[/_a-zA-Z0-9\pL-]*'),
+ 'reference' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ 'meta_title' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ 'manufacturer' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ 'supplier' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ 'price' => array('regexp' => '[0-9\.,]*'),
+ 'tags' => array('regexp' => '[a-zA-Z0-9\pL-]*'),
+ ),
+ ),
+ 'layered_rule' => array(
+ 'controller' => 'category',
+ 'rule' => '{rewrite}/f/{selected_filters}',
+ 'keywords' => array(
+ 'id' => array('regexp' => '[0-9]+'),
+ 'selected_filters' => array('regexp' => '.*', 'param' => 'selected_filters'),
+ 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL-]*', 'param' => 'category_rewrite'),
+ 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ 'meta_title' => array('regexp' => '[_a-zA-Z0-9\pL-]*'),
+ ),
+ ),
+ );
+
+ parent::loadRoutes($id_shop);
+ }
+
+ /**
+ * @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
+ * @param int $id_shop
+ */
+ public function addRoute($route_id, $rule, $controller, $id_lang = null, array $keywords = array(), array $params = array(), $id_shop = null)
+ {
+ if (isset(Context::getContext()->language) && $id_lang === null) {
+ $id_lang = (int) Context::getContext()->language->id;
+ }
+
+ if (isset(Context::getContext()->shop) && $id_shop === null) {
+ $id_shop = (int) Context::getContext()->shop->id;
+ }
+
+ $regexp = preg_quote($rule, '#');
+ if ($keywords) {
+ $transform_keywords = array();
+ preg_match_all('#\\\{(([^{}]*)\\\:)?('.implode('|', array_keys($keywords)).')(\\\:([^{}]*))?\\\}#', $regexp, $m);
+ for ($i = 0, $total = count($m[0]); $i < $total; ++$i) {
+ $prepend = $m[2][$i];
+ $keyword = $m[3][$i];
+ $append = $m[5][$i];
+ $transform_keywords[$keyword] = array(
+ 'required' => isset($keywords[$keyword]['param']),
+ 'prepend' => stripslashes($prepend),
+ 'append' => stripslashes($append),
+ );
+
+ $prepend_regexp = $append_regexp = '';
+ if ($prepend || $append) {
+ $prepend_regexp = '('.$prepend;
+ $append_regexp = $append.')??'; // fix greediness (step 1)
+ }
+
+ if (isset($keywords[$keyword]['param'])) {
+ $regexp = str_replace($m[0][$i], $prepend_regexp.'(?P<'.$keywords[$keyword]['param'].'>'.$keywords[$keyword]['regexp'].')'.$append_regexp, $regexp);
+ } else {
+ $regexp = str_replace($m[0][$i], $prepend_regexp.'('.$keywords[$keyword]['regexp'].')'.$append_regexp, $regexp);
+ }
+ }
+ $keywords = $transform_keywords;
+ }
+
+ $regexp = '#^/'.$regexp.'$#uU'; // fix greediness (step 2)
+ if (!isset($this->routes[$id_shop])) {
+ $this->routes[$id_shop] = array();
+ }
+ if (!isset($this->routes[$id_shop][$id_lang])) {
+ $this->routes[$id_shop][$id_lang] = array();
+ }
+
+ $this->routes[$id_shop][$id_lang][$route_id] = array(
+ 'rule' => $rule,
+ 'regexp' => $regexp,
+ 'controller' => $controller,
+ 'keywords' => $keywords,
+ 'params' => $params,
+ );
+ }
+
+ /**
+ * Retrieve the controller from url or request uri if routes are activated.
+ *
+ * @param int $id_shop, defaults null
+ *
+ * @return string
+ */
+ public function getController($id_shop = null)
+ {
+ if (defined('_PS_ADMIN_DIR_')) {
+ $_GET['controllerUri'] = Tools::getvalue('controller');
+ }
+
+ if ($this->controller) {
+ $_GET['controller'] = $this->controller;
+
+ return $this->controller;
+ }
+
+ if (null === $id_shop) {
+ $id_shop = (int) Context::getContext()->shop->id;
+ }
+
+ $controller = Tools::getValue('controller');
+
+ $curr_lang_id = Context::getContext()->language->id;
+
+ if (isset($controller) && is_string($controller) && preg_match('/^([0-9a-z_-]+)\?(.*)=(.*)$/Ui', $controller, $m)) {
+ $controller = $m[1];
+ if (isset($_GET['controller'])) {
+ $_GET[$m[2]] = $m[3];
+ } elseif (isset($_POST['controller'])) {
+ $_POST[$m[2]] = $m[3];
+ }
+ }
+
+ if (!Validate::isControllerName($controller)) {
+ $controller = false;
+ }
+
+ // Use routes ? (for url rewriting)
+ if ($this->use_routes && !$controller && !defined('_PS_ADMIN_DIR_')) {
+ if (!$this->request_uri) {
+ return strtolower($this->controller_not_found);
+ }
+ $controller = $this->controller_not_found;
+
+ // If the request_uri matches a static file, then there is no need to check the routes, we keep "controller_not_found" (a static file should not go through the dispatcher)
+ if (!preg_match('/\.(gif|jpe?g|png|css|js|ico)$/i', $this->request_uri)) {
+ // 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'], $curr_lang_id, array(), array(), $id_shop);
+ }
+
+ list($uri) = explode('?', $this->request_uri);
+
+ if (isset($this->routes[$id_shop][$curr_lang_id])) {
+ $route = array();
+
+ // check, whether request_uri is template or not
+ foreach ($this->routes[$id_shop][$curr_lang_id] as $k => $r) {
+ if (preg_match($r['regexp'], $uri, $m)) {
+ $isTemplate = false;
+ $module = isset($r['params']['module']) ? $r['params']['module'] : '';
+ switch ($r['controller'].$module) { // Avoid name collision between core and modules' controllers
+ case 'supplier':
+ case 'manufacturer':
+ // these two can be processed in normal way and also as template
+ if (false !== strpos($r['rule'], '{')) {
+ $isTemplate = true;
+ }
+ break;
+
+ case 'cms':
+ case 'product':
+ $isTemplate = true;
+ break;
+ case 'category':
+ // category can be processed in two ways
+ if (false === strpos($r['rule'], 'selected_filters')) {
+ $isTemplate = true;
+ }
+ break;
+ }
+
+ if (!$isTemplate) {
+ $route = $r;
+ break;
+ }
+ }
+ }
+
+ // if route is not found, we have to find rewrite link in database
+ if (empty($route)) {
+ // get the path from requested URI, and remove "/" at the beginning
+ $short_link = ltrim(parse_url($uri, PHP_URL_PATH), '/');
+
+ $route = $this->routes[$id_shop][$curr_lang_id]['product_rule'];
+ if (!self::isProductLink($short_link, $route)) {
+ $route = $this->routes[$id_shop][$curr_lang_id]['category_rule'];
+ if (!self::isCategoryLink($short_link, $route)) {
+ $route = $this->routes[$id_shop][$curr_lang_id]['cms_rule'];
+ if (!self::isCmsLink($short_link, $route)) {
+ $route = $this->routes[$id_shop][$curr_lang_id]['cms_category_rule'];
+ if (!self::isCmsCategoryLink($short_link, $route)) {
+ $route = $this->routes[$id_shop][$curr_lang_id]['manufacturer_rule'];
+ if (!self::isManufacturerLink($short_link, $route)) {
+ $route = $this->routes[$id_shop][$curr_lang_id]['supplier_rule'];
+ if (!self::isSupplierLink($short_link, $route)) {
+ // no route found
+ $route = array();
+ $controller = $this->controller_not_found;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (!empty($route['controller'])) {
+ $controller = $route['controller'];
+ }
+ }
+
+ if (!empty($route)) {
+ if (preg_match($route['regexp'], $uri, $m)) {
+ // Route found! Now fill $_GET with parameters of uri
+ foreach ($m as $k => $v) {
+ if (!is_numeric($k)) {
+ $_GET[$k] = $v;
+ }
+ }
+
+ $controller = $route['controller'] ? $route['controller'] : $_GET['controller'];
+ if (!empty($route['params'])) {
+ foreach ($route['params'] as $k => $v) {
+ $_GET[$k] = $v;
+ }
+ }
+
+ // A patch for module friendly urls
+ if (preg_match('#module-([a-z0-9_-]+)-([a-z0-9]+)$#i', $controller, $m)) {
+ $_GET['module'] = $m[1];
+ $_GET['fc'] = 'module';
+ $controller = $m[2];
+ }
+
+ if (isset($_GET['fc']) && $_GET['fc'] == 'module') {
+ $this->front_controller = self::FC_MODULE;
+ }
+ }
+ }
+ }
+ }
+
+ if ($controller == 'index' || $this->request_uri == '/index.php') {
+ $controller = $this->default_controller;
+ }
+ $this->controller = $controller;
+ } else { // Default mode, take controller from url
+ $this->controller = $controller;
+ }
+
+ $this->controller = str_replace('-', '', $this->controller);
+ $_GET['controller'] = $this->controller;
+
+ return $this->controller;
+ }
+
+ /**
+ * Check if $short_link is a Product Link.
+ *
+ * @param string $short_link: requested url without '?' part and without '/' on begining
+ *
+ * @return bool true: it's a link to product, false: it isn't
+ */
+ private static function isProductLink($short_link, $route)
+ {
+ $short_link = preg_replace('#\.html?$#', '', '/'.$short_link);
+ $regexp = preg_replace('!\\\.html?\\$#!', '$#', $route['regexp']);
+
+ preg_match($regexp, $short_link, $kw);
+ if (empty($kw['product_rewrite'])) {
+ return false;
+ }
+
+ $sql = 'SELECT `id_product`
+ FROM `'._DB_PREFIX_.'product_lang`
+ WHERE `link_rewrite` = \''.pSQL($kw['product_rewrite']).'\' AND `id_lang` = '.(int) Context::getContext()->language->id;
+ if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) {
+ $sql .= ' AND `id_shop` = '.(int) Shop::getContextShopID();
+ }
+ $id_product = (int) Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+
+ return $id_product > 0;
+ }
+
+ /**
+ * Check if $short_link is a Category Link.
+ *
+ * @param string $short_link: requested url without '?' part and without '/' on begining
+ *
+ * @return bool true: it's a link to category, false: it isn't
+ */
+ private static function isCategoryLink($short_link, $route)
+ {
+ $short_link = preg_replace('#\.html?$#', '', '/'.$short_link);
+ $regexp = preg_replace('!\\\.html?\\$#!', '$#', $route['regexp']);
+
+ preg_match($regexp, $short_link, $kw);
+ if (empty($kw['category_rewrite'])) {
+ return false;
+ }
+
+ $sql = 'SELECT `id_category`
+ FROM `'._DB_PREFIX_.'category_lang`
+ WHERE `link_rewrite` = \''.pSQL($kw['category_rewrite']).'\' AND `id_lang` = '.(int) Context::getContext()->language->id;
+ if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) {
+ $sql .= ' AND `id_shop` = '.(int) Shop::getContextShopID();
+ }
+
+ $id_category = (int) Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+
+ return $id_category > 0;
+ }
+
+ /**
+ * Check if $short_link is a Cms Link.
+ *
+ * @param string $short_link: requested url without '?' part and without '/' on begining
+ *
+ * @return bool true: it's a link to cms page, false: it isn't
+ */
+ private static function isCmsLink($short_link, $route)
+ {
+ $short_link = preg_replace('#\.html?$#', '', '/'.$short_link);
+ $regexp = preg_replace('!\\\.html?\\$#!', '$#', $route['regexp']);
+
+ preg_match($regexp, $short_link, $kw);
+ if (empty($kw['cms_rewrite'])) {
+ return false;
+ }
+
+ $sql = 'SELECT l.`id_cms`
+ FROM `'._DB_PREFIX_.'cms_lang` l
+ LEFT JOIN `'._DB_PREFIX_.'cms_shop` s ON (l.`id_cms` = s.`id_cms`)
+ WHERE l.`link_rewrite` = \''.pSQL($kw['cms_rewrite']).'\'';
+ if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) {
+ $sql .= ' AND s.`id_shop` = '.(int) Shop::getContextShopID();
+ }
+
+ $id_cms = (int) Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+
+ return $id_cms > 0;
+ }
+
+ /**
+ * Check if $short_link is a Cms Category Link.
+ *
+ * @param string $short_link: requested url without '?' part and without '/' on begining
+ *
+ * @return bool true: it's a link to cms page, false: it isn't
+ */
+ private static function isCmsCategoryLink($short_link, $route)
+ {
+ $short_link = preg_replace('#\.html?$#', '', '/'.$short_link);
+ $regexp = preg_replace('!\\\.html?\\$#!', '$#', $route['regexp']);
+
+ preg_match($regexp, $short_link, $kw);
+ if (empty($kw['cms_category_rewrite'])) {
+ if (0 === strpos('/'.$route['rule'], $short_link)) {
+ //no link_rewrite, but uri starts with the link -> cms categories' list
+ return true;
+ }
+
+ return false;
+ }
+
+ $sql = 'SELECT l.`id_cms_category`
+ FROM `'._DB_PREFIX_.'cms_category_lang` l
+ LEFT JOIN `'._DB_PREFIX_.'cms_category_shop` s ON (l.`id_cms_category` = s.`id_cms_category`)
+ WHERE l.`link_rewrite` = \''.$kw['cms_category_rewrite'].'\'';
+ if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) {
+ $sql .= ' AND s.`id_shop` = '.(int) Shop::getContextShopID();
+ }
+
+ $id_cms_cat = (int) Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+
+ return $id_cms_cat > 0;
+ }
+
+ /**
+ * Check if $short_link is a Manufacturer Link.
+ *
+ * @param string $short_link: requested url without '?' part and without '/' on begining
+ *
+ * @return bool true: it's a link to manufacturer, false: it isn't
+ */
+ private static function isManufacturerLink($short_link, $route)
+ {
+ $short_link = preg_replace('#\.html?$#', '', '/'.$short_link);
+ $regexp = preg_replace('!\\\.html?\\$#!', '$#', $route['regexp']);
+
+ preg_match($regexp, $short_link, $kw);
+ if (empty($kw['manufacturer_rewrite'])) {
+ if (0 === strpos('/'.$route['rule'], $short_link)) {
+ //no link_rewrite, but uri starts with the link -> manufactures' list
+ return true;
+ }
+
+ return false;
+ }
+
+ $manufacturer = str_replace('-', '_', $kw['manufacturer_rewrite']);
+
+ $sql = 'SELECT m.`id_manufacturer`
+ FROM `'._DB_PREFIX_.'manufacturer` m
+ LEFT JOIN `'._DB_PREFIX_.'manufacturer_shop` s ON (m.`id_manufacturer` = s.`id_manufacturer`)
+ WHERE LOWER(m.`name`) LIKE \''.pSQL($manufacturer).'\'';
+ if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) {
+ $sql .= ' AND s.`id_shop` = '.(int) Shop::getContextShopID();
+ }
+
+ $id_manufacturer = (int) Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+
+ return $id_manufacturer > 0;
+ }
+
+ /**
+ * Check if $short_link is a Supplier Link.
+ *
+ * @param string $short_link: requested url without '?' part and without '/' on begining
+ *
+ * @return bool true: it's a link to supplier, false: it isn't
+ */
+ private static function isSupplierLink($short_link, $route)
+ {
+ $short_link = preg_replace('#\.html?$#', '', '/'.$short_link);
+ $regexp = preg_replace('!\\\.html?\\$#!', '$#', $route['regexp']);
+
+ preg_match($regexp, $short_link, $kw);
+ if (empty($kw['supplier_rewrite'])) {
+ if (0 === strpos('/'.$route['rule'], $short_link)) {
+ //no link_rewrite, but uri starts with the link -> suppliers' list
+ return true;
+ }
+
+ return false;
+ }
+
+ $supplier = str_replace('-', '_', $kw['supplier_rewrite']);
+
+ $sql = 'SELECT sp.`id_supplier`
+ FROM `'._DB_PREFIX_.'supplier` sp
+ LEFT JOIN `'._DB_PREFIX_.'supplier_shop` s ON (sp.`id_supplier` = s.`id_supplier`)
+ WHERE LOWER(sp.`name`) LIKE \''.pSQL($supplier).'\'';
+ if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) {
+ $sql .= ' AND s.`id_shop` = '.(int) Shop::getContextShopID();
+ }
+
+ $id_supplier = (int) Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+
+ return $id_supplier > 0;
+ }
+}
diff --git a/faktiva_clean_urls/override/classes/Link.php b/faktiva_clean_urls/override/classes/Link.php
new file mode 100644
index 0000000..d2196bb
--- /dev/null
+++ b/faktiva_clean_urls/override/classes/Link.php
@@ -0,0 +1,158 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+class Link extends LinkCore
+{
+ /**
+ * 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, $id_shop = null, $relative_protocol = false)
+ {
+ if (!$id_lang) {
+ $id_lang = Context::getContext()->language->id;
+ }
+
+ $url = $this->getBaseLink($id_shop, null, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop);
+
+ if (!is_object($category)) {
+ $category = new Category($category, $id_lang);
+ }
+
+ // Set available keywords
+ $params = array();
+ $params['id'] = $category->id;
+ $params['rewrite'] = (!$alias) ? $category->link_rewrite : $alias;
+ $params['meta_keywords'] = Tools::str2url($category->getFieldByLang('meta_keywords'));
+ $params['meta_title'] = Tools::str2url($category->getFieldByLang('meta_title'));
+
+ // Selected filters is used by the module blocklayered
+ $selected_filters = is_null($selected_filters) ? '' : $selected_filters;
+
+ if (empty($selected_filters)) {
+ $rule = 'category_rule';
+ } else {
+ $rule = 'layered_rule';
+ $params['selected_filters'] = $selected_filters;
+ }
+
+ $dispatcher = Dispatcher::getInstance();
+
+ if ($dispatcher->hasKeyword('category_rule', $id_lang, 'categories')) {
+ // Retrieve all parent categories
+ $p_cats = array();
+ foreach ($category->getParentsCategories($id_lang) as $p_cat) {
+ // remove root and current category from the URL
+ if (!in_array($p_cat['id_category'], array_merge(self::$category_disable_rewrite, array($category->id)))) {
+ $p_cats[] = $p_cat['link_rewrite'];
+ }
+ }
+ // add the URL slashes among categories, in reverse order
+ $params['categories'] = implode('/', array_reverse($p_cats));
+ }
+
+ return $url.$dispatcher->createUrl($rule, $id_lang, $params, $this->allow, '', $id_shop);
+ }
+
+ /**
+ * Get pagination link.
+ *
+ * @param string $type Controller name
+ * @param int $id_object
+ * @param bool $nb Show nb element per page attribute
+ * @param bool $sort Show sort attribute
+ * @param bool $pagination Show page number attribute
+ * @param bool $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' && $k != $type.'_rewrite' /* skip *_rewrite */) {
+ 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) {
+ if (count($vars)) {
+ return $url.(!strstr($url, '?') && ($this->allow == 1 || $url == $this->url) ? '?' : '&').http_build_query($vars, '', '&');
+ } else {
+ return $url;
+ }
+ }
+
+ $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;
+ }
+}
diff --git a/faktiva_clean_urls/override/classes/controller/FrontController.php b/faktiva_clean_urls/override/classes/controller/FrontController.php
new file mode 100644
index 0000000..5c029c5
--- /dev/null
+++ b/faktiva_clean_urls/override/classes/controller/FrontController.php
@@ -0,0 +1,44 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+class FrontController extends FrontControllerCore
+{
+ /**
+ * Redirects to canonical URL.
+ *
+ * Excludes "*_rewrite" URLs from being treated as non-canonical
+ *
+ * @param string $canonical_url
+ */
+ protected function canonicalRedirection($canonical_url = '')
+ {
+ $_unfiltered_GET = $_GET;
+
+ // hack original behavior on cananocalRedirection: remove *_rewrite from _GET
+ $_GET = array_filter($_GET, function ($v) {
+ return '_rewrite' === substr($v, -8);
+ });
+
+ parent::canonicalRedirection($canonical_url);
+
+ //restore original _GET
+ $_GET = $_unfiltered_GET;
+ }
+}
diff --git a/faktiva_clean_urls/override/classes/controller/index.php b/faktiva_clean_urls/override/classes/controller/index.php
new file mode 100644
index 0000000..5bbd579
--- /dev/null
+++ b/faktiva_clean_urls/override/classes/controller/index.php
@@ -0,0 +1,30 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+header('Expires: Fri, 31 Dec 1999 23:59:59 GMT');
+header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
+
+header('Cache-Control: no-store, no-cache, must-revalidate');
+header('Cache-Control: post-check=0, pre-check=0', false);
+header('Pragma: no-cache');
+
+header('Location: ../');
+
+return;
diff --git a/faktiva_clean_urls/override/classes/index.php b/faktiva_clean_urls/override/classes/index.php
new file mode 100644
index 0000000..5bbd579
--- /dev/null
+++ b/faktiva_clean_urls/override/classes/index.php
@@ -0,0 +1,30 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+header('Expires: Fri, 31 Dec 1999 23:59:59 GMT');
+header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
+
+header('Cache-Control: no-store, no-cache, must-revalidate');
+header('Cache-Control: post-check=0, pre-check=0', false);
+header('Pragma: no-cache');
+
+header('Location: ../');
+
+return;
diff --git a/faktiva_clean_urls/override/controllers/front/CategoryController.php b/faktiva_clean_urls/override/controllers/front/CategoryController.php
new file mode 100644
index 0000000..39e7d4d
--- /dev/null
+++ b/faktiva_clean_urls/override/controllers/front/CategoryController.php
@@ -0,0 +1,40 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+class CategoryController extends CategoryControllerCore
+{
+ public function init()
+ {
+ if ($category_rewrite = Tools::getValue('category_rewrite')) {
+ $sql = 'SELECT `id_category` FROM `'._DB_PREFIX_.'category_lang`
+ WHERE `link_rewrite` = \''.pSQL(str_replace('.html', '', $category_rewrite)).'\' AND `id_lang` = '.Context::getContext()->language->id;
+ if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) {
+ $sql .= ' AND `id_shop` = '.(int) Shop::getContextShopID();
+ }
+
+ $id_category = (int) Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+ if ($id_category > 0) {
+ $_GET['id_category'] = $id_category;
+ }
+ }
+
+ parent::init();
+ }
+}
diff --git a/faktiva_clean_urls/override/controllers/front/CmsController.php b/faktiva_clean_urls/override/controllers/front/CmsController.php
new file mode 100644
index 0000000..a650b9d
--- /dev/null
+++ b/faktiva_clean_urls/override/controllers/front/CmsController.php
@@ -0,0 +1,54 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+class CmsController extends CmsControllerCore
+{
+ public function init()
+ {
+ $shop_sql = '';
+ if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) {
+ $shop_sql = ' AND s.`id_shop` = '.(int) Shop::getContextShopID();
+ }
+
+ if ($cms_rewrite = Tools::getValue('cms_rewrite')) {
+ $sql = 'SELECT l.`id_cms`
+ FROM `'._DB_PREFIX_.'cms_lang` l
+ LEFT JOIN `'._DB_PREFIX_.'cms_shop` s ON (l.`id_cms` = s.`id_cms`)
+ WHERE l.`link_rewrite` = \''.pSQL(str_replace('.html', '', $cms_rewrite)).'\''.$shop_sql;
+
+ $id_cms = (int) Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+ if ($id_cms > 0) {
+ $_GET['id_cms'] = $id_cms;
+ }
+ } elseif ($cms_category_rewrite = Tools::getValue('cms_category_rewrite')) {
+ $sql = 'SELECT l.`id_cms_category`
+ FROM `'._DB_PREFIX_.'cms_category_lang` l
+ LEFT JOIN `'._DB_PREFIX_.'cms_category_shop` s ON (l.`id_cms_category` = s.`id_cms_category`)
+ WHERE `link_rewrite` = \''.pSQL(str_replace('.html', '', $cms_category_rewrite)).'\''.$shop_sql;
+
+ $id_cms_category = (int) Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+ if ($id_cms_category > 0) {
+ $_GET['id_cms_category'] = $id_cms_category;
+ }
+ }
+
+ parent::init();
+ }
+}
diff --git a/faktiva_clean_urls/override/controllers/front/ManufacturerController.php b/faktiva_clean_urls/override/controllers/front/ManufacturerController.php
new file mode 100644
index 0000000..fece097
--- /dev/null
+++ b/faktiva_clean_urls/override/controllers/front/ManufacturerController.php
@@ -0,0 +1,42 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+class ManufacturerController extends ManufacturerControllerCore
+{
+ public function init()
+ {
+ if ($manufacturer_rewrite = Tools::getValue('manufacturer_rewrite')) {
+ $sql = 'SELECT m.`id_manufacturer`
+ FROM `'._DB_PREFIX_.'manufacturer` m
+ LEFT JOIN `'._DB_PREFIX_.'manufacturer_shop` s ON (m.`id_manufacturer` = s.`id_manufacturer`)
+ WHERE m.`name` LIKE \''.pSQL(str_replace('-', '_', $manufacturer_rewrite)).'\'';
+ if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) {
+ $sql .= ' AND s.`id_shop` = '.(int) Shop::getContextShopID();
+ }
+
+ $id_manufacturer = (int) Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+ if ($id_manufacturer > 0) {
+ $_GET['id_manufacturer'] = $id_manufacturer;
+ }
+ }
+
+ parent::init();
+ }
+}
diff --git a/faktiva_clean_urls/override/controllers/front/ProductController.php b/faktiva_clean_urls/override/controllers/front/ProductController.php
new file mode 100644
index 0000000..2c9f34c
--- /dev/null
+++ b/faktiva_clean_urls/override/controllers/front/ProductController.php
@@ -0,0 +1,56 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+class ProductController extends ProductControllerCore
+{
+ public function init()
+ {
+ if ($product_rewrite = Tools::getValue('product_rewrite')) {
+ $url_id_pattern = '/.*?([0-9]+)\-([a-zA-Z0-9-]*)(\.html)?/';
+ $lang_id = (int) Context::getContext()->language->id;
+
+ $sql = 'SELECT `id_product`
+ FROM `'._DB_PREFIX_.'product_lang`
+ WHERE `link_rewrite` = \''.pSQL(str_replace('.html', '', $product_rewrite)).'\' AND `id_lang` = '.$lang_id;
+ if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) {
+ $sql .= ' AND `id_shop` = '.(int) Shop::getContextShopID();
+ }
+
+ $id_product = (int) Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+ if ($id_product > 0) {
+ $_GET['id_product'] = $id_product;
+ } elseif (preg_match($url_id_pattern, $this->request_uri, $url_parts)) {
+ $sql = 'SELECT `id_product`
+ FROM `'._DB_PREFIX_.'product_lang`
+ WHERE `id_product` = \''.pSQL($url_parts[1]).'\' AND `id_lang` = '.$lang_id;
+ if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) {
+ $sql .= ' AND `id_shop` = '.(int) Shop::getContextShopID();
+ }
+
+ $id_product = (int) Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+ if ($id_product > 0) {
+ $_GET['id_product'] = $id_product;
+ }
+ }
+ }
+
+ parent::init();
+ }
+}
diff --git a/faktiva_clean_urls/override/controllers/front/SupplierController.php b/faktiva_clean_urls/override/controllers/front/SupplierController.php
new file mode 100644
index 0000000..40dab3c
--- /dev/null
+++ b/faktiva_clean_urls/override/controllers/front/SupplierController.php
@@ -0,0 +1,42 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+class SupplierController extends SupplierControllerCore
+{
+ public function init()
+ {
+ if ($supplier_rewrite = Tools::getValue('supplier_rewrite')) {
+ $sql = 'SELECT sp.`id_supplier`
+ FROM `'._DB_PREFIX_.'supplier` sp
+ LEFT JOIN `'._DB_PREFIX_.'supplier_shop` s ON (sp.`id_supplier` = s.`id_supplier`)
+ WHERE sp.`name` LIKE \''.pSQL(str_replace('-', '_', $supplier_rewrite)).'\'';
+ if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) {
+ $sql .= ' AND s.`id_shop` = '.(int) Shop::getContextShopID();
+ }
+
+ $id_supplier = (int) Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+ if ($id_supplier > 0) {
+ $_GET['id_supplier'] = $id_supplier;
+ }
+ }
+
+ parent::init();
+ }
+}
diff --git a/faktiva_clean_urls/override/controllers/front/index.php b/faktiva_clean_urls/override/controllers/front/index.php
new file mode 100644
index 0000000..5bbd579
--- /dev/null
+++ b/faktiva_clean_urls/override/controllers/front/index.php
@@ -0,0 +1,30 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+header('Expires: Fri, 31 Dec 1999 23:59:59 GMT');
+header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
+
+header('Cache-Control: no-store, no-cache, must-revalidate');
+header('Cache-Control: post-check=0, pre-check=0', false);
+header('Pragma: no-cache');
+
+header('Location: ../');
+
+return;
diff --git a/faktiva_clean_urls/override/controllers/index.php b/faktiva_clean_urls/override/controllers/index.php
new file mode 100644
index 0000000..5bbd579
--- /dev/null
+++ b/faktiva_clean_urls/override/controllers/index.php
@@ -0,0 +1,30 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+header('Expires: Fri, 31 Dec 1999 23:59:59 GMT');
+header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
+
+header('Cache-Control: no-store, no-cache, must-revalidate');
+header('Cache-Control: post-check=0, pre-check=0', false);
+header('Pragma: no-cache');
+
+header('Location: ../');
+
+return;
diff --git a/faktiva_clean_urls/override/index.php b/faktiva_clean_urls/override/index.php
new file mode 100644
index 0000000..5bbd579
--- /dev/null
+++ b/faktiva_clean_urls/override/index.php
@@ -0,0 +1,30 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+header('Expires: Fri, 31 Dec 1999 23:59:59 GMT');
+header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
+
+header('Cache-Control: no-store, no-cache, must-revalidate');
+header('Cache-Control: post-check=0, pre-check=0', false);
+header('Pragma: no-cache');
+
+header('Location: ../');
+
+return;
diff --git a/faktiva_clean_urls/tools/debug.php b/faktiva_clean_urls/tools/debug.php
new file mode 100644
index 0000000..b3337c0
--- /dev/null
+++ b/faktiva_clean_urls/tools/debug.php
@@ -0,0 +1,24 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+if (defined('FKV_DEBUG') && FKV_DEBUG && is_readable(__DIR__.'/vendor/autoload.php')) {
+ require_once __DIR__.'/vendor/autoload.php';
+ Symfony\Component\Debug\Debug::enable();
+}
diff --git a/faktiva_clean_urls/translations/it.php b/faktiva_clean_urls/translations/it.php
new file mode 100644
index 0000000..9f9866c
--- /dev/null
+++ b/faktiva_clean_urls/translations/it.php
@@ -0,0 +1,38 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+global $_MODULE;
+$_MODULE = array();
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_66711d755755f94e8f48d9cb858290c8'] = 'Faktiva Clean URLs';
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_4abf1025eb40d230f80b0470e5c60696'] = 'Questo modulo permette di rimuovere gli ID dalle URL. Utilizza gli \"override\".';
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_3c3419c3ec1896fbfd5c37549eda9144'] = 'Sicuro di voler rimuovere il modulo \"Faktiva Clean URLs\"?';
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_8aa6176f15ae0b8ec0f7f7797bc129cb'] = 'In alcune versioni di Prestashop potrebbe essere necessario disabilitare la Cache, salvare, accedere al proprio negozio e riabilitare la cache di nuovo:';
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_c9d7eedc8be4380c02106619824b8449'] = 'Parametri avanzati';
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_9446a98ad14416153cc4d45ab8b531bf'] = 'Prestazioni';
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_341be761f9f11e9b06dac0071fb8a5ed'] = 'pulisci la Cache';
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_d0834fcec6337785ee749c8f5464f6f6'] = 'Impostazioni';
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_acc42ebe7b6b25f7d6ea8618f514f79b'] = 'SEO and URLs';
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_a3637ddc43eefbe21947f64210bae984'] = 'disattivare \"Friendly url\"';
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_c9cc8cce247e49bae79f15173ce97354'] = 'Salva';
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_7e497263357c140cc3d2396dbfa8b2eb'] = 'attivare \"Friendly url\"';
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_851645568061b03aeeb2b4c2af435a5e'] = 'Dovresti eliminare queste URL duplicate:';
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_c961f5d807b8ae34a9a4a825606f953b'] = 'Lingua:';
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_63de125555fddc0e009f92ec0e9e64e4'] = 'Negozio:';
+$_MODULE['<{faktiva_clean_urls}prestashop>faktiva_clean_urls_dae2931f3df26903e6ddbb123b751344'] = 'Perfetto. Non ci sono URL duplicate.';
diff --git a/faktiva_clean_urls/upgrade/index.php b/faktiva_clean_urls/upgrade/index.php
new file mode 100644
index 0000000..5bbd579
--- /dev/null
+++ b/faktiva_clean_urls/upgrade/index.php
@@ -0,0 +1,30 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+header('Expires: Fri, 31 Dec 1999 23:59:59 GMT');
+header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
+
+header('Cache-Control: no-store, no-cache, must-revalidate');
+header('Cache-Control: post-check=0, pre-check=0', false);
+header('Pragma: no-cache');
+
+header('Location: ../');
+
+return;
diff --git a/faktiva_clean_urls/upgrade/install-1.1.0.php b/faktiva_clean_urls/upgrade/install-1.1.0.php
new file mode 100644
index 0000000..d8b086d
--- /dev/null
+++ b/faktiva_clean_urls/upgrade/install-1.1.0.php
@@ -0,0 +1,41 @@
+
+ * @license https://creativecommons.org/licenses/by-sa/4.0/ CC-BY-SA-4.0
+ * @source https://github.com/faktiva/prestashop-clean-urls
+ */
+
+if (!defined('_PS_VERSION_')) {
+ return;
+}
+
+function upgrade_module_1_1_0($module)
+{
+ $old_module = 'zzcleanurls';
+
+ if (Module::isInstalled($old_module)) {
+ Module::disableByName($this->name);
+
+ die(Tools::displayError('You must first un-install module "ZiZuu Clean URLs"'));
+ }
+
+ Db::getInstance()->delete('module', "`name` = '$old_module'", 1);
+ Db::getInstance()->delete('module_preference', "`module` = '$old_module'");
+ Db::getInstance()->delete('configuration', "`name` LIKE '$old_module%'");
+ Db::getInstance()->delete('quick_access', "`link` LIKE '%module_name=$old_module%'");
+
+ return true;
+}