1

I am running a function whereby I check if a user has a refunded item/s on their previous order and if they do then apply a credit as a negative cart fee at checkout. The function is working for users who have placed an order before but is causing a critical error on the site for new users.

Fatal error: Uncaught Error: Call to a member function get_refunds() on bool in /wp-content/themes/my-theme/refunds.php:20 Stack trace:  
#0 /wp-includes/class-wp-hook.php(287): add_last_order_refund_total_at_checkout(Object(WC_Cart))  
#1 /wp-includes/class-wp-hook.php(311): WP_Hook->apply_filters('', Array)  
#2 /wp-includes/plugin.php(478): WP_Hook->do_action(Array)  
#3 /wp-content/plugins/woocommerce/includes/class-wc-cart.php(1714): do_action('woocommerce_car...', Object(WC_Cart))  
#4 /wp-content/plugins/woocommerce/includes/class-wc-cart-totals.php(270): WC_Cart->calculate_fees()  
#5 /wp-content/plugins/woocommerce/includes/class-wc-cart-totals.php(829): WC_Cart_Totals->get_fees_from_cart()  
#6 /wp-content/plugins/woocommerce/includes/class-wc- in /wp-content/themes/my-theme/refunds.php on line 20

Here is the code to check for any refunds on the previous order:

//Check total of refunded items from last order - add as a fee at checkout
function add_last_order_refund_total_at_checkout($cart_object){
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    $user_id = get_current_user_id(); // The current user ID
    $customer = new WC_Customer( $user_id );
    $last_order = $customer->get_last_order();
    $order_id = $last_order;

    // Get the WC_Order Object instance (from the order ID)
    $order = wc_get_order( $order_id );

    // Get the Order refunds (array of refunds)
    $order_refunds = $order->get_refunds();
    $total_to_refund = $order->get_total_refunded()*(-1);//WIP need to check which items have tax
    
    if (!empty($order_refunds)) WC()->cart->add_fee( 'Refund', $total_to_refund  );  
}
add_action( 'woocommerce_cart_calculate_fees', 'add_last_order_refund_total_at_checkout', 10, 1 );
 

I believe I need to first check to see if a user has any previous orders otherwise the get_refund() is causing an error as their aren't any orders to check? How would I safely do this?

2 Answers 2

3

If you look to WC_Customer get_last_order() method documentation or source code, you will see:

/*
 * @return WC_Order|false
 */

which means that get_last_order() method can return alternatively:

  • the WC_Order object
  • or false boolean value.

So you can just use in your code:

$last_order = $customer->get_last_order();

if ( ! $last_order )  {
   return; // Exit (Not an order)
}

To avoid this error.


Now you can use is_a() php conditional functions to check that a variable is a from a specific Object class and not something else like:

$last_order = $customer->get_last_order();

if ( ! is_a( $last_order, 'WC_Order' ) ) {
   return; // Exit (Not an order)
}

// Your other code… 

Or you can use method_exists() php conditional functions for WC_Order get_refunds() method, to check that the a variable is a from a specific Object class and not something else:

$last_order = $customer->get_last_order();

if ( ! method_exists( $last_order, 'get_refunds' ) )  {
   return; // Exit (Not an order)
}

// Your other code…

The three cases work nicely, avoiding an error

Sign up to request clarification or add additional context in comments.

Comments

1

Give it a try this way, multiple controls have been added, see comments

// Check total of refunded items from last order - add as a fee at checkout
function add_last_order_refund_total_at_checkout( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    // The current user ID
    $user_id = get_current_user_id();
    
    // User id exists
    if ( $user_id > 0 ) {
        $customer = new WC_Customer( $user_id );
        
        // Get last order
        $last_order = $customer->get_last_order();

        // True
        if ( $last_order ) {

            // Get the order id
            $order_id = $last_order->get_id();
        
            // Order ID exists
            if ( is_numeric( $order_id ) ) {
                // Get the WC_Order Object instance (from the order ID)
                $order = wc_get_order( $order_id );

                // Get the Order refunds (array of refunds)
                $order_refunds = $order->get_refunds();
            
                // NOT empty
                if ( ! empty( $order_refunds) ) {
                    // WIP need to check which items have tax
                    $total_to_refund = $order->get_total_refunded();
                
                    // Add fee
                    $cart->add_fee( 'Refund', $total_to_refund  );
                }
            }
        }
    }
}
add_action( 'woocommerce_cart_calculate_fees', 'add_last_order_refund_total_at_checkout', 10, 1 );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.