Only show category to certain user levels without plugin

If I understand you have some categories, eg: ‘reserved’, ‘people’, ‘landscapes’, ‘personal’ and so on.

Now you want that subscribers can see posts in, e.g. ‘people’, ‘landscapes’ categories but not posts in ‘reserved’ and ‘personal’ categories.

This is relatively easy, just hook into pre_get_posts and if the request is for a post having that terms or the term archive disable the viewing.

To disable you have different chanches, you can redirect, you can show 404 or you can show a custom template.

Below I’m sayng how to last option.

First of all create a template file, e.g. not-allowed.php and put in your theme folder.

Then in functions.php use this code:

add_filter('template_include', 'restict_by_category');

function check_user() {
  $user = wp_get_current_user();
  if ( ! $user->ID || in_array('subscriber', $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('reserved', 'personal'); // 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_template_directory() . '/not-allowed.php';
}

Leave a Comment