Code

Support for WooCommerce Hide Products, Categories, Prices, Payment and Shipping by User Role

Support for WooCommerce Hide Products, Categories, Prices, Payment and Shipping by User Role

4.82 (33 ratings) 4.82 stars
Cart 1,361 sales

codemine supports this item

Supported

This author's response time can be up to 1 business day.

Popular questions for this item

I have added some rules to hide some products, but they are visible

Most of the times, this is due to the fact that you are using a caching plugin, like eg. WP Rocket, WP Fastest Cache, etc.

Make sure that you clear the cache after having set your visibility rules.

Can I hide a product variation?

No, you cannot hide each variation seperately. If a product has a variation, eg. color: black, and you say that you want to hide all products that have the black variation, then the product will be hidden for all variations (either if it’s white or black).

I get the error “The package could not be installed. No valid plugins were found. Plugin install failed.” when I try to install the plugin.

Make sure that you are uploading the correct zip file to your WordPress site. Which is woocommerce-visibility.zip. And not the whole zip file that you have downloaded from envato.

I have product categories with a parent-child relation and the plugin seems to break the menu

if the category you want to hide is a subcategory, and it’s parent category has no products attached to it, then the plugin may not work as expected.

Solution 1 (recommended)

Attach at least one product to it’s parent category.

In other words, you should ensure that no product categories are empty. To check if you have empty product categories, go to your site’s backend and navigate to Products > Categories. Check there if you have any categories with zero (0) products (the count column). If you have, assign the empty category to it’s products.

Let’s take a practical example. Let’s say you have a category clothes with a subcategory shirts. When you create a product, you should assign both the clothes and shirts at the same for the desired product. Not only the shirts category.

If you go to backend and see that the shirts category has a count of 0 and the shirts a count ,eg. of 10, than you should add the clothes category to all the shirts products.

To do so easily, just follow these steps:

  1. Click the count number right next to the shirts category. This will lead you to all the proucts that have the shirts category.
  2. Select all the products by checking the tick box right next to each product (or by using the global tick box right down the bulk actions select box).
  3. On the Bulk actions select box, select the edit option.
  4. Press Apply.
  5. Go to the product categories box, and tick the clothes categoriy.
  6. Press Update on the bottom right part and you are set!

Solution 2

You can also go to General Settings , disable the setting Hide Empty Categories/Tags/Taxonomies and check if it fixes your problem.

Solution 3

As an alternate solution, you can add this filter in your functions.php.

add_filter('get_terms_args', 'wcpv_get_terms_empty', 10, 2);

function wcpv_get_terms_empty($args, $taxonomies) {
    $wcpv_tax_init = isset($args["wcpv_tax"]) ? ($args["wcpv_tax"] == "init") : false;
    if ($wcpv_tax_init) {
        $args["hide_empty"] = false;
    }

    return $args;
}

I have a WPML multilingual site, but the plugin does not hide the products in all languages

Make sure that all of your products, tags and categories on your default language, have been properly translated through WPML.

Also, if you have a caching plugin activated, make sure that you have cleared the cache.

I want to be able to give the direct URL for hidden categories

To do so, just enable the Show Products Through Direct URL option. in the Settings page.

I want to exlude the rules from specific pages that contain the [products] shortcode

Our plugin apply the selected rules to every WooCommerce shortcode in your site.

Which means, that if you hide a category for a user role and include the [products] shortcode to a page, then this role will not be able to see the category when he visits the page.

In some cases, you may need to create a page that contains the [products] shortcode and exclude the rules for this page.

To do so, just open your functions.php and paste the code below. Make sure that you replace the xxx below with your page ID.

add_action('pre_get_posts', 'wcpv_modify_main_query_exclude_pageID');

function wcpv_modify_main_query_exclude_pageID($query) {
    // hide products in shop page
    if (is_shop()) {
        return; 
    }
    // exlude rules in selected page
    $page_id = get_the_ID();
    if ($page_id == xxx) { // replace xxx with your page ID
        $query->set('is_category_page', 'true');
    }
}

add_filter('wcpv_where', 'wcpv_exclude_pageID', 10, 2);

function wcpv_exclude_pageID($subquery, $query) {
    if (isset($query->query_vars['is_category_page'])) {
        $subquery = '';
    }
    return $subquery;
}

Can I remove all products for a user role?

Yes, it is possible with a small patch. Let’s say that we want to hide all products for the shop manager user role. Here are the steps:

  1. Go to the plugin’s backend page and add a rule (any rule) to the role you want to hide the products. In our example, go to shop manager and hide just one category (eg. shirts).
  2. Open your functions.php and paste the code below. Make sure that you replace the shop_manager role at our code with your own user role.
add_action('posts_where_paged', 'wcpv_modify_main_query_remove_all', 1, 2);

function wcpv_modify_main_query_remove_all($where, $query) {
    if (wcpv_get_user_role() == 'shop_manager') { // Replace the shop_manager role here, with your own user role, eg. administrator, etc.
        $post_type = $query->query_vars['post_type'];
        $product_category_check = isset($query->query_vars['taxonomy']) ? $query->query_vars['taxonomy'] : null;
        if ($post_type == 'product' || $post_type == 'any' || (isset($product_category_check) && ( $product_category_check == 'product_cat' || $product_category_check == 'product_tag'))) {
            $where .= " AND 1==2 ";
        }
    }
    return $where;
}

function wcpv_get_user_role($user = null) {
    $user = $user ? new WP_User($user) : wp_get_current_user();
    return $user->roles ? $user->roles[0] : false;
}

Can I disable the plugin’s functionallity for menus only?

Our plugin hides the selected products, categories and tags from your whole website, eg. from the menus, the widgets and even from the theme you use, as long as the theme is using standard WordPress filters.

If, for some reason, want to exclude the menu, you can do so easily, by disabling the Apply Rules on Menus option in the Settings page.

Bear in mind, that if you click a menu item that leads to a hidden product or category page, it will returns the No products found of WooCommerce.

Can I use my own PHP conditions?

Yes you can, by using the relevant PHP code. You should have some PHP knowledge though, in order to do so.

Product visibility filters

Our plugin contains 6 available filters that regard product visibility which you can use in functions.php. These are:

// Product rules filters
add_filter('wcpv_productids', 'wcpv_productids_custom');
add_filter('wcpv_products_visibility', 'wcpv_products_visibility_custom');

// Tag rules filters
add_filter('wcpv_tagids', 'wcpv_tagids_custom');
add_filter('wcpv_tags_visibility', 'wcpv_tags_visibility_custom');

// Category rules filters
add_filter('wcpv_categoryids', 'wcpv_categoryids_custom');
add_filter('wcpv_categories_visibility', 'wcpv_categories_visibility_custom');

Example 1

Let say that you want to override all the category rules you have added for customer user roles, when a PHP condition is true, and hide 2 categories instead.

To do so, you can use this code in your functions.php:

$condition = true; // set your own condition through PHP here
if ((wcpv_get_user_role() == 'customer') && ($condition == true)) {
    add_filter('wcpv_categoryids',  'wcpv_categoryids_custom');
    add_filter('wcpv_categories_visibility',  'wcpv_categories_visibility_custom');
}

function wcpv_categoryids_custom($args) {
    return array(40,42); // An array of the category ids. You also can return an empty array.
}

function wcpv_categories_visibility_custom($args) { 
    return "exclude";  //exclude or include
}

// Helper function to get the current user role
function wcpv_get_user_role($user = null) {
    $user = $user ? new WP_User($user) : wp_get_current_user();
    return $user->roles ? $user->roles[0] : false;
}

Hide price + add to cart filters

Our plugin contains 6 available filters that regard hide price + add to cart mode which you can use in functions.php. These are:

// Product rules filters
add_filter('wcpcv_productids', 'wcpcv_productids_custom');
add_filter('wcpcv_products_visibility', 'wcpcv_products_visibility_custom');

// Tag rules filters
add_filter('wcpcv_tagids', 'wcpcv_tagids_custom');
add_filter('wcpcv_tags_visibility', 'wcpcv_tags_visibility_custom');

// Category rules filters
add_filter('wcpcv_categoryids', 'wcpcv_categoryids_custom');
add_filter('wcpcv_categories_visibility', 'wcpcv_categories_visibility_custom');

Example 2

Let’s say that you want to hide all product prices for guest or customer.

To do so, you can use this code in your functions.php:

$current_user_role = wcpv_get_user_role();
//Hide all product prices for guest or customer
if (!$current_user_role || (wcpv_get_user_role() == 'customer') ) {
    add_filter('wcpcv_productids',  'wcpcv_productids_custom');
    add_filter('wcpcv_products_visibility',  'wcpcv_products_visibility_custom');
}

function wcpcv_productids_custom($args) {
    return get_posts( array(
        'post_type' => 'product',
        'numberposts' => -1,
        'post_status' => 'publish',
        'fields' => 'ids',
   ) );
}

function wcpcv_products_visibility_custom($args) { 
    return "exclude";  //exclude or include
}

// Helper function to get the current user role
function wcpv_get_user_role($user = null) {
    $user = $user ? new WP_User($user) : wp_get_current_user();
    return $user->roles ? $user->roles[0] : false;
}

Can i hide a product by user?

No, but as a workaround, you can create a separate user role for each of the users you want. For example create a User A role and assign it to the user you want, a User B role and assign to another, etc. You can user the User Role Editor plugin in order to create custom user roles.

Can I hide prices and add to cart buttons only (instead of whole products)?

Yes you can. Just select the Hide prices and add to cart button mode in the general settings page.

Is there a way to add a message like LOGIN TO BUY when hiding the Add to Cart button?

Yes you can.

To add the link in the single product page, add the code below in the functions.php:

add_action('woocommerce_single_product_summary', 'wcpv_login_required', 30);

function wcpv_login_required() {
    if (class_exists('WCPCV_FRONTEND')) {
        $wcpcv_frontent = WCPCV_FRONTEND::get_instance();
        if ($wcpcv_frontent->rules_are_applied() && $wcpcv_frontent->general_settings["wcpcv_hide_add_to_card"]) {
            global $product;
            $product_id = $product->get_id();
            if (!in_array($product_id, $wcpcv_frontent->include_products)) {
                $myaccount_permalink = get_permalink(get_option('woocommerce_myaccount_page_id'));
                $btn_permalink = __('LOGIN TO BUY', 'woocommerce-products-visibility');
                echo '<a href="' . $myaccount_permalink . '">' . $btn_permalink . '</a>';
            }
        }
    }
}

To add the link in the archive product page and right next to the Read More button, add the code below in the functions.php:

add_filter('woocommerce_loop_add_to_cart_link', 'wcpv_login_required_archive');

function wcpv_login_required_archive($link) {
    if (class_exists('WCPCV_FRONTEND')) {
        $wcpcv_frontent = WCPCV_FRONTEND::get_instance();
        if ($wcpcv_frontent->rules_are_applied() && $wcpcv_frontent->general_settings["wcpcv_hide_add_to_card"]) {
            global $product;
            $product_id = $product->get_id();
            if (!in_array($product_id, $wcpcv_frontent->include_products)) {
                $myaccount_permalink = get_permalink(get_option('woocommerce_myaccount_page_id'));
                $btn_permalink = __('LOGIN TO BUY', 'woocommerce-products-visibility');
                $login = '<a href="' . $myaccount_permalink . '">' . $btn_permalink . '</a>';
                return $link . $login;
                // return $login; // Use this in you want to return ONLY login button
            }
        }
    }
    return $link;
}

I cannot see the WooCommerce product attributes at the plugin backend

If you do not see WooCommerce product attributes at the Custom Taxonomies section of the plugin’s backend, then you have 2 options:

Option 1

Enable archives for your product attributes.

Option 2

You can add the following code at your functions.php:

add_filter('wcpv_custom_tax_args', 'wcpv_show_hidden_tax', 10, 2);

function wcpv_show_hidden_tax($args) {
    $args = array(
        'object_type' => array("product"),
    );
    return $args;
}

Is the plugin compatible with Advanced Woo Search plugin?

By default it is not, since Advanced Woo Search plugin does not use standard WordPress functions. In order for it to be compatible, add the following code in your functions.php:

add_filter('aws_search_query_array', 'wcpv_aws_search_query_array');

function wcpv_aws_search_query_array($query) {
    if (class_exists('WCPV_FRONTEND')) {
        $wcpv_frontent = WCPV_FRONTEND::get_instance();
        if ($wcpv_frontent->rules_are_applied()) {
            $subquery = $wcpv_frontent->products_total_subquery;
            $subquery = str_replace("post_type='product' AND", "", $subquery);
            $query['exclude_products'] = $query['exclude_products'] . ' ' . $subquery;
        }
    }
    return $query;
}

Is the plugin compatible with Ajax Search Lite plugin?

By default it is not, since Ajax Search Lite plugin does not use standard WordPress functions. In order for it to be compatible, add the following code in your functions.php:

add_filter('asl_query_add_args', 'asl_query_add_args_custom', 10, 3);

function asl_query_add_args_custom($_qargs, $sd, $options) {
    if (class_exists('WCPV_FRONTEND')) {
        $wcpv_frontent = WCPV_FRONTEND::get_instance();
        if ($wcpv_frontent->rules_are_applied()) {
            $subquery = $wcpv_frontent->products_total_subquery;
            $_qargs['where'] = $subquery;
        }
    }
    return $_qargs;
}

If user tries to see a hidden product, redirect to login form and then to the product

Just add the code below in your functions.php:

add_action('pre_get_posts', 'show_product_page_through_direct_url_modify_main_query');

function show_product_page_through_direct_url_modify_main_query($query) {
    if (class_exists('WCPV_FRONTEND')) {
        $wcpv_frontend = WCPV_FRONTEND::get_instance();
        if ($wcpv_frontend->rules_are_applied()) {
            if ($query->is_single() && $query->is_main_query()) {
                $post_type = $query->get('post_type');
                if ($post_type == "product") {
                    $product_slug = $query->get('product');
                    $product_obj = get_page_by_path($product_slug, OBJECT, 'product');
                    $product_id = $product_obj->ID;
                    if (!in_array($product_id, $wcpv_frontend->include_products)) {
                        $woocommerce_myaccount_page = get_permalink(get_option('woocommerce_myaccount_page_id'));
                        $query_vars = array(
                            'product-redirect' => $product_slug,
                        );
                        $woocommerce_myaccount_page_with_product = add_query_arg($query_vars, $woocommerce_myaccount_page);
                        wp_redirect($woocommerce_myaccount_page_with_product);
                        exit();
                    }
                }
            }
        }
    }
}

add_filter('woocommerce_login_redirect', 'wcpv_redirect_to_product', 10, 2);

function wcpv_redirect_to_product($redirect, $user) {
    if (isset($_GET['product-redirect'])) {
        $product_slug = $_GET['product-redirect'];
        $product_obj = get_page_by_path($product_slug, OBJECT, 'product');
        $product_id = $product_obj->ID;
        $product_url = get_permalink($product_id);
        return $product_url;
    }

    return $redirect;
}

If a user tries to see a hidden category, show a custom text instead of “No products found”

Just add the code below in your functions.php:
add_action( 'woocommerce_no_products_found', function(){
    if (class_exists('WCPV_FRONTEND')) {
        $wcpv_frontend = WCPV_FRONTEND::get_instance();
        if ($wcpv_frontend->rules_are_applied()) {
            remove_action( 'woocommerce_no_products_found', 'wc_no_products_found' );

            $term_id = get_queried_object()->term_id;
            if (in_array($term_id, $wcpv_frontend->get_excluded_taxonomies())) {
                $woocommerce_myaccount_page = get_permalink(get_option('woocommerce_myaccount_page_id'));
                echo '<a href=" . $woocommerce_myaccount_page .">Please login to access the page</a>';
            }
        }
    }
}, 1 );

Notice

In case you want to use your own page, just replace in the code above the lines below and use your page ID .

$redirect_page_id = 123;
$woocommerce_myaccount_page = get_permalink($redirect_page_id );

The plugin hides products from Google Product Feed

If you use Google Product Feed plugin, then add this code in your functions.php:

add_filter('wcpv_rules_are_applied', 'wcpv_remove_rules_for_google_product_feed');

function wcpv_remove_rules_for_google_product_feed($rules_are_applied) {
    if (isset($_GET["woocommerce_gpf"])) {
        return false;
    }
    return $rules_are_applied;
}

The plugin hides products and categories in the WooCommerce API

Our plugin, by default, will follow the guest rules to the results of the WooCommerce API.

To override this, and not filter the API results, just add this code in your functions.php.

add_filter('wcpv_rules_are_applied', 'wcpv_remove_rules_for_wc_api');

function wcpv_remove_rules_for_wc_api($rules_are_applied) {
    if (defined('WC_API_REQUEST') && WC_API_REQUEST) {
        return false;
    }
    return $rules_are_applied;
}

Can I hide out-of-stock products for specific user roles?

Yes you can by adding the following code in functions.php. Bear in mind, that you cannot at the same time add rules in products. The following code hides out of stock and backorder products for guest and customer user roles.

//Guest User or customer
if ((wcpv_get_user_role() == '') || (wcpv_get_user_role() == 'customer')) {
    add_filter('wcpv_rules_are_applied', 'wcpv_rules_are_applied_custom');
    add_filter('wcpv_productids', 'wcpv_productids_custom');
    add_filter('wcpv_products_visibility', 'wcpv_productids_visibility_custom');
}

function wcpv_rules_are_applied_custom() {
    return true;
}

function wcpv_productids_custom($args) {

    $args = array(
        'post_type' => 'product',
        'posts_per_page' => -1,
        'post_status' => 'publish',
        'meta_query' => array(
            array(
                'key' => '_stock_status',
                'value' => array('outofstock','onbackorder'),
                'compare' => 'IN',
            )
        ),
        'fields' => 'ids',
    );

    $product_ids = get_posts($args);
    return $product_ids;
}

function wcpv_productids_visibility_custom($args) {
    return "exclude";  //exclude or include
}

// Helper function to get the current user role
function wcpv_get_user_role($user = null) {
    $user = $user ? new WP_User($user) : wp_get_current_user();
    return $user->roles ? $user->roles[0] : false;
}

Can I ignore rules for products in search results?

Yes you can, by adding this code in functions.php:

add_filter('wcpv_where', 'wcpv_exclude_search', 10, 2);

function wcpv_exclude_search($subquery, $query) {
    if ($query->is_search() ) {
        $subquery = '';
    }
    return $subquery;
}

Can I hide downloadable products for specific user roles?

Yes you can by adding the following code in functions.php. Bear in mind, that you cannot at the same time add rules in products.

//Guest User or customer
if ((wcpv_get_user_role() == '') || (wcpv_get_user_role() == 'customer')) {
    add_filter('wcpv_rules_are_applied', 'wcpv_rules_are_applied_custom');
    add_filter('wcpv_productids', 'wcpv_productids_custom');
    add_filter('wcpv_products_visibility', 'wcpv_productids_visibility_custom');
}

function wcpv_rules_are_applied_custom() {
    return true;
}

function wcpv_productids_custom($args) {

    $args = array(
        'post_type' => 'product',
        'posts_per_page' => -1,
        'post_status' => 'publish',
        'meta_query' => array(
            array(
                'key' => '_downloadable',
                'value' => 'yes',
                'compare' => '=',
            )
        ),
        'fields' => 'ids',
    );

    $product_ids = get_posts($args);
    return $product_ids;
}

function wcpv_productids_visibility_custom($args) {
    return "exclude";  //exclude or include
}

// Helper function to get the current user role
function wcpv_get_user_role($user = null) {
    $user = $user ? new WP_User($user) : wp_get_current_user();
    return $user->roles ? $user->roles[0] : false;
}

When I hide add to cart button, can I also hide all variations in single product page?

Yes you can by adding this filter in your functions.php:

add_action('woocommerce_before_single_product', 'wcpcv_hide_variations', 1);

function wcpcv_hide_variations() {
    if (class_exists('WCPCV_FRONTEND')) {
        $wcpcv_frontent = WCPCV_FRONTEND::get_instance();
        if ($wcpcv_frontent->rules_are_applied() && $wcpcv_frontent->general_settings["wcpcv_hide_add_to_card"]) {
            global $product;
            $product_id = $product->get_id();
            if (!in_array($product_id, $wcpcv_frontent->include_products)) {
                remove_action( 'woocommerce_variable_add_to_cart', 'woocommerce_variable_add_to_cart', 30 );
            }
        }
    }
}

Can I hide price and add to cart only in one language in WPML?

Yes you can, by inserting the code below in your functions.php:

add_filter('wcpcv_rules_are_applied', 'wcpcv_remove_rules_for_language');

function wcpcv_remove_rules_for_language($rules_are_applied) {
    //Remove rules for language == English
    if (ICL_LANGUAGE_CODE == 'en') {
        return false;
    }
    return $rules_are_applied;
}

Multiple user roles with show rules remove intersection

By default, when you have multiple user roles, and for each role you have a show rule, the products that are returned are an intersection.

This means that in the next scenario

  • Rule on user role category A : Show category A
  • Rule on user role category B : Show category B

if a user has both roles, he will not see anything.

You can add a filter, which changes the intersection to a merge.

add_filter('wcpv_mur_intersect_include', 'wcpv_mur_intersect_inlucude_set_merge');

function wcpv_mur_intersect_inlucude_set_merge() {
    return false;
}

With this filter, in the test scenario, a user with roles A and B will only see products with categories A and B respectively.

Show more

Contact the author

This author provides limited support for this item through this item's comments.

Item support includes:

  • Availability of the author to answer questions
  • Answering technical questions about item’s features
  • Assistance with reported bugs and issues
  • Help with included 3rd party assets

However, item support does not include:

  • Customization services
  • Installation services

View the item support policy

by
by
by
by
by
by

Tell us what you think!

We'd like to ask you a few questions to help improve CodeCanyon.

Sure, take me to the survey