Filtering Out Recurring Events in Events Calendar Pro

I was working on a site that uses Events Calendar Pro and recurring events weren’t displayed quite how we wanted. The problem is that all instances of a recurring event will be displayed as separate events. So for example let’s say you have four occurrences of Event A before Event B happens. In Upcoming Events, you’ll see Event A listed four times before Event B is listed. Maybe you want that, but in this case we did not. We wanted only the next occurrence of each recurring event to be displayed, and there was no way to chance that in the plugin settings.

I ended up writing a few custom queries/loops to get this done. There are basically two steps:

  1. Get all the upcoming events, including multiple occurrences of recurring events. Filter out the recurrences (is that a word?).
  2. Use the remaining IDs to do a second query and display those in a loop.

Here’s the code:

PHP
// Get the initial batch of events (includes multiple instances of recurring events).
$args = array(
  'post_type' => 'tribe_events',
  'post_status' => 'publish',
  'posts_per_page' => 30, // Can be anything, we just need enough to still have at least 3 when recurring events are filtered out.
  'meta_key' => '_eventstartdate',
  'orderby' => 'meta_value_datetime',
  'order' => 'ASC',
  'meta_value' => date("Y-m-d H:i:s"),
  'meta_compare' => '>',
  'tag' => 'featured-event-home',
);
$the_query = new WP_Query( $args );
$posts = $the_query->posts;

// Pull post ID and title from the results above. That's all we need to find "duplicate" events.
foreach ($posts as $post) {
  $simplified_postdata[$post->ID] = $post->post_title;
}

// Duplicate the simplified postdata into an array we will filter.
$filtered_postdata = $simplified_postdata;

// Loop through the postdata array to remove duplicate events (matching titles). Events are only removed from the filtered array.
foreach ($simplified_postdata as $inspected_id=>$inspected_title) {
  foreach ($simplified_postdata as $comparing_id=>$comparing_title) {
    if ($inspected_title === $comparing_title && $inspected_id < $comparing_id) {
      unset($filtered_postdata[$comparing_id]);
    }
  }
}

// Create an array of post IDs from the filtered postdata array.
$ids = array_keys($filtered_postdata);

// The final query args.
$args2 = [
  'post_type' => 'tribe_events',
  'post__in' => $ids,
  'posts_per_page' => 3,
];

// Do another query and loop through the results to display them.