Tribe__Events__Pro__Repositories__Event::get_query()
Overrides the base method to take display and render context into account.
Return
(WP_Query) A built query object, get_posts has not been called yet.
Source
File: src/Tribe/Repositories/Event.php
public function get_query() {
// Handle the case where we're fetching by post name and want all event instances.
$this->maybe_expand_post_name( );
if ( ! $this->should_collapse_recurring_event_instances() ) {
// Nothing to do here!
return parent::get_query();
}
global $wpdb;
if ( ! $this->has_date_filters() ) {
/*
* Let's not add costly queries if not really needed.
* If no date filters are being applied we just want the first event of a series.
*/
$this->filter_query->where( "{$wpdb->posts}.post_parent = 0" );
} else {
/*
* To make the cut an event must fit the date(s) criteria and either:
* - have no children and no parent (a single event)
* - have children and have no children fitting the criteria (a series first event)
* - have a parent not fitting the criteria (a series instance)
*
* Here we clone the query, run it, and get all the events fitting the date criteria.
*/
$secondary_query = clone parent::get_query();
// Lighten the query fetching IDs only.
$secondary_query->set( 'fields', 'ids' );
// Fetch ALL matching event IDs to override what limits the pagination would apply.
$secondary_query->set( 'posts_per_page', - 1 );
// Order events, whatever the criteria applying to the main query, by start date.
$secondary_query->set( 'orderby', 'meta_value' );
$secondary_query->set( 'meta_key', '_EventStartDateUTC' );
/*
* Since we use the `post__in` query argument for our logic
* let's remove what `post__in` IDs we might have added to make sure we fetch the correct results.
*/
$this->clean_post__in( $secondary_query );
/*
* We need the SQL to get the `post_parent` and `meta_value` fields included in the results.
* There is no way to do that other than filtering the WordPress query generated in the context
* of a `get_posts` request.
*/
$filter = new Tribe__Repository__Query_Filters();
$filter->set_query( $secondary_query );
$filter->fields( 'post_parent' );
$filter->fields( $wpdb->postmeta . '.meta_value' );
$request = $filter->get_request();
$all_ids = $wpdb->get_results( $request, ARRAY_N );
if ( ! empty( $all_ids ) ) {
/*
* Let's put events in races:
* 1. group them by post parent, or own if parent, ID
* 2. order them by start date in order
*/
$order = $secondary_query->get( 'order', 'ASC' );
$winners = array_reduce( $all_ids, function ( array $acc, array $result ) use ( $order ) {
list( $post_id, $post_parent, $start_date ) = $result;
$post_id = (int) $post_id;
$post_parent = (int) $post_parent;
$post_parent = 0 === $post_parent ? $post_id : $post_parent;
$current = isset( $acc[ $post_parent ]['start_date'] ) ? $acc[ $post_parent ]['start_date'] : false;
if ( ! $current ) {
$acc[ $post_parent ]['start_date'] = $start_date;
} else {
$acc[ $post_parent ]['start_date'] = $order === 'DESC' ? max( $start_date,
$current ) : min( $start_date, $current );
}
if ( $acc[ $post_parent ]['start_date'] !== $current ) {
$acc[ $post_parent ]['ID'] = $post_id;
}
return $acc;
}, [] );
// Let's add a query argument to keep track of what post IDs we've added in the `post__in` clause.
$this->query_args['tribe_post__in'] = array_column( $winners, 'ID' );
$this->where( 'post__in', array_column( $winners, 'ID' ) );
}
}
return parent::get_query();
}
Changelog
| Version | Description |
|---|---|
| 4.7 | Introduced. |