Skip to content

Commit

Permalink
Merge pull request PrestaShop#7873 from fatmaBouchekoua/BOOM-2742
Browse files Browse the repository at this point in the history
Fix bug after removing product customization
  • Loading branch information
toutantic authored Nov 6, 2017
2 parents 637323a + 7d3d517 commit 263ead8
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 17 deletions.
21 changes: 21 additions & 0 deletions classes/Customization.php
Original file line number Diff line number Diff line change
Expand Up @@ -392,4 +392,25 @@ public function setWsCustomizedDataTextFields($values)

return true;
}

/**
* Delete the current context shops langs
*
* @param int $idCustomizationField
* @param int[] $shopList
* @return bool
* @throws PrestaShopDatabaseException
*/
public static function deleteCustomizationFieldLangByShop($idCustomizationField, $shopList)
{
$return = Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'customization_field_lang`
WHERE `id_customization_field` = ' . (int)$idCustomizationField . '
AND `id_shop` IN (' . implode(',', $shopList) . ')');

if (!$return) {
throw new PrestaShopDatabaseException('An error occurred while deletion the customization fields lang');
}

return $return;
}
}
1 change: 1 addition & 0 deletions classes/CustomizationField.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class CustomizationFieldCore extends ObjectModel
'type' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true),
'required' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true),
'is_module' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => false),
'is_deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => false),

/* Lang fields */
'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'required' => true, 'size' => 255),
Expand Down
104 changes: 97 additions & 7 deletions classes/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -5219,13 +5219,15 @@ public function getCustomizationFields($id_lang = false, $id_shop = null)
$front = isset($context->controller->controller_type) && in_array($context->controller->controller_type, array('front'));

if (!$result = Db::getInstance()->executeS('
SELECT cf.`id_customization_field`, cf.`type`, cf.`required`, cfl.`name`, cfl.`id_lang`
FROM `'._DB_PREFIX_.'customization_field` cf
NATURAL JOIN `'._DB_PREFIX_.'customization_field_lang` cfl
WHERE cf.`id_product` = '.(int)$this->id.($id_lang ? ' AND cfl.`id_lang` = '.(int)$id_lang : '').
($id_shop ? ' AND cfl.`id_shop` = '.(int)$id_shop : '').
($front ? ' AND !cf.`is_module`' : '').'
ORDER BY cf.`id_customization_field`')) {
SELECT cf.`id_customization_field`, cf.`type`, cf.`required`, cfl.`name`, cfl.`id_lang`
FROM `' . _DB_PREFIX_ . 'customization_field` cf
NATURAL JOIN `' . _DB_PREFIX_ . 'customization_field_lang` cfl
WHERE cf.`id_product` = ' . (int)$this->id . ($id_lang ? ' AND cfl.`id_lang` = ' . (int)$id_lang : '') .
($id_shop ? ' AND cfl.`id_shop` = ' . (int)$id_shop : '') .
($front ? ' AND !cf.`is_module`' : '') . '
AND cf.`is_deleted` = 0
ORDER BY cf.`id_customization_field`')
) {
return false;
}

Expand All @@ -5241,6 +5243,25 @@ public function getCustomizationFields($id_lang = false, $id_shop = null)
return $customization_fields;
}

/**
* check if product has an activated and required customizationFields
* @return bool
* @throws \PrestaShopDatabaseException
*/
public function hasActivatedRequiredCustomizableFields(){
if (!Customization::isFeatureActive()) {
return false;
}

return (bool)Db::getInstance()->executeS('
SELECT 1
FROM `' . _DB_PREFIX_ . 'customization_field`
WHERE `id_product` = ' . (int)$this->id . '
AND `required` = 1
AND `is_deleted` = 0'
);
}

public function getCustomizationFieldIds()
{
if (!Customization::isFeatureActive()) {
Expand Down Expand Up @@ -6594,4 +6615,73 @@ public function getRedirectType()

return false;
}

/**
* Return an array of customization fields IDs
*
* @return array|false
*/
public function getUsedCustomizationFieldsIds()
{
return Db::getInstance()->executeS(
'SELECT cd.`index` FROM `' . _DB_PREFIX_ . 'customized_data` cd
LEFT JOIN `' . _DB_PREFIX_ . 'customization_field` cf ON cf.`id_customization_field` = cd.`index`
WHERE cf.`id_product` = ' . (int)$this->id
);
}

/**
* Remove unused customization for the product
*
* @param array $customizationIds - Array of customization fields IDs
* @return bool
* @throws PrestaShopDatabaseException
*/
public function deleteUnusedCustomizationFields($customizationIds)
{
$return = true;
if (is_array($customizationIds) && !empty($customizationIds)) {
$toDeleteIds = implode(",", $customizationIds);
$return &= Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'customization_field` WHERE
`id_product` = ' . (int)$this->id . ' AND `id_customization_field` IN (' . $toDeleteIds . ')');

$return &= Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'customization_field_lang` WHERE
`id_customization_field` IN (' . $toDeleteIds . ')');
}

if (!$return) {
throw new PrestaShopDatabaseException('An error occurred while deletion the customization fields');
}

return $return;
}

/**
* Update the customization fields to be deleted if not used
*
* @param array $customizationIds - Array of excluded customization fields IDs
* @return bool
* @throws PrestaShopDatabaseException
*/
public function softDeleteCustomizationFields($customizationIds)
{
$return = true;
$updateQuery = 'UPDATE `' . _DB_PREFIX_ . 'customization_field` cf
SET cf.`is_deleted` = 1
WHERE
cf.`id_product` = ' . (int)$this->id . '
AND cf.`is_deleted` = 0 ';

if (is_array($customizationIds) && !empty($customizationIds)) {
$updateQuery .= 'AND cf.`id_customization_field` NOT IN (' . implode(',', array_map('intval', $customizationIds)) . ')';
}

$return &= Db::getInstance()->execute($updateQuery);

if (!$return) {
throw new PrestaShopDatabaseException('An error occurred while soft deletion the customization fields');
}

return $return;
}
}
2 changes: 1 addition & 1 deletion controllers/front/CartController.php
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ protected function processChangeProductInCart()
}

// Check customizable fields
if (!$product->hasAllRequiredCustomizableFields() && !$this->customization_id) {
if ($product->hasActivatedRequiredCustomizableFields() && !$this->customization_id) {
$this->errors[] = $this->trans('Please fill in all of the required fields, and then save your customizations.', array(), 'Shop.Notifications.Error');
}

Expand Down
1 change: 1 addition & 0 deletions install-dev/data/db_structure.sql
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,7 @@ CREATE TABLE `PREFIX_customization_field` (
`type` tinyint(1) NOT NULL,
`required` tinyint(1) NOT NULL,
`is_module` TINYINT(1) NOT NULL DEFAULT '0',
`is_deleted` TINYINT(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id_customization_field`),
KEY `id_product` (`id_product`)
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 COLLATION;
Expand Down
2 changes: 2 additions & 0 deletions install-dev/upgrade/sql/1.7.3.0.sql
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@ CREATE TABLE IF NOT EXISTS `PREFIX_store_lang` (
ALTER TABLE `PREFIX_store` DROP `name`, DROP `address1`, DROP `address2`, DROP `hours`, DROP `note`;

ALTER TABLE `PREFIX_feature_product` DROP PRIMARY KEY, ADD PRIMARY KEY (`id_feature`, `id_product`, `id_feature_value`);

ALTER TABLE `PREFIX_customization_field` ADD `is_deleted` TINYINT(1) NOT NULL DEFAULT '0';
28 changes: 19 additions & 9 deletions src/Adapter/Product/AdminProductWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
namespace PrestaShop\PrestaShop\Adapter\Product;

use Attachment;
use PrestaShop\PrestaShop\Adapter\Entity\Customization;
use SpecificPrice;
use Customer;
use Combination;
Expand Down Expand Up @@ -500,20 +501,29 @@ public function processProductCustomization($product, $data)

$shopList = Shop::getContextListShopID();

/** Update the customization fields to be deleted in the next step if not used */
$product->softDeleteCustomizationFields($customization_ids);

$usedCustomizationIds = $product->getUsedCustomizationFieldsIds();
$usedCustomizationIds = array_column($usedCustomizationIds, 'index');
$usedCustomizationIds = array_map('intval', $usedCustomizationIds);
$usedCustomizationIds = array_unique(array_merge($usedCustomizationIds, $customization_ids), SORT_REGULAR);

//remove customization field langs for current context shops
foreach ($product->getCustomizationFieldIds() as $customizationFiled) {
$productCustomization = $product->getCustomizationFieldIds();
$toDeleteCustomizationIds = array();
foreach ($productCustomization as $customizationFiled) {
if (!in_array((int)$customizationFiled['id_customization_field'], $usedCustomizationIds)) {
$toDeleteCustomizationIds[] = (int)$customizationFiled['id_customization_field'];
}
//if the customization_field is still in use, only delete the current context shops langs,
//else delete all the langs
Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'customization_field_lang WHERE
`id_customization_field` = '.(int)$customizationFiled['id_customization_field'].
(in_array((int)$customizationFiled['id_customization_field'], $customization_ids) ? ' AND `id_shop` IN ('.implode(',', $shopList).')' : ''));
if (in_array((int)$customizationFiled['id_customization_field'], $customization_ids)) {
Customization::deleteCustomizationFieldLangByShop($customizationFiled['id_customization_field'], $shopList);
}
}

//remove unused customization for the product
if (!empty($customization_ids)) {
Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'customization_field WHERE
`id_product` = '.(int)$product->id.' AND `id_customization_field` NOT IN ('.implode(",", $customization_ids).')');
}
$product->deleteUnusedCustomizationFields($toDeleteCustomizationIds);

//create new customizations
$countFieldText = 0;
Expand Down

0 comments on commit 263ead8

Please sign in to comment.