Writing Complex Conditional Statements


This is a piece about slowing down and writing out all the conditions that need to be met in advance of actually trying to write the code.  I was recently asked to make some pretty complex things happen in a WooCommerce shopping cart based on Cart Amount, Applied Coupons, and WooDiscount as well as core WooCommerce Shipping rules.  Initially, I thought I could just start writing the code, but as soon as I started testing, I would find that a fix in one scenario would cause a break in another.  So, I slowed down and wrote out the following:

  • // If the cart total is greater than 250 dollars and none of the excluded coupons are applied then the user should get free shipping or pick up in the shop. Remove flat Rate
  • // Here is the list of excluded coupons: $excluded_coupons = array(‘coupon1’, ‘coupon2’, ‘coupon3’, ‘coupon4’, ‘coupon5’, ‘coupon6’, ‘coupon7’, ‘coupon8’);
  • // If an excluded coupon is applied, then free shipping should no longer be an option. They should only get presented pickup in in the shop or flat rate shipping.
  • // If the cart is under 250 they get flat rate shipping or free pickup in the shop.
  • // If a cart is over 250 and they use any other coupon, not in the excluded coupons array, the user should get free shipping or pickup in the shop.
  • // So the only time Flat Rate should get presented is when the cart is under 250 or the user has applied a coupon in the Excluded coupons array.
  • // free shipping should be an option to anyone with a cart over 250 and is not using an excluded coupon

I then started writing my code to accomplish the first task.  Once it was tested and working I wrote the next condition and so on.  Then at the end, I figured out how to combine them using && and ||.

In the end, I was successful in writing a single filter that accommodated all of my conditions.

Now, it took a lot of Xdebugging and figuring out how WooCommerce returns object data.  So the lesson here is that Xdebug or any debugging tools come in really handy and are your friend in cases like this.

Also, make sure that your coupon codes and WooDiscount Rules are entered correctly.  One of the coupons in my excluded coupons array was set up differently than the others and one didn’t even exist in the system which made testing difficult as I got different results when trying to test those two coupons.

/* Change shipping based on total cost purchased and or applied coupons are excluded. */
add_filter( 'woocommerce_shipping_packages', 'hide_flat_rate_if_cart_total_is_greater_than_threshold', 5, 1 );
function hide_flat_rate_if_cart_total_is_greater_than_threshold( $packages ) {
    $threshold1 = 249;
    $applied_coupons = WC()->session->get( 'applied_coupons', array() );
    $amount = WC()->cart->cart_contents_total;
    $availableRates = $packages[0]['rates'];
    $excluded_coupons = array('coupon1', 'coupon2', 'coupon3', 'coupon4', 'coupon5', 'coupon6', 'cooupon7', 'eight', 'nine', 'ten');

    $isExcludedCoupon = false;
    $map = array_map(function($c) use($excluded_coupons, &$isExcludedCoupon ){
        if( in_array($c, $excluded_coupons) ){
            $isExcludedCoupon = true;
        }
        return $c;
    }, $applied_coupons);

    $flatRateKey = '';
    array_map(function($r) use($availableRates, &$flatRateKey){
        $id = $r->get_id();
        $pos = substr_count($id, 'flat_rate');

        if($pos == 1 ){
            $flatRateKey = $id;
        }

        return $r;
    }, $availableRates);

    if ( $amount > $threshold1 && !$isExcludedCoupon) {
        unset($packages[0]['rates'][$flatRateKey]);
    }

    if ($isExcludedCoupon) {
        unset($packages[0]['rates']['woodiscountfree']);
        unset($packages[0]['rates']['free_shipping:2']);
    }

    return $packages;
}