/** * Function to apply discounts to a product and get the discounted price (before tax is applied) * * @param mixed $values * @param mixed $price * @param bool $add_totals (default: false) * @return float price * @since 1.0 */ public static function get_discounted_price($values, $price, $add_totals = false) { global $woocommerce; if (!$price) { return $price; } if (!empty($woocommerce->cart->applied_coupons)) { foreach ($woocommerce->cart->applied_coupons as $code) { $coupon = new WC_Coupon($code); if ($coupon->apply_before_tax() && $coupon->is_valid()) { switch ($coupon->type) { case "fixed_product": case "percent_product": $this_item_is_discounted = false; $product_cats = wp_get_post_terms($values['product_id'], 'product_cat', array("fields" => "ids")); // Specific products get the discount if (sizeof($coupon->product_ids) > 0) { if (in_array($values['product_id'], $coupon->product_ids) || in_array($values['variation_id'], $coupon->product_ids) || in_array($values['data']->get_parent(), $coupon->product_ids)) { $this_item_is_discounted = true; } // Category discounts } elseif (sizeof($coupon->product_categories) > 0) { if (sizeof(array_intersect($product_cats, $coupon->product_categories)) > 0) { $this_item_is_discounted = true; } } else { // No product ids - all items discounted $this_item_is_discounted = true; } // Specific product ID's excluded from the discount if (sizeof($coupon->exclude_product_ids) > 0) { if (in_array($values['product_id'], $coupon->exclude_product_ids) || in_array($values['variation_id'], $coupon->exclude_product_ids) || in_array($values['data']->get_parent(), $coupon->exclude_product_ids)) { $this_item_is_discounted = false; } } // Specific categories excluded from the discount if (sizeof($coupon->exclude_product_categories) > 0) { if (sizeof(array_intersect($product_cats, $coupon->exclude_product_categories)) > 0) { $this_item_is_discounted = false; } } // Apply filter $this_item_is_discounted = apply_filters('woocommerce_item_is_discounted', $this_item_is_discounted, $values, $before_tax = true); // Apply the discount if ($this_item_is_discounted) { if ($coupon->type == 'fixed_product') { if ($price < $coupon->amount) { $discount_amount = $price; } else { $discount_amount = $coupon->amount; } $price = $price - $coupon->amount; if ($price < 0) { $price = 0; } if ($add_totals) { $woocommerce->cart->sign_up_fee_discount_cart = $woocommerce->cart->sign_up_fee_discount_cart + $discount_amount * $values['quantity']; } } elseif ($coupon->type == 'percent_product') { $percent_discount = WC_Subscriptions_Product::get_sign_up_fee_excluding_tax($values['data']) / 100 * $coupon->amount; if ($add_totals) { $woocommerce->cart->sign_up_fee_discount_cart = $woocommerce->cart->sign_up_fee_discount_cart + $percent_discount * $values['quantity']; } $price = $price - $percent_discount; } } break; case "fixed_cart": /** * This is the most complex discount - we need to divide the discount between rows based on their price in * proportion to the subtotal. This is so rows with different tax rates get a fair discount, and so rows * with no price (free) don't get discount too. */ // Get item discount by dividing item cost by subtotal to get a % if ($woocommerce->cart->sign_up_fee_subtotal_ex_tax) { $discount_percent = WC_Subscriptions_Product::get_sign_up_fee_excluding_tax($values['data']) * $values['quantity'] / $woocommerce->cart->sign_up_fee_subtotal_ex_tax; } else { $discount_percent = 0; } // Use pence to help prevent rounding errors $coupon_amount_pence = $coupon->amount * 100; // Work out the discount for the row $item_discount = $coupon_amount_pence * $discount_percent; // Work out discount per item $item_discount = $item_discount / $values['quantity']; // Pence $price = $price * 100; // Check if discount is more than price if ($price < $item_discount) { $discount_amount = $price; } else { $discount_amount = $item_discount; } // Take discount off of price (in pence) $price = $price - $discount_amount; // Back to pounds $price = $price / 100; // Cannot be below 0 if ($price < 0) { $price = 0; } // Add coupon to discount total (once, since this is a fixed cart discount and we don't want rounding issues) if ($add_totals) { $woocommerce->cart->sign_up_fee_discount_cart = $woocommerce->cart->sign_up_fee_discount_cart + $discount_amount * $values['quantity'] / 100; } break; case "percent": $percent_discount = WC_Subscriptions_Product::get_sign_up_fee($values['data']->id) / 100 * $coupon->amount; if ($add_totals) { $woocommerce->cart->sign_up_fee_discount_cart = $woocommerce->cart->sign_up_fee_discount_cart + $percent_discount * $values['quantity']; } $price = $price - $percent_discount; break; } } } } return $price; }