diff --git a/.gitignore b/.gitignore index beb165d67..da50e211e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,15 @@ .DS_Store robots.txt sitemap.xml +cache/cachefs/* +!cache/cachefs/index.php +download/* +!download/index.php +upload/* +!upload/index.php +admin-dev/autoupgrade/* +admin-dev/backups/* +!admin-dev/backups/index.php cache/smarty/cache/* !cache/smarty/cache/index.php cache/smarty/compile/* @@ -16,6 +25,7 @@ cache/tcpdf/* !cache/tcpdf/index.php config/xml/*.xml config/settings.inc.php +config/settings.old.php log/*.log img/* !img/index.php @@ -27,6 +37,10 @@ tools/smarty*/compile/*.php override/classes/*.php themes/default/cache/*.js themes/default/cache/*.css +themes/default/modules/*/*.php +!themes/default/modules/*/index.php +themes/default/lang/*.php +!themes/default/lang/index.php modules/*/translations/*.php !modules/*/translations/index.php mails/* @@ -35,4 +49,59 @@ modules/*/mails/* !modules/*/mails/en translations/* !translations/*.gzip - +modules/atos/* +modules/addshoppers +modules/alliedwallet +modules/authorizeaim +modules/autoupgrade +modules/avalaratax +modules/backwardcompatibility +modules/canadapost +modules/cloudcache +modules/ebay +modules/fedexcarrier +modules/fianetfraud +modules/fianetsceau +modules/fidbag +modules/firstdata +modules/gadwords +modules/gamification +modules/ganalytics +modules/gsitemap +modules/hipay +modules/iadvize +modules/itembase +modules/jirafe +modules/kiala +modules/kialasmall +modules/klarnaprestashop +modules/kwixo +modules/livezilla +modules/mailjet +modules/merchantware +modules/mobile_theme +modules/mondialrelay +modules/moneybookers +modules/nqgatewayneteven +modules/ogone +modules/pagseguro +modules/paypal +modules/payulatam +modules/prediggo +modules/prestafraud +modules/shipwire +modules/shoppingfeedexport +modules/shoppingfluxexport +modules/socolissimo +modules/stripejs +modules/themeinstallator +modules/tntcarrier +modules/treepodia +modules/trustedshops +modules/trustly +modules/twenga +modules/upscarrier +modules/uspscarrier +modules/wexpay +modules/yotpo +modules/zingaya diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 944062c4e..29f1cdfdc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,5 +8,5 @@ All core files you commit in your pull request must have Open Software License ( All modules files you commit in your pull request must have Academic Free License (AFL 3.0) [1]: https://help.github.com/articles/using-pull-requests -[2]: http://docs.prestashop.com/display/PS15/Coding+Standard -[3]: http://docs.prestashop.com/display/PS15/How+to+write+a+commit+message \ No newline at end of file +[2]: http://docs.prestashop.com/display/PS15/Coding+Standards +[3]: http://docs.prestashop.com/display/PS15/How+to+write+a+commit+message diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 06dcfe350..bb91f96b5 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -1,80 +1,140 @@ - - (d)oekia - - Alexander Otchenashev - - Benjamin PONGY - - Burhan - - Caleydon Media - - Damien Metzger - - DamienMetzger - - Damon Skelhorn - - Daniel - - David Gasperoni - - DrySs - - DrÿSs' - - François Gaillard - - Gabriel Schwardy - - Gregory Roussac - - Ha!*!*y - - Jonathan Danse - - Krystian Podemski - - Marco Cervellin - - Michel Courtade - - Milow - - Patanock - - Pierre - - PrestaEdit - - Raphaël Malié - - Rémi Gaillard - - Samy Rabih - - Sarah Lorenzini - - Shagshag - - Vincent Augagneur - - Xavier POITAU - - aFolletete - - aKorczak - - aNiassy - - adonis karavokyros - - anat - - bLeveque - - bMancone - - bumbu - - cmouleyre - - dMetzger - - dSevere - - djfm - - fBrignoli - - fSerny - - fram - - gBrunier - - gCharmes - - gPoulain - - gRoussac - - hAitmansour - - ivancasasempere - - jBreux - - jObregon - - jessylenne - - jmCollin - - kpodemski - - lBrieu - - lCherifi - - lLefevre - - mBertholino - - mDeflotte - - mMarinetti - - marcinsz101 - - montes - - nPellicari - - nezenmoins - - oleacorner - - rGaillard - - rMalie - - rMontagne - - root - - sLorenzini - - sThiebaut - - tDidierjean - - vAugagneur - - vChabot - - vKham - - vSchoener - +- adonis karavokyros +- aFolletete +- Agence CINS +- aKorczak +- Alexander Otchenashev +- anat +- Andrew +- aNiassy +- antoniofr +- AntonLejon +- Arnaud Lemercier +- Axome +- Benjamin PONGY +- BigZ +- bLeveque +- bMancone +- bumbu +- Burhan +- Cédric Mouleyre +- Caleydon Media +- cam.lafit +- Captain FLAM +- Captain-FLAM +- ccauw +- ChristopheBoucaut +- cippest +- cmouleyre +- Corentin Delcourt +- Cosmin Hutanu +- Damien Metzger +- DamienMetzger +- Damon Skelhorn +- Daniel +- David Gasperoni +- Davy Rolink +- djfm +- dMetzger +- (d)oekia +- Dragan Skrbic +- DrÿSs' +- dreammeup +- DrySs +- dSevere +- Edouard Gaulué +- emily-d +- Fabio Chelly +- fBrignoli +- fram +- François Gaillard +- fSerny +- Gabriel Schwardy +- gBrunier +- gCharmes +- gPoulain +- Grégoire Bélorgey +- Gregory Roussac +- gRoussac +- Guillaume DELOINCE +- hAitmansour +- Ha!*!*y +- indesign47 +- inem0o +- ivancasasempere +- Jérôme Nadaud +- jBreux +- jeromenadaud +- Jerome Nadaud +- jessylenne +- jmCollin +- jObregon +- Jonathan Danse +- joseantgv +- Kevin Granger +- kpodemski +- Krystian Podemski +- lBrieu +- lCherifi +- ldecoker +- lLefevre +- marcinsz101 +- Marco Cervellin +- Mats Rynge +- MatthieuB +- Maxence +- mBertholino +- mDeflotte +- Michel Courtade +- Milow +- minic studio +- misthero +- mMarinetti +- montes +- nezenmoins +- Nicolas Sorosac +- Nils-Helge Garli Hegvik +- nPellicari +- nturato +- oleacorner +- Otto Nascarella +- Patanock +- PhpMadman +- Pierre +- Piotr Kaczor +- Piotr Moćko +- PrestaEdit +- prestarocket +- pxls +- Rémi Gaillard +- Raphaël Malié +- raulgundin +- rGaillard +- Rimas Kudelis +- rMalie +- rMontagne +- root +- runningz +- Sébastien +- Sébastien Bocahu +- Samy Rabih +- Sarah Lorenzini +- Seb +- Seynaeve +- Shagshag +- sLorenzini +- soware +- Staging +- sThiebaut +- Sylvain WITMEYER +- tDidierjean +- vAugagneur +- vChabot +- Vincent Augagneur +- Vincent Schoener +- Vincent Terenti +- vinvin27 +- vKham +- vSchoener +- Xavier +- Xavier POITAU +- Yoozio diff --git a/address.php b/address.php index fcfac54af..4dbf1d223 100644 --- a/address.php +++ b/address.php @@ -34,4 +34,4 @@ require(dirname(__FILE__).'/config/config.inc.php'); Tools::displayFileAsDeprecated(); -Tools::redirect('index.php?controller=address'.($_REQUEST ? '&'.http_build_query($_REQUEST, '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file +Tools::redirect('index.php?controller=address'.((count($_GET) || count($_POST)) ? '&'.http_build_query(array_merge($_GET, $_POST), '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file diff --git a/addresses.php b/addresses.php index 75e3a1dfe..cda46efcf 100644 --- a/addresses.php +++ b/addresses.php @@ -34,4 +34,4 @@ require(dirname(__FILE__).'/config/config.inc.php'); Tools::displayFileAsDeprecated(); -Tools::redirect('index.php?controller=addresses'.($_REQUEST ? '&'.http_build_query($_REQUEST, '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file +Tools::redirect('index.php?controller=addresses'.((count($_GET) || count($_POST)) ? '&'.http_build_query(array_merge($_GET, $_POST), '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file diff --git a/admin-dev/ajaxfilemanager/ajax_file_upload.php b/admin-dev/ajaxfilemanager/ajax_file_upload.php index 309490e06..b21a39c13 100755 --- a/admin-dev/ajaxfilemanager/ajax_file_upload.php +++ b/admin-dev/ajaxfilemanager/ajax_file_upload.php @@ -60,7 +60,7 @@ $tem[$k] = $v; } - $tem['path'] = backslashToSlash($path); + $tem['path'] = addslashes(backslashToSlash($path)); $tem['type'] = "file"; $tem['size'] = transformFileSize($tem['size']); $tem['ctime'] = date(DATE_TIME_FORMAT, $tem['ctime']); @@ -73,7 +73,7 @@ $info .= sprintf(", %s:'%s'", $k, $v); } - $info .= sprintf(", url:'%s'", getFileUrl($path)); + $info .= sprintf(", url:'%s'", addslashes(getFileUrl($path))); $info .= sprintf(", tipedit:'%s'", TIP_DOC_RENAME); diff --git a/admin-dev/ajaxfilemanager/ajax_get_file_listing.php b/admin-dev/ajaxfilemanager/ajax_get_file_listing.php index 133486637..c72110344 100755 --- a/admin-dev/ajaxfilemanager/ajax_get_file_listing.php +++ b/admin-dev/ajaxfilemanager/ajax_get_file_listing.php @@ -99,9 +99,9 @@ { $v = transformFileSize($v); } - echo (($j++ > 1)?",":'') . "'" . $k . "':'" . $v . "'"; + echo (($j++ > 1)?",":'') . "'" . addslashes($k) . "':'" . addslashes($v) . "'"; } - echo (($j++ > 1)?",":'') . "'url':'" . getFileUrl($file['path']) . "'"; + echo (($j++ > 1)?",":'') . "'url':'" . addslashes(getFileUrl($file['path'])) . "'"; echo "}\n"; } echo "};\n"; diff --git a/admin-dev/ajaxfilemanager/inc/class.file.php b/admin-dev/ajaxfilemanager/inc/class.file.php index 85512eb02..d35ff7a33 100755 --- a/admin-dev/ajaxfilemanager/inc/class.file.php +++ b/admin-dev/ajaxfilemanager/inc/class.file.php @@ -33,15 +33,15 @@ $this->fileInfo['atime'] = $this->fileStat[8]; $this->fileInfo['ctime'] = $this->fileStat[10]; $this->fileInfo['mtime'] = $this->fileStat[9]; - $this->fileInfo['path'] = $path; - $this->fileInfo['name'] = basename($path); + $this->fileInfo['path'] = addslashes($path); + $this->fileInfo['name'] = addslashes(basename($path)); $this->fileInfo['is_writable'] = $this->isWritable(); $this->fileInfo['is_readable'] = $this->isReadable(); }elseif(is_dir($this->filePath)) { $this->fileStat = @stat($path); - $this->fileInfo['name'] = basename($path); - $this->fileInfo['path'] = $path; + $this->fileInfo['name'] = addslashes(basename($path)); + $this->fileInfo['path'] = addslashes($path); $this->fileInfo['atime'] = $this->fileStat[8]; $this->fileInfo['ctime'] = $this->fileStat[10]; $this->fileInfo['mtime'] = $this->fileStat[9]; diff --git a/admin-dev/drawer.php b/admin-dev/drawer.php index c52ea4547..22baa705c 100644 --- a/admin-dev/drawer.php +++ b/admin-dev/drawer.php @@ -37,7 +37,6 @@ $height = Tools::getValue('height'); $id_employee = Tools::getValue('id_employee'); $id_lang = Tools::getValue('id_lang'); - if (!isset($cookie->id_employee) || !$cookie->id_employee || $cookie->id_employee != $id_employee) die(Tools::displayError()); @@ -47,6 +46,51 @@ if (!Validate::isModuleName($module)) if (!Tools::file_exists_cache($module_path = dirname(__FILE__).'/../modules/'.$module.'/'.$module.'.php')) die(Tools::displayError()); +$shop_id = ''; +Shop::setContext(Shop::CONTEXT_ALL); +if (Context::getContext()->cookie->shopContext) +{ + $split = explode('-', Context::getContext()->cookie->shopContext); + if (count($split) == 2) + { + if ($split[0] == 'g') + { + if (Context::getContext()->employee->hasAuthOnShopGroup($split[1])) + Shop::setContext(Shop::CONTEXT_GROUP, $split[1]); + else + { + $shop_id = Context::getContext()->employee->getDefaultShopID(); + Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); + } + } + else if (Shop::getShop($split[1]) && Context::getContext()->employee->hasAuthOnShop($split[1])) + { + $shop_id = $split[1]; + Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); + } + else + { + $shop_id = Context::getContext()->employee->getDefaultShopID(); + Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); + } + } +} + +// Check multishop context and set right context if need +if (Shop::getContext()) +{ + if (Shop::getContext() == Shop::CONTEXT_SHOP && !Shop::CONTEXT_SHOP) + Shop::setContext(Shop::CONTEXT_GROUP, Shop::getContextShopGroupID()); + if (Shop::getContext() == Shop::CONTEXT_GROUP && !Shop::CONTEXT_GROUP) + Shop::setContext(Shop::CONTEXT_ALL); +} + +// Replace existing shop if necessary +if (!$shop_id) + Context::getContext()->shop = new Shop(Configuration::get('PS_SHOP_DEFAULT')); +elseif (Context::getContext()->shop->id != $shop_id) + Context::getContext()->shop = new Shop($shop_id); + require_once($module_path); $graph = new $module(); @@ -57,4 +101,3 @@ if ($option) $graph->create($render, $type, $width, $height, $layers); $graph->draw(); - diff --git a/admin-dev/footer.inc.php b/admin-dev/footer.inc.php index 5f91c44fa..de8dc6a14 100644 --- a/admin-dev/footer.inc.php +++ b/admin-dev/footer.inc.php @@ -30,14 +30,14 @@ echo ' diff --git a/admin-dev/functions.php b/admin-dev/functions.php index d64c3e3e8..314d2b867 100644 --- a/admin-dev/functions.php +++ b/admin-dev/functions.php @@ -223,8 +223,16 @@ function checkPSVersion() return $upgrader->checkPSVersion(); } +/** + * Deprecated since > 1.5.4.1 + * Use Translate::getAdminTranslation($string) instead + * + * @param string $string + */ function translate($string) { + Tools::displayAsDeprecated(); + global $_LANGADM; if (!is_array($_LANGADM)) return str_replace('"', '"', $string); @@ -233,7 +241,6 @@ function translate($string) return str_replace('"', '"', stripslashes($str)); } - /** * Returns a new Tab object * @@ -461,7 +468,7 @@ function runAdminTab($tab, $ajaxMode = false) echo '
- '.translate('Back Office').' + '.Translate::getAdminTranslation('Back Office').' '.$bread.'
'; if (!$ajaxMode && Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL && Context::getContext()->controller->multishop_context != Shop::CONTEXT_ALL) @@ -470,10 +477,10 @@ function runAdminTab($tab, $ajaxMode = false) if (Shop::getContext() == Shop::CONTEXT_GROUP) { $shop_group = new ShopGroup((int)Shop::getContextShopGroupID()); - printf(translate('You are configuring your store for group shop %s'), ''.$shop_group->name.''); + printf(Translate::getAdminTranslation('You are configuring your store for group shop %s'), ''.$shop_group->name.''); } elseif (Shop::getContext() == Shop::CONTEXT_SHOP) - printf(translate('You are configuring your store for shop %s'), ''.Context::getContext()->shop->name.''); + printf(Translate::getAdminTranslation('You are configuring your store for shop %s'), ''.Context::getContext()->shop->name.''); echo ''; } if (Validate::isLoadedObject($adminObj)) @@ -546,8 +553,8 @@ function runAdminTab($tab, $ajaxMode = false) // we can display the correct url - // die(Tools::jsonEncode(array(translate('Invalid security token'),$url))); - die(Tools::jsonEncode(translate('Invalid security token'))); + // die(Tools::jsonEncode(array(Translate::getAdminTranslation('Invalid security token'),$url))); + die(Tools::jsonEncode(Translate::getAdminTranslation('Invalid security token'))); } else { @@ -559,17 +566,17 @@ function runAdminTab($tab, $ajaxMode = false) if (false === strpos($url, '?token=') AND false === strpos($url, '&token=')) $url .= '&token='.$adminObj->token; - $message = translate('Invalid security token'); + $message = Translate::getAdminTranslation('Invalid security token'); echo ''.$message.'
'.$message.'
'; echo ' - + - + '; die; diff --git a/admin-dev/get-file-admin.php b/admin-dev/get-file-admin.php index b37f691e5..39fcd8a85 100644 --- a/admin-dev/get-file-admin.php +++ b/admin-dev/get-file-admin.php @@ -25,5 +25,5 @@ */ define('_PS_ADMIN_DIR_', getcwd()); -require(_PS_ADMIN_DIR_.'/config/config.inc.php'); +require(_PS_ADMIN_DIR_.'/../config/config.inc.php'); Controller::getController('GetFileController')->run(); \ No newline at end of file diff --git a/admin-dev/grider.php b/admin-dev/grider.php index 6e97baf68..a8506a94d 100644 --- a/admin-dev/grider.php +++ b/admin-dev/grider.php @@ -50,6 +50,53 @@ if (!Validate::isModuleName($module)) if (!Tools::file_exists_cache($module_path = dirname(__FILE__).'/../modules/'.$module.'/'.$module.'.php')) die(Tools::displayError()); + +$shop_id = ''; +Shop::setContext(Shop::CONTEXT_ALL); +if (Context::getContext()->cookie->shopContext) +{ + $split = explode('-', Context::getContext()->cookie->shopContext); + if (count($split) == 2) + { + if ($split[0] == 'g') + { + if (Context::getContext()->employee->hasAuthOnShopGroup($split[1])) + Shop::setContext(Shop::CONTEXT_GROUP, $split[1]); + else + { + $shop_id = Context::getContext()->employee->getDefaultShopID(); + Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); + } + } + else if (Shop::getShop($split[1]) && Context::getContext()->employee->hasAuthOnShop($split[1])) + { + $shop_id = $split[1]; + Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); + } + else + { + $shop_id = Context::getContext()->employee->getDefaultShopID(); + Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); + } + } +} + +// Check multishop context and set right context if need +if (Shop::getContext()) +{ + if (Shop::getContext() == Shop::CONTEXT_SHOP && !Shop::CONTEXT_SHOP) + Shop::setContext(Shop::CONTEXT_GROUP, Shop::getContextShopGroupID()); + if (Shop::getContext() == Shop::CONTEXT_GROUP && !Shop::CONTEXT_GROUP) + Shop::setContext(Shop::CONTEXT_ALL); +} + +// Replace existing shop if necessary +if (!$shop_id) + Context::getContext()->shop = new Shop(Configuration::get('PS_SHOP_DEFAULT')); +elseif (Context::getContext()->shop->id != $shop_id) + Context::getContext()->shop = new Shop($shop_id); + + require_once($module_path); $grid = new $module(); diff --git a/admin-dev/header.inc.php b/admin-dev/header.inc.php index 077fde82f..5ed525a84 100644 --- a/admin-dev/header.inc.php +++ b/admin-dev/header.inc.php @@ -41,7 +41,7 @@ echo ' - PrestaShop™ - '.translate('Administration panel').' + PrestaShop™ - '.Translate::getAdminTranslation('Administration panel').' + +

+ {l s='Format:'} JPG, GIF, PNG. {l s='Filesize:'} {$max_image_size|string_format:"%.2f"} {l s='MB max.'} +
{l s='Current size:'} {l s='undefined'}. +

+ + {/if} + {$smarty.block.parent} +{/block} diff --git a/admin-dev/themes/default/template/controllers/carrier_wizard/helpers/form/form_ranges.tpl b/admin-dev/themes/default/template/controllers/carrier_wizard/helpers/form/form_ranges.tpl new file mode 100644 index 000000000..b19611d31 --- /dev/null +++ b/admin-dev/themes/default/template/controllers/carrier_wizard/helpers/form/form_ranges.tpl @@ -0,0 +1,61 @@ + +
+ + + + + {foreach from=$ranges key=r item=range} + + {foreachelse} + + {/foreach} + + + + + {foreach from=$ranges key=r item=range} + + {foreachelse} + + {/foreach} + + + + + {foreach from=$ranges key=r item=range} + + {foreachelse} + + {/foreach} + + {foreach from=$zones key=i item=zone} + + + + {foreach from=$ranges key=r item=range} + + {/foreach} + + {/foreach} + + + + {foreach from=$ranges name=ranges key=r item=range} + {if $smarty.foreach.ranges.first} + + {else} + +
>=*  {$PS_WEIGHT_UNIT}  {$currency_sign}*  {$PS_WEIGHT_UNIT}  {$currency_sign}
<*  {$PS_WEIGHT_UNIT}  {$currency_sign}*  {$PS_WEIGHT_UNIT}  {$currency_sign}
All + + + +
+ + +   {$currency_sign} +
   
+
diff --git a/admin-dev/themes/default/template/controllers/carrier_wizard/helpers/form/index.php b/admin-dev/themes/default/template/controllers/carrier_wizard/helpers/form/index.php new file mode 100644 index 000000000..30839633c --- /dev/null +++ b/admin-dev/themes/default/template/controllers/carrier_wizard/helpers/form/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header('Expires: Mon, 26 Jul 1997 05:00:00 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/admin-dev/themes/default/template/controllers/carrier_wizard/helpers/index.php b/admin-dev/themes/default/template/controllers/carrier_wizard/helpers/index.php new file mode 100644 index 000000000..063209789 --- /dev/null +++ b/admin-dev/themes/default/template/controllers/carrier_wizard/helpers/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header('Expires: Mon, 26 Jul 1997 05:00:00 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/admin-dev/themes/default/template/controllers/carrier_wizard/helpers/view/index.php b/admin-dev/themes/default/template/controllers/carrier_wizard/helpers/view/index.php new file mode 100644 index 000000000..30839633c --- /dev/null +++ b/admin-dev/themes/default/template/controllers/carrier_wizard/helpers/view/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header('Expires: Mon, 26 Jul 1997 05:00:00 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/admin-dev/themes/default/template/controllers/carrier_wizard/helpers/view/view.tpl b/admin-dev/themes/default/template/controllers/carrier_wizard/helpers/view/view.tpl new file mode 100644 index 000000000..b7b7d49f0 --- /dev/null +++ b/admin-dev/themes/default/template/controllers/carrier_wizard/helpers/view/view.tpl @@ -0,0 +1,66 @@ +{* +* 2007-2013 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +{extends file="helpers/view/view.tpl"} +{block name="override_tpl"} + +
+ + {foreach from=$wizard_contents.contents key=step_nbr item=content} +
+ {$content} +
+ {/foreach} +
+{/block} diff --git a/admin-dev/themes/default/template/controllers/carrier_wizard/logo.tpl b/admin-dev/themes/default/template/controllers/carrier_wizard/logo.tpl new file mode 100644 index 000000000..f947c9762 --- /dev/null +++ b/admin-dev/themes/default/template/controllers/carrier_wizard/logo.tpl @@ -0,0 +1,91 @@ +{* +* 2007-2013 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + + + + \ No newline at end of file diff --git a/admin-dev/themes/default/template/controllers/carrier_wizard/summary.tpl b/admin-dev/themes/default/template/controllers/carrier_wizard/summary.tpl new file mode 100644 index 000000000..fbad12c22 --- /dev/null +++ b/admin-dev/themes/default/template/controllers/carrier_wizard/summary.tpl @@ -0,0 +1,68 @@ +{* +* 2007-2013 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + + +
+
+ {l s='Carrier name:'} +
 
+
+
 
+
+
 
+
+
 
+
+ {l s='This carrier will be proposed for those delivery zones:'} +
    +
    +
     
    +
    + {l s='And it will be proposed for those client groups:'} +
      +
      + {if $is_multishop} +
       
      +
      + {l s='Finally, this carrier will be proposed in those shops:'} +
        +
        + {/if} +
         
        + {$active_form} +
        +
        +
         
        + diff --git a/admin-dev/themes/default/template/controllers/carriers/helpers/list/list_content.tpl b/admin-dev/themes/default/template/controllers/carriers/helpers/list/list_content.tpl new file mode 100644 index 000000000..a106c0b2f --- /dev/null +++ b/admin-dev/themes/default/template/controllers/carriers/helpers/list/list_content.tpl @@ -0,0 +1,40 @@ +{* +* 2007-2013 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +{extends file="helpers/list/list_content.tpl"} + {block name="open_td"} + + {else} + > + {/if} + {/block} diff --git a/admin-dev/themes/default/template/controllers/categories/helpers/form/form.tpl b/admin-dev/themes/default/template/controllers/categories/helpers/form/form.tpl index cfc2cf8df..633751d07 100644 --- a/admin-dev/themes/default/template/controllers/categories/helpers/form/form.tpl +++ b/admin-dev/themes/default/template/controllers/categories/helpers/form/form.tpl @@ -34,7 +34,7 @@ {if $shared_category}

        {l s='If you delete this picture, it will be deleted in all of your shared shops!'}

        {/if} -
        +
        {l s='Delete'} {l s='Delete'} @@ -71,4 +71,4 @@ {$input.customer}

        {/if} -{/block} +{/block} \ No newline at end of file diff --git a/admin-dev/themes/default/template/controllers/categories/helpers/list/list_header.tpl b/admin-dev/themes/default/template/controllers/categories/helpers/list/list_header.tpl index 60f8494ae..bedd47b5f 100644 --- a/admin-dev/themes/default/template/controllers/categories/helpers/list/list_header.tpl +++ b/admin-dev/themes/default/template/controllers/categories/helpers/list/list_header.tpl @@ -33,7 +33,7 @@   {assign var=params_url value=""} {else} - {assign var=params_url value="&id_category={$category.id_category}&viewcategory"} + {assign var=params_url value="&id_category={$category.id_category|intval}&viewcategory"} {/if} {if $category.id_category == $categories_tree_current_id} {$category.name} @@ -43,7 +43,7 @@ {/foreach} {if isset($delete_category) && $delete_category} -
        +

        {if $need_delete_mode} @@ -74,10 +74,10 @@ {if $key != 'deleteMode'} {if is_array($value)} {foreach $value as $val} - + {/foreach} {else} - + {/if} {/if} {/foreach} diff --git a/admin-dev/themes/default/template/controllers/countries/helpers/form/form.tpl b/admin-dev/themes/default/template/controllers/countries/helpers/form/form.tpl index 14ecde6ad..88f0278cf 100644 --- a/admin-dev/themes/default/template/controllers/countries/helpers/form/form.tpl +++ b/admin-dev/themes/default/template/controllers/countries/helpers/form/form.tpl @@ -48,6 +48,21 @@

        {else} {$smarty.block.parent} + {/if} +{/block} +{block name="label"} + {if $input.name == 'standardization'} + + {else} + {$smarty.block.parent} {/if} {/block} @@ -85,7 +100,11 @@ $('#need_zip_code_on, #need_zip_code_off').change(function() { disableZipFormat(); }); - + + $('#iso_code').change(function() { + disableTAASC(); + }); + disableTAASC(); }); function switchExplanationText(text) { diff --git a/admin-dev/themes/default/template/controllers/customers/helpers/list/list_header.tpl b/admin-dev/themes/default/template/controllers/customers/helpers/list/list_header.tpl index 39fec4f95..59c39e4e9 100644 --- a/admin-dev/themes/default/template/controllers/customers/helpers/list/list_header.tpl +++ b/admin-dev/themes/default/template/controllers/customers/helpers/list/list_header.tpl @@ -35,7 +35,7 @@ {/block} {block name=leadin} {if isset($delete_customer) && $delete_customer} - +

        {l s='How do you want to delete these customer(s)?'}

        {l s='There are two ways of deleting a customer. Please choose your preferred method.'}

        @@ -52,10 +52,10 @@ {foreach $POST as $key => $value} {if is_array($value)} {foreach $value as $val} - + {/foreach} {else} - + {/if} {/foreach}
        diff --git a/admin-dev/themes/default/template/controllers/customers/helpers/view/view.tpl b/admin-dev/themes/default/template/controllers/customers/helpers/view/view.tpl index b2f16ade3..9a0b01041 100644 --- a/admin-dev/themes/default/template/controllers/customers/helpers/view/view.tpl +++ b/admin-dev/themes/default/template/controllers/customers/helpers/view/view.tpl @@ -149,7 +149,7 @@
        -

        {l s='Vouchers'} ({count($discounts)})

        {if count($discounts)} @@ -488,4 +488,4 @@ {/block} -
         
        \ No newline at end of file +
         
        diff --git a/admin-dev/themes/default/template/controllers/employees/helpers/form/form.tpl b/admin-dev/themes/default/template/controllers/employees/helpers/form/form.tpl index 395e949d0..e9a05e5f1 100644 --- a/admin-dev/themes/default/template/controllers/employees/helpers/form/form.tpl +++ b/admin-dev/themes/default/template/controllers/employees/helpers/form/form.tpl @@ -60,7 +60,7 @@ ifSuperAdmin($(this)); $.ajax({ - url: "{$link->getAdminLink('AdminEmployees')}", + url: "{$link->getAdminLink('AdminEmployees')|addslashes}", cache: false, data : { ajax : '1', diff --git a/admin-dev/themes/default/template/controllers/groups/helpers/form/form.tpl b/admin-dev/themes/default/template/controllers/groups/helpers/form/form.tpl index acb52c2e8..0a14884db 100644 --- a/admin-dev/themes/default/template/controllers/groups/helpers/form/form.tpl +++ b/admin-dev/themes/default/template/controllers/groups/helpers/form/form.tpl @@ -106,63 +106,61 @@ if ($(this).attr('name') == 'category_reduction['+$('[name="id_category"]:checked').val()+']') { exist = true; - jAlert('{l s='This category already exists for this group.'}'); + jAlert('{l s='This category already exists for this group.' js=1}'); return false; } - }); if (exist) return; $.ajax({ - type:"POST", - url: "ajax-tab.php", - async: true, - dataType: "json", - data : { - ajax: "1", - token: "{getAdminToken tab='AdminGroups'}", - controller: "AdminGroups", - action: "addCategoryReduction", - category_reduction: $('#category_reduction_fancybox').val() , - id_category: $('[name="id_category"]:checked').val() - }, - success : function(jsonData) + type:"POST", + url: "ajax-tab.php", + async: true, + dataType: "json", + data : { + ajax: "1", + token: "{getAdminToken tab='AdminGroups'}", + controller: "AdminGroups", + action: "addCategoryReduction", + category_reduction: $('#category_reduction_fancybox').val() , + id_category: $('[name="id_category"]:checked').val() + }, + success : function(jsonData) { + if (jsonData.hasError) { - if (jsonData.hasError) - { - var errors = ''; - for(error in jsonData.errors) - //IE6 bug fix - if(error != 'indexOf') - errors += jsonData.errors[error] + "\n"; - jAlert(errors); - } - else - { - $('#group_discount_category_table').append(''); - - var input_hidden = document.createElement("input"); - input_hidden.setAttribute('type', 'hidden'); - input_hidden.setAttribute('value', jsonData.discount); - input_hidden.setAttribute('name', 'category_reduction['+jsonData.id_category+']'); - input_hidden.setAttribute('class', 'category_reduction'); - - $('#group_discount_category_table tr#'+jsonData.id_category+' > td:last').append(input_hidden); - $.fancybox.close(); - } + var errors = ''; + for (error in jsonData.errors) + //IE6 bug fix + if (error != 'indexOf') + errors += $('
        ').html(jsonData.errors[error]).text() + "\n"; + jAlert(errors); } - }); + else + { + $('#group_discount_category_table').append('
        '); + + var input_hidden = document.createElement("input"); + input_hidden.setAttribute('type', 'hidden'); + input_hidden.setAttribute('value', jsonData.discount); + input_hidden.setAttribute('name', 'category_reduction['+jsonData.id_category+']'); + input_hidden.setAttribute('class', 'category_reduction'); + + $('#group_discount_category_table tr#'+jsonData.id_category+' > td:last').append(input_hidden); + $.fancybox.close(); + } + } + }); return false; } - function initFancyBox() - { - $('[name="id_category"]:checked').removeAttr('checked'); - collapseAllCategories(); - $('#category_reduction_fancybox').val('0.00'); - } + function initFancyBox() + { + $('[name="id_category"]:checked').removeAttr('checked'); + collapseAllCategories(); + $('#category_reduction_fancybox').val('0.00'); + }
        {l s='Add a category discount'} @@ -270,4 +268,4 @@ {else} {$smarty.block.parent} {/if} -{/block} \ No newline at end of file +{/block} diff --git a/admin-dev/themes/default/template/controllers/home/content.tpl b/admin-dev/themes/default/template/controllers/home/content.tpl index df2d03d7f..35740fa6e 100644 --- a/admin-dev/themes/default/template/controllers/home/content.tpl +++ b/admin-dev/themes/default/template/controllers/home/content.tpl @@ -223,7 +223,7 @@ $(document).ready(function() { $.fancybox( this.href, { - 'width' : 660, + 'width' : 920, 'height' : 384, 'transitionIn' : 'none', 'transitionOut' : 'none', diff --git a/admin-dev/themes/default/template/controllers/import/helpers/form/form.tpl b/admin-dev/themes/default/template/controllers/import/helpers/form/form.tpl index 7f270fa20..059ccfdd2 100644 --- a/admin-dev/themes/default/template/controllers/import/helpers/form/form.tpl +++ b/admin-dev/themes/default/template/controllers/import/helpers/form/form.tpl @@ -50,14 +50,14 @@ console.log(truncateAuthorized); if (truncateAuthorized) { - if (!confirm('{l s='Are you sure that you would like to delete this' js=1}' + ' ' + $.trim($('#entity > option:selected').text().toLowerCase()) + '{l s='?' js=1}')) + if (!confirm('{l s='Are you sure that you would like to delete this' js=1}' + ' ' + $.trim($('#entity > option:selected').text().toLowerCase()) + '?')) { e.preventDefault(); } } else { - jAlert('{l s='You do not have permission to delete here. When the multistore is enabled, only a SuperAdmin can delete all items before an import.'}'); + jAlert('{l s='You do not have permission to delete here. When the multistore is enabled, only a SuperAdmin can delete all items before an import.' js=1}'); return false; } } diff --git a/admin-dev/themes/default/template/controllers/import/helpers/view/view.tpl b/admin-dev/themes/default/template/controllers/import/helpers/view/view.tpl index 12a8f5850..618d1a819 100644 --- a/admin-dev/themes/default/template/controllers/import/helpers/view/view.tpl +++ b/admin-dev/themes/default/template/controllers/import/helpers/view/view.tpl @@ -58,7 +58,7 @@
        - {l s='Skip'} {l s='lines'} + {l s='Skip'} {l s='lines'} diff --git a/admin-dev/themes/default/template/controllers/information/helpers/view/view.tpl b/admin-dev/themes/default/template/controllers/information/helpers/view/view.tpl index 782c4b834..d11e4721c 100644 --- a/admin-dev/themes/default/template/controllers/information/helpers/view/view.tpl +++ b/admin-dev/themes/default/template/controllers/information/helpers/view/view.tpl @@ -32,7 +32,7 @@ { $.ajax({ type: 'GET', - url: '{$link->getAdminLink('AdminInformation')}', + url: '{$link->getAdminLink('AdminInformation')|addslashes}', data: { 'action': 'checkFiles', 'ajax': 1 diff --git a/admin-dev/themes/default/template/controllers/login/content.tpl b/admin-dev/themes/default/template/controllers/login/content.tpl index 784fdec19..047f6bf5f 100755 --- a/admin-dev/themes/default/template/controllers/login/content.tpl +++ b/admin-dev/themes/default/template/controllers/login/content.tpl @@ -49,14 +49,14 @@
        - +
        - +
        - +

        diff --git a/admin-dev/themes/default/template/controllers/modules/list.tpl b/admin-dev/themes/default/template/controllers/modules/list.tpl index aaee81658..7dd84356f 100644 --- a/admin-dev/themes/default/template/controllers/modules/list.tpl +++ b/admin-dev/themes/default/template/controllers/modules/list.tpl @@ -77,7 +77,7 @@

        {if isset($module->description) && $module->description ne ''}{l s='Description'} : {$module->description}{else} {/if}

        - {if isset($module->message)}
        {$module->message}
        {/if} + {if isset($module->message) && (!isset($module->type) || ($module->type != 'addonsMustHave' || $module->type !== 'addonsNative'))}
        {$module->message}
        {/if}
        {if !isset($module->not_on_disk)} {$module->optionsHtml} diff --git a/admin-dev/themes/default/template/controllers/modules/page.tpl b/admin-dev/themes/default/template/controllers/modules/page.tpl index ea759f137..00e197055 100644 --- a/admin-dev/themes/default/template/controllers/modules/page.tpl +++ b/admin-dev/themes/default/template/controllers/modules/page.tpl @@ -58,7 +58,7 @@ {foreach from=$list_modules_categories item=module_category key=module_category_key} {/foreach} diff --git a/admin-dev/themes/default/template/controllers/modules/tab_module_line.tpl b/admin-dev/themes/default/template/controllers/modules/tab_module_line.tpl index 8c860d2e8..044183bf6 100644 --- a/admin-dev/themes/default/template/controllers/modules/tab_module_line.tpl +++ b/admin-dev/themes/default/template/controllers/modules/tab_module_line.tpl @@ -31,10 +31,10 @@
        - + {if $display_warehouse}{/if} {if ($order->hasBeenPaid())}{/if} {if ($order->hasBeenDelivered() || $order->hasProductReturned())}{/if} {if $stock_management}{/if} @@ -103,6 +104,7 @@ {/if} + {if $display_warehouse}{/if} {if ($order->hasBeenPaid())}{/if} {if ($order->hasBeenDelivered())}{/if} diff --git a/admin-dev/themes/default/template/controllers/orders/_new_product.tpl b/admin-dev/themes/default/template/controllers/orders/_new_product.tpl index 44027fb81..381be5cdc 100644 --- a/admin-dev/themes/default/template/controllers/orders/_new_product.tpl +++ b/admin-dev/themes/default/template/controllers/orders/_new_product.tpl @@ -40,6 +40,7 @@ {if ($order->hasBeenPaid())}{/if} + {if $display_warehouse}{/if} {if ($order->hasBeenDelivered())}{/if} diff --git a/admin-dev/themes/default/template/controllers/orders/_product_line.tpl b/admin-dev/themes/default/template/controllers/orders/_product_line.tpl index f16827cc4..930f907be 100755 --- a/admin-dev/themes/default/template/controllers/orders/_product_line.tpl +++ b/admin-dev/themes/default/template/controllers/orders/_product_line.tpl @@ -56,6 +56,7 @@ {/if} + {if $display_warehouse}{/if} {if ($order->hasBeenPaid())} '); + $('#condition_group_'+current_id_condition_group+' table tbody').append(''); $('#condition_group_'+current_id_condition_group+' table tbody').append(html); } @@ -284,7 +291,7 @@ $(document).ready(function() { $('#id_attribute_group option[value="{$condition.id_attribute_group}"]').attr('selected', true); $('#id_attribute_{$condition.id_attribute_group} option[value="{$condition.value}"]').attr('selected', true); {elseif $condition.type == 'feature'} - $('#id_feature[value="{$condition.id_feature}"]').attr('selected', true); + $('#id_feature option[value="{$condition.id_feature}"]').attr('selected', true); $('#id_feature_{$condition.id_feature} option[value="{$condition.value}"]').attr('selected', true); {else} $('#id_{$condition.type} option[value="{$condition.value}"]').attr('selected', true); diff --git a/admin-dev/themes/default/template/controllers/stats/calendar.tpl b/admin-dev/themes/default/template/controllers/stats/calendar.tpl index 31e607224..7e96f3a7e 100644 --- a/admin-dev/themes/default/template/controllers/stats/calendar.tpl +++ b/admin-dev/themes/default/template/controllers/stats/calendar.tpl @@ -25,7 +25,7 @@
        -
        + @@ -51,4 +51,4 @@ }); }); -
        \ No newline at end of file +
        diff --git a/admin-dev/themes/default/template/controllers/suppliers/helpers/view/view.tpl b/admin-dev/themes/default/template/controllers/suppliers/helpers/view/view.tpl index 8ce702b06..fec2106d7 100644 --- a/admin-dev/themes/default/template/controllers/suppliers/helpers/view/view.tpl +++ b/admin-dev/themes/default/template/controllers/suppliers/helpers/view/view.tpl @@ -30,55 +30,44 @@

        {$supplier->name}

        {l s='Number of products:'} {count($products)}

        +
        '+jsonData.catPath+'{l s='Discount:'}'+jsonData.discount+'{l s='%'}
        '+jsonData.catPath+'{l s='Discount:'}'+jsonData.discount+'{l s='%'}
        +

        - {$module->displayName|truncate:40:'…'} {$module->version} + {$module->displayName|truncate:36:'…'} {$module->version} {if isset($module->id) && $module->id gt 0 } {if $module->active} {l s='Enabled'} @@ -52,7 +52,7 @@

        {if isset($module->description) && $module->description ne ''} - {$module->description|truncate:100:'…'} + {$module->description|truncate:86:'…'} {else}   {/if} diff --git a/admin-dev/themes/default/template/controllers/modules_positions/form.tpl b/admin-dev/themes/default/template/controllers/modules_positions/form.tpl index ebd8d9dbc..39eca9ff9 100644 --- a/admin-dev/themes/default/template/controllers/modules_positions/form.tpl +++ b/admin-dev/themes/default/template/controllers/modules_positions/form.tpl @@ -26,7 +26,7 @@ {include file="toolbar.tpl" toolbar_btn=$toolbar_btn toolbar_scroll=$toolbar_scroll title=$title}

        {block name="leadin"}{/block}
        - + {if $display_key} {/if} @@ -49,38 +49,10 @@ *
        - -
        + {l s='Please specify the files for which you do not want the module to be displayed.'}
        + {l s='Please input each filename, separated by a comma.'}
        {if !$except_diff} {$exception_list} {else} @@ -88,9 +60,6 @@ {$value} {/foreach} {/if} - {l s='Please specify the files for which you do not want the module to be displayed.'}.
        - {l s='Please input each filename, separated by a comma.'}. -

        @@ -102,4 +71,40 @@
        * {l s='Required field'}
        - \ No newline at end of file + + \ No newline at end of file diff --git a/admin-dev/themes/default/template/controllers/not_found/content.tpl b/admin-dev/themes/default/template/controllers/not_found/content.tpl index 67933528c..cd836c0ea 100644 --- a/admin-dev/themes/default/template/controllers/not_found/content.tpl +++ b/admin-dev/themes/default/template/controllers/not_found/content.tpl @@ -22,7 +22,9 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) * International Registered Trademark & Property of PrestaShop SA *} +{if isset($controller) && !empty($controller) && $controller != 'adminnotfound'}

        {l s='The controller %s is missing or invalid.' sprintf=$controller}

        +{/if}
        • {l s='Go to the dashboard.'}
        • {l s='Back to the previous page.'}
        • diff --git a/admin-dev/themes/default/template/controllers/orders/_customized_data.tpl b/admin-dev/themes/default/template/controllers/orders/_customized_data.tpl index 7e5b10b7e..7740fcdce 100755 --- a/admin-dev/themes/default/template/controllers/orders/_customized_data.tpl +++ b/admin-dev/themes/default/template/controllers/orders/_customized_data.tpl @@ -45,6 +45,7 @@ {/if}
        {$product['customizationQuantityTotal']} {$product['customizationQuantityRefunded']}{$product['customizationQuantityReturned']} -  {$customization['quantity_refunded']}{$customization['quantity_returned']} diff --git a/admin-dev/themes/default/template/controllers/orders/_documents.tpl b/admin-dev/themes/default/template/controllers/orders/_documents.tpl index 54b1e8599..47671da59 100644 --- a/admin-dev/themes/default/template/controllers/orders/_documents.tpl +++ b/admin-dev/themes/default/template/controllers/orders/_documents.tpl @@ -68,9 +68,9 @@ {/if} {if get_class($document) eq 'OrderInvoice'} {if isset($document->is_delivery)} - #{Configuration::get('PS_DELIVERY_PREFIX', $current_id_lang)}{'%06d'|sprintf:$document->delivery_number} + #{Configuration::get('PS_DELIVERY_PREFIX', $current_id_lang, null, $order->id_shop)}{'%06d'|sprintf:$document->delivery_number} {else} - {$document->getInvoiceNumberFormatted($current_id_lang)} + {$document->getInvoiceNumberFormatted($current_id_lang, $order->id_shop)} {/if} {elseif get_class($document) eq 'OrderSlip'} #{Configuration::get('PS_CREDIT_SLIP_PREFIX', $current_id_lang)}{'%06d'|sprintf:$document->id} @@ -110,7 +110,7 @@ {if !isset($document->is_delivery)}
          {$product.warehouse_name|escape:'htmlall':'UTF-8'} {$product['product_quantity_refunded']} diff --git a/admin-dev/themes/default/template/controllers/orders/_shipping.tpl b/admin-dev/themes/default/template/controllers/orders/_shipping.tpl index ca22c24c1..d9807c089 100644 --- a/admin-dev/themes/default/template/controllers/orders/_shipping.tpl +++ b/admin-dev/themes/default/template/controllers/orders/_shipping.tpl @@ -24,11 +24,11 @@ *} - - - - - + + + + + @@ -46,7 +46,7 @@ - + diff --git a/admin-dev/themes/default/template/controllers/request_sql/helpers/form/form.tpl b/admin-dev/themes/default/template/controllers/request_sql/helpers/form/form.tpl index d23e8c976..aaf7da7d1 100644 --- a/admin-dev/themes/default/template/controllers/request_sql/helpers/form/form.tpl +++ b/admin-dev/themes/default/template/controllers/request_sql/helpers/form/form.tpl @@ -90,7 +90,7 @@ var table = $('#selectTables select').val(); if (!table) - jAlert("{l s='Please choose a table.'}"); + jAlert("{l s='Please choose a table.' js=1}"); else AddRequestSql(table); }); diff --git a/admin-dev/themes/default/template/controllers/shipping/content.tpl b/admin-dev/themes/default/template/controllers/shipping/content.tpl deleted file mode 100644 index 4ab2ff01a..000000000 --- a/admin-dev/themes/default/template/controllers/shipping/content.tpl +++ /dev/null @@ -1,105 +0,0 @@ -{* -* 2007-2013 PrestaShop -* -* NOTICE OF LICENSE -* -* This source file is subject to the Academic Free License (AFL 3.0) -* that is bundled with this package in the file LICENSE.txt. -* It is also available through the world-wide-web at this URL: -* http://opensource.org/licenses/afl-3.0.php -* If you did not receive a copy of the license and are unable to -* obtain it through the world-wide-web, please send an email -* to license@prestashop.com so we can send you a copy immediately. -* -* DISCLAIMER -* -* Do not edit or add to this file if you wish to upgrade PrestaShop to newer -* versions in the future. If you wish to customize PrestaShop for your -* needs please refer to http://www.prestashop.com for more information. -* -* @author PrestaShop SA -* @copyright 2007-2013 PrestaShop SA -* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) -* International Registered Trademark & Property of PrestaShop SA -*} - -{$content} -

        -

        {l s='Fees by carrier, geographical zone and ranges'}

        - -
        - {l s='Fees'} - {if empty($carriers)} - {l s='If you only have free carriers, there\'s no need to configure delivery prices.'} - {else} - {l s='Carrier:'} -
        - -
        {dateFormat date=$line.date_add full=true} {$line.type} {$line.carrier_name}{$line.weight|string_format:"%.3f"} {Configuration::get('PS_WEIGHT_UNIT')}{$line.weight|string_format:"%.3f"} {Configuration::get('PS_WEIGHT_UNIT')} {if $order->getTaxCalculationMethod() == $smarty.const.PS_TAX_INC} {displayPrice price=$line.shipping_cost_tax_incl currency=$currency->id} @@ -55,7 +55,7 @@ {/if} - {if $line.url && $line.tracking_number}{$line.tracking_number}{else}{$line.tracking_number}{/if} + {if $line.url && $line.tracking_number}{$line.tracking_number}{else}{$line.tracking_number}{/if} {if $line.can_edit} {$product->productDownload->getHtmlLink(false, true)} - + {l s='Delete this file'}
        - - - {if !$carrierSelected->is_free} - {foreach $ranges AS $range} - - {/foreach} - {/if} - - {if sizeof($ranges) && !$carrierSelected->is_free} - {if sizeof($zones) > 1} - - - {foreach $ranges AS $range} - - {/foreach} - - {/if} - - {foreach $zones AS $zone} - - - {foreach $ranges AS $range} - {if isset($deliveryArray[$zone['id_zone']][$id_carrier][$range[$rangeIdentifier]])} - {$price = $deliveryArray[$zone['id_zone']][$id_carrier][$range[$rangeIdentifier]]} - {else} - {$price = '0.00'} - {/if} - - {/foreach} - - {/foreach} - {/if} - - - -
        {l s='Zone / Range'}{$range['delimiter1']|floatval}{$suffix} {l s='to'} {$range['delimiter2']|floatval}{$suffix}
        {l s='All'} - {$currency->getSign('left')} - - {$currency->getSign('right')} {l s='(tax excl.)'} -
        {$zone['name']} - {$currency->getSign('left')} - - {$currency->getSign('right')} {l s='(tax excl.)'} -
        - - {if sizeof($ranges) && !$carrierSelected->is_free} - - {else if $carrierSelected->is_free} - {l s='This is a free carrier'} - {else} - {l s='No ranges is set for this carrier'} - {/if} -
        - {/if} - - - diff --git a/admin-dev/themes/default/template/controllers/shop/helpers/list/list_action_delete.tpl b/admin-dev/themes/default/template/controllers/shop/helpers/list/list_action_delete.tpl index 197faa431..649b9df26 100644 --- a/admin-dev/themes/default/template/controllers/shop/helpers/list/list_action_delete.tpl +++ b/admin-dev/themes/default/template/controllers/shop/helpers/list/list_action_delete.tpl @@ -24,9 +24,9 @@ *} {$action} \ No newline at end of file diff --git a/admin-dev/themes/default/template/controllers/shop/tree.tpl b/admin-dev/themes/default/template/controllers/shop/tree.tpl index 25fba6604..8019d0174 100644 --- a/admin-dev/themes/default/template/controllers/shop/tree.tpl +++ b/admin-dev/themes/default/template/controllers/shop/tree.tpl @@ -186,7 +186,7 @@ $("#multishop-tree").jstree({ 'plugins': ["themes","json_data","cookies","contextmenu"], 'json_data': { 'ajax': { - 'url': "{$link->getAdminLink('AdminShop')}", + 'url': "{$link->getAdminLink('AdminShop')|addslashes}", 'data': function(n) { return { diff --git a/admin-dev/themes/default/template/controllers/specific_price_rule/helpers/form/form.tpl b/admin-dev/themes/default/template/controllers/specific_price_rule/helpers/form/form.tpl index da734f23b..5e8d4e00d 100755 --- a/admin-dev/themes/default/template/controllers/specific_price_rule/helpers/form/form.tpl +++ b/admin-dev/themes/default/template/controllers/specific_price_rule/helpers/form/form.tpl @@ -161,6 +161,13 @@ function add_condition(id_condition_group, type, value) function delete_condition(condition) { delete conditions[condition]; + + to_delete = $('#'+condition).prev(); + if ($(to_delete).children().hasClass('btn_delete_condition')) + $(to_delete).remove(); + else + $('#'+condition).next().remove(); + $('#'+condition).remove(); return false; } @@ -178,7 +185,7 @@ function new_condition_group() function appendConditionToGroup(html) { if ($('#condition_group_'+current_id_condition_group+' table tbody tr').length > 0) - $('#condition_group_'+current_id_condition_group+' table tbody').append('
        {l s='AND' js=1}
        {l s='AND' js=1}
        + + + + + + + + + {if $stock_management && $shopContext != Shop::CONTEXT_ALL}{/if} + {foreach $products AS $product} -
        {if !$product->hasAttributes()} -
        {l s='Product name'}{l s='Attribute name'}{l s='Supplier Reference'}{l s='Wholesale price'}{l s='Reference'}{l s='EAN13'}{l s='UPC'}{l s='Available Quantity'}
        - - - {if !empty($product->product_supplier_reference)}{/if} - {if !empty($product->product_supplier_price_te)}{/if} - {if !empty($product->reference)}{/if} - {if !empty($product->ean13)}{/if} - {if !empty($product->upc)}{/if} - {if $stock_management}{/if} - -
        {l s='Name'} {$product->name}{l s='Supplier Reference:'} {$product->product_supplier_reference}{l s='Wholesale price:'} {$product->product_supplier_price_te}{l s='Reference:'} {$product->reference}{l s='EAN13:'} {$product->ean13}{l s='UPC:'} {$product->upc}{l s='Available Quantity:'} {$product->quantity}
        + + {$product->name} + {l s='N/A'} + {if empty($product->product_supplier_reference)}{l s='N/A'}{else}{$product->product_supplier_reference}{/if} + {if empty($product->product_supplier_price_te)}0{else}{$product->product_supplier_price_te}{/if} + {if empty($product->reference)}{l s='N/A'}{else}{$product->reference}{/if} + {if empty($product->ean13)}{l s='N/A'}{else}{$product->ean13}{/if} + {if empty($product->upc)}{l s='N/A'}{else}{$product->upc}{/if} + {if $stock_management && $shopContext != Shop::CONTEXT_ALL}{$product->quantity}{/if} + {else} -

        {$product->name}

        - - - - - - - - - - - - - - - - - - {if $stock_management && $shopContext != Shop::CONTEXT_ALL}{/if} + {foreach $product->combination AS $id_product_attribute => $product_attribute} + + + + + + + + + {if $stock_management && $shopContext != Shop::CONTEXT_ALL}{/if} - {foreach $product->combination AS $id_product_attribute => $product_attribute} - - - - - - - - {if $stock_management && $shopContext != Shop::CONTEXT_ALL}{/if} - - {/foreach} -
        {l s='Attribute name'}{l s='Supplier Reference'}{l s='Wholesale price'}{l s='Reference'}{l s='EAN13'}{l s='UPC'}{l s='Available Quantity'}
        {$product->name}{if empty($product_attribute.attributes)}{l s='N/A'}{else}{$product_attribute.attributes}{/if}{if empty($product_attribute.product_supplier_reference)}{l s='N/A'}{else}{$product_attribute.product_supplier_reference}{/if}{if empty($product_attribute.product_supplier_price_te)}0{else}{$product_attribute.product_supplier_price_te}{/if}{if empty($product_attribute.reference)}{l s='N/A'}{else}{$product_attribute.reference}{/if}{if empty($product_attribute.ean13)}{l s='N/A'}{else}{$product_attribute.ean13}{/if}{if empty($product_attribute.upc)}{l s='N/A'}{else}{$product_attribute.upc}{/if}{$product_attribute.quantity}
        {$product_attribute.attributes}{$product_attribute.product_supplier_reference}{$product_attribute.product_supplier_price_te}{$product_attribute.reference}{$product_attribute.ean13}{$product_attribute.upc}{$product_attribute.quantity}
        + {/foreach} {/if} {/foreach} - + {/block} diff --git a/admin-dev/themes/default/template/controllers/supply_orders/helpers/form/form.tpl b/admin-dev/themes/default/template/controllers/supply_orders/helpers/form/form.tpl index 79f38f94b..06d43e078 100644 --- a/admin-dev/themes/default/template/controllers/supply_orders/helpers/form/form.tpl +++ b/admin-dev/themes/default/template/controllers/supply_orders/helpers/form/form.tpl @@ -138,7 +138,7 @@ // check if it's possible to add the product if (product_infos == null || $('#cur_product_name').val() == '') { - jAlert('{l s='Please select at least one product.'}'); + jAlert('{l s='Please select at least one product.' js=1}'); return false; } diff --git a/admin-dev/themes/default/template/controllers/translations/helpers/view/translation_modules.tpl b/admin-dev/themes/default/template/controllers/translations/helpers/view/translation_modules.tpl index 81fae60f5..4455c007a 100644 --- a/admin-dev/themes/default/template/controllers/translations/helpers/view/translation_modules.tpl +++ b/admin-dev/themes/default/template/controllers/translations/helpers/view/translation_modules.tpl @@ -92,7 +92,7 @@
        {foreach $modules_translations as $theme_name => $theme} -

        >{l s='Theme:'} {if $theme_name === $default_theme_name}{l s='default'}{else}{$theme_name}{/if}

        + {if $theme_name}

        >{l s='Theme:'} {$theme_name}

        {/if} {foreach $theme as $module_name => $module}

        {l s='Module:'} {$module_name}

        {foreach $module as $template_name => $newLang} @@ -107,7 +107,7 @@ {$missing_translations_module = 0} {/if}
        - {if $theme_name === 'default'}{l s='default'}{else}{$theme_name}{/if} - {$template_name} + {if $theme_name}{$theme_name} - {/if}{$template_name} {$newLang|count} {l s='expressions'} ({$missing_translations_module})
        diff --git a/admin-dev/themes/default/template/footer.tpl b/admin-dev/themes/default/template/footer.tpl index 8caf2c64a..5f2212a0d 100644 --- a/admin-dev/themes/default/template/footer.tpl +++ b/admin-dev/themes/default/template/footer.tpl @@ -35,11 +35,12 @@
        {if $iso_is_fr} - Questions / Renseignements / Formations : +33 (0)1.40.18.30.04 de 09h à 18h + Questions / Renseignements / Formations : +33 (0)1.40.18.30.04 {/if} - | {l s='Contact'} - | {l s='Bug Tracker'} - | {l s='Forum'} + | {l s='Contact'} + | {l s='Bug Tracker'} + | {l s='Forum'} + | {l s='Addons'}
        diff --git a/admin-dev/themes/default/template/header.tpl b/admin-dev/themes/default/template/header.tpl index dc80e8831..1ddf6bffc 100644 --- a/admin-dev/themes/default/template/header.tpl +++ b/admin-dev/themes/default/template/header.tpl @@ -69,6 +69,7 @@ var token_admin_customers = '{getAdminToken tab='AdminCustomers' slashes=1}'; var token_admin_customer_threads = '{getAdminToken tab='AdminCustomerThreads' slashes=1}'; var currentIndex = '{$currentIndex}'; + var choose_language_translate = "{l s='Choose language' slashes=1 }"; {/if} @@ -204,7 +205,7 @@ diff --git a/admin-dev/themes/default/template/helpers/form/form.tpl b/admin-dev/themes/default/template/helpers/form/form.tpl index 96d43a781..694486e03 100644 --- a/admin-dev/themes/default/template/helpers/form/form.tpl +++ b/admin-dev/themes/default/template/helpers/form/form.tpl @@ -30,7 +30,7 @@ {if isset($fields.title)}

        {$fields.title}

        {/if} {block name="defaultForm"} - + {if $form_id} {/if} @@ -234,17 +234,29 @@ {/foreach} {elseif $input.type == 'file'} {if isset($input.display_image) && $input.display_image} - {if isset($fields_value.image) && $fields_value.image} + {if isset($fields_value[$input.name].image) && $fields_value[$input.name].image}
        - {$fields_value.image} -

        {l s='File size'} {$fields_value.size}kb

        + {$fields_value[$input.name].image} +

        {l s='File size'} {$fields_value[$input.name].size}kb

        {l s='Delete'} {l s='Delete'}

        {/if} {/if} - + + {if isset($input.lang) AND $input.lang} +
        + {foreach $languages as $language} +
        + + +
        + {/foreach} +
        + {else} + + {/if} {if !empty($input.hint)}{$input.hint} {/if} {elseif $input.type == 'password'} {elseif $input.type == 'date'} diff --git a/admin-dev/themes/default/template/helpers/list/list_content.tpl b/admin-dev/themes/default/template/helpers/list/list_content.tpl index add0db76d..ae80d9d10 100644 --- a/admin-dev/themes/default/template/helpers/list/list_content.tpl +++ b/admin-dev/themes/default/template/helpers/list/list_content.tpl @@ -59,7 +59,7 @@ {block name="td_content"} {if isset($params.prefix)}{$params.prefix}{/if} {if isset($params.color) && isset($tr[$params.color])} - + {/if} {if isset($tr.$key)} {if isset($params.active)} diff --git a/admin-dev/themes/default/template/helpers/list/list_header.tpl b/admin-dev/themes/default/template/helpers/list/list_header.tpl index b8df4bd49..e861bce1e 100644 --- a/admin-dev/themes/default/template/helpers/list/list_header.tpl +++ b/admin-dev/themes/default/template/helpers/list/list_header.tpl @@ -27,8 +27,8 @@ @@ -37,7 +37,7 @@ @@ -45,8 +45,8 @@ + return ($live_edit ? '
        ' : '').$output.($live_edit ? '
        ' : '');// Return html string } @@ -445,13 +481,13 @@ class HookCore extends ObjectModel return '
        - - ' + + ' .Tools::safeOutput($moduleInstance->displayName).' - + '.$display.'
        '; } diff --git a/classes/ImageManager.php b/classes/ImageManager.php index c7500c8fd..c647b6ea3 100644 --- a/classes/ImageManager.php +++ b/classes/ImageManager.php @@ -407,6 +407,7 @@ class ImageManagerCore case 'jpeg': default: $quality = (Configuration::get('PS_JPEG_QUALITY') === false ? 90 : Configuration::get('PS_JPEG_QUALITY')); + imageinterlace($resource,1); /// make it PROGRESSIVE $success = imagejpeg($resource, $filename, (int)$quality); break; } diff --git a/classes/Language.php b/classes/Language.php index 3ce4b1908..361687432 100644 --- a/classes/Language.php +++ b/classes/Language.php @@ -70,7 +70,7 @@ class LanguageCore extends ObjectModel /** @var array Languages cache */ protected static $_checkedLangs; protected static $_LANGUAGES; - protected static $countActiveLanguages; + protected static $countActiveLanguages = array(); protected $webserviceParameters = array( 'objectNodeName' => 'language', @@ -262,7 +262,7 @@ class LanguageCore extends ObjectModel $mPath_to = _PS_MAIL_DIR_.(string)$iso_to.'/'; } - $lFiles = array('admin.php', 'errors.php', 'fields.php', 'pdf.php', 'tabs.php', 'index.php'); + $lFiles = array('admin.php', 'errors.php', 'fields.php', 'pdf.php', 'tabs.php'); // Added natives mails files $mFiles = array( @@ -273,7 +273,7 @@ class LanguageCore extends ObjectModel 'contact.html', 'contact.txt', 'contact_form.html', 'contact_form.txt', 'credit_slip.html', 'credit_slip.txt', - 'download_product.html', 'download_product.txt', 'download-product.tpl', + 'download_product.html', 'download_product.txt', 'employee_password.html', 'employee_password.txt', 'forward_msg.html', 'forward_msg.txt', 'guest_to_customer.html', 'guest_to_customer.txt', @@ -297,7 +297,7 @@ class LanguageCore extends ObjectModel 'test.html', 'test.txt', 'voucher.html', 'voucher.txt', 'voucher_new.html', 'voucher_new.txt', - 'order_changed.html', 'order_changed.txt', 'index.php' + 'order_changed.html', 'order_changed.txt' ); $number = -1; @@ -466,7 +466,7 @@ class LanguageCore extends ObjectModel public function delete() { - if (!$this->hasMultishopEntries()) + if (!$this->hasMultishopEntries() || Shop::getContext() == Shop::CONTEXT_ALL) { if (empty($this->iso_code)) $this->iso_code = Language::getIsoById($this->id); @@ -514,7 +514,7 @@ class LanguageCore extends ObjectModel if (!parent::delete()) return false; - if (!$this->hasMultishopEntries()) + if (!$this->hasMultishopEntries() || Shop::getContext() == Shop::CONTEXT_ALL) { // delete images $files_copy = array( @@ -580,7 +580,7 @@ class LanguageCore extends ObjectModel public static function getLanguage($id_lang) { - if (!array_key_exists((int)($id_lang), self::$_LANGUAGES)) + if (!array_key_exists((int)$id_lang, self::$_LANGUAGES)) return false; return self::$_LANGUAGES[(int)($id_lang)]; } @@ -704,10 +704,8 @@ class LanguageCore extends ObjectModel $lang->name = $lang_pack->name; } elseif ($params_lang !== null && is_array($params_lang)) - { foreach ($params_lang as $key => $value) $lang->$key = $value; - } else return false; @@ -764,15 +762,18 @@ class LanguageCore extends ObjectModel return (isset(self::$_cache_language_installation[$iso_code]) ? self::$_cache_language_installation[$iso_code] : false); } - public static function countActiveLanguages() + public static function countActiveLanguages($id_shop = null) { - if (!self::$countActiveLanguages) - self::$countActiveLanguages = Db::getInstance()->getValue(' + if ($id_shop === null) + $id_shop = (int)Context::getContext()->shop->id; + + if (!isset(self::$countActiveLanguages[$id_shop])) + self::$countActiveLanguages[$id_shop] = Db::getInstance()->getValue(' SELECT COUNT(DISTINCT l.id_lang) FROM `'._DB_PREFIX_.'lang` l - '.Shop::addSqlAssociation('lang', 'l').' + JOIN '._DB_PREFIX_.'lang_shop lang_shop ON (lang_shop.id_lang = l.id_lang AND lang_shop.id_shop = '.(int)$id_shop.') WHERE l.`active` = 1 '); - return self::$countActiveLanguages; + return self::$countActiveLanguages[$id_shop]; } public static function downloadAndInstallLanguagePack($iso, $version = null, $params = null) @@ -788,11 +789,11 @@ class LanguageCore extends ObjectModel $lang_pack_ok = false; $errors = array(); $file = _PS_TRANSLATIONS_DIR_.$iso.'.gzip'; - if (!$lang_pack_link = Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/get_language_pack.php?version='.$version.'&iso_lang='.$iso)) + if (!$lang_pack_link = Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/get_language_pack.php?version='.$version.'&iso_lang='.Tools::strtolower($iso))) $errors[] = Tools::displayError('Archive cannot be downloaded from prestashop.com.'); elseif (!$lang_pack = Tools::jsonDecode($lang_pack_link)) $errors[] = Tools::displayError('Error occurred when language was checked according to your Prestashop version.'); - elseif ($content = Tools::file_get_contents('http://translations.prestashop.com/download/lang_packs/gzip/'.$lang_pack->version.'/'.$lang_pack->iso_code.'.gzip')) + elseif ($content = Tools::file_get_contents('http://translations.prestashop.com/download/lang_packs/gzip/'.$lang_pack->version.'/'.Tools::strtolower($lang_pack->iso_code.'.gzip'))) if (!@file_put_contents($file, $content)) $errors[] = Tools::displayError('Server does not have permissions for writing.'); if (file_exists($file)) @@ -827,8 +828,8 @@ class LanguageCore extends ObjectModel * @since 1.5.0 * @return bool */ - public static function isMultiLanguageActivated() + public static function isMultiLanguageActivated($id_shop = null) { - return (Language::countActiveLanguages() > 1); + return (Language::countActiveLanguages($id_shop) > 1); } -} +} \ No newline at end of file diff --git a/classes/Link.php b/classes/Link.php index 0a0c98322..21e6201ea 100644 --- a/classes/Link.php +++ b/classes/Link.php @@ -91,19 +91,19 @@ class LinkCore if (!$id_lang) $id_lang = Context::getContext()->language->id; - if (!$id_shop) - $shop = Context::getContext()->shop; - else + if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && $id_shop !== null) $shop = new Shop($id_shop); + else + $shop = Context::getContext()->shop; - $url = 'http://'.$shop->domain.$shop->getBaseURI().$this->getLangLink($id_lang); + $url = 'http://'.$shop->domain.$shop->getBaseURI().$this->getLangLink($id_lang, null, $id_shop); if (!is_object($product)) { if (is_array($product) && isset($product['id_product'])) - $product = new Product($product['id_product'], false, $id_lang); - else if (is_numeric($product) || !$product) - $product = new Product($product, false, $id_lang); + $product = new Product($product['id_product'], false, $id_lang, $id_shop); + elseif ((int)$product) + $product = new Product((int)$product, false, $id_lang, $id_shop); else throw new PrestaShopException('Invalid product vars'); } @@ -112,29 +112,30 @@ class LinkCore $params = array(); $params['id'] = $product->id; $params['rewrite'] = (!$alias) ? $product->getFieldByLang('link_rewrite') : $alias; + $params['ean13'] = (!$ean13) ? $product->ean13 : $ean13; $params['meta_keywords'] = Tools::str2url($product->getFieldByLang('meta_keywords')); $params['meta_title'] = Tools::str2url($product->getFieldByLang('meta_title')); - if ($dispatcher->hasKeyword('product_rule', $id_lang, 'manufacturer')) + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'manufacturer', $id_shop)) $params['manufacturer'] = Tools::str2url($product->isFullyLoaded ? $product->manufacturer_name : Manufacturer::getNameById($product->id_manufacturer)); - if ($dispatcher->hasKeyword('product_rule', $id_lang, 'supplier')) + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'supplier', $id_shop)) $params['supplier'] = Tools::str2url($product->isFullyLoaded ? $product->supplier_name : Supplier::getNameById($product->id_supplier)); - if ($dispatcher->hasKeyword('product_rule', $id_lang, 'price')) + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'price', $id_shop)) $params['price'] = $product->isFullyLoaded ? $product->price : Product::getPriceStatic($product->id, false, null, 6, null, false, true, 1, false, null, null, null, $product->specificPrice); - if ($dispatcher->hasKeyword('product_rule', $id_lang, 'tags')) + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'tags', $id_shop)) $params['tags'] = Tools::str2url($product->getTags($id_lang)); - if ($dispatcher->hasKeyword('product_rule', $id_lang, 'category')) - $params['category'] = !is_null($product->category) ? Tools::str2url($product->category) : Tools::str2url($category); + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'category', $id_shop)) + $params['category'] = (!is_null($product->category) && !empty($product->category)) ? Tools::str2url($product->category) : Tools::str2url($category); - if ($dispatcher->hasKeyword('product_rule', $id_lang, 'reference')) + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'reference', $id_shop)) $params['reference'] = Tools::str2url($product->reference); - if ($dispatcher->hasKeyword('product_rule', $id_lang, 'categories')) + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'categories', $id_shop)) { $params['category'] = (!$category) ? $product->category : $category; $cats = array(); @@ -145,7 +146,7 @@ class LinkCore } $anchor = $ipa ? $product->getAnchor($ipa) : ''; - return $url.$dispatcher->createUrl('product_rule', $id_lang, $params, $force_routes, $anchor); + return $url.$dispatcher->createUrl('product_rule', $id_lang, $params, $force_routes, $anchor, $id_shop); } /** @@ -157,11 +158,16 @@ class LinkCore * @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) + public function getCategoryLink($category, $alias = null, $id_lang = null, $selected_filters = null, $id_shop = null) { if (!$id_lang) $id_lang = Context::getContext()->language->id; - $url = _PS_BASE_URL_.__PS_BASE_URI__.$this->getLangLink($id_lang); + + if ($id_shop === null) + $shop = Context::getContext()->shop; + else + $shop = new Shop($id_shop); + $url = 'http://'.$shop->domain.$shop->getBaseURI().$this->getLangLink($id_lang, null, $id_shop); if (!is_object($category)) $category = new Category($category, $id_lang); @@ -184,7 +190,7 @@ class LinkCore $params['selected_filters'] = $selected_filters; } - return $url.Dispatcher::getInstance()->createUrl($rule, $id_lang, $params, $this->allow); + return $url.Dispatcher::getInstance()->createUrl($rule, $id_lang, $params, $this->allow, '', $id_shop); } /** @@ -195,24 +201,33 @@ class LinkCore * @param int $id_lang * @return string */ - public function getCMSCategoryLink($category, $alias = null, $id_lang = null) + public function getCMSCategoryLink($cms_category, $alias = null, $id_lang = null, $id_shop = null) { if (!$id_lang) $id_lang = Context::getContext()->language->id; - - $url = _PS_BASE_URL_.__PS_BASE_URI__.$this->getLangLink($id_lang); - if (!is_object($category)) - $category = new CMSCategory($category, $id_lang); + if ($id_shop === null) + $shop = Context::getContext()->shop; + else + $shop = new Shop($id_shop); + $url = 'http://'.$shop->domain.$shop->getBaseURI().$this->getLangLink($id_lang, null, $id_shop); + + $dispatcher = Dispatcher::getInstance(); + if (!is_object($cms_category)) + { + if ($alias !== null && !$dispatcher->hasKeyword('cms_category_rule', $id_lang, 'meta_keywords', $id_shop) && !$dispatcher->hasKeyword('cms_category_rule', $id_lang, 'meta_title', $id_shop)) + return $url.$dispatcher->createUrl('cms_category_rule', $id_lang, array('id' => (int)$cms_category, 'rewrite' => (string)$alias), $this->allow, '', $id_shop); + $cms_category = new CMSCategory($cms_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); + $params['id'] = $cms_category->id; + $params['rewrite'] = (!$alias) ? $cms_category->link_rewrite : $alias; + $params['meta_keywords'] = Tools::str2url($cms_category->meta_keywords); + $params['meta_title'] = Tools::str2url($cms_category->meta_title); - return $url.Dispatcher::getInstance()->createUrl('cms_category_rule', $id_lang, $params, $this->allow); + return $url.$dispatcher->createUrl('cms_category_rule', $id_lang, $params, $this->allow, '', $id_shop); } /** @@ -224,33 +239,42 @@ class LinkCore * @param int $id_lang * @return string */ - public function getCMSLink($cms, $alias = null, $ssl = false, $id_lang = null) + public function getCMSLink($cms, $alias = null, $ssl = false, $id_lang = null, $id_shop = null) { - $base = (($ssl && $this->ssl_enable) ? _PS_BASE_URL_SSL_ : _PS_BASE_URL_); + $base = (($ssl && $this->ssl_enable) ? 'https://' : 'http://'); if (!$id_lang) $id_lang = Context::getContext()->language->id; - $url = $base.__PS_BASE_URI__.$this->getLangLink($id_lang); + + if ($id_shop === null) + $shop = Context::getContext()->shop; + else + $shop = new Shop($id_shop); + $url = $base.$shop->domain.$shop->getBaseURI().$this->getLangLink($id_lang, null, $id_shop); + + $dispatcher = Dispatcher::getInstance(); if (!is_object($cms)) + { + if ($alias !== null && !$dispatcher->hasKeyword('cms_rule', $id_lang, 'meta_keywords', $id_shop) && !$dispatcher->hasKeyword('cms_rule', $id_lang, 'meta_title', $id_shop)) + return $url.$dispatcher->createUrl('cms_rule', $id_lang, array('id' => (int)$cms, 'rewrite' => (string)$alias), $this->allow, '', $id_shop); $cms = new CMS($cms, $id_lang); + } // Set available keywords $params = array(); $params['id'] = $cms->id; $params['rewrite'] = (!$alias) ? (is_array($cms->link_rewrite) ? $cms->link_rewrite[(int)$id_lang] : $cms->link_rewrite) : $alias; + $params['meta_keywords'] = ''; if (isset($cms->meta_keywords) && !empty($cms->meta_keywords)) $params['meta_keywords'] = is_array($cms->meta_keywords) ? Tools::str2url($cms->meta_keywords[(int)$id_lang]) : Tools::str2url($cms->meta_keywords); - else - $params['meta_keywords'] = ''; + $params['meta_title'] = ''; if (isset($cms->meta_title) && !empty($cms->meta_title)) $params['meta_title'] = is_array($cms->meta_title) ? Tools::str2url($cms->meta_title[(int)$id_lang]) : Tools::str2url($cms->meta_title); - else - $params['meta_title'] = ''; - return $url.Dispatcher::getInstance()->createUrl('cms_rule', $id_lang, $params, $this->allow); + return $url.$dispatcher->createUrl('cms_rule', $id_lang, $params, $this->allow, '', $id_shop); } /** @@ -261,14 +285,24 @@ class LinkCore * @param int $id_lang * @return string */ - public function getSupplierLink($supplier, $alias = null, $id_lang = null) + public function getSupplierLink($supplier, $alias = null, $id_lang = null, $id_shop = null) { if (!$id_lang) $id_lang = Context::getContext()->language->id; - $url = _PS_BASE_URL_.__PS_BASE_URI__.$this->getLangLink($id_lang); + if ($id_shop === null) + $shop = Context::getContext()->shop; + else + $shop = new Shop($id_shop); + $url = 'http://'.$shop->domain.$shop->getBaseURI().$this->getLangLink($id_lang, null, $id_shop); + + $dispatcher = Dispatcher::getInstance(); if (!is_object($supplier)) + { + if ($alias !== null && !$dispatcher->hasKeyword('supplier_rule', $id_lang, 'meta_keywords', $id_shop) && !$dispatcher->hasKeyword('supplier_rule', $id_lang, 'meta_title', $id_shop)) + return $url.$dispatcher->createUrl('supplier_rule', $id_lang, array('id' => (int)$supplier, 'rewrite' => (string)$alias), $this->allow, '', $id_shop); $supplier = new Supplier($supplier, $id_lang); + } // Set available keywords $params = array(); @@ -277,7 +311,7 @@ class LinkCore $params['meta_keywords'] = Tools::str2url($supplier->meta_keywords); $params['meta_title'] = Tools::str2url($supplier->meta_title); - return $url.Dispatcher::getInstance()->createUrl('supplier_rule', $id_lang, $params, $this->allow); + return $url.$dispatcher->createUrl('supplier_rule', $id_lang, $params, $this->allow, '', $id_shop); } /** @@ -288,14 +322,24 @@ class LinkCore * @param int $id_lang * @return string */ - public function getManufacturerLink($manufacturer, $alias = null, $id_lang = null) + public function getManufacturerLink($manufacturer, $alias = null, $id_lang = null, $id_shop = null) { if (!$id_lang) $id_lang = Context::getContext()->language->id; - $url = _PS_BASE_URL_.__PS_BASE_URI__.$this->getLangLink($id_lang); + if ($id_shop === null) + $shop = Context::getContext()->shop; + else + $shop = new Shop($id_shop); + $url = 'http://'.$shop->domain.$shop->getBaseURI().$this->getLangLink($id_lang, null, $id_shop); + + $dispatcher = Dispatcher::getInstance(); if (!is_object($manufacturer)) + { + if ($alias !== null && !$dispatcher->hasKeyword('manufacturer_rule', $id_lang, 'meta_keywords', $id_shop) && !$dispatcher->hasKeyword('manufacturer_rule', $id_lang, 'meta_title', $id_shop)) + return $url.$dispatcher->createUrl('manufacturer_rule', $id_lang, array('id' => (int)$manufacturer, 'rewrite' => (string)$alias), $this->allow, '', $id_shop); $manufacturer = new Manufacturer($manufacturer, $id_lang); + } // Set available keywords $params = array(); @@ -304,7 +348,7 @@ class LinkCore $params['meta_keywords'] = Tools::str2url($manufacturer->meta_keywords); $params['meta_title'] = Tools::str2url($manufacturer->meta_title); - return $url.Dispatcher::getInstance()->createUrl('manufacturer_rule', $id_lang, $params, $this->allow); + return $url.$dispatcher->createUrl('manufacturer_rule', $id_lang, $params, $this->allow, '', $id_shop); } /** @@ -316,23 +360,29 @@ class LinkCore * @param int $id_lang * @return string */ - public function getModuleLink($module, $controller = 'default', array $params = array(), $ssl = false, $id_lang = null) + public function getModuleLink($module, $controller = 'default', array $params = array(), $ssl = false, $id_lang = null, $id_shop = null) { - $base = (($ssl && $this->ssl_enable) ? _PS_BASE_URL_SSL_ : _PS_BASE_URL_); + $base = (($ssl && $this->ssl_enable) ? 'https://' : 'http://'); if (!$id_lang) $id_lang = Context::getContext()->language->id; - $url = $base.__PS_BASE_URI__.$this->getLangLink($id_lang); - // Set available keywords - $params['module'] = $module; - $params['controller'] = $controller ? $controller : 'default'; + if ($id_shop === null) + $shop = Context::getContext()->shop; + else + $shop = new Shop($id_shop); + $url = $base.$shop->domain.$shop->getBaseURI().$this->getLangLink($id_lang, null, $id_shop); // If the module has its own route ... just use it ! - if (Dispatcher::getInstance()->hasRoute('module-'.$module.'-'.$controller, $id_lang)) + if (Dispatcher::getInstance()->hasRoute('module-'.$module.'-'.$controller, $id_lang, $id_shop)) return $this->getPageLink('module-'.$module.'-'.$controller, $ssl, $id_lang, $params); else - return $url.Dispatcher::getInstance()->createUrl('module', $id_lang, $params, $this->allow); + { + // Set available keywords + $params['module'] = $module; + $params['controller'] = $controller ? $controller : 'default'; + return $url.Dispatcher::getInstance()->createUrl('module', $id_lang, $params, $this->allow, '', $id_shop); + } } /** @@ -403,7 +453,7 @@ class LinkCore * * @return string Page link */ - public function getPageLink($controller, $ssl = false, $id_lang = null, $request = null, $request_url_encode = false) + public function getPageLink($controller, $ssl = false, $id_lang = null, $request = null, $request_url_encode = false, $id_shop = null) { $controller = Tools::strReplaceFirst('.php', '', $controller); @@ -419,16 +469,24 @@ class LinkCore parse_str($request, $request); } - $uri_path = Dispatcher::getInstance()->createUrl($controller, $id_lang, $request); - $url = ($ssl && $this->ssl_enable) ? Tools::getShopDomainSsl(true) : Tools::getShopDomain(true); - $url .= __PS_BASE_URI__.$this->getLangLink($id_lang).ltrim($uri_path, '/'); + if ($id_shop === null) + $shop = Context::getContext()->shop; + else + $shop = new Shop($id_shop); + + $uri_path = Dispatcher::getInstance()->createUrl($controller, $id_lang, $request, false, '', $id_shop); + $url = ($ssl && $this->ssl_enable) ? 'https://' : 'http://'; + $url .= $shop->domain.$shop->getBaseURI().$this->getLangLink($id_lang, null, $id_shop).ltrim($uri_path, '/'); return $url; } public function getCatImageLink($name, $id_category, $type = null) { - $uri_path = ($this->allow == 1) ? (__PS_BASE_URI__.'c/'.$id_category.($type ? '-'.$type : '').'/'.$name.'.jpg') : (_THEME_CAT_DIR_.$id_category.($type ? '-'.$type : '').'.jpg'); + if($this->allow == 1 && $type) + $uri_path = __PS_BASE_URI__.'c/'.$id_category.'-'.$type.'/'.$name.'.jpg'; + else + $uri_path = _THEME_CAT_DIR_.$id_category.($type ? '-'.$type : '').'.jpg'; return $this->protocol_content.Tools::getMediaServer($uri_path).$uri_path; } @@ -452,6 +510,7 @@ class LinkCore unset($params['id_lang']); $controller = Dispatcher::getInstance()->getController(); + if (!empty(Context::getContext()->controller->php_self)) $controller = Context::getContext()->controller->php_self; @@ -467,6 +526,15 @@ class LinkCore return $this->getCMSLink((int)$params['id_cms'], null, false, (int)$id_lang); elseif ($controller == 'cms' && isset($params['id_cms_category'])) return $this->getCMSCategoryLink((int)$params['id_cms_category'], null, (int)$id_lang); + elseif (isset($params['fc']) && $params['fc'] == 'module') + { + $module = Validate::isModuleName(Tools::getValue('module')) ? Tools::getValue('module') : ''; + if (!empty($module)) + { + unset($params['fc'], $params['module']); + return $this->getModuleLink($module, $controller, $params, false, (int)$id_lang); + } + } return $this->getPageLink($controller, false, $id_lang, $params); } @@ -561,12 +629,12 @@ class LinkCore return $url.(!strstr($url, '?') ? '?' : '&').'orderby='.urlencode($orderby).'&orderway='.urlencode($orderway); } - protected function getLangLink($id_lang = null, Context $context = null) + protected function getLangLink($id_lang = null, Context $context = null, $id_shop = null) { if (!$context) $context = Context::getContext(); - if (!$this->allow || !Language::isMultiLanguageActivated()) + if ((!$this->allow && in_array($id_shop, array($context->shop->id, null))) || !Language::isMultiLanguageActivated($id_shop) || !(int)Configuration::get('PS_REWRITING_SETTINGS', null, null, $id_shop)) return ''; if (!$id_lang) diff --git a/classes/LocalizationPack.php b/classes/LocalizationPack.php index 133ad8534..5a738b1a4 100644 --- a/classes/LocalizationPack.php +++ b/classes/LocalizationPack.php @@ -70,8 +70,16 @@ class LocalizationPackCore return $res; } foreach ($selection as $selected) - if (!Validate::isLocalizationPackSelection($selected) || !$this->{'_install'.ucfirst($selected)}($xml)) - return false; + if (strtolower((string)$selected) == 'currencies') + { + if (!Validate::isLocalizationPackSelection($selected) || !$this->{'_install'.ucfirst($selected)}($xml, true)) + return false; + } + else + { + if (!Validate::isLocalizationPackSelection($selected) || !$this->{'_install'.ucfirst($selected)}($xml)) + return false; + } return true; } @@ -239,8 +247,6 @@ class LocalizationPackCore { if (isset($xml->currencies->currency)) { - - foreach ($xml->currencies->currency as $data) { $attributes = $data->attributes(); @@ -294,7 +300,7 @@ class LocalizationPackCore // if we are not in an installation context or if the pack is not available in the local directory if (Language::getIdByIso($attributes['iso_code']) && !$install_mode) continue; - $errors = Language::downloadAndInstallLanguagePack($attributes['iso_code'], $attributes['version']); + $errors = Language::downloadAndInstallLanguagePack($attributes['iso_code'], $attributes['version'], $attributes); if ($errors !== true && is_array($errors)) $this->_errors = array_merge($this->_errors, $errors); } diff --git a/classes/Logger.php b/classes/Logger.php index bed56b480..0bc46bf16 100644 --- a/classes/Logger.php +++ b/classes/Logger.php @@ -43,6 +43,9 @@ class LoggerCore extends ObjectModel /** @var integer Object ID */ public $object_id; + + /** @var integer Object ID */ + public $id_employee; /** @var string Object creation date */ public $date_add; @@ -61,6 +64,7 @@ class LoggerCore extends ObjectModel 'error_code' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), 'message' => array('type' => self::TYPE_STRING, 'validate' => 'isMessage', 'required' => true), 'object_id' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), 'object_type' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), @@ -98,7 +102,7 @@ class LoggerCore extends ObjectModel * @param boolean $allow_duplicate if set to true, can log several time the same information (not recommended) * @return boolean true if succeed */ - public static function addLog($message, $severity = 1, $error_code = null, $object_type = null, $object_id = null, $allow_duplicate = false) + public static function addLog($message, $severity = 1, $error_code = null, $object_type = null, $object_id = null, $allow_duplicate = false, $id_employee = null) { $log = new Logger(); $log->severity = intval($severity); @@ -106,6 +110,13 @@ class LoggerCore extends ObjectModel $log->message = pSQL($message); $log->date_add = date('Y-m-d H:i:s'); $log->date_upd = date('Y-m-d H:i:s'); + + if ($id_employee === null && isset(Context::getContext()->employee) && Validate::isLoadedObject(Context::getContext()->employee)) + $id_employee = Context::getContext()->employee->id; + + if ($id_employee !== null) + $log->id_employee = (int)$id_employee; + if (!empty($object_type) && !empty($object_id)) { $log->object_type = pSQL($object_type); diff --git a/classes/Mail.php b/classes/Mail.php index bc09523d1..76a3de1d8 100644 --- a/classes/Mail.php +++ b/classes/Mail.php @@ -63,7 +63,6 @@ class MailCore 'PS_SHOP_NAME', 'PS_MAIL_SMTP_ENCRYPTION', 'PS_MAIL_SMTP_PORT', - 'PS_MAIL_METHOD', 'PS_MAIL_TYPE' ), null, null, $id_shop); @@ -245,11 +244,14 @@ class MailCore else $template_vars['{shop_logo}'] = ''; } - + ShopUrl::cacheMainDomainForShop((int)$id_shop); /* don't attach the logo as */ if (isset($logo)) $template_vars['{shop_logo}'] = $message->attach(new Swift_Message_EmbeddedFile(new Swift_File($logo), null, ImageManager::getMimeTypeByExtension($logo))); + if ((Context::getContext()->link instanceof Link) === false) + Context::getContext()->link = new Link(); + $template_vars['{shop_name}'] = Tools::safeOutput(Configuration::get('PS_SHOP_NAME', null, null, $id_shop)); $template_vars['{shop_url}'] = Context::getContext()->link->getPageLink('index', true, Context::getContext()->language->id); $template_vars['{my_account_url}'] = Context::getContext()->link->getPageLink('my-account', true, Context::getContext()->language->id); @@ -274,6 +276,9 @@ class MailCore /* Send mail */ $send = $swift->send($message, $to, new Swift_Address($from, $from_name)); $swift->disconnect(); + + ShopUrl::resetMainDomainCache(); + return $send; } catch (Swift_Exception $e) { diff --git a/classes/Manufacturer.php b/classes/Manufacturer.php index 118433fe2..8cc573bad 100644 --- a/classes/Manufacturer.php +++ b/classes/Manufacturer.php @@ -78,8 +78,8 @@ class ManufacturerCore extends ObjectModel 'date_upd' => array('type' => self::TYPE_DATE), // Lang fields - 'description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isString'), - 'short_description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isString', 'size' => 254), + 'description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'), + 'short_description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml', 'size' => 254), 'meta_title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), 'meta_description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), 'meta_keywords' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName'), @@ -198,6 +198,7 @@ class ManufacturerCore extends ObjectModel LEFT JOIN `'._DB_PREFIX_.'manufacturer` as m ON (m.`id_manufacturer`= p.`id_manufacturer`) WHERE m.`id_manufacturer` = '.(int)$manufacturer['id_manufacturer']. ($active ? ' AND product_shop.`active` = 1 ' : ''). + ' AND product_shop.`visibility` NOT IN ("none")'. ($all_group ? '' : ' AND p.`id_product` IN ( SELECT cp.`id_product` FROM `'._DB_PREFIX_.'category_group` cg @@ -215,7 +216,7 @@ class ManufacturerCore extends ObjectModel for ($i = 0; $i < $total_manufacturers; $i++) if ($rewrite_settings) - $manufacturers[$i]['link_rewrite'] = Tools::link_rewrite($manufacturers[$i]['name'], false); + $manufacturers[$i]['link_rewrite'] = Tools::link_rewrite($manufacturers[$i]['name']); else $manufacturers[$i]['link_rewrite'] = 0; @@ -258,7 +259,7 @@ class ManufacturerCore extends ObjectModel public function getLink() { - return Tools::link_rewrite($this->name, false); + return Tools::link_rewrite($this->name); } public static function getProducts($id_manufacturer, $id_lang, $p, $n, $order_by = null, $order_way = null, @@ -339,7 +340,7 @@ class ManufacturerCore extends ObjectModel '.Shop::addSqlAssociation('product', 'p').' LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (p.`id_product` = pa.`id_product`) - '.Shop::addSqlAssociation('product_attribute', 'pa', false).' + '.Shop::addSqlAssociation('product_attribute', 'pa', false, 'product_attribute_shop.`default_on` = 1').' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').') LEFT JOIN `'._DB_PREFIX_.'image` i diff --git a/classes/Media.php b/classes/Media.php index a769218e2..72c6e786b 100755 --- a/classes/Media.php +++ b/classes/Media.php @@ -1,6 +1,6 @@ array('fileName' => 'jquery.ui.core.min.js', 'dependencies' => array(), 'theme' => true), 'ui.widget' => array('fileName' => 'jquery.ui.widget.min.js', 'dependencies' => array(), 'theme' => false), 'ui.mouse' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => false), - 'ui.position' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array(), 'theme' => false), - 'ui.draggable' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => false), - 'ui.droppable' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse', 'ui.draggable'), 'theme' => false), - 'ui.resizable' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), - 'ui.selectable' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), - 'ui.sortable' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), - 'ui.accordion' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => true), - 'ui.autocomplete' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.position'), 'theme' => true), - 'ui.button' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => true), - 'ui.dialog' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.position'), 'theme' => true), - 'ui.slider' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), - 'ui.tabs' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => true), - 'ui.datepicker' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core'), 'theme' => true), - 'ui.progressbar' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => true), - 'effects.core' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array(), 'theme' => false), - 'effects.blind' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.bounce' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.clip' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.drop' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.explode' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.fade' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.fold' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.highlight' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.pulsate' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.scale' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.shake' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.slide' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.transfer' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('effects.core'), 'theme' => false) + 'ui.position' => array('fileName' => 'jquery.ui.position.min.js', 'dependencies' => array(), 'theme' => false), + 'ui.draggable' => array('fileName' => 'jquery.ui.draggable.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => false), + 'ui.droppable' => array('fileName' => 'jquery.ui.droppable.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse', 'ui.draggable'), 'theme' => false), + 'ui.resizable' => array('fileName' => 'jquery.ui.resizable.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), + 'ui.selectable' => array('fileName' => 'jquery.ui.selectable.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), + 'ui.sortable' => array('fileName' => 'jquery.ui.sortable.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), + 'ui.accordion' => array('fileName' => 'jquery.ui.accordion.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => true), + 'ui.autocomplete' => array('fileName' => 'jquery.ui.autocomplete.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.position'), 'theme' => true), + 'ui.button' => array('fileName' => 'jquery.ui.button.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => true), + 'ui.dialog' => array('fileName' => 'jquery.ui.dialog.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.position'), 'theme' => true), + 'ui.slider' => array('fileName' => 'jquery.ui.slider.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), + 'ui.tabs' => array('fileName' => 'jquery.ui.tabs.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => true), + 'ui.datepicker' => array('fileName' => 'jquery.ui.datepicker.min.js', 'dependencies' => array('ui.core'), 'theme' => true), + 'ui.progressbar' => array('fileName' => 'jquery.ui.progressbar.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => true), + 'effects.core' => array('fileName' => 'jquery.effects.core.min.js', 'dependencies' => array(), 'theme' => false), + 'effects.blind' => array('fileName' => 'jquery.effects.blind.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.bounce' => array('fileName' => 'jquery.effects.bounce.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.clip' => array('fileName' => 'jquery.effects.clip.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.drop' => array('fileName' => 'jquery.effects.drop.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.explode' => array('fileName' => 'jquery.effects.explode.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.fade' => array('fileName' => 'jquery.effects.fade.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.fold' => array('fileName' => 'jquery.effects.fold.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.highlight' => array('fileName' => 'jquery.effects.highlight.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.pulsate' => array('fileName' => 'jquery.effects.pulsate.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.scale' => array('fileName' => 'jquery.effects.scale.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.shake' => array('fileName' => 'jquery.effects.shake.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.slide' => array('fileName' => 'jquery.effects.slide.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.transfer' => array('fileName' => 'jquery.effects.transfer.min.js', 'dependencies' => array('effects.core'), 'theme' => false) ); + public static function minifyHTML($html_content) { if (strlen($html_content) > 0) @@ -110,7 +111,8 @@ class MediaCore // In this case, we don't compress the content if (preg_last_error() == PREG_BACKTRACK_LIMIT_ERROR) { - error_log('ERROR: PREG_BACKTRACK_LIMIT_ERROR in function packJSinHTML'); + if (_PS_MODE_DEV_) + error_log('ERROR: PREG_BACKTRACK_LIMIT_ERROR in function packJSinHTML'); return $html_content_copy; } return $html_content; @@ -223,7 +225,7 @@ class MediaCore $url_data = parse_url($css_uri); $file_uri = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); // check if css files exists - if (!@filemtime($file_uri)) + if (!@filemtime($file_uri) && !array_key_exists('host', $url_data)) return false; if (Context::getContext()->controller->controller_type == 'admin') @@ -269,7 +271,10 @@ class MediaCore if ($add_no_conflict) $return[] = Media::getJSPath(_PS_JS_DIR_.'jquery/jquery.noConflict.php?version='.$version); - + + //added query migrate for compatibility with new version of jquery will be removed in ps 1.6 + $return[] = Media::getJSPath(_PS_JS_DIR_.'jquery/jquery-migrate-1.2.1.js'); + return $return; } @@ -385,6 +390,7 @@ class MediaCore { //inits $css_files_by_media = array(); + $external_css_files = array(); $compressed_css_files = array(); $compressed_css_files_not_found = array(); $compressed_css_files_infos = array(); @@ -399,6 +405,13 @@ class MediaCore $infos = array(); $infos['uri'] = $filename; $url_data = parse_url($filename); + + if(array_key_exists('host', $url_data)) + { + $external_css_files[$filename] = $media; + continue; + } + $infos['path'] = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, '/', $url_data['path']); $css_files_by_media[$media]['files'][] = $infos; if (!array_key_exists('date', $css_files_by_media[$media])) @@ -460,7 +473,7 @@ class MediaCore $url = str_replace(_PS_THEME_DIR_, _THEMES_DIR_._THEME_NAME_.'/', $filename); $css_files[$protocol_link.Tools::getMediaServer($url).$url] = $media; } - return $css_files; + return array_merge($external_css_files, $css_files); } public static function getBackTrackLimit() diff --git a/classes/Meta.php b/classes/Meta.php index 8d82adfb3..e4c3b3147 100644 --- a/classes/Meta.php +++ b/classes/Meta.php @@ -168,7 +168,7 @@ class MetaCore extends ObjectModel $result = $result && $this->delete(); } - return Tools::generateHtaccess(); + return $result && Tools::generateHtaccess(); } public static function getEquivalentUrlRewrite($new_id_lang, $id_lang, $url_rewrite) diff --git a/classes/ObjectModel.php b/classes/ObjectModel.php index ebe12dc1c..20be99921 100644 --- a/classes/ObjectModel.php +++ b/classes/ObjectModel.php @@ -242,16 +242,6 @@ abstract class ObjectModelCore $this->{$key} = $value; } } - - if (!is_array(self::$fieldsRequiredDatabase)) - { - $fields = $this->getfieldsRequiredDatabase(true); - if ($fields) - foreach ($fields as $row) - self::$fieldsRequiredDatabase[$row['object_name']][(int)$row['id_required_field']] = pSQL($row['field_name']); - else - self::$fieldsRequiredDatabase = array(); - } } /** @@ -537,29 +527,36 @@ abstract class ObjectModelCore if (!$res) return false; unset($res[$definition['primary']]); + foreach ($res as $field => &$value) + if (isset($definition['fields'][$field])) + $value = ObjectModel::formatValue($value, $definition['fields'][$field]['type']); if (!Db::getInstance()->insert($definition['table'], $res)) return false; $object_id = Db::getInstance()->Insert_ID(); - - if ($definition['multilang']) - { - $res = Db::getInstance()->executeS(' - SELECT * - FROM `'._DB_PREFIX_.bqSQL($definition['table']).'_lang` - WHERE `'.bqSQL($definition['primary']).'` = '.(int)$this->id - ); - if (!$res) + if (isset($definition['multilang']) && $definition['multilang']) + { + $result = Db::getInstance()->executeS(' + SELECT * + FROM `'._DB_PREFIX_.bqSQL($definition['table']).'_lang` + WHERE `'.bqSQL($definition['primary']).'` = '.(int)$this->id); + if (!$result) return false; + + foreach ($result as &$row) + foreach ($row as $field => &$value) + if (isset($definition['fields'][$field])) + $value = ObjectModel::formatValue($value, $definition['fields'][$field]['type']); - foreach ($res as $row) + // Keep $row2, you cannot use $row because there is an unexplicated conflict with the previous usage of this variable + foreach ($result as $row2) { - $row[$definition['primary']] = (int)$object_id; - if (!Db::getInstance()->insert($definition['table'].'_lang', $row)) + $row2[$definition['primary']] = (int)$object_id; + if (!Db::getInstance()->insert($definition['table'].'_lang', $row2)) return false; - } + } } $object_duplicated = new $definition['classname']((int)$object_id); @@ -626,7 +623,7 @@ abstract class ObjectModelCore $shop_exists = ObjectModel::$db->getValue('SELECT '.$this->def['primary'].' FROM '._DB_PREFIX_.$this->def['table'].'_shop WHERE '.$where); if ($shop_exists) $result &= ObjectModel::$db->update($this->def['table'].'_shop', $fields, $where, 0, $null_values); - else if (Shop::getContext() == Shop::CONTEXT_SHOP) + elseif (Shop::getContext() == Shop::CONTEXT_SHOP) $result &= ObjectModel::$db->insert($this->def['table'].'_shop', $all_fields, $null_values); } } @@ -756,6 +753,9 @@ abstract class ObjectModelCore if (!array_key_exists('active', $this)) throw new PrestaShopException('property "active" is missing in object '.get_class($this)); + // Update only active field + $this->setFieldsToUpdate(array('active' => true)); + // Update active status on object $this->active = !(int)$this->active; @@ -857,8 +857,12 @@ abstract class ObjectModelCore continue; $values = $this->$field; + + // If the object has not been loaded in multilanguage, then the value is the one for the current language of the object if (!is_array($values)) $values = array($this->id_lang => $values); + + // The value for the default must always be set, so we put an empty string if it does not exists if (!isset($values[Configuration::get('PS_LANG_DEFAULT')])) $values[Configuration::get('PS_LANG_DEFAULT')] = ''; @@ -891,6 +895,7 @@ abstract class ObjectModelCore */ public function validateField($field, $value, $id_lang = null) { + $this->cacheFieldsRequiredDatabase(); $data = $this->def['fields'][$field]; // Check if field is required @@ -929,8 +934,22 @@ abstract class ObjectModelCore if (!method_exists('Validate', $data['validate'])) throw new PrestaShopException('Validation function not found. '.$data['validate']); - if (!empty($value) && !call_user_func(array('Validate', $data['validate']), $value)) - return 'Property '.get_class($this).'->'.$field.' is not valid'; + if (!empty($value)) + { + $res = true; + if (Tools::strtolower($data['validate']) == 'iscleanhtml') + { + if (!call_user_func(array('Validate', $data['validate']), $value, (int)Configuration::get('PS_ALLOW_HTML_IFRAME'))) + $res = false; + } + else + { + if (!call_user_func(array('Validate', $data['validate']), $value)) + $res = false; + } + if (!$res) + return 'Property '.get_class($this).'->'.$field.' is not valid'; + } } return true; @@ -959,22 +978,24 @@ abstract class ObjectModelCore public function validateController($htmlentities = true) { + $this->cacheFieldsRequiredDatabase(); $errors = array(); $required_fields_database = (isset(self::$fieldsRequiredDatabase[get_class($this)])) ? self::$fieldsRequiredDatabase[get_class($this)] : array(); foreach ($this->def['fields'] as $field => $data) { + $value = Tools::getValue($field, $this->{$field}); // Check if field is required by user if (in_array($field, $required_fields_database)) $data['required'] = true; // Checking for required fields - if (isset($data['required']) && $data['required'] && ($value = Tools::getValue($field, $this->{$field})) == false && (string)$value != '0') + if (isset($data['required']) && $data['required'] && empty($value) && $value !== '0') if (!$this->id || $field != 'passwd') - $errors[] = ''.self::displayFieldName($field, get_class($this), $htmlentities).' '.Tools::displayError('is required.'); + $errors[$field] = ''.self::displayFieldName($field, get_class($this), $htmlentities).' '.Tools::displayError('is required.'); // Checking for maximum fields sizes - if (isset($data['size']) && ($value = Tools::getValue($field, $this->{$field})) && Tools::strlen($value) > $data['size']) - $errors[] = sprintf( + if (isset($data['size']) && !empty($value) && Tools::strlen($value) > $data['size']) + $errors[$field] = sprintf( Tools::displayError('%1$s is too long. Maximum length: %2$d'), self::displayFieldName($field, get_class($this), $htmlentities), $data['size'] @@ -982,10 +1003,10 @@ abstract class ObjectModelCore // Checking for fields validity // Hack for postcode required for country which does not have postcodes - if (($value = Tools::getValue($field, $this->{$field})) || ($field == 'postcode' && $value == '0')) + if (!empty($value) || $value === '0' || ($field == 'postcode' && $value == '0')) { if (isset($data['validate']) && !Validate::$data['validate']($value) && (!empty($value) || $data['required'])) - $errors[] = ''.self::displayFieldName($field, get_class($this), $htmlentities).' '.Tools::displayError('is invalid.'); + $errors[$field] = ''.self::displayFieldName($field, get_class($this), $htmlentities).' '.Tools::displayError('is invalid.'); else { if (isset($data['copy_post']) && !$data['copy_post']) @@ -1005,6 +1026,7 @@ abstract class ObjectModelCore public function getWebserviceParameters($ws_params_attribute_name = null) { + $this->cacheFieldsRequiredDatabase(); $default_resource_parameters = array( 'objectSqlId' => $this->def['primary'], 'retrieveData' => array( @@ -1115,6 +1137,7 @@ abstract class ObjectModelCore public function validateFieldsRequiredDatabase($htmlentities = true) { + $this->cacheFieldsRequiredDatabase(); $errors = array(); $required_fields = (isset(self::$fieldsRequiredDatabase[get_class($this)])) ? self::$fieldsRequiredDatabase[get_class($this)] : array(); @@ -1129,7 +1152,7 @@ abstract class ObjectModelCore $value = Tools::getValue($field); if (empty($value)) - $errors[] = sprintf(Tools::displayError('The field %s is required.'), self::displayFieldName($field, get_class($this), $htmlentities)); + $errors[$field] = sprintf(Tools::displayError('The field %s is required.'), self::displayFieldName($field, get_class($this), $htmlentities)); } return $errors; @@ -1142,6 +1165,19 @@ abstract class ObjectModelCore FROM '._DB_PREFIX_.'required_field '.(!$all ? 'WHERE object_name = \''.pSQL(get_class($this)).'\'' : '')); } + + public function cacheFieldsRequiredDatabase() + { + if (!is_array(self::$fieldsRequiredDatabase)) + { + $fields = $this->getfieldsRequiredDatabase(true); + if ($fields) + foreach ($fields as $row) + self::$fieldsRequiredDatabase[$row['object_name']][(int)$row['id_required_field']] = pSQL($row['field_name']); + else + self::$fieldsRequiredDatabase = array(); + } + } public function addFieldsRequiredDatabase($fields) { @@ -1270,6 +1306,11 @@ abstract class ObjectModelCore { return Shop::isTableAssociated($this->def['table']) || !empty($this->def['multilang_shop']); } + + public function isMultiShopField($field) + { + return (isset($this->def['fields'][$field]) && isset($this->def['fields'][$field]['shop']) && $this->def['fields'][$field]['shop']); + } public function isLangMultishop() { @@ -1286,7 +1327,7 @@ abstract class ObjectModelCore * @param string $specific_where Only executed for common table * @return bool */ - public static function updateMultishopTable($classname, $data, $where, $specific_where = '') + public static function updateMultishopTable($classname, $data, $where = '', $specific_where = '') { $def = ObjectModel::getDefinition($classname); $update_data = array(); @@ -1306,8 +1347,8 @@ abstract class ObjectModelCore $sql = 'UPDATE '._DB_PREFIX_.$def['table'].' a '.Shop::addSqlAssociation($def['table'], 'a', true, null, true).' - SET '.implode(', ', $update_data).' - WHERE '.$where; + SET '.implode(', ', $update_data). + (!empty($where) ? ' WHERE '.$where : ''); return Db::getInstance()->execute($sql); } diff --git a/classes/PaymentModule.php b/classes/PaymentModule.php index f23fd83b7..022e580ec 100644 --- a/classes/PaymentModule.php +++ b/classes/PaymentModule.php @@ -135,6 +135,8 @@ abstract class PaymentModuleCore extends Module $this->context->customer = new Customer($this->context->cart->id_customer); $this->context->language = new Language($this->context->cart->id_lang); $this->context->shop = ($shop ? $shop : new Shop($this->context->cart->id_shop)); + ShopUrl::resetMainDomainCache(); + $id_currency = $currency_special ? (int)$currency_special : (int)$this->context->cart->id_currency; $this->context->currency = new Currency($id_currency, null, $this->context->shop->id); if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') @@ -346,7 +348,8 @@ abstract class PaymentModuleCore extends Module // Construct order detail table for the email $products_list = ''; $virtual_product = true; - foreach ($products as $key => $product) + + foreach ($order->product_list as $key => $product) { $price = Product::getPriceStatic((int)$product['id_product'], false, ($product['id_product_attribute'] ? (int)$product['id_product_attribute'] : null), 6, null, false, true, $product['cart_quantity'], false, (int)$order->id_customer, (int)$order->id_cart, (int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); $price_wt = Product::getPriceStatic((int)$product['id_product'], true, ($product['id_product_attribute'] ? (int)$product['id_product_attribute'] : null), 2, null, false, true, $product['cart_quantity'], false, (int)$order->id_customer, (int)$order->id_cart, (int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); @@ -384,7 +387,7 @@ abstract class PaymentModuleCore extends Module ' '.$product['reference'].' '.$product['name'].(isset($product['attributes']) ? ' - '.$product['attributes'] : '').' - '.Tools::displayPrice(Product::getTaxCalculationMethod() == PS_TAX_EXC ? Tools::ps_round($price, 2) : $price_wt, $this->context->currency, false).' + '.Tools::displayPrice(Product::getTaxCalculationMethod((int)$this->context->customer->id) == PS_TAX_EXC ? Tools::ps_round($price, 2) : $price_wt, $this->context->currency, false).' '.((int)$product['cart_quantity'] - $customization_quantity).' '.Tools::displayPrice(((int)$product['cart_quantity'] - $customization_quantity) * (Product::getTaxCalculationMethod() == PS_TAX_EXC ? Tools::ps_round($price, 2) : $price_wt), $this->context->currency, false).' '; @@ -429,9 +432,9 @@ abstract class PaymentModuleCore extends Module // Set the new voucher value if ($voucher->reduction_tax) - $voucher->reduction_amount = $values['tax_incl'] - $order->total_products_wt - $order->total_shipping_tax_incl; + $voucher->reduction_amount = $values['tax_incl'] - $order->total_products_wt - ($voucher->free_shipping == 1 ? $order->total_shipping_tax_incl : 0); else - $voucher->reduction_amount = $values['tax_excl'] - $order->total_products - $order->total_shipping_tax_excl; + $voucher->reduction_amount = $values['tax_excl'] - $order->total_products - ($voucher->free_shipping == 1 ? $order->total_shipping_tax_excl : 0); $voucher->id_customer = $order->id_customer; $voucher->quantity = 1; @@ -593,7 +596,7 @@ abstract class PaymentModuleCore extends Module '{invoice_phone}' => ($invoice->phone) ? $invoice->phone : $invoice->phone_mobile, '{invoice_other}' => $invoice->other, '{order_name}' => $order->getUniqReference(), - '{date}' => Tools::displayDate(date('Y-m-d H:i:s'), (int)$order->id_lang, 1), + '{date}' => Tools::displayDate(date('Y-m-d H:i:s'),null , 1), '{carrier}' => $virtual_product ? Tools::displayError('No carrier') : $carrier->name, '{payment}' => Tools::substr($order->payment, 0, 32), '{products}' => $this->formatProductAndVoucherForEmail($products_list), @@ -602,7 +605,8 @@ abstract class PaymentModuleCore extends Module '{total_products}' => Tools::displayPrice($order->total_paid - $order->total_shipping - $order->total_wrapping + $order->total_discounts, $this->context->currency, false), '{total_discounts}' => Tools::displayPrice($order->total_discounts, $this->context->currency, false), '{total_shipping}' => Tools::displayPrice($order->total_shipping, $this->context->currency, false), - '{total_wrapping}' => Tools::displayPrice($order->total_wrapping, $this->context->currency, false)); + '{total_wrapping}' => Tools::displayPrice($order->total_wrapping, $this->context->currency, false), + '{total_tax_paid}' => Tools::displayPrice(($order->total_products_wt - $order->total_products) + ($order->total_shipping_tax_incl - $order->total_shipping_tax_excl), $this->context->currency, false)); if (is_array($extra_vars)) $data = array_merge($data, $extra_vars); diff --git a/classes/Product.php b/classes/Product.php index 5eb9a0017..74e65ee20 100644 --- a/classes/Product.php +++ b/classes/Product.php @@ -297,8 +297,8 @@ class ProductCore extends ObjectModel 'meta_title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), 'link_rewrite' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isLinkRewrite', 'required' => true, 'size' => 128), 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCatalogName', 'required' => true, 'size' => 128), - 'description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isString'), - 'description_short' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isString'), + 'description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'), + 'description_short' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'), 'available_now' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), 'available_later' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'IsGenericName', 'size' => 255), ), @@ -347,7 +347,7 @@ class ProductCore extends ObjectModel ), 'id_tax_rules_group' => array( 'xlink_resource' => array( - 'resourceName' => 'tax_rules_group' + 'resourceName' => 'tax_rule_groups' ) ), 'position_in_category' => array( @@ -364,7 +364,7 @@ class ProductCore extends ObjectModel ), 'type' => array( 'getter' => 'getWsType', - 'setter' => false, + 'setter' => 'setWsType', ), ), 'associations' => array( @@ -394,6 +394,7 @@ class ProductCore extends ObjectModel 'resource' => 'product_feature', 'fields' => array( 'id' => array('required' => true), + 'custom' => array('required' => false), 'id_feature_value' => array( 'required' => true, 'xlink_resource' => 'product_feature_values' @@ -667,6 +668,45 @@ class ProductCore extends ObjectModel return false; } + /** + * For a given id_product and id_product_attribute, return available date + * + * @param int $id_product + * @param int $id_product_attribute Optional + * @return string/null + */ + public static function getAvailableDate($id_product, $id_product_attribute = null) + { + $sql = 'SELECT'; + + if ($id_product_attribute === null) + $sql .= ' p.`available_date`'; + else + $sql .= ' IF(pa.`available_date` = "0000-00-00", p.`available_date`, pa.`available_date`) AS available_date'; + + $sql .= ' FROM `'._DB_PREFIX_.'product` p'; + + if ($id_product_attribute !== null) + $sql .= ' LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (pa.`id_product` = p.`id_product`)'; + + $sql .= Shop::addSqlAssociation('product', 'p'); + + if ($id_product_attribute !== null) + $sql .= Shop::addSqlAssociation('product_attribute', 'pa'); + + $sql .= ' WHERE p.`id_product` = '.(int)$id_product; + + if ($id_product_attribute !== null) + $sql .= ' AND pa.`id_product` = '.(int)$id_product.' AND pa.`id_product_attribute` = '.(int)$id_product_attribute; + + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); + + if ($result == '0000-00-00') + $result = null; + + return $result; + } + public static function updateIsVirtual($id_product) { Db::getInstance()->update('product', array( @@ -867,12 +907,13 @@ class ProductCore extends ObjectModel AND cp.id_product = '.$this->id ); - foreach ($result as $categ_to_delete) - $this->deleteCategory($categ_to_delete['id_category']); // if none are found, it's an error if (!is_array($result)) return false; + foreach ($result as $categ_to_delete) + $this->deleteCategory($categ_to_delete['id_category']); + if (!$this->addToCategories($categories)) return false; @@ -1298,7 +1339,7 @@ class ProductCore extends ObjectModel } /** - * Sets Supplier Reference + * Sets or updates Supplier Reference * * @param int $id_supplier * @param int $id_product_attribute @@ -1311,30 +1352,25 @@ class ProductCore extends ObjectModel //in some case we need to add price without supplier reference if ($supplier_reference === null) $supplier_reference = ''; - + //Try to set the default supplier reference - if ($id_supplier > 0) + if (($id_supplier > 0) && ($this->id > 0)) { $id_product_supplier = (int)ProductSupplier::getIdByProductAndSupplier($this->id, $id_product_attribute, $id_supplier); + $product_supplier = new ProductSupplier($id_product_supplier); + if (!$id_product_supplier) { - //create new record - $product_supplier_entity = new ProductSupplier(); - $product_supplier_entity->id_product = (int)$this->id; - $product_supplier_entity->id_product_attribute = (int)$id_product_attribute; - $product_supplier_entity->id_supplier = (int)$id_supplier; - $product_supplier_entity->product_supplier_reference = pSQL($supplier_reference); - $product_supplier_entity->product_supplier_price_te = (int)$price; - $product_supplier_entity->id_currency = (int)$id_currency; - $product_supplier_entity->save(); - } - else - { - $product_supplier = new ProductSupplier((int)$id_product_supplier); - $product_supplier->product_supplier_reference = pSQL($supplier_reference); - $product_supplier->update(); + $product_supplier->id_product = (int)$this->id; + $product_supplier->id_product_attribute = (int)$id_product_attribute; + $product_supplier->id_supplier = (int)$id_supplier; } + + $product_supplier->product_supplier_reference = pSQL($supplier_reference); + $product_supplier->product_supplier_price_te = (float)$price; + $product_supplier->id_currency = (int)$id_currency; + $product_supplier->save(); } } @@ -1448,6 +1484,7 @@ class ProductCore extends ObjectModel $id_shop_list_array = Product::getShopsByProduct($this->id); foreach ($id_shop_list_array as $array_shop) $id_shop_list[] = $array_shop['id_shop']; + $id_shop_list = array_unique($id_shop_list); } if (count($id_shop_list)) @@ -1975,13 +2012,7 @@ class ProductCore extends ObjectModel FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' WHERE product_shop.`active` = 1 - AND DATEDIFF( - product_shop.`date_add`, - DATE_SUB( - NOW(), - INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY - ) - ) > 0 + AND product_shop.`date_add` > "'.date('Y-m-d', strtotime('-'.(Configuration::get('PS_NB_DAYS_NEW_PRODUCT') ? (int)Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY')).'" '.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').' AND p.`id_product` IN ( SELECT cp.`id_product` @@ -1996,13 +2027,7 @@ class ProductCore extends ObjectModel $sql->select( 'p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, MAX(image_shop.`id_image`) id_image, il.`legend`, m.`name` AS manufacturer_name, - DATEDIFF( - product_shop.`date_add`, - DATE_SUB( - NOW(), - INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY - ) - ) > 0 AS new' + product_shop.`date_add` > "'.date('Y-m-d', strtotime('-'.(Configuration::get('PS_NB_DAYS_NEW_PRODUCT') ? (int)Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY')).'" as new' ); $sql->from('product', 'p'); @@ -2017,25 +2042,15 @@ class ProductCore extends ObjectModel $sql->leftJoin('manufacturer', 'm', 'm.`id_manufacturer` = p.`id_manufacturer`'); $sql->where('product_shop.`active` = 1'); - if ($front) $sql->where('product_shop.`visibility` IN ("both", "catalog")'); - $sql->where(' - DATEDIFF( - product_shop.`date_add`, - DATE_SUB( - NOW(), - INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY - ) - ) > 0' - ); - + $sql->where('product_shop.`date_add` > "'.date('Y-m-d', strtotime('-'.(Configuration::get('PS_NB_DAYS_NEW_PRODUCT') ? (int)Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY')).'"'); $sql->where('p.`id_product` IN ( SELECT cp.`id_product` FROM `'._DB_PREFIX_.'category_group` cg LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON (cp.`id_category` = cg.`id_category`) - WHERE cg.`id_group` '.$sql_groups.')' - ); + WHERE cg.`id_group` '.$sql_groups.' + )'); $sql->groupBy('product_shop.id_product'); $sql->orderBy((isset($order_by_prefix) ? pSQL($order_by_prefix).'.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way)); @@ -2369,8 +2384,14 @@ class ProductCore extends ObjectModel WHERE id_product = '.(int)$this->id.' AND id_shop = '.(int)$this->id_shop ); - if (count($data)) - Db::getInstance()->insert('product_carrier', $data); + + $uniqueArray = array(); + foreach($data as $subArray) + if(!in_array($subArray, $uniqueArray)) + $uniqueArray[] = $subArray; + + if (count($uniqueArray)) + Db::getInstance()->insert('product_carrier', $uniqueArray, false, true, Db::INSERT_IGNORE); } /** @@ -2470,13 +2491,12 @@ class ProductCore extends ObjectModel if ((int)$id_cart) { $condition = ''; - $cache_name = (int)$id_cart.'_'.(int)$id_product.'_'.(int)$id_product_attribute; + $cache_name = (int)$id_cart.'_'.(int)$id_product; if (!isset(self::$_cart_quantity[$cache_name]) || self::$_cart_quantity[$cache_name] != (int)$quantity) self::$_cart_quantity[$cache_name] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT SUM(`quantity`) FROM `'._DB_PREFIX_.'cart_product` WHERE `id_product` = '.(int)$id_product.' - AND `id_product_attribute` = '.(int)$id_product_attribute.' AND `id_cart` = '.(int)$id_cart); $cart_quantity = self::$_cart_quantity[$cache_name]; } @@ -2698,8 +2718,10 @@ class ProductCore extends ObjectModel // Group reduction if ($use_group_reduction) { - if ($reduction_from_category = (float)GroupReduction::getValueForProduct($id_product, $id_group)) - $price -= $price * $reduction_from_category; + $reduction_from_category = GroupReduction::getValueForProduct($id_product, $id_group); + + if (!empty($reduction_from_category) && (float)$reduction_from_category == 0) + $price -= $price * (float)$reduction_from_category; else // apply group reduction if there is no group reduction for this category $price *= ((100 - Group::getReductionByIdGroup($id_group)) / 100); } @@ -3214,8 +3236,9 @@ class ProductCore extends ObjectModel return array(); if (!array_key_exists($id_product, self::$_cacheFeatures)) self::$_cacheFeatures[$id_product] = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' - SELECT id_feature, id_product, id_feature_value - FROM `'._DB_PREFIX_.'feature_product` + SELECT fp.id_feature, fp.id_product, fp.id_feature_value, custom + FROM `'._DB_PREFIX_.'feature_product` fp + LEFT JOIN `'._DB_PREFIX_.'feature_value` fv ON (fp.id_feature_value = fv.id_feature_value) WHERE `id_product` = '.(int)$id_product ); return self::$_cacheFeatures[$id_product]; @@ -3263,6 +3286,7 @@ class ProductCore extends ObjectModel LEFT JOIN '._DB_PREFIX_.'feature_lang fl ON (fl.id_feature = pf.id_feature AND fl.id_lang = '.(int)$id_lang.') LEFT JOIN '._DB_PREFIX_.'feature_value_lang fvl ON (fvl.id_feature_value = pf.id_feature_value AND fvl.id_lang = '.(int)$id_lang.') LEFT JOIN '._DB_PREFIX_.'feature f ON (f.id_feature = pf.id_feature) + '.Shop::addSqlAssociation('feature', 'f').' WHERE `id_product` IN ('.implode($product_implode, ',').') ORDER BY f.position ASC'); @@ -3347,33 +3371,57 @@ class ProductCore extends ObjectModel WHERE pa.`id_product` = '.(int)$id_product_old ); + $combinations = array(); foreach ($result as $row) { $id_product_attribute_old = (int)$row['id_product_attribute']; - $result2 = Db::getInstance()->executeS(' - SELECT * - FROM `'._DB_PREFIX_.'product_attribute_combination` - WHERE `id_product_attribute` = '.$id_product_attribute_old - ); + if (!isset($combinations[$id_product_attribute_old])) + { + $id_combination = null; + $id_shop = null; + $result2 = Db::getInstance()->executeS(' + SELECT * + FROM `'._DB_PREFIX_.'product_attribute_combination` + WHERE `id_product_attribute` = '.$id_product_attribute_old + ); + } + else + { + $id_combination = (int)$combinations[$id_product_attribute_old]; + $id_shop = (int)$row['id_shop']; + $context_old = Shop::getContext(); + $context_shop_id_old = Shop::getContextShopID(); + Shop::setContext(Shop::CONTEXT_SHOP, $id_shop); + + } $row['id_product'] = $id_product_new; unset($row['id_product_attribute']); - $combination = new Combination(); + + $combination = new Combination($id_combination, null, $id_shop); foreach ($row as $k => $v) $combination->$k = $v; - $return &= $combination->add(); + $return &= $combination->save(); $id_product_attribute_new = (int)$combination->id; + if ($result_images = Product::_getAttributeImageAssociations($id_product_attribute_old)) { $combination_images['old'][$id_product_attribute_old] = $result_images; $combination_images['new'][$id_product_attribute_new] = $result_images; } - foreach ($result2 as $row2) + + if (!isset($combinations[$id_product_attribute_old])) { - $row2['id_product_attribute'] = $id_product_attribute_new; - $return &= Db::getInstance()->insert('product_attribute_combination', $row2); + $combinations[$id_product_attribute_old] = (int)$id_product_attribute_new; + foreach ($result2 as $row2) + { + $row2['id_product_attribute'] = $id_product_attribute_new; + $return &= Db::getInstance()->insert('product_attribute_combination', $row2); + } } + else + Shop::setContext($context_old, $context_shop_id_old); } return !$return ? false : $combination_images; } @@ -3767,15 +3815,14 @@ class ProductCore extends ObjectModel isset($row['cache_is_pack']) ? $row['cache_is_pack'] : null ); + $row['quantity_all_versions'] = $row['quantity']; + if ($row['id_product_attribute']) - { - $row['quantity_all_versions'] = $row['quantity']; $row['quantity'] = Product::getQuantity( (int)$row['id_product'], $row['id_product_attribute'], isset($row['cache_is_pack']) ? $row['cache_is_pack'] : null ); - } $row['id_image'] = Product::defineProductImage($row, $id_lang); $row['features'] = Product::getFrontFeaturesStatic((int)$id_lang, $row['id_product']); @@ -3849,6 +3896,7 @@ class ProductCore extends ObjectModel LEFT JOIN '._DB_PREFIX_.'feature_lang fl ON (fl.id_feature = pf.id_feature AND fl.id_lang = '.(int)$id_lang.') LEFT JOIN '._DB_PREFIX_.'feature_value_lang fvl ON (fvl.id_feature_value = pf.id_feature_value AND fvl.id_lang = '.(int)$id_lang.') LEFT JOIN '._DB_PREFIX_.'feature f ON (f.id_feature = pf.id_feature AND fl.id_lang = '.(int)$id_lang.') + '.Shop::addSqlAssociation('feature', 'f').' WHERE pf.id_product = '.(int)$id_product.' ORDER BY f.position ASC' ); @@ -4401,10 +4449,49 @@ class ProductCore extends ObjectModel */ public function setWsProductFeatures($product_features) { - $this->deleteProductFeatures(); + + $db_features = Db::getInstance()->executeS(' + SELECT p.*, f.`custom` + FROM `'._DB_PREFIX_.'feature_product` p + LEFT JOIN `'._DB_PREFIX_.'feature_value` f ON (f.`id_feature_value` = p.`id_feature_value`) + WHERE `id_product` = '.(int)$this->id + ); + + + $pfa = array(); foreach ($product_features as $product_feature) - $this->addFeaturesToDB($product_feature['id'], $product_feature['id_feature_value']); - return true; + $pfa[$product_feature['id']] = 1; + + foreach ($db_features as $db_feature) + { + // test if feature should stay in db (if it is part of updated product) + if (!isset($pfa[$db_feature['id_feature']])) + { + // delete only custom features + if ($db_feature['custom']) + { + Db::getInstance()->execute(' + DELETE FROM `'._DB_PREFIX_.'feature_value_lang` + WHERE `id_feature_value` = '.(int)$db_feature['id_feature_value'] + ); + Db::getInstance()->execute(' + DELETE FROM `'._DB_PREFIX_.'feature_value` + WHERE `id_feature_value` = '.(int)$db_feature['id_feature_value'] + ); + + } + } + } + + Db::getInstance()->execute(' + DELETE FROM `'._DB_PREFIX_.'feature_product` + WHERE `id_product` = '.(int)$this->id + ); + + foreach ($product_features as $product_feature) + $this->addFeaturesToDB($product_feature['id'], $product_feature['id_feature_value'], $product_feature['custom']); + + return true; } /** @@ -4498,6 +4585,7 @@ class ProductCore extends ObjectModel */ public function setWsAccessories($accessories) { + $this->deleteAccessories(); foreach ($accessories as $accessory) Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'accessory` (`id_product_1`, `id_product_2`) VALUES ('.(int)$this->id.', '.(int)$accessory['id'].')'); @@ -4670,6 +4758,44 @@ class ProductCore extends ObjectModel FROM `'._DB_PREFIX_.'product_tag` WHERE `id_product` = '.(int)$this->id); } + + /** + * Webservice setter : set tag ids of current product for association + * + * @param $tag_ids tag ids + */ + public function setWsTags($tag_ids) + { + $ids = array(); + foreach ($tag_ids as $value) + $ids[] = $value['id']; + if ($this->deleteWsTags()) + { + if ($ids) + { + $sql_values = ''; + $ids = array_map('intval', $ids); + foreach ($ids as $position => $id) + $sql_values[] = '('.(int)$this->id.', '.(int)$id.')'; + $result = Db::getInstance()->execute(' + INSERT INTO `'._DB_PREFIX_.'product_tag` (`id_product`, `id_tag`) + VALUES '.implode(',', $sql_values) + ); + return $result; + } + } + return true; + } + + /** + * Delete products tags entries without delete tags for webservice usage + * + * @return array Deletion result + */ + public function deleteWsTags() + { + return Db::getInstance()->delete('product_tag', 'id_product = '.(int)$this->id); + } public function getWsManufacturerName() @@ -4681,7 +4807,7 @@ class ProductCore extends ObjectModel { return ObjectModel::updateMultishopTable('product', array( 'ecotax' => 0, - ), ''); + )); } /** @@ -5274,7 +5400,41 @@ class ProductCore extends ObjectModel public function getWsProductBundle() { - return Db::getInstance()->executeS('SELECT id_product_item as id, quantity FROM '._DB_PREFIX_.'pack where id_product_pack = '.(int)$this->id); + return Db::getInstance()->executeS('SELECT id_product_item as id, quantity FROM '._DB_PREFIX_.'pack WHERE id_product_pack = '.(int)$this->id); + } + + public function setWsType($type_str) + { + $reverse_type_information = array( + 'simple' => Product::PTYPE_SIMPLE, + 'pack' => Product::PTYPE_PACK, + 'virtual' => Product::PTYPE_VIRTUAL, + ); + + if (!isset($reverse_type_information[$type_str])) + return false; + + $type = $reverse_type_information[$type_str]; + + if (Pack::isPack((int)$this->id) && $type != Product::PTYPE_PACK) + Pack::deleteItems($this->id); + + $this->cache_is_pack = ($type == Product::PTYPE_PACK); + $this->is_virtual = ($type == Product::PTYPE_VIRTUAL); + + return true; + } + + public function setWsProductBundle($items) + { + if($this->is_virtual) + return false; + + Pack::deleteItems($this->id); + + foreach ($items as $item) + if((int)$item['id'] > 0) + Pack::addItem($this->id, (int)$item['id'], (int)$item['quantity']); + return true; } } - diff --git a/classes/ProductSale.php b/classes/ProductSale.php index 53503664d..2f8166a4d 100644 --- a/classes/ProductSale.php +++ b/classes/ProductSale.php @@ -34,7 +34,7 @@ class ProductSaleCore { $sql = 'REPLACE INTO '._DB_PREFIX_.'product_sale (`id_product`, `quantity`, `sale_nbr`, `date_upd`) - SELECT od.product_id, COUNT(od.product_id), SUM(od.product_quantity), NOW() + SELECT od.product_id, SUM(od.product_quantity), COUNT(od.product_id), NOW() FROM '._DB_PREFIX_.'order_detail od GROUP BY od.product_id'; return Db::getInstance()->execute($sql); } @@ -66,12 +66,19 @@ class ProductSaleCore if ($page_number < 0) $page_number = 0; if ($nb_products < 1) $nb_products = 10; $final_order_by = $order_by; + $order_table = ''; if (is_null($order_by) || $order_by == 'position' || $order_by == 'price') $order_by = 'sales'; - if (is_null($order_way) || $order_by == 'sales') $order_way == 'DESC'; + if ($order_by == 'date_add' || $order_by == 'date_upd') + $order_table = 'product_shop'; + if (is_null($order_way) || $order_by == 'sales') $order_way = 'DESC'; $groups = FrontController::getCurrentCustomerGroups(); $sql_groups = (count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'); $interval = Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20; - + + $prefix = ''; + if ($order_by == 'date_add') + $prefix = 'p.'; + $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, @@ -104,7 +111,7 @@ class ProductSaleCore WHERE cg.`id_group` '.$sql_groups.' ) GROUP BY product_shop.id_product - ORDER BY `'.pSQL($order_by).'` '.pSQL($order_way).' + ORDER BY '.(!empty($order_table) ? '`'.pSQL($order_table).'`.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way).' LIMIT '.(int)($page_number * $nb_products).', '.(int)$nb_products; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); diff --git a/classes/ProductSupplier.php b/classes/ProductSupplier.php index eb15f47c4..6ba1ea952 100644 --- a/classes/ProductSupplier.php +++ b/classes/ProductSupplier.php @@ -208,9 +208,10 @@ class ProductSupplierCore extends ObjectModel * * @param int $id_product * @param int $id_product_attribute Optional + * @param bool $converted_price Optional * @return Array keys: price_te, id_currency */ - public static function getProductPrice($id_supplier, $id_product, $id_product_attribute = 0) + public static function getProductPrice($id_supplier, $id_product, $id_product_attribute = 0, $converted_price = false) { if (is_null($id_supplier) || is_null($id_product)) return; @@ -222,6 +223,9 @@ class ProductSupplierCore extends ObjectModel $query->where('id_supplier = '.(int)$id_supplier); $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query); + if ($converted_price) + return Tools::convertPrice($row['price_te'], $row['id_currency']); + return $row['price_te']; } -} +} \ No newline at end of file diff --git a/classes/RequestSql.php b/classes/RequestSql.php index 43ac2a81f..27c0b966f 100644 --- a/classes/RequestSql.php +++ b/classes/RequestSql.php @@ -37,7 +37,7 @@ class RequestSqlCore extends ObjectModel 'primary' => 'id_request_sql', 'fields' => array( 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => true, 'size' => 200), - 'sql' => array('type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => true, 'size' => 1000), + 'sql' => array('type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => true), ), ); @@ -232,8 +232,6 @@ class RequestSqlCore extends ObjectModel { if ($attribut = $this->cutAttribute(trim($attr), $from)) $tab[] = $attribut; - else - return false; } return $tab; } diff --git a/classes/Scene.php b/classes/Scene.php index 86b53036e..b3bc32f5a 100644 --- a/classes/Scene.php +++ b/classes/Scene.php @@ -116,19 +116,12 @@ class SceneCore extends ObjectModel } public function deleteImage($force_delete = false) - { - // Hack to prevent the main scene image from being deleted in AdminController::uploadImage() when a thumb image is uploaded - if (isset($_FILES['thumb']) && (!isset($_FILES['image']) || empty($_FILES['image']['name']))) - return true; - - if (parent::deleteImage()) - { - if (file_exists($this->image_dir.'thumbs/'.$this->id.'-thumb_scene.'.$this->image_format) - && !unlink($this->image_dir.'thumbs/'.$this->id.'-thumb_scene.'.$this->image_format)) - return false; - } - else + { + if (file_exists($this->image_dir.'thumbs/'.$this->id.'-m_scene_default.'.$this->image_format) + && !unlink($this->image_dir.'thumbs/'.$this->id.'-m_scene_default.'.$this->image_format)) return false; + if (!(isset($_FILES) && count($_FILES))) + return parent::deleteImage(); return true; } diff --git a/classes/Search.php b/classes/Search.php index 1c9bbd68b..df3a4f23f 100644 --- a/classes/Search.php +++ b/classes/Search.php @@ -93,8 +93,12 @@ define('PREG_CLASS_CJK', '\x{3041}-\x{30ff}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{ class SearchCore { - public static function sanitize($string, $id_lang, $indexation = false) + public static function sanitize($string, $id_lang, $indexation = false, $iso_code = false) { + $string = trim($string); + if (empty($string)) + return ''; + $string = Tools::strtolower(strip_tags($string)); $string = html_entity_decode($string, ENT_NOQUOTES, 'utf-8'); @@ -102,11 +106,11 @@ class SearchCore $string = preg_replace('/['.PREG_CLASS_SEARCH_EXCLUDE.']+/u', ' ', $string); if ($indexation) - $string = preg_replace('/[._-]+/', '', $string); + $string = preg_replace('/[._-]+/', ' ', $string); else { $string = preg_replace('/[._]+/', '', $string); - $string = ltrim(preg_replace('/([^ ])-/', '$1', ' '.$string)); + $string = ltrim(preg_replace('/([^ ])-/', '$1 ', ' '.$string)); $string = preg_replace('/[._]+/', '', $string); $string = preg_replace('/[^\s]-+/', '', $string); } @@ -138,14 +142,34 @@ class SearchCore if ($indexation) { - $minWordLen = (int)Configuration::get('PS_SEARCH_MINWORDLEN'); - if ($minWordLen > 1) + // If the language is constituted with symbol and there is no "words", then split every chars + if (in_array($iso_code, array('zh', 'tw', 'ja')) && function_exists('mb_strlen')) { - $minWordLen -= 1; - $string = preg_replace('/(?<=\s)[^\s]{1,'.$minWordLen.'}(?=\s)/Su', ' ', $string); - $string = preg_replace('/^[^\s]{1,'.$minWordLen.'}(?=\s)/Su', '', $string); - $string = preg_replace('/(?<=\s)[^\s]{1,'.$minWordLen.'}$/Su', '', $string); - $string = preg_replace('/^[^\s]{1,'.$minWordLen.'}$/Su', '', $string); + // Cut symbols from letters + $symbols = ''; + $letters = ''; + foreach (explode(' ', $string) as $mb_word) + if (strlen(Tools::replaceAccentedChars($mb_word)) == mb_strlen(Tools::replaceAccentedChars($mb_word))) + $letters .= $mb_word.' '; + else + $symbols .= $mb_word.' '; + + if (preg_match_all('/./u', $symbols, $matches)) + $symbols = implode(' ', $matches[0]); + + $string = $letters.$symbols; + } + else + { + $minWordLen = (int)Configuration::get('PS_SEARCH_MINWORDLEN'); + if ($minWordLen > 1) + { + $minWordLen -= 1; + $string = preg_replace('/(?<=\s)[^\s]{1,'.$minWordLen.'}(?=\s)/Su', ' ', $string); + $string = preg_replace('/^[^\s]{1,'.$minWordLen.'}(?=\s)/Su', '', $string); + $string = preg_replace('/(?<=\s)[^\s]{1,'.$minWordLen.'}$/Su', '', $string); + $string = preg_replace('/^[^\s]{1,'.$minWordLen.'}$/Su', '', $string); + } } } @@ -175,7 +199,7 @@ class SearchCore $intersect_array = array(); $score_array = array(); - $words = explode(' ', Search::sanitize($expr, $id_lang)); + $words = explode(' ', Search::sanitize($expr, $id_lang, false, $context->language->iso_code)); foreach ($words as $key => $word) if (!empty($word) && strlen($word) >= (int)Configuration::get('PS_SEARCH_MINWORDLEN')) @@ -224,7 +248,7 @@ class SearchCore AND product_shop.`active` = 1 AND product_shop.`visibility` IN ("both", "search") AND product_shop.indexed = 1 - AND cg.`id_group` '.(!$id_customer ? '= 1' : 'IN ( + AND cg.`id_group` '.(!$id_customer ? '= '.(int)Configuration::get('PS_UNIDENTIFIED_GROUP') : 'IN ( SELECT id_group FROM '._DB_PREFIX_.'customer_group WHERE id_customer = '.(int)$id_customer.' )'); @@ -281,6 +305,8 @@ class SearchCore $alias = ''; if ($order_by == 'price') $alias = 'product_shop.'; + else if ($order_by == 'date_upd') + $alias = 'p.'; $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`, pl.`name`, MAX(image_shop.`id_image`) id_image, il.`legend`, m.`name` manufacturer_name '.$score.', MAX(product_attribute_shop.`id_product_attribute`) id_product_attribute, @@ -381,7 +407,7 @@ class SearchCore return Db::getInstance()->executeS(' SELECT p.id_product, pl.id_lang, pl.id_shop, pl.name pname, p.reference, p.ean13, p.upc, - pl.description_short, pl.description, cl.name cname, m.name mname + pl.description_short, pl.description, cl.name cname, m.name mname, l.iso_code FROM '._DB_PREFIX_.'product p LEFT JOIN '._DB_PREFIX_.'product_lang pl ON p.id_product = pl.id_product @@ -390,6 +416,8 @@ class SearchCore ON (cl.id_category = product_shop.id_category_default AND pl.id_lang = cl.id_lang AND cl.id_shop = product_shop.id_shop) LEFT JOIN '._DB_PREFIX_.'manufacturer m ON m.id_manufacturer = p.id_manufacturer + LEFT JOIN '._DB_PREFIX_.'lang l + ON l.id_lang = pl.id_lang WHERE product_shop.indexed = 0 AND product_shop.visibility IN ("both", "search") '.($id_product ? 'AND p.id_product = '.(int)$id_product : '').' @@ -408,7 +436,7 @@ class SearchCore { $db->execute('TRUNCATE '._DB_PREFIX_.'search_index'); $db->execute('TRUNCATE '._DB_PREFIX_.'search_word'); - ObjectModel::updateMultishopTable('Product', array('indexed' => 0), '1'); + ObjectModel::updateMultishopTable('Product', array('indexed' => 0)); } else { @@ -450,7 +478,6 @@ class SearchCore // Those are kind of global variables required to save the processed data in the database every X occurrences, in order to avoid overloading MySQL $count_words = 0; $query_array3 = array(); - $products_array = array(); // Every indexed words are cached into a PHP array $word_ids = $db->executeS(' @@ -470,6 +497,7 @@ class SearchCore // Products are processed 50 by 50 in order to avoid overloading MySQL while (($products = Search::getProductsToIndex($total_languages, $id_product, 50)) && (count($products) > 0)) { + $products_array = array(); // Now each non-indexed product is processed one by one, langage by langage foreach ($products as $product) { @@ -480,9 +508,9 @@ class SearchCore // Data must be cleaned of html, bad characters, spaces and anything, then if the resulting words are long enough, they're added to the array $product_array = array(); foreach ($product as $key => $value) - if (strncmp($key, 'id_', 3)) + if (strncmp($key, 'id_', 3) && isset($weight_array[$key])) { - $words = explode(' ', Search::sanitize($value, (int)$product['id_lang'], true)); + $words = explode(' ', Search::sanitize($value, (int)$product['id_lang'], true, $product['iso_code'])); foreach ($words as $word) if (!empty($word)) { @@ -569,6 +597,14 @@ class SearchCore return true; } + public static function removeProductsSearchIndex($products) + { + if (count($products)) { + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'search_index WHERE id_product IN ('.implode(',', $products).')'); + ObjectModel::updateMultishopTable('Product', array('indexed' => 0), 'a.id_product IN ('.implode(',', $products).')'); + } + } + protected static function setProductsAsIndexed(&$products) { if (count($products)) @@ -620,7 +656,7 @@ class SearchCore LEFT JOIN `'._DB_PREFIX_.'category_group` cg ON (cg.`id_category` = cp.`id_category`) WHERE product_shop.`active` = 1 AND cs.`id_shop` = '.(int)Context::getContext()->shop->id.' - AND cg.`id_group` '.(!$id_customer ? '= 1' : 'IN ( + AND cg.`id_group` '.(!$id_customer ? '= '.(int)Configuration::get('PS_UNIDENTIFIED_GROUP') : 'IN ( SELECT id_group FROM '._DB_PREFIX_.'customer_group WHERE id_customer = '.(int)$id_customer.')').' AND t.`name` LIKE \'%'.pSQL($tag).'%\''; @@ -654,7 +690,7 @@ class SearchCore '.Product::sqlStock('p', 0).' WHERE product_shop.`active` = 1 AND cs.`id_shop` = '.(int)Context::getContext()->shop->id.' - AND cg.`id_group` '.(!$id_customer ? '= 1' : 'IN ( + AND cg.`id_group` '.(!$id_customer ? '= '.(int)Configuration::get('PS_UNIDENTIFIED_GROUP') : 'IN ( SELECT id_group FROM '._DB_PREFIX_.'customer_group WHERE id_customer = '.(int)$id_customer.')').' AND t.`name` LIKE \'%'.pSQL($tag).'%\' @@ -666,4 +702,4 @@ class SearchCore return Product::getProductsProperties((int)$id_lang, $result); } -} +} \ No newline at end of file diff --git a/classes/SearchEngine.php b/classes/SearchEngine.php index 30bc7fa21..851d8b9ef 100644 --- a/classes/SearchEngine.php +++ b/classes/SearchEngine.php @@ -60,6 +60,8 @@ class SearchEngineCore extends ObjectModel if (empty($array[0])) return false; $str = urldecode(str_replace('+', ' ', ltrim(substr(rtrim($array[0], '&'), strlen($varname) + 1), '='))); + if (!Validate::isMessage($str)) + return false; return $str; } } diff --git a/classes/SpecificPrice.php b/classes/SpecificPrice.php index f47f1a5c4..27475c771 100644 --- a/classes/SpecificPrice.php +++ b/classes/SpecificPrice.php @@ -135,7 +135,7 @@ class SpecificPriceCore extends ObjectModel SELECT * FROM `'._DB_PREFIX_.'specific_price` WHERE `id_product` = '.(int)$id_product. - ($id_product_attribute ? 'AND id_product_attribute = '.(int)$id_product_attribute : '').' + ($id_product_attribute ? ' AND id_product_attribute = '.(int)$id_product_attribute : '').' AND id_cart = '.(int)$id_cart); } diff --git a/classes/Store.php b/classes/Store.php index e40d670e2..22a43ed66 100644 --- a/classes/Store.php +++ b/classes/Store.php @@ -91,8 +91,8 @@ class StoreCore extends ObjectModel 'address2' => array('type' => self::TYPE_STRING, 'validate' => 'isAddress', 'size' => 128), 'postcode' => array('type' => self::TYPE_STRING, 'size' => 12), 'city' => array('type' => self::TYPE_STRING, 'validate' => 'isCityName', 'required' => true, 'size' => 64), - 'latitude' => array('type' => self::TYPE_FLOAT, 'validate' => 'isCoordinate', 'size' => 12), - 'longitude' => array('type' => self::TYPE_FLOAT, 'validate' => 'isCoordinate', 'size' => 12), + 'latitude' => array('type' => self::TYPE_FLOAT, 'validate' => 'isCoordinate', 'size' => 13), + 'longitude' => array('type' => self::TYPE_FLOAT, 'validate' => 'isCoordinate', 'size' => 13), 'hours' => array('type' => self::TYPE_STRING, 'validate' => 'isSerializedArray', 'size' => 254), 'phone' => array('type' => self::TYPE_STRING, 'validate' => 'isPhoneNumber', 'size' => 16), 'fax' => array('type' => self::TYPE_STRING, 'validate' => 'isPhoneNumber', 'size' => 16), diff --git a/classes/Supplier.php b/classes/Supplier.php index 80bca2139..7749fb6de 100644 --- a/classes/Supplier.php +++ b/classes/Supplier.php @@ -95,7 +95,7 @@ class SupplierCore extends ObjectModel public function getLink() { - return Tools::link_rewrite($this->name, false); + return Tools::link_rewrite($this->name); } /** @@ -140,6 +140,7 @@ class SupplierCore extends ObjectModel WHERE ps.`id_supplier` = '.(int)$supplier['id_supplier'].' AND ps.id_product_attribute = 0'. ($active ? ' AND product_shop.`active` = 1' : ''). + ' AND product_shop.`visibility` NOT IN ("none")'. ($all_groups ? '' :' AND ps.`id_product` IN ( SELECT cp.`id_product` @@ -156,7 +157,7 @@ class SupplierCore extends ObjectModel $rewrite_settings = (int)Configuration::get('PS_REWRITING_SETTINGS'); for ($i = 0; $i < $nb_suppliers; $i++) if ($rewrite_settings) - $suppliers[$i]['link_rewrite'] = Tools::link_rewrite($suppliers[$i]['name'], false); + $suppliers[$i]['link_rewrite'] = Tools::link_rewrite($suppliers[$i]['name']); else $suppliers[$i]['link_rewrite'] = 0; return $suppliers; diff --git a/classes/Tab.php b/classes/Tab.php index 19d839031..94cb98de4 100644 --- a/classes/Tab.php +++ b/classes/Tab.php @@ -140,7 +140,11 @@ class TabCore extends ObjectModel public function delete() { if (Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'access WHERE `id_tab` = '.(int)$this->id) && parent::delete()) + { + if (is_array(self::$_getIdFromClassName) && isset(self::$_getIdFromClassName[strtolower($this->class_name)])) + unset(self::$_getIdFromClassName[strtolower($this->class_name)]); return $this->cleanPositions($this->id_parent); + } return false; } @@ -165,12 +169,18 @@ class TabCore extends ObjectModel */ public static function getCurrentParentId() { - if ($result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' - SELECT `id_parent` - FROM `'._DB_PREFIX_.'tab` - WHERE LOWER(class_name) = \''.pSQL(Tools::strtolower(Tools::getValue('controller'))).'\'')) - return $result['id_parent']; - return -1; + $cache_id = 'getCurrentParentId_'.Tools::strtolower(Tools::getValue('controller')); + if (!Cache::isStored($cache_id)) + { + $value = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + SELECT `id_parent` + FROM `'._DB_PREFIX_.'tab` + WHERE LOWER(class_name) = \''.pSQL(Tools::strtolower(Tools::getValue('controller'))).'\''); + if (!$value) + $value = -1; + Cache::store($cache_id, $value); + } + return Cache::retrieve($cache_id); } /** @@ -534,11 +544,10 @@ class TabCore extends ObjectModel foreach($tab->attributes() as $key => $value) if ($key == 'display_type') $display_type = (string)$value; - + foreach ($tab->children() as $module) - foreach ($module->attributes() as $k => $v) - if ($k == 'name') - $modules_list[$display_type][] = (string)$v; + $modules_list[$display_type][(int)$module['position']] = (string)$module['name']; + ksort($modules_list[$display_type]); } } diff --git a/classes/Tools.php b/classes/Tools.php index 7617ddec1..10e8d712e 100644 --- a/classes/Tools.php +++ b/classes/Tools.php @@ -267,6 +267,9 @@ class ToolsCore // $_SERVER['SSL'] exists only in some specific configuration if (isset($_SERVER['SSL'])) return ($_SERVER['SSL'] == 1 || strtolower($_SERVER['SSL']) == 'on'); + // $_SERVER['REDIRECT_HTTPS'] exists only in some specific configuration + if (isset($_SERVER['REDIRECT_HTTPS'])) + return ($_SERVER['REDIRECT_HTTPS'] == 1 || strtolower($_SERVER['REDIRECT_HTTPS']) == 'on'); return false; } @@ -335,15 +338,13 @@ class ToolsCore /* If language does not exist or is disabled, erase it */ if ($cookie->id_lang) { - //echo $cookie->id_lang;exit; $lang = new Language((int)$cookie->id_lang); if (!Validate::isLoadedObject($lang) || !$lang->active || !$lang->isAssociatedToShop()) $cookie->id_lang = null; - } - /* Automatically detect language if not already defined */ - if (!$cookie->id_lang && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) + /* Automatically detect language if not already defined, detect_language is set in Cookie::update */ + if ((!$cookie->id_lang || isset($cookie->detect_language)) && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { $array = explode(',', Tools::strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE'])); if (Tools::strlen($array[0]) > 2) @@ -357,9 +358,17 @@ class ToolsCore { $lang = new Language(Language::getIdByIso($string)); if (Validate::isLoadedObject($lang) && $lang->active) + { + $language = new Language((int)$lang->id); + if (Validate::isLoadedObject($language)) + Context::getContext()->language = $language; $cookie->id_lang = (int)$lang->id; + } } } + + if (isset($cookie->detect_language)) + unset($cookie->detect_language); /* If language file not present, you must use default language file */ if (!$cookie->id_lang || !Validate::isUnsignedId($cookie->id_lang)) @@ -396,7 +405,7 @@ class ToolsCore { $context->cookie->id_lang = $id_lang; $language = new Language($id_lang); - if (Validate::isLoadedObject($language)) + if (Validate::isLoadedObject($language) && $language->active) $context->language = $language; $params = $_GET; @@ -430,8 +439,11 @@ class ToolsCore { // get currency from context $currency = Shop::getEntityIds('currency', Context::getContext()->shop->id); - $cookie->id_currency = $currency[0]['id_currency']; - return Currency::getCurrencyInstance((int)$cookie->id_currency); + if (isset($currency[0]) && $currency[0]['id_currency']) + { + $cookie->id_currency = $currency[0]['id_currency']; + return Currency::getCurrencyInstance((int)$cookie->id_currency); + } } } $currency = Currency::getCurrencyInstance(Configuration::get('PS_CURRENCY_DEFAULT')); @@ -598,20 +610,25 @@ class ToolsCore */ public static function dateFormat($params, &$smarty) { - return Tools::displayDate($params['date'], Context::getContext()->language->id, (isset($params['full']) ? $params['full'] : false)); + return Tools::displayDate($params['date'], null, (isset($params['full']) ? $params['full'] : false)); } /** * Display date regarding to language preferences * * @param string $date Date to display format UNIX - * @param integer $id_lang Language id + * @param integer $id_lang Language id DEPRECATED * @param boolean $full With time or not (optional) * @param string $separator DEPRECATED * @return string Date */ - public static function displayDate($date, $id_lang, $full = false, $separator = '-') + public static function displayDate($date, $id_lang = null, $full = false, $separator = null) { + if ($id_lang !== null) + Tools::displayParameterAsDeprecated('id_lang'); + if ($separator !== null) + Tools::displayParameterAsDeprecated('separator'); + if (!$date || !($time = strtotime($date))) return $date; @@ -669,20 +686,36 @@ class ToolsCore public static function deleteDirectory($dirname, $delete_self = true) { $dirname = rtrim($dirname, '/').'/'; - if ($files = scandir($dirname)) - { - foreach ($files as $file) - if ($file != '.' && $file != '..' && $file != '.svn') + if (file_exists($dirname)) + if ($files = scandir($dirname)) { - if (is_dir($dirname.$file)) - Tools::deleteDirectory($dirname.$file, true); - elseif (file_exists($dirname.$file)) - unlink($dirname.$file); + foreach ($files as $file) + if ($file != '.' && $file != '..' && $file != '.svn') + { + if (is_dir($dirname.$file)) + Tools::deleteDirectory($dirname.$file, true); + elseif (file_exists($dirname.$file)) + unlink($dirname.$file); + } + if ($delete_self) + if (!rmdir($dirname)) + return false; + return true; } - if ($delete_self) - rmdir($dirname); - } - } + return false; + } + + /** + * Clear smarty cache folders + */ + public static function clearSmartyCache() + { + foreach (array(_PS_CACHE_DIR_.'smarty/cache', _PS_CACHE_DIR_.'smarty/compile') as $dir) + if (file_exists($dir)) + foreach (scandir($dir) as $file) + if ($file[0] != '.' && $file != 'index.php') + self::deleteDirectory($dir.DIRECTORY_SEPARATOR.$file); + } /** * Display an error according to an error code @@ -755,6 +788,33 @@ class ToolsCore { return (Tools::dieObject($object, $kill)); } + + public static function debug_backtrace($start = 0, $limit = null) + { + $backtrace = debug_backtrace(); + array_shift($backtrace); + for ($i = 0; $i < $start; ++$i) + array_shift($backtrace); + + echo ' +
        +
          '; + $i = 0; + foreach ($backtrace as $id => $trace) + { + if ((int)$limit && (++$i > $limit )) + break; + $relative_file = (isset($trace['file'])) ? 'in /'.ltrim(str_replace(array(_PS_ROOT_DIR_, '\\'), array('', '/'), $trace['file']), '/') : ''; + $current_line = (isset($trace['line'])) ? ':'.$trace['line'] : ''; + + echo '
        • + '.((isset($trace['class'])) ? $trace['class'] : '').((isset($trace['type'])) ? $trace['type'] : '').$trace['function'].' + '.$relative_file.$current_line.' +
        • '; + } + echo '
        +
        '; + } /** * ALIAS OF dieObject() - Display an error with detailed object but don't stop the execution @@ -958,11 +1018,13 @@ class ToolsCore * Return the friendly url from the provided string * * @param string $str - * @param bool $utf8_decode => needs to be marked as deprecated + * @param bool $utf8_decode (deprecated) * @return string */ - public static function link_rewrite($str, $utf8_decode = false) + public static function link_rewrite($str, $utf8_decode = null) { + if ($utf8_decode !== null) + Tools::displayParameterAsDeprecated('utf8_decode'); return Tools::str2url($str); } @@ -1012,45 +1074,66 @@ class ToolsCore */ public static function replaceAccentedChars($str) { + /* One source among others: + http://www.tachyonsoft.com/uc0000.htm + http://www.tachyonsoft.com/uc0001.htm + */ $patterns = array( + /* Lowercase */ - '/[\x{0105}\x{00E0}\x{00E1}\x{00E2}\x{00E3}\x{00E4}\x{00E5}]/u', - '/[\x{00E7}\x{010D}\x{0107}]/u', - '/[\x{010F}]/u', - '/[\x{00E8}\x{00E9}\x{00EA}\x{00EB}\x{011B}\x{0119}]/u', - '/[\x{00EC}\x{00ED}\x{00EE}\x{00EF}]/u', - '/[\x{0142}\x{013E}\x{013A}]/u', - '/[\x{00F1}\x{0148}]/u', - '/[\x{00F2}\x{00F3}\x{00F4}\x{00F5}\x{00F6}\x{00F8}]/u', - '/[\x{0159}\x{0155}]/u', - '/[\x{015B}\x{0161}]/u', - '/[\x{00DF}]/u', - '/[\x{0165}]/u', - '/[\x{00F9}\x{00FA}\x{00FB}\x{00FC}\x{016F}]/u', - '/[\x{00FD}\x{00FF}]/u', - '/[\x{017C}\x{017A}\x{017E}]/u', - '/[\x{00E6}]/u', - '/[\x{0153}]/u', + /* a */ '/[\x{00E0}\x{00E1}\x{00E2}\x{00E3}\x{00E4}\x{00E5}\x{0101}\x{0103}\x{0105}]/u', + /* c */ '/[\x{00E7}\x{0107}\x{0109}\x{010D}]/u', + /* d */ '/[\x{010F}\x{0111}]/u', + /* e */ '/[\x{00E8}\x{00E9}\x{00EA}\x{00EB}\x{0113}\x{0115}\x{0117}\x{0119}\x{011B}]/u', + /* g */ '/[\x{011F}\x{0121}\x{0123}]/u', + /* h */ '/[\x{0125}\x{0127}]/u', + /* i */ '/[\x{00EC}\x{00ED}\x{00EE}\x{00EF}\x{0129}\x{012B}\x{012D}\x{012F}\x{0131}]/u', + /* j */ '/[\x{0135}]/u', + /* k */ '/[\x{0137}\x{0138}]/u', + /* l */ '/[\x{013A}\x{013C}\x{013E}\x{0140}\x{0142}]/u', + /* n */ '/[\x{00F1}\x{0144}\x{0146}\x{0148}\x{0149}\x{014B}]/u', + /* o */ '/[\x{00F2}\x{00F3}\x{00F4}\x{00F5}\x{00F6}\x{00F8}\x{014D}\x{014F}\x{0151}]/u', + /* r */ '/[\x{0155}\x{0157}\x{0159}]/u', + /* s */ '/[\x{015B}\x{015D}\x{015F}\x{0161}]/u', + /* ss*/ '/[\x{00DF}]/u', + /* t */ '/[\x{0163}\x{0165}\x{0167}]/u', + /* u */ '/[\x{00F9}\x{00FA}\x{00FB}\x{00FC}\x{0169}\x{016B}\x{016D}\x{016F}\x{0171}\x{0173}]/u', + /* w */ '/[\x{0175}]/u', + /* y */ '/[\x{00FF}\x{0177}\x{00FD}]/u', + /* z */ '/[\x{017A}\x{017C}\x{017E}]/u', + /* ae*/ '/[\x{00E6}]/u', + /* oe*/ '/[\x{0153}]/u', /* Uppercase */ - '/[\x{0104}\x{00C0}\x{00C1}\x{00C2}\x{00C3}\x{00C4}\x{00C5}]/u', - '/[\x{00C7}\x{010C}\x{0106}]/u', - '/[\x{010E}]/u', - '/[\x{00C8}\x{00C9}\x{00CA}\x{00CB}\x{011A}\x{0118}]/u', - '/[\x{0141}\x{013D}\x{0139}]/u', - '/[\x{00D1}\x{0147}]/u', - '/[\x{00D3}]/u', - '/[\x{0158}\x{0154}]/u', - '/[\x{015A}\x{0160}]/u', - '/[\x{0164}]/u', - '/[\x{00D9}\x{00DA}\x{00DB}\x{00DC}\x{016E}]/u', - '/[\x{017B}\x{0179}\x{017D}]/u', - '/[\x{00C6}]/u', - '/[\x{0152}]/u'); + /* A */ '/[\x{0100}\x{0102}\x{0104}\x{00C0}\x{00C1}\x{00C2}\x{00C3}\x{00C4}\x{00C5}]/u', + /* C */ '/[\x{00C7}\x{0106}\x{0108}\x{010A}\x{010C}]/u', + /* D */ '/[\x{010E}\x{0110}]/u', + /* E */ '/[\x{00C8}\x{00C9}\x{00CA}\x{00CB}\x{0112}\x{0114}\x{0116}\x{0118}\x{011A}]/u', + /* G */ '/[\x{011C}\x{011E}\x{0120}\x{0122}]/u', + /* H */ '/[\x{0124}\x{0126}]/u', + /* I */ '/[\x{0128}\x{012A}\x{012C}\x{012E}\x{0130}]/u', + /* J */ '/[\x{0134}]/u', + /* K */ '/[\x{0136}]/u', + /* L */ '/[\x{0139}\x{013B}\x{013D}\x{0139}\x{0141}]/u', + /* N */ '/[\x{00D1}\x{0143}\x{0145}\x{0147}\x{014A}]/u', + /* O */ '/[\x{00D3}\x{014C}\x{014E}\x{0150}]/u', + /* R */ '/[\x{0154}\x{0156}\x{0158}]/u', + /* S */ '/[\x{015A}\x{015C}\x{015E}\x{0160}]/u', + /* T */ '/[\x{0162}\x{0164}\x{0166}]/u', + /* U */ '/[\x{00D9}\x{00DA}\x{00DB}\x{00DC}\x{0168}\x{016A}\x{016C}\x{016E}\x{0170}\x{0172}]/u', + /* W */ '/[\x{0174}]/u', + /* Y */ '/[\x{0176}]/u', + /* Z */ '/[\x{0179}\x{017B}\x{017D}]/u', + /* AE*/ '/[\x{00C6}]/u', + /* OE*/ '/[\x{0152}]/u'); + + // ö to oe + // å to aa + // ä to ae $replacements = array( - 'a', 'c', 'd', 'e', 'i', 'l', 'n', 'o', 'r', 's', 'ss', 't', 'u', 'y', 'z', 'ae', 'oe', - 'A', 'C', 'D', 'E', 'L', 'N', 'O', 'R', 'S', 'T', 'U', 'Z', 'AE', 'OE' + 'a', 'c', 'd', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r', 's', 'ss', 't', 'u', 'y', 'w', 'z', 'ae', 'oe', + 'A', 'C', 'D', 'E', 'G', 'H', 'I', 'J', 'K', 'L', 'N', 'O', 'R', 'S', 'T', 'U', 'Z', 'AE', 'OE' ); return preg_replace($patterns, $replacements, $str); @@ -1291,14 +1374,16 @@ class ToolsCore curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($curl, CURLOPT_TIMEOUT, $curl_timeout); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); - $opts = stream_context_get_options($stream_context); - if (isset($opts['http']['method']) && Tools::strtolower($opts['http']['method']) == 'post') - { - curl_setopt($curl, CURLOPT_POST, true); - if (isset($opts['http']['content'])) + if ($stream_context != null) { + $opts = stream_context_get_options($stream_context); + if (isset($opts['http']['method']) && Tools::strtolower($opts['http']['method']) == 'post') { - parse_str($opts['http']['content'], $datas); - curl_setopt($curl, CURLOPT_POSTFIELDS, $datas); + curl_setopt($curl, CURLOPT_POST, true); + if (isset($opts['http']['content'])) + { + parse_str($opts['http']['content'], $datas); + curl_setopt($curl, CURLOPT_POSTFIELDS, $datas); + } } } $content = curl_exec($curl); @@ -1313,9 +1398,30 @@ class ToolsCore { return @simplexml_load_string(Tools::file_get_contents($url), $class_name); } + + public static function copy($source, $destination, $stream_context = null) + { + if ($stream_context == null && preg_match('/^https?:\/\//', $source)) + $stream_context = @stream_context_create(array('http' => array('timeout' => 10))); - - public static $a = 0; + if (in_array(@ini_get('allow_url_fopen'), array('On', 'on', '1')) || !preg_match('/^https?:\/\//', $source)) + return @copy($source, $destination, $stream_context); + elseif (function_exists('curl_init')) + { + $curl = curl_init(); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_URL, $source); + curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5); + curl_setopt($curl, CURLOPT_TIMEOUT, 10); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); + $opts = stream_context_get_options($stream_context); + $content = curl_exec($curl); + curl_close($curl); + return file_put_contents($destination, $content); + } + else + return false; + } /** * @deprecated as of 1.5 use Media::minifyHTML() @@ -1328,13 +1434,13 @@ class ToolsCore /** * Translates a string with underscores into camel case (e.g. first_name -> firstName) - * @prototype string public static function toCamelCase(string $str[, bool $catapitalise_first_char = false]) + * @prototype string public static function toCamelCase(string $str[, bool $capitalise_first_char = false]) */ public static function toCamelCase($str, $catapitalise_first_char = false) { - $str = strtolower($str); + $str = Tools::strtolower($str); if ($catapitalise_first_char) - $str = ucfirst($str); + $str = Tools::ucfirst($str); return preg_replace_callback('/_+([a-z])/', create_function('$c', 'return strtoupper($c[1]);'), $str); } @@ -1490,7 +1596,7 @@ class ToolsCore if (self::$_cache_nb_media_servers && ($id_media_server = (abs(crc32($filename)) % self::$_cache_nb_media_servers + 1))) return constant('_MEDIA_SERVER_'.$id_media_server.'_'); - return Tools::getHttpHost(); + return Tools::getShopDomain(); } public static function generateHtaccess($path = null, $rewrite_settings = null, $cache_control = null, $specific = '', $disable_multiviews = null, $medias = false, $disable_modsec = null) @@ -1530,7 +1636,7 @@ class ToolsCore } // Write .htaccess data - if (!$write_fd = @fopen($path, 'w')) + if (!$write_fd = fopen($path, 'w')) return false; fwrite($write_fd, trim($specific_before)."\n\n"); @@ -1822,8 +1928,8 @@ exit; { $backtrace = debug_backtrace(); $callee = next($backtrace); - $error = 'Parameter '.$parameter.' in function '.$callee['function'].'() is deprecated in '.$callee['file'].' on line '.$callee['Line'].'
        '; - $message = 'The parameter '.$parameter.' in function '.$callee['function'].' (Line '.$callee['Line'].') is deprecated and will be removed in the next major version.'; + $error = 'Parameter '.$parameter.' in function '.(isset($callee['function']) ? $callee['function'] : '').'() is deprecated in '.$callee['file'].' on line '.(isset($callee['line']) ? $callee['line'] : '(undefined)').'
        '; + $message = 'The parameter '.$parameter.' in function '.$callee['function'].' (Line '.(isset($callee['line']) ? $callee['line'] : 'undefined').') is deprecated and will be removed in the next major version.'; $class = isset($callee['class']) ? $callee['class'] : null; Tools::throwDeprecated($error, $message, $class); @@ -2068,6 +2174,9 @@ exit; } } + /** + * @deprecated as of 1.5 use Controller::getController('PageNotFoundController')->run(); + */ public static function display404Error() { header('HTTP/1.1 404 Not Found'); @@ -2175,6 +2284,28 @@ exit; return (PHP_INT_MAX == '9223372036854775807'); } + /** + * + * @return bool true if php-cli is used + */ + public static function isPHPCLI() + { + return (defined('STDIN') || (Tools::strtolower(php_sapi_name()) == 'cli' && (!isset($_SERVER['REMOTE_ADDR']) || empty($_SERVER['REMOTE_ADDR'])))); + } + + public static function argvToGET($argc, $argv) + { + if ($argc <= 1) + return; + + // get the first argument and parse it like a query string + parse_str($argv[1], $args); + if (!is_array($args) || !count($args)) + return; + $_GET = array_merge($args, $_GET); + $_SERVER['QUERY_STRING'] = $argv[1]; + } + /** * Get max file upload size considering server settings and optional max value * @@ -2346,7 +2477,7 @@ exit; return $pattern; return preg_replace('/\\\[px]\{[a-z]\}{1,2}|(\/[a-z]*)u([a-z]*)$/i', "$1$2", $pattern); } - + public static function addonsRequest($request, $params = array()) { $addons_url = 'api.addons.prestashop.com'; @@ -2432,6 +2563,21 @@ exit; // No content, return false return false; } + + public static function fileAttachment($input = 'fileUpload') + { + $fileAttachment = null; + if (isset($_FILES[$input]['name']) && !empty($_FILES[$input]['name']) && !empty($_FILES[$input]['tmp_name'])) + { + $fileAttachment['rename'] = uniqid(). Tools::strtolower(substr($_FILES[$input]['name'], -5)); + $fileAttachment['content'] = file_get_contents($_FILES[$input]['tmp_name']); + $fileAttachment['tmp_name'] = $_FILES[$input]['tmp_name']; + $fileAttachment['name'] = $_FILES[$input]['name']; + $fileAttachment['mime'] = $_FILES[$input]['type']; + $fileAttachment['error'] = $_FILES[$input]['error']; + } + return $fileAttachment; + } } /** diff --git a/classes/Translate.php b/classes/Translate.php index 549158861..bbf4a5bdd 100644 --- a/classes/Translate.php +++ b/classes/Translate.php @@ -180,7 +180,13 @@ class TranslateCore if ($js) $ret = addslashes($ret); - $lang_cache[$cache_key] = str_replace('"', '"', $ret); + $ret = str_replace('"', '"', $ret); + + if ($sprintf === null) + $lang_cache[$cache_key] = $ret; + else + return $ret; + } return $lang_cache[$cache_key]; } diff --git a/classes/Validate.php b/classes/Validate.php index 84d8bc24e..d59a63fa0 100644 --- a/classes/Validate.php +++ b/classes/Validate.php @@ -174,7 +174,7 @@ class ValidateCore */ public static function isMailName($mail_name) { - return preg_match(Tools::cleanNonUnicodeSupport('/^[^<>;=#{}]*$/u'), $mail_name); + return (is_string($mail_name) && preg_match(Tools::cleanNonUnicodeSupport('/^[^<>;=#{}]*$/u'), $mail_name)); } /** @@ -229,7 +229,7 @@ class ValidateCore */ public static function isPrice($price) { - return preg_match('/^[0-9]{1,10}(\.[0-9]{1,9})?$/', $price); + return preg_match('/^[0-9]{1,10}(\.[0-9]{1,9})?$/', sprintf('%f', $price)); } /** @@ -240,7 +240,7 @@ class ValidateCore */ public static function isNegativePrice($price) { - return preg_match('/^[-]?[0-9]{1,10}(\.[0-9]{1,9})?$/', $price); + return preg_match('/^[-]?[0-9]{1,10}(\.[0-9]{1,9})?$/', sprintf('%f', $price)); } /** @@ -380,7 +380,7 @@ class ValidateCore */ public static function isGenericName($name) { - return empty($name) || preg_match('/^[^<>=#{}]*$/u', $name); + return empty($name) || preg_match('/^[^<>={}]*$/u', $name); } /** @@ -389,7 +389,7 @@ class ValidateCore * @param string $html HTML field to validate * @return boolean Validity is ok or not */ - public static function isCleanHtml($html) + public static function isCleanHtml($html, $allow_iframe = false) { $events = 'onmousedown|onmousemove|onmmouseup|onmouseover|onmouseout|onload|onunload|onfocus|onblur|onchange'; $events .= '|onsubmit|ondblclick|onclick|onkeydown|onkeyup|onkeypress|onmouseenter|onmouseleave|onerror|onselect|onreset|onabort|ondragdrop|onresize|onactivate|onafterprint|onmoveend'; @@ -398,7 +398,14 @@ class ValidateCore $events .= '|ondragleave|ondragover|ondragstart|ondrop|onerrorupdate|onfilterchange|onfinish|onfocusin|onfocusout|onhashchange|onhelp|oninput|onlosecapture|onmessage|onmouseup|onmovestart'; $events .= '|onoffline|ononline|onpaste|onpropertychange|onreadystatechange|onresizeend|onresizestart|onrowenter|onrowexit|onrowsdelete|onrowsinserted|onscroll|onsearch|onselectionchange'; $events .= '|onselectstart|onstart|onstop'; - return (!preg_match('/<[ \t\n]*script/ims', $html) && !preg_match('/('.$events.')[ \t\n]*=/ims', $html) && !preg_match('/.*script\:/ims', $html) && !preg_match('/<[ \t\n]*i?frame/ims', $html)); + + if (preg_match('/<[\s]*script/ims', $html) || preg_match('/('.$events.')[\s]*=/ims', $html) || preg_match('/.*script\:/ims', $html)) + return false; + + if (!$allow_iframe && preg_match('/<[\s]*(i?frame|form|input|embed|object)/ims', $html)) + return false; + + return true; } /** @@ -724,7 +731,7 @@ class ValidateCore */ public static function isTrackingNumber($tracking_number) { - return preg_match('/^[~:#,%&_=\(\)\.\? \+\-@\/a-zA-Z0-9]+$/', $tracking_number); + return preg_match('/^[~:#,%&_=\(\)\[\]\.\? \+\-@\/a-zA-Z0-9]+$/', $tracking_number); } /** @@ -747,7 +754,7 @@ class ValidateCore public static function isAbsoluteUrl($url) { if (!empty($url)) - return preg_match('/^https?:\/\/[,:#%&_=\(\)\.\? \+\-@\/a-zA-Z0-9]+$/', $url); + return preg_match('/^https?:\/\/[~:#,%&_=\(\)\[\]\.\? \+\-@\/a-zA-Z0-9]+$/', $url); return true; } @@ -1055,6 +1062,9 @@ class ValidateCore { return (bool)(is_string($name) && preg_match('/^[0-9a-zA-Z-_]*$/u', $name)); } - -} - + + public static function isPrestaShopVersion($version) + { + return (preg_match('/^[0-1]\.[0-9]{1,2}(\.[0-9]{1,2}){0,2}$/', $version) && ip2long($version)); + } +} \ No newline at end of file diff --git a/classes/cache/Cache.php b/classes/cache/Cache.php index 9343f04e7..994f06c31 100755 --- a/classes/cache/Cache.php +++ b/classes/cache/Cache.php @@ -144,7 +144,7 @@ abstract class CacheCore */ public function set($key, $value, $ttl = 0) { - if ($this->_set($key, $value)) + if ($this->_set($key, $value, $ttl)) { if ($ttl < 0) $ttl = 0; diff --git a/classes/cache/CacheFs.php b/classes/cache/CacheFs.php index 538ea18b8..4b37b58a3 100755 --- a/classes/cache/CacheFs.php +++ b/classes/cache/CacheFs.php @@ -149,6 +149,7 @@ class CacheFsCore extends Cache */ protected function getFilename($key) { + $key = md5($key); $path = _PS_CACHEFS_DIRECTORY_; for ($i = 0; $i < $this->depth; $i++) $path .= $key[$i].'/'; diff --git a/classes/cache/CacheMemcache.php b/classes/cache/CacheMemcache.php index 99ef0ee92..046d40529 100755 --- a/classes/cache/CacheMemcache.php +++ b/classes/cache/CacheMemcache.php @@ -44,11 +44,19 @@ class CacheMemcacheCore extends Cache { $this->connect(); - // Get keys (this code comes from Doctrine 2 project) $this->keys = array(); $servers = self::getMemcachedServers(); - if(is_array($servers) && count($servers) > 0 && method_exists('Memcache', 'getStats')) + if(is_array($servers) && count($servers) > 0) + { + $this->keys = $this->memcache->get(_COOKIE_IV_); + if (!is_array($this->keys)) + $this->keys = array(); + } + + /* + // Get keys (this code comes from Doctrine 2 project) + if(is_array($servers) && count($servers) > 0 && method_exists('Memcache', 'getStats')) $all_slabs = $this->memcache->getStats('slabs'); if(isset($all_slabs) && is_array($all_slabs)) @@ -56,23 +64,24 @@ class CacheMemcacheCore extends Cache { if (is_array($slabs)) { - foreach (array_keys($slabs) as $slab_id) + foreach (array_keys($slabs) as $i => $slab_id) // $slab_id is not an int but a string, using the key instead ? { - if(is_int($slab_id)) - { - $dump = $this->memcache->getStats('cachedump', (int)$slab_id); + if(is_int($i)) + { + $dump = $this->memcache->getStats('cachedump', (int)$i); if ($dump) { foreach ($dump as $entries) { - if ($entries) - $this->keys = array_merge($this->keys, array_keys($entries)); + if($entries) + foreach ($entries as $key => $data) + $this->keys[$key] = $data[1]; } } } } } - } + }*/ } public function __destruct() @@ -144,6 +153,7 @@ class CacheMemcacheCore extends Cache */ protected function _writeKeys() { + $this->memcache->set(_COOKIE_IV_, $this->keys); } /** diff --git a/classes/controller/AdminController.php b/classes/controller/AdminController.php index 87f4d5ea7..a84eb1a0e 100644 --- a/classes/controller/AdminController.php +++ b/classes/controller/AdminController.php @@ -47,6 +47,8 @@ class AdminControllerCore extends Controller /** @var string Associated table name */ public $table; + public $list_id; + /** @var string Object identifier inside the associated table */ protected $identifier = false; @@ -313,7 +315,7 @@ class AdminControllerCore extends Controller 19 => $this->l('Duplication was completed successfully.'), 20 => $this->l('The translation was added successfully, but the language has not been created.'), 21 => $this->l('Module reset successfully.'), 22 => $this->l('Module deleted successfully.'), 23 => $this->l('Localization pack imported successfully.'), 24 => $this->l('Localization pack imported successfully.'), - 25 => $this->l('The selcted images have successfully been moved.'), + 25 => $this->l('The selected images have successfully been moved.'), 26 => $this->l('Your cover selection has been saved.'), 27 => $this->l('The image shop association has been modified.'), 28 => $this->l('A zone has been assigned to the selection successfully.'), @@ -379,6 +381,39 @@ class AdminControllerCore extends Controller break; } $this->toolbar_title = $bread_extended; + + if (Tools::isSubmit('submitFilter')) + { + $filter = ''; + foreach ($this->fields_list AS $field => $t) + { + if ($val = htmlspecialchars(Tools::getValue($this->table.'Filter_'.$field), ENT_QUOTES, 'UTF-8')) + { + if(!is_array($val) && !empty($val)) + $filter .= ($filter ? ', ' : $this->l(' filter by ')).$t['title'].' : '; + + if (isset($t['type']) && $t['type'] == 'bool') + $filter .= ((bool)$val) ? $this->l('yes') : $this->l('no'); + elseif(is_string($val)) + $filter .= $val; + elseif(is_array($val)) + { + $tmp = ''; + foreach($val as $v) + if(is_string($v) && !empty($v)) + $tmp .= ' - '.$v; + if(Tools::strlen($tmp)) + { + $tmp = ltrim($tmp, ' - '); + $filter .= ($filter ? ', ' : $this->l(' filter by ')).$t['title'].' : '; + $filter .= $tmp; + } + } + } + } + if ($filter) + $this->toolbar_title[] = $filter; + } } /** @@ -429,29 +464,33 @@ class AdminControllerCore extends Controller */ public function processFilter() { + if (!isset($this->list_id)) + $this->list_id = $this->table; + $prefix = str_replace(array('admin', 'controller'), '', Tools::strtolower(get_class($this))); // Filter memorization - if (isset($_POST) && !empty($_POST) && isset($this->table)) + if (isset($_POST) && !empty($_POST) && isset($this->list_id)) foreach ($_POST as $key => $value) { - if (stripos($key, $this->table.'Filter_') === 0) + if (stripos($key, $this->list_id.'Filter_') === 0) $this->context->cookie->{$prefix.$key} = !is_array($value) ? $value : serialize($value); elseif(stripos($key, 'submitFilter') === 0) $this->context->cookie->$key = !is_array($value) ? $value : serialize($value); } - if (isset($_GET) && !empty($_GET) && isset($this->table)) + if (isset($_GET) && !empty($_GET) && isset($this->list_id)) foreach ($_GET as $key => $value) - if (stripos($key, $this->table.'OrderBy') === 0 || stripos($key, $this->table.'Orderway') === 0) + if (stripos($key, $this->list_id.'OrderBy') === 0 || stripos($key, $this->list_id.'Orderway') === 0) $this->context->cookie->{$prefix.$key} = $value; - $filters = $this->context->cookie->getFamily($prefix.$this->table.'Filter_'); + $filters = $this->context->cookie->getFamily($prefix.$this->list_id.'Filter_'); + foreach ($filters as $key => $value) { /* Extracting filters from $_POST on key filter_ */ - if ($value != null && !strncmp($key, $prefix.$this->table.'Filter_', 7 + Tools::strlen($prefix.$this->table))) + if ($value != null && !strncmp($key, $prefix.$this->list_id.'Filter_', 7 + Tools::strlen($prefix.$this->list_id))) { - $key = Tools::substr($key, 7 + Tools::strlen($prefix.$this->table)); + $key = Tools::substr($key, 7 + Tools::strlen($prefix.$this->list_id)); /* Table alias could be specified using a ! eg. alias!field */ $tmp_tab = explode('!', $key); $filter = count($tmp_tab) > 1 ? $tmp_tab[1] : $tmp_tab[0]; @@ -513,37 +552,42 @@ class AdminControllerCore extends Controller */ public function postProcess() { - if ($this->ajax) - { - // from ajax-tab.php - $action = Tools::getValue('action'); - // no need to use displayConf() here - if (!empty($action) && method_exists($this, 'ajaxProcess'.Tools::toCamelCase($action))) - return $this->{'ajaxProcess'.Tools::toCamelCase($action)}(); - elseif (method_exists($this, 'ajaxProcess')) - return $this->ajaxProcess(); - } - else - { - // Process list filtering - if ($this->filter) - $this->processFilter(); - - // If the method named after the action exists, call "before" hooks, then call action method, then call "after" hooks - if (!empty($this->action) && method_exists($this, 'process'.ucfirst(Tools::toCamelCase($this->action)))) + try { + if ($this->ajax) { - // Hook before action - Hook::exec('actionAdmin'.ucfirst($this->action).'Before', array('controller' => $this)); - Hook::exec('action'.get_class($this).ucfirst($this->action).'Before', array('controller' => $this)); - // Call process - $return = $this->{'process'.Tools::toCamelCase($this->action)}(); - // Hook After Action - Hook::exec('actionAdmin'.ucfirst($this->action).'After', array('controller' => $this, 'return' => $return)); - Hook::exec('action'.get_class($this).ucfirst($this->action).'After', array('controller' => $this, 'return' => $return)); - - return $return; + // from ajax-tab.php + $action = Tools::getValue('action'); + // no need to use displayConf() here + if (!empty($action) && method_exists($this, 'ajaxProcess'.Tools::toCamelCase($action))) + return $this->{'ajaxProcess'.Tools::toCamelCase($action)}(); + elseif (method_exists($this, 'ajaxProcess')) + return $this->ajaxProcess(); } - } + else + { + // Process list filtering + if ($this->filter) + $this->processFilter(); + + // If the method named after the action exists, call "before" hooks, then call action method, then call "after" hooks + if (!empty($this->action) && method_exists($this, 'process'.ucfirst(Tools::toCamelCase($this->action)))) + { + // Hook before action + Hook::exec('actionAdmin'.ucfirst($this->action).'Before', array('controller' => $this)); + Hook::exec('action'.get_class($this).ucfirst($this->action).'Before', array('controller' => $this)); + // Call process + $return = $this->{'process'.Tools::toCamelCase($this->action)}(); + // Hook After Action + Hook::exec('actionAdmin'.ucfirst($this->action).'After', array('controller' => $this, 'return' => $return)); + Hook::exec('action'.get_class($this).ucfirst($this->action).'After', array('controller' => $this, 'return' => $return)); + + return $return; + } + } + } catch (PrestaShopException $e) { + $this->errors[] = $e->getMessage(); + }; + return false; } /** @@ -583,16 +627,27 @@ class AdminControllerCore extends Controller $headers = array(); foreach ($this->fields_list as $datas) $headers[] = Tools::htmlentitiesDecodeUTF8($datas['title']); - $content = array(); foreach ($this->_list as $i => $row) { $content[$i] = array(); - foreach ($this->fields_list as $key => $value) - if (isset($row[$key])) - $content[$i][] = Tools::htmlentitiesDecodeUTF8($row[$key]); - + $path_to_image = false; + foreach ($this->fields_list as $key => $params) + { + $field_value = isset($row[$key]) ? Tools::htmlentitiesDecodeUTF8($row[$key]) : ''; + if ($key == 'image') + { + if ($params['image'] != 'p' || Configuration::get('PS_LEGACY_IMAGES')) + $path_to_image = Tools::getShopDomain(true)._PS_IMG_.$params['image'].'/'.$row['id_'.$this->table].(isset($row['id_image']) ? '-'.(int)$row['id_image'] : '').'.'.$this->imageType; + else + $path_to_image = Tools::getShopDomain(true)._PS_IMG_.$params['image'].'/'.Image::getImgFolderStatic($row['id_image']).(int)$row['id_image'].'.'.$this->imageType; + if ($path_to_image) + $field_value = $path_to_image; + } + $content[$i][] = $field_value; + } } + $this->context->smarty->assign(array( 'export_precontent' => "\xEF\xBB\xBF", 'export_headers' => $headers, @@ -631,12 +686,14 @@ class AdminControllerCore extends Controller $this->errors[] = Tools::displayError('Unable to delete associated images.'); $object->deleted = 1; - if ($object->update()) + if ($res = $object->update()) $this->redirect_after = self::$currentIndex.'&conf=1&token='.$this->token; } - elseif ($object->delete()) + elseif ($res = $object->delete()) $this->redirect_after = self::$currentIndex.'&conf=1&token='.$this->token; $this->errors[] = Tools::displayError('An error occurred during deletion.'); + if ($res) + Logger::addLog(sprintf($this->l('%s deletion'), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id); } } else @@ -685,6 +742,7 @@ class AdminControllerCore extends Controller /* voluntary do affectation here */ elseif (($_POST[$this->identifier] = $this->object->id) && $this->postImage($this->object->id) && !count($this->errors) && $this->_redirect) { + Logger::addLog(sprintf($this->l('%s addition'), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id); $parent_id = (int)Tools::getValue('id_parent', 1); $this->afterAdd($this->object); $this->updateAssoShop($this->object->id); @@ -719,7 +777,6 @@ class AdminControllerCore extends Controller { /* Checking fields validity */ $this->validateRules(); - if (empty($this->errors)) { $id = (int)Tools::getValue($this->identifier); @@ -785,6 +842,7 @@ class AdminControllerCore extends Controller if (empty($this->redirect_after)) $this->redirect_after = self::$currentIndex.($parent_id ? '&'.$this->identifier.'='.$object->id : '').'&conf=4&token='.$this->token; } + Logger::addLog(sprintf($this->l('%s edition'), $this->className), 1, null, $this->className, (int)$object->id, true, (int)$this->context->employee->id); } else $this->errors[] = Tools::displayError('An error occurred while updating an object.'). @@ -868,30 +926,32 @@ class AdminControllerCore extends Controller /** * Cancel all filters for this tab */ - public function processResetFilters() + public function processResetFilters($list_id = null) { + if (!isset($list_id)) + $list_id = isset($this->list_id) ? $this->list_id : $this->table; + $prefix = str_replace(array('admin', 'controller'), '', Tools::strtolower(get_class($this))); - $filters = $this->context->cookie->getFamily($prefix.$this->table.'Filter_'); + $filters = $this->context->cookie->getFamily($prefix.$list_id.'Filter_'); + foreach ($filters as $cookie_key => $filter) - if (strncmp($cookie_key, $prefix.$this->table.'Filter_', 7 + Tools::strlen($prefix.$this->table)) == 0) + if (strncmp($cookie_key, $prefix.$list_id.'Filter_', 7 + Tools::strlen($prefix.$list_id)) == 0) { - $key = substr($cookie_key, 7 + Tools::strlen($prefix.$this->table)); - /* Table alias could be specified using a ! eg. alias!field */ - $tmp_tab = explode('!', $key); - $key = (count($tmp_tab) > 1 ? $tmp_tab[1] : $tmp_tab[0]); + $key = substr($cookie_key, 7 + Tools::strlen($prefix.$list_id)); if (is_array($this->fields_list) && array_key_exists($key, $this->fields_list)) + $this->context->cookie->$cookie_key = null; unset($this->context->cookie->$cookie_key); } - if (isset($this->context->cookie->{'submitFilter'.$this->table})) - unset($this->context->cookie->{'submitFilter'.$this->table}); + if (isset($this->context->cookie->{'submitFilter'.$list_id})) + unset($this->context->cookie->{'submitFilter'.$list_id}); - if (isset($this->context->cookie->{$prefix.$this->table.'Orderby'})) - unset($this->context->cookie->{$prefix.$this->table.'Orderby'}); + if (isset($this->context->cookie->{$prefix.$list_id.'Orderby'})) + unset($this->context->cookie->{$prefix.$list_id.'Orderby'}); - if (isset($this->context->cookie->{$prefix.$this->table.'Orderway'})) - unset($this->context->cookie->{$prefix.$this->table.'Orderway'}); + if (isset($this->context->cookie->{$prefix.$list_id.'Orderway'})) + unset($this->context->cookie->{$prefix.$list_id.'Orderway'}); unset($_POST); $this->_filter = false; @@ -939,7 +999,8 @@ class AdminControllerCore extends Controller continue; // Check if field is required - if (isset($values['required']) && $values['required'] && !empty($_POST['multishopOverrideOption'][$field])) + if ((!Shop::isFeatureActive() && isset($values['required']) && $values['required']) + || (Shop::isFeatureActive() && isset($_POST['multishopOverrideOption'][$field]) && isset($values['required']) && $values['required'])) if (isset($values['type']) && $values['type'] == 'textLang') { foreach ($languages as $language) @@ -1100,7 +1161,7 @@ class AdminControllerCore extends Controller } else { - $this->errors[] = Tools::displayError('The object cannot be loaded (ithe dentifier is missing or invalid)'); + $this->errors[] = Tools::displayError('The object cannot be loaded (the dentifier is missing or invalid)'); return false; } @@ -1131,6 +1192,9 @@ class AdminControllerCore extends Controller protected function filterToField($key, $filter) { + if (!isset($this->fields_list)) + return false; + foreach ($this->fields_list as $field) if (array_key_exists('filter_key', $field) && $field['filter_key'] == $key) return $field; @@ -1161,6 +1225,7 @@ class AdminControllerCore extends Controller header('Location: '.$this->redirect_after); exit; } + public function display() { $this->context->smarty->assign(array( @@ -1176,8 +1241,7 @@ class AdminControllerCore extends Controller $tpl_action = $this->tpl_folder.$this->display.'.tpl'; - // Check if action template has been override - + // Check if action template has been overriden foreach ($this->context->smarty->getTemplateDir() as $template_dir) if (file_exists($template_dir.DIRECTORY_SEPARATOR.$tpl_action) && $this->display != 'view' && $this->display != 'options') { @@ -1196,27 +1260,15 @@ class AdminControllerCore extends Controller $page = $this->content; if ($conf = Tools::getValue('conf')) - if ($this->json) - $this->context->smarty->assign('conf', Tools::jsonEncode($this->_conf[(int)$conf])); - else - $this->context->smarty->assign('conf', $this->_conf[(int)$conf]); - - $notifications_type = array('errors', 'warnings', 'informations', 'confirmations'); - foreach($notifications_type as $type) - if ($this->json) - $this->context->smarty->assign($type, Tools::jsonEncode(array_unique($this->$type))); - else - $this->context->smarty->assign($type, array_unique($this->$type)); + $this->context->smarty->assign('conf', $this->json ? Tools::jsonEncode($this->_conf[(int)$conf]) : $this->_conf[(int)$conf]); - if ($this->json) - $this->context->smarty->assign('page', Tools::jsonEncode($page)); - else - $this->context->smarty->assign('page', $page); - + foreach (array('errors', 'warnings', 'informations', 'confirmations') as $type) + $this->context->smarty->assign($type, $this->json ? Tools::jsonEncode(array_unique($this->$type)) : array_unique($this->$type)); + + $this->context->smarty->assign('page', $this->json ? Tools::jsonEncode($page) : $page); $this->smartyOutputContent($this->layout); } - /** * add a warning message to display at the top of the page * @@ -1278,7 +1330,7 @@ class AdminControllerCore extends Controller $current_id = Tab::getCurrentParentId(); foreach ($tabs as $index => $tab) { - if ($tab['class_name'] == 'AdminStock' && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') == 0) + if (($tab['class_name'] == 'AdminStock' && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') == 0) || $tab['class_name'] == 'AdminCarrierWizard') { unset($tabs[$index]); continue; @@ -1318,11 +1370,13 @@ class AdminControllerCore extends Controller foreach ($sub_tabs as $index2 => $sub_tab) { // class_name is the name of the class controller - if (Tab::checkTabRights($sub_tab['id_tab']) === true - && (bool)$sub_tab['active']) + if (Tab::checkTabRights($sub_tab['id_tab']) === true && (bool)$sub_tab['active'] && $sub_tab['class_name'] != 'AdminCarrierWizard') + { $sub_tabs[$index2]['href'] = $this->context->link->getAdminLink($sub_tab['class_name']); + $sub_tabs[$index2]['current'] = ($sub_tab['class_name'].'Controller' == get_class($this)); + } else - unset($sub_tabs[$index2]); + unset($sub_tabs[$index2]); } $tabs[$index]['sub_tabs'] = $sub_tabs; @@ -1458,6 +1512,8 @@ class AdminControllerCore extends Controller */ protected function initTabModuleList() { + if (!$this->isFresh(Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, 86400)) + @file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, Tools::addonsRequest('must-have')); if (!$this->isFresh(Module::CACHE_FILE_TAB_MODULES_LIST, 604800)) $this->refresh(Module::CACHE_FILE_TAB_MODULES_LIST, 'http://'.Tab::TAB_MODULE_LIST_URL); @@ -1479,6 +1535,16 @@ class AdminControllerCore extends Controller protected function addToolBarModulesListButton() { + + if (!$this->isFresh(Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 86400)) + file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, Tools::addonsRequest('native')); + + $country_module_list_xml = simplexml_load_file(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST); + $country_module_list = array(); + foreach ($country_module_list_xml->module as $k => $m) + $country_module_list[] = (string)$m->name; + $this->tab_modules_list['slider_list'] = array_intersect($this->tab_modules_list['slider_list'], $country_module_list); + if (is_array($this->tab_modules_list['slider_list']) && count($this->tab_modules_list['slider_list'])) $this->toolbar_btn['modules-list'] = array( 'href' => '#', @@ -1514,7 +1580,6 @@ class AdminControllerCore extends Controller public function renderModulesList() { - if ($this->getModulesList($this->filter_modules_list)) { $helper = new Helper(); @@ -1679,6 +1744,7 @@ class AdminControllerCore extends Controller $helper->row_hover = $this->row_hover; $helper->position_identifier = $this->position_identifier; $helper->controller_name = $this->controller_name; + $helper->list_id = isset($this->list_id) ? $this->list_id : $this->table; // For each action, try to add the corresponding skip elements list $helper->list_skip_actions = $this->list_skip_actions; @@ -1760,7 +1826,11 @@ class AdminControllerCore extends Controller $this->context->employee->logout(); if ($this->controller_name != 'AdminLogin' && (!isset($this->context->employee) || !$this->context->employee->isLoggedBack())) - Tools::redirectAdmin($this->context->link->getAdminLink('AdminLogin').(!isset($_GET['logout']) ? '&redirect='.$this->controller_name : '')); + { + if (isset($this->context->employee)) + $this->context->employee->logout(); + Tools::redirectAdmin($this->context->link->getAdminLink('AdminLogin').((!isset($_GET['logout']) && $this->controller_name != 'AdminNotFound') ? '&redirect='.$this->controller_name : '')); + } // Set current index $current_index = 'index.php'.(($controller = Tools::getValue('controller')) ? '?controller='.$controller : ''); @@ -1873,11 +1943,14 @@ class AdminControllerCore extends Controller */ public function initProcess() { + if (!isset($this->list_id)) + $this->list_id = $this->table; + // Manage list filtering - if (Tools::isSubmit('submitFilter'.$this->table) - || $this->context->cookie->{'submitFilter'.$this->table} !== false - || Tools::getValue($this->table.'Orderby') - || Tools::getValue($this->table.'Orderway')) + if (Tools::isSubmit('submitFilter'.$this->list_id) + || $this->context->cookie->{'submitFilter'.$this->list_id} !== false + || Tools::getValue($this->list_id.'Orderby') + || Tools::getValue($this->list_id.'Orderway')) $this->filter = true; $this->id_object = (int)Tools::getValue($this->identifier); @@ -1979,7 +2052,7 @@ class AdminControllerCore extends Controller $this->action = 'export'; } /* Cancel all filters for this tab */ - elseif (isset($_POST['submitReset'.$this->table])) + elseif (isset($_POST['submitReset'.$this->list_id])) $this->action = 'reset_filters'; /* Submit options list */ elseif (Tools::getValue('submitOptions'.$this->table) || Tools::getValue('submitOptions')) @@ -2033,14 +2106,17 @@ class AdminControllerCore extends Controller */ public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) { + if (!isset($this->list_id)) + $this->list_id = $this->table; + /* Manage default params values */ $use_limit = true; if ($limit === false) $use_limit = false; elseif (empty($limit)) { - if (isset($this->context->cookie->{$this->table.'_pagination'}) && $this->context->cookie->{$this->table.'_pagination'}) - $limit = $this->context->cookie->{$this->table.'_pagination'}; + if (isset($this->context->cookie->{$this->list_id.'_pagination'}) && $this->context->cookie->{$this->list_id.'_pagination'}) + $limit = $this->context->cookie->{$this->list_id.'_pagination'}; else $limit = $this->_pagination[1]; } @@ -2050,8 +2126,8 @@ class AdminControllerCore extends Controller $prefix = str_replace(array('admin', 'controller'), '', Tools::strtolower(get_class($this))); if (empty($order_by)) { - if ($this->context->cookie->{$prefix.$this->table.'Orderby'}) - $order_by = $this->context->cookie->{$prefix.$this->table.'Orderby'}; + if ($this->context->cookie->{$prefix.$this->list_id.'Orderby'}) + $order_by = $this->context->cookie->{$prefix.$this->list_id.'Orderby'}; elseif ($this->_orderBy) $order_by = $this->_orderBy; else @@ -2060,16 +2136,16 @@ class AdminControllerCore extends Controller if (empty($order_way)) { - if ($this->context->cookie->{$prefix.$this->table.'Orderway'}) - $order_way = $this->context->cookie->{$prefix.$this->table.'Orderway'}; + if ($this->context->cookie->{$prefix.$this->list_id.'Orderway'}) + $order_way = $this->context->cookie->{$prefix.$this->list_id.'Orderway'}; elseif ($this->_orderWay) $order_way = $this->_orderWay; else $order_way = $this->_defaultOrderWay; } - $limit = (int)Tools::getValue('pagination', $limit); - $this->context->cookie->{$this->table.'_pagination'} = $limit; + $limit = (int)Tools::getValue($this->list_id.'_pagination', $limit); + $this->context->cookie->{$this->list_id.'_pagination'} = $limit; /* Check params validity */ if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way) @@ -2081,12 +2157,12 @@ class AdminControllerCore extends Controller $order_by = $this->fields_list[$order_by]['filter_key']; /* Determine offset from current page */ - if ((isset($_POST['submitFilter'.$this->table]) || - isset($_POST['submitFilter'.$this->table.'_x']) || - isset($_POST['submitFilter'.$this->table.'_y'])) && - !empty($_POST['submitFilter'.$this->table]) && - is_numeric($_POST['submitFilter'.$this->table])) - $start = ((int)$_POST['submitFilter'.$this->table] - 1) * $limit; + if ((isset($_POST['submitFilter'.$this->list_id]) || + isset($_POST['submitFilter'.$this->list_id.'_x']) || + isset($_POST['submitFilter'.$this->list_id.'_y'])) && + !empty($_POST['submitFilter'.$this->list_id]) && + is_numeric($_POST['submitFilter'.$this->list_id])) + $start = ((int)$_POST['submitFilter'.$this->list_id] - 1) * $limit; /* Cache */ $this->_lang = (int)$id_lang; @@ -2182,9 +2258,9 @@ class AdminControllerCore extends Controller } else $this->_listsql .= ($this->lang ? 'b.*,' : '').' a.*'; - + $this->_listsql .= ' - '.(isset($this->_select) ? ', '.$this->_select : '').$select_shop.' + '.(isset($this->_select) ? ', '.rtrim($this->_select, ', ') : '').$select_shop.' FROM `'._DB_PREFIX_.$sql_table.'` a '.$lang_join.' '.(isset($this->_join) ? $this->_join.' ' : '').' @@ -2197,6 +2273,7 @@ class AdminControllerCore extends Controller ($this->_tmpTableFilter ? ') tmpTable WHERE 1'.$this->_tmpTableFilter : ''). (($use_limit === true) ? ' LIMIT '.(int)$start.','.(int)$limit : ''); + $this->_listTotal = 0; if (!($this->_list = Db::getInstance()->executeS($this->_listsql))) $this->_list_error = Db::getInstance()->getMsgError(); else @@ -2213,7 +2290,7 @@ class AdminControllerCore extends Controller $all_modules = Module::getModulesOnDisk(true); $this->modules_list = array(); - foreach($all_modules as $module) + foreach ($all_modules as $module) { $perm = true; if ($module->id) @@ -2229,9 +2306,11 @@ class AdminControllerCore extends Controller if (in_array($module->name, $filter_modules_list) && $perm) { $this->fillModuleData($module, 'select'); - $this->modules_list[] = $module; + $this->modules_list[array_search($module->name, $filter_modules_list)] = $module; } } + ksort($this->modules_list); + if (count($this->modules_list)) return true; @@ -2357,7 +2436,7 @@ class AdminControllerCore extends Controller foreach ($rules['required'] as $field) if (($value = Tools::getValue($field)) == false && (string)$value != '0') if (!Tools::getValue($this->identifier) || ($field != 'passwd' && $field != 'no-picture')) - $this->errors[] = sprintf( + $this->errors[$field] = sprintf( Tools::displayError('The %s field is required.'), call_user_func(array($class_name, 'displayFieldName'), $field, $class_name) ); @@ -2366,7 +2445,7 @@ class AdminControllerCore extends Controller if (isset($rules['requiredLang']) && is_array($rules['requiredLang'])) foreach ($rules['requiredLang'] as $field_lang) if (($empty = Tools::getValue($field_lang.'_'.$default_language->id)) === false || $empty !== '0' && empty($empty)) - $this->errors[] = sprintf( + $this->errors[$field_lang.'_'.$default_language->id] = sprintf( Tools::displayError('The field %1$s is required at least in %2$s.'), call_user_func(array($class_name, 'displayFieldName'), $field_lang, $class_name), $default_language->name @@ -2376,7 +2455,7 @@ class AdminControllerCore extends Controller if (isset($rules['size']) && is_array($rules['size'])) foreach ($rules['size'] as $field => $max_length) if (Tools::getValue($field) !== false && Tools::strlen(Tools::getValue($field)) > $max_length) - $this->errors[] = sprintf( + $this->errors[$field] = sprintf( Tools::displayError('The %1$s field is too long (%2$d chars max).'), call_user_func(array($class_name, 'displayFieldName'), $field, $class_name), $max_length @@ -2389,7 +2468,7 @@ class AdminControllerCore extends Controller { $field_lang_value = Tools::getValue($field_lang.'_'.$language['id_lang']); if ($field_lang_value !== false && Tools::strlen($field_lang_value) > $max_length) - $this->errors[] = sprintf( + $this->errors[$field_lang.'_'.$language['id_lang']] = sprintf( Tools::displayError('The field %1$s (%2$s) is too long (%3$d chars max, html chars including).'), call_user_func(array($class_name, 'displayFieldName'), $field_lang, $class_name), $language['name'], @@ -2404,7 +2483,7 @@ class AdminControllerCore extends Controller foreach ($rules['validate'] as $field => $function) if (($value = Tools::getValue($field)) !== false && ($field != 'passwd')) if (!Validate::$function($value) && !empty($value)) - $this->errors[] = sprintf( + $this->errors[$field] = sprintf( Tools::displayError('The %s field is invalid.'), call_user_func(array($class_name, 'displayFieldName'), $field, $class_name) ); @@ -2413,12 +2492,12 @@ class AdminControllerCore extends Controller if (($value = Tools::getValue('passwd')) != false) { if ($class_name == 'Employee' && !Validate::isPasswdAdmin($value)) - $this->errors[] = sprintf( + $this->errors['passwd'] = sprintf( Tools::displayError('The %s field is invalid.'), call_user_func(array($class_name, 'displayFieldName'), 'passwd', $class_name) ); elseif ($class_name == 'Customer' && !Validate::isPasswd($value)) - $this->errors[] = sprintf( + $this->errors['passwd'] = sprintf( Tools::displayError('The %s field is invalid.'), call_user_func(array($class_name, 'displayFieldName'), 'passwd', $class_name) ); @@ -2430,7 +2509,7 @@ class AdminControllerCore extends Controller foreach ($languages as $language) if (($value = Tools::getValue($field_lang.'_'.$language['id_lang'])) !== false && !empty($value)) if (!Validate::$function($value)) - $this->errors[] = sprintf( + $this->errors[$field_lang.'_'.$language['id_lang']] = sprintf( Tools::displayError('The %1$s field (%2$s) is invalid.'), call_user_func(array($class_name, 'displayFieldName'), $field_lang, $class_name), $language['name'] @@ -2690,18 +2769,31 @@ class AdminControllerCore extends Controller else { $result = true; - if ($this->deleted) + foreach ($this->boxes as $id) { - foreach ($this->boxes as $id) + $to_delete = new $this->className($id); + $delete_ok = true; + if ($this->deleted) { - $to_delete = new $this->className($id); $to_delete->deleted = 1; - $result = $result && $to_delete->update(); + if (!$to_delete->update()) + { + $result = false; + $delete_ok = false; + } } + else + if (!$to_delete->delete()) + { + $result = false; + $delete_ok = false; + } + + if ($delete_ok) + Logger::addLog(sprintf($this->l('%s deletion'), $this->className), 1, null, $this->className, (int)$to_delete->id, true, (int)$this->context->employee->id); + else + $this->errors[] = sprintf(Tools::displayError('Can\'t delete #%d'), $id); } - else - $result = $object->deleteSelection(Tools::getValue($this->table.'Box')); - if ($result) $this->redirect_after = self::$currentIndex.'&conf=2&token='.$this->token; $this->errors[] = Tools::displayError('An error occurred while deleting this selection.'); diff --git a/classes/controller/FrontController.php b/classes/controller/FrontController.php index 14dc91682..4d34edf32 100755 --- a/classes/controller/FrontController.php +++ b/classes/controller/FrontController.php @@ -108,27 +108,24 @@ class FrontControllerCore extends Controller // If current URL use SSL, set it true (used a lot for module redirect) if (Tools::usingSecureMode()) - $useSSL = $this->ssl = true; + $useSSL = true; // For compatibility with globals, DEPRECATED as of version 1.5 $css_files = $this->css_files; $js_files = $this->js_files; - if ($this->ssl && !Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) - { + // If we call a SSL controller without SSL or a non SSL controller with SSL, we redirect with the right protocol + if (Configuration::get('PS_SSL_ENABLED') && ($_SERVER['REQUEST_METHOD'] != 'POST') && $this->ssl != Tools::usingSecureMode()) + { header('HTTP/1.1 301 Moved Permanently'); header('Cache-Control: no-cache'); - header('Location: '.Tools::getShopDomainSsl(true).$_SERVER['REQUEST_URI']); + if ($this->ssl) + header('Location: '.Tools::getShopDomainSsl(true).$_SERVER['REQUEST_URI']); + else + header('Location: '.Tools::getShopDomain(true).$_SERVER['REQUEST_URI']); exit(); } - elseif (Configuration::get('PS_SSL_ENABLED') && Tools::usingSecureMode() && !($this->ssl)) - { - header('HTTP/1.1 301 Moved Permanently'); - header('Cache-Control: no-cache'); - header('Location: '.Tools::getShopDomain(true).$_SERVER['REQUEST_URI']); - exit(); - } - + if ($this->ajax) { $this->display_header = false; @@ -336,7 +333,8 @@ class FrontControllerCore extends Controller 'opc' => (bool)Configuration::get('PS_ORDER_PROCESS_TYPE'), 'PS_CATALOG_MODE' => (bool)Configuration::get('PS_CATALOG_MODE') || !(bool)Group::getCurrent()->show_prices, 'b2b_enable' => (bool)Configuration::get('PS_B2B_ENABLE'), - 'request' => $link->getPaginationLink(false, false, false, true) + 'request' => $link->getPaginationLink(false, false, false, true), + 'PS_STOCK_MANAGEMENT' => Configuration::get('PS_STOCK_MANAGEMENT') )); // Add the tpl files directory for mobile @@ -596,7 +594,7 @@ class FrontControllerCore extends Controller protected function canonicalRedirection($canonical_url = '') { - if (!$canonical_url || !Configuration::get('PS_CANONICAL_REDIRECT') || strtoupper($_SERVER['REQUEST_METHOD']) != 'GET') + if (!$canonical_url || !Configuration::get('PS_CANONICAL_REDIRECT') || strtoupper($_SERVER['REQUEST_METHOD']) != 'GET' || Tools::getValue('live_edit')) return; $match_url = (($this->ssl && Configuration::get('PS_SSL_ENABLED')) ? 'https://' : 'http://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; @@ -775,9 +773,11 @@ class FrontControllerCore extends Controller public function checkLiveEditAccess() { - $live_token = Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee')); - $ad = Tools::getValue('ad'); - return Tools::isSubmit('live_edit') && $ad && Tools::getValue('liveToken') == $live_token && is_dir(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$ad); + if (!Tools::isSubmit('live_edit') || !Tools::getValue('ad') || !Tools::getValue('liveToken')) + return false; + if (Tools::getValue('liveToken') != Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee'))) + return false; + return is_dir(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.Tools::getValue('ad')); } public function getLiveEditFooter() @@ -806,7 +806,7 @@ class FrontControllerCore extends Controller // 'orderwaydefault' => Tools::getProductsOrder('way'), $stock_management = Configuration::get('PS_STOCK_MANAGEMENT') ? true : false; // no display quantity order if stock management disabled - $order_by_values = array(0 => 'name', 1 => 'price', 2 => 'date_add', 3 => 'date_upd', 4 => 'position', 5 => 'manufacturer_name', 6 => 'quantity'); + $order_by_values = array(0 => 'name', 1 => 'price', 2 => 'date_add', 3 => 'date_upd', 4 => 'position', 5 => 'manufacturer_name', 6 => 'quantity', 7 => 'reference'); $order_way_values = array(0 => 'asc', 1 => 'desc'); $this->orderBy = Tools::strtolower(Tools::getValue('orderby', $order_by_values[(int)Configuration::get('PS_PRODUCTS_ORDER_BY')])); $this->orderWay = Tools::strtolower(Tools::getValue('orderway', $order_way_values[(int)Configuration::get('PS_PRODUCTS_ORDER_WAY')])); @@ -847,8 +847,8 @@ class FrontControllerCore extends Controller $range = 2; /* how many pages around page selected */ - if ($this->p < 0) - $this->p = 0; + if ($this->p < 1) + $this->p = 1; if (isset($this->context->cookie->nb_item_per_page) && $this->n != $this->context->cookie->nb_item_per_page && in_array($this->n, $nArray)) $this->context->cookie->nb_item_per_page = $this->n; diff --git a/classes/controller/ModuleAdminController.php b/classes/controller/ModuleAdminController.php index ba0ac7c11..45375251b 100644 --- a/classes/controller/ModuleAdminController.php +++ b/classes/controller/ModuleAdminController.php @@ -51,9 +51,10 @@ abstract class ModuleAdminControllerCore extends AdminController public function createTemplate($tpl_name) { - if (file_exists($this->getTemplatePath().$this->override_folder.$tpl_name) && $this->viewAccess()) + if (file_exists(_PS_THEME_DIR_.'modules/'.$this->module->name.'/views/templates/admin/'.$tpl_name) && $this->viewAccess()) + return $this->context->smarty->createTemplate(_PS_THEME_DIR_.'modules/'.$this->module->name.'/views/templates/admin/'.$tpl_name, $this->context->smarty); + elseif (file_exists($this->getTemplatePath().$this->override_folder.$tpl_name) && $this->viewAccess()) return $this->context->smarty->createTemplate($this->getTemplatePath().$this->override_folder.$tpl_name, $this->context->smarty); - return parent::createTemplate($tpl_name); } diff --git a/classes/controller/ModuleFrontController.php b/classes/controller/ModuleFrontController.php index 0ab4932a5..f2db4a085 100644 --- a/classes/controller/ModuleFrontController.php +++ b/classes/controller/ModuleFrontController.php @@ -55,6 +55,8 @@ class ModuleFrontControllerCore extends FrontController { if (Tools::file_exists_cache(_PS_THEME_DIR_.'modules/'.$this->module->name.'/'.$template)) $this->template = _PS_THEME_DIR_.'modules/'.$this->module->name.'/'.$template; + elseif (Tools::file_exists_cache(_PS_THEME_DIR_.'modules/'.$this->module->name.'/views/templates/front/'.$template)) + $this->template = _PS_THEME_DIR_.'modules/'.$this->module->name.'/views/templates/front/'.$template; elseif (Tools::file_exists_cache($this->getTemplatePath().$template)) $this->template = $this->getTemplatePath().$template; else diff --git a/classes/db/Db.php b/classes/db/Db.php old mode 100644 new mode 100755 index e543f35ce..be9f1530a --- a/classes/db/Db.php +++ b/classes/db/Db.php @@ -79,12 +79,7 @@ abstract class DbCore /** * @var array Object instance for singleton */ - protected static $_servers = array( - array('server' => _DB_SERVER_, 'user' => _DB_USER_, 'password' => _DB_PASSWD_, 'database' => _DB_NAME_), /* MySQL Master server */ - // Add here your slave(s) server(s) - // array('server' => '192.168.0.15', 'user' => 'rep', 'password' => '123456', 'database' => 'rep'), - // array('server' => '192.168.0.3', 'user' => 'myuser', 'password' => 'mypassword', 'database' => 'mydatabase'), - ); + protected static $_servers = array(); /** * Store last executed query @@ -169,6 +164,8 @@ abstract class DbCore /* do not remove, useful for some modules */ abstract public function set_db($db_name); + + abstract public function getBestEngine(); /** * Get Db object instance @@ -180,6 +177,15 @@ abstract class DbCore { static $id = 0; + // This MUST not be declared with the class members because some defines (like _DB_SERVER_) may not exist yet (the constructor can be called directly with params) + if (!self::$_servers) + self::$_servers = array( + array('server' => _DB_SERVER_, 'user' => _DB_USER_, 'password' => _DB_PASSWD_, 'database' => _DB_NAME_), /* MySQL Master server */ + // Add here your slave(s) server(s) + // array('server' => '192.168.0.15', 'user' => 'rep', 'password' => '123456', 'database' => 'rep'), + // array('server' => '192.168.0.3', 'user' => 'myuser', 'password' => 'mypassword', 'database' => 'mydatabase'), + ); + $total_servers = count(self::$_servers); if ($master || $total_servers == 1) $id_server = 0; @@ -674,7 +680,7 @@ abstract class DbCore return call_user_func_array(array(Db::getClass(), 'hasTableWithSamePrefix'), array($server, $user, $pwd, $db, $prefix)); } - public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine) + public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine = null) { return call_user_func_array(array(Db::getClass(), 'checkCreatePrivilege'), array($server, $user, $pwd, $db, $prefix, $engine)); } diff --git a/classes/db/DbMySQLi.php b/classes/db/DbMySQLi.php index 3d5556908..41d1d5a35 100644 --- a/classes/db/DbMySQLi.php +++ b/classes/db/DbMySQLi.php @@ -52,6 +52,21 @@ class DbMySQLiCore extends Db return $this->link; } + + public static function createDatabase($host, $user, $password, $dbname, $dropit = false) + { + if (strpos($host, ':') !== false) + { + list($host, $port) = explode(':', $host); + $link = @new mysqli($host, $this->user, $this->password, null, $port); + } + else + $link = @new mysqli($host, $user, $password); + $success = $link->query('CREATE DATABASE `'.str_replace('`', '\\`', $dbname).'`'); + if ($dropit && ($link->query('DROP DATABASE `'.str_replace('`', '\\`', $dbname).'`') !== false)) + return true; + return $success; + } /** * @see DbCore::disconnect() @@ -169,24 +184,40 @@ class DbMySQLiCore extends Db if (!$link->options(MYSQLI_OPT_CONNECT_TIMEOUT, $timeout)) return 1; - if (!$link->real_connect($server, $user, $pwd, $db)) + // There is an @ because mysqli throw a warning when the database does not exists + if (!@$link->real_connect($server, $user, $pwd, $db)) return (mysqli_connect_errno() == 1049) ? 2 : 1; - if (strtolower($engine) == 'innodb') - { - $sql = 'SHOW VARIABLES WHERE Variable_name = \'have_innodb\''; - $result = $link->query($sql); - if (!$result) - return 4; - $row = $result->fetch_assoc(); - if (!$row || strtolower($row['Value']) != 'yes') - return 4; - } $link->close(); return 0; } - public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine) + public function getBestEngine() + { + $value = 'InnoDB'; + + $sql = 'SHOW VARIABLES WHERE Variable_name = \'have_innodb\''; + $result = $this->link->query($sql); + if (!$result) + $value = 'MyISAM'; + $row = $result->fetch_assoc(); + if (!$row || strtolower($row['Value']) != 'yes') + $value = 'MyISAM'; + + /* MySQL >= 5.6 */ + $sql = 'SHOW ENGINES'; + $result = $this->link->query($sql); + while ($row = $result->fetch_assoc()) + if ($row['Engine'] == 'InnoDB') + { + if (in_array($row['Support'], array('DEFAULT', 'YES'))) + $value = 'InnoDB'; + break; + } + return $value; + } + + public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine = null) { $link = @new mysqli($server, $user, $pwd, $db); if (mysqli_connect_error()) diff --git a/classes/db/DbPDO.php b/classes/db/DbPDO.php index cc1709801..ab5d1ede8 100644 --- a/classes/db/DbPDO.php +++ b/classes/db/DbPDO.php @@ -1,239 +1,264 @@ - -* @copyright 2007-2013 PrestaShop SA -* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) -* International Registered Trademark & Property of PrestaShop SA -*/ - -/** - * This class is currently only here for tests - * - * @since 1.5.0 - */ -class DbPDOCore extends Db -{ - protected static function _getPDO($host, $user, $password, $dbname, $timeout = 5) - { - $dsn = 'mysql:'; - if ($dbname) - $dsn .= 'dbname='.$dbname.';'; - if (preg_match('/^(.*):([0-9]+)$/', $host, $matches)) - $dsn .= 'host='.$matches[1].';port='.$matches[2]; - elseif (preg_match('#^.*:(/.*)$#', $host, $matches)) - $dsn .= 'unix_socket='.$matches[1]; - else - $dsn .= 'host='.$host; - - return new PDO($dsn, $user, $password, array(PDO::ATTR_TIMEOUT => $timeout, PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true)); - } - - /** - * @see DbCore::connect() - */ - public function connect() - { - try { - $this->link = $this->_getPDO($this->server, $this->user, $this->password, $this->database, 5); - } catch (PDOException $e) { - die(sprintf(Tools::displayError('Link to database cannot be established: %s'), utf8_encode($e->getMessage()))); - } - - // UTF-8 support - if ($this->link->exec('SET NAMES \'utf8\'') === false) - die(Tools::displayError('PrestaShop Fatal error: no utf-8 support. Please check your server configuration.')); - - return $this->link; - } - - /** - * @see DbCore::disconnect() - */ - public function disconnect() - { - unset($this->link); - } - - /** - * @see DbCore::_query() - */ - protected function _query($sql) - { - return $this->link->query($sql); - } - - /** - * @see DbCore::nextRow() - */ - public function nextRow($result = false) - { - if (!$result) - $result = $this->result; - return $result->fetch(PDO::FETCH_ASSOC); - } - - /** - * @see DbCore::_numRows() - */ - protected function _numRows($result) - { - return $result->rowCount(); - } - - /** - * @see DbCore::Insert_ID() - */ - public function Insert_ID() - { - return $this->link->lastInsertId(); - } - - /** - * @see DbCore::Affected_Rows() - */ - public function Affected_Rows() - { - return $this->result->rowCount(); - } - - /** - * @see DbCore::getMsgError() - */ - public function getMsgError($query = false) - { - $error = $this->link->errorInfo(); - return ($error[0] == '00000') ? '' : $error[2]; - } - - /** - * @see DbCore::getNumberError() - */ - public function getNumberError() - { - $error = $this->link->errorInfo(); - return isset($error[1]) ? $error[1] : 0; - } - - /** - * @see DbCore::getVersion() - */ - public function getVersion() - { - return $this->getValue('SELECT VERSION()'); - } - - /** - * @see DbCore::_escape() - */ - public function _escape($str) - { - $search = array("\\", "\0", "\n", "\r", "\x1a", "'", '"'); - $replace = array("\\\\", "\\0", "\\n", "\\r", "\Z", "\'", '\"'); - return str_replace($search, $replace, $str); - } - - /** - * @see DbCore::set_db() - */ - public function set_db($db_name) - { - return $this->link->exec('USE '.pSQL($db_name)); - } - - /** - * @see Db::hasTableWithSamePrefix() - */ - public static function hasTableWithSamePrefix($server, $user, $pwd, $db, $prefix) - { - try { - $link = DbPDO::_getPDO($server, $user, $pwd, $db, 5); - } catch (PDOException $e) { - return false; - } - - $sql = 'SHOW TABLES LIKE \''.$prefix.'%\''; - $result = $link->query($sql); - return (bool)$result->fetch(); - } - - public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine) - { - try { - $link = DbPDO::_getPDO($server, $user, $pwd, $db, 5); - } catch (PDOException $e) { - return false; - } - - $sql = ' - CREATE TABLE `'.$prefix.'test` ( - `test` tinyint(1) unsigned NOT NULL - ) ENGINE=MyISAM'; - $result = $link->query($sql); - if (!$result) - { - $error = $link->errorInfo(); - return $error[2]; - } - $link->query('DROP TABLE `'.$prefix.'test`'); - return true; - } - - /** - * @see Db::checkConnection() - */ - public static function tryToConnect($server, $user, $pwd, $db, $newDbLink = true, $engine = null, $timeout = 5) - { - try { - $link = DbPDO::_getPDO($server, $user, $pwd, $db, $timeout); - } catch (PDOException $e) { - return ($e->getCode() == 1049) ? 2 : 1; - } - - if (strtolower($engine) == 'innodb') - { - $sql = 'SHOW VARIABLES WHERE Variable_name = \'have_innodb\''; - $result = $link->query($sql); - if (!$result) - return 4; - $row = $result->fetch(); - if (!$row || strtolower($row['Value']) != 'yes') - return 4; - } - unset($link); - return 0; - } - - /** - * @see Db::checkEncoding() - */ - public static function tryUTF8($server, $user, $pwd) - { - try { - $link = DbPDO::_getPDO($server, $user, $pwd, false, 5); - } catch (PDOException $e) { - return false; - } - $result = $link->exec('SET NAMES \'utf8\''); - unset($link); - - return ($result === false) ? false : true; - } -} + +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +/** + * @since 1.5.0 + */ +class DbPDOCore extends Db +{ + protected static function _getPDO($host, $user, $password, $dbname, $timeout = 5) + { + $dsn = 'mysql:'; + if ($dbname) + $dsn .= 'dbname='.$dbname.';'; + if (preg_match('/^(.*):([0-9]+)$/', $host, $matches)) + $dsn .= 'host='.$matches[1].';port='.$matches[2]; + elseif (preg_match('#^.*:(/.*)$#', $host, $matches)) + $dsn .= 'unix_socket='.$matches[1]; + else + $dsn .= 'host='.$host; + + return new PDO($dsn, $user, $password, array(PDO::ATTR_TIMEOUT => $timeout, PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true)); + } + + public static function createDatabase($host, $user, $password, $dbname, $dropit = false) + { + try { + $link = DbPDO::_getPDO($host, $user, $password, false); + $success = $link->exec('CREATE DATABASE `'.str_replace('`', '\\`', $dbname).'`'); + if ($dropit && ($link->exec('DROP DATABASE `'.str_replace('`', '\\`', $dbname).'`') !== false)) + return true; + } catch (PDOException $e) { + return false; + } + return $success; + } + + /** + * @see DbCore::connect() + */ + public function connect() + { + try { + $this->link = $this->_getPDO($this->server, $this->user, $this->password, $this->database, 5); + } catch (PDOException $e) { + die(sprintf(Tools::displayError('Link to database cannot be established: %s'), utf8_encode($e->getMessage()))); + } + + // UTF-8 support + if ($this->link->exec('SET NAMES \'utf8\'') === false) + die(Tools::displayError('PrestaShop Fatal error: no utf-8 support. Please check your server configuration.')); + + return $this->link; + } + + /** + * @see DbCore::disconnect() + */ + public function disconnect() + { + unset($this->link); + } + + /** + * @see DbCore::_query() + */ + protected function _query($sql) + { + return $this->link->query($sql); + } + + /** + * @see DbCore::nextRow() + */ + public function nextRow($result = false) + { + if (!$result) + $result = $this->result; + return $result->fetch(PDO::FETCH_ASSOC); + } + + /** + * @see DbCore::_numRows() + */ + protected function _numRows($result) + { + return $result->rowCount(); + } + + /** + * @see DbCore::Insert_ID() + */ + public function Insert_ID() + { + return $this->link->lastInsertId(); + } + + /** + * @see DbCore::Affected_Rows() + */ + public function Affected_Rows() + { + return $this->result->rowCount(); + } + + /** + * @see DbCore::getMsgError() + */ + public function getMsgError($query = false) + { + $error = $this->link->errorInfo(); + return ($error[0] == '00000') ? '' : $error[2]; + } + + /** + * @see DbCore::getNumberError() + */ + public function getNumberError() + { + $error = $this->link->errorInfo(); + return isset($error[1]) ? $error[1] : 0; + } + + /** + * @see DbCore::getVersion() + */ + public function getVersion() + { + return $this->getValue('SELECT VERSION()'); + } + + /** + * @see DbCore::_escape() + */ + public function _escape($str) + { + $search = array("\\", "\0", "\n", "\r", "\x1a", "'", '"'); + $replace = array("\\\\", "\\0", "\\n", "\\r", "\Z", "\'", '\"'); + return str_replace($search, $replace, $str); + } + + /** + * @see DbCore::set_db() + */ + public function set_db($db_name) + { + return $this->link->exec('USE '.pSQL($db_name)); + } + + /** + * @see Db::hasTableWithSamePrefix() + */ + public static function hasTableWithSamePrefix($server, $user, $pwd, $db, $prefix) + { + try { + $link = DbPDO::_getPDO($server, $user, $pwd, $db, 5); + } catch (PDOException $e) { + return false; + } + + $sql = 'SHOW TABLES LIKE \''.$prefix.'%\''; + $result = $link->query($sql); + return (bool)$result->fetch(); + } + + public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine = null) + { + try { + $link = DbPDO::_getPDO($server, $user, $pwd, $db, 5); + } catch (PDOException $e) { + return false; + } + + $sql = ' + CREATE TABLE `'.$prefix.'test` ( + `test` tinyint(1) unsigned NOT NULL + ) ENGINE=MyISAM'; + $result = $link->query($sql); + if (!$result) + { + $error = $link->errorInfo(); + return $error[2]; + } + $link->query('DROP TABLE `'.$prefix.'test`'); + return true; + } + + /** + * @see Db::checkConnection() + */ + public static function tryToConnect($server, $user, $pwd, $db, $newDbLink = true, $engine = null, $timeout = 5) + { + try { + $link = DbPDO::_getPDO($server, $user, $pwd, $db, $timeout); + } catch (PDOException $e) { + return ($e->getCode() == 1049) ? 2 : 1; + } + unset($link); + return 0; + } + + public function getBestEngine() + { + $value = 'InnoDB'; + + $sql = 'SHOW VARIABLES WHERE Variable_name = \'have_innodb\''; + $result = $this->link->query($sql); + if (!$result) + $value = 'MyISAM'; + $row = $result->fetch(); + if (!$row || strtolower($row['Value']) != 'yes') + $value = 'MyISAM'; + + /* MySQL >= 5.6 */ + $sql = 'SHOW ENGINES'; + $result = $this->link->query($sql); + while ($row = $result->fetch()) + if ($row['Engine'] == 'InnoDB') + { + if (in_array($row['Support'], array('DEFAULT', 'YES'))) + $value = 'InnoDB'; + break; + } + return $value; + } + + /** + * @see Db::checkEncoding() + */ + public static function tryUTF8($server, $user, $pwd) + { + try { + $link = DbPDO::_getPDO($server, $user, $pwd, false, 5); + } catch (PDOException $e) { + return false; + } + $result = $link->exec('SET NAMES \'utf8\''); + unset($link); + + return ($result === false) ? false : true; + } +} diff --git a/classes/db/MySQL.php b/classes/db/MySQL.php index b8db3dbd6..062f2608e 100644 --- a/classes/db/MySQL.php +++ b/classes/db/MySQL.php @@ -46,6 +46,15 @@ class MySQLCore extends Db return $this->link; } + + public static function createDatabase($host, $user, $password, $dbname, $dropit = false) + { + $link = mysql_connect($host, $user, $password); + $success = mysql_query('CREATE DATABASE `'.str_replace('`', '\\`', $dbname).'`', $link); + if ($dropit && (mysql_query('DROP DATABASE `'.str_replace('`', '\\`', $dbname).'`', $link) !== false)) + return true; + return $success; + } /** * @see DbCore::disconnect() @@ -165,22 +174,36 @@ class MySQLCore extends Db return 1; if (!@mysql_select_db($db, $link)) return 2; - - if (strtolower($engine) == 'innodb') - { - $sql = 'SHOW VARIABLES WHERE Variable_name = \'have_innodb\''; - $result = mysql_query($sql); - if (!$result) - return 4; - $row = mysql_fetch_assoc($result); - if (!$row || strtolower($row['Value']) != 'yes') - return 4; - } @mysql_close($link); return 0; } + + public function getBestEngine() + { + $value = 'InnoDB'; + + $sql = 'SHOW VARIABLES WHERE Variable_name = \'have_innodb\''; + $result = mysql_query($sql); + if (!$result) + $value = 'MyISAM'; + $row = mysql_fetch_assoc($result); + if (!$row || strtolower($row['Value']) != 'yes') + $value = 'MyISAM'; + + /* MySQL >= 5.6 */ + $sql = 'SHOW ENGINES'; + $result = mysql_query($sql); + while ($row = mysql_fetch_assoc($result)) + if ($row['Engine'] == 'InnoDB') + { + if (in_array($row['Support'], array('DEFAULT', 'YES'))) + $value = 'InnoDB'; + break; + } + return $value; + } - public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine) + public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine = null) { ini_set('mysql.connect_timeout', 5); if (!$link = @mysql_connect($server, $user, $pwd, true)) diff --git a/classes/exception/PrestaShopException.php b/classes/exception/PrestaShopException.php index 1476cd612..465bf0ddd 100644 --- a/classes/exception/PrestaShopException.php +++ b/classes/exception/PrestaShopException.php @@ -51,7 +51,7 @@ class PrestaShopExceptionCore extends Exception '; echo '
        '; echo '

        ['.get_class($this).']

        '; - echo $this->getExentedMessage(); + echo $this->getExtendedMessage(); $this->displayFileDebug($this->getFile(), $this->getLine()); @@ -145,14 +145,23 @@ class PrestaShopExceptionCore extends Exception { $logger = new FileLogger(); $logger->setFilename(_PS_ROOT_DIR_.'/log/'.date('Ymd').'_exception.log'); - $logger->logError($this->getExentedMessage(false)); + $logger->logError($this->getExtendedMessage(false)); + } + + /** + * @deprecated 1.5.5 + */ + protected function getExentedMessage($html = true) + { + Tools::displayAsDeprecated(); + return $this->getExtendedMessage($html); } /** * Return the content of the Exception * @return string content of the exception */ - protected function getExentedMessage($html = true) + protected function getExtendedMessage($html = true) { $format = '

        %s
        at line %d in file %s

        '; if (!$html) diff --git a/classes/helper/Helper.php b/classes/helper/Helper.php index d5516c3e6..826502bc0 100755 --- a/classes/helper/Helper.php +++ b/classes/helper/Helper.php @@ -351,7 +351,6 @@ class HelperCore public function renderModulesList($modules_list) { $this->tpl_vars = array('modules_list' => $modules_list); - $tpl = $this->createTemplate('helpers/modules_list/list.tpl'); $tpl->assign($this->tpl_vars); diff --git a/classes/helper/HelperList.php b/classes/helper/HelperList.php index 34db27bdf..69a6127c2 100644 --- a/classes/helper/HelperList.php +++ b/classes/helper/HelperList.php @@ -173,13 +173,13 @@ class HelperListCore extends Helper public function displayListContent() { - if ($this->position_identifier) - $id_category = (int)Tools::getValue('id_'.($this->is_cms ? 'cms_' : '').'category', ($this->is_cms ? '1' : Category::getRootCategory()->id )); - else - $id_category = Category::getRootCategory()->id; - if (isset($this->fields_list['position'])) { + if ($this->position_identifier) + $id_category = (int)Tools::getValue('id_'.($this->is_cms ? 'cms_' : '').'category', ($this->is_cms ? '1' : Category::getRootCategory()->id )); + else + $id_category = Category::getRootCategory()->id; + $positions = array_map(create_function('$elem', 'return (int)($elem[\'position\']);'), $this->_list); sort($positions); } @@ -259,7 +259,7 @@ class HelperListCore extends Helper $path_to_image = _PS_IMG_DIR_.$params['image'].'/'.$item_id.(isset($tr['id_image']) ? '-'.(int)$tr['id_image'] : '').'.'.$this->imageType; else $path_to_image = _PS_IMG_DIR_.$params['image'].'/'.Image::getImgFolderStatic($tr['id_image']).(int)$tr['id_image'].'.'.$this->imageType; - $this->_list[$index][$key] = ImageManager::thumbnail($path_to_image, $this->table.'_mini_'.$item_id.'.'.$this->imageType, 45, $this->imageType); + $this->_list[$index][$key] = ImageManager::thumbnail($path_to_image, $this->table.'_mini_'.$item_id.'_'.$this->context->shop->id.'.'.$this->imageType, 45, $this->imageType); } elseif (isset($params['icon']) && isset($tr[$key]) && (isset($params['icon'][$tr[$key]]) || isset($params['icon']['default']))) { @@ -282,9 +282,9 @@ class HelperListCore extends Helper $this->_list[$index][$key] = Tools::displayPrice($tr[$key], $currency, false); } elseif (isset($params['type']) && $params['type'] == 'date') - $this->_list[$index][$key] = Tools::displayDate($tr[$key], $this->context->language->id); + $this->_list[$index][$key] = Tools::displayDate($tr[$key]); elseif (isset($params['type']) && $params['type'] == 'datetime') - $this->_list[$index][$key] = Tools::displayDate($tr[$key], $this->context->language->id, true); + $this->_list[$index][$key] = Tools::displayDate($tr[$key],null , true); elseif (isset($tr[$key])) { $echo = $tr[$key]; @@ -307,7 +307,7 @@ class HelperListCore extends Helper 'table' => $this->table, 'token' => $this->token, 'color_on_bg' => $this->colorOnBackground, - 'id_category' => $id_category, + 'id_category' => isset($id_category) ? $id_category : false, 'bulk_actions' => $this->bulk_actions, 'positions' => isset($positions) ? $positions : null, 'order_by' => $this->orderBy, @@ -456,7 +456,7 @@ class HelperListCore extends Helper ); if ($this->specificConfirmDelete !== false) - $data['confirm'] = !is_null($this->specificConfirmDelete) ? '\r'.$this->specificConfirmDelete : self::$cache_lang['DeleteItem'].$name; + $data['confirm'] = !is_null($this->specificConfirmDelete) ? '\r'.$this->specificConfirmDelete : addcslashes(Tools::htmlentitiesDecodeUTF8(self::$cache_lang['DeleteItem'].$name), '\''); $tpl->assign(array_merge($this->tpl_delete_link_vars, $data)); @@ -486,18 +486,21 @@ class HelperListCore extends Helper */ public function displayListHeader() { + if (!isset($this->list_id)) + $this->list_id = $this->table; + $id_cat = (int)Tools::getValue('id_'.($this->is_cms ? 'cms_' : '').'category'); if (!isset($token) || empty($token)) $token = $this->token; /* Determine total page number */ - if (isset($this->context->cookie->{$this->table.'_pagination'}) && $this->context->cookie->{$this->table.'_pagination'}) - $default_pagination = $this->context->cookie->{$this->table.'_pagination'}; + if (isset($this->context->cookie->{$this->list_id.'_pagination'}) && $this->context->cookie->{$this->list_id.'_pagination'}) + $default_pagination = $this->context->cookie->{$this->list_id.'_pagination'}; else $default_pagination = $this->_pagination[0]; - $total_pages = ceil($this->listTotal / Tools::getValue('pagination', ($default_pagination))); + $total_pages = ceil($this->listTotal / Tools::getValue($this->list_id.'_pagination', ($default_pagination))); if (!$total_pages) $total_pages = 1; @@ -510,14 +513,13 @@ class HelperListCore extends Helper $action = $this->currentIndex.$identifier.'&token='.$token.$order.'#'.$this->table; /* Determine current page number */ - $page = (int)Tools::getValue('submitFilter'.$this->table); + $page = (int)Tools::getValue('submitFilter'.$this->list_id); if (!$page) $page = 1; /* Choose number of results per page */ - $selected_pagination = Tools::getValue( - 'pagination', - isset($this->context->cookie->{$this->table.'_pagination'}) ? $this->context->cookie->{$this->table.'_pagination'} : null + $selected_pagination = Tools::getValue($this->list_id.'_pagination', + isset($this->context->cookie->{$this->list_id.'_pagination'}) ? $this->context->cookie->{$this->list_id.'_pagination'} : null ); // Cleaning links @@ -535,7 +537,7 @@ class HelperListCore extends Helper { if (!isset($params['type'])) $params['type'] = 'text'; - $value = Context::getContext()->cookie->{$prefix.$this->table.'Filter_'.(array_key_exists('filter_key', $params) ? $params['filter_key'] : $key)}; + $value = Context::getContext()->cookie->{$prefix.$this->list_id.'Filter_'.(array_key_exists('filter_key', $params) && $key != 'active' ? $params['filter_key'] : $key)}; switch ($params['type']) { case 'bool': @@ -547,7 +549,7 @@ class HelperListCore extends Helper $value = Tools::unSerialize($value); if (!Validate::isCleanHtml($value[0]) || !Validate::isCleanHtml($value[1])) $value = ''; - $name = $this->table.'Filter_'.(isset($params['filter_key']) ? $params['filter_key'] : $key); + $name = $this->list_id.'Filter_'.(isset($params['filter_key']) ? $params['filter_key'] : $key); $name_id = str_replace('!', '__', $name); $params['id_date'] = $name_id; @@ -559,9 +561,9 @@ class HelperListCore extends Helper case 'select': foreach ($params['list'] as $option_value => $option_display) { - if (isset(Context::getContext()->cookie->{$prefix.$this->table.'Filter_'.$params['filter_key']}) - && Context::getContext()->cookie->{$prefix.$this->table.'Filter_'.$params['filter_key']} == $option_value - && Context::getContext()->cookie->{$prefix.$this->table.'Filter_'.$params['filter_key']} != '') + if (isset(Context::getContext()->cookie->{$prefix.$this->list_id.'Filter_'.$params['filter_key']}) + && Context::getContext()->cookie->{$prefix.$this->list_id.'Filter_'.$params['filter_key']} == $option_value + && Context::getContext()->cookie->{$prefix.$this->list_id.'Filter_'.$params['filter_key']} != '') $this->fields_list[$key]['select'][$option_value]['selected'] = 'selected'; } break; @@ -605,6 +607,7 @@ class HelperListCore extends Helper 'name' => isset($name) ? $name : null, 'name_id' => isset($name_id) ? $name_id : null, 'row_hover' => $this->row_hover, + 'list_id' => isset($this->list_id) ? $this->list_id : $this->table ))); return $this->header_tpl->fetch(); diff --git a/classes/module/Module.php b/classes/module/Module.php index 2877c1bad..8fcbddd8c 100644 --- a/classes/module/Module.php +++ b/classes/module/Module.php @@ -153,18 +153,22 @@ abstract class ModuleCore // If cache is not generated, we generate it if (self::$modules_cache == null && !is_array(self::$modules_cache)) { - // Join clause is done to check if the module is activated in current shop context - $sql_limit_shop = 'SELECT COUNT(*) FROM `'._DB_PREFIX_.'module_shop` ms WHERE m.`id_module` = ms.`id_module` AND ms.`id_shop` = '.((is_object(Context::getContext()->shop) && $id = (int)Context::getContext()->shop->id) ? $id : 1); - - $sql = 'SELECT m.`id_module`, m.`name`, ('.$sql_limit_shop.') as total FROM `'._DB_PREFIX_.'module` m'; - - // Result is cached + $id_shop = (Validate::isLoadedObject($this->context->shop) ? $this->context->shop->id : 1); self::$modules_cache = array(); - $result = Db::getInstance()->executeS($sql); + // Join clause is done to check if the module is activated in current shop context + $result = Db::getInstance()->executeS(' + SELECT m.`id_module`, m.`name`, ( + SELECT id_module + FROM `'._DB_PREFIX_.'module_shop` ms + WHERE m.`id_module` = ms.`id_module` + AND ms.`id_shop` = '.(int)$id_shop.' + LIMIT 1 + ) as mshop + FROM `'._DB_PREFIX_.'module` m'); foreach ($result as $row) { self::$modules_cache[$row['name']] = $row; - self::$modules_cache[$row['name']]['active'] = ($row['total'] > 0) ? 1 : 0; + self::$modules_cache[$row['name']]['active'] = ($row['mshop'] > 0) ? 1 : 0; } } @@ -215,7 +219,7 @@ abstract class ModuleCore } // Check if module is installed - $result = Db::getInstance()->getRow('SELECT `id_module` FROM `'._DB_PREFIX_.'module` WHERE `name` = \''.pSQL($this->name).'\''); + $result = Module::isInstalled($this->name); if ($result) { $this->_errors[] = $this->l('This module has already been installed.'); @@ -288,15 +292,17 @@ abstract class ModuleCore else { if (!$upgrade_detail['number_upgraded']) - $this->_errors[] = $this->l('None upgrades have been applied'); + $this->_errors[] = $this->l('No upgrade has been applied'); else { - $this->_errors[] = $this->l('Upgraded from: ').$upgrade_detail['upgraded_from'].$this->l(' to '). - $upgrade_detail['upgraded_to']; + $this->_errors[] = sprintf($this->l('Upgraded from: %S to %s'), $upgrade_detail['upgraded_from'], $upgrade_detail['upgraded_to']); $this->_errors[] = $upgrade_detail['number_upgrade_left'].' '.$this->l('upgrade left'); } - $this->_errors[] = $this->l('To prevent any problem, this module has been turned off'); + if ($upgrade_detail['duplicate']) + $this->_errors[] = sprintf(Tools::displayError('Module %s cannot be upgraded this time: please refresh this page to update it.'), $this->name); + else + $this->_errors[] = $this->l('To prevent any problem, this module has been turned off'); } } } @@ -311,6 +317,12 @@ abstract class ModuleCore */ public static function initUpgradeModule($module) { + if (((int)$module->installed == 1) & (empty($module->database_version) === true)) + { + Module::upgradeModuleVersion($module->name, $module->version); + $module->database_version = $module->version; + } + // Init cache upgrade details self::$modules_cache[$module->name]['upgrade'] = array( 'success' => false, // bool to know if upgrade succeed or not @@ -338,19 +350,21 @@ abstract class ModuleCore $upgrade = &self::$modules_cache[$this->name]['upgrade']; foreach ($upgrade['upgrade_file_left'] as $num => $file_detail) { - // Default variable required in the included upgrade file need to be set by default there: - // upgrade_version, success_upgrade - $upgrade_result = false; + if (function_exists($file_detail['upgrade_function'])) + { + $upgrade['success'] = false; + $upgrade['duplicate'] = true; + break; + } include($file_detail['file']); // Call the upgrade function if defined + $upgrade['success'] = false; if (function_exists($file_detail['upgrade_function'])) - $upgrade_result = $file_detail['upgrade_function']($this); - - $upgrade['success'] = $upgrade_result; + $upgrade['success'] = $file_detail['upgrade_function']($this); // Set detail when an upgrade succeed or failed - if ($upgrade_result) + if ($upgrade['success']) { $upgrade['number_upgraded'] += 1; $upgrade['upgraded_to'] = $file_detail['version']; @@ -368,6 +382,7 @@ abstract class ModuleCore } $upgrade['number_upgrade_left'] = count($upgrade['upgrade_file_left']); + // Update module version in DB with the last succeed upgrade if ($upgrade['upgraded_to']) Module::upgradeModuleVersion($this->name, $upgrade['upgraded_to']); @@ -386,9 +401,9 @@ abstract class ModuleCore public static function upgradeModuleVersion($name, $version) { return Db::getInstance()->execute(' - UPDATE `'._DB_PREFIX_.'module` m - SET m.version = \''.bqSQL($version).'\' - WHERE m.name = \''.bqSQL($name).'\''); + UPDATE `'._DB_PREFIX_.'module` m + SET m.version = \''.bqSQL($version).'\' + WHERE m.name = \''.bqSQL($name).'\''); } /** @@ -659,11 +674,14 @@ abstract class ModuleCore return false; // Retrocompatibility + $hook_name_bak = $hook_name; if ($alias = Hook::getRetroHookName($hook_name)) $hook_name = $alias; + Hook::exec('actionModuleRegisterHookBefore', array('object' => $this, 'hook_name' => $hook_name)); // Get hook id $id_hook = Hook::getIdByName($hook_name); + $live_edit = Hook::getLiveEditById((int)Hook::getIdByName($hook_name_bak)); // If hook does not exist, we create it if (!$id_hook) @@ -671,6 +689,7 @@ abstract class ModuleCore $new_hook = new Hook(); $new_hook->name = pSQL($hook_name); $new_hook->title = pSQL($hook_name); + $new_hook->live_edit = pSQL($live_edit); $new_hook->add(); $id_hook = $new_hook->id; if (!$id_hook) @@ -708,6 +727,7 @@ abstract class ModuleCore )); } + Hook::exec('actionModuleRegisterHookAfter', array('object' => $this, 'hook_name' => $hook_name)); return $return; } @@ -723,11 +743,16 @@ abstract class ModuleCore // Get hook id if a name is given as argument if (!is_numeric($hook_id)) { + $hook_name = (int)$hook_id; // Retrocompatibility $hook_id = Hook::getIdByName($hook_id); if (!$hook_id) return false; } + else + $hook_name = Hook::getNameById((int)$hook_id); + + Hook::exec('actionModuleUnRegisterHookBefore', array('object' => $this, 'hook_name' => $hook_name)); // Unregister module on hook by id $sql = 'DELETE FROM `'._DB_PREFIX_.'hook_module` @@ -738,6 +763,8 @@ abstract class ModuleCore // Clean modules position $this->cleanPositions($hook_id, $shop_list); + Hook::exec('actionModuleUnRegisterHookAfter', array('object' => $this, 'hook_name' => $hook_name)); + return $result; } @@ -1335,7 +1362,7 @@ abstract class ModuleCore elseif (isset($context->customer)) { $groups = $context->customer->getGroups(); - if (empty($groups)) + if (!count($groups)) $groups = array(Configuration::get('PS_UNIDENTIFIED_GROUP')); } @@ -1358,7 +1385,7 @@ abstract class ModuleCore '.(isset($billing) && $frontend ? 'AND mc.id_country = '.(int)$billing->id_country : '').' AND (SELECT COUNT(*) FROM '._DB_PREFIX_.'module_shop ms WHERE ms.id_module = m.id_module AND ms.id_shop IN('.implode(', ', $list).')) = '.count($list).' AND hm.id_shop IN('.implode(', ', $list).') - '.(count($groups) && $frontend ? 'AND (mg.`id_group` IN('.implode(', ', $groups).'))' : '').$paypal_condition.' + '.((count($groups) && $frontend) ? 'AND (mg.`id_group` IN ('.implode(', ', $groups).'))' : '').$paypal_condition.' GROUP BY hm.id_hook, hm.id_module ORDER BY hm.`position`, m.`name` DESC'); } @@ -1496,12 +1523,12 @@ abstract class ModuleCore * @param int $id_hook Hook ID * @return array Exceptions */ - protected static $exceptionsCache = null; - public function getExceptions($hookID, $dispatch = false) + public function getExceptions($id_hook, $dispatch = false) { - if (self::$exceptionsCache === null) + $cache_id = 'exceptionsCache'; + if (!Cache::isStored($cache_id)) { - self::$exceptionsCache = array(); + $exceptionsCache = array(); $sql = 'SELECT * FROM `'._DB_PREFIX_.'hook_module_exceptions` WHERE `id_shop` IN ('.implode(', ', Shop::getContextListShopID()).')'; $result = Db::getInstance()->executeS($sql); @@ -1510,40 +1537,41 @@ abstract class ModuleCore if (!$row['file_name']) continue; $key = $row['id_hook'].'-'.$row['id_module']; - if (!isset(self::$exceptionsCache[$key])) - self::$exceptionsCache[$key] = array(); - if (!isset(self::$exceptionsCache[$key][$row['id_shop']])) - self::$exceptionsCache[$key][$row['id_shop']] = array(); - self::$exceptionsCache[$key][$row['id_shop']][] = $row['file_name']; + if (!isset($exceptionsCache[$key])) + $exceptionsCache[$key] = array(); + if (!isset($exceptionsCache[$key][$row['id_shop']])) + $exceptionsCache[$key][$row['id_shop']] = array(); + $exceptionsCache[$key][$row['id_shop']][] = $row['file_name']; } + Cache::store($cache_id, $exceptionsCache); } + else + $exceptionsCache = Cache::retrieve($cache_id); - $key = $hookID.'-'.$this->id; - if (!$dispatch) + $key = $id_hook.'-'.$this->id; + $array_return = array(); + if ($dispatch) { - $files = array(); foreach (Shop::getContextListShopID() as $shop_id) - if (isset(self::$exceptionsCache[$key], self::$exceptionsCache[$key][$shop_id])) - foreach (self::$exceptionsCache[$key][$shop_id] as $file) - if (!in_array($file, $files)) - $files[] = $file; - return $files; + if (isset($exceptionsCache[$key], $exceptionsCache[$key][$shop_id])) + $array_return[$shop_id] = $exceptionsCache[$key][$shop_id]; } else { - $list = array(); foreach (Shop::getContextListShopID() as $shop_id) - if (isset(self::$exceptionsCache[$key], self::$exceptionsCache[$key][$shop_id])) - $list[$shop_id] = self::$exceptionsCache[$key][$shop_id]; - return $list; + if (isset($exceptionsCache[$key], $exceptionsCache[$key][$shop_id])) + foreach ($exceptionsCache[$key][$shop_id] as $file) + if (!in_array($file, $array_return)) + $array_return[] = $file; } + return $array_return; } public static function isInstalled($module_name) { if (!Cache::isStored('Module::isInstalled'.$module_name)) { - $id_module = Db::getInstance()->getValue('SELECT `id_module` FROM `'._DB_PREFIX_.'module` WHERE `name` = \''.pSQL($module_name).'\''); + $id_module = Module::getModuleIdByName($module_name); Cache::store('Module::isInstalled'.$module_name, (bool)$id_module); } return Cache::retrieve('Module::isInstalled'.$module_name); @@ -1554,7 +1582,7 @@ abstract class ModuleCore if (!Cache::isStored('Module::isEnabled'.$module_name)) { $active = false; - $id_module = Db::getInstance()->getValue('SELECT `id_module` FROM `'._DB_PREFIX_.'module` WHERE `name` = \''.pSQL($module_name).'\''); + $id_module = Module::getModuleIdByName($module_name); if (Db::getInstance()->getValue('SELECT `id_module` FROM `'._DB_PREFIX_.'module_shop` WHERE `id_module` = '.(int)$id_module.' AND `id_shop` = '.(int)Context::getContext()->shop->id)) $active = true; Cache::store('Module::isEnabled'.$module_name, (bool)$active); @@ -1580,7 +1608,11 @@ abstract class ModuleCore protected static function _isTemplateOverloadedStatic($module_name, $template) { if (Tools::file_exists_cache(_PS_THEME_DIR_.'modules/'.$module_name.'/'.$template)) - return true; + return _PS_THEME_DIR_.'modules/'.$module_name.'/'.$template; + elseif (Tools::file_exists_cache(_PS_THEME_DIR_.'modules/'.$module_name.'/views/templates/hook/'.$template)) + return _PS_THEME_DIR_.'modules/'.$module_name.'/views/templates/hook/'.$template; + elseif (Tools::file_exists_cache(_PS_THEME_DIR_.'modules/'.$module_name.'/views/templates/front/'.$template)) + return _PS_THEME_DIR_.'modules/'.$module_name.'/views/templates/front/'.$template; elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$module_name.'/views/templates/hook/'.$template)) return false; elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$module_name.'/'.$template)) @@ -1595,9 +1627,16 @@ abstract class ModuleCore protected function getCacheId($name = null) { - if ($name === null) - $name = $this->name; - return $name.'|'.(int)Tools::usingSecureMode().'|'.(int)$this->context->shop->id.'|'.(int)Group::getCurrent()->id.'|'.(int)$this->context->language->id; + $cache_array = array( + $name !== null ? $name : $this->name, + (int)Tools::usingSecureMode(), + (int)$this->context->shop->id, + (int)Group::getCurrent()->id, + (int)$this->context->language->id, + (int)$this->context->currency->id, + (int)$this->context->country->id + ); + return implode('|', $cache_array); } public function display($file, $template, $cacheId = null, $compileId = null) @@ -1641,8 +1680,9 @@ abstract class ModuleCore $overloaded = $this->_isTemplateOverloaded($template); if ($overloaded === null) return null; + if ($overloaded) - return _PS_THEME_DIR_.'modules/'.$this->name.'/'.$template; + return $overloaded; else if (file_exists(_PS_MODULE_DIR_.$this->name.'/views/templates/hook/'.$template)) return _PS_MODULE_DIR_.$this->name.'/views/templates/hook/'.$template; else diff --git a/classes/order/Order.php b/classes/order/Order.php index 4e17e68c4..a4d4db1b0 100644 --- a/classes/order/Order.php +++ b/classes/order/Order.php @@ -63,7 +63,7 @@ class OrderCore extends ObjectModel /** @var string Payment module */ public $module; - /** @var float Currency conversion rate */ + /** @var float Currency exchange rate */ public $conversion_rate; /** @var boolean Customer is ok for a recyclable package */ @@ -240,6 +240,8 @@ class OrderCore extends ObjectModel 'product_quantity' => array('required' => true), 'product_name' => array('setter' => false), 'product_price' => array('setter' => false), + 'unit_price_tax_incl' => array('setter' => false), + 'unit_price_tax_excl' => array('setter' => false), )), ), @@ -252,10 +254,12 @@ class OrderCore extends ObjectModel public function __construct($id = null, $id_lang = null) { parent::__construct($id, $id_lang); - if ($this->id_customer) + + $is_admin = (is_object(Context::getContext()->controller) && Context::getContext()->controller->controller_type == 'admin'); + if ($this->id_customer && !$is_admin) { $customer = new Customer((int)($this->id_customer)); - $this->_taxCalculationMethod = Group::getPriceDisplayMethod((int)($customer->id_default_group)); + $this->_taxCalculationMethod = Group::getPriceDisplayMethod((int)$customer->id_default_group); } else $this->_taxCalculationMethod = Group::getDefaultPriceDisplayMethod(); @@ -288,7 +292,7 @@ class OrderCore extends ObjectModel /* Does NOT delete a product but "cancel" it (which means return/refund/delete it depending of the case) */ public function deleteProduct($order, $orderDetail, $quantity) { - if (!(int)($this->getCurrentState())) + if (!(int)($this->getCurrentState()) || !validate::isLoadedObject($orderDetail)) return false; if ($this->hasBeenDelivered()) @@ -1144,13 +1148,14 @@ class OrderCore extends ObjectModel if ($use_existing_payment) { $id_order_payments = Db::getInstance()->executeS(' - SELECT op.id_order_payment + SELECT DISTINCT op.id_order_payment FROM `'._DB_PREFIX_.'order_payment` op INNER JOIN `'._DB_PREFIX_.'orders` o ON (o.reference = op.order_reference) LEFT JOIN `'._DB_PREFIX_.'order_invoice_payment` oip ON (oip.id_order_payment = op.id_order_payment) - WHERE oip.id_order_payment IS NULL AND o.id_order = '.(int)$order_invoice->id_order); - + WHERE (oip.id_order != '.(int)$order_invoice->id_order.' OR oip.id_order IS NULL) AND o.id_order = '.(int)$order_invoice->id_order); + if (count($id_order_payments)) + { foreach ($id_order_payments as $order_payment) Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'order_invoice_payment` @@ -1158,6 +1163,9 @@ class OrderCore extends ObjectModel `id_order_invoice` = '.(int)$order_invoice->id.', `id_order_payment` = '.(int)$order_payment['id_order_payment'].', `id_order` = '.(int)$order_invoice->id_order); + // Clear cache + Cache::clean('order_invoice_paid_*'); + } } // Update order cart rule @@ -1235,12 +1243,11 @@ class OrderCore extends ObjectModel public function getTotalWeight() { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' - SELECT SUM(product_weight * product_quantity) weight + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + SELECT SUM(product_weight * product_quantity) FROM '._DB_PREFIX_.'order_detail WHERE id_order = '.(int)($this->id)); - - return (float)($result['weight']); + return (float)($result); } /** @@ -1287,7 +1294,7 @@ class OrderCore extends ObjectModel public function getWsOrderRows() { - $query = 'SELECT id_order_detail as `id`, `product_id`, `product_price`, `id_order`, `product_attribute_id`, `product_quantity`, `product_name` + $query = 'SELECT id_order_detail as `id`, `product_id`, `product_price`, `id_order`, `product_attribute_id`, `product_quantity`, `product_name`, `unit_price_tax_incl`, `unit_price_tax_excl` FROM `'._DB_PREFIX_.'order_detail` WHERE id_order = '.(int)$this->id; $result = Db::getInstance()->executeS($query); @@ -1464,6 +1471,9 @@ class OrderCore extends ObjectModel $res = Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'order_invoice_payment` VALUES('.(int)$order_invoice->id.', '.(int)$order_payment->id.', '.(int)$this->id.')'); + + // Clear cache + Cache::clean('order_invoice_paid_*'); } return $res; @@ -1627,7 +1637,7 @@ class OrderCore extends ObjectModel return Db::getInstance()->getValue(' SELECT SUM(total_paid_tax_incl) FROM `'._DB_PREFIX_.'orders` - WHERE `reference` = '.(int)$this->reference.' + WHERE `reference` = \''.pSQL($this->reference).'\' AND `id_cart` = '.(int)$this->id_cart ); } @@ -1879,5 +1889,21 @@ class OrderCore extends ObjectModel $order = new Order($id_order); return $order->getUniqReference(); } + + /** + * Return a unique reference like : GWJTHMZUN#2 + * + * With multishipping, order reference are the same for all orders made with the same cart + * in this case this method suffix the order reference by a # and the order number + * + * @since 1.5.5.0 + */ + public function getIdOrderCarrier() + { + return (int)Db::getInstance()->getValue(' + SELECT `id_order_carrier` + FROM `'._DB_PREFIX_.'order_carrier` + WHERE `id_order` = '.(int)$this->id); + } } diff --git a/classes/order/OrderDetail.php b/classes/order/OrderDetail.php index a21486bd5..1136ebfdc 100644 --- a/classes/order/OrderDetail.php +++ b/classes/order/OrderDetail.php @@ -508,7 +508,7 @@ class OrderDetailCore extends ObjectModel $this->purchase_supplier_price = (float)$product['wholesale_price']; if ($product['id_supplier'] > 0) - $this->purchase_supplier_price = (float)ProductSupplier::getProductPrice((int)$product['id_supplier'], $product['id_product'], $product['id_product_attribute']); + $this->purchase_supplier_price = (float)ProductSupplier::getProductPrice((int)$product['id_supplier'], $product['id_product'], $product['id_product_attribute'], true); $this->setSpecificPrice($order, $product); diff --git a/classes/order/OrderHistory.php b/classes/order/OrderHistory.php index 3e2cb1574..9c0721baa 100644 --- a/classes/order/OrderHistory.php +++ b/classes/order/OrderHistory.php @@ -64,6 +64,9 @@ class OrderHistoryCore extends ObjectModel 'id_order_state' => array('required' => true, 'xlink_resource'=> 'order_states'), 'id_order' => array('xlink_resource' => 'orders'), ), + 'objectMethods' => array( + 'add' => 'addWs', + ), ); /** @@ -85,13 +88,15 @@ class OrderHistoryCore extends ObjectModel else return; + ShopUrl::cacheMainDomainForShop($order->id_shop); + $new_os = new OrderState((int)$new_order_state, $order->id_lang); $old_os = $order->getCurrentOrderState(); $is_validated = $this->isValidated(); // executes hook - if ($new_os->id == Configuration::get('PS_OS_PAYMENT')) + if (in_array($new_os->id, array(Configuration::get('PS_OS_PAYMENT'), Configuration::get('PS_OS_WS_PAYMENT')))) Hook::exec('actionPaymentConfirmation', array('id_order' => (int)$order->id)); // executes hook @@ -120,8 +125,8 @@ class OrderHistoryCore extends ObjectModel .'&id_order='.(int)$order->id .'&secure_key='.$order->secure_key; $assign[$key]['link'] = $dl_link; - if ($virtual_product['date_expiration'] != '0000-00-00 00:00:00') - $assign[$key]['deadline'] = Tools::displayDate($virtual_product['date_expiration '], $order->id_lang); + if (isset($virtual_product['download_deadline']) && $virtual_product['download_deadline'] != '0000-00-00 00:00:00') + $assign[$key]['deadline'] = Tools::displayDate($virtual_product['download_deadline']); if ($product_download->nb_downloadable != 0) $assign[$key]['downloadable'] = (int)$product_download->nb_downloadable; } @@ -140,7 +145,7 @@ class OrderHistoryCore extends ObjectModel $links .= ' '.Tools::htmlentitiesUTF8(sprintf(Tools::displayError('downloadable %d time(s)'), (int)$product['downloadable'])); $links .= ''; } - $links .= '
          '; + $links .= '
        '; $data = array( '{lastname}' => $customer->lastname, '{firstname}' => $customer->firstname, @@ -159,6 +164,9 @@ class OrderHistoryCore extends ObjectModel $manager = null; if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) $manager = StockManagerFactory::getManager(); + + $errorOrCanceledStatuses = array(Configuration::get('PS_OS_ERROR'), Configuration::get('PS_OS_CANCELED')); + // foreach products of the order if (Validate::isLoadedObject($old_os)) foreach ($order->getProductsDetail() as $product) @@ -169,7 +177,7 @@ class OrderHistoryCore extends ObjectModel ProductSale::addProductSale($product['product_id'], $product['product_quantity']); // @since 1.5.0 - Stock Management if (!Pack::isPack($product['product_id']) && - ($old_os->id == Configuration::get('PS_OS_ERROR') || $old_os->id == Configuration::get('PS_OS_CANCELED')) && + in_array($old_os->id, $errorOrCanceledStatuses) && !StockAvailable::dependsOnStock($product['id_product'], (int)$order->id_shop)) StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], -(int)$product['product_quantity'], $order->id_shop); } @@ -180,13 +188,14 @@ class OrderHistoryCore extends ObjectModel // @since 1.5.0 - Stock Management if (!Pack::isPack($product['product_id']) && - ($new_os->id == Configuration::get('PS_OS_ERROR') || $new_os->id == Configuration::get('PS_OS_CANCELED')) && + in_array($new_os->id, $errorOrCanceledStatuses) && !StockAvailable::dependsOnStock($product['id_product'])) StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], (int)$product['product_quantity'], $order->id_shop); } // if waiting for payment => payment error/canceled elseif (!$new_os->logable && !$old_os->logable && - ($new_os->id == Configuration::get('PS_OS_ERROR') || $new_os->id == Configuration::get('PS_OS_CANCELED')) && + in_array($new_os->id, $errorOrCanceledStatuses) && + !in_array($old_os->id, $errorOrCanceledStatuses) && !StockAvailable::dependsOnStock($product['id_product'])) StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], (int)$product['product_quantity'], $order->id_shop); // @since 1.5.0 : if the order is being shipped and this products uses the advanced stock management : @@ -326,6 +335,8 @@ class OrderHistoryCore extends ObjectModel 'newOrderStatus' => $new_os, 'id_order' => (int)$order->id, )); + + ShopUrl::resetMainDomainCache(); } /** @@ -368,7 +379,7 @@ class OrderHistoryCore extends ObjectModel return false; $result = Db::getInstance()->getRow(' - SELECT osl.`template`, c.`lastname`, c.`firstname`, osl.`name` AS osname, c.`email`, os.`module_name` + SELECT osl.`template`, c.`lastname`, c.`firstname`, osl.`name` AS osname, c.`email`, os.`module_name`, os.`id_order_state` FROM `'._DB_PREFIX_.'order_history` oh LEFT JOIN `'._DB_PREFIX_.'orders` o ON oh.`id_order` = o.`id_order` LEFT JOIN `'._DB_PREFIX_.'customer` c ON o.`id_customer` = c.`id_customer` @@ -377,6 +388,8 @@ class OrderHistoryCore extends ObjectModel WHERE oh.`id_order_history` = '.(int)$this->id.' AND os.`send_email` = 1'); if (isset($result['template']) && Validate::isEmail($result['email'])) { + ShopUrl::cacheMainDomainForShop($order->id_shop); + $topic = $result['osname']; $data = array( '{lastname}' => $result['lastname'], @@ -398,8 +411,24 @@ class OrderHistoryCore extends ObjectModel $data['{order_name}'] = $order->getUniqReference(); if (Validate::isLoadedObject($order)) + { + // Join PDF invoice if order state is "payment accepted" + if ((int)$result['id_order_state'] === 2 && (int)Configuration::get('PS_INVOICE') && $order->invoice_number) + { + $context = Context::getContext(); + $pdf = new PDF($order->getInvoicesCollection(), PDF::TEMPLATE_INVOICE, $context->smarty); + $file_attachement['content'] = $pdf->render(false); + $file_attachement['name'] = Configuration::get('PS_INVOICE_PREFIX', (int)$order->id_lang, null, $order->id_shop).sprintf('%06d', $order->invoice_number).'.pdf'; + $file_attachement['mime'] = 'application/pdf'; + } + else + $file_attachement = null; + Mail::Send((int)$order->id_lang, $result['template'], $topic, $data, $result['email'], $result['firstname'].' '.$result['lastname'], - null, null, null, null, _PS_MAIL_DIR_, false, (int)$order->id_shop); + null, null, $file_attachement, null, _PS_MAIL_DIR_, false, (int)$order->id_shop); + } + + ShopUrl::resetMainDomainCache(); } return true; @@ -433,4 +462,27 @@ class OrderHistoryCore extends ObjectModel AND os.`logable` = 1'); } + /** + * Add method for webservice create resource Order History + * If sendemail=1 GET parameter is present sends email to customer otherwise does not + * @return bool + */ + public function addWs() + { + $sendemail = (bool)Tools::getValue('sendemail', false); + if ($sendemail) + { + //Mail::Send requires link object on context and is not set when getting here + $context = Context::getContext(); + if ($context->link == null) + { + $protocol_link = (Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) ? 'https://' : 'http://'; + $protocol_content = (Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) ? 'https://' : 'http://'; + $context->link = new Link($protocol_link, $protocol_content); + } + return $this->addWithemail(); + } + else + return $this->add(); + } } diff --git a/classes/order/OrderInvoice.php b/classes/order/OrderInvoice.php index 2ab0cdf47..31614f2c5 100644 --- a/classes/order/OrderInvoice.php +++ b/classes/order/OrderInvoice.php @@ -522,14 +522,16 @@ class OrderInvoiceCore extends ObjectModel */ public function getTotalPaid() { - if (!array_key_exists($this->id, self::$_total_paid_cache)) + $cache_id = 'order_invoice_paid_'.(int)$this->id; + if (!Cache::isStored($cache_id)) { - self::$_total_paid_cache[$this->id] = 0; + $amount = 0; $payments = OrderPayment::getByInvoiceId($this->id); foreach ($payments as $payment) - self::$_total_paid_cache[$this->id] += $payment->amount; + $amount += $payment->amount; + Cache::store($cache_id, $amount); } - return self::$_total_paid_cache[$this->id]; + return Cache::retrieve($cache_id); } /** diff --git a/classes/pdf/HTMLTemplateDeliverySlip.php b/classes/pdf/HTMLTemplateDeliverySlip.php index a18a4e3b5..b5ea014fe 100755 --- a/classes/pdf/HTMLTemplateDeliverySlip.php +++ b/classes/pdf/HTMLTemplateDeliverySlip.php @@ -38,7 +38,7 @@ class HTMLTemplateDeliverySlipCore extends HTMLTemplate $this->smarty = $smarty; // header informations - $this->date = Tools::displayDate($this->order->invoice_date, (int)$this->order->id_lang); + $this->date = Tools::displayDate($this->order->invoice_date); $this->title = HTMLTemplateDeliverySlip::l('Delivery').' #'.Configuration::get('PS_DELIVERY_PREFIX', Context::getContext()->language->id).sprintf('%06d', $this->order_invoice->delivery_number); // footer informations @@ -60,13 +60,16 @@ class HTMLTemplateDeliverySlipCore extends HTMLTemplate $invoice_address = new Address((int)$this->order->id_address_invoice); $formatted_invoice_address = AddressFormat::generateAddress($invoice_address, array(), '
        ', ' '); } - + + $carrier = new Carrier($this->order->id_carrier); + $carrier->name = ($carrier->name == '0' ? Configuration::get('PS_SHOP_NAME') : $carrier->name); $this->smarty->assign(array( 'order' => $this->order, 'order_details' => $this->order_invoice->getProducts(), 'delivery_address' => $formatted_delivery_address, 'invoice_address' => $formatted_invoice_address, - 'order_invoice' => $this->order_invoice + 'order_invoice' => $this->order_invoice, + 'carrier' => $carrier )); return $this->smarty->fetch($this->getTemplate('delivery-slip')); @@ -87,7 +90,7 @@ class HTMLTemplateDeliverySlipCore extends HTMLTemplate */ public function getFilename() { - return Configuration::get('PS_DELIVERY_PREFIX').sprintf('%06d', $this->order->invoice_number).'.pdf'; + return Configuration::get('PS_DELIVERY_PREFIX', Context::getContext()->language->id, null, $this->order->id_shop).sprintf('%06d', $this->order->invoice_number).'.pdf'; } } diff --git a/classes/pdf/HTMLTemplateInvoice.php b/classes/pdf/HTMLTemplateInvoice.php index 52600802f..8116eb03c 100755 --- a/classes/pdf/HTMLTemplateInvoice.php +++ b/classes/pdf/HTMLTemplateInvoice.php @@ -39,7 +39,7 @@ class HTMLTemplateInvoiceCore extends HTMLTemplate $this->smarty = $smarty; // header informations - $this->date = Tools::displayDate($order_invoice->date_add, (int)$this->order->id_lang); + $this->date = Tools::displayDate($order_invoice->date_add); $id_lang = Context::getContext()->language->id; $this->title = HTMLTemplateInvoice::l('Invoice ').' #'.Configuration::get('PS_INVOICE_PREFIX', $id_lang, null, (int)$this->order->id_shop).sprintf('%06d', $order_invoice->number); @@ -89,7 +89,8 @@ class HTMLTemplateInvoiceCore extends HTMLTemplate $tax_exempt = Configuration::get('VATNUMBER_MANAGEMENT') && !empty($address->vat_number) && $address->id_country != Configuration::get('VATNUMBER_COUNTRY'); - + $carrier = new Carrier($this->order->id_carrier); + $this->smarty->assign(array( 'tax_exempt' => $tax_exempt, 'use_one_after_another_method' => $this->order_invoice->useOneAfterAnotherTaxComputationMethod(), @@ -98,7 +99,8 @@ class HTMLTemplateInvoiceCore extends HTMLTemplate 'ecotax_tax_breakdown' => $this->order_invoice->getEcoTaxTaxesBreakdown(), 'wrapping_tax_breakdown' => $this->order_invoice->getWrappingTaxesBreakdown(), 'order' => $this->order, - 'order_invoice' => $this->order_invoice + 'order_invoice' => $this->order_invoice, + 'carrier' => $carrier )); return $this->smarty->fetch($this->getTemplate('invoice.tax-tab')); @@ -137,7 +139,7 @@ class HTMLTemplateInvoiceCore extends HTMLTemplate */ public function getFilename() { - return Configuration::get('PS_INVOICE_PREFIX').sprintf('%06d', $this->order_invoice->number).'.pdf'; + return Configuration::get('PS_INVOICE_PREFIX', Context::getContext()->language->id, null, $this->order->id_shop).sprintf('%06d', $this->order_invoice->number).'.pdf'; } } diff --git a/classes/pdf/HTMLTemplateOrderReturn.php b/classes/pdf/HTMLTemplateOrderReturn.php index 0e366ce91..7efda9b4a 100755 --- a/classes/pdf/HTMLTemplateOrderReturn.php +++ b/classes/pdf/HTMLTemplateOrderReturn.php @@ -39,8 +39,8 @@ class HTMLTemplateOrderReturnCore extends HTMLTemplate $this->order = new Order($order_return->id_order); // header informations - $this->date = Tools::displayDate($this->order->invoice_date, (int)$this->order->id_lang); - $this->title = HTMLTemplateOrderReturn::l('Order Return ').sprintf('%06d', $this->order_return->id); + $this->date = Tools::displayDate($this->order->invoice_date); + $this->title = sprintf(HTMLTemplateOrderReturn::l('Order Return %s'), sprintf('%06d', $this->order_return->id)); // footer informations $this->shop = new Shop((int)$this->order->id_shop); diff --git a/classes/pdf/HTMLTemplateOrderSlip.php b/classes/pdf/HTMLTemplateOrderSlip.php index 06b8b2e23..db9df275d 100644 --- a/classes/pdf/HTMLTemplateOrderSlip.php +++ b/classes/pdf/HTMLTemplateOrderSlip.php @@ -45,7 +45,7 @@ class HTMLTemplateOrderSlipCore extends HTMLTemplateInvoice $this->smarty = $smarty; // header informations - $this->date = Tools::displayDate($this->order->invoice_date, (int)$this->order->id_lang); + $this->date = Tools::displayDate($this->order_slip->date_add); $this->title = HTMLTemplateOrderSlip::l('Slip #').Configuration::get('PS_CREDIT_SLIP_PREFIX', Context::getContext()->language->id).sprintf('%06d', (int)$this->order_slip->id); // footer informations @@ -211,6 +211,8 @@ class HTMLTemplateOrderSlipCore extends HTMLTemplateInvoice if ($ecotax) foreach ($tmp_tax_infos as $rate => &$row) { + if (!isset($ecotax[$rate])) + continue; $row['total_price_tax_excl'] -= $ecotax[$rate]['ecotax_tax_excl']; $row['total_amount'] -= ($ecotax[$rate]['ecotax_tax_incl'] - $ecotax[$rate]['ecotax_tax_excl']); } diff --git a/classes/pdf/HTMLTemplateSupplyOrderForm.php b/classes/pdf/HTMLTemplateSupplyOrderForm.php index 16a94b8e5..15139644d 100644 --- a/classes/pdf/HTMLTemplateSupplyOrderForm.php +++ b/classes/pdf/HTMLTemplateSupplyOrderForm.php @@ -45,7 +45,7 @@ class HTMLTemplateSupplyOrderFormCore extends HTMLTemplate $this->address_supplier = new Address(Address::getAddressIdBySupplierId((int)$supply_order->id_supplier)); // header informations - $this->date = Tools::displayDate($supply_order->date_add, (int)$this->supply_order->id_lang); + $this->date = Tools::displayDate($supply_order->date_add); $this->title = HTMLTemplateSupplyOrderForm::l('Supply order form'); } diff --git a/classes/pdf/PDFGenerator.php b/classes/pdf/PDFGenerator.php index 1c117ad86..3049eaf62 100755 --- a/classes/pdf/PDFGenerator.php +++ b/classes/pdf/PDFGenerator.php @@ -46,6 +46,7 @@ class PDFGeneratorCore extends TCPDF 'uk' => 'freeserif', 'mk' => 'freeserif', 'el' => 'freeserif', + 'en' => 'dejavusans', 'vn' => 'dejavusans', 'pl' => 'dejavusans', 'ar' => 'dejavusans', diff --git a/classes/shop/Shop.php b/classes/shop/Shop.php index 1538bb2e2..4ca5cf8f4 100644 --- a/classes/shop/Shop.php +++ b/classes/shop/Shop.php @@ -187,18 +187,16 @@ class ShopCore extends ObjectModel public function setUrl() { - $sql = 'SELECT su.physical_uri, su.virtual_uri, - su.domain, su.domain_ssl, t.id_theme, t.name, t.directory - FROM '._DB_PREFIX_.'shop s - LEFT JOIN '._DB_PREFIX_.'shop_url su ON (s.id_shop = su.id_shop) - LEFT JOIN '._DB_PREFIX_.'theme t ON (t.id_theme = s.id_theme) - WHERE s.id_shop = '.(int)$this->id.' - AND s.active = 1 - AND s.deleted = 0 - AND su.main = 1'; - - if (!$row = Db::getInstance()->getRow($sql)) - return; + $row = Db::getInstance()->getRow(' + SELECT su.physical_uri, su.virtual_uri, su.domain, su.domain_ssl, t.id_theme, t.name, t.directory + FROM '._DB_PREFIX_.'shop s + LEFT JOIN '._DB_PREFIX_.'shop_url su ON (s.id_shop = su.id_shop) + LEFT JOIN '._DB_PREFIX_.'theme t ON (t.id_theme = s.id_theme) + WHERE s.id_shop = '.(int)$this->id.' + AND s.active = 1 AND s.deleted = 0 AND su.main = 1'); + + if (!$row) + return false; $this->theme_id = $row['id_theme']; $this->theme_name = $row['name']; @@ -349,12 +347,27 @@ class ShopCore extends ObjectModel } } - if (!$id_shop && defined('_PS_ADMIN_DIR_')) + if ((!$id_shop && defined('_PS_ADMIN_DIR_')) || Tools::isPHPCLI()) { // If in admin, we can access to the shop without right URL - $shop = new Shop(Configuration::get('PS_SHOP_DEFAULT')); + if ((!$id_shop && Tools::isPHPCLI()) || defined('_PS_ADMIN_DIR_')) + $id_shop = (int)Configuration::get('PS_SHOP_DEFAULT'); + + $shop = new Shop((int)$id_shop); + if (!Validate::isLoadedObject($shop)) + $shop = new Shop((int)Configuration::get('PS_SHOP_DEFAULT')); + $shop->physical_uri = preg_replace('#/+#', '/', str_replace('\\', '/', dirname(dirname($_SERVER['SCRIPT_NAME']))).'/'); $shop->virtual_uri = ''; + + // Define some $_SERVER variables like HTTP_HOST if PHP is launched with php-cli + if (Tools::isPHPCLI()) + { + if(!isset($_SERVER['HTTP_HOST']) || empty($_SERVER['HTTP_HOST'])) + $_SERVER['HTTP_HOST'] = $shop->domain; + if(!isset($_SERVER['SERVER_NAME']) || empty($_SERVER['SERVER_NAME'])) + $_SERVER['SERVER_NAME'] = $shop->domain; + } } else { diff --git a/classes/shop/ShopGroup.php b/classes/shop/ShopGroup.php index 288463918..7818fb56f 100644 --- a/classes/shop/ShopGroup.php +++ b/classes/shop/ShopGroup.php @@ -153,4 +153,15 @@ class ShopGroupCore extends ObjectModel return false; } -} + + public function shopNameExists($name, $id_shop = false) + { + return Db::getInstance()->getValue(' + SELECT id_shop + FROM '._DB_PREFIX_.'shop + WHERE name = "'.pSQL($name).'" + AND id_shop_group = '.(int)$this->id.' + '.($id_shop ? 'AND id_shop != '.(int)$id_shop : '') + ); + } +} \ No newline at end of file diff --git a/classes/shop/ShopUrl.php b/classes/shop/ShopUrl.php index 62d43aaa9..5edf106d4 100644 --- a/classes/shop/ShopUrl.php +++ b/classes/shop/ShopUrl.php @@ -34,8 +34,8 @@ class ShopUrlCore extends ObjectModel public $main; public $active; - protected static $main_domain = null; - protected static $main_domain_ssl = null; + protected static $main_domain = array(); + protected static $main_domain_ssl = array(); /** * @see ObjectModel::$definition @@ -143,25 +143,35 @@ class ShopUrlCore extends ObjectModel return Db::getInstance()->getValue($sql); } - public static function getMainShopDomain() + public static function cacheMainDomainForShop($id_shop) { - if (!self::$main_domain) - self::$main_domain = Db::getInstance()->getValue('SELECT domain - FROM '._DB_PREFIX_.'shop_url - WHERE main=1 AND id_shop = '.Context::getContext()->shop->id); - return self::$main_domain; + if (!isset(self::$main_domain_ssl[(int)$id_shop]) || !isset(self::$main_domain[(int)$id_shop])) + { + $row = Db::getInstance()->getRow(' + SELECT domain, domain_ssl + FROM '._DB_PREFIX_.'shop_url + WHERE main = 1 + AND id_shop = '.($id_shop !== null ? (int)$id_shop : Context::getContext()->shop->id)); + self::$main_domain[(int)$id_shop] = $row['domain']; + self::$main_domain_ssl[(int)$id_shop] = $row['domain_ssl']; + } + } + + public static function resetMainDomainCache() + { + self::$main_domain = array(); + self::$main_domain_ssl = array(); } - public static function getMainShopDomainSSL() + public static function getMainShopDomain($id_shop = null) { - if (!self::$main_domain_ssl) - { - $sql = 'SELECT domain_ssl - FROM '._DB_PREFIX_.'shop_url - WHERE main = 1 - AND id_shop='.Context::getContext()->shop->id; - self::$main_domain_ssl = Db::getInstance()->getValue($sql); - } - return self::$main_domain_ssl; + ShopUrl::cacheMainDomainForShop($id_shop); + return self::$main_domain[(int)$id_shop]; } -} + + public static function getMainShopDomainSSL($id_shop = null) + { + ShopUrl::cacheMainDomainForShop($id_shop); + return self::$main_domain_ssl[(int)$id_shop]; + } +} \ No newline at end of file diff --git a/classes/stock/StockAvailable.php b/classes/stock/StockAvailable.php index fbdaa1a2f..12e23cd39 100644 --- a/classes/stock/StockAvailable.php +++ b/classes/stock/StockAvailable.php @@ -680,7 +680,7 @@ class StockAvailableCore extends ObjectModel // if there is no $id_shop, gets the context one // get shop group too - if ($shop === null) + if ($shop === null || $shop === $context->shop->id) { if (Shop::getContext() == Shop::CONTEXT_GROUP) $shop_group = Shop::getContextShopGroup(); diff --git a/classes/stock/StockManager.php b/classes/stock/StockManager.php index 1ad67d77b..a313da21f 100644 --- a/classes/stock/StockManager.php +++ b/classes/stock/StockManager.php @@ -479,13 +479,13 @@ class StockManagerCore implements StockManagerInterface $query->where('o.valid = 1 OR (os.id_order_state != '.(int)Configuration::get('PS_OS_ERROR').' AND os.id_order_state != '.(int)Configuration::get('PS_OS_CANCELED').')'); $query->groupBy('od.id_order_detail'); - //if (count($ids_warehouse)) - //$query->where('od.id_warehouse IN('.implode(', ', $ids_warehouse).')'); + if (count($ids_warehouse)) + $query->where('od.id_warehouse IN('.implode(', ', $ids_warehouse).')'); $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); $client_orders_qty = 0; if (count($res)) foreach ($res as $row) - $client_orders_qty += $row['product_quantity'] + $row['product_quantity_refunded']; + $client_orders_qty += ($row['product_quantity'] - $row['product_quantity_refunded']); // Gets supply_orders_qty $query = new DbQuery(); @@ -658,4 +658,4 @@ class StockManagerCore implements StockManagerInterface return $stocks; } -} +} \ No newline at end of file diff --git a/classes/stock/StockMvt.php b/classes/stock/StockMvt.php index 2245cf648..83bd79e08 100644 --- a/classes/stock/StockMvt.php +++ b/classes/stock/StockMvt.php @@ -236,7 +236,7 @@ class StockMvtCore extends ObjectModel $query->innerJoin('stock', 's', 's.id_stock = sm.id_stock'); $query->innerJoin('warehouse', 'w', 'w.id_warehouse = s.id_warehouse'); $query->where('sm.sign = 1'); - $query->where('s.id_product = '.(int)$id_product.' AND s.id_product_attribute = '.(int)$id_product_attribute); + $query->where('s.id_product = '.(int)$id_product.' OR s.id_product_attribute = '.(int)$id_product_attribute); $query->orderBy('date_add DESC'); $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); diff --git a/classes/tax/TaxRulesGroup.php b/classes/tax/TaxRulesGroup.php index 02391e134..469b6c641 100644 --- a/classes/tax/TaxRulesGroup.php +++ b/classes/tax/TaxRulesGroup.php @@ -56,10 +56,12 @@ class TaxRulesGroupCore extends ObjectModel public static function getTaxRulesGroups($only_active = true) { return Db::getInstance()->executeS(' - SELECT * - FROM `'._DB_PREFIX_.'tax_rules_group` g' - .($only_active ? ' WHERE g.`active` = 1' : '').' - ORDER BY name ASC'); + SELECT DISTINCT g.id_tax_rules_group, g.name, g.active + FROM `'._DB_PREFIX_.'tax_rules_group` g' + .Shop::addSqlAssociation('tax_rules_group', 'g') + .($only_active ? ' WHERE g.`active` = 1' : '').' + ORDER BY name ASC'); + } /** @@ -113,11 +115,11 @@ class TaxRulesGroupCore extends ObjectModel ); } - public function hasUniqueTaxRuleForCountry($id_country, $id_state) + public function hasUniqueTaxRuleForCountry($id_country, $id_state, $id_tax_rule = false) { $rules = TaxRule::getTaxRulesByGroupId((int)Context::getContext()->language->id, (int)$this->id); foreach ($rules as $rule) - if ($rule['id_country'] == $id_country && $id_state == $rule['id_state'] && !$rule['behavior']) + if ($rule['id_country'] == $id_country && $id_state == $rule['id_state'] && !$rule['behavior'] && (int)$id_tax_rule != $rule['id_tax_rule']) return true; return false; diff --git a/classes/webservice/WebserviceOutputBuilder.php b/classes/webservice/WebserviceOutputBuilder.php index 00bae700f..8aaabea65 100755 --- a/classes/webservice/WebserviceOutputBuilder.php +++ b/classes/webservice/WebserviceOutputBuilder.php @@ -47,6 +47,8 @@ class WebserviceOutputBuilderCore protected $virtualFields = array(); protected $statusInt; protected $wsParamOverrides; + + protected static $_cache_ws_parameters = array(); // Header properties protected $headerParams = array( @@ -283,7 +285,7 @@ class WebserviceOutputBuilderCore if (is_null($this->wsResource)) throw new WebserviceException ('You must set web service resource for get the resources list.', array(82, 500)); $output = ''; - $more_attr = array('shop_name' => htmlentities(Configuration::get('PS_SHOP_NAME'))); + $more_attr = array('shop_name' => htmlspecialchars(Configuration::get('PS_SHOP_NAME'))); $output .= $this->objectRender->renderNodeHeader('api', array(), $more_attr); foreach ($this->wsResource as $resourceName => $resource) { @@ -359,7 +361,11 @@ class WebserviceOutputBuilderCore $type_of_view = self::VIEW_DETAILS; } - $ws_params = $objects['empty']->getWebserviceParameters(); + $class = get_class($objects['empty']); + if (!isset(WebserviceOutputBuilder::$_cache_ws_parameters[$class])) + WebserviceOutputBuilder::$_cache_ws_parameters[$class] = $objects['empty']->getWebserviceParameters(); + $ws_params = WebserviceOutputBuilder::$_cache_ws_parameters[$class]; + foreach ($this->wsParamOverrides AS $p) { $object = $p['object']; @@ -376,7 +382,7 @@ class WebserviceOutputBuilderCore { if ($key !== 'empty') { - if ($this->fieldsToDisplay === 'minimum') + if ($this->fieldsToDisplay === 'minimum') $output .= $this->renderEntityMinimum($object, $depth); else $output .= $this->renderEntity($object, $depth); @@ -406,7 +412,11 @@ class WebserviceOutputBuilderCore */ public function renderEntityMinimum($object, $depth) { - $ws_params = $object->getWebserviceParameters(); + $class = get_class($object); + if (!isset(WebserviceOutputBuilder::$_cache_ws_parameters[$class])) + WebserviceOutputBuilder::$_cache_ws_parameters[$class] = $object->getWebserviceParameters(); + $ws_params = WebserviceOutputBuilder::$_cache_ws_parameters[$class]; + $more_attr['id'] = $object->id; $more_attr['xlink_resource'] = $this->wsUrl.$ws_params['objectsNodeName'].'/'.$object->id; $output = $this->setIndent($depth).$this->objectRender->renderNodeHeader($ws_params['objectNodeName'], $ws_params, $more_attr, false); @@ -446,7 +456,12 @@ class WebserviceOutputBuilderCore public function renderEntity($object, $depth) { $output = ''; - $ws_params = $object->getWebserviceParameters(); + + $class = get_class($object); + if (!isset(WebserviceOutputBuilder::$_cache_ws_parameters[$class])) + WebserviceOutputBuilder::$_cache_ws_parameters[$class] = $object->getWebserviceParameters(); + $ws_params = WebserviceOutputBuilder::$_cache_ws_parameters[$class]; + foreach ($this->wsParamOverrides AS $p) { $o = $p['object']; @@ -792,4 +807,4 @@ class WebserviceOutputBuilderCore { $this->fieldsToDisplay = $fields; } -} \ No newline at end of file +} diff --git a/classes/webservice/WebserviceRequest.php b/classes/webservice/WebserviceRequest.php index a4f5ee6b5..39ca28043 100644 --- a/classes/webservice/WebserviceRequest.php +++ b/classes/webservice/WebserviceRequest.php @@ -513,7 +513,6 @@ class WebserviceRequestCore $this->setError(501, sprintf('The specific management class is not implemented for the "%s" entity.', $this->urlSegment[0]), 124); else { - $this->setFieldsToDisplay(); $this->objectSpecificManagement = new $specificObjectName(); $this->objectSpecificManagement->setObjectOutput($this->objOutput) ->setWsObject($this); @@ -530,9 +529,10 @@ class WebserviceRequestCore } } } - return $this->returnOutput(); + $return = $this->returnOutput(); unset($webservice_call); - unset ($display_errors); + unset($display_errors); + return $return; } protected function webserviceChecks() @@ -1158,6 +1158,7 @@ class WebserviceRequestCore $sorts = array($this->urlFragments['sort']); $sql_sort .= ' ORDER BY '; + foreach ($sorts as $sort) { $delimiterPosition = strrpos($sort, '_'); @@ -1184,7 +1185,14 @@ class WebserviceRequestCore $sql_sort .= 'main_i18n.`'.pSQL($this->resourceConfiguration['fields'][$fieldName]['sqlId']).'` '.$direction.', ';// ORDER BY main_i18n.`field` ASC|DESC } else - $sql_sort .= (isset($this->resourceConfiguration['retrieveData']['tableAlias']) ? $this->resourceConfiguration['retrieveData']['tableAlias'].'.' : '').'`'.pSQL($this->resourceConfiguration['fields'][$fieldName]['sqlId']).'` '.$direction.', ';// ORDER BY `field` ASC|DESC + { + $object = new $this->resourceConfiguration['retrieveData']['className'](); + if ($object->isMultiShopField($this->resourceConfiguration['fields'][$fieldName]['sqlId'])) + $table_alias = 'multi_shop_'.$this->resourceConfiguration['retrieveData']['table']; + else + $table_alias = ''; + $sql_sort .= (isset($this->resourceConfiguration['retrieveData']['tableAlias']) ? '`'.bqSQL($this->resourceConfiguration['retrieveData']['tableAlias']).'`.' : '`'.bqSQL($table_alias).'`.').'`'.pSQL($this->resourceConfiguration['fields'][$fieldName]['sqlId']).'` '.$direction.', ';// ORDER BY `field` ASC|DESC + } } $sql_sort = rtrim($sql_sort, ', ')."\n"; } @@ -1212,12 +1220,15 @@ class WebserviceRequestCore return $filters; } - - public function getFilteredObjectList() { $objects = array(); $filters = $this->manageFilters(); + + /* If we only need to display the synopsis, analyzing the first row is sufficient */ + if (isset($this->urlFragments['schema']) && in_array($this->urlFragments['schema'], array('blank', 'synopsis'))) + $filters = array('sql_join' => '', 'sql_filter' => '', 'sql_sort' => '', 'sql_limit' => ' LIMIT 1'); + $this->resourceConfiguration['retrieveData']['params'][] = $filters['sql_join']; $this->resourceConfiguration['retrieveData']['params'][] = $filters['sql_filter']; $this->resourceConfiguration['retrieveData']['params'][] = $filters['sql_sort']; @@ -1229,7 +1240,16 @@ class WebserviceRequestCore if ($sqlObjects) { foreach ($sqlObjects as $sqlObject) - $objects[] = new $this->resourceConfiguration['retrieveData']['className']((int)$sqlObject[$this->resourceConfiguration['fields']['id']['sqlId']]); + { + if ($this->fieldsToDisplay == 'minimum') + { + $obj = new $this->resourceConfiguration['retrieveData']['className'](); + $obj->id = (int)$sqlObject[$this->resourceConfiguration['fields']['id']['sqlId']]; + $objects[] = $obj; + } + else + $objects[] = new $this->resourceConfiguration['retrieveData']['className']((int)$sqlObject[$this->resourceConfiguration['fields']['id']['sqlId']]); + } return $objects; } } @@ -1244,14 +1264,22 @@ class WebserviceRequestCore $assoc = Shop::getAssoTable($this->resourceConfiguration['retrieveData']['table']); if ($assoc !== false) { + $check_shop_group = false; + $sql = 'SELECT 1 FROM `'.bqSQL(_DB_PREFIX_.$this->resourceConfiguration['retrieveData']['table']); if ($assoc['type'] != 'fk_shop') $sql .= '_'.$assoc['type']; + else + { + $def = ObjectModel::getDefinition($this->resourceConfiguration['retrieveData']['className']); + if (isset($def['fields']) && isset($def['fields']['id_shop_group'])) + $check_shop_group = true; + } $sql .= '`'; foreach (self::$shopIDs as $id_shop) - $OR[] = ' id_shop = '.(int)$id_shop.' '; + $OR[] = ' (id_shop = '.(int)$id_shop.($check_shop_group ? ' OR (id_shop = 0 AND id_shop_group='.(int)Shop::getGroupFromShop((int)$id_shop).')' : '').') '; $check = ' WHERE ('.implode('OR', $OR).') AND `'.bqSQL($this->resourceConfiguration['fields']['id']['sqlId']).'` = '.(int)$this->urlSegment[1]; if (!Db::getInstance()->getValue($sql.$check)) diff --git a/cms.php b/cms.php index 5eef078cc..ff2c40d7c 100644 --- a/cms.php +++ b/cms.php @@ -34,4 +34,4 @@ require(dirname(__FILE__).'/config/config.inc.php'); Tools::displayFileAsDeprecated(); -Tools::redirect('index.php?controller=cms'.($_REQUEST ? '&'.http_build_query($_REQUEST, '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file +Tools::redirect('index.php?controller=cms'.((count($_GET) || count($_POST)) ? '&'.http_build_query(array_merge($_GET, $_POST), '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file diff --git a/config/config.inc.php b/config/config.inc.php index ce76ea8c6..763f3a135 100644 --- a/config/config.inc.php +++ b/config/config.inc.php @@ -62,6 +62,9 @@ if (_PS_DEBUG_PROFILING_) include_once(_PS_TOOL_DIR_.'profiling/Tools.php'); } +if (Tools::isPHPCLI()) + Tools::argvToGET($argc, $argv); + /* Redefine REQUEST_URI if empty (on some webservers...) */ if (!isset($_SERVER['REQUEST_URI']) || empty($_SERVER['REQUEST_URI'])) { @@ -87,7 +90,15 @@ if (!isset($_SERVER['HTTP_HOST']) || empty($_SERVER['HTTP_HOST'])) $context = Context::getContext(); /* Initialize the current Shop */ -$context->shop = Shop::initialize(); +try +{ + $context->shop = Shop::initialize(); +} +catch (PrestaShopException $e) +{ + $e->displayMessage(); +} + define('_THEME_NAME_', $context->shop->getTheme()); define('__PS_BASE_URI__', $context->shop->getBaseURI()); diff --git a/config/defines.inc.php b/config/defines.inc.php index 8ce70b580..ab72ff105 100755 --- a/config/defines.inc.php +++ b/config/defines.inc.php @@ -28,7 +28,8 @@ define('_PS_MODE_DEV_', true); if (_PS_MODE_DEV_) { - @ini_set('display_errors', 'on'); + @ini_set('display_errors', 'on'); + @error_reporting(E_ALL | E_STRICT); define('_PS_DEBUG_SQL_', true); /* Compatibility warning */ define('_PS_DISPLAY_COMPATIBILITY_WARNING_', true); diff --git a/config/smarty.config.inc.php b/config/smarty.config.inc.php index 128900a6d..392b42a58 100644 --- a/config/smarty.config.inc.php +++ b/config/smarty.config.inc.php @@ -44,7 +44,10 @@ $smarty->debugging = false; $smarty->debugging_ctrl = 'NONE'; if (Configuration::get('PS_SMARTY_CONSOLE') == _PS_SMARTY_CONSOLE_OPEN_BY_URL_) +{ $smarty->debugging_ctrl = 'URL'; + $smarty->smarty_debug_id = Configuration::get('PS_SMARTY_CONSOLE_KEY'); +} else if (Configuration::get('PS_SMARTY_CONSOLE') == _PS_SMARTY_CONSOLE_OPEN_) $smarty->debugging = true; @@ -176,6 +179,7 @@ function smartyHook($params, &$smarty) { $id_module = null; $hook_params = $params; + $hook_params['smarty'] = $smarty; if (!empty($params['mod'])) { $module = Module::getInstanceByName($params['mod']); diff --git a/config/smartyadmin.config.inc.php b/config/smartyadmin.config.inc.php index 60d9a149f..9f5654082 100644 --- a/config/smartyadmin.config.inc.php +++ b/config/smartyadmin.config.inc.php @@ -36,7 +36,7 @@ function smartyTranslate($params, &$smarty) { $htmlentities = !isset($params['js']); $pdf = isset($params['pdf']); - $addslashes = isset($params['slashes']); + $addslashes = (isset($params['slashes']) || isset($params['js'])); $sprintf = isset($params['sprintf']) ? $params['sprintf'] : false; if ($pdf) @@ -57,7 +57,14 @@ function smartyTranslate($params, &$smarty) // If the tpl is used by a Controller else { - // Split by \ and / to get the folder tree for the file + if (isset(Context::getContext()->controller)) + { + $class_name = get_class(Context::getContext()->controller); + $class = substr($class_name, 0, strpos(Tools::strtolower($class_name), 'controller')); + } + else + { + // Split by \ and / to get the folder tree for the file $folder_tree = preg_split('#[/\\\]#', $filename); $key = array_search('controllers', $folder_tree); @@ -69,8 +76,8 @@ function smartyTranslate($params, &$smarty) $class = 'Admin'.Tools::toCamelCase($folder_tree[0], true); else $class = null; + } } return Translate::getAdminTranslation($params['s'], $class, $addslashes, $htmlentities, $sprintf); -} - +} \ No newline at end of file diff --git a/config/smartyfront.config.inc.php b/config/smartyfront.config.inc.php index b95642a4b..6441344c2 100644 --- a/config/smartyfront.config.inc.php +++ b/config/smartyfront.config.inc.php @@ -62,8 +62,10 @@ function smartyTranslate($params, &$smarty) else $msg = $params['s']; - if ($msg != $params['s']) - $msg = $params['js'] ? addslashes($msg) : stripslashes($msg); + if ($msg != $params['s'] && !$params['js']) + $msg = stripslashes($msg); + elseif ($params['js']) + $msg = addslashes($msg); if ($params['sprintf'] !== null) $msg = Translate::checkAndReplaceArgs($msg, $params['sprintf']); diff --git a/contact-form.php b/contact-form.php index ceef9234d..5891e5b0a 100644 --- a/contact-form.php +++ b/contact-form.php @@ -34,4 +34,4 @@ require(dirname(__FILE__).'/config/config.inc.php'); Tools::displayFileAsDeprecated(); -Tools::redirect('index.php?controller=contact'.($_REQUEST ? '&'.http_build_query($_REQUEST, '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file +Tools::redirect('index.php?controller=contact'.((count($_GET) || count($_POST)) ? '&'.http_build_query(array_merge($_GET, $_POST), '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file diff --git a/controllers/admin/AdminAccessController.php b/controllers/admin/AdminAccessController.php index a3f79ab4b..543a3b5d2 100644 --- a/controllers/admin/AdminAccessController.php +++ b/controllers/admin/AdminAccessController.php @@ -153,35 +153,32 @@ class AdminAccessControllerCore extends AdminController $join = 'LEFT JOIN `'._DB_PREFIX_.'tab` t ON (t.`id_tab` = a.`id_tab`)'; } - if ($id_tab == -1 && $perm == 'all' && $enabled == 0) - $sql = ' - UPDATE `'._DB_PREFIX_.'access` a - SET `view` = '.(int)$enabled.', `add` = '.(int)$enabled.', `edit` = '.(int)$enabled.', `delete` = '.(int)$enabled.' - WHERE `id_profile` = '.(int)$id_profile.' AND `id_tab` != '.(int)$this->id_tab_access; - else if ($id_tab == -1 && $perm == 'all') - $sql = ' + if ($id_tab == -1) + { + if ($perm == 'all') + $sql = ' UPDATE `'._DB_PREFIX_.'access` a SET `view` = '.(int)$enabled.', `add` = '.(int)$enabled.', `edit` = '.(int)$enabled.', `delete` = '.(int)$enabled.' WHERE `id_profile` = '.(int)$id_profile; - else if ($id_tab == -1) - $sql = ' + else + $sql = ' UPDATE `'._DB_PREFIX_.'access` a SET `'.bqSQL($perm).'` = '.(int)$enabled.' WHERE `id_profile` = '.(int)$id_profile; - else if ($perm == 'all') - $sql = ' - UPDATE `'._DB_PREFIX_.'access` a - '.$join.' - SET `view` = '.(int)$enabled.', `add` = '.(int)$enabled.', `edit` = '.(int)$enabled.', `delete` = '.(int)$enabled.' - WHERE '.$where.' = '.(int)$id_tab.' - AND `id_profile` = '.(int)$id_profile; + } else - $sql = ' - UPDATE `'._DB_PREFIX_.'access` a - '.$join.' + { + if ($perm == 'all') + $sql = ' + UPDATE `'._DB_PREFIX_.'access` a '.$join.' + SET `view` = '.(int)$enabled.', `add` = '.(int)$enabled.', `edit` = '.(int)$enabled.', `delete` = '.(int)$enabled.' + WHERE '.$where.' = '.(int)$id_tab.' AND `id_profile` = '.(int)$id_profile; + else + $sql = ' + UPDATE `'._DB_PREFIX_.'access` a '.$join.' SET `'.bqSQL($perm).'` = '.(int)$enabled.' - WHERE '.$where.' = '.(int)$id_tab.' - AND `id_profile` = '.(int)$id_profile; + WHERE '.$where.' = '.(int)$id_tab.' AND `id_profile` = '.(int)$id_profile; + } $res = Db::getInstance()->execute($sql) ? 'ok' : 'error'; diff --git a/controllers/admin/AdminAddressesController.php b/controllers/admin/AdminAddressesController.php index 959687eef..cc411b8eb 100644 --- a/controllers/admin/AdminAddressesController.php +++ b/controllers/admin/AdminAddressesController.php @@ -152,18 +152,7 @@ class AdminAddressesControllerCore extends AdminController $token_customer = Tools::getAdminToken('AdminCustomers'.(int)(Tab::getIdFromClassName('AdminCustomers')).(int)$this->context->employee->id); } - // @todo in 1.4, this include was done before the class declaration - // We should use a hook now - if (Configuration::get('VATNUMBER_MANAGEMENT') && file_exists(_PS_MODULE_DIR_.'vatnumber/vatnumber.php')) - include_once(_PS_MODULE_DIR_.'vatnumber/vatnumber.php'); - if (Configuration::get('VATNUMBER_MANAGEMENT')) - if (file_exists(_PS_MODULE_DIR_.'vatnumber/vatnumber.php') && VatNumber::isApplicable(Configuration::get('PS_COUNTRY_DEFAULT'))) - $vat = 'is_applicable'; - else - $vat = 'management'; - $this->tpl_form_vars = array( - 'vat' => isset($vat) ? $vat : null, 'customer' => isset($customer) ? $customer : null, 'tokenCustomer' => isset ($token_customer) ? $token_customer : null ); @@ -444,4 +433,41 @@ class AdminAddressesControllerCore extends AdminController } die; } + + /** + * Object Delete + */ + public function processDelete() + { + if (Validate::isLoadedObject($object = $this->loadObject())) + if (!$object->isUsed()) + $this->deleted = false; + + return parent::processDelete(); + } + + /** + * Delete multiple items + * + * @return boolean true if succcess + */ + protected function processBulkDelete() + { + if (is_array($this->boxes) && !empty($this->boxes)) + { + $deleted = false; + foreach ($this->boxes as $id) + { + $to_delete = new Address((int)$id); + if ($to_delete->isUsed()) + { + $deleted = true; + break; + } + } + $this->deleted = $deleted; + } + + return parent::processBulkDelete(); + } } diff --git a/controllers/admin/AdminAttributesGroupsController.php b/controllers/admin/AdminAttributesGroupsController.php index 26c53cc83..4e3a2f1aa 100644 --- a/controllers/admin/AdminAttributesGroupsController.php +++ b/controllers/admin/AdminAttributesGroupsController.php @@ -54,6 +54,7 @@ class AdminAttributesGroupsControllerCore extends AdminController 'title' => $this->l('Values count'), 'width' => 120, 'align' => 'center', + 'search' => false ), 'position' => array( 'title' => $this->l('Position'), @@ -328,6 +329,11 @@ class AdminAttributesGroupsControllerCore extends AdminController 'label' => $this->l('Current texture:'), 'name' => 'current_texture' ); + + $this->fields_form['input'][] = array( + 'type' => 'closediv', + 'name' => '' + ); $this->fields_form['submit'] = array( 'title' => $this->l('Save '), @@ -686,7 +692,11 @@ class AdminAttributesGroupsControllerCore extends AdminController { foreach ($this->_list as &$list) if (file_exists(_PS_IMG_DIR_.$this->fieldImageSettings['dir'].'/'.(int)$list['id_attribute'].'.jpg')) + { + if (!isset($list['color']) || !is_array($list['color'])) + $list['color'] = array(); $list['color']['texture'] = '../img/'.$this->fieldImageSettings['dir'].'/'.(int)$list['id_attribute'].'.jpg'; + } } else { diff --git a/controllers/admin/AdminCarrierWizardController.php b/controllers/admin/AdminCarrierWizardController.php new file mode 100644 index 000000000..1f9066d82 --- /dev/null +++ b/controllers/admin/AdminCarrierWizardController.php @@ -0,0 +1,931 @@ + +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +class AdminCarrierWizardControllerCore extends AdminController +{ + protected $wizard_access; + + public function __construct() + { + $this->display = 'view'; + $this->table = 'carrier'; + $this->identifier = 'id_carrier'; + $this->className = 'Carrier'; + $this->lang = false; + $this->deleted = true; + $this->step_number = 0; + + $this->fieldImageSettings = array( + 'name' => 'logo', + 'dir' => 's' + ); + + parent::__construct(); + + $this->tabAccess = Profile::getProfileAccess($this->context->employee->id_profile, Tab::getIdFromClassName('AdminCarriers')); + } + + public function setMedia() + { + parent::setMedia(); + $this->addJqueryPlugin('smartWizard'); + $this->addJqueryPlugin('typewatch'); + $this->addJs(_PS_JS_DIR_.'admin_carrier_wizard.js'); + } + + public function initWizard() + { + $this->wizard_steps = array( + 'name' => 'carrier_wizard', + 'steps' => array( + array( + 'title' => $this->l('General settings'), + ), + array( + 'title' => $this->l('Shipping locations and costs'), + ), + array( + 'title' => $this->l('Size, weight, and group access'), + ), + array( + 'title' => $this->l('Summary'), + ), + + )); + + if (Shop::isFeatureActive()) + { + $multistore_step = array( + array( + 'title' => $this->l('MultiStore'), + ) + ); + array_splice($this->wizard_steps['steps'], 1, 0, $multistore_step); + } + } + + public function renderView() + { + $this->initWizard(); + + if (Tools::getValue('id_carrier') && $this->tabAccess['edit']) + $carrier = $this->loadObject(); + elseif ($this->tabAccess['add']) + $carrier = new Carrier(); + + if ((!$this->tabAccess['edit'] && Tools::getValue('id_carrier')) || (!$this->tabAccess['add'] && !Tools::getValue('id_carrier'))) + { + $this->errors[] = Tools::displayError('You do not have permission to use this wizard.'); + return ; + } + $currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); + $this->tpl_view_vars = array( + 'currency_sign' => $currency->sign, + 'PS_WEIGHT_UNIT' => Configuration::get('PS_WEIGHT_UNIT'), + 'enableAllSteps' => Validate::isLoadedObject($carrier), + 'wizard_steps' => $this->wizard_steps, + 'validate_url' => $this->context->link->getAdminLink('AdminCarrierWizard'), + 'carrierlist_url' => $this->context->link->getAdminLink('AdminCarriers').'&conf='.((int)Validate::isLoadedObject($carrier) ? 4 : 3), + 'multistore_enable' => Shop::isFeatureActive(), + 'wizard_contents' => array( + 'contents' => array( + 0 => $this->renderStepOne($carrier), + 1 => $this->renderStepThree($carrier), + 2 => $this->renderStepFour($carrier), + 3 => $this->renderStepFive($carrier), + )), + 'labels' => array('next' => $this->l('Next'), 'previous' => $this->l('Previous'), 'finish' => $this->l('Finish')) + ); + + + if (Shop::isFeatureActive()) + array_splice($this->tpl_view_vars['wizard_contents']['contents'], 1, 0, array(0 => $this->renderStepTwo($carrier))); + + $this->context->smarty->assign(array( + 'carrier_logo' => (Validate::isLoadedObject($carrier) && file_exists(_PS_SHIP_IMG_DIR_.$carrier->id.'.jpg') ? _THEME_SHIP_DIR_.$carrier->id.'.jpg' : false) + )); + $this->content .= $this->createTemplate('logo.tpl')->fetch(); + $this->addjQueryPlugin(array('ajaxfileupload')); + + return parent::renderView(); + } + + public function initToolbarTitle() + { + $bread_extended = array_unique($this->breadcrumbs); + + if (Tools::getValue('id_carrier')) + $bread_extended[1] = $this->l('Edit'); + else + $bread_extended[1] = $this->l('Add new'); + + $this->toolbar_title = $bread_extended; + } + + public function initToolbar() + { + parent::initToolbar(); + $this->toolbar_btn['back']['href'] = $this->context->link->getAdminLink('AdminCarriers'); + } + + public function renderStepOne($carrier) + { + $this->fields_form = array( + 'form' => array( + 'id_form' => 'step_carrier_general', + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Carrier name:'), + 'name' => 'name', + 'size' => 25, + 'required' => true, + 'hint' => sprintf($this->l('Allowed characters: letters, spaces and %s'), '().-'), + 'desc' => array( + $this->l('Carrier name displayed during checkout'), + $this->l('For in-store pickup, enter 0 to replace the carrier name with your shop name.') + ) + ), + array( + 'type' => 'text', + 'label' => $this->l('Transit time:'), + 'name' => 'delay', + 'lang' => true, + 'required' => true, + 'size' => 41, + 'maxlength' => 128, + 'desc' => $this->l('Estimated delivery time will be displayed during checkout.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Speed grade:'), + 'name' => 'grade', + 'required' => false, + 'size' => 1, + 'desc' => $this->l('Enter "0" for a longest shipping delay, or "9" for the shortest shipping delay.') + ), + array( + 'type' => 'logo', + 'label' => $this->l('Logo:'), + 'name' => 'logo', + ), + array( + 'type' => 'text', + 'label' => $this->l('Tracking URL:'), + 'name' => 'url', + 'size' => 40, + 'desc' => $this->l('Delivery tracking URL: Type \'@\' where the tracking number should appear. It will then be automatically replaced by the tracking number.') + ), + )), + ); + + $tpl_vars = array('max_image_size' => (int)Configuration::get('PS_PRODUCT_PICTURE_MAX_SIZE') / 1024 / 1024); + $fields_value = $this->getStepOneFieldsValues($carrier); + return $this->renderGenericForm(array('form' => $this->fields_form), $fields_value, $tpl_vars); + } + + public function renderStepTwo($carrier) + { + $this->fields_form = array( + 'form' => array( + 'id_form' => 'step_carrier_shops', + 'input' => array( + array( + 'type' => 'shop', + 'label' => $this->l('Shop association:'), + 'name' => 'checkBoxShopAsso', + ), + )) + ); + $fields_value = $this->getStepTwoFieldsValues($carrier); + return $this->renderGenericForm(array('form' => $this->fields_form), $fields_value); + } + + public function renderStepThree($carrier) + { + $this->fields_form = array( + 'form' => array( + 'id_form' => 'step_carrier_ranges', + 'input' => array( + array( + 'type' => 'radio', + 'label' => $this->l('Shipping and handling:'), + 'name' => 'shipping_handling', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'shipping_handling_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'shipping_handling_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'desc' => $this->l('Include the shipping and handling costs in the carrier price.') + ), + array( + 'type' => 'radio', + 'label' => $this->l('Apply shipping cost:'), + 'name' => 'is_free', + 'required' => false, + 'class' => 't', + 'values' => array( + array( + 'id' => 'is_free_off', + 'value' => 0, + 'label' => ''.$this->l('Yes').'' + ), + array( + 'id' => 'is_free_on', + 'value' => 1, + 'label' => ''.$this->l('No').'' + ) + ), + 'desc' => $this->l('Apply both regular shipping cost and product-specific shipping costs.') + ), + array( + 'type' => 'radio', + 'label' => $this->l('Billing:'), + 'name' => 'shipping_method', + 'required' => false, + 'class' => 't', + 'br' => true, + 'values' => array( + array( + 'id' => 'billing_price', + 'value' => Carrier::SHIPPING_METHOD_PRICE, + 'label' => $this->l('According to total price') + ), + array( + 'id' => 'billing_weight', + 'value' => Carrier::SHIPPING_METHOD_WEIGHT, + 'label' => $this->l('According to total weight') + ) + ) + ), + array( + 'type' => 'select', + 'label' => $this->l('Tax:'), + 'name' => 'id_tax_rules_group', + 'options' => array( + 'query' => TaxRulesGroup::getTaxRulesGroups(true), + 'id' => 'id_tax_rules_group', + 'name' => 'name', + 'default' => array( + 'label' => $this->l('No Tax'), + 'value' => 0 + ) + ) + ), + array( + 'type' => 'zone', + 'name' => 'zones' + ), + array( + 'type' => 'select', + 'label' => $this->l('Out-of-range behavior:'), + 'name' => 'range_behavior', + 'options' => array( + 'query' => array( + array( + 'id' => 0, + 'name' => $this->l('Apply the cost of the highest defined range') + ), + array( + 'id' => 1, + 'name' => $this->l('Disable carrier') + ) + ), + 'id' => 'id', + 'name' => 'name' + ), + 'desc' => $this->l('Out-of-range behavior occurs when no defined range matches the customer\'s cart (e.g. when the weight of the cart is greater than the highest weight limit defined by the weight ranges)') + ) + ), + + )); + + $tpl_vars = array(); + $tpl_vars['PS_WEIGHT_UNIT'] = Configuration::get('PS_WEIGHT_UNIT'); + $currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); + $tpl_vars['currency_sign'] = $currency->sign; + + $fields_value = $this->getStepThreeFieldsValues($carrier); + + $this->getTplRangesVarsAndValues($carrier, $tpl_vars, $fields_value); + return $this->renderGenericForm(array('form' => $this->fields_form), $fields_value, $tpl_vars); + } + + public function renderStepFour($carrier) + { + $this->fields_form = array( + 'form' => array( + 'id_form' => 'step_carrier_conf', + 'input' => array( + array( + 'type' => 'text', + 'label' => sprintf($this->l('Maximum package height (%s):'), Configuration::get('PS_DIMENSION_UNIT')), + 'name' => 'max_height', + 'required' => false, + 'size' => 10, + 'desc' => $this->l('Maximum height managed by this carrier. Set the value to "0", or leave this field blank to ignore.').' '.$this->l('The value must be an integer +.') + ), + array( + 'type' => 'text', + 'label' => sprintf($this->l('Maximum package width (%s):'), Configuration::get('PS_DIMENSION_UNIT')), + 'name' => 'max_width', + 'required' => false, + 'size' => 10, + 'desc' => $this->l('Maximum width managed by this carrier. Set the value to "0", or leave this field blank to ignore.').' '.$this->l('The value must be an integer +.') + ), + array( + 'type' => 'text', + 'label' => sprintf($this->l('Maximum package depth (%s):'), Configuration::get('PS_DIMENSION_UNIT')), + 'name' => 'max_depth', + 'required' => false, + 'size' => 10, + 'desc' => $this->l('Maximum depth managed by this carrier. Set the value to "0", or leave this field blank to ignore.').' '.$this->l('The value must be an integer +.') + ), + array( + 'type' => 'text', + 'label' => sprintf($this->l('Maximum package weight (%s):'), Configuration::get('PS_WEIGHT_UNIT')), + 'name' => 'max_weight', + 'required' => false, + 'size' => 10, + 'desc' => $this->l('Maximum weight managed by this carrier. Set the value to "0", or leave this field blank to ignore.') + ), + array( + 'type' => 'group', + 'label' => $this->l('Group access:'), + 'name' => 'groupBox', + 'values' => Group::getGroups(Context::getContext()->language->id), + 'desc' => $this->l('Mark the groups that are allowed access to this carrier.') + ) + ) + )); + + $fields_value = $this->getStepFourFieldsValues($carrier); + + // Added values of object Group + $carrier_groups = $carrier->getGroups(); + $carrier_groups_ids = array(); + if (is_array($carrier_groups)) + foreach ($carrier_groups as $carrier_group) + $carrier_groups_ids[] = $carrier_group['id_group']; + + $groups = Group::getGroups($this->context->language->id); + + foreach ($groups as $group) + $fields_value['groupBox_'.$group['id_group']] = Tools::getValue('groupBox_'.$group['id_group'], (in_array($group['id_group'], $carrier_groups_ids) || empty($carrier_groups_ids) && !$carrier->id)); + + return $this->renderGenericForm(array('form' => $this->fields_form), $fields_value); + } + + public function renderStepFive($carrier) + { + $this->fields_form = array( + 'form' => array( + 'id_form' => 'step_carrier_summary', + 'input' => array( + array( + 'type' => 'radio', + 'label' => $this->l('Status:'), + 'name' => 'active', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'desc' => $this->l('Enable the carrier in the Front Office') + ) + ) + )); + + $template = $this->createTemplate('controllers/carrier_wizard/summary.tpl'); + + $fields_value = $this->getStepFiveFieldsValues($carrier); + + $active_form = $this->renderGenericForm(array('form' => $this->fields_form), $fields_value); + + $active_form = str_replace(array('
        ', '
        '), '', $active_form); + + $template->assign('active_form', $active_form); + + return $template->fetch('controllers/carrier_wizard/summary.tpl'); + } + + protected function getTplRangesVarsAndValues($carrier, &$tpl_vars, &$fields_value) + { + $tpl_vars['zones'] = Zone::getZones(false); + $carrier_zones = $carrier->getZones(); + $carrier_zones_ids = array(); + if (is_array($carrier_zones)) + foreach ($carrier_zones as $carrier_zone) + $carrier_zones_ids[] = $carrier_zone['id_zone']; + + $range_table = $carrier->getRangeTable(); + $shipping_method = $carrier->getShippingMethod(); + + $zones = Zone::getZones(false); + foreach ($zones as $zone) + $fields_value['zones'][$zone['id_zone']] = Tools::getValue('zone_'.$zone['id_zone'], (in_array($zone['id_zone'], $carrier_zones_ids))); + + if ($shipping_method == Carrier::SHIPPING_METHOD_FREE) + { + $range_obj = $carrier->getRangeObject($carrier->shipping_method); + $price_by_range = array(); + } + else + { + $range_obj = $carrier->getRangeObject(); + $price_by_range = Carrier::getDeliveryPriceByRanges($range_table, (int)$carrier->id); + } + + foreach ($price_by_range as $price) + $tpl_vars['price_by_range'][$price['id_'.$range_table]][$price['id_zone']] = $price['price']; + + $tmp_range = $range_obj->getRanges((int)$carrier->id); + $tpl_vars['ranges'] = array(); + if ($shipping_method != Carrier::SHIPPING_METHOD_FREE) + foreach ($tmp_range as $id => $range) + { + $tpl_vars['ranges'][$range['id_'.$range_table]] = $range; + $tpl_vars['ranges'][$range['id_'.$range_table]]['id_range'] = $range['id_'.$range_table]; + } + + // init blank range + if (!count($tpl_vars['ranges'])) + $tpl_vars['ranges'][] = array('id_range' => 0, 'delimiter1' => 0, 'delimiter2' => 0); + } + + public function renderGenericForm($fields_form, $fields_value, $tpl_vars = array()) + { + $helper = new HelperForm(); + $helper->show_toolbar = false; + $helper->table = $this->table; + $lang = new Language((int)Configuration::get('PS_LANG_DEFAULT')); + $helper->default_form_language = $lang->id; + $helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') ? Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') : 0; + $this->fields_form = array(); + $helper->id = (int)Tools::getValue('id_carrier'); + $helper->identifier = $this->identifier; + $helper->tpl_vars = array_merge(array( + 'fields_value' => $fields_value, + 'languages' => $this->getLanguages(), + 'id_language' => $this->context->language->id + ), $tpl_vars); + $helper->override_folder = 'carrier_wizard/'; + + return $helper->generateForm($fields_form); + } + + public function getStepOneFieldsValues($carrier) + { + return array( + 'id_carrier' => $this->getFieldValue($carrier, 'id_carrier'), + 'name' => $this->getFieldValue($carrier, 'name'), + 'delay' => $this->getFieldValue($carrier, 'delay'), + 'grade' => $this->getFieldValue($carrier, 'grade'), + 'url' => $this->getFieldValue($carrier, 'url'), + ); + } + + public function getStepTwoFieldsValues($carrier) + { + return array('shop' => $this->getFieldValue($carrier, 'shop')); + + } + + public function getStepThreeFieldsValues($carrier) + { + $id_tax_rules_group = (is_object($this->object) && !$this->object->id) ? Carrier::getIdTaxRulesGroupMostUsed() : $this->getFieldValue($carrier, 'id_tax_rules_group'); + + $shipping_handling = (is_object($this->object) && !$this->object->id) ? 0 : $this->getFieldValue($carrier, 'shipping_handling'); + + return array( + 'is_free' => $this->getFieldValue($carrier, 'is_free'), + 'id_tax_rules_group' => (int)$id_tax_rules_group, + 'shipping_handling' => $shipping_handling, + 'shipping_method' => $this->getFieldValue($carrier, 'shipping_method'), + 'range_behavior' => $this->getFieldValue($carrier, 'range_behavior'), + 'zones' => $this->getFieldValue($carrier, 'zones'), + ); + } + + public function getStepFourFieldsValues($carrier) + { + return array( + 'range_behavior' => $this->getFieldValue($carrier, 'range_behavior'), + 'max_height' => $this->getFieldValue($carrier, 'max_height'), + 'max_width' => $this->getFieldValue($carrier, 'max_width'), + 'max_depth' => $this->getFieldValue($carrier, 'max_depth'), + 'max_weight' => $this->getFieldValue($carrier, 'max_weight'), + 'group' => $this->getFieldValue($carrier, 'group'), + ); + } + + public function getStepFiveFieldsValues($carrier) + { + return array('active' => $this->getFieldValue($carrier, 'active')); + } + + public function ajaxProcessChangeRanges() + { + if ((Validate::isLoadedObject($this->object) && !$this->tabAccess['edit']) || !$this->tabAccess['add']) + { + $this->errors[] = Tools::displayError('You do not have permission to use this wizard.'); + return; + } + if ((!(int)$shipping_method = Tools::getValue('shipping_method')) || !in_array($shipping_method, array(Carrier::SHIPPING_METHOD_PRICE, Carrier::SHIPPING_METHOD_WEIGHT))) + return ; + + $carrier = $this->loadObject(true); + $carrier->shipping_method = $shipping_method; + + $tpl_vars = array(); + $fields_value = $this->getStepThreeFieldsValues($carrier); + $this->getTplRangesVarsAndValues($carrier, $tpl_vars, $fields_value); + $template = $this->createTemplate('controllers/carrier_wizard/helpers/form/form_ranges.tpl'); + $template->assign($tpl_vars); + $template->assign('change_ranges', 1); + + $template->assign('fields_value', $fields_value); + $template->assign('input', array('type' => 'zone', 'name' => 'zones' )); + + $currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); + $template->assign('currency_sign', $currency->sign); + $template->assign('PS_WEIGHT_UNIT', Configuration::get('PS_WEIGHT_UNIT')); + + die($template->fetch()); + } + + public function ajaxProcessValidateStep() + { + $step_number = (int)Tools::getValue('step_number'); + $return = array('has_error' => false); + + if (!$this->tabAccess['edit']) + $this->errors[] = Tools::displayError('You do not have permission to use this wizard.'); + else + { + if (Shop::isFeatureActive() && $step_number == 2) + { + if (!Tools::getValue('checkBoxShopAsso_carrier')) + { + $return['has_error'] = true; + $return['errors'][] = $this->l('You must choose at least one shop or group shop.'); + } + } + else + $this->validateRules('AdminCarrierWizardControllerCore'); + } + + if (count($this->errors)) + { + $return['has_error'] = true; + $return['errors'] = $this->errors; + } + die(Tools::jsonEncode($return)); + } + + public function processRanges($id_carrier) + { + if (!$this->tabAccess['edit'] || !$this->tabAccess['add']) + { + $this->errors[] = Tools::displayError('You do not have permission to use this wizard.'); + return; + } + + $carrier = new Carrier((int)$id_carrier); + if (!Validate::isLoadedObject($carrier)) + return false; + + $range_inf = Tools::getValue('range_inf'); + $range_sup = Tools::getValue('range_sup'); + $range_type = Tools::getValue('shipping_method'); + + $fees = Tools::getValue('fees'); + + $carrier->deleteDeliveryPrice($carrier->getRangeTable()); + if ($range_type != Carrier::SHIPPING_METHOD_FREE) + { + foreach ($range_inf as $key => $delimiter1) + { + if (!isset($range_sup[$key])) + continue; + $add_range = true; + if ($range_type == Carrier::SHIPPING_METHOD_WEIGHT) + { + if (!RangeWeight::rangeExist((int)$carrier->id, (float)$delimiter1, (float)$range_sup[$key])) + $range = new RangeWeight(); + else + { + $range = new RangeWeight((int)$key); + $add_range = false; + } + } + + if ($range_type == Carrier::SHIPPING_METHOD_PRICE) + { + if (!RangePrice::rangeExist((int)$carrier->id, (float)$delimiter1, (float)$range_sup[$key])) + $range = new RangePrice(); + else + { + $range = new RangePrice((int)$key); + $add_range = false; + } + } + if ($add_range) + { + $range->id_carrier = (int)$carrier->id; + $range->delimiter1 = (float)$delimiter1; + $range->delimiter2 = (float)$range_sup[$key]; + $range->save(); + } + + if (!Validate::isLoadedObject($range)) + return false; + $price_list = array(); + if (is_array($fees) && count($fees)) + { + foreach ($fees as $id_zone => $fee) + $price_list[] = array( + 'id_range_price' => ($range_type == Carrier::SHIPPING_METHOD_PRICE ? (int)$range->id : null), + 'id_range_weight' => ($range_type == Carrier::SHIPPING_METHOD_WEIGHT ? (int)$range->id : null), + 'id_carrier' => (int)$carrier->id, + 'id_zone' => (int)$id_zone, + 'price' => (float)$fee[$key] + ); + } + + if (count($price_list) && !$carrier->addDeliveryPrice($price_list, true)) + return false; + } + } + return true; + } + + public function ajaxProcessUploadLogo() + { + if (!$this->tabAccess['edit']) + die(''); + + $allowedExtensions = array('jpeg', 'gif', 'png', 'jpg'); + + $logo = (isset($_FILES['carrier_logo_input']) ? $_FILES['carrier_logo_input'] : false); + if ($logo && !empty($logo['tmp_name']) && $logo['tmp_name'] != 'none' + && (!isset($logo['error']) || !$logo['error']) + && preg_match('/\.(jpe?g|gif|png)$/', $logo['name']) + && is_uploaded_file($logo['tmp_name']) + && ImageManager::isRealImage($logo['tmp_name'], $logo['type'])) + { + $file = $logo['tmp_name']; + do $tmp_name = uniqid().'.jpg'; + while (file_exists(_PS_TMP_IMG_DIR_.$tmp_name)); + if (!ImageManager::resize($file, _PS_TMP_IMG_DIR_.$tmp_name)) + die(''); + @unlink($file); + die(''); + } + else + die(''); + } + + public function ajaxProcessFinishStep() + { + $return = array('has_error' => false); + + if (!$this->tabAccess['edit']) + $return = array( + 'has_error' => true, + $return['errors'][] = Tools::displayError('You do not have permission to use this wizard.') + ); + else + { + if ($id_carrier = Tools::getValue('id_carrier')) + { + $current_carrier = new Carrier((int)$id_carrier); + // if update we duplicate current Carrier + $new_carrier = $current_carrier->duplicateObject(); + if (Validate::isLoadedObject($new_carrier)) + { + // Set flag deteled to true for historization + $current_carrier->deleted = true; + $current_carrier->update(); + + // Fill the new carrier object + $this->copyFromPost($new_carrier, $this->table); + $new_carrier->position = $current_carrier->position; + $new_carrier->update(); + + $this->updateAssoShop((int)$new_carrier->id); + $this->duplicateLogo((int)$new_carrier->id, (int)$current_carrier->id); + $this->changeGroups((int)$new_carrier->id); + // Call of hooks + Hook::exec('actionCarrierUpdate', array( + 'id_carrier' => (int)$current_carrier->id, + 'carrier' => $new_carrier + )); + $this->postImage($new_carrier->id); + $this->changeZones($new_carrier->id); + $new_carrier->setTaxRulesGroup((int)Tools::getValue('id_tax_rules_group')); + $carrier = $new_carrier; + } + } + else + { + $carrier = new Carrier(); + $this->copyFromPost($carrier, $this->table); + if (!$carrier->add()) + { + $return['has_error'] = true; + $return['errors'][] = $this->l('An error occurred while saving this carrier.'); + } + } + + if ($carrier->is_free) + { + //if carrier is free delete shipping cost + $carrier->deleteDeliveryPrice('range_weight'); + $carrier->deleteDeliveryPrice('range_price'); + } + + if (Validate::isLoadedObject($carrier)) + { + if (!$this->changeGroups((int)$carrier->id)) + { + $return['has_error'] = true; + $return['errors'][] = $this->l('An error occurred while saving carrier groups.'); + } + + if (!$this->changeZones((int)$carrier->id)) + { + $return['has_error'] = true; + $return['errors'][] = $this->l('An error occurred while saving carrier zones.'); + } + + if (!$carrier->is_free) + if (!$this->processRanges((int)$carrier->id)) + { + $return['has_error'] = true; + $return['errors'][] = $this->l('An error occurred while saving carrier ranges.'); + } + + if (Shop::isFeatureActive() && !$this->updateAssoShop((int)$carrier->id)) + { + $return['has_error'] = true; + $return['errors'][] = $this->l('An error occurred while saving associations of shops.'); + } + + if (!$carrier->setTaxRulesGroup((int)Tools::getValue('id_tax_rules_group'))) + { + $return['has_error'] = true; + $return['errors'][] = $this->l('An error occurred while saving the tax rules group.'); + } + + if (Tools::getValue('logo')) + { + if (Tools::getValue('logo') == 'null' && file_exists(_PS_SHIP_IMG_DIR_.$carrier->id.'.jpg')) + unlink(_PS_SHIP_IMG_DIR_.$carrier->id.'.jpg'); + else + { + $logo = basename(Tools::getValue('logo')); + if (!file_exists(_PS_TMP_IMG_DIR_.$logo) || !copy(_PS_TMP_IMG_DIR_.$logo, _PS_SHIP_IMG_DIR_.$carrier->id.'.jpg')) + { + $return['has_error'] = true; + $return['errors'][] = $this->l('An error occurred while saving carrier logo.'); + } + } + } + $return['id_carrier'] = $carrier->id; + } + } + die(Tools::jsonEncode($return)); + } + + protected function changeGroups($id_carrier, $delete = true) + { + $carrier = new Carrier((int)$id_carrier); + if (!Validate::isLoadedObject($carrier)) + return false; + + return $carrier->setGroups(Tools::getValue('groupBox')); + } + + public function changeZones($id) + { + $return = true; + $carrier = new Carrier($id); + if (!Validate::isLoadedObject($carrier)) + die (Tools::displayError('The object cannot be loaded.')); + $zones = Zone::getZones(false); + foreach ($zones as $zone) + if (count($carrier->getZone($zone['id_zone']))) + { + if (!isset($_POST['zone_'.$zone['id_zone']]) || !$_POST['zone_'.$zone['id_zone']]) + $return &= $carrier->deleteZone((int)$zone['id_zone']); + } + else + if (isset($_POST['zone_'.$zone['id_zone']]) && $_POST['zone_'.$zone['id_zone']]) + $return &= $carrier->addZone((int)$zone['id_zone']); + + return $return; + } + + public static function getValidationRules() + { + $step_number = Tools::getValue('step_number'); + + if ($step_number == 4 && !Shop::isFeatureActive() || $step_number == 5 && Shop::isFeatureActive()) + return array(); + + $step_fields = array( + 1 => array('name', 'delay', 'grade', 'url'), + 2 => array('is_free', 'id_tax_rules_group', 'shipping_handling', 'shipping_method', 'range_behavior'), + 3 => array('range_behavior', 'max_height', 'max_width', 'max_depth', 'max_weight'), + 4 => array(), + ); + + if (Shop::isFeatureActive()) + { + $multistore_field = array(array('shop')); + array_splice($step_fields, 1, 0, $multistore_field); + } + + $rules = Carrier::getValidationRules('Carrier'); + + foreach ($rules as $key_r => $rule) + foreach ($rule as $key_f => $field) + { + if (in_array($key_r, array('required', 'requiredLang'))) + { + if(!in_array($field, $step_fields[$step_number])) + unset($rules[$key_r][$key_f]); + } + else if(!in_array($key_f, $step_fields[$step_number])) + unset($rules[$key_r][$key_f]); + } + return $rules; + } + + public static function displayFieldName($field) + { + return $field; + } + + public function duplicateLogo($new_id, $old_id) + { + $old_logo = _PS_SHIP_IMG_DIR_.'/'.(int)$old_id.'.jpg'; + if (file_exists($old_logo)) + copy($old_logo, _PS_SHIP_IMG_DIR_.'/'.(int)$new_id.'.jpg'); + + $old_tmp_logo = _PS_TMP_IMG_DIR_.'/carrier_mini_'.(int)$old_id.'.jpg'; + if (file_exists($old_tmp_logo)) + { + if (!isset($_FILES['logo'])) + copy($old_tmp_logo, _PS_TMP_IMG_DIR_.'/carrier_mini_'.$new_id.'.jpg'); + unlink($old_tmp_logo); + } + } +} diff --git a/controllers/admin/AdminCarriersController.php b/controllers/admin/AdminCarriersController.php index 84a51b04d..53a7efa29 100644 --- a/controllers/admin/AdminCarriersController.php +++ b/controllers/admin/AdminCarriersController.php @@ -87,11 +87,7 @@ class AdminCarriersControllerCore extends AdminController 'is_free' => array( 'title' => $this->l('Free Shipping'), 'align' => 'center', - 'icon' => array( - 0 => 'disabled.gif', - 1 => 'enabled.gif', - 'default' => 'disabled.gif' - ), + 'active' => 'isFree', 'type' => 'bool', 'orderby' => false, 'width' => 150 @@ -105,84 +101,19 @@ class AdminCarriersControllerCore extends AdminController ) ); - $carrier_default_sort = array( - array('value' => Carrier::SORT_BY_PRICE, 'name' => $this->l('Price')), - array('value' => Carrier::SORT_BY_POSITION, 'name' => $this->l('Position')) - ); - - $carrier_default_order = array( - array('value' => Carrier::SORT_BY_ASC, 'name' => $this->l('Ascending')), - array('value' => Carrier::SORT_BY_DESC, 'name' => $this->l('Descending')) - ); - - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Carrier options'), - 'fields' => array( - 'PS_CARRIER_DEFAULT' => array( - 'title' => $this->l('Default carrier:'), - 'desc' => $this->l('Your shop\'s default carrier'), - 'cast' => 'intval', - 'type' => 'select', - 'identifier' => 'id_carrier', - 'list' => array_merge( - array( - -1 => array('id_carrier' => -1, 'name' => $this->l('Best price')), - -2 => array('id_carrier' => -2, 'name' => $this->l('Best grade')) - ), - Carrier::getCarriers((int)Configuration::get('PS_LANG_DEFAULT'), true, false, false, null, Carrier::ALL_CARRIERS)) - ), - 'PS_CARRIER_DEFAULT_SORT' => array( - 'title' => $this->l('Sort by:'), - 'desc' => $this->l('This will only be visible in the Front Office'), - 'cast' => 'intval', - 'type' => 'select', - 'identifier' => 'value', - 'list' => $carrier_default_sort - ), - 'PS_CARRIER_DEFAULT_ORDER' => array( - 'title' => $this->l('Order by:'), - 'desc' => $this->l('This will only be visible in the Front Office'), - 'cast' => 'intval', - 'type' => 'select', - 'identifier' => 'value', - 'list' => $carrier_default_order - ), - ), - 'submit' => array() - ) - ); - parent::__construct(); } + public function initToolbar() + { + parent::initToolbar(); + + if (isset($this->toolbar_btn['new'])) + $this->toolbar_btn['new']['href'] = $this->context->link->getAdminLink('AdminCarrierWizard'); + } + public function renderList() { - $this->displayInformation( - ' '.$this->l('How do I create a new carrier?').' -
        -
          -
        • '.$this->l('Click "Add New."').'
        • -
        • '.$this->l('Fill in the fields and click "Save."').'
        • -
        • '. - $this->l('You need to set a price range -- or weight range -- for which the new carrier will be available.').' '. - $this->l('Under the "Shipping" menu, click either "Price ranges" or "Weight ranges.".').' -
        • -
        • '.$this->l('Click "Add New."').'
        • -
        • '. - $this->l('Select the name of the carrier before defining the price or weight range.').' '. - $this->l('For example, the carrier can be made available for a weight range between 0 and 5lbs. Another carrier can have a range between 5 and 10lbs.').' -
        • -
        • '.$this->l('When you\'re done, click "Save."').'
        • -
        • '.$this->l('Click on the "Shipping" menu.').'
        • -
        • '. - $this->l('You need to set the fees that will be applied for this carrier.').' '. - $this->l('At the bottom on the page -- in the "Fees" section -- select the name of the carrier.').' -
        • -
        • '.$this->l('For each zone, enter a price and then click "Save."').'
        • -
        • '.$this->l('You\'re all set! The new carrier will now be displayed to customers.').'
        • -
        ' - ); $this->_select = 'b.*'; $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'carrier_lang` b ON a.id_carrier = b.id_carrier'.Shop::addSqlRestrictionOnLang('b').' LEFT JOIN `'._DB_PREFIX_.'carrier_tax_rules_group_shop` ctrgs ON (a.`id_carrier` = ctrgs.`id_carrier` @@ -539,7 +470,8 @@ class AdminCarriersControllerCore extends AdminController } parent::postProcess(); } - else if ((isset($_GET['status'.$this->table]) || isset($_GET['status'])) && Tools::getValue($this->identifier)) + /* +else if ((isset($_GET['status'.$this->table]) || isset($_GET['status'])) && Tools::getValue($this->identifier)) { if ($this->tabAccess['edit'] === '1') { @@ -551,13 +483,20 @@ class AdminCarriersControllerCore extends AdminController else $this->errors[] = Tools::displayError('You do not have permission to edit this.'); } +*/ + else if (isset($_GET['isFree'.$this->table])) + { + $this->processIsFree(); + } else { - if ((Tools::isSubmit('submitDel'.$this->table) && in_array(Configuration::get('PS_CARRIER_DEFAULT'), Tools::getValue('carrierBox'))) + /* + if ((Tools::isSubmit('submitDel'.$this->table) && in_array(Configuration::get('PS_CARRIER_DEFAULT'), Tools::getValue('carrierBox'))) || (isset($_GET['delete'.$this->table]) && Tools::getValue('id_carrier') == Configuration::get('PS_CARRIER_DEFAULT'))) $this->errors[] = $this->l('Please set another carrier as default before deleting this one.'); else { +*/ // if deletion : removes the carrier from the warehouse/carrier association if (Tools::isSubmit('delete'.$this->table)) { @@ -579,10 +518,21 @@ class AdminCarriersControllerCore extends AdminController } parent::postProcess(); Carrier::cleanPositions(); - } + //} } } + public function processIsFree() + { + $carrier = new Carrier($this->id_object); + if (!Validate::isLoadedObject($carrier)) + $this->errors[] = Tools::displayError('An error occurred while updating carrier information.'); + $carrier->is_free = $carrier->is_free ? 0 : 1; + if (!$carrier->update()) + $this->errors[] = Tools::displayError('An error occurred while updating carrier information.'); + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } + /** * Overload the property $fields_value * @@ -696,6 +646,22 @@ class AdminCarriersControllerCore extends AdminController } } + public function displayEditLink($token = null, $id, $name = null) + { + if ($this->tabAccess['edit'] == 1) + return ''; + else + return; + } + + public function displayDeleteLink($token = null, $id, $name = null) + { + if ($this->tabAccess['delete'] == 1) + return ''; + else + return; + } + } diff --git a/controllers/admin/AdminCartRulesController.php b/controllers/admin/AdminCartRulesController.php index 3cae2ec55..9a0fddeb8 100644 --- a/controllers/admin/AdminCartRulesController.php +++ b/controllers/admin/AdminCartRulesController.php @@ -31,8 +31,8 @@ class AdminCartRulesControllerCore extends AdminController $this->table = 'cart_rule'; $this->className = 'CartRule'; $this->lang = true; - $this->addRowAction('delete'); $this->addRowAction('edit'); + $this->addRowAction('delete'); $this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?'))); $this->fields_list = array( diff --git a/controllers/admin/AdminCartsController.php b/controllers/admin/AdminCartsController.php index fc0cf91ce..b4c5bf35c 100755 --- a/controllers/admin/AdminCartsController.php +++ b/controllers/admin/AdminCartsController.php @@ -209,7 +209,7 @@ class AdminCartsControllerCore extends AdminController if (!$this->context->cart->id_customer) $this->context->cart->id_customer = $id_customer; - if ($this->context->cart->OrderExists()) + if (Validate::isLoadedObject($this->context->cart) && $this->context->cart->OrderExists()) return; if (!$this->context->cart->secure_key) $this->context->cart->secure_key = $this->context->customer->secure_key; @@ -273,15 +273,15 @@ class AdminCartsControllerCore extends AdminController $field_id = 'customization_'.$id_product.'_'.$customization_field['id_customization_field']; if ($customization_field['type'] == Product::CUSTOMIZE_TEXTFIELD) { - if (!isset($_POST[$field_id]) || empty($_POST[$field_id])) + if (!Tools::getValue($field_id)) { if ($customization_field['required']) $errors[] = Tools::displayError('Please fill in all the required fields.'); continue; } - if (!Validate::isMessage($_POST[$field_id]) || empty($_POST[$field_id])) + if (!Validate::isMessage(Tools::getValue($field_id))) $errors[] = Tools::displayError('Invalid message'); - $this->context->cart->addTextFieldToProduct((int)$product->id, (int)$customization_field['id_customization_field'], Product::CUSTOMIZE_TEXTFIELD, $_POST[$field_id]); + $this->context->cart->addTextFieldToProduct((int)$product->id, (int)$customization_field['id_customization_field'], Product::CUSTOMIZE_TEXTFIELD, Tools::getValue($field_id)); } elseif ($customization_field['type'] == Product::CUSTOMIZE_FILE) { diff --git a/controllers/admin/AdminCategoriesController.php b/controllers/admin/AdminCategoriesController.php index e7a4ea71c..69db3dc17 100644 --- a/controllers/admin/AdminCategoriesController.php +++ b/controllers/admin/AdminCategoriesController.php @@ -38,6 +38,8 @@ class AdminCategoriesControllerCore extends AdminController /** @var boolean does the product have to be disable during the delete process */ public $disable_products = false; + private $original_filter = ''; + public function __construct() { $this->table = 'category'; @@ -130,7 +132,7 @@ class AdminCategoriesControllerCore extends AdminController $id_parent = $this->context->shop->id_category; $this->_select = 'sa.position position'; - $this->_filter .= ' AND `id_parent` = '.(int)$id_parent.' '; + $this->original_filter = $this->_filter .= ' AND `id_parent` = '.(int)$id_parent.' '; if (Shop::getContext() == Shop::CONTEXT_SHOP) $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'category_shop` sa ON (a.`id_category` = sa.`id_category` AND sa.id_shop = '.(int)$this->context->shop->id.') '; @@ -146,7 +148,7 @@ class AdminCategoriesControllerCore extends AdminController if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP) unset($this->fields_list['position']); // shop restriction : if category is not available for current shop, we redirect to the list from default category - if (!$this->_category->isAssociatedToShop() && Shop::getContext() == Shop::CONTEXT_SHOP) + if (Validate::isLoadedObject($this->_category) && !$this->_category->isAssociatedToShop() && Shop::getContext() == Shop::CONTEXT_SHOP) { $this->redirect_after = self::$currentIndex.'&id_category='.(int)$this->context->shop->getCategory().'&token='.$this->token; $this->redirect(); @@ -174,6 +176,9 @@ class AdminCategoriesControllerCore extends AdminController public function renderList() { + if (isset($this->_filter) && trim($this->_filter) == '') + $this->_filter = $this->original_filter; + $this->addRowAction('edit'); $this->addRowAction('delete'); $this->addRowAction('add'); @@ -208,8 +213,7 @@ class AdminCategoriesControllerCore extends AdminController public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) { - $alias = 'sa'; - parent::getList($id_lang, $alias.'.position', $order_way, $start, $limit, Context::getContext()->shop->id); + parent::getList($id_lang, $order_by, $order_way, $start, $limit, Context::getContext()->shop->id); // Check each row to see if there are combinations and get the correct action in consequence $nb_items = count($this->_list); @@ -391,30 +395,11 @@ class AdminCategoriesControllerCore extends AdminController 'use_context' => true, ) ), - array( - 'type' => 'radio', - 'label' => $this->l('Root Category:'), - 'name' => 'is_root_category', - 'required' => false, - 'is_bool' => true, - 'class' => 't', - 'values' => array( - array( - 'id' => 'is_root_on', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'is_root_off', - 'value' => 0, - 'label' => $this->l('No') - ) - ) - ), array( 'type' => 'textarea', 'label' => $this->l('Description:'), 'name' => 'description', + 'autoload_rte' => true, 'lang' => true, 'rows' => 10, 'cols' => 100, @@ -477,21 +462,46 @@ class AdminCategoriesControllerCore extends AdminController $this->tpl_form_vars['shared_category'] = Validate::isLoadedObject($obj) && $obj->hasMultishopEntries(); $this->tpl_form_vars['PS_ALLOW_ACCENTED_CHARS_URL'] = (int)Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL'); + + // Display this field only if multistore option is enabled + if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && Tools::isSubmit('add'.$this->table.'root')) + { + $this->fields_form['input'][] = array( + 'type' => 'radio', + 'label' => $this->l('Root Category:'), + 'name' => 'is_root_category', + 'required' => false, + 'is_bool' => true, + 'class' => 't', + 'values' => array( + array( + 'id' => 'is_root_on', + 'value' => 1, + 'label' => $this->l('Yes') + ), + array( + 'id' => 'is_root_off', + 'value' => 0, + 'label' => $this->l('No') + ) + ) + ); + unset($this->fields_form['input'][2],$this->fields_form['input'][3]); + } + // Display this field only if multistore option is enabled AND there are several stores configured if (Shop::isFeatureActive()) $this->fields_form['input'][] = array( 'type' => 'shop', 'label' => $this->l('Shop association:'), 'name' => 'checkBoxShopAsso', ); + // remove category tree and radio button "is_root_category" if this category has the root category as parent category to avoid any conflict if ($this->_category->id_parent == Category::getTopCategory()->id && Tools::isSubmit('updatecategory')) foreach ($this->fields_form['input'] as $k => $input) if (in_array($input['name'], array('id_parent', 'is_root_category'))) unset($this->fields_form['input'][$k]); - if (Tools::isSubmit('add'.$this->table.'root')) - unset($this->fields_form['input'][2],$this->fields_form['input'][3]); - if (!($obj = $this->loadObject(true))) return; @@ -515,6 +525,8 @@ class AdminCategoriesControllerCore extends AdminController foreach ($groups as $group) $this->fields_value['groupBox_'.$group['id_group']] = Tools::getValue('groupBox_'.$group['id_group'], (in_array($group['id_group'], $category_groups_ids))); + $this->fields_value['is_root_category'] = (bool)Tools::isSubmit('add'.$this->table.'root'); + return parent::renderForm(); } @@ -545,7 +557,7 @@ class AdminCategoriesControllerCore extends AdminController $id_parent = (int)Tools::getValue('id_parent'); // if true, we are in a root category creation - if (!$id_parent && !Tools::isSubmit('is_root_category')) + if (!$id_parent) { $_POST['is_root_category'] = $_POST['level_depth'] = 1; $_POST['id_parent'] = $id_parent = (int)Configuration::get('PS_ROOT_CATEGORY'); diff --git a/controllers/admin/AdminCmsController.php b/controllers/admin/AdminCmsController.php index 71497c56e..c46c61b88 100644 --- a/controllers/admin/AdminCmsController.php +++ b/controllers/admin/AdminCmsController.php @@ -220,11 +220,28 @@ class AdminCmsControllerCore extends AdminController $this->displayListFooter($token); } - public function postProcess() + /** + * Modifying initial getList method to display position feature (drag and drop) + */ + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) { if (Tools::isSubmit($this->table.'Orderby') || Tools::isSubmit($this->table.'Orderway')) $this->filter = true; + if ($order_by && $this->context->cookie->__get($this->table.'Orderby')) + $order_by = $this->context->cookie->__get($this->table.'Orderby'); + else + $order_by = 'position'; + + if (is_null($order_way)) + $order_way = Tools::getValue($this->table.'Orderway', 'ASC'); + + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + } + + public function postProcess() + { + if (Tools::isSubmit('viewcms') && ($id_cms = (int)Tools::getValue('id_cms')) && ($cms = new CMS($id_cms, $this->context->language->id)) && Validate::isLoadedObject($cms)) { $redir = $this->context->link->getCMSLink($cms); diff --git a/controllers/admin/AdminCountriesController.php b/controllers/admin/AdminCountriesController.php index 5a80556cd..fbf5f84df 100644 --- a/controllers/admin/AdminCountriesController.php +++ b/controllers/admin/AdminCountriesController.php @@ -145,7 +145,8 @@ class AdminCountriesControllerCore extends AdminController array('address2'), array('postcode', 'city'), array('Country:name'), - array('phone')); + array('phone'), + array('phone_mobile')); foreach ($default_layout_tab as $line) $default_layout .= implode(' ', $line)."\r\n"; @@ -251,6 +252,26 @@ class AdminCountriesControllerCore extends AdminController 'encoding_default_layout' => urlencode($default_layout), 'display_valid_fields' => $this->displayValidFields() ), + array( + 'type' => 'radio', + 'label' => $this->l('Address Standardization:'), + 'name' => 'standardization', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'standardization_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'standardization_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + ), array( 'type' => 'radio', 'label' => $this->l('Active:'), @@ -271,7 +292,7 @@ class AdminCountriesControllerCore extends AdminController ) ), 'desc' => $this->l('Display this country to your customers (the selected country will always be displayed in the Back Office)') - ), + ), array( 'type' => 'radio', 'label' => $this->l('Contains following states:'), @@ -330,6 +351,7 @@ class AdminCountriesControllerCore extends AdminController ) ) ) + ); if (Shop::isFeatureActive()) @@ -345,7 +367,10 @@ class AdminCountriesControllerCore extends AdminController 'title' => $this->l('Save '), 'class' => 'button' ); - + + if ($this->object->iso_code == 'US') + $this->object->standardization = Configuration::get('PS_TAASC'); + return parent::renderForm(); } @@ -362,6 +387,9 @@ class AdminCountriesControllerCore extends AdminController if (!is_null($id_country) && $id_country != Tools::getValue('id_'.$this->table)) $this->errors[] = Tools::displayError('This ISO code already exists.You cannot create two countries with the same ISO code.'); } + + if (Tools::isSubmit('standardization')) + Configuration::updateValue('PS_TAASC', (bool)Tools::getValue('standardization', false)); if (!count($this->errors)) $res = parent::postProcess(); @@ -406,10 +434,10 @@ class AdminCountriesControllerCore extends AdminController public function processStatus() { - if (Validate::isLoadedObject($object = $this->loadObject())) - Country::addModuleRestrictions(array(), array(array('id_country' => $object->id)), array()); - parent::processStatus(); + if (Validate::isLoadedObject($object = $this->loadObject()) && $object->active == 1) + return Country::addModuleRestrictions(array(), array(array('id_country' => $object->id)), array()); + return false; } public function processBulkStatusSelection($way) diff --git a/controllers/admin/AdminCurrenciesController.php b/controllers/admin/AdminCurrenciesController.php index e4a7a33b6..bf8690b64 100644 --- a/controllers/admin/AdminCurrenciesController.php +++ b/controllers/admin/AdminCurrenciesController.php @@ -38,7 +38,7 @@ class AdminCurrenciesControllerCore extends AdminController 'iso_code' => array('title' => $this->l('ISO code'), 'align' => 'center', 'width' => 80), 'iso_code_num' => array('title' => $this->l('ISO code number'), 'align' => 'center', 'width' => 120), 'sign' => array('title' => $this->l('Symbol'), 'width' => 20, 'align' => 'center', 'orderby' => false, 'search' => false), - 'conversion_rate' => array('title' => $this->l('Conversion rate'), 'type' => 'float', 'align' => 'center', 'width' => 130, 'search' => false), + 'conversion_rate' => array('title' => $this->l('Exchange rate'), 'type' => 'float', 'align' => 'center', 'width' => 130, 'search' => false, 'filter_key' => 'currency_shop!conversion_rate'), 'active' => array('title' => $this->l('Enabled'), 'width' => 25, 'align' => 'center', 'active' => 'status', 'type' => 'bool', 'orderby' => false), ); @@ -130,12 +130,12 @@ class AdminCurrenciesControllerCore extends AdminController ), array( 'type' => 'text', - 'label' => $this->l('Conversion rate:'), + 'label' => $this->l('Exchange rate:'), 'name' => 'conversion_rate', 'size' => 3, 'maxlength' => 11, 'required' => true, - 'desc' => $this->l('Conversion rates are calculated from one unit of your shop\'s default currency. For example, if the default currency is euros and your chosen currency is dollars, type "1.20"').' 1€ = $1.20', + 'desc' => $this->l('Exchange rates are calculated from one unit of your shop\'s default currency. For example, if the default currency is euros and your chosen currency is dollars, type "1.20"').' 1€ = $1.20', ), array( 'type' => 'select', diff --git a/controllers/admin/AdminCustomerPreferencesController.php b/controllers/admin/AdminCustomerPreferencesController.php index 07e7393dd..497f69314 100644 --- a/controllers/admin/AdminCustomerPreferencesController.php +++ b/controllers/admin/AdminCustomerPreferencesController.php @@ -72,6 +72,14 @@ class AdminCustomerPreferencesControllerCore extends AdminController 'cast' => 'intval', 'type' => 'bool' ), + 'PS_CUSTOMER_CREATION_EMAIL' => array( + 'title' => $this->l('Send an email after registration'), + 'desc' => $this->l('Send an email with summary account (email, password) after registration.'), + 'validation' => 'isUnsignedInt', + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), 'PS_PASSWD_TIME_FRONT' => array( 'title' => $this->l('Regenerate password'), 'desc' => $this->l('Minimum time required to regenerate a password.'), diff --git a/controllers/admin/AdminCustomerThreadsController.php b/controllers/admin/AdminCustomerThreadsController.php index b678cc1d4..3714a0a17 100644 --- a/controllers/admin/AdminCustomerThreadsController.php +++ b/controllers/admin/AdminCustomerThreadsController.php @@ -373,6 +373,9 @@ class AdminCustomerThreadsControllerCore extends AdminController if (Tools::isSubmit('submitReply')) { $ct = new CustomerThread($id_customer_thread); + + ShopUrl::cacheMainDomainForShop((int)$ct->id_shop); + $cm = new CustomerMessage(); $cm->id_employee = (int)$this->context->employee->id; $cm->id_customer_thread = $ct->id; @@ -398,10 +401,10 @@ class AdminCustomerThreadsControllerCore extends AdminController ), ); //#ct == id_customer_thread #tc == token of thread <== used in the synchronization imap - $contact = new Contact((int)$ct->id_contact); + $contact = new Contact((int)$ct->id_contact, (int)$ct->id_lang); if (Validate::isLoadedObject($contact)) { - $from_name = $contact->name; + $from_name = $contact->name[(int)$ct->id_lang]; $from_email = $contact->email; } else @@ -546,7 +549,7 @@ class AdminCustomerThreadsControllerCore extends AdminController $orders_ok[] = $order; $total_ok += $order['total_paid_real']; } - $orders[$key]['date_add'] = Tools::displayDate($order['date_add'], $this->context->language->id); + $orders[$key]['date_add'] = Tools::displayDate($order['date_add']); $orders[$key]['total_paid_real'] = Tools::displayPrice($order['total_paid_real'], new Currency((int)$order['id_currency'])); } } @@ -554,7 +557,7 @@ class AdminCustomerThreadsControllerCore extends AdminController $products = $customer->getBoughtProducts(); if ($products && count($products)) foreach ($products as $key => $product) - $products[$key]['date_add'] = Tools::displayDate($product['date_add'], $this->context->language->id, true); + $products[$key]['date_add'] = Tools::displayDate($product['date_add'], null, true); } foreach ($messages as $key => $message) @@ -592,7 +595,7 @@ class AdminCustomerThreadsControllerCore extends AdminController if (!empty($message['id_product']) && empty($message['employee_name'])) $id_order_product = Order::getIdOrderProduct((int)$message['id_customer'], (int)$message['id_product']); } - $message['date_add'] = Tools::displayDate($message['date_add'], $this->context->language->id, true); + $message['date_add'] = Tools::displayDate($message['date_add'], null, true); $message['user_agent'] = strip_tags($message['user_agent']); $message['message'] = preg_replace( '/(https?:\/\/[a-z0-9#%&_=\(\)\.\? \+\-@\/]{6,1000})([\s\n<])/Uui', @@ -802,4 +805,4 @@ class AdminCustomerThreadsControllerCore extends AdminController die('{"hasError" : false, "errors" : ["'.$str_errors.$str_error_delete.'"]}'); } } -} \ No newline at end of file +} diff --git a/controllers/admin/AdminCustomersController.php b/controllers/admin/AdminCustomersController.php index e395e725d..621e9b765 100644 --- a/controllers/admin/AdminCustomersController.php +++ b/controllers/admin/AdminCustomersController.php @@ -555,7 +555,7 @@ class AdminCustomersControllerCore extends AdminController $total_orders = count($orders); for ($i = 0; $i < $total_orders; $i++) { - $orders[$i]['date_add'] = Tools::displayDate($orders[$i]['date_add'], $this->context->language->id); + $orders[$i]['date_add'] = Tools::displayDate($orders[$i]['date_add']); $orders[$i]['total_paid_real_not_formated'] = $orders[$i]['total_paid_real']; $orders[$i]['total_paid_real'] = Tools::displayPrice($orders[$i]['total_paid_real'], new Currency((int)$orders[$i]['id_currency'])); } @@ -565,7 +565,7 @@ class AdminCustomersControllerCore extends AdminController for ($i = 0; $i < $total_messages; $i++) { $messages[$i]['message'] = substr(strip_tags(html_entity_decode($messages[$i]['message'], ENT_NOQUOTES, 'UTF-8')), 0, 75); - $messages[$i]['date_add'] = Tools::displayDate($messages[$i]['date_add'], $this->context->language->id, true); + $messages[$i]['date_add'] = Tools::displayDate($messages[$i]['date_add'], null, true); } $groups = $customer->getGroups(); @@ -598,7 +598,7 @@ class AdminCustomersControllerCore extends AdminController $products = $customer->getBoughtProducts(); $total_products = count($products); for ($i = 0; $i < $total_products; $i++) - $products[$i]['date_add'] = Tools::displayDate($products[$i]['date_add'], $this->default_form_language, true); + $products[$i]['date_add'] = Tools::displayDate($products[$i]['date_add'], null, true); $carts = Cart::getCustomerCarts($customer->id); $total_carts = count($carts); @@ -610,7 +610,7 @@ class AdminCustomersControllerCore extends AdminController $currency = new Currency((int)$carts[$i]['id_currency']); $carrier = new Carrier((int)$carts[$i]['id_carrier']); $carts[$i]['id_cart'] = sprintf('%06d', $carts[$i]['id_cart']); - $carts[$i]['date_add'] = Tools::displayDate($carts[$i]['date_add'], $this->default_form_language, true); + $carts[$i]['date_add'] = Tools::displayDate($carts[$i]['date_add'], null, true); $carts[$i]['total_price'] = Tools::displayPrice($summary['total_price'], $currency); $carts[$i]['name'] = $carrier->name; } @@ -646,7 +646,7 @@ class AdminCustomersControllerCore extends AdminController $total_connections = count($connections); for ($i = 0; $i < $total_connections; $i++) { - $connections[$i]['date_add'] = Tools::displayDate($connections[$i]['date_add'], $this->default_form_language, true); + $connections[$i]['date_add'] = Tools::displayDate($connections[$i]['date_add'],null , true); $connections[$i]['http_referer'] = $connections[$i]['http_referer'] ? preg_replace('/^www./', '', parse_url($connections[$i]['http_referer'], PHP_URL_HOST)) : $this->l('Direct link'); @@ -655,7 +655,7 @@ class AdminCustomersControllerCore extends AdminController $referrers = Referrer::getReferrers($customer->id); $total_referrers = count($referrers); for ($i = 0; $i < $total_referrers; $i++) - $referrers[$i]['date_add'] = Tools::displayDate($referrers[$i]['date_add'], $this->default_form_language, true); + $referrers[$i]['date_add'] = Tools::displayDate($referrers[$i]['date_add'],null , true); $shop = new Shop($customer->id_shop); $this->tpl_view_vars = array( @@ -663,14 +663,14 @@ class AdminCustomersControllerCore extends AdminController 'gender_image' => $gender_image, // General information of the customer - 'registration_date' => Tools::displayDate($customer->date_add, $this->default_form_language, true), + 'registration_date' => Tools::displayDate($customer->date_add,null , true), 'customer_stats' => $customer_stats, - 'last_visit' => Tools::displayDate($customer_stats['last_visit'], $this->default_form_language, true), + 'last_visit' => Tools::displayDate($customer_stats['last_visit'],null , true), 'count_better_customers' => $count_better_customers, 'shop_is_feature_active' => Shop::isFeatureActive(), 'name_shop' => $shop->name, - 'customer_birthday' => Tools::displayDate($customer->birthday, $this->default_form_language), - 'last_update' => Tools::displayDate($customer->date_upd, $this->default_form_language, true), + 'customer_birthday' => Tools::displayDate($customer->birthday), + 'last_update' => Tools::displayDate($customer->date_upd,null , true), 'customer_exists' => Customer::customerExists($customer->email), 'id_lang' => $customer->id_lang, 'customerLanguage' => (new Language($customer->id_lang)), diff --git a/controllers/admin/AdminEmailsController.php b/controllers/admin/AdminEmailsController.php index a0c26e124..1e1394b9f 100644 --- a/controllers/admin/AdminEmailsController.php +++ b/controllers/admin/AdminEmailsController.php @@ -165,6 +165,15 @@ class AdminEmailsControllerCore extends AdminController ); } + public function updateOptionPsMailPasswd($value) + { + if (Tools::getValue('PS_MAIL_PASSWD') == '' && Configuration::get('PS_MAIL_PASSWD')) + return true; + else + Configuration::updateValue('PS_MAIL_PASSWD', Tools::getValue('PS_MAIL_PASSWD')); + } + + /** * AdminController::initContent() override * @see AdminController::initContent() diff --git a/controllers/admin/AdminEmployeesController.php b/controllers/admin/AdminEmployeesController.php index ebdef6a4a..3d69d1a84 100644 --- a/controllers/admin/AdminEmployeesController.php +++ b/controllers/admin/AdminEmployeesController.php @@ -297,7 +297,7 @@ class AdminEmployeesControllerCore extends AdminController } $this->fields_form['input'][] = array( 'type' => 'select', - 'label' => $this->l('Profile:'), + 'label' => $this->l('Profile Permission:'), 'name' => 'id_profile', 'required' => true, 'options' => array( @@ -463,6 +463,16 @@ class AdminEmployeesControllerCore extends AdminController return parent::initContent(); } + protected function afterUpdate($object) + { + $res = parent::afterUpdate($object); + // Update cookie if needed + if (Tools::getValue('id_employee') == $this->context->employee->id && Tools::getValue('passwd') && $object->passwd != $this->context->employee->passwd) + $this->context->cookie->passwd = $this->context->employee->passwd = $object->passwd; + + return $res; + } + public function ajaxProcessGetTabByIdProfile() { $id_profile = Tools::getValue('id_profile'); diff --git a/controllers/admin/AdminFeaturesController.php b/controllers/admin/AdminFeaturesController.php index 8045e2c56..f63ceb83a 100644 --- a/controllers/admin/AdminFeaturesController.php +++ b/controllers/admin/AdminFeaturesController.php @@ -455,7 +455,7 @@ class AdminFeaturesControllerCore extends AdminController * AdminController::getList() override * @see AdminController::getList() */ - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = false, $id_lang_shop = false) { if ($this->table == 'feature_value') $this->_where .= ' AND a.custom = 0'; diff --git a/controllers/admin/AdminGroupsController.php b/controllers/admin/AdminGroupsController.php index a17063f88..3c8f26a79 100644 --- a/controllers/admin/AdminGroupsController.php +++ b/controllers/admin/AdminGroupsController.php @@ -312,36 +312,32 @@ class AdminGroupsControllerCore extends AdminController return parent::renderForm(); } - protected function formatCategoryDiscountList($id) + protected function formatCategoryDiscountList($id_group) { - $category = GroupReduction::getGroupReductions((int)$id, $this->context->language->id); + $group_reductions = GroupReduction::getGroupReductions((int)$id_group, $this->context->language->id); $category_reductions = array(); $category_reduction = Tools::getValue('category_reduction'); - foreach ($category as $category) + foreach ($group_reductions as $category) { if (is_array($category_reduction) && array_key_exists($category['id_category'], $category_reduction)) $category['reduction'] = $category_reduction[$category['id_category']]; - $tmp = array(); - $tmp['path'] = getPath(self::$currentIndex.'?tab=AdminCategories', (int)$category['id_category']); - $tmp['reduction'] = (float)$category['reduction'] * 100; - $tmp['id_category'] = (int)$category['id_category']; - $category_reductions[(int)$category['id_category']] = $tmp; + $category_reductions[(int)$category['id_category']] = array( + 'path' => getPath(self::$currentIndex.'?tab=AdminCategories', (int)$category['id_category']), + 'reduction' => (float)$category['reduction'] * 100, + 'id_category' => (int)$category['id_category'] + ); } if (is_array($category_reduction)) foreach ($category_reduction as $key => $val) - { if (!array_key_exists($key, $category_reductions)) - { - $tmp = array(); - $tmp['path'] = getPath(self::$currentIndex.'?tab=AdminCategories', $key); - $tmp['reduction'] = (float)$val * 100; - $tmp['id_category'] = (int)$key; - $category_reductions[(int)$category['id_category']] = $tmp; - } - } + $category_reductions[(int)$key] = array( + 'path' => getPath(self::$currentIndex.'?tab=AdminCategories', $key), + 'reduction' => (float)$val * 100, + 'id_category' => (int)$key + ); return $category_reductions; } diff --git a/controllers/admin/AdminHomeController.php b/controllers/admin/AdminHomeController.php index 2e9059150..45797273e 100644 --- a/controllers/admin/AdminHomeController.php +++ b/controllers/admin/AdminHomeController.php @@ -71,10 +71,15 @@ class AdminHomeControllerCore extends AdminController $indexRebuiltAfterUpdate = 2; $smartyOptimized = 0; - if (Configuration::get('PS_SMARTY_FORCE_COMPILE') == _PS_SMARTY_NO_COMPILE_) + // Forcing compilation is not good, really slow + if (in_array(Configuration::get('PS_SMARTY_FORCE_COMPILE'), array(_PS_SMARTY_CHECK_COMPILE_, _PS_SMARTY_NO_COMPILE_))) ++$smartyOptimized; + // Enabling cache is better if (Configuration::get('PS_SMARTY_CACHE')) ++$smartyOptimized; + // If the console is enabled, not good for production + if (Configuration::get('PS_SMARTY_CONSOLE') != _PS_SMARTY_CONSOLE_CLOSE_) + $smartyOptimized = 0; $cccOptimized = Configuration::get('PS_CSS_THEME_CACHE'); $cccOptimized += Configuration::get('PS_JS_THEME_CACHE'); @@ -170,10 +175,16 @@ class AdminHomeControllerCore extends AdminController $shop = Context::getContext()->shop; if ($_SERVER['HTTP_HOST'] != $shop->domain && $_SERVER['HTTP_HOST'] != $shop->domain_ssl && Tools::getValue('ajax') == false) - $this->displayWarning($this->l('You are currently connected under the following domain name:').' '.$_SERVER['HTTP_HOST'].'
        '. - $this->l('This is different from the main shop domain name set in the "Multistore" page under the "Advanced Parameters" menu:').' '.$shop->domain.'
        - '. - $this->l('Click here if you want to modify your main shop\'s domain name.').''); + { + $warning = $this->l('You are currently connected under the following domain name:').' '.$_SERVER['HTTP_HOST'].'
        '; + if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE')) + $warning .= sprintf($this->l('This is different from the shop domain name set in the Multistore settings: "%s".'), $shop->domain).' + '.preg_replace('@{link}(.*){/link}@', '$1', $this->l('If this is your main domain, please {link}change it now{/link}.')); + else + $warning .= $this->l('This is different from the domain name set in the "SEO & URLs" tab.').' + '.preg_replace('@{link}(.*){/link}@', '$1', $this->l('If this is your main domain, please {link}change it now{/link}.')); + $this->displayWarning($warning); + } } protected function getQuickLinks() @@ -377,12 +388,13 @@ class AdminHomeControllerCore extends AdminController $chart = new Chart(); $chart->getCurve(1)->setType('bars'); $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' - SELECT total_paid / conversion_rate as total_converted, left(invoice_date, 10) as invoice_date + SELECT SUM(total_paid / conversion_rate) as total_converted, left(invoice_date, 10) as invoice_date FROM '._DB_PREFIX_.'orders o WHERE valid = 1 AND total_paid > 0 AND invoice_date BETWEEN \''.date('Y-m-d', strtotime('-7 DAYS', time())).' 00:00:00\' AND \''.date('Y-m-d H:i:s').'\' - '.Shop::addSqlRestriction(Shop::SHARE_ORDER).' + '.Shop::addSqlRestriction(Shop::SHARE_ORDER).' + GROUP BY DATE(invoice_date) '); foreach ($result as $row) $chart->getCurve(1)->setPoint(strtotime($row['invoice_date'].' 02:00:00'), $row['total_converted']); @@ -474,7 +486,7 @@ class AdminHomeControllerCore extends AdminController $result = array(); $content = ''; - $protocol = Tools::usingSecureMode() ? 'https' : 'http'; + $protocol = Tools::getCurrentUrlProtocolPrefix(); $isoUser = Context::getContext()->language->iso_code; $isoCountry = Context::getContext()->country->iso_code; $stream_context = @stream_context_create(array('http' => array('method'=> 'GET', 'timeout' => 2))); @@ -482,17 +494,15 @@ class AdminHomeControllerCore extends AdminController // SCREENCAST $result['screencast'] = 'OK'; - // PREACTIVATION $result['partner_preactivation'] = $this->getBlockPartners(); // DISCOVER PRESTASHOP $result['discover_prestashop'] = '
        '.$this->getBlockDiscover().'
        '; - - $result['discover_prestashop'] .= '
        '; + $result['discover_prestashop'] .= '
        '; // SHOW TIPS OF THE DAY - $content = @file_get_contents($protocol.'://api.prestashop.com/partner/tipsoftheday/?protocol='.$protocol.'&iso_country='.$isoCountry.'&iso_lang='.Tools::strtolower($isoUser), false, $stream_context); + $content = Tools::file_get_contents($protocol.'api.prestashop.com/partner/tipsoftheday/?iso_country='.$isoCountry.'&iso_lang='.Tools::strtolower($isoUser), false, $stream_context); $content = explode('|', $content); if ($content[0] == 'OK' && Validate::isCleanHtml($content[1])) $result['discover_prestashop'] .= '
        '.$content[1].'
        '; @@ -518,7 +528,7 @@ class AdminHomeControllerCore extends AdminController { // Init var $return = ''; - $protocol = Tools::getShopProtocol(); + $protocol = Tools::getCurrentUrlProtocolPrefix(); $isoCountry = Context::getContext()->country->iso_code; $isoUser = Context::getContext()->language->iso_code; @@ -526,7 +536,7 @@ class AdminHomeControllerCore extends AdminController if (is_writable('../config/xml/') && (!file_exists('../config/xml/preactivation.xml') || (time() - filemtime('../config/xml/preactivation.xml')) > 86400)) { $stream_context = @stream_context_create(array('http' => array('method'=> 'GET', 'timeout' => AdminHomeController::TIPS_TIMEOUT))); - $content = Tools::file_get_contents('http://api.prestashop.com/partner/premium/get_partners.php?protocol='.$protocol.'&iso_country='.Tools::strtoupper($isoCountry).'&iso_lang='.Tools::strtolower($isoUser).'&ps_version='._PS_VERSION_.'&ps_creation='._PS_CREATION_DATE_.'&host='.urlencode($_SERVER['HTTP_HOST']).'&email='.urlencode(Configuration::get('PS_SHOP_EMAIL')), false, $stream_context); + $content = Tools::file_get_contents($protocol.'api.prestashop.com/partner/premium/get_partners.php?iso_country='.Tools::strtoupper($isoCountry).'&iso_lang='.Tools::strtolower($isoUser).'&ps_version='._PS_VERSION_.'&ps_creation='._PS_CREATION_DATE_.'&host='.urlencode($_SERVER['HTTP_HOST']), false, $stream_context); @unlink('../config/xml/preactivation.xml'); file_put_contents('../config/xml/preactivation.xml', $content); } @@ -540,7 +550,7 @@ class AdminHomeControllerCore extends AdminController // Cache the logo if (!file_exists('../img/tmp/preactivation_'.htmlentities((string)$partner->module).'.png')) { - $logo = @Tools::file_get_contents(htmlentities((string)$partner->logo)); + $logo = Tools::file_get_contents(htmlentities((string)$partner->logo)); if (sizeof($logo) > 0) file_put_contents('../img/tmp/preactivation_'.htmlentities((string)$partner->module).'.png', $logo); } @@ -566,12 +576,12 @@ class AdminHomeControllerCore extends AdminController if (empty($optional_final) && (string)$optional->attributes()->iso == $isoUser) $optional_final = (string)$optional; - $link = 'index.php?controller=adminmodules&install='.htmlentities((string)$partner->module).'&token='.Tools::getAdminTokenLite('AdminModules').'&module_name='.htmlentities((string)$partner->module).'&redirect=config'; + $link = 'index.php?controller=adminmodules&install='.Tools::htmlentitiesUTF8((string)$partner->module).'&token='.Tools::getAdminTokenLite('AdminModules').'&module_name='.Tools::htmlentitiesUTF8((string)$partner->module).'&redirect=config'; $return .= '

        - '.htmlentities((string)$partner->name).'
        - '.htmlentities(utf8_decode((string)$label_final)).' - '.(($optional_final != '') ? '' : '').' + '.htmlentities((string)$partner->name).'
        + '.Tools::htmlentitiesUTF8($label_final).' + '.(($optional_final != '') ? '' : '').'

        '; $count++; @@ -658,15 +668,12 @@ class AdminHomeControllerCore extends AdminController $smarty->assign('protocol', $protocol); $isoUser = $this->context->language->iso_code; $smarty->assign('isoUser', $isoUser); - $upgrade = null; $tpl_vars['refresh_check_version'] = 0; - if (@ini_get('allow_url_fopen')) - { - $upgrade = new Upgrader(true); - // if this information is outdated, the version will be checked after page loading - if (Configuration::get('PS_LAST_VERSION_CHECK') < time() - (3600 * Upgrader::DEFAULT_CHECK_VERSION_DELAY_HOURS)) - $tpl_vars['refresh_check_version'] = 1; - } + $upgrade = new Upgrader(true); + + // if this information is outdated, the version will be checked after page loading + if (Configuration::get('PS_LAST_VERSION_CHECK') < time() - (3600 * Upgrader::DEFAULT_CHECK_VERSION_DELAY_HOURS)) + $tpl_vars['refresh_check_version'] = 1; if (!$this->isFresh(Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 86400)) file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, Tools::addonsRequest('native')); diff --git a/controllers/admin/AdminImagesController.php b/controllers/admin/AdminImagesController.php index 38ecea2e4..8791cd27f 100644 --- a/controllers/admin/AdminImagesController.php +++ b/controllers/admin/AdminImagesController.php @@ -53,7 +53,7 @@ class AdminImagesControllerCore extends AdminController ); // No need to display the old image system if the install has been made later than 2013-03-26 - $this->display_move = (defined('_PS_CREATION_DATE_') && strtotime(_PS_CREATION_DATE_) > strtotime('2013-03-26')) ? false : true; + $this->display_move = (!Configuration::get('PS_LEGACY_IMAGES') && defined('_PS_CREATION_DATE_') && strtotime(_PS_CREATION_DATE_) > strtotime('2013-03-26')) ? false : true; $this->fields_options = array( 'images' => array( @@ -62,7 +62,7 @@ class AdminImagesControllerCore extends AdminController 'top' => '', 'bottom' => '', 'description' => $this->l('JPEG images have a small file size and standard quality. PNG images have a larger file size, a higher quality and support transparency. Note that in all cases the image files will have the .jpg extension.').' -

        '.$this->l('WARNING: This feature may not be compatible with your theme, or with some of your modules. In particular, PNG mode is not compatible with the Watermark module. If you encounter any issues, turn it off by selecting "Use JPEG".'), +

        '.$this->l('WARNING: This feature may not be compatible with your theme, or with some of your modules. In particular, PNG mode is not compatible with the Watermark module. If you encounter any issues, turn it off by selecting "Use JPEG".'), 'fields' => array( 'PS_IMAGE_QUALITY' => array( 'title' => $this->l('Image quality'), @@ -375,6 +375,7 @@ class AdminImagesControllerCore extends AdminController || !Configuration::updateValue('PS_PNG_QUALITY', Tools::getValue('PS_PNG_QUALITY'))) $this->errors[] = Tools::displayError('Unknown error.'); else + $this->confirmations[] = $this->_conf[6]; return parent::postProcess(); } else diff --git a/controllers/admin/AdminImportController.php b/controllers/admin/AdminImportController.php index 2bf3a7aa5..e00153fe8 100644 --- a/controllers/admin/AdminImportController.php +++ b/controllers/admin/AdminImportController.php @@ -819,7 +819,7 @@ class AdminImportControllerCore extends AdminController // 'file_exists' doesn't work on distant file, and getimagesize make the import slower. // Just hide the warning, the traitment will be the same. - if (@copy($url, $tmpfile)) + if (Tools::copy($url, $tmpfile)) { ImageManager::resize($tmpfile, $path.'.jpg'); $images_types = ImageType::getImagesTypes($entity); @@ -1433,9 +1433,7 @@ class AdminImportControllerCore extends AdminController $image->position = Image::getHighestPosition($product->id) + 1; $image->cover = (!$key && !$product_has_images) ? true : false; // file_exists doesn't work with HTTP protocol - if (@fopen($url, 'r') == false) - $error = true; - else if (($field_error = $image->validateFields(UNFRIENDLY_ERROR, true)) === true && + if (($field_error = $image->validateFields(UNFRIENDLY_ERROR, true)) === true && ($lang_field_error = $image->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $image->add()) { // associate image to selected shops @@ -2660,6 +2658,13 @@ class AdminImportControllerCore extends AdminController Image::clearTmpDir(); return true; } + + public function clearSmartyCache() + { + Tools::enableCache(); + Tools::clearCache($this->context->smarty); + Tools::restoreCacheSettings(); + } public function postProcess() { @@ -2712,43 +2717,56 @@ class AdminImportControllerCore extends AdminController // If i am a superadmin, i can truncate table if (((Shop::isFeatureActive() && $this->context->employee->isSuperAdmin()) || !Shop::isFeatureActive()) && Tools::getValue('truncate')) $this->truncateTables((int)Tools::getValue('entity')); - + $import_type = false; switch ((int)Tools::getValue('entity')) { - case $this->entities[$this->l('Categories')]: + case $this->entities[$import_type = $this->l('Categories')]: $this->categoryImport(); + $this->clearSmartyCache(); break; - case $this->entities[$this->l('Products')]: + case $this->entities[$import_type = $this->l('Products')]: + $import_type = $this->l('Categories'); $this->productImport(); + $this->clearSmartyCache(); break; - case $this->entities[$this->l('Customers')]: + case $this->entities[$import_type = $this->l('Customers')]: $this->customerImport(); break; - case $this->entities[$this->l('Addresses')]: + case $this->entities[$import_type = $this->l('Addresses')]: $this->addressImport(); break; - case $this->entities[$this->l('Combinations')]: + case $this->entities[$import_type = $this->l('Combinations')]: $this->attributeImport(); + $this->clearSmartyCache(); break; - case $this->entities[$this->l('Manufacturers')]: + case $this->entities[$import_type = $this->l('Manufacturers')]: $this->manufacturerImport(); + $this->clearSmartyCache(); break; - case $this->entities[$this->l('Suppliers')]: + case $this->entities[$import_type = $this->l('Suppliers')]: $this->supplierImport(); + $this->clearSmartyCache(); break; // @since 1.5.0 - case $this->entities[$this->l('Supply Orders')]: + case $this->entities[$import_type = $this->l('Supply Orders')]: if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) $this->supplyOrdersImport(); break; // @since 1.5.0 - case $this->entities[$this->l('Supply Order Details')]: + case $this->entities[$import_type = $this->l('Supply Order Details')]: if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) $this->supplyOrdersDetailsImport(); break; default: $this->errors[] = $this->l('Please select what you would like to import'); } + if ($import_type !== false) + { + $log_message = sprintf($this->l('%s import'), $import_type); + if (Tools::getValue('truncate')) + $log_message .= ' '.$this->l('with truncate'); + Logger::addLog($log_message, 1, null, $import_type, null, true, (int)$this->context->employee->id); + } } else $this->errors[] = $this->l('You must upload a file in order to proceed to the next step'); @@ -2808,4 +2826,4 @@ class AdminImportControllerCore extends AdminController die; } } -} +} \ No newline at end of file diff --git a/controllers/admin/AdminLanguagesController.php b/controllers/admin/AdminLanguagesController.php index 9a00c8ca0..233b3e7dd 100644 --- a/controllers/admin/AdminLanguagesController.php +++ b/controllers/admin/AdminLanguagesController.php @@ -104,7 +104,8 @@ class AdminLanguagesControllerCore extends AdminController $this->addRowAction('delete'); $this->displayWarning($this->l('When you delete a language, all related translations in the database will be deleted.')); - $this->displayInformation($this->l('Your .htaccess file must be writable.')); + if (!is_writable(_PS_ROOT_DIR_.'/.htaccess') && Configuration::get('PS_REWRITING_SETTINGS')) + $this->displayInformation($this->l('Your .htaccess file must be writable.')); return parent::renderList(); } @@ -144,7 +145,7 @@ class AdminLanguagesControllerCore extends AdminController 'required' => true, 'size' => 2, 'maxlength' => 5, - 'desc' => $this->l('Full language code (e.g. EN-US, PT-BR)') + 'desc' => $this->l('IETF language tag (e.g. en-US, pt-BR).').' '.sprintf('%s ', $this->l('IETF on Wikipedia')) ), array( 'type' => 'text', @@ -152,7 +153,7 @@ class AdminLanguagesControllerCore extends AdminController 'name' => 'date_format_lite', 'required' => true, 'size' => 15, - 'desc' => $this->l('Short date format (e.g. YY-MM-DD)') + 'desc' => sprintf($this->l('Short date format (e.g., %s)'), 'Y-m-d') ), array( 'type' => 'text', @@ -160,7 +161,7 @@ class AdminLanguagesControllerCore extends AdminController 'name' => 'date_format_full', 'required' => true, 'size' => 25, - 'desc' => $this->l('Full date format (e.g., YYYY-MM-DD)') + 'desc' => sprintf($this->l('Full date format (e.g., %s)'), 'Y-m-d H:i:s') ), array( 'type' => 'file', @@ -374,12 +375,11 @@ class AdminLanguagesControllerCore extends AdminController if ($_FILES['no-picture']['error'] == UPLOAD_ERR_OK) $this->copyNoPictureImage(strtolower(Tools::getValue('iso_code'))); unset($_FILES['no-picture']); - return parent::processAdd(); } else $this->errors[] = Tools::displayError('Flag and "No picture" image fields are required.'); - return false; + return parent::processAdd(); } public function processUpdate() @@ -475,19 +475,21 @@ class AdminLanguagesControllerCore extends AdminController public function ajaxProcessCheckLangPack() { $this->json = true; - if (empty($_GET['iso_lang'])) + if (!Tools::getValue('iso_lang') || !Validate::isLanguageIsoCode(Tools::getValue('iso_lang'))) { $this->status = 'error'; - $this->errors[] = '[TECHNICAL ERROR] iso_lang not set or empty'; + $this->errors[] = $this->l('Iso code is not valid'); + return; } - if (empty($_GET['ps_version'])) + if (!Tools::getValue('ps_version') || !Validate::isPrestaShopVersion(Tools::getValue('ps_version'))) { $this->status = 'error'; - $this->errors[] = '[TECHNICAL ERROR] ps_version not set or empty'; + $this->errors[] = $this->l('Technical Error: ps_version is not valid'); + return; } // Get all iso code available - if($lang_packs = Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/get_language_pack.php?version='.(string)$_GET['ps_version'].'&iso_lang='.(string)$_GET['iso_lang'])) + if ($lang_packs = Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/get_language_pack.php?version='.Tools::getValue('ps_version').'&iso_lang='.Tools::strtolower(Tools::getValue('iso_lang')))) { $result = Tools::jsonDecode($lang_packs); if ($lang_packs !== '' && $result && !isset($result->error)) @@ -498,16 +500,13 @@ class AdminLanguagesControllerCore extends AdminController else { $this->status = 'error'; - $msg = $this->l('Wrong ISO code, or the selected language pack is unavailable.'); - if ($result) - $msg = $result->msg; - $this->errors[] = $msg; + $this->errors[] = $this->l('Wrong ISO code, or the selected language pack is unavailable.'); } } else { $this->status = 'error'; - $this->errors[] = '[TECHNICAL ERROR] Server unreachable'; + $this->errors[] = $this->l('Technical Error: translation server unreachable'); } } diff --git a/controllers/admin/AdminLogsController.php b/controllers/admin/AdminLogsController.php index 081c76e53..b1b33bdb7 100644 --- a/controllers/admin/AdminLogsController.php +++ b/controllers/admin/AdminLogsController.php @@ -33,11 +33,9 @@ class AdminLogsControllerCore extends AdminController $this->lang = false; $this->noLink = true; - $this->addRowAction('delete'); - $this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?'))); - $this->fields_list = array( 'id_log' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25), + 'employee' => array('title' => $this->l('Employee'), 'align' => 'center', 'width' => 100), 'severity' => array('title' => $this->l('Severity (1-4)'), 'align' => 'center', 'width' => 50), 'message' => array('title' => $this->l('Message')), 'object_type' => array('title' => $this->l('Object type'), 'width' => 75), @@ -62,6 +60,8 @@ class AdminLogsControllerCore extends AdminController ) ); $this->list_no_link = true; + $this->_select .= 'CONCAT(LEFT(e.firstname, 1), \'. \', e.lastname) employee'; + $this->_join .= ' LEFT JOIN '._DB_PREFIX_.'employee e ON (a.id_employee = e.id_employee)'; parent::__construct(); } diff --git a/controllers/admin/AdminManufacturersController.php b/controllers/admin/AdminManufacturersController.php index 80d6fc516..2931ecd96 100644 --- a/controllers/admin/AdminManufacturersController.php +++ b/controllers/admin/AdminManufacturersController.php @@ -115,45 +115,23 @@ class AdminManufacturersControllerCore extends AdminController $this->content .= parent::renderList(); } - - public function initListManufacturerAddresses() + + protected function getAddressFieldsList() { - $this->toolbar_title = $this->l('Addresses'); - // reset actions and query vars - $this->actions = array(); - unset($this->fields_list, $this->_select, $this->_join, $this->_group, $this->_filterHaving, $this->_filter); - - $this->table = 'address'; - $this->identifier = 'id_address'; - $this->deleted = true; - $this->_orderBy = null; - - $this->addRowAction('editaddresses'); - $this->addRowAction('delete'); - - // test if a filter is applied for this list - if (Tools::isSubmit('submitFilter'.$this->table) || $this->context->cookie->{'submitFilter'.$this->table} !== false) - $this->filter = true; - - // test if a filter reset request is required for this list - if (isset($_POST['submitReset'.$this->table])) - $this->action = 'reset_filters'; - else - $this->action = ''; - // Sub tab addresses $countries = Country::getCountries($this->context->language->id); foreach ($countries as $country) $this->countries_array[$country['id_country']] = $country['name']; - $this->fields_list = array( + return array( 'id_address' => array( 'title' => $this->l('ID'), 'width' => 25 ), 'manufacturer_name' => array( 'title' => $this->l('Manufacturer'), - 'width' => 'auto' + 'width' => 'auto', + 'filter_key' => 'm!name' ), 'firstname' => array( 'title' => $this->l('First name'), @@ -181,6 +159,32 @@ class AdminManufacturersControllerCore extends AdminController 'filter_key' => 'cl!id_country' ) ); + } + + public function initListManufacturerAddresses() + { + $this->toolbar_title = $this->l('Addresses'); + // reset actions and query vars + $this->actions = array(); + unset($this->fields_list, $this->_select, $this->_join, $this->_group, $this->_filterHaving, $this->_filter); + + $this->table = 'address'; + $this->list_id = 'address'; + $this->identifier = 'id_address'; + $this->deleted = true; + $this->_orderBy = null; + + $this->addRowAction('editaddresses'); + $this->addRowAction('delete'); + + // test if a filter is applied for this list + if (Tools::isSubmit('submitFilter'.$this->table) || $this->context->cookie->{'submitFilter'.$this->table} !== false) + $this->filter = true; + + // test if a filter reset request is required for this list + $this->action = (isset($_POST['submitReset'.$this->table]) ? 'reset_filters' : ''); + + $this->fields_list = $this->getAddressFieldsList(); $this->_select = 'cl.`name` as country, m.`name` AS manufacturer_name'; $this->_join = ' @@ -189,7 +193,7 @@ class AdminManufacturersControllerCore extends AdminController $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (a.`id_manufacturer` = m.`id_manufacturer`)'; - $this->_where = 'AND a.`id_customer` = 0 AND a.`id_supplier` = 0 AND a.`id_warehouse` = 0'; + $this->_where = 'AND a.`id_customer` = 0 AND a.`id_supplier` = 0 AND a.`id_warehouse` = 0 AND a.`deleted`=0'; $this->context->smarty->assign('title_list', $this->l('Manufacturers addresses:')); @@ -406,6 +410,12 @@ class AdminManufacturersControllerCore extends AdminController 'type' => 'hidden', 'name' => 'alias', ); + + $form['input'][] = array( + 'type' => 'hidden', + 'name' => 'id_address', + ); + $form['input'][] = array( 'type' => 'text', 'label' => $this->l('Last name:'), @@ -440,6 +450,7 @@ class AdminManufacturersControllerCore extends AdminController 'type' => 'text', 'label' => $this->l('Zip Code/Postal Code'), 'name' => 'postcode', + 'required' => true, 'size' => 33, 'required' => false, ); @@ -504,7 +515,7 @@ class AdminManufacturersControllerCore extends AdminController $this->fields_value = array( 'name' => Manufacturer::getNameById($address->id_manufacturer), 'alias' => 'manufacturer', - 'id_country' => Configuration::get('PS_COUNTRY_DEFAULT') + 'id_country' => $address->id_country ); $this->initToolbar(); @@ -664,6 +675,8 @@ class AdminManufacturersControllerCore extends AdminController if (Tools::isSubmit('editaddresses')) $this->display = 'editaddresses'; + else if (Tools::isSubmit('updateaddress')) + $this->display = 'editaddresses'; else if (Tools::isSubmit('addaddress')) $this->display = 'addaddress'; else if (Tools::isSubmit('submitAddaddress')) @@ -674,12 +687,13 @@ class AdminManufacturersControllerCore extends AdminController public function initProcess() { - if (Tools::getValue('submitAddaddress') || Tools::isSubmit('deleteaddress') || Tools::isSubmit('submitBulkdeleteaddress')) + if (Tools::getValue('submitAddaddress') || Tools::isSubmit('deleteaddress') || Tools::isSubmit('submitBulkdeleteaddress') || Tools::isSubmit('exportaddress')) { $this->table = 'address'; $this->className = 'Address'; $this->identifier = 'id_address'; $this->deleted = true; + $this->fields_list = $this->getAddressFieldsList(); } parent::initProcess(); } @@ -711,6 +725,9 @@ class AdminManufacturersControllerCore extends AdminController return $res; } -} - - + + protected function beforeDelete($object) + { + return true; + } +} \ No newline at end of file diff --git a/controllers/admin/AdminMetaController.php b/controllers/admin/AdminMetaController.php index 6a08f8bc7..9fad901c9 100644 --- a/controllers/admin/AdminMetaController.php +++ b/controllers/admin/AdminMetaController.php @@ -139,7 +139,7 @@ class AdminMetaControllerCore extends AdminController $this->url = ShopUrl::getShopUrls($this->context->shop->id)->where('main', '=', 1)->getFirst(); if ($this->url) { - $shop_url_options['description'] = $this->l('Here you can set the URL for your shop. If you migrate your shop to a new URL, remember to change the values bellow.'); + $shop_url_options['description'] = $this->l('Here you can set the URL for your shop. If you migrate your shop to a new URL, remember to change the values below.'); $shop_url_options['fields'] = array( 'domain' => array( 'title' => $this->l('Shop domain'), @@ -363,6 +363,9 @@ class AdminMetaControllerCore extends AdminController else if (Tools::isSubmit('submitRobots')) $this->generateRobotsFile(); + if (Tools::isSubmit('PS_ROUTE_product_rule')) + Tools::clearCache($this->context->smarty); + return parent::postProcess(); } @@ -467,7 +470,6 @@ class AdminMetaControllerCore extends AdminController else Configuration::updateValue('PS_ROUTE_'.$route_id, $rule); } - } /** @@ -476,11 +478,21 @@ class AdminMetaControllerCore extends AdminController public function updateOptionPsRewritingSettings() { Configuration::updateValue('PS_REWRITING_SETTINGS', (int)Tools::getValue('PS_REWRITING_SETTINGS')); - Tools::generateHtaccess($this->ht_file, null, null, '', Tools::getValue('PS_HTACCESS_DISABLE_MULTIVIEWS'), false, Tools::getValue('PS_HTACCESS_DISABLE_MODSEC')); - - Tools::enableCache(); - Tools::clearCache($this->context->smarty); - Tools::restoreCacheSettings(); + if (Tools::generateHtaccess($this->ht_file, null, null, '', Tools::getValue('PS_HTACCESS_DISABLE_MULTIVIEWS'), false, Tools::getValue('PS_HTACCESS_DISABLE_MODSEC'))) + { + Tools::enableCache(); + Tools::clearCache($this->context->smarty); + Tools::restoreCacheSettings(); + } + else + { + Configuration::updateValue('PS_REWRITING_SETTINGS', 0); + // Message copied/pasted from the information tip + $message = $this->l('Before being able to use this tool, you need to:'); + $message .= '
        - '.$this->l('Create a blank .htaccess in your root directory.'); + $message .= '
        - '.$this->l('Give it write permissions (CHMOD 666 on Unix system)'); + $this->errors[] = $message; + } } public function updateOptionPsRouteProductRule() @@ -529,6 +541,7 @@ class AdminMetaControllerCore extends AdminController { $this->url->domain = $value; $this->url->update(); + Configuration::updateGlobalValue('PS_SHOP_DOMAIN', $value); } else $this->errors[] = Tools::displayError('This domain is not valid.'); @@ -546,6 +559,7 @@ class AdminMetaControllerCore extends AdminController { $this->url->domain_ssl = $value; $this->url->update(); + Configuration::updateGlobalValue('PS_SHOP_DOMAIN_SSL', $value); } else $this->errors[] = Tools::displayError('The SSL domain is not valid.'); @@ -648,7 +662,7 @@ class AdminMetaControllerCore extends AdminController } $tab['GB'] = array( - 'orderby=','orderway=','tag=','id_currency=','search_query=','back=','utm_source=','utm_medium=','utm_campaign=','n=' + 'orderby=','orderway=','tag=','id_currency=','search_query=','back=','n=' ); foreach ($disallow_controllers as $controller) diff --git a/controllers/admin/AdminModulesController.php b/controllers/admin/AdminModulesController.php index c457c4496..dc2b3cdd9 100644 --- a/controllers/admin/AdminModulesController.php +++ b/controllers/admin/AdminModulesController.php @@ -571,7 +571,8 @@ class AdminModulesControllerCore extends AdminController else { // Uninstall the module before deleting the files, but do not block the process if uninstall returns false - $module->uninstall(); + if (Module::isInstalled($module->name)) + $module->uninstall(); $moduleDir = _PS_MODULE_DIR_.str_replace(array('.', '/', '\\'), array('', '', ''), Tools::getValue('module_name')); $this->recursiveDeleteOnDisk($moduleDir); Tools::redirectAdmin(self::$currentIndex.'&conf=22&token='.$this->token.'&tab_module='.Tools::getValue('tab_module').'&module_name='.Tools::getValue('module_name')); @@ -629,9 +630,8 @@ class AdminModulesControllerCore extends AdminController if (!$download_ok) $this->errors[] = $this->l('Error on downloading the lastest version'); - else - if(!$this->extractArchive(_PS_MODULE_DIR_.$modaddons->name.'.zip', false)) - $this->errors[] = $this->l(sprintf("Module %s can't be upgraded: ", $modaddons->name)); + elseif (!$this->extractArchive(_PS_MODULE_DIR_.$modaddons->name.'.zip', false)) + $this->errors[] = $this->l(sprintf("Module %s can't be upgraded: ", $modaddons->name)); } } } @@ -673,14 +673,18 @@ class AdminModulesControllerCore extends AdminController // Get the return value of current method $echo = $module->{$method}(); + + // After a successful install of a single module that has a configuration method, to the configuration page + if ($key == 'install' && $echo === true && strpos(Tools::getValue('install'), '|') === false && method_exists($module, 'getContent')) + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&configure='.$module->name.'&conf=12'); } - + // If the method called is "configure" (getContent method), we show the html code of configure page if ($key == 'configure' && Module::isInstalled($module->name)) { if (isset($module->multishop_context)) $this->multishop_context = $module->multishop_context; - + $backlink = self::$currentIndex.'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name; $hooklink = 'index.php?tab=AdminModulesPositions&token='.Tools::getAdminTokenLite('AdminModulesPositions').'&show_modules='.(int)$module->id; $tradlink = 'index.php?tab=AdminTranslations&token='.Tools::getAdminTokenLite('AdminTranslations').'&type=modules&lang='; @@ -762,6 +766,9 @@ class AdminModulesControllerCore extends AdminController Tools::redirectAdmin('index.php?controller=adminmodules&configure='.Tools::getValue('module_name').'&token='.Tools::getValue('token').'&module_name='.Tools::getValue('module_name').$params); Tools::redirectAdmin(self::$currentIndex.'&conf='.$return.'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor=anchor'.ucfirst($module->name).(isset($modules_list_save) ? '&modules_list='.$modules_list_save : '').$params); } + + if (isset($_GET['update'])) + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&updated=1tab_module='.$module->tab.'&module_name='.$module->name.'&anchor=anchor'.ucfirst($module->name).(isset($modules_list_save) ? '&modules_list='.$modules_list_save : '').$params); } public function postProcess() @@ -769,7 +776,6 @@ class AdminModulesControllerCore extends AdminController // Parent Post Process parent::postProcess(); - // Get the list of installed module ans prepare it for ajax call. if (($list = Tools::getValue('installed_modules'))) Context::getContext()->smarty->assign('installed_modules', Tools::jsonEncode(explode('|', $list))); @@ -1008,6 +1014,14 @@ class AdminModulesControllerCore extends AdminController // Browse modules list foreach ($modules as $km => $module) { + //Add succes message for one module update + if (Tools::getValue('updated') && Tools::getValue('module_name')) + { + if ($module->name === (string)Tools::getValue('module_name')) + $module_success[] = array('name' => $module->displayName, 'message' => array( + 0 => $this->l('Current version:').$module->version)); + } + //if we are in favorites view we only display installed modules if (Tools::getValue('select') == 'favorites' && !$module->id) { diff --git a/controllers/admin/AdminModulesPositionsController.php b/controllers/admin/AdminModulesPositionsController.php index 8b7820b19..b1fafa5c8 100644 --- a/controllers/admin/AdminModulesPositionsController.php +++ b/controllers/admin/AdminModulesPositionsController.php @@ -270,12 +270,13 @@ class AdminModulesPositionsControllerCore extends AdminController 'href' => self::$currentIndex.'&addToHook'.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token, 'desc' => $this->l('Transplant a module') ); - + $live_edit_params = array( 'live_edit' => true, 'ad' => $admin_dir, 'liveToken' => $this->token, - 'id_employee' => (int)$this->context->employee->id + 'id_employee' => (int)$this->context->employee->id, + 'id_shop' => (int)$this->context->shop->id ); $this->context->smarty->assign(array( @@ -302,10 +303,13 @@ class AdminModulesPositionsControllerCore extends AdminController public function getLiveEditUrl($live_edit_params) { $lang = ''; + $admin_dir = dirname($_SERVER['PHP_SELF']); + $admin_dir = substr($admin_dir, strrpos($admin_dir, '/') + 1); + $dir = str_replace($admin_dir, '', dirname($_SERVER['SCRIPT_NAME'])); if (Configuration::get('PS_REWRITING_SETTINGS') && count(Language::getLanguages(true)) > 1) $lang = Language::getIsoById($this->context->employee->id_lang).'/'; - $url = $this->context->shop->getBaseURL().$lang.Dispatcher::getInstance()->createUrl('index', (int)$this->context->language->id, $live_edit_params); + $url = Tools::getCurrentUrlProtocolPrefix().Tools::getHttpHost().$dir.$lang.Dispatcher::getInstance()->createUrl('index', (int)$this->context->language->id, $live_edit_params); return $url; } @@ -393,21 +397,35 @@ class AdminModulesPositionsControllerCore extends AdminController if (!is_array($file_list)) $file_list = ($file_list) ? array($file_list) : array(); - $content = ''; + $content = ''; if ($shop_id) { $shop = new Shop($shop_id); $content .= ' ('.$shop->name.')'; } - $content .= '
        + '; + // @todo do something better with controllers $controllers = Dispatcher::getControllers(_PS_FRONT_CONTROLLER_DIR_); ksort($controllers); + + foreach ($file_list as $k => $v) + if ( ! array_key_exists ($v, $controllers)) + $content .= ' + '; + + $content .= ' + '; foreach ($controllers as $k => $v) - $content .= ''; - $content .= ' -

        '; + $content .= ' + '; + + $content .= ' + + '; return $content; } diff --git a/controllers/admin/AdminNotFoundController.php b/controllers/admin/AdminNotFoundController.php index 00344cd61..d26e92827 100644 --- a/controllers/admin/AdminNotFoundController.php +++ b/controllers/admin/AdminNotFoundController.php @@ -39,8 +39,7 @@ class AdminNotFoundControllerCore extends AdminController public function initContent() { $this->errors[] = Tools::displayError('Controller not found'); - $tpl_vars['controller'] = Tools::getvalue('controller'); - + $tpl_vars['controller'] = Tools::getvalue('controllerUri', Tools::getvalue('controller')); $this->context->smarty->assign($tpl_vars); parent::initContent(); } diff --git a/controllers/admin/AdminOrdersController.php b/controllers/admin/AdminOrdersController.php index 67e8fd9a1..0b9557f64 100755 --- a/controllers/admin/AdminOrdersController.php +++ b/controllers/admin/AdminOrdersController.php @@ -266,6 +266,7 @@ class AdminOrdersControllerCore extends AdminController $order = new Order(Tools::getValue('id_order')); if (!Validate::isLoadedObject($order)) throw new PrestaShopException('Can\'t load Order object'); + ShopUrl::cacheMainDomainForShop((int)$order->id_shop); } /* Update shipping number */ @@ -304,11 +305,11 @@ class AdminOrdersControllerCore extends AdminController '{shipping_number}' => $order->shipping_number, '{order_name}' => $order->getUniqReference() ); - if (@Mail::Send((int)$order->id_lang, 'in_transit', Mail::l('Package in transit', (int)$order->id_lang), $templateVars, + if (@Mail::Send((int)$order->id_lang, 'in_transit', Mail::l('Package in transit'), $templateVars, $customer->email, $customer->firstname.' '.$customer->lastname, null, null, null, null, _PS_MAIL_DIR_, true, (int)$order->id_shop)) { - Hook::exec('actionAdminOrdersTrackingNumberUpdate', array('order' => $order)); + Hook::exec('actionAdminOrdersTrackingNumberUpdate', array('order' => $order, 'customer' => $customer, 'carrier' => $carrier)); Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token); } else @@ -488,6 +489,14 @@ class AdminOrdersControllerCore extends AdminController if ($shipping_cost_amount > 0) $amount += $shipping_cost_amount; + $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); + if (Validate::isLoadedObject($order_carrier)) + { + $order_carrier->weight = (float)$order->getTotalWeight(); + if ($order_carrier->update()) + $order->weight = sprintf("%.3f ".Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight); + } + if ($amount > 0) { if (!OrderSlip::createPartialOrderSlip($order, $amount, $shipping_cost_amount, $order_detail_list)) @@ -513,6 +522,7 @@ class AdminOrdersControllerCore extends AdminController $now = time(); $cart_rule->date_from = date('Y-m-d H:i:s', $now); $cart_rule->date_to = date('Y-m-d H:i:s', $now + (3600 * 24 * 365.25)); /* 1 year */ + $cart_rule->partial_use = 1; $cart_rule->active = 1; $cart_rule->reduction_amount = $amount; @@ -652,8 +662,16 @@ class AdminOrdersControllerCore extends AdminController // Delete product $order_detail = new OrderDetail((int)$id_order_detail); - if (!$order->deleteProduct($order, $order_detail, $qtyCancelProduct)) + if (!$order->deleteProduct($order, $order_detail, $qty_cancel_product)) $this->errors[] = Tools::displayError('An error occurred while attempting to delete the product.').' '.$order_detail->product_name.''; + // Update weight SUM + $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); + if (Validate::isLoadedObject($order_carrier)) + { + $order_carrier->weight = (float)$order->getTotalWeight(); + if ($order_carrier->update()) + $order->weight = sprintf("%.3f ".Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight); + } Hook::exec('actionProductCancel', array('order' => $order, 'id_order_detail' => (int)$id_order_detail)); } if (!count($this->errors) && $customizationList) @@ -843,7 +861,7 @@ class AdminOrdersControllerCore extends AdminController $payment_module->validateOrder( (int)$cart->id, (int)$id_order_state, $cart->getOrderTotal(true, Cart::BOTH), $payment_module->displayName, $this->l('Manual order -- Employee:'). - Tools::safeOutput(substr($employee->firstname, 0, 1).'. '.$employee->lastname), array(), null, false, $cart->secure_key + substr($employee->firstname, 0, 1).'. '.$employee->lastname, array(), null, false, $cart->secure_key ); if ($payment_module->currentOrder) Tools::redirectAdmin(self::$currentIndex.'&id_order='.$payment_module->currentOrder.'&vieworder'.'&token='.$this->token); @@ -912,13 +930,10 @@ class AdminOrdersControllerCore extends AdminController $order_detail->updateTaxAmount($order); } - $id_order_carrier = Db::getInstance()->getValue(' - SELECT `id_order_carrier` - FROM `'._DB_PREFIX_.'order_carrier` - WHERE `id_order` = '.(int)$order->id); + $id_order_carrier = (int)$order->getIdOrderCarrier(); if ($id_order_carrier) { - $order_carrier = new OrderCarrier($id_order_carrier); + $order_carrier = $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); $order_carrier->shipping_cost_tax_excl = (float)Tools::convertPriceFull($order_carrier->shipping_cost_tax_excl, $old_currency, $currency); $order_carrier->shipping_cost_tax_incl = (float)Tools::convertPriceFull($order_carrier->shipping_cost_tax_incl, $old_currency, $currency); $order_carrier->update(); @@ -961,7 +976,7 @@ class AdminOrdersControllerCore extends AdminController // Update currency in order $order->id_currency = $currency->id; - // Update conversion rate + // Update exchange rate $order->conversion_rate = (float)$currency->conversion_rate; $order->update(); } @@ -1047,16 +1062,17 @@ class AdminOrdersControllerCore extends AdminController } $cart_rules = array(); + $discount_value = (float)str_replace(',', '.', Tools::getValue('discount_value')); switch (Tools::getValue('discount_type')) { // Percent type case 1: - if (Tools::getValue('discount_value') < 100) + if ($discount_value < 100) { if (isset($order_invoice)) { - $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($order_invoice->total_paid_tax_incl * Tools::getValue('discount_value') / 100, 2); - $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($order_invoice->total_paid_tax_excl * Tools::getValue('discount_value') / 100, 2); + $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($order_invoice->total_paid_tax_incl * $discount_value / 100, 2); + $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($order_invoice->total_paid_tax_excl * $discount_value / 100, 2); // Update OrderInvoice $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); @@ -1066,8 +1082,8 @@ class AdminOrdersControllerCore extends AdminController $order_invoices_collection = $order->getInvoicesCollection(); foreach ($order_invoices_collection as $order_invoice) { - $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($order_invoice->total_paid_tax_incl * Tools::getValue('discount_value') / 100, 2); - $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($order_invoice->total_paid_tax_excl * Tools::getValue('discount_value') / 100, 2); + $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($order_invoice->total_paid_tax_incl * $discount_value / 100, 2); + $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($order_invoice->total_paid_tax_excl * $discount_value / 100, 2); // Update OrderInvoice $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); @@ -1075,8 +1091,8 @@ class AdminOrdersControllerCore extends AdminController } else { - $cart_rules[0]['value_tax_incl'] = Tools::ps_round($order->total_paid_tax_incl * Tools::getValue('discount_value') / 100, 2); - $cart_rules[0]['value_tax_excl'] = Tools::ps_round($order->total_paid_tax_excl * Tools::getValue('discount_value') / 100, 2); + $cart_rules[0]['value_tax_incl'] = Tools::ps_round($order->total_paid_tax_incl * $discount_value / 100, 2); + $cart_rules[0]['value_tax_excl'] = Tools::ps_round($order->total_paid_tax_excl * $discount_value / 100, 2); } } else @@ -1086,12 +1102,12 @@ class AdminOrdersControllerCore extends AdminController case 2: if (isset($order_invoice)) { - if (Tools::getValue('discount_value') > $order_invoice->total_paid_tax_incl) + if ($discount_value > $order_invoice->total_paid_tax_incl) $this->errors[] = Tools::displayError('The discount value is greater than the order invoice total.'); else { - $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round(Tools::getValue('discount_value'), 2); - $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round(Tools::getValue('discount_value') / (1 + ($order->getTaxesAverageUsed() / 100)), 2); + $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($discount_value, 2); + $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($discount_value / (1 + ($order->getTaxesAverageUsed() / 100)), 2); // Update OrderInvoice $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); @@ -1102,12 +1118,12 @@ class AdminOrdersControllerCore extends AdminController $order_invoices_collection = $order->getInvoicesCollection(); foreach ($order_invoices_collection as $order_invoice) { - if (Tools::getValue('discount_value') > $order_invoice->total_paid_tax_incl) + if ($discount_value > $order_invoice->total_paid_tax_incl) $this->errors[] = Tools::displayError('The discount value is greater than the order invoice total.').$order_invoice->getInvoiceNumberFormatted(Context::getContext()->language->id, (int)$order->id_shop).')'; else { - $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round(Tools::getValue('discount_value'), 2); - $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round(Tools::getValue('discount_value') / (1 + ($order->getTaxesAverageUsed() / 100)), 2); + $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($discount_value, 2); + $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($discount_value / (1 + ($order->getTaxesAverageUsed() / 100)), 2); // Update OrderInvoice $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); @@ -1116,12 +1132,12 @@ class AdminOrdersControllerCore extends AdminController } else { - if (Tools::getValue('discount_value') > $order->total_paid_tax_incl) + if ($discount_value > $order->total_paid_tax_incl) $this->errors[] = Tools::displayError('The discount value is greater than the order total.'); else { - $cart_rules[0]['value_tax_incl'] = Tools::ps_round(Tools::getValue('discount_value'), 2); - $cart_rules[0]['value_tax_excl'] = Tools::ps_round(Tools::getValue('discount_value') / (1 + ($order->getTaxesAverageUsed() / 100)), 2); + $cart_rules[0]['value_tax_incl'] = Tools::ps_round($discount_value, 2); + $cart_rules[0]['value_tax_excl'] = Tools::ps_round($discount_value / (1 + ($order->getTaxesAverageUsed() / 100)), 2); } } break; @@ -1172,7 +1188,7 @@ class AdminOrdersControllerCore extends AdminController $cartRuleObj->quantity = 0; $cartRuleObj->quantity_per_user = 1; if (Tools::getValue('discount_type') == 1) - $cartRuleObj->reduction_percent = Tools::getValue('discount_value'); + $cartRuleObj->reduction_percent = $discount_value; elseif (Tools::getValue('discount_type') == 2) $cartRuleObj->reduction_amount = $cart_rule['value_tax_excl']; elseif (Tools::getValue('discount_type') == 3) @@ -1298,7 +1314,7 @@ class AdminOrdersControllerCore extends AdminController // display warning if there are products out of stock $display_out_of_stock_warning = false; $current_order_state = $order->getCurrentOrderState(); - if (configuration::get('PS_STOCK_MANAGEMENT') && (!Validate::isLoadedObject($current_order_state) || ($current_order_state->delivery != 1 && $current_order_state->shipped != 1))) + if (Configuration::get('PS_STOCK_MANAGEMENT') && (!Validate::isLoadedObject($current_order_state) || ($current_order_state->delivery != 1 && $current_order_state->shipped != 1))) $display_out_of_stock_warning = true; // products current stock (from stock_available) @@ -1316,6 +1332,13 @@ class AdminOrdersControllerCore extends AdminController // if the current stock requires a warning if ($product['current_stock'] == 0 && $display_out_of_stock_warning) $this->displayWarning($this->l('This product is out of stock: ').' '.$product['product_name']); + if ($product['id_warehouse'] != 0) + { + $warehouse = new Warehouse((int)$product['id_warehouse']); + $product['warehouse_name'] = $warehouse->name; + } + else + $product['warehouse_name'] = '--'; } // Smarty assign @@ -1358,7 +1381,8 @@ class AdminOrdersControllerCore extends AdminController 'invoices_collection' => $order->getInvoicesCollection(), 'not_paid_invoices_collection' => $order->getNotPaidInvoicesCollection(), 'payment_methods' => $payment_methods, - 'invoice_management_active' => Configuration::get('PS_INVOICE', null, null, $order->id_shop) + 'invoice_management_active' => Configuration::get('PS_INVOICE', null, null, $order->id_shop), + 'display_warehouse' => (int)Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') ); return parent::renderView(); @@ -1694,6 +1718,15 @@ class AdminOrdersControllerCore extends AdminController // Save changes of order $order->update(); + + // Update weight SUM + $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); + if (Validate::isLoadedObject($order_carrier)) + { + $order_carrier->weight = (float)$order->getTotalWeight(); + if ($order_carrier->update()) + $order->weight = sprintf("%.3f ".Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight); + } // Update Tax lines $order_detail->updateTaxAmount($order); @@ -1712,6 +1745,13 @@ class AdminOrdersControllerCore extends AdminController $product['amount_refund'] = Tools::displayPrice($resume['amount_tax_incl']); $product['return_history'] = OrderReturn::getProductReturnDetail((int)$product['id_order_detail']); $product['refund_history'] = OrderSlip::getProductSlipDetail((int)$product['id_order_detail']); + if ($product['id_warehouse'] != 0) + { + $warehouse = new Warehouse((int)$product['id_warehouse']); + $product['warehouse_name'] = $warehouse->name; + } + else + $product['warehouse_name'] = '--'; // Get invoices collection $invoice_collection = $order->getInvoicesCollection(); @@ -1732,7 +1772,8 @@ class AdminOrdersControllerCore extends AdminController 'invoices_collection' => $invoice_collection, 'current_id_lang' => Context::getContext()->language->id, 'link' => Context::getContext()->link, - 'current_index' => self::$currentIndex + 'current_index' => self::$currentIndex, + 'display_warehouse' => (int)Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') )); $this->sendChangedNotification($order); @@ -1901,6 +1942,17 @@ class AdminOrdersControllerCore extends AdminController // Save order detail $res &= $order_detail->update(); + + // Update weight SUM + $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); + if (Validate::isLoadedObject($order_carrier)) + { + $order_carrier->weight = (float)$order->getTotalWeight(); + $res &= $order_carrier->update(); + if ($res) + $order->weight = sprintf("%.3f ".Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight); + } + // Save order invoice if (isset($order_invoice)) $res &= $order_invoice->update(); @@ -1916,6 +1968,14 @@ class AdminOrdersControllerCore extends AdminController $product['amount_refundable'] = $product['total_price_tax_incl'] - $resume['amount_tax_incl']; $product['amount_refund'] = Tools::displayPrice($resume['amount_tax_incl']); $product['refund_history'] = OrderSlip::getProductSlipDetail($order_detail->id); + if ($product['id_warehouse'] != 0) + { + $warehouse = new Warehouse((int)$product['id_warehouse']); + $product['warehouse_name'] = $warehouse->name; + } + else + $product['warehouse_name'] = '--'; + // Get invoices collection $invoice_collection = $order->getInvoicesCollection(); @@ -1935,7 +1995,8 @@ class AdminOrdersControllerCore extends AdminController 'invoices_collection' => $invoice_collection, 'current_id_lang' => Context::getContext()->language->id, 'link' => Context::getContext()->link, - 'current_index' => self::$currentIndex + 'current_index' => self::$currentIndex, + 'display_warehouse' => (int)Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') )); if (!$res) @@ -1969,8 +2030,8 @@ class AdminOrdersControllerCore extends AdminController { $res = true; - $order_detail = new OrderDetail(Tools::getValue('id_order_detail')); - $order = new Order(Tools::getValue('id_order')); + $order_detail = new OrderDetail((int)Tools::getValue('id_order_detail')); + $order = new Order((int)Tools::getValue('id_order')); $this->doDeleteProductLineValidation($order_detail, $order); @@ -1994,8 +2055,21 @@ class AdminOrdersControllerCore extends AdminController $res &= $order->update(); + // Reinject quantity in stock + $this->reinjectQuantity($order_detail, $order_detail->product_quantity); + // Delete OrderDetail $res &= $order_detail->delete(); + + // Update weight SUM + $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); + if (Validate::isLoadedObject($order_carrier)) + { + $order_carrier->weight = (float)$order->getTotalWeight(); + $res &= $order_carrier->update(); + if ($res) + $order->weight = sprintf("%.3f ".Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight); + } if (!$res) die(Tools::jsonEncode(array( diff --git a/controllers/admin/AdminPPreferencesController.php b/controllers/admin/AdminPPreferencesController.php index c3cb9a352..22656808d 100644 --- a/controllers/admin/AdminPPreferencesController.php +++ b/controllers/admin/AdminPPreferencesController.php @@ -116,7 +116,8 @@ class AdminPPreferencesControllerCore extends AdminController array('id' => '3', 'name' => $this->l('Product modified date')), array('id' => '4', 'name' => $this->l('Position inside category')), array('id' => '5', 'name' => $this->l('Manufacturer')), - array('id' => '6', 'name' => $this->l('Product quantity')) + array('id' => '6', 'name' => $this->l('Product quantity')), + array('id' => '7', 'name' => $this->l('Product reference')) ), 'identifier' => 'id' ), @@ -231,7 +232,7 @@ class AdminPPreferencesControllerCore extends AdminController // if advanced stock management is disabled, updates concerned tables if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') == 1 && - (int)Tools::getValue('PS_ADVANCED_STOCK_MANAGEMENT') == 0) + (int)Tools::getValue('PS_ADVANCED_STOCK_MANAGEMENT') == 0 && Context::getContext()->shop->getContext() == Shop::CONTEXT_ALL) { ObjectModel::updateMultishopTable('Product', array('advanced_stock_management' => 0), 'product_shop.`advanced_stock_management` = 1'); diff --git a/controllers/admin/AdminPaymentController.php b/controllers/admin/AdminPaymentController.php index 0c10bab4a..8a09dda92 100644 --- a/controllers/admin/AdminPaymentController.php +++ b/controllers/admin/AdminPaymentController.php @@ -175,7 +175,7 @@ class AdminPaymentControllerCore extends AdminController ), array('items' => Group::getGroups($this->context->language->id), 'title' => $this->l('Group restrictions'), - 'desc' => $this->l('Please mark each checkbox for the currency, or currencies, in which you want the payment module(s) to be available.'), + 'desc' => $this->l('Please mark each checkbox for the customer group(s), in which you want the payment module(s) to be available.'), 'name_id' => 'group', 'identifier' => 'id_group', 'icon' => 'group', diff --git a/controllers/admin/AdminPerformanceController.php b/controllers/admin/AdminPerformanceController.php index c19b3c221..798e1912d 100644 --- a/controllers/admin/AdminPerformanceController.php +++ b/controllers/admin/AdminPerformanceController.php @@ -118,12 +118,20 @@ class AdminPerformanceControllerCore extends AdminController ) ) ), + array( + 'type' => 'text', + 'label' => $this->l('Debug console Key'), + 'name' => 'smarty_console_key', + 'size' => 30, + 'desc' => $this->l('SMARTY_DEBUG parameter in the URL.') + ), ) ); $this->fields_value['smarty_force_compile'] = Configuration::get('PS_SMARTY_FORCE_COMPILE'); $this->fields_value['smarty_cache'] = Configuration::get('PS_SMARTY_CACHE'); $this->fields_value['smarty_console'] = Configuration::get('PS_SMARTY_CONSOLE'); + $this->fields_value['smarty_console_key'] = Configuration::get('PS_SMARTY_CONSOLE_KEY'); } public function initFieldsetFeaturesDetachables() @@ -471,21 +479,6 @@ class AdminPerformanceControllerCore extends AdminController $this->tpl_form_vars['servers'] = CacheMemcache::getMemcachedServers(); } - public function initFieldsetCloudCache() - { - if (!class_exists('CloudCache')) - $this->fields_form[6]['form'] = array( - 'legend' => array( - 'title' => $this->l('CloudCache'), - 'image' => '../img/admin/subdomain.gif' - ), - 'desc' => $this->l('Performance matters! Improve speed and conversions the easy way.').'
        '. - $this->l('CloudCache supercharges your site in minutes through its state-of-the-art content delivery network.').'

        '. - $this->l('Subscribe now using the code "presta25" and get an exclusive 25% monthly discount on every available package.').'

        - > '.$this->l('Click here to install the CloudCache module for PrestaShop').'
        ' - ); - } - public function renderForm() { // Initialize fieldset for a form @@ -495,7 +488,6 @@ class AdminPerformanceControllerCore extends AdminController $this->initFieldsetMediaServer(); $this->initFieldsetCiphering(); $this->initFieldsetCaching(); - $this->initFieldsetCloudCache(); // Activate multiple fieldset $this->multiple_fieldsets = true; @@ -602,7 +594,8 @@ class AdminPerformanceControllerCore extends AdminController Configuration::updateValue('PS_SMARTY_FORCE_COMPILE', Tools::getValue('smarty_force_compile', _PS_SMARTY_NO_COMPILE_)); Configuration::updateValue('PS_SMARTY_CACHE', Tools::getValue('smarty_cache', 0)); Configuration::updateValue('PS_SMARTY_CONSOLE', Tools::getValue('smarty_console', 0)); - $redirectAdmin = true; + Configuration::updateValue('PS_SMARTY_CONSOLE_KEY', Tools::getValue('smarty_console_key', 'SMARTY_DEBUG')); + $redirecAdmin = true; } else $this->errors[] = Tools::displayError('You do not have permission to edit this.'); @@ -798,6 +791,13 @@ class AdminPerformanceControllerCore extends AdminController else $this->errors[] = Tools::displayError('You do not have permission to edit this.'); } + + if ((bool)Tools::getValue('empty_smarty_cache')) + { + $redirectAdmin = true; + Tools::clearSmartyCache(); + } + if ($redirectAdmin && (!isset($this->errors) || !count($this->errors))) { Hook::exec('action'.get_class($this).ucfirst($this->action).'After', array('controller' => $this, 'return' => '')); @@ -833,4 +833,4 @@ class AdminPerformanceControllerCore extends AdminController die; } -} \ No newline at end of file +} diff --git a/controllers/admin/AdminPreferencesController.php b/controllers/admin/AdminPreferencesController.php index 5df23eae9..f878f69fc 100644 --- a/controllers/admin/AdminPreferencesController.php +++ b/controllers/admin/AdminPreferencesController.php @@ -95,6 +95,14 @@ class AdminPreferencesControllerCore extends AdminController 'default' => '0', 'visibility' => Shop::CONTEXT_ALL ), + 'PS_ALLOW_HTML_IFRAME' => array( + 'title' => $this->l('Allow iframes on html fields'), + 'desc' => $this->l('Allow iframes on fields like product description. We recommend that you leave this option disabled'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'default' => '0' + ), 'PS_PRICE_ROUND_MODE' => array( 'title' => $this->l('Round mode'), 'desc' => $this->l('You can choose how to round prices: Always round superior, always round inferior or classic rounding.'), diff --git a/controllers/admin/AdminProductsController.php b/controllers/admin/AdminProductsController.php index f87a2bfc7..b35380195 100644 --- a/controllers/admin/AdminProductsController.php +++ b/controllers/admin/AdminProductsController.php @@ -76,7 +76,7 @@ class AdminProductsControllerCore extends AdminController $this->allow_export = true; // @since 1.5 : translations for tabs - $this->available_tabs_lang = array ( + $this->available_tabs_lang = array( 'Informations' => $this->l('Information'), 'Pack' => $this->l('Pack'), 'VirtualProduct' => $this->l('Virtual Product'), @@ -160,40 +160,28 @@ class AdminProductsControllerCore extends AdminController if (Validate::isLoadedObject($this->_category) && empty($this->_filter)) $join_category = true; - $this->_join .= 'LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = a.`id_product` '.(!Shop::isFeatureActive() ? ' AND i.cover=1' : '').')'; - if (Shop::isFeatureActive()) - { - $alias = 'sa'; - $alias_image = 'image_shop'; - if (Shop::getContext() == Shop::CONTEXT_SHOP) - { - $this->_join .= ' JOIN `'._DB_PREFIX_.'product_shop` sa ON (a.`id_product` = sa.`id_product` AND sa.id_shop = '.(int)$this->context->shop->id.') - LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON ('.$alias.'.`id_category_default` = cl.`id_category` AND b.`id_lang` = cl.`id_lang` AND cl.id_shop = '.(int)$this->context->shop->id.') - LEFT JOIN `'._DB_PREFIX_.'shop` shop ON (shop.id_shop = '.(int)$this->context->shop->id.') - LEFT JOIN `'._DB_PREFIX_.'image_shop` image_shop ON (image_shop.`id_image` = i.`id_image` AND image_shop.`cover` = 1 AND image_shop.id_shop='.(int)$this->context->shop->id.')'; - } - else - { - $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'product_shop` sa ON (a.`id_product` = sa.`id_product` AND sa.id_shop = a.id_shop_default) - LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON ('.$alias.'.`id_category_default` = cl.`id_category` AND b.`id_lang` = cl.`id_lang` AND cl.id_shop = a.id_shop_default) - LEFT JOIN `'._DB_PREFIX_.'shop` shop ON (shop.id_shop = a.id_shop_default) - LEFT JOIN `'._DB_PREFIX_.'image_shop` image_shop ON (image_shop.`id_image` = i.`id_image` AND image_shop.`cover` = 1 AND image_shop.id_shop=a.id_shop_default)'; - } - $this->_select .= 'shop.name as shopname, '; - } - else - { - $alias = 'a'; - $alias_image = 'i'; - $this->_join .= 'LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON ('.$alias.'.`id_category_default` = cl.`id_category` AND b.`id_lang` = cl.`id_lang` AND cl.id_shop = 1)'; - } - - $this->_select .= 'MAX('.$alias_image.'.id_image) id_image,'; - - $this->_join .= ($join_category ? 'INNER JOIN `'._DB_PREFIX_.'category_product` cp ON (cp.`id_product` = a.`id_product` AND cp.`id_category` = '.(int)$this->_category->id.')' : '').' + $this->_join .= ' + LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = a.`id_product`) LEFT JOIN `'._DB_PREFIX_.'stock_available` sav ON (sav.`id_product` = a.`id_product` AND sav.`id_product_attribute` = 0 '.StockAvailable::addSqlShopRestriction(null, null, 'sav').') '; - $this->_select .= 'cl.name `name_category` '.($join_category ? ', cp.`position`' : '').', '.$alias.'.`price`, 0 AS price_final, sav.`quantity` as sav_quantity, '.$alias.'.`active`'; + + $alias = 'sa'; + $alias_image = 'image_shop'; + + $id_shop = Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP? (int)$this->context->shop->id : 'a.id_shop_default'; + $this->_join .= ' JOIN `'._DB_PREFIX_.'product_shop` sa ON (a.`id_product` = sa.`id_product` AND sa.id_shop = '.$id_shop.') + LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON ('.$alias.'.`id_category_default` = cl.`id_category` AND b.`id_lang` = cl.`id_lang` AND cl.id_shop = '.$id_shop.') + LEFT JOIN `'._DB_PREFIX_.'shop` shop ON (shop.id_shop = '.$id_shop.') + LEFT JOIN `'._DB_PREFIX_.'image_shop` image_shop ON (image_shop.`id_image` = i.`id_image` AND image_shop.`cover` = 1 AND image_shop.id_shop = '.$id_shop.')'; + + $this->_select .= 'shop.name as shopname, '; + $this->_select .= 'MAX('.$alias_image.'.id_image) id_image, cl.name `name_category`, '.$alias.'.`price`, 0 AS price_final, sav.`quantity` as sav_quantity, '.$alias.'.`active`'; + + if ($join_category) + { + $this->_join .= ' INNER JOIN `'._DB_PREFIX_.'category_product` cp ON (cp.`id_product` = a.`id_product` AND cp.`id_category` = '.(int)$this->_category->id.') '; + $this->_select .= ' , cp.`position`, '; + } $this->_group = 'GROUP BY '.$alias.'.id_product'; @@ -201,7 +189,8 @@ class AdminProductsControllerCore extends AdminController $this->fields_list['id_product'] = array( 'title' => $this->l('ID'), 'align' => 'center', - 'width' => 20 + 'type' => 'int', + 'width' => 40 ); $this->fields_list['image'] = array( 'title' => $this->l('Photo'), @@ -249,14 +238,16 @@ class AdminProductsControllerCore extends AdminController 'havingFilter' => true, 'orderby' => false ); - $this->fields_list['sav_quantity'] = array( - 'title' => $this->l('Quantity'), - 'width' => 90, - 'align' => 'right', - 'filter_key' => 'sav!quantity', - 'orderby' => true, - 'hint' => $this->l('This is the quantity available in the current shop/group.'), - ); + if (Configuration::get('PS_STOCK_MANAGEMENT')) + $this->fields_list['sav_quantity'] = array( + 'title' => $this->l('Quantity'), + 'width' => 90, + 'type' => 'int', + 'align' => 'right', + 'filter_key' => 'sav!quantity', + 'orderby' => true, + 'hint' => $this->l('This is the quantity available in the current shop/group.'), + ); $this->fields_list['active'] = array( 'title' => $this->l('Status'), 'width' => 70, @@ -267,7 +258,7 @@ class AdminProductsControllerCore extends AdminController 'orderby' => false ); - if ((int)$this->id_current_category) + if ($join_category && (int)$this->id_current_category) $this->fields_list['position'] = array( 'title' => $this->l('Position'), 'width' => 70, @@ -368,12 +359,18 @@ class AdminProductsControllerCore extends AdminController $result = parent::loadObject($opt); if ($result && Validate::isLoadedObject($this->object)) { - if (Shop::getContext() == Shop::CONTEXT_SHOP && !$this->object->isAssociatedToShop()) + if (Shop::getContext() == Shop::CONTEXT_SHOP && Shop::isFeatureActive() && !$this->object->isAssociatedToShop()) { $default_product = new Product((int)$this->object->id, false, null, (int)$this->object->id_shop_default); $def = ObjectModel::getDefinition($this->object); foreach ($def['fields'] as $field_name => $row) - $this->object->$field_name = $default_product->$field_name; + { + if (is_array($default_product->$field_name)) + foreach ($default_product->$field_name as $key => $value) + $this->object->{$field_name}[$key] = ObjectModel::formatValue($value, $def['fields'][$field_name]['type']); + else + $this->object->$field_name = ObjectModel::formatValue($default_product->$field_name, $def['fields'][$field_name]['type']); + } } $this->object->loadStockData(); } @@ -633,6 +630,7 @@ class AdminProductsControllerCore extends AdminController { $id_category = (int)Tools::getValue('id_category'); $category_url = empty($id_category) ? '' : '&id_category='.(int)$id_category; + Logger::addLog(sprintf($this->l('%s deletion'), $this->className), 1, null, $this->className, (int)$object->id, true, (int)$this->context->employee->id); $this->redirect_after = self::$currentIndex.'&conf=1&token='.$this->token.$category_url; } else @@ -671,7 +669,7 @@ class AdminProductsControllerCore extends AdminController { $productId = (int)Tools::getValue('id_product'); @unlink(_PS_TMP_IMG_DIR_.'product_'.$productId.'.jpg'); - @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.$productId.'.jpg'); + @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.$productId.'_'.$this->context->shop->id.'.jpg'); $this->redirect_after = self::$currentIndex.'&id_product='.$image->id_product.'&id_category='.(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '').'&action=Images&addproduct'.'&token='.$this->token; } } @@ -729,7 +727,12 @@ class AdminProductsControllerCore extends AdminController $this->errors[] = sprintf(Tools::displayError('You cannot delete the product #%d because there is physical stock left.'), $product->id); } if (!count($this->errors)) - $success &= $product->delete(); + { + if ($product->delete()) + Logger::addLog(sprintf($this->l('%s deletion'), $this->className), 1, null, $this->className, (int)$product->id, true, (int)$this->context->employee->id); + else + $success = false; + } else $success = 0; } @@ -764,6 +767,26 @@ class AdminProductsControllerCore extends AdminController $this->errors[] = Tools::displayError('The price attribute is required.'); if (!Tools::getIsset('attribute_combination_list') || Tools::isEmpty(Tools::getValue('attribute_combination_list'))) $this->errors[] = Tools::displayError('You must add at least one attribute.'); + + $array_checks = array( + 'reference' => 'isReference', + 'supplier_reference' => 'isReference', + 'location' => 'isReference', + 'ean13' => 'isEan13', + 'upc' => 'isUpc', + 'wholesale_price' => 'isPrice', + 'price' => 'isPrice', + 'ecotax' => 'isPrice', + 'quantity' => 'isInt', + 'weight' => 'isUnsignedFloat', + 'unit_price_impact' => 'isPrice', + 'default_on' => 'isBool', + 'minimal_quantity' => 'isUnsignedInt', + 'available_date' => 'isDateFormat' + ); + foreach ($array_checks as $property => $check) + if (Tools::getValue('attribute_'.$property) !== false && !call_user_func(array('Validate', $check), Tools::getValue('attribute_'.$property))) + $this->errors[] = sprintf(Tools::displayError('Field %s is not valid'), $property); if (!count($this->errors)) { @@ -779,8 +802,7 @@ class AdminProductsControllerCore extends AdminController { if ($this->tabAccess['edit'] === '1') { - - if ($this->isProductFieldUpdated('available_date_attribute') && !Validate::isDateFormat(Tools::getValue('available_date_attribute'))) + if ($this->isProductFieldUpdated('available_date_attribute') && (Tools::getValue('available_date_attribute') != '' &&!Validate::isDateFormat(Tools::getValue('available_date_attribute')))) $this->errors[] = Tools::displayError('Invalid date format.'); else { @@ -841,6 +863,12 @@ class AdminProductsControllerCore extends AdminController { $combination = new Combination((int)$id_product_attribute); $combination->setAttributes(Tools::getValue('attribute_combination_list')); + + // images could be deleted before + $id_images = Tools::getValue('id_image_attr'); + if (!empty($id_images)) + $combination->setImages($id_images); + $product->checkDefaultAttributes(); if (Tools::getValue('attribute_default')) { @@ -914,7 +942,9 @@ class AdminProductsControllerCore extends AdminController $tos = Tools::getValue('spm_to'); foreach ($id_specific_prices as $key => $id_specific_price) - if ($this->_validateSpecificPrice($id_shops[$key], $id_currencies[$key], $id_countries[$key], $id_groups[$key], $id_customers[$key], $prices[$key], $from_quantities[$key], $reductions[$key], $reduction_types[$key], $froms[$key], $tos[$key], $id_combinations[$key])) + if ($reduction_types[$key] == 'percentage' && ((float)$reductions[$key] <= 0 || (float)$reductions[$key] > 100)) + $this->errors[] = Tools::displayError('Submitted reduction value (0-100) is out-of-range'); + elseif ($this->_validateSpecificPrice($id_shops[$key], $id_currencies[$key], $id_countries[$key], $id_groups[$key], $id_customers[$key], $prices[$key], $from_quantities[$key], $reductions[$key], $reduction_types[$key], $froms[$key], $tos[$key], $id_combinations[$key])) { $specific_price = new SpecificPrice((int)($id_specific_price)); $specific_price->id_shop = (int)$id_shops[$key]; @@ -930,7 +960,7 @@ class AdminProductsControllerCore extends AdminController $specific_price->from = !$froms[$key] ? '0000-00-00 00:00:00' : $froms[$key]; $specific_price->to = !$tos[$key] ? '0000-00-00 00:00:00' : $tos[$key]; if (!$specific_price->update()) - $this->errors = Tools::displayError('An error occurred while updating the specific price.'); + $this->errors[] = Tools::displayError('An error occurred while updating the specific price.'); } if (!count($this->errors)) $this->redirect_after = self::$currentIndex.'&id_product='.(int)(Tools::getValue('id_product')).(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '').'&update'.$this->table.'&action=Prices&token='.$this->token; @@ -960,7 +990,10 @@ class AdminProductsControllerCore extends AdminController $to = Tools::getValue('sp_to'); if (!$to) $to = '0000-00-00 00:00:00'; - if ($this->_validateSpecificPrice($id_shop, $id_currency, $id_country, $id_group, $id_customer, $price, $from_quantity, $reduction, $reduction_type, $from, $to, $id_product_attribute)) + + if ($reduction_type == 'percentage' && ((float)$reduction <= 0 || (float)$reduction > 100)) + $this->errors[] = Tools::displayError('Submitted reduction value (0-100) is out-of-range'); + elseif ($this->_validateSpecificPrice($id_shop, $id_currency, $id_country, $id_group, $id_customer, $price, $from_quantity, $reduction, $reduction_type, $from, $to, $id_product_attribute)) { $specificPrice = new SpecificPrice(); $specificPrice->id_product = (int)$id_product; @@ -977,7 +1010,7 @@ class AdminProductsControllerCore extends AdminController $specificPrice->from = $from; $specificPrice->to = $to; if (!$specificPrice->add()) - $this->errors = Tools::displayError('An error occurred while updating the specific price.'); + $this->errors[] = Tools::displayError('An error occurred while updating the specific price.'); } } @@ -1321,7 +1354,7 @@ class AdminProductsControllerCore extends AdminController 'shops' => $json_shops, ); @unlink(_PS_TMP_IMG_DIR_.'product_'.(int)$obj->id_product.'.jpg'); - @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.(int)$obj->id_product.'.jpg'); + @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.(int)$obj->id_product.'_'.$this->context->shop->id.'.jpg'); die(Tools::jsonEncode($json)); } else @@ -1493,7 +1526,7 @@ class AdminProductsControllerCore extends AdminController $img->cover = 1; @unlink(_PS_TMP_IMG_DIR_.'product_'.(int)$img->id_product.'.jpg'); - @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.(int)$img->id_product.'.jpg'); + @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.(int)$img->id_product.'_'.$this->context->shop->id.'.jpg'); if ($img->update()) $this->jsonConfirmation($this->_conf[26]); @@ -1529,8 +1562,8 @@ class AdminProductsControllerCore extends AdminController if (file_exists(_PS_TMP_IMG_DIR_.'product_'.$image->id_product.'.jpg')) $res &= @unlink(_PS_TMP_IMG_DIR_.'product_'.$image->id_product.'.jpg'); - if (file_exists(_PS_TMP_IMG_DIR_.'product_mini_'.$image->id_product.'.jpg')) - $res &= @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.$image->id_product.'.jpg'); + if (file_exists(_PS_TMP_IMG_DIR_.'product_mini_'.$image->id_product.'_'.$this->context->shop->id.'.jpg')) + $res &= @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.$image->id_product.'_'.$this->context->shop->id.'.jpg'); if ($res) $this->jsonConfirmation($this->_conf[7]); @@ -1619,7 +1652,7 @@ class AdminProductsControllerCore extends AdminController if (count($this->errors)) return false; @unlink(_PS_TMP_IMG_DIR_.'product_'.$product->id.'.jpg'); - @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.$product->id.'.jpg'); + @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.$product->id.'_'.$this->context->shop->id.'.jpg'); return ((isset($id_image) && is_int($id_image) && $id_image) ? $id_image : false); } /** @@ -1681,6 +1714,7 @@ class AdminProductsControllerCore extends AdminController if ($this->object->add()) { + Logger::addLog(sprintf($this->l('%s addition'), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id); $this->addCarriers(); $this->updateAccessories($this->object); $this->updatePackItems($this->object); @@ -1797,8 +1831,32 @@ class AdminProductsControllerCore extends AdminController if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP) $object->setFieldsToUpdate((array)Tools::getValue('multishop_check')); + // Duplicate combinations if not associated to shop + if ($this->context->shop->getContext() == Shop::CONTEXT_SHOP && !$object->isAssociatedToShop()) + { + $is_associated_to_shop = false; + $combinations = Product::getProductAttributesIds($object->id); + if ($combinations) + { + foreach ($combinations as $id_combination) + { + $combination = new Combination((int)$id_combination['id_product_attribute']); + $default_combination = new Combination((int)$id_combination['id_product_attribute'], null, (int)$this->object->id_shop_default); + + $def = ObjectModel::getDefinition($default_combination); + foreach ($def['fields'] as $field_name => $row) + $combination->$field_name = ObjectModel::formatValue($default_combination->$field_name, $def['fields'][$field_name]['type']); + + $combination->save(); + } + } + } + else + $is_associated_to_shop = true; + if ($object->update()) { + Logger::addLog(sprintf($this->l('%s edition'), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id); if (in_array($this->context->shop->getContext(), array(Shop::CONTEXT_SHOP, Shop::CONTEXT_ALL))) { if ($this->isTabSubmitted('Shipping')) @@ -1887,7 +1945,15 @@ class AdminProductsControllerCore extends AdminController $this->display = 'edit'; } else + { + if (!$is_associated_to_shop && $combinations) + foreach ($combinations as $id_combination) + { + $combination = new Combination((int)$id_combination['id_product_attribute']); + $combination->delete(); + } $this->errors[] = Tools::displayError('An error occurred while updating an object.').' '.$this->table.' ('.Db::getInstance()->getMsgError().')'; + } } else $this->errors[] = Tools::displayError('An error occurred while updating an object.').' '.$this->table.' ('.Tools::displayError('The object cannot be loaded. ').')'; @@ -1980,17 +2046,28 @@ class AdminProductsControllerCore extends AdminController // Check fields validity foreach ($rules['validate'] as $field => $function) if ($this->isProductFieldUpdated($field) && ($value = Tools::getValue($field))) - if (!Validate::$function($value)) + { + $res = true; + if (Tools::strtolower($function) == 'iscleanhtml') + { + if (!Validate::$function($value, (int)Configuration::get('PS_ALLOW_HTML_IFRAME'))) + $res = false; + } + else + if (!Validate::$function($value)) + $res = false; + + if (!$res) $this->errors[] = sprintf( Tools::displayError('The %s field is invalid.'), call_user_func(array($className, 'displayFieldName'), $field, $className) ); - + } // Check multilingual fields validity foreach ($rules['validateLang'] as $fieldLang => $function) foreach ($languages as $language) if ($this->isProductFieldUpdated('description_short', $language['id_lang']) && ($value = Tools::getValue($fieldLang.'_'.$language['id_lang']))) - if (!Validate::$function($value)) + if (!Validate::$function($value, (int)Configuration::get('PS_ALLOW_HTML_IFRAME'))) $this->errors[] = sprintf( Tools::displayError('The %1$s field (%2$s) is invalid.'), call_user_func(array($className, 'displayFieldName'), $fieldLang, $className), @@ -2338,18 +2415,23 @@ class AdminProductsControllerCore extends AdminController { if ($product = $this->loadObject(true)) { + if ($this->tabAccess['edit']) + { + $this->toolbar_btn['save'] = array( + 'short' => 'Save', + 'href' => '#', + 'desc' => $this->l('Save'), + ); + + $this->toolbar_btn['save-and-stay'] = array( + 'short' => 'SaveAndStay', + 'href' => '#', + 'desc' => $this->l('Save and stay'), + ); + } + if ((bool)$product->id) { - // adding button for delete this product - if ($this->tabAccess['delete'] && $this->display != 'add') - $this->toolbar_btn['delete'] = array( - 'short' => 'Delete', - 'href' => $this->context->link->getAdminLink('AdminProducts').'&id_product='.(int)$product->id.'&deleteproduct', - 'desc' => $this->l('Delete this product.'), - 'confirm' => 1, - 'js' => 'if (confirm(\''.$this->l('Delete product?').'\')){return true;}else{event.preventDefault();}' - ); - // adding button for duplicate this product if ($this->tabAccess['add'] && $this->display != 'add') $this->toolbar_btn['duplicate'] = array( @@ -2383,22 +2465,17 @@ class AdminProductsControllerCore extends AdminController 'desc' => $this->l('New combination'), 'class' => 'toolbar-new' ); - } - - if ($this->tabAccess['edit']) - { - $this->toolbar_btn['save'] = array( - 'short' => 'Save', - 'href' => '#', - 'desc' => $this->l('Save'), - ); - - $this->toolbar_btn['save-and-stay'] = array( - 'short' => 'SaveAndStay', - 'href' => '#', - 'desc' => $this->l('Save and stay'), - ); - } + + // adding button for delete this product + if ($this->tabAccess['delete'] && $this->display != 'add') + $this->toolbar_btn['delete'] = array( + 'short' => 'Delete', + 'href' => $this->context->link->getAdminLink('AdminProducts').'&id_product='.(int)$product->id.'&deleteproduct', + 'desc' => $this->l('Delete this product.'), + 'confirm' => 1, + 'js' => 'if (confirm(\''.$this->l('Delete product?').'\')){return true;}else{event.preventDefault();}' + ); + } } } else @@ -2465,7 +2542,7 @@ class AdminProductsControllerCore extends AdminController $this->tpl_form_vars['currentIndex'] = self::$currentIndex; $this->tpl_form_vars['display_multishop_checkboxes'] = (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP && $this->display == 'edit'); $this->fields_form = array(''); - $this->display = 'edit'; + $this->tpl_form_vars['token'] = $this->token; $this->tpl_form_vars['combinationImagesJs'] = $this->getCombinationImagesJs(); $this->tpl_form_vars['PS_ALLOW_ACCENTED_CHARS_URL'] = (int)Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL'); @@ -2495,8 +2572,8 @@ class AdminProductsControllerCore extends AdminController $this->tpl_form_vars['upload_max_filesize'] = $upload_max_filesize; $this->tpl_form_vars['country_display_tax_label'] = $this->context->country->display_tax_label; $this->tpl_form_vars['has_combinations'] = $this->object->hasAttributes(); - $this->product_exists_in_shop = true; + if ($this->display == 'edit' && Validate::isLoadedObject($product) && Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP && !$product->isAssociatedToShop($this->context->shop->id)) { $this->product_exists_in_shop = false; @@ -2524,12 +2601,14 @@ class AdminProductsControllerCore extends AdminController $this->initPack($this->object); $this->{'initForm'.$this->tab_display}($this->object); $this->tpl_form_vars['product'] = $this->object; + if ($this->ajax) if (!isset($this->tpl_form_vars['custom_form'])) throw new PrestaShopException('custom_form empty for action '.$this->tab_display); else return $this->tpl_form_vars['custom_form']; } + $parent = parent::renderForm(); $this->addJqueryPlugin(array('autocomplete', 'fancybox', 'typewatch')); return $parent; @@ -2539,6 +2618,7 @@ class AdminProductsControllerCore extends AdminController { if (!ShopUrl::getMainShopDomain()) return false; + $is_rewrite_active = (bool)Configuration::get('PS_REWRITING_SETTINGS'); $preview_url = $this->context->link->getProductLink( $product, @@ -2550,6 +2630,7 @@ class AdminProductsControllerCore extends AdminController 0, $is_rewrite_active ); + if (!$product->active) { $preview_url = $this->context->link->getProductLink( @@ -2562,15 +2643,12 @@ class AdminProductsControllerCore extends AdminController 0, $is_rewrite_active ); + $admin_dir = dirname($_SERVER['PHP_SELF']); + $admin_dir = substr($admin_dir, strrpos($admin_dir, '/') + 1); + $preview_url .= ((strpos($preview_url, '?') === false) ? '?' : '&').'adtoken='.$this->token.'&ad='.$admin_dir.'&id_employee='.(int)$this->context->employee->id; - if (!$product->active) - { - $admin_dir = dirname($_SERVER['PHP_SELF']); - $admin_dir = substr($admin_dir, strrpos($admin_dir, '/') + 1); - - $preview_url .= $product->active ? '' : '&adtoken='.$this->token.'&ad='.$admin_dir.'&id_employee='.(int)$this->context->employee->id; - } } + return $preview_url; } @@ -2673,7 +2751,7 @@ class AdminProductsControllerCore extends AdminController if (!$product_supplier_id) { - $product->addSupplierReference($supplier->id_supplier, (int)$attribute['id_product_attribute'], $reference, (float)Tools::convertPrice($price, $id_currency), (int)$id_currency); + $product->addSupplierReference($supplier->id_supplier, (int)$attribute['id_product_attribute'], $reference, (float)$price, (int)$id_currency); if ($product->id_supplier == $supplier->id_supplier) { if ((int)$attribute['id_product_attribute'] > 0) @@ -2699,7 +2777,7 @@ class AdminProductsControllerCore extends AdminController { $product_supplier = new ProductSupplier($product_supplier_id); $product_supplier->id_currency = (int)$id_currency; - $product_supplier->product_supplier_price_te = (float)Tools::convertPrice($price, $id_currency); //converted in the default currency + $product_supplier->product_supplier_price_te = (float)$price; $product_supplier->product_supplier_reference = pSQL($reference); $product_supplier->update(); @@ -3412,7 +3490,7 @@ class AdminProductsControllerCore extends AdminController $data->assign('languages', $this->_languages); $data->assign('currency', $currency); $this->object = $product; - $this->display = 'edit'; + //$this->display = 'edit'; $data->assign('product_name_redirected', Product::getProductName((int)$product->id_product_redirected, null, (int)$this->context->language->id)); /* * Form for adding a virtual product like software, mp3, etc... @@ -3568,12 +3646,15 @@ class AdminProductsControllerCore extends AdminController $current_shop_id = (int)$this->context->shop->id; else $current_shop_id = 0; + + $languages = Language::getLanguages(true); $data->assign(array( 'countImages' => $count_images, 'id_product' => (int)Tools::getValue('id_product'), 'id_category_default' => (int)$this->_category->id, 'images' => $images, + 'iso_lang' => $languages[0]['iso_code'], 'token' => $this->token, 'table' => $this->table, 'max_image_size' => $this->max_image_size / 1024 / 1024, diff --git a/controllers/admin/AdminReturnController.php b/controllers/admin/AdminReturnController.php index fe51775f9..39866ea4b 100644 --- a/controllers/admin/AdminReturnController.php +++ b/controllers/admin/AdminReturnController.php @@ -136,7 +136,7 @@ class AdminReturnControllerCore extends AdminController $this->tpl_form_vars = array( 'customer' => new Customer($this->object->id_customer), 'url_customer' => 'index.php?tab=AdminCustomers&id_customer='.(int)$this->object->id_customer.'&viewcustomer&token='.Tools::getAdminToken('AdminCustomers'.(int)(Tab::getIdFromClassName('AdminCustomers')).(int)$this->context->employee->id), - 'text_order' => sprintf($this->l('Order #%1$d from %2$s'), $order->id, Tools::displayDate($order->date_upd, $order->id_lang)), + 'text_order' => sprintf($this->l('Order #%1$d from %2$s'), $order->id, Tools::displayDate($order->date_upd)), 'url_order' => 'index.php?tab=AdminOrders&id_order='.(int)$order->id.'&vieworder&token='.Tools::getAdminToken('AdminOrders'.(int)Tab::getIdFromClassName('AdminOrders').(int)$this->context->employee->id), 'picture_folder' => _THEME_PROD_PIC_DIR_, 'type_file' => Product::CUSTOMIZE_FILE, diff --git a/controllers/admin/AdminScenesController.php b/controllers/admin/AdminScenesController.php index 7f9ef8b91..346a5543b 100644 --- a/controllers/admin/AdminScenesController.php +++ b/controllers/admin/AdminScenesController.php @@ -75,16 +75,15 @@ class AdminScenesControllerCore extends AdminController $images_types = ImageType::getImagesTypes('scenes'); foreach ($images_types as $k => $image_type) - { - if ($image_type['name'] == 'scene_default' && isset($_FILES['image'])) + { + if ($image_type['name'] == 'scene_default' AND isset($_FILES['image']) AND isset($_FILES['image']['tmp_name']) AND !$_FILES['image']['error']) ImageManager::resize( $base_img_path, _PS_SCENE_IMG_DIR_.$obj->id.'-'.stripslashes($image_type['name']).'.jpg', (int)$image_type['width'], - (int)$image_type['height'] - ); + (int)$image_type['height']); else if ($image_type['name'] == 'm_scene_default') - { + { if (isset($_FILES['thumb']) && !$_FILES['thumb']['error']) $base_thumb_path = _PS_SCENE_THUMB_IMG_DIR_.$obj->id.'.jpg'; else @@ -93,8 +92,7 @@ class AdminScenesControllerCore extends AdminController $base_thumb_path, _PS_SCENE_THUMB_IMG_DIR_.$obj->id.'-'.stripslashes($image_type['name']).'.jpg', (int)$image_type['width'], - (int)$image_type['height'] - ); + (int)$image_type['height']); } } } @@ -207,20 +205,20 @@ class AdminScenesControllerCore extends AdminController $this->addJqueryPlugin('imgareaselect'); $this->addJs(_PS_JS_DIR_.'admin-scene-cropping.js' ); $image_to_map_desc .= '

        '; + _THEME_SCENE_DIR_.$obj->id.'-scene_default.jpg?rand='.(int)rand().'" />
        '; $image_to_map_desc .= ' '; - if ($obj->id && file_exists(_PS_SCENE_IMG_DIR_.'thumbs/'.$obj->id.'-thumb_scene.jpg')) + if ($obj->id && file_exists(_PS_SCENE_IMG_DIR_.'thumbs/'.$obj->id.'-m_scene_default.jpg')) $image_to_map_desc .= '
        - +
        '; $img_alt_desc = ''; @@ -229,7 +227,7 @@ class AdminScenesControllerCore extends AdminController .$this->l('File size:').' '.(Tools::getMaxUploadSize() / 1024).''.$this->l('Kb max.').' ' .sprintf($this->l('Automatically resized to %1$d x %2$dpx (width x height).'), $thumb_scene_image_type['width'], $thumb_scene_image_type['height']).'.
        ' - .$this->l('Note: To change image dimensions, please change the \'thumb_scene\' image type settings to the desired size (in Back Office > Preferences > Images).'); + .$this->l('Note: To change image dimensions, please change the \'m_scene_default\' image type settings to the desired size (in Back Office > Preferences > Images).'); $input_img_alt = array( 'type' => 'file', @@ -312,7 +310,14 @@ class AdminScenesControllerCore extends AdminController if (!Tools::isSubmit('zones') || !count(Tools::getValue('zones'))) $this->errors[] = Tools::displayError('You should create at least one zone.'); } - + + if (Tools::isSubmit('delete'.$this->table)) + { + if (Validate::isLoadedObject($object = $this->loadObject())) + $object->deleteImage(false); + else + return false; + } parent::postProcess(); } } diff --git a/controllers/admin/AdminShippingController.php b/controllers/admin/AdminShippingController.php index 7d804b0f9..ec4d01129 100644 --- a/controllers/admin/AdminShippingController.php +++ b/controllers/admin/AdminShippingController.php @@ -37,7 +37,17 @@ class AdminShippingControllerCore extends AdminController foreach ($carriers as $key => $carrier) if ($carrier['is_free']) unset($carriers[$key]); + + $carrier_default_sort = array( + array('value' => Carrier::SORT_BY_PRICE, 'name' => $this->l('Price')), + array('value' => Carrier::SORT_BY_POSITION, 'name' => $this->l('Position')) + ); + $carrier_default_order = array( + array('value' => Carrier::SORT_BY_ASC, 'name' => $this->l('Ascending')), + array('value' => Carrier::SORT_BY_DESC, 'name' => $this->l('Descending')) + ); + $this->fields_options = array( 'handling' => array( 'title' => $this->l('Handling'), @@ -69,73 +79,42 @@ class AdminShippingControllerCore extends AdminController ', 'submit' => array() ), - 'billing' => array( - 'title' => $this->l('Billing'), - 'icon' => 'money', - 'fields' => array( - 'PS_SHIPPING_METHOD' => array( - 'title' => $this->l('Billing'), + 'general' => array( + 'title' => $this->l('Carrier options'), + 'fields' => array( + 'PS_CARRIER_DEFAULT' => array( + 'title' => $this->l('Default carrier:'), + 'desc' => $this->l('Your shop\'s default carrier'), 'cast' => 'intval', - 'type' => 'radio', - 'choices' => array( - 0 => $this->l('According to total price'), - 1 => $this->l('According to total weight') - ), - 'validation' => 'isBool' + 'type' => 'select', + 'identifier' => 'id_carrier', + 'list' => array_merge( + array( + -1 => array('id_carrier' => -1, 'name' => $this->l('Best price')), + -2 => array('id_carrier' => -2, 'name' => $this->l('Best grade')) + ), + Carrier::getCarriers((int)Configuration::get('PS_LANG_DEFAULT'), true, false, false, null, Carrier::ALL_CARRIERS)) ), - ) - ), - ); - } - - public function initContent() - { - $array_carrier = array(); - $carriers = Carrier::getCarriers($this->context->language->id, true, false, false, null, Carrier::PS_CARRIERS_AND_CARRIER_MODULES_NEED_RANGE); - foreach ($carriers as $key => $carrier) - if ($carrier['is_free']) - unset($carriers[$key]); - else - $array_carrier[] = $carrier['id_carrier']; - - $id_carrier = (int)Tools::getValue('id_carrier'); - - if (count($carriers) && isset($array_carrier[0])) - { - if (!$id_carrier) - $id_carrier = (int)$array_carrier[0]; - - $carrierSelected = new Carrier((int)$id_carrier); - } - else - $carrierSelected = new Carrier((int)$id_carrier); - - $currency = $this->context->currency; - $rangeObj = $carrierSelected->getRangeObject(); - $rangeTable = $carrierSelected->getRangeTable(); - $suffix = $carrierSelected->getRangeSuffix(); - - $rangeIdentifier = 'id_'.$rangeTable; - $ranges = $rangeObj->getRanges($id_carrier); - $delivery = Carrier::getDeliveryPriceByRanges($rangeTable, $id_carrier); - $deliveryArray = array(); - foreach ($delivery as $deliv) - $deliveryArray[$deliv['id_zone']][$deliv['id_carrier']][$deliv[$rangeIdentifier]] = $deliv['price']; - - $this->context->smarty->assign(array( - 'zones' => $carrierSelected->getZones(), - 'carriers' => $carriers, - 'ranges' => $ranges, - 'currency' => $currency, - 'deliveryArray' => $deliveryArray, - 'carrierSelected' => $carrierSelected, - 'id_carrier' => $id_carrier, - 'suffix' => $suffix, - 'rangeIdentifier' => $rangeIdentifier, - 'action_fees' => self::$currentIndex.'&token='.$this->token - )); - - parent::initContent(); + 'PS_CARRIER_DEFAULT_SORT' => array( + 'title' => $this->l('Sort by:'), + 'desc' => $this->l('This will only be visible in the Front Office'), + 'cast' => 'intval', + 'type' => 'select', + 'identifier' => 'value', + 'list' => $carrier_default_sort + ), + 'PS_CARRIER_DEFAULT_ORDER' => array( + 'title' => $this->l('Order by:'), + 'desc' => $this->l('This will only be visible in the Front Office'), + 'cast' => 'intval', + 'type' => 'select', + 'identifier' => 'value', + 'list' => $carrier_default_order + ), + ), + 'submit' => array() + ) + ); } public function postProcess() diff --git a/controllers/admin/AdminShopController.php b/controllers/admin/AdminShopController.php index 285459ea2..47bd270cb 100755 --- a/controllers/admin/AdminShopController.php +++ b/controllers/admin/AdminShopController.php @@ -226,13 +226,8 @@ class AdminShopControllerCore extends AdminController if (Tools::isSubmit('submitAddshopAndStay') || Tools::isSubmit('submitAddshop')) { - $same_name = Db::getInstance()->getValue(' - SELECT id_shop - FROM '._DB_PREFIX_.'shop - WHERE name = "'.pSQL(Tools::getValue('name')).'" - AND id_shop_group = '.(int)Tools::getValue('id_shop_group').' - '.(Tools::getValue('id_shop') ? 'AND id_shop != '.(int)Tools::getValue('id_shop') : '')); - if ($same_name) + $shop_group = new ShopGroup((int)Tools::getValue('id_shop_group')); + if ($shop_group->shopNameExists(Tools::getValue('name'), (int)Tools::getValue('id_shop'))) $this->errors[] = Tools::displayError('You cannot have two shops with the same name in the same group.'); } @@ -391,7 +386,7 @@ class AdminShopControllerCore extends AdminController $this->fields_form['input'][] = array( 'type' => 'select', 'label' => $this->l('Category root:'), - 'desc' => $this->l('This is the root category of the store that you\'ve created. To define a new root category for your store,').' '.$this->l('Please click here').'', + 'desc' => $this->l('This is the root category of the store that you\'ve created. To define a new root category for your store,').' '.$this->l('Please click here').'', 'name' => 'id_category', 'options' => array( 'query' => $categories, diff --git a/controllers/admin/AdminShopUrlController.php b/controllers/admin/AdminShopUrlController.php index f7fd28c78..05d3ca9d1 100644 --- a/controllers/admin/AdminShopUrlController.php +++ b/controllers/admin/AdminShopUrlController.php @@ -394,6 +394,42 @@ class AdminShopUrlControllerCore extends AdminController if ($this->redirect_shop_url) $this->redirect_after = $object->getBaseURI().basename(_PS_ADMIN_DIR_).'/'.$this->context->link->getAdminLink('AdminShopUrl'); } + + /** + * @param string $token + * @param integer $id + * @param string $name + * @return mixed + */ + public function displayDeleteLink($token = null, $id, $name = null) + { + $tpl = $this->createTemplate('helpers/list/list_action_delete.tpl'); + + if (!array_key_exists('Delete', self::$cache_lang)) + self::$cache_lang['Delete'] = $this->l('Delete', 'Helper'); + + if (!array_key_exists('DeleteItem', self::$cache_lang)) + self::$cache_lang['DeleteItem'] = $this->l('Delete selected item?', 'Helper'); + + if (!array_key_exists('Name', self::$cache_lang)) + self::$cache_lang['Name'] = $this->l('Name:', 'Helper'); + + if (!is_null($name)) + $name = '\n\n'.self::$cache_lang['Name'].' '.$name; + + $data = array( + $this->identifier => $id, + 'href' => Tools::safeOutput(self::$currentIndex.'&'.$this->identifier.'='.$id.'&delete'.$this->table.'&id_shop='.$this->id_shop.'&token='.($token != null ? $token : $this->token)), + 'action' => self::$cache_lang['Delete'], + ); + + if ($this->specificConfirmDelete !== false) + $data['confirm'] = !is_null($this->specificConfirmDelete) ? '\r'.$this->specificConfirmDelete : self::$cache_lang['DeleteItem'].$name; + + $tpl->assign(array_merge($this->tpl_delete_link_vars, $data)); + + return $tpl->fetch(); + } } diff --git a/controllers/admin/AdminStatusesController.php b/controllers/admin/AdminStatusesController.php index e1cc6f887..b046fe3ea 100644 --- a/controllers/admin/AdminStatusesController.php +++ b/controllers/admin/AdminStatusesController.php @@ -231,14 +231,6 @@ class AdminStatusesControllerCore extends AdminController } public function renderForm() - { - if (Tools::isSubmit('updateorder_state') || Tools::isSubmit('addorder_state')) - return $this->renderOrderStatusForm(); - else if (Tools::isSubmit('updateorder_return_state') || Tools::isSubmit('addorder_return_state')) - return $this->renderOrderReturnsForm(); - } - - protected function renderOrderStatusForm() { $this->fields_form = array( 'tinymce' => true, @@ -366,7 +358,17 @@ class AdminStatusesControllerCore extends AdminController 'class' => 'button' ) ); - + + if (Tools::isSubmit('updateorder_state') || Tools::isSubmit('addorder_state')) + return $this->renderOrderStatusForm(); + else if (Tools::isSubmit('updateorder_return_state') || Tools::isSubmit('addorder_return_state')) + return $this->renderOrderReturnsForm(); + else + return parent::renderForm(); + } + + protected function renderOrderStatusForm() + { if (!($obj = $this->loadObject(true))) return; diff --git a/controllers/admin/AdminStockInstantStateController.php b/controllers/admin/AdminStockInstantStateController.php index 04079c882..a3db14452 100644 --- a/controllers/admin/AdminStockInstantStateController.php +++ b/controllers/admin/AdminStockInstantStateController.php @@ -181,11 +181,13 @@ class AdminStockInstantStateControllerCore extends AdminController */ public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) { - if (Tools::isSubmit('csv') && (int)Tools::getValue('id_warehouse') != -1) + if ((Tools::isSubmit('csv_quantities') || Tools::isSubmit('csv_prices')) && + (int)Tools::getValue('id_warehouse') != -1) $limit = false; $order_by_valuation = false; $order_by_real_quantity = false; + if ($this->context->cookie->{$this->table.'Orderby'} == 'valuation') { unset($this->context->cookie->{$this->table.'Orderby'}); @@ -200,6 +202,7 @@ class AdminStockInstantStateControllerCore extends AdminController parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); $nb_items = count($this->_list); + for ($i = 0; $i < $nb_items; ++$i) { $item = &$this->_list[$i]; diff --git a/controllers/admin/AdminStockManagementController.php b/controllers/admin/AdminStockManagementController.php index cb14e032d..22319e557 100644 --- a/controllers/admin/AdminStockManagementController.php +++ b/controllers/admin/AdminStockManagementController.php @@ -1060,8 +1060,8 @@ class AdminStockManagementControllerCore extends AdminController { $helper->fields_value['id_warehouse_from'] = Tools::getValue('id_warehouse_from', ''); $helper->fields_value['id_warehouse_to'] = Tools::getValue('id_warehouse_to', ''); - $helper->fields_value['usable_from'] = Tools::getValue('usable_from', ''); - $helper->fields_value['usable_to'] = Tools::getValue('usable_to', ''); + $helper->fields_value['usable_from'] = Tools::getValue('usable_from', '1'); + $helper->fields_value['usable_to'] = Tools::getValue('usable_to', '1'); } $this->content .= $helper->generateForm($this->fields_form); diff --git a/controllers/admin/AdminStoresController.php b/controllers/admin/AdminStoresController.php index 03a001d34..ec9175901 100644 --- a/controllers/admin/AdminStoresController.php +++ b/controllers/admin/AdminStoresController.php @@ -296,8 +296,12 @@ class AdminStoresControllerCore extends AdminController if (!($obj = $this->loadObject(true))) return; + + if (file_exists(_PS_TMP_IMG_DIR_.$this->table.'_'.(int)$obj->id.'.'.$this->imageType)) { + @unlink(_PS_TMP_IMG_DIR_.$this->table.'_'.(int)$obj->id.'.'.$this->imageType); + } - $image = ImageManager::thumbnail(_PS_STORE_IMG_DIR_.'/'.$obj->id.'.jpg', $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350, $this->imageType, true); + $image = ImageManager::thumbnail(_PS_STORE_IMG_DIR_.DIRECTORY_SEPARATOR.$obj->id.'.jpg', $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350, $this->imageType, true, true); $days = array(); $days[1] = $this->l('Monday'); @@ -316,7 +320,7 @@ class AdminStoresControllerCore extends AdminController 'latitude' => $this->getFieldValue($obj, 'latitude') ? $this->getFieldValue($obj, 'latitude') : Configuration::get('PS_STORES_CENTER_LAT'), 'longitude' => $this->getFieldValue($obj, 'longitude') ? $this->getFieldValue($obj, 'longitude') : Configuration::get('PS_STORES_CENTER_LONG'), 'image' => $image ? $image : false, - 'size' => $image ? filesize(_PS_STORE_IMG_DIR_.'/'.$obj->id.'.jpg') / 1000 : false, + 'size' => $image ? filesize(_PS_STORE_IMG_DIR_.DIRECTORY_SEPARATOR.$obj->id.'.jpg') / 1000 : false, 'days' => $days, 'hours' => isset($hours_unserialized) ? $hours_unserialized : false ); diff --git a/controllers/admin/AdminSupplyOrdersController.php b/controllers/admin/AdminSupplyOrdersController.php index 7980fb48f..17da45533 100644 --- a/controllers/admin/AdminSupplyOrdersController.php +++ b/controllers/admin/AdminSupplyOrdersController.php @@ -39,6 +39,7 @@ class AdminSupplyOrdersControllerCore extends AdminController { $this->context = Context::getContext(); $this->table = 'supply_order'; + $this->className = 'SupplyOrder'; $this->identifier = 'id_supply_order'; $this->lang = false; @@ -462,6 +463,8 @@ class AdminSupplyOrdersControllerCore extends AdminController $this->_where .= ' AND st.enclosed != 1'; self::$currentIndex .= '&filter_status=on'; } + + $this->list_id = 'orders'; $first_list = parent::renderList(); if (Tools::isSubmit('csv_orders') || Tools::isSubmit('csv_orders_details') || Tools::isSubmit('csv_order_details')) @@ -514,6 +517,8 @@ class AdminSupplyOrdersControllerCore extends AdminController 'href' => self::$currentIndex.'&add'.$this->table.'&mod=template&token='.$this->token, 'desc' => $this->l('Add new template') ); + + $this->list_id = 'templates'; // inits list $second_list = parent::renderList(); @@ -1074,9 +1079,12 @@ class AdminSupplyOrdersControllerCore extends AdminController $this->errors[] = Tools::displayError($this->l('The date you specified cannot be in the past.')); // gets threshold - $quantity_threshold = null; - if (Tools::getValue('load_products') && Validate::isInt(Tools::getValue('load_products'))) - $quantity_threshold = (int)Tools::getValue('load_products'); + $quantity_threshold = Tools::getValue('load_products'); + + if (is_numeric($quantity_threshold)) + $quantity_threshold = (int)$quantity_threshold; + else + $quantity_threshold = null; if (!count($this->errors)) { @@ -1095,15 +1103,14 @@ class AdminSupplyOrdersControllerCore extends AdminController //specific discount check $_POST['discount_rate'] = (float)str_replace(array(' ', ','), array('', '.'), Tools::getValue('discount_rate', 0)); - } // manage each associated product $this->manageOrderProducts(); // if the threshold is defined and we are saving the order - if (Tools::isSubmit('submitAddsupply_order') && $quantity_threshold != null) - $this->loadProducts($quantity_threshold); + if (Tools::isSubmit('submitAddsupply_order') && Validate::isInt($quantity_threshold)) + $this->loadProducts((int)$quantity_threshold); } // Manage state change @@ -1186,7 +1193,7 @@ class AdminSupplyOrdersControllerCore extends AdminController } // updates receipt - if (Tools::isSubmit('submitFiltersupply_order_detail') && Tools::isSubmit('submitBulkUpdatesupply_order_detail') && Tools::isSubmit('id_supply_order')) + if (Tools::isSubmit('submitBulkUpdatesupply_order_detail') && Tools::isSubmit('id_supply_order')) $this->postProcessUpdateReceipt(); // use template to create a supply order @@ -1331,6 +1338,7 @@ class AdminSupplyOrdersControllerCore extends AdminController $this->errors[] = sprintf(Tools::displayError($this->l('Quantity (%d) for product #%d is not valid')), (int)$quantity, (int)$id_supply_order_detail); else // everything is valid : updates { + // creates the history $supplier_receipt_history = new SupplyOrderReceiptHistory(); $supplier_receipt_history->id_supply_order_detail = (int)$id_supply_order_detail; @@ -1362,7 +1370,7 @@ class AdminSupplyOrdersControllerCore extends AdminController // first, converts the price to the default currency $price_converted_to_default_currency = Tools::convertPrice($supply_order_detail->unit_price_te, $supply_order->id_currency, false); - // then, converts the newly calculated price from the default currency to the needed currency + // then, converts the newly calculated pri-ce from the default currency to the needed currency $price = Tools::ps_round(Tools::convertPrice($price_converted_to_default_currency, $warehouse->id_currency, true), @@ -1378,14 +1386,27 @@ class AdminSupplyOrdersControllerCore extends AdminController $price, true, $supply_order->id); - if ($res) // if product has been added + + if (!$res) + $this->errors[] = Tools::displayError($this->l('Something went wrong when adding products to the warehouse.')); + + $location = Warehouse::getProductLocation($supply_order_detail->id_product, + $supply_order_detail->id_product_attribute, + $warehouse->id); + + $res = Warehouse::setProductlocation($supply_order_detail->id_product, + $supply_order_detail->id_product_attribute, + $warehouse->id, + $location ? $location : ''); + + if ($res) { $supplier_receipt_history->add(); $supply_order_detail->save(); $supply_order->save(); } else - $this->errors[] = Tools::displayError($this->l('Something went wrong when adding products to the warehouse.')); + $this->errors[] = Tools::displayError($this->l('Something went wrong when setting warehouse on product record')); } } } @@ -1877,9 +1898,9 @@ class AdminSupplyOrdersControllerCore extends AdminController 'supply_order_warehouse' => (Validate::isLoadedObject($warehouse) ? $warehouse->name : ''), 'supply_order_reference' => $supply_order->reference, 'supply_order_supplier_name' => $supply_order->supplier_name, - 'supply_order_creation_date' => Tools::displayDate($supply_order->date_add, $lang_id, false), - 'supply_order_last_update' => Tools::displayDate($supply_order->date_upd, $lang_id, false), - 'supply_order_expected' => Tools::displayDate($supply_order->date_delivery_expected, $lang_id, false), + 'supply_order_creation_date' => Tools::displayDate($supply_order->date_add,null , false), + 'supply_order_last_update' => Tools::displayDate($supply_order->date_upd,null , false), + 'supply_order_expected' => Tools::displayDate($supply_order->date_delivery_expected,null , false), 'supply_order_discount_rate' => Tools::ps_round($supply_order->discount_rate, 2), 'supply_order_total_te' => Tools::displayPrice($supply_order->total_te, $currency), 'supply_order_discount_value_te' => Tools::displayPrice($supply_order->discount_value_te, $currency), @@ -1980,7 +2001,7 @@ class AdminSupplyOrdersControllerCore extends AdminController */ protected function afterAdd($object) { - if (Tools::getValue('load_products') && Validate::isInt(Tools::getValue('load_products'))) + if (is_numeric(Tools::getValue('load_products'))) $this->loadProducts((int)Tools::getValue('load_products')); $this->object = $object; @@ -2053,7 +2074,7 @@ class AdminSupplyOrdersControllerCore extends AdminController $diff = (int)$threshold - (int)$real_quantity; } - if ($diff > 0) + if ($diff >= 0) { // sets supply_order_detail $supply_order_detail = new SupplyOrderDetail(); @@ -2066,7 +2087,7 @@ class AdminSupplyOrdersControllerCore extends AdminController $supply_order_detail->name = Product::getProductName($item['id_product'], $item['id_product_attribute'], $supply_order->id_lang); $supply_order_detail->ean13 = $item['ean13']; $supply_order_detail->upc = $item['upc']; - $supply_order_detail->quantity_expected = (int)$diff; + $supply_order_detail->quantity_expected = ((int)$diff == 0) ? 1 : (int)$diff; $supply_order_detail->exchange_rate = $order_currency->conversion_rate; $product_currency = new Currency($item['id_currency']); diff --git a/controllers/admin/AdminTabsController.php b/controllers/admin/AdminTabsController.php index 735a41b00..beb37e2f1 100644 --- a/controllers/admin/AdminTabsController.php +++ b/controllers/admin/AdminTabsController.php @@ -159,16 +159,6 @@ class AdminTabsControllerCore extends AdminController ), 'desc' => $this->l('Show or hide menu.') ), - array( - 'type' => 'select', - 'label' => $this->l('Parent:'), - 'name' => 'id_parent', - 'options' => array( - 'query' => $tabs, - 'id' => 'id_tab', - 'name' => 'name' - ) - ) ), 'submit' => array( 'title' => $this->l(' Save '), @@ -176,6 +166,22 @@ class AdminTabsControllerCore extends AdminController ) ); + $display_parent = true; + if (Validate::isLoadedObject($this->object) && !class_exists($this->object->class_name.'Controller')) + $display_parent = false; + + if ($display_parent) + $this->fields_form['input'][] = array( + 'type' => 'select', + 'label' => $this->l('Parent:'), + 'name' => 'id_parent', + 'options' => array( + 'query' => $tabs, + 'id' => 'id_tab', + 'name' => 'name' + ) + ); + return parent::renderForm(); } @@ -324,4 +330,4 @@ class AdminTabsControllerCore extends AdminController } } } -} +} \ No newline at end of file diff --git a/controllers/admin/AdminTagsController.php b/controllers/admin/AdminTagsController.php index 7e7ffcf41..57a158d37 100644 --- a/controllers/admin/AdminTagsController.php +++ b/controllers/admin/AdminTagsController.php @@ -77,8 +77,23 @@ class AdminTagsControllerCore extends AdminController public function postProcess() { if ($this->tabAccess['edit'] === '1' && Tools::getValue('submitAdd'.$this->table)) + { if (($id = (int)Tools::getValue($this->identifier)) && ($obj = new $this->className($id)) && Validate::isLoadedObject($obj)) + { + $previousProducts = $obj->getProducts(); + $removedProducts = array(); + + foreach ($previousProducts as $product) + if (!in_array($product['id_product'], $_POST['products'])) + $removedProducts[] = $product['id_product']; + + if (Configuration::get('PS_SEARCH_INDEXATION')) + Search::removeProductsSearchIndex($removedProducts); + $obj->setProducts($_POST['products']); + } + } + return parent::postProcess(); } diff --git a/controllers/admin/AdminTaxRulesGroupController.php b/controllers/admin/AdminTaxRulesGroupController.php index ac37c2d72..51bfa8896 100644 --- a/controllers/admin/AdminTaxRulesGroupController.php +++ b/controllers/admin/AdminTaxRulesGroupController.php @@ -179,6 +179,15 @@ class AdminTaxRulesGroupControllerCore extends AdminController 'stay' => true ) ); + + if (Shop::isFeatureActive()) + { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association:'), + 'name' => 'checkBoxShopAsso', + ); + } if (!($obj = $this->loadObject(true))) return; @@ -404,7 +413,7 @@ class AdminTaxRulesGroupControllerCore extends AdminController { foreach ($this->selected_states as $id_state) { - if ($tax_rules_group->hasUniqueTaxRuleForCountry($id_country, $id_state)) + if ($tax_rules_group->hasUniqueTaxRuleForCountry($id_country, $id_state, $id_rule)) { $this->errors[] = Tools::displayError('A tax rule already exists for this country/state with tax only behavior'); continue; diff --git a/controllers/admin/AdminThemesController.php b/controllers/admin/AdminThemesController.php index bd210073a..2d0c63706 100644 --- a/controllers/admin/AdminThemesController.php +++ b/controllers/admin/AdminThemesController.php @@ -122,7 +122,7 @@ class AdminThemesControllerCore extends AdminController 'fields' => array( 'PS_LOGO' => array( 'title' => $this->l('Header logo'), - 'desc' => $this->l('Will appear on main page'), + 'desc' => $this->l('Will appear on main page.').' '.$this->l('Recommended height: 52px. Maximum height on default theme: 65px.'), 'type' => 'file', 'thumb' => _PS_IMG_.Configuration::get('PS_LOGO').'?date='.time() ), @@ -614,7 +614,7 @@ class AdminThemesControllerCore extends AdminController $ext = ($field_name == 'PS_STORES_ICON') ? '.gif' : '.jpg'; $logo_name = $logo_prefix.'-'.(int)$id_shop.$ext; - if (Context::getContext()->shop->getContext() == Shop::CONTEXT_ALL || $id_shop == 0 || Shop::isFeatureActive()==false) + if (Context::getContext()->shop->getContext() == Shop::CONTEXT_ALL || $id_shop == 0 || Shop::isFeatureActive() == false) $logo_name = $logo_prefix.$ext; if ($field_name == 'PS_STORES_ICON') diff --git a/controllers/admin/AdminTrackingController.php b/controllers/admin/AdminTrackingController.php index 2ccb0c6ab..d4d35dfc0 100644 --- a/controllers/admin/AdminTrackingController.php +++ b/controllers/admin/AdminTrackingController.php @@ -52,6 +52,9 @@ class AdminTrackingControllerCore extends AdminController public function initContent() { + if ($id_category = Tools::getValue('id_category') && Tools::getIsset('viewcategory')) + Tools::redirectAdmin($this->context->link->getAdminLink('AdminProducts').'&id_category='.(int)$id_category.'&viewcategory'); + $this->_helper_list = new HelperList(); if (!Configuration::get('PS_STOCK_MANAGEMENT')) @@ -74,6 +77,7 @@ class AdminTrackingControllerCore extends AdminController public function getCustomListCategoriesEmpty() { $this->table = 'category'; + $this->list_id = 'empty_categories'; $this->lang = true; $this->className = 'Category'; $this->identifier = 'id_category'; @@ -116,6 +120,7 @@ class AdminTrackingControllerCore extends AdminController return; $this->table = 'product'; + $this->list_id = 'no_stock_products_attributes'; $this->lang = true; $this->identifier = 'id_product'; $this->_orderBy = 'id_product'; @@ -151,8 +156,6 @@ class AdminTrackingControllerCore extends AdminController $this->tpl_list_vars = array('sub_title' => $this->l('List of products with attributes but without available quantities for sale:')); - - return $this->renderList(); } @@ -162,6 +165,7 @@ class AdminTrackingControllerCore extends AdminController return; $this->table = 'product'; + $this->list_id = 'no_stock_products'; $this->className = 'Product'; $this->lang = true; $this->identifier = 'id_product'; @@ -202,13 +206,13 @@ class AdminTrackingControllerCore extends AdminController public function getCustomListProductsDisabled() { $this->table = 'product'; + $this->list_id = 'disabled_products'; $this->className = 'Product'; $this->lang = true; $this->identifier = 'id_product'; $this->_orderBy = 'id_product'; $this->_orderWay = 'DESC'; $this->_filter = 'AND product_shop.`active` = 0'; - $this->list_no_filter = true; $this->tpl_list_vars = array('sub_title' => $this->l('List of disabled products:')); $this->show_toolbar = false; $this->_list_index = 'index.php?controller=AdminProducts'; @@ -265,8 +269,17 @@ class AdminTrackingControllerCore extends AdminController protected function clearFilters() { - if ((Tools::isSubmit('submitResetcategory') && $this->table == 'category' ) || (Tools::isSubmit('submitResetproduct') && $this->table == 'product' )) - $this->processResetFilters(); + if (Tools::isSubmit('submitResetcategory')) + $this->processResetFilters('empty_categories'); + + if (Tools::isSubmit('submitResetproduct')) + $this->processResetFilters('no_stock_products_attributes'); + + if (Tools::isSubmit('submitResetno_stock_products')) + $this->processResetFilters('no_stock_products'); + + if (Tools::isSubmit('submitResetdisabled_products')) + $this->processResetFilters('disabled_products'); } public function clearListOptions() @@ -280,7 +293,6 @@ class AdminTrackingControllerCore extends AdminController $this->_filter = ''; $this->_group = ''; $this->_where = ''; - $this->list_no_filter = true; $this->list_title = $this->l('Product disabled'); } diff --git a/controllers/admin/AdminTranslationsController.php b/controllers/admin/AdminTranslationsController.php index 3456183b3..3bbb11dc0 100644 --- a/controllers/admin/AdminTranslationsController.php +++ b/controllers/admin/AdminTranslationsController.php @@ -127,7 +127,7 @@ class AdminTranslationsControllerCore extends AdminController $this->l('%1$s (Language: %2$s, Theme: %3$s)'), $this->translations_informations[$this->type_selected]['name'], $this->lang_selected->name, - $this->theme_selected + $this->theme_selected ? $this->theme_selected : $this->l('none') ); // Set vars for all forms @@ -353,13 +353,15 @@ class AdminTranslationsControllerCore extends AdminController $items = Language::getFilesList($from_lang, $from_theme, $to_lang, $to_theme, false, false, true); foreach ($items as $source => $dest) { - $bool &= $this->checkDirAndCreate($dest); - $bool &= @copy($source, $dest); - - if (strpos($dest, 'modules') && basename($source) === $from_lang.'.php' && $bool !== false) - $bool &= $this->changeModulesKeyTranslation($dest, $from_theme, $to_theme); + if (!$this->checkDirAndCreate($dest)) + $this->errors[] = sprintf($this->l('Impossible to create the directory "%s".'), $dest); + elseif (!copy($source, $dest)) + $this->errors[] = sprintf($this->l('Impossible to copy "%s" to "%s".'), $source, $dest); + elseif (strpos($dest, 'modules') && basename($source) === $from_lang.'.php' && $bool !== false) + if (!$this->changeModulesKeyTranslation($dest, $from_theme, $to_theme)) + $this->errors[] = sprintf($this->l('Impossible to translate "$dest".'), $dest); } - if ($bool) + if (!count($this->errors)) $this->redirect(false, 14); $this->errors[] = $this->l('A part of the data has been copied but some of the language files could not be found.'); } @@ -426,8 +428,8 @@ class AdminTranslationsControllerCore extends AdminController { $this->exportTabs(); $items = array_flip(Language::getFilesList($this->lang_selected->iso_code, $this->theme_selected, false, false, false, false, true)); - $gz = new Archive_Tar(_PS_TRANSLATIONS_DIR_.'/export/'.$this->lang_selected->iso_code.'.gzip', true); - $file_name = Tools::getCurrentUrlProtocolPrefix().Tools::getShopDomain().__PS_BASE_URI__.'translations/export/'.$this->lang_selected->iso_code.'.gzip'; + $file_name = _PS_TRANSLATIONS_DIR_.'/export/'.$this->lang_selected->iso_code.'.gzip'; + $gz = new Archive_Tar($file_name, true); if ($gz->createModify($items, null, _PS_ROOT_DIR_)); { ob_start(); @@ -440,7 +442,8 @@ class AdminTranslationsControllerCore extends AdminController header('Content-Disposition: attachment; filename="'.$this->lang_selected->iso_code.'.gzip'.'"'); header('Content-Transfer-Encoding: binary'); ob_end_flush(); - @readfile($file_name); + readfile($file_name); + @unlink($file_name); exit; } $this->errors[] = Tools::displayError('An error occurred while creating archive.'); @@ -719,9 +722,8 @@ class AdminTranslationsControllerCore extends AdminController $arr_import_lang = explode('|', Tools::getValue('params_import_language')); /* 0 = Language ISO code, 1 = PS version */ if (Validate::isLangIsoCode($arr_import_lang[0])) { - if ($content = Tools::file_get_contents( - 'http://www.prestashop.com/download/lang_packs/gzip/'.$arr_import_lang[1].'/'.$arr_import_lang[0].'.gzip', false, - @stream_context_create(array('http' => array('method' => 'GET', 'timeout' => 5))))) + $content = Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/gzip/'.$arr_import_lang[1].'/'.Tools::strtolower($arr_import_lang[0]).'.gzip'); + if ($content) { $file = _PS_TRANSLATIONS_DIR_.$arr_import_lang[0].'.gzip'; if ((bool)@file_put_contents($file, $content)) @@ -815,7 +817,7 @@ class AdminTranslationsControllerCore extends AdminController $type_file = substr($file, -4) == '.tpl' ? 'tpl' : 'php'; // Parse this content - $matches = $this->userParseFile($content, $this->type_selected, $type_file); + $matches = $this->userParseFile($content, $this->type_selected, $type_file, $module_name); // Write each translation on its module file $template_name = substr(basename($file), 0, -4); @@ -858,7 +860,7 @@ class AdminTranslationsControllerCore extends AdminController public function clearModuleFiles($files, $type_clear = 'file', $path = '') { // List of directory which not must be parsed - $arr_exclude = array('img', 'js', 'mails'); + $arr_exclude = array('img', 'js', 'mails','override'); // List of good extention files $arr_good_ext = array('.tpl', '.php'); @@ -914,7 +916,7 @@ class AdminTranslationsControllerCore extends AdminController $type_file = substr($file, -4) == '.tpl' ? 'tpl' : 'php'; // Parse this content - $matches = $this->userParseFile($content, $this->type_selected, $type_file); + $matches = $this->userParseFile($content, $this->type_selected, $type_file, $module_name); // Write each translation on its module file $template_name = substr(basename($file), 0, -4); @@ -936,7 +938,6 @@ class AdminTranslationsControllerCore extends AdminController $this->modules_translations[$theme_name][$module_name][$template_name][$key]['trad'] = html_entity_decode($GLOBALS[$name_var][$default_key], ENT_COMPAT, 'UTF-8'); else { - //d(array($module_key, $default_key, $key, $GLOBALS[$name_var])); $this->modules_translations[$theme_name][$module_name][$template_name][$key]['trad'] = ''; $this->missing_translations++; } @@ -983,8 +984,6 @@ class AdminTranslationsControllerCore extends AdminController 'header.inc.php', 'footer.inc.php', 'index.php', - 'login.php', - 'password.php', 'functions.php' ) ) @@ -1057,15 +1056,16 @@ class AdminTranslationsControllerCore extends AdminController * @param $content * @param $type_translation : front, back, errors, modules... * @param string|bool $type_file : (tpl|php) + * @param string $module_name : name of the module * @return return $matches */ - protected function userParseFile($content, $type_translation, $type_file = false) + protected function userParseFile($content, $type_translation, $type_file = false, $module_name = '') { switch ($type_translation) { case 'front': // Parsing file in Front office - $regex = '/\{l\s*s=[\'\"]'._PS_TRANS_PATTERN_.'[\'\"](\s*sprintf=.*)?(\s*js=1)?\s*\}/U'; + $regex = '/\{l\s*s=(?|\'('._PS_TRANS_PATTERN_.')\'|"('._PS_TRANS_PATTERN_.')")(\s*sprintf=.*)?(\s*js=1)?\s*\}/U'; break; case 'back': @@ -1073,9 +1073,9 @@ class AdminTranslationsControllerCore extends AdminController if ($type_file == 'php') $regex = '/this->l\(\''._PS_TRANS_PATTERN_.'\'[\)|\,]/U'; else if ($type_file == 'specific') - $regex = '/translate\(\''._PS_TRANS_PATTERN_.'\'\)/U'; + $regex = '/Translate::getAdminTranslation\(\''._PS_TRANS_PATTERN_.'\'\)/U'; else - $regex = '/\{l\s*s\s*=[\'\"]'._PS_TRANS_PATTERN_.'[\'\"](\s*sprintf=.*)?(\s*js=1)?(\s*slashes=1)?\s*\}/U'; + $regex = '/\{l\s*s\s*=(?|\''._PS_TRANS_PATTERN_.'\'|"'._PS_TRANS_PATTERN_.'")(\s*sprintf=.*)?(\s*js=1)?(\s*slashes=1)?\s*\}/U'; break; case 'errors': @@ -1088,7 +1088,8 @@ class AdminTranslationsControllerCore extends AdminController if ($type_file == 'php') $regex = '/->l\(\''._PS_TRANS_PATTERN_.'\'(, ?\'(.+)\')?(, ?(.+))?\)/U'; else - $regex = '/\{l\s*s=[\'\"]'._PS_TRANS_PATTERN_.'[\'\"](\s*sprintf=.*)?(\s*mod=\'.+\')?(\s*js=1)?\s*\}/U'; + // In tpl file look for something that should contain mod='module_name' according to the documentation + $regex = '/\{l\s*s=(?|\''._PS_TRANS_PATTERN_.'\'|"'._PS_TRANS_PATTERN_.'").*\s+mod=\''.$module_name.'\'.*\}/U'; break; case 'pdf': @@ -1096,7 +1097,7 @@ class AdminTranslationsControllerCore extends AdminController if ($type_file == 'php') $regex = '/HTMLTemplate.*::l\(\''._PS_TRANS_PATTERN_.'\'[\)|\,]/U'; else - $regex = '/\{l\s*s=[\'\"]'._PS_TRANS_PATTERN_.'[\'\"](\s*sprintf=.*)?(\s*js=1)?(\s*pdf=\'true\')?\s*\}/U'; + $regex = '/\{l\s*s=(?|\''._PS_TRANS_PATTERN_.'\'|"'._PS_TRANS_PATTERN_.'")(\s*sprintf=.*)?(\s*js=1)?(\s*pdf=\'true\')?\s*\}/U'; break; } @@ -1454,6 +1455,8 @@ class AdminTranslationsControllerCore extends AdminController $path = $arr_mail_path[$group_name]; if ($module_name) $path = str_replace('{module}', $module_name, $path); + if (!file_exists($path) && !mkdir($path, 0777, true)) + throw new PrestaShopException(sprintf(Tools::displayError('Directory "%s" cannot be created'), dirname($file_path))); file_put_contents($path.$mail_name.'.'.$type_content, $content); } else @@ -1466,12 +1469,10 @@ class AdminTranslationsControllerCore extends AdminController $array_subjects = array(); if (($subjects = Tools::getValue('subject')) && is_array($subjects)) { - $array_subjects['core_and_modules'] = array('translations'=>array(), 'path'=>$arr_mail_path['core_mail'].'lang.php'); - + $array_subjects['core_and_modules'] = array('translations' => array(), 'path' => $arr_mail_path['core_mail'].'lang.php'); foreach ($subjects as $subject_translation) $array_subjects['core_and_modules']['translations'] = array_merge($array_subjects['core_and_modules']['translations'], $subject_translation); } - if (!empty($array_subjects)) foreach ($array_subjects as $infos) $this->writeSubjectTranslationFile($infos['translations'], $infos['path']); @@ -1771,12 +1772,14 @@ class AdminTranslationsControllerCore extends AdminController if (preg_match('#controllers#', $tmp)) { - $parent_class = explode(DIRECTORY_SEPARATOR, $tmp); + $parent_class = explode(DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, $tmp)); $override = array_search('override', $parent_class); if ($override !== false) - $prefix_key = 'Admin'.ucfirst($parent_class[count($parent_class) - 1]); + // case override/controllers/admin/templates/controller_name + $prefix_key = 'Admin'.ucfirst($parent_class[$override + 4]); else { + // case admin_name/themes/theme_name/template/controllers/controller_name $key = array_search('controllers', $parent_class); $prefix_key = 'Admin'.ucfirst($parent_class[$key + 1]); } @@ -2142,32 +2145,37 @@ class AdminTranslationsControllerCore extends AdminController
        '; if (!empty($mails['files'])) { + $topic_already_displayed = array(); foreach ($mails['files'] as $mail_name => $mail_files) { if (array_key_exists('html', $mail_files) || array_key_exists('txt', $mail_files)) { if (array_key_exists($mail_name, $all_subject_mail)) { - $subject_mail = $all_subject_mail[$mail_name]; - $value_subject_mail = isset($mails['subject'][$subject_mail]) ? $mails['subject'][$subject_mail] : ''; - $str_return .= ' -
        - -
        - '.$subject_mail.'
        '; - if (isset($value_subject_mail['trad']) && $value_subject_mail['trad']) - $str_return .= ''; - else - $str_return .= ''; + foreach ($all_subject_mail[$mail_name] as $subject_mail) + { + $subject_key = 'subject['.Tools::htmlentitiesUTF8($group_name).']['.Tools::htmlentitiesUTF8($subject_mail).']'; + if (in_array($subject_key, $topic_already_displayed)) + continue; + $topic_already_displayed[] = $subject_key; + $value_subject_mail = isset($mails['subject'][$subject_mail]) ? $mails['subject'][$subject_mail] : ''; + $str_return .= ' +
        + +
        + '.$subject_mail.'
        '; + if (isset($value_subject_mail['trad']) && $value_subject_mail['trad']) + $str_return .= ''; + else + $str_return .= ''; - if (isset($value_subject_mail['use_sprintf']) && $value_subject_mail['use_sprintf']) - { - $str_return .= ' - '.$value_subject_mail['use_sprintf'].' - '; - } + if (isset($value_subject_mail['use_sprintf']) && $value_subject_mail['use_sprintf']) + $str_return .= ' + '.$value_subject_mail['use_sprintf'].' + '; $str_return .= '
        -
        '; +
        '; + } } else { @@ -2189,12 +2197,11 @@ class AdminTranslationsControllerCore extends AdminController } } else - { - $str_return .= ' -

        '.$this->l('There was a problem getting the mail files.').'
        ' - .sprintf($this->l('English language files must exist in %s folder'), ''.$mails['directory'].'en') - .'

        '; - } + $str_return .= '

        + '.$this->l('There was a problem getting the mail files.').'
        + '.sprintf($this->l('English language files must exist in %s folder'), ''.preg_replace('@/[a-z]{2}(/?)$@', '/en$1', $mails['directory']).'').' +

        '; + $str_return .= '
        @@ -2346,7 +2353,8 @@ class AdminTranslationsControllerCore extends AdminController foreach ($files_by_directiories['php'] as $dir => $files) foreach ($files as $file) - if (Tools::file_exists_cache($dir.$file) && is_file($dir.$file) && !in_array($file, self::$ignore_folder) && preg_match('/\.php$/', $file)) + // If file exist and is not in ignore_folder, in the next step we check if a folder or mail + if (Tools::file_exists_cache($dir.$file) && !in_array($file, self::$ignore_folder)) $subject_mail = $this->getSubjectMail($dir, $file, $subject_mail); // Get path of directory for find a good path of translation file @@ -2402,24 +2410,37 @@ class AdminTranslationsControllerCore extends AdminController */ protected function getSubjectMail($dir, $file, $subject_mail) { - $content = file_get_contents($dir.'/'.$file); - $content = str_replace("\n", ' ', $content); + // If is file and is not in ignore_folder + if (is_file($dir.'/'.$file) && !in_array($file, self::$ignore_folder) && preg_match('/\.php$/', $file)) + { + $content = file_get_contents($dir.'/'.$file); + $content = str_replace("\n", ' ', $content); - if (preg_match_all('/Mail::Send([^;]*);/si', $content, $tab)) - for ($i = 0; isset($tab[1][$i]); $i++) + // Subject must match with a template, therefor we first grep the Mail::Send() function then the Mail::l() inside. + if (preg_match_all('/Mail::Send([^;]*);/si', $content, $tab)) { - $tab2 = explode(',', $tab[1][$i]); - if (is_array($tab2)) - if ($tab2 && isset($tab2[1])) + for ($i = 0; isset($tab[1][$i]); $i++) + { + $tab2 = explode(',', $tab[1][$i]); + if (is_array($tab2) && isset($tab2[1])) { - $tab2[1] = trim(str_replace('\'', '', $tab2[1])); - if (preg_match('/Mail::l\(\''._PS_TRANS_PATTERN_.'\'/s', $tab2[2], $matches)) - $subject_mail[$tab2[1]] = $matches[1]; + $template = trim(str_replace('\'', '', $tab2[1])); + foreach ($tab2 as $tab3) + if (preg_match('/Mail::l\(\''._PS_TRANS_PATTERN_.'\'\)/Us', $tab3.')', $matches)) + { + if (!isset($subject_mail[$template])) + $subject_mail[$template] = array(); + if (!in_array($matches[1], $subject_mail[$template])) + $subject_mail[$template][] = $matches[1]; + } } + } } - - if (!in_array($file, self::$ignore_folder) && is_dir($dir.'/'.$file)) - $subject_mail = $this->getSubjectMail($dir, $file, $subject_mail); + } + // Of if is colder, we scan colder for check if find in folder and subfolder + else if (!in_array($file, self::$ignore_folder) && is_dir($dir.'/'.$file)) + foreach( scandir($dir.'/'.$file ) as $temp ) + $subject_mail = $this->getSubjectMail($dir.'/'.$file, $temp, $subject_mail); return $subject_mail; } @@ -2453,6 +2474,9 @@ class AdminTranslationsControllerCore extends AdminController protected function writeSubjectTranslationFile($sub, $path) { + if (!Tools::file_exists_cache(dirname(path))) + if (!mkdir(dirname(path), 0700)) + throw new PrestaShopException('Directory '.dirname(path).' cannot be created.'); if ($fd = @fopen($path, 'w')) { $tab = 'LANGMAIL'; @@ -2748,4 +2772,4 @@ class AdminTranslationsControllerCore extends AdminController return true; return false; } -} \ No newline at end of file +} diff --git a/controllers/admin/AdminWarehousesController.php b/controllers/admin/AdminWarehousesController.php index 8628f1f52..dc4d2d1ec 100644 --- a/controllers/admin/AdminWarehousesController.php +++ b/controllers/admin/AdminWarehousesController.php @@ -424,7 +424,7 @@ class AdminWarehousesControllerCore extends AdminController $address = new Address($object->id_address); if (Validate::isLoadedObject($address)) { - $address->id_warehouse = $object->id_address; + $address->id_warehouse = (int)$object->id; $address->save(); } diff --git a/controllers/front/AddressController.php b/controllers/front/AddressController.php index 0d5a399c3..eb17888ce 100644 --- a/controllers/front/AddressController.php +++ b/controllers/front/AddressController.php @@ -138,7 +138,7 @@ class AddressControllerCore extends FrontController $this->errors[] = Tools::displayError('This country requires you to chose a State.'); // US customer: normalize the address - if ($address->id_country == Country::getByIso('US')) + if ($address->id_country == Country::getByIso('US') && Configuration::get('PS_TAASC')) { include_once(_PS_TAASC_PATH_.'AddressStandardizationSolution.php'); $normalize = new AddressStandardizationSolution; @@ -303,7 +303,9 @@ class AddressControllerCore extends FrontController $selected_country = (int)$this->_address->id_country; else if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - $array = preg_split('/,|-/', $_SERVER['HTTP_ACCEPT_LANGUAGE']); + // get all countries as language (xy) or language-country (wz-XY) + $array = array(); + preg_match("#(?<=-)\w\w|\w\w(?!-)#",$_SERVER['HTTP_ACCEPT_LANGUAGE'],$array); if (!Validate::isLanguageIsoCode($array[0]) || !($selected_country = Country::getByIso($array[0]))) $selected_country = (int)Configuration::get('PS_COUNTRY_DEFAULT'); } diff --git a/controllers/front/AttachmentController.php b/controllers/front/AttachmentController.php index 47fd32c08..3c5daedda 100644 --- a/controllers/front/AttachmentController.php +++ b/controllers/front/AttachmentController.php @@ -32,6 +32,9 @@ class AttachmentControllerCore extends FrontController if (!$a->id) Tools::redirect('index.php'); + if (ob_get_level()) + ob_end_clean(); + header('Content-Transfer-Encoding: binary'); header('Content-Type: '.$a->mime); header('Content-Length: '.filesize(_PS_DOWNLOAD_DIR_.$a->file)); diff --git a/controllers/front/AuthController.php b/controllers/front/AuthController.php index f5b8563b4..79b09cce6 100644 --- a/controllers/front/AuthController.php +++ b/controllers/front/AuthController.php @@ -43,7 +43,7 @@ class AuthControllerCore extends FrontController parent::init(); if (!Tools::getIsset('step') && $this->context->customer->isLogged() && !$this->ajax) - Tools::redirect('index.php?controller='.(($this->authRedirection !== false) ? url_encode($this->authRedirection) : 'my-account')); + Tools::redirect('index.php?controller='.(($this->authRedirection !== false) ? urlencode($this->authRedirection) : 'my-account')); if (Tools::getValue('create_account')) $this->create_account = true; @@ -85,11 +85,7 @@ class AuthControllerCore extends FrontController $this->assignCountries(); - $active_module_newsletter = false; - if ($module_newsletter = Module::getInstanceByName('blocknewsletter')) - $active_module_newsletter = $module_newsletter->active; - - $this->context->smarty->assign('newsletter', (int)$active_module_newsletter); + $this->context->smarty->assign('newsletter', 1); $back = Tools::getValue('back'); $key = Tools::safeOutput(Tools::getValue('key')); @@ -107,7 +103,9 @@ class AuthControllerCore extends FrontController if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - $array = preg_split('/,|-/', $_SERVER['HTTP_ACCEPT_LANGUAGE']); + // get all countries as language (xy) or language-country (wz-XY) + $array = array(); + preg_match("#(?<=-)\w\w|\w\w(?!-)#",$_SERVER['HTTP_ACCEPT_LANGUAGE'],$array); if (!Validate::isLanguageIsoCode($array[0]) || !($sl_country = Country::getByIso($array[0]))) $sl_country = (int)Configuration::get('PS_COUNTRY_DEFAULT'); } @@ -139,6 +137,9 @@ class AuthControllerCore extends FrontController 'HOOK_CREATE_ACCOUNT_TOP' => Hook::exec('displayCustomerAccountFormTop') )); + // Just set $this->template value here in case it's used by Ajax + $this->setTemplate(_PS_THEME_DIR_.'authentication.tpl'); + if ($this->ajax) { // Call a hook to display more information on form @@ -150,12 +151,11 @@ class AuthControllerCore extends FrontController $return = array( 'hasError' => !empty($this->errors), 'errors' => $this->errors, - 'page' => $this->context->smarty->fetch(_PS_THEME_DIR_.'authentication.tpl'), + 'page' => $this->context->smarty->fetch($this->template), 'token' => Tools::getToken(false) ); die(Tools::jsonEncode($return)); } - $this->setTemplate(_PS_THEME_DIR_.'authentication.tpl'); } /** @@ -329,7 +329,7 @@ class AuthControllerCore extends FrontController { if ($back = Tools::getValue('back')) Tools::redirect(html_entity_decode($back)); - Tools::redirect('index.php?controller='.(($this->authRedirection !== false) ? url_encode($this->authRedirection) : 'my-account')); + Tools::redirect('index.php?controller='.(($this->authRedirection !== false) ? urlencode($this->authRedirection) : 'my-account')); } } } @@ -401,8 +401,8 @@ class AuthControllerCore extends FrontController if (!Tools::getValue('phone') && !Tools::getValue('phone_mobile')) $error_phone = true; } - elseif (((Configuration::get('PS_REGISTRATION_PROCESS_TYPE') || Configuration::get('PS_ORDER_PROCESS_TYPE')) - && (Configuration::get('PS_ORDER_PROCESS_TYPE') && !Tools::getValue('email_create'))) + elseif (((Configuration::get('PS_REGISTRATION_PROCESS_TYPE') && Configuration::get('PS_ORDER_PROCESS_TYPE')) + || (Configuration::get('PS_ORDER_PROCESS_TYPE') && !Tools::getValue('email_create'))) && (!Tools::getValue('phone') && !Tools::getValue('phone_mobile'))) $error_phone = true; elseif (((Configuration::get('PS_REGISTRATION_PROCESS_TYPE') && Configuration::get('PS_ORDER_PROCESS_TYPE') && Tools::getValue('email_create'))) @@ -412,11 +412,11 @@ class AuthControllerCore extends FrontController if ($error_phone) $this->errors[] = Tools::displayError('You must register at least one phone number.'); - + $this->errors = array_unique(array_merge($this->errors, $customer->validateController())); // Check the requires fields which are settings in the BO - $this->errors = array_merge($this->errors, $customer->validateFieldsRequiredDatabase()); + $this->errors = $this->errors + $customer->validateFieldsRequiredDatabase(); if (!Configuration::get('PS_REGISTRATION_PROCESS_TYPE') && !$this->ajax && !Tools::isSubmit('submitGuestAccount')) { @@ -469,10 +469,10 @@ class AuthControllerCore extends FrontController Tools::redirect('index.php?controller=order&multi-shipping='.(int)Tools::getValue('multi-shipping')); // else : redirection to the account else - Tools::redirect('index.php?controller='.(($this->authRedirection !== false) ? url_encode($this->authRedirection) : 'my-account')); + Tools::redirect('index.php?controller='.(($this->authRedirection !== false) ? urlencode($this->authRedirection) : 'my-account')); } else - $this->errors[] = Tools::displayError('An error occurred while creating your account..'); + $this->errors[] = Tools::displayError('An error occurred while creating your account.'); } } @@ -487,7 +487,7 @@ class AuthControllerCore extends FrontController $this->errors = array_unique(array_merge($this->errors, $address->validateController())); // US customer: normalize the address - if ($address->id_country == Country::getByIso('US')) + if ($address->id_country == Country::getByIso('US') && Configuration::get('PS_TAASC')) { include_once(_PS_TAASC_PATH_.'AddressStandardizationSolution.php'); $normalize = new AddressStandardizationSolution; @@ -529,13 +529,13 @@ class AuthControllerCore extends FrontController if (!count($this->errors)) { // if registration type is in one step, we save the address - if (Configuration::get('PS_REGISTRATION_PROCESS_TYPE') || Tools::isSubmit('submitGuestAccount')) + if (Tools::isSubmit('submitAccount') || Tools::isSubmit('submitGuestAccount')) if (!($country = new Country($address->id_country, Configuration::get('PS_LANG_DEFAULT'))) || !Validate::isLoadedObject($country)) die(Tools::displayError()); $contains_state = isset($country) && is_object($country) ? (int)$country->contains_states: 0; $id_state = isset($address) && is_object($address) ? (int)$address->id_state: 0; - if (Configuration::get('PS_REGISTRATION_PROCESS_TYPE') && $contains_state && !$id_state) - $this->errors[] = Tools::displayError('This country requires you to chose a State.'); + if ((Tools::isSubmit('submitAccount')|| Tools::isSubmit('submitGuestAccount')) && $contains_state && !$id_state) + $this->errors[] = Tools::displayError('This country requires you to choose a State.'); else { $customer->active = 1; @@ -545,7 +545,7 @@ class AuthControllerCore extends FrontController else $customer->is_guest = 0; if (!$customer->add()) - $this->errors[] = Tools::displayError('An error occurred while creating your account..'); + $this->errors[] = Tools::displayError('An error occurred while creating your account.'); else { $address->id_customer = (int)$customer->id; @@ -608,7 +608,7 @@ class AuthControllerCore extends FrontController Tools::redirect('index.php?controller=order&multi-shipping='.(int)Tools::getValue('multi-shipping')); // else : redirection to the account else - Tools::redirect('index.php?controller='.(($this->authRedirection !== false) ? url_encode($this->authRedirection) : 'my-account')); + Tools::redirect('index.php?controller='.(($this->authRedirection !== false) ? urlencode($this->authRedirection) : 'my-account')); } } } @@ -688,6 +688,9 @@ class AuthControllerCore extends FrontController */ protected function sendConfirmationMail(Customer $customer) { + if (!Configuration::get('PS_CUSTOMER_CREATION_EMAIL')) + return true; + return Mail::Send( $this->context->language->id, 'account', diff --git a/controllers/front/CartController.php b/controllers/front/CartController.php index a29dcbf39..3e2a69b66 100644 --- a/controllers/front/CartController.php +++ b/controllers/front/CartController.php @@ -33,6 +33,7 @@ class CartControllerCore extends FrontController protected $id_address_delivery; protected $customization_id; protected $qty; + public $ssl = false; protected $ajax_refresh = false; @@ -66,13 +67,13 @@ class CartControllerCore extends FrontController { if (Tools::getIsset('add') || Tools::getIsset('update')) $this->processChangeProductInCart(); - else if (Tools::getIsset('delete')) + elseif (Tools::getIsset('delete')) $this->processDeleteProductInCart(); - else if (Tools::getIsset('changeAddressDelivery')) + elseif (Tools::getIsset('changeAddressDelivery')) $this->processChangeProductAddressDelivery(); - else if (Tools::getIsset('allowSeperatedPackage')) + elseif (Tools::getIsset('allowSeperatedPackage')) $this->processAllowSeperatedPackage(); - else if (Tools::getIsset('duplicate')) + elseif (Tools::getIsset('duplicate')) $this->processDuplicateProduct(); // Make redirection if (!$this->errors && !$this->ajax) @@ -178,7 +179,7 @@ class CartControllerCore extends FrontController if ($this->qty == 0) $this->errors[] = Tools::displayError('Null quantity.'); - else if (!$this->id_product) + elseif (!$this->id_product) $this->errors[] = Tools::displayError('Product not found'); $product = new Product($this->id_product, true, $this->context->language->id); @@ -188,23 +189,43 @@ class CartControllerCore extends FrontController return; } + $qty_to_check = $this->qty; + $cart_products = $this->context->cart->getProducts(); + + if (is_array($cart_products)) + foreach ($cart_products as $cart_product) + { + if ((!isset($this->id_product_attribute) || $cart_product['id_product_attribute'] == $this->id_product_attribute) && + (isset($this->id_product) && $cart_product['id_product'] == $this->id_product)) + { + $qty_to_check = $cart_product['cart_quantity']; + + if (Tools::getValue('op', 'up') == 'down') + $qty_to_check -= $this->qty; + else + $qty_to_check += $this->qty; + + break; + } + } + // Check product quantity availability if ($this->id_product_attribute) { - if (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && !Attribute::checkAttributeQty($this->id_product_attribute, $this->qty)) + if (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && !Attribute::checkAttributeQty($this->id_product_attribute, $qty_to_check)) $this->errors[] = Tools::displayError('There isn\'t enough product in stock.'); } - else if ($product->hasAttributes()) + elseif ($product->hasAttributes()) { $minimumQuantity = ($product->out_of_stock == 2) ? !Configuration::get('PS_ORDER_OUT_OF_STOCK') : !$product->out_of_stock; $this->id_product_attribute = Product::getDefaultAttribute($product->id, $minimumQuantity); // @todo do something better than a redirect admin !! if (!$this->id_product_attribute) Tools::redirectAdmin($this->context->link->getProductLink($product)); - else if (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && !Attribute::checkAttributeQty($this->id_product_attribute, $this->qty)) + elseif (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && !Attribute::checkAttributeQty($this->id_product_attribute, $qty_to_check)) $this->errors[] = Tools::displayError('There isn\'t enough product in stock.'); } - else if (!$product->checkQty($this->qty)) + elseif (!$product->checkQty($qty_to_check)) $this->errors[] = Tools::displayError('There isn\'t enough product in stock.'); // If no errors, process product addition @@ -335,7 +356,8 @@ class CartControllerCore extends FrontController if ($result['customizedDatas']) Product::addCustomizationPrice($result['summary']['products'], $result['customizedDatas']); - die(Tools::jsonEncode($result)); + Hook::exec('actionCartListOverride', array('summary' => $result, 'json' => &$json)); + die(Tools::jsonEncode(array_merge($result, (array)Tools::jsonDecode($json, true)))); } // @todo create a hook elseif (file_exists(_PS_MODULE_DIR_.'/blockcart/blockcart-ajax.php')) diff --git a/controllers/front/CategoryController.php b/controllers/front/CategoryController.php index 33dfc3bf3..f270f0bfb 100644 --- a/controllers/front/CategoryController.php +++ b/controllers/front/CategoryController.php @@ -53,6 +53,8 @@ class CategoryControllerCore extends FrontController public function canonicalRedirection($canonicalURL = '') { + if (Tools::getValue('live_edit')) + return ; if (!Validate::isLoadedObject($this->category) || !$this->category->inShop() || !$this->category->isAssociatedToShop()) { $this->redirect_after = '404'; diff --git a/controllers/front/CmsController.php b/controllers/front/CmsController.php index 75877f647..c5a282b00 100644 --- a/controllers/front/CmsController.php +++ b/controllers/front/CmsController.php @@ -33,6 +33,8 @@ class CmsControllerCore extends FrontController public function canonicalRedirection($canonicalURL = '') { + if (Tools::getValue('live_edit')) + return ; if (Validate::isLoadedObject($this->cms) && ($canonicalURL = $this->context->link->getCMSLink($this->cms))) parent::canonicalRedirection($canonicalURL); else if (Validate::isLoadedObject($this->cms_category) && ($canonicalURL = $this->context->link->getCMSCategoryLink($this->cms_category))) diff --git a/controllers/front/ContactController.php b/controllers/front/ContactController.php index 598258a8d..01941bf4d 100644 --- a/controllers/front/ContactController.php +++ b/controllers/front/ContactController.php @@ -37,15 +37,8 @@ class ContactControllerCore extends FrontController { if (Tools::isSubmit('submitMessage')) { - $fileAttachment = null; - if (isset($_FILES['fileUpload']['name']) && !empty($_FILES['fileUpload']['name']) && !empty($_FILES['fileUpload']['tmp_name'])) - { - $extension = array('.txt', '.rtf', '.doc', '.docx', '.pdf', '.zip', '.png', '.jpeg', '.gif', '.jpg'); - $filename = uniqid().substr($_FILES['fileUpload']['name'], -5); - $fileAttachment['content'] = file_get_contents($_FILES['fileUpload']['tmp_name']); - $fileAttachment['name'] = $_FILES['fileUpload']['name']; - $fileAttachment['mime'] = $_FILES['fileUpload']['type']; - } + $extension = array('.txt', '.rtf', '.doc', '.docx', '.pdf', '.zip', '.png', '.jpeg', '.gif', '.jpg'); + $fileAttachment = Tools::fileAttachment('fileUpload'); $message = Tools::getValue('message'); // Html entities is not usefull, iscleanHtml check there is no bad html tags. if (!($from = trim(Tools::getValue('from'))) || !Validate::isEmail($from)) $this->errors[] = Tools::displayError('Invalid email address.'); @@ -55,9 +48,9 @@ class ContactControllerCore extends FrontController $this->errors[] = Tools::displayError('Invalid message'); else if (!($id_contact = (int)(Tools::getValue('id_contact'))) || !(Validate::isLoadedObject($contact = new Contact($id_contact, $this->context->language->id)))) $this->errors[] = Tools::displayError('Please select a subject from the list provided. '); - else if (!empty($_FILES['fileUpload']['name']) && $_FILES['fileUpload']['error'] != 0) + else if (!empty($fileAttachment['name']) && $fileAttachment['error'] != 0) $this->errors[] = Tools::displayError('An error occurred during the file-upload process.'); - else if (!empty($_FILES['fileUpload']['name']) && !in_array(substr(Tools::strtolower($_FILES['fileUpload']['name']), -4), $extension) && !in_array(substr(Tools::strtolower($_FILES['fileUpload']['name']), -5), $extension)) + else if (!empty($fileAttachment['name']) && !in_array( Tools::strtolower(substr($fileAttachment['name'], -4)), $extension) && !in_array( Tools::strtolower(substr($fileAttachment['name'], -5)), $extension)) $this->errors[] = Tools::displayError('Bad file extension'); else { @@ -152,8 +145,8 @@ class ContactControllerCore extends FrontController $cm = new CustomerMessage(); $cm->id_customer_thread = $ct->id; $cm->message = Tools::htmlentitiesUTF8($message); - if (isset($filename) && rename($_FILES['fileUpload']['tmp_name'], _PS_MODULE_DIR_.'../upload/'.$filename)) - $cm->file_name = $filename; + if (isset($fileAttachment['rename']) && !empty($fileAttachment['rename']) && rename($fileAttachment['tmp_name'], _PS_MODULE_DIR_.'../upload/'.basename($fileAttachment['rename']))) + $cm->file_name = $fileAttachment['rename']; $cm->ip_address = ip2long($_SERVER['REMOTE_ADDR']); $cm->user_agent = $_SERVER['HTTP_USER_AGENT']; if (!$cm->add()) @@ -170,21 +163,18 @@ class ContactControllerCore extends FrontController '{attached_file}' => '-', '{message}' => Tools::nl2br(stripslashes($message)), '{email}' => $from, + '{product_name}' => '', ); - if (isset($filename)) - $var_list['{attached_file}'] = $_FILES['fileUpload']['name']; + if (isset($fileAttachment['name'])) + $var_list['{attached_file}'] = $fileAttachment['name']; $id_order = (int)Tools::getValue('id_order'); - if (isset($ct) && Validate::isLoadedObject($ct)) - { - if ($ct->id_order) - $id_order = $ct->id_order; - $subject = sprintf(Mail::l('Your message has been correctly sent #ct%1$s #tc%2$s'), $ct->id, $ct->token); - } - else - $subject = Mail::l('Your message has been correctly sent'); + $id_product = (int)Tools::getValue('id_product'); + + if (isset($ct) && Validate::isLoadedObject($ct) && $ct->id_order) + $id_order = $ct->id_order; if ($id_order) { @@ -193,14 +183,21 @@ class ContactControllerCore extends FrontController $var_list['{id_order}'] = $id_order; } + if ($id_product) + { + $product = new Product((int)$id_product); + if (Validate::isLoadedObject($product) && isset($product->name[Context::getContext()->language->id])) + $var_list['{product_name}'] = $product->name[Context::getContext()->language->id]; + } + if (empty($contact->email)) - Mail::Send($this->context->language->id, 'contact_form', $subject, $var_list, $from, null, null, null, $fileAttachment); + Mail::Send($this->context->language->id, 'contact_form', ((isset($ct) && Validate::isLoadedObject($ct)) ? sprintf(Mail::l('Your message has been correctly sent #ct%1$s #tc%2$s'), $ct->id, $ct->token) : Mail::l('Your message has been correctly sent')), $var_list, $from, null, null, null, $fileAttachment); else { if (!Mail::Send($this->context->language->id, 'contact', Mail::l('Message from contact form').' [no_sync]', $var_list, $contact->email, $contact->name, $from, ($customer->id ? $customer->firstname.' '.$customer->lastname : ''), $fileAttachment) || - !Mail::Send($this->context->language->id, 'contact_form', $subject, $var_list, $from, null, $contact->email, $contact->name, $fileAttachment)) + !Mail::Send($this->context->language->id, 'contact_form', ((isset($ct) && Validate::isLoadedObject($ct)) ? sprintf(Mail::l('Your message has been correctly sent #ct%1$s #tc%2$s'), $ct->id, $ct->token) : Mail::l('Your message has been correctly sent')), $var_list, $from, null, $contact->email, $contact->name, $fileAttachment)) $this->errors[] = Tools::displayError('An error occurred while sending the message.'); } } @@ -281,12 +278,11 @@ class ContactControllerCore extends FrontController $tmp = $order->getProducts(); foreach ($tmp as $key => $val) $products[$row['id_order']][$val['product_id']] = array('value' => $val['product_id'], 'label' => $val['product_name']); - $orders[] = array('value' => $order->id, 'label' => $order->getUniqReference().' - '.Tools::displayDate($date[0], $this->context->language->id), 'selected' => (int)Tools::getValue('id_order') == $order->id); + $orders[] = array('value' => $order->id, 'label' => $order->getUniqReference().' - '.Tools::displayDate($date[0],null) , 'selected' => (int)Tools::getValue('id_order') == $order->id); } $this->context->smarty->assign('orderList', $orders); $this->context->smarty->assign('orderedProductList', $products); } } -} - +} \ No newline at end of file diff --git a/controllers/front/GetFileController.php b/controllers/front/GetFileController.php index 44dcd8fbe..f39990b4d 100644 --- a/controllers/front/GetFileController.php +++ b/controllers/front/GetFileController.php @@ -270,12 +270,14 @@ class GetFileControllerCore extends FrontController $mimeType = 'application/octet-stream'; } + if (ob_get_level()) + ob_end_clean(); + /* Set headers for download */ header('Content-Transfer-Encoding: binary'); header('Content-Type: '.$mimeType); header('Content-Length: '.filesize($file)); header('Content-Disposition: attachment; filename="'.$filename.'"'); - ob_end_flush(); $fp = fopen($file, 'rb'); while (!feof($fp)) echo fgets($fp, 16384); diff --git a/controllers/front/IdentityController.php b/controllers/front/IdentityController.php index 048a1d07a..7f0eb50b4 100644 --- a/controllers/front/IdentityController.php +++ b/controllers/front/IdentityController.php @@ -57,13 +57,14 @@ class IdentityControllerCore extends FrontController { $email = trim(Tools::getValue('email')); $this->customer->birthday = (empty($_POST['years']) ? '' : (int)$_POST['years'].'-'.(int)$_POST['months'].'-'.(int)$_POST['days']); - $_POST['old_passwd'] = trim($_POST['old_passwd']); + if (isset($_POST['old_passwd'])) + $_POST['old_passwd'] = trim($_POST['old_passwd']); if (!Validate::isEmail($email)) $this->errors[] = Tools::displayError('This email address is not valid'); elseif ($this->customer->email != $email && Customer::customerExists($email, true)) $this->errors[] = Tools::displayError('An account using this email address has already been registered.'); - elseif (empty($_POST['old_passwd']) || (Tools::encrypt($_POST['old_passwd']) != $this->context->cookie->passwd)) + elseif ((!isset($_POST['old_passwd']) || empty($_POST['old_passwd'])) || (Tools::encrypt($_POST['old_passwd']) != $this->context->cookie->passwd)) $this->errors[] = Tools::displayError('The password you entered is incorrect.'); elseif ($_POST['passwd'] != $_POST['confirmation']) $this->errors[] = Tools::displayError('The password and confirmation do not match.'); diff --git a/controllers/front/ManufacturerController.php b/controllers/front/ManufacturerController.php index 1aa4ae22e..dbc2f3b2a 100644 --- a/controllers/front/ManufacturerController.php +++ b/controllers/front/ManufacturerController.php @@ -40,6 +40,8 @@ class ManufacturerControllerCore extends FrontController public function canonicalRedirection($canonicalURL = '') { + if (Tools::getValue('live_edit')) + return ; if (Validate::isLoadedObject($this->manufacturer)) parent::canonicalRedirection($this->context->link->getManufacturerLink($this->manufacturer)); } @@ -113,6 +115,9 @@ class ManufacturerControllerCore extends FrontController { $data = Manufacturer::getManufacturers(true, $this->context->language->id, true, false, false, false); $nbProducts = count($data); + $this->n = abs((int)(Tools::getValue('n', Configuration::get('PS_PRODUCTS_PER_PAGE')))); + $this->p = abs((int)(Tools::getValue('p', 1))); + $data = Manufacturer::getManufacturers(true, $this->context->language->id, true, $this->p, $this->n, false); $this->pagination($nbProducts); foreach ($data as &$item) @@ -129,4 +134,4 @@ class ManufacturerControllerCore extends FrontController else $this->context->smarty->assign('nbManufacturers', 0); } -} +} \ No newline at end of file diff --git a/controllers/front/NewProductsController.php b/controllers/front/NewProductsController.php index 7cf283eba..a438c4826 100644 --- a/controllers/front/NewProductsController.php +++ b/controllers/front/NewProductsController.php @@ -47,6 +47,13 @@ class NewProductsControllerCore extends FrontController $this->productSort(); + // Override default configuration values: cause the new products page must display latest products first. + if (!Tools::getIsset('orderway') || !Tools::getIsset('orderby')) + { + $this->orderBy = 'date_add'; + $this->orderWay = 'DESC'; + } + $nbProducts = (int)Product::getNewProducts( $this->context->language->id, (isset($this->p) ? (int)($this->p) - 1 : null), diff --git a/controllers/front/OrderController.php b/controllers/front/OrderController.php index 37b5d90b8..3704de6d3 100644 --- a/controllers/front/OrderController.php +++ b/controllers/front/OrderController.php @@ -155,14 +155,18 @@ class OrderControllerCore extends ParentOrderController Tools::redirect('index.php?controller=order&step=2'); Context::getContext()->cookie->check_cgv = true; - // Check the delivery option is setted + // Check the delivery option is set if (!$this->context->cart->isVirtualCart()) { if (!Tools::getValue('delivery_option') && !Tools::getValue('id_carrier') && !$this->context->cart->delivery_option && !$this->context->cart->id_carrier) Tools::redirect('index.php?controller=order&step=2'); elseif (!Tools::getValue('id_carrier') && !$this->context->cart->id_carrier) { - foreach (Tools::getValue('delivery_option') as $delivery_option) + $deliveries_options = Tools::getValue('delivery_option'); + if (!$deliveries_options) { + $deliveries_options = $this->context->cart->delivery_option; + } + foreach ($deliveries_options as $delivery_option) if (empty($delivery_option)) Tools::redirect('index.php?controller=order&step=2'); } diff --git a/controllers/front/OrderDetailController.php b/controllers/front/OrderDetailController.php index a53e8422e..a5f9321c1 100644 --- a/controllers/front/OrderDetailController.php +++ b/controllers/front/OrderDetailController.php @@ -73,7 +73,7 @@ class OrderDetailControllerCore extends FrontController $ct->id_contact = 0; $ct->id_customer = (int)$order->id_customer; $ct->id_shop = (int)$this->context->shop->id; - if ($id_product = (int)Tools::getValue('id_product') && $order->orderContainProduct((int)$id_product)) + if (($id_product = (int)Tools::getValue('id_product')) && $order->orderContainProduct((int)$id_product)) $ct->id_product = $id_product; $ct->id_order = (int)$order->id; $ct->id_lang = (int)$this->context->language->id; @@ -114,6 +114,7 @@ class OrderDetailControllerCore extends FrontController if (Tools::getValue('ajax') != 'true') Tools::redirect('index.php?controller=order-detail&id_order='.(int)$idOrder); + $this->context->smarty->assign('message_confirmation', true); } else $this->errors[] = Tools::displayError('Order not found'); diff --git a/controllers/front/OrderFollowController.php b/controllers/front/OrderFollowController.php index a0a62afaa..3c4767c6e 100644 --- a/controllers/front/OrderFollowController.php +++ b/controllers/front/OrderFollowController.php @@ -40,11 +40,12 @@ class OrderFollowControllerCore extends FrontController if (Tools::isSubmit('submitReturnMerchandise')) { $customizationQtyInput = Tools::getValue('customization_qty_input'); + $order_qte_input = Tools::getValue('order_qte_input'); + $customizationIds = Tools::getValue('customization_ids'); + if (!$id_order = (int)(Tools::getValue('id_order'))) Tools::redirect('index.php?controller=history'); - if (!$order_qte_input = Tools::getValue('order_qte_input')) - Tools::redirect('index.php?controller=order-follow&errorDetail1'); - if (!$customizationQtyInput && $customizationIds = Tools::getValue('customization_ids')) + if (!$order_qte_input && !$customizationQtyInput && !$customizationIds) Tools::redirect('index.php?controller=order-follow&errorDetail1'); if (!$customizationIds && !$ids_order_detail = Tools::getValue('ids_order_detail')) Tools::redirect('index.php?controller=order-follow&errorDetail2'); diff --git a/controllers/front/OrderOpcController.php b/controllers/front/OrderOpcController.php index 166afebeb..8b6f6d0a0 100644 --- a/controllers/front/OrderOpcController.php +++ b/controllers/front/OrderOpcController.php @@ -28,6 +28,8 @@ class OrderOpcControllerCore extends ParentOrderController { public $php_self = 'order-opc'; public $isLogged; + + protected $ajax_refresh = false; /** * Initialize order opc controller @@ -199,8 +201,28 @@ class OrderOpcControllerCore extends ParentOrderController } // Address has changed, so we check if the cart rules still apply + $cart_rules = $this->context->cart->getCartRules(); CartRule::autoRemoveFromCart($this->context); CartRule::autoAddToCart($this->context); + if ((int)Tools::getValue('allow_refresh')) + { + // If the cart rules has changed, we need to refresh the whole cart + $cart_rules2 = $this->context->cart->getCartRules(); + if (count($cart_rules2) != count($cart_rules)) + $this->ajax_refresh = true; + else + { + $rule_list = array(); + foreach ($cart_rules2 as $rule) + $rule_list[] = $rule['id_cart_rule']; + foreach ($cart_rules as $rule) + if (!in_array($rule['id_cart_rule'], $rule_list)) + { + $this->ajax_refresh = true; + break; + } + } + } if (!$this->context->cart->isMultiAddressDelivery()) $this->context->cart->setNoMultishipping(); // As the cart is no multishipping, set each delivery address lines with the main delivery address @@ -215,7 +237,8 @@ class OrderOpcControllerCore extends ParentOrderController 'HOOK_TOP_PAYMENT' => Hook::exec('displayPaymentTop'), 'HOOK_PAYMENT' => $this->_getPaymentMethods(), 'gift_price' => Tools::displayPrice(Tools::convertPrice(Product::getTaxCalculationMethod() == 1 ? $wrapping_fees : $wrapping_fees_tax_inc, new Currency((int)($this->context->cookie->id_currency)))), - 'carrier_data' => $this->_getCarrierList()), + 'carrier_data' => $this->_getCarrierList(), + 'refresh' => (bool)$this->ajax_refresh), $this->getFormatedSummaryDetail() ); die(Tools::jsonEncode($result)); @@ -376,6 +399,9 @@ class OrderOpcControllerCore extends ParentOrderController $customer = $this->context->customer; $address_delivery = new Address($this->context->cart->id_address_delivery); + $id_address_invoice = $this->context->cart->id_address_invoice != $this->context->cart->id_address_delivery ? (int)$this->context->cart->id_address_invoice : 0; + $address_invoice = new Address($id_address_invoice); + if ($customer->birthday) $birthday = explode('-', $customer->birthday); else @@ -404,7 +430,21 @@ class OrderOpcControllerCore extends ParentOrderController 'id_gender' => (int)$customer->id_gender, 'sl_year' => $birthday[0], 'sl_month' => $birthday[1], - 'sl_day' => $birthday[2] + 'sl_day' => $birthday[2], + 'id_address_invoice' => $id_address_invoice, + 'company_invoice' => Tools::htmlentitiesUTF8($address_invoice->company), + 'lastname_invoice' => Tools::htmlentitiesUTF8($address_invoice->lastname), + 'firstname_invoice' => Tools::htmlentitiesUTF8($address_invoice->firstname), + 'vat_number_invoice' => Tools::htmlentitiesUTF8($address_invoice->vat_number), + 'dni_invoice' => Tools::htmlentitiesUTF8($address_invoice->dni), + 'address1_invoice' => Tools::htmlentitiesUTF8($address_invoice->address1), + 'address2_invoice' => Tools::htmlentitiesUTF8($address_invoice->address2), + 'postcode_invoice' => Tools::htmlentitiesUTF8($address_invoice->postcode), + 'city_invoice' => Tools::htmlentitiesUTF8($address_invoice->city), + 'phone_invoice' => Tools::htmlentitiesUTF8($address_invoice->phone), + 'phone_mobile_invoice' => Tools::htmlentitiesUTF8($address_invoice->phone_mobile), + 'id_country_invoice' => (int)($address_invoice->id_country), + 'id_state_invoice' => (int)($address_invoice->id_state), ); } @@ -493,7 +533,7 @@ class OrderOpcControllerCore extends ParentOrderController $address_delivery = new Address($this->context->cart->id_address_delivery); $cms = new CMS(Configuration::get('PS_CONDITIONS_CMS_ID'), $this->context->language->id); - $link_conditions = $this->context->link->getCMSLink($cms, $cms->link_rewrite, true); + $link_conditions = $this->context->link->getCMSLink($cms, $cms->link_rewrite); if (!strpos($link_conditions, '?')) $link_conditions .= '?content_only=1'; else @@ -514,7 +554,9 @@ class OrderOpcControllerCore extends ParentOrderController $free_shipping = true; break; } - } + } + + $this->context->smarty->assign('isVirtualCart', $this->context->cart->isVirtualCart()); $vars = array( 'free_shipping' => $free_shipping, @@ -574,13 +616,21 @@ class OrderOpcControllerCore extends ParentOrderController protected function _processAddressFormat() { - $selectedCountry = (int)(Configuration::get('PS_COUNTRY_DEFAULT')); - $address_delivery = new Address((int)$this->context->cart->id_address_delivery); $address_invoice = new Address((int)$this->context->cart->id_address_invoice); $inv_adr_fields = AddressFormat::getOrderedAddressFields((int)$address_delivery->id_country, false, true); $dlv_adr_fields = AddressFormat::getOrderedAddressFields((int)$address_invoice->id_country, false, true); + $requireFormFieldsList = AddressFormat::$requireFormFieldsList; + + // Add missing require fields for a new user susbscription form + foreach ($requireFormFieldsList as $fieldName) + if (!in_array($fieldName, $dlv_adr_fields)) + $dlv_adr_fields[] = trim($fieldName); + + foreach ($requireFormFieldsList as $fieldName) + if (!in_array($fieldName, $inv_adr_fields)) + $inv_adr_fields[] = trim($fieldName); $inv_all_fields = array(); $dlv_all_fields = array(); @@ -591,6 +641,9 @@ class OrderOpcControllerCore extends ParentOrderController foreach (explode(' ', $fields_line) as $field_item) ${$adr_type.'_all_fields'}[] = trim($field_item); + ${$adr_type.'_adr_fields'} = array_unique(${$adr_type.'_adr_fields'}); + ${$adr_type.'_all_fields'} = array_unique(${$adr_type.'_all_fields'}); + $this->context->smarty->assign($adr_type.'_adr_fields', ${$adr_type.'_adr_fields'}); $this->context->smarty->assign($adr_type.'_all_fields', ${$adr_type.'_all_fields'}); } diff --git a/controllers/front/ParentOrderController.php b/controllers/front/ParentOrderController.php index 075198f2f..10e17bb85 100644 --- a/controllers/front/ParentOrderController.php +++ b/controllers/front/ParentOrderController.php @@ -153,8 +153,8 @@ class ParentOrderControllerCore extends FrontController $this->addJqueryPlugin('fancybox'); if ((int)(Configuration::get('PS_BLOCK_CART_AJAX')) || Configuration::get('PS_ORDER_PROCESS_TYPE') == 1) { - $this->addJS(_THEME_JS_DIR_.'cart-summary.js'); $this->addJqueryPlugin('typewatch'); + $this->addJS(_THEME_JS_DIR_.'cart-summary.js'); } } @@ -399,10 +399,12 @@ class ParentOrderControllerCore extends FrontController // Getting a list of formated address fields with associated values $formatedAddressFieldsValuesList = array(); - foreach ($customerAddresses as $address) - { - $tmpAddress = new Address($address['id_address']); + foreach ($customerAddresses as $i => $address) + { + if (!Address::isCountryActiveById((int)($address['id_address']))) + unset($customerAddresses[$i]); + $tmpAddress = new Address($address['id_address']); $formatedAddressFieldsValuesList[$address['id_address']]['ordered_fields'] = AddressFormat::getOrderedAddressFields($address['id_country']); $formatedAddressFieldsValuesList[$address['id_address']]['formated_fields_values'] = AddressFormat::getFormattedAddressFieldsValues( $tmpAddress, @@ -410,6 +412,10 @@ class ParentOrderControllerCore extends FrontController unset($tmpAddress); } + + if (key($customerAddresses) != 0) + $customerAddresses = array_values($customerAddresses); + $this->context->smarty->assign(array( 'addresses' => $customerAddresses, 'formatedAddressFieldsValuesList' => $formatedAddressFieldsValuesList)); @@ -459,6 +465,8 @@ class ParentOrderControllerCore extends FrontController { $address = new Address($this->context->cart->id_address_delivery); $id_zone = Address::getZoneById($address->id); + if (!Address::isCountryActiveById((int)($this->context->cart->id_address_delivery)) || !Address::isCountryActiveById((int)($this->context->cart->id_address_invoice))) + Tools::redirect('index.php?controller=order&step=1'); $carriers = $this->context->cart->simulateCarriersOutput(); $checked = $this->context->cart->simulateCarrierSelectedOutput(); $delivery_option_list = $this->context->cart->getDeliveryOptionList(); @@ -494,7 +502,7 @@ class ParentOrderControllerCore extends FrontController // TOS $cms = new CMS(Configuration::get('PS_CONDITIONS_CMS_ID'), $this->context->language->id); - $this->link_conditions = $this->context->link->getCMSLink($cms, $cms->link_rewrite, false); + $this->link_conditions = $this->context->link->getCMSLink($cms, $cms->link_rewrite); if (!strpos($this->link_conditions, '?')) $this->link_conditions .= '?content_only=1'; else diff --git a/controllers/front/PasswordController.php b/controllers/front/PasswordController.php index 1a7959887..e36d84a9a 100644 --- a/controllers/front/PasswordController.php +++ b/controllers/front/PasswordController.php @@ -36,7 +36,7 @@ class PasswordControllerCore extends FrontController { if (Tools::isSubmit('email')) { - if (!($email = Tools::getValue('email')) || !Validate::isEmail($email)) + if (!($email = trim(Tools::getValue('email'))) || !Validate::isEmail($email)) $this->errors[] = Tools::displayError('Invalid email address.'); else { diff --git a/controllers/front/ProductController.php b/controllers/front/ProductController.php index 0938d1106..2b315a282 100644 --- a/controllers/front/ProductController.php +++ b/controllers/front/ProductController.php @@ -69,6 +69,8 @@ class ProductControllerCore extends FrontController public function canonicalRedirection($canonical_url = '') { + if (Tools::getValue('live_edit')) + return ; if (Validate::isLoadedObject($this->product)) parent::canonicalRedirection($this->context->link->getProductLink($this->product)); } @@ -143,7 +145,8 @@ class ProductControllerCore extends FrontController // Load category if (isset($_SERVER['HTTP_REFERER']) && strstr($_SERVER['HTTP_REFERER'], Tools::getHttpHost()) // Assure us the previous page was one of the shop - && preg_match('!^(.*)\/([0-9]+)\-(.*[^\.])|(.*)id_category=([0-9]+)(.*)$!', $_SERVER['HTTP_REFERER'], $regs)) + && (stripos($_SERVER['HTTP_REFERER'], '.html') === false) + && preg_match('~^(.*)\/([0-9]+)\-((?![.]+html).*)|(.*)id_category=([0-9]+)(.*)$~', $_SERVER['HTTP_REFERER'], $regs)) { // If the previous page was a category and is a parent category of the product use this category as parent category if (isset($regs[2]) && is_numeric($regs[2])) @@ -157,8 +160,7 @@ class ProductControllerCore extends FrontController $this->category = new Category($regs[5], (int)$this->context->cookie->id_lang); } } - else - // Set default product category + if (!isset($this->category)) $this->category = new Category($this->product->id_category_default, (int)$this->context->cookie->id_lang); } } @@ -454,7 +456,7 @@ class ProductControllerCore extends FrontController { if (isset($this->context->smarty->tpl_vars['images']->value)) $product_images = $this->context->smarty->tpl_vars['images']->value; - if (is_array($product_images) && isset($product_images[$id_image])) + if (isset($product_images) && is_array($product_images) && isset($product_images[$id_image])) { $product_images[$id_image]['cover'] = 1; $this->context->smarty->assign('mainImage', $product_images[$id_image]); @@ -463,7 +465,7 @@ class ProductControllerCore extends FrontController } if (isset($this->context->smarty->tpl_vars['cover']->value)) $cover = $this->context->smarty->tpl_vars['cover']->value; - if (is_array($cover) && is_array($product_images)) + if (isset($cover) && is_array($cover) && isset($product_images) && is_array($product_images)) { $product_images[$cover['id_image']]['cover'] = 0; if (isset($product_images[$id_image])) @@ -510,9 +512,12 @@ class ProductControllerCore extends FrontController protected function assignAttributesCombinations() { $attributes_combinations = Product::getAttributesInformationsByProduct($this->product->id); - foreach ($attributes_combinations as &$ac) - foreach ($ac as &$val) - $val = str_replace('-', '_', Tools::link_rewrite(str_replace(array(',', '.'), '-', $val))); + if (is_array($attributes_combinations) && count($attributes_combinations)) + foreach ($attributes_combinations as &$ac) + foreach ($ac as &$val) + $val = str_replace('-', '_', Tools::link_rewrite(str_replace(array(',', '.'), '-', $val))); + else + $attributes_combinations = array(); $this->context->smarty->assign('attributesCombinations', $attributes_combinations); } diff --git a/controllers/front/StatisticsController.php b/controllers/front/StatisticsController.php index b583d284c..e3b9c5c83 100644 --- a/controllers/front/StatisticsController.php +++ b/controllers/front/StatisticsController.php @@ -54,17 +54,17 @@ class StatisticsControllerCore extends FrontController if (sha1($id_guest._COOKIE_KEY_) != $this->param_token) die; - $guest = new Guest($id_guest); + $guest = new Guest((int)substr($_POST['id_guest'],0,10)); $guest->javascript = true; - $guest->screen_resolution_x = (int)Tools::getValue('screen_resolution_x'); - $guest->screen_resolution_y = (int)Tools::getValue('screen_resolution_y'); - $guest->screen_color = (int)Tools::getValue('screen_color'); - $guest->sun_java = (int)Tools::getValue('sun_java'); - $guest->adobe_flash = (int)Tools::getValue('adobe_flash'); - $guest->adobe_director = (int)Tools::getValue('adobe_director'); - $guest->apple_quicktime = (int)Tools::getValue('apple_quicktime'); - $guest->real_player = (int)Tools::getValue('real_player'); - $guest->windows_media = (int)Tools::getValue('windows_media'); + $guest->screen_resolution_x = (int)substr($_POST['screen_resolution_x'],0,5); + $guest->screen_resolution_y = (int)substr($_POST['screen_resolution_y'],0,5); + $guest->screen_color = (int)substr($_POST['screen_color'],0,3); + $guest->sun_java = (int)substr($_POST['sun_java'],0,1); + $guest->adobe_flash = (int)substr($_POST['adobe_flash'],0,1); + $guest->adobe_director = (int)substr($_POST['adobe_director'],0,1); + $guest->apple_quicktime = (int)substr($_POST['apple_quicktime'],0,1); + $guest->real_player = (int)substr($_POST['real_player'],0,1); + $guest->windows_media = (int)substr($_POST['windows_media'],0,1); $guest->update(); } diff --git a/controllers/front/SupplierController.php b/controllers/front/SupplierController.php index 5d39df6d6..78fda9152 100644 --- a/controllers/front/SupplierController.php +++ b/controllers/front/SupplierController.php @@ -41,6 +41,8 @@ class SupplierControllerCore extends FrontController public function canonicalRedirection($canonicalURL = '') { + if (Tools::getValue('live_edit')) + return ; if (Validate::isLoadedObject($this->supplier)) parent::canonicalRedirection($this->context->link->getSupplierLink($this->supplier)); } diff --git a/css/admin.css b/css/admin.css index 4ee837e91..82e20b075 100644 --- a/css/admin.css +++ b/css/admin.css @@ -486,6 +486,7 @@ select optgroup option { border: 1px solid #CC0000; color:#D8000C; } + #content .conf a, #content .warn a, #content .error a { color:#D8000C; font-weight: bold; @@ -498,7 +499,7 @@ select optgroup option { background: #FFBABA url(../img/admin/icon-cancel.png) no-repeat scroll 6px 6px; border: 1px solid #CC0000; color:#D8000C; - padding:20px; + padding:20px 40px; position:fixed; bottom:0; width:100%; @@ -509,7 +510,7 @@ select optgroup option { background: #DFF2BF url(../img/admin/icon-valid.png) no-repeat scroll 6px 6px; border: 1px solid #4F8A10; color:#4F8A10; - padding:20px; + padding:20px 40px; position:fixed; bottom:0; width:100%; @@ -567,6 +568,12 @@ select optgroup option { background: url(../img/admin/warning.gif) no-repeat 0 0; } +#blockNewVersionCheck .warn h3 { + padding: 0 0 0 5px; + margin: 0px; + background: none; +} + #content .error h3 { padding: 0 0 0 20px; background: url(../img/admin/warning.gif) no-repeat 0 0; @@ -1872,6 +1879,7 @@ div.progressBarImage height: 15px; margin-left: 3px; width: 233px; + position:relative; } #showCounter { @@ -2394,3 +2402,269 @@ margin-bottom:7px; min-width: 205px; width: 205px; } + + +/******************** CSS Carrier Wizard ************************/ +#carrier_wizard.swMain { + position:relative; + display:block; + margin:0; + padding:0; + float:left; + min-width: 980px; + width: 100%; +} +#carrier_wizard.swMain .stepContainer { + display:block; + position: relative; + margin: 0; + padding:0; + overflow:hidden; + clear:both; +} +#carrier_wizard.swMain .stepContainer div.content { + width: 100%; + display:block; + position: absolute; + float:left; + margin: 0; + padding: 0; + text-align:left; + overflow:visible; + z-index:88; + clear:both; +} +#carrier_wizard.swMain div.actionBar { + display:block; + position: relative; + clear:both; + padding: 0; + text-align:left; + overflow:auto; + z-index:88; + background-color: #f7f8f7; + border: 1px solid #caccca; + height: 37px; + margin-bottom: 20px; +} +#carrier_wizard.swMain .stepContainer .StepTitle { + display:block; + position: relative; + margin:0; + padding:5px; + clear:both; + text-align:left; + z-index:88; + -webkit-border-radius: 5px; + -moz-border-radius : 5px; +} +#carrier_wizard.swMain ul.anchor { + position: relative; + display:block; + float:left; + list-style: none; + padding: 0; + margin: 0 0 10px 0; + clear: both; + width: 100%; +} + +#carrier_wizard.swMain ul.anchor li{ + position: relative; + display:block; + margin: 0; + padding: 0; + float: left; +} +#carrier_wizard.swMain ul.nbr_steps_4.anchor li{ + width: 25%; +} +#carrier_wizard.swMain ul.nbr_steps_5.anchor li{ + width: 20%; +} +#carrier_wizard.swMain ul.anchor li a { + height: 32px; + display:block; + position:relative; + margin: 0; + padding-right: 25px; + text-decoration: none; + outline-style:none; + z-index:99; + overflow: hidden; +} +#carrier_wizard.swMain ul.anchor li a .stepNumber{ + position:relative; + float:left; + width: 24px; + height: 32px; + text-align: center; + padding:0 5px; + padding-top:0; + font-size: 30px; + line-height: 32px; + color: #fffffe; + text-shadow: none; + font-weight: normal; + font-style: normal; +} +#carrier_wizard.swMain ul.anchor li a .stepDesc{ + position:relative; + text-align: left; + font-size: 15px; + height: 32px; + display: table-cell; + vertical-align: middle; + line-height: 13px; +} +#carrier_wizard.swMain ul.anchor li a.selected{ + color:#F8F8F8; + cursor:text; + background: #404956 url(../img/admin/steps-carrierwizard.png) no-repeat right -32px; +} +#carrier_wizard.swMain ul.anchor li a.done, +#carrier_wizard.swMain ul.anchor li.done.selected a.selected { + position:relative; + color:#FFF; + background: url(../img/admin/steps-carrierwizard.png) right 0 no-repeat #3f4856; + z-index:99; +} +#carrier_wizard.swMain ul.anchor li a.disabled { + cursor:text; + background: url(../img/admin/steps-carrierwizard.png) right -64px no-repeat #cbcccb; + color: #878787; +} +#carrier_wizard.swMain .buttonNext { + display:block; + float:right; + margin:5px 3px 0 3px; + padding:5px; + text-decoration: none; + text-align: center; + width:100px; + color:#FFF; + outline-style:none; + background-color: #5A5655; + border: 1px solid #5A5655; + -moz-border-radius : 5px; + -webkit-border-radius: 5px; +} +#carrier_wizard.swMain .buttonDisabled { + color:#F8F8F8 !important; + background-color: #CCCCCC !important; + border: 1px solid #CCCCCC !important; + cursor:text; +} +#carrier_wizard.swMain .buttonPrevious { + display:block; + float:right; + margin:5px 3px 0 3px; + padding:5px; + text-decoration: none; + text-align: center; + width:100px; + color:#FFF; + outline-style:none; + background-color: #5A5655; + border: 1px solid #5A5655; + -moz-border-radius : 5px; + -webkit-border-radius: 5px; +} +#carrier_wizard.swMain .buttonFinish { + display:block; + float:right; + margin:5px 10px 0 3px; + padding:5px; + text-decoration: none; + text-align: center; + width:100px; + color:#FFF; + outline-style:none; + background-color: #5A5655; + border: 1px solid #5A5655; + -moz-border-radius : 5px; + -webkit-border-radius: 5px; +} +#carrier_logo_block{ + position: absolute; + right: 10px; + padding: 0; + margin: 0; +} +#carrier_wizard.swMain .msgBox { + position:relative; + display:none; + float:left; + margin: 4px 0 0 5px; + padding:5px; + border: 1px solid #FFD700; + background-color: #FFFFDD; + color:#5A5655; + -moz-border-radius : 5px; + -webkit-border-radius: 5px; + z-index:999; + min-width:200px; +} +#carrier_wizard.swMain .msgBox .content { + padding: 0px; + float:left; +} +#carrier_wizard.swMain .msgBox .close { + border: 1px solid #CCC; + border-radius: 3px; + color: #CCC; + display: block; + float: right; + margin: 0 0 0 5px; + outline-style: none; + padding: 0 2px 0 2px; + position: relative; + text-align: center; + text-decoration: none; +} +#carrier_wizard.swMain .msgBox .close:hover{color: #EA8511;border: 1px solid #EA8511;} +#carrier_wizard.swMain ul.anchor li a.done .stepNumber {color: #A9B6C8;text-shadow: none;} +#carrier_wizard.swMain ul.anchor li a.done .stepDesc {color: #A9B6C8;text-shadow: none;} +#carrier_wizard .border_top {border-top:solid 1px #C0C0C0;} +#carrier_wizard .border_bottom {border-bottom:solid 1px #C0C0C0;} +#carrier_wizard .border_left {border-left:solid 1px #C0C0C0;} +#carrier_wizard .border_right {border-right:solid 1px #C0C0C0;} +#carrier_wizard .border_all {border:solid 1px #C0C0C0;} +#carrier_wizard input.field_error {border : solid 1px red; background-color:#FFCCCC;} +#carrier_wizard table td.center {text-align: center} +#carrier_wizard .new_range, #carrier_wizard .validate_range {float: left; margin: 35px 0 0 10px; width: 130px;} +#carrier_wizard tr.fees_all { background: #CCCCCC} +#carrier_wizard #zones_table input[type=text] {width: 45px;} +#carrier_wizard #fieldset_form { min-height: 190px} +#carrier_wizard #zone_ranges label { float: none; width: inherit } +#carrier_wizard #step_carrier_summary label {width: 40px} +#carrier_wizard #step_carrier_summary .margin-form {padding-left: 60px;} +#carrier_wizard #summary_zones, #carrier_wizard #summary_groups, #carrier_wizard #summary_shops {margin-left: 20px; margin-top: 10px; list-style: disc} +#carrier_wizard .ranges_not_follow label {width: inherit; float:none} +#carrier_wizard .ranges_not_follow {width: 300px; margin-bottom: 0} +#carrier_wizard .assoShop { min-height: inherit} + +/*** IE10 ***/ +/*@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { + #carrier_wizard.swMain ul.anchor li a{padding: 3px 19px 3px 19px;} + #carrier_wizard.swMain ul.anchor li{padding-right: 60px;} + #carrier_wizard.swMain ul.nbr_steps_3 li{ min-width: 30%;} + #carrier_wizard.swMain ul.nbr_steps_4 li{ min-width: 21.7%;} + #carrier_wizard.swMain ul.nbr_steps_5 li{ min-width: 16.7%;} + +} +.ie9 #carrier_wizard.swMain ul.anchor li a, +.ie8 #carrier_wizard.swMain ul.anchor li a{padding: 3px 19px 3px 19px;} +.ie9 #carrier_wizard.swMain ul.anchor li, +.ie8 #carrier_wizard.swMain ul.anchor li, +.ie7 #carrier_wizard.swMain ul.anchor li{padding-right: 60px;} +.ie7 #carrier_wizard.swMain ul.anchor li a{padding: 3px 19px 3px 19px;} +.ie9 #carrier_wizard.swMain ul.nbr_steps_3 li, +.ie8 #carrier_wizard.swMain ul.nbr_steps_3 li{ min-width: 30%;} +.ie9 #carrier_wizard.swMain ul.nbr_steps_4 li, +.ie8 #carrier_wizard.swMain ul.nbr_steps_4 li{ min-width: 21.7%;} +.ie9 #carrier_wizard.swMain ul.nbr_steps_5 li, +.ie8 #carrier_wizard.swMain ul.nbr_steps_5 li{ min-width: 16.7%;} +.ie7 #carrier_wizard.swMain ul.nbr_steps_3 li{ width: 312px;} +.ie7 #carrier_wizard.swMain ul.nbr_steps_4 li{ width: 312px;} +.ie7 #carrier_wizard.swMain ul.nbr_steps_5 li{ width: 312px;}*/ diff --git a/discount.php b/discount.php index b01f1e5fa..173f8d5a5 100644 --- a/discount.php +++ b/discount.php @@ -34,4 +34,4 @@ require(dirname(__FILE__).'/config/config.inc.php'); Tools::displayFileAsDeprecated(); -Tools::redirect('index.php?controller=discount'.($_REQUEST ? '&'.http_build_query($_REQUEST, '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file +Tools::redirect('index.php?controller=discount'.((count($_GET) || count($_POST)) ? '&'.http_build_query(array_merge($_GET, $_POST), '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7244ffb36..7bdda3762 100755 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -1,4 +1,4 @@ -2007-2012 PrestaShop +2007-2013 PrestaShop NOTICE OF LICENSE @@ -17,12 +17,519 @@ versions in the future. If you wish to customize PrestaShop for your needs please refer to http://www.prestashop.com for more information. @author PrestaShop SA -@copyright 2007-2012 PrestaShop SA +@copyright 2007-2013 PrestaShop SA @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) International Registred Trademark & Property of PrestaShop SA Release Notes for PrestaShop 1.5 -------------------------------- +#################################### +# v1.5.5.0 - (2013-08-22) # +#################################### + + Fixed bugs: + + [-] Installer : added ob_start() (required with the cookie mode when debug mode is activated) + [-] Installer : fixed clear smarty cache + [-] Installer : changed syntax from $class:func to call_user_func because it seems to be more compliant with old PHP versions + [-] INSTALLER : Force update of PS_LEGACY_IMAGES to 0 + [-] INSTALLER : missing parenthesis in SQL in set_product_suppliers, thanks to @EvaldasUzkuras + [-] INSTALLER : Fix bug while updateing supplier reference, back from https://github.com/PrestaShop/PrestaShop/pull/618 thanks @EvaldasUzkuras + [-] Installer: update leftcolumn alias to enable live_edit on blockmyaccount + [-] INSTALLER : Errors in upgrader + [-] INSTALLER : Fix SQL warnings when upgrading + [-] INSTALLER : fix bug when updating add_new_tab not defined + [-] INSTALLER : Remove warnings + [-] Installer: Fix some sql queries + [-] INSTALLER : Shown index can return empty array + [-] INSTALLER : Prevent crash when populating data, MACOSX OS creates hidden files + [-] INSTALLER : Fix bug #PSCFV-8813 1.4.7.0.sql not uptodate + [-] INSTALLER : Fix bug #PSCFV-8813 missing file PHP:setAllGroupsOnHomeCategory(); + [-] INSTALLER : Create reinsurance_lang when updating from below 1.5.0.13 + [-] INSTALLER : SQL error during upgrade from 1.5.0.13 + [-] INSTALLER : SQL error during upgrade from 1.5.0.9 + [-] INSTALLER : Fix bug #PSCFV-8605 loop on ressource wether than n array + [-] INSTALLER : Fix bug #PSCFI-7075 too short column in PREFIX_webservice_account + [-] INSTALLER : Fix bug #PSCFV-8605 first part, do not affect memeory limit when upgrading if set to -1 + [-] INSTALLER : Fix bug #PSCFV-8750 do not activate disabled module during upgrade + + [-] FO : fixed bad search redirection #PSCFV-10158 + [-] FO : FixBug Missing PS_STOCK_MANAGEMENT smarty variable + [-] FO : fixed html tags that should not appear in blockcategories + [-] FO: Fix quantity discount table display for non default attribute #PSCFV-9942 + [-] FO : FixBug #PSCFV-10058 - Missing required form fields in address format + [-] FO : FixBug #PSCFV-10090 urlencode syntax error - Thanks Duarte + [-] FO : FixBug #PSCFV-10058 Invalid id country after allow to select no country + [-] FO : FixBug CGV does not pop-up in Fancy Box + [-] FO : FixBug generated_date error + [-] FO : input token missplaced in address.tpl + [-] FO : Do not redirect on 301 when POST request + [-] FO :ProductSale::getBestSales() by modified date renders SQL error, thanks @SebSept + [-] FO : expiration date not displayed in email for downloadable product + [-] FO : FixBug No warning message when no carriers available from advanced stock management + [-] Fo : Bad date format in order-detail, merge from https://github.com/PrestaShop/PrestaShop/pull/476 thanks @gbelorgey + [-] FO: fixed bug shopping cart price misplaced - #9971 + [-] FO : Fix bug #PSCFV-9856 could not add Uncombinable cart rules and Minimum amount check badly calculated + [-] FO : Fix bug #PSCFV-9993 could not see product quantity in pack content + [-] FO : Fix bug #PSCFV-9847 Cart Rule not updated when address is updated on Checkout Page + [-] FO : FixBug #PSCFV-9846 Bookmark title escape problem on special language + [-] FO : FixBug #PSCFV-9766 All products in products list for email confirmation with multi-shipping + [-] FO : FixBug Wrong offset in more than one shipping address + [-] FO : FixBug #PSCFV-9961 Remove wishlists icon + [-] FO : FixBug #PSCFV-9951 Syntax error - Thanks to Oleacorner-Olivier B + [-] FO : Force browser language detection in Tools::setCookieLanguage + [-] FO : FixBug #PSCFV-9879 Email confirmation message not present + [-] FO : Prevent unsassigned category id, thans @PrestaCaptainFLAM + [-] FO : fixed pagination for p = 0 #PSCFV-9746 + [-] FO : Removed useless live edit query #PSCFV-9845 + [-] FO : FixBug of total products from supliers and manufacturer + [-] FO : FixBug #PSCFV-8018 All products was counted in manufacturer lsit even if products was set as hidden + [-] FO : FixBug #PSCFV-8018 All products was counted in manufacturer list even hidden products + [-] FO : FixBug #PSCFV-7723 Bad manufacturers list pagination + [-] FO : fixed group query for cart rules #PSCFV-8992 + [-] FO : Fixed partial use of cart rules which does not offer free shipping #PSCFV-9216 + [-] FO : Fix bug #PSCFV-9662 udpate payments means after delete thanks @maofree + [-] FO : Fix bug #PSCFV-9754 do not use back url on cart summary link in steps + [-] FO : fixed useless error when the product id in the URL is not an int #PSCFV-9726 + [-] FO : Fix bug #PSCFV-9021 : bad category id for breadcrumb on product when url rewrite is on + [-] FO : you cannot access the front office with a disabled language anymore #PSCFV-9714 + [-] FO : fixed bad condition in the dispatcher rules + [-] FO : Fix bug #PSCFV-9653 could not return a custom product + [-] FO : could not see old_price_display when specific price on one combination + [-] FO : Bad specific price for a combination // sorry + [-] FO : Bad specific price for a combination + [-] FO : Fix bug #PSCFV-9355 dleete button missing for custo in blockcart + [-] FO : Fix bug #PSCFV-9669, update total price on order-payment + [-] FO :Fix bug #PSCFV-9650 could not see delete href in block cart + [-] FO: OrderHistory - Unclosed tag + [-] FO : added smarty cache to blockcms + [-] FO: Fix #PSCFV-9325 all was included on 301 for root deprecated controllers + [-] FO : fixed remove button for free product in the cart block #PSCFV-8465 + [-] FO : fixed entities issue in javascript alerts #PSCFV-9001 + [-] FO : fixed bug #PSCFV-9388 - newsletter is required error, showing two times + [-] FO : Fix bug #PSCFV-8412 no zipcode for countries when default country has no zip code in adress format + [-] FO : fixed bug #PSCFV-7454 + [-] FO : Css fix on first address and avaibility + [-] FO : Fix one_phone_at_leastphone again when PS_REGISTRATION_PROCESS_TYPE = 1 && PS_ORDER_PROCESS_TYPE =0 + [-] FO : fixed bug #PSCFV-9007 - Best sales query has ambigious column when sorted on date_add + [-] FO : Fix #PSCFV-9414 submitGuestAccount is not submitAccount + [-] FO : #PSCFV-9532 remove hardcoded unidentified group number + [-] FO : Fix bug #PSCFV-9525 escape double quote in address formated fields + [-] FO : Fix #PSCFV-7388 again Instant checkout - State validation + [-] FO : fixed alternative row color on shopping cart summary #PSCFV-9208 + [-] FO: Fixed bug PrestaShop 1.5.4.1 Catalog Mode Display Incorrect Header (mis-aligned) - #PSCFV-9327 + [-] FO : fixed pdf template #PSCFV-9430 + [-] FO: Fix shop restriction on features #PSCFV-7848 + [-] FO : fixed bug #PSCFV-9092 - conflict on the company field during account creation + [-] FO: fixed w3c errors + [-] FO: solved some W3C errors + [-] FO: some W3C errors corrected + [-] FO: Fix no image displayed for products in the cart when it was added from another store in multishop #PSCFV-9385 + [-] FO : In stock sort is now removed when Stock managment is disabled on default theme. Not to be confused for my pull #465, which was for default mobile theme. This is for the default regular theme. + [-] FO : Report of #PSCFI-7240 typos in cms.tpl + [-] FO: http page should be redirected to http when accessed with https #PSCFV-9212 + [-] FO: Fix Category::getSubCategories() default group used #PSCFV-9356 + [-] FO: Fix Order::getOrdersTotalPaid() reference is now a string #PSCFV-9342 + [-] FO : In stock is now removed when Stock managment is disabled Fixes the bug where Stock managment is disabled, it stil show "In Stock" in the sort by list. Added $PS_STOCK_MANAGEMENT to line 64. + [-] FO: Fix Carrier::getDeliveredCountries for multishop #PSCFV-9279 + [-] FO : Fix bug #PSCFV-9171, can not order with a unactivated country + [-] FO: Tools::getMediaServer() should return Tools::getShopDomain() instead of Tools::getHttpHost() #PSCFV-9217 + [-] FO : first_item class don t exist if shopping cart have only one item if shopping cart have only one product, last_item class exist but not first_item because of "else if" after if isset($productLast) + [-] FO: Fix #PSCFV-9057 close output buffer before sending attachment and virtualproducts + [-] FO : Fix bug #PSCFV-8967 large image instead of thickbox when one image + [-] FO: fixed bug: Solved a javascript problem on the new 1.5.4.1 with the full image on product page - PSCFV-8967 + [-] FO: improve some css for RTL language + [-] FO: replace logo on the left (fixed bug RTL language - #PSCFV-8891) + [-] FO : Jqzoom must be enabled to add class jqzoom + [-] FO : removed misleading label on the shipping total #PSCFV-8556 + [-] FO : fixed truncate and entities in the cart block #PSCFV-8870 + + [-] BO : fixed bug when save carrier without range + [-] BO: Fix multishop association for tax rules group - #PSCFV-9967 + [-] BO : fixed bug #PSCFV-10169 - now you can go backward from step 3 to 2 when no ranges are set + [-] BO : fixed bug #PSCFV-10073 - now you can upload carrier logo on windows + [-] BO: Delete from attribute_shop when an attribute group is deleted #PSCFV-9902 + [-] BO : FixBug #PSCFV-10075 remove product attribute image association on delete product attribute + [-] BO : FixBug Preview product url + [-] BO : fixed bug #PSCFV-9782 - live edit bug with multistore + [-] BO : fixed range deletion when press enter on input 'all' on carrier wizard + [-] BO : FixBug #PSCFV-7571 Error checking available product quantity + [-] BO : FixBug update received quantity in suply order + [-] BO : fixed bug #PSCFV-10111 when carrier is free don't display ranges in summary + [-] BO : Added comprehensive error display when prestashop cannot write the .htaccess file + [-] BO :FixBug Suppliers and Warehouses accordion + [-] BO : fixed bug #PSCFV-10096 + [-] BO : fixed bug when carrier is free and change shipping method + [-] BO : fixed bug #PSCFV-10091 - you can now enable all zone in one clic + [-] BO : fixed bug #PSCFV-10033 - disable next step if no range has been added on carrier wizard + [-] BO : fixed multistore thumbnail on product list + [-] BO : FixBug root category listed after list reset + [-] BO : Fix additional quote in live edit template + [-] BO : list of carriers should only contain the active one in AdminProducts + [-] BO : OrderSlip now correctly displays the order slip date, thanks @Jacky75 + [-] BO : Do not display root category bool if addrootcategory not in url + [-] BO : Fix send e-mails updating tracking number Hi, We've fixed some bugs parameters about the Send function of Mail class in the AdminOrdersController.php. Regards, Massimo. + [-] BO : FixBug Multiple list pagination error. + [-] BO : FixBug Manufacturer multilist pagination, filter, order problems and manufacturer address filter exception + [-] BO : FixBug #PSCFV-8311 pagination, filter and order with multilist + [-] BO : Fix bug #PSCFV-8139 bad renderform on errors in AdminStatuses + [-] BO: Fix #PSCFV-9885 catalog price rules edition + [-] BO : FixBug #PSCFV-7839 No invoice file attached to payment email confirmation + [-] BO : Fix warning in AdminAttributesGroups after https://github.com/PrestaShop/PrestaShop/pull/392 + [-] BO : FixBug #PSCFV-7824 No total tax not show in order email confirmation + [-] BO: FixBug #PSCFV-10005 Filter on COUNT field + [-] BO : Fix bug #PSCFV-9990 bad count on list header helper + [-] BO : FixBug #PSCFV-9859 Carriers free shipping inline edit + [-] BO : FixBug #PSCFV-9748 Missing confirmation and update button problem + [-] BO : fixed domain warning + [-] BO : FixBug Install currency on Localization Pack + [-] BO : FixBug Invalid offset when only one error in layout + [-] BO : Fix onchange event on Adminmodules list execption + [-] BO : Fix onchange event on adminmoudlue list execption + [-] BO : FixBug allow_url_fopen on BackOffice home page + [-] BO : fixed bug #PSCFV-9809 - carrier wizard tab access fix + [-] BO : FixBug #PSCFV-9959 file_get_contents error + [-] BO : Fix while of translation, to find in folder if translation exists + [-] BO : FixBug #PSCFV-9965 currency not active by default in Localization pack + [-] BO : fixed some bug on carrier wizard - added tabindex on input - new default carrier img + [-] BO : doesn't match available_fields of AdminImportController - Correct wrong position of available_fields - Add some of available_fields + [-] BO : fixed input action when set fees for all zones in carrier wizard + [-] BO : FixBug #PSCFV-9895 Mal function in products suppliers accordion + [-] BO : FixBug Impossible to remove available date from product attribute + [-] BO : FixBug #PSCFV-9042 Supply orders now accept 0 value to automatically load products + [-] BO : FixBug #PSCFV-9839 Update product warehouse on suply order - thanks @O'Donnell + [-] BO : FixBug #PSCFV-9894 undefined quantity_all_version variable in product.tpl + [-] BO : Fix SQL query when $join_category == false, pull request https://github.com/Captain-FLAM/PrestaShop/commit/d5f75c63b6e21dd87c77a027bf8dd293afb1a94f thanks @Captain-FLAM + [-] BO : Could not find cover when image table corrupted + [-] BO : FixBug #PSCFV-9881 Remove updateCarriersList on zip code blur + [-] BO : FixBug #PSCFV-9878 Wrong login tab order + [-] BO : FixBug #PSCFV-8060 Error getting last quantity and price in stock mouvement + [-] BO : FixBug #PSCFV-8237 Javascript Error setting default supplier + [-] BO : FixBug #PSCFV-9138 Error duplicate product group reduction + [-] BO : FixBug #PSCFV-9251 Meta Tag delete previous + [-] BO : FixBug #PSCFV-9049 Bad actionOrderSlipAdd hook description + [-] BO : FIxBug Correct image language in product + [-] BO : fixed sort by currency exchange rate #PSCFV-9840 + [-] BO : If no nb, get default 8, not 10. + [-] BO : translation copy is now easier #PSCFV-8886 + [-] BO : FixBug #PSCFV-5316 Translation problem in delete button link + [-] BO : FixBug #PSCFV-6140 Pagination link error + [-] BO : FixBug #PSCFV-9723 Exporting quantity in instant stock was not returning all rows + [-] BO : FixBug #PSCFV-8234 Products tags not correctly indexed in search + [-] BO : Bad return value for AdminCountries::processStatus() + [-] BO : FixBug Directory Separator on URL + [-] BO : FixBug #PSCFV-8217 Shop logo image not refresh after change + [-] BO : FixBug #PSCFV-9613 Fix product tax to be shop dependent + [-] BO : FixBug #PSCFV-8287 Breadcrumbs label was wrong + [-] BO : FixBug #PSCFV-8229 Default country value set to manufacturer country Default country value set to manufacturer country Click on manufacturer address line now redirect to manufacturer address edition + [-] BO : FixBug #PSCFV-6365 Missing message confirmation for Images modification in Preferences > Images + [-] BO : Fix bug #PSCFV-9722, do not propose adding root categories in categories when there is only one shop + [-] BO : Use only 0% reduction from category in group + [-] BO: Fix tax rule edition - unique tax rule can't be edited + [-] BO : Fix bug #PSCFV-9395 Missing vertical separation between flags + [-] BO : Fix Bug #PSCFV-9550 Bad URL redirection + [-] BO : Fix bug #PSCFV-9310 bad type for input in helper thankx @Piotr Moćko + [-] BO: Delete specific price after combination deletion && fix SpecificPrice::getByProductId() sql query + [-] BO : fixed charts and grids in multishop #PSCFV-8978 + [-] BO : you can now have different mail topic for one mail template #PSCFV-9617 + [-] BO : added checks on product attributes properties #PSCFV-9703 + [-] BO: display vat number field should not depends of the vatnumber module #PSCFV-9672 + [-] BO : products comments impossible if quantity > 0 The pull request https://github.com/PrestaShop/PrestaShop/pull/219 makes the module not working properly in v1.5.4.1. Indeed, after this change, the OosHook works as expected but now, as the product comments module is attached to the OosHook, comments information is only shown when the product is out of stock! + [-] BO: product supplier price should not be converted on product page #PSCFV-9420 + [-] BO : Fix bug #PSCFV-8666 COD module association no more deleted when restrition on other currency + [-] BO : Fix bug #PSCFV-8619 update order weight when modifying products + [-] BO : fixed bug #PSCFV-9622 + [-] BO: remove old icon into New Version block + [-] BO: Fix manufacturer addresses duplication #PSCFV-9601 + [-] BO : fixed translation and languages issues + [-] BO : fixed addslashes on tpl translations (compatibility between "slashes" and "js" parameters) #PSCFV-9427 + [-] BO : fixed bug #PSCFV-9586 - Unable to sort CMS page in back office + [-] BO: Fix #PSCFV-9455 stock was resetted if adv stock management is enable and product preference is submited on shop context + [-] BO : Fix warnings when product not available in Shop + [-] BO : fixed bug #PSCFV-7921 - Language selector (with flags) cant be translated + [-] BO : fixed bug #PSCFV-7634 - Add non-existent new product to order using autocomplete gives javascript error (data.products is not defined) + [-] BO: This is now not possible to move a tab with id_parent = 0 to an another tab + [-] BO : Fix bug #PSCFV-7353 can not see the thumb for a scene + [-] BO : Fix bug #PSCFV-7353 can not see the thumb for a scenes + [-] BO : remove "utm_*" rules preventing Google services from indexing the shop Google shopping refuses all products having their URL blocked by the robots.txt file + [-] BO : allow partial use for credit slip vouchers #PSCFV-9539 + [-] BO : Fix bug #PSCFV-9264 bad cancel qty when refund / return + [-] BO : missing colspan after update product detail + [-] BO: Stock should not appears on product listing when stock management is disabled #PSCFV-8207 + [-] BO: fixed bug button on module list + [-] BO: fixed bug #PSCFV-9463 + improve some css on BO menu + [-] BO: fixed bug #PSCFV-9461 + [-] BO: fixed bug #PSCFV-7440 + [-] BO : fixed quote issue with magic quote in customization in adminorders #PSCFV-9311 + [-] BO : fixed parsing of discount value in AdminOrders #PSCFV-9481 + [-] BO : Upload image name with trailing slash in name + [-] BO : fixed ajax in permissions tab #PSCFV-7442 + [-] BO : fixed bug #PSCFV-9405 - Delete file of downloadable product when cancel + [-] BO : Fixed permission update #PSCFV-7441 + [-] BO : postcode required in manufacturer address + [-] BO : fixed link in AdminTracking #PSCFV-7409 + [-] BO : fix require path to config.inc.php + [-] BO: Fix #PSCFV-8904 bad id_warehouse is stored on ps_address table + [-] BO: association of product attributes on associating a product to another shop #PSCFV-8735 + [-] BO: Fix #PSCFV-9428 features duplicated with multishop on Feature::getFeatures() + [-] BO: Fix #PSCFV-7763 Re-inject quantities after deleting a product from a order + [-] BO: Addresses are now totally deleted from the database if not used on a order + [-] BO: Fix #PSCFV-6657 translations of overriden admin templates + [-] BO : Fix bug #PNM-788 Loyalty points in adminCustomers when only one order + [-] Bo : Fix #PSCFV-9306 report of #PSCFI-7115 Add a new specific price = faulty validation + [-] BO: Fix combinations duplication on multishop with context all for the product duplication #PSCFV-9020 + [-] BO : Report of #PSCFI-6790 REQUEST_URI badly recorded + [-] BO : Fix bug #PSCFI-7231 strtolower iso_lang for package download link + [-] BO : Fixed unregistered version field for some modules + [-] BO: Fix language deletion with multishop when shops still associate to the language #PSCFV-9244 + [-] BO : fixed bug #PSCFV-9178 - is_color_group is not inserted correctly + [-] BO : Fix bug #PSCFI-6755 "+" in email + [-] BO: Fix PHP warning on orderslip generation without ecotax #PSCFV-8743 + [-] BO : remove deprecated parameter when call Tools::displayDate() + [-] BO : remove deprecated parameter when call Tools::link_rewrite() part 2 + [-] BO : remove deprecated parameter when call Tools::link_rewrite() + [-] BO : Fix #PSCFI-7186 incorrect return in Meta->deleteSelection() + [-] BO: Root category should be the shop category and not the higher category with multiple root and without multishop #PSCFV-8860 + [-] BO : fixed gift deletion when there is no products anymore in the cart + [-] BO: Fix listing exports with image or other empty fields + [-] BO : catch prestashop exception and display smart error messages #PSCFV-9147 + [-] BO : fixed issue with reduction in the category for groups #PSCFV-9101 + [-] BO : Fix "The controller adminnotound is missing or invalid." error when no controller get variable + [-] BO: Ajax Confirmation / padding-left + [-] BO : fixed turkish characters replacement #PSCFV-8968 + [-] BO : fixed potential warning with texture list #PSCFV-9050 + [-] BO : tab cache wasn't emptied on delete #PSCFV-9053 + [-] BO: You can now disable the email sent after account creation + [-] BO : don't show unecessary tpl module translations - complience with documentation + [-] BO: Fix #PSCFV-8179 shop domain used in emails sometimes was for the wrong shop + [-] BO : don't show translation for class/controler overrides when on modules translation page + [-] BO : fixed infinite loop in the categories #PSCFV-8965 + [-] Bo : Admin login loop under Firefox + [-] BO : fixed image import with allow_url_fopen deactivated #PSCFV-8181 + [-] BO : bug in BO translations when Windows OS [-] BO : bug in BO translations when Windows OS Impossible to translate the strings of the back office in the directory override/controllers/admin/... under windows environment. The statement " $parent_class = explode(DIRECTORY_SEPARATOR,..) " returns wrong result under windows environment. because the path name has '/' and '\' chars. $parent_class contains bad values and the string "override" is not found. + [-] BO: Fix #PSCFV-8957 order creation when id_cart=0 is present in database but should normally not happen + [-] BO : fixed automatic creation of email overrides in the template #PSCFV-8785 + [-] BO : fixed error message in language form #PSCFV-8890 + [-] BO : fixed bug #PSCFV-7411 - Store location problem with some longitude values + [-] BO : Fix bug #PSCFI-7141, wrong quantity and sales number in Product Sales, thankx to @Tuan Tran + [-] BO : Fixed display when you translate modules without theme selected + + [-] Classes : fix memcache ext #PSCFV-5225 thanks @up2date + [-] Classes : ModuleFrontController updated. Thank you @codeurWeb + [-] Classes : ModuleFrontController & templates overrides fixed + [-] Classes : Bug fix Validate.php - Error with $mail_name + [-] Classes : SwiftMailer - Fix deprecated preg_replace (PHP 5. 5.0) + [-] Classes : fixed cachefs and memcache classes #PSCFV-5225 thanks @prestalab + [-] Classes : Mail - check instance of link in the context + [-] Classes : Db : Fixed $link + [-] Classes : Db classe fixed (check InnoDB support MySQL >= 5.6) + + [-] Core: Fix language link with multishop from another shop #PSCFV-10063 + [-] CORE : Do not delete index.php in smarty cache or /img/tmp/ + [-] Core: Fix #PSCFV-8887 - improve performance of search indexation + [-] CORE : Fix bug #PSCFV-8542 could not have rewrited link for modules in blocklanguage + [-] CORE : getModuleLink not working on module custom route, merge from https://github.com/PrestaShop/PrestaShop/pull/487 thanks @zimmi1 + [-] CORE : Addslashes on not translated strings for javascript js=1 + [-] CORE : Fix for field validation in ObjectModel::validateFieldsLang() when default lang value not set, thanks @rimas-kudelis + [-] CORE : Cast product price to float instead of int when adding supplier reference, thanks @rimas-kudelis + [-] CORE : Merge from PrestaEdit last pull request again + [-] CORE : Fix warning #PSCFV-9678 when sending message to customer + [-] CORE : Fix bug #PSCFV-9572 when seizing in 0 in forms input fields for objects + [-] CORE: Copy live_edit bool when register alias hook + [-] CORE: No category in url preview on BO product page + [-] Core: ObjectModel::toggleStatus should change only active field on multishop with global context #PSCFV-9707 + [-] Core: Fix #PSCFV-9652 too much payments for multishipping orders + [-] CORE : fixed bug #PSCFV-8745 Contact form e-mail template with incomplete information + [-] CORE : fixed bug #PSCFV-9460 + [-] CORE: Fix bug #PSCFV-9474 missing unity and unit_price_ratio in Cart::getProducts + [-] CORE : fixed #PSCFV-7451 - error in classes Carrier + [-] CORE : Report of https://github.com/PrestaShop/PrestaShop/pull/504 Thanks @aseques + [-] CORE : CartRule::checkProductRestrictions : A gift product in the same category as its restrictions causes the gift to stay in the cart even if emptied + [-] CORE : fixed bug #PSCFV-9121 - virtual product does not have link after upgrade - part 2 + [-] CORE : fixed bug #PSCFV-9121 - virtual product does not have link after upgrade + [-] Core: Hook actionPaymentConfirmation should also be called for PS_OS_WS_PAYMENT order statuse + [-] CORE : Report of https://github.com/PrestaShop/PrestaShop-1.4/commit/ec8deb289185daa03cd11d239797bbe5bdbaecd0 + [-] CORE : Report of https://github.com/PrestaShop/PrestaShop-1.4/commit/a6e8a2eda7fe3bab5245df9b98df7b2f6f7d541f + [-] Core : fixed URL regexp #PSCFV-8986 + [-] Core: Fix StockManager::getProductRealQuantities() per warehouse with some orderstatuses #PSCFV-9219 + [-] CORE: Fix #PSCFV-9185 Wrong product price display on list by manufacturer Added default_on condition on getProducts() query in Manufacturer class. + [-] CORE : Fix bug #PSCFI-7168 cast and truncate POST values for statistics.php controller + [-] CORE : TRACKING_DIRECT_TRAFFIC not respected + [-] CORE : referer keywords truncated before insertion in connections table + [-] CORE : Fix bug #PSCFI-7072 redundant configuration get + [-] Core: Fix StockManager::getProductRealQuantities() for refunded quantities on non delivered orders + [-] Core: Fix specific prices if they are configured to count quantity per product and not per combination + [-] CORE : fixed PHP Notice: Undefined index: date_expiration on virtual product + + [-] MO : fixed smarty cache on blocksearch #PSCFV-8739 + [-] MO : multilines translations does not work #PNM-1645 + [-] MO : sendtofriend FixBug Form error + [-] MO : fixed potential warning in pscleaner #PSCFV-10070 + [-] MO: no more 1.4 support for blocklayered + [-] MO : fixed bug #PNM-792 : remove unused js file in blocklayered + [-] MO : fixed category link on blocklayered #PNM-1427 + [-] MO : blocklayered also try to find the translations in the translations directory + [-] MO : added `visibility` IN ("both", "catalog") in blocklayered + [-] MO : fixed module upgrade with common version number + [-] MO: cover image issue with layered block on multishop, thanks @theginie + [-] MO : My account column block should not display module icon in list + [-] MO : blocktopmenu should clear cache when adding a new subcategory + [-] MO : Missing image in my account for MODULE WishList + [-] MO : mod='blockmyaccount' missing in blockmyaccountfooter.tpl + [-] MO : mod='blockmyaccount' missing in blockmyaccountfooter.tpl (translation doesnt work), thanks @mypresta-eu + [-] MO : Fix sort order for combinations, report of pull request https://github.com/PrestaShop/PrestaShop/pull/364 + [-] MO : blockviewed Fix bug adding last product to list, thanks @kluevandrew + [-] MO : Fix bug discount display in mail, manual merge from https://github.com/202-ecommerce/PrestaShop/commit/1d5df338c46aef723d13aef3e213792df6ea92e2 + [-] MO : fixed disappearing form in sekeyword #PSCFV-9743 + [-] MO : Followup : don't send emails for empty carts thanks @axometeam + [-] MO : fixed bad redirection in trackingfront #PSCFV-8378 + [-] MO : Bug fix - PS Cleaner, check if module favoriteproducts is installed. Fix Bug when favoriteproducts is not install. + [-] MO: exec hook on hook registration #PSCFV-8977 + [-] MO : fixed bug #PSCFV-5724 - 1.5.2.0 cms block error when adding more than one column to the categories block in the footer + [-] MO : fixed bug #PSCFV-8654 - 1.5.4.0 My Favorites doesn't add product + [-] MO : fixed bug #PSCFV-9040 - Block CMS Multishop bug + [-] MO : fixed bug #PSCFV-8910 - Productcomments module allows post only one comment per product + [-] MO : do not check the VAT number if the module is disabled #PSCFV-9397 + [-] MO : removed doubled "/" in homeslider template #PSCFV-9439 + [-] MO : fixed editorial issue when the entity does not exist yet for a shop #PSCFV-9442 + [-] MO : do not truncate order return state in pscleaner #PSCFV-9431 + [-] MO : loyalty small smarty fix #PNM-1305 + [-] MO : Fixed double creation of vouchers in loyalty and some redirections #PNM-1317 + [-] MO : Followup : Don't send followup vouchers to guest accounts + [-] MO : Followup : Don't execute crontasks if the module is disabled + [-] MO : Report of #PNM-1413 when alert already set on default combination + [-] MO: Fix newsletter module mail like newsletter_voucher.html - Edit html/css/translation for newsletter_conf.html and newsletter_verif.html - Use {color} variable + [-] MO: Fix sendtoafriend module #PSCFV-8340 http://code.google.com/p/jquery-json/issues/detail?id=43 + [-] MO : Remove link "Notify me when available" when in stock + [-] MO: Fix double html entities on link edition in the blocktopmenumodule #PSCFV-8808 + [-] MO: Don't make unnecessary request to ajax cart + [-] MO: Fix #PSCFV-8973 product images in the blockviewed module + [-] MO : Fix bug #PSCFI-7055 do not relay on ".html" in referer to find previous category + [-] MO: blockcart ajax cart product insert missing html class Added the same HTML class as the other product names have in the ajax cart. Perhaps it would be nice to add an added_from_ajax as well in case you would want to differ between the newly added items and previously added ones? Another potential issue is on line 445 where there is no space after the insert. If Prestashop is set to minify the normal page, this is correct, otherwise there will be a space missing. + [-] MO : fixed hug #PSCFV-8994 - clear cache when truncate catalog + [-] MO : fixed bug #PSCFV-7703 - Images for bank wire, cheque and cash payment missing on Order Summary + + [-] WS: Fix retrieve of stock_availables when stock is shared on the shop group + [-] WS: add id_address_delivery on cart products association + [-] WS: Sanity check before creating packs As it is before this commit, every product that is created from the schema without removing the empty bundle item in the schema will become a pack containing one broken item. Sorry, this bug was introduced by my previous pull request. + [-] WS: Enable feature request #PSCFV-5581, thanks @codl for pull request #593 + [-] WS: do not escape shop name overzealously + [-] WS : fixed ?schema=blank (performance issue) + [-] WS: Fix accessories duplication on product update + [-] WS: Fix webservice sort for multishop fields #PSCFV-5634 + [-] WS: Fix #PSCFI-7009 product prices on orders with specific prices + [-] WS: Fix deletion of product_features on product update #PSCFI-6740 + [-] WS: Fix memory leak when getting synopsis + + [-] PDF : Fix columns error + [-] PDF : Fix dejavusans font for en lang + + [-] TR : fixed missing space in RMA PDF + + Improved/changed features: + + [*] Installer : added cookie mode instead of session for the installer + [*] Installer: you can now choose to send an email to the administrator after installation with php-cli + + [*] Security : deny access to this folder as already done for classes + + [*] FO : added chinese/japanese search + [*] FO : Add reference sort to theme + [*] FO : Blur for tab navigation, followup a0ee3d3, thanks @Seynaeve + [*] FO : Blur for tab navigation, followup a0ee3d3c34b7fc5d149228197be382af59a49e47, thanks @Seynaeve + [*] FO : Fix bug #PSCFV-9611, autocomplete to off on opc page and other pages + [*] FO : updated Fancybox plug-in + [*] FO : a few more SQL improvements + [*] FO : lots of performance improvements (removed or merged useless SQL queries) + [*] FO: display Error500 if no database access Sometimes, we have some problems with the MySQL Database and a Fatal Error is done. With this, we show the error500 template. + [*] FO : getCatImageLink doesn't work without type thanks @axometeam + [*] FO : Retrieve invoice address in OPC + guest checkout, thanks @Piotr Moćko + [*] FO : Fix bug #PSCFV-9440 add another address in guest checkout in OPC + [*] FO : removed code specific to multishipping from the no-multishipping process + [*] FO : added smarty cache on productscategory + [*] FO : added smarty cache on crossselling module + [*] FO : improved entity links retrieval (no need to instanciate an object when there is no need... to instanciate un object) + [*] FO : added smarty cache to blockspecials + [*] FO : added smarty cache on blockbestsellers + [*] FO : added smarty cache on homefeatured module + [*] FO : added smarty cache on blocknewproducts + [*] FO: Don't make useless ajax requests to blockcart on the cart page + [*] FO : AuthController can now have its own template + [*] FO: use Tools::fileAttachment() in ContactController + + [*] BO: Warehouse name is now displayed on each product line orders + [*] BO : Clear smarty cache when submitting SEO rules + [*] BO : Add clear smarty cache button + [*] BO: Add reference to Options + [*] BO: Add reference to FrontController + [*] BO : Do not insert duplicates in product_carrier, thanks @edamart + [*] BO : Do not insert duplicates in poruct_carrier, thanks @edamart + [*] BO : Add filter choices in title of List, thankx to @ccauw + [*] BO : refact for modules exeptions regarding https://github.com/PrestaShop/PrestaShop/pull/614 + [*] BO : Fix statistics redirection when change date When going into a special stats module (for exemple "statsproduct") if you change the date, Prestashop redirect to the "home" of statistics. + [*] BO : shipping enlarge listbox carriers enlarge listbox carriers to see all the name of the carrier + [*] BO : skip the first line by default All sample csv file use a first line of information + [*] BO : Proposition : IMPROVEMENT Admin Modules Positions You can see in action over there : http://www.youtube.com/watch?v=e7KXuCU3RIM + [*] BO: Add an option to allow iframes on descriptions + [*] BO : #PSCFV-8498 You can now use 0% in groups category rules in order to not apply discount on this category + [*] BO : Not increment stock if statut change fom Error to Canceled Not increment stock if statut change fom Error => Canceled or Canceled => Error (stock should stay the same). Add a code simplification too + [*] BO : Correct the getList() request for quantity and id_product Quantity and Id_product should be fixe as Int, else the Mysql request do something like : quantity LIKE "%0%" When an admin key-in quantity as 0, he want product with quantity as 0, not as 0 / 10 /20 / 30... ect (The same for id_product) + [*] BO : improved unicode characters replacement in URLs + [*] BO : Fix #PSCFV-8504 carrier on invoice and delivery slip + [*] BO : Correct Request Sql Manager validate options Correct Request Sql Manager validate options : - No size limit for the request - cutJoin() doesn't work for multiple Join (exemple : LEFT JOIN `XXX ON XXX AND XXX) => Then you can't save the request, even if it work + [*] BO : AdminControllers : Keep active filter on pagination + [*] BO: more than one image in HelperForm + [*] BO : Reselect current step in AdminOrders + [*] BO : Enable current subtab active class + [*] BO : attributes taken into account for the language entity in the localization packs + [*] BO: use Translate::getAdminTranslation instead of translate() + [*] BO: hook displayAdminForm / add param fieldset + + [*] CORE : Allow external css loading, manual merge of https://github.com/PrestaShop/PrestaShop/pull/406 thanks @m-hume + [*] CORE : Fix bug #PSCFV-9811 doc on display404Error + [*] Core: that is now easier to get links for another shop + [*] Core : Smarty updated from 3.1.13 to 3.1.14 (cache issues fixed) + [*] CORE: can not delete class_index.php + [*] Core: you can now pass a query string with php-cli which will merged with for cronjobs and other things + + [*] MO : added manufactureres order by name, thanks@Jacky75 + [*] MO : Templates overrides works with the new structure (/views/templates/admin|front|hook) + [*] MO : Added customer and product object to hook sending email + [*] MO : added configuration cleaning to pscleaner + [*] MO : you can now exclude IP addresses from the online visitors module #PSCFV-9056 + [*] MO : pscleaner reset employees notyfications pscleaner afetr truncating orders, messages and customers reset also employees notyfications + [*] MO : blocklayered optimization + [*] MO : Followup https://github.com/runningz/PrestaShop/commit/040ff3396ac32a1cc35d4d2464e8d36486cac418 + [*] MO : blockcart - simpler selectors + [*] MO: Add smarty cache on blocksupplier and blockmanufacturer + [*] MO: blockcart animation optimization The animated element would not be removed upon the animation being finished. This made the site slow and unresponsive if the animated image was heavy (eg. a transparent png) and added to cart many times without reloading the page. This addition makes the animation behave as expected also when performing it multiple times. + + [*] WS : order history add(POST) send customer email if sendemail=1 url parameter, thanks @gerdus + [*] WS : improved performances + [*] WS : improved web service performances + + [*] PDF : Free shipping in invoice PDF display X2 thanks @axometeam + [*] PDF : Small column width fix + + [*] TR : Added 10 new localization packs + + [*] LO: Improved Argentina Localization Pack + [*] LO : corrected Israel standard tax rate + [*] LO : Fixed units in Belgium localization pack + [*] LO : Fix PSCFV-9330 (decimals=2) + [*] LO : Updated it & nl localization files + + Added Features: + + [+] BO: Add a wizard to create and edit your carriers + [+] BO: Addition, deletion and edition are now logged + [+] BO: Fix Bug Progress Bar Upload Image Product Lorsque l'on ajoute des images a des produits, la barre de progression s'affiche en dehors de son cadre. "position:relative" n'est pas présent pour "div.progressBarImage" dans le fichier admin.css . ---- When we add pictures to products, the progress bar is out of his wrapper. "position:relative" is missing for "div.progressBarImage" in admin.css file. + + [+] CORE : new jquery UI version (1.10.3) + + [+] TR: Created file structure for Dutch installer + + #################################### # v1.5.4.1 - (2013-04-25) # #################################### @@ -7578,4 +8085,4 @@ Release Notes for PrestaShop 1.5 [+] SQL : add the replication SQL -Release Notes for PrestaShop 1.3 +Release Notes for PrestaShop 1.3 \ No newline at end of file diff --git a/docs/csv_import/products_import.csv b/docs/csv_import/products_import.csv index b49f79225..7253bc2eb 100644 --- a/docs/csv_import/products_import.csv +++ b/docs/csv_import/products_import.csv @@ -1,3 +1,3 @@ -id;Active (0/1);Name*;Categories (x,y,z,...);Price tax excl. Or Price tax excl;Tax rules id;Wholesale price;On sale (0/1);Discount amount;Discount percent;Discount from (yyy-mm-dd);Discount to (yyy-mm-dd);Reference #;Supplier reference #;Supplier;Manufacturer;EAN13;UPC;Ecotax;Weight;Quantity;Short description;Description;Tags (x,y,z,...);Meta-title;Meta-keywords;Meta-description;URL rewritten;Text when in-stock;Text if back-order allowed;Image URLs (x,y,z,...);Feature;Only available online -1;1;iPod Nano;Home, iPods;49;1;;1;;;;;92458844;54778855;AppleStore;Apple Computer, Inc;;;;0.5;800;New design. New features. Now i….;Curved ahead of the curve. For those about to rock, we give you nine amazing colors. But that's only part of the story. Feel the curved, all-aluminum and glass de...;apple, ipod, nano;;;;ipod-nano;In stock;;http://youdomain.com/img.jpg, http://yourdomain.com/img1.jpg;; -2;1;iPod shuffle;Home, iPods;66.05;1;79;1;;;;;92458845;54778855;AppleStore;Apple Computer, Inc;;;;0;500;iPod shuffle, the world’s most wearabl….;;ipod, shuffle;;;;ipod-shuffle;In stock;;http://youdomain.com/img25.jpg, http://yourdomain.com/img30.jpg;; \ No newline at end of file +id;Active (0/1);Name*;Categories (x,y,z,...);Price tax excl. Or Price tax excl;Tax rules id;Wholesale price;On sale (0/1);Discount amount;Discount percent;Discount from (yyy-mm-dd);Discount to (yyy-mm-dd);Reference #;Supplier reference #;Supplier;Manufacturer;EAN13;UPC;Ecotax;Weight;Quantity;Short description;Description;Tags (x,y,z,...);Meta-title;Meta-keywords;Meta-description;URL rewritten;Text when in-stock;Text if back-order allowed;Available for order (0 = No, 1 = Yes);Product creation date;Show price (0 = No, 1 = Yes);Image URLs (x,y,z,...);Delete existing images (0 = No, 1 = Yes);Feature (Name:Value:Position);Available online only (0 = No, 1 = Yes);Condition (new,used,refurbished);ID / Name of shop +1;1;iPod Nano;Home, iPods;49;1;;1;;;;;92458844;54778855;AppleStore;Apple Computer, Inc;;;;0.5;800;New design. New features. Now i….;Curved ahead of the curve. For those about to rock, we give you nine amazing colors. But that's only part of the story. Feel the curved, all-aluminum and glass de...;apple, ipod, nano;;;;ipod-nano;In stock;Out stock;1;;1;http://youdomain.com/img.jpg, http://yourdomain.com/img1.jpg;1;;0;new;1 +2;1;iPod shuffle;Home, iPods;66.05;1;79;1;;;;;92458845;54778855;AppleStore;Apple Computer, Inc;;;;0;500;iPod shuffle, the world’s most wearabl….;;ipod, shuffle;;;;ipod-shuffle;In stock;Out stock;1;;1;http://youdomain.com/img25.jpg, http://yourdomain.com/img30.jpg;1;;0;new;1 diff --git a/docs/readme_de.txt b/docs/readme_de.txt index c5038ba98..829309cc7 100755 --- a/docs/readme_de.txt +++ b/docs/readme_de.txt @@ -21,8 +21,8 @@ needs please refer to http://www.prestashop.com for more information. @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) International Registered Trademark & Property of PrestaShop SA -NAME: Prestashop 1.5.4.1 -VERSION: 1.5.4.1 +NAME: Prestashop 1.5.5.0 +VERSION: 1.5.5.0 VORBEREITUNG =========== diff --git a/docs/readme_en.txt b/docs/readme_en.txt index 8fd02b40c..52e111108 100755 --- a/docs/readme_en.txt +++ b/docs/readme_en.txt @@ -21,8 +21,8 @@ needs please refer to http://www.prestashop.com for more information. @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) International Registered Trademark & Property of PrestaShop SA -NAME: Prestashop 1.5.4.1 -VERSION: 1.5.4.1 +NAME: Prestashop 1.5.5.0 +VERSION: 1.5.5.0 PREPARATION =========== diff --git a/docs/readme_es.txt b/docs/readme_es.txt index dd37179d4..c67c99b47 100755 --- a/docs/readme_es.txt +++ b/docs/readme_es.txt @@ -21,8 +21,8 @@ needs please refer to http://www.prestashop.com for more information. @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) International Registered Trademark & Property of PrestaShop SA -NAME: Prestashop 1.5.4.1 -VERSION: 1.5.4.1 +NAME: Prestashop 1.5.5.0 +VERSION: 1.5.5.0 PREPARACI�N =========== diff --git a/docs/readme_fr.txt b/docs/readme_fr.txt index 64eae1dc2..9f03d88eb 100755 --- a/docs/readme_fr.txt +++ b/docs/readme_fr.txt @@ -21,8 +21,8 @@ needs please refer to http://www.prestashop.com for more information. @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) International Registered Trademark & Property of PrestaShop SA -NAME: Prestashop 1.5.4.1 -VERSION: 1.5.4.1 +NAME: Prestashop 1.5.5.0 +VERSION: 1.5.5.0 PREPARATION =========== diff --git a/docs/readme_it.txt b/docs/readme_it.txt index e07a67d29..cb9f844f6 100755 --- a/docs/readme_it.txt +++ b/docs/readme_it.txt @@ -21,8 +21,8 @@ needs please refer to http://www.prestashop.com for more information. @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) International Registered Trademark & Property of PrestaShop SA -NAME: Prestashop 1.5.4.1 -VERSION: 1.5.4.1 +NAME: Prestashop 1.5.5.0 +VERSION: 1.5.5.0 PREPARAZIONE =========== diff --git a/get-file.php b/get-file.php index b283dfce5..70507df4a 100644 --- a/get-file.php +++ b/get-file.php @@ -34,4 +34,4 @@ require(dirname(__FILE__).'/config/config.inc.php'); Tools::displayFileAsDeprecated(); -Tools::redirect('index.php?controller=get-file'.($_REQUEST ? '&'.http_build_query($_REQUEST, '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file +Tools::redirect('index.php?controller=get-file'.((count($_GET) || count($_POST)) ? '&'.http_build_query(array_merge($_GET, $_POST), '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file diff --git a/history.php b/history.php index 8009c4980..e4a97510b 100644 --- a/history.php +++ b/history.php @@ -34,4 +34,4 @@ require(dirname(__FILE__).'/config/config.inc.php'); Tools::displayFileAsDeprecated(); -Tools::redirect('index.php?controller=history'.($_REQUEST ? '&'.http_build_query($_REQUEST, '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file +Tools::redirect('index.php?controller=history'.((count($_GET) || count($_POST)) ? '&'.http_build_query(array_merge($_GET, $_POST), '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file diff --git a/identity.php b/identity.php index 1a4ca7613..845738311 100644 --- a/identity.php +++ b/identity.php @@ -34,4 +34,4 @@ require(dirname(__FILE__).'/config/config.inc.php'); Tools::displayFileAsDeprecated(); -Tools::redirect('index.php?controller=identity'.($_REQUEST ? '&'.http_build_query($_REQUEST, '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file +Tools::redirect('index.php?controller=identity'.((count($_GET) || count($_POST)) ? '&'.http_build_query(array_merge($_GET, $_POST), '', '&') : ''), __PS_BASE_URI__, null, 'HTTP/1.1 301 Moved Permanently'); \ No newline at end of file diff --git a/img/admin/carrier-default.jpg b/img/admin/carrier-default.jpg new file mode 100644 index 000000000..5677b65c1 Binary files /dev/null and b/img/admin/carrier-default.jpg differ diff --git a/img/admin/external_link.png b/img/admin/external_link.png new file mode 100644 index 000000000..8951d24d4 Binary files /dev/null and b/img/admin/external_link.png differ diff --git a/img/admin/steps-carrierwizard.png b/img/admin/steps-carrierwizard.png new file mode 100644 index 000000000..4c0d980be Binary files /dev/null and b/img/admin/steps-carrierwizard.png differ diff --git a/install-dev/classes/controllerHttp.php b/install-dev/classes/controllerHttp.php index 8063ab9af..7cef69f5f 100644 --- a/install-dev/classes/controllerHttp.php +++ b/install-dev/classes/controllerHttp.php @@ -29,8 +29,8 @@ abstract class InstallControllerHttp /** * @var array List of installer steps */ - protected static $steps = array('welcome', 'license', 'system', 'database', 'configure', 'process'); - + protected static $steps = array('welcome', 'license', 'system', 'configure', 'database', 'process'); + protected $phone; protected static $instances = array(); /** @@ -318,7 +318,14 @@ abstract class InstallControllerHttp */ public function getPhone() { - return $this->language->getInformation('phone', false); + if ($this->phone === null) + { + $this->phone = $this->language->getInformation('phone', false); + if ($iframe = Tools::file_get_contents('http://api.prestashop.com/iframe/install.php?lang='.$this->language->getLanguageIso())) + if (preg_match('//Ui', $iframe, $matches) && isset($matches[1])) + $this->phone = $matches[1]; + } + return $this->phone; } /** diff --git a/install-dev/classes/datas.php b/install-dev/classes/datas.php index 964d737cf..feba9c196 100644 --- a/install-dev/classes/datas.php +++ b/install-dev/classes/datas.php @@ -133,6 +133,11 @@ class Datas 'default' => 1, 'help' => 'get news from PrestaShop', ), + 'send_email' => array( + 'name' => 'send_email', + 'default' => 1, + 'help' => 'send an email to the administrator after installation', + ), ); protected $datas = array(); @@ -200,4 +205,4 @@ class Datas return count($errors) ? $errors : true; } -} +} \ No newline at end of file diff --git a/install-dev/classes/session.php b/install-dev/classes/session.php index 27a0506c6..a8eabefc5 100644 --- a/install-dev/classes/session.php +++ b/install-dev/classes/session.php @@ -30,6 +30,8 @@ class InstallSession { protected static $_instance; + protected static $_cookie_mode = false; + protected static $_cookie = false; public static function getInstance() { @@ -40,40 +42,78 @@ class InstallSession public function __construct() { - session_name('install_'.md5(__PS_BASE_URI__)); - session_start(); + session_name('install_'.md5($_SERVER['HTTP_HOST'])); + $session_started = session_start(); + if (!($session_started) + || (!isset($_SESSION['session_mode']) && (isset($_POST['submitNext']) || isset($_POST['submitPrevious']) || isset($_POST['language'])))) + { + InstallSession::$_cookie_mode = true; + InstallSession::$_cookie = new Cookie('ps_install', null, time() + 7200, null, true); + } + if ($session_started && !isset($_SESSION['session_mode'])) + { + $_SESSION['session_mode'] = 'session'; + session_write_close(); + } } public function clean() { - foreach ($_SESSION as $k => $v) - unset($_SESSION[$k]); + if (InstallSession::$_cookie_mode) + InstallSession::$_cookie->logout(); + else + foreach ($_SESSION as $k => $v) + unset($_SESSION[$k]); } public function &__get($varname) { - if (isset($_SESSION[$varname])) - $ref = &$_SESSION[$varname]; + if (InstallSession::$_cookie_mode) + { + $ref = InstallSession::$_cookie->{$varname}; + if (0 === strncmp($ref, 'serialized_array:', strlen('serialized_array:'))) + $ref = unserialize(substr($ref, strlen('serialized_array:'))); + } else { - $null = null; - $ref = &$null; + if (isset($_SESSION[$varname])) + $ref = &$_SESSION[$varname]; + else + { + $null = null; + $ref = &$null; + } } return $ref; } public function __set($varname, $value) { - $_SESSION[$varname] = $value; + if (InstallSession::$_cookie_mode) + { + if ($varname == 'xml_loader_ids') + return; + if (is_array($value)) + $value = 'serialized_array:'.serialize($value); + InstallSession::$_cookie->{$varname} = $value; + } + else + $_SESSION[$varname] = $value; } public function __isset($varname) { - return isset($_SESSION[$varname]); + if (InstallSession::$_cookie_mode) + return isset(InstallSession::$_cookie->{$varname}); + else + return isset($_SESSION[$varname]); } public function __unset($varname) { - unset($_SESSION[$varname]); + if (InstallSession::$_cookie_mode) + unset(InstallSession::$_cookie->{$varname}); + else + unset($_SESSION[$varname]); } } diff --git a/install-dev/classes/xmlLoader.php b/install-dev/classes/xmlLoader.php index 2b6daad41..a871a375b 100644 --- a/install-dev/classes/xmlLoader.php +++ b/install-dev/classes/xmlLoader.php @@ -81,12 +81,15 @@ class InstallXmlLoader $this->img_path = _PS_INSTALL_DATA_PATH_.'img/'; } - public function setFixturesPath() + public function setFixturesPath($path = null) { + if ($path === null) + $path = _PS_INSTALL_FIXTURES_PATH_.'apple/'; + $this->path_type = 'fixture'; - $this->data_path = _PS_INSTALL_FIXTURES_PATH_.'apple/data/'; - $this->lang_path = _PS_INSTALL_FIXTURES_PATH_.'apple/langs/'; - $this->img_path = _PS_INSTALL_FIXTURES_PATH_.'apple/img/'; + $this->data_path = $path.'data/'; + $this->lang_path = $path.'langs/'; + $this->img_path = $path.'img/'; } /** @@ -224,10 +227,13 @@ class InstallXmlLoader return; } + if (substr($entity, 0, 1) == '.' || substr($entity, 0, 1) == '_') + return; + $xml = $this->loadEntity($entity); // Read list of fields - if (!$xml->fields) + if (!is_object($xml) || !$xml->fields) throw new PrestashopInstallerException('List of fields not found for entity '.$entity); if ($this->isMultilang($entity)) diff --git a/install-dev/controllers/console/process.php b/install-dev/controllers/console/process.php index 346114ece..48ac9e674 100644 --- a/install-dev/controllers/console/process.php +++ b/install-dev/controllers/console/process.php @@ -110,17 +110,21 @@ class InstallControllerConsoleProcess extends InstallControllerConsole $this->printErrors(); if (!$this->processInstallTheme()) $this->printErrors(); - if (!$this->processSendEmail()) - $this->printErrors(); + if ($this->datas->send_email) + if (!$this->processSendEmail()) + $this->printErrors(); - $params = http_build_query(array( - 'email' => $this->datas->admin_email, - 'method' => 'addMemberToNewsletter', - 'language' => $this->datas->lang, - 'visitorType' => 1, - 'source' => 'installer' - )); - Tools::file_get_contents('http://www.prestashop.com/ajax/controller.php?'.$params); + if ($this->datas->newsletter) + { + $params = http_build_query(array( + 'email' => $this->datas->admin_email, + 'method' => 'addMemberToNewsletter', + 'language' => $this->datas->lang, + 'visitorType' => 1, + 'source' => 'installer' + )); + Tools::file_get_contents('http://www.prestashop.com/ajax/controller.php?'.$params); + } } /** @@ -221,7 +225,7 @@ class InstallControllerConsoleProcess extends InstallControllerConsole $this->initializeContext(); $this->model_install->xml_loader_ids = $this->datas->xml_loader_ids; - $result = $this->model_install->installFixtures(); + $result = $this->model_install->installFixtures(null, array('shop_activity' => $this->datas->shop_activity, 'shop_country' => $this->datas->shop_country)); $this->datas->xml_loader_ids = $this->model_install->xml_loader_ids; return $result; } @@ -285,4 +289,3 @@ class InstallControllerConsoleProcess extends InstallControllerConsole return $this->model_install->installModulesAddons(); } } - diff --git a/install-dev/controllers/http/configure.php b/install-dev/controllers/http/configure.php index 1b35a3a9f..c600c04ad 100644 --- a/install-dev/controllers/http/configure.php +++ b/install-dev/controllers/http/configure.php @@ -56,7 +56,7 @@ class InstallControllerHttpConfigure extends InstallControllerHttp $params = http_build_query(array( 'email' => $this->session->admin_email, 'method' => 'addMemberToNewsletter', - 'language' => $this->session->lang, + 'language' => $this->language->getLanguageIso(), 'visitorType' => 1, 'source' => 'installer' )); diff --git a/install-dev/controllers/http/database.php b/install-dev/controllers/http/database.php index 6ec8ece98..d6e950fc7 100644 --- a/install-dev/controllers/http/database.php +++ b/install-dev/controllers/http/database.php @@ -56,7 +56,6 @@ class InstallControllerHttpDatabase extends InstallControllerHttp $this->session->database_login = trim(Tools::getValue('dbLogin')); $this->session->database_password = trim(Tools::getValue('dbPassword')); $this->session->database_prefix = trim(Tools::getValue('db_prefix')); - $this->session->database_engine = Tools::getValue('dbEngine'); $this->session->database_clear = Tools::getValue('database_clear'); // Save email config @@ -81,21 +80,23 @@ class InstallControllerHttpDatabase extends InstallControllerHttp $this->session->database_login, $this->session->database_password, $this->session->database_prefix, - $this->session->database_engine, - // We do not want to validate table prefix if we are already in install process ($this->session->step == 'process') ? true : $this->session->database_clear ); - - return count($this->errors) ? false : true; + if (count($this->errors)) + return false; + + if (!isset($this->session->database_engine)) + $this->session->database_engine = $this->model_database->getBestEngine($this->session->database_server, $this->session->database_name, $this->session->database_login, $this->session->database_password); + return true; } public function process() { if (Tools::getValue('checkDb')) $this->processCheckDb(); - else if (Tools::getValue('sendMail')) - $this->processSendMail(); + elseif (Tools::getValue('createDb')) + $this->processCreateDb(); } /** @@ -108,10 +109,9 @@ class InstallControllerHttpDatabase extends InstallControllerHttp $login = Tools::getValue('dbLogin'); $password = Tools::getValue('dbPassword'); $prefix = Tools::getValue('db_prefix'); - $engine = Tools::getValue('dbEngine'); $clear = Tools::getValue('clear'); - $errors = $this->model_database->testDatabaseSettings($server, $database, $login, $password, $prefix, $engine, $clear); + $errors = $this->model_database->testDatabaseSettings($server, $database, $login, $password, $prefix, $clear); $this->ajaxJsonAnswer( (count($errors)) ? false : true, @@ -120,28 +120,20 @@ class InstallControllerHttpDatabase extends InstallControllerHttp } /** - * Send a test email + * Attempt to create the database */ - public function processSendMail() + public function processCreateDb() { - $smtp_checked = (Tools::getValue('smtpChecked') == 'true'); - $server = Tools::getValue('smtpSrv'); - $encryption = Tools::getValue('smtpEnc'); - $port = Tools::getValue('smtpPort'); - $login = Tools::getValue('smtpLogin'); - $password = Tools::getValue('smtpPassword'); - $email = Tools::getValue('testEmail'); + $server = Tools::getValue('dbServer'); + $database = Tools::getValue('dbName'); + $login = Tools::getValue('dbLogin'); + $password = Tools::getValue('dbPassword'); - require_once _PS_INSTALL_MODELS_PATH_.'mail.php'; - $this->model_mail = new InstallModelMail($smtp_checked, $server, $login, $password, $port, $encryption, $email); - $result = $this->model_mail->send( - $this->l('Test message from PrestaShop'), - $this->l('This is a test message, your server is now available to send email') - ); + $success = $this->model_database->createDatabase($server, $database, $login, $password); $this->ajaxJsonAnswer( - $result === false, - ($result === false) ? $this->l('A test e-mail has been sent to %s', $email) : $this->l('An error occurred while sending email, please verify your parameters') + $success, + $success ? $this->l('Database is created') : $this->l('Cannot create the database automatically') ); } diff --git a/install-dev/controllers/http/process.php b/install-dev/controllers/http/process.php index f9d98996f..8ab8b0286 100644 --- a/install-dev/controllers/http/process.php +++ b/install-dev/controllers/http/process.php @@ -78,7 +78,7 @@ class InstallControllerHttpProcess extends InstallControllerHttp public function process() { if (file_exists(_PS_ROOT_DIR_.'/'.self::SETTINGS_FILE)) - @require_once _PS_ROOT_DIR_.'/'.self::SETTINGS_FILE; + require_once _PS_ROOT_DIR_.'/'.self::SETTINGS_FILE; if (!$this->session->process_validated) $this->session->process_validated = array(); @@ -241,7 +241,7 @@ class InstallControllerHttpProcess extends InstallControllerHttp public function processInstallAddonsModules() { $this->initializeContext(); - if ($module = Tools::getValue('module') && $id_module = Tools::getValue('id_module')) + if (($module = Tools::getValue('module')) && $id_module = Tools::getValue('id_module')) $result = $this->model_install->installModulesAddons(array('name' => $module, 'id_module' => $id_module)); else $result = $this->model_install->installModulesAddons(); @@ -260,7 +260,7 @@ class InstallControllerHttpProcess extends InstallControllerHttp $this->initializeContext(); $this->model_install->xml_loader_ids = $this->session->xml_loader_ids; - if (!$this->model_install->installFixtures(Tools::getValue('entity')) || $this->model_install->getErrors()) + if (!$this->model_install->installFixtures(Tools::getValue('entity', null), array('shop_activity' => $this->session->shop_activity, 'shop_country' => $this->session->shop_country)) || $this->model_install->getErrors()) $this->ajaxJsonAnswer(false, $this->model_install->getErrors()); $this->session->xml_loader_ids = $this->model_install->xml_loader_ids; $this->ajaxJsonAnswer(true); diff --git a/install-dev/controllers/http/system.php b/install-dev/controllers/http/system.php index 4db6d3ce1..00341a461 100644 --- a/install-dev/controllers/http/system.php +++ b/install-dev/controllers/http/system.php @@ -85,7 +85,7 @@ class InstallControllerHttpSystem extends InstallControllerHttp 'upload' => $this->l('Cannot upload files'), 'system' => $this->l('Cannot create new files and folders'), 'gd' => $this->l('GD Library is not installed'), - 'mysql_support' => $this->l('MySQL support is not activated'), + 'mysql_support' => $this->l('MySQL support is not activated') ) ), array( @@ -103,8 +103,7 @@ class InstallControllerHttpSystem extends InstallControllerHttp 'theme_cache_dir' => '~/themes/default/cache/', 'translations_dir' => '~/translations/', 'customizable_products_dir' => '~/upload/', - 'virtual_products_dir' => '~/download/', - 'sitemap' => '~/sitemap.xml', + 'virtual_products_dir' => '~/download/' ) ), ), @@ -120,7 +119,7 @@ class InstallControllerHttpSystem extends InstallControllerHttp 'mbstring' => $this->l('Mbstring extension is not enabled'), 'magicquotes' => $this->l('PHP magic quotes option is enabled'), 'dom' => $this->l('Dom extension is not loaded'), - 'pdo_mysql' => $this->l('PDO MySQL extension is not loaded'), + 'pdo_mysql' => $this->l('PDO MySQL extension is not loaded') ) ), ), diff --git a/install-dev/data/db_structure.sql b/install-dev/data/db_structure.sql index 5a06fb9ac..d067ea6f0 100644 --- a/install-dev/data/db_structure.sql +++ b/install-dev/data/db_structure.sql @@ -1437,7 +1437,7 @@ CREATE TABLE IF NOT EXISTS `PREFIX_product_shop` ( `date_upd` datetime NOT NULL, PRIMARY KEY (`id_product`, `id_shop`), KEY `id_category_default` (`id_category_default`), - KEY `date_add` (`date_add`) + KEY `date_add` (`date_add` , `active` , `visibility`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; CREATE TABLE `PREFIX_product_attribute` ( @@ -1819,8 +1819,8 @@ CREATE TABLE `PREFIX_store` ( `address2` varchar(128) DEFAULT NULL, `city` varchar(64) NOT NULL, `postcode` varchar(12) NOT NULL, - `latitude` decimal(11,8) DEFAULT NULL, - `longitude` decimal(11,8) DEFAULT NULL, + `latitude` decimal(13,8) DEFAULT NULL, + `longitude` decimal(13,8) DEFAULT NULL, `hours` varchar(254) DEFAULT NULL, `phone` varchar(16) DEFAULT NULL, `fax` varchar(16) DEFAULT NULL, @@ -1924,6 +1924,7 @@ CREATE TABLE `PREFIX_log` ( `message` text NOT NULL, `object_type` varchar(32) DEFAULT NULL, `object_id` int(10) unsigned DEFAULT NULL, + `id_employee` int(10) unsigned DEFAULT NULL, `date_add` datetime NOT NULL, `date_upd` datetime NOT NULL, PRIMARY KEY (`id_log`) diff --git a/install-dev/data/xml/access.xml b/install-dev/data/xml/access.xml index 97c2e66ea..9b71e93fc 100644 --- a/install-dev/data/xml/access.xml +++ b/install-dev/data/xml/access.xml @@ -51,6 +51,7 @@ + diff --git a/install-dev/data/xml/configuration.xml b/install-dev/data/xml/configuration.xml index 515f0762a..828538b0e 100644 --- a/install-dev/data/xml/configuration.xml +++ b/install-dev/data/xml/configuration.xml @@ -689,7 +689,7 @@ Country 7700 - 1.5.0.9 + 1.5.5.0 m @@ -701,7 +701,7 @@ Country localhost - 1.5.0.9 + 1.5.5.0 PrestaShop @@ -769,5 +769,11 @@ Country 1 + + 1 + + + SMARTY_DEBUG + diff --git a/install-dev/data/xml/hook.xml b/install-dev/data/xml/hook.xml index 1139431f2..005284227 100644 --- a/install-dev/data/xml/hook.xml +++ b/install-dev/data/xml/hook.xml @@ -86,7 +86,7 @@ displayCustomerAccountCustomer account displayed in Front OfficeThis hook displays new elements on the customer account page - actionOrderSlipAddOrder slip creationThis hook is called when a product's quantity is modified + actionOrderSlipAddOrder slip creationThis hook is called when a new credit slip is added regarding client order displayProductTabTabs on product pageThis hook is called on the product page's tab diff --git a/install-dev/data/xml/tab.xml b/install-dev/data/xml/tab.xml index efc6295cc..477d81b3d 100644 --- a/install-dev/data/xml/tab.xml +++ b/install-dev/data/xml/tab.xml @@ -156,11 +156,8 @@ AdminCarriers - - AdminRangePrice - - - AdminRangeWeight + + AdminCarrierWizard AdminLocalization diff --git a/install-dev/fixtures/apple/data/access.xml b/install-dev/fixtures/apple/data/access.xml index 31636ce76..45126998a 100644 --- a/install-dev/fixtures/apple/data/access.xml +++ b/install-dev/fixtures/apple/data/access.xml @@ -96,7 +96,7 @@ - + diff --git a/install-dev/fixtures/apple/data/orders.xml b/install-dev/fixtures/apple/data/orders.xml index c70f895fb..3296d006c 100644 --- a/install-dev/fixtures/apple/data/orders.xml +++ b/install-dev/fixtures/apple/data/orders.xml @@ -41,7 +41,7 @@ - + Chèque cheque diff --git a/install-dev/fixtures/apple/langs/nl/data/attribute.xml b/install-dev/fixtures/apple/langs/nl/data/attribute.xml new file mode 100644 index 000000000..f27df851c --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/attribute.xml @@ -0,0 +1,63 @@ + + + + 2GB + + + 4GB + + + Metal + + + Blue + + + Pink + + + Green + + + Orange + + + Optional 64GB solid-state drive + + + 80GB Parallel ATA Drive @ 4200 rpm + + + 1.60GHz Intel Core 2 Duo + + + 1.80GHz Intel Core 2 Duo + + + 80GB: 20,000 Songs + + + 160GB: 40,000 Songs + + + Black + + + 8GB + + + 16GB + + + 32GB + + + Purple + + + Yellow + + + Red + + diff --git a/install-dev/fixtures/apple/langs/nl/data/attribute_group.xml b/install-dev/fixtures/apple/langs/nl/data/attribute_group.xml new file mode 100644 index 000000000..221a81bc7 --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/attribute_group.xml @@ -0,0 +1,15 @@ + + + + Disk space + Disk space + + + Color + Color + + + ICU + Processor + + diff --git a/install-dev/fixtures/apple/langs/nl/data/attributegroup.xml b/install-dev/fixtures/apple/langs/nl/data/attributegroup.xml new file mode 100644 index 000000000..977fceeb7 --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/attributegroup.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/install-dev/fixtures/apple/langs/nl/data/carrier.xml b/install-dev/fixtures/apple/langs/nl/data/carrier.xml new file mode 100644 index 000000000..c59766e73 --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/carrier.xml @@ -0,0 +1,6 @@ + + + + Delivery next day! + + diff --git a/install-dev/fixtures/apple/langs/nl/data/category.xml b/install-dev/fixtures/apple/langs/nl/data/category.xml new file mode 100644 index 000000000..eeae63831 --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/category.xml @@ -0,0 +1,27 @@ + + + + iPods + Now that you can buy movies from the iTunes Store and sync them to your iPod, the whole world is your theater. + music-ipods + + + + + + Accessories + Wonderful accessories for your iPod + accessories-ipod + + + + + + Laptops + The latest Intel processor, a bigger hard drive, plenty of memory, and even more new features all fit inside just one liberating inch. The new Mac laptops have the performance, power, and connectivity of a desktop computer. Without the desk part. + laptops + Apple laptops + Apple laptops MacBook Air + Powerful and chic Apple laptops + + diff --git a/install-dev/fixtures/apple/langs/nl/data/feature.xml b/install-dev/fixtures/apple/langs/nl/data/feature.xml new file mode 100644 index 000000000..7682c6495 --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/feature.xml @@ -0,0 +1,18 @@ + + + + Height + + + Width + + + Depth + + + Weight + + + Headphone + + diff --git a/install-dev/fixtures/apple/langs/nl/data/feature_value.xml b/install-dev/fixtures/apple/langs/nl/data/feature_value.xml new file mode 100644 index 000000000..d3a824d22 --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/feature_value.xml @@ -0,0 +1,45 @@ + + + + Jack stereo + + + Mini-jack stereo + + + 2.75 in + + + 2.06 in + + + 49.2 g + + + 0.26 in + + + 1.07 in + + + 1.62 in + + + 15.5 g + + + 0.41 in (clip included) + + + 4.33 in + + + 2.76 in + + + 120g + + + 0.31 in + + diff --git a/install-dev/fixtures/apple/langs/nl/data/featurevalue.xml b/install-dev/fixtures/apple/langs/nl/data/featurevalue.xml new file mode 100644 index 000000000..d101bed96 --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/featurevalue.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/install-dev/fixtures/apple/langs/nl/data/image.xml b/install-dev/fixtures/apple/langs/nl/data/image.xml new file mode 100644 index 000000000..49a836dc3 --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/image.xml @@ -0,0 +1,81 @@ + + + + MacBook Air + + + MacBook Air + + + MacBook Air + + + MacBook Air + + + MacBook Air + + + MacBook Air SuperDrive + + + iPod touch + + + iPod touch + + + iPod touch + + + iPod touch + + + iPod touch + + + iPod touch + + + housse-portefeuille-en-cuir + + + Shure SE210 Sound-Isolating Earphones for iPod and iPhone + + + iPod Nano + + + iPod Nano + + + iPod Nano + + + iPod Nano + + + iPod Nano + + + iPod Nano + + + iPod Nano + + + iPod Nano + + + iPod shuffle + + + iPod shuffle + + + iPod shuffle + + + iPod shuffle + + diff --git a/admin-dev/themes/default/template/controllers/shipping/index.php b/install-dev/fixtures/apple/langs/nl/data/index.php similarity index 100% rename from admin-dev/themes/default/template/controllers/shipping/index.php rename to install-dev/fixtures/apple/langs/nl/data/index.php diff --git a/install-dev/fixtures/apple/langs/nl/data/manufacturer.xml b/install-dev/fixtures/apple/langs/nl/data/manufacturer.xml new file mode 100644 index 000000000..f06ff9661 --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/manufacturer.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/install-dev/fixtures/apple/langs/nl/data/order_message.xml b/install-dev/fixtures/apple/langs/nl/data/order_message.xml new file mode 100644 index 000000000..93ad3b501 --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/order_message.xml @@ -0,0 +1,12 @@ + + + + Delay + Hi, + +Unfortunately, an item on your order is currently out of stock. This may cause a slight delay in delivery. +Please accept our apologies and rest assured that we are working hard to rectify this. + +Best regards, + + diff --git a/install-dev/fixtures/apple/langs/nl/data/ordermessage.xml b/install-dev/fixtures/apple/langs/nl/data/ordermessage.xml new file mode 100644 index 000000000..e743f5d97 --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/ordermessage.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/install-dev/fixtures/apple/langs/nl/data/product.xml b/install-dev/fixtures/apple/langs/nl/data/product.xml new file mode 100644 index 000000000..0c405b001 --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/product.xml @@ -0,0 +1,135 @@ + + + + <p><strong><span style="font-size: small;">Curved ahead of the curve.</span></strong></p> +<p>For those about to rock, we give you nine amazing colors. But that's only part of the story. Feel the curved, all-aluminum and glass design and you won't want to put iPod nano down.</p> +<p><strong><span style="font-size: small;">Great looks. And brains, too.</span></strong></p> +<p>The new Genius feature turns iPod nano into your own highly intelligent, personal DJ. It creates playlists by finding songs in your library that go great together.</p> +<p><strong><span style="font-size: small;">Made to move with your moves.</span></strong></p> +<p>The accelerometer comes to iPod nano. Give it a shake to shuffle your music. Turn it sideways to view Cover Flow. And play games designed with your moves in mind.</p> + <p>New design. New features. Now in 8GB and 16GB. iPod nano rocks like never before.</p> + ipod-nano + + + + iPod Nano + In stock + + + + <p><span style="font-size: small;"><strong>Instant attachment.</strong></span></p> +<p>Wear up to 500 songs on your sleeve. Or your belt. Or your gym shorts. iPod shuffle is a badge of musical devotion. Now in new, more brilliant colors.</p> +<p><span style="font-size: small;"><strong>Feed your iPod shuffle.</strong></span></p> +<p>iTunes is your entertainment superstore. It’s your ultra-organized music collection and jukebox. And it’s how you load up your iPod shuffle in one click.</p> +<p><span style="font-size: small;"><strong>Beauty and the beat.</strong></span></p> +<p>Intensely colorful anodized aluminum complements the simple design of iPod shuffle. Now in blue, green, pink, red, and original silver.</p> + <p>iPod shuffle, the world’s most wearable music player, now clips on in more vibrant blue, green, pink, and red.</p> + ipod-shuffle + + + + iPod shuffle + In stock + + + + <p>MacBook Air is nearly as thin as your index finger. Practically every detail that could be streamlined has been. Yet it still has a 13.3-inch widescreen LED display, full-size keyboard, and large multi-touch trackpad. It’s incomparably portable without the usual ultraportable screen and keyboard compromises.</p><p>The incredible thinness of MacBook Air is the result of numerous size- and weight-shaving innovations. From a slimmer hard drive to strategically hidden I/O ports to a lower-profile battery, everything has been considered and reconsidered with thinness in mind.</p><p>MacBook Air is designed and engineered to take full advantage of the wireless world. A world in which 802.11n Wi-Fi is now so fast and so available, people are truly living untethered — buying and renting movies online, downloading software, and sharing and storing files on the web. </p> + MacBook Air is ultrathin, ultraportable, and ultra unlike anything else. But you don’t lose inches and pounds overnight. It’s the result of rethinking conventions. Of multiple wireless innovations. And of breakthrough design. With MacBook Air, mobile computing suddenly has a new standard. + macbook-air + + + + MacBook Air + + + + + Every MacBook has a larger hard drive, up to 250GB, to store growing media collections and valuable data.<br /><br />The 2.4GHz MacBook models now include 2GB of memory standard — perfect for running more of your favorite applications smoothly. + MacBook makes it easy to hit the road thanks to its tough polycarbonate case, built-in wireless technologies, and innovative MagSafe Power Adapter that releases automatically if someone accidentally trips on the cord. + macbook + + + + MacBook + + + + + <h3>Five new hands-on applications</h3> +<p>View rich HTML email with photos as well as PDF, Word, and Excel attachments. Get maps, directions, and real-time traffic information. Take notes and read stock and weather reports.</p> +<h3>Touch your music, movies, and more</h3> +<p>The revolutionary Multi-Touch technology built into the gorgeous 3.5-inch display lets you pinch, zoom, scroll, and flick with your fingers.</p> +<h3>Internet in your pocket</h3> +<p>With the Safari web browser, see websites the way they were designed to be seen and zoom in and out with a tap.<sup>2</sup> And add Web Clips to your Home screen for quick access to favorite sites.</p> +<h3>What's in the box</h3> +<ul> +<li><span></span>iPod touch</li> +<li><span></span>Earphones</li> +<li><span></span>USB 2.0 cable</li> +<li><span></span>Dock adapter</li> +<li><span></span>Polishing cloth</li> +<li><span></span>Stand</li> +<li><span></span>Quick Start guide</li> +</ul> + <ul> +<li>Revolutionary Multi-Touch interface</li> +<li>3.5-inch widescreen color display</li> +<li>Wi-Fi (802.11b/g)</li> +<li>8 mm thin</li> +<li>Safari, YouTube, Mail, Stocks, Weather, Notes, iTunes Wi-Fi Music Store, Maps</li> +</ul> + ipod-touch + + + + iPod touch + + + + + <p>Lorem ipsum</p> + <p>Lorem ipsum</p> + belkin-leather-folio-for-ipod-nano-black-chocolate + + + + Belkin Leather Folio for iPod nano - Black / Chocolate + + + + + <div class="product-overview-full">Using Hi-Definition MicroSpeakers to deliver full-range audio, the ergonomic and lightweight design of the SE210 earphones is ideal for premium on-the-go listening on your iPod or iPhone. They offer the most accurate audio reproduction from both portable and home stereo audio sources--for the ultimate in precision highs and rich low end. In addition, the flexible design allows you to choose the most comfortable fit from a variety of wearing positions. <br /> <br /> <strong>Features </strong> <br /> +<ul> +<li>Sound-isolating design </li> +<li> Hi-Definition MicroSpeaker with a single balanced armature driver </li> +<li> Detachable, modular cable so you can make the cable longer or shorter depending on your activity </li> +<li> Connector compatible with earphone ports on both iPod and iPhone </li> +</ul> +<strong>Specifications </strong><br /> +<ul> +<li>Speaker type: Hi-Definition MicroSpeaker </li> +<li> Frequency range: 25Hz-18.5kHz </li> +<li> Impedance (1kHz): 26 Ohms </li> +<li> Sensitivity (1mW): 114 dB SPL/mW </li> +<li> Cable length (with extension): 18.0 in./45.0 cm (54.0 in./137.1 cm) </li> +</ul> +<strong>In the box</strong><br /> +<ul> +<li>Shure SE210 earphones </li> +<li> Extension cable (36.0 in./91.4 cm) </li> +<li> Three pairs foam earpiece sleeves (small, medium, large) </li> +<li> Three pairs soft flex earpiece sleeves (small, medium, large) </li> +<li> One pair triple-flange earpiece sleeves </li> +<li> Carrying case </li> +</ul> +Warranty<br /> Two-year limited <br />(For details, please visit <br />www.shure.com/PersonalAudio/CustomerSupport/ProductReturnsAndWarranty/index.htm.) <br /><br /> Mfr. Part No.: SE210-A-EFS <br /><br />Note: Products sold through this website that do not bear the Apple Brand name are serviced and supported exclusively by their manufacturers in accordance with terms and conditions packaged with the products. Apple's Limited Warranty does not apply to products that are not Apple-branded, even if packaged or sold with Apple products. Please contact the manufacturer directly for technical support and customer service.</div> + <p>Evolved from personal monitor technology road-tested by pro musicians and perfected by Shure engineers, the lightweight and stylish SE210 delivers full-range audio that's free from outside noise.</p> + ecouteurs-a-isolation-sonore-shure-se210-blanc + + + + Shure SE210 Sound-Isolating Earphones for iPod and iPhone + + + + diff --git a/install-dev/fixtures/apple/langs/nl/data/profile.xml b/install-dev/fixtures/apple/langs/nl/data/profile.xml new file mode 100644 index 000000000..02aa4d76c --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/profile.xml @@ -0,0 +1,15 @@ + + + + Administrator + + + Logistician + + + Translator + + + Salesman + + diff --git a/install-dev/fixtures/apple/langs/nl/data/scene.xml b/install-dev/fixtures/apple/langs/nl/data/scene.xml new file mode 100644 index 000000000..f7270d3ff --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/scene.xml @@ -0,0 +1,12 @@ + + + + The iPods Nano + + + The iPods + + + The MacBooks + + diff --git a/install-dev/fixtures/apple/langs/nl/data/supplier.xml b/install-dev/fixtures/apple/langs/nl/data/supplier.xml new file mode 100644 index 000000000..e9db64034 --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/supplier.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/install-dev/fixtures/apple/langs/nl/data/tag.xml b/install-dev/fixtures/apple/langs/nl/data/tag.xml new file mode 100644 index 000000000..b781c0ed2 --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/data/tag.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/install-dev/fixtures/apple/langs/nl/index.php b/install-dev/fixtures/apple/langs/nl/index.php new file mode 100644 index 000000000..67d9932bf --- /dev/null +++ b/install-dev/fixtures/apple/langs/nl/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header('Expires: Mon, 26 Jul 1997 05:00:00 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/install-dev/index.php b/install-dev/index.php index 995a182ca..67ad72e8f 100644 --- a/install-dev/index.php +++ b/install-dev/index.php @@ -24,14 +24,11 @@ * International Registered Trademark & Property of PrestaShop SA */ -require_once 'init.php'; +require_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'init.php'); -try -{ - require_once _PS_INSTALL_PATH_.'classes/controllerHttp.php'; +try { + require_once(_PS_INSTALL_PATH_.'classes'.DIRECTORY_SEPARATOR.'controllerHttp.php'); InstallControllerHttp::execute(); -} -catch (PrestashopInstallerException $e) -{ +} catch (PrestashopInstallerException $e) { $e->displayMessage(); } diff --git a/install-dev/init.php b/install-dev/init.php index cf0d611ab..d55d22b87 100644 --- a/install-dev/init.php +++ b/install-dev/init.php @@ -24,6 +24,8 @@ * International Registered Trademark & Property of PrestaShop SA */ +ob_start(); + // Check PHP version if (version_compare(PHP_VERSION, '5.1.3', '<')) die('You need at least PHP 5.1.3 to run PrestaShop. Your current PHP version is '.PHP_VERSION); @@ -37,7 +39,7 @@ define('_PS_INSTALL_MODELS_PATH_', _PS_INSTALL_PATH_.'models/'); define('_PS_INSTALL_LANGS_PATH_', _PS_INSTALL_PATH_.'langs/'); define('_PS_INSTALL_FIXTURES_PATH_', _PS_INSTALL_PATH_.'fixtures/'); -require_once(_PS_INSTALL_PATH_ . 'install_version.php'); +require_once(_PS_INSTALL_PATH_.'install_version.php'); // we check if theses constants are defined // in order to use init.php in upgrade.php script @@ -71,8 +73,8 @@ if (!@ini_get('date.timezone')) ini_set('magic_quotes_runtime', 0); // Try to improve memory limit if it's under 32M -if (psinstall_get_memory_limit() < psinstall_get_octets('32M')) - ini_set('memory_limit', '32M'); +if (psinstall_get_memory_limit() < psinstall_get_octets('64M')) + ini_set('memory_limit', '64M'); function psinstall_get_octets($option) { diff --git a/install-dev/install_version.php b/install-dev/install_version.php index 5d86dc4df..0eb85db70 100644 --- a/install-dev/install_version.php +++ b/install-dev/install_version.php @@ -24,4 +24,4 @@ * International Registered Trademark & Property of PrestaShop SA */ -define('_PS_INSTALL_VERSION_', '1.5.4.1'); +define('_PS_INSTALL_VERSION_', '1.5.5.0'); diff --git a/install-dev/langs/br/data/tab.xml b/install-dev/langs/br/data/tab.xml index 27e2d2651..d0dd5591e 100644 --- a/install-dev/langs/br/data/tab.xml +++ b/install-dev/langs/br/data/tab.xml @@ -64,7 +64,6 @@ - @@ -76,7 +75,7 @@ - + @@ -100,6 +99,5 @@ - diff --git a/install-dev/langs/br/install.php b/install-dev/langs/br/install.php index 104f2a514..ab4e5715b 100644 --- a/install-dev/langs/br/install.php +++ b/install-dev/langs/br/install.php @@ -2,7 +2,8 @@ return array( 'informations' => array( 'phone' => '+1 888.947.6543', - 'support' => 'http://support.prestashop.com/en/', + 'support' => 'https://www.prestashop.com/pt/support', + 'blog' => 'http://www.prestashop.com/blog/pt/' ), 'translations' => array( 'menu_welcome' => 'Escolha seu idioma', @@ -162,7 +163,7 @@ return array( 'Test message from PrestaShop' => 'Mensagem de teste do PrestaShop', 'This is a test message, your server is now available to send email' => 'Esta é uma mensagem de teste, seu servidor está disponível agora para enviar emails.', '%s - Login information' => '%s - Informação de identificação', - 'An SQL error occured for entity %1$s: %2$s' => 'Um erro SQL ocorrey para a entidade %1$s : %2$s', + 'An SQL error occured for entity %1$s: %2$s' => 'Um erro SQL ocorreu para a entidade %1$s : %2$s', 'Cannot create image "%1$s" for entity "%2$s"' => 'Não é possível criar imagem "%1$s" para a entidade "%2$s"', 'Cannot create image "%1$s" (bad permissions on folder "%2$s")' => 'Não é possível criar imagem "%1$s" (permissão inválida na pasta "%2$s")', 'Cannot create image "%s"' => 'Não é possível criar imagem "%s"', @@ -211,7 +212,7 @@ return array( 'We are currently checking PrestaShop compatibility with your system environment' => 'Neste momento, nós estamos verificando a compatibilidade do PrestaShop com seu ambiente de sistema.', 'PrestaShop compatibility with your system environment has been verified!' => 'A compatibilidade do PrestaShop com seu ambiente de sistema foi verificada!', 'Oops! Please correct the item(s) below, and then click "Refresh information" to test the compatibility of your new system.' => 'Ups! Por favor corrija o(s) item(s) abaixo, e depois clique “Atualizar Informação” para testar a compatibilidade do seu novo sistema.', - 'The installation of PrestaShop is quick and easy. In just a few moments, you will become part of a community consisting of more than 130,000 merchants. You are on the way to creating your own unique online store that you can manage easily every day.' => 'A instalação do PrestaShop é rápida e fácil. Em alguns minutos, você vai se tornar parte de uma comunidade composta por mais de 130 mil comerciantes. Você está no caminho certo para criar sua própria loja virtual original que você pode gerenciar facilmente todos os dias.', + 'The installation of PrestaShop is quick and easy. In just a few moments, you will become part of a community consisting of more than 150,000 merchants. You are on the way to creating your own unique online store that you can manage easily every day.' => 'A instalação do PrestaShop é rápida e fácil. Em alguns minutos, você vai se tornar parte de uma comunidade composta por mais de 150 mil comerciantes. Você está no caminho certo para criar sua própria loja virtual original que você pode gerenciar facilmente todos os dias.', 'Continue the installation in:' => 'Continue a instalação em:', 'The language selection above only applies to the Installation Assistant. Once your store is installed, you can choose the language of your store from over %d translations, all for free!' => 'A seleção de idioma acima é válida somente para o Assistente de Instalação. Uma vez que a loja for instalada, você pode escolher o idioma da sua loja entre mais de %d traduções disponíveis, totalmente grátis!', 'The field %s is limited to %d characters' => 'O campo %s está limitado a %d caractéres', @@ -237,5 +238,14 @@ return array( 'E-mail:' => 'E-mail:', 'PrestaShop requires at least 32M of memory to run, please check the memory_limit directive in php.ini or contact your host provider' => 'PrestaShop requer pelo menos 32M de memória para funcionar, por favor verifique memory_limit no php.ini ou contate seu provedor de hospedagem.', 'Your PHP sessions path is not writable - check with your hosting provider:' => 'O caminho para sessão PHP não pode ser escrito - verifique com o seu provedor de hospedagem', + 'Database is created' => 'Banco de dados está criado', + 'Cannot create the database automatically' => 'Não é possível criar o banco de dados automaticamente', + 'Install modules Addons' => 'Instalar módulos Addons', + 'Attempt to create the database automatically' => 'Tentativa de criar o banco de dados automaticamente', + 'Country:' => 'País:', + 'Must be letters and numbers with at least 8 characters' => 'Deve ser letras e números com pelo menos 8 caractéres', + 'To install PrestaShop, you need to have JavaScript enabled in your browser.' => 'Para instalar o PrestaShop, você precisa ter JavaScript ativado no seu navegador', + 'To enjoy the many features that are offered for free by PrestaShop, please read the license terms below. PrestaShop core is licensed under OSL 3.0, while the modules and themes are licensed under AFL 3.0.' => 'Para aproveitar os muitos recursos que são oferecidos grátis pelo PrestaShop, por favor, leia os termos de licença abaixo. O núcleo do PrestaShop é licenciado sob OSL 3.0, enquanto os módulos e temas são licenciados sob AFL 3.0.', + 'For security purposes, you must delete the "install" folder.' => 'Por questões de segurança, você deve deletar a pasta "install"', ), -); \ No newline at end of file +); diff --git a/install-dev/langs/de/data/tab.xml b/install-dev/langs/de/data/tab.xml index fdda483e3..237e792eb 100644 --- a/install-dev/langs/de/data/tab.xml +++ b/install-dev/langs/de/data/tab.xml @@ -64,7 +64,6 @@ - @@ -76,7 +75,7 @@ - + @@ -100,6 +99,5 @@ - diff --git a/install-dev/langs/de/install.php b/install-dev/langs/de/install.php index fedcb2247..b39302665 100644 --- a/install-dev/langs/de/install.php +++ b/install-dev/langs/de/install.php @@ -2,6 +2,7 @@ return array( 'informations' => array( 'phone' => '+33 (0)1.40.18.30.04', + 'support' => 'https://www.prestashop.com/de/support', ), 'translations' => array( 'menu_welcome' => 'Sprachauswahl', @@ -203,7 +204,7 @@ return array( 'Print my login information' => 'Meine Zugangsinformationen ausdrucken', 'We are currently checking PrestaShop compatibility with your system environment' => 'Wir überprüfen derzeit die Kompatibilität von PrestaShop mit Ihrer Systemumgebung.', 'Oops! Please correct the item(s) below, and then click "Refresh information" to test the compatibility of your new system.' => 'Bitte korrigieren Sie untenstehende(n) Punkt(e) und klicken Sie anschließend auf den Refresh-Button, um erneut die Kompatibilität Ihres Systems zu überprüfen.', - 'The installation of PrestaShop is quick and easy. In just a few moments, you will become part of a community consisting of more than 130,000 merchants. You are on the way to creating your own unique online store that you can manage easily every day.' => 'Die PrestaShop-Installation ist schnell und einfach. In nur wenigen Minuten werden Sie Teil einer Community aus über 130 000 Händlern und erstellen einen Onlineshop, der genau zu Ihnen passt und der einfach in der täglichen Verwaltung ist.', + 'The installation of PrestaShop is quick and easy. In just a few moments, you will become part of a community consisting of more than 150,000 merchants. You are on the way to creating your own unique online store that you can manage easily every day.' => 'Die PrestaShop-Installation ist schnell und einfach. In nur wenigen Minuten werden Sie Teil einer Community aus über 150 000 Händlern und erstellen einen Onlineshop, der genau zu Ihnen passt und der einfach in der täglichen Verwaltung ist.', 'Continue the installation in:' => 'Die Installation fortführen als:', 'The language selection above only applies to the Installation Assistant. Once your store is installed, you can choose the language of your store from over %d translations, all for free!' => 'Die untenstehende Sprachauswahl bezieht sich auf den Installationsassistenten. Sobald Ihr Shop installiert ist, können Sie aus %d Sprachen Ihre Shopsprache wählen!', 'An error occurred during logo copy.' => 'Beim Logo Copy ist ein Fehler aufgetreten.', diff --git a/install-dev/langs/en/data/meta.xml b/install-dev/langs/en/data/meta.xml index bae593782..9fc060f31 100644 --- a/install-dev/langs/en/data/meta.xml +++ b/install-dev/langs/en/data/meta.xml @@ -3,61 +3,61 @@ 404 error This page cannot be found - error, 404, not found + page-not-found Best sales Our best sales - best sales + best-sales Contact us Use our form to contact us - contact, form, e-mail + contact-us <description>Shop powered by PrestaShop</description> - <keywords>shop, prestashop</keywords> + <keywords/> <url_rewrite/> </meta> <meta id="manufacturer" id_shop="1"> <title>Manufacturers Manufacturers list - manufacturer + manufacturers New products Our new products - new, products + new-products Forgot your password Enter your e-mail address used to register in goal to get e-mail with your new password - forgot, password, e-mail, new, reset + password-recovery Prices drop Our special products - special, prices drop + prices-drop Sitemap Lost ? Find what your are looking for - sitemap + sitemap Suppliers Suppliers list - supplier + supplier @@ -73,10 +73,10 @@ addresses - Authentication + Login - authentication + login Cart diff --git a/install-dev/langs/en/data/tab.xml b/install-dev/langs/en/data/tab.xml index e6d9c8f35..4eaf19c75 100644 --- a/install-dev/langs/en/data/tab.xml +++ b/install-dev/langs/en/data/tab.xml @@ -48,10 +48,8 @@ - + - - diff --git a/install-dev/langs/en/install.php b/install-dev/langs/en/install.php index ee296298a..cd29befe8 100644 --- a/install-dev/langs/en/install.php +++ b/install-dev/langs/en/install.php @@ -6,7 +6,7 @@ return array( 'documentation_upgrade' => 'http://docs.prestashop.com/display/PS15/Updating+PrestaShop', 'forum' => 'http://www.prestashop.com/forums/', 'blog' => 'http://www.prestashop.com/blog/', - 'support' => 'http://support.prestashop.com/en/', + 'support' => 'https://www.prestashop.com/en/support', ), 'translations' => array( 'menu_welcome' => 'Choose your language', diff --git a/install-dev/langs/es/data/tab.xml b/install-dev/langs/es/data/tab.xml index 0d83e4f2a..6d0c59194 100644 --- a/install-dev/langs/es/data/tab.xml +++ b/install-dev/langs/es/data/tab.xml @@ -64,7 +64,6 @@ - @@ -75,8 +74,8 @@ - - + + @@ -100,6 +99,5 @@ - diff --git a/install-dev/langs/es/install.php b/install-dev/langs/es/install.php index e9fb6d41c..cb7234192 100644 --- a/install-dev/langs/es/install.php +++ b/install-dev/langs/es/install.php @@ -1,7 +1,9 @@ array( - 'phone' => '+1 (888) 947-6543', + 'phone' => '+34 917.872.909', + 'support' => 'https://www.prestashop.com/es/support', + 'blog' => 'http://www.prestashop.com/blog/es/' ), 'translations' => array( 'menu_welcome' => 'Elegir el idioma', @@ -204,7 +206,7 @@ return array( 'Print my login information' => 'Imprimir la información e inicio de sesión', 'We are currently checking PrestaShop compatibility with your system environment' => 'Verificamos en este momento la compatibilidad de PrestaShop con tu entorno del sistema', 'Oops! Please correct the item(s) below, and then click "Refresh information" to test the compatibility of your new system.' => '¡Uups! Por favor corrija los siguientes puntos marcados como errores y después hacer Clic en el botón "Actualizar esta información" con el fin de probar de nuevo la compatibilidad de tu sistema.', - 'The installation of PrestaShop is quick and easy. In just a few moments, you will become part of a community consisting of more than 130,000 merchants. You are on the way to creating your own unique online store that you can manage easily every day.' => 'La instalación de PrestaShop es rápida y fácil. En solo unos minutos, podrás unirte a una comunidad de más de 130.000 comerciantes electrónicos. Así podrás crear tu propia tienda Online con tu imagen corporativa y administrarla a diario de forma muy sencilla.', + 'The installation of PrestaShop is quick and easy. In just a few moments, you will become part of a community consisting of more than 150,000 merchants. You are on the way to creating your own unique online store that you can manage easily every day.' => 'La instalación de PrestaShop es rápida y fácil. En solo unos minutos, podrás unirte a una comunidad de más de 150.000 comerciantes electrónicos. Así podrás crear tu propia tienda Online con tu imagen corporativa y administrarla a diario de forma muy sencilla.', 'Continue the installation in:' => 'Continuar la instalación en:', 'The language selection above only applies to the Installation Assistant. Once your store is installed, you can choose the language of your store from over %d translations, all for free!' => 'La elección del idioma se realiza sólo al inicio y se aplica al asistente de instalación. Una vez que tu tienda Online está instalada, podrás elegir el idioma de tu tienda, ¡entre las más de %d traducciones disponibles, ¡todas ellas de forma gratuitas!', 'The field %s is limited to %d characters' => 'El campo %s está limitado a %d caracteres', @@ -233,5 +235,16 @@ return array( 'PrestaShop compatibility with your system environment has been verified!' => '¡La compatibilidad de PrestaShop con su entorno del sistema ha sido verificada correctamente!', 'PrestaShop requires at least 32M of memory to run, please check the memory_limit directive in php.ini or contact your host provider' => 'PrestaShop requiere al menos 32MB de memoria para funcionar, por favor verifica la directiva memory_limit que se encuentra en el fichero php.ini o contacta con su proveedor de alojamiento', 'Your PHP sessions path is not writable - check with your hosting provider:' => 'El fichero de almacenamiento no está disponible en modo escritura, consulte con su proveedor de alojamiento', + 'Database is created' => 'Base de datos se creada', + 'Cannot create the database automatically' => 'No se puede crear la base de datos automáticamente', + 'Install modules Addons' => 'Instalar módulos Addons', + 'Attempt to create the database automatically' => 'Tentativa de crear la base de datos automáticamente', + 'Country:' => 'País:', + 'Must be letters and numbers with at least 8 characters' => 'Deben ser letras y números con un mínimo de 8 caracteres', + 'To install PrestaShop, you need to have JavaScript enabled in your browser.' => 'Para instalar PrestaShop, usted necesita tener el Javascript activado en su navegador.', + 'http://doc.prestashop.com/display/PS15/What+you+need+to+get+started#HowtoenableJavaScript-HowtoenableJavaScript' => 'http://doc.prestashop.com/display/PS15/What+you+need+to+get+started#HowtoenableJavaScript-HowtoenableJavaScript', + 'To enjoy the many features that are offered for free by PrestaShop, please read the license terms below. PrestaShop core is licensed under OSL 3.0, while the modules and themes are licensed under AFL 3.0.' => 'Para disfrutar de las numerosas funcionalidades ofrecidas de forma gratuita por PrestaShop, por favor lea los términos de la licencia a continuación. Core PrestaShop está disponible bajo la licencia OSL 3.0, mientras que los módulos y los temas están licenciados bajo la AFL 3.0.', + 'For security purposes, you must delete the "install" folder.' => 'Por razones de seguridad, debe eliminar la carpeta "install".', + 'http://doc.prestashop.com/display/PS15/Installing+PrestaShop#InstallingPrestaShop-Completingtheinstallation' => 'http://doc.prestashop.com/display/PS15/Installing+PrestaShop#InstallingPrestaShop-Completingtheinstallation', ), -); \ No newline at end of file +); diff --git a/install-dev/langs/fr/data/country.xml b/install-dev/langs/fr/data/country.xml index 3a525918c..6fcb1fbae 100644 --- a/install-dev/langs/fr/data/country.xml +++ b/install-dev/langs/fr/data/country.xml @@ -76,7 +76,7 @@ Singapour - Ireland + Irlande Nouvelle-Zélande diff --git a/install-dev/langs/fr/data/meta.xml b/install-dev/langs/fr/data/meta.xml index a197ea60a..9d845be18 100644 --- a/install-dev/langs/fr/data/meta.xml +++ b/install-dev/langs/fr/data/meta.xml @@ -3,61 +3,61 @@ Erreur 404 Cette page est introuvable - erreur, 404, introuvable + page-non-trouvee Meilleures ventes Liste de nos produits les mieux vendus - meilleures ventes + meilleures-ventes Contactez-nous Utilisez notre formulaire pour nous contacter - contact, formulaire, e-mail + contactez-nous <description>Boutique propulsée par PrestaShop</description> - <keywords>boutique, prestashop</keywords> + <keywords/> <url_rewrite/> </meta> <meta id="manufacturer" id_shop="1"> <title>Fabricants Liste de nos fabricants - fabricants + fabricants Nouveaux produits Liste de nos nouveaux produits - nouveau, produit + nouveaux-produits Mot de passe oublié Renseignez votre adresse e-mail afin de recevoir votre nouveau mot de passe. - mot de passe, oublié, e-mail, nouveau, regénération + mot-de-passe-oublie Promotions Nos produits en promotion - promotion, réduction + promotions Plan du site Perdu ? Trouvez ce que vous cherchez - plan, site + plan-du-site Fournisseurs Liste de nos fournisseurs - fournisseurs + fournisseurs diff --git a/install-dev/langs/fr/data/tab.xml b/install-dev/langs/fr/data/tab.xml index 0da00ee0b..db545d6b9 100644 --- a/install-dev/langs/fr/data/tab.xml +++ b/install-dev/langs/fr/data/tab.xml @@ -64,7 +64,6 @@ - @@ -76,7 +75,7 @@ - + @@ -100,6 +99,5 @@ - diff --git a/install-dev/langs/fr/install.php b/install-dev/langs/fr/install.php index 4d2e0980b..c4a31b4f5 100644 --- a/install-dev/langs/fr/install.php +++ b/install-dev/langs/fr/install.php @@ -200,7 +200,7 @@ return array( 'firstname' => 'prénom', 'lastname' => 'nom de famille', 'Installation Assistant' => 'Assistant d\'installation', - 'To enjoy the many features that are offered by PrestaShop, please read the license terms below. PrestaShop core is licensed under OSL 3.0, while the modules and themes are licensed under AFL 3.0.' => 'Afin de profiter des nombreuses fonctionnalités qu\'offre PrestaShop, merci de prendre connaissance des termes des licences ci-dessous. Le coeur de PrestaShop est publié sous licence OSL 3.0 tandis que les modules et thèmes sont publiés sous licence AFL 3.0.', + 'To enjoy the many features that are offered for free by PrestaShop, please read the license terms below. PrestaShop core is licensed under OSL 3.0, while the modules and themes are licensed under AFL 3.0.' => 'Afin de profiter gratuitement des nombreuses fonctionnalités qu\'offre PrestaShop, merci de prendre connaissance des termes des licences ci-dessous. Le coeur de PrestaShop est publié sous licence OSL 3.0 tandis que les modules et thèmes sont publiés sous licence AFL 3.0.', 'PrestaShop Installation Assistant' => 'Assistant d\'installation', 'Contact us!' => 'Contactez-nous !', 'E-mail:' => 'E-mail :', @@ -209,10 +209,10 @@ return array( 'PrestaShop compatibility with your system environment has been verified!' => 'La compatibilité de PrestaShop avec votre système a été vérifiée', 'Oops! Please correct the item(s) below, and then click "Refresh information" to test the compatibility of your new system.' => 'Merci de bien vouloir corriger le(s) point(s) ci-dessous puis de cliquer sur le bouton "Rafraichir ces informations" afin de tester à nouveau la compatibilité de votre système.', 'PrestaShop requires at least 32M of memory to run, please check the memory_limit directive in php.ini or contact your host provider' => 'PrestaShop nécessite au moins 32Mo de mémoire pour fonctionner, merci de vérifier la valeur de la directive memory_limit dans votre fichier php.ini ou de contacter votre hébergeur.', - 'The installation of PrestaShop is quick and easy. In just a few moments, you will become part of a community consisting of more than 130,000 merchants. You are on the way to creating your own unique online store that you can manage easily every day.' => 'L\'installation de PrestaShop est simple et rapide. En quelques minutes seulement, vous rejoindrez une communauté de plus de 130 000 marchands pour créer une boutique en ligne à votre image et la gérer facilement au quotidien.', + 'The installation of PrestaShop is quick and easy. In just a few moments, you will become part of a community consisting of more than 150,000 merchants. You are on the way to creating your own unique online store that you can manage easily every day.' => 'L\'installation de PrestaShop est simple et rapide. En quelques minutes seulement, vous rejoindrez une communauté de plus de 150 000 marchands pour créer une boutique en ligne à votre image et la gérer facilement au quotidien.', 'Continue the installation in:' => 'Continuer l\'installation en :', 'The language selection above only applies to the Installation Assistant. Once your store is installed, you can choose the language of your store from over %d translations, all for free!' => 'Le choix de la langue ci-dessus s\'applique à l\'assistant d\'installation. Une fois votre boutique installée, vous pourrez choisir la langue de votre boutique parmi plus de %d traductions disponibles gratuitement !', - 'To use PrestaShop, you must create a database to collect all of your store’s data-related activities.' => 'Pour utiliser PrestaShop, vous devez créer une base de données afin de rassembler l\'ensemble des données liées à l\'activité de votre boutique.', + 'To use PrestaShop, you must create a database to collect all of your store’s data-related activities.' => 'Pour utiliser PrestaShop, vous devez créer une base de données afin de rassembler l\'ensemble des données liées à l\'activité de votre boutique.', 'Please complete the fields below in order for PrestaShop to connect to your database. ' => 'Merci de renseigner ci-dessous les informations requises pour que PrestaShop puisse se connecter à votre base de données.', 'The default port is 3306. To use a different port, add the port number at the end of your server’s address i.e ":4242".' => 'Si vous souhaitez utiliser un port différent du port par défaut (3306) ajoutez ":XX" à l\'adresse de votre serveur, XX étant le numéro de votre port.', 'Test your database connection now!' => 'Tester la connexion à la base de données', @@ -240,5 +240,13 @@ return array( 'Sign-up to the newsletter' => 'S\'inscrire à la newsletter de PrestaShop', 'PrestaShop can provide you with guidance on a regular basis by sending you tips on how to optimize the management of your store which will help you grow your business. If you do not wish to receive these tips, please uncheck this box.' => 'PrestaShop peut vous guider de façon régulière en vous faisant parvenir des conseils afin d\'optimiser la gestion de votre boutique et développer votre activité. Si vous ne souhaitez pas recevoir ces conseils, nous vous invitons à décocher cette case.', 'Your PHP sessions path is not writable - check with your hosting provider:' => 'Le dossier de stockage n\'est pas accessible en écriture - consultez votre hébergeur', + 'Database is created' => 'Base de données créée', + 'Cannot create the database automatically' => 'Impossible de créer la base de données automatiquement', + 'Install modules Addons' => 'Installation des modules Addons', + 'Attempt to create the database automatically' => 'Essayer de créer la base de données automatiquement', + 'Country:' => 'Pays :', + 'Must be letters and numbers with at least 8 characters' => 'Lettres et chiffres avec au moins 8 caractères', + 'To install PrestaShop, you need to have JavaScript enabled in your browser.' => 'Pour installer PrestaShop, vous devez avoir JavaScript activé dans votre navigateur', + 'For security purposes, you must delete the "install" folder.' => 'Pour des raisons de sécurité, vous devez supprimer le dossier "install" manuellement.', ), -); +); \ No newline at end of file diff --git a/install-dev/langs/it/data/tab.xml b/install-dev/langs/it/data/tab.xml index cbf510160..d92e19771 100644 --- a/install-dev/langs/it/data/tab.xml +++ b/install-dev/langs/it/data/tab.xml @@ -64,7 +64,6 @@ - @@ -76,7 +75,7 @@ - + @@ -100,6 +99,5 @@ - diff --git a/install-dev/langs/it/install.php b/install-dev/langs/it/install.php index 77e6eb468..ac4e5c6c7 100644 --- a/install-dev/langs/it/install.php +++ b/install-dev/langs/it/install.php @@ -2,6 +2,8 @@ return array( 'informations' => array( 'phone' => '+33 (0)1.40.18.30.04', + 'support' => 'https://www.prestashop.com/it/support', + 'blog' => 'http://www.prestashop.com/blog/it/' ), 'translations' => array( 'menu_welcome' => 'Scelta della lingua', @@ -15,9 +17,9 @@ return array( 'Invalid shop name' => 'Nome negozio non valido', 'Your firstname contains some invalid characters' => 'Il tuo nome contiene caratteri non validi', 'Your lastname contains some invalid characters' => 'Il tuo cognome contiene caratteri non validi', - 'The password is incorrect (alphanumeric string with at least 8 characters)' => 'La password non è corretta (stringa alfanumerica di almeno 8 caratteri)', - 'Password and its confirmation are different' => 'La prima password digitata non coincide con la seconda', - 'This e-mail address is invalid' => 'L\'indirizzo e-mail non è valido', + 'The password is incorrect (alphanumeric string with at least 8 characters)' => 'La password non è corretta (sequenza alfanumerica di almeno 8 caratteri)', + 'Password and its confirmation are different' => 'La password digitata non coincide con la conferma della stessa', + 'This e-mail address is invalid' => 'L\'indirizzo email non è valido', 'The uploaded file exceeds the upload_max_filesize directive in php.ini' => 'Il file inviato supera la dimensione massima autorizzata.', 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form' => 'Il file inviato supera la dimensione massima autorizzata.', 'The uploaded file was only partially uploaded' => 'Il file è stato parzialmente inviato.', @@ -33,7 +35,7 @@ return array( 'Lingerie and Adult' => 'Intimo e adulti', 'Animals and Pets' => 'Animali', 'Art and Culture' => 'Arte e cultura', - 'Babies' => 'Neonato', + 'Babies' => 'Neonati', 'Beauty and Personal Care' => 'Bellezza e cura del corpo', 'Cars' => 'Automobili', 'Computer Hardware and Software' => 'Informatica e software', @@ -49,7 +51,7 @@ return array( 'Services' => 'Servizi', 'Shoes and accessories' => 'Scarpe e accessori', 'Sports and Entertainment' => 'Sport e divertimenti', - 'Travel' => 'Viaggi e turismo', + 'Travel' => 'Viaggi', 'Database is connected' => 'Il database è connesso', 'A test e-mail has been sent to %s' => 'Un\'e-mail di prova è stata inviata a %s', 'An error occurred while sending email, please verify your parameters' => 'Si è verificato un errore nell\'invio dell\'e-mail. Controlla le impostazioni.', @@ -58,7 +60,7 @@ return array( 'Populate database tables' => 'Compilazione tabelle nel database', 'Configure shop information' => 'Configurazione del negozio', 'Install modules' => 'Installazione moduli', - 'Install demonstration data' => 'Installazione demo', + 'Install demonstration data' => 'Installazione dati dimostrativi', 'Install theme' => 'Installazione del tema', 'PHP parameters:' => 'Parametri PHP:', 'Is PHP 5.1.2 or later installed ?' => 'PHP 5.1.2 o successivi installato?', @@ -80,21 +82,21 @@ return array( 'Please choose your main activity' => 'Seleziona l\'attività principale', 'Other activity...' => 'Altre attività...', 'This information is not required, it will only be used for statistical purposes. This information does not change anything in your store.' => 'Queste informazioni non sono obbligatorie, saranno utilizzate a fini statistici. Queste informazioni non cambieranno nulla nel tuo negozio.', - 'Install demo products:' => 'Installazione prodotti demo:', + 'Install demo products:' => 'Installazione prodotti dimostrativi:', 'Yes' => 'Sì', 'No' => 'No', - 'Demo products are a good way to learn how to use PrestaShop. You should install them if you are not familiar with it.' => 'I prodotti demo sono un buon modo per imparare a utilizzare PrestaShop. Dovresti installarli se non hai ancora dimestichezza con la soluzione', + 'Demo products are a good way to learn how to use PrestaShop. You should install them if you are not familiar with it.' => 'I prodotti dimostrativi sono un buon modo per imparare a utilizzare PrestaShop. Dovresti installarli se non hai ancora dimestichezza con la piattaforma.', 'Default country:' => 'Paese di default:', 'Select your country' => 'Seleziona il tuo paese', - 'Shop timezone:' => 'Zona oraria del negozio:', - 'Select your timezone' => 'Seleziona la tua zona oraria', + 'Shop timezone:' => 'Fuso orario del negozio:', + 'Select your timezone' => 'Seleziona il tuo fuso orario', 'Shop logo:' => 'Logo del negozio:', 'Recommended dimensions:' => 'Dimensioni suggerite:', 'First name:' => 'Nome:', 'Last name:' => 'Cognome:', - 'E-mail address:' => 'Indirizzo e-mail:', + 'E-mail address:' => 'Indirizzo email:', 'Shop password:' => 'Password del negozio:', - 'Re-type to confirm:' => 'Ridigita la password:', + 'Re-type to confirm:' => 'Digita nuovamente la password:', 'Receive this information by e-mail' => 'Riceverò le mie informazioni tramite e-mail', 'Warning: You will receive this information only if your e-mail configuration is correct.' => 'Attenzione: riceverai queste informazioni per email solo le la configurazione è corretta', 'Configure your database by filling out the following fields:' => 'Configura il database compilando i campi sottostanti:', @@ -102,23 +104,23 @@ return array( 'Database server address:' => 'Indirizzo server del database:', 'If you want to use a different port, add :XX after your server address where XX is your port number.' => 'Se vuoi utilizzare una porta differente aggiungi :XX dopo il tuo indirizzo dove XX è il numero della porta', 'Database name:' => 'Nome del database:', - 'Database login:' => 'ID del database:', + 'Database login:' => 'Nome di accesso database:', 'Database password:' => 'Password del database:', 'Database Engine:' => 'Motore del database:', 'Tables prefix:' => 'Prefisso delle tabelle:', - 'Drop existing tables (mode dev):' => 'Cancella le tabelle esistenti (modalità DEV):', + 'Drop existing tables (mode dev):' => 'Cancella le tabelle esistenti (modalità dev):', 'Verify now!' => 'Controlla ora!', 'E-mail delivery set-up' => 'Impostazioni invio e-mail', 'Configure SMTP manually (advanced users only)' => 'Configura il server SMTP manualmente (solo per utenti esperti)', 'By default, the PHP mail() function is used' => 'La funzione PHP mail() è utilizzata per default', 'SMTP server address:' => 'Indirizzo server SMTP:', - 'Encryption:' => 'Criptaggio:', + 'Encryption:' => 'Crittografia:', 'None' => 'Nessuno', 'Port:' => 'Porta:', - 'Login:' => 'ID:', + 'Login:' => 'Nome:', 'Password:' => 'Password:', - 'enter@your.email' => 'inserisci@latua.email', - 'Send me a test email!' => 'Inviami un\'e-mail di prova!', + 'enter@your.email' => 'inserisci@la.tua.email', + 'Send me a test email!' => 'Inviami un\'email di prova!', 'Next' => 'Avanti', 'Back' => 'Indietro', 'Official forum' => 'Forum ufficiale', @@ -128,17 +130,17 @@ return array( 'Forum' => 'Forum', 'Blog' => 'Blog', 'Done!' => 'Fatto!', - 'An error occured during installation...' => 'Si è verificato un errore in fase di installazione…', + 'An error occured during installation...' => 'Si è verificato un errore durane la fase di installazione…', 'You can use the links on the left column to go back to the previous steps, or restart the installation process by clicking here.' => 'Puoi usare i link sulla colonna di sinistra per tornare indietro alle fasi precedenti, oppure puoi riavviare il processo di installazione cliccando qui.', 'Your installation is finished!' => 'Installazione conclusa!', - 'You have just finished installing your shop. Thank you for using PrestaShop!' => 'Il tuo negozio è stato installato correttamente. Grazie di aver scelto PrestaShop!', - 'Please remember your login information:' => 'Ricorda i dati per il login:', + 'You have just finished installing your shop. Thank you for using PrestaShop!' => 'Il tuo negozio è stato installato correttamente. Grazie per aver scelto PrestaShop!', + 'Please remember your login information:' => 'Ricorda le credenziali per il login:', 'WARNING: For security purposes, you must delete the "install" folder.' => 'ATTENZIONE: per motivi di sicurezza, devi cancellare la cartella \'install\'.', 'Back Office' => 'Back Office', - 'Manage your store using your Back Office. Manage your orders and customers, add modules, change themes, etc.' => 'Gestisci il tuo negozio a partire dal Back Office. Gestisci ordini e clienti, aggiungi moduli, modifica i temi...', + 'Manage your store using your Back Office. Manage your orders and customers, add modules, change themes, etc.' => 'Gestisci il tuo negozio tramite il Back Office. Gestisci ordini e clienti, aggiungi moduli, modifica i temi, ecc.', 'Manage your store' => 'Gestisci il negozio', 'Front Office' => 'Front Office', - 'Discover your store as your future customers will see it!' => 'Scopri come vedranno il negozio i tuoi futuri clienti!', + 'Discover your store as your future customers will see it!' => 'Scopri come i tuoi futuri clienti vedranno il negozio!', 'Discover your store' => 'Scopri il negozio', 'Required set-up. Please verify the following checklist items are true.' => 'Impostazioni obbligatorie. Per favore verifica che la lista sia ok', 'Your configuration is valid, click next to continue!' => 'La tua configurazione è valida, clicca su avanti per continuare', @@ -147,62 +149,62 @@ return array( 'Refresh these settings' => 'Aggiorna le impostazioni', 'Welcome to the PrestaShop %s Installer.' => 'Benvenuto nell\'Assistente di Installazione di PrestaShop %s .', 'The installation process should take only few minutes!' => 'Il processo di installazione dovrebbe durare solo pochi minuti!', - 'If you need help, do not hesitate to check our documentation or to contact our support team: %2$s' => 'Se hai bisogno di aiuto, consulta i nostri documenti oppure contatta il nostro servizio di assistenza: %2$s', + 'If you need help, do not hesitate to check our documentation or to contact our support team: %2$s' => 'Se hai bisogno di aiuto, consulta la nostra documentazione oppure contatta il nostro servizio di assistenza: %2$s', 'Did you know?' => 'Lo sapevi?', 'PrestaShop and its community offers over %d different languages for free, directly accessible from your Back Office on the Localization tab.' => 'PrestaShop e la sua comunità offre %d diverse lingue gratuite, direttamente accessibile nel tuo back office nel tab Traduzioni', - 'License Agreements' => 'Contratti di Licenza', + 'License Agreements' => 'Accordi di licenza', 'PrestaShop core is released under the OSL 3.0 while PrestaShop modules and themes are released under the AFL 3.0.' => 'Il core di PrestaShop è rilasicata sollo licenza OSL 3.0 mentre i moduli e i temi prestashop sono rilasciati sotto licenza AFL 3.0', - 'I agree to the above terms and conditions.' => 'Accetto i termini e le condizioni dei presenti contratti.', - 'I agree to participate in improving the solution by sending anonymous information about my configuration.' => 'Accetto di contribuire al miglioramento della soluzione inviando informazioni anonime sulla mia configurazione.', - 'If you have any questions, please visit our documentation and community forum.' => 'Se hai domande o dubbi, visita i nostri documenti e il forum dedicato alla nostra comunità.', + 'I agree to the above terms and conditions.' => 'Accetto i termini e le condizioni dei presenti accordi.', + 'I agree to participate in improving the solution by sending anonymous information about my configuration.' => 'Accetto di contribuire al miglioramento della piattaforma mediante l\'invio di informazioni anonime sulla mia configurazione.', + 'If you have any questions, please visit our documentation and community forum.' => 'Se hai domande o dubbi, visita la nostra documentazione e il forum dedicato alla nostra comunità.', 'Test message from PrestaShop' => 'Messaggio di prova da parte di Prestashop', 'This is a test message, your server is now available to send email' => 'Questo è un messaggio di prova, il tuo server può ora inviare e-mail', '%s - Login information' => '%s - credenziali per il login', 'An SQL error occured for entity %1$s: %2$s' => 'Si è verificato un errore SQL per l\'entità %1$s: %2$s', 'Cannot create image "%1$s" for entity "%2$s"' => 'Impossibile creare l\'immagine "%1$s" per l\'entità "%2$s"', - 'Cannot create image "%1$s" (bad permissions on folder "%2$s")' => 'Impossibile creare l\'immagine "%1$s" (errore permessi cartella "%2$s")', + 'Cannot create image "%1$s" (bad permissions on folder "%2$s")' => 'Impossibile creare l\'immagine "%1$s" (errore permessi nella cartella "%2$s")', 'Cannot create image "%s"' => 'Impossibile creare l\'immagine "%s"', - 'SQL error on query %s' => 'Errore SQL nella ricerca %s', + 'SQL error on query %s' => 'Errore SQL nella query %s', 'Server name is not valid' => 'Il nome del server non è valido', - 'You must enter a database name' => 'Digita il nome del database', - 'You must enter a database login' => 'Digita i dati di accesso al database', + 'You must enter a database name' => 'Devi inserire il nome del database', + 'You must enter a database login' => 'Devi inserire un nome di accesso al database', 'Tables prefix is invalid' => 'Prefisso tabelle non valido', 'Wrong engine chosen for MySQL' => 'Il motore selezionato non è valido per MySQL', 'Cannot convert database data to utf-8' => 'Impossibile convertire i dati del database in utf-8', 'At least one table with same prefix was already found, please change your prefix or drop your database' => 'È stata trovata almeno un\'altra tabella con lo stesso prefisso. Cambia il prefisso o cancella le altre tabelle esistenti.', - 'Database Server is not found. Please verify the login, password and server fields' => 'Impossibile connettersi al server del database. Verifica l\'ID, la password e i campi riservati al server', + 'Database Server is not found. Please verify the login, password and server fields' => 'Impossibile connettersi al server del database. Verifica i campi con il nome di accesso, la password e il server', 'Connection to MySQL server succeeded, but database "%s" not found' => 'La connessione al server MySQL è avvenuta con successo, ma è impossibile trovare il database "%s"', 'Engine innoDB is not supported by your MySQL server, please use MyISAM' => 'Il motore innoDB non è supportato dal tuo server MySQL. Adopera MyISAM', '%s file is not writable (check permissions)' => 'Il file %s non è scrivibile (verifica i permessi)', '%s folder is not writable (check permissions)' => 'La cartella %s non è scrivibile (verifica i permessi)', - 'Cannot write settings file' => 'Impossibile generare il file settings', + 'Cannot write settings file' => 'Impossibile generare il file di impostazioni (settings)', 'Database structure file not found' => 'Struttura del database non trovata', - 'Cannot create group shop' => 'Impossibile accedere al gruppo del negozio', + 'Cannot create group shop' => 'Impossibile creare il gruppo negozi', 'Cannot create shop' => 'Impossibile creare il negozio', 'Cannot create shop URL' => 'Impossibile creare l\'URL del negozio', - 'File "language.xml" not found for language iso "%s"' => 'File "language.xml" non trovato per l\'iso "%s"', - 'File "language.xml" not valid for language iso "%s"' => 'File "language.xml" non valido per l\'iso "%s"', + 'File "language.xml" not found for language iso "%s"' => 'File "language.xml" non trovato per la lingua con iso "%s"', + 'File "language.xml" not valid for language iso "%s"' => 'File "language.xml" non valido per la lingua con iso "%s"', 'Cannot install language "%s"' => 'Impossibile installare la lingua "%s"', 'Cannot create admin account' => 'Impossibile creare l\'account admin', 'Cannot install module "%s"' => 'Impossibile installare il modulo "%s"', - 'Fixtures class "%s" not found' => 'Classe "%s" per le fixture non trovata', + 'Fixtures class "%s" not found' => 'Classe fixture "%s" non trovata', '"%s" must be an instane of "InstallXmlLoader"' => '"%s" deve essere un\'istanza di "InstallXmlLoader"', 'Information about your Store' => 'Informazioni relative al negozio', 'Help us learn more about your store so we can offer you optimal guidance and the best features for your business!' => 'Aiutaci a conoscerti per orientarti al meglio e proporti le funzioni più adatte alla tua attività!', 'Optional - You can add you logo at a later time.' => 'Facoltativo – Potrai aggiungerlo in un secondo momento.', 'Your Account' => 'Il tuo account', - 'This email address will be your username to access your store\'s back office.' => 'Questo indirizzo e-mail sarà l\'ID con cui potrai accedere all’interfaccia di gestione del negozio.', - 'PrestaShop can provide you with guidance on a regular basis by sending you tips on how to optimize the management of your store which will help you grow your business. If you do not wish to receive these tips, please uncheck this box.' => 'PrestaShop può assisterti regolarmente facendoti pervenire i suoi consigli per ottimizzare la gestione del negozio e sviluppare la tua attività online. Se non desideri ricevere i nostri consigli, ti invitiamo a deselezionare questa casella.', + 'This email address will be your username to access your store\'s back office.' => 'Questo indirizzo email sarà il tuo nome utente con cui potrai accedere all’interfaccia di gestione del negozio.', + 'PrestaShop can provide you with guidance on a regular basis by sending you tips on how to optimize the management of your store which will help you grow your business. If you do not wish to receive these tips, please uncheck this box.' => 'PrestaShop può assisterti regolarmente facendoti pervenire i suoi consigli per ottimizzare la gestione del negozio e sviluppare la tua attività online. Se non desideri ricevere i nostri consigli, deseleziona questa casella.', 'The field %s is limited to %d characters' => 'Il campo %s può comprendere fino a %d caratteri', - 'An error occurred during logo copy.' => 'Si è verificato un errore durante la copiatura del logo', - 'An error occurred during logo upload.' => 'Si è verificato un errore durante il caricamento del logo', - 'Create default shop and languages' => 'Creazione negozio e lingue per default', + 'An error occurred during logo copy.' => 'Si è verificato un errore durante la copiatura del logo.', + 'An error occurred during logo upload.' => 'Si è verificato un errore durante il caricamento del logo.', + 'Create default shop and languages' => 'Creazione negozio e lingue di default', 'PHP 5.1.2 or later is not enabled' => 'PHP 5.1.2 o successivo non attivo', 'Cannot upload files' => 'Impossibile caricare i file', 'Cannot create new files and folders' => 'Impossibile creare nuovi file e cartelle', - 'GD Library is not installed' => 'La GD Library non è installata', - 'MySQL support is not activated' => 'L\'assistenza di MySQL non è attiva', - 'Recursive write permissions on files and folders:' => 'Permessi scrittura ricorsiva su file e cartelle:', + 'GD Library is not installed' => 'La libreria GD non è installata', + 'MySQL support is not activated' => 'Il supporto MySQL non è attivo', + 'Recursive write permissions on files and folders:' => 'Permessi di scrittura ricorsivi su file e cartelle:', 'Cannot open external URLs' => 'Impossibile aprire URL esterne', 'PHP register global option is on' => 'L\'opzione PHP register global è attiva', 'GZIP compression is not activated' => 'La compressione GZIP non è attiva', @@ -213,26 +215,35 @@ return array( 'PDO MySQL extension is not loaded' => 'L\'estensione PDO MySQL non è caricata', 'Cannot copy flag language "%s"' => 'Impossibile copiare la bandiera per la lingua "%s"', 'Must be alphanumeric string with at least 8 characters' => 'Deve essere una stringa alfanumerica di almeno 8 caratteri', - 'Sign-up to the newsletter' => 'Mi abbono alla newsletter', + 'Sign-up to the newsletter' => 'Abbonamento alla newsletter', 'To use PrestaShop, you must create a database to collect all of your store’s data-related activities.' => 'Per usare PrestaShop, devi creare un database per riunire tutti i dati inerenti alle attività del tuo negozio.', 'Please complete the fields below in order for PrestaShop to connect to your database. ' => 'Compila i campi sottostanti per far sì che PrestaShop possa connettersi al tuo database.', - 'The default port is 3306. To use a different port, add the port number at the end of your server’s address i.e ":4242".' => 'La porta di default è 3306. Per usare un\'altra porta, digita il numero della porta alla fine del tuo indirizzo di server. Per esempio: "4242".', - 'Test your database connection now!' => 'Verifica subito la connessione al tuo database!', - 'If you need some assistance during the installation process, please call our team at %s and one of our experts will be happy to help.' => 'Se si verificano problemi durante il processo di installazione, chiamaci allo %s. Uno dei nostri esperti sarà felice di aiutarti.', + 'The default port is 3306. To use a different port, add the port number at the end of your server’s address i.e ":4242".' => 'La porta di default è 3306. Per usare un\'altra porta, digita il numero della porta alla fine dell\'indirizzo server. Ad esempio ":4242".', + 'Test your database connection now!' => 'Verifica adesso la connessione al tuo database!', + 'If you need some assistance during the installation process, please call our team at %s and one of our experts will be happy to help.' => 'Se si verificano problemi durante il processo di installazione, chiamaci: %s. Uno dei nostri esperti sarà felice di aiutarti.', 'PrestaShop Installation Assistant' => 'Assistente di Installazione PrestaShop', 'Contact us!' => 'Contattaci!', 'Installation Assistant' => 'Assistente di Installazione', 'To enjoy the many features that are offered by PrestaShop, please read the license terms below. PrestaShop core is licensed under OSL 3.0, while the modules and themes are licensed under AFL 3.0.' => 'Per usufruire delle numerose funzioni offerte da PrestaShop, leggi i termini e le condizioni dei contratti di licenza. Il core di PrestaShop è pubblicato sotto licenza OSL 3.0, mentre i moduli e i temi sotto licenza AFL 3.0. ', - 'E-mail:' => 'E-mail:', - 'Print my login information' => 'Stampa delle credenziali per il login', + 'E-mail:' => 'Email:', + 'Print my login information' => 'Stampa le credenziali per il login', 'Display' => 'Visualizza', 'We are currently checking PrestaShop compatibility with your system environment' => 'Stiamo verificando la compatibilità di PrestaShop con il tuo sistema', - 'PrestaShop compatibility with your system environment has been verified!' => 'Abbiamo verificato la compatibilità del tuo sistema con PrestaShop!', - 'Oops! Please correct the item(s) below, and then click "Refresh information" to test the compatibility of your new system.' => 'Correggi i punti seguenti, quindi clicca sul pulsante "Aggiorna" per verificare la compatibilità di PrestaShop con il nuovo sistema.', - 'PrestaShop requires at least 32M of memory to run, please check the memory_limit directive in php.ini or contact your host provider' => 'L\'esecuzione di PrestaShop necessita di almeno 32M di memoria. Controlla i limiti della tua memoria in php.ini o contatta il tuo fornitore di hosting', - 'The installation of PrestaShop is quick and easy. In just a few moments, you will become part of a community consisting of more than 130,000 merchants. You are on the way to creating your own unique online store that you can manage easily every day.' => 'L\'installazione di PrestaShop è semplice e veloce. Tra pochi minuti, farai parte di una comunità di oltre 130.000 commercianti. Potrai creare un negozio a tua immagina e facile da gestire giorno dopo giorno.', + 'PrestaShop compatibility with your system environment has been verified!' => 'La compatibilità del tuo sistema con PrestaShop è stata verificata!', + 'Oops! Please correct the item(s) below, and then click "Refresh information" to test the compatibility of your new system.' => 'Ops! Correggi i seguenti punti, quindi clicca sul pulsante "Aggiorna" per verificare la compatibilità di PrestaShop del tuo nuovo sistema.', + 'PrestaShop requires at least 32M of memory to run, please check the memory_limit directive in php.ini or contact your host provider' => 'L\'esecuzione di PrestaShop necessita di almeno 32M di memoria. Controlla la voce memory_limit nel file php.ini o contatta il tuo fornitore di hosting', + 'The installation of PrestaShop is quick and easy. In just a few moments, you will become part of a community consisting of more than 150,000 merchants. You are on the way to creating your own unique online store that you can manage easily every day.' => 'L\'installazione di PrestaShop è semplice e veloce. In pochi minuti, farai parte di una comunità di oltre 150.000 commercianti. Potrai creare un negozio unico a tuo piacere, facile da gestire giorno dopo giorno.', 'Continue the installation in:' => 'Continua l\'installazione in:', - 'The language selection above only applies to the Installation Assistant. Once your store is installed, you can choose the language of your store from over %d translations, all for free!' => 'La selezione della lingua si applica solo all\'Assistente di Installazione. Una volta che il negozio è installato, potrai scegliere la lingua del negozio tra le oltre %d traduzioni disponibili gratuitamente!', + 'The language selection above only applies to the Installation Assistant. Once your store is installed, you can choose the language of your store from over %d translations, all for free!' => 'La selezione della lingua qui sopra è valida solamente nell\'Assistente di Installazione. Una volta che il negozio è installato, potrai scegliere la lingua del negozio tra le oltre %d traduzioni disponibili gratuitamente!', 'Your PHP sessions path is not writable - check with your hosting provider:' => 'La cartella di backup non è accessibile per scrittura - consulta il nostro servizio di hosting', + 'Database is created' => 'Il database è creato', + 'Cannot create the database automatically' => 'Non è possibile creare il database automaticamente', + 'Install modules Addons' => 'Installazione moduli Addons', + 'Attempt to create the database automatically' => 'Tentativo di creare il database automaticamente', + 'Country:' => 'Paese:', + 'Must be letters and numbers with at least 8 characters' => 'Deve contenere lettere e numeri ed essere composta da almeno 8 caratteri', + 'To install PrestaShop, you need to have JavaScript enabled in your browser.' => 'Per installare PrestaShop, devi avere JavaScript abilitato nel tuo browser.', + 'To enjoy the many features that are offered for free by PrestaShop, please read the license terms below. PrestaShop core is licensed under OSL 3.0, while the modules and themes are licensed under AFL 3.0.' => 'Per godere delle svariate funzioni che PrestaShop offre gratuitamente, si prega di leggere le condizioni di licenza qui di seguito. Il nucleo di PrestaShop è rilasciato sotto licenza OSL 3.0, mentre i moduli e i temi sono rilasciati sotto licenza AFL 3.0.', + 'For security purposes, you must delete the "install" folder.' => 'Per motivi di sicurezza, devi cancellare la cartella "install".', ), -); \ No newline at end of file +); diff --git a/install-dev/langs/nl/data/carrier.xml b/install-dev/langs/nl/data/carrier.xml new file mode 100644 index 000000000..343fa6f51 --- /dev/null +++ b/install-dev/langs/nl/data/carrier.xml @@ -0,0 +1,6 @@ + + + + Pick up in-store + + diff --git a/install-dev/langs/nl/data/category.xml b/install-dev/langs/nl/data/category.xml new file mode 100644 index 000000000..87b90b95e --- /dev/null +++ b/install-dev/langs/nl/data/category.xml @@ -0,0 +1,19 @@ + + + + Root + + root + + + + + + Home + + home + + + + + diff --git a/install-dev/langs/nl/data/cms.xml b/install-dev/langs/nl/data/cms.xml new file mode 100644 index 000000000..37edee2c4 --- /dev/null +++ b/install-dev/langs/nl/data/cms.xml @@ -0,0 +1,45 @@ + + + + Delivery + Our terms and conditions of delivery + conditions, delivery, delay, shipment, pack + <h2>Shipments and returns</h2><h3>Your pack shipment</h3><p>Packages are generally dispatched within 2 days after receipt of payment and are shipped via UPS with tracking and drop-off without signature. If you prefer delivery by UPS Extra with required signature, an additional cost will be applied, so please contact us before choosing this method. Whichever shipment choice you make, we will provide you with a link to track your package online.</p><p>Shipping fees include handling and packing fees as well as postage costs. Handling fees are fixed, whereas transport fees vary according to total weight of the shipment. We advise you to group your items in one order. We cannot group two distinct orders placed separately, and shipping fees will apply to each of them. Your package will be dispatched at your own risk, but special care is taken to protect fragile objects.<br /><br />Boxes are amply sized and your items are well-protected.</p> + delivery + + + Legal Notice + Legal notice + notice, legal, credits + <h2>Legal</h2><h3>Credits</h3><p>Concept and production:</p><p>This Web site was created using <a href="http://www.prestashop.com">PrestaShop</a>&trade; open-source software.</p> + legal-notice + + + Terms and conditions of use + Our terms and conditions of use + conditions, terms, use, sell + <h2>Your terms and conditions of use</h2><h3>Rule 1</h3><p>Here is the rule 1 content</p> +<h3>Rule 2</h3><p>Here is the rule 2 content</p> +<h3>Rule 3</h3><p>Here is the rule 3 content</p> + terms-and-conditions-of-use + + + About us + Learn more about us + about us, informations + <h2>About us</h2> +<h3>Our company</h3><p>Our company</p> +<h3>Our team</h3><p>Our team</p> +<h3>Informations</h3><p>Informations</p> + about-us + + + Secure payment + Our secure payment mean + secure payment, ssl, visa, mastercard, paypal + <h2>Secure payment</h2> +<h3>Our secure payment</h3><p>With SSL</p> +<h3>Using Visa/Mastercard/Paypal</h3><p>About this services</p> + secure-payment + + diff --git a/install-dev/langs/nl/data/cms_category.xml b/install-dev/langs/nl/data/cms_category.xml new file mode 100644 index 000000000..ceb8cf491 --- /dev/null +++ b/install-dev/langs/nl/data/cms_category.xml @@ -0,0 +1,11 @@ + + + + Home + + home + + + + + diff --git a/install-dev/langs/nl/data/configuration.xml b/install-dev/langs/nl/data/configuration.xml new file mode 100644 index 000000000..ef31b5d07 --- /dev/null +++ b/install-dev/langs/nl/data/configuration.xml @@ -0,0 +1,21 @@ + + + + IN + + + DE + + + a|the|of|on|in|and|to + + + 0 + + + Dear Customer, + +Regards, +Customer service + + diff --git a/install-dev/langs/nl/data/contact.xml b/install-dev/langs/nl/data/contact.xml new file mode 100644 index 000000000..bdc0b24d9 --- /dev/null +++ b/install-dev/langs/nl/data/contact.xml @@ -0,0 +1,9 @@ + + + + If a technical problem occurs on this website + + + For any question about a product, an order + + diff --git a/install-dev/langs/nl/data/country.xml b/install-dev/langs/nl/data/country.xml new file mode 100644 index 000000000..d57ea1e36 --- /dev/null +++ b/install-dev/langs/nl/data/country.xml @@ -0,0 +1,735 @@ + + + + Germany + + + Austria + + + Belgium + + + Canada + + + China + + + Spain + + + Finland + + + France + + + Greece + + + Italy + + + Japan + + + Luxemburg + + + Netherlands + + + Poland + + + Portugal + + + Czech Republic + + + United Kingdom + + + Sweden + + + Switzerland + + + Denmark + + + United States + + + HongKong + + + Norway + + + Australia + + + Singapore + + + Ireland + + + New Zealand + + + South Korea + + + Israel + + + South Africa + + + Nigeria + + + Ivory Coast + + + Togo + + + Bolivia + + + Mauritius + + + Romania + + + Slovakia + + + Algeria + + + American Samoa + + + + Angola + + + Anguilla + + + Antigua and Barbuda + + + Argentina + + + Armenia + + + Aruba + + + Azerbaijan + + + Bahamas + + + Bahrain + + + Bangladesh + + + Barbados + + + Belarus + + + Belize + + + Benin + + + Bermuda + + + Bhutan + + + Botswana + + + Brazil + + + Brunei + + + Burkina Faso + + + Burma (Myanmar) + + + Burundi + + + Cambodia + + + Cameroon + + + Cape Verde + + + Central African Republic + + + Chad + + + Chile + + + Colombia + + + Comoros + + + Congo, Dem. Republic + + + Congo, Republic + + + Costa Rica + + + Croatia + + + Cuba + + + Cyprus + + + Djibouti + + + Dominica + + + Dominican Republic + + + East Timor + + + Ecuador + + + Egypt + + + El Salvador + + + Equatorial Guinea + + + Eritrea + + + Estonia + + + Ethiopia + + + Falkland Islands + + + Faroe Islands + + + Fiji + + + Gabon + + + Gambia + + + Georgia + + + Ghana + + + Grenada + + + Greenland + + + Gibraltar + + + Guadeloupe + + + Guam + + + Guatemala + + + Guernsey + + + Guinea + + + Guinea-Bissau + + + Guyana + + + Haiti + + + Heard Island and McDonald Islands + + + Vatican City State + + + Honduras + + + Iceland + + + India + + + Indonesia + + + Iran + + + Iraq + + + Man Island + + + Jamaica + + + Jersey + + + Jordan + + + Kazakhstan + + + Kenya + + + Kiribati + + + Korea, Dem. Republic of + + + Kuwait + + + Kyrgyzstan + + + Laos + + + Latvia + + + Lebanon + + + Lesotho + + + Liberia + + + Libya + + + Liechtenstein + + + Lithuania + + + Macau + + + Macedonia + + + Madagascar + + + Malawi + + + Malaysia + + + Maldives + + + Mali + + + Malta + + + Marshall Islands + + + Martinique + + + Mauritania + + + Hungary + + + Mayotte + + + Mexico + + + Micronesia + + + Moldova + + + Monaco + + + Mongolia + + + Montenegro + + + Montserrat + + + Morocco + + + Mozambique + + + Namibia + + + Nauru + + + Nepal + + + Netherlands Antilles + + + New Caledonia + + + Nicaragua + + + Niger + + + Niue + + + Norfolk Island + + + Northern Mariana Islands + + + Oman + + + Pakistan + + + Palau + + + Palestinian Territories + + + Panama + + + Papua New Guinea + + + Paraguay + + + Peru + + + Philippines + + + Pitcairn + + + Puerto Rico + + + Qatar + + + Reunion Island + + + Russian Federation + + + Rwanda + + + Saint Barthelemy + + + Saint Kitts and Nevis + + + Saint Lucia + + + Saint Martin + + + Saint Pierre and Miquelon + + + Saint Vincent and the Grenadines + + + Samoa + + + San Marino + + + São Tomé and Príncipe + + + Saudi Arabia + + + Senegal + + + Serbia + + + Seychelles + + + Sierra Leone + + + Slovenia + + + Solomon Islands + + + Somalia + + + South Georgia and the South Sandwich Islands + + + Sri Lanka + + + Sudan + + + Suriname + + + Svalbard and Jan Mayen + + + Swaziland + + + Syria + + + Taiwan + + + Tajikistan + + + Tanzania + + + Thailand + + + Tokelau + + + Tonga + + + Trinidad and Tobago + + + Tunisia + + + Turkey + + + Turkmenistan + + + Turks and Caicos Islands + + + Tuvalu + + + Uganda + + + Ukraine + + + United Arab Emirates + + + Uruguay + + + Uzbekistan + + + Vanuatu + + + Venezuela + + + Vietnam + + + Virgin Islands (British) + + + Virgin Islands (U.S.) + + + Wallis and Futuna + + + Western Sahara + + + Yemen + + + Zambia + + + Zimbabwe + + + Albania + + + Afghanistan + + + Antarctica + + + Bosnia and Herzegovina + + + Bouvet Island + + + British Indian Ocean Territory + + + Bulgaria + + + Cayman Islands + + + Christmas Island + + + Cocos (Keeling) Islands + + + Cook Islands + + + French Guiana + + + French Polynesia + + + French Southern Territories + + + Åland Islands + + diff --git a/install-dev/langs/nl/data/gender.xml b/install-dev/langs/nl/data/gender.xml new file mode 100644 index 000000000..75fc2ed2a --- /dev/null +++ b/install-dev/langs/nl/data/gender.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/install-dev/langs/nl/data/group.xml b/install-dev/langs/nl/data/group.xml new file mode 100644 index 000000000..2d1b70934 --- /dev/null +++ b/install-dev/langs/nl/data/group.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/install-dev/langs/nl/data/index.php b/install-dev/langs/nl/data/index.php new file mode 100644 index 000000000..10edbfe91 --- /dev/null +++ b/install-dev/langs/nl/data/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2013 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header('Expires: Mon, 26 Jul 1997 05:00:00 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/install-dev/langs/nl/data/meta.xml b/install-dev/langs/nl/data/meta.xml new file mode 100644 index 000000000..bae593782 --- /dev/null +++ b/install-dev/langs/nl/data/meta.xml @@ -0,0 +1,159 @@ + + + + 404 error + This page cannot be found + error, 404, not found + page-not-found + + + Best sales + Our best sales + best sales + best-sales + + + Contact us + Use our form to contact us + contact, form, e-mail + contact-us + + + + <description>Shop powered by PrestaShop</description> + <keywords>shop, prestashop</keywords> + <url_rewrite/> + </meta> + <meta id="manufacturer" id_shop="1"> + <title>Manufacturers + Manufacturers list + manufacturer + manufacturers + + + New products + Our new products + new, products + new-products + + + Forgot your password + Enter your e-mail address used to register in goal to get e-mail with your new password + forgot, password, e-mail, new, reset + password-recovery + + + Prices drop + Our special products + special, prices drop + prices-drop + + + Sitemap + Lost ? Find what your are looking for + sitemap + sitemap + + + Suppliers + Suppliers list + supplier + supplier + + + Address + + + address + + + Addresses + + + addresses + + + Authentication + + + authentication + + + Cart + + + cart + + + Discount + + + discount + + + Order history + + + order-history + + + Identity + + + identity + + + My account + + + my-account + + + Order follow + + + order-follow + + + Order slip + + + order-slip + + + Order + + + order + + + Search + + + search + + + Stores + + + stores + + + Order + + + quick-order + + + Guest tracking + + + guest-tracking + + + Order confirmation + + + order-confirmation + + diff --git a/install-dev/langs/nl/data/order_return_state.xml b/install-dev/langs/nl/data/order_return_state.xml new file mode 100644 index 000000000..37ad31de9 --- /dev/null +++ b/install-dev/langs/nl/data/order_return_state.xml @@ -0,0 +1,18 @@ + + + + Waiting for confirmation + + + Waiting for package + + + Package received + + + Return denied + + + Return completed + + diff --git a/install-dev/langs/nl/data/order_state.xml b/install-dev/langs/nl/data/order_state.xml new file mode 100644 index 000000000..c44dc3358 --- /dev/null +++ b/install-dev/langs/nl/data/order_state.xml @@ -0,0 +1,51 @@ + + + + Awaiting cheque payment + + + + Payment accepted + + + + Preparation in progress + + + + Shipped + + + + Delivered +