0
votes

My initial problem is that AJAX add-to-cart button on Woocommerce doesn't seem to work on Private products (which we're only displaying to a selection of customers): the wheel appears on the add-to-cart button, the page reloads, and the product is added to cart but there's no notice that it has, so it's quite confusing.

After lots of research, all I could find is this thread https://wordpress.org/support/topic/add-to-cart-redirecting-only-on-private-products-2/ which led me to believe it's most likely a bug?

I tried to come up with a work-around: disable AJAX add-to-cart and revert to default behaviour on Private products only so we can still display some kind of notification that the product has been added to cart. I've thought of this code as a starting point:

add_action( 'wp_enqueue_scripts', 'bbloomer_disable_woocommerce_cart_fragments', 11 ); 
 
function bbloomer_disable_woocommerce_cart_fragments() { 
   if ( is_front_page() ) wp_dequeue_script( 'wc-cart-fragments' ); 
}

Would this work? And how would I modify it so the condition is "if is private product"?

1

1 Answers

0
votes

You could solve the problem by thinking the other way around. Instead of showing private products only for specific users you could hide them for all other user roles (leaving the products with the "publish" status).

This way the Ajax problem does not arise.

If the user has one of the roles defined in the $user_roles array of the following function, it hides all products in the $product_ids_to_hide array:

// hide products based on user role
add_filter( 'woocommerce_product_is_visible', 'hide_products_by_user_role', 10, 2 );
function hide_products_by_user_role( $visible, $product_id ) {
    // only if the user is logged in
    if ( ! is_user_logged_in() ) {
        return $visible;
    }
    // set the product ids to hide
    $product_ids_to_hide = array( 12, 14 );
    // sets the user roles for which products are to be hidden
    $user_roles = array( 'custom_role_1', 'custom_role_2' );
    $user = wp_get_current_user();
    if ( array_intersect( $user_roles, $user->roles ) && in_array( $product_id, $product_ids_to_hide ) ) {
        return false;
    }
    return $visible;
}

To reply to your comment:

If you want to allow the user to modify the product ids to be hidden based on the user role you can create a .csv file to be uploaded to FTP with the list of product ids, one per line.

If your client in the future wants to remove or add a product id, he can do so simply by overwriting the .csv file with an FTP import or directly in the file manager (if the hosting allows it).

The file I created as an example will be called product-ids-to-hide.csv and will need to be uploaded to the same directory as the functions.php file. No header is required. Here is an example:

349
235
456
745

and this will be the new updated function:

// hide products based on user role
add_filter( 'woocommerce_product_is_visible', 'hide_products_by_user_role', 10, 2 );
function hide_products_by_user_role( $visible, $product_id ) {
    // only if the user is logged in
    if ( ! is_user_logged_in() ) {
        return $visible;
    }

    // sets the user roles for which products are to be hidden
    $user_roles = array( 'custom_role_1', 'custom_role_2' );
    $user = wp_get_current_user();
    // only if the user has at least one role present in the array
    if ( empty( array_intersect( $user_roles, $user->roles ) ) ) {
        return $visible;
    }

    // get an array with product ids
    $product_ids_to_hide = file( realpath( __DIR__ . '/product-ids-to-hide.csv' ), FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );
    if ( in_array( $product_id, $product_ids_to_hide ) ) {
        return false;
    }

    return $visible;
}

The code has been tested and works. Add it to your active theme's functions.php.