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
Contents
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
Return
(string)
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;
}
Changelog
| Version | Description |
|---|---|
| 4.6.12 | Moved to new Tribe<strong>Events</strong>Adjacent_Events class. |
| 4.0.2 | Introduced. |