phpwordpresswoocommerceordersusermetadata

Updating user custom metadata from WooCommerce order status change


I'm pretty new at coding and I have difficulties finding out why my code does not work properly.

In WordPress/Woocommerce, I want to check if the customer has bought a product (box subscription), and if so, the customer can access a special content.

For that, I used to put the information in the database in user_meta.

Here is the code I used before when it worked :

// Order check to activate private content
add_action( 'woocommerce_order_status_changed', 'TB_verify_order_content', 10, 3 );
function TB_verify_order_content( $order_id, $old_status, $new_status ) {
    if( $new_status != 'processing' ) return;
    
    $order = wc_get_order( $order_id );
    $user_id = $order->get_user_id();
    
    // Check the product in the order
    $items = $order->get_items();
    foreach ( $items as $item ) {
        $product_id = $item->get_product_id();
        
        if( $product_id == 18899 ) {

            // Check date user put in form
            $item_meta_data = $item->get_formatted_meta_data( '_', true );
            foreach( $item_meta_data as $the_data ) {
                if( $the_data->key == 'End Date' ) $enddate = $the_data->value;
            }
            
            // Check if it's a renew
            $renew = get_post_meta( $order_id, 'is_a_renew', true );
            $is_a_renew = ( isset( $renew ) && $renew == 'yes' ) ? true : false;
            
            
            if( $enddate != '' ) {
                $first_date = date( 'd/m/Y' );
                
                // Access to private content : setup at first subscription
                if ( !$is_a_renew ) {
                    $tab_access = array( 'access_begining' => time(), 
                                        'access_first_date' => $first_date, 
                                        'access_end' => '-1', 
                                        'access_end_date' => '', 
                                        'end' => $enddate                               
                                        );
                    update_user_meta( $user_id, 'BO_access_content', $tab_access );
                    
                    // End of subscription : subscription ID = Order ID of first order +1
                    $time_end = TB_end_of_subscription( $first_date, $enddate );
                    update_post_meta( $order_id+1, 'expired_date' , $time_end );
                    
                    // Date of last payment : max 25 days before 3 years
                    $time_end = DateTime::createFromFormat( 'd/m/Y', $enddate );
                    $time_end->modify( '- 25 days' );
                    $time_thirtysix = TB_end_of_subscription( $first_date, $enddate, 36 ); // 36th subscription month
                    $tab_payments = array( 'date_dp' => date( 'd/m/Y', $time_end->getTimestamp() ),
                                            'time_adp' => $time_thirtysix
                                            );
                    update_post_meta( $order_id, 'last_payment' , $tab_payments );
                }
                
                // Data to check box and next box
                $num_box = TB_calculate_box( $first_date, $enddate );
                $next_month = date( 'd/m/Y', mktime(0, 0, 0, date('m')+1, 5, date('Y') ) );
                
                $tab_box = array( array( 'box' => $num_box, 'date' => $first_date ) );
                if( $num_box < 36 ) $tab_box[] = array( 'box' => $num_box+1, 'date' => $next_month );

                update_post_meta( $order_id, 'BO_envoi_box', $tab_box );
            }
                }
            }
            
        }
    }
}

// Evaluating subscription month and verify end of subscription
function TB_max_month_autorized( $tab_param ) {
    $return = -1;   
    
    // Ongoing month
    $return = TB_calculate_month( $tab_param['access_first_date'], $tab_param['end'] );
    
    // If subscription stops, changes content access autorization 
    if( $tab_param['access_end'] != '-1' && $tab_param['access_end_date'] != '' ) {
        $return = TB_calculate_month( $tab_param['access_first_date'], $tab_param['acces_end_date'] );
    }
    
    return $return;
}

// Add content in tab "My content"
add_action( 'woocommerce_account_downloads_endpoint', 'TB_add_content' );
function TB_add_content() {
    // Getting user data
    $current_user = wp_get_current_user();
    $access_autorized = false;
    $month_user = -1;
    
    if ( $current_user->ID > 0 ) {
                    
        $tab_access = get_user_meta( $current_user->ID, 'BO_access_content', true );
        
        // Calculation of subscription month and number of box
        if( isset( $tab_access ) && is_array( $tab_access ) && $tab_access['end'] != '' ) {
            $month_user = TB_max_month_autorized( $tab_access );
        } 
                            
        // Subscription ongoing, list of accessible content
        if( $month_user > 0 ) {
            $query = new WP_Query( array(
                'post_type'     => 'page',
                'meta_key'      => '_wp_page_template',
                'meta_value'    => 'templates/template-private_page.php',
                'order'         => 'DESC',
                'orderby'       => 'menu_order',
                'meta_key'      => 'access_month',
                'meta_value'    => $month_user,
                'meta_compare'  => '<=',
                'posts_per_page' => -1,
            ) );
            
            if ( $query->have_posts() ) {
                while ( $query->have_posts() ) : $query->the_post();
                    $menu_order = get_post_field('menu_order', get_the_ID());

                    if ($menu_order < 100) {
                        echo '<a class="button content_link" target="_blank" title="'.get_the_title().'" href="'.get_the_permalink().'">';
                            the_title();
                        echo '</a>';
                    
                        echo '<br/>';
                    }
                endwhile; // end of the loop.
            } 
            wp_reset_query();
        }
    }
}

Then I wanted to add another condition for another product and it stopped working :(

Here is the code I am currently using :

// Order check to activate private content
add_action( 'woocommerce_order_status_changed', 'TB_verify_order_content', 10, 3 );
function TB_verify_order_content( $order_id, $old_status, $new_status ) {
   // Check New product in the order
    foreach ( $items as $item ) {
        $product_id = $item->get_product_id();
        
        if( $product_id == 19232 ) {
            update_user_meta( $user_id, 'BO_access_special_content', true );
        }
    }
}
    

// Add content in tab "My content"
add_action( 'woocommerce_account_downloads_endpoint', 'TB_add_content' );
function TB_add_content() {

    // Check if user bought product and Display Special Content
    $current_user = wp_get_current_user();
    if ( $current_user->ID > 0 ) {
        $user_orders = wc_get_orders( array( 'customer_id' => $current_user->ID ) );
        foreach ( $user_orders as $user_order ) {
            if ( get_post_meta( $user_order->get_id(), 'BO_access_special_content', true ) ) {                
                $article_ids = array(19232);
                foreach ($article_ids as $article_id) {
                    echo '<a class="button content_link" target="_blank" title="'.get_the_title($article_id).'" href="'.get_permalink($article_id).'">';
                    echo get_the_title($article_id);
                    echo '</a><br/>';
                }
            }
        }
    }
}

At this point, I don't know where the problem is, I checked in database and user_meta is empty when I perform real tests.

I checked in database and it's empty. When I use my previous function.php template, database is filled with correct info. I emptied cache and still got no result.


Solution

  • In your recent code, first you save 'BO_access_special_content' custom field as user metadata but not as order metadata, so you don't need to query customer orders.

    Also, the hook woocommerce_order_status_changed has 4 available arguments. The last argument is the WC_Order object $order, so you don't need to get the order object, like in your previous code).

    If you don't add your new code in your previous functions, you need different unique function names, than previous existing ones. Also, there are some missing things in your first new function.

    Instead, try the following code replacement:

    // Order check to activate private content
    add_action( 'woocommerce_order_status_changed', 'TB_verify_order_content_2', 10, 4 );
    function TB_verify_order_content_2( $order_id, $old_status, $new_status, $order ) {    
        if( $new_status !== 'processing' ) return;
        
        $user_id = $order->get_customer_id();
    
       // Check New product in the order
        foreach ( $order->get_items() as $item ) {
            $product_id = $item->get_product_id();
            
            if( $product_id == 19232 ) {
                update_user_meta( $user_id, 'BO_access_special_content', true );
            }
        }
    }
    
    // Add content in tab "My content"
    add_action( 'woocommerce_account_downloads_endpoint', 'TB_add_content_2' );
    function TB_add_content_2() {
        global $current_user;
    
        if ( $current_user->ID > 0 ) {
    
            if ( get_user_meta( $current_user->ID, 'BO_access_special_content', true ) ) {                
                $article_ids = array(19232);
    
                foreach ($article_ids as $article_id) {
                    echo '<a class="button content_link" target="_blank" title="' . get_the_title($article_id) . '" href="'.get_permalink($article_id).'">';
                    echo get_the_title($article_id);
                    echo '</a><br/>';
                }
            }
        }
    }
    

    Now the code should work…


    As WooCommerce is migrating orders to custom tables, since WooCommerce 3 you need to use all available CRUD methods instead of old WordPress post meta functions. This is mandatory for newly WooCommerce High-Performance Order Storage (HPOS).

    For WooCommerce subscriptions, always try to use their methods and functions too.

    Here is the complete revised version from your previous and last code, merged…

    Try the following (untested as there is missing custom function and custom metadata usage):

    // Order check to activate private content
    add_action( 'woocommerce_order_status_changed', 'TB_verify_order_content', 10, 4 );
    function TB_verify_order_content( $order_id, $old_status, $new_status, $order ) {
        if( $new_status !== 'processing' ) return;
        
        $user_id = $order->get_customer_id();
        
        // Check the product in the order
        foreach ( $order->get_items() as $item ) {
            if( $item->get_product_id() == 18899 ) {
                // Check date user put in form
                $end_date = $item->get_meta('End Date');
                
                // Check if it's a renew
                $renew = $order->get_meta('is_a_renew');
                
                
                if( $end_date ) {
                    $first_date = date( 'd/m/Y' );
                    
                    // Access to private content : setup at first subscription
                    if ( $renew !== 'yes' ) {
                        update_user_meta( $user_id, 'BO_access_content', array( 
                            'access_begining' => time(), 
                            'access_first_date' => $first_date, 
                            'access_end' => '-1', 
                            'access_end_date' => '', 
                            'end' => $end_date                               
                        ) );
                        
                        // End of subscription : subscription ID = Order ID of first order +1
                        $time_end = TB_end_of_subscription( $first_date, $end_date );
    
                        // Get the current WC_Subscription from order
                        $subscription = current(wcs_get_subscriptions_for_order( $order_id, array('order_type' => 'any') ));
                        $subscription->update_meta_data( 'expired_date' , $time_end );
                        $subscription->save();
                        
                        // Date of last payment : max 25 days before 3 years
                        $time_end = DateTime::createFromFormat( 'd/m/Y', $end_date );
                        $time_end->modify( '- 25 days' );
    
                        $order->update_meta_data('last_payment' , array( 
                            'date_dp' => date( 'd/m/Y', $time_end->getTimestamp() ),
                            'time_adp' => TB_end_of_subscription( $first_date, $end_date, 36 ), // 36th subscription month
                        ));
                    }
                    
                    // Data to check box and next box
                    $num_box = TB_calculate_box( $first_date, $end_date );
                    $next_month = date( 'd/m/Y', mktime(0, 0, 0, date('m')+1, 5, date('Y') ) );
                    
                    $tab_box = array( array( 'box' => $num_box, 'date' => $first_date ) );
                    if( $num_box < 36 ) {
                        $tab_box[] = array( 'box' => $num_box+1, 'date' => $next_month );
                    }
                    $order->update_meta_data('BO_envoi_box', $tab_box );
                    $order->save();
                }
            }
            elseif( $item->get_product_id() == 19232 ) {
                update_user_meta( $user_id, 'BO_access_special_content', true );
            }
        }
    }
    
    // Evaluating subscription month and verify end of subscription
    function TB_max_month_autorized( $tab_param ) {
        // Ongoing month
        $return = TB_calculate_month( $tab_param['access_first_date'], $tab_param['end'] );
        
        // If subscription stops, changes content access autorization 
        if( $tab_param['access_end'] != '-1' && $tab_param['access_end_date'] != '' ) {
            $return = TB_calculate_month( $tab_param['access_first_date'], $tab_param['acces_end_date'] );
        }
        return $return;
    }
    
    // Add content in tab "My content"
    add_action( 'woocommerce_account_downloads_endpoint', 'TB_add_content' );
    function TB_add_content() {
        global $current_user;
        
        if ( $current_user->ID > 0 ) {
        
            $access_autorized = false;
            $month_user = -1;
                        
            $tab_access = get_user_meta( $current_user->ID, 'BO_access_content', true );
            
            // Calculation of subscription month and number of box
            if( isset( $tab_access ) && is_array( $tab_access ) && $tab_access['end'] != '' ) {
                $month_user = TB_max_month_autorized( $tab_access );
            } 
                                
            // Subscription ongoing, list of accessible content
            if( $month_user > 0 ) {
                $query = new WP_Query( array(
                    'post_type'     => 'page',
                    'meta_key'      => '_wp_page_template',
                    'meta_value'    => 'templates/template-private_page.php',
                    'order'         => 'DESC',
                    'orderby'       => 'menu_order',
                    'meta_key'      => 'access_month',
                    'meta_value'    => $month_user,
                    'meta_compare'  => '<=',
                    'posts_per_page' => -1,
                ) );
                
                if ( $query->have_posts() ) {
                    while ( $query->have_posts() ) : $query->the_post();
                        $menu_order = get_post_field('menu_order', get_the_ID());
    
                        if ($menu_order < 100) {
                            echo '<a class="button content_link" target="_blank" title="'.get_the_title().'" href="'.get_the_permalink().'">';
                                the_title();
                            echo '</a><br/>';
                        }
                    endwhile; // end of the loop.
                } 
                wp_reset_query();
            }
    
            if ( get_user_meta( $current_user->ID, 'BO_access_special_content', true ) ) {                
                $article_ids = array(19232);
    
                foreach ($article_ids as $article_id) {
                    echo '<a class="button content_link" target="_blank" title="' . get_the_title($article_id) . '" href="'.get_permalink($article_id).'">';
                    echo get_the_title($article_id);
                    echo '</a><br/>';
                }
            }
        }
    }
    

    It should work.