Tribe__Events__Adjacent_Events::get_closest_event_where( string $where_sql )

Modify the WHERE clause of query when fetching next/prev posts so events with identical times are not excluded

This method ensures that when viewing single events that occur at a given time, other events that occur at the exact same time are are not excluded from the prev/next links


Parameters

$where_sql

(string) (Required) WHERE SQL statement

$query

(WP_Query) (Required) WP_Query object


Top ↑

Return

(string)


Top ↑

Source

File: src/Tribe/Adjacent_Events.php

	public function get_closest_event_where( $where_sql ) {
		// if we are in this method, we KNOW there is a section of the SQL that looks like this:
		//     ( table.meta_key = '_EventStartDate' AND CAST( table.meta_value AS DATETIME ) [<|>] '2015-01-01 00:00:00' )
		// What we want to do is to extract all the portions of the WHERE BEFORE that section, all the
		// portions AFTER that section, and then rebuild that section to be flexible enough to include
		// events that have the SAME datetime as the event we're comparing against.  Sadly, this requires
		// some regex-fu.
		//
		// The end-game is to change the known SQL line (from above) into the following:
		//
		//  (
		//    ( table.meta_key = '_EventStartDate' AND CAST( table.meta_value AS DATETIME ) [<|>] '2015-01-01 00:00:00' )
		//    OR (
		//      ( table.meta_key = '_EventStartDate' AND CAST( table.meta_value AS DATETIME ) = '2015-01-01 00:00:00' )
		//      AND
		//      table.post_id [<|>] POST_ID
		//    )
		//  )
		//

		// Here's the regex portion that matches the part that we know. From that line, we want to
		// have a few capture groups.
		//     1) We need the whole thing
		//     2) We need the meta table alias
		//     3) We need the < or > sign

		// Here's the regex for getting the meta table alias
		$meta_table_regex = '([^\.]+)\.meta_key\s*=\s*';

		// Here's the regex for the middle section of the know line
		$middle_regex = '[\'"]_EventStartDate[\'"]\s+AND\s+CAST[^\)]+AS DATETIME\s*\)\s*';

		// Here's the regex for the < and > sign
		$gt_lt_regex = '(\<|\>)';

		// Let's put that line together, making sure we are including the wrapping parens and the
		// characters that make up the rest of the line - spacing in front, non paren characters at
		// the end
		$known_sql_regex = "\(\s*{$meta_table_regex}{$middle_regex}{$gt_lt_regex}[^\)]+\)";

		// The known SQL line will undoubtedly be included amongst other WHERE statements. We need
		// to generically grab the SQL before and after the known line so we can rebuild our nice new
		// where statement. Here's the regex that brings it all together.
		//   Note: We are using the 'm' modifier so that the regex looks over multiple lines as well
		//         as the 's' modifier so that '.' includes linebreaks
		$full_regex = "/(.*)($known_sql_regex)(.*)/ms";

		// here's a regex to grab the post ID from a portion of the WHERE statement
		$post_id_regex = '/NOT IN\s*\(([0-9]+)\)/';

		if ( preg_match( $full_regex, $where_sql, $matches ) ) {
			// place capture groups into vars that are easier to read
			$before = $matches[1];
			$known  = $matches[2];
			$alias  = $matches[3];
			$gt_lt  = $matches[4];
			$after  = $matches[5];

			// copy the known line but replace the < or > symbol with an =
			$equal = preg_replace( '/(\<|\>)/', '=', $known );

			// extract the post ID from the extra "before" or "after" WHERE
			if (
				preg_match( $post_id_regex, $before, $post_id )
				|| preg_match( $post_id_regex, $after, $post_id )
			) {
				$post_id = absint( $post_id[1] );
			} else {
				// if we can't find the post ID, then let's bail
				return $where_sql;
			}

			// rebuild the WHERE clause
			$where_sql = "{$before} (
				{$known}
				OR (
					{$equal}
					AND {$alias}.post_id {$gt_lt} {$post_id}
				)
			) {$after} ";
		}

		return $where_sql;
	}

Top ↑

Changelog

Changelog
Version Description
4.6.12 Moved to new Tribe<strong>Events</strong>Adjacent_Events class.
4.0.2 Introduced.