文件操作 - Controller.php
返回文件管理
返回主菜单
删除本文件
文件: /home/www/public/wp-content/plugins/the-events-calendar/src/Events/SEO/Headers/Controller.php
编辑文件内容
<?php /** * Manages the legacy view removal and messaging. * * @since 6.10.2 * * @package TEC\Events\SEO */ namespace TEC\Events\SEO\Headers; use TEC\Common\Contracts\Provider\Controller as Controller_Contract; use TEC\Events\SEO\Settings; use Tribe__Events__Main as TEC; /** * Class Controller * * @since 6.10.2 * * @package TEC\Events\SEO\Headers */ class Controller extends Controller_Contract { /** * Register actions. * * @since 6.10.2 * @since 6.15.20 */ public function do_register(): void { $this->container->singleton( static::class, $this ); add_action( 'send_headers', [ $this, 'filter_headers' ] ); add_filter( 'pre_handle_404', [ $this, 'prevent_list_view_paged_404' ], 10, 2 ); } /** * Unregister actions. * * @since 6.10.2 * @since 6.15.20 */ public function unregister(): void { remove_action( 'send_headers', [ $this, 'filter_headers' ] ); remove_filter( 'pre_handle_404', [ $this, 'prevent_list_view_paged_404' ], 10 ); } /** * Prevent WordPress from issuing a 404 for paginated TEC list view requests. * * On MariaDB, the Custom Tables query can return 0 rows for paged list view * requests due to GROUP BY occurrence_id + LIMIT offset optimiser differences * versus MySQL. WordPress's handle_404() unconditionally sets 404 when * is_paged() = true and $wp_query->posts is empty, so this filter intercepts * before that logic runs and lets TEC render the view with its own repository. * * @since 6.15.20 * * @param bool $preempt Whether to short-circuit handle_404(). * @param \WP_Query $wp_query The main query object. * * @return bool True to prevent the 404, otherwise the original value. */ public function prevent_list_view_paged_404( bool $preempt, \WP_Query $wp_query ): bool { if ( $preempt ) { return $preempt; } if ( ! $wp_query->is_main_query() || ! isset( $wp_query->query['post_type'] ) || $wp_query->query['post_type'] !== TEC::POSTTYPE || ! isset( $wp_query->query['eventDisplay'] ) || $wp_query->query['eventDisplay'] !== 'list' || empty( $wp_query->query['paged'] ) || (int) $wp_query->query['paged'] <= 1 ) { return $preempt; } $enabled_views = tribe_get_option( 'tribeEnableViews', [] ); if ( ! in_array( 'list', $enabled_views, true ) ) { return $preempt; } return true; } /** * Filter the headers based on the query. * * @since 6.10.2 */ public function filter_headers() { global $wp_query; if ( ! isset( $wp_query->query['post_type'] ) || $wp_query->query['post_type'] !== TEC::POSTTYPE || ! isset( $wp_query->query['eventDisplay'] ) ) { return; } $enabled_views = tribe_get_option( 'tribeEnableViews', [] ); $event_display = $wp_query->query['eventDisplay']; // 'past' is a List view display-mode modifier, not a view slug — normalize it so // the enabled-view guard and per-view dispatch both treat it as 'list'. $effective_display = 'past' === $event_display ? 'list' : $event_display; // disabled-view guard — otherwise the main events page receives a false 404. if ( 'default' === $effective_display ) { return; } if ( $this->is_single_event_request( $wp_query ) ) { return; } // 404 for any view that is currently disabled, regardless of how the URL was built. // Site owners can disable this guard via Settings > Display > SEO & URL Handling. if ( ! in_array( $effective_display, $enabled_views, true ) ) { if ( tribe_get_option( Settings::OPT_DISABLED_VIEW_404, true ) ) { $this->set_404( $wp_query ); } // Either way, skip per-view date checks for a disabled view. return; } // Day/Month views carry the date as a WP query var (set by URL rewrite rules). // List view keeps the date as a raw GET parameter (?tribe-bar-date) instead. $has_pretty_date = isset( $wp_query->query['eventDate'] ); $has_list_date = 'list' === $effective_display && ! empty( tribe_get_request_var( 'tribe-bar-date' ) ); if ( ! $has_pretty_date && ! $has_list_date ) { return; } if ( 'day' === $effective_display ) { $this->check_day_view( $wp_query, $enabled_views ); } elseif ( 'month' === $effective_display ) { $this->check_month_view( $wp_query, $enabled_views ); } elseif ( 'list' === $effective_display ) { $this->check_list_view( $wp_query, $enabled_views ); } } /** * Whether the current request targets a single event rather than an event archive. * * The disabled-view 404 guard is only meaningful for the calendar *archive* views * (list, month, day, photo, …). Single-event endpoints reuse the `eventDisplay` * query var for non-archive purposes — the Event Tickets registration page * (eventDisplay=tickets), the recurring-series `all` view and the single-event * `ical` feed — and must never be treated as a disabled archive view. * * A single event is always addressed by its slug (`name` / `tribe_events`) or its * ID (`p`) in the parsed query, which archive requests never carry. The WP * conditionals are checked first for real requests, with the raw query vars as a * fallback for early hooks or direct calls where the conditionals are not yet set. * * @since 6.17.1 * * @param \WP_Query $wp_query The global WP_Query object. * * @return bool True when the request is for a single event. */ private function is_single_event_request( \WP_Query $wp_query ): bool { if ( $wp_query->is_single || $wp_query->is_singular ) { return true; } return ! empty( $wp_query->query['name'] ) || ! empty( $wp_query->query['tribe_events'] ) || ! empty( $wp_query->query['p'] ); } /** * Prepare common date variables for view checks. * * This method collects variables needed for both day and month view checks. * For day view, it expects $date_format = 'Y-m-d' (and computes the event's month). * For month view, it expects $date_format = 'Y-m' (where eventDate is already in "Y-m" format). * * @param object $wp_query The global WP_Query object. * @param string $date_format Format to use for tribe_events_* functions. * Use 'Y-m-d' for day view and 'Y-m' for month view. * * @return array An array with the following keys: * - event_date_str: The raw event date from the query. * - event_timestamp: (For day view) The event date as a timestamp. * - event_month: The event's month in "Y-m" format. * - current_month: The current month in "Y-m" format. * - earliest_date_str: The earliest event date (in the specified format). * - latest_date_str: The latest event date (in the specified format). */ private function prepare_date_check( object $wp_query, string $date_format ): array { $event_date_str = $wp_query->query['eventDate']; $current_month = static::get_current_month(); if ( 'Y-m-d' === $date_format ) { $event_timestamp = strtotime( $event_date_str ); $event_month = gmdate( 'Y-m', $event_timestamp ); } else { $event_timestamp = null; $event_month = $event_date_str; } $earliest_date_str = tribe_events_earliest_date( $date_format ); $latest_date_str = tribe_events_latest_date( $date_format ); return [ 'event_date_str' => $event_date_str, 'event_timestamp' => $event_timestamp, 'current_month' => $current_month, 'event_month' => $event_month, 'earliest_date_str' => $earliest_date_str, 'latest_date_str' => $latest_date_str, ]; } /** * Check the conditions for the day view. * * If either tribe_events_earliest_date() or tribe_events_latest_date() returns false/empty * and the event's month is the current month, do not set a 404. * * @param object $wp_query The global WP_Query object. * @param array $enabled_views An array of the enabled views. */ private function check_day_view( object $wp_query, array $enabled_views ) { if ( ! in_array( 'day', $enabled_views, true ) ) { $this->set_404( $wp_query ); return; } $data = $this->prepare_date_check( $wp_query, 'Y-m-d' ); // If either date is false/empty and the event's month matches the current month, skip further checks. if ( ( ! $data['earliest_date_str'] || ! $data['latest_date_str'] ) && ( $data['event_month'] === $data['current_month'] ) ) { return; } if ( strtotime( $data['earliest_date_str'] ) > $data['event_timestamp'] ) { $this->set_404( $wp_query ); return; } if ( strtotime( $data['latest_date_str'] ) < $data['event_timestamp'] ) { $this->set_404( $wp_query ); return; } } /** * Check the conditions for the month view. * * If either tribe_events_earliest_date() or tribe_events_latest_date() returns false/empty * and the eventDate equals the current month, do not set a 404. * * @param object $wp_query The global WP_Query object. * @param array $enabled_views An array of the enabled views. */ private function check_month_view( object $wp_query, array $enabled_views ) { if ( ! in_array( 'month', $enabled_views, true ) ) { $this->set_404( $wp_query ); return; } $data = $this->prepare_date_check( $wp_query, 'Y-m' ); // For month view, eventDate is expected to be in "Y-m" format. // If either date is false/empty and eventDate equals the current month, skip further checks. if ( ( ! $data['earliest_date_str'] || ! $data['latest_date_str'] ) && ( $data['event_date_str'] === $data['current_month'] ) ) { return; } if ( $data['earliest_date_str'] > $data['event_date_str'] ) { $this->set_404( $wp_query ); return; } if ( $data['latest_date_str'] < $data['event_date_str'] ) { $this->set_404( $wp_query ); return; } } /** * Check the conditions for the list view. * * Returns a 404 (or noindex, depending on the tec_seo_out_of_range_behavior setting) when: * - List view is disabled in TEC settings. * - The ?tribe-bar-date parameter refers to a date before the earliest event on record. * - The ?tribe-bar-date parameter refers to a date after the latest event on record. * * Mirrors the grace logic used in check_day_view(): if the site has no events yet and * the requested date is in the current month, validation is skipped so the live list * view is not erroneously suppressed. * * @since 6.16.5 * * @param object $wp_query The global WP_Query object. * @param array $enabled_views An array of the enabled view slugs. */ private function check_list_view( object $wp_query, array $enabled_views ): void { if ( ! in_array( 'list', $enabled_views, true ) ) { $this->set_404( $wp_query ); return; } // List view stores the date in ?tribe-bar-date (a raw GET param, not a WP query var). $tribe_bar_date = tribe_get_request_var( 'tribe-bar-date', '' ); if ( empty( $tribe_bar_date ) ) { return; } $event_timestamp = strtotime( $tribe_bar_date ); // Bail on malformed date strings. if ( false === $event_timestamp ) { return; } $event_month = gmdate( 'Y-m', $event_timestamp ); $current_month = static::get_current_month(); $earliest_date_str = tribe_events_earliest_date( 'Y-m-d' ); $latest_date_str = tribe_events_latest_date( 'Y-m-d' ); // No events exist yet: allow only the current month (grace), 404 everything else. if ( ! $earliest_date_str || ! $latest_date_str ) { if ( $event_month !== $current_month ) { $this->handle_out_of_range( $wp_query ); } return; } if ( strtotime( $earliest_date_str ) > $event_timestamp ) { $this->handle_out_of_range( $wp_query ); return; } if ( strtotime( $latest_date_str ) < $event_timestamp ) { $this->handle_out_of_range( $wp_query ); } } /** * Respond to an out-of-range date request. * * By default (setting: 'hard_404'), the WP_Query is set to a 404 so WordPress * returns an HTTP 404 Not Found response — the strongest SEO signal. * * When the site owner has chosen 'soft_noindex' in Settings > Display > * SEO & URL Handling, the page is still served (HTTP 200) but a noindex * robots directive is injected via the wp_robots filter, so search engines * will not index the URL without surfacing a 404 error page to visitors. * * @since 6.16.5 * * @param object $wp_query The global WP_Query object. */ private function handle_out_of_range( object $wp_query ): void { $behavior = tribe_get_option( Settings::OPT_OUT_OF_RANGE_BEHAVIOR, 'hard_404' ); if ( 'soft_noindex' === $behavior ) { // Add noindex at the wp_robots filter stage instead of returning a 404. add_filter( 'wp_robots', static function ( array $robots ): array { $robots['noindex'] = true; return $robots; } ); return; } $this->set_404( $wp_query ); } /** * Set the query to 404 and send the HTTP 404 status header. * * @param \WP_Query $wp_query The query to mark as 404. */ private function set_404( \WP_Query $wp_query ): void { $wp_query->set_404(); status_header( 404 ); } /** * Get the current month. * * This method is used to determine the current month and can be overridden in tests. * * @return string The current month in "Y-m" format. */ protected static function get_current_month() { return gmdate( 'Y-m' ); } }
修改文件时间
将文件时间修改为当前时间的前一年
删除文件