Search code examples
phpwordpresswoocommercehook-woocommerceorders

Process custom bulk action on admin Orders list in Woocommerce


I have added a custom action in my woocommerce orders page like shown below, and I also have a custom order field "number of meals". Now what I want is when I select the orders in bulk and use that custom action then count of number of meals should get decreased by 1.
For example if order id 1 & 2 had 15 & 12 number of meals respectively then after using the action it should become 14 & 11…

The screenshot of my orders page, the custom hook and the custom order field I created:

screenshot of my orders page

My code:

add_filter( 'bulk_actions-edit-shop_order', 'decrease_number_of_meals_by_1' );
function decrease_number_of_meals_by_1( $bulk_actions ) {
    $bulk_actions['decrease_number_of_meals'] = 'Decrease Number of Meals by 1';
    return $bulk_actions;
}

add_action( 'admin_action_decrease_number_of_meals', 'fire_my_hook' );
function fire_my_hook() {
    if( !isset( $_REQUEST['post'] ) && !is_array( $_REQUEST['post'] ) )
        return;

    foreach( $_REQUEST['post'] as $order_id ) {

        $order = new WC_Order( $order_id );
        $no_of_meals = $order->get_post_meta( $order_id, '_wc_acof_{3}', true );
    }
}

I am stuck here and have no idea on how to do it further.
Please guide me on how can I achieve this.


Solution

  • You are not using the right way and hooks. Also the right custom field meta key should be _wc_acof_3 when using WooCommerce Admin Custom Order Fields plugin.

    So try the following instead:

    // Add a bulk action to Orders bulk actions dropdown
    add_filter( 'bulk_actions-edit-shop_order', 'decrease_meals_orders_bulk_actions' );
    function decrease_meals_orders_bulk_actions( $bulk_actions ) {
        $bulk_actions['decrease_meals'] = 'Decrease Number of Meals by 1';
        return $bulk_actions;
    }
    
    // Process the bulk action from selected orders
    add_filter( 'handle_bulk_actions-edit-shop_order', 'decrease_meals_bulk_action_edit_shop_order', 10, 3 );
    function decrease_meals_bulk_action_edit_shop_order( $redirect_to, $action, $post_ids ) {
        if ( $action === 'decrease_meals' ){
            $processed_ids = array(); // Initializing
    
            foreach ( $post_ids as $post_id ) {
                // Get number of meals
                $nb_meal = (int) get_post_meta( $post_id, '_wc_acof_3', true );
    
                // Save the decreased number of meals ($meals - 1)
                update_post_meta( $post_id, '_wc_acof_3', $nb_meal - 1 );
    
                $processed_ids[] = $post_id; // Adding processed order IDs to an array
            }
    
            // Adding the right query vars to the returned URL
            $redirect_to = add_query_arg( array(
                'decrease_meals' => '1',
                'processed_count' => count( $processed_ids ),
                'processed_ids' => implode( ',', $processed_ids ),
            ), $redirect_to );
        }
        return $redirect_to;
    }
    
    // Display the results notice from bulk action on orders
    add_action( 'admin_notices', 'decrease_meals_bulk_action_admin_notice' );
    function decrease_meals_bulk_action_admin_notice() {
        global $pagenow;
    
        if ( 'edit.php' === $pagenow && isset($_GET['post_type']) 
        && 'shop_order' === $_GET['post_type'] && isset($_GET['decrease_meals']) {
    
            $count = intval( $_REQUEST['processed_count'] );
    
            printf( '<div class="notice notice-success fade is-dismissible"><p>' .
                _n( 'Decreased meals for %s Order.',
                'Decreased meals for %s Orders.',
                $count,
                'woocommerce'
            ) . '</p></div>', $count );
        }
    

    Code goes in function.php file of your active child theme (or active theme). Tested and works.

    enter image description here

    enter image description here