next_post_link() on custom menu structure

In a blog, I am using next_post_link() and prev_post_link() extensively on posts.

I also have a number of pages that I show in a WP3 menu. They are organized in topics and sub-topics e.g. like so:

Read More
Home
About
- Subpage 1
- Subpage 2 
- Subpage 3 
Contact

I would like to set up a “previous” and “next” navigation on these pages as well, so that when I’m on “About”‘s Subpage 2, I can navigate to Subpages 1 and 3 using the “next” and “previous” arrows.

The default behaviour of next_post_link()/prev_post_link() doesn’t work for this: It calculates the next and previous items based on the list of all pages.

Is there an easy way to make next_post_link() and prev_post_link() sensitive to my menu structure, or will I have to build this myself?

Related posts

Leave a Reply

1 comment

  1. The function behind the function behind the function…

    next_post_link(); is a wrapper for adjacent_post_link(); which then calls get_adjacent_post(); where the 3rd argument is $previous and set to true/false to get the previous or next post.

    This gives you two opportunities: Use the output or the query filter.

    Output filter

    This might sound easier, but you’ll have to do an extra query for this.

    // The core:
    $adjacent = $previous ? 'previous' : 'next';
    echo apply_filters( "{$adjacent}_post_link", $format, $link );
    
    // Add your callbacks like this:
    add_filter( 'previous_post_link', 'your_callback_fn', 20, 2 );
    add_filter( 'next_post_link', 'your_callback_fn', 20, 2 );
    

    Query filter

    This is what I’d recommend you: Check whether there’s $post->post_parent set and then modify the query to get the post with the next higher id that has the same parent.

    // The core:
    $adjacent = $previous ? 'previous' : 'next';
    $join  = apply_filters( "get_{$adjacent}_post_join", $join, $in_same_cat, $excluded_categories );
    $where = apply_filters( "get_{$adjacent}_post_where", $wpdb->prepare("WHERE p.post_date $op %s AND p.post_type = %s AND p.post_status = 'publish' $posts_in_ex_cats_sql", $current_post_date, $post->post_type), $in_same_cat, $excluded_categories );
    $sort  = apply_filters( "get_{$adjacent}_post_sort", "ORDER BY p.post_date $order LIMIT 1" );