0

Is it possible to limit the categories so that user in a list of groups does not see these posts at all? Not even in a list of posts?

I'm using the answer from here:

Only show category to certain user levels without plugin

My Code:

###########

// restrikcija posameznih kategorij za grupo ki je subscriber
// source: https://wordpress.stackexchange.com/questions/113500/only-show-category-to-certain-user-levels-without-plugin
add_filter('template_include', 'restict_by_category');

function check_user() {
    $user = wp_get_current_user();
    $restricted_groups = array( 'company1', 'company2', 'company3', 'subscriber' ); // categories subscribers cannot see
    if ( ! $user->ID ||  array_intersect( $restricted_groups, $user->roles ) ) {
        // user is not logged or is a subscriber
        return false;
    }
    return true;
}

function restict_by_category( $template ) {
    if ( ! is_main_query() ) {
        return $template; // only affect main query.
    }
    $allow = true;
    $private_categories = array( 'podjetje', 'personal', 'nekategorizirano', 'razno', 'sola-2' ); // categories subscribers cannot see
    if ( is_single() ) {
        $cats = wp_get_object_terms( get_queried_object()->ID, 'category', array('fields' => 'slugs') ); // get the categories associated to the required post
        if ( array_intersect( $private_categories, $cats ) ) {
            // post has a reserved category, let's check user
            $allow = check_user();
        }
    } elseif ( is_tax('category', $private_categories) ) {
        // the archive for one of private categories is required, let's check user
        $allow = check_user();
    }
    // if allowed include the required template, otherwise include the 'not-allowed' one
    return $allow ? $template : get_home_url(); //get_template_directory() . '/not-allowed.php';
}

###########

The problem is that user still sees post in a list of posts, but when clicked upon it's content is empty (which is OK, but even better would be that it doesnt sees posts at all).

And also if I have a master category with lots of sub-categorys, is it possible to also limit all these child categories?

1

Problem with your code is that you don't modify queries at all in any way, so all queries on your site still get these posts - so they are visible on lists. And later, you use template_include filter which allows you to redirect single post view and single category archive if it shouldn't be visible for given user... Also redirecting to home page in such case isn't best - it may confuse users...

So how to hide these posts properly, so users won't see them at all?

You should use pre_get_posts filter. This way you can check if current user can see these posts and hide them, if he shouldn't.

function check_user() {
    if ( ! get_current_user_id() ) {  // this way you won't get notices when user is not logged in
        return false;
    }

    $user = wp_get_current_user();
    $restricted_groups = array('company1', 'company2', 'company3', 'subscriber'); // categories subscribers cannot see
    if ( array_intersect( $restricted_groups, $user->roles ) ) {
        // user is a subscriber or restricted user
        return false;
    }
    return true;
}

function restrict_users_categories( $query ) {
    if ( ! is_admin() ) {
        if ( ! check_user() ) {
            // change 1, 2, 3 to IDs of your excluded categories
            $cats_excluded = array_merge( array(1, 2, 3), (array)$query->get( 'category__not_in' ) );  // don't ignore any other excluded categories
            $query->set( 'category__not_in', $cats_excluded );
        }
    }
}
add_action( 'pre_get_posts', 'restrict_users_categories' );

Also... There is something a little bit odd in your check_user function... If you want to check if user has one of these roles 'company1', 'company2', and so on, then it's OK.

But if you want to restrict only subscribers, then it should be:

function check_user() {
    if ( ! get_current_user_id() ) {  // this way you won't get notices when user is not logged in
        return false;
    }

    $user = wp_get_current_user();
    if ( in_array( 'subscriber', $user->roles ) ) {
        // user is a subscriber
        return false;
    }
    return true;
}
  • Yes if user is subcriber or in a list of restricted groups i want to limit him. – Kiki Jan 24 at 7:19
  • Hello. That is awesome. It works. Now I must figure it out how to hide all subcategories of some category. thanx – Kiki Jan 25 at 6:54
  • It works great, i'm trying to get also the child catgories in array: smth like this: $args1 = array('child_of' => get_cat_ID('podjetje')); // <- trying to get all child categories of category podjetje $query->set( 'category__not_in', array_merge($cats_excluded, $args1)); – Kiki Jan 25 at 7:09
1

You need to hide those categories in your WP_Query calls. using the pre_get_posts hook will allow you to hide posts in those categories wherever you want. In the function below I'm hiding them everywhere except for admin pages unless your user_check() function returns true. Modify as you like.

add_action( 'pre_get_posts', 'hide_private_cats', 10);

function hide_private_cats($query) {
    if (is_admin() || check_user()) { // If this is an admin page or your user check passes, do nothing
    return;
    } else {
        $query->set('category__not_in', array( 3, 8, 10 )); // don't show posts that are in the categories specified (only takes IDs)
    }
}
  • 1
    pre_get_posts is an action and it doesn’t need to return anything... – Krzysiek Dróżdż Jan 23 at 19:28
  • you are correct sir, edited – mrben522 Jan 23 at 19:38
  • sorry, but now it’s not even correct php... – Krzysiek Dróżdż Jan 23 at 19:40
  • Man... Still wrong. Now your condition doesn't make much sense... It will be always true on front-end. – Krzysiek Dróżdż Jan 23 at 19:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.