/** * This function can parse an "advanced / custom attribute" * description like * Size:big[+2.99]; Color:red[+0.99] * and return the same string with values, tax added * Size: big (+3.47), Color: red (+1.15) * * @param string $description * @param int $product_id * @return string The reformatted description */ function getDescriptionWithTax($description, $product_id = 0) { global $CURRENCY_DISPLAY, $mosConfig_secret; require_once CLASSPATH . 'ps_product_attribute.php'; $auth = $_SESSION['auth']; $description = stripslashes($description); // if we've been given a description to deal with, get the adjusted price if ($description != '' && $auth["show_price_including_tax"] == 1 && $product_id != 0) { $my_taxrate = $this->get_product_taxrate($product_id); $price = $this->get_price($product_id); $product_currency = $price['product_currency']; } else { $my_taxrate = 0.0; $product_currency = ''; } // We must care for custom attribute fields! Their value can be freely given // by the customer, so we mustn't include them into the price calculation // Thanks to AryGroup@ua.fm for the good advice if (empty($_REQUEST["custom_attribute_fields"])) { if (!empty($_SESSION["custom_attribute_fields"])) { $custom_attribute_fields = vmGet($_SESSION, "custom_attribute_fields", array()); $custom_attribute_fields_check = vmGet($_SESSION, "custom_attribute_fields_check", array()); } else { $custom_attribute_fields = $custom_attribute_fields_check = array(); } } else { $custom_attribute_fields = $_SESSION["custom_attribute_fields"] = vmGet($_REQUEST, "custom_attribute_fields", array()); $custom_attribute_fields_check = $_SESSION["custom_attribute_fields_check"] = vmGet($_REQUEST, "custom_attribute_fields_check", array()); } $product_attributes = ps_product_attribute::getAdvancedAttributes($product_id); $attribute_keys = explode(";", $description); foreach ($attribute_keys as $temp_desc) { $finish = strpos($temp_desc, "]"); $temp_desc = trim($temp_desc); // Get the key name (e.g. "Color" ) $this_key = substr($temp_desc, 0, strpos($temp_desc, ":")); $this_value = substr($temp_desc, strpos($temp_desc, ":") + 1); if (in_array($this_key, $custom_attribute_fields)) { if (@$custom_attribute_fields_check[$this_key] == md5($mosConfig_secret . $this_key)) { // the passed value is valid, don't use it for calculating prices continue; } } if (isset($product_attributes[$this_key]['values'][$this_value])) { $modifier = $product_attributes[$this_key]['values'][$this_value]['adjustment']; $operand = $product_attributes[$this_key]['values'][$this_value]['operand']; $value_notax = $GLOBALS['CURRENCY']->convert($modifier, $product_currency); if (abs($value_notax) > 0) { $value_taxed = $value_notax * ($my_taxrate + 1); $temp_desc_new = str_replace($operand . $modifier, $operand . ' ' . $CURRENCY_DISPLAY->getFullValue($value_taxed), $temp_desc); $description = str_replace($this_key . ':' . $this_value, $this_key . ':' . $this_value . ' (' . $operand . ' ' . $CURRENCY_DISPLAY->getFullValue($value_taxed) . ')', $description); } $temp_desc = substr($temp_desc, $finish + 1); } } $description = str_replace($CURRENCY_DISPLAY->symbol, '@saved@', $description); $description = str_replace("[", " (", $description); $description = str_replace("]", ")", $description); $description = str_replace(":", ": ", $description); $description = str_replace(";", "<br/>", $description); $description = str_replace('@saved@', $CURRENCY_DISPLAY->symbol, $description); return $description; }
function get_adjusted_attribute_price($product_id, $quantity = 0, $description = '', $result_attributes = '') { global $mosConfig_secret; $auth = $_SESSION['auth']; $price = $this->get_price($product_id, $quantity, true, $result_attributes); $base_price = $price["product_price"]; $setprice = 0; $set_price = false; $adjustment = 0; // We must care for custom attribute fields! Their value can be freely given // by the customer, so we mustn't include them into the price calculation // Thanks to AryGroup@ua.fm for the good advice if (empty($_REQUEST["custom_attribute_fields"])) { if (!empty($_SESSION["custom_attribute_fields"])) { $custom_attribute_fields = vmGet($_SESSION, "custom_attribute_fields", array()); $custom_attribute_fields_check = vmGet($_SESSION, "custom_attribute_fields_check", array()); } else { $custom_attribute_fields = $custom_attribute_fields_check = array(); } } else { $custom_attribute_fields = $_SESSION["custom_attribute_fields"] = vmGet($_REQUEST, "custom_attribute_fields", array()); $custom_attribute_fields_check = $_SESSION["custom_attribute_fields_check"] = vmGet($_REQUEST, "custom_attribute_fields_check", array()); } // if we've been given a description to deal with, get the adjusted price if ($description != '') { // description is safe to use at this point cause it's set to '' require_once CLASSPATH . 'ps_product_attribute.php'; $product_attributes = ps_product_attribute::getAdvancedAttributes($product_id, true); $attribute_keys = explode(";", $description); for ($i = 0; $i < sizeof($attribute_keys); $i++) { $temp_desc = $attribute_keys[$i]; $temp_desc = trim($temp_desc); // Get the key name (e.g. "Color" ) $this_key = substr($temp_desc, 0, strpos($temp_desc, ":")); $this_value = substr($temp_desc, strpos($temp_desc, ":") + 1); if (in_array($this_key, $custom_attribute_fields)) { if (@$custom_attribute_fields_check[$this_key] == md5($mosConfig_secret . $this_key)) { // the passed value is valid, don't use it for calculating prices continue; } } if (isset($product_attributes[$this_key]['values'][$this_value])) { $modifier = $product_attributes[$this_key]['values'][$this_value]['adjustment']; $operand = $product_attributes[$this_key]['values'][$this_value]['operand']; // if we have a number, allow the adjustment if (true == is_numeric($modifier)) { // $modifier = $GLOBALS['CURRENCY']->convert( $modifier, $price['product_currency'], $GLOBALS['product_currency'] ); // Now add or sub the modifier on if ($operand == "+") { $adjustment += $modifier; } else { if ($operand == "-") { $adjustment -= $modifier; } else { if ($operand == '=') { // NOTE: the +=, so if we have 2 sets they get added // this could be moded to say, if we have a set_price, then // calc the diff from the base price and start from there if we encounter // another set price... just a thought. $setprice += $modifier; $set_price = true; } } } } } else { continue; } } } // no set price was set from the attribs if ($set_price == false) { $price["product_price"] = $base_price + $adjustment * (1 - $auth["shopper_group_discount"] / 100); } else { // otherwise, set the price // add the base price to the price set in the attributes // then subtract the adjustment amount // we could also just add the set_price to the adjustment... not sure on that one. if (!empty($adjustment)) { $setprice += $adjustment; } $setprice *= 1 - $auth["shopper_group_discount"] / 100; $price["product_price"] = $setprice; } // don't let negative prices get by, set to 0 if ($price["product_price"] < 0) { $price["product_price"] = 0; } // Get the DISCOUNT AMOUNT $ps_product = new ps_product(); $discount_info = $ps_product->get_discount($product_id); // Read user_info_id from db $dbu = new ps_DB(); $q = "SELECT user_info_id FROM #__{vm}_orders WHERE order_id = '" . $this->order_id . "' "; $dbu->query($q); $dbu->next_record(); $user_info_id = $dbu->f("user_info_id"); $prod_weight = $ps_product->get_weight($product_id); $my_taxrate = $ps_product->get_product_taxrate($product_id, $prod_weight, $user_info_id); // If discounts are applied after tax, but prices are shown without tax, // AND tax is EU mode and shopper is not in the EU, // then ps_product::get_product_taxrate() returns 0, so $my_taxrate = 0. // But, the discount still needs to be reduced by the shopper's tax rate, so we obtain it here: if (PAYMENT_DISCOUNT_BEFORE != '1' && $auth["show_price_including_tax"] != 1 && !ps_checkout::tax_based_on_vendor_address($user_info_id)) { $db = new ps_DB(); $ps_vendor_id = $_SESSION["ps_vendor_id"]; require_once CLASSPATH . 'ps_checkout.php'; if (!ps_checkout::tax_based_on_vendor_address($user_info_id)) { if ($auth["user_id"] > 0) { $q = "SELECT state, country FROM #__{vm}_user_info WHERE user_id='" . $auth["user_id"] . "'"; $db->query($q); $db->next_record(); $state = $db->f("state"); $country = $db->f("country"); $q = "SELECT tax_rate FROM #__{vm}_tax_rate WHERE tax_country='{$country}' "; if (!empty($state)) { $q .= "AND (tax_state='{$state}' OR tax_state=' {$state} ' OR tax_state='-')"; } $db->query($q); if ($db->next_record()) { $my_taxrate = $db->f("tax_rate"); } else { $my_taxrate = 0; } } else { $my_taxrate = 0; } } else { if (empty($_SESSION['taxrate'][$ps_vendor_id])) { // let's get the store's tax rate $q = "SELECT `tax_rate` FROM #__{vm}_vendor, #__{vm}_tax_rate "; $q .= "WHERE tax_country=vendor_country AND #__{vm}_vendor.vendor_id=1 "; // !! Important !! take the highest available tax rate for the store's country $q .= "ORDER BY `tax_rate` DESC"; $db->query($q); if ($db->next_record()) { $my_taxrate = $db->f("tax_rate"); } else { $my_taxrate = 0; } } else { $my_taxrate = $_SESSION['taxrate'][$ps_vendor_id]; } } } // Apply the discount if (!empty($discount_info["amount"])) { $undiscounted_price = $base_price; switch ($discount_info["is_percent"]) { case 0: if (PAYMENT_DISCOUNT_BEFORE == '1') { // If we subtract discounts BEFORE tax // Subtract the whole discount $price["product_price"] -= $discount_info["amount"]; } else { // But, if we subtract discounts AFTER tax // Subtract the untaxed portion of the discount $price["product_price"] -= $discount_info["amount"] / ($my_taxrate + 1); } break; case 1: $price["product_price"] -= $price["product_price"] * ($discount_info["amount"] / 100); break; } } return $price; }