PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / trunk
Yoast SEO – Advanced SEO with real-time guidance and built-in AI vtrunk
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
← All changes | inc/sitemaps/class-sitemaps.php +76 -49 18.3 → trunk View file →
@@ -16,9 +16,9 @@
16 16 * Sitemap index identifier.
17 17 *
18 18 * @var string
19 19 */
20 - const SITEMAP_INDEX_TYPE = '1';
20 + public const SITEMAP_INDEX_TYPE = '1';
21 21
22 22 /**
23 23 * Content of the sitemap to output.
24 24 *
@@ -100,9 +100,8 @@
100 100 add_action( 'after_setup_theme', [ $this, 'init_sitemaps_providers' ] );
101 101 add_action( 'after_setup_theme', [ $this, 'reduce_query_load' ], 99 );
102 102 add_action( 'pre_get_posts', [ $this, 'redirect' ], 1 );
103 103 add_action( 'wpseo_hit_sitemap_index', [ $this, 'hit_sitemap_index' ] );
104 - add_action( 'wpseo_ping_search_engines', [ __CLASS__, 'ping_search_engines' ] );
105 104
106 105 $this->router = new WPSEO_Sitemaps_Router();
107 106 $this->renderer = new WPSEO_Sitemaps_Renderer();
108 107 $this->cache = new WPSEO_Sitemaps_Cache();
@@ -115,8 +114,10 @@
115 114 /**
116 115 * Initialize sitemap providers classes.
117 116 *
118 117 * @since 5.3
118 + *
119 + * @return void
119 120 */
120 121 public function init_sitemaps_providers() {
121 122
122 123 $this->providers = [
@@ -135,8 +136,10 @@
135 136 }
136 137
137 138 /**
138 139 * Check the current request URI, if we can determine it's probably an XML sitemap, kill loading the widgets.
140 + *
141 + * @return void
139 142 */
140 143 public function reduce_query_load() {
141 144 if ( ! isset( $_SERVER['REQUEST_URI'] ) ) {
142 145 return;
@@ -153,13 +156,15 @@
153 156 *
154 157 * @param string $name The name of the sitemap.
155 158 * @param callback $building_function Function to build your sitemap.
156 159 * @param string $rewrite Optional. Regular expression to match your sitemap with.
160 + *
161 + * @return void
157 162 */
158 163 public function register_sitemap( $name, $building_function, $rewrite = '' ) {
159 164 add_action( 'wpseo_do_sitemap_' . $name, $building_function );
160 - if ( ! empty( $rewrite ) ) {
161 - add_rewrite_rule( $rewrite, 'index.php?sitemap=' . $name, 'top' );
165 + if ( $rewrite ) {
166 + Yoast_Dynamic_Rewrites::instance()->add_rule( $rewrite, 'index.php?sitemap=' . $name, 'top' );
162 167 }
163 168 }
164 169
165 170 /**
@@ -169,13 +174,15 @@
169 174 *
170 175 * @param string $name The name of the XSL file.
171 176 * @param callback $building_function Function to build your XSL file.
172 177 * @param string $rewrite Optional. Regular expression to match your sitemap with.
178 + *
179 + * @return void
173 180 */
174 181 public function register_xsl( $name, $building_function, $rewrite = '' ) {
175 182 add_action( 'wpseo_xsl_' . $name, $building_function );
176 - if ( ! empty( $rewrite ) ) {
177 - add_rewrite_rule( $rewrite, 'index.php?yoast-sitemap-xsl=' . $name, 'top' );
183 + if ( $rewrite ) {
184 + Yoast_Dynamic_Rewrites::instance()->add_rule( $rewrite, 'index.php?yoast-sitemap-xsl=' . $name, 'top' );
178 185 }
179 186 }
180 187
181 188 /**
@@ -182,12 +189,14 @@
182 189 * Set the sitemap current page to allow creating partial sitemaps with WP-CLI
183 190 * in a one-off process.
184 191 *
185 192 * @param int $current_page The part that should be generated.
193 + *
194 + * @return void
186 195 */
187 196 public function set_n( $current_page ) {
188 - if ( is_scalar( $current_page ) && intval( $current_page ) > 0 ) {
189 - $this->current_page = intval( $current_page );
197 + if ( is_scalar( $current_page ) && (int) $current_page > 0 ) {
198 + $this->current_page = (int) $current_page;
190 199 }
191 200 }
192 201
193 202 /**
@@ -193,8 +202,10 @@
193 202 /**
194 203 * Set the sitemap content to display after you have generated it.
195 204 *
196 205 * @param string $sitemap The generated sitemap to output.
206 + *
207 + * @return void
197 208 */
198 209 public function set_sitemap( $sitemap ) {
199 210 $this->sitemap = $sitemap;
200 211 }
@@ -202,8 +213,10 @@
202 213 /**
203 214 * Set as true to make the request 404. Used stop the display of empty sitemaps or invalid requests.
204 215 *
205 216 * @param bool $is_bad Is this a bad request. True or false.
217 + *
218 + * @return void
206 219 */
207 220 public function set_bad_sitemap( $is_bad ) {
208 221 $this->bad_sitemap = (bool) $is_bad;
209 222 }
@@ -211,18 +224,22 @@
211 224 /**
212 225 * Prevent stupid plugins from running shutdown scripts when we're obviously not outputting HTML.
213 226 *
214 227 * @since 1.4.16
228 + *
229 + * @return void
215 230 */
216 231 public function sitemap_close() {
217 232 remove_all_actions( 'wp_footer' );
218 - die();
233 + exit();
219 234 }
220 235
221 236 /**
222 237 * Hijack requests for potential sitemaps and XSL files.
223 238 *
224 - * @param \WP_Query $query Main query instance.
239 + * @param WP_Query $query Main query instance.
240 + *
241 + * @return void
225 242 */
226 243 public function redirect( $query ) {
227 244
228 245 if ( ! $query->is_main_query() ) {
@@ -250,8 +267,13 @@
250 267 if ( empty( $type ) ) {
251 268 return;
252 269 }
253 270
271 + if ( get_query_var( 'sitemap_n' ) === '1' || get_query_var( 'sitemap_n' ) === '0' ) {
272 + wp_safe_redirect( home_url( "/$type-sitemap.xml" ), 301, 'Yoast SEO' );
273 + exit();
274 + }
275 +
254 276 $this->set_n( get_query_var( 'sitemap_n' ) );
255 277
256 278 if ( ! $this->get_sitemap_from_cache( $type, $this->current_page ) ) {
257 279 $this->build_sitemap( $type );
@@ -327,8 +349,10 @@
327 349 *
328 350 * Sets $bad_sitemap if this isn't for the root sitemap, a post type or taxonomy.
329 351 *
330 352 * @param string $type The requested sitemap's identifier.
353 + *
354 + * @return void
331 355 */
332 356 public function build_sitemap( $type ) {
333 357
334 358 /**
@@ -377,8 +401,10 @@
377 401 }
378 402
379 403 /**
380 404 * Build the root sitemap (example.com/sitemap_index.xml) which lists sub-sitemaps for other content types.
405 + *
406 + * @return void
381 407 */
382 408 public function build_root_map() {
383 409
384 410 $links = [];
@@ -410,8 +436,10 @@
410 436 *
411 437 * @since 1.4.13
412 438 *
413 439 * @param string $type Type to output.
440 + *
441 + * @return void
414 442 */
415 443 public function xsl_output( $type ) {
416 444
417 445 if ( $type !== 'main' ) {
@@ -440,8 +468,10 @@
440 468 }
441 469
442 470 /**
443 471 * Spit out the generated sitemap.
472 + *
473 + * @return void
444 474 */
445 475 public function output() {
446 476 $this->send_headers();
447 477 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaping sitemap as either xml or html results in empty document.
@@ -487,9 +517,9 @@
487 517 break;
488 518 }
489 519 }
490 520
491 - if ( is_null( $post_type_dates ) ) {
521 + if ( $post_type_dates === null ) {
492 522
493 523 $post_type_dates = [];
494 524 $post_type_names = WPSEO_Post_Type::get_accessible_post_types();
495 525
@@ -494,19 +524,43 @@
494 524 $post_type_names = WPSEO_Post_Type::get_accessible_post_types();
495 525
496 526 if ( ! empty( $post_type_names ) ) {
497 527 $post_statuses = array_map( 'esc_sql', self::get_post_statuses() );
528 + $replacements = array_merge(
529 + [
530 + 'post_type',
531 + 'post_modified_gmt',
532 + 'date',
533 + $wpdb->posts,
534 + 'post_status',
535 + ],
536 + $post_statuses,
537 + [ 'post_type' ],
538 + array_keys( $post_type_names ),
539 + [
540 + 'post_type',
541 + 'date',
542 + ],
543 + );
498 544
499 - $sql = "
500 - SELECT post_type, MAX(post_modified_gmt) AS date
501 - FROM $wpdb->posts
502 - WHERE post_status IN ('" . implode( "','", $post_statuses ) . "')
503 - AND post_type IN ('" . implode( "','", $post_type_names ) . "')
504 - GROUP BY post_type
505 - ORDER BY date DESC
506 - ";
545 + //phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- We need to use a direct query here.
546 + //phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: No relevant caches.
547 + $dates = $wpdb->get_results(
548 + //phpcs:disable WordPress.DB.PreparedSQLPlaceholders -- %i placeholder is still not recognized.
549 + $wpdb->prepare(
550 + '
551 + SELECT %i, MAX(%i) AS %i
552 + FROM %i
553 + WHERE %i IN (' . implode( ', ', array_fill( 0, count( $post_statuses ), '%s' ) ) . ')
554 + AND %i IN (' . implode( ', ', array_fill( 0, count( $post_type_names ), '%s' ) ) . ')
555 + GROUP BY %i
556 + ORDER BY %i DESC
557 + ',
558 + $replacements,
559 + ),
560 + );
507 561
508 - foreach ( $wpdb->get_results( $sql ) as $obj ) {
562 + foreach ( $dates as $obj ) {
509 563 $post_type_dates[ $obj->post_type ] = $obj->date;
510 564 }
511 565 }
512 566 }
@@ -535,37 +589,8 @@
535 589 return YoastSEO()->helpers->date->format( self::get_last_modified_gmt( $post_types ) );
536 590 }
537 591
538 592 /**
539 - * Notify search engines of the updated sitemap.
540 - *
541 - * @param string|null $url Optional URL to make the ping for.
542 - */
543 - public static function ping_search_engines( $url = null ) {
544 -
545 - /**
546 - * Filter: 'wpseo_allow_xml_sitemap_ping' - Check if pinging is not allowed (allowed by default)
547 - *
548 - * @api boolean $allow_ping The boolean that is set to true by default.
549 - */
550 - if ( apply_filters( 'wpseo_allow_xml_sitemap_ping', true ) === false ) {
551 - return;
552 - }
553 -
554 - if ( get_option( 'blog_public' ) === '0' ) { // Don't ping if blog is not public.
555 - return;
556 - }
557 -
558 - if ( empty( $url ) ) {
559 - $url = rawurlencode( WPSEO_Sitemaps_Router::get_base_url( 'sitemap_index.xml' ) );
560 - }
561 -
562 - // Ping Google and Bing.
563 - wp_remote_get( 'https://www.google.com/ping?sitemap=' . $url, [ 'blocking' => false ] );
564 - wp_remote_get( 'https://www.bing.com/ping?sitemap=' . $url, [ 'blocking' => false ] );
565 - }
566 -
567 - /**
568 593 * Get the maximum number of entries per XML sitemap.
569 594 *
570 595 * @return int The maximum number of entries.
571 596 */
@@ -615,8 +640,10 @@
615 640 }
616 641
617 642 /**
618 643 * Sends all the required HTTP Headers.
644 + *
645 + * @return void
619 646 */
620 647 private function send_headers() {
621 648 if ( headers_sent() ) {
622 649 return;