Catalog Price Rules is a widely used Prestashop tool for mass creation of discounts. But if you have a lot of features and feature_values associated with them, one day this function can get unavailable for you. Let’s check why exactly you won’t be able to use it.
The reason is hidden in the AdminSpecificPriceRuleControllerCore::renderForm method, and more particularly here:
1 2 3 4 5 6 |
``` $features = Feature::getFeatures((int)$this->context->language->id); foreach ($features as &$feature) { $feature['values'] = FeatureValue::getFeatureValuesWithLang((int)$this->context->language->id, $feature['id_feature'], true); } ``` |
The thing is while loading the form, Prestashop tries to load all features and their values because Catalog Price Rules allows using Features as one of the conditions for a discount.
We solved this problem using asynchronous load of Feature Values.
To do so made a few corrections:
1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
``` $features = Feature::getFeatures((int)$this->context->language->id); foreach ($features as &$feature) $feature['values'] = array(); /*FeatureValue::getFeatureValuesWithLang((int)$this->context->language->id, $feature['id_feature'], true);*/ // we simply create an empty array instead of loading all values /*override [begin]*/ //for created conditions we load features values $conditions = $this->object->getConditions(); foreach ($conditions as $condition) { foreach ($condition as $cond) { $f_value = array(); if ($cond['type'] == 'feature') { $f_value = FeatureValue::getFeatureValueWithLang((int)$this->context->language->id, $cond['id_feature'], $cond['value']); foreach ($features as &$feature) { if ($feature['id_feature'] == $f_value['id_feature']) { $feature['values'][] = $f_value; } } } } } /*override [end]*/ ``` |
2. The FeatureValue::getFeatureValueWithLang() class is a new method that gets values for a particular Feature.
class FeatureValue extends FeatureValueCore
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ public static function getFeatureValueWithLang($id_lang, $id_feature, $id_feature_value) { return Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_.'feature_value` v LEFT JOIN `'._DB_PREFIX_.'feature_value_lang` vl ON (v.`id_feature_value` = vl.`id_feature_value` AND vl.`id_lang` = '.(int)$id_lang.') WHERE v.`id_feature` = '.(int)$id_feature.' AND v.`id_feature_value` = '.(int)$id_feature_value.' ORDER BY vl.`value` ASC '); } } |
3. The SpecificPriceRule::getConditions() class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
``` class SpecificPriceRule extends SpecificPriceRuleCore { public function getConditions() { $conditions = Db::getInstance()->executeS(' SELECT g.*, c.* FROM '._DB_PREFIX_.'specific_price_rule_condition_group g LEFT JOIN '._DB_PREFIX_.'specific_price_rule_condition c ON (c.id_specific_price_rule_condition_group = g.id_specific_price_rule_condition_group) WHERE g.id_specific_price_rule='.(int)$this->id ); $conditions_group = array(); if ($conditions) { foreach ($conditions as &$condition) { if ($condition['type'] == 'attribute') $condition['id_attribute_group'] = Db::getInstance()->getValue('SELECT id_attribute_group FROM '._DB_PREFIX_.'attribute WHERE id_attribute='.(int)$condition['value']); elseif ($condition['type'] == 'feature') { $condition['id_feature'] = Db::getInstance()->getValue('SELECT id_feature FROM '._DB_PREFIX_.'feature_value WHERE id_feature_value='.(int)$condition['value']); $condition['value_name'] = Db::getInstance()->getValue('select value FROM `'._DB_PREFIX_.'feature_value_lang` where id_feature_value = '.(int)$condition['value'].' AND id_lang = ' . Context::getContext()->language->id); //override reason: get feature value } $conditions_group[(int)$condition['id_specific_price_rule_condition_group']][] = $condition; } } return $conditions_group; } } ``` |
4. Override of a theme file
/administration/themes/default/template/controllers/specific_price_rule/helpers/form/form.tpl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
... //action when we change id_feature values, we load feature values asynchronously $('#id_feature').change(function() { $('.id_feature_value').hide(); $.ajax({ type: 'POST', url: currentIndex, headers: { "cache-control": "no-cache" }, async: true, data: 'token=' + token + '&ajax=1&action=getFeatureValues&id_feature=' + $('#id_feature').val(), cache: false, dataType: 'json', success: function(data) { //console.log(data); for (i = 0; i < data.length; i++) { $('#id_feature_' + $('#id_feature').val()).append($('<option>').text(data[i].value).attr('value', data[i].id_feature_value)); } } }); $('#id_feature_'+$(this).val()).show(); }); ``` |
5. New action in AdminSpecificPriceRuleController::ajaxProcessGetFeatureValues() controller that is used in /administration/themes/default/template/controllers/specific_price_rule/helpers/form/form.tpl
1 2 3 4 5 6 7 8 9 10 |
``` public function ajaxProcessGetFeatureValues() { $id_feature = Tools::getValue('id_feature'); $values = FeatureValue::getFeatureValuesWithLang((int)$this->context->language->id, $id_feature, true); die(Tools::jsonEncode($values)); } ``` |
Download all changed files here.
@Andrei, link is fixed
Hello,
Is it possible to fix the link, download is not working. Also i am having issues to understand exactly where you need to modify, could you please look maybe you havent specified clearly what file and where to add/modify.
Thank you