Next/Previous Posts Links: Alphabetically and from Same Category

To get next/prev posts, usually all you need is to se to true the parameter that indicates that next/prev post should be in the same taxonomy term in the get next/prev post functions, you don’t need to deal with any filter.

For example:

To get next and prev post objects:

// First parameter for these functions indicates
// if next/prev post should be in the same taxonomy term
// More in https://codex.wordpress.org/Function_Reference/get_next_post
// And https://codex.wordpress.org/Function_Reference/get_previous_post
$prev_post = get_previous_post(true);
$next_post = get_next_post(true);

To print prev/next post links:

// Third parameter for these functions indicates
// if next/prev post should be in the same taxonomy term
// More in https://codex.wordpress.org/Template_Tags/next_post_link
// And https://codex.wordpress.org/Template_Tags/previous_post_link
previous_post_link( '« %link', '%title', true );
next_post_link( '%link »', '%title', true );

The problem is that, when you filter the where statement to change the order, you change the same taxonomy part, so you need to rebuilt it.

This code should work (I’ve not tested it):

add_filter('get_next_post_sort',  'filter_next_and_prev_post_sort');
add_filter('get_previous_post_sort',  'filter_next_and_prev_post_sort');
function filter_next_and_prev_post_sort($sort) {
    $op = ('get_previous_post_sort' == current_filter()) ? 'DESC' : 'ASC';
    $sort = "ORDER BY p.post_title ".$op ." LIMIT 1";
    return $sort;

}

add_filter( 'get_next_post_join', 'navigate_in_same_taxonomy_join', 20);
add_filter( 'get_previous_post_join', 'navigate_in_same_taxonomy_join', 20 );
function navigate_in_same_taxonomy_join() {
  global $wpdb;
  return " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id";
}

add_filter( 'get_next_post_where' , 'filter_next_and_prev_post_where' );
add_filter( 'get_previous_post_where' , 'filter_next_and_prev_post_where' );
function filter_next_and_prev_post_where( $original ) {
  global $wpdb, $post;
  $where="";
  $taxonomy   = 'category';
  $op = ('get_previous_post_where' == current_filter()) ? '<' : '>';

  if ( ! is_object_in_taxonomy( $post->post_type, $taxonomy ) ) {
    return $original ;
  }

  $term_array = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) );

  $term_array = array_map( 'intval', $term_array );

  if ( ! $term_array || is_wp_error( $term_array ) ) {
    return $original;
  }
  $where = " AND tt.term_id IN (" . implode( ',', $term_array ) . ")";
  return $wpdb->prepare( "WHERE p.post_title $op %s AND p.post_type = %s AND p.post_status="publish" $where", $post->post_title, $post->post_type );
}

Leave a Comment