Search code examples
phpwoocommerceordersemail-notificationscoupon

Custom code in Woocommerce causes site crash when updating order status


If I try and update an order, ie: When looking at an order in backend, Order Actions > Choose and Action > Resend order notification as an example, it gives me a critical error as below.

This only seems to happen on certain orders that look to have coupons utilised on orders?

An error of type E_ERROR was caused in line 21 of the file /usr/www/users/africgebks/wp-content/themes/woodmart-child/functions.php. Error message: Uncaught TypeError: count(): Argument #1 ($value) must be of type Countable|array, null given in /usr/www/users/africgebks/wp-content/themes/woodmart-child/functions.php:21
Stack trace:
#0 /usr/www/users/africgebks/wp-includes/class-wp-hook.php(310): display_applied_coupons(Object(Automattic\WooCommerce\Admin\Overrides\Order), true, false, Object(WC_Email_New_Order))
#1 /usr/www/users/africgebks/wp-includes/class-wp-hook.php(334): WP_Hook->apply_filters('', Array)
#2 /usr/www/users/africgebks/wp-includes/plugin.php(517): WP_Hook->do_action(Array)
#3 /usr/www/users/africgebks/wp-content/plugins/woocommerce/templates/emails/admin-new-order.php(35): do_action('woocommerce_ema...', Object(Automattic\WooCommerce\Admin\Overrides\Order), true, false, Object(WC_Email_New_Order))
#4 /usr/www/users/africgebks/wp-content/plugins/woocommerce/includes/wc-core-functions.php(345): include('/usr/www/users/...')
#5 /usr/www/users/africgebks/wp-content/plugins/woocommerce/includes/wc-core-functions.php(364): wc_get_template('emails/admin-ne...', Array, '', '')
#6 /usr/www/users/africgebks/wp-content/plugins/woocommerce/includes/emails/class-wc-email-new-order.php(134): wc_get_template_html('emails/admin-ne...', Array)
#7 /usr/www/users/africgebks/wp-content/plugins/woocommerce/includes/emails/class-wc-email.php(581): WC_Email_New_Order->get_content_html()
#8 /usr/www/users/africgebks/wp-content/plugins/woocommerce/includes/emails/class-wc-email-new-order.php(111): WC_Email->get_content()
#9 /usr/www/users/africgebks/wp-content/plugins/woocommerce/includes/admin/meta-boxes/class-wc-meta-box-order-actions.php(156): WC_Email_New_Order->trigger(14992, Object(Automattic\WooCommerce\Admin\Overrides\Order), true)
#10 /usr/www/users/africgebks/wp-includes/class-wp-hook.php(310): WC_Meta_Box_Order_Actions::save(14992, Object(WP_Post))
#11 /usr/www/users/africgebks/wp-includes/class-wp-hook.php(334): WP_Hook->apply_filters(NULL, Array)
#12 /usr/www/users/africgebks/wp-includes/plugin.php(517): WP_Hook->do_action(Array)
#13 /usr/www/users/africgebks/wp-content/plugins/woocommerce/includes/admin/class-wc-admin-meta-boxes.php(258): do_action('woocommerce_pro...', 14992, Object(WP_Post))
#14 /usr/www/users/africgebks/wp-includes/class-wp-hook.php(312): WC_Admin_Meta_Boxes->save_meta_boxes(14992, Object(WP_Post))
#15 /usr/www/users/africgebks/wp-includes/class-wp-hook.php(334): WP_Hook->apply_filters('', Array)
#16 /usr/www/users/africgebks/wp-includes/plugin.php(517): WP_Hook->do_action(Array)
#17 /usr/www/users/africgebks/wp-includes/post.php(4751): do_action('save_post', 14992, Object(WP_Post), true)
#18 /usr/www/users/africgebks/wp-includes/post.php(4853): wp_insert_post(Array, false, true)
#19 /usr/www/users/africgebks/wp-admin/includes/post.php(445): wp_update_post(Array)
#20 /usr/www/users/africgebks/wp-admin/post.php(227): edit_post()
#21 {main}
  thrown

code added by woocommerce coupons to functions.php file. I assume this is where the error is coming from

// The email function hooked that display the text
add_action( 'woocommerce_email_order_details', 'display_applied_coupons', 10, 4 );
function display_applied_coupons( $order, $sent_to_admin, $plain_text, $email ) {

    // Only for admins and when there at least 1 coupon in the order
    if ( ! $sent_to_admin && count($order->get_items('coupon') ) == 0 ) return;

    foreach( $order->get_items('coupon') as $coupon ){
        $coupon_codes[] = $coupon->get_code();
    }
    // For one coupon
    if( count($coupon_codes) == 1 ){
        $coupon_code = reset($coupon_codes);
        echo '<p>'.__( 'Coupon Used: ').$coupon_code.'<p>';
    } 
    // For multiple coupons
    else {
        $coupon_codes = implode( ', ', $coupon_codes);
        echo '<p>'.__( 'Coupons Used: ').$coupon_codes.'<p>';
    }
}
  • WordPress version 6.3
  • Active theme: Woodmart Child (version 1.0.0)
  • Current plugin: (version )
  • PHP version 8.1.22

Solution

  • There are some mistakes in your code, try this simplified code version instead:

    add_action( 'woocommerce_email_order_details', 'display_applied_coupons', 10, 4 );
    function display_applied_coupons( $order, $sent_to_admin, $plain_text, $email ) {
        if ( $sent_to_admin ) {
            $coupon_codes = (array) $order->get_coupon_codes();
    
            if( count($coupon_codes) === 1 ){
                echo '<p>'.__( 'Coupon Used: ').reset($coupon_codes).'<p>';
            } elseif( count($coupon_codes) > 1 ) {
                echo '<p>'.__( 'Coupons Used: ').implode( ', ', $coupon_codes).'<p>';
            }
        }
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works, It will solve your issue. The problem was in count($order->get_items('coupon') ).