Next we’ll need to be able to calculate the total of items in the matching category. Depending on how you are working with your fees and discounts, you may want to count the Items by Quantity or just count the amount of different items.
I’m using the Version where I just go with the number of different items but you do what suits your needs. You could combine these and make the quantity and item count a variable, but since I’m assuming most of you will need either one or the other, I suggest you just use one of them.
1/**2 * Cart Category Count3 *4 * Get the Number of Items in the Cart matching a Product Category5 *6 * @param integer $cat_id Product Category ID7 *8 * @return Number of Items9 */10function cart_cat_item_count( $cat_id ) {11 $cat_item_count = 0;12 foreach( WC()->cart->get_cart() as $cart_item )13 if( has_term( $cat_id, 'product_cat', $cart_item['product_id']))14 $cat_item_count += 1;15 return $cat_item_count;16}17
18/**19 * Cart Category Quantity Count20 *21 * Get the total Quantity of Items in the Cart matching a Product Category22 *23 * @param integer $cat_id Product Category ID24 *25 * @return Quantity of Items26 */27function cart_cat_quantity_count( $cat_id ) {28 $cat_quantity_count = 0;29
30 foreach( WC()->cart->get_cart() as $cart_item )31 if( has_term( $cat_id, 'product_cat', $cart_item['product_id'] ) )32 $cat_quantity_count += $cart_item['quantity'];33
34 return $cat_quantity_count;35}
If we are working with percentage based Discounts that just apply to our matching items, we’ll need an additional function that calculates the total of all of our items.
1/**2 * Cart Category Items Total3 *4 * Get the total value of all Cart Items in matching category5 *6 * @param integer $cat_id Product Category ID7 *8 * @return Total Value of Category Items9 */10function cat_cart_total( $cat_id ) {11 $cat_total = 0;12
13 foreach( WC()->cart->get_cart() as $cart_item )14 if( has_term( $cat_id, 'product_cat', $cart_item['product_id'] ) )15 $cat_total += $cart_item['data']->get_price();16
17 return $cat_total;18}
Okay, now we are ready to have some fun!
The idea behind this function is, to create an array for every type of discount, where we would be able to enter Data and then iterate through all of those items and do the whole math and all.
1/**2 * Custom Discount and Fees3 *4 */5function custom_discount_and_fees() {6 global $woocommerce;7
8 global $woocommerce;9 $discounts_and_fees = array(10 // Items Arrays in here11 );12
13 foreach ( $discounts_and_fees as $c ){14 if ( test_condition( cart_cat_item_count($c['cat_id']), $c['operator'], $c['apply_count'] ) ) {15 if( $c['percentage'] ){16 $total = cat_cart_total( $c['cat_id'] );17 $charge = $total * ( $c['percentage'] / 100 );18 } else{19 $charge = $c['value'];20 }21 if( $c['type'] == 'discount'){22 $charge = $charge * -1;23 }24 $woocommerce->cart->add_fee( $c['name'], $charge, true, '' );25 }26 }27}
Let’s have a bit of a closer look at the last part of that, the foreach loop. We have 3 conditions in our case which only need to be applied, if the item count of or the quantity count match a certain criteria, I decided to call this the apply count.
Then we have value based Fees and Discounts and Percentage based. If we want to use percentage, we need to get the total of the items and multiply it with our percentage to get the right fraction.
Since we do have Fees (adding value to the cart) and Discounts (removing value from the cart, thus creating a negative fee) we might have to multiply our entire charge with negative one to turn it into a discount. So for every Discount or Fee, we need to provided that information in an array.
Which brings me back to the Conditions and how we’d add them to make the function work.
1/**2 * Custom Discount and Fees3 *4 */5function custom_discount_and_fees() {6 global $woocommerce;7
8 global $woocommerce;9 $discounts_and_fees = array(10 array(11 'cat_id' => 15,12 'operator' => '<',13 'apply_count' => 3,14 'name' => 'Custom Fee ($5)',15 'type' => 'fee',16 'value' => 5,17 ),18 array(19 'cat_id' => 15,20 'operator' => '==',21 'apply_count' => 3,22 'name' => '3 Item Discount (5%)',23 'type' => 'discount',24 'percentage' => 5,25 ),26 array(27 'cat_id' => 15,28 'operator' => '>=',29 'apply_count' => 4,30 'name' => '4+ Items Discount (10%)',31 'type' => 'discount',32 'percentage' => 10,33 ),34 );35
36 foreach ( $discounts_and_fees as $c ){37 if ( test_condition( cart_cat_item_count($c['cat_id']), $c['operator'], $c['apply_count'] ) ) {38 if( $c['percentage'] ){39 $total = cat_cart_total( $c['cat_id'] );40 $charge = $total * ( $c['percentage'] / 100 );41 } else{42 $charge = $c['value'];43 }44 if( $c['type'] == 'discount'){45 $charge = $charge * -1;46 }47 $woocommerce->cart->add_fee( $c['name'], $charge, true, '' );48 }49 }50}
And then all that’s left is hook it into Woocommerce and we’re done.
// Add custom Discountsadd_action( 'woocommerce_cart_calculate_fees','custom_discount_and_fees' );
And then you’ll be seeing your Discounts based on the Items in the Cart
I hope this was helpful and if you have any questions left, feel free to ask!