Buy_X_For_Y_Discount extends Type implements Actionable, Applicable Uses Discount_With_Reductions, Discount_With_Required_Qty, Discount_With_Calculated_Subtotal
Buy X for Y discount type.
Give a percentage or fixed discount when the customer buys a certain quantity, e.g. buy products and get 10% off, or buy 4 t-shirts and get $5 off.
Tags
Interfaces, Classes and Traits
- Actionable
- Interface for discount types that have cart actions.
- Applicable
- Indicates that a discount type needs to be verified as applicable to the cart as a whole.
Table of Contents
- ORDER = 5
- $discount : Discount
- The discount object.
- $processing_order : bool
- Whether the discount type is processing a WooCommerce order.
- $total_discounted_products : int
- The total number of discounted products in the cart|order.
- $total_order_discount : float
- The total discount that needs to be applied to the order.
- apply_discount_to_additional_products() : void
- The idea with "Additional products only" is to offer this kind of discount:
- apply_discount_to_all_products() : void
- Apply the discount to the cart or order.
- cart_meets_products_selection_and_quantity() : bool
- Check whether the cart meets the minimum required quantity for the discount to apply.
- decrease_total_discounted_products() : self
- Decrease the total number of discounted products in the cart|order.
- decrease_total_order_discount() : self
- Decrease the total discount that needs to be applied to the order.
- generate_virtual_coupon_for_order() : void
- Generate a virtual coupon for the order.
- get_apply_to() : string
- Determine whether the discount is applicable to all products or additional products above the required quantity.
- get_cart_quantity_of_relevant_products() : int
- Return the total quantity of relevant products in the cart.
- get_default_settings_values() : array<string|int, mixed>
- Get the default settings values for this discount type.
- get_discount() : Discount
- Get the discount object.
- get_discount_amount_type() : string
- Get the type of discount amount.
- get_min_required_qty() : int
- Retrieve the minimum required quantity for the discount to apply.
- get_name() : string
- Get the name for this discount type.
- get_order_quantity_of_relevant_products() : int
- Return the total quantity of relevant products in the order.
- get_reduction() : Reduction
- Get the reduction to apply to products.
- get_settings() : array<string|int, mixed>
- Get the settings for this discount type.
- get_slug() : string
- Get the slug for this discount type.
- get_tooltip() : string
- Get the tooltip for this discount type.
- get_total_discounted_products() : int
- Return the total number of discounted products in the cart|order.
- get_total_order_discount() : float
- Return the total discount that needs to be applied to the order.
- increase_total_discounted_products() : self
- Increase the total number of discounted products in the cart|order.
- increase_total_order_discount() : self
- Increase the total discount that needs to be applied to the order.
- is_applicable_to_cart() : bool
- Determine if the discount is applicable to the cart as a whole.
- is_applicable_to_order() : bool
- Determine if the discount is applicable to the order as a whole.
- is_processing_order() : bool
- Return whether the discount type is being applied to a WooCommerce order.
- make() : static
- Make a new discount type.
- order_meets_products_selection_and_quantity() : bool
- Check whether the order meets the minimum required quantity for the discount to apply.
- reset_total_discounted_products() : self
- Reset the total number of discounted products in the cart|order.
- reset_total_order_discount() : self
- Reset the total discount that needs to be applied to the order.
- run_cart_actions() : void
- Run the cart actions for the discount type.
- run_order_actions() : void
- Run the order actions for the discount type.
- set_discount() : self
- Set the discount object.
- set_proccesing_order() : self
- Flag whether the discount type is being applied to a WooCommerce order.
- set_total_discounted_products() : self
- Set the total number of discounted products in the cart|order.
- set_total_order_discount() : self
- Set the total discount that needs to be applied to the order.
- calculate_number_of_items_to_buy_with_discount() : int
- Calculate the number of items to buy with discount.
- cart_has_product_with_required_qty() : bool
- Check if the cart has a product with the required quantity.
- discount_cart_level() : void
- Apply the discount to the cart or order subtotal by looping through the products and applying the discount to each product so that the final discount is applied to the cart or order subtotal.
- discount_cheapest_in_cart_order() : void
- This method is used to discount products at a cart level instead of per line item.
- discount_cheapest_product_with_the_required_qty() : void
- Discount the cheapest product with the required quantity in the cart or order.
- exclude_the_required_products() : array<string|int, mixed>
- Filter the array of relevant products, we need to exclude the products that match the requirements because we're only discounting the additional products.
- get_cart_subtotal() : float
- Get the appropriate subtotal used to determine the dynamic discount amount generated by the fixed price.
- get_cheapest_product_with_required_qty() : array<string|int, mixed>|null|WC_Order_Item_Product
- Get the cheapest product with the required quantity.
- get_order_subtotal() : float
- Get the appropriate subtotal used to determine the dynamic discount amount generated by the fixed price.
- maybe_discount_all_items() : void
- Maybe discount all items.
- order_has_product_with_required_qty() : bool
- Check if the order has a product with the required quantity.
Constants
ORDER
public
mixed
ORDER
= 5
Properties
$discount
The discount object.
protected
Discount
$discount
$processing_order
Whether the discount type is processing a WooCommerce order.
protected
bool
$processing_order
= false
This is used so that we prevent applying discounts at a order line level due to the multitude of issues in how taxes are calculated in WooCommerce.
$total_discounted_products
The total number of discounted products in the cart|order.
protected
int
$total_discounted_products
= 0
This is used to track the number of discounted products in the cart|order but not all types will use this.
Not all discount types need to track the number of discounted products.
$total_order_discount
The total discount that needs to be applied to the order.
protected
float
$total_order_discount
= 0
Methods
apply_discount_to_additional_products()
The idea with "Additional products only" is to offer this kind of discount:
public
apply_discount_to_additional_products(array<string|int, mixed> $products[, bool|WC_Cart $cart = false ][, bool|WC_Order $order = false ]) : void
"Buy 2, get a 3rd half price."
Here's an example where the product costs $10.
Cart calculation for 2 products in cart: 2 at full price, 2 x $10 = $20 Cart total = $20
Cart calculation for 3 products in cart: 2 at full price, 2 x $10 = $20 1 at half price, 1 X $5 = $5 Cart total = $25
Cart calculation for 6 products in cart: 4 at full price, 4 x $10 = $40 2 at half price, 2 X $5 = $10 Cart total = $50 So the discount "loops" when there is sufficient quantity in the cart.
Parameters
- $products : array<string|int, mixed>
- $cart : bool|WC_Cart = false
-
Whether we're handling a cart or an order.
- $order : bool|WC_Order = false
-
Whether we're handling a cart or an order.
Return values
void —apply_discount_to_all_products()
Apply the discount to the cart or order.
public
apply_discount_to_all_products(array<string|int, mixed> $products[, bool|WC_Cart $cart = false ][, bool|WC_Order $order = false ]) : void
The idea with "All products" is to offer a discount that loops each time a line item has been found with the required quantity.
Alternatively, when there's a sufficient quantity of products in the cart/order (total line items), the discount loops.
Parameters
- $products : array<string|int, mixed>
-
Array of products to apply the discount to (cart items or order items).
- $cart : bool|WC_Cart = false
-
Whether we're handling a cart or an order.
- $order : bool|WC_Order = false
-
Whether the products are order items or cart items.
Return values
void —cart_meets_products_selection_and_quantity()
Check whether the cart meets the minimum required quantity for the discount to apply.
public
cart_meets_products_selection_and_quantity(WC_Cart $cart, Discount $discount) : bool
- If the discount is applicable to all products, the cart must contain the minimum required quantity of any product.
- If the discount is applicable to specific products, the cart must contain the minimum required quantity of any of the selected products.
- If the discount is applicable to specific categories, the cart must contain the minimum required quantity of any product in the selected categories.
Parameters
- $cart : WC_Cart
- $discount : Discount
Return values
bool —decrease_total_discounted_products()
Decrease the total number of discounted products in the cart|order.
public
decrease_total_discounted_products(int $amount) : self
Parameters
- $amount : int
-
The amount to decrease the total number of discounted products by.
Return values
self —The discount type.
decrease_total_order_discount()
Decrease the total discount that needs to be applied to the order.
public
decrease_total_order_discount(float $amount) : self
Parameters
- $amount : float
-
The amount to decrease the total discount by.
Return values
self —The discount type.
generate_virtual_coupon_for_order()
Generate a virtual coupon for the order.
public
generate_virtual_coupon_for_order(WC_Order $order) : void
This is used to apply the discount to the order and is not a real coupon.
This is mainly used during the creating of manual orders.
Parameters
- $order : WC_Order
-
The order object.
Return values
void —get_apply_to()
Determine whether the discount is applicable to all products or additional products above the required quantity.
public
get_apply_to() : string
Return values
string —'any' or 'addition'
get_cart_quantity_of_relevant_products()
Return the total quantity of relevant products in the cart.
public
get_cart_quantity_of_relevant_products(WC_Cart $cart) : int
Parameters
- $cart : WC_Cart
-
The cart object.
Return values
int —get_default_settings_values()
Get the default settings values for this discount type.
public
static get_default_settings_values() : array<string|int, mixed>
Tags
Return values
array<string|int, mixed> —get_discount()
Get the discount object.
public
get_discount() : Discount
Return values
Discount —get_discount_amount_type()
Get the type of discount amount.
public
get_discount_amount_type() : string
Possible values: 'percentage', 'fixed'.
Return values
string —The type of discount amount.
get_min_required_qty()
Retrieve the minimum required quantity for the discount to apply.
public
get_min_required_qty() : int
Return values
int —get_name()
Get the name for this discount type.
public
static get_name() : string
Tags
Return values
string —get_order_quantity_of_relevant_products()
Return the total quantity of relevant products in the order.
public
get_order_quantity_of_relevant_products(WC_Order $order) : int
Parameters
- $order : WC_Order
-
The order object.
Return values
int —get_reduction()
Get the reduction to apply to products.
public
get_reduction() : Reduction
Return values
Reduction —The reduction to apply to products.
get_settings()
Get the settings for this discount type.
public
static get_settings() : array<string|int, mixed>
Tags
Return values
array<string|int, mixed> —get_slug()
Get the slug for this discount type.
public
static get_slug() : string
Tags
Return values
string —get_tooltip()
Get the tooltip for this discount type.
public
static get_tooltip() : string
Tags
Return values
string —get_total_discounted_products()
Return the total number of discounted products in the cart|order.
public
get_total_discounted_products() : int
Return values
int —get_total_order_discount()
Return the total discount that needs to be applied to the order.
public
get_total_order_discount() : float
Return values
float —increase_total_discounted_products()
Increase the total number of discounted products in the cart|order.
public
increase_total_discounted_products(int $amount) : self
Parameters
- $amount : int
-
The amount to increase the total number of discounted products by.
Return values
self —The discount type.
increase_total_order_discount()
Increase the total discount that needs to be applied to the order.
public
increase_total_order_discount(float $amount) : self
Parameters
- $amount : float
-
The amount to increase the total discount by.
Return values
self —The discount type.
is_applicable_to_cart()
Determine if the discount is applicable to the cart as a whole.
public
is_applicable_to_cart(WC_Cart $cart) : bool
Parameters
- $cart : WC_Cart
-
The cart object.
Tags
Return values
bool —True if the discount is applicable to the cart as a whole.
is_applicable_to_order()
Determine if the discount is applicable to the order as a whole.
public
is_applicable_to_order(WC_Order $order) : bool
Parameters
- $order : WC_Order
-
The order object.
Tags
Return values
bool —True if the discount is applicable to the order as a whole.
is_processing_order()
Return whether the discount type is being applied to a WooCommerce order.
public
is_processing_order() : bool
Return values
bool —make()
Make a new discount type.
public
static make(Discount $discount) : static
Parameters
- $discount : Discount
-
The discount object.
Return values
static —The new discount type.
order_meets_products_selection_and_quantity()
Check whether the order meets the minimum required quantity for the discount to apply.
public
order_meets_products_selection_and_quantity(WC_Order $order, Discount $discount) : bool
- If the discount is applicable to all products, the order must contain the minimum required quantity of any product.
- If the discount is applicable to specific products, the order must contain the minimum required quantity of any of the selected products.
- If the discount is applicable to specific categories, the order must contain the minimum required quantity of any product in the selected categories.
Parameters
- $order : WC_Order
- $discount : Discount
Return values
bool —reset_total_discounted_products()
Reset the total number of discounted products in the cart|order.
public
reset_total_discounted_products() : self
Return values
self —The discount type.
reset_total_order_discount()
Reset the total discount that needs to be applied to the order.
public
reset_total_order_discount() : self
Return values
self —The discount type.
run_cart_actions()
Run the cart actions for the discount type.
public
run_cart_actions(WC_Cart &$cart) : void
Parameters
- $cart : WC_Cart
Tags
Return values
void —run_order_actions()
Run the order actions for the discount type.
public
run_order_actions(WC_Order &$order) : void
Parameters
- $order : WC_Order
Tags
Return values
void —set_discount()
Set the discount object.
public
set_discount(Discount $discount) : self
Parameters
- $discount : Discount
-
The discount object.
Return values
self —set_proccesing_order()
Flag whether the discount type is being applied to a WooCommerce order.
public
set_proccesing_order(bool $processing_order) : self
Parameters
- $processing_order : bool
-
Whether the discount type is processing a WooCommerce order.
Return values
self —The discount type.
set_total_discounted_products()
Set the total number of discounted products in the cart|order.
public
set_total_discounted_products(int $total_discounted_products) : self
Parameters
- $total_discounted_products : int
-
The total number of discounted products in the cart|order.
Return values
self —The discount type.
set_total_order_discount()
Set the total discount that needs to be applied to the order.
public
set_total_order_discount(float $total_order_discount) : self
Parameters
- $total_order_discount : float
-
The total discount that needs to be applied to the order.
Return values
self —The discount type.
calculate_number_of_items_to_buy_with_discount()
Calculate the number of items to buy with discount.
private
calculate_number_of_items_to_buy_with_discount(int $quantity_in_cart, int $full_price_buy, int $discounted_buy) : int
Parameters
- $quantity_in_cart : int
-
The quantity of the product in the cart.
- $full_price_buy : int
-
The number of items to buy at full price.
- $discounted_buy : int
-
The number of items to buy with discount.
Return values
int —The number of items to buy with discount.
cart_has_product_with_required_qty()
Check if the cart has a product with the required quantity.
private
cart_has_product_with_required_qty(array<string|int, mixed> $products[, bool|int $custom_additional_qty = false ][, bool $skip_additional_qty = false ]) : bool
Parameters
- $products : array<string|int, mixed>
-
Array of products in the cart.
- $custom_additional_qty : bool|int = false
-
Whether to use the custom additional quantity or not.
- $skip_additional_qty : bool = false
-
Whether to skip the additional quantity or not.
Return values
bool —True if the cart has a product with the required quantity, false otherwise.
discount_cart_level()
Apply the discount to the cart or order subtotal by looping through the products and applying the discount to each product so that the final discount is applied to the cart or order subtotal.
private
discount_cart_level(array<string|int, mixed> $products[, bool|WC_Cart $cart = false ][, bool|WC_Order $order = false ], int $total_line_items, int $discount_applications) : void
Parameters
- $products : array<string|int, mixed>
-
Array of products to apply the discount to (cart items or order items).
- $cart : bool|WC_Cart = false
-
Whether we're handling a cart or an order.
- $order : bool|WC_Order = false
-
Whether the products are order items or cart items.
- $total_line_items : int
-
The total number of line items in the cart or order.
- $discount_applications : int
-
The number of times the discount should be applied.
Return values
void —discount_cheapest_in_cart_order()
This method is used to discount products at a cart level instead of per line item.
private
discount_cheapest_in_cart_order(array<string|int, mixed> $products, int $number_of_products_to_discount[, WC_Cart|bool $cart = false ][, WC_Order|bool $order = false ]) : void
For example, a user of the plugin might offer the discount “Buy 2 get 1 half price” on a specific product only. But they might offer it on a whole category of products, which would lead to this scenario.
Based on the number of products to discount, find the cheapest product and determine if the product's quantity is greater than or equal to the number of products to discount.
- If a product is found, then apply the discount to the product.
- If a product is not found, then keep looking for the cheapest product until the number of products to discount is reached.
In the latter case, the products to discount will have at least a quantity of 1.
Parameters
- $products : array<string|int, mixed>
-
Array of products in the cart or order.
- $number_of_products_to_discount : int
-
The number of products to discount.
- $cart : WC_Cart|bool = false
-
Whether we're handling a cart or an order.
- $order : WC_Order|bool = false
-
Whether we're handling a cart or an order.
Return values
void —discount_cheapest_product_with_the_required_qty()
Discount the cheapest product with the required quantity in the cart or order.
private
discount_cheapest_product_with_the_required_qty(array<string|int, mixed> $products, int $required_qty, int $number_of_items_to_discount[, bool $is_order = false ][, bool $forced_applications = false ]) : void
based on the number of items to discount.
Parameters
- $products : array<string|int, mixed>
-
Array of products in the cart or order.
- $required_qty : int
-
The required quantity.
- $number_of_items_to_discount : int
-
The number of items to discount.
- $is_order : bool = false
-
Whether the products are order items or cart items.
- $forced_applications : bool = false
-
Set to integer to force the number of applications.
Return values
void —exclude_the_required_products()
Filter the array of relevant products, we need to exclude the products that match the requirements because we're only discounting the additional products.
private
exclude_the_required_products(array<string|int, mixed> $products[, bool $is_order = false ]) : array<string|int, mixed>
The criteria for excluding the products are is based on their quantity in the order/cart. Filter the array of products by tracking their quantity into the $number_of_excluded_qty variable.
When the variable reaches the required quantity, then we stop filtering the array.
Parameters
- $products : array<string|int, mixed>
- $is_order : bool = false
-
Whether the products are order items or cart items.
Return values
array<string|int, mixed> —get_cart_subtotal()
Get the appropriate subtotal used to determine the dynamic discount amount generated by the fixed price.
private
get_cart_subtotal(WC_Cart $cart) : float
- If the discount applies to all products, then the subtotal of the cart is used.
- If the discount applies to specific products, then the subtotal of those products combined is used.
- If the discount applies to specific categories, then the subtotal of the products in those categories combined is used.
The subtotal also needs to take into account whether prices include tax.
Parameters
- $cart : WC_Cart
-
The cart.
Return values
float —The subtotal.
get_cheapest_product_with_required_qty()
Get the cheapest product with the required quantity.
private
get_cheapest_product_with_required_qty(array<string|int, mixed> $products, int $required_qty[, bool $is_order = false ]) : array<string|int, mixed>|null|WC_Order_Item_Product
Parameters
- $products : array<string|int, mixed>
-
Array of products in the cart or order.
- $required_qty : int
-
The required quantity.
- $is_order : bool = false
-
Whether the products are order items or cart items.
Return values
array<string|int, mixed>|null|WC_Order_Item_Product —The cheapest product with the required quantity, or null if no product was found.
get_order_subtotal()
Get the appropriate subtotal used to determine the dynamic discount amount generated by the fixed price.
private
get_order_subtotal(WC_Order $order) : float
- If the discount applies to all products, then the subtotal of the order is used.
- If the discount applies to specific products, then the subtotal of those products combined is used.
- If the discount applies to specific categories, then the subtotal of the products in those categories combined is used.
The subtotal also needs to take into account whether prices include tax.
Parameters
- $order : WC_Order
-
The order.
Return values
float —The subtotal.
maybe_discount_all_items()
Maybe discount all items.
private
maybe_discount_all_items(array<string|int, mixed> $items[, bool|WC_Cart $cart = false ][, bool|WC_Order $order = false ]) : void
Parameters
- $items : array<string|int, mixed>
-
Array of cart items or order items.
- $cart : bool|WC_Cart = false
-
The cart.
- $order : bool|WC_Order = false
-
The order.
Return values
void —order_has_product_with_required_qty()
Check if the order has a product with the required quantity.
private
order_has_product_with_required_qty(array<string|int, mixed> $products[, bool|int $custom_additional_qty = false ][, bool $skip_additional_qty = false ]) : bool
Parameters
- $products : array<string|int, mixed>
-
Array of products in the order.
- $custom_additional_qty : bool|int = false
-
Whether to use the custom additional quantity or not.
- $skip_additional_qty : bool = false
Return values
bool —True if the order has a product with the required quantity, false otherwise.