getDiscountRules(); } /** * get available rules * @return array|object|null */ function getDiscountRules() { if (empty(self::$available_rules)) { $rule_helper = new Rule(); self::$available_rules = $rule_helper->getAvailableRules($this->getAvailableConditions()); } self::$calculator = new DiscountCalculator(self::$available_rules); return self::$available_rules; } /** * load required styles and scripts needed for site */ function loadAssets() { $bulk_table_on_off = self::$config->getConfig('show_bulk_table', 0); $ajax_update_price = self::$config->getConfig('show_strikeout_when', 'show_when_matched'); $minified_text = ''; $compress_css_and_js = self::$config->getConfig('compress_css_and_js', 0); if($compress_css_and_js) $minified_text = '.min'; // This have been added from v2.3.9. As it is added inline(Because it has only one css). //wp_enqueue_style(WDR_SLUG . '-customize-table-ui-css', WDR_PLUGIN_URL . 'Assets/Css/customize-table'.$minified_text.'.css', array(), WDR_VERSION); wp_enqueue_script('awdr-main', WDR_PLUGIN_URL . 'Assets/Js/site_main'.$minified_text.'.js', array('jquery'), WDR_VERSION, true); $awdr_front_end_script = array( 'ajaxurl' => admin_url('admin-ajax.php'), 'nonce' => Helper::create_nonce('awdr_ajax_front_end'), 'enable_update_price_with_qty' => $ajax_update_price, 'refresh_order_review' => self::$config->getConfig('refresh_order_review', 0), 'custom_target_simple_product' => apply_filters('advanced_woo_discount_rules_custom_target_for_simple_product_on_qty_update', ""), 'custom_target_variable_product' => apply_filters('advanced_woo_discount_rules_custom_target_for_variable_product_on_qty_update', ""), 'js_init_trigger' => apply_filters('advanced_woo_discount_rules_update_discount_price_init_trigger', ""), 'awdr_opacity_to_bulk_table' => apply_filters('advanced_woo_discount_rules_opacity_to_bulk_table', ""), 'awdr_dynamic_bulk_table_status' => $bulk_table_on_off, 'awdr_dynamic_bulk_table_off' => apply_filters('advanced_woo_discount_rules_disable_load_dynamic_bulk_table', "on"), 'custom_simple_product_id_selector' => apply_filters('advanced_woo_discount_rules_custom_simple_product_id_selector', ""), 'custom_variable_product_id_selector' => apply_filters('advanced_woo_discount_rules_custom_variable_product_id_selector', ""), ); wp_enqueue_script('awdr-dynamic-price', WDR_PLUGIN_URL . 'Assets/Js/awdr-dynamic-price'.$minified_text.'.js', array('jquery'), WDR_VERSION, true); wp_localize_script('awdr-main', 'awdr_params', $awdr_front_end_script); } /** * Check the product is in sale * @param $on_sale * @param $product * @return bool */ function isProductInSale($on_sale, $product) { if(is_null($product)){ return $on_sale; } remove_filter('woocommerce_product_is_on_sale', array($this, 'isProductInSale'), 100); //Need to check if conditions also passed $show_on_sale_badge = self::$config->getConfig('show_on_sale_badge', 'disabled'); if ($show_on_sale_badge == 'when_condition_matches') { if (self::$woocommerce_helper->productTypeIs($product, 'variable')) { $price_html = $this->getVariablePriceHtml('', $product); } else { // pass empty string as first argument in 'woocommerce_get_price_html' method to check if rule has been applied // empty result means that price was not change $price_html = $this->getPriceHtml('', $product); } } else { $price_html = self::$calculator->saleBadgeDisplayChecker($product, true); } if($price_html !== '' && $price_html === false){ $product_id = Woocommerce::getProductId($product); self::updateProductsAsOnSale($product_id); } add_filter('woocommerce_product_is_on_sale', array($this, 'isProductInSale'), 100, 2); return $on_sale OR $price_html; } /** * Set product is on sale in static variable for avoid multiple run * This helps for sale badge text override * */ protected static function updateProductsAsOnSale($product_id){ if(!empty(self::$on_sale_products)){ if(!in_array($product_id, self::$on_sale_products)){ self::$on_sale_products[] = $product_id; } } else { self::$on_sale_products[] = $product_id; } } /** * Is product on sale through our plugin * This helps for sale badge text override * */ protected static function isProductOnSale($product_id){ if(!in_array($product_id, self::$on_sale_products)){ return true; } return false; } /** * Replace sale tag text * */ public function replaceSaleTagText($html, $post, $product){ if(!is_object($product)){ return $html; } $use_sale_badge_customize = apply_filters('advanced_woo_discount_rules_use_sale_badge_customization', false, $post, $product); $use_sale_badge_percentage_customize = apply_filters('advanced_woo_discount_rules_use_sale_badge_percentage_customization', true, $post, $product); $product_id = Woocommerce::getProductId($product); if(self::isProductOnSale($product_id) || $use_sale_badge_customize){ $display_percentage_on_sale_badge = self::$config->getConfig('display_percentage_on_sale_badge', ''); if($display_percentage_on_sale_badge == 1 && $use_sale_badge_percentage_customize === true){ if (Woocommerce::productTypeIs($product, array('variable'))) { $variation_product = Woocommerce::getFirstChildOfVariableProduct($product); if ($variation_product) { $product = $variation_product; } } $discount = self::calculateProductDiscountPrice(false, $product, 1, 0, 'all', true, false); if($discount !== false && is_array($discount)){ $percentage_value = $discount_value = 0; if (!empty($discount['initial_price']) && isset($discount['discounted_price'])) { $percentage_value = (($discount['initial_price'] - $discount['discounted_price']) / $discount['initial_price']) * 100; } $percentage = apply_filters('advanced_woo_discount_rules_percentage_value_on_sale_badge', round($percentage_value, 2), $percentage_value, $product); if (isset($discount['initial_price_with_tax']) && isset($discount['discounted_price_with_tax'])) { $discount_value = $discount['initial_price_with_tax'] - $discount['discounted_price_with_tax']; } $discount_value_to_display = Woocommerce::formatPrice(($discount_value)); $on_sale_badge_percentage_html = self::$config->getConfig('on_sale_badge_percentage_html', '{{percentage}}%'); $translate = __('{{percentage}}%', 'woo-discount-rules'); $on_sale_badge_percentage_html = Helper::getCleanHtml($on_sale_badge_percentage_html); $html = __($on_sale_badge_percentage_html, 'woo-discount-rules'); $html = str_replace('{{percentage}}', $percentage, $html); $html = str_replace('{{discount_value}}', $discount_value_to_display, $html); $html = apply_filters('advanced_woo_discount_rules_on_sale_badge_html', $html, $post, $product); return $html; } } $on_sale_badge_html = self::$config->getConfig('on_sale_badge_html', 'Sale!'); $translate = __('Sale!', 'woo-discount-rules'); $on_sale_badge_html = Helper::getCleanHtml($on_sale_badge_html); $html = __($on_sale_badge_html, 'woo-discount-rules'); $html = apply_filters('advanced_woo_discount_rules_on_sale_badge_html', $html, $post, $product); } return $html; } /** * get product sale price * @param $value * @param $product * @return mixed */ function getProductSalePrice($value, $product) { $prices = self::calculateInitialAndDiscountedPrice($product, 1); if (!empty($prices['discounted_price_with_tax'])) $value = $prices['discounted_price_with_tax']; return $value; } /** * get product regular price * @param $value * @param $product * @return mixed */ function getProductRegularPrice($value, $product) { $prices = self::calculateInitialAndDiscountedPrice($product, 1); if (!empty($prices['initial_price_with_tax'])) $value = $prices['initial_price_with_tax']; return $value; } function doProcessStrikeOut($price_html, $product, $quantity = 1, $ajax_price = false){ if(isset($_REQUEST['action'])){ $blocked_actions = array('inline-save'); if(in_array($_REQUEST['action'], $blocked_actions)){ return false; } } return true; } /** * Modify the product's price when discount applicable. * @param $price_html * @param $product * @param int $quantity * @param boolean $ajax_price * @return mixed */ function getPriceHtml($price_html, $product, $quantity = 1, $ajax_price = false) { if(is_null($product)){ return $price_html; } if($this->doProcessStrikeOut($price_html, $product, $quantity, $ajax_price)){ if (empty(self::$available_rules)) { if($ajax_price){ return false; } return $price_html; } $disable_strikeout_for_product_types = apply_filters('advanced_woo_discount_rules_disable_strikeout_for_product_types', array('grouped'), $product, $ajax_price); if (self::$woocommerce_helper->productTypeIs($product, $disable_strikeout_for_product_types)) { return $price_html; } // $initial_price_html = $price_html; $initial_price_html = $this->getCalculateDiscountPriceFrom($product, $price_html, $ajax_price); $modify_price = apply_filters('advanced_woo_discount_rules_modify_price_html', true, $price_html, $product, $quantity); if (!$modify_price) { if($ajax_price){ return false; } return $price_html; } if(empty(self::$config->getConfig('modify_price_at_product_page', 1)) && empty(self::$config->getConfig('modify_price_at_shop_page', 1)) && empty(self::$config->getConfig('modify_price_at_category_page', 1))){ if($ajax_price){ return false; } return $price_html; } if (is_product() && empty(self::$config->getConfig('modify_price_at_product_page', 1))) { if($ajax_price){ return false; } return $price_html; } if (is_shop() && empty(self::$config->getConfig('modify_price_at_shop_page', 1))) { if($ajax_price){ return false; } return $price_html; } if (is_product_category() && empty(self::$config->getConfig('modify_price_at_category_page', 1))) { if($ajax_price){ return false; } return $price_html; } if ($ajax_price) { $price_html = $initial_price_html; $quantity = $this->input->post('qty', ''); if(!$price_html || empty($quantity)){ return false; } } //Check the product object is from WC_Product Class if (is_a($product, 'WC_Product')) { if(!$ajax_price) { if (self::$woocommerce_helper->productTypeIs($product, array('variable'))) { return $price_html; } } $product_id = Woocommerce::getProductId($product); //Calculate the product price $prices = self::calculateInitialAndDiscountedPrice($product, $quantity, $is_cart = false, $ajax_price); $apply_as_cart_rule = isset($prices['apply_as_cart_rule']) ? $prices['apply_as_cart_rule'] : array('no'); if(!empty($apply_as_cart_rule)){ if(!in_array('no', $apply_as_cart_rule)){ return $price_html; } } if($ajax_price){ $discount_details = (isset($prices['total_discount_details'])) ? $prices['total_discount_details'] : false; if($discount_details) { // $initial_price = (isset($prices['initial_price_with_tax'])) ? $prices['initial_price_with_tax'] : 0; //$discounted_price = (isset($prices['discounted_price_with_tax'])) ? $prices['discounted_price_with_tax'] : 0; $initial_price = isset($prices['initial_price']) ? $prices['initial_price'] : 0; $discounted_price = isset($prices['discounted_price']) ? $prices['discounted_price'] : 0; if(empty($initial_price) || empty($discounted_price) || empty($discount_details)){ return $price_html; } $strikeout_html = $this->getSetDiscountItemPriceHtml($discount_details, $initial_price, $discounted_price, $product, $price_html = true, $quantity, $ajax_price); return apply_filters('advanced_woo_discount_rules_dynamic_price_html_update', $strikeout_html, $product, $initial_price, $discounted_price, $discount_details, $prices); //return $this->getSetDiscountItemPriceHtml($discount_details, $initial_price, $discounted_price, $product, $price_html = true, $quantity, $ajax_price); }else{ return false; } }else { if (!$prices) { return $price_html; } self::$calculated_product_discount[$product_id] = $prices; $initial_price_with_tax_call = $discounted_price_with_tax_call = 0; $calculator = self::$calculator; $initial_price = isset($prices['initial_price']) ? $prices['initial_price'] : 0; $discounted_price = isset($prices['discounted_price']) ? $prices['discounted_price'] : 0; if(!empty($initial_price)){ $initial_price_with_tax_call = $calculator->mayHaveTax($product, $initial_price); } if(!empty($discounted_price)){ $discounted_price_with_tax_call = $calculator->mayHaveTax($product, $discounted_price); } $price_html = $this->getStrikeoutPrice($initial_price_with_tax_call, $discounted_price_with_tax_call, true, false, $initial_price_html); $price_html = $price_html.Woocommerce::getProductPriceSuffix($product, $discounted_price, $prices); } } } return $price_html; } /** * getCalculateDiscountPriceFrom * * @param $product * @param $price_html * @param $ajax_price * @return string */ function getCalculateDiscountPriceFrom($product, $price_html, $ajax_price){ $calculate_discount_from = self::$config->getConfig('calculate_discount_from', 'sale_price'); if ($calculate_discount_from == 'regular_price') { $product_price = self::$woocommerce_helper->getProductRegularPrice($product); $calculator = self::$calculator; if(!empty($product_price)){ $product_price = $calculator->mayHaveTax($product, $product_price); } $price_html = self::$woocommerce_helper->formatPrice($product_price); return $price_html.Woocommerce::getProductPriceSuffix($product, $product_price); } if($ajax_price){ $product_price = self::$woocommerce_helper->getProductPrice($product); $price_html = self::$woocommerce_helper->formatPrice($product_price); return $price_html.Woocommerce::getProductPriceSuffix($product, $product_price); } return $price_html; } /** * Modify the product's price before modified by our plugin to adjust sale price. * * @param $price_html * @param $product * @param int $quantity * @return mixed * */ function getPriceHtmlSalePriceAdjustment($price_html, $product, $quantity = 1) { if(is_null($product)){ return $price_html; } if (empty(self::$available_rules)) { return $price_html; } $show_on_sale_badge = self::$config->getConfig('show_on_sale_badge', 'disabled'); if($show_on_sale_badge != 'at_least_has_any_rules' ){ return $price_html; } $modify_price = apply_filters('advanced_woo_discount_rules_modify_sale_price_adjustment_html', true, $price_html, $product, $quantity); if (!$modify_price) { return $price_html; } $excluded_product_type = apply_filters('advanced_woo_discount_rules_exclude_product_type_for_sale_price_strikeout_adjustment', array('variable', 'subscription_variation', 'variable-subscription', 'grouped', 'composite'), $product); if (is_array($excluded_product_type) && !empty($excluded_product_type)) { if (!Woocommerce::productTypeIs($product, $excluded_product_type)) { $sale_price = Woocommerce::getProductSalePrice($product); $regular_price = Woocommerce::getProductPrice($product); if ($sale_price <= 0) { if($regular_price > 0){ $regular_price = get_option('woocommerce_tax_display_shop') == 'excl' ? Woocommerce::getExcludingTaxPrice($product, 1, $regular_price) : Woocommerce::getIncludingTaxPrice($product, 1, $regular_price); $price_to_display = Woocommerce::formatPrice($regular_price); $price_html = (($price_to_display) . Woocommerce::getProductPriceSuffix($product)); } return $price_html; } } } return $price_html; } /** * Remove duplicate strikeout price * */ function removeDuplicateStrikeoutPrice($item_price){ $del_pattern = "/]*>(.*?)<\/del>/s"; preg_match($del_pattern, $item_price, $matches); $del_content = isset($matches[1]) ? trim(strip_tags($matches[1])) : ''; // Match with possible attributes $ins_pattern = "/]*>(.*?)<\/ins>/s"; preg_match($ins_pattern, $item_price, $matches); $ins_content_org = isset($matches[1]) ? $matches[1] : ''; $ins_content = trim(strip_tags($ins_content_org)); // Remove if its content matches if (!empty($del_content) && !empty($ins_content) && $del_content === $ins_content) { $item_price = $ins_content_org; } return $item_price; } /** * Variable product * * @param $price_html * @param $product * @param int $quantity * @return mixed|string */ function getVariablePriceHtml($price_html, $product, $quantity = 1) { if(is_null($product)){ return $price_html; } if($this->doProcessStrikeOut($price_html, $product, $quantity)){ if (empty(self::$available_rules)) { return $price_html; } $modify_price = apply_filters('advanced_woo_discount_rules_modify_price_html', true, $price_html, $product, $quantity); if (!$modify_price) { return $price_html; } if(empty(self::$config->getConfig('modify_price_at_product_page', 1)) && empty(self::$config->getConfig('modify_price_at_shop_page', 1)) && empty(self::$config->getConfig('modify_price_at_category_page', 1))){ return $price_html; } if (is_product() && empty(self::$config->getConfig('modify_price_at_product_page', 1))) { return $price_html; } if (is_shop() && empty(self::$config->getConfig('modify_price_at_shop_page', 1))) { return $price_html; } if (is_product_category() && empty(self::$config->getConfig('modify_price_at_category_page', 1))) { return $price_html; } $original_prices_list = $sale_prices_lists = $discount_prices_lists = array(); $available_variations = Woocommerce::getProductChildren($product); if (!empty($available_variations)) { $consider_out_of_stock_variants = apply_filters('advanced_woo_discount_rules_do_strikeout_for_out_of_stock_variants', false); $variants_check_limit = (int) apply_filters('advanced_woo_discount_rules_check variants_limit_for_variable_strikeout', 20); $variations = []; if (count($available_variations) > $variants_check_limit) { $variation_prices = self::$woocommerce_helper->getVariationPrices($product); $calculate_discount_from = self::$config->getConfig('calculate_discount_from', 'sale_price'); $original_prices = ($calculate_discount_from) == 'regular_price' ? $variation_prices['regular_price'] : $variation_prices['price']; if (!empty($original_prices)){ $variations[] = array_keys($original_prices, min($original_prices))[0]; $variations[] = array_keys($original_prices, max($original_prices))[0]; } } else { $variations = $available_variations; } foreach ($variations as $variation_id) { if (empty($variation_id)) { continue; } $variation = Woocommerce::getProduct($variation_id); if(!Woocommerce::variationIsVisible($variation)){ continue; } if(!Woocommerce::isProductHasStock($variation) && !$consider_out_of_stock_variants) { continue; } $prices = self::calculateInitialAndDiscountedPrice($variation, $quantity); if (!isset($prices['initial_price']) || !isset($prices['discounted_price'])) { $original_prices_list[] = Woocommerce::getProductRegularPrice($variation); $sale_prices_lists[] = Woocommerce::getProductPrice($variation); continue; } $original_prices_list[] = $prices['initial_price']; $discount_prices_lists[] = $prices['discounted_price']; } } $discount_prices_lists = array_unique($discount_prices_lists); $original_prices_list = array_unique($original_prices_list); if(empty($discount_prices_lists)){ return $this->removeDuplicateStrikeoutPrice($price_html); } if(empty($original_prices_list)){ return $this->removeDuplicateStrikeoutPrice($price_html); } $discount_prices_lists = array_merge($discount_prices_lists, $sale_prices_lists); $min_price = min($discount_prices_lists); $max_price = max($discount_prices_lists); $min_original_price = min($original_prices_list); $max_original_price = max($original_prices_list); $calculator = self::$calculator; if(!empty($min_original_price)){ $min_original_price = $calculator->mayHaveTax($product, $min_original_price); } if(!empty($max_original_price)){ $max_original_price = $calculator->mayHaveTax($product, $max_original_price); } if(!empty($min_price)){ $min_price = $calculator->mayHaveTax($product, $min_price); } if(!empty($max_price)){ $max_price = $calculator->mayHaveTax($product, $max_price); } $min_original_price_range_suffix = self::$woocommerce_helper->getProductPriceSuffix($product, $min_original_price); if ($min_original_price == $max_original_price) { $price_html = self::$woocommerce_helper->formatPrice($min_original_price) . $min_original_price_range_suffix; } elseif ($min_original_price < $max_original_price) { $price_html = self::$woocommerce_helper->formatPriceRange($min_original_price, $max_original_price, true) . $min_original_price_range_suffix; } $min_price_range_suffix = self::$woocommerce_helper->getProductPriceSuffix($product, $min_price); if ($min_price == $max_price) { $price_html_discounted = self::$woocommerce_helper->formatPrice($min_price) . $min_price_range_suffix; return $this->getStrikeoutPrice($price_html, $price_html_discounted, false, true); } elseif ($min_price < $max_price) { $price_html_discounted = self::$woocommerce_helper->formatPriceRange($min_price, $max_price, false) . $min_price_range_suffix; return $this->getStrikeoutPrice($price_html, $price_html_discounted, false, true); } } return $price_html; } /** * override original price html with discounted price html * @param $original_price * @param $discounted_price * @param $format_price * @param $is_variable_product * @param $initial_price_html * @return string */ function getStrikeoutPrice($original_price, $discounted_price, $format_price = true, $is_variable_product = false, $initial_price_html=false) { $separator = ($is_variable_product) ? '
' : ' '; $original_price_raw = $original_price; $discounted_price_raw = $discounted_price; if ($original_price == $discounted_price) { if ($format_price) { $discounted_price = self::$woocommerce_helper->formatPrice($discounted_price); } $html = '' . $discounted_price . ''; } else { if ($format_price) { $original_price = self::$woocommerce_helper->formatPrice($original_price); $discounted_price = self::$woocommerce_helper->formatPrice($discounted_price); } if($initial_price_html){ $initial_price_html = preg_replace('/.*<\/del>/', '', $initial_price_html); $initial_price_html = preg_replace('/