Search code examples
phpwordpresswoocommerceordersuser-roles

Change user role based on total items purchased in Woocommerce


In Woocommerce I am trying to combine these two functions:

The first one gets the total amount of ordered items by a user (all time)

function get_user_total_purchased_items( $user_id = 0 ){
    global $wpdb;

    $customer_id = $user_id === 0 ? get_current_user_id() : (int) $user_id;

    return (int) $wpdb->get_var( "
        SELECT SUM(woim.meta_value)
        FROM {$wpdb->prefix}woocommerce_order_items AS woi
        INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS woim ON woi.order_item_id = woim.order_item_id
        INNER JOIN {$wpdb->prefix}posts as p ON woi.order_id = p.ID
        INNER JOIN {$wpdb->prefix}postmeta as pm ON woi.order_id = pm.post_id
        WHERE woi.order_item_type = 'line_item'
        AND p.post_type LIKE 'shop_order'
        AND p.post_status IN ('wc-completed')
        AND pm.meta_key LIKE '_customer_user'
        AND pm.meta_value LIKE '$customer_id'
        AND woim.meta_key LIKE '_qty'
    " );
}

And the second one changes user role if user orders a certain item.

function change_role_on_purchase( $order_id ) {

    $order = new WC_Order( $order_id );
    $items = $order->get_items();

    foreach ( $items as $item ) {
        $product_name = $item['name'];
        $product_id = $item['product_id'];
        $product_variation_id = $item['variation_id'];

        if ( $order->user_id > 0 && $product_id == '416' ) {
            update_user_meta( $order->user_id, 'paying_customer', 1 );
            $user = new WP_User( $order->user_id );

            // Remove role
            $user->remove_role( 'subscriber' ); 

            // Add role
            $user->add_role( 'premium' );
        }
    }
}

add_action( 'woocommerce_order_status_processing', 'change_role_on_purchase' );

What I am trying to accomplish is that if a user has ordered 50-99 items totally his user role is to be changed from standard_user to bronze_user and if he has ordered 100-199 his user role bronze_user -> silver_user and if total items exceed 200 hus user role silver_user -> gold_user.

The first function works well and comes from this answer.

Now just trying to figure out how to implement it into the second function.


Solution

  • Since Woocommerce 3 your code is a bit outdated and need some changes. The following should change the user role conditionally based on number of purchased items (untested):

    function get_user_total_purchased_items( $user_id = 0 ){
        global $wpdb;
    
        $customer_id = $user_id === 0 ? get_current_user_id() : (int) $user_id;
    
        return (int) $wpdb->get_var( "
            SELECT SUM(woim.meta_value)
            FROM {$wpdb->prefix}woocommerce_order_items AS woi
            INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS woim ON woi.order_item_id = woim.order_item_id
            INNER JOIN {$wpdb->prefix}posts as p ON woi.order_id = p.ID
            INNER JOIN {$wpdb->prefix}postmeta as pm ON woi.order_id = pm.post_id
            WHERE woi.order_item_type = 'line_item'
            AND p.post_type LIKE 'shop_order'
            AND p.post_status IN ('wc-completed')
            AND pm.meta_key LIKE '_customer_user'
            AND pm.meta_value LIKE '$customer_id'
            AND woim.meta_key LIKE '_qty'
        " );
    }
    
    add_action( 'woocommerce_order_status_processing', 'change_role_on_purchase', 20, 2 );
    function change_role_on_purchase( $order_id, $order ) {
    
        $user_id   = $order->get_customer_id();
        $user      = new WP_User( $user_id );
        $purchases = get_user_total_purchased_items( $user_id );
    
        if( $purchases >= 50 &&  $purchases < 100 && ! in_array( 'bronze_user', $user->roles ) ) {
            // Remove role
            $user->remove_role( 'subscriber' );
    
            // Add role
            $user->add_role( 'bronze_user' );
        }
        elseif( $purchases >= 100 &&  $purchases < 200 && ! in_array( 'silver_user', $user->roles ) ) {
            // Remove role
            $user->remove_role( 'bronze_user' );
    
            // Add role
            $user->add_role( 'silver_user' );
        }
        elseif( $purchases >= 200 && ! in_array( 'gold_user', $user->roles ) ) {
            // Remove role
            $user->remove_role( 'silver_user' );
    
            // Add role
            $user->add_role( 'gold_user' );
        }
    
        if ( $user_id > 0 && $product_id == '416' ) {
            foreach ( $order->get_items() as $item ) {
                if ( $order->user_id > 0 && $item->get_product_id() == '416' ) {
                    update_user_meta( $user_id, 'paying_customer', 1 );
    
                    // Remove role
                    $user->remove_role( 'subscriber' );
    
                    // Add role
                    $user->add_role( 'premium' );
                }
            }
        }
    }
    

    Code goes in function.php file of your active child theme (or active theme). I hope it will work, as I can't test it.


    For reference regarding orders in Woocommerce 3: