Posted on

Private posts in custom post types

UPDATE 15.5.2018: Relevanssi doesn’t have the relevanssi_private_cap filter hook anymore. Relevanssi should be able to get the correct capability automatically, if it has been registered within WordPress. If something doesn’t work as expected, then creating a relevanssi_post_ok filter function is the way to go.

Relevanssi has some problems when it comes to checking if it can show private posts to a user, if the post is in a custom post type.

Relevanssi doesn’t actually check the what the capability to read private posts is called, but instead assumes it’s read_private_slugs, where slug is the name of the post type.

That’s a problem, if the custom post type uses a different name for the capability. Sermon manager for WordPress, for example, uses a custom post type wpcf_sermon, but the capability is read_private_posts, not read_private_wpcf_sermons.

From Premium 1.13 and Relevanssi 3.3.6 onwards, you can do this to fix this:

add_filter('relevanssi_private_cap', 'private_sermon_cap');
function private_sermon_cap($cap) {
    if ($cap == 'read_private_wpfc_sermons') $cap = 'read_private_posts';
    return $cap;
}

In earlier versions, the fix is more complicated:

add_filter('relevanssi_post_ok', 'private_sermon_post_ok', 11, 2);
function private_sermon_post_ok($post_ok, $doc) {
	$status = relevanssi_get_post_status($doc);
 
	if ('private' == $status) {
		$type = relevanssi_get_post_type($doc);
		if ($type == 'wpfc_sermon') $type = "post";
		$cap = 'read_private_' . $type . 's';
		if (current_user_can($cap)) {
			$post_ok = true;
		}
	}
 
	return $post_ok;
}

This function will run after the default check, and if the post type is wpfc_sermon and the post is private, the function will check if the user is allowed to see the post.

16 comments Private posts in custom post types

  1. I have tried this code, but when I search I still see private posts in the search results. I have added the code via the Code Snippet plugin

    Is there an update to the above code?

    I have tried uninstalling/reinstalling the relevanssi plugin.

    I am using the Tooltypes plugins to create custom fields.
    Ray

    1. Can you show me the code you’re using (put it in a Pastebin, for example)? What is the correct capability for reading your private post type? Without any code, Relevanssi tries to guess ’read_private_SLUGs’ where SLUG is the slug of your post type. If that doesn’t work, you need code that tells Relevanssi the correct capability.

      1. This is the code I am using.

        add_filter( ‘relevanssi_private_cap’, ‘tssupp_relevanssi_private_cap’ );
        function tssupp_relevanssi_private_cap( $cap ) {

        $cpt_slug = ‘job-application’; // Edit as required

        if ( $cap == ‘read_private_’ . $cpt_slug ) {
        $cap = ‘read_private_posts’;
        }

        return $cap;
        }

        1. The capability Relevanssi uses is ’read_private_’ . $cpt_slug . ’s’, the plural s must be in the end. That way your code should work, if read_private_posts is the correct capability.

  2. I’m also struggling to get this to work with Avada Portfolios custom post type. My code is:

    add_filter(‘relevanssi_private_cap’, ‘private_portfolio_cap’);
    function private_portfolio_cap($cap) {
    if ($cap == ‘read_private_avada_portfolios’) $cap = ‘read_private_posts’;
    return $cap;
    }

    Can you spot anything obvious?

    1. Luke, yeah, just one little thing: there’s no such thing as relevanssi_private_cap. That filter does not exist anymore. Not really sure when it was removed; it hasn’t been a part of Relevanssi in a while. Looks like I’ve forgotten that as well…

      Relevanssi gets the capability from $GLOBALS[‘wp_post_types’][‘avada_portfolio’]->cap->read_private_posts. If that returns the correct value, Relevanssi should handle the posts correctly.

      So what is your problem? Are you seeing private posts you shouldn’t, or the not seeing the ones you should? If things don’t work, the best solution is probably to write a relevanssi_post_ok filter that handles the private posts correctly.

    1. Something’s a bit messed up somewhere, then, as Relevanssi shouldn’t even consider showing private posts to people who aren’t logged in – Relevanssi checks the capability and checks if current_user_can() returns true. That function always returns false if the user is not logged in.

      Do you have any membership plugins that might be involved in this?

  3. Firstly, thank you so much for developing this plugin and for providing support.

    I’m in the process of trying to do something unusual with this “for reasons,” where I’ve setup a sub domain adjacent to a WordPress install purely for the purposes of separating out a search area for a custom post type of the main site. I’ve included the wp-blog-header.php and all the normal WordPress functions work just fine.

    Relevanssi appears to work fine, at first, too, but I’m having an issue getting a new WP_Query to work, where I need to set the post_status to ‘any’ but only ‘publish’ posts are being retrieved. I’ve tried a separate WP_Query without Relevanssi and it successfully retrieves ‘any,’ so I’m wondering if there’s an additional query_vars that needs to be set somewhere for Relevanssi.

    Below is an example of what I have leading into a new WP_Query loop for a search results page. Thanks in advance for your help!

    $search_query = get_search_query();
    $args = array (
    ‘s’ => $search_query,
    ‘post_type’ => ‘entries’,
    ‘posts_per_page’ => ‘-1’,
    ‘post_status’ => ‘any’,
    );

    $the_query = new WP_Query( $args );
    $the_query->query_vars[‘post_status’] = ‘any’;
    relevanssi_do_query($the_query);

    1. MoDaD, when you search like that, Relevanssi will find all the posts in any post statuses, but then there’s the post visibility filter that kicks and says that if a post isn’t public, the user is not allowed to see it. However, all you need to do is to circumvent that filter. For example this:

      add_filter( 'relevanssi_post_ok', '__return_true', 11 );

      would simply tell Relevanssi every post is fine and nothing should be held from the search. Add this right before the relevanssi_do_query() and you’ll get all the posts in the results. If you want more finesse, then something like this will work better:

      add_filter( 'relevanssi_post_ok', 'rlv_status_ok', 11, 2 );
      function rlv_status_ok( $post_ok, $post_id ) {
      $status = relevanssi_get_post_status( $post_id );
      if ( in_array( $status, array( 'publish', 'pending', 'draft', 'etc', 'foo', 'bar' ), true ) ) {
      $post_ok = true;
      }
      return $post_ok;
      }

      This will only let through some post statuses.

      1. Thank you so much for your assistance! Both of the methods you suggested work.

        For anyone else using these methods, I noticed having ‘post_status’ in your $args will cause a conflict, so I had to remove that from the $args.

        Other $args values seem to be working fine and appear in the new WP_Query as expected.

        Working markup:

        $search_query = get_search_query();
        $args = array (
        ‘s’ => $search_query,
        ‘post_type’ => array(‘entries’),
        ‘posts_per_page’ => ‘-1’,
        );

        $the_query = new WP_Query( $args );

        add_filter( ‘relevanssi_post_ok’, ‘rlv_status_ok’, 11, 2 );
        function rlv_status_ok( $post_ok, $post_id ) {
        $status = relevanssi_get_post_status( $post_id );
        if ( in_array( $status, array( ‘publish’, ‘private’ ), true ) ) {
        $post_ok = true;
        }
        return $post_ok;
        }

        relevanssi_do_query($the_query);

        // The Loop
        if ( $the_query->have_posts() ) {
        while ( $the_query->have_posts() ) {
        $the_query->the_post();
        //content goes here
        }
        /* Restore original Post Data */
        wp_reset_postdata();
        } else {
        // no posts found
        }

  4. Hi. I want my relevanssi shows private posts in search results. I want to show private posts to all guest visitors on my site. Everything I set up correct. But when I activate relevanssi private posts disappears from search results. And I need relevanssi for synonyms option. So can you please guide me how to prevent relevanssi blocking private posts in search results? Thanks

    1. In order to show all posts to all users, add this to your theme functions.php:

      `add_filter( ‘relevanssi_post_ok’, ‘__return_true’ );`

      This will disable all permission filtering, and Relevanssi will ok everything.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.