How to get next and previous post links, alphabetically by title, across post types, in a shortcode

I need next and previous post links in a single post page using a "page-builder" type of CMS—specifically the DIVI theme by Elegant Themes. So, I need the links to be able to appear using Shortcodes, as the controls in the template, along with a lot of the default template stuff, are hidden when you use the page builder. AND, my client needs to be able to manipulate where in the page layout the next/previous post controls appear, depending on the post type, as it's a portfolio site and "sculptures" get treated with a different layout than "paintings", if that makes sense.

And, I need them to go to the next / previous page alphabetically, rather than chronologically (the default).

Finally, I have multiple custom post types, and they all need the same type of filtering.

Topic next-post-link previous-post-link Wordpress

Category Web


So in order to do this, I had to filter the SQL queries. I found this snippet that filters post order by title and returns them for next and previous post links. Unfortunately, this doesn't work in a custom post type. So I replaced 'post' with get_post_type($post) to grab the current post type and return it. This then allows this to work in custom post types. AND, if you wanted to, you could limit this so that it ONLY works in custom post types, and not blog posts. I didn't do that here, but it's possible. Here's the code I put in my functions.php:

function filter_next_post_sort($sort) {
    $sort = "ORDER BY p.post_title ASC LIMIT 1";
    return $sort;
}
function filter_next_post_where($where) {
    global $post, $wpdb;
    return $wpdb->prepare("WHERE p.post_title > '%s' AND p.post_type = '". get_post_type($post)."' AND p.post_status = 'publish'",$post->post_title);
}

function filter_previous_post_sort($sort) {
    $sort = "ORDER BY p.post_title DESC LIMIT 1";
    return $sort;
}
function filter_previous_post_where($where) {
    global $post, $wpdb;
    return $wpdb->prepare("WHERE p.post_title < '%s' AND p.post_type = '". get_post_type($post)."' AND p.post_status = 'publish'",$post->post_title);
}

add_filter('get_next_post_sort',   'filter_next_post_sort');
add_filter('get_next_post_where',  'filter_next_post_where');

add_filter('get_previous_post_sort',  'filter_previous_post_sort');
add_filter('get_previous_post_where', 'filter_previous_post_where');

Next, I set up a couple shortcodes to be able to add the next and previous post links. Because the theme I'm using gets screwy if there's nothing returned (and the first and last post won't return anything for the previous and next post link, respectively), I needed to return a blank space:

function next_shortcode($atts) {
    global $post;
    ob_start(); 
    next_post_link( '<div class="nav-next">%link</div>', 'Next Work <span class="arrow_carrot-right_alt2"></span>' );              
    $result = ob_get_contents();
    ob_end_clean();
    $result = (!$result ? '<div class="nav-next">&nbsp;</div>' : $result);
    return $result;
}

function prev_shortcode($atts) {
    global $post;
    ob_start();
    previous_post_link( '<div class="nav-previous">%link</div>', '<span class="arrow_carrot-left_alt2"></span> Previous Work' );              
    $result = ob_get_contents();
    ob_end_clean();
    $result = (!$result ? '<div class="nav-previous">&nbsp;</div>' : $result);
    return $result;
}
add_shortcode( 'prev_work', 'prev_shortcode' );
add_shortcode( 'next_work', 'next_shortcode' );

Note that I'm using Elegant Themes' elegant icon font, so that's what the <span> with the arrow_carrot-left/right_alt2 class is for.

Anyway, hope this helps someone else!!

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.