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 -====== +[![SensioLabsInsight](https://insight.sensiolabs.com/projects/58d1de4f-45fc-4f63-aeb3-7ddc51d4a64e/small.png)](https://insight.sensiolabs.com/projects/58d1de4f-45fc-4f63-aeb3-7ddc51d4a64e) +[PrestaShop module "Clean URLs"](https://github.com/faktiva/prestashop-seo-tk) +=== +[![GitHub release](https://img.shields.io/github/release/faktiva/prestashop-clean-urls.svg?style=plastic&label=latest)](https://github.com/faktiva/prestashop-clean-urls/releases/latest) +[![Project Status](http://opensource.box.com/badges/active.svg)](http://opensource.box.com/badges) +[![Percentage of issues still open](http://isitmaintained.com/badge/open/faktiva/prestashop-clean-urls.svg)](http://isitmaintained.com/project/faktiva/prestashop-clean-urls "Percentage of issues still open") +[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/faktiva/prestashop-clean-urls.svg)](http://isitmaintained.com/project/faktiva/prestashop-clean-urls "Average time to resolve an issue") +[![composer.lock](https://poser.pugx.org/faktiva/prestashop-clean-urls/composerlock)](https://packagist.org/packages/faktiva/prestashop-clean-urls) +[![Dependencies Status](https://img.shields.io/librariesio/github/faktiva/prestashop-clean-urls.svg?maxAge=3600)](https://libraries.io/github/faktiva/prestashop-clean-urls) +[![License](https://img.shields.io/packagist/l/faktiva/prestashop-clean-urls.svg?style=flat)](https://creativecommons.org/licenses/by-sa/4.0/) -ABOUT --------- +[![Join the chat at https://gitter.im/faktiva/prestashop-clean-urls](https://img.shields.io/badge/Gitter-CHAT%20NOW-brightgreen.svg?style=plastic)](https://gitter.im/faktiva/prestashop-clean-urls) +[![Twitter](https://img.shields.io/twitter/url/https/github.com/faktiva/prestashop-clean-urls.svg?style=social)](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 + +![Creative Commons BY-SA License](https://i.creativecommons.org/l/by-sa/4.0/88x31.png) + + +**[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; +}