php - Disable WooCommerce products for some time if customer has purchased specific product

In WooCommerce would like to disable purchases from defined products ( B, C and D ) during a month if customer has purchased a product ( A or B ), so products B, C and D should be disabled for a month for that specific user only.

Note: In the code below I am using has_bought_items() a custom function from Check if a user has purchased specific products in WooCommerce answer.

My code attempt:

$product_ids = array( 255, 256 );

$args2 = array(
    'customer_id' => get_current_user_id()
);
$orders = wc_get_orders( $args2 );
$orders = has_bought_items( get_current_user_id(), $product_ids );

if($orders){
    add_filter('woocommerce_is_purchasable', 'disable_product', 10, 2 );
 
    function disable_product( $is_purchasable, $product ) {
 
        if( in_array( $product->get_id(), array( 256, 257, 258 ) ) ) {
            return false;
        }
 
        return $is_purchasable;
    }
}

So far I am able to disable the products for the user. But I don't how can I get date from the purchase and add a month to it. Any help will be great. 

Answer

Solution:

You need to customize a bit the code from has_bought_items() to get the highest "post date" from a customer order that has purchased product id 255 or 256 (for the current user ID).

Then using strtotime() function you will be able to disable purchases on other defined products during a month.

The code using a customized SQL query:

add_filter('woocommerce_is_purchasable', 'disable_specific_product_conditionally', 10, 2 );
function disable_specific_product_conditionally( $is_purchasable, $product ) {
    $targeted_ids = array( 256, 257, 258 ); // Related targeted products to be disabled

    if( in_array( $product->get_id(), $targeted_ids ) && is_user_logged_in() ) {
        global $wpdb;

        $product_ids   = array( 255, 256 ); // Check orders for this products

        // Count the number of products
        $date = $wpdb->get_var("
            SELECT p.post_date FROM {$wpdb->prefix}posts AS p
            INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
            INNER JOIN {$wpdb->prefix}woocommerce_order_items AS woi ON p.ID = woi.order_id
            INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS woim ON woi.order_item_id = woim.order_item_id
            WHERE p.post_status IN ( 'wc-" . implode( "','wc-", array_map( 'esc_sql', wc_get_is_paid_statuses() ) ) . "' )
            AND pm.meta_key = '_customer_user'
            AND pm.meta_value = '".get_current_user_id()."'
            AND woim.meta_key IN ( '_product_id', '_variation_id' )
            AND woim.meta_value IN (".implode(',', $product_ids).")
            ORDER BY p.post_date DESC
        ");
        
        // When a date is found we disable during a month purchases from this date
        return ! empty($date) && strtotime('now') > strtotime( $date . ' + 1 month') ? false : $is_purchasable;
    }
    return $is_purchasable;
}

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

Source