• Resolved gaiusjaugustus

    (@gaiusjaugustus)


    I’m currently using the following code to limit previous/next links within the same category.

    add_filter( 'next_post_link',     'my_adjacent_post_link', 10, 5 );
    add_filter( 'previous_post_link', 'my_adjacent_post_link', 10, 5 );
    
    function my_adjacent_post_link( $output, $format, $link, $post, $adjacent )
    {
    	$previous = 'previous' === $adjacent;
    
    	if ( ! ( $previous && is_attachment() ) ) {
    		$post = get_adjacent_post( true, '', $previous, 'category' );
    	}
    
    	if ( ! $post ) {
    		$output = '';
    	} else {
    		$title = $post->post_title;
    
    		if ( empty( $post->post_title ) ) {
    			$title = $previous ? __( 'Previous Post' ) : __( 'Next Post' );
    		}
    
    		$title = apply_filters( 'the_title', $title, $post->ID );
    
    		$date = mysql2date( get_option( 'date_format' ), $post->post_date );
    		$rel  = $previous ? 'prev' : 'next';
    
    		$string = '<a href="' . get_permalink( $post ) . '" rel="' . $rel . '">';
    		$inlink = str_replace( '%title', $title, $link );
    		$inlink = str_replace( '%date', $date, $inlink );
    		$inlink = $string . $inlink . '</a>';
    
    		$output = str_replace( '%link', $inlink, $format );
    	}
    
    	return $output;
    }

    The problem is that if a post is in multiple categories, the adjacent post retrieved is a match for any of those categories.

    I want to limit results to ONLY posts in the same PRIMARY category.

    There must be a way to do this. So far, I’ve only been able to find posts about returning the primary category name. Can anyone help me?

    Thanks in advance!

Viewing 4 replies - 1 through 4 (of 4 total)
  • Moderator bcworkz

    (@bcworkz)

    You could use the “get_next_post_where” and “get_previous_post_where” filters to alter the adjacent post query’s WHERE clause. It’ll include something like AND tt.term_id IN (12,23,34,45). The numbers are IDs for category terms assigned to the current post. You could add, replace, or remove IDs in order to get the proper post according to your criteria.

    It’s not clear what is considered to be a primary category though. There’s no such designation in default WP, though it’s possible your theme or a plugin as added such a feature. If you can somehow get code to identify what a primary category is, then a solution is possible.

    Thread Starter gaiusjaugustus

    (@gaiusjaugustus)

    That’s great! Thank you.

    I thought it was built in, but now that I know it’s not, I’ve pinpointed it to be part of the RankMath SEO plugin. So it sounds like a total rewrite, instead of using the get_adjacent_post I would use get_next_post_where.

    I’m struggling with the usage of this, as I’ve never coded a filter before.

    Can you potentially give an example of how to retrieve the post details for the next post in a predetermined category (by ID)? Something like this?

    $primarycat = get_post_meta( $post_id, 'rank_math_primary_category', true );
    $adjacent = 'previous';
    $where = 'AND tt.term_id IN ($primarycat)';
    
    apply_filters( "get_{$adjacent}_post_where", string $where, bool $in_same_term, array $excluded_terms, string $taxonomy, WP_Post $post );
    
    function modify_get_adjacent_post_where_defaults($where, $in_same_term, $excluded_terms, $taxonomy, $post) { 
        return $where; 
    }
    // add the filter
    add_filter( "get_adjacent_post_where", "modify_get_adjacent_post_where_defaults", 10, 5 );
    
    if ($adjacent = 'previous') {
    $post=get_previous_post_where( true, '', $previous, 'category' );
    }
    else {
    $post=get_next_post_where( true, '', $previous, 'category' );
    }
    Moderator bcworkz

    (@bcworkz)

    get_previous_post_where() ? Is that a RankMath function? I suspect not.

    What your filter callback needs to do is determine what the primary category is. I do not know how RankMath manages that. You might consider asking in RankMath’s dedicated support channel.

    Once the primary category is known, what you actually need is its term ID. Your callback is passed the default WHERE clause. You need to use PHP string functions such as preg_replace() to find the list of IDs in the clause and replace it with a list of IDs or ID of what categories should be queried for.

    Or perhaps better, let’s say the desired primary ID is 66. Find the existing tt.term_id IN (12,23,34,45) portion, realizing the numbers listed will vary. Replace that portion with tt.term_id = 66. Return the modified WHERE clause.

    If a post has only one assigned category, it’s presumably the primary category and there’s nothing your callback needs to do. This condition would need to be deduced from the nature of the WHERE clause. If only one category, your callback should immediately return the default WHERE clause without doing anything to it.

    Thread Starter gaiusjaugustus

    (@gaiusjaugustus)

    Supposedly, the following code will get the RankMath primary category for a post:

    get_post_meta( $post_id, 'rank_math_primary_category', true );
    

    The problem is that I’m not proficient enough at WordPress’s coding conventions to then translate this into a php snippet I can install on my site.

    Therefore, what I’ve done instead is create a custom taxonomy using Advanced Custom Fields, called “story”. Each post is assigned to 1 story only. Then I can use the code from my original post as-is, replacing “category” with “story”, as shown below.

    add_filter( 'next_post_link',     'my_adjacent_post_link', 10, 5 );
    add_filter( 'previous_post_link', 'my_adjacent_post_link', 10, 5 );
    
    function my_adjacent_post_link( $output, $format, $link, $post, $adjacent )
    {
    	$previous = 'previous' === $adjacent;
    
    	if ( ! ( $previous && is_attachment() ) ) {
    		$post = get_adjacent_post( true, '', $previous, 'story' );
    	}
    
    	if ( ! $post ) {
    		$output = '';
    	} else {
    		$title = $post->post_title;
    
    		if ( empty( $post->post_title ) ) {
    			$title = $previous ? __( 'Previous Post' ) : __( 'Next Post' );
    		}
    
    		$title = apply_filters( 'the_title', $title, $post->ID );
    
    		$date = mysql2date( get_option( 'date_format' ), $post->post_date );
    		$rel  = $previous ? 'prev' : 'next';
    
    		$string = '<a href="' . get_permalink( $post ) . '" rel="' . $rel . '">';
    		$inlink = str_replace( '%title', $title, $link );
    		$inlink = str_replace( '%date', $date, $inlink );
    		$inlink = $string . $inlink . '</a>';
    
    		$output = str_replace( '%link', $inlink, $format );
    	}
    
    	return $output;
    }

    Thank you again for the assistance.

Viewing 4 replies - 1 through 4 (of 4 total)
  • The topic ‘Previous/Next links within primary category only’ is closed to new replies.