load('plg_hikashop_fees', JPATH_ADMINISTRATOR); } public function onAfterCartShippingLoad(&$cart) { $formulas = hikashop_copy($this->params->get('formulas', '[{"label": "","condition": "","formula": "","fee_included":"0"}]')); if (is_string($formulas)) { $formulas = json_decode($formulas); } foreach($formulas as $formula_id => $formula) { if(empty($formula->formula)) continue; $skip = false; if(!empty($formula->condition)) { $skip = $this->_replaceMainTags($formula->condition, $cart); if($skip) continue; if(count($this->productTags)) { $valid = true; foreach($cart->products as $product) { $contidionCopy = hikashop_copy($formula->condition); $skip = $this->_replaceProductTags($contidionCopy, $product); if(!$skip) { $valid = $valid && (bool)$this->_evaluate($contidionCopy); if ((bool)$this->_evaluate($contidionCopy)) { $valid=1; break; } } elseif($skip === 2) { $valid = false; break; } } } else { $valid = (bool)$this->_evaluate($formula->condition); } if(!$valid) continue; } $skip = $this->_replaceMainTags($formula->formula, $cart); if(!$skip && count($this->productTags)) { $value = 0; foreach($cart->products as $product) { $formulaCopy = hikashop_copy($formula->formula); $skip = $this->_replaceProductTags($formulaCopy, $product); if(!$skip) { if ($value==0) $value += $this->_evaluate($formulaCopy); } elseif($skip === 2) { break; } } } elseif($skip) { continue; } else { $value = $this->_evaluate($formula->formula); } if($value) { $additional = new stdClass(); $additional->price_currency_id = hikashop_getCurrency(); if($formula->fee_included) { $currencyClass = hikashop_get('class.currency'); $additional->value = $currencyClass->format($value, $additional->price_currency_id); } else { $additional->price_value = $value; $additional->price_value_with_tax = $value; } $additional->name = $formula->label; $key = 'fee_formula_'.$formula_id; if(is_array($cart->additional)) $cart->additional[$key] = $additional; else $cart->additional->$key = $additional; } } } private function _replaceProductTags(&$formulaCopy, &$product) { $skip = false; foreach($this->productTags as $tag) { $name = trim($tag, '{}'); $parts = explode('.', $name, 2); $table = $parts[0]; $column = $parts[1]; if($column == 'price') { if(isset($product->prices[0]->price_value_with_tax)) { $amount += $product->prices[0]->price_value_with_tax; } else { continue; } }elseif($column == 'unit_price') { if(isset($product->prices[0]->unit_price->price_value_with_tax)) { $amount += $product->prices[0]->unit_price->price_value_with_tax; } else { continue; } }elseif(is_object($product->$column) || is_array($product->$column)) { $app = JFactory::getApplication(); $app->enqueueMessage(JText::sprintf('THE_TAG_IS_INVALID_IN_FORMULA_Y', $tag, $formulaCopy), 'error'); $skip = 2; break; } else { $amount = $product->$column; $this->_prepareValue($amount); } if(!$skip) { $formulaCopy = str_replace($tag, $amount, $formulaCopy); } } return $skip; } private function _replaceMainTags(&$formula, &$cart) { $skip = false; if(!preg_match_all('/\{(.*)\}/mU',$formula, $matches)) { return $skip; } $done = array(); $skip = false; $this->productTags = array(); foreach($matches[0] as $k => $tag) { $name = $matches[1][$k]; switch($name) { case 'price': case 'cart.price': case 'order.price': $price = 0; if(isset($cart->full_total->prices[0]->price_value_with_tax)) { $price = $cart->full_total->prices[0]->price_value_with_tax; } $formula = str_replace($tag, $price, $formula); $done[] = $name; break; default: if(in_array($name, $done)) break; $table = 'order'; if(strpos($name,'.')) { $parts = explode('.', $name, 2); $table = $parts[0]; $column = $parts[1]; } else { $column = $name; } if($table == 'order') { if(empty($cart->cart_fields->$column)) { $skip = true; break 2; } if(is_object($cart->cart_fields->$column) && !empty($attribute) && isset($cart->cart_fields->$column->$attribute)) { $value = $cart->cart_fields->$column->$attribute; }else { if(is_object($cart->cart_fields->$column) || is_array($cart->cart_fields->$column)) { $app = JFactory::getApplication(); $app->enqueueMessage(JText::sprintf('THE_TAG_IS_INVALID_IN_FORMULA_Y', $tag, $formula), 'error'); $skip = true; break 2; } $value = $cart->cart_fields->$column; } $this->_prepareValue($value); $formula = str_replace($tag, $value, $formula); $done[] = $name; }elseif($table == 'cart') { if(empty($cart->$column)) { $skip = true; break 2; } if(is_array($cart->$column) && count($cart->$column) >= 1) { $el = reset($cart->$column); if(is_object($el) && !empty($attribute) && isset($el->$attribute) && !is_object($el->$attribute) && !is_array($el->$attribute)) { $value = $el->$attribute; } else { if(is_object($el) || is_array($el)) { $app = JFactory::getApplication(); $app->enqueueMessage(JText::sprintf('THE_TAG_IS_INVALID_IN_FORMULA_Y', $tag, $formula), 'error'); $skip = true; break 2; } $value = $el; } }elseif(is_object($cart->$column) && !empty($attribute) && isset($cart->$column->$attribute) && !is_object($cart->$column->$attribute) && !is_array($cart->$column->$attribute)) { $value = $cart->$column->$attribute; }else { if(is_object($cart->$column) || is_array($cart->$column)) { $app = JFactory::getApplication(); $app->enqueueMessage(JText::sprintf('THE_TAG_IS_INVALID_IN_FORMULA_Y', $tag, $formula), 'error'); $skip = true; break 2; } $value = $cart->$column; } $this->_prepareValue($value); $formula = str_replace($tag, $value, $formula); $done[] = $name; }elseif($table =='item' || $table == 'product') { if(!count($cart->products)) { $skip = true; break 2; } $this->productTags[] = $tag; } break; } } return $skip; } private function _evaluate($formula) { $e = hikashop_get('inc.expression'); $e->fb[] = 'strlen'; $e->fb[] = 'mb_strlen'; $e->fb[] = 'substr'; $e->fb[] = 'mb_substr'; $e->fb[] = 'trim'; $e->fb[] = 'str_word_count'; try { $result = $e->evaluate($formula); } catch(Exception $e) { $app = JFactory::getApplication(); $app->enqueueMessage($e->getMessage(), 'error'); return false; } return $result; } private function _prepareValue(&$value) { $text = false; if(!is_numeric($value)){ if(strpos($value, ',')) { $els = explode(',', $value); $allNumbers = true; $total = 0; foreach($els as $el) { if(!is_numeric($el)) { $allNumbers = false; break; } $total += $el; } if($allNumbers) { $value = $total; } else { $text = true; } } else { $text = true; } } if($text) { $value = "'".str_replace("'","\'", $value)."'"; } } }