'title' => $rule->getTitle(), 'type' => $rule_type, 'discount' => $discount, ]; } } return $applied_rule_discounts; } /** * Get applied discount details form cart discount details. */ private static function getAppliedRuleDiscountsFromCartDiscountDetails($cart_discount_details, $product_id = 0) { $applied_rule_discounts = []; if (is_array($cart_discount_details)) { foreach ($cart_discount_details as $rule_id => $details) { if (!isset(self::$available_rules[$rule_id])) { continue; } $rule = self::$available_rules[$rule_id]; $rule_type = substr($rule->getRuleDiscountType(), 4); // without prefix (wdr_) $discount = [ 'applied_in' => 'cart_level', 'discount_type' => isset($details['cart_discount_type']) ? $details['cart_discount_type'] : '', 'discount_value' => isset($details['cart_discount']) ? round($details['cart_discount']) : 0, 'discount_label' => isset($details['cart_discount_label']) ? $details['cart_discount_label'] : '', 'discount_price' => isset($details['cart_discount_product_price'][$product_id][$rule_id]) ? round($details['cart_discount_product_price'][$product_id][$rule_id], 4) : 0, ]; $applied_rule_discounts[] = [ 'id' => $rule_id, 'title' => $rule->getTitle(), 'type' => $rule_type, 'discount' => $discount, ]; } } return $applied_rule_discounts; } /** * Calculate the product's initial and discount price * @param $product * @param $quantity * @param $is_cart * @param $ajax_price * @return array|bool */ static function calculateInitialAndDiscountedPrice($product, $quantity, $is_cart = false, $ajax_price = false, $cart_item = array(), $on_coupon_validate = false) { return self::$calculator->getProductPriceToDisplay($product, $quantity, $is_cart, $ajax_price, $cart_item, $on_coupon_validate); } /** * Re-calculate cart total * */ public static function reCalculateCartTotal() { if (function_exists('WC')) { if(isset(WC()->cart) && WC()->cart != null){ if (is_object(WC()->cart) && method_exists(WC()->cart, 'calculate_totals')) { WC()->cart->calculate_totals(); } } } } /** * Calculate cart totals if is not calculated already * */ public static function calculateCartTotalIfIsNotCalculated() { if (!did_action('woocommerce_before_calculate_totals')) { self::reCalculateCartTotal(); } } /** * @param $discount_details * @param $initial_price * @param $discounted_price * @param $product_obj * @param $price_html * @param $cart_item_qty * @param $ajax_price * @return bool|string */ function getSetDiscountItemPriceHtml($discount_details, $initial_price, $discounted_price, $product_obj, $price_html, $cart_item_qty=0, $ajax_price = false) { if (is_array($discount_details) && !empty($discount_details)) { $bogo_cheapest_aditional = array(); $calculator = self::$calculator; $other_discounts = $total_discount_price = $total_quantity = $current_product_quantity = $discount_operator = $bogo_cheapest_aditional_sum = 0; $partially_qualified_set = array(); $partially_qualified_set_amount_duplicate = array(); $apply_full_set = false; $int_increment = 0; foreach ($discount_details as $detail_key => $detail) { $bogo_cheapest_discount = $bogo_cheapest_quantity = 0; //BOGO cheapest discount $bogo_cheap_in_cart = isset($detail['buy_x_get_y_cheapest_in_cart_discount']) ? $detail['buy_x_get_y_cheapest_in_cart_discount'] : ''; $bogo_cheap_in_products = isset($detail['buy_x_get_y_cheapest_from_products_discount']) ? $detail['buy_x_get_y_cheapest_from_products_discount'] : ''; $bogo_cheap_in_category = isset($detail['buy_x_get_y_cheapest_from_categories_discount']) ? $detail['buy_x_get_y_cheapest_from_categories_discount'] : ''; $bogo_auto_add = isset($detail['buy_x_get_y_discount']) ? $detail['buy_x_get_y_discount'] : ''; $bogo_getx = isset($detail['buy_x_get_x_discount']) ? $detail['buy_x_get_x_discount'] : ''; $buy_x_get_y_cheapest_additional = isset($detail['buy_x_get_y_cheapest_in_cart_discount']['additional_discounts']) ? $detail['buy_x_get_y_cheapest_in_cart_discount']['additional_discounts'] : ''; if(!empty($buy_x_get_y_cheapest_additional)){ $all_matched_rule = self::$config->getConfig('apply_product_discount_to', 'biggest_discount');//all foreach ($buy_x_get_y_cheapest_additional as $aditional){ if($all_matched_rule != 'all' && $price_html){ $price_html = $this->buy_x_get_y_cheapest_additional_strike_out($product_obj, $bogo_cheap_in_cart, $initial_price, $cart_item_qty); if(!empty($price_html)){ return $price_html; } } $bogo_cheapest_discount_aditional = isset($aditional['discount_price_per_quantity']) ? $aditional['discount_price_per_quantity'] : 0; $bogo_cheapest_quantity_aditional = isset($aditional['discount_quantity']) ? $aditional['discount_quantity'] : 0; $bogo_cheapest_aditional[] = $bogo_cheapest_discount_aditional*$bogo_cheapest_quantity_aditional; } if($all_matched_rule == 'all' && !empty($cart_item_qty)){ $bogo_cheapest_discount_extra = isset($bogo_cheap_in_cart['discount_price_per_quantity']) ? $bogo_cheap_in_cart['discount_price_per_quantity'] : 0; $bogo_cheapest_quantity_extra = isset($bogo_cheap_in_cart['discount_quantity']) ? $bogo_cheap_in_cart['discount_quantity'] : 0; $bogo_cheapest_aditional_discount = array_sum($bogo_cheapest_aditional); if($bogo_cheapest_quantity_extra > 1){ $bogo_cheapest_quantity_extra = (int)$bogo_cheapest_quantity_extra - 1; $bogo_cheapest_aditional_discount += $bogo_cheapest_discount_extra*$bogo_cheapest_quantity_extra; } if($cart_item_qty != 0){ $bogo_cheapest_aditional_discount = $bogo_cheapest_aditional_discount / $cart_item_qty; } $discounted_price = $discounted_price-$bogo_cheapest_aditional_discount; $bogo_cheap_in_cart = array(); }else{ $bogo_cheapest_aditional_sum = array_sum($bogo_cheapest_aditional); } } if(!empty($bogo_cheap_in_cart)){ $bogo_cheapest_discount = isset($bogo_cheap_in_cart['discount_price_per_quantity']) ? $bogo_cheap_in_cart['discount_price_per_quantity'] : 0; $bogo_cheapest_quantity = isset($bogo_cheap_in_cart['discount_quantity']) ? $bogo_cheap_in_cart['discount_quantity'] : 0; }elseif(!empty($bogo_cheap_in_products)){ $bogo_cheapest_discount = isset($bogo_cheap_in_products['discount_price_per_quantity']) ? $bogo_cheap_in_products['discount_price_per_quantity'] : 0; $bogo_cheapest_quantity = isset($bogo_cheap_in_products['discount_quantity']) ? $bogo_cheap_in_products['discount_quantity'] : 0; }elseif (!empty($bogo_cheap_in_category)){ $bogo_cheapest_discount = isset($bogo_cheap_in_category['discount_price_per_quantity']) ? $bogo_cheap_in_category['discount_price_per_quantity'] : 0; $bogo_cheapest_quantity = isset($bogo_cheap_in_category['discount_quantity']) ? $bogo_cheap_in_category['discount_quantity'] : 0; }elseif(!empty($bogo_auto_add)){ $bogo_cheapest_discount = isset($bogo_auto_add['discount_price_per_quantity']) ? $bogo_auto_add['discount_price_per_quantity'] : 0; $bogo_cheapest_quantity = isset($bogo_auto_add['discount_quantity']) ? $bogo_auto_add['discount_quantity'] : 0; }else{ $bogo_cheapest_discount = isset($bogo_getx['discount_price_per_quantity']) ? $bogo_getx['discount_price_per_quantity'] : 0; $bogo_cheapest_quantity = isset($bogo_getx['discount_quantity']) ? $bogo_getx['discount_quantity'] : 0; } $bogo_partial_set = ''; if(!empty($bogo_cheapest_quantity) && $bogo_cheapest_quantity < $cart_item_qty){ $bogo_partial_set = 'yes'; }elseif($bogo_cheapest_quantity == $cart_item_qty){ $bogo_cheapest_full_matched_set = $bogo_cheapest_discount; } $int_increment++; //per product quantity for set discount $fully_qualified_set = $discounted_price_per_set = $bogo_cheapest_full_matched_set = 0; $total_quantity = $cart_item_qty; $current_product_quantity = $cart_item_qty; if(!empty($detail['set_discount'])){ $total_quantity = isset($detail['set_discount']['total_quantity']) ? $detail['set_discount']['total_quantity'] : 0; $discount_operator = isset($detail['set_discount']['discount_operator']) ? $detail['set_discount']['discount_operator'] : ""; //original price quantity for set discount $original_price_quantity = isset($detail['set_discount']['original_price_quantity']) ? $detail['set_discount']['original_price_quantity'] : 0; //min set quantity $discounted_price_quantity = isset($detail['set_discount']['discounted_price_quantity']) ? $detail['set_discount']['discounted_price_quantity'] : 0; //set discounted price $discounted_price_per_set = isset($detail['set_discount']['discount_value']) ? $detail['set_discount']['discount_value'] : 0; $discounted_price_quantities = isset($detail['set_discount']['discounted_price_quantity']) ? $detail['set_discount']['discounted_price_quantity'] : 0; if (!empty($total_quantity)) { self::$set_total_quantity = $total_quantity; } if (empty($total_quantity)) { $total_quantity = self::$set_total_quantity; } } //simple discounted price if(isset($detail['simple_discount']) && is_array($detail['simple_discount'])){ $simple_discount = isset($detail['simple_discount']['discount_price']) ? $detail['simple_discount']['discount_price'] : 0; } else { $simple_discount = isset($detail['simple_discount']) ? $detail['simple_discount'] : 0; } //bulk discounted price if(isset($detail['bulk_discount']) && is_array($detail['bulk_discount'])){ $bulk_discounts = isset($detail['bulk_discount']['discount_price']) ? $detail['bulk_discount']['discount_price'] : 0; } else { $bulk_discounts = isset($detail['bulk_discount']) ? $detail['bulk_discount'] : 0; } //set discounted price quantity $total_discount_price += $discounted_price_per_set + $simple_discount + $bulk_discounts + $bogo_cheapest_discount; if (empty($original_price_quantity) && empty($discounted_price_quantity) && empty($bogo_partial_set)) { if (!empty($discounted_price_per_set)) { $fully_qualified_set = $discounted_price_per_set; } } else { if(!empty($detail['set_discount']) && !empty($discounted_price_per_set) && !empty($discounted_price_quantities)){ if (isset($partially_qualified_set[$discounted_price_per_set]) && !empty($partially_qualified_set[$discounted_price_per_set])) { $partially_qualified_set_amount_duplicate[$discounted_price_per_set . '-' . $int_increment] = $discounted_price_quantities; } else { $partially_qualified_set[$discounted_price_per_set] = $discounted_price_quantities; } } if(!empty($bogo_partial_set)){ $int_increment++; if (isset($partially_qualified_set[$bogo_cheapest_discount]) && !empty($partially_qualified_set[$bogo_cheapest_discount])) { $partially_qualified_set_amount_duplicate[$bogo_cheapest_discount . '-' . $int_increment] = $bogo_cheapest_quantity; } else { $partially_qualified_set[$bogo_cheapest_discount] = $bogo_cheapest_quantity; } } } $other_discounts += $simple_discount + $bulk_discounts + $fully_qualified_set + $bogo_cheapest_full_matched_set + $bogo_cheapest_aditional_sum; } $initial_price_with_tax_call = $discounted_price_with_tax_call = 0; if (empty($partially_qualified_set) || $apply_full_set == true) { if ($price_html) { if($ajax_price){ $discounted_price = $initial_price - $discounted_price; if($discounted_price < 0){ $discounted_price = 0; } if(!empty($initial_price)){ $initial_price_with_tax_call = $calculator->mayHaveTax($product_obj, $initial_price); } if(!empty($discounted_price)){ $discounted_price_with_tax_call = $calculator->mayHaveTax($product_obj, $discounted_price); } $item_price = $this->getStrikeoutPrice($initial_price_with_tax_call, $discounted_price_with_tax_call); return $item_price.Woocommerce::getProductPriceSuffix($product_obj, $discounted_price_with_tax_call); } if(!empty($initial_price)){ $initial_price_with_tax_call = $calculator->mayHaveTax($product_obj, $initial_price); } if(!empty($discounted_price)){ $discounted_price_with_tax_call = $calculator->mayHaveTax($product_obj, $discounted_price); } $item_price = $this->getStrikeoutPrice($initial_price_with_tax_call, $discounted_price_with_tax_call); return $item_price.Woocommerce::getProductPriceSuffix($product_obj, $discounted_price_with_tax_call); } else { if($discounted_price < 0){ $discounted_price = 0; } return $discounted_price; ///return false; } } else { $original_item_price_html = $this->getSetStrikeoutPrice($initial_price, $partially_qualified_set, $total_discount_price, $other_discounts, $total_quantity, $product_obj, $price_html, $current_product_quantity, $discount_operator, $partially_qualified_set_amount_duplicate); return $original_item_price_html; } } else { return false; } } /** * buy_x_get_y_cheapest_additional_strike_out * @param $product_obj * @param $bogo_cheap_in_cart * @param $initial_price * @param $cart_item_qty * @return string */ public function buy_x_get_y_cheapest_additional_strike_out($product_obj, $bogo_cheap_in_cart, $initial_price, $cart_item_qty) { $price_html = $original_price_with_tax_call = $discounted_price_with_tax_call = ''; $bogo_cheap_in_cart_first_discount = isset($bogo_cheap_in_cart['discount_price_per_quantity']) ? $bogo_cheap_in_cart['discount_price_per_quantity'] : 0; $bogo_cheap_in_cart_first_discount_qty = isset($bogo_cheap_in_cart['discount_quantity']) ? $bogo_cheap_in_cart['discount_quantity'] : 0; $discounted_price = $bogo_cheap_in_cart_first_discount * $bogo_cheap_in_cart_first_discount_qty; $discounted_price = $initial_price - $discounted_price; if(!empty($initial_price)){ $original_price_with_tax_call = self::$calculator->mayHaveTax($product_obj, $initial_price); } if(!empty($discounted_price)){ $discounted_price_with_tax_call = self::$calculator->mayHaveTax($product_obj, $discounted_price); } $price_suffix = Woocommerce::getProductPriceSuffix($product_obj, $discounted_price_with_tax_call); $price_html .= '' . self::$woocommerce_helper->formatPrice($original_price_with_tax_call) . ' ' . self::$woocommerce_helper->formatPrice($discounted_price_with_tax_call) .$price_suffix. ' x ' . $bogo_cheap_in_cart_first_discount_qty . '
'; $bogo_cheap_in_cart_total_discount_qty[] = $bogo_cheap_in_cart_first_discount_qty; $bogo_cheap_in_cart_additional_discounts = $bogo_cheap_in_cart['additional_discounts']; foreach ($bogo_cheap_in_cart_additional_discounts as $additional_discount){ $bogo_cheapest_discount_aditional = isset($additional_discount['discount_price_per_quantity']) ? $additional_discount['discount_price_per_quantity'] : 0; $bogo_cheapest_quantity_aditional = isset($additional_discount['discount_quantity']) ? $additional_discount['discount_quantity'] : 0; $discounted_price = $bogo_cheapest_discount_aditional * $bogo_cheapest_quantity_aditional; $discounted_price = $initial_price - $discounted_price; if(!empty($discounted_price)){ $discounted_price_with_tax_call = self::$calculator->mayHaveTax($product_obj, $discounted_price); } $price_suffix = Woocommerce::getProductPriceSuffix($product_obj, $discounted_price_with_tax_call); $price_html .= '' . self::$woocommerce_helper->formatPrice($original_price_with_tax_call) . ' ' . self::$woocommerce_helper->formatPrice($discounted_price_with_tax_call) .$price_suffix. ' x ' . $bogo_cheapest_quantity_aditional . '
'; $bogo_cheap_in_cart_total_discount_qty[] = $bogo_cheapest_quantity_aditional; } $discount_applied_qty = array_sum($bogo_cheap_in_cart_total_discount_qty); if($discount_applied_qty < $cart_item_qty){ $not_applied = $cart_item_qty - $discount_applied_qty; $price_suffix = Woocommerce::getProductPriceSuffix($product_obj, $original_price_with_tax_call); $price_html .= '' . self::$woocommerce_helper->formatPrice($original_price_with_tax_call) .$price_suffix. ' x ' . $not_applied . ''; } return $price_html; } /** * Calculate discount for product or calculate discount from custom price * @param $price * @param $product * @param int $quantity * @param int $custom_price * @param string $get_only * @return array|float|false */ static function calculateProductDiscountPrice($price, $product, $quantity = 1, $custom_price = 0, $get_only = 'discounted_price', $manual_request = false, $is_cart = true) { if (!is_a($product, 'WC_Product')) { if (is_numeric($product)) { $product = self::$woocommerce_helper->getProduct($product); } else { return false; } } if (!$product) { return false; } $discounts = self::$calculator->mayApplyPriceDiscount($product, $quantity, $custom_price, false, array(), $is_cart, $manual_request); if ($discounts) { switch ($get_only) { case 'all': $product_id = self::$woocommerce_helper->getProductId($product); if (isset($discounts['total_discount_details'][$product_id])) { $discounts['total_discount_details'] = $discounts['total_discount_details'][$product_id]; } if (isset($discounts['cart_discount_details'])) { unset($discounts['cart_discount_details']); } $price = $discounts; break; default: case 'discounted_price': $price = isset($discounts['discounted_price']) ? $discounts['discounted_price'] : $price; break; } } else { return false; } return $price; } /** * Get discount price of a product * @param int|float|false $product_price * @param int|\WC_Product $product_or_id * @param int|float $quantity * @param int|float $custom_price * @return float|false * */ static function getDiscountPriceOfAProduct($product_price, $product_or_id, $quantity = 1, $custom_price = 0) { $details = self::getDiscountDetailsOfAProduct(false, $product_or_id, $quantity, $custom_price); if ($details !== false && isset($details['discounted_price'])) { return (float) $details['discounted_price']; } return $product_price; } /** * Get discount details of a product * @param array|false $discount_details * @param int|\WC_Product $product_or_id * @param int|float $quantity * @param int|float $custom_price * @return array|false * */ static function getDiscountDetailsOfAProduct($discount_details, $product_or_id, $quantity = 1, $custom_price = 0) { $product = $product_or_id; if (is_numeric($product)) { $product = self::$woocommerce_helper->getProduct($product); } if (!is_object($product) || !is_a($product, 'WC_Product')) { return false; } if (Woocommerce::productTypeIs($product, array('variable'))) { $variation_product = Woocommerce::getFirstChildOfVariableProduct($product); if (is_object($variation_product)) { $product = $variation_product; } } $discounts = self::calculateProductDiscountPrice(false, $product, $quantity, $custom_price, 'all', true, false); if ($discounts !== false && is_array($discounts)) { return self::prepareDiscountDetails($discounts); } return $discount_details; } /** * Get discount percentage of a product * @param int|float|false $discount_percentage * @param int|\WC_Product $product_or_id * @return float|false * */ static function getDiscountPercentageOfAProduct($discount_percentage, $product_or_id) { $details = self::getDiscountDetailsOfAProduct(false, $product_or_id); if ($details !== false && is_array($details) && !empty($details['initial_price']) && isset($details['discounted_price'])) { return round((($details['initial_price'] - $details['discounted_price']) / $details['initial_price']) * 100, 4); } return $discount_percentage; } /** * Get save amount of a product * @param int|float|false $save_amount * @param int|\WC_Product $product_or_id * @return float|false * */ static function getSaveAmountOfAProduct($save_amount, $product_or_id) { if ($details = self::getDiscountDetailsOfAProduct(false, $product_or_id)) { if (is_array($details) && !empty($details['initial_price_based_on_tax_settings']) && isset($details['discounted_price_based_on_tax_settings'])) { return round($details['initial_price_based_on_tax_settings'] - $details['discounted_price_based_on_tax_settings'], 4); } } return $save_amount; } /** * Get discount price of a product in cart * @param int|float|false $product_price * @param string|array $cart_item_or_key * @return float|false * */ static function getDiscountPriceFromCartItem($product_price, $cart_item_or_key) { if ($data = self::getDiscountDetailsFromCartItem(false, $cart_item_or_key)) { if (is_array($data) && isset($data['discounted_price'])) { return (float) $data['discounted_price']; } } return $product_price; } /** * Get discount details of a product in cart * @param array|false $discount_details * @param string|array $cart_item_or_key * @return array|false * */ static function getDiscountDetailsFromCartItem($discount_details, $cart_item_or_key) { if (is_array($cart_item_or_key) && isset($cart_item_or_key['key'])) { $cart_item = $cart_item_or_key; $key = (string) $cart_item['key']; } elseif (is_string($cart_item_or_key)) { $key = $cart_item_or_key; $cart_item = self::$woocommerce_helper->getCartItem($key); } if (empty($key) || empty($cart_item) || !is_array($cart_item)) { return false; } $product_id = $cart_item['variation_id'] > 0 ? $cart_item['variation_id'] : $cart_item['product_id']; if (isset(self::$calculated_cart_item_discount[$key])) { $cart_item_discounts = self::$calculated_cart_item_discount[$key]; } if (empty($cart_item_discounts) && $free_item_discounts = apply_filters('advanced_woo_discount_rules_get_auto_add_discount_details_from_cart_item', array(), $cart_item, $key)) { $cart_item_discounts = $free_item_discounts; } if (!empty($cart_item_discounts)) { return self::prepareDiscountDetails($cart_item_discounts, $product_id, 1, $key); } return $discount_details; } /** * Get save amount of a product in cart * @param int|float|false $saved_amount * @param string|array $cart_item_or_key * @return float|false * */ static function getSavedAmountFromCartItem($saved_amount, $cart_item_or_key) { if ($details = self::getDiscountDetailsFromCartItem(false, $cart_item_or_key)) { if (is_array($details) && !empty($details['initial_price_based_on_tax_settings']) && isset($details['discounted_price_based_on_tax_settings'])) { return round($details['initial_price_based_on_tax_settings'] - $details['discounted_price_based_on_tax_settings'], 4); } } return $saved_amount; } /** * Get discount of a product in order * @param int|float|false $product_price * @param int|\WC_Order_Item $order_item_or_id * @return float|false * */ static function getDiscountPriceFromOrderItem($product_price, $order_item_or_id) { if ($details = self::getDiscountDetailsFromOrderItem(false, $order_item_or_id)) { if (is_array($details) && isset($details['discounted_price'])) { return (float) $details['discounted_price']; } } return $product_price; } /** * Get discount details of a product in order * @param array|false $discount_details * @param int|\WC_Order_Item $order_item_or_id * @return array|false * */ static function getDiscountDetailsFromOrderItem($discount_details, $order_item_or_id) { if (is_object($order_item_or_id) && is_a($order_item_or_id, '\WC_Order_Item')) { $order_item = $order_item_or_id; } elseif (is_numeric($order_item_or_id)) { $order_item = self::$woocommerce_helper->getOrderItem($order_item_or_id); } else { return false; } if (is_object($order_item) && method_exists($order_item, 'get_meta')) { $data = $order_item->get_meta('_wdr_discounts'); if (empty($data)) { $data = $order_item->get_meta('_advanced_woo_discount_item_total_discount'); if (!empty($data) && is_array($data)) { $data['initial_price_with_tax'] = $data['initial_price_based_on_tax_settings']; $data['discounted_price_with_tax'] = $data['discounted_price_based_on_tax_settings']; return self::prepareDiscountDetails($data); } } if (!empty($data) && is_array($data)) { return $data; } return $discount_details; } return false; } /** * Get save amount of a product in order * @param int|float|false $saved_amount * @param int|\WC_Order_Item $order_item_or_id * @return float|false * */ static function getSavedAmountFromOrderItem($saved_amount, $order_item_or_id) { if ($details = self::getDiscountDetailsFromOrderItem(false, $order_item_or_id)) { if (is_array($details) && !empty($details['initial_price_based_on_tax_settings']) && isset($details['discounted_price_based_on_tax_settings'])) { return round($details['initial_price_based_on_tax_settings'] - $details['discounted_price_based_on_tax_settings'], 4); } } return $saved_amount; } /** * Get discount details from order * @param array|false $discount_details * @param int|\WC_Order $order_or_id * @return array|false * */ static function getDiscountDetailsFromOrder($discount_details, $order_or_id) { if (is_object($order_or_id) && is_a($order_or_id, '\WC_Order')) { $order = $order_or_id; } elseif (is_numeric($order_or_id)) { $order = self::$woocommerce_helper->getOrder($order_or_id); } else { return false; } if (is_object($order) && method_exists($order, 'get_meta')) { $data = $order->get_meta('_wdr_discounts'); if (!empty($data) && is_array($data)) { return $data; } return $discount_details; } return false; } /** * Get save amount from order * @param int|float|false $saved_amount * @param int|\WC_Order $order_or_id * @return float|false * */ static function getSavedAmountFromOrder($saved_amount, $order_or_id) { if ($details = self::getDiscountDetailsFromOrder(false, $order_or_id)) { if (is_array($details) && isset($details['saved_amount']['total_based_on_tax_settings'])) { return $details['saved_amount']['total_based_on_tax_settings']; } } return $saved_amount; } /** * Change the default template for sale badge * * @param $located string * @param $template_name string * @param $args array * @param $template_path string * @param $default_path string * @return string * */ public static function changeTemplateForSaleTag($located, $template_name, $args, $template_path, $default_path){ if($template_name == 'single-product/sale-flash.php'){ $located = Helper::getTemplatePath('sale-flash.php', WDR_PLUGIN_PATH . 'App/Views/Templates/single-product/sale-flash.php', 'single-product'); } else if($template_name == 'loop/sale-flash.php'){ $located = Helper::getTemplatePath('sale-flash.php', WDR_PLUGIN_PATH . 'App/Views/Templates/loop/sale-flash.php', 'loop'); } return $located; } /** * Remove on sale flash except our hooks * */ function removeOnSaleFlashEvent(){ $allowed_hooks = array( //Filters "woocommerce_sale_flash" => array( "Wdr\App\Controllers\ManageDiscount|replaceSaleTagText" ), ); $this->removeOtherEvents($allowed_hooks); } /** * Suppress third party discount plugins from accessing the discount data */ function suppressOtherDiscountPlugins() { $allowed_hooks = array( //Filters "woocommerce_get_price_html" => array("Wdr\App\Controllers\ManageDiscount|getPriceHtml", "Wdr\App\Controllers\ManageDiscount|getPriceHtmlSalePriceAdjustment"), "woocommerce_product_is_on_sale" => array("Wdr\App\Controllers\ManageDiscount|isProductInSale"), "woocommerce_product_get_sale_price" => array(), "woocommerce_product_get_regular_price" => array(), "woocommerce_variable_price_html" => array("Wdr\App\Controllers\ManageDiscount|getVariablePriceHtml"), "woocommerce_cart_item_price" => array("Wdr\App\Controllers\ManageDiscount|getCartPriceHtml"), "woocommerce_cart_item_subtotal" => array("Wdr\App\Controllers\ManageDiscount|getCartProductSubtotalPriceHtml"), //Actions "woocommerce_checkout_order_processed" => array(), "woocommerce_before_calculate_totals" => array("Wdr\App\Controllers\ManageDiscount|applyCartProductDiscount"), //nothing allowed! ); $allowed_hooks = apply_filters('advanced_woo_discount_rules_exclude_hooks_from_removing', $allowed_hooks); $this->removeOtherEvents($allowed_hooks); } /** * Remove methods from the event * Exclude from the list * * @param $allowed_hooks array * */ function removeOtherEvents($allowed_hooks){ global $wp_filter; foreach ($wp_filter as $hook_name => $hook_obj) { if (preg_match('#^woocommerce_#', $hook_name)) { if (isset($allowed_hooks[$hook_name])) { $wp_filter[$hook_name] = $this->removeWrongCallbacks($hook_obj, $allowed_hooks[$hook_name]); } } } } /** * Remove the third party call backs * @param $hook_obj * @param $allowed_hooks * @return mixed */ function removeWrongCallbacks($hook_obj, $allowed_hooks) { if (method_exists($hook_obj, 'offsetSet') && method_exists($hook_obj, 'offsetUnset')) { foreach ($hook_obj->callbacks as $priority => $callbacks) { $priority_callbacks = array(); foreach ($callbacks as $idx => $callback_details) { if ($this->isCallbackMatch($callback_details, $allowed_hooks)) { $priority_callbacks[$idx] = $callback_details; } } $hook_obj->offsetUnset($priority); if ($priority_callbacks) { $hook_obj->offsetSet($priority, $priority_callbacks); } } } else { $new_callbacks = array(); foreach ($hook_obj->callbacks as $priority => $callbacks) { $priority_callbacks = array(); foreach ($callbacks as $idx => $callback_details) { if ($this->isCallbackMatch($callback_details, $allowed_hooks)) { $priority_callbacks[$idx] = $callback_details; } } if ($priority_callbacks) { $new_callbacks[$priority] = $priority_callbacks; } } $hook_obj->callbacks = $new_callbacks; } return $hook_obj; } /** * check the call back matched or not * @param $callback_details * @param $allowed_hooks * @return bool */ function isCallbackMatch($callback_details, $allowed_hooks) { $result = false; foreach ($allowed_hooks as $callback_name) { list($class_name, $func_name) = explode("|", $callback_name); if(empty($callback_details['function'])){ continue; } if(is_string($callback_details['function'])){ continue; } if(is_object($callback_details['function'])){ if($this->is_closure($callback_details['function'])){ continue; } } if (count($callback_details['function']) != 2) { continue; } if(!is_object($callback_details['function'][0])){ continue; } if ($class_name == get_class($callback_details['function'][0]) AND $func_name == $callback_details['function'][1]) { $result = true; break;// done! } } return $result; } function is_closure($t) { if(class_exists('\Closure')){ return $t instanceof \Closure; } else { return false; } } /** * Display you saved text in order pages * @param $total * @param $order * @return string */ function displayTotalSavingsInOrderAfterOrderTotal($total, $order) { if (!is_object($order)) { if (!empty($order) && is_int($order)) { $order = self::$woocommerce_helper->getOrder($order); } } $items = $order->get_items(); $total_discount = $this->getItemTotalDiscount($items); $save_text = NULL; if (!empty($total_discount)) { $total_discounted_price = self::$woocommerce_helper->formatPrice($total_discount, array('currency' => self::$woocommerce_helper->getOrderCurrency($order))); $subtotal_additional_text = $this->getYouSavedText($total_discounted_price); $save_text = apply_filters('advanced_woo_discount_rules_order_saved_text', $subtotal_additional_text, $total_discounted_price, $total_discount,['filter_type'=>'complete_order_total','order'=>$order, 'item'=>$items]); } return $total . $save_text; } /** * Calculate items total discount * @param $items * @return float|int */ function getItemTotalDiscount($items) { $total_discount = 0; if (!empty($items)) { foreach ($items as $key => $item) { $discount_details = $item->get_meta('_advanced_woo_discount_item_total_discount'); if (!empty($discount_details)) { $total_discount += $this->getDiscountPerItem($discount_details); } } } return $total_discount; } /** * order line item saved text * @param $subtotal * @param $item * @param $order * @return string */ function orderSubTotalDiscountDetails($subtotal, $item, $order) { $discount_details = self::$woocommerce_helper->getOrderItemMeta($item, '_advanced_woo_discount_item_total_discount'); if (!empty($discount_details)) { $total_discount = $this->getDiscountPerItem($discount_details); if (!empty($total_discount)) { $total_discounted_price = self::$woocommerce_helper->formatPrice($total_discount, array('currency' => self::$woocommerce_helper->getOrderCurrency($order))); $subtotal_additional_text = $this->getYouSavedText($total_discounted_price); $subtotal .= apply_filters('advanced_woo_discount_rules_order_saved_text', $subtotal_additional_text, $total_discounted_price, $total_discount,['filter_type'=>'complete_order_line_item','order'=> $order, 'item'=>$item]); } } return $subtotal; } /** * Show order discount details * @param $item_id * @param $item * @param $product */ public function orderItemMetaDiscountDetails($item_id, $item, $product) { $discount_details = self::$woocommerce_helper->getOrderItemMeta($item, '_advanced_woo_discount_item_total_discount'); if (!empty($discount_details)) { $total_discount = $this->getDiscountPerItem($discount_details); $order = self::$woocommerce_helper->getOrderByItem($item); if (!empty($order) && !empty($total_discount)) { $total_discounted_price = self::$woocommerce_helper->formatPrice($total_discount, array('currency' => self::$woocommerce_helper->getOrderCurrency($order))); $subtotal_additional_text = $this->getYouSavedText($total_discounted_price); echo wp_kses_post(apply_filters('advanced_woo_discount_rules_order_saved_text', $subtotal_additional_text, $total_discounted_price, $total_discount,['filter_type'=>'woo_order_line_item','order'=>$order, 'item'=>$item])); } } } /** * Hide Zero Coupon Value * @param $coupon_html * @param $coupon * @return mixed */ public function hideZeroCouponValue($coupon_html, $coupon) { $hide_zero_value_coupon = apply_filters('advanced_woo_discount_rules_hide_zero_value_coupon', true, $coupon); if ($hide_zero_value_coupon) { $rule_helper = new Rule(); $original_coupon_html = $coupon_html; $all_coupon_codes = $rule_helper->getCouponsFromDiscountRules(); $coupon_code = self::$woocommerce_helper->getCouponCode($coupon); $virtual_coupon = (isset($all_coupon_codes['custom_coupons']) && !empty($all_coupon_codes['custom_coupons'])) ? array_map('strtolower',$all_coupon_codes['custom_coupons']) : []; $woo_coupons = (isset($all_coupon_codes['woo_coupons'][0]) && !empty($all_coupon_codes['woo_coupons'][0])) ? $all_coupon_codes['woo_coupons'][0] : []; if (!empty($woo_coupons) && in_array($coupon_code, $woo_coupons)) { $zero_price_html = '-' . self::$woocommerce_helper->formatPrice(0); $coupon_html = str_replace($zero_price_html, '', $coupon_html); } else if (!empty($virtual_coupon) && in_array(strtolower($coupon_code), $virtual_coupon)) { $zero_price_html = '-' . self::$woocommerce_helper->formatPrice(0); $coupon_html = str_replace($zero_price_html, '', $coupon_html); } $coupon_html = apply_filters('advanced_woo_discount_rules_hide_zero_value_coupon_html', $coupon_html, $original_coupon_html, $coupon); } return $coupon_html; } /** * Display promotional messages * */ public function displayPromotionMessages(){ $cart = Woocommerce::getCart(); $messages = Helper::getPromotionMessages(); $messages = empty($cart) ? '' : $messages; if(!empty($messages) && is_array($messages)) { foreach ($messages as $message) { self::$woocommerce_helper->printNotice($message, "notice"); } } } /** * Load outer div for displaying promotional message in check out * */ public function displaySubTotalPromotionMessagesInCheckoutContainer(){ echo "
"; echo "
"; } /** * Display promotional message in check out while processing order review * */ public function displaySubTotalPromotionMessagesInCheckout(){ echo "
"; $this->displayPromotionMessages(); echo "
"; echo ""; } /** * Export Data via CSV */ public function awdrExportCsv(){ if (isset($_POST['wdr-export']) && isset($_POST['security'])) { if(wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['security'])),'awdr_export_rules')) { ob_end_clean(); $rule_helper = new Rule(); $rules = $rule_helper->exportRuleByName('all'); $file_name = 'advanced-discount-rules-' . gmdate("Y-m-d-h-i-a") . '.csv'; $file = fopen('php://output', 'w'); header('Content-type: application/csv'); header('Content-Disposition: attachment; filename=' . $file_name); $export_csv_separator = apply_filters('advanced_woo_discount_rules_csv_import_export_separator', ','); $enclosure = apply_filters('advanced_woo_discount_rules_csv_import_export_encloser','"'); $escape = apply_filters('advanced_woo_discount_rules_csv_import_export_escape',"\\"); fputcsv($file, array('id', 'enabled', 'deleted', 'exclusive', 'title', 'priority', 'apply_to', 'filters', 'conditions', 'product_adjustments', 'cart_adjustments', 'buy_x_get_x_adjustments', 'buy_x_get_y_adjustments', 'bulk_adjustments', 'set_adjustments', 'other_discounts', 'date_from', 'date_to', 'usage_limits', 'rule_language', 'used_limits', 'additional', 'max_discount_sum', 'advanced_discount_message', 'discount_type', 'used_coupons', 'created_by', 'created_on', 'modified_by', 'modified_on'), $export_csv_separator,$enclosure,$escape); foreach ($rules as $rule_row) { $row_data = (array)$rule_row; fputcsv($file, $row_data, $export_csv_separator, $enclosure, $escape); } exit; } } } /** * Display total savings in order * @param $order */ public function displayTotalSavingsThroughDiscountInOrder($order){ if (!is_object($order)) { if (!empty($order) && is_int($order)) { $order = self::$woocommerce_helper->getOrder($order); } } $items = $order->get_items(); $total_discount = $this->getItemTotalDiscount($items); $save_text = NULL; if (!empty($total_discount)) { $total_discounted_price = self::$woocommerce_helper->formatPrice($total_discount, array('currency' => self::$woocommerce_helper->getOrderCurrency($order))); $subtotal_additional_text = $this->getYouSavedText($total_discounted_price); $save_text = apply_filters('advanced_woo_discount_rules_order_saved_text', $subtotal_additional_text, $total_discounted_price, $total_discount,['filter_type'=>'woo_order_total','order'=>$order, 'item'=>$items]); } echo wp_kses_post($save_text); } /** * Include tax in fee * */ public function applyTaxInFee($fee, $cart){ if(Woocommerce::isTaxEnabled() && apply_filters('advanced_woo_discount_rules_is_allow_tax_calculation_for_fee',true,$fee,$cart)){ if(Woocommerce::isEnteredPriceIncludeTax()){ if(class_exists('\WC_Tax')){ $fee_taxs = \WC_Tax::calc_tax( $fee, \WC_Tax::get_rates( '', \WC()->cart->get_customer() ), true ); if(!empty($fee_taxs)){ foreach ($fee_taxs as $key => $val){ $fee = $fee - $val; } } } } } return $fee; } /** * Change the custom taxonomies label * * @param $custom_taxonomies * * @return array */ public static function changeCustomTaxonomyLabel($custom_taxonomies){ if(!empty($custom_taxonomies) && is_array($custom_taxonomies) && method_exists(Woocommerce::class,'changeCustomTaxonomyLabel') ){ return Woocommerce::changeCustomTaxonomyLabel($custom_taxonomies); } return $custom_taxonomies; } /** * Add coupon meta data to validate the coupon restrictions * * @param $item * @param $code * @param $coupon * @param $order */ public static function addCouponMeta($item, $code, $coupon, $order ){ if ( is_a( $coupon, 'WC_Coupon' ) ) { !empty($coupon->get_product_ids()) ? $item->add_meta_data( 'wdr_apply_coupon_product_ids', $coupon->get_product_ids(), true ) : ''; !empty($coupon->get_excluded_product_ids()) ? $item->add_meta_data( 'wdr_exclude_product_ids', $coupon->get_excluded_product_ids(), true ): ''; !empty($coupon->get_product_categories()) ? $item->add_meta_data( 'wdr_product_categories', $coupon->get_product_categories(), true ): ''; !empty($coupon->get_excluded_product_categories()) ? $item->add_meta_data( 'wdr_exclude_product_categories', $coupon->get_excluded_product_categories(), true ): ''; !empty($coupon->get_exclude_sale_items()) ? $item->add_meta_data( 'wdr_exclude_sale_items', $coupon->get_exclude_sale_items(), true ): ''; !empty($coupon->get_minimum_amount()) ? $item->add_meta_data( 'wdr_minimum_amount', $coupon->get_minimum_amount(), true ): ''; !empty($coupon->get_maximum_amount()) ? $item->add_meta_data( 'wdr_maximum_amount', $coupon->get_maximum_amount(), true ): ''; !empty($coupon->get_email_restrictions()) ? $item->add_meta_data( 'wdr_customer_emails', $coupon->get_email_restrictions(), true ): ''; !empty($coupon->get_usage_limit()) ? $item->add_meta_data( 'wdr_usage_limit', $coupon->get_usage_limit(), true ): ''; !empty($coupon->get_usage_limit_per_user()) ? $item->add_meta_data( 'wdr_usage_limit_per_user', $coupon->get_usage_limit_per_user(), true ): ''; } } /** * validate the coupon restrictions based on product, category, sale items * * @param $valid * @param $product * @param $coupon * @param $order_item * * @return false */ public static function validateCoupon( $valid, $product, $coupon, $order_item ) { // Only proceed if we are in admin and wc_get_order() exists if ( ! $order_item || ! is_admin() || ! function_exists( 'wc_get_order' ) ) { return $valid; } //Safely get order ID (works for both array and object) $order_id = 0; if ( is_object( $order_item ) && method_exists( $order_item, 'get_order_id' ) ) { $order_id = $order_item->get_order_id(); } elseif ( is_array( $order_item ) && ! empty( $order_item['order_id'] ) ) { $order_id = absint( $order_item['order_id'] ); } if ( ! $order_id ) { return $valid; } // Check if function wc_get_order exists before calling if ( ! function_exists( 'wc_get_order' ) ) { return $valid; } $order = wc_get_order( $order_id ); if ( ! $order ) { return $valid; } $coupon_code = $coupon->get_code(); $matched_coupon_item = null; // Loop through coupon items foreach ( $order->get_items( 'coupon' ) as $order_coupon ) { if ( strtolower( $order_coupon->get_code() ) === strtolower( $coupon_code ) ) { $matched_coupon_item = $order_coupon; break; } } if ( ! $matched_coupon_item ) { return $valid; } // Safely get product data if ( ! is_object( $product ) || ! method_exists( $product, 'get_id' ) ) { return $valid; } $product_id = $product->get_id(); $product_cats = method_exists( $product, 'get_category_ids' ) ? $product->get_category_ids() : []; $product_on_sale = method_exists( $product, 'is_on_sale' ) ? $product->is_on_sale() : false; // Coupon restrictions $coupon_product_ids = array_filter((array) $matched_coupon_item->get_meta( 'wdr_apply_coupon_product_ids', true )); if ( ! empty( $coupon_product_ids ) ) { if ( method_exists( $product, 'is_type' ) && $product->is_type( 'variation' ) ) { $parent_product_id = $product->get_parent_id(); if ( in_array( $parent_product_id, $coupon_product_ids, true ) ) { $parent_product = wc_get_product( $parent_product_id ); if ( is_object( $parent_product ) && method_exists( $parent_product, 'get_children' ) ) { $variable_product_ids = $parent_product->get_children(); if ( is_array( $variable_product_ids ) && ! empty( $variable_product_ids ) ) { $coupon_product_ids = array_merge( $coupon_product_ids, $variable_product_ids ); } } } } if ( ! in_array( $product_id, $coupon_product_ids, true ) ) { return false; } } // Excluded products $exclude_product_ids = array_filter((array) $matched_coupon_item->get_meta( 'wdr_exclude_product_ids', true )); if ( ! empty($exclude_product_ids ) && in_array( $product_id, $exclude_product_ids, true ) ) { return false; } // Allowed categories (your logic was reversed) $allowed_cats = array_filter( (array)$matched_coupon_item->get_meta( 'wdr_product_categories', true )); if ( ! empty( $allowed_cats ) ) { $found_allowed_cat = false; foreach ( $product_cats as $cat_id ) { if ( in_array( $cat_id, $allowed_cats, true ) ) { $found_allowed_cat = true; break; } } if ( ! $found_allowed_cat ) { return false; } } // Excluded categories $excluded_cats = array_filter((array) $matched_coupon_item->get_meta( 'wdr_exclude_product_categories', true )); if ( ! empty( $excluded_cats) ) { foreach ( $product_cats as $cat_id ) { if ( in_array( $cat_id, $excluded_cats, true ) ) { return false; } } } // Exclude sale items $exclude_sale_items = (bool) $matched_coupon_item->get_meta( 'wdr_exclude_sale_items', true ); if ( $exclude_sale_items && $product_on_sale ) { return false; } return $valid; } }