芝麻web文件管理V1.00
编辑当前文件:/var/www/cognitio.in/wp-content/plugins/the-events-calendar/src/Tribe/Adjacent_Events.php
current_event_id = $event_id; } /** * Get the "center" event ID to look on either side of in prev/next methods. * * @since 4.6.12 * * @param int $event_id The event ID to look on either side of in prev/next methods. */ public function get_current_event_id() { return $this->current_event_id; } /** * Get link to the previous event. * * @since 4.6.12 * * @param boolean $anchor * @return string */ public function get_prev_event_link( $anchor ) { if ( empty( $this->previous_event_link ) ) { $this->previous_event_link = $this->get_event_link( 'previous', $anchor ); } return $this->previous_event_link; } /** * Get link to the next event. * * @since 4.6.12 * * @param boolean $anchor * @return string */ public function get_next_event_link( $anchor ) { if ( empty( $this->next_event_link ) ) { $this->next_event_link = $this->get_event_link( 'next', $anchor ); } return $this->next_event_link; } /** * 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 * * @since 4.0.2 * @since 4.6.12 Moved to new Tribe__Events__Adjacent_Events class. * * @param string $where_sql WHERE SQL statement * @param WP_Query $query WP_Query object * * @return string */ 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; } /** * Get the prev/next post for a given event. Ordered by start date instead of ID. * * @since 4.6.12 * @since 6.0.7 Cache the query results. * * @param string $mode Either 'next' or 'previous'. * * @return null|WP_Post The closest Event post object, or `null` if no post was found. */ public function get_closest_event( $mode = 'next' ) { if ( empty( $this->current_event_id ) ) { return null; } $cache = tribe_cache(); $cache_key = 'tec_events_closest_event_' . $this->current_event_id . '_' . $mode; // The cached value will be the post ID, or `null`, to avoid pre-fetch issues. $cached = $cache->get( $cache_key, Cache_Listener::TRIGGER_SAVE_POST, false ); $event = $cached; if ( ! empty( $cached ) ) { // If not empty, it should be a valid event post ID. $event = get_post( $cached ); if ( ! ( $event instanceof WP_Post && $event->post_type === TEC::POSTTYPE ) ) { $event = false; } } elseif ( $cached !== null ) { // If not a post ID, then it should be `null`. $event = false; } $post_obj = get_post( $this->current_event_id ); if ( $event === false ) { if ( 'previous' === $mode ) { $order = 'DESC'; $direction = '<'; } else { $order = 'ASC'; $direction = '>'; $mode = 'next'; } $args = [ 'posts_per_page' => 1, 'post__not_in' => [ $this->current_event_id ], 'meta_query' => [ [ 'key' => '_EventStartDate', 'value' => $post_obj->_EventStartDate, 'type' => 'DATETIME', 'compare' => $direction, ], [ 'key' => '_EventHideFromUpcoming', 'compare' => 'NOT EXISTS', ], 'relation' => 'AND', ], ]; $events_orm = tribe_events(); /** * Allows the query arguments used when retrieving the next/previous event link * to be modified. * * @since 4.6.12 * * @param array $args * @param WP_Post $post_obj */ $args = (array) apply_filters( "tribe_events_get_{$mode}_event_link", $args, $post_obj ); $events_orm->order_by( 'event_date', $order ); $events_orm->by_args( $args ); $query = $events_orm->get_query();// Make sure we are not including same datetime events add_filter( 'posts_where', [ $this, 'get_closest_event_where' ] );// Fetch the posts $query->get_posts();// Remove this filter right after fetching the events remove_filter( 'posts_where', [ $this, 'get_closest_event_where' ] ); $results = $query->posts; $event = null; // If we successfully located the next/prev event, we should have precisely one element in $results if ( 1 === count( $results ) ) { $event = reset( $results ); } $value = $event instanceof WP_Post ? $event->ID : $event; // Cache until an Event is updated; just the ID to avoid pre-fetching issues, or `null`. $cache->set( $cache_key, $value, WEEK_IN_SECONDS, Cache_Listener::TRIGGER_SAVE_POST ); } /** * Affords an opportunity to modify the event used to generate the event link (typically for * the next or previous event in relation to $post). * * @since 4.6.12 * * @param WP_Post $post_obj * @param string $mode (typically "previous" or "next") */ return apply_filters( 'tribe_events_get_closest_event', $event, $post_obj, $mode ); } /** * Get a "previous/next post" link for events. Ordered by start date instead of ID. * * @since 4.6.12 * * @param string $mode Either 'next' or 'previous'. * @param mixed $anchor * * @return string The link (with
tags). */ public function get_event_link( $mode = 'next', $anchor = false ) { $link = null; $event = $this->get_closest_event( $mode ); // If we successfully located the next/prev event, we should have precisely one element in $results if ( $event ) { if ( ! $anchor ) { $anchor = apply_filters( 'the_title', $event->post_title, $event->ID ); } elseif ( strpos( $anchor, '%title%' ) !== false ) { // get the nicely filtered post title $title = apply_filters( 'the_title', $event->post_title, $event->ID ); // escape special characters used in the second parameter of preg_replace $title = str_replace( [ '\\', '$', ], [ '\\\\', '\$', ], $title ); $anchor = preg_replace( '|%title%|', $title, $anchor ); } $link = '
' . $anchor . '
'; } /** * Affords an opportunity to modify the event link (typically for the next or previous * event in relation to $post). * * @since 4.6.12 * * @param string $link * @param int $current_event_id * @param WP_Post $event * @param string $mode (typically "previous" or "next") * @param string $anchor */ return apply_filters( 'tribe_events_get_event_link', $link, $this->current_event_id, $event, $mode, $anchor ); } }