| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Sitemaps: WP_Sitemaps class 4 * 5 * This is the main class integrating all other classes. 6 * 7 * @package WordPress 8 * @subpackage Sitemaps 9 * @since 5.5.0 10 */ 11 12 /** 13 * Class WP_Sitemaps. 14 * 15 * @since 5.5.0 16 */ 17 #[AllowDynamicProperties] 18 class WP_Sitemaps { 19 /** 20 * The main index of supported sitemaps. 21 * 22 * @since 5.5.0 23 * 24 * @var WP_Sitemaps_Index 25 */ 26 public $index; 27 28 /** 29 * The main registry of supported sitemaps. 30 * 31 * @since 5.5.0 32 * 33 * @var WP_Sitemaps_Registry 34 */ 35 public $registry; 36 37 /** 38 * An instance of the renderer class. 39 * 40 * @since 5.5.0 41 * 42 * @var WP_Sitemaps_Renderer 43 */ 44 public $renderer; 45 46 /** 47 * WP_Sitemaps constructor. 48 * 49 * @since 5.5.0 50 */ 51 public function __construct() { 52 $this->registry = new WP_Sitemaps_Registry(); 53 $this->renderer = new WP_Sitemaps_Renderer(); 54 $this->index = new WP_Sitemaps_Index( $this->registry ); 55 } 56 57 /** 58 * Initiates all sitemap functionality. 59 * 60 * If sitemaps are disabled, only the rewrite rules will be registered 61 * by this method, in order to properly send 404s. 62 * 63 * @since 5.5.0 64 */ 65 public function init() { 66 // These will all fire on the init hook. 67 $this->register_rewrites(); 68 69 add_action( 'template_redirect', array( $this, 'render_sitemaps' ) ); 70 71 if ( ! $this->sitemaps_enabled() ) { 72 return; 73 } 74 75 $this->register_sitemaps(); 76 77 // Add additional action callbacks. 78 add_filter( 'robots_txt', array( $this, 'add_robots' ), 0, 2 ); 79 } 80 81 /** 82 * Determines whether sitemaps are enabled or not. 83 * 84 * @since 5.5.0 85 * 86 * @return bool Whether sitemaps are enabled. 87 */ 88 public function sitemaps_enabled() { 89 $is_enabled = (bool) get_option( 'blog_public' ); 90 91 /** 92 * Filters whether XML Sitemaps are enabled or not. 93 * 94 * When XML Sitemaps are disabled via this filter, rewrite rules are still 95 * in place to ensure a 404 is returned. 96 * 97 * @see WP_Sitemaps::register_rewrites() 98 * 99 * @since 5.5.0 100 * 101 * @param bool $is_enabled Whether XML Sitemaps are enabled or not. 102 * Defaults to true for public sites. 103 */ 104 return (bool) apply_filters( 'wp_sitemaps_enabled', $is_enabled ); 105 } 106 107 /** 108 * Registers and sets up the functionality for all supported sitemaps. 109 * 110 * @since 5.5.0 111 */ 112 public function register_sitemaps() { 113 $providers = array( 114 'posts' => new WP_Sitemaps_Posts(), 115 'taxonomies' => new WP_Sitemaps_Taxonomies(), 116 'users' => new WP_Sitemaps_Users(), 117 ); 118 119 /* @var WP_Sitemaps_Provider $provider */ 120 foreach ( $providers as $name => $provider ) { 121 $this->registry->add_provider( $name, $provider ); 122 } 123 } 124 125 /** 126 * Registers sitemap rewrite tags and routing rules. 127 * 128 * @since 5.5.0 129 */ 130 public function register_rewrites() { 131 // Add rewrite tags. 132 add_rewrite_tag( '%sitemap%', '([^?]+)' ); 133 add_rewrite_tag( '%sitemap-subtype%', '([^?]+)' ); 134 135 // Register index route. 136 add_rewrite_rule( '^wp-sitemap\.xml$', 'index.php?sitemap=index', 'top' ); 137 138 // Register routes for providers. 139 add_rewrite_rule( 140 '^wp-sitemap-([a-z]+?)-([a-z\d_-]+?)-(\d+?)\.xml$', 141 'index.php?sitemap=$matches[1]&sitemap-subtype=$matches[2]&paged=$matches[3]', 142 'top' 143 ); 144 add_rewrite_rule( 145 '^wp-sitemap-([a-z]+?)-(\d+?)\.xml$', 146 'index.php?sitemap=$matches[1]&paged=$matches[2]', 147 'top' 148 ); 149 } 150 151 /** 152 * Renders sitemap templates based on rewrite rules. 153 * 154 * @since 5.5.0 155 */ 156 public function render_sitemaps() { 157 /* 158 * Bail early if this isn't a sitemap route. 159 * 160 * This runs on every front-end request, so it comes before any 161 * sanitizing. The raw query vars are tested here, matching 162 * WP::handle_404(), which exempts sitemap requests from its own 404 on 163 * the same basis. Testing the sanitized values instead would let a 164 * request that handle_404() exempted fall through both, leaving it a 200. 165 */ 166 if ( ! get_query_var( 'sitemap' ) ) { 167 return; 168 } 169 170 $sitemap = sanitize_text_field( get_query_var( 'sitemap' ) ); 171 $object_subtype = sanitize_text_field( get_query_var( 'sitemap-subtype' ) ); 172 $paged = absint( get_query_var( 'paged' ) ); 173 174 // Force a 404 and bail early if the route did not survive sanitizing. 175 if ( ! $sitemap ) { 176 $this->send_404(); 177 return; 178 } 179 180 if ( ! $this->sitemaps_enabled() ) { 181 $this->send_404(); 182 return; 183 } 184 185 // Render the index. 186 if ( 'index' === $sitemap ) { 187 $sitemap_list = $this->index->get_sitemap_list(); 188 189 $this->renderer->render_index( $sitemap_list ); 190 exit; 191 } 192 193 $provider = $this->registry->get_provider( $sitemap ); 194 195 // Force a 404 and bail early if the requested provider is not registered. 196 if ( ! $provider ) { 197 $this->send_404(); 198 return; 199 } 200 201 if ( empty( $paged ) ) { 202 $paged = 1; 203 } 204 205 // Force a 404 and bail early if the sub-type query variable is set to an invalid value. 206 if ( $object_subtype && ! array_key_exists( $object_subtype, $provider->get_object_subtypes() ) ) { 207 $this->send_404(); 208 return; 209 } 210 211 $url_list = $provider->get_url_list( $paged, $object_subtype ); 212 213 // Force a 404 and bail early if the requested page is out of range. 214 if ( $paged > $provider->get_max_num_pages( $object_subtype ) ) { 215 $this->send_404(); 216 return; 217 } 218 219 $this->renderer->render_sitemap( $url_list ); 220 if ( ! defined( 'WP_RUN_CORE_TESTS' ) || ! WP_RUN_CORE_TESTS ) { 221 exit; 222 } 223 } 224 225 /** 226 * Sends a 404 for a sitemap route that cannot be served. 227 * 228 * WP::handle_404() exempts sitemap requests, so every sitemap 404 is issued 229 * here instead. That includes the no-cache headers handle_404() sends with 230 * its own 404, so an intermediary does not retain a 404 for a route that 231 * becomes valid once the site has more content. 232 * 233 * @since 7.1.1 234 * 235 * @global WP_Query $wp_query WordPress Query object. 236 */ 237 private function send_404(): void { 238 global $wp_query; 239 240 $wp_query->set_404(); 241 status_header( 404 ); 242 nocache_headers(); 243 } 244 245 /** 246 * Redirects a URL to the wp-sitemap.xml 247 * 248 * @since 5.5.0 249 * @deprecated 6.7.0 Deprecated in favor of {@see WP_Rewrite::rewrite_rules()} 250 * 251 * @param bool $bypass Pass-through of the pre_handle_404 filter value. 252 * @param WP_Query $query The WP_Query object. 253 * @return bool Bypass value. 254 */ 255 public function redirect_sitemapxml( $bypass, $query ) { 256 _deprecated_function( __FUNCTION__, '6.7.0' ); 257 258 // If a plugin has already utilized the pre_handle_404 function, return without action to avoid conflicts. 259 if ( $bypass ) { 260 return $bypass; 261 } 262 263 // 'pagename' is for most permalink types, name is for when the %postname% is used as a top-level field. 264 if ( 'sitemap-xml' === $query->get( 'pagename' ) 265 || 'sitemap-xml' === $query->get( 'name' ) 266 ) { 267 wp_safe_redirect( $this->index->get_index_url() ); 268 exit(); 269 } 270 271 return $bypass; 272 } 273 274 /** 275 * Adds the sitemap index to robots.txt. 276 * 277 * @since 5.5.0 278 * 279 * @param string $output robots.txt output. 280 * @param bool $is_public Whether the site is public. 281 * @return string The robots.txt output. 282 */ 283 public function add_robots( $output, $is_public ) { 284 if ( $is_public ) { 285 $output .= "\nSitemap: " . esc_url( $this->index->get_index_url() ) . "\n"; 286 } 287 288 return $output; 289 } 290 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Tue Nov 3 08:20:36 2026 | Cross-referenced by PHPXref |