PressXtoJason
PressXtoJason

Reputation: 68

WooCommerce how to perform conditional checks for custom categories

I have a Woocommerce store and I'm trying to add prefixes to the order number based on if the order contains a product within one of two different categories.

The two categories are Customs and Refurbished.

This code works perfectly if the order only contains a Custom or a Refurbished product, but the problem occurs when an order contains both a Custom and Refurbished product. This code will just apply the prefix of CPC- or REF- depending on whatever item is first in the order.

I want to make it so that if an order contains both of these categories, that the system defaults to adding the Custom prefix of CPC- but I can't figure out how to do that.

Below is my code, look for the 💩 to find my failed attempt to fix this

add_filter( 'woocommerce_order_number', 'change_woocommerce_order_number' );

function change_woocommerce_order_number( $order_id ) {
      
   // 1. Get order object
   $order = wc_get_order( $order_id );
  
   // 2. Initialize $cat_in_order variable
   $cat_in_order = '';
  
   // 3. Get order items and loop through them...
   // ... if product in category, edit $cat_in_order
   $items = $order->get_items(); 
     
   foreach ( $items as $item ) {
      $product_id = $item->get_product_id();
      if ( has_term( 'refurbished', 'product_cat', $product_id )) {
         $cat_in_order = 'refurbished';
         break;
      }  elseif ( has_term( 'customs', 'product_cat', $product_id )) {
         $cat_in_order = 'customs';
         break;
//
// 💩 Here's my attempt to fix this, but it's not working 💩
//
      }  elseif ( has_term( 'customs', 'product_cat', $product_id ) && has_term( 'refurbished', 'product_cat', $product_id )) {
         $cat_in_order = 'customs';
         break;
      }
   }
  
   // 4. Add Order Prefix if in Customs Category 
   if ( $cat_in_order == 'refurbished' ) {
        $prefix = 'REF-';
        $new_order_id = $prefix . $order_id;
        return $new_order_id;
   } elseif ( $cat_in_order == 'customs' ) {
        $prefix = 'CPC-';
        $new_order_id = $prefix . $order_id;
        return $new_order_id;
   } else {
       return $order_id;
   }
    
}

Upvotes: 2

Views: 218

Answers (3)

Maulik patel
Maulik patel

Reputation: 2432

foreach ( $items as $item ) {
      $product_id = $item->get_product_id();
      if ( has_term( 'customs', 'product_cat', $product_id ) && has_term( 'refurbished', 'product_cat', $product_id )) {
         $cat_in_order = 'customs';
         
      }
      elseif ( has_term( 'refurbished', 'product_cat', $product_id )) {
         $cat_in_order = 'refurbished';
         
      }  elseif ( has_term( 'customs', 'product_cat', $product_id )) {
         $cat_in_order = 'customs';
         ;

      }  
   }

Upvotes: 0

Ruvee
Ruvee

Reputation: 9097

There are multiple ways to set this up, but since you're already using if statement, I'll take the same approach!

The simple answer would be to add another condition to your if/elseif statements.

So replace your first conditional check with this line:

if (has_term('refurbished', 'product_cat', $product_id) && !has_term('customs', 'product_cat', $product_id))

Replace the second condition with this one:

elseif (has_term('customs', 'product_cat', $product_id) && !has_term('refurbished', 'product_cat', $product_id))

And the last condition stays intact!

elseif (has_term('customs', 'product_cat', $product_id) && has_term('refurbished', 'product_cat', $product_id))

So the entire conditional section of your snippet would be something like this:

foreach ($items as $item) 
{
    $product_id = $item->get_product_id();
    if 
    (
        has_term('refurbished', 'product_cat', $product_id) 
        && 
        !has_term('customs', 'product_cat', $product_id)
    )
    {
        $cat_in_order = 'refurbished';
    } 
    elseif 
      (
        has_term('customs', 'product_cat', $product_id) 
        && 
        !has_term('refurbished', 'product_cat', $product_id)
      )
    {
        $cat_in_order = 'customs';
    } 
    elseif 
      (
        has_term('customs', 'product_cat', $product_id) 
        && 
        has_term('refurbished', 'product_cat', $product_id)
      ) 
    {
        $cat_in_order = 'customs';
    }
}

Upvotes: 3

Domenico Lorusso
Domenico Lorusso

Reputation: 39

Starting from answer of Ruvee there is some tuning we can perform.

The problem is implicity you set a hierarchy in your choice.

So if Custom attribute is set this has precedence.

in this case we can simply the code in this way.

foreach ($items as $item) {
$product_id = $item->get_product_id();
if (  has_term('customs', 'product_cat', $product_id) ){
    $cat_in_order = 'customs';

} elseif ( has_term('refurbished', 'product_cat', $product_id) )  {
    $cat_in_order = 'refurbished';
}  else {
    
    // Manage the exception!
}

}

So if Custom is true elseif is not processed and we don't need to set other conditions.

However, pay attantion on the break usage, is not needed in if / elseif statement, and it's wrong.

Upvotes: 0

Related Questions