0

I've registered an employers post type with several associated taxonomies and want to all associated pages (single, term archives, post type archive page) only viewable by logged-in users.

I've played around with the capabilities argument for register_post_type() and looked at the map_meta_cap filter, but just can't quite put the pieces together. It seems that maybe I need to use a custom capability but that feels like overkill for this one feature. I've seen some references to using the template_redirect feature too but not sure if that's the right way to go.

Despite a lot of searching, I'm struggling to answer what feels like a simple question. How can I restrict access of a custom post type or custom taxonomy to logged-in users of any capability?

I've seen "Restrict custom post type view by user role" but that's only filters the_content. I've also looked a lot at "Restrict custom post type to only site administrator role" but it seems more about logged-in users. Finally "Set posts of a custom post type to be private by default?" only sets the post status meaning that an editor could accidentally make the post public which is a dealbreaker.

1

I've faced similar situations (say a client wants to see how a custom post type and/or taxonomy behaves before they're ready for the general public to see it). In those cases I'll use something like the following code snippet, added either to the plugin file (assuming I've built the CPT/taxonomy as a plugin) or directly in the active theme's functions.php:

/**
 * IN-DEVELOPMENT REDIRECTS
 * While specified areas are under development, redirect users to home page if not logged in
 */
add_filter( 'wp', 'f040925b_redirect', 0 );
function f040925b_redirect( $content ) {
    global $post;
    if(
        (
            $post->post_type == '[custom_post_type_name]'
            ||
            is_post_type_archive( '[custom_post_type_name]' )
            ||
            is_tax( '[custom_taxonomy_name]' )
        )
        &&
        !is_user_logged_in()
    ) {
        wp_redirect( get_home_url() );
        exit;
    }
    return $content;
}

Essentially, this runs three early checks:

  1. Does the $post object's post type match what you're trying to hide?
  2. Is this URL a post type archive for the post type you're trying to hide?
  3. Is this URL a taxonomy/term page for the taxonomy you're trying to hide?

If any of these is a match and the user is not logged in, then the user is redirected to the site's homepage.

0

I may be misreading what you want, but you can do this with current_user_can() in your template.

if( ! current_user_can( 'read' ) {
    echo "You must log in to see this content.";
}
else {
    //The Loop goes here
}

The problem with this is that it doesn't cache; or, at least, it doesn't cache well, especially if you are using a file-only cache.

  • I could see this working. My concern with an approach like this (or template_redirect) is that it's not directly tied to the post type/taxonomy object and requires me to make sure I catch every possible template and situation where the posts might leak out. That's why I included "comprehensively" in the title. – mrwweb Mar 13 '15 at 0:55
  • I hear you. An (ugly) option is to use subtemplates for your custom posts and taxonomy which are really just wrappers of the actual templates, assuming you share templates between post types and taxonomies. – user12479 Mar 13 '15 at 13:48

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.