Jump to content

Product Customization fields


wapmakerw

Recommended Posts

Hello everyone,

This is my first forum post here. :)
I have a multi-shop Prestashop (1.7.5.2) site with two subdomains (shop1 & shop2).

The problem I am facing:

On shop1, when I go to Back-Office -> Catalogue -> Products -> Product choose -> Options tab -> Customization Head 

and enter the some Customization text as a Text Field for one shop (check screenshot attached). On saving, it gets saved but the Text Field disappears from the shop2. The same behavior occurs when I save the Text Field from the shop2. I cannot simultaneously have the Customization text fields on both shops.

(The same issue occurs on Prestashop version 1.7.7 also)

I looked into the code and found that in `src/Adapter/Product/AdminProductWrapper.php` the following function calls delete all other text fields than the ones currently entered.

$product->softDeleteCustomizationFields($customization_ids); // and
Customization::deleteCustomizationFieldLangByShop($customizationFiled['id_customization_field'], $shopList);


I could not find how to fix it though. :(

Can anyone please help me with this asap? I'll be highly grateful.

 

2021-04-26_11-49.png

Edited by wapmakerw
Added more information (see edit history)
Link to comment
Share on other sites

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;
    }

 

Edited by wapmakerw (see edit history)
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...