() exempted fall through both, leaving it a 200. */ if ( ! get_query_var( 'sitemap' ) && ! get_query_var( 'sitemap-stylesheet' ) ) { return; } $sitemap = sanitize_text_field( get_query_var( 'sitemap' ) ); $object_subtype = sanitize_text_field( get_query_var( 'sitemap-subtype' ) ); $stylesheet_type = sanitize_text_field( get_query_var( 'sitemap-stylesheet' ) ); $paged = absint( get_query_var( 'paged' ) ); // Force a 404 and bail early if the route did not survive sanitizing. if ( ! ( $sitemap || $stylesheet_type ) ) { $this->send_404(); return; } if ( ! $this->sitemaps_enabled() ) { $this->send_404(); return; } // Render stylesheet if this is stylesheet route. if ( $stylesheet_type ) { // Force a 404 and bail early if the stylesheet type is not recognized. if ( ! in_array( $stylesheet_type, array( 'sitemap', 'index' ), true ) ) { $this->send_404(); return; } $stylesheet = new WP_Sitemaps_Stylesheet(); $stylesheet->render_stylesheet( $stylesheet_type ); exit; } // Render the index. if ( 'index' === $sitemap ) { $sitemap_list = $this->index->get_sitemap_list(); $this->renderer->render_index( $sitemap_list ); exit; } $provider = $this->registry->get_provider( $sitemap ); // Force a 404 and bail early if the requested provider is not registered. if ( ! $provider ) { $this->send_404(); return; } if ( empty( $paged ) ) { $paged = 1; } $url_list = $provider->get_url_list( $paged, $object_subtype ); // Force a 404 and bail early if no URLs are present. if ( empty( $url_list ) ) { $this->send_404(); return; } $this->renderer->render_sitemap( $url_list ); exit; } /** * Sends a 404 for a sitemap route that cannot be served. * * WP::handle_404() exempts sitemap requests, so every sitemap 404 is issued * here instead. That includes the no-cache headers handle_404() sends with * its own 404, so an intermediary does not retain a 404 for a route that * becomes valid once the site has more content. * * @since 7.1.1 * * @global WP_Query $wp_query WordPress Query object. */ private function send_404(): void { global $wp_query; $wp_query->set_404(); status_header( 404 ); nocache_headers(); } /** * Redirects a URL to the wp-sitemap.xml * * @since 5.5.0 * @deprecated 6.7.0 Deprecated in favor of {@see WP_Rewrite::rewrite_rules()} * * @param bool $bypass Pass-through of the pre_handle_404 filter value. * @param WP_Query $query The WP_Query object. * @return bool Bypass value. */ public function redirect_sitemapxml( $bypass, $query ) { _deprecated_function( __FUNCTION__, '6.7.0' ); // If a plugin has already utilized the pre_handle_404 function, return without action to avoid conflicts. if ( $bypass ) { return $bypass; } // 'pagename' is for most permalink types, name is for when the %postname% is used as a top-level field. if ( 'sitemap-xml' === $query->get( 'pagename' ) || 'sitemap-xml' === $query->get( 'name' ) ) { wp_safe_redirect( $this->index->get_index_url() ); exit(); } return $bypass; } /** * Adds the sitemap index to robots.txt. * * @since 5.5.0 * * @param string $output robots.txt output. * @param bool $is_public Whether the site is public. * @return string The robots.txt output. */ public function add_robots( $output, $is_public ) { if ( $is_public ) { $output .= "\nSitemap: " . esc_url( $this->index->get_index_url() ) . "\n"; } return $output; } }