{/if}
@@ -247,7 +248,6 @@
--
{/if}
-
{* Filters (input, select, date or bool) *}
{foreach $fields_display AS $key => $params}
diff --git a/admin-dev/themes/default/template/toolbar.tpl b/admin-dev/themes/default/template/toolbar.tpl
index fc8a6275d..3a68ec602 100644
--- a/admin-dev/themes/default/template/toolbar.tpl
+++ b/admin-dev/themes/default/template/toolbar.tpl
@@ -23,7 +23,7 @@
* International Registered Trademark & Property of PrestaShop SA
*}
-
+
{block name=toolbarBox}
@@ -52,7 +52,7 @@
var modules_list_loaded = false;
$(function() {
//get reference on save link
- btn_save = $('span[class~="process-icon-save"]').parent();
+ btn_save = $('#{$table}_toolbar span[class~="process-icon-save"]').parent();
//get reference on form submit button
btn_submit = $('#{$table}_form_submit_btn');
@@ -89,6 +89,9 @@
//submit the form
{block name=formSubmit}
btn_save.click(function() {
+ // Vars
+ var btn_submit = $('#{$table}_form_submit_btn');
+
// Avoid double click
if (submited)
return false;
diff --git a/classes/Address.php b/classes/Address.php
index 10600c1cf..f74697445 100644
--- a/classes/Address.php
+++ b/classes/Address.php
@@ -264,13 +264,17 @@ class AddressCore extends ObjectModel
if(!isset($id_address) || empty($id_address))
return false;
- if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
- SELECT c.`active`
- FROM `'._DB_PREFIX_.'address` a
- LEFT JOIN `'._DB_PREFIX_.'country` c ON c.`id_country` = a.`id_country`
- WHERE a.`id_address` = '.(int)$id_address))
- return false;
- return ($result['active']);
+ $cache_id = 'Address::isCountryActiveById_'.(int)$id_address;
+ if (!Cache::isStored($cache_id))
+ {
+ $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getvalue('
+ SELECT c.`active`
+ FROM `'._DB_PREFIX_.'address` a
+ LEFT JOIN `'._DB_PREFIX_.'country` c ON c.`id_country` = a.`id_country`
+ WHERE a.`id_address` = '.(int)$id_address);
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
@@ -324,12 +328,17 @@ class AddressCore extends ObjectModel
{
if (!$id_customer)
return false;
-
- return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
- SELECT `id_address`
- FROM `'._DB_PREFIX_.'address`
- WHERE `id_customer` = '.(int)$id_customer.' AND `deleted` = 0'.($active ? ' AND `active` = 1' : '')
- );
+ $cache_id = 'Address::getFirstCustomerAddressId_'.(int)$id_customer.'-'.(bool)$active;
+ if (!Cache::isStored($cache_id))
+ {
+ $result = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
+ SELECT `id_address`
+ FROM `'._DB_PREFIX_.'address`
+ WHERE `id_customer` = '.(int)$id_customer.' AND `deleted` = 0'.($active ? ' AND `active` = 1' : '')
+ );
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
@@ -379,5 +388,4 @@ class AddressCore extends ObjectModel
$query->where('id_warehouse = 0');
return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query);
}
-}
-
+}
\ No newline at end of file
diff --git a/classes/AddressFormat.php b/classes/AddressFormat.php
index 0c9fc1183..bf288096f 100644
--- a/classes/AddressFormat.php
+++ b/classes/AddressFormat.php
@@ -99,6 +99,7 @@ class AddressFormatCore extends ObjectModel
'outstanding_allow_amount',
'call_prefix',
'definition',
+ 'debug_list'
);
public static $forbiddenClassList = array(
diff --git a/classes/Autoload.php b/classes/Autoload.php
index 765a75d58..9d7a6ea28 100644
--- a/classes/Autoload.php
+++ b/classes/Autoload.php
@@ -137,25 +137,17 @@ class Autoload
// Write classes index on disc to cache it
$filename = $this->root_dir.Autoload::INDEX_FILE;
- if ((file_exists($filename) && !is_writable($filename)) || !is_writable(dirname($filename)))
+ $filename_tmp = tempnam(dirname($filename), basename($filename.'.'));
+ if ($filename_tmp !== false && file_put_contents($filename_tmp, $content, LOCK_EX) !== false)
{
- header('HTTP/1.1 503 temporarily overloaded');
- // Cannot use PrestaShopException in this context
- die('/cache/class_index.php is not writable, please give write permissions (chmod 666) on this file.');
- }
- else
- {
- $filename_tmp = tempnam(dirname($filename), basename($filename.'.'));
- if ($filename_tmp !== false && file_put_contents($filename_tmp, $content, LOCK_EX) !== false)
- {
- if (!@rename($filename_tmp, $filename))
- unlink($filename_tmp);
- @chmod($filename, 0666);
- }
- // $filename_tmp couldn't be written. $filename should be there anyway (even if outdated), no need to die.
+ if (!rename($filename_tmp, $filename))
+ unlink($filename_tmp);
else
- error_log('Cannot write temporary file '.$filename_tmp);
- }
+ @chmod($filename, 0666);
+ }
+ // $filename_tmp couldn't be written. $filename should be there anyway (even if outdated), no need to die.
+ else
+ error_log('Cannot write temporary file '.$filename_tmp);
$this->index = $classes;
}
diff --git a/classes/CMS.php b/classes/CMS.php
index 13b7cac0b..ee2f28d30 100644
--- a/classes/CMS.php
+++ b/classes/CMS.php
@@ -190,7 +190,7 @@ class CMSCore extends ObjectModel
return (Db::getInstance()->getValue($sql));
}
- public static function getCMSPages($id_lang = null, $id_cms_category = null, $active = true)
+ public static function getCMSPages($id_lang = null, $id_cms_category = null, $active = true, $id_shop = null)
{
$sql = new DbQuery();
$sql->select('*');
@@ -198,6 +198,9 @@ class CMSCore extends ObjectModel
if ($id_lang)
$sql->innerJoin('cms_lang', 'l', 'c.id_cms = l.id_cms AND l.id_lang = '.(int)$id_lang);
+ if ($id_shop)
+ $sql->innerJoin('cms_shop', 'cs', 'c.id_cms = cs.id_cms AND cs.id_shop = '.(int)$id_shop);
+
if ($active)
$sql->where('c.active = 1');
diff --git a/classes/Carrier.php b/classes/Carrier.php
index f526eb953..f7a137a5e 100644
--- a/classes/Carrier.php
+++ b/classes/Carrier.php
@@ -277,17 +277,20 @@ class CarrierCore extends ObjectModel
public function getMaxDeliveryPriceByWeight($id_zone)
{
- $sql = 'SELECT d.`price`
- FROM `'._DB_PREFIX_.'delivery` d
- INNER JOIN `'._DB_PREFIX_.'range_weight` w ON d.`id_range_weight` = w.`id_range_weight`
- WHERE d.`id_zone` = '.(int)$id_zone.'
- AND d.`id_carrier` = '.(int)$this->id.'
- '.Carrier::sqlDeliveryRangeShop('range_weight').'
- ORDER BY w.`delimiter2` DESC LIMIT 1';
- $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
- if (!isset($result[0]['price']))
- return false;
- return $result[0]['price'];
+ $cache_id = 'Carrier::getMaxDeliveryPriceByWeight_'.(int)$this->id.'-'.(int)$id_zone;
+ if (!Cache::isStored($cache_id))
+ {
+ $sql = 'SELECT d.`price`
+ FROM `'._DB_PREFIX_.'delivery` d
+ INNER JOIN `'._DB_PREFIX_.'range_weight` w ON d.`id_range_weight` = w.`id_range_weight`
+ WHERE d.`id_zone` = '.(int)$id_zone.'
+ AND d.`id_carrier` = '.(int)$this->id.'
+ '.Carrier::sqlDeliveryRangeShop('range_weight').'
+ ORDER BY w.`delimiter2` DESC';
+ $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
@@ -357,17 +360,20 @@ class CarrierCore extends ObjectModel
public function getMaxDeliveryPriceByPrice($id_zone)
{
- $sql = 'SELECT d.`price`
- FROM `'._DB_PREFIX_.'delivery` d
- INNER JOIN `'._DB_PREFIX_.'range_price` r ON d.`id_range_price` = r.`id_range_price`
- WHERE d.`id_zone` = '.(int)$id_zone.'
- AND d.`id_carrier` = '.(int)$this->id.'
- '.Carrier::sqlDeliveryRangeShop('range_price').'
- ORDER BY r.`delimiter2` DESC LIMIT 1';
- $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
- if (!isset($result[0]['price']))
- return false;
- return $result[0]['price'];
+ $cache_id = 'Carrier::getMaxDeliveryPriceByPrice_'.(int)$this->id.'-'.(int)$id_zone;
+ if (!Cache::isStored($cache_id))
+ {
+ $sql = 'SELECT d.`price`
+ FROM `'._DB_PREFIX_.'delivery` d
+ INNER JOIN `'._DB_PREFIX_.'range_price` r ON d.`id_range_price` = r.`id_range_price`
+ WHERE d.`id_zone` = '.(int)$id_zone.'
+ AND d.`id_carrier` = '.(int)$this->id.'
+ '.Carrier::sqlDeliveryRangeShop('range_price').'
+ ORDER BY r.`delimiter2` DESC';
+ $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
@@ -440,11 +446,17 @@ class CarrierCore extends ObjectModel
}
$sql .= ' GROUP BY c.`id_carrier` ORDER BY c.`position` ASC';
- $carriers = Db::getInstance()->executeS($sql);
+
+ $cache_id = 'Carrier::getCarriers_'.md5($sql);
+ if (!Cache::isStored($cache_id))
+ {
+ $carriers = Db::getInstance()->executeS($sql);
+ Cache::store($cache_id, $carriers);
+ }
+ $carriers = Cache::retrieve($cache_id);
foreach ($carriers as $key => $carrier)
if ($carrier['name'] == '0')
$carriers[$key]['name'] = Configuration::get('PS_SHOP_NAME');
-
return $carriers;
}
@@ -1184,7 +1196,14 @@ class CarrierCore extends ObjectModel
$query->where('pc.id_product = '.(int)$product->id);
$query->where('pc.id_shop = '.(int)$id_shop);
- $carriers_for_product = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query);
+ $cache_id = 'Carrier::getAvailableCarrierList_'.(int)$product->id.'-'.(int)$id_shop;
+ if (!Cache::isStored($cache_id))
+ {
+ $carriers_for_product = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query);
+ Cache::store($cache_id, $carriers_for_product);
+ }
+ $carriers_for_product = Cache::retrieve($cache_id);
+
$carrier_list = array();
if (!empty($carriers_for_product))
{
diff --git a/classes/Cart.php b/classes/Cart.php
index f38015171..4c678c978 100644
--- a/classes/Cart.php
+++ b/classes/Cart.php
@@ -325,7 +325,7 @@ class CartCore extends ObjectModel
if (!CartRule::isFeatureActive() || !$this->id)
return array();
- $cache_key = 'Cart::getCartRules'.$this->id.'-'.$filter;
+ $cache_key = 'Cart::getCartRules_'.$this->id.'-'.$filter;
if (!Cache::isStored($cache_key))
{
$result = Db::getInstance()->executeS('
@@ -368,12 +368,16 @@ class CartCore extends ObjectModel
{
if (!CartRule::isFeatureActive())
return 0;
-
- return Db::getInstance()->getValue('
- SELECT COUNT(*)
- FROM `'._DB_PREFIX_.'cart_cart_rule`
- WHERE `id_cart_rule` = '.(int)$id_cart_rule.' AND `id_cart` = '.(int)$this->id
- );
+ $cache_id = 'Cart::getDiscountsCustomer_'.(int)$this->id.'-'.(int)$id_cart_rule;
+ if (!Cache::isStored($cache_id))
+ {
+ $result = (int)Db::getInstance()->getValue('
+ SELECT COUNT(*)
+ FROM `'._DB_PREFIX_.'cart_cart_rule`
+ WHERE `id_cart_rule` = '.(int)$id_cart_rule.' AND `id_cart` = '.(int)$this->id);
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
public function getLastProduct()
@@ -632,14 +636,19 @@ class CartCore extends ObjectModel
if (!isset($row['pai_id_image']) || $row['pai_id_image'] == 0)
{
- $row2 = Db::getInstance()->getRow('
- SELECT image_shop.`id_image` id_image, il.`legend`
- FROM `'._DB_PREFIX_.'image` i
- JOIN `'._DB_PREFIX_.'image_shop` image_shop ON (i.id_image = image_shop.id_image AND image_shop.cover=1 AND image_shop.id_shop='.(int)$row['id_shop'].')
- LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (image_shop.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$this->id_lang.')
- WHERE i.`id_product` = '.(int)$row['id_product'].' AND image_shop.`cover` = 1'
- );
-
+ $cache_id = 'Cart::getProducts_'.'-pai_id_image-'.(int)$row['id_product'].'-'.(int)$this->id_lang.'-'.(int)$row['id_shop'];
+ if (!Cache::isStored($cache_id))
+ {
+ $row2 = Db::getInstance()->getRow('
+ SELECT image_shop.`id_image` id_image, il.`legend`
+ FROM `'._DB_PREFIX_.'image` i
+ JOIN `'._DB_PREFIX_.'image_shop` image_shop ON (i.id_image = image_shop.id_image AND image_shop.cover=1 AND image_shop.id_shop='.(int)$row['id_shop'].')
+ LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (image_shop.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$this->id_lang.')
+ WHERE i.`id_product` = '.(int)$row['id_product'].' AND image_shop.`cover` = 1'
+ );
+ Cache::store($cache_id, $row2);
+ }
+ $row2 = Cache::retrieve($cache_id);
if (!$row2)
$row2 = array('id_image' => false, 'legend' => false);
else
@@ -727,7 +736,7 @@ class CartCore extends ObjectModel
*
* @result integer Products quantity
*/
- public function nbProducts()
+ public function nbProducts()
{
if (!$this->id)
return 0;
@@ -1078,9 +1087,9 @@ class CartCore extends ObjectModel
);
$id_customization = Db::getInstance()->Insert_ID();
}
-
+
$query = 'INSERT INTO `'._DB_PREFIX_.'customized_data` (`id_customization`, `type`, `index`, `value`)
- VALUES ('.(int)$id_customization.', '.(int)$type.', '.(int)$index.', \''.pSql($field).'\')';
+ VALUES ('.(int)$id_customization.', '.(int)$type.', '.(int)$index.', \''.pSQL($field).'\')';
if (!Db::getInstance()->execute($query))
return false;
@@ -1094,7 +1103,13 @@ class CartCore extends ObjectModel
*/
public function orderExists()
{
- return (bool)Db::getInstance()->getValue('SELECT count(*) FROM `'._DB_PREFIX_.'orders` WHERE `id_cart` = '.(int)$this->id);
+ $cache_id = 'Cart::orderExists_'.(int)$this->id;
+ if (!Cache::isStored($cache_id))
+ {
+ $result = (bool)Db::getInstance()->getValue('SELECT count(*) FROM `'._DB_PREFIX_.'orders` WHERE `id_cart` = '.(int)$this->id);
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
@@ -2277,18 +2292,23 @@ class CartCore extends ObjectModel
public function getAddressCollection()
{
$collection = array();
- $result = Db::getInstance()->executeS(
- 'SELECT DISTINCT `id_address_delivery`
- FROM `'._DB_PREFIX_.'cart_product`
- WHERE id_cart = '.(int)$this->id
- );
+ $cache_id = 'Cart::getAddressCollection'.(int)$this->id;
+ if (!Cache::isStored($cache_id))
+ {
+ $result = Db::getInstance()->executeS(
+ 'SELECT DISTINCT `id_address_delivery`
+ FROM `'._DB_PREFIX_.'cart_product`
+ WHERE id_cart = '.(int)$this->id
+ );
+ Cache::store($cache_id, $result);
+ }
+ $result = Cache::retrieve($cache_id);
$result[] = array('id_address_delivery' => (int)$this->id_address_delivery);
foreach ($result as $row)
if ((int)$row['id_address_delivery'] != 0)
$collection[(int)$row['id_address_delivery']] = new Address((int)$row['id_address_delivery']);
-
return $collection;
}
@@ -3038,7 +3058,6 @@ class CartCore extends ObjectModel
*/
public function addTextFieldToProduct($id_product, $index, $type, $text_value)
{
- $text_value = str_replace(array("\n", "\r"), '', nl2br($text_value));
if (!_PS_MAGIC_QUOTES_GPC_){
$text_value = str_replace('\\', '\\\\', $text_value);
$text_value = str_replace('\'', '\\\'', $text_value);
@@ -3466,10 +3485,14 @@ class CartCore extends ObjectModel
)
WHERE `id_cart` = '.(int)$this->id.'
'.(Configuration::get('PS_ALLOW_MULTISHIPPING') ? ' AND `id_shop` = '.(int)$this->id_shop : '');
-
- $result = Db::getInstance()->execute($sql);
- if ($result)
- $emptyCache = true;
+
+ $cache_id = 'Cart::setNoMultishipping'.(int)$this->id.'-'.(int)$this->id_shop;
+ if (!Cache::isStored($cache_id))
+ {
+ if ($result = (bool)Db::getInstance()->execute($sql))
+ $emptyCache = true;
+ Cache::store($cache_id, $result);
+ }
if (Customization::isFeatureActive())
Db::getInstance()->execute('
diff --git a/classes/CartRule.php b/classes/CartRule.php
index 1890bda2d..0461d53e7 100644
--- a/classes/CartRule.php
+++ b/classes/CartRule.php
@@ -254,7 +254,8 @@ class CartRuleCore extends ObjectModel
}
else
$cart_rule['quantity_for_user'] = 0;
-
+ unset($cart_rule);
+
foreach ($result as $cart_rule)
if ($cart_rule['shop_restriction'])
{
diff --git a/classes/Category.php b/classes/Category.php
index d73bb2f4c..a4c5eb00e 100644
--- a/classes/Category.php
+++ b/classes/Category.php
@@ -706,9 +706,9 @@ class CategoryCore extends ObjectModel
* @param boolean $active return only active categories
* @return array categories
*/
- public static function getHomeCategories($id_lang, $active = true)
+ public static function getHomeCategories($id_lang, $active = true, $id_shop = false)
{
- return self::getChildren(Configuration::get('PS_HOME_CATEGORY'), $id_lang, $active);
+ return self::getChildren(Configuration::get('PS_HOME_CATEGORY'), $id_lang, $active, $id_shop);
}
public static function getRootCategory($id_lang = null, Shop $shop = null)
@@ -744,16 +744,22 @@ class CategoryCore extends ObjectModel
if (!Validate::isBool($active))
die(Tools::displayError());
- $query = 'SELECT c.`id_category`, cl.`name`, cl.`link_rewrite`, category_shop.`id_shop`
- FROM `'._DB_PREFIX_.'category` c
- LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category`'.Shop::addSqlRestrictionOnLang('cl').')
- '.Shop::addSqlAssociation('category', 'c').'
- WHERE `id_lang` = '.(int)$id_lang.'
- AND c.`id_parent` = '.(int)$id_parent.'
- '.($active ? 'AND `active` = 1' : '').'
- GROUP BY c.`id_category`
- ORDER BY category_shop.`position` ASC';
- return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query);
+ $cache_id = 'Category::getChildren_'.(int)$id_parent.'-'.(int)$id_lang.'-'.(bool)$active.'-'.(int)$id_shop;
+ if (!Cache::isStored($cache_id))
+ {
+ $query = 'SELECT c.`id_category`, cl.`name`, cl.`link_rewrite`, category_shop.`id_shop`
+ FROM `'._DB_PREFIX_.'category` c
+ LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category`'.Shop::addSqlRestrictionOnLang('cl').')
+ '.Shop::addSqlAssociation('category', 'c').'
+ WHERE `id_lang` = '.(int)$id_lang.'
+ AND c.`id_parent` = '.(int)$id_parent.'
+ '.($active ? 'AND `active` = 1' : '').'
+ GROUP BY c.`id_category`
+ ORDER BY category_shop.`position` ASC';
+ $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query);
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
@@ -1048,14 +1054,20 @@ class CategoryCore extends ObjectModel
public function getGroups()
{
$groups = array();
- $result = Db::getInstance()->executeS('
- SELECT cg.`id_group`
- FROM '._DB_PREFIX_.'category_group cg
- WHERE cg.`id_category` = '.(int)$this->id
- );
- foreach ($result as $group)
- $groups[] = $group['id_group'];
- return $groups;
+ $cache_id = 'Category::getGroups_'.(int)$this->id;
+ if (!Cache::isStored($cache_id))
+ {
+ $result = Db::getInstance()->executeS('
+ SELECT cg.`id_group`
+ FROM '._DB_PREFIX_.'category_group cg
+ WHERE cg.`id_category` = '.(int)$this->id
+ );
+ $groups = array();
+ foreach ($result as $group)
+ $groups[] = $group['id_group'];
+ Cache::store($cache_id, $groups);
+ }
+ return Cache::retrieve($cache_id);
}
public function addGroupsIfNoExist($id_group)
@@ -1076,24 +1088,23 @@ class CategoryCore extends ObjectModel
*/
public function checkAccess($id_customer)
{
- if (!$id_customer)
+ $cache_id = 'Category::checkAccess_'.(int)$this->id.'-'.$id_customer.(!$id_customer ? '-'.(int)Group::getCurrent()->id : '');
+ if (!Cache::isStored($cache_id))
{
- $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
+ if (!$id_customer)
+ $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
SELECT ctg.`id_group`
FROM '._DB_PREFIX_.'category_group ctg
- WHERE ctg.`id_category` = '.(int)$this->id.' AND ctg.`id_group` = '.(int)Group::getCurrent()->id.'
- ');
- } else {
- $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
+ WHERE ctg.`id_category` = '.(int)$this->id.' AND ctg.`id_group` = '.(int)Group::getCurrent()->id);
+ else
+ $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
SELECT ctg.`id_group`
FROM '._DB_PREFIX_.'category_group ctg
INNER JOIN '._DB_PREFIX_.'customer_group cg on (cg.`id_group` = ctg.`id_group` AND cg.`id_customer` = '.(int)$id_customer.')
- WHERE ctg.`id_category` = '.(int)$this->id
- );
+ WHERE ctg.`id_category` = '.(int)$this->id);
+ Cache::store($cache_id, $result);
}
- if ($result && isset($result['id_group']) && $result['id_group'])
- return true;
- return false;
+ return Cache::retrieve($cache_id);
}
/**
@@ -1239,12 +1250,16 @@ class CategoryCore extends ObjectModel
*/
public static function getInterval($id)
{
- $sql = 'SELECT nleft, nright, level_depth
- FROM '._DB_PREFIX_.'category
- WHERE id_category = '.(int)$id;
- if (!$result = Db::getInstance()->getRow($sql))
- return false;
- return $result;
+ $cache_id = 'Category::getInterval_'.(int)$id;
+ if (!Cache::isStored($cache_id))
+ {
+ $sql = 'SELECT nleft, nright, level_depth
+ FROM '._DB_PREFIX_.'category
+ WHERE id_category = '.(int)$id;
+ $result = Db::getInstance()->getRow($sql);
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
@@ -1426,11 +1441,17 @@ class CategoryCore extends ObjectModel
public static function getCategoriesWithoutParent()
{
- return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
- SELECT DISTINCT c.*
- FROM `'._DB_PREFIX_.'category` c
- LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category` AND cl.`id_lang` = '.(int)Context::getContext()->language->id.')
- WHERE `level_depth` = 1');
+ $cache_id = 'Category::getCategoriesWithoutParent_'.(int)Context::getContext()->language->id;
+ if (!Cache::isStored($cache_id))
+ {
+ $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
+ SELECT DISTINCT c.*
+ FROM `'._DB_PREFIX_.'category` c
+ LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category` AND cl.`id_lang` = '.(int)Context::getContext()->language->id.')
+ WHERE `level_depth` = 1');
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
public function isRootCategoryForAShop()
@@ -1449,12 +1470,17 @@ class CategoryCore extends ObjectModel
public static function getTopCategory($id_lang = null)
{
if (is_null($id_lang))
- $id_lang = Context::getContext()->language->id;
- $id_category = Db::getInstance()->getValue('
- SELECT `id_category`
- FROM `'._DB_PREFIX_.'category`
- WHERE `id_parent` = 0');
- return new Category($id_category, $id_lang);
+ $id_lang = (int)Context::getContext()->language->id;
+ $cache_id = 'Category::getTopCategory_'.(int)$id_lang;
+ if (!Cache::isStored($cache_id))
+ {
+ $id_category = (int)Db::getInstance()->getValue('
+ SELECT `id_category`
+ FROM `'._DB_PREFIX_.'category`
+ WHERE `id_parent` = 0');
+ Cache::store($cache_id, new Category($id_category, $id_lang));
+ }
+ return Cache::retrieve($cache_id);
}
public function addPosition($position, $id_shop = null)
diff --git a/classes/Currency.php b/classes/Currency.php
index 3280ec189..d92660542 100644
--- a/classes/Currency.php
+++ b/classes/Currency.php
@@ -296,10 +296,16 @@ class CurrencyCore extends ObjectModel
*/
public static function getIdByIsoCode($iso_code, $id_shop = 0)
{
- $query = Currency::getIdByQuery($id_shop);
- $query->where('iso_code = \''.pSQL($iso_code).'\'');
-
- return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query->build());
+ $cache_id = 'Currency::getIdByIsoCode_'.pSQL($iso_code).'-'.(int)$id_shop;
+ if (!Cache::isStored($cache_id))
+ {
+ $query = Currency::getIdByQuery($id_shop);
+ $query->where('iso_code = \''.pSQL($iso_code).'\'');
+
+ $result = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query->build());
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
diff --git a/classes/Customer.php b/classes/Customer.php
index 431d217e6..8191d3ee6 100644
--- a/classes/Customer.php
+++ b/classes/Customer.php
@@ -362,15 +362,18 @@ class CustomerCore extends ObjectModel
{
if (!Validate::isUnsignedId($id_customer))
return true;
- $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
- SELECT `id_customer`
- FROM `'._DB_PREFIX_.'customer`
- WHERE `id_customer` = \''.(int)$id_customer.'\'
- AND active = 1
- AND `deleted` = 0');
- if (isset($result['id_customer']))
- return false;
- return true;
+ $cache_id = 'Customer::isBanned_'.(int)$id_customer;
+ if (!Cache::isStored($cache_id))
+ {
+ $result = (bool)!Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
+ SELECT `id_customer`
+ FROM `'._DB_PREFIX_.'customer`
+ WHERE `id_customer` = \''.(int)$id_customer.'\'
+ AND active = 1
+ AND `deleted` = 0');
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
@@ -413,7 +416,7 @@ class CustomerCore extends ObjectModel
public static function customerHasAddress($id_customer, $id_address)
{
$key = (int)$id_customer.'-'.(int)$id_address;
- if (!array_key_exists($id_address, self::$_customerHasAddress))
+ if (!array_key_exists($key, self::$_customerHasAddress))
{
self::$_customerHasAddress[$key] = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
SELECT `id_address`
@@ -439,15 +442,22 @@ class CustomerCore extends ObjectModel
*/
public function getAddresses($id_lang)
{
- $sql = 'SELECT DISTINCT a.*, cl.`name` AS country, s.name AS state, s.iso_code AS state_iso
- FROM `'._DB_PREFIX_.'address` a
- LEFT JOIN `'._DB_PREFIX_.'country` c ON (a.`id_country` = c.`id_country`)
- LEFT JOIN `'._DB_PREFIX_.'country_lang` cl ON (c.`id_country` = cl.`id_country`)
- LEFT JOIN `'._DB_PREFIX_.'state` s ON (s.`id_state` = a.`id_state`)
- '.(Context::getContext()->shop->getGroup()->share_order ? '' : Shop::addSqlAssociation('country', 'c')).'
- WHERE `id_lang` = '.(int)$id_lang.' AND `id_customer` = '.(int)$this->id.' AND a.`deleted` = 0';
+ $share_order = (bool)Context::getContext()->shop->getGroup()->share_order;
+ $cache_id = 'Customer::getAddresses'.(int)$this->id.'-'.(int)$id_lang.'-'.$share_order;
+ if (!Cache::isStored($cache_id))
+ {
+ $sql = 'SELECT DISTINCT a.*, cl.`name` AS country, s.name AS state, s.iso_code AS state_iso
+ FROM `'._DB_PREFIX_.'address` a
+ LEFT JOIN `'._DB_PREFIX_.'country` c ON (a.`id_country` = c.`id_country`)
+ LEFT JOIN `'._DB_PREFIX_.'country_lang` cl ON (c.`id_country` = cl.`id_country`)
+ LEFT JOIN `'._DB_PREFIX_.'state` s ON (s.`id_state` = a.`id_state`)
+ '.($share_order ? '' : Shop::addSqlAssociation('country', 'c')).'
+ WHERE `id_lang` = '.(int)$id_lang.' AND `id_customer` = '.(int)$this->id.' AND a.`deleted` = 0';
- return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
+ $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
@@ -476,12 +486,17 @@ class CustomerCore extends ObjectModel
{
if (!Validate::isUnsignedId($id_customer) || !Validate::isMd5($passwd))
die (Tools::displayError());
-
- $sql = 'SELECT `id_customer`
- FROM `'._DB_PREFIX_.'customer`
- WHERE `id_customer` = '.$id_customer.'
+ $cache_id = 'Customer::checkPassword'.(int)$id_customer.'-'.$passwd;
+ if (!Cache::isStored($cache_id))
+ {
+ $sql = 'SELECT `id_customer`
+ FROM `'._DB_PREFIX_.'customer`
+ WHERE `id_customer` = '.$id_customer.'
AND `passwd` = \''.$passwd.'\'';
- return (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+ $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
@@ -574,12 +589,16 @@ class CustomerCore extends ObjectModel
public static function customerIdExistsStatic($id_customer)
{
- $row = Db::getInstance()->getRow('
- SELECT `id_customer`
- FROM '._DB_PREFIX_.'customer c
- WHERE c.`id_customer` = '.(int)$id_customer);
-
- return isset($row['id_customer']);
+ $cache_id = 'Customer::customerIdExistsStatic'.(int)$id_customer;
+ if (!Cache::isStored($cache_id))
+ {
+ $result = (int)Db::getInstance()->getValue('
+ SELECT `id_customer`
+ FROM '._DB_PREFIX_.'customer c
+ WHERE c.`id_customer` = '.(int)$id_customer);
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
diff --git a/classes/FileUploader.php b/classes/FileUploader.php
index 9c3758244..695217189 100755
--- a/classes/FileUploader.php
+++ b/classes/FileUploader.php
@@ -105,8 +105,10 @@ class QqUploadedFileForm
$legends = Tools::getValue('legend');
if (is_array($legends))
foreach ($legends as $key => $legend)
- if (!empty($legend))
+ if (!empty($legend) && Validate::isGenericName($legend))
$image->legend[(int)$key] = $legend;
+ else
+ return array('error' => sprintf(Tools::displayError('Error on image legend "%1s." is not a valid legend.'), Tools::safeOutput($legend)));
if (!Image::getCover($image->id_product))
$image->cover = 1;
else
@@ -192,8 +194,10 @@ class QqUploadedFileXhr
$legends = Tools::getValue('legend');
if (is_array($legends))
foreach ($legends as $key => $legend)
- if (!empty($legend))
+ if (!empty($legend) && Validate::isGenericName($legend))
$image->legend[(int)$key] = $legend;
+ else
+ return array('error' => sprintf(Tools::displayError('Error on image legend "%1s." is not a valid legend.'), Tools::safeOutput($legend)));
if (!Image::getCover($image->id_product))
$image->cover = 1;
else
diff --git a/classes/Group.php b/classes/Group.php
index 056fb73cd..7a64e1359 100644
--- a/classes/Group.php
+++ b/classes/Group.php
@@ -301,12 +301,21 @@ class GroupCore extends ObjectModel
public static function getCurrent()
{
static $groups = array();
+
$customer = Context::getContext()->customer;
if (Validate::isLoadedObject($customer))
+ {
$id_group = (int)$customer->id_default_group;
+ $group = new Group((int)$id_group);
+ if (!$group->isAssociatedToShop(Context::getContext()->shop->id))
+ $group = new Group((int)Configuration::get('PS_CUSTOMER_GROUP'));
+ }
else
$id_group = (int)Configuration::get('PS_UNIDENTIFIED_GROUP');
-
+
+ if (!isset($groups[$id_group]) && isset($group))
+ $groups[$id_group] = $group;
+
if (!isset($groups[$id_group]))
$groups[$id_group] = new Group($id_group);
diff --git a/classes/Hook.php b/classes/Hook.php
index c233d99e1..339d5ff38 100644
--- a/classes/Hook.php
+++ b/classes/Hook.php
@@ -326,7 +326,10 @@ class HookCore extends ObjectModel
if ($frontend)
{
$sql->leftJoin('module_group', 'mg', 'mg.`id_module` = m.`id_module`');
- $sql->where('mg.`id_group` IN ('.implode(', ', $groups).')');
+ if (Validate::isLoadedObject($context->shop))
+ $sql->where('mg.id_shop = '.((int)$context->shop->id).' AND mg.`id_group` IN ('.implode(', ', $groups).')');
+ else
+ $sql->where('mg.`id_group` IN ('.implode(', ', $groups).')');
$sql->groupBy('hm.id_hook, hm.id_module');
}
diff --git a/classes/Language.php b/classes/Language.php
index be53bf8f5..45fd98408 100644
--- a/classes/Language.php
+++ b/classes/Language.php
@@ -619,6 +619,35 @@ class LanguageCore extends ObjectModel
return Db::getInstance()->getValue('SELECT `language_code` FROM `'._DB_PREFIX_.'lang` WHERE `iso_code` = \''.pSQL(strtolower($iso_code)).'\'');
}
+ public static function getLanguageByIETFCode($code)
+ {
+ if (!Validate::isLanguageCode($code))
+ die(sprintf(Tools::displayError('Fatal error: IETF code %s is not correct'), $code));
+
+ // $code is in the form of 'xx-YY' where xx is the language code
+ // and 'YY' a country code identifying a variant of the language.
+ $lang_country = explode('-', $code);
+ // Get the language component of the code
+ $lang = $lang_country[0];
+
+ // Find the id_lang of the language.
+ // We look for anything with the correct language code
+ // and sort on equality with the exact IETF code wanted.
+ // That way using only one query we get either the exact wanted language
+ // or a close match.
+ $id_lang = Db::getInstance()->getValue(
+ 'SELECT `id_lang` FROM '
+ .'`'._DB_PREFIX_.'lang` WHERE LEFT(`language_code`,2) = \''.pSQL($lang).'\' '
+ .'ORDER BY language_code = \''.pSQL($code).'\' DESC'
+ );
+
+ // Instantiate the Language object if we found it.
+ if ($id_lang)
+ return new Language($id_lang);
+ else
+ return false;
+ }
+
/**
* Return array (id_lang, iso_code)
*
diff --git a/classes/Link.php b/classes/Link.php
index cb207e6db..b2e4f0776 100644
--- a/classes/Link.php
+++ b/classes/Link.php
@@ -423,6 +423,15 @@ class LinkCore
*/
public function getPageLink($controller, $ssl = null, $id_lang = null, $request = null, $request_url_encode = false, $id_shop = null)
{
+
+ //If $controller contains '&' char, it means that $controller contains request data and must be parsed first
+ $p = strpos($controller, '&');
+ if ($p !== false) {
+ $request = substr($controller, $p + 1);
+ $request_url_encode = false;
+ $controller = substr($controller, 0, $p);
+ }
+
$controller = Tools::strReplaceFirst('.php', '', $controller);
if (!$id_lang)
$id_lang = (int)Context::getContext()->language->id;
@@ -501,6 +510,7 @@ class LinkCore
public function goPage($url, $p)
{
+ $url = rtrim(str_replace('?&', '?', $url), '?');
return $url.($p == 1 ? '' : (!strstr($url, '?') ? '?' : '&').'p='.(int)$p);
}
diff --git a/classes/LocalizationPack.php b/classes/LocalizationPack.php
index 87b90967c..9d7449835 100644
--- a/classes/LocalizationPack.php
+++ b/classes/LocalizationPack.php
@@ -64,6 +64,7 @@ class LocalizationPackCore
if ($install_mode && $res && isset($this->iso_currency))
{
+ Cache::clean('Currency::getIdByIsoCode_*');
$res &= Configuration::updateValue('PS_CURRENCY_DEFAULT', (int)Currency::getIdByIsoCode($this->iso_currency));
Currency::refreshCurrencies();
}
diff --git a/classes/Media.php b/classes/Media.php
index bc8257c76..fc042320d 100755
--- a/classes/Media.php
+++ b/classes/Media.php
@@ -37,9 +37,10 @@ class MediaCore
'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.autocomplete' => array('fileName' => 'jquery.ui.autocomplete.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.position', 'ui.menu'), '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','ui.button'), 'theme' => true),
+ 'ui.menu' => array('fileName' => 'jquery.ui.menu.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),
@@ -109,7 +110,7 @@ class MediaCore
// If the string is too big preg_replace return an error
// In this case, we don't compress the content
- if (preg_last_error() == PREG_BACKTRACK_LIMIT_ERROR)
+ if (function_exists('preg_last_error') && preg_last_error() == PREG_BACKTRACK_LIMIT_ERROR)
{
if (_PS_MODE_DEV_)
error_log('ERROR: PREG_BACKTRACK_LIMIT_ERROR in function packJSinHTML');
diff --git a/classes/Meta.php b/classes/Meta.php
index 4e911fe72..1612812b1 100644
--- a/classes/Meta.php
+++ b/classes/Meta.php
@@ -277,24 +277,31 @@ class MetaCore extends ObjectModel
FROM `'._DB_PREFIX_.'category_lang` cl
WHERE cl.`id_lang` = '.(int)$id_lang.'
AND cl.`id_category` = '.(int)$id_category.Shop::addSqlRestrictionOnLang('cl');
- if ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql))
+
+ $cache_id = 'Meta::getCategoryMetas'.(int)$id_category.'-'.(int)$id_lang;
+ if (!Cache::isStored($cache_id))
{
- if (empty($row['meta_description']))
- $row['meta_description'] = strip_tags($row['description']);
-
- // Paginate title
- if (!empty($row['meta_title']))
- $row['meta_title'] = $title.$row['meta_title'].(!empty($page_number) ? ' ('.$page_number.')' : '').' - '.Configuration::get('PS_SHOP_NAME');
+ if ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql))
+ {
+ if (empty($row['meta_description']))
+ $row['meta_description'] = strip_tags($row['description']);
+
+ // Paginate title
+ if (!empty($row['meta_title']))
+ $row['meta_title'] = $title.$row['meta_title'].(!empty($page_number) ? ' ('.$page_number.')' : '').' - '.Configuration::get('PS_SHOP_NAME');
+ else
+ $row['meta_title'] = $row['name'].(!empty($page_number) ? ' ('.$page_number.')' : '').' - '.Configuration::get('PS_SHOP_NAME');
+
+ if (!empty($title))
+ $row['meta_title'] = $title.(!empty($page_number) ? ' ('.$page_number.')' : '').' - '.Configuration::get('PS_SHOP_NAME');
+
+ $result = Meta::completeMetaTags($row, $row['name']);
+ }
else
- $row['meta_title'] = $row['name'].(!empty($page_number) ? ' ('.$page_number.')' : '').' - '.Configuration::get('PS_SHOP_NAME');
-
- if (!empty($title))
- $row['meta_title'] = $title.(!empty($page_number) ? ' ('.$page_number.')' : '').' - '.Configuration::get('PS_SHOP_NAME');
-
- return Meta::completeMetaTags($row, $row['name']);
+ $result = Meta::getHomeMetas($id_lang, $page_name);
+ Cache::store($cache_id, $result);
}
-
- return Meta::getHomeMetas($id_lang, $page_name);
+ return Cache::retrieve($cache_id);
}
/**
diff --git a/classes/ObjectModel.php b/classes/ObjectModel.php
index 0c70cbf3c..783cd6abf 100644
--- a/classes/ObjectModel.php
+++ b/classes/ObjectModel.php
@@ -191,7 +191,7 @@ abstract class ObjectModelCore
if ($id)
{
// Load object from database if object id is present
- $cache_id = 'objectmodel_'.$this->def['classname'].'_'.(int)$id.'_'.(int)$id_shop.'_'.(int)$id_lang;
+ $cache_id = 'objectmodel_'.$this->def['classname'].'_'.(int)$id.'_'.(int)$this->id_shop.'_'.(int)$id_lang;
if (!Cache::isStored($cache_id))
{
$sql = new DbQuery();
@@ -1234,11 +1234,16 @@ abstract class ObjectModelCore
if ($id_shop === null)
$id_shop = Context::getContext()->shop->id;
- $sql = 'SELECT id_shop
- FROM `'.pSQL(_DB_PREFIX_.$this->def['table']).'_shop`
- WHERE `'.$this->def['primary'].'` = '.(int)$this->id.'
- AND id_shop = '.(int)$id_shop;
- return (bool)Db::getInstance()->getValue($sql);
+ $cache_id = 'objectmodel_shop_'.$this->def['classname'].'_'.(int)$this->id.'-'.(int)$id_shop;
+ if (!Cache::isStored($cache_id))
+ {
+ $sql = 'SELECT id_shop
+ FROM `'.pSQL(_DB_PREFIX_.$this->def['table']).'_shop`
+ WHERE `'.$this->def['primary'].'` = '.(int)$this->id.'
+ AND id_shop = '.(int)$id_shop;
+ Cache::store($cache_id, (bool)Db::getInstance()->getValue($sql));
+ }
+ return Cache::retrieve($cache_id);
}
/**
diff --git a/classes/PaymentModule.php b/classes/PaymentModule.php
index 68bec3226..f8585a69d 100644
--- a/classes/PaymentModule.php
+++ b/classes/PaymentModule.php
@@ -378,7 +378,8 @@ abstract class PaymentModuleCore extends Module
$customization_text .= sprintf(Tools::displayError('%d image(s)'), count($customization['datas'][Product::CUSTOMIZE_FILE])).' ';
$customization_text .= '--- ';
}
- $customization_text = rtrim($customization_text, '--- ');
+
+ $customization_text = Tools::rtrimString($customization_text, '--- ');
$customization_quantity = (int)$product['customization_quantity'];
$products_list .=
diff --git a/classes/Product.php b/classes/Product.php
index cd8e85b53..98fd2099e 100644
--- a/classes/Product.php
+++ b/classes/Product.php
@@ -229,7 +229,13 @@ class ProductCore extends ObjectModel
protected static $_prices = array();
protected static $_pricesLevel2 = array();
protected static $_incat = array();
+
+ /**
+ * @since 1.5.6.1
+ * @var array $_cart_quantity is deprecated since 1.5.6.1
+ */
protected static $_cart_quantity = array();
+
protected static $_tax_rules_group = array();
protected static $_cacheFeatures = array();
protected static $_frontFeaturesCache = array();
@@ -2443,13 +2449,18 @@ class ProductCore extends ObjectModel
{
if (!$context)
$context = Context::getContext();
-
- $sql = 'SELECT image_shop.`id_image`
- FROM `'._DB_PREFIX_.'image` i
- '.Shop::addSqlAssociation('image', 'i').'
- WHERE i.`id_product` = '.(int)$id_product.'
- AND image_shop.`cover` = 1';
- return Db::getInstance()->getRow($sql);
+ $cache_id = 'Product::getOrderStates_'.(int)$id_product.'-'.(int)$context->shop->id;
+ if (!Cache::isStored($cache_id))
+ {
+ $sql = 'SELECT image_shop.`id_image`
+ FROM `'._DB_PREFIX_.'image` i
+ '.Shop::addSqlAssociation('image', 'i').'
+ WHERE i.`id_product` = '.(int)$id_product.'
+ AND image_shop.`cover` = 1';
+ $result = Db::getInstance()->getRow($sql);
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
@@ -2511,15 +2522,17 @@ class ProductCore extends ObjectModel
$cart_quantity = 0;
if ((int)$id_cart)
{
- $condition = '';
- $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`)
+ $cache_id = 'Product::getPriceStatic_'.(int)$id_product.'-'.(int)$id_cart;
+ if (!Cache::isStored($cache_id))
+ {
+ $sql = 'SELECT SUM(`quantity`)
FROM `'._DB_PREFIX_.'cart_product`
WHERE `id_product` = '.(int)$id_product.'
- AND `id_cart` = '.(int)$id_cart);
- $cart_quantity = self::$_cart_quantity[$cache_name];
+ AND `id_cart` = '.(int)$id_cart;
+ $cart_quantity = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+ Cache::store($cache_id, $cart_quantity);
+ }
+ $cart_quantity = Cache::retrieve($cache_id);
}
$id_currency = (int)Validate::isLoadedObject($context->currency) ? $context->currency->id : Configuration::get('PS_CURRENCY_DEFAULT');
@@ -4345,22 +4358,27 @@ class ProductCore extends ObjectModel
if (!Group::isFeatureActive())
return true;
- if (!$id_customer)
- return (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
- SELECT ctg.`id_group`
- FROM `'._DB_PREFIX_.'category_product` cp
- INNER JOIN `'._DB_PREFIX_.'category_group` ctg ON (ctg.`id_category` = cp.`id_category`)
- WHERE cp.`id_product` = '.(int)$this->id.' AND ctg.`id_group` ='.(int)Group::getCurrent()->id);
- else
- return (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
- SELECT cg.`id_group`
- FROM `'._DB_PREFIX_.'category_product` cp
- INNER JOIN `'._DB_PREFIX_.'category_group` ctg ON (ctg.`id_category` = cp.`id_category`)
- INNER JOIN `'._DB_PREFIX_.'customer_group` cg ON (cg.`id_group` = ctg.`id_group`)
- WHERE cp.`id_product` = '.(int)$this->id.' AND cg.`id_customer` = '.(int)$id_customer);
+ $cache_id = 'Product::checkAccess_'.(int)$this->id.'-'.(int)$id_customer.(!$id_customer ? '-'.(int)Group::getCurrent()->id : '');
+ if (!Cache::isStored($cache_id))
+ {
+ if (!$id_customer)
+ $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
+ SELECT ctg.`id_group`
+ FROM `'._DB_PREFIX_.'category_product` cp
+ INNER JOIN `'._DB_PREFIX_.'category_group` ctg ON (ctg.`id_category` = cp.`id_category`)
+ WHERE cp.`id_product` = '.(int)$this->id.' AND ctg.`id_group` = '.(int)Group::getCurrent()->id);
+ else
+ $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
+ SELECT cg.`id_group`
+ FROM `'._DB_PREFIX_.'category_product` cp
+ INNER JOIN `'._DB_PREFIX_.'category_group` ctg ON (ctg.`id_category` = cp.`id_category`)
+ INNER JOIN `'._DB_PREFIX_.'customer_group` cg ON (cg.`id_group` = ctg.`id_group`)
+ WHERE cp.`id_product` = '.(int)$this->id.' AND cg.`id_customer` = '.(int)$id_customer);
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
-
/**
* Add a stock movement for current product
*
@@ -4917,8 +4935,12 @@ class ProductCore extends ObjectModel
*/
public static function getAttributesParams($id_product, $id_product_attribute)
{
+ $id_lang = (int)Context::getContext()->language->id;
+ $id_shop = (int)Context::getContext()->shop->id;
+ $cache_id = 'Product::getAttributesParams_'.(int)$id_product.'-'.(int)$id_product_attribute.'-'.(int)$id_lang.'-'.(int)$id_shop;
+
// if blocklayered module is installed we check if user has set custom attribute name
- if (Module::isInstalled('blocklayered'))
+ if (Module::isInstalled('blocklayered') && Module::isEnabled('blocklayered'))
{
$nb_custom_values = Db::getInstance()->executeS('
SELECT DISTINCT la.`id_attribute`, la.`url_name` as `name`
@@ -4929,7 +4951,7 @@ class ProductCore extends ObjectModel
ON (pac.`id_product_attribute` = pa.`id_product_attribute`)
'.Shop::addSqlAssociation('product_attribute', 'pa').'
LEFT JOIN `'._DB_PREFIX_.'layered_indexable_attribute_lang_value` la
- ON (la.`id_attribute` = a.`id_attribute` AND la.`id_lang` = '.(int)Context::getContext()->language->id.')
+ ON (la.`id_attribute` = a.`id_attribute` AND la.`id_lang` = '.(int)$id_lang.')
WHERE la.`url_name` IS NOT NULL AND la.`url_name` != \'\'
AND pa.`id_product` = '.(int)$id_product.'
AND pac.`id_product_attribute` = '.(int)$id_product_attribute);
@@ -4947,7 +4969,7 @@ class ProductCore extends ObjectModel
LEFT JOIN `'._DB_PREFIX_.'attribute` a
ON (a.`id_attribute_group` = g.`id_attribute_group`)
WHERE a.`id_attribute` = '.(int)$attribute['id_attribute'].'
- AND g.`id_lang` = '.(int)Context::getContext()->language->id.'
+ AND g.`id_lang` = '.(int)$id_lang.'
AND g.`url_name` IS NOT NULL AND g.`url_name` != \'\'');
if (empty($group))
{
@@ -4957,7 +4979,7 @@ class ProductCore extends ObjectModel
LEFT JOIN `'._DB_PREFIX_.'attribute` a
ON (a.`id_attribute_group` = g.`id_attribute_group`)
WHERE a.`id_attribute` = '.(int)$attribute['id_attribute'].'
- AND g.`id_lang` = '.(int)Context::getContext()->language->id.'
+ AND g.`id_lang` = '.(int)$id_lang.'
AND g.`name` IS NOT NULL');
}
$result[] = array_merge($attribute, $group[0]);
@@ -4966,9 +4988,9 @@ class ProductCore extends ObjectModel
SELECT DISTINCT a.`id_attribute_group`, al.`name`, agl.`name` as `group`
FROM `'._DB_PREFIX_.'attribute` a
LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al
- ON (a.`id_attribute` = al.`id_attribute` AND al.`id_lang` = '.(int)Context::getContext()->language->id.')
+ ON (a.`id_attribute` = al.`id_attribute` AND al.`id_lang` = '.(int)$id_lang.')
LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl
- ON (a.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = '.(int)Context::getContext()->language->id.')
+ ON (a.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = '.(int)$id_lang.')
LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac
ON (a.`id_attribute` = pac.`id_attribute`)
LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa
@@ -4977,45 +4999,30 @@ class ProductCore extends ObjectModel
WHERE pa.`id_product` = '.(int)$id_product.'
AND pac.id_product_attribute = '.(int)$id_product_attribute.'
AND a.`id_attribute` NOT IN('.implode(', ', $tab_id_attribute).')');
- $result = array_merge($values_not_custom, $result);
- }
- else
- {
- $result = Db::getInstance()->executeS('
- SELECT al.`name`, agl.`name` as `group`
- FROM `'._DB_PREFIX_.'attribute` a
- LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al
- ON (al.`id_attribute` = a.`id_attribute` AND al.`id_lang` = '.(int)Context::getContext()->language->id.')
- LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac
- ON (pac.`id_attribute` = a.`id_attribute`)
- LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa
- ON (pa.`id_product_attribute` = pac.`id_product_attribute`)
- '.Shop::addSqlAssociation('product_attribute', 'pa').'
- LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl
- ON (a.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = '.(int)Context::getContext()->language->id.')
- WHERE pa.`id_product` = '.(int)$id_product.'
- AND pac.`id_product_attribute` = '.(int)$id_product_attribute.'
- AND agl.`id_lang` = '.(int)Context::getContext()->language->id);
+ return array_merge($values_not_custom, $result);
}
}
- else
+
+ if (!Cache::isStored($cache_id))
{
$result = Db::getInstance()->executeS('
SELECT al.`name`, agl.`name` as `group`
FROM `'._DB_PREFIX_.'attribute` a
LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al
- ON (al.`id_attribute` = a.`id_attribute` AND al.`id_lang` = '.(int)Context::getContext()->language->id.')
+ ON (al.`id_attribute` = a.`id_attribute` AND al.`id_lang` = '.(int)$id_lang.')
LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac
ON (pac.`id_attribute` = a.`id_attribute`)
LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa
ON (pa.`id_product_attribute` = pac.`id_product_attribute`)
'.Shop::addSqlAssociation('product_attribute', 'pa').'
LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl
- ON (a.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = '.(int)Context::getContext()->language->id.')
+ ON (a.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = '.(int)$id_lang.')
WHERE pa.`id_product` = '.(int)$id_product.'
AND pac.`id_product_attribute` = '.(int)$id_product_attribute.'
- AND agl.`id_lang` = '.(int)Context::getContext()->language->id);
+ AND agl.`id_lang` = '.(int)$id_lang);
+ Cache::store($cache_id, $result);
}
+ $result = Cache::retrieve($cache_id);
return $result;
}
@@ -5315,7 +5322,10 @@ class ProductCore extends ObjectModel
WHERE id_product='.(int)$this->id.Shop::addSqlRestriction()
);
else
+ {
+ $this->setFieldsToUpdate(array('advanced_stock_management' => true));
$this->save();
+ }
}
/**
diff --git a/classes/ProductSale.php b/classes/ProductSale.php
index 44627f159..d24400f5d 100644
--- a/classes/ProductSale.php
+++ b/classes/ProductSale.php
@@ -91,41 +91,40 @@ class ProductSaleCore
foreach ($products as $product)
$ids[$product['id_product']] = 1;
$ids = array_keys($ids);
+ $ids = array_filter($ids);
sort($ids);
$ids = count($ids) > 0 ? implode(',', $ids) : 'NULL';
- // Main query
- if ($order_by == 'date_add')
- $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`,
- m.`name` AS manufacturer_name, p.`id_manufacturer` as id_manufacturer,
- MAX(image_shop.`id_image`) id_image, il.`legend`,
- ps.`quantity` AS sales, t.`rate`, pl.`meta_keywords`, pl.`meta_title`, pl.`meta_description`,
- DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.$interval.' DAY)) > 0 AS new
- FROM `'._DB_PREFIX_.'product_sale` ps
- LEFT JOIN `'._DB_PREFIX_.'product` p ON ps.`id_product` = p.`id_product`
- '.Shop::addSqlAssociation('product', 'p', false).'
- 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 ON (i.`id_product` = p.`id_product`)'.
- Shop::addSqlAssociation('image', 'i', false, 'image_shop.cover=1').'
- LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.')
- LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (m.`id_manufacturer` = p.`id_manufacturer`)
- LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (product_shop.`id_tax_rules_group` = tr.`id_tax_rules_group`)
- AND tr.`id_country` = '.(int)Context::getContext()->country->id.'
- AND tr.`id_state` = 0
- LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)
- '.Product::sqlStock('p').'
- WHERE product_shop.`active` = 1
- AND p.`visibility` != \'none\'
- AND p.`id_product` IN ('.$ids.')
- GROUP BY product_shop.id_product
- ORDER BY '.(!empty($order_table) ? '`'.pSQL($order_table).'`.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way).'
- LIMIT '.(int)($page_number * $nb_products).', '.(int)$nb_products;
+ //Main query
+ $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`,
+ m.`name` AS manufacturer_name, p.`id_manufacturer` as id_manufacturer,
+ MAX(image_shop.`id_image`) id_image, il.`legend`,
+ ps.`quantity` AS sales, t.`rate`, pl.`meta_keywords`, pl.`meta_title`, pl.`meta_description`,
+ DATEDIFF(p.`date_add`, DATE_SUB(NOW(),
+ INTERVAL '.$interval.' DAY)) > 0 AS new
+ FROM `'._DB_PREFIX_.'product_sale` ps
+ LEFT JOIN `'._DB_PREFIX_.'product` p ON ps.`id_product` = p.`id_product`
+ '.Shop::addSqlAssociation('product', 'p', false).'
+ 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 ON (i.`id_product` = p.`id_product`)'.
+ Shop::addSqlAssociation('image', 'i', false, 'image_shop.cover=1').'
+ LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.')
+ LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (m.`id_manufacturer` = p.`id_manufacturer`)
+ LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (product_shop.`id_tax_rules_group` = tr.`id_tax_rules_group`)
+ AND tr.`id_country` = '.(int)Context::getContext()->country->id.'
+ AND tr.`id_state` = 0
+ LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)
+ '.Product::sqlStock('p').'
+ WHERE product_shop.`active` = 1
+ AND p.`visibility` != \'none\'
+ AND p.`id_product` IN ('.$ids.')
+ GROUP BY product_shop.id_product
+ 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);
@@ -170,6 +169,7 @@ class ProductSaleCore
$ids[$product['id_product']] = 1;
$ids = array_keys($ids);
sort($ids);
+ $ids = array_filter($ids);
$ids = count($ids) > 0 ? implode(',', $ids) : 'NULL';
//Main query
diff --git a/classes/State.php b/classes/State.php
index e818c07a5..205868a81 100644
--- a/classes/State.php
+++ b/classes/State.php
@@ -80,13 +80,19 @@ class StateCore extends ObjectModel
*/
public static function getNameById($id_state)
{
- $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
- SELECT `name`
- FROM `'._DB_PREFIX_.'state`
- WHERE `id_state` = '.(int)$id_state
- );
-
- return $result['name'];
+ if (!$id_state)
+ return false;
+ $cache_id = 'State::getNameById_'.(int)$id_state;
+ if (!Cache::isStored($cache_id))
+ {
+ $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
+ SELECT `name`
+ FROM `'._DB_PREFIX_.'state`
+ WHERE `id_state` = '.(int)$id_state
+ );
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
@@ -97,13 +103,19 @@ class StateCore extends ObjectModel
*/
public static function getIdByName($state)
{
- $result = Db::getInstance()->getValue('
- SELECT `id_state`
- FROM `'._DB_PREFIX_.'state`
- WHERE `name` LIKE \''.pSQL($state).'\'
- ');
-
- return (int)$result;
+ if (empty($state))
+ return false;
+ $cache_id = 'State::getNameById_'.pSQL($state);
+ if (!Cache::isStored($cache_id))
+ {
+ $result = (int)Db::getInstance()->getValue('
+ SELECT `id_state`
+ FROM `'._DB_PREFIX_.'state`
+ WHERE `name` LIKE \''.pSQL($state).'\'
+ ');
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
diff --git a/classes/Tab.php b/classes/Tab.php
index add391536..a0bc246aa 100644
--- a/classes/Tab.php
+++ b/classes/Tab.php
@@ -190,14 +190,20 @@ class TabCore extends ObjectModel
*/
public static function getTab($id_lang, $id_tab)
{
- /* Tabs selection */
- return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
- SELECT *
- FROM `'._DB_PREFIX_.'tab` t
- LEFT JOIN `'._DB_PREFIX_.'tab_lang` tl
- ON (t.`id_tab` = tl.`id_tab` AND tl.`id_lang` = '.(int)$id_lang.')
- WHERE t.`id_tab` = '.(int)$id_tab
- );
+ $cache_id = 'Tab::getTab_'.(int)$id_lang.'-'.(int)$id_tab;
+ if (!Cache::isStored($cache_id))
+ {
+ /* Tabs selection */
+ $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
+ SELECT *
+ FROM `'._DB_PREFIX_.'tab` t
+ LEFT JOIN `'._DB_PREFIX_.'tab_lang` tl
+ ON (t.`id_tab` = tl.`id_tab` AND tl.`id_lang` = '.(int)$id_lang.')
+ WHERE t.`id_tab` = '.(int)$id_tab
+ );
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
diff --git a/classes/Tag.php b/classes/Tag.php
index ae5146959..522f547d6 100644
--- a/classes/Tag.php
+++ b/classes/Tag.php
@@ -105,7 +105,7 @@ class TagCore extends ObjectModel
{
if (!Validate::isGenericName($tag))
return false;
- $tag = trim(substr($tag, 0, self::$definition['fields']['name']['size']));
+ $tag = trim(Tools::substr($tag, 0, self::$definition['fields']['name']['size']));
$tag_obj = new Tag(null, $tag, (int)$id_lang);
/* Tag does not exist in database */
diff --git a/classes/Tools.php b/classes/Tools.php
index 44bd53e46..547a3fb66 100644
--- a/classes/Tools.php
+++ b/classes/Tools.php
@@ -346,17 +346,12 @@ class ToolsCore
/* 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)
+ $array = explode(',', Tools::strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']));
+ $string = $array[0];
+
+ if (Validate::isLanguageCode($string))
{
- $tab = explode('-', $array[0]);
- $string = $tab[0];
- }
- else
- $string = $array[0];
- if (Validate::isLanguageIsoCode($string))
- {
- $lang = new Language(Language::getIdByIso($string));
+ $lang = Language::getLanguageByIETFCode($string);
if (Validate::isLoadedObject($lang) && $lang->active && $lang->isAssociatedToShop())
{
Context::getContext()->language = $lang;
@@ -364,7 +359,7 @@ class ToolsCore
}
}
}
-
+
if (isset($cookie->detect_language))
unset($cookie->detect_language);
@@ -374,7 +369,7 @@ class ToolsCore
$iso = Language::getIsoById((int)$cookie->id_lang);
@include_once(_PS_THEME_DIR_.'lang/'.$iso.'.php');
-
+
return $iso;
}
@@ -672,10 +667,8 @@ class ToolsCore
public static function htmlentitiesUTF8($string, $type = ENT_QUOTES)
{
if (is_array($string))
- {
- $string = array_map(array('Tools', 'htmlentitiesUTF8'), $string);
- return (string)array_shift($string);
- }
+ return array_map(array('Tools', 'htmlentitiesUTF8'), $string);
+
return htmlentities((string)$string, $type, 'utf-8');
}
@@ -691,9 +684,10 @@ class ToolsCore
public static function safePostVars()
{
- if (!is_array($_POST))
- return array();
- $_POST = array_map(array('Tools', 'htmlentitiesUTF8'), $_POST);
+ if (!isset($_POST) || !is_array($_POST))
+ $_POST = array();
+ else
+ $_POST = array_map(array('Tools', 'htmlentitiesUTF8'), $_POST);
}
/**
@@ -1222,6 +1216,129 @@ class ToolsCore
return (utf8_encode(substr($str, 0, $max_length - Tools::strlen($suffix)).$suffix));
}
+ /*Copied from CakePHP String utility file*/
+ public static function truncateString($text, $length = 120, $options = array())
+ {
+ $default = array(
+ 'ellipsis' => '...', 'exact' => true, 'html' => true
+ );
+
+ $options = array_merge($default, $options);
+ extract($options);
+
+ if ($html)
+ {
+ if (Tools::strlen(preg_replace('/<.*?>/', '', $text)) <= $length)
+ return $text;
+
+ $totalLength = Tools::strlen(strip_tags($ellipsis));
+ $openTags = array();
+ $truncate = '';
+ preg_match_all('/(<\/?([\w+]+)[^>]*>)?([^<>]*)/', $text, $tags, PREG_SET_ORDER);
+
+ foreach ($tags as $tag)
+ {
+ if (!preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag[2]))
+ {
+ if (preg_match('/<[\w]+[^>]*>/s', $tag[0]))
+ array_unshift($openTags, $tag[2]);
+ elseif (preg_match('/<\/([\w]+)[^>]*>/s', $tag[0], $closeTag))
+ {
+ $pos = array_search($closeTag[1], $openTags);
+ if ($pos !== false)
+ array_splice($openTags, $pos, 1);
+ }
+ }
+ $truncate .= $tag[1];
+ $contentLength = Tools::strlen(preg_replace('/&[0-9a-z]{2,8};|[0-9]{1,7};|[0-9a-f]{1,6};/i', ' ', $tag[3]));
+
+ if ($contentLength + $totalLength > $length)
+ {
+ $left = $length - $totalLength;
+ $entitiesLength = 0;
+
+ if (preg_match_all('/&[0-9a-z]{2,8};|[0-9]{1,7};|[0-9a-f]{1,6};/i', $tag[3], $entities, PREG_OFFSET_CAPTURE))
+ {
+ foreach ($entities[0] as $entity)
+ {
+ if ($entity[1] + 1 - $entitiesLength <= $left)
+ {
+ $left--;
+ $entitiesLength += Tools::strlen($entity[0]);
+ }
+ else
+ break;
+ }
+ }
+
+ $truncate .= Tools::substr($tag[3], 0, $left + $entitiesLength);
+ break;
+ }
+ else
+ {
+ $truncate .= $tag[3];
+ $totalLength += $contentLength;
+ }
+
+ if ($totalLength >= $length)
+ break;
+ }
+ }
+ else
+ {
+ if (Tools::strlen($text) <= $length)
+ return $text;
+
+ $truncate = Tools::substr($text, 0, $length - Tools::strlen($ellipsis));
+ }
+
+ if (!$exact)
+ {
+ $spacepos = mb_strrpos($truncate, ' ');
+ if ($html)
+ {
+ $truncateCheck = Tools::substr($truncate, 0, $spacepos);
+ $lastOpenTag = Tools::strrpos($truncateCheck, '<');
+ $lastCloseTag = Tools::strrpos($truncateCheck, '>');
+
+ if ($lastOpenTag > $lastCloseTag)
+ {
+ preg_match_all('/<[\w]+[^>]*>/s', $truncate, $lastTagMatches);
+ $lastTag = array_pop($lastTagMatches[0]);
+ $spacepos = Tools::strrpos($truncate, $lastTag) + Tools::strlen($lastTag);
+ }
+
+ $bits = Tools::substr($truncate, $spacepos);
+ preg_match_all('/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER);
+
+ if (!empty($droppedTags))
+ {
+ if (!empty($openTags))
+ {
+ foreach ($droppedTags as $closingTag)
+ if (!in_array($closingTag[1], $openTags))
+ array_unshift($openTags, $closingTag[1]);
+ }
+ else
+ {
+ foreach ($droppedTags as $closingTag)
+ $openTags[] = $closingTag[1];
+ }
+ }
+ }
+
+ $truncate = Tools::substr($truncate, 0, $spacepos);
+ }
+
+ $truncate .= $ellipsis;
+
+ if ($html)
+ foreach ($openTags as $tag)
+ $truncate .= '' . $tag . '>';
+
+ return $truncate;
+ }
+
/**
* Generate date form
*
@@ -1320,6 +1437,13 @@ class ToolsCore
return substr($str, $start, ($length === false ? Tools::strlen($str) : (int)$length));
}
+ public static function strrpos($str, $find, $offset = 0, $encoding = 'utf-8')
+ {
+ if (function_exists('mb_strrpos'))
+ return mb_strrpos($str, $find, $offset, $encoding);
+ return strrpos($str, $find, $offset);
+ }
+
public static function ucfirst($str)
{
return Tools::strtoupper(Tools::substr($str, 0, 1)).Tools::substr($str, 1);
@@ -2645,6 +2769,20 @@ exit;
usleep(300);
}
}
+
+ /**
+ * Delete a substring from another one starting from the right
+ * @param string $str
+ * @param string $str_search
+ * @return string
+ */
+ public static function rtrimString($str, $str_search)
+ {
+ $length_str = strlen($str_search);
+ if (strlen($str) >= $length_str && substr($str, -$length_str) == $str_search)
+ $str = substr($str, 0, -$length_str);
+ return $str;
+ }
}
/**
diff --git a/classes/Validate.php b/classes/Validate.php
index a3083572d..bb44f1167 100644
--- a/classes/Validate.php
+++ b/classes/Validate.php
@@ -44,7 +44,7 @@ class ValidateCore
*/
public static function isEmail($email)
{
- return !empty($email) && preg_match(Tools::cleanNonUnicodeSupport('/^[a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]+[.a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]*@[a-z\p{L}0-9]+[._a-z\p{L}0-9-]*\.[a-z0-9]+$/ui'), $email);
+ return !empty($email) && preg_match(Tools::cleanNonUnicodeSupport('/^[a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]+[.a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]*@[a-z\p{L}0-9]+[._a-z\p{L}0-9-]*\.[a-z\p{L}0-9]+$/ui'), $email);
}
/**
@@ -1072,4 +1072,4 @@ class ValidateCore
{
return (preg_match('/^['.Configuration::get('PS_INVOICE_PREFIX', Context::getContext()->language->id).']*([0-9]+)?/i', $id));
}
-}
\ No newline at end of file
+}
diff --git a/classes/Zone.php b/classes/Zone.php
index 699a90e52..1d39ad7b2 100644
--- a/classes/Zone.php
+++ b/classes/Zone.php
@@ -54,12 +54,18 @@ class ZoneCore extends ObjectModel
*/
public static function getZones($active = false)
{
- return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
- SELECT *
- FROM `'._DB_PREFIX_.'zone`
- '.($active ? 'WHERE active = 1' : '').'
- ORDER BY `name` ASC
- ');
+ $cache_id = 'Zone::getZones_'.(bool)$active;
+ if (!Cache::isStored($cache_id))
+ {
+ $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
+ SELECT *
+ FROM `'._DB_PREFIX_.'zone`
+ '.($active ? 'WHERE active = 1' : '').'
+ ORDER BY `name` ASC
+ ');
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
diff --git a/classes/cache/CacheMemcache.php b/classes/cache/CacheMemcache.php
index 8c4445a7f..a795ed6a1 100755
--- a/classes/cache/CacheMemcache.php
+++ b/classes/cache/CacheMemcache.php
@@ -153,6 +153,8 @@ class CacheMemcacheCore extends Cache
*/
protected function _writeKeys()
{
+ if (!$this->is_connected)
+ return false;
$this->memcache->set(_COOKIE_IV_, $this->keys);
}
diff --git a/classes/controller/AdminController.php b/classes/controller/AdminController.php
index 04bf06874..2fbd5e8f3 100644
--- a/classes/controller/AdminController.php
+++ b/classes/controller/AdminController.php
@@ -1707,12 +1707,14 @@ class AdminControllerCore extends Controller
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'));
+ libxml_use_internal_errors(true);
$country_module_list = file_get_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST);
- if (!empty($country_module_list) && $country_module_list_xml = simplexml_load_string($country_module_list))
+ if (!empty($country_module_list) && is_string($country_module_list) && $country_module_list_xml = simplexml_load_string($country_module_list))
{
$country_module_list_array = array();
- foreach ($country_module_list_xml->module as $k => $m)
- $country_module_list_array[] = (string)$m->name;
+ if (is_array($country_module_list_xml->module))
+ foreach ($country_module_list_xml->module as $k => $m)
+ $country_module_list_array[] = (string)$m->name;
$this->tab_modules_list['slider_list'] = array_intersect($this->tab_modules_list['slider_list'], $country_module_list_array);
}
@@ -2557,7 +2559,7 @@ class AdminControllerCore extends Controller
$cookie = $this->context->cookie;
$this->allow_employee_form_lang = (int)Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG');
if ($this->allow_employee_form_lang && !$cookie->employee_form_lang)
- $cookie->employee_form_lang = (int)$this->context->language->id;
+ $cookie->employee_form_lang = (int)Configuration::get('PS_LANG_DEFAULT');
$lang_exists = false;
$this->_languages = Language::getLanguages(false);
@@ -2565,7 +2567,7 @@ class AdminControllerCore extends Controller
if (isset($cookie->employee_form_lang) && $cookie->employee_form_lang == $lang['id_lang'])
$lang_exists = true;
- $this->default_form_language = $lang_exists ? (int)$cookie->employee_form_lang : (int)$this->context->language->id;
+ $this->default_form_language = $lang_exists ? (int)$cookie->employee_form_lang : (int)Configuration::get('PS_LANG_DEFAULT');
foreach ($this->_languages as $k => $language)
$this->_languages[$k]['is_default'] = ((int)($language['id_lang'] == $this->default_form_language));
diff --git a/classes/controller/Controller.php b/classes/controller/Controller.php
index af4861b19..6593eef52 100644
--- a/classes/controller/Controller.php
+++ b/classes/controller/Controller.php
@@ -175,8 +175,8 @@ abstract class ControllerCore
// then using displayAjax[action]
if ($this->ajax)
{
- $action = Tools::getValue('action');
- if (!empty($action) && method_exists($this, 'displayAjax'.Tools::toCamelCase($action, true)))
+ $action = Tools::toCamelCase(Tools::getValue('action'), true);
+ if (!empty($action) && method_exists($this, 'displayAjax'.$action))
$this->{'displayAjax'.$action}();
elseif (method_exists($this, 'displayAjax'))
$this->displayAjax();
@@ -367,4 +367,4 @@ abstract class ControllerCore
Tools::restoreCacheSettings();
return $res;
}
-}
\ No newline at end of file
+}
diff --git a/classes/controller/FrontController.php b/classes/controller/FrontController.php
index 5771606de..eea4a1bf1 100644
--- a/classes/controller/FrontController.php
+++ b/classes/controller/FrontController.php
@@ -865,7 +865,7 @@ class FrontControllerCore extends Controller
if (!is_numeric(Tools::getValue('p', 1)) || Tools::getValue('p', 1) < 0)
Tools::redirect(self::$link->getPaginationLink(false, false, $this->n, false, 1, false));
- $current_url = tools::htmlentitiesUTF8($_SERVER['REQUEST_URI']);
+ $current_url = Tools::htmlentitiesUTF8($_SERVER['REQUEST_URI']);
//delete parameter page
$current_url = preg_replace('/(\?)?(&)?p=\d+/', '$1', $current_url);
@@ -934,7 +934,7 @@ class FrontControllerCore extends Controller
$ips = array_map('trim', $ips);
if (is_array($ips) && count($ips))
foreach ($ips as $ip)
- if (!empty($ip) && strpos($user_ip, $ip) === 0)
+ if (!empty($ip) && preg_match('/^'.$ip.'.*/', $user_ip))
$allowed = true;
return $allowed;
}
@@ -1199,4 +1199,4 @@ class FrontControllerCore extends Controller
{
return Product::getColorsListCacheId($id_product);
}
-}
\ No newline at end of file
+}
diff --git a/classes/db/Db.php b/classes/db/Db.php
index 4060e85bc..0d829a433 100755
--- a/classes/db/Db.php
+++ b/classes/db/Db.php
@@ -523,13 +523,13 @@ abstract class DbCore
$this->last_cached = true;
return $result;
}
-
$this->result = $this->query($sql);
if (!$this->result)
return false;
-
$this->last_cached = false;
$result = $this->nextRow($this->result);
+ if (is_null($result))
+ $result = false;
if ($use_cache && $this->is_cache_enabled)
Cache::getInstance()->setQuery($sql, $result);
return $result;
diff --git a/classes/module/Module.php b/classes/module/Module.php
index 350cdfe5d..b712c97f7 100644
--- a/classes/module/Module.php
+++ b/classes/module/Module.php
@@ -1271,7 +1271,9 @@ abstract class ModuleCore
$modules = scandir(_PS_MODULE_DIR_);
foreach ($modules as $name)
{
- if (is_dir(_PS_MODULE_DIR_.$name) && Tools::file_exists_cache(_PS_MODULE_DIR_.$name.'/'.$name.'.php'))
+ if (is_file(_PS_MODULE_DIR_.$name))
+ continue;
+ elseif (is_dir(_PS_MODULE_DIR_.$name.DIRECTORY_SEPARATOR) && Tools::file_exists_cache(_PS_MODULE_DIR_.$name.'/'.$name.'.php'))
{
if (!Validate::isModuleName($name))
throw new PrestaShopException(sprintf('Module %s is not a valid module name', $name));
@@ -1879,7 +1881,13 @@ abstract class ModuleCore
*/
public static function getModuleIdByName($name)
{
- return Db::getInstance()->getValue('SELECT `id_module` FROM `'._DB_PREFIX_.'module` WHERE `name` = "'.pSQL($name).'"');
+ $cache_id = 'Module::getModuleIdByName_'.pSQL($name);
+ if (!Cache::isStored($cache_id))
+ {
+ $result = (int)Db::getInstance()->getValue('SELECT `id_module` FROM `'._DB_PREFIX_.'module` WHERE `name` = "'.pSQL($name).'"');
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
diff --git a/classes/order/Order.php b/classes/order/Order.php
index fcc9f4a4f..7e72ee35f 100644
--- a/classes/order/Order.php
+++ b/classes/order/Order.php
@@ -721,11 +721,17 @@ class OrderCore extends ObjectModel
public static function getDiscountsCustomer($id_customer, $id_cart_rule)
{
- return Db::getInstance()->getValue('
- SELECT COUNT(*) FROM `'._DB_PREFIX_.'orders` o
- LEFT JOIN '._DB_PREFIX_.'order_cart_rule ocr ON (ocr.id_order = o.id_order)
- WHERE o.id_customer = '.(int)$id_customer.'
- AND ocr.id_cart_rule = '.(int)$id_cart_rule);
+ $cache_id = 'Order::getDiscountsCustomer_'.(int)$id_customer.'-'.(int)$id_cart_rule;
+ if (!Cache::isStored($cache_id))
+ {
+ $result = (int)Db::getInstance()->getValue('
+ SELECT COUNT(*) FROM `'._DB_PREFIX_.'orders` o
+ LEFT JOIN '._DB_PREFIX_.'order_cart_rule ocr ON (ocr.id_order = o.id_order)
+ WHERE o.id_customer = '.(int)$id_customer.'
+ AND ocr.id_cart_rule = '.(int)$id_cart_rule);
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
diff --git a/classes/order/OrderState.php b/classes/order/OrderState.php
index 7cc1d5375..19dddb875 100644
--- a/classes/order/OrderState.php
+++ b/classes/order/OrderState.php
@@ -112,12 +112,18 @@ class OrderStateCore extends ObjectModel
*/
public static function getOrderStates($id_lang)
{
- return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
- SELECT *
- FROM `'._DB_PREFIX_.'order_state` os
- LEFT JOIN `'._DB_PREFIX_.'order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = '.(int)$id_lang.')
- WHERE deleted = 0
- ORDER BY `name` ASC');
+ $cache_id = 'OrderState::getOrderStates_'.(int)$id_lang;
+ if (!Cache::isStored($cache_id))
+ {
+ $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
+ SELECT *
+ FROM `'._DB_PREFIX_.'order_state` os
+ LEFT JOIN `'._DB_PREFIX_.'order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = '.(int)$id_lang.')
+ WHERE deleted = 0
+ ORDER BY `name` ASC');
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
/**
diff --git a/classes/shop/Shop.php b/classes/shop/Shop.php
index 98ae61c53..ee7dddcf7 100644
--- a/classes/shop/Shop.php
+++ b/classes/shop/Shop.php
@@ -187,14 +187,19 @@ class ShopCore extends ObjectModel
public function setUrl()
{
- $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');
-
+ $cache_id = 'Shop::setUrl_'.(int)$this->id;
+ if (!Cache::isStored($cache_id))
+ {
+ $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');
+ Cache::store($cache_id, $row);
+ }
+ $row = Cache::retrieve($cache_id);
if (!$row)
return false;
diff --git a/classes/stock/StockAvailable.php b/classes/stock/StockAvailable.php
index 62f6a0548..d544dec5d 100644
--- a/classes/stock/StockAvailable.php
+++ b/classes/stock/StockAvailable.php
@@ -53,6 +53,8 @@ class StockAvailableCore extends ObjectModel
/** @var bool determine if a product is out of stock - it was previously in Product class */
public $out_of_stock = false;
+ protected static $cache_quantity_available;
+
/**
* @see ObjectModel::$definition
*/
@@ -343,18 +345,23 @@ class StockAvailableCore extends ObjectModel
if ($id_product_attribute === null)
$id_product_attribute = 0;
- $query = new DbQuery();
- $query->select('SUM(quantity)');
- $query->from('stock_available');
+ $key = (int)$id_product.'-'.(int)$id_product_attribute.'-'.(int)$id_shop;
+ if (!isset(self::$cache_quantity_available[$key]))
+ {
+ $query = new DbQuery();
+ $query->select('SUM(quantity)');
+ $query->from('stock_available');
+
+ // if null, it's a product without attributes
+ if ($id_product !== null)
+ $query->where('id_product = '.(int)$id_product);
+
+ $query->where('id_product_attribute = '.(int)$id_product_attribute);
+ $query = StockAvailable::addSqlShopRestriction($query, $id_shop);
- // if null, it's a product without attributes
- if ($id_product !== null)
- $query->where('id_product = '.(int)$id_product);
-
- $query->where('id_product_attribute = '.(int)$id_product_attribute);
- $query = StockAvailable::addSqlShopRestriction($query, $id_shop);
-
- return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query);
+ self::$cache_quantity_available[$key] = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query);
+ }
+ return self::$cache_quantity_available[$key];
}
/**
diff --git a/classes/tax/TaxRule.php b/classes/tax/TaxRule.php
index e59a2ddb9..b41d61fa1 100644
--- a/classes/tax/TaxRule.php
+++ b/classes/tax/TaxRule.php
@@ -124,9 +124,13 @@ class TaxRuleCore extends ObjectModel
*/
public static function isTaxInUse($id_tax)
{
- return Db::getInstance()->getValue('
- SELECT COUNT(*) FROM `'._DB_PREFIX_.'tax_rule` WHERE `id_tax` = '.(int)$id_tax
- );
+ $cache_id = 'TaxRule::isTaxInUse_'.(int)$id_tax;
+ if (!Cache::isStored($cache_id))
+ {
+ $result = (int)Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'tax_rule` WHERE `id_tax` = '.(int)$id_tax);
+ Cache::store($cache_id, $result);
+ }
+ return Cache::retrieve($cache_id);
}
diff --git a/classes/tax/TaxRulesTaxManager.php b/classes/tax/TaxRulesTaxManager.php
index ba6b07456..98047c69c 100644
--- a/classes/tax/TaxRulesTaxManager.php
+++ b/classes/tax/TaxRulesTaxManager.php
@@ -33,9 +33,6 @@ class TaxRulesTaxManagerCore implements TaxManagerInterface
public $type;
public $tax_calculator;
- protected static $cache_tax_calculator;
-
-
/**
*
* @param Address $address
@@ -80,7 +77,8 @@ class TaxRulesTaxManagerCore implements TaxManagerInterface
if (!empty($this->address->postcode))
$postcode = $this->address->postcode;
- if (!isset(self::$cache_tax_calculator[(int)$this->address->id_country.'-'.$postcode.'-'.$this->type]))
+ $cache_id = (int)$this->address->id_country.'-'.(int)$this->address->id_state.'-'.$postcode.'-'.(int)$this->type;
+ if (!Cache::isStored($cache_id))
{
$rows = Db::getInstance()->executeS('
SELECT *
@@ -110,11 +108,8 @@ class TaxRulesTaxManagerCore implements TaxManagerInterface
if ($row['behavior'] == 0)
break;
}
-
- self::$cache_tax_calculator[(int)$this->address->id_country.'-'.$postcode.'-'.$this->type] = new TaxCalculator($taxes, $behavior);
+ Cache::store($cache_id, new TaxCalculator($taxes, $behavior));
}
-
- return self::$cache_tax_calculator[(int)$this->address->id_country.'-'.$postcode.'-'.$this->type];
+ return Cache::retrieve($cache_id);
}
}
-
diff --git a/classes/webservice/WebserviceSpecificManagementImages.php b/classes/webservice/WebserviceSpecificManagementImages.php
index dd6401e5a..8d9fd1626 100755
--- a/classes/webservice/WebserviceSpecificManagementImages.php
+++ b/classes/webservice/WebserviceSpecificManagementImages.php
@@ -845,11 +845,13 @@ class WebserviceSpecificManagementImagesCore implements WebserviceSpecificManage
$imaged = imagegif($destImage, $newPath);
break;
case 'png':
- $imaged = imagepng($destImage, $newPath, 7);
+ $quality = (Configuration::get('PS_PNG_QUALITY') === false ? 7 : Configuration::get('PS_PNG_QUALITY'));
+ $imaged = imagepng($destImage, $newPath, (int)$quality);
break;
case 'jpeg':
default:
- $imaged = imagejpeg($destImage, $newPath, 90);
+ $quality = (Configuration::get('PS_JPEG_QUALITY') === false ? 90 : Configuration::get('PS_JPEG_QUALITY'));
+ $imaged = imagejpeg($destImage, $newPath, (int)$quality);
break;
}
imagedestroy($destImage);
diff --git a/config/defines_uri.inc.php b/config/defines_uri.inc.php
index 34cbae33b..7744e9cdd 100644
--- a/config/defines_uri.inc.php
+++ b/config/defines_uri.inc.php
@@ -38,13 +38,14 @@ if (file_exists(_PS_THEME_DIR_.'mobile/'))
{
define('_PS_THEME_MOBILE_DIR_', _PS_THEME_DIR_.'mobile/');
define('_THEME_MOBILE_DIR_', _THEMES_DIR_._THEME_NAME_.'/mobile/');
- define('_PS_THEME_MOBILE_OVERRIDE_DIR_', _PS_THEME_MOBILE_DIR_.'override/');
}
else
{
define('_PS_THEME_MOBILE_DIR_', _PS_ROOT_DIR_.'/themes/default/mobile/');
define('_THEME_MOBILE_DIR_', __PS_BASE_URI__.'themes/default/mobile/');
}
+define('_PS_THEME_MOBILE_OVERRIDE_DIR_', _PS_THEME_MOBILE_DIR_.'override/');
+
define('_THEME_MOBILE_IMG_DIR_', _THEME_MOBILE_DIR_.'img/');
define('_THEME_MOBILE_CSS_DIR_', _THEME_MOBILE_DIR_.'css/');
define('_THEME_MOBILE_JS_DIR_', _THEME_MOBILE_DIR_.'js/');
diff --git a/controllers/admin/AdminCartRulesController.php b/controllers/admin/AdminCartRulesController.php
index cef27a879..6689f023f 100644
--- a/controllers/admin/AdminCartRulesController.php
+++ b/controllers/admin/AdminCartRulesController.php
@@ -143,6 +143,8 @@ class AdminCartRulesControllerCore extends AdminController
$this->errors[] = Tools::displayError('Reduction amount cannot be lower than zero.');
if (Tools::getValue('code') && ($same_code = (int)CartRule::getIdByCode(Tools::getValue('code'))) && $same_code != Tools::getValue('id_cart_rule'))
$this->errors[] = sprintf(Tools::displayError('This cart rule code is already used (conflict with cart rule %d)'), $same_code);
+ if (Tools::getValue('apply_discount') == 'off' && !Tools::getValue('free_shipping') && !Tools::getValue('free_gift'))
+ $this->errors[] = Tools::displayError('An action is required for this cart rule.');
}
return parent::postProcess();
diff --git a/controllers/admin/AdminCustomerThreadsController.php b/controllers/admin/AdminCustomerThreadsController.php
index efc682ac8..2feec12bc 100644
--- a/controllers/admin/AdminCustomerThreadsController.php
+++ b/controllers/admin/AdminCustomerThreadsController.php
@@ -309,12 +309,15 @@ class AdminCustomerThreadsControllerCore extends AdminController
$cm = new CustomerMessage();
$cm->id_employee = (int)$this->context->employee->id;
$cm->id_customer_thread = (int)Tools::getValue('id_customer_thread');
- $cm->ip_address = ip2long($_SERVER['REMOTE_ADDR']);
+ $cm->ip_address = ip2long(Tools::getRemoteAddr());
$current_employee = $this->context->employee;
$id_employee = (int)Tools::getValue('id_employee_forward');
$employee = new Employee($id_employee);
$email = Tools::getValue('email');
- if ($id_employee && $employee && Validate::isLoadedObject($employee))
+ $message = Tools::getValue('message_forward');
+ if (($error = $cm->validateField('message', $message, null, array(), true)) !== true)
+ $this->errors[] = $error;
+ elseif ($id_employee && $employee && Validate::isLoadedObject($employee))
{
$params = array(
'{messages}' => Tools::nl2br(stripslashes($output)),
@@ -333,7 +336,7 @@ class AdminCustomerThreadsControllerCore extends AdminController
null, null, _PS_MAIL_DIR_, true))
{
$cm->private = 1;
- $cm->message = $this->l('Message forwarded to').' '.$employee->firstname.' '.$employee->lastname."\n".$this->l('Comment:').' '.$_POST['message_forward'];
+ $cm->message = $this->l('Message forwarded to').' '.$employee->firstname.' '.$employee->lastname."\n".$this->l('Comment:').' '.$message;
$cm->add();
}
}
@@ -352,7 +355,7 @@ class AdminCustomerThreadsControllerCore extends AdminController
$current_employee->email, $current_employee->firstname.' '.$current_employee->lastname,
null, null, _PS_MAIL_DIR_, true))
{
- $cm->message = $this->l('Message forwarded to').' '.$email."\n".$this->l('Comment:').' '.$_POST['message_forward'];
+ $cm->message = $this->l('Message forwarded to').' '.$email."\n".$this->l('Comment:').' '.$message;
$cm->add();
}
}
@@ -368,10 +371,11 @@ class AdminCustomerThreadsControllerCore extends AdminController
$cm = new CustomerMessage();
$cm->id_employee = (int)$this->context->employee->id;
$cm->id_customer_thread = $ct->id;
-
+ $cm->ip_address = ip2long(Tools::getRemoteAddr());
$cm->message = Tools::getValue('reply_message');
- $cm->ip_address = ip2long($_SERVER['REMOTE_ADDR']);
- if (isset($_FILES) && !empty($_FILES['joinFile']['name']) && $_FILES['joinFile']['error'] != 0)
+ if (($error = $cm->validateField('message', $cm->message, null, array(), true)) !== true)
+ $this->errors[] = $error;
+ elseif (isset($_FILES) && !empty($_FILES['joinFile']['name']) && $_FILES['joinFile']['error'] != 0)
$this->errors[] = Tools::displayError('An error occurred during the file upload process.');
elseif ($cm->add())
{
diff --git a/controllers/admin/AdminImportController.php b/controllers/admin/AdminImportController.php
index 051f5135a..a78b13e07 100644
--- a/controllers/admin/AdminImportController.php
+++ b/controllers/admin/AdminImportController.php
@@ -2019,7 +2019,7 @@ class AdminImportControllerCore extends AdminController
$myGroup = new Group();
$myGroup->name = Array($id_lang => $group);
if ($id_lang != $default_language_id)
- $myGroup->name = array_merge($myGroup->name, array($default_language_id => $group));
+ $myGroup->name = $myGroup->name + array($default_language_id => $group);
$myGroup->price_display_method = 1;
$myGroup->add();
if (Validate::isLoadedObject($myGroup))
diff --git a/controllers/admin/AdminLocalizationController.php b/controllers/admin/AdminLocalizationController.php
index 889bf6854..d22128131 100644
--- a/controllers/admin/AdminLocalizationController.php
+++ b/controllers/admin/AdminLocalizationController.php
@@ -142,8 +142,10 @@ class AdminLocalizationControllerCore extends AdminController
if (Validate::isFileName(Tools::getValue('iso_localization_pack')))
{
-
- $pack = @Tools::file_get_contents('http://api.prestashop.com/localization/'.$version.'/'.Tools::getValue('iso_localization_pack').'.xml');
+ if (Tools::getValue('download_updated_pack') == '1')
+ $pack = @Tools::file_get_contents('http://api.prestashop.com/localization/'.$version.'/'.Tools::getValue('iso_localization_pack').'.xml');
+ else
+ $pack = false;
if (!$pack && !($pack = @Tools::file_get_contents(_PS_ROOT_DIR_.'/localization/'.Tools::getValue('iso_localization_pack').'.xml')))
$this->errors[] = Tools::displayError('Cannot load the localization pack.');
@@ -266,6 +268,26 @@ class AdminLocalizationControllerCore extends AdminController
'id' => 'id',
'name' => 'name'
)
+ ),
+ array(
+ 'type' => 'radio',
+ 'label' => $this->l('Download pack data'),
+ 'desc' => $this->l('If set to yes then the localization pack will be downloaded from prestashop.com. Otherwise the local xml file found in the localization folder of your PrestaShop installation will be used.'),
+ 'name' => 'download_updated_pack',
+ 'class' => 't',
+ 'is_bool'=> true,
+ 'values' => array(
+ array(
+ 'id' => 'download_updated_pack_yes',
+ 'value' => 1,
+ 'label' => $this->l('Yes')
+ ),
+ array(
+ 'id' => 'download_updated_pack_no',
+ 'value' => 0,
+ 'label' => $this->l('No')
+ )
+ )
)
),
'submit' => array(
@@ -280,7 +302,8 @@ class AdminLocalizationControllerCore extends AdminController
'selection[]_taxes' => true,
'selection[]_currencies' => true,
'selection[]_languages' => true,
- 'selection[]_units' => true
+ 'selection[]_units' => true,
+ 'download_updated_pack' => 1
);
$this->show_toolbar = false;
diff --git a/controllers/admin/AdminOrdersController.php b/controllers/admin/AdminOrdersController.php
index 415d00ed3..c121de902 100755
--- a/controllers/admin/AdminOrdersController.php
+++ b/controllers/admin/AdminOrdersController.php
@@ -897,7 +897,7 @@ class AdminOrdersControllerCore extends AdminController
Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token);
}
else
- $this->errors[] = Tools::displayErrror('This address can\'t be loaded');
+ $this->errors[] = Tools::displayError('This address can\'t be loaded');
}
else
$this->errors[] = Tools::displayError('You do not have permission to edit this.');
diff --git a/controllers/admin/AdminPPreferencesController.php b/controllers/admin/AdminPPreferencesController.php
index 3e39e6150..f8f64cbc5 100644
--- a/controllers/admin/AdminPPreferencesController.php
+++ b/controllers/admin/AdminPPreferencesController.php
@@ -188,6 +188,14 @@ class AdminPPreferencesControllerCore extends AdminController
),
'identifier' => 'id'
)
+ 'PS_DISPLAY_DISCOUNT_PRICE' => array(
+ 'title' => $this->l('Display discounted price'),
+ 'desc' => $this->l('Instead of showing the discount (-5%) it will instead show the new price with the discount applied'),
+ 'validation' => 'isBool',
+ 'cast' => 'intval',
+ 'required' => false,
+ 'type' => 'bool'
+ ),
)
),
'stock' => array(
diff --git a/controllers/admin/AdminPerformanceController.php b/controllers/admin/AdminPerformanceController.php
index 494031e49..37927a154 100644
--- a/controllers/admin/AdminPerformanceController.php
+++ b/controllers/admin/AdminPerformanceController.php
@@ -793,7 +793,7 @@ class AdminPerformanceControllerCore extends AdminController
{
$new_settings = $prev_settings = file_get_contents(_PS_ROOT_DIR_.'/config/settings.inc.php');
$cache_active = (bool)Tools::getValue('cache_active');
-
+
if ($caching_system = Tools::getValue('caching_system'))
{
$new_settings = preg_replace(
@@ -807,7 +807,6 @@ class AdminPerformanceControllerCore extends AdminController
$cache_active = false;
$this->errors[] = Tools::displayError('The caching system is missing.');
}
-
if ($cache_active)
{
if ($caching_system == 'CacheMemcache' && !extension_loaded('memcache'))
@@ -912,5 +911,4 @@ class AdminPerformanceControllerCore extends AdminController
}
die;
}
-
}
diff --git a/controllers/admin/AdminProductsController.php b/controllers/admin/AdminProductsController.php
index 388a552c2..8ef5b8806 100644
--- a/controllers/admin/AdminProductsController.php
+++ b/controllers/admin/AdminProductsController.php
@@ -2688,6 +2688,10 @@ class AdminProductsControllerCore extends AdminController
$product_supplier->id_product = $product->id;
$product_supplier->id_product_attribute = 0;
$product_supplier->id_supplier = $id;
+ if ($this->context->currency->id)
+ $product_supplier->id_currency = (int)$this->context->currency->id;
+ else
+ $product_supplier->id_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT');
$product_supplier->save();
$associated_suppliers[] = $product_supplier;
diff --git a/controllers/admin/AdminShopController.php b/controllers/admin/AdminShopController.php
index cf94d0943..1fcea5901 100755
--- a/controllers/admin/AdminShopController.php
+++ b/controllers/admin/AdminShopController.php
@@ -148,7 +148,7 @@ class AdminShopControllerCore extends AdminController
{
parent::initContent();
- $this->addJqueryPlugin('cookie-plugin');
+ $this->addJqueryPlugin('cooki-plugin');
$this->addJqueryPlugin('jstree');
$this->addCSS(_PS_JS_DIR_.'jquery/plugins/jstree/themes/classic/style.css');
diff --git a/controllers/admin/AdminShopGroupController.php b/controllers/admin/AdminShopGroupController.php
index b890f8eb8..d7a680032 100644
--- a/controllers/admin/AdminShopGroupController.php
+++ b/controllers/admin/AdminShopGroupController.php
@@ -109,7 +109,7 @@ class AdminShopGroupControllerCore extends AdminController
);
}
- $this->addJqueryPlugin('cookie-plugin');
+ $this->addJqueryPlugin('cooki-plugin');
$this->addJqueryPlugin('jstree');
$this->addCSS(_PS_JS_DIR_.'jquery/plugins/jstree/themes/classic/style.css');
diff --git a/controllers/admin/AdminShopUrlController.php b/controllers/admin/AdminShopUrlController.php
index 54af8b48c..9eba3f435 100644
--- a/controllers/admin/AdminShopUrlController.php
+++ b/controllers/admin/AdminShopUrlController.php
@@ -289,7 +289,7 @@ class AdminShopUrlControllerCore extends AdminController
{
parent::initContent();
- $this->addJqueryPlugin('cookie-plugin');
+ $this->addJqueryPlugin('cooki-plugin');
$this->addJqueryPlugin('jstree');
$this->addCSS(_PS_JS_DIR_.'jquery/plugins/jstree/themes/classic/style.css');
diff --git a/controllers/front/AuthController.php b/controllers/front/AuthController.php
index 0c664eaa5..7d8bfd3e6 100644
--- a/controllers/front/AuthController.php
+++ b/controllers/front/AuthController.php
@@ -89,12 +89,15 @@ class AuthControllerCore extends FrontController
$this->context->smarty->assign('newsletter', 1);
- $back = Tools::getValue('back');
- $key = Tools::safeOutput(Tools::getValue('key'));
- if (!empty($key))
- $back .= (strpos($back, '?') !== false ? '&' : '?').'key='.$key;
- if (!empty($back))
- $this->context->smarty->assign('back', Tools::safeOutput(Tools::secureReferrer($back)));
+ if ($back = Tools::safeOutput(Tools::getValue('back')))
+ {
+ $key = Tools::safeOutput(Tools::getValue('key'));
+ if (!empty($key))
+ $back .= (strpos($back, '?') !== false ? '&' : '?').'key='.$key;
+ if ($back == Tools::secureReferrer(Tools::getValue('back')))
+ $this->context->smarty->assign('back', html_entity_decode($back));
+ $this->context->smarty->assign('back', $back);
+ }
if (Tools::getValue('display_guest_checkout'))
{
diff --git a/controllers/front/CategoryController.php b/controllers/front/CategoryController.php
index e6480cdb6..3b8fd070e 100644
--- a/controllers/front/CategoryController.php
+++ b/controllers/front/CategoryController.php
@@ -116,6 +116,7 @@ class CategoryControllerCore extends FrontController
$this->context->smarty->assign(array(
'category' => $this->category,
+ 'description_short' => Tools::truncateString($this->category->description),
'products' => (isset($this->cat_products) && $this->cat_products) ? $this->cat_products : null,
'id_category' => (int)$this->category->id,
'id_category_parent' => (int)$this->category->id_parent,
diff --git a/controllers/front/CmsController.php b/controllers/front/CmsController.php
index a62047b02..2c9793ec4 100644
--- a/controllers/front/CmsController.php
+++ b/controllers/front/CmsController.php
@@ -30,12 +30,13 @@ class CmsControllerCore extends FrontController
public $assignCase;
public $cms;
public $cms_category;
+ public $ssl = false;
public function canonicalRedirection($canonicalURL = '')
{
if (Tools::getValue('live_edit'))
return ;
- if (Validate::isLoadedObject($this->cms) && ($canonicalURL = $this->context->link->getCMSLink($this->cms)))
+ if (Validate::isLoadedObject($this->cms) && ($canonicalURL = $this->context->link->getCMSLink($this->cms, $this->cms->link_rewrite, $this->ssl)))
parent::canonicalRedirection($canonicalURL);
else if (Validate::isLoadedObject($this->cms_category) && ($canonicalURL = $this->context->link->getCMSCategoryLink($this->cms_category)))
parent::canonicalRedirection($canonicalURL);
@@ -47,13 +48,16 @@ class CmsControllerCore extends FrontController
*/
public function init()
{
- parent::init();
-
if ($id_cms = (int)Tools::getValue('id_cms'))
$this->cms = new CMS($id_cms, $this->context->language->id);
else if ($id_cms_category = (int)Tools::getValue('id_cms_category'))
$this->cms_category = new CMSCategory($id_cms_category, $this->context->language->id);
+ if (Configuration::get('PS_SSL_ENABLED') && Tools::getValue('content_only') && Tools::getValue('id_cms') == (int)Configuration::get('PS_CONDITIONS_CMS_ID') && Validate::isLoadedObject($this->cms))
+ $this->ssl = true;
+
+ parent::init();
+
$this->canonicalRedirection();
// assignCase (1 = CMS page, 2 = CMS category)
@@ -120,7 +124,7 @@ class CmsControllerCore extends FrontController
'category' => $this->cms_category, //for backward compatibility
'cms_category' => $this->cms_category,
'sub_category' => $this->cms_category->getSubCategories($this->context->language->id),
- 'cms_pages' => CMS::getCMSPages($this->context->language->id, (int)($this->cms_category->id) ),
+ 'cms_pages' => CMS::getCMSPages($this->context->language->id, (int)($this->cms_category->id), true, (int)$this->context->shop->id),
'path' => ($this->cms_category->id !== 1) ? Tools::getPath($this->cms_category->id, $this->cms_category->name, false, 'CMS') : '',
));
}
diff --git a/controllers/front/ContactController.php b/controllers/front/ContactController.php
index 8d3e5689e..c127fa46a 100644
--- a/controllers/front/ContactController.php
+++ b/controllers/front/ContactController.php
@@ -147,7 +147,7 @@ class ContactControllerCore extends FrontController
$cm->message = $message;
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->ip_address = ip2long(Tools::getRemoteAddr());
$cm->user_agent = $_SERVER['HTTP_USER_AGENT'];
if (!$cm->add())
$this->errors[] = Tools::displayError('An error occurred while sending the message.');
diff --git a/controllers/front/OrderOpcController.php b/controllers/front/OrderOpcController.php
index 2b03955a6..7bde212a6 100644
--- a/controllers/front/OrderOpcController.php
+++ b/controllers/front/OrderOpcController.php
@@ -529,8 +529,8 @@ class OrderOpcControllerCore extends ParentOrderController
$minimalPurchase = Tools::convertPrice((float)Configuration::get('PS_PURCHASE_MINIMUM'), $currency);
if ($this->context->cart->getOrderTotal(false, Cart::ONLY_PRODUCTS) < $minimalPurchase)
return '
'.sprintf(
- Tools::displayError('A minimum purchase total of %s is required in order to validate your order.'),
- Tools::displayPrice($minimalPurchase, $currency)
+ Tools::displayError('A minimum purchase total of %1s (tax excl.) is required in order to validate your order, current purchase total is %2s (tax excl.).'),
+ Tools::displayPrice($minimal_purchase, $currency), Tools::displayPrice($this->context->cart->getOrderTotal(false, Cart::ONLY_PRODUCTS), $currency)
).'
';
/* Bypass payment step if total is 0 */
diff --git a/controllers/front/ParentOrderController.php b/controllers/front/ParentOrderController.php
index 6fa902bdc..e0672255e 100644
--- a/controllers/front/ParentOrderController.php
+++ b/controllers/front/ParentOrderController.php
@@ -415,6 +415,17 @@ class ParentOrderControllerCore extends FrontController
if (key($customerAddresses) != 0)
$customerAddresses = array_values($customerAddresses);
+ if (!count($customerAddresses))
+ {
+ $bad_delivery = false;
+ if (($bad_delivery = (bool)!Address::isCountryActiveById((int)$this->context->cart->id_address_delivery)) || (!Address::isCountryActiveById((int)$this->context->cart->id_address_invoice)))
+ {
+ $back_url = $this->context->link->getPageLink('order', true, (int)$this->context->language->id, array('step' => Tools::getValue('step'), 'multi-shipping' => (int)Tools::getValue('multi-shipping')));
+ $params = array('multi-shipping' => (int)Tools::getValue('multi-shipping'), 'id_address' => ($bad_delivery ? (int)$this->context->cart->id_address_delivery : (int)$this->context->cart->id_address_invoice), 'back' => $back_url);
+ Tools::redirect($this->context->link->getPageLink('address', true, (int)$this->context->language->id, $params));
+ }
+ }
+
$this->context->smarty->assign(array(
'addresses' => $customerAddresses,
'formatedAddressFieldsValuesList' => $formatedAddressFieldsValuesList));
@@ -465,16 +476,6 @@ class ParentOrderControllerCore extends FrontController
$address = new Address($this->context->cart->id_address_delivery);
$id_zone = Address::getZoneById($address->id);
$bad_delivery = false;
- if (($bad_delivery = (bool)!Address::isCountryActiveById((int)$this->context->cart->id_address_delivery)) || (!Address::isCountryActiveById((int)$this->context->cart->id_address_invoice)))
- {
- if (Configuration::get('PS_ORDER_PROCESS_TYPE') == 1 && Dispatcher::getInstance()->getController() != 'order-opc')
- {
- $back_url = $this->context->link->getPageLink('order', true, (int)$this->context->language->id, array('step' => Tools::getValue('step'), 'multi-shipping' => (int)Tools::getValue('multi-shipping')));
- $params = array('multi-shipping' => (int)Tools::getValue('multi-shipping'), 'id_address' => ($bad_delivery ? (int)$this->context->cart->id_address_delivery : (int)$this->context->cart->id_address_invoice), 'back' => $back_url);
- Tools::redirect($this->context->link->getPageLink('address', true, (int)$this->context->language->id, $params));
- }
- 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();
@@ -510,7 +511,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);
+ $this->link_conditions = $this->context->link->getCMSLink($cms, $cms->link_rewrite, (bool)Configuration::get('PS_SSL_ENABLED'));
if (!strpos($this->link_conditions, '?'))
$this->link_conditions .= '?content_only=1';
else
diff --git a/controllers/front/ProductController.php b/controllers/front/ProductController.php
index 8e7092fd6..a1fb28ee7 100644
--- a/controllers/front/ProductController.php
+++ b/controllers/front/ProductController.php
@@ -551,7 +551,7 @@ class ProductControllerCore extends FrontController
$path = Tools::getPath((int)$this->context->shop->id_category, $this->product->name);
$this->context->smarty->assign('path', $path);
- $this->context->smarty->assign('categories', Category::getHomeCategories($this->context->language->id));
+ $this->context->smarty->assign('categories', Category::getHomeCategories($this->context->language->id, true, (int)$this->context->shop->id));
$this->context->smarty->assign(array('HOOK_PRODUCT_FOOTER' => Hook::exec('displayFooterProduct', array('product' => $this->product, 'category' => $this->category))));
}
diff --git a/controllers/front/StoresController.php b/controllers/front/StoresController.php
index ac10c1dc1..33bc1d3d2 100644
--- a/controllers/front/StoresController.php
+++ b/controllers/front/StoresController.php
@@ -279,6 +279,6 @@ class StoresControllerCore extends FrontController
if (!Configuration::get('PS_STORES_SIMPLIFIED'))
$this->addJS(_THEME_JS_DIR_.'stores.js');
$default_country = new Country((int)Configuration::get('PS_COUNTRY_DEFAULT'));
- $this->addJS('http://maps.google.com/maps/api/js?sensor=true®ion='.substr($default_country->iso_code, 0, 2));
+ $this->addJS('http'.((Configuration::get('PS_SSL_ENABLED') && Configuration::get('PS_SSL_ENABLED_EVERYWHERE')) ? 's' : '').'://maps.google.com/maps/api/js?sensor=true®ion='.substr($default_country->iso_code, 0, 2));
}
}
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 9cc74bcff..514993ed2 100755
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -23,6 +23,225 @@ International Registred Trademark & Property of PrestaShop SA
Release Notes for PrestaShop 1.5
--------------------------------
+####################################
+# v1.5.6.1 - (2013-11-18) #
+####################################
+
+ Fixed bugs:
+
+ [-] Project : missing ui.menu in jquery_ui_dependencies.
+
+ [-] FO : Fix bug #PSCFV-11043, bad cache id from module template
+ [-] FO : Missing sup for DNI field
+ [-] FO : Fix bug #PSCFV-10911, doubles in cart rules highlight
+ [-] FO : Bad value for back when controller name is sent
+ [-] FO : FixBug #PSCFV-9291 - Ecotax increment display price in product combination
+ [-] FO : fix contact-form id_order input when customer is not logged
+ [-] Fo : Call Gmaps on https if required
+ [-] FO : Wordwrap on prices in history
+ [-] FO : Fixed errors when calculating most selled products from footer link
+ [-] FO : #PSCFV-10978 firstname displayed instead of lastname in invoice address
+ [-] FO : Customized meesage with carriage return follow up #962
+ [-] FO : getTaxCalculator bad cache key again // sorry about that
+ [-] FO : getTaxCalculator bad cache key
+ [-] FO : Prevents warning in safePostVars when $_POST has been unset
+ [-] FO : in multistore payment module restrictions by customer group was not applied to specific shop
+ [-] FO : Fix bug #PSCFV-10892, getCMSPages by id_shop thnaks @jd440
+ [-] FO : FixBug Categories description
+ [-] FO : Fix bug #PSCFV-10889 wrong color when oos product
+ [-] FO : CustomerMessage ip_address to string
+ [-] FO : Fix bug #PSCFV-10851, no shop restriction in vouchers display in cart
+ [-] FO: fixed bug #PSCFV-10654 - TinyMCE editor: List of products by manufacturer, products by supplier - Long description is not hidden.
+ [-] FO: Fix bug #PSCFV-10623 blocknewproducts shows products when PS_NB_DAYS_NEW_PRODUCT == 0
+ [-] FO: Fix bug #PSCFV-10230, Blockspecials still caching when files cache limit is 0
+ [-] FO: Fix bug #PSCFV-10625 Js error on carriers step if AjaxCart disabled
+ [-] FO : Follow up https://github.com/PrestaShop/PrestaShop/pull/879
+ [-] FO: removed width on message product select Limiting select could make the user think the select is not working if they click to much to the left on bigger screens
+ [-] FO : Prevent fatal error on getUniqReference when order not loaded
+ [-] FO: Don't auto detect language if it not associated to the shop #PSCFV-10273
+ [-] FO : Could not redirect back to url in adress.php
+ [-] FO : $back value twice escaped
+ [-] FO : #PSCFV-10640 again, bad assignement
+ [-] Fo : Fix bug #PSCFV-10640, redirect loop when country address is not among active countries in OPC
+ [-] FO : Fix bug #PSCFV-10688, bad priceDisplay in order-carrier
+ [-] FO : Fix #PSCFV-10690 again, change just on directories
+ [-] FO : Fix bug #PSCFV-10690 could not index a category beacause of robot.txt
+ [-] FO : Copuld not load datepicker in trackingfront stats.php
+ [-] FO : Fix bug #PSCFV-10497 cart_block hooked on column disappearing
+ [-] FO : Fix bug #PSCFV-10606 could not have correct taxCalculationMethod when vat number in customer address
+
+ [-] BO : Fix bug #PNM-1594, selected value error in helper list
+ [-] BO: product price was changed on changing to advanced stock management #PSCFV-10996
+ [-] BO : Fix warning when no memcached servers
+ [-] BO : Fix #PSCFV-11016 typo
+ [-] BO : Model return html error messagae instead of json while image uploading
+ [-] BO : Product final price can not be hidden on loading tab, report of https://github.com/PrestaShop/PrestaShop/commit/6c6c3b240ee2249b7f99be1a112905cd0edbee46
+ [-] BO : test on xml string follow up https://github.com/PrestaShop/PrestaShop/pull/690#issuecomment-28542506
+ [-] BO : 406 when mod_security follow up https://github.com/PrestaShop/PrestaShop/commit/034e6a7e7f391e3a8861248db45a4a376b19633c
+ [-] BO : AdminImport, execption when creating groups
+ [-] BO : Fix bug #PSCFV-10990 bad version comparison for ps_versions_compliancy
+ [-] BO : Fix bug #PSCFV-10982 reduction group truncated
+ [-] BO : Could not check all modules after ajax call
+ [-] BO : Fix css bug #PSCFV-10899, fixed fix-toolbar z-index
+ [-] BO : Fix bug #PSCFV-10932, ranges input disabled on load
+ [-] BO : getCMSPages to associated shop in cmscontroller
+ [-] BO : Fix bug #PSCFV-10666 product_supllier currency set to 0
+ [-] BO : Fix bug #PSCFV-10937, bad escaping for var product_prices in prices.tpl
+ [-] BO : Cart was not using order reference, corrected syntax
+ [-] BO : Cart was not using order reference
+ [-] BO : Could not change image position
+ [-] BO: Fix from name when replying to customer threads
+ [-] BO : Do not enable rewrite url for index
+ [-] BO: Fix empty group list on changing opt or newsletter on customers listing
+ [-] BO : AdminImport withdraw separator changed in js
+ [-] BO : AdminImport wrong group by default
+ [-] BO : FixBug #PSCFV-10882 - Add json encode and decode smarty modifier via tools class
+ [-] Bo : AdminImport customer group default
+ [-] BO : Fix bug #PSCFV-10872 AdminImport could not import supllier orders
+ [-] BO: fix the checkbox of shop activation on modules configuration
+ [-] BO : Adminimport default customers group
+ [-] BO : tagify call twice if field is not translatable
+ [-] BO : Stats are empty when no conversion rate
+ [-] BO : Order-follow displayed order id instead of order reference
+ [-] BO : hide stmp options when selecting never send emails
+ [-] BO : FixBug #PSCFV-10866 - Tagify system not working
+ [-] BO : FixBug #PSCFV-9319 - display only valid order id
+ [-] BO : Do not delete other default jpg when _deleteOldImages and type defined
+ [-] BO : AdminImport, fix bug from https://github.com/indesign47/PrestaShop/commit/84454bbc1c7a315e232245c5e43b300b8f153473#commitcomment-4418502
+ [-] BO : Fix bug #10689, could not set image legend in back office
+ [-] BO : Fixed bug PSCFV-9910 using basic queries to prevent locking errors
+ [-] BO : Fix bug #PSCFV-10718 AdminAttachments old file not deleted on update
+ [-] BO : FixBug #PSCFV-10600 - Unmatched Boundary with mod_security
+ [-] BO : fix #PSCFV-10728, prices incorrectly formatted when creating new order from BO
+ [-] BO : FIx bug #PSCFV-10736 again, fixing query when product is not in base
+ [-] BO : FIx bug #PSCFV-10736, could not load a product given from getBoughtProducts
+ [-] BO : Fix bug #PSCFV-10790, Customer group names not exploded
+ [-] BO: product listing should call Product::getPriceStatic() with the product default shop in the context when it is not a shop context
+ [-] BO: Synchronize stock available after receipt supply order items #PSCFV-10724
+ [-] BO : Fix bug #PSCFV-10638, Admin Import by reference moves products to home category
+ [-] BO : Fix bug #PSCFV-7907 AdminImport, add custom field to features
+ [-] BO : Fix bug #PSCFV-10767, could not retrieve feature value when product IDs not forced
+ [-] BO : Fix bug #PSCFV-10607 one upload name
+ [-] BO : wrong csv files name
+ [-] BO : Report of https://github.com/PrestaShop/PrestaShop/commit/fd86a29c5c369ec5da0f91bbe97c584a00d02d0d
+ [-] BO: Default country should be overriden in the context in multishop
+ [-] BO : Fix bug #PSCFV-10709 rename root category with slashes in it
+ [-] BO : Could not order by reserved words like 'key'
+ [-] BO : AdminImport, wrong default separators
+ [-] BO : Fix bug #PSCFV-10692, AdminImport bad utf8 cars for subst
+ [-] BO : Fix #PSCFV-10678 warning in chrome
+ [-] BO : FixBug #PSCFV-10671 - remove htmlentities on customer message
+ [-] BO : Could not insert referrer id_connections_source can not be null
+ [-] Bo : Could not update mailalert 2.5 with id_lang missing
+ [-] Bo : Could not update mailarler 2.5 with id_mlang
+ [-] BO: Fixbug #PSCFV-10671 - Double htmlentities.
+ [-] BO : AdminImport, fix Group searchByName
+ [-] BO : Adminimport, id_specific key_price not defined
+ [-] BO : FixBug - Remove second email in recipient
+ [-] BO : Fix bug #PSCFV-10660, could not delete csv file on NT
+ [-] BO : FixBug #PSCFV-9957 - Duplicate order invoice number
+ [-] BO : fixed bug #PSCFV-10637 PS_CARRIER_DEFAULT is not updated after edit default carrier
+ [-] BO : AdminImport no default value for separators
+ [-] BO : pass correct typed parameter to setCurrency
+
+ [-] Classes : Hook - Installer & context shop id
+ [-] Classes : Modules listing and case insensitive
+
+ [-] Core: Group::getCurrent() return the default customer group of the shop if default customer group is not associated to shop
+ [-] CORE : invalid method name in displayAjax method of Controller action
+ [-] CORE : Fix bug #PSCFV-10901 warnings on htmlentities
+ [-] CORE : Currency conversion rate can not be 0
+ [-] CORE : SetEnv in if statement
+ [-] CORE : SetEnv not available on all config // @todo curl request on dummy .htacces
+ [-] CORE : Fix bug #PSCFV-10687 again, #PSCFV-10752 replaceAccentedChars() // sorry for that
+ [-] CORE : error_get_last > PHP 5.1
+ [-] Core: Out of stock status should be setted after the first order history
+ [-] Core: Product::getPriceStatic called with 1 quantity return the specific price for 1 qty if called with id_cart = 0
+ [-] CORE : Fix bug #PSCFV-10687 bad conversion for accentuated Y and W, thanks @mike15
+ [-] CORE : $smarty->compile_check is not set to false, thanks @prestamodule
+
+ [-] MO : Referralprogram Prevent Exception when badly configured
+ [-] MO : Missinag closing href
+ [-] MO :Fixed #PNM-1654 (Loyalty module) by using most expensive attribute instead of default one
+ [-] MO : Mailalert was not using order reference
+ [-] MO : Blocklayered follow up https://github.com/PrestaShop/PrestaShop/commit/a6e67b078e067445eef358e907649e843a1dc26a#commitcomment-4538556
+ [-] MO : Fixed #PNM-1600 by modifying getPageLink()
+ [-] MO : Blockcategories last_visited_category must not be cached
+ [-] MO : Could not translate in transit mail, revert from https://github.com/viger-creator/PrestaShop/commit/3213b5dffb266ddb0639b94f72babd892328ffa2
+ [-] MO : mailalert - Fix deprecated warning on displayDate
+ [-] MO : Blockwishlist no product image when id_product_attribute is defined, thanks @Broceliande
+ [-] MO : Fix NetworkError 404 Not Found on admin in blocklayered.php These files not exists : - /js/jquery/jquery-ui-1.8.10.custom.min.js - /css/jquery-ui-1.8.10.custom.css
+ [-] MO : Fix bug #PSCFV-10841, blockcart hides on product page when last product is removed from cart
+ [-] MO : Fixbug #PSCFV-10679 dateofdelivery PDF invoice array and array
+ [-] MO : Fixed bug PNM-1431 - referralprogram Lack the % sign
+ [-] MO : Fix bug #PSCFV-10787, cms associated to all shops
+ [-] MO : if customer is logged we do not recreate it
+ [-] MO : Fix bug #PSCFV-10775, could not upload .jpeg in TinyMCE
+ [-] MO : ScrollTo not loaded
+ [-] MO : Trackingfront, could not load employee stats date
+
+ [-] WS: Fix bug #PSCFV-10970 use configuration for uploaded images quality
+ [-] WS: Fix stockavailables list when stock is shared between shops #PSCFV-10793
+ [-] WS: Fix #PSCFV-10672 order by ID for non multishop entities
+
+ Improved/changed features:
+
+ [*] FO : DNI can be not required
+ [*] FO : Fix #PSCFV-8715 add product.attributes in carrier tpl
+ [*] FO : set at least a class to body
+ [*] FO : addTextFieldToProduct without Line feed, follow up https://github.com/PrestaShop/PrestaShop/pull/962#issuecomment-28294571
+ [*] FO : https on TOS in fancybox, follow up https://github.com/PrestaShop/PrestaShop/pull/956
+ [*] FO : Redirect to address.tpl when !Address::isCountryActiveById
+ [*] FO : Cache on getDiscountsCustomer, follow up https://github.com/PrestaShop/PrestaShop/pull/960
+ [*] FO : Set cache for StockAvailable::getQuantityAvailableByProduct
+ [*] FO : Added posibilty to display new price instead of quantity discount
+ [*] FO: Follow up https://github.com/PrestaShop/PrestaShop/commit/e86c56172dad2892d5c7e7dbb0908b0f4ffbaae0
+ [*] FO: Can not establish purchase total when tax incl.
+ [*] FO : Fix bug #PSCFV-10689 handle image legend
+ [*] FO: Removed missplaced on mobile theme
+
+ [*] BO : AdminPerformances Hide warnings message when not necessary
+ [*] BO : add class on TD in standard List Back office : Add a class on TD in list created by getList() In fields_list array of AdminController, we can add a new parameter('class') example : 'name' => array( 'title' => $this->l('Name'), 'width' => 150, 'class' => 'ma_classe', 'filter_key' => 'b!name' ), This parameter can be used for javascript effect, ... Thanks.
+ [*] BO : New import csv files
+ [*] BO : Manual merge of https://github.com/PrestaShop/PrestaShop/pull/891 1/2
+ [*] BO : AdminProducts find smallest images
+ [*] BO : improved unicode characters replacement in URLs (Russian and Ukrainian characters added)
+ [*] BO : AdminImport add img manufacturers-suppliers
+ [*] BO : AdminImport add img suppliers
+ [*] BO : AdminImport add img manufacturers
+ [*] BO : chmod 664 to config.xml file
+ [*] BO : Adding a title tag to display the module name on hover like PS 1.4
+
+ [*] CORE : Remove duplicate SQL queries
+ [*] CORE : Profiling hide non doubles
+ [*] CORE : Cache store for isAssociatedToShop::isAssociatedToShop
+ [*] CORE : Manual merge of https://github.com/PrestaShop/PrestaShop/ thanks @kpodemski
+ [*] CORE: Add phone_mobile to address format I honestly do not know why you decided by default to show only the first field of the phone :) Users often ask me why they don't see their mobile phone on orders in BO.
+
+ [*] MO : Remove calls to isRegisteredInHook in crossselling and productscategory
+ [*] MO : New modules version since 1.5.6.0
+ [*] MO: blocksharefb optimization
+ [*] MO: productcomments optimization
+
+ [*] LO : Fix PSCFV-10876: use IETF code to set language of shop, not 'iso' code, allows to distinguish between chinese variants etc.
+ [*] LO : Added states to Spanish localization pack
+ [*] LO : Fixed a few bugs with currency formats in Back-Office orders
+ [*] LO : set correct currency format for CHF
+
+ Added Features:
+
+ [+] BO : Add debug mode system
+ [+] BO : AdminImport add entity Alias
+
+ [+] CORE : Fixed cache_id
+
+ [+] MO : Blockcart - Add error handler on ajax function
+
+ Deprecated methods:
+
+ [~] BO : Export DeliverySlip The dates range wasn't using the correct sql fields.
+
+
####################################
# v1.5.6.0 - (2013-10-07) #
####################################
diff --git a/docs/csv_import/addresses_import.csv b/docs/csv_import/addresses_import.csv
index 60f603f4a..ff241ada0 100644
--- a/docs/csv_import/addresses_import.csv
+++ b/docs/csv_import/addresses_import.csv
@@ -1,4 +1,17 @@
-"id";"Alias*";"Active (0/1)";"Customer e-mail*";"Customer ID";"Manufacturer";"Supplier";"Company";"Lastname*";"Firstname*";"Address 1*";"Address 2";"Postcode* / Zipcode*";"City*";"Country*";"State";"Other";"Phone";"Mobile Phone";"VAT number"
-1;"My Adress";1;"pub@prestashop.com";1;;;;"Doe";"John";"16, Main street";"2nd floor";75000;"PARIS ";"France";;;140138844;;
-2;"My work";1;"pub@prestashop.com";1;;;"My Company";"Doe";"John";"535, Baker street";;13000;"Marseile";"France";;;235445588;;
-3;"My work";0;;;"Apple Computer, Inc";;;"Jobs";"Steve";"1 Infinite Loop";;95014;"CUPERTINO";"United States";"California";;"(800) 275-2273";;
+id;Alias*;Active (0/1);Customer e-mail*;Customer ID;Manufacturer;Supplier;Company;Lastname*;Firstname*;Address 1*;Address 2;Zipcode*;City*;Country*;State;Other;Phone;Mobile Phone;VAT number
+1;Peter.Pan / New York;1;Peter.Pan@prestashop.com;;;;;Pan;Peter;360W, 42nd Street;;12001;New York;United States;New York;;01 02 03 04 05;06 02 03 04 05;
+2;Wendy.Moira.Darling / New York;1;Wendy.Moira.Darling@prestashop.com;;;;;Darling;Wendy Moira;360W, 42nd Street;;12001;New York;United States;New York;;01 02 03 04 05;06 02 03 04 05;
+3;Wendy.Moira.Darling / London;1;Wendy.Moira.Darling@prestashop.com;;;;;Darling;Wendy Moira;Lansdowne road 50 London;Kensington;W11;London;United Kingdom;;;01 02 03 04 05;06 02 03 04 05;
+4;Tiger.Lily / Arizona;1;Tiger.Lily@prestashop.com;;;;;Lily;Tiger;Brackin Ranch Road;;86001;Flagstaff;United States;Arizona;;01 02 03 04 05;06 02 03 04 05;
+5;Tiger.Lily / Le Chesnay;1;Tiger.Lily@prestashop.com;;;;;Lily;Tiger;53 passage des pas sages;;78150;Le Chesnay;France;;;01 02 03 04 05;06 02 03 04 05;
+6;James.Hook / Home;1;James.Hook@prestashop.com;;;;;Hook;James;Mass Gravesite;P.O. Box 007;2101;Cayman Brac;Cayman Islands;;;01 02 03 04 05;06 02 03 04 05;
+7;James Hook / Pro;1;James.Hook@prestashop.com;;;;Räuber Schätze GmBH;Hook;James;12 Leipziger Platz;;13505;Berlin;Germany;;;01 02 03 04 05;06 02 03 04 05;
+8;Tinker.Bell / Napaiiri;1;Tinker.Bell@prestashop.com;;;;Santa Clauss Inc.;Bell;Tinker;Tähtikuja 1;;96930;Napapiiri;Finland;;;01 02 03 04 05;06 02 03 04 05;
+9;Smee / Fiji;1;Bob.Smee@prestashop.com;;;;;Smee;Bob;Cross Island rd 321;Vanua Levu;;Savusavu;Fiji;;;01 02 03 04 05;06 02 03 04 05;
+10;Smee / Portland;1;Bob.Smee@prestashop.com;;;;Lattice Semiconductor;Smee;Bob;5555 NE Moore Ct;;97124;Hillsboro;United States;Oregon;;01 02 03 04 05;06 02 03 04 05;
+11;Tictac Crocodile / Home;1;Tictac.Crocodile@prestashop.com;;;;;Crocodile;Tictac;Old State Rd 4A;Saddlebunch keys;33040;Bay Point;United States;Florida;Beware the Shark :);01 02 03 04 05;06 02 03 04 05;
+12;Apple / address1;1;;;Apple;;;Doe;John;1–6 Infinite Loop;;95014;Cupertino;United States;California;;01 02 03 04 05;06 02 03 04 05;
+13;Shure / address1;1;;;Shure;;;Non-Doe;John;5800W Touhy Avenue;;60714;Niles;United States;Illinois;;01 02 03 04 05;06 02 03 04 05;
+14;Shure / address2;1;;;Shure;;;Schuss-mayer;Kurt;Jakob-Dieffenbacher-Str. 12;;75031;Eppingen;Germany;;;01 02 03 04 05;06 02 03 04 05;
+15;UPS / address1;1;;;;U.P.S;;Austin;Steve;55NE Glenlake Parkway;;30328;Atlanta;United States;Georgia;;01 02 03 04 05;06 02 03 04 05;
+16;FedEX / address1;1;;;;FedEX;;Noland;Chuck;3640 Hacks Cross Rd;;32125;Memphis;United States;Tennessee;;01 02 03 04 05;06 02 03 04 05;
diff --git a/docs/csv_import/alias_import.csv b/docs/csv_import/alias_import.csv
index b64a435be..77007ea6a 100644
--- a/docs/csv_import/alias_import.csv
+++ b/docs/csv_import/alias_import.csv
@@ -1,3 +1,5 @@
-id;Alias *;Search *;Active (0/1)
-3;microsft,micro;microsoft;1
-4;adbe,adaub;adobe;1
+id;Alias *;Search *;Active (0/1)
+1;ano, anno, nona;nano;1
+2;ipdo, idop, podi;ipod;1
+3;McBook, Mbcook;MacBook;1
+4;Blekin;Belkin;1
diff --git a/docs/csv_import/categories_import.csv b/docs/csv_import/categories_import.csv
index 300974a3e..96024f6e5 100644
--- a/docs/csv_import/categories_import.csv
+++ b/docs/csv_import/categories_import.csv
@@ -1,4 +1,4 @@
-id;Active (0/1);Name*;Parent Category;Root category (0/1);Description;Meta-title;Meta-keywords;Meta-description;URL rewritten;Image URL;ID ou nom de la boutique
-10;1;iPods;Home;0;Now that you can buy movies from the iTunes Store and sync them to your iPod, the whole world is your theater.;;;;music-ipods;http://yourlinktotheimage.com/img1000.jpg;1
-11;1;Accessories;Home;0;Wonderful accessories for your iPod;;;;accessories-ipod;http://yourlinktotheimage.com/img1001.jpg;1
-12;1;Laptops;Home;0;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.;Apple laptops;Apple laptops MacBook Air;Powerful and chic Apple laptops;laptops;http://yourlinktotheimage.com/img1002.jpg;1
\ No newline at end of file
+ID;Active (0/1);Name *;Parent category;Root category (0/1) ;Description;Meta title;Meta keywords;Meta description;URL rewritten;Image URL
+10;1;iPods;Home;0;Now that you can buy movies from the iTunes Store and sync them to your iPod, the whole world is your theater.;Meta title-iPods;Meta keywords-iPods;Meta description-iPods;music-ipods;http://yourlinktotheimage.com/img1000.jpg
+11;1;Accessories;Home;0;Wonderful accessories for your iPod;Meta title-Accessories;Meta keywords-Accessories;Meta description-Accessories;accessories-ipod;http://yourlinktotheimage.com/img1001.jpg
+12;1;Laptops;Home;0;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.;Meta title-Laptops;Meta keywords-Laptops;Meta description-Laptops;laptops;http://yourlinktotheimage.com/img1002.jpg
diff --git a/docs/csv_import/combinations_import.csv b/docs/csv_import/combinations_import.csv
index aa0b6853a..e8373297b 100644
--- a/docs/csv_import/combinations_import.csv
+++ b/docs/csv_import/combinations_import.csv
@@ -1,4 +1,28 @@
-Id_product*;Group*;Attribute*;Supplier_reference;Reference;Ean13;Upc;Wholesale price;Impact on price;Ecotax;Quantity;Minimal quantity;Impact on weight;Default (0 = No, 1 = Yes);Image position;Image URL;Delete existing images (0 = No, 1 = Yes);ID / Name of shop
-1;Capacity:select:0, Color:color:1;16Go:0, Bleu:1;Ref suppplier 1;Ref 1;1234567891234;123456789123;0;None;0.000000;10;1;None;0;1;http://youdomain.com/img.jpg;0;1
-1;Capacity:select:0, Color:color:1;16Go:0, Red:1;Ref suppplier 2;Ref 2;1234567891235;123456789124;0;None;0.000000;10;1;None;0;2;http://youdomain.com/img.jpg;0;1
-
+Product ID*;Attribute (Name:Type:Position)*;Value (Value:Position)*;Supplier reference;Reference;EAN13;UPC;Wholesale price;Impact on price;Ecotax;Quantity;Minimal quantity;Impact on weight;Default (0 = No, 1 = Yes);Image position;Image URL;Delete existing images (0 = No, 1 = Yes);ID / Name of shop
+1;Color:color:0, Disk space:select:1;Blue:0, 16GB:1;RF-Nano-Blue-16GB;RP-Nano-Blue-16GB;0000080446392;;100;40;;10;1;0;0;1;http://youdomain.com/img.jpg;1;
+1;Color:color:0, Disk space:select:1;Blue:0, 8GB:1;RF-Nano-Blue-8GB;RP-Nano-Blue-8GB;0000080446393;;80;0;;10;1;0;0;2;http://youdomain.com/img.jpg;1;
+1;Color:color:0, Disk space:select:1;Yellow:0, 16GB:1;RF-Nano-Yellow-16GB;RP-Nano-Yellow-16GB;0000080446394;;100;40;;10;1;0;0;3;http://youdomain.com/img.jpg;1;
+1;Color:color:0, Disk space:select:1;Yellow:0, 8GB:1;RF-Nano-Yellow-8GB;RP-Nano-Yellow-8GB;0000080446395;;80;0;;10;1;0;1;4;http://youdomain.com/img.jpg;1;
+1;Color:color:0, Disk space:select:1;Metal:0, 16GB:1;RF-Nano-Metal-16GB;RP-Nano-Metal-16GB;0000080446396;;100;40;;10;1;0;0;5;http://youdomain.com/img.jpg;1;
+1;Color:color:0, Disk space:select:1;Metal:0, 8GB:1;RF-Nano-Metal-8GB;RP-Nano-Metal-8GB;0000080446397;;80;0;;10;1;0;0;6;http://youdomain.com/img.jpg;1;
+1;Color:color:0, Disk space:select:1;Black:0, 16GB:1;RF-Nano-Black-16GB;RP-Nano-Black-16GB;0000080446398;;100;40;;10;1;0;0;7;http://youdomain.com/img.jpg;1;
+1;Color:color:0, Disk space:select:1;Black:0, 8GB:1;RF-Nano-Black-8GB;RP-Nano-Black-8GB;0000080446399;;80;0;;10;1;0;0;8;http://youdomain.com/img.jpg;1;
+1;Color:color:0, Disk space:select:1;Orange:0, 16GB:1;RF-Nano-Orange-16GB;RP-Nano-Orange-16GB;0000080446400;;100;40;;10;1;0;0;9;http://youdomain.com/img.jpg;1;
+1;Color:color:0, Disk space:select:1;Orange:0, 8GB:1;RF-Nano-Orange-8GB;RP-Nano-Orange-8GB;0000080446401;;80;0;;10;1;0;0;10;http://youdomain.com/img.jpg;1;
+1;Color:color:0, Disk space:select:1;Pink:0, 16GB:1;RF-Nano-Pink-16GB;RP-Nano-Pink-16GB;0000080446402;;100;40;;10;1;0;0;11;http://youdomain.com/img.jpg;1;
+1;Color:color:0, Disk space:select:1;Pink:0, 8GB:1;RF-Nano-Pink-8GB;RP-Nano-Pink-8GB;0000080446403;;80;0;;10;1;0;0;12;http://youdomain.com/img.jpg;1;
+1;Color:color:0, Disk space:select:1;Green:0, 16GB:1;RF-Nano-Green-16GB;RP-Nano-Green-16GB;0000080446404;;100;40;;10;1;0;0;13;http://youdomain.com/img.jpg;1;
+1;Color:color:0, Disk space:select:1;Green:0, 8GB:1;RF-Nano-Green-8GB;RP-Nano-Green-8GB;0000080446405;;80;0;;10;1;0;0;14;http://youdomain.com/img.jpg;1;
+1;Color:color:0, Disk space:select:1;Purple:0, 16GB:1;RF-Nano-Purple-16GB;RP-Nano-Purple-16GB;0000080446406;;100;40;;10;1;0;0;15;http://youdomain.com/img.jpg;1;
+1;Color:color:0, Disk space:select:1;Purple:0, 8GB:1;RF-Nano-Purple-8GB;RP-Nano-Purple-8GB;0000080446407;;80;0;;10;1;0;0;16;http://youdomain.com/img.jpg;1;
+2;Color:color:0;Metal:0;RF-Shuffle-Metal;RP-Shuffle-Metal;0685387080038;;40;0;;12;1;0;1;1;http://youdomain.com/img.jpg;1;
+2;Color:color:0;Blue:0;RF-Shuffle-Blue;RP-Shuffle-Blue;0685387080039;;40;0;;12;1;0;0;2;http://youdomain.com/img.jpg;1;
+2;Color:color:0;Pink:0;RF-Shuffle-Pink;RP-Shuffle-Pink;0685387080040;;40;0;;12;1;0;0;3;http://youdomain.com/img.jpg;1;
+2;Color:color:0;Green:0;RF-Shuffle-Green;RP-Shuffle-Green;0685387080041;;40;0;;12;1;0;0;4;http://youdomain.com/img.jpg;1;
+3;Color:color:0, Disk space:select:1, ICU:select:2;Metal:0, 80GB Parallel ATA Drive @ 4200 rpm:1, 1.60GHz Intel Core 2 Duo:2;RF-MacBookAir80GB-1.6MHz;RP-MacBookAir80GB-1.6MHz;0123456791230;;0;750;;10;1;0;0;1;http://youdomain.com/img.jpg;1;
+3;Color:color:0, Disk space:select:1, ICU:select:2;Metal:0, 80GB Parallel ATA Drive @ 4200 rpm:1, 1.80GHz Intel Core 2 Duo:2;RF-MacBookAir80GB-1.6MHz;RP-MacBookAir80GB-1.6MHz;0123456791230;;0;0;;10;1;0;1;2;http://youdomain.com/img.jpg;1;
+3;Color:color:0, Disk space:select:1, ICU:select:2;Metal:0, Optional 64GB solid-state drive:1, 1.60GHz Intel Core 2 Duo:2;RF-MacBookAir64GB-1.8MHz;RP-MacBookAir64GB-1.8MHz;0123456791230;;0;225;;10;1;0;0;3;http://youdomain.com/img.jpg;1;
+3;Color:color:0, Disk space:select:1, ICU:select:2;Metal:0, Optional 64GB solid-state drive:1, 1.60GHz Intel Core 2 Duo:2;RF-MacBookAir64GB-1.8MHz;RP-MacBookAir64GB-1.8MHz;0123456791230;;0;975;;10;1;0;0;4;http://youdomain.com/img.jpg;1;
+5;Disk space:select:1;8GB:0;RF-IpodTouch8GB;RP-IpodTouch8GB;8456123645123;;200;0;;10;1;0;1;1;http://youdomain.com/img.jpg;1;
+5;Disk space:select:1;16GB:0;RF-IpodTouch16GB;RP-IpodTouch16GB;8456123645124;;250;75;;10;1;0;0;2;http://youdomain.com/img.jpg;1;
+5;Disk space:select:1;32GB:0;RF-IpodTouch32GB;RP-IpodTouch32GB;8456123645125;;300;150;;10;1;0;0;3;http://youdomain.com/img.jpg;1;
diff --git a/docs/csv_import/customers_import.csv b/docs/csv_import/customers_import.csv
index 8f839bc8e..362fe9560 100644
--- a/docs/csv_import/customers_import.csv
+++ b/docs/csv_import/customers_import.csv
@@ -1,3 +1,10 @@
-id;Active (0/1);Gender ID (Mr=1, Ms=2, else 9);E-mail*;Password*;Birthday;Lastname*;Firstname*;Newletter (0/1);Opt-in (0/1);Groups (x,y,z...);Default group ID;ID / Name of shop
-1;1;1;johndoe@prestashop.com;#res152EDRF;1987-09-21;Doe;John;1;1;1,2;1;1
-2;1;2;mariedoe@prestashop.com;58@ret26#;1986-10-14;Doe;Marie;0;1;1,3;3;1
\ No newline at end of file
+ID;Active (0/1);Titles ID (Mr = 1, Ms = 2, else 0);Email *;Password *;Birthday (yyyy-mm-dd);Last Name *;First Name *;Newsletter (0/1);Opt-in (0/1);Groups (x,y,z...);Default group ID
+1;1;1;Peter.Pan@prestashop.com;123456789;1987-04-02;Pan;Peter;1;0;Customer;Customer
+2;1;2;Wendy.Moira.Darling@prestashop.com;123456789;1989-11-12;Darling;Wendy Moira;1;0;Customer;Customer
+3;1;2;Tiger.Lily@prestashop.com;123456789;1982-02-28;Lily;Tiger;1;0;Customer;Customer
+4;1;1;James.Hook@prestashop.com;123456789;1952-12-04;Hook;James;0;1;Customer, Carribean;Carribean
+5;1;2;Tinker.Bell@prestashop.com;123456789;1900-01-01;Bell;Tinker;1;1;Customer;Customer
+6;1;1;Bob.Smee@prestashop.com;123456789;1971-10-21;Smee;Bob;1;1;Customer;Customer
+7;1;1;Tictac.Crocodile@prestashop.com;123456789;1991-09-27;Crocodile;Tictac;0;0;Customer, Carribean;Carribean
+8;1;1;Jack.Banning@prestashop.com;123456789;2003-07-05;Banning;Jack;0;0;Kids;Kids
+9;0;2;Maggie.Banning@prestashop.com;123456789;2006-02-27;Banning;Maggie;0;0;Kids;Kids
diff --git a/docs/csv_import/manufacturers_import.csv b/docs/csv_import/manufacturers_import.csv
index 2e4ef5d24..4749d81b3 100644
--- a/docs/csv_import/manufacturers_import.csv
+++ b/docs/csv_import/manufacturers_import.csv
@@ -1,3 +1,63 @@
-id;Active (0/1);Name*;Description;Short description;Meta-title;Meta-keywords;Meta-description;Image URL
-1;1;Apple Computer, Inc;;;;;http://youdomain.com/img.jpg
-2;1;Shure Incorporated;;;;;http://youdomain.com/img.jpg
+ID;Active (0/1);Name *;Description;Short description;Meta title;Meta keywords;Meta description
+1;1;Apple;"
The company was founded on April 1, 1976, and incorporated as Apple Computer, Inc. on January 3, 1977.The word ""Computer"" was removed from its name on January 9, 2007, the same day Steve Jobs introduced the iPhone, reflecting its shifted focus towards consumer electronics.
Apple is the world's second-largest information technology company by revenue after Samsung Electronics, and the world's third-largest mobile phone maker after Samsung and Nokia.Fortune magazine named Apple the most admired company in the United States in 2008, and in the world from 2008 to 2012. However, the company has received criticism for its contractors' labor practices, and for Apple's own environmental and business practices.
As of May 2013, Apple maintains 408 retail stores in fourteen countries as well as the online Apple Store and iTunes Store, the latter of which is the world's largest music retailer. Apple is the largest publicly traded corporation in the world by market capitalization, with an estimated value of US$415 billion as of March 2013. As of Sept 29 2012, the company had 72,800 permanent full-time employees and 3,300 temporary full-time employees worldwide. Its worldwide annual revenue in 2012 totalled $156 billion. In May 2013, Apple entered the top ten of the Fortune 500 list of companies for the first time, rising 11 places above its 2012 ranking to take the sixth position.
Apple Inc., formerly Apple Computer, Inc., is an American multinational corporation headquartered in Cupertino, California that designs, develops, and sells consumer electronics, computer software and personal computers.
Shure was founded by Sidney N. Shure in 1925 as ""The Shure Radio Company"", selling radio parts kits in the days before complete manufactured radios were available. The company's office was located at 19 South Wells Street in downtown Chicago, Illinois. The following year, Shure published its first direct mail catalog, which was one of only six radio parts catalogs in the United States at the time. By 1928, the company had grown to over 75 employees, and Sidney's brother, Samuel J. Shure, joined the company, which was renamed Shure Brothers Company. The company moved into new offices at 335 West Madison Street in Chicago. In 1929, with the advent of the Great Depression and the increased availability of factory-built radios, Shure Brothers Company was forced to greatly reduce their staff and became the exclusive US distributor of a small microphone manufacturer. In 1930, Samuel J. Shure left the company.
+
In 1931, Shure and engineer Ralph Glover began development of the first Shure microphone, and the following year, the Model 33N Two-Button Carbon Microphone was introduced, making Shure one of only four microphone manufacturers in the U.S.. Shure's first condenser microphone, crystal microphone, and microphone suspension support system (for which they received their first patent) were all introduced that same decade. In 1939, Shure introduced the Model 55 Unidyne Microphone, which went on to become one of the world's most recognized microphones.
+
In 1941, Shure was contracted by the United States armed forces to supply microphones during World War II, and by the following year, the T-17B was the microphone most widely used by the U.S. Army and Navy. Shure also manufactured throat, headset, and oxygen mask microphones, and adopted the United States Military Standard for all Shure microphones.
+
By the mid-1940s, Shure was also manufacturing and supplying phonograph cartridges to major phonograph manufacturers including Philco, RCA, Emerson, Magnavox, Admiral, and Motorola, and was the largest producer of phonograph cartridges in the U.S. at that time. Among Shure's innovations in phonograph cartridge design was Ralph Glover and Ben Bauer's ""needle-tilt"" principle for minimizing record wear while improving sound reproduction, and Jim Kogen's engineering concept of ""trackability."" Shure produced the first phonograph cartridge capable of playing both long-playing and 78 rpm records, the first cartridge with tracking force of only one gram, and the first cartridge meeting the requirements of stereo recording. At the peak of Shure's phonograph cartridge production, the company was producing approximately 28,000 cartridges per day, with 25,000 of those coming from a Shure phonograph cartridge plant in Phoenix, Arizona. After the introduction of compact discs in the 1980s reduced the demand for phonograph cartridges, Shure closed the Phoenix facility but continued manufacturing phonograph cartridges, and continues to manufacture them today.
+
Shure also developed and produced products for medical applications. In 1937, their 66A piezoelectric stethophone was designed to accurately reproduce chest sounds, and in the early 1960s, the SP-5, SP-5S and SP-6 stethoscope pickups were produced. Shure also produced hearing aid cartridges used in hearing aid products from manufacturers like Maico, Telex, Dictograph, Otarian, Vocalite, and Trimm.
+
In 1956, Shure moved its corporate headquarters to Hartrey Avenue in Evanston, Illinois, where it remained for 47 years. Beginning in the 1956, Shure manufactured magnetic tape recording heads and two years later, the company announced it was ready to mass-produce 4-ch recording heads. By 1964, however, Shure announced it would no longer produce tape recording heads due to increased competition.
+
In 1953, Shure introduced their first wireless microphone system for performers, and in 1959, they introduced the Unidyne III Microphone, which was the predecessor to the SM57, which would be introduced, along with the SM58, six years later. Shure also produced portable equipment for broadcast field recording like Vocal Master, the M67 Portable Mixer, and the FP31 Portable Mixer. In 1990, Shure entered the wireless microphone market with the L-Series.
+
In 1981, James Kogen, Executive Vice President, Operations, was promoted to President and General Manager of Shure. In 1995, Sidney N. Shure died at the age of 93, and Rose L. Shure was elected Chairman of the Board of Directors. In 1996, James Kogen retired; Santo (Sandy) LaMantia, Vice President of Engineering, was named President and CEO. Shure Brothers Incorporated was officially renamed Shure Incorporated in 1999.
+
In 2001, Shure acquired the Popper Stopper brand of studio pop filters from Middle Atlantic Products Inc. The following year, Shure adopted hearing conservation as the company’s corporate cause and established the Shure Bid for Hearing program. In 2003, Shure moved into new corporate headquarters in Niles, Illinois, into a building designed by architect Helmut Jahn which was originally the headquarters of HA•LO Industries. The 65,000-square-foot (6,000 m2) Technology Annex designed by Krueck and Sexton Architects, opened in 2005, houses Shure's Performance Listening Center. In 2008, Shure celebrated the opening of The S.N. Shure Theater and Interactive Display at their corporate headquarters.
+
International offices
+
+
1991: Shure Europe GmbH opened in Heilbronn, Germany to provide sales, service and support to Shure distribution centers in 34 European countries.
+
1999: Shure Asia Limited is opened in Hong Kong to serve Distribution Centers and distributors throughout Asia and the Pacific Rim.
+
2002: Shure Distribution GmbH established as a subsidiary of Shure Europe GmbH, to handle direct sales with Shure dealers in Germany.
+
2003: HW International, Shure's United Kingdom Distribution Center, acquired and renamed Shure Distribution UK.
+
2005: Sales and marketing office opened in Shanghai, China.
+
2006: Sales and marketing office opened in Tokyo, Japan.
+
2010: New subsidiary formed in the Netherlands
+
+
Production facility expansion
+
+
1982: Manufacturing facility opened in Wheeling, Illinois
+
1983: Phonograph cartridge manufacturing facility opened in Agua Prieta, Mexico
+
1984: Wired microphone manufacturing facility opened in Juarez, Mexico
+
1989: Juarez, Mexico facility expanded
+
1994: Agua Prieta facility expanded in 1994
+
2005: Manufacturing facility opened in Suzhou, China
Shure Incorporated is an American corporation originally founded by Sidney N. Shure in Chicago, Illinois in 1925 as a supplier of radio parts kits. The company became a consumer and professional audio-electronics manufacturer of microphones, wireless microphone systems, phonograph cartridges, discussion systems, mixers, and digital signal processing.
+
The company also produces listening products, including headphones, high-end earbuds and personal monitor systems.
Sony found its beginning in the wake of World War II. In 1946, Masaru Ibuka started an electronics shop in a bomb-damaged department store building in Tokyo. The company had $530 in capital and a total of eight employees. The next year, he was joined by his colleague, Akio Morita, and they founded a company called Tokyo Tsushin Kogyo (Tokyo Telecommunications Engineering Corporation). The company built Japan's first tape recorder, called the Type-G. In 1958 the company name was changed to Sony.
+
In the early 1950s, Ibuka traveled in the United States and heard about Bell Labs' invention of the...
Sony Corporation, commonly referred to as Sony, is a Japanese multinational conglomerate corporation headquartered in Konan Minato, Tokyo, Japan. Its diversified business is primarily focused on the electronics, game, entertainment and financial services sectors. The company is one of the leading manufacturers of electronic products for the consumer and professional markets. Sony is ranked 87th on the 2012 list of Fortune Global 500.
Samsung was founded by Lee Byung-chul in 1938 as a trading company. Over the next three decades the group diversified into areas including food processing, textiles, insurance, securities and retail. Samsung entered the electronics industry in the late 1960s and the construction and shipbuilding industries in the mid-1970s; these areas would drive its subsequent growth. Following Lee's death in 1987, Samsung was separated into four business groups – Samsung Group, Shinsegae Group, CJ Group and Hansol Group. Since the 1990s Samsung has increasingly globalized its activities, and electronics, particularly mobile phones and semiconductors, have become its most important source of income.
+
Notable Samsung industrial subsidiaries include Samsung Electronics (the world's largest information technology company measured by 2012 revenues, and 4th in market value), Samsung Heavy Industries (the world's 2nd-largest shipbuilder measured by 2010 revenues), and Samsung Engineering and Samsung C&T (respectively the world's 13th and 36th-largest construction companies). Other notable subsidiaries include Samsung Life Insurance (the world's 14th-largest life insurance company), Samsung Everland (operator of Everland Resort, the oldest theme park in South Korea), Samsung Techwin (an aerospace, surveillance and defense company) and Cheil Worldwide (the world's 16th-largest advertising agency measured by 2011 revenues).
+
Samsung has a powerful influence on South Korea's economic development, politics, media and culture, and has been a major driving force behind the ""Miracle on the Han River"". Its affiliate companies produce around a fifth of South Korea's total exports. Samsung's revenue was equal to 17% of the South Korea's $1,082 billion GDP.
+
In 2013, Samsung began construction on building the world's largest ...
Samsung Group is a South Korean multinational conglomerate company headquartered in Samsung Town, Seoul. It comprises numerous subsidiaries and affiliated businesses, most of them united under the Samsung brand, and is the largest South Korean chaebol (business conglomerate).
";MetaTitle-Samsung;MetaKeywords-Samsung;Meta description-Samsung
diff --git a/docs/csv_import/products_import.csv b/docs/csv_import/products_import.csv
index 2952a2f05..2757ec186 100644
--- a/docs/csv_import/products_import.csv
+++ b/docs/csv_import/products_import.csv
@@ -1,3 +1,8 @@
-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;Width;Height;Depth;Weight;Quantity;Minimum quantity;Visibility;Additional shipping cost;Unity;Unity price ratio;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 available date;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);Customizable;File fields;Text fields;Out of stock;Advanced stock management;ID / Name of shop
-1;1;iPod Nano;Home, iPods;49;1;40;0;;;;;92458844;54778855;AppleStore;Apple Computer, Inc;5605055055056;560505505555;0;1;2;3;0.5;800;1;both;0.00;;0.00;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;Meta title;Meta keywords;Meta description;ipod-nano;In stock;Out stock;1;;;1;http://youdomain.com/img.jpg, http://yourdomain.com/img1.jpg;0;Music:Rock:1;0;new;0;0;0;2;0;1
-2;1;iPod shuffle;Home, iPods;66.05;1;50;0;;;;;92458845;54778855;AppleStore;Apple Computer, Inc;5605055055057;560505505556;0;1;2;3;0.5;800;1;both;0.00;;0.00;iPod shuffle, the world’s most wearabl….;You want listen to music;ipod, shuffle;Meta title;Meta keywords;Meta description;ipod-shuffle;In stock;Out stock;1;;;1;http://youdomain.com/img25.jpg, http://yourdomain.com/img30.jpg;0;Music:Blues:2;0;new;0;0;0;2;0;1
+ID;Active (0/1);Name *;Categories (x,y,z...);Price tax excluded or Price tax included;Tax rules ID;Wholesale price;On sale (0/1);Discount amount;Discount percent;Discount from (yyyy-mm-dd);Discount to (yyyy-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 when backorder allowed;Available for order (0 = No, 1 = Yes);Product available date;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;Customizable (0 = No, 1 = Yes);Uploadable files (0 = No, 1 = Yes);Text fields (0 = No, 1 = Yes);Out_of_stock;Advanced stock management;ID / Name of shop
+1;1;iPod Nano;iPods;100;1;80;1;;5.5;2013-06-01;2018-12-31;RP-demo_1;RF-demo_1;Applestore;Apple;1234567890123;;1;0.6;0.2;0.4;0.068357;160;1;;;;;
The Apple Store is a chain of retail stores owned and operated by Apple Inc., dealing in computers and consumer electronics. The stores sell Macintosh personal computers, software, iPods, iPads, iPhones, third-party accessories, and other consumer electronics such as Apple TV. Some high profile stores feature a Theatre for presentations and workshops and a Studio for training with Apple products; all stores offer a Genius Bar for technical support and repairs, as well as free workshops available to the public. Under the leadership of Ron Johnson, the former Senior Vice President of Retail Operations, the Apple Stores have, according to an article in the New York Times, been responsible for "[turning] the boring computer sales floor into a sleek playroom filled with gadgets".
{if $tax_excluded_display}
{displayPrice currency=$order->id_currency price=$order_detail.total_price_tax_excl}
{else}
diff --git a/themes/default/address.tpl b/themes/default/address.tpl
new file mode 100644
index 000000000..177e83c3c
--- /dev/null
+++ b/themes/default/address.tpl
@@ -0,0 +1,252 @@
+{*
+* 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
+*}
+
+
+
+{capture name=path}{l s='Your addresses'}{/capture}
+{include file="$tpl_dir./breadcrumb.tpl"}
+
+
{l s='Your addresses'}
+
+
+{if isset($id_address) && (isset($smarty.post.alias) || isset($address->alias))}
+ {l s='Modify address'}
+ {if isset($smarty.post.alias)}
+ "{$smarty.post.alias}"
+ {else}
+ {if isset($address->alias)}"{$address->alias|escape:'html'}"{/if}
+ {/if}
+{else}
+ {l s='To add a new address, please fill out the form below.'}
+{/if}
+
+
+{include file="$tpl_dir./errors.tpl"}
+
+
* {l s='Required field'}
+
+
diff --git a/themes/default/authentication.tpl b/themes/default/authentication.tpl
new file mode 100644
index 000000000..545000879
--- /dev/null
+++ b/themes/default/authentication.tpl
@@ -0,0 +1,741 @@
+{*
+* 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
+*}
+
+{capture name=path}
+ {if !isset($email_create)}{l s='Authentication'}{else}
+ {l s='Authentication'}
+ {$navigationPipe}{l s='Create your account'}
+ {/if}
+{/capture}
+ {include file="$tpl_dir./breadcrumb.tpl"}
+
+
+
+
{if !isset($email_create)}{l s='Authentication'}{else}{l s='Create an account'}{/if}
+{if !isset($back) || $back != 'my-account'}{assign var='current_step' value='login'}{include file="$tpl_dir./order-steps.tpl"}{/if}
+{include file="$tpl_dir./errors.tpl"}
+{assign var='stateExist' value=false}
+{assign var="postCodeExist" value=false}
+{assign var="dniExist" value=false}
+{if !isset($email_create)}
+
+
+
+
+
+
+ {if isset($inOrderProcess) && $inOrderProcess && $PS_GUEST_CHECKOUT_ENABLED}
+
+ {/if}
+{else}
+
+
+{/if}
diff --git a/themes/default/category.tpl b/themes/default/category.tpl
new file mode 100644
index 000000000..415e79f64
--- /dev/null
+++ b/themes/default/category.tpl
@@ -0,0 +1,120 @@
+{*
+* 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
+*}
+
+{include file="$tpl_dir./breadcrumb.tpl"}
+{include file="$tpl_dir./errors.tpl"}
+
+{if isset($category)}
+ {if $category->id AND $category->active}
+
+ {/if}
+{/if}
diff --git a/themes/default/contact-form.tpl b/themes/default/contact-form.tpl
new file mode 100644
index 000000000..6fb91cf25
--- /dev/null
+++ b/themes/default/contact-form.tpl
@@ -0,0 +1,132 @@
+{*
+* 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
+*}
+
+{capture name=path}{l s='Contact'}{/capture}
+{include file="$tpl_dir./breadcrumb.tpl"}
+
+
+{* > TO CHECK ==========================*}
+{*$HOOK_ORDERDETAILDISPLAYED*}
+{* / TO CHECK ==========================*}
+{if $return_allowed}
{l s='If you wish to return one or more products, please mark the corresponding boxes and provide an explanation for the return. When complete, click the button below.'}
{l s='You cannot return merchandise with a guest account'}
+{/if}
+
diff --git a/themes/default/modules/blocksearch/blocksearch.tpl b/themes/default/modules/blocksearch/blocksearch.tpl
new file mode 100644
index 000000000..e4d2cc745
--- /dev/null
+++ b/themes/default/modules/blocksearch/blocksearch.tpl
@@ -0,0 +1,41 @@
+{*
+* 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='Search' mod='blocksearch'}
+
+
+{include file="$self/blocksearch-instantsearch.tpl"}
+
diff --git a/themes/default/modules/productcomments/productcomments.tpl b/themes/default/modules/productcomments/productcomments.tpl
new file mode 100644
index 000000000..6560f5c5a
--- /dev/null
+++ b/themes/default/modules/productcomments/productcomments.tpl
@@ -0,0 +1,160 @@
+{*
+* 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='No customer comments for the moment.' mod='productcomments'}
+ {/if}
+ {/if}
+
+
+{if isset($product) && $product}
+
+
+
+
+
+
+
+{/if}
\ No newline at end of file
diff --git a/themes/default/order-carrier.tpl b/themes/default/order-carrier.tpl
new file mode 100644
index 000000000..af59cfe69
--- /dev/null
+++ b/themes/default/order-carrier.tpl
@@ -0,0 +1,314 @@
+{*
+* 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
+*}
+{if !$opc}
+
+{else}
+
+{/if}
+
+{if isset($virtual_cart) && !$virtual_cart && $giftAllowed && $cart->gift == 1}
+
+{/if}
+
+{if !$opc}
+ {capture name=path}{l s='Shipping:'}{/capture}
+ {include file="$tpl_dir./breadcrumb.tpl"}
+{/if}
+
+{if !$opc}
+
diff --git a/themes/default/order-detail.tpl b/themes/default/order-detail.tpl
new file mode 100644
index 000000000..67c002556
--- /dev/null
+++ b/themes/default/order-detail.tpl
@@ -0,0 +1,427 @@
+{*
+* 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
+*}
+{if isset($order)}
+
+
+
{l s='You cannot return merchandise with a guest account'}
+{/if}
+{/if}
\ No newline at end of file
diff --git a/themes/default/order-opc-new-account.tpl b/themes/default/order-opc-new-account.tpl
new file mode 100644
index 000000000..7d452cb38
--- /dev/null
+++ b/themes/default/order-opc-new-account.tpl
@@ -0,0 +1,428 @@
+
+
+
1 {l s='Account'}
+
+
+
+
diff --git a/themes/default/product.tpl b/themes/default/product.tpl
new file mode 100644
index 000000000..9c3c0e6da
--- /dev/null
+++ b/themes/default/product.tpl
@@ -0,0 +1,647 @@
+{*
+* 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
+*}
+
+{include file="$tpl_dir./errors.tpl"}
+{if $errors|@count == 0}
+
+
+{include file="$tpl_dir./breadcrumb.tpl"}
+
+ {dateFormat date=$comment.date_add|escape:'html':'UTF-8' full=0} +
{$comment.title}
+{$comment.content|escape:'html':'UTF-8'|nl2br}
++ {if $comment.total_advice > 0} +- {l s='%1$d out of %2$d people found this review useful.' sprintf=[$comment.total_useful,$comment.total_advice] mod='productcomments'}
+ {/if}
+ {if $logged == 1}
+ {if !$comment.customer_advice}
+ - {l s='Was this comment useful to you?' mod='productcomments'}
+ {/if}
+ {if !$comment.customer_report}
+ - {l s='Report abuse' mod='productcomments'}
+ {/if}
+ {/if}
+
+