I have a page with two sections, each uses a different WP_Query() to pull in events, which are a custom post type. Each WP_Query() queries a meta_key for the event date so that Section 1 only displays upcoming events and Section 2 displays past events.

The upcoming events in Section 1 display all relevant information on my page, so clicking them is not possible.

The past events in Section 2 only display the event title and are clickable. When users click a past event they link to a custom single-event.php template for the past event.

I want to display Previous/Next navigation in the single-event.php template, but the navigation should only point to past events.

I tried using next_post_link() and previous_post_link() but these will link to upcoming events too, which I do not want. I can probably setup a new WP_Query() on my single-event.php and loop through it to get the Prev/Next IDs, but repeating the query seems like a drastic step.

I would really appreciate some insight on a way to filter out upcoming events from my Previous/Next post links. I’ve seen this question but I would prefer not to use a plugin.

2 s
2

I managed to get this working using nothing but WordPress filters, thanks to @Milo’s hint.

Just note that these are pretty specific to my case but you shouldn’t have a problem modifying them for your own use. I am using Advanced Custom Fields with a Date Picker field called date and Prev/Next links only point to events with date fields set to any day before today.

I created 5 filters:

  • 1 to modify JOIN (to add wp_postmeta)
  • 1 to modify WHERE for the Previous link
  • 1 to modify WHERE for the Next link
  • 1 to modify SORT for the Previous link
  • 1 to modify SORT for the Next link

Here’s what I came up with, it seems to be working but if anyone spots any issues I would love feedback:

function get_adjacent_past_events_join($join) {
  if(is_singular('event')) {
    global $wpdb;
    $new_join = $join."INNER JOIN $wpdb->postmeta AS m ON p.ID = m.post_id ";
    return $new_join;
  }
  return $join;
}
add_filter('get_previous_post_join', 'get_adjacent_past_events_join');
add_filter('get_next_post_join', 'get_adjacent_past_events_join');

function get_prev_past_events_where($where) {
  if(is_singular('event')) {
    global $wpdb, $post;
    $id = $post->ID;
    $current_event_date = get_field('date', $id);
    $today = date('Ymd');
    $new_where = "WHERE p.post_type="event" AND p.post_status="publish" AND (m.meta_key = 'date' AND (m.meta_key = 'date' AND CAST(m.meta_value AS CHAR) < '$today')) AND (m.meta_key = 'date' AND (m.meta_key = 'date' AND CAST(m.meta_value AS CHAR) < '$current_event_date'))";
    return $new_where;
  }
  return $where;
}
add_filter('get_previous_post_where', 'get_prev_past_events_where');

function get_next_past_events_where($where) {
  if(is_singular('event')) {
    global $wpdb, $post;
    $id = $post->ID;
    $current_event_date = get_field('date', $id);
    $today = date('Ymd');
    $new_where = "WHERE p.post_type="event" AND p.post_status="publish" AND (m.meta_key = 'date' AND (m.meta_key = 'date' AND CAST(m.meta_value AS CHAR) < '$today')) AND (m.meta_key = 'date' AND (m.meta_key = 'date' AND CAST(m.meta_value AS CHAR) > '$current_event_date'))";
    return $new_where;
  }
  return $where;
}
add_filter('get_next_post_where', 'get_next_past_events_where');

function get_prev_past_events_sort($sort) {
  if(is_singular('event')) {
    global $wpdb;
    $new_sort = " GROUP BY p.ID ORDER BY m.meta_value+0 DESC";
    return $new_sort;
  }
  return $sort;
}
add_filter('get_previous_post_sort', 'get_prev_past_events_sort');

function get_next_past_events_sort($sort) {
  if(is_singular('event')) {
    global $wpdb;
    $new_sort = " GROUP BY p.ID ORDER BY m.meta_value+0 ASC";
    return $new_sort;
  }
  return $sort;
}
add_filter('get_next_post_sort', 'get_next_past_events_sort');

Leave a Reply

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