Essentially, you need:
- A global role-category relationship list, and/or...
- A per-user category list
For per-user categories, hook onto the relevant profile actions:
show_user_profile
& edit_user_profile
for displaying the field (use wp_terms_checklist()
)
personal_options_update
& edit_user_profile_update
for saving the data
For the role-category data, use an options page. Loop over all roles ($wp_roles->roles
) with a term checklist for each. Store the settings as an associative array:
Array
(
[role_1] => Array
(
[0] => 4 // term ID
[1] => 5
[2] => 6
)
[role_2] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
)
Now, once a user is logged in, you can grab their allowed categories like so:
if ( $user = wp_get_current_user() ) {
$terms = array();
if ( is_array( $role_terms = get_option( 'product_cat_roles' ) ) ) {
foreach ( $user->roles as $role ) {
if ( isset( $role_terms[ $role ] ) )
$terms = array_merge( $terms, $role_terms[ $role ] );
}
}
if ( $user_terms = get_user_meta( $user->ID, '_product_cats', true ) )
$terms = array_merge( $terms, $user_terms );
$terms = array_unique( $terms );
}
Now for the fun part. We need to handle:
- Product archives (all products)
- Product category archive
- Single product
- Search
This is the core idea behind the "blocking", but you'll probably need to implement a more finely tuned solution. For example, blocked product category archive pages will load fine, just with an empty loop.
function wpse_148948_block_product_cats( $wp_query ) {
if ( ! is_admin() && (
$wp_query->is_tax( 'product_cat' ) ||
$wp_query->is_singular( 'product' ) ||
$wp_query->is_post_type_archive( 'product' ) ||
$wp_query->is_search()
) ) {
$user_terms = wpse_148948_get_user_product_cats();
if ( ! is_array( $tax_query = $wp_query->get( 'tax_query' ) ) )
$tax_query = array();
$tax_query[] = array(
'taxonomy' => 'product_category',
'terms' => $user_terms,
);
$wp_query->set( 'tax_query', $tax_query );
}
}
add_action( 'pre_get_posts', 'wpse_148948_block_product_cats' );
You'll also need to hide blocked categories from any front-end lists. If you're using wp_list_categories
, just apply the include
argument. If you're using widgets, you'll have to find the appropriate hooks to filter out excluded product categories.