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.


Top ↑

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();
	}

Top ↑

Changelog

Changelog
Version Description
4.7 Introduced.