diff --git a/admin-dev/themes/default/template/controllers/products/informations.tpl b/admin-dev/themes/default/template/controllers/products/informations.tpl
index 8e56f4b88..93e92fc18 100644
--- a/admin-dev/themes/default/template/controllers/products/informations.tpl
+++ b/admin-dev/themes/default/template/controllers/products/informations.tpl
@@ -154,16 +154,57 @@
- {l s='Displayed text when allowed to be back-ordered:'}
-
+
+ {include file="controllers/products/multishop/checkbox.tpl" field="available_later" type="default" multilang="true"}
+ {l s='Displayed text when allowed to be back-ordered:'}
+
+
{include file="controllers/products/input_text_lang.tpl"
languages=$languages
input_value=$product->available_later
diff --git a/classes/Address.php b/classes/Address.php
index bd2daea0e..616b44dac 100644
--- a/classes/Address.php
+++ b/classes/Address.php
@@ -337,12 +337,6 @@ class AddressCore extends ObjectModel
*/
public static function initialize($id_address = null)
{
- // set the default address
- $address = new Address();
- $address->id_country = (int)Context::getContext()->country->id;
- $address->id_state = 0;
- $address->postcode = 0;
-
// if an id_address has been specified retrieve the address
if ($id_address)
{
@@ -351,6 +345,14 @@ class AddressCore extends ObjectModel
if (!Validate::isLoadedObject($address))
throw new PrestaShopException('Invalid address');
}
+ else
+ {
+ // set the default address
+ $address = new Address();
+ $address->id_country = (int)Context::getContext()->country->id;
+ $address->id_state = 0;
+ $address->postcode = 0;
+ }
return $address;
}
diff --git a/classes/Cart.php b/classes/Cart.php
index 11641a80f..c821ffe58 100644
--- a/classes/Cart.php
+++ b/classes/Cart.php
@@ -1509,9 +1509,8 @@ class CartCore extends ObjectModel
// If the cart rule offers a reduction, the amount is prorated (with the products in the package)
if ($cart_rule['obj']->reduction_percent > 0 || $cart_rule['obj']->reduction_amount > 0)
- {
$order_total_discount += Tools::ps_round($cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_REDUCTION, $package, $use_cache), 2);
- }
+
}
$order_total_discount = min(Tools::ps_round($order_total_discount, 2), $wrapping_fees + $order_total_products + $shipping_fees);
@@ -2600,7 +2599,10 @@ class CartCore extends ObjectModel
// Select carrier tax
if ($use_tax && !Tax::excludeTaxeOption())
- $carrier_tax = $carrier->getTaxesRate(new Address((int)$address_id));
+ {
+ $address = Address::initialize((int)$address_id);
+ $carrier_tax = $carrier->getTaxesRate($address);
+ }
$configuration = Configuration::getMultiple(array(
'PS_SHIPPING_FREE_PRICE',
diff --git a/classes/Hook.php b/classes/Hook.php
index eb5e76f21..54892a996 100644
--- a/classes/Hook.php
+++ b/classes/Hook.php
@@ -418,7 +418,7 @@ class HookCore extends ObjectModel
else if ($hook_retro_callable)
$display = $moduleInstance->{'hook'.$retro_hook_name}($hook_args);
// Live edit
- if ($array_return && $array['live_edit'] && Tools::isSubmit('live_edit') && Tools::getValue('ad') && Tools::getValue('liveToken') == Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee')))
+ if (!$array_return && $array['live_edit'] && Tools::isSubmit('live_edit') && Tools::getValue('ad') && Tools::getValue('liveToken') == Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee')))
{
$live_edit = true;
$output .= self::wrapLiveEdit($display, $moduleInstance, $array['id_hook']);
diff --git a/classes/Image.php b/classes/Image.php
index 0f56d1295..75c0a7f52 100644
--- a/classes/Image.php
+++ b/classes/Image.php
@@ -409,9 +409,8 @@ class ImageCore extends ObjectModel
// Delete auto-generated images
$image_types = ImageType::getImagesTypes();
foreach ($image_types as $image_type)
- {
$files_to_delete[] = $this->image_dir.$this->getExistingImgPath().'-'.$image_type['name'].'.'.$this->image_format;
- }
+
// Delete watermark image
$files_to_delete[] = $this->image_dir.$this->getExistingImgPath().'-watermark.'.$this->image_format;
// delete index.php
@@ -533,11 +532,11 @@ class ImageCore extends ObjectModel
if (!file_exists(_PS_PROD_IMG_DIR_.$this->getImgFolder()))
{
// Apparently sometimes mkdir cannot set the rights, and sometimes chmod can't. Trying both.
- $success = @mkdir(_PS_PROD_IMG_DIR_.$this->getImgFolder(), self::$access_rights, true)
- || @chmod(_PS_PROD_IMG_DIR_.$this->getImgFolder(), self::$access_rights);
+ $success = @mkdir(_PS_PROD_IMG_DIR_.$this->getImgFolder(), self::$access_rights, true);
+ $chmod = @chmod(_PS_PROD_IMG_DIR_.$this->getImgFolder(), self::$access_rights);
// Create an index.php file in the new folder
- if ($success
+ if (($success || $chmod)
&& !file_exists(_PS_PROD_IMG_DIR_.$this->getImgFolder().'index.php')
&& file_exists($this->source_index))
return @copy($this->source_index, _PS_PROD_IMG_DIR_.$this->getImgFolder().'index.php');
diff --git a/classes/PaymentModule.php b/classes/PaymentModule.php
index 95cefa218..86b505d69 100644
--- a/classes/PaymentModule.php
+++ b/classes/PaymentModule.php
@@ -186,7 +186,7 @@ abstract class PaymentModuleCore extends Module
foreach ($data['package_list'] as $id_package)
{
// Rewrite the id_warehouse
- $package_list[$id_address][$id_package]['id_warehouse'] = $this->context->cart->getPackageIdWarehouse($package_list[$id_address][$id_package], (int)$id_carrier);
+ $package_list[$id_address][$id_package]['id_warehouse'] = (int)$this->context->cart->getPackageIdWarehouse($package_list[$id_address][$id_package], (int)$id_carrier);
$package_list[$id_address][$id_package]['id_carrier'] = $id_carrier;
}
// Make sure CarRule caches are empty
diff --git a/classes/Product.php b/classes/Product.php
index 8af855564..88d789415 100644
--- a/classes/Product.php
+++ b/classes/Product.php
@@ -163,7 +163,13 @@ class ProductCore extends ObjectModel
/** @var boolean Product statuts */
public $active = true;
-
+
+ /** @var boolean Product statuts */
+ public $redirect_type = '';
+
+ /** @var boolean Product statuts */
+ public $id_product_redirected = 0;
+
/** @var boolean Product available for order */
public $available_for_order = true;
@@ -272,6 +278,8 @@ class ProductCore extends ObjectModel
'text_fields' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'),
'uploadable_files' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'),
'active' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'),
+ 'redirect_type' => array('type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isString'),
+ 'id_product_redirected' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedId'),
'available_for_order' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'),
'available_date' => array('type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDateFormat'),
'condition' => array('type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isGenericName', 'values' => array('new', 'used', 'refurbished'), 'default' => 'new'),
@@ -650,7 +658,26 @@ class ProductCore extends ObjectModel
return parent::validateFieldsLang($die, $error_return);
}
-
+
+ public function toggleStatus()
+ {
+ //test if the product is active and if redirect_type is empty string and set default value to id_product_redirected & redirect_type
+ // /!\ after parent::toggleStatus() active will be false, that why we set 404 by default :p
+ if ($this->active)
+ {
+ //case where active will be false after parent::toggleStatus()
+ $this->id_product_redirected = 0;
+ $this->redirect_type = '404';
+ }
+ else
+ {
+ //case where active will be true after parent::toggleStatus()
+ $this->id_product_redirected = 0;
+ $this->redirect_type = '';
+ }
+ return parent::toggleStatus();
+ }
+
public function delete()
{
/*
@@ -798,7 +825,7 @@ class ProductCore extends ObjectModel
SELECT c.`id_category`
FROM `'._DB_PREFIX_.'category_product` cp
LEFT JOIN `'._DB_PREFIX_.'category` c ON (c.`id_category` = cp.`id_category`)
- '.Shop::addSqlAssociation('category', 'c', true).'
+ '.Shop::addSqlAssociation('category', 'c', true, null, true).'
WHERE cp.`id_category` NOT IN ('.implode(',', array_map('intval', $categories)).')
AND cp.id_product = '.$this->id
);
diff --git a/classes/Validate.php b/classes/Validate.php
index 2aa05df0c..a3e564f1b 100644
--- a/classes/Validate.php
+++ b/classes/Validate.php
@@ -472,9 +472,9 @@ class ValidateCore
*/
public static function isDate($date)
{
- if (!preg_match('/^([0-9]{4})-((0?[0-9])|(1[0-2]))-((0?[0-9])|([1-2][0-9])|(3[01]))( [0-9]{2}:[0-9]{2}:[0-9]{2})?$/', $date, $matches))
+ if (!preg_match('/^([0-9]{4})-((?:0?[0-9])|(?:1[0-2]))-((?:0?[0-9])|(?:[1-2][0-9])|(?:3[01]))( [0-9]{2}:[0-9]{2}:[0-9]{2})?$/', $date, $matches))
return false;
- return checkdate((int)$matches[2], (int)$matches[5], (int)$matches[0]);
+ return checkdate((int)$matches[2], (int)$matches[3], (int)$matches[1]);
}
/**
@@ -487,9 +487,9 @@ class ValidateCore
{
if (empty($date) || $date == '0000-00-00')
return true;
- if (preg_match('/^([0-9]{4})-((0?[1-9])|(1[0-2]))-((0?[1-9])|([1-2][0-9])|(3[01]))( [0-9]{2}:[0-9]{2}:[0-9]{2})?$/', $date, $birth_date))
+ if (preg_match('/^([0-9]{4})-((?:0?[1-9])|(?:1[0-2]))-((?:0?[1-9])|(?:[1-2][0-9])|(?:3[01]))([0-9]{2}:[0-9]{2}:[0-9]{2})?$/', $date, $birth_date))
{
- if ($birth_date[1] > date('Y') || $birth_date[2] > date('m') || $birth_date[3] > date('d'))
+ if ($birth_date[1] > date('Y') && $birth_date[2] > date('m') && $birth_date[3] > date('d'))
return false;
return true;
}
diff --git a/classes/controller/FrontController.php b/classes/controller/FrontController.php
index bd1d3feab..61959314e 100755
--- a/classes/controller/FrontController.php
+++ b/classes/controller/FrontController.php
@@ -252,12 +252,6 @@ class FrontControllerCore extends Controller
CartRule::autoAddToCart($this->context);
}
- $locale = strtolower(Configuration::get('PS_LOCALE_LANGUAGE')).'_'.strtoupper(Configuration::get('PS_LOCALE_COUNTRY').'.UTF-8');
- setlocale(LC_COLLATE, $locale);
- setlocale(LC_CTYPE, $locale);
- setlocale(LC_TIME, $locale);
- setlocale(LC_NUMERIC, 'en_US.UTF-8');
-
/* get page name to display it in body id */
// Are we in a payment module
@@ -402,10 +396,8 @@ class FrontControllerCore extends Controller
if ($this->restrictedCountry)
$this->displayRestrictedCountryPage();
- //live edit
- if (Tools::isSubmit('live_edit') && ($ad = Tools::getValue('ad')) && Tools::getValue('liveToken') == Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee')))
- if (!is_dir(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$ad))
- die(Tools::displayError());
+ if (Tools::isSubmit('live_edit') && !$this->checkLiveEditAccess())
+ die(Tools::displayError());
$this->iso = $iso;
$this->setMedia();
@@ -413,7 +405,7 @@ class FrontControllerCore extends Controller
$this->context->cart = $cart;
$this->context->currency = $currency;
}
-
+
public function postProcess()
{
/*// For retrocompatibility with versions before 1.5, preProcess support will be removed on next release
@@ -549,23 +541,24 @@ class FrontControllerCore extends Controller
'display_header' => $this->display_header,
'display_footer' => $this->display_footer,
));
-
+
+ $live_edit_content = '';
// Don't use live edit if on mobile device
- if ($this->context->getMobileDevice() == false && Tools::isSubmit('live_edit'))
- $this->context->smarty->assign('live_edit', $this->getLiveEditFooter());
-
+ if (!$this->context->getMobileDevice() && $this->checkLiveEditAccess())
+ $live_edit_content = $this->getLiveEditFooter();
+
$layout = $this->getLayout();
if ($layout)
{
if ($this->template)
- $this->context->smarty->assign('template', $this->context->smarty->fetch($this->template));
+ $this->context->smarty->assign('template', $this->context->smarty->fetch($this->template).$live_edit_content);
else // For retrocompatibility with 1.4 controller
{
ob_start();
$this->displayContent();
$template = ob_get_contents();
ob_clean();
- $this->context->smarty->assign('template', $template);
+ $this->context->smarty->assign('template', $template.$live_edit_content);
}
$this->smartyOutputContent($layout);
}
@@ -583,16 +576,9 @@ class FrontControllerCore extends Controller
if ($this->display_footer)
$this->smartyOutputContent(_PS_THEME_DIR_.'footer.tpl');
-
- // live edit
- if (Tools::isSubmit('live_edit') && ($ad = Tools::getValue('ad')) && Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee')))
- {
- $this->context->smarty->assign(array('ad' => $ad, 'live_edit' => true));
- $this->smartyOutputContent(_PS_ALL_THEMES_DIR_.'live_edit.tpl');
- }
// END - 1.4 retrocompatibility - will be removed in 1.6
}
-
+
return true;
}
@@ -799,16 +785,21 @@ class FrontControllerCore extends Controller
));
}
-
+
+ public function checkLiveEditAccess()
+ {
+ $live_token = Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee'));
+ $ad = Tools::getValue('ad');
+ return Tools::isSubmit('live_edit') && $ad && Tools::getValue('liveToken') == $live_token && is_dir(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$ad);
+ }
+
public function getLiveEditFooter()
{
- if (Tools::isSubmit('live_edit')
- && ($ad = Tools::getValue('ad'))
- && Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee')))
+ if ($this->checkLiveEditAccess())
{
$data = $this->context->smarty->createData();
$data->assign(array(
- 'ad' => $ad,
+ 'ad' => Tools::getValue('ad'),
'live_edit' => true,
'hook_list' => Hook::$executed_hooks,
'id_shop' => $this->context->shop->id
@@ -1144,12 +1135,12 @@ class FrontControllerCore extends Controller
* @return array
*/
public function initLogoAndFavicon()
- {
- return array(
- 'favicon_url' => _PS_IMG_.Configuration::get('PS_FAVICON'),
+ {
+ return array(
+ 'favicon_url' => _PS_IMG_.Configuration::get('PS_FAVICON'),
'logo_image_width' => ($this->context->getMobileDevice() == false ? Configuration::get('SHOP_LOGO_WIDTH') : Configuration::get('SHOP_LOGO_MOBILE_WIDTH')),
'logo_image_height' => ($this->context->getMobileDevice() == false ? Configuration::get('SHOP_LOGO_HEIGHT') : Configuration::get('SHOP_LOGO_MOBILE_HEIGHT')),
'logo_url' => ($this->context->getMobileDevice() == false ? _PS_IMG_.Configuration::get('PS_LOGO').'?'.Configuration::get('PS_IMG_UPDATE_TIME') : _PS_IMG_.Configuration::get('PS_LOGO_MOBILE').'?'.Configuration::get('PS_IMG_UPDATE_TIME'))
);
- }
+ }
}
diff --git a/classes/webservice/WebserviceSpecificManagementImages.php b/classes/webservice/WebserviceSpecificManagementImages.php
index 7901617bc..96a9bc63d 100755
--- a/classes/webservice/WebserviceSpecificManagementImages.php
+++ b/classes/webservice/WebserviceSpecificManagementImages.php
@@ -323,7 +323,7 @@ class WebserviceSpecificManagementImagesCore implements WebserviceSpecificManage
// Set the image path on display in relation to the header image
case 'header':
if (in_array($this->wsObject->method, array('GET','HEAD','PUT')))
- $path = _PS_IMG_DIR_.'logo.jpg';
+ $path = _PS_IMG_DIR_.Configuration::get('PS_LOGO');
else
throw new WebserviceException('This method is not allowed with general image resources.', array(49, 405));
break;
@@ -387,7 +387,7 @@ class WebserviceSpecificManagementImagesCore implements WebserviceSpecificManage
{
case 'GET':
case 'HEAD':
- $this->imgToDisplay = ($path != '' && file_exists($path)) ? $path : $alternative_path;
+ $this->imgToDisplay = ($path != '' && file_exists($path) && is_file($path)) ? $path : $alternative_path;
return true;
break;
case 'PUT':
diff --git a/config/config.inc.php b/config/config.inc.php
index 568a8f90a..fb9e98a74 100644
--- a/config/config.inc.php
+++ b/config/config.inc.php
@@ -107,6 +107,13 @@ Context::getContext()->country = $defaultCountry;
/* It is not safe to rely on the system's timezone settings, and this would generate a PHP Strict Standards notice. */
@date_default_timezone_set(Configuration::get('PS_TIMEZONE'));
+/* Set locales */
+$locale = strtolower(Configuration::get('PS_LOCALE_LANGUAGE')).'_'.strtoupper(Configuration::get('PS_LOCALE_COUNTRY').'.UTF-8');
+setlocale(LC_COLLATE, $locale);
+setlocale(LC_CTYPE, $locale);
+setlocale(LC_TIME, $locale);
+setlocale(LC_NUMERIC, 'en_US.UTF-8');
+
/* Instantiate cookie */
@@ -122,7 +129,7 @@ else
else
{
$domains = null;
- if(Context::getContext()->shop->domain != Context::getContext()->shop->domain_ssl)
+ if (Context::getContext()->shop->domain != Context::getContext()->shop->domain_ssl)
$domains = array(Context::getContext()->shop->domain_ssl, Context::getContext()->shop->domain);
$cookie = new Cookie('ps-s'.Context::getContext()->shop->id, '', $cookie_lifetime, $domains);
@@ -153,7 +160,7 @@ else
{
$customer = new Customer();
- // Change the default group
+ // Change the default group
if (Group::isFeatureActive())
$customer->id_default_group = Configuration::get('PS_UNIDENTIFIED_GROUP');
}
diff --git a/controllers/admin/AdminEmailsController.php b/controllers/admin/AdminEmailsController.php
index 8fcbbaddf..20b5affd3 100644
--- a/controllers/admin/AdminEmailsController.php
+++ b/controllers/admin/AdminEmailsController.php
@@ -202,7 +202,7 @@ class AdminEmailsControllerCore extends AdminController
if (isset($_POST['PS_SHOP_EMAIL']))
$_POST['PS_SHOP_EMAIL'] = Configuration::get('PS_SHOP_EMAIL');
- if ($_POST['PS_MAIL_METHOD'] == 2 && (empty($_POST['PS_MAIL_SERVER']) || empty($_POST['PS_MAIL_SMTP_PORT'])))
+ if (isset($_POST['PS_MAIL_METHOD']) && $_POST['PS_MAIL_METHOD'] == 2 && (empty($_POST['PS_MAIL_SERVER']) || empty($_POST['PS_MAIL_SMTP_PORT'])))
$this->errors[] = Tools::displayError('You must define an SMTP server and an SMTP port. If you do not know, use the PHP mail() function instead.');
}
diff --git a/controllers/admin/AdminHomeController.php b/controllers/admin/AdminHomeController.php
index dee062dfb..dc38db107 100644
--- a/controllers/admin/AdminHomeController.php
+++ b/controllers/admin/AdminHomeController.php
@@ -95,7 +95,6 @@ class AdminHomeControllerCore extends AdminController
$opti_list = array();
if ($rewrite + $htaccessOptimized + $smartyOptimized + $cccOptimized + $shopEnabled + $htaccessAfterUpdate + $indexRebuiltAfterUpdate != 14)
{
- $this->context->smarty->assign('hide_tips', Configuration::get('PS_HIDE_OPTIMIZATION_TIPS'));
$opti_list[] = array(
'title' => $this->l('URL rewriting'),
'href' => $link->getAdminLink('AdminMeta'),
@@ -145,8 +144,12 @@ class AdminHomeControllerCore extends AdminController
'image' => $lights[$htaccessAfterUpdate]['image'],
);
}
- $this->context->smarty->assign('opti_list', $opti_list);
- $this->context->smarty->assign('content', $content);
+ $this->context->smarty->assign(array(
+ 'opti_list' => $opti_list,
+ 'content' => $content,
+ 'hide_tips' => Configuration::get('PS_HIDE_OPTIMIZATION_TIPS'))
+ );
+
$template = $this->createTemplate('optimizationTips.tpl');
return $template->fetch();
}
diff --git a/controllers/admin/AdminModulesController.php b/controllers/admin/AdminModulesController.php
index 400c5176c..354d01a04 100644
--- a/controllers/admin/AdminModulesController.php
+++ b/controllers/admin/AdminModulesController.php
@@ -462,6 +462,7 @@ class AdminModulesControllerCore extends AdminController
}
else
$this->errors[] = Tools::displayError('Cannot load module object');
+ $this->errors = array_merge($this->errors, $module->getErrors());
}
else
$this->errors[] = Tools::displayError('You do not have permission to add here.');
@@ -688,6 +689,7 @@ class AdminModulesControllerCore extends AdminController
}
elseif ($echo === false)
$module_errors[] = array('name' => $name, 'message' => $module->getErrors());
+
if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL && isset(Context::getContext()->tmpOldShop))
{
Context::getContext()->shop = clone(Context::getContext()->tmpOldShop);
diff --git a/controllers/admin/AdminProductsController.php b/controllers/admin/AdminProductsController.php
index ae2b93f8d..f826f226d 100644
--- a/controllers/admin/AdminProductsController.php
+++ b/controllers/admin/AdminProductsController.php
@@ -536,13 +536,17 @@ class AdminProductsControllerCore extends AdminController
$this->errors[] = Tools::displayError('You cannot delete the product because there is physical stock left or supply orders in progress.');
}
- if ($object->delete())
+ if (!count($this->errors))
{
- $id_category = (int)Tools::getValue('id_category');
- $category_url = empty($id_category) ? '' : '&id_category='.(int)$id_category;
- $this->redirect_after = self::$currentIndex.'&conf=1&token='.$this->token.$category_url;
+ if ($object->delete())
+ {
+ $id_category = (int)Tools::getValue('id_category');
+ $category_url = empty($id_category) ? '' : '&id_category='.(int)$id_category;
+ $this->redirect_after = self::$currentIndex.'&conf=1&token='.$this->token.$category_url;
+ }
+ else
+ $this->errors[] = Tools::displayError('An error occurred during deletion.');
}
- $this->errors[] = Tools::displayError('An error occurred during deletion.');
}
}
else
@@ -632,10 +636,8 @@ class AdminProductsControllerCore extends AdminController
$real_quantity = $stock_manager->getProductRealQuantities($product->id, 0);
if ($physical_quantity > 0 || $real_quantity > $physical_quantity)
$this->errors[] = sprintf(Tools::displayError('You cannot delete the product #%d because there is physical stock left or supply orders in progress.'), $product->id);
- else
- $success &= $product->delete();
}
- else
+ if (!count($this->errors))
$success &= $product->delete();
}
}
@@ -1704,7 +1706,7 @@ class AdminProductsControllerCore extends AdminController
$this->updateDownloadProduct($object, 1);
$this->updateTags(Language::getLanguages(false), $object);
- if ($this->isProductFieldUpdated('category_box') && !$object->updateCategories(Tools::getValue('categoryBox'), true))
+ if ($this->isProductFieldUpdated('category_box') && !$object->updateCategories(Tools::getValue('categoryBox')))
$this->errors[] = Tools::displayError('An error occurred while linking object.').' '.$this->table.' '.Tools::displayError('To categories');
}
@@ -3299,8 +3301,7 @@ class AdminProductsControllerCore extends AdminController
$data->assign('currency', $currency);
$this->object = $product;
$this->display = 'edit';
-
-
+ $data->assign('product_name_redirected', Product::getProductName((int)$product->id_product_redirected, null, (int)$this->context->language->id));
/*
* Form for adding a virtual product like software, mp3, etc...
*/
diff --git a/controllers/admin/AdminTranslationsController.php b/controllers/admin/AdminTranslationsController.php
index 98cd2748a..86508e22f 100644
--- a/controllers/admin/AdminTranslationsController.php
+++ b/controllers/admin/AdminTranslationsController.php
@@ -570,7 +570,7 @@ class AdminTranslationsControllerCore extends AdminController
if (isset($tab->class_name) && !empty($tab->class_name))
{
$id_lang = Language::getIdByIso($iso_code);
- $tab->name[(int)$id_lang] = pSQL($translations);
+ $tab->name[(int)$id_lang] = $translations;
// Update this tab
$tab->update();
diff --git a/controllers/front/AddressController.php b/controllers/front/AddressController.php
index d3abd9ddb..67c73f54d 100644
--- a/controllers/front/AddressController.php
+++ b/controllers/front/AddressController.php
@@ -256,7 +256,7 @@ class AddressControllerCore extends FrontController
// Assign common vars
$this->context->smarty->assign(array(
- 'onr_phone_at_least' => (int)Configuration::get('PS_ONE_PHONE_AT_LEAST'),
+ 'one_phone_at_least' => (int)Configuration::get('PS_ONE_PHONE_AT_LEAST'),
'ajaxurl' => _MODULE_DIR_,
'errors' => $this->errors,
'token' => Tools::getToken(false),
diff --git a/controllers/front/AuthController.php b/controllers/front/AuthController.php
index 92859d12c..5776a4f01 100644
--- a/controllers/front/AuthController.php
+++ b/controllers/front/AuthController.php
@@ -166,7 +166,7 @@ class AuthControllerCore extends FrontController
$days = Tools::dateDays();
$this->context->smarty->assign(array(
- 'onr_phone_at_least' => (int)Configuration::get('PS_ONE_PHONE_AT_LEAST'),
+ 'one_phone_at_least' => (int)Configuration::get('PS_ONE_PHONE_AT_LEAST'),
'years' => $years,
'sl_year' => (isset($selectedYears) ? $selectedYears : 0),
'months' => $months,
diff --git a/controllers/front/OrderFollowController.php b/controllers/front/OrderFollowController.php
index 2ac6a39cc..db270da14 100644
--- a/controllers/front/OrderFollowController.php
+++ b/controllers/front/OrderFollowController.php
@@ -113,7 +113,7 @@ class OrderFollowControllerCore extends FrontController
parent::setMedia();
$this->addCSS(array(_THEME_CSS_DIR_.'history.css', _THEME_CSS_DIR_.'addresses.css'));
$this->addJqueryPlugin('scrollTo');
- $this->addJS(_THEME_JS_DIR_.'history.js', _THEME_JS_DIR_.'tools.js');
+ $this->addJS(array(_THEME_JS_DIR_.'history.js', _THEME_JS_DIR_.'tools.js'));
}
}
diff --git a/controllers/front/ProductController.php b/controllers/front/ProductController.php
index 0a3064a46..9ce391d2e 100644
--- a/controllers/front/ProductController.php
+++ b/controllers/front/ProductController.php
@@ -104,16 +104,45 @@ class ProductControllerCore extends FrontController
* allow showing the product
* In all the others cases => 404 "Product is no longer available"
*/
- if (!$this->product->isAssociatedToShop()
- || ((!$this->product->active && ((Tools::getValue('adtoken') != Tools::getAdminToken('AdminProducts'.(int)Tab::getIdFromClassName('AdminProducts').(int)Tools::getValue('id_employee')))
- || !file_exists(_PS_ROOT_DIR_.'/'.Tools::getValue('ad').'/index.php')))))
+ if (!$this->product->isAssociatedToShop() || !$this->product->active)
{
- header('HTTP/1.1 404 page not found');
- $this->errors[] = Tools::displayError('Product is no longer available.');
+ if (Tools::getValue('adtoken') == Tools::getAdminToken('AdminProducts'.(int)Tab::getIdFromClassName('AdminProducts').(int)Tools::getValue('id_employee')))
+ {
+ // If the product is not active, it's the admin preview mode
+ $this->context->smarty->assign('adminActionDisplay', true);
+ }
+ else
+ {
+ $this->context->smarty->assign('adminActionDisplay', false);
+ if ($this->product->id_product_redirected == $this->product->id)
+ $this->product->redirect_type = '404';
+
+ switch ($this->product->redirect_type)
+ {
+ case '301':
+ header('HTTP/1.1 301 Moved Permanently');
+ header('Location: '.$this->context->link->getProductLink($this->product->id_product_redirected));
+ break;
+ case '302':
+ header('HTTP/1.1 302 Moved Temporarily');
+ header('Cache-Control: no-cache');
+ header('Location: '.$this->context->link->getProductLink($this->product->id_product_redirected));
+ break;
+ case '404':
+ header('HTTP/1.1 404 Not Found');
+ header('Status: 404 Not Found');
+ $this->errors[] = Tools::displayError('Product is no longer available.');
+ break;
+ }
+ }
}
else if (!$this->product->checkAccess(isset($this->context->customer) ? $this->context->customer->id : 0))
+ {
+ header('HTTP/1.1 403 Forbidden');
+ header('Status: 403 Forbidden');
$this->errors[] = Tools::displayError('You do not have access to this product.');
-
+ }
+
// Load category
if (isset($_SERVER['HTTP_REFERER'])
&& !strstr($_SERVER['HTTP_REFERER'], Tools::getHttpHost()) // Assure us the previous page was one of the shop
@@ -150,10 +179,6 @@ class ProductControllerCore extends FrontController
// Assign to the template the id of the virtual product. "0" if the product is not downloadable.
$this->context->smarty->assign('virtual', ProductDownload::getIdFromIdProduct((int)$this->product->id));
- // If the product is not active, it's the admin preview mode
- if (!$this->product->active)
- $this->context->smarty->assign('adminActionDisplay', true);
-
// Product pictures management
require_once('images.inc.php');
$this->context->smarty->assign('customizationFormTarget', Tools::safeOutput(urldecode($_SERVER['REQUEST_URI'])));
diff --git a/install-dev/data/db_structure.sql b/install-dev/data/db_structure.sql
index d07b63842..bf5cbc15c 100644
--- a/install-dev/data/db_structure.sql
+++ b/install-dev/data/db_structure.sql
@@ -1376,6 +1376,8 @@ CREATE TABLE `PREFIX_product` (
`uploadable_files` tinyint(4) NOT NULL default '0',
`text_fields` tinyint(4) NOT NULL default '0',
`active` tinyint(1) unsigned NOT NULL default '0',
+ `redirect_type` ENUM('', '404', '301', '302') NOT NULL DEFAULT '',
+ `id_product_redirected` int(10) unsigned NOT NULL default '0',
`available_for_order` tinyint(1) NOT NULL default '1',
`available_date` date NOT NULL,
`condition` ENUM('new', 'used', 'refurbished') NOT NULL DEFAULT 'new',
@@ -1415,6 +1417,8 @@ CREATE TABLE IF NOT EXISTS `PREFIX_product_shop` (
`uploadable_files` tinyint(4) NOT NULL default '0',
`text_fields` tinyint(4) NOT NULL DEFAULT '0',
`active` tinyint(1) unsigned NOT NULL DEFAULT '0',
+ `redirect_type` ENUM('', '404', '301', '302') NOT NULL DEFAULT '',
+ `id_product_redirected` int(10) unsigned NOT NULL default '0',
`available_for_order` tinyint(1) NOT NULL DEFAULT '1',
`available_date` date NOT NULL,
`condition` enum('new','used','refurbished') NOT NULL DEFAULT 'new',
diff --git a/install-dev/fixtures/apple/data/product.xml b/install-dev/fixtures/apple/data/product.xml
index 227202823..e04599d94 100644
--- a/install-dev/fixtures/apple/data/product.xml
+++ b/install-dev/fixtures/apple/data/product.xml
@@ -29,6 +29,8 @@
+
+
@@ -41,31 +43,31 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/install-dev/upgrade/sql/1.5.2.1.sql b/install-dev/upgrade/sql/1.5.2.1.sql
index 7725a0b4a..8dea65958 100644
--- a/install-dev/upgrade/sql/1.5.2.1.sql
+++ b/install-dev/upgrade/sql/1.5.2.1.sql
@@ -6,4 +6,8 @@ ALTER TABLE `PREFIX_address` CHANGE `outstanding_allow_amount` `outstanding_all
/* PHP:block_category_1521(); */;
-UPDATE `PREFIX_order_state` SET `delivery` = 0 WHERE `id_order_state` = 3 ;
\ No newline at end of file
+UPDATE `PREFIX_order_state` SET `delivery` = 0 WHERE `id_order_state` = 3;
+
+ALTER TABLE `PREFIX_product_shop` ADD `id_product_redirected` int(10) unsigned NOT NULL default '0' AFTER `active` , ADD `available_for_order` tinyint(1) NOT NULL default '1' AFTER `id_product_redirected`;
+
+ALTER TABLE `PREFIX_product` ADD `id_product_redirected` int(10) unsigned NOT NULL default '0' AFTER `active` , ADD `available_for_order` tinyint(1) NOT NULL default '1' AFTER `id_product_redirected`;
\ No newline at end of file
diff --git a/js/admin-products.js b/js/admin-products.js
index 5701cc586..997e8c776 100644
--- a/js/admin-products.js
+++ b/js/admin-products.js
@@ -763,9 +763,8 @@ product_tabs['Attachments'] = new function(){
product_tabs['Informations'] = new function(){
var self = this;
this.bindAvailableForOrder = function (){
- $("#available_for_order").click(function(){
-
-
+ $("#available_for_order").click(function()
+ {
if ($(this).is(':checked') || ($('input[name=\'multishop_check[show_price]\']').lenght && !$('input[name=\'multishop_check[show_price]\']').prop('checked')))
{
$('#show_price').attr('checked', true);
@@ -776,6 +775,37 @@ product_tabs['Informations'] = new function(){
$('#show_price').attr('disabled', false);
}
});
+
+ if ($('#active_on').prop('checked'))
+ {
+ showRedirectProductOptions(false);
+ showRedirectProductSelectOptions(false);
+ }
+ else
+ showRedirectProductOptions(true);
+
+ $('#redirect_type').change(function () {
+ redirectSelectChange();
+ });
+
+ $('#related_product_autocomplete_input')
+ .autocomplete('ajax_products_list.php?excludeIds='+id_product, {
+ minChars: 1,
+ autoFill: true,
+ max:20,
+ matchContains: true,
+ mustMatch:true,
+ scroll:false,
+ cacheLength:0,
+ formatItem: function(item) {
+ return item[0]+' - '+item[1];
+ }
+ }).result(function(e, i){
+ if(i != undefined)
+ addRelatedProduct(i[1], i[0]);
+ $(this).val('');
+ });
+ addRelatedProduct(id_product_redirected, product_name_redirected);
};
this.bindTagImage = function (){
@@ -1196,6 +1226,8 @@ product_tabs['Quantities'] = new function(){
self.refreshQtyAvailabilityForm();
self.ajaxCall({actionQty: 'out_of_stock', value: $(this).val()});
});
+ if (display_multishop_checkboxes)
+ ProductMultishop.checkAllQuantities();
self.refreshQtyAvailabilityForm();
};
@@ -1544,6 +1576,15 @@ var ProductMultishop = new function()
ProductMultishop.checkField($('input[name=\'multishop_check[link_rewrite]['+v.id_lang+']\']').prop('checked'), 'link_rewrite_'+v.id_lang);
});
};
+
+ this.checkAllQuantities = function()
+ {
+ $.each(languages, function(k, v)
+ {
+ ProductMultishop.checkField($('input[name=\'multishop_check[available_later]['+v.id_lang+']\']').prop('checked'), 'available_later_'+v.id_lang);
+ ProductMultishop.checkField($('input[name=\'multishop_check[available_now]['+v.id_lang+']\']').prop('checked'), 'available_now_'+v.id_lang);
+ });
+ };
this.checkAllAssociations = function()
{
diff --git a/js/admin.js b/js/admin.js
index e6f85de01..34f6186e2 100644
--- a/js/admin.js
+++ b/js/admin.js
@@ -571,6 +571,56 @@ function toggleDraftWarning(show)
$('.draft').show();
}
+function showRedirectProductOptions(show)
+{
+ if (show)
+ $('.redirect_product_options').fadeIn();
+ else
+ $('.redirect_product_options').fadeOut();
+
+ redirectSelectChange();
+}
+
+function redirectSelectChange()
+{
+ if ($('#redirect_type :selected').val() == '404')
+ showRedirectProductSelectOptions(false);
+ else
+ showRedirectProductSelectOptions(true);
+}
+
+function addRelatedProduct(id_product_to_add, product_name)
+{
+ if (!id_product_to_add || id_product == id_product_to_add)
+ return;
+ $('#related_product_name').html(product_name);
+ $('#related_product_name').parent('p').css('margin-top', 0);
+ $('input[name=id_product_redirected]').val(id_product_to_add);
+ $('#related_product_autocomplete_input').hide();
+ $('#related_product_remove').show();
+}
+
+function removeRelatedProduct()
+{
+ $('#related_product_name').html(no_related_product);
+ $('#related_product_name').parent('p').css('margin-top', '0.5em');
+ $('input[name=id_product_redirected]').val(0);
+ $('#related_product_remove').hide();
+ $('#related_product_autocomplete_input').fadeIn();
+}
+
+function showRedirectProductSelectOptions(show)
+{
+ if (show)
+ $('.redirect_product_options_product_choise').show();
+ else
+ {
+ $('.redirect_product_options_product_choise').hide();
+ removeRelatedProduct();
+ }
+
+}
+
function showOptions(show)
{
if (show)
diff --git a/modules/blockcms/blockcms.tpl b/modules/blockcms/blockcms.tpl
index 3e0f2b038..2ac276188 100755
--- a/modules/blockcms/blockcms.tpl
+++ b/modules/blockcms/blockcms.tpl
@@ -57,7 +57,7 @@
{$cmslink.meta_title|escape:'htmlall':'UTF-8'}
{/if}
{/foreach}
-
+ {l s='Sitemap' mod='blockcms'}
{if $display_poweredby}{l s='Powered by' mod='blockcms'} PrestaShop ™ {/if}
{$footer_text}
diff --git a/themes/default/address.tpl b/themes/default/address.tpl
index 122518bbd..7618fa369 100644
--- a/themes/default/address.tpl
+++ b/themes/default/address.tpl
@@ -214,7 +214,7 @@ $(function(){ldelim}
{l s='Additional information'}
- {if $onr_phone_at_least}
+ {if $one_phone_at_least}
{l s='You must register at least one phone number'} *
{/if}
diff --git a/themes/default/authentication.tpl b/themes/default/authentication.tpl
index 8e4d5b932..01c5d4dd3 100644
--- a/themes/default/authentication.tpl
+++ b/themes/default/authentication.tpl
@@ -548,7 +548,7 @@ $(function(){ldelim}
{l s='Additional information'}
- {if $onr_phone_at_least}
+ {if $one_phone_at_least}
{l s='You must register at least one phone number'}
{/if}
@@ -556,7 +556,7 @@ $(function(){ldelim}
- {l s='Mobile phone'} {if $onr_phone_at_least}* {/if}
+ {l s='Mobile phone'} {if $one_phone_at_least}* {/if}
diff --git a/themes/default/js/product.js b/themes/default/js/product.js
index fd738d6da..8f787e60b 100644
--- a/themes/default/js/product.js
+++ b/themes/default/js/product.js
@@ -147,7 +147,7 @@ function findCombination(firstTime)
//update display of the availability of the product AND the prices of the product
function updateDisplay()
{
- if (!selectedCombination['unavailable'] && quantityAvailable > 0 && productAvailableForOrder === 1)
+ if (!selectedCombination['unavailable'] && quantityAvailable > 0 && parseInt(productAvailableForOrder) === 1)
{
//show the choice of quantities
$('#quantity_wanted_p:hidden').show('slow');
@@ -165,6 +165,7 @@ function updateDisplay()
//availability value management
if (availableNowValue !== '')
{
+
//update the availability statut of the product
$('#availability_value').removeClass('warning_inline');
$('#availability_value').text(availableNowValue);
@@ -689,7 +690,7 @@ function initLocationChange(time)
function checkUrl()
{
- if (original_url !== window.location || first_url_check)
+ if (original_url != window.url || first_url_check)
{
first_url_check = false;
url = window.location+'';
diff --git a/themes/default/mobile/product.tpl b/themes/default/mobile/product.tpl
index 47fd5f021..ec1536694 100644
--- a/themes/default/mobile/product.tpl
+++ b/themes/default/mobile/product.tpl
@@ -72,7 +72,7 @@
reference}style="display: none;"{/if}>
- {l s='Reference:'}
+ {l s='Reference:'}
{$product->reference|escape:'htmlall':'UTF-8'}
diff --git a/translations/br/admin.php b/translations/br/admin.php
new file mode 100644
index 000000000..3e9562c2b
--- /dev/null
+++ b/translations/br/admin.php
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/translations/br/errors.php b/translations/br/errors.php
new file mode 100644
index 000000000..604f75d22
--- /dev/null
+++ b/translations/br/errors.php
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/translations/br/fields.php b/translations/br/fields.php
new file mode 100644
index 000000000..03674f89c
--- /dev/null
+++ b/translations/br/fields.php
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/translations/br/pdf.php b/translations/br/pdf.php
new file mode 100644
index 000000000..9d9d1dac0
--- /dev/null
+++ b/translations/br/pdf.php
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/translations/br/tabs.php b/translations/br/tabs.php
new file mode 100644
index 000000000..83db297a2
--- /dev/null
+++ b/translations/br/tabs.php
@@ -0,0 +1,4 @@
+
\ No newline at end of file