I am making a plugin to hide specific product category only for a user role.
add_action( 'woocommerce_product_query', 'wcpp_hide_product' );
function wcpp_hide_product( $q ) {
//if main query, skip
if ( ! $q->is_main_query() ) return;
//jika admin, skip
if(is_admin()) return;
//if user is not logged in, or dont have PRIVATE_MEMBER roles hide the product
$current_user = wp_get_current_user();
if(!isset($current_user->roles) || !in_array('PRIVATE_MEMBER', $current_user->roles)){
$tax_query = (array) $q->get( 'tax_query' );
$tax_query[] = array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => 'PRIVATE_CATEGORY',
'operator' => 'NOT IN'
);
$q->set( 'tax_query', $tax_query );
}
}
Thats code will hide product from search. But other users still can access the product detail page from direct link.
Here my code that hide the product single pages (which is not works):
add_action( 'woocommerce_before_single_product', 'wcpp_hide_product_detail' );
//add_action( 'pre_get_posts', 'wcpp_hide_product_detail' );
function wcpp_hide_product_detail() {
if(is_admin()) return;
global $post;
$terms = get_the_terms( $post->ID, 'product_cat' );
if(empty($terms)) return;
$is_private=false;
foreach($terms as $term){
if('PRIVATE_CATEGORY'==$term->term_id){
$is_private = true;
break;
}
}
if(!$is_private) return;
$current_user = wp_get_current_user();
if(!isset($current_user->roles) || !in_array('PRIVATE_MEMBER', $current_user->roles)){
//need do something here, but not works
//maybe redirect
//wp_redirect(home_url());
/* or like set 404
global $wp_query;
$wp_query->set_404();
status_header(404);
*/
}
}
If I set a redirect script, it says: "Cannot modify header information - headers already sent by ..."
I think this will works if I can modify the product query to negative ID number which will trigger the "product not found" page. But I dont know which is the action hook name to do it. Then I may be my code could works using wp
action hook like add_action( 'wp', 'wcpp_hide_product_detail' );
. But I dont know the right hook.
Any help is appreciated.
I am making a plugin to hide specific product category only for a user role.
add_action( 'woocommerce_product_query', 'wcpp_hide_product' );
function wcpp_hide_product( $q ) {
//if main query, skip
if ( ! $q->is_main_query() ) return;
//jika admin, skip
if(is_admin()) return;
//if user is not logged in, or dont have PRIVATE_MEMBER roles hide the product
$current_user = wp_get_current_user();
if(!isset($current_user->roles) || !in_array('PRIVATE_MEMBER', $current_user->roles)){
$tax_query = (array) $q->get( 'tax_query' );
$tax_query[] = array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => 'PRIVATE_CATEGORY',
'operator' => 'NOT IN'
);
$q->set( 'tax_query', $tax_query );
}
}
Thats code will hide product from search. But other users still can access the product detail page from direct link.
Here my code that hide the product single pages (which is not works):
add_action( 'woocommerce_before_single_product', 'wcpp_hide_product_detail' );
//add_action( 'pre_get_posts', 'wcpp_hide_product_detail' );
function wcpp_hide_product_detail() {
if(is_admin()) return;
global $post;
$terms = get_the_terms( $post->ID, 'product_cat' );
if(empty($terms)) return;
$is_private=false;
foreach($terms as $term){
if('PRIVATE_CATEGORY'==$term->term_id){
$is_private = true;
break;
}
}
if(!$is_private) return;
$current_user = wp_get_current_user();
if(!isset($current_user->roles) || !in_array('PRIVATE_MEMBER', $current_user->roles)){
//need do something here, but not works
//maybe redirect
//wp_redirect(home_url());
/* or like set 404
global $wp_query;
$wp_query->set_404();
status_header(404);
*/
}
}
If I set a redirect script, it says: "Cannot modify header information - headers already sent by ..."
I think this will works if I can modify the product query to negative ID number which will trigger the "product not found" page. But I dont know which is the action hook name to do it. Then I may be my code could works using wp
action hook like add_action( 'wp', 'wcpp_hide_product_detail' );
. But I dont know the right hook.
Any help is appreciated.
Share Improve this question edited Apr 14, 2019 at 1:07 LoicTheAztec 3,39117 silver badges24 bronze badges asked Apr 13, 2019 at 1:42 plonknimbuzzplonknimbuzz 1131 silver badge6 bronze badges1 Answer
Reset to default 3I have revisited your code as there was some mistakes (everything is commented in the code). Also:
You can use
current_user_can()
to check a user role for the current user.You can use
has_term()
conditional function to check for post terms of any taxonomy.
The following code will hide products that belongs to a specific product category from user that have not a specific user role. If they try to access that specific products, they will be redirected to shop page with a custom notice…
Additionally the ajax add to cart button or the "Read more" button is replaced on all products loop for that specific products by a disable greyed button (in front end only).
Here is the code:
// Hide specific products from shop and archives pages
add_action( 'woocommerce_product_query', 'wcpp_hide_product' );
function wcpp_hide_product( $q ) {
// skip for main query and on admin
if ( ! $q->is_main_query() || is_admin() )
return;
// Hide specific products for unlogged users or users without PRIVATE_MEMBER user role
if ( is_user_logged_in() || ! current_user_can('PRIVATE_MEMBER') ) {
$tax_query = (array) $q->get( 'tax_query' );
$tax_query[] = array(
'taxonomy' => 'product_cat',
'field' => 'term_id', // it's not 'id' but 'term_id' (or 'name' or 'slug')
'terms' => 'PRIVATE_CATEGORY',
'operator' => 'NOT IN'
);
$q->set( 'tax_query', $tax_query );
}
}
// Replace add to cart button by a disabled button on specific products in Shop and archives pages
add_filter( 'woocommerce_loop_add_to_cart_link', 'wcpp_replace_loop_add_to_cart_button', 10, 2 );
function wcpp_replace_loop_add_to_cart_button( $button, $product ) {
if ( ( is_user_logged_in() || ! current_user_can('PRIVATE_MEMBER') )
&& has_term( 'PRIVATE_CATEGORY', 'product_cat', $product->get_id() ) ) {;
$button = '<a class="button alt disabled">' . __( "Private", "woocommerce" ) . '</a>';
}
return $button;
}
// On single product pages, redirect to shop and display a custom notice for specific products
add_action( 'template_redirect', 'wcpp_redirect_hiding_product_detail' );
function wcpp_redirect_hiding_product_detail() {
if ( ( is_user_logged_in() || ! current_user_can('PRIVATE_MEMBER') )
&& has_term( 'PRIVATE_CATEGORY', 'product_cat' ) && is_product() ) {
// Add a notice (optional)
wc_add_notice(__("Sorry, but you are not allowed yet to see this product."), 'notice' );
// Shop redirection url
$redirect_url = get_permalink( get_option('woocommerce_shop_page_id') );
wp_redirect($redirect_url); // Redirect to shop
exit(); // Always exit
}
}
Code goes in function.php file of your active child theme (or active theme), or in a plugin file.
Tested and works.