How do I hide WooCommerce products with a given category based on user role
Asked Answered
S

3

6

I have a client with the following issue:

I need to be able to split their WooCommerce WordPress site into essentially two categories. If a user is logged in as a "Wholeseller", only products in the "Wholesale" category get pulled from the database.

However if the user is not logged in or is logged in but not a "Wholeseller", then only products without the "Wholesale" category get pulled from the database.

I figure I'll add something like this to the theme's functions.php file:

add_filter("some_woocommerce_hook", "wholeseller_filter");

function wholeseller_filter() {
    if (current_user->role == "Wholeseller"){
        //omit products without "wholesale" category while browsing whole site
    } else { 
        //omit products with "wholesale" in the category while browsing whole site.
    }
}

I've browsed around StackOverflow, but I haven't found what I'm looking for or quite know what keywords I should be using for my searches.

Can you point me in the right direction?

Schear answered 17/8, 2016 at 19:29 Comment(0)
D
11

Yes it is possible. There is 2 ways:

1) With the pre_get_posts wordpress hook that is called after the query variable object is created, but before the actual query is run. So it is perfect for this case. We imagine here that the ID of 'Wholesale' category is '123'.

Here is the custom code:

function wholeseller_role_cat( $query ) {

    // Get the current user
    $current_user = wp_get_current_user();

    if ( $query->is_main_query() ) {
        // Displaying only "Wholesale" category products to "whole seller" user role
        if ( in_array( 'wholeseller', $current_user->roles ) ) {
            // Set here the ID for Wholesale category 
            $query->set( 'cat', '123' ); 

        // Displaying All products (except "Wholesale" category products) 
        // to all other users roles (except "wholeseller" user role)
        // and to non logged user.
        } else {
            // Set here the ID for Wholesale category (with minus sign before)
            $query->set( 'cat', '-123' ); // negative number
        }
    }
}
add_action( 'pre_get_posts', 'wholeseller_role_cat' );

This code goes on function.php file of your active child theme or theme, or better in a custom plugin.


2) With the woocommerce_product_query WooCommerce hook. (We still imagine here that the ID of 'Wholesale' category is '123').

Here is the custom code:

function wholeseller_role_cat( $q ) {

    // Get the current user
    $current_user = wp_get_current_user();

    // Displaying only "Wholesale" category products to "whole seller" user role
    if ( in_array( 'wholeseller', $current_user->roles ) ) {
        // Set here the ID for Wholesale category 
        $q->set( 'tax_query', array(
            array(
                'taxonomy' => 'product_cat',
                'field' => 'term_id',
                'terms' => '123', // your category ID
            )
        ) ); 

    // Displaying All products (except "Wholesale" category products) 
    // to all other users roles (except "wholeseller" user role)
    // and to non logged user.
    } else {
        // Set here the ID for Wholesale category
        $q->set( 'tax_query', array(
            array(
                'taxonomy' => 'product_cat',
                'field' => 'term_id',
                'terms' => '123', // your category ID
                'operator' => 'NOT IN'
            )
        ) ); 
    }
}
add_action( 'woocommerce_product_query', 'wholeseller_role_cat' );

This code goes on function.php file of your active child theme or theme, or better in a custom plugin.

If you want to use the category slug instead of the category ID you will have to replace partially (both arrays) with:

            array(
                'taxonomy' => 'product_cat',
                'field' => 'slug',
                'terms' => 'wholesale', // your category slug (to use the slug see below)

You could add if you wish and need, some woocommerce conditionals tags in the if statements to restrict this even more.

References:

Diagraph answered 17/8, 2016 at 22:2 Comment(6)
pre_get_posts all the things!! Though I would advise not keeping this in your theme's functions.php and rather move it into a plugin.Blunk
functions.php is the easiest place to drop snippets for quick testing, but I always advise using your theme for display-related functions and keeping any functionality-specific code in plugins.Blunk
You should not run this on pre_get_posts unless you want this run across every query. The Woocommerce hook 'woocommerce_product_query' will allow you to run it only on woocommerce queries.Rident
@NicholasKoskowski I have added to my answer a variant using woocommerce_product_query… Your suggestion is an interesting option, as if you go inside woocommerce core code related functions, they use too pre_get_posts hook and similar… Thanks anywayDiagraph
@Diagraph FYI, the first method hinders the Admin section, and hid all the products from the editor. I've nested it in an if statement: if (!in_array('administrator', $current_user->roles) { ... }Schear
Hey, your solution with woocommerce_product_query is great, thanks, but is there a way to affect to the category counters when product is hidden? For example we have in the widget "Shoes (42)", but if hide some products, then this category should display another count (42 - hidden products).Ayrshire
E
0
function exclude_categories_for_vendors( $query ) {

    // Get the current user
    $current_user = wp_get_current_user();
     $ARRAY_OF_PRODUCT_CATEGORIES_IDS_YOU_WANT_HIDDEN = array(26,23,20);

    if( is_user_logged_in() ){

        if ( $query->is_main_query() ) {
           
            if ( in_array( 'editor', (array) $current_user->roles ) ) {
                
                //echo "editor";
                //below query will hide categories for Vendor user in Admin Panel
                
                   $query->set( 'tax_query', array(
                    array(
                        'taxonomy' => 'product_cat',
                        'field' => 'term_id',
                        'terms' => $ARRAY_OF_PRODUCT_CATEGORIES_IDS_YOU_WANT_HIDDEN, // your category ID
                        'operator' => 'NOT IN'
                    )
                ) ); 

            } else{
                //no changes
            }
        }
    }
}
add_action( 'pre_get_posts', 'exclude_categories_for_vendors' );
Endogen answered 22/7, 2020 at 11:52 Comment(2)
Please add some explanation to your answer such that others can learn from itBacklash
Manually keying in IDs into an array is not a great content management approach. Using a Category as the original post suggests is much better, then all the IDs are queried from the category instead.Far
R
-1

To make this more performant and only work on the woocommerce query use the following function and hook.

function exclude_product_from_wholesale( $q ){

 $current_user = wp_get_current_user();
 $ARRAY_OF_PRODUCT_IDS_YOU_WANT_HIDDEN = array();

 if ( in_array( 'wholeseller', $current_user->roles ) ) {
  $q->set( 'post__not_in', $ARRAY_OF_PRODUCT_IDS_YOU_WANT_HIDDEN );
 }

}

add_action( 'woocommerce_product_query', 'exclude_product_from_wholesale' );

You can drop this simple function into your functions.php.

Rident answered 17/8, 2016 at 23:49 Comment(1)
This didn't use a Product Category.. That's the point of using a category, to never have to key-in IDs into an array as a way to add or remove products from the special role based visibilityFar

© 2022 - 2024 — McMap. All rights reserved.