Jump to content

Edit History

wapmakerw

wapmakerw

Finally, it seems to be a bug in Prestashop core. Customization fields don't seem to be configured correctly for multi-shop Prestashop.

For anyone facing the same issue, you can fix this bug by patching the core Prestashop files:

src/Adapter/Product/AdminProductWrapper.php

// make function changes    
public function processProductCustomization($product, $data)
    {
        $customization_ids = [];
        if ($data) {
            foreach ($data as $customization) {
                $customization_ids[] = (int) $customization['id_customization_field'];
            }
        }

        $shopList = Shop::getContextListShopID();

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

        /* Update the customization fields to be deleted in the next step if not used */
        $product->softDeleteCustomizationFieldsByShop($usedCustomizationIds, $shopList); //  only from current shop

        //remove customization field langs for current context shops
        $productCustomization = $product->getCustomizationFieldIdsByShop($shopList); // for current shop only
        $toDeleteCustomizationIds = [];
        if($productCustomization){
            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,
                if (in_array((int) $customizationFiled['id_customization_field'], $customization_ids)) {
                    Customization::deleteCustomizationFieldLangByShop($customizationFiled['id_customization_field'], $shopList);
                }
            }
        }

        //remove unused customization for the product
        $product->deleteUnusedCustomizationFields($toDeleteCustomizationIds);

Finally add the following functions to:

classes/Product.php


    public function getCustomizationFieldIdsByShop(array $shopIds)
    {
        if(count($shopIds) == 0) return [];

        if (!Customization::isFeatureActive()) {
            return [];
        }

        return Db::getInstance()->executeS('
            SELECT cf.`id_customization_field`, cf.`type`, cf.`required`
            FROM `' . _DB_PREFIX_ . 'customization_field` cf 
            LEFT JOIN `' . _DB_PREFIX_ . 'customization_field_lang` cfl ON cf.`id_customization_field`=cfl.`id_customization_field`
            WHERE cf.`id_product` = ' . (int) $this->id.' AND cfl.`id_shop` in ('.implode(", ", array_map('intval', $shopIds)).') GROUP BY cf.`id_customization_field`');
    }
	
	
    /**
     * Update the customization fields to be deleted if not used.
     *
     * @param array $customizationIds - Array of excluded customization fields IDs
     * 
     * @param array $shopList - Array of shop ids
     *
     * @return bool
     *
     * @throws PrestaShopDatabaseException
     */
    public function softDeleteCustomizationFieldsByShop($customizationIds, $shopList)
    {
        $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)) . ')';
        }

        if (is_array($shopList) && !empty($shopList)) {
            $updateQuery .= ' AND (SELECT cfl.`id_shop` from `' . _DB_PREFIX_ . 'customization_field_lang` cfl where `id_customization_field` = cf.`id_customization_field` LIMIT 1) IN (' . implode(',', array_map('intval', $shopList)) . ')';
        }

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

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

        return $return;
    }

 

wapmakerw

wapmakerw

Finally, it seems to be a bug in Prestashop core. Customization fields don't seem to be configured for multi-shop Prestashop.

For anyone who face the same issue, you can fix this bug by patching the core Prestashop file:

src/Adapter/Product/AdminProductWrapper.php

// make function changes    
public function processProductCustomization($product, $data)
    {
        $customization_ids = [];
        if ($data) {
            foreach ($data as $customization) {
                $customization_ids[] = (int) $customization['id_customization_field'];
            }
        }

        $shopList = Shop::getContextListShopID();

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

        /* Update the customization fields to be deleted in the next step if not used */
        $product->softDeleteCustomizationFieldsByShop($usedCustomizationIds, $shopList); //  only from current shop

        //remove customization field langs for current context shops
        $productCustomization = $product->getCustomizationFieldIdsByShop($shopList); // for current shop only
        $toDeleteCustomizationIds = [];
        if($productCustomization){
            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,
                if (in_array((int) $customizationFiled['id_customization_field'], $customization_ids)) {
                    Customization::deleteCustomizationFieldLangByShop($customizationFiled['id_customization_field'], $shopList);
                }
            }
        }

        //remove unused customization for the product
        $product->deleteUnusedCustomizationFields($toDeleteCustomizationIds);

Finally add the following functions to:

classes/Product.php

``
    public function getCustomizationFieldIdsByShop(array $shopIds)
    {
        if(count($shopIds) == 0) return [];

        if (!Customization::isFeatureActive()) {
            return [];
        }

        return Db::getInstance()->executeS('
            SELECT cf.`id_customization_field`, cf.`type`, cf.`required`
            FROM `' . _DB_PREFIX_ . 'customization_field` cf 
            LEFT JOIN `' . _DB_PREFIX_ . 'customization_field_lang` cfl ON cf.`id_customization_field`=cfl.`id_customization_field`
            WHERE cf.`id_product` = ' . (int) $this->id.' AND cfl.`id_shop` in ('.implode(", ", array_map('intval', $shopIds)).') GROUP BY cf.`id_customization_field`');
    }
	
	
    /**
     * Update the customization fields to be deleted if not used.
     *
     * @param array $customizationIds - Array of excluded customization fields IDs
     * 
     * @param array $shopList - Array of shop ids
     *
     * @return bool
     *
     * @throws PrestaShopDatabaseException
     */
    public function softDeleteCustomizationFieldsByShop($customizationIds, $shopList)
    {
        $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)) . ')';
        }

        if (is_array($shopList) && !empty($shopList)) {
            $updateQuery .= ' AND (SELECT cfl.`id_shop` from `' . _DB_PREFIX_ . 'customization_field_lang` cfl where `id_customization_field` = cf.`id_customization_field` LIMIT 1) IN (' . implode(',', array_map('intval', $shopList)) . ')';
        }

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

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

        return $return;
    }

 

×
×
  • Create New...