korvent Posted July 9, 2021 Share Posted July 9, 2021 Howdy everyone ! I'm trying to add additional fields on my product combinations in order to have custom meta titles for the combinations. My module definition: class CombinationCustomFields extends Module { public function __construct() { $this->name = 'combinationcustomfields'; $this->tab = 'administration'; $this->author = ''; $this->version = '1.0'; $this->need_instance = 0; $this->bootstrap = true; parent::__construct(); $this->displayName = $this->l('Combination Custom Fields'); $this->description = $this->l('Add additional fields on combinations'); $this->ps_versions_compliancy = array('min' => '1.7.1', 'max' => _PS_VERSION_); } public function install() { if (!parent::install() || !$this->_installSql() || !$this->registerHook('displayAdminProductsCombinationBottom') || !$this->registerHook('actionAttributeCombinationSave') ) { return false; } return true; } public function uninstall() { return parent::uninstall() && $this->_unInstallSql(); } /** * Add database fields * @return boolean */ protected function _installSql() { $sqlInstall = "ALTER TABLE " . _DB_PREFIX_ . "product_attribute " . "ADD meta_title_fr VARCHAR(255) NULL, " . "ADD meta_title_en VARCHAR(255) NULL;"; $returnSql = Db::getInstance()->execute($sqlInstall); return $returnSql; } /** * Remove database fields * @return boolean */ protected function _unInstallSql() { $sqlInstall = "ALTER TABLE " . _DB_PREFIX_ . "product_attribute " . "DROP meta_title_fr, " . "DROP meta_title_en"; $returnSql = Db::getInstance()->execute($sqlInstall); return $returnSql; } public function hookDisplayAdminProductsCombinationBottom($params) { $combination = new Combination($params['id_product_attribute']); $this->context->smarty->assign(array( 'id_product_attribute' => $params['id_product_attribute'], 'meta_title_fr' => $combination->meta_title_fr, 'meta_title_en' => $combination->meta_title_en, ) ); return $this->display(__FILE__, 'views/templates/hook/combinationfields.tpl'); } public function hookActionAttributeCombinationSave($params) { $combination = new Combination($params['id_product_attribute']); $this->context->smarty->assign(array( 'id_product_attribute' => $params['id_product_attribute'], 'meta_title_fr' => $combination->meta_title_fr, 'meta_title_en' => $combination->meta_title_en, ) ); $combination->meta_title_fr = Tools::getValue('meta_title_fr'); $combination->meta_title_en = Tools::getValue('meta_title_en'); $combination->save(); return $this->display(__FILE__, 'views/templates/hook/combinationfields.tpl'); } } My HTML for the admin hook: <div class="m-b-1 m-t-1"> <h2>{l s='Combination Custom Fields' mod='combinationcustomfields'}</h2> <fieldset class="form-group"> <div class="col-lg-12 col-xl-4"> <label class="form-control-label" for="combination_{$id_product_attribute}_attribute_meta_title_fr">{l s='Meta title FR' mod='combinationcustomfields'}</label> <input class="form-control" name="combination_{$id_product_attribute}[attribute_meta_title_fr]" id="combination_{$id_product_attribute}_attribute_meta_title_fr" type="text" value="{if $meta_title_fr != ''}{$meta_title_fr}{/if}"> <br /> </div> <div class="col-lg-12 col-xl-4"> <label class="form-control-label" for="combination_{$id_product_attribute}_attribute_meta_title_en">{l s='Meta title EN' mod='cmp_combination_customfields'}</label> <input class="form-control" name="combination_{$id_product_attribute}[attribute_meta_title_en]" id="combination_{$id_product_attribute}_attribute_meta_title_en" type="text" value="{if $meta_title_en != ''}{$meta_title_en}{/if}"> <br /> </div> </fieldset> <div class="clearfix"></div> </div> My override of the combination class: class Combination extends CombinationCore { public $meta_title_fr; public $meta_title_en; /** * @see ObjectModel::$definition */ public static $definition = [ 'table' => 'product_attribute', 'primary' => 'id_product_attribute', 'fields' => [ 'id_product' => ['type' => self::TYPE_INT, 'shop' => 'both', 'validate' => 'isUnsignedId', 'required' => true], 'location' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 64], 'ean13' => ['type' => self::TYPE_STRING, 'validate' => 'isEan13', 'size' => 13], 'isbn' => ['type' => self::TYPE_STRING, 'validate' => 'isIsbn', 'size' => 32], 'upc' => ['type' => self::TYPE_STRING, 'validate' => 'isUpc', 'size' => 12], 'mpn' => ['type' => self::TYPE_STRING, 'validate' => 'isMpn', 'size' => 40], 'quantity' => ['type' => self::TYPE_INT, 'validate' => 'isInt', 'size' => 10], 'reference' => ['type' => self::TYPE_STRING, 'size' => 64], 'supplier_reference' => ['type' => self::TYPE_STRING, 'size' => 64], 'meta_title_fr' => ['type' => self::TYPE_STRING, 'size' => 64], 'meta_title_en' => ['type' => self::TYPE_STRING, 'size' => 64], /* Shop fields */ 'wholesale_price' => ['type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice', 'size' => 27], 'price' => ['type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isNegativePrice', 'size' => 20], 'ecotax' => ['type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice', 'size' => 20], 'weight' => ['type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isFloat'], 'unit_price_impact' => ['type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isNegativePrice', 'size' => 20], 'minimal_quantity' => ['type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedId', 'required' => true], 'low_stock_threshold' => ['type' => self::TYPE_INT, 'shop' => true, 'allow_null' => true, 'validate' => 'isInt'], 'low_stock_alert' => ['type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'], 'default_on' => ['type' => self::TYPE_BOOL, 'allow_null' => true, 'shop' => true, 'validate' => 'isBool'], 'available_date' => ['type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDateFormat'], ], ]; } But when I save the product, the fields are in the request: But I have a 400 Error: Any idea of my mistake here ? All the best and thanks in advance for you help Link to comment Share on other sites More sharing options...
korvent Posted July 20, 2021 Author Share Posted July 20, 2021 No one has an answer ? Link to comment Share on other sites More sharing options...
l2phmode Posted September 23, 2021 Share Posted September 23, 2021 On 7/20/2021 at 1:03 PM, korvent said: No one has an answer ? This problem comes from the smarty validator, or something like that, as I understand it. The bottom line is that when we save the page, we have undeclared fields for the form. Since the error is related to symphony, I tried to modify /src/PrestaShopBundle/Form/Admin/Product/ProductCombinationBulk.php public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'allow_extra_fields' => false // adding this ]); } Unfortunately, this did not solve the problem. Although they write on the Internet what should help, maybe you tried to register in the wrong place? Perhaps you have already found a solution to this task? Link to comment Share on other sites More sharing options...
Butch0071 Posted April 9 Share Posted April 9 Any new thouughts on issue ? ForPresta 8.1 and > it is explained in docs (with example) -> https://devdocs.prestashop-project.org/8/modules/sample-modules/extend-product-page/ but what about 8.0.1 ? How to make proper override in PRoduct and in Combination class? Override of Product: * Override Class ProductCore * @param string|null $combination_erp_id * @param string|null $link */ class Product extends ProductCore { public $combination_erp_id; public $link; public function updateAttribute( $id_product_attribute, $wholesale_price, $price, $weight, $unit, $ecotax, $id_images, $reference, $ean13, $default, $location = null, $upc = null, $minimal_quantity = null, $available_date = null, $update_all_fields = true, array $id_shop_list = [], $isbn = '', $low_stock_threshold = null, $low_stock_alert = false, $mpn = null ){ $combination = new Combination($id_product_attribute); if (!$update_all_fields) { $combination->setFieldsToUpdate([ 'price' => null !== $price, 'wholesale_price' => null !== $wholesale_price, 'ecotax' => null !== $ecotax, 'weight' => null !== $weight, 'unit_price_impact' => null !== $unit, 'default_on' => null !== $default, 'minimal_quantity' => null !== $minimal_quantity, 'reference' => null !== $reference, 'ean13' => null !== $ean13, 'upc' => null !== $upc, 'isbn' => null !== $isbn, 'mpn' => null !== $mpn, 'available_date' => null !== $available_date, 'low_stock_threshold' => null !== $low_stock_threshold, 'low_stock_alert' => null !== $low_stock_alert, 'id_shop_list' => !empty($id_shop_list), 'combination_erp_id' => !empty($combination_erp_id), 'link' => !empty($link), ]); } $price = (float) str_replace(',', '.', (string) $price); $weight = (float) str_replace(',', '.', (string) $weight); $combination->price = $price; $combination->wholesale_price = (float) $wholesale_price; $combination->ecotax = (float) $ecotax; $combination->weight = $weight; $combination->unit_price_impact = (float) $unit; $combination->reference = pSQL($reference); $combination->ean13 = pSQL($ean13); $combination->isbn = pSQL($isbn); $combination->upc = pSQL($upc); $combination->mpn = pSQL($mpn); $combination->default_on = (bool) $default; $combination->minimal_quantity = (int) $minimal_quantity; $combination->low_stock_threshold = empty($low_stock_threshold) && '0' != $low_stock_threshold ? null : (int) $low_stock_threshold; $combination->low_stock_alert = !empty($low_stock_alert); $combination->available_date = $available_date ? pSQL($available_date) : '0000-00-00'; $combination->combination_erp_id = pSQL($combination_erp_id); $combination->link = pSQL($link); if (!empty($id_shop_list)) { $combination->id_shop_list = $id_shop_list; } $combination->save(); if (is_array($id_images) && count($id_images)) { $combination->setImages($id_images); } $id_default_attribute = (int) Product::updateDefaultAttribute($this->id); if ($id_default_attribute) { $this->cache_default_attribute = $id_default_attribute; } // Sync stock Reference, EAN13, ISBN, MPN and UPC for this attribute if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && StockAvailable::dependsOnStock($this->id, Context::getContext()->shop->id)) { Db::getInstance()->update('stock', [ 'reference' => pSQL($reference), 'ean13' => pSQL($ean13), 'isbn' => pSQL($isbn), 'upc' => pSQL($upc), 'mpn' => pSQL($mpn), ], 'id_product = ' . $this->id . ' AND id_product_attribute = ' . (int) $id_product_attribute); } Hook::exec('actionProductAttributeUpdate', ['id_product_attribute' => (int) $id_product_attribute]); Tools::clearColorListCache($this->id); return true; } } and combination override: class Combination extends CombinationCore { public $combination_erp_id; public $link; /** * @see ObjectModel::$definition */ public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, Context $context = null){ Combination::$definition['fields']['combination_erp_id'] = [ 'type' => self::TYPE_STRING, 'required' => false, 'size' => 255 ]; Combination::$definition['fields']['link'] = [ 'type' => self::TYPE_STRING, 'required' => false, 'size' => 255 ]; parent::__construct($id_product, $full, $id_lang, $id_shop, $context); } } However the module still does not save data to SQL... Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now