Merged in feature/314-dev-dev01 (pull request #24)
auto-patch 314-dev-dev01-2024-01-25T04_09_02 * auto-patch 314-dev-dev01-2024-01-25T04_09_02
This commit is contained in:
@@ -115,32 +115,7 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider {
|
||||
$all_dates = [];
|
||||
|
||||
if ( $max_pages > 1 ) {
|
||||
$post_statuses = array_map( 'esc_sql', WPSEO_Sitemaps::get_post_statuses( $post_type ) );
|
||||
|
||||
if ( version_compare( $wpdb->db_version(), '8.0', '>=' ) ) {
|
||||
$sql = "
|
||||
WITH ordering AS (SELECT ROW_NUMBER() OVER (ORDER BY post_modified_gmt) AS n, post_modified_gmt
|
||||
FROM {$wpdb->posts} USE INDEX ( type_status_date )
|
||||
WHERE post_status IN ('" . implode( "','", $post_statuses ) . "')
|
||||
AND post_type = %s
|
||||
ORDER BY post_modified_gmt)
|
||||
SELECT post_modified_gmt
|
||||
FROM ordering
|
||||
WHERE MOD(n, %d) = 0;";
|
||||
}
|
||||
else {
|
||||
$sql = "
|
||||
SELECT post_modified_gmt
|
||||
FROM ( SELECT @rownum:=0 ) init
|
||||
JOIN {$wpdb->posts} USE INDEX( type_status_date )
|
||||
WHERE post_status IN ('" . implode( "','", $post_statuses ) . "')
|
||||
AND post_type = %s
|
||||
AND ( @rownum:=@rownum+1 ) %% %d = 0
|
||||
ORDER BY post_modified_gmt ASC
|
||||
";
|
||||
}
|
||||
|
||||
$all_dates = $wpdb->get_col( $wpdb->prepare( $sql, $post_type, $max_entries ) );
|
||||
$all_dates = version_compare( $wpdb->db_version(), '8.0', '>=' ) ? $this->get_all_dates_using_with_clause( $post_type, $max_entries ) : $this->get_all_dates( $post_type, $max_entries );
|
||||
}
|
||||
|
||||
for ( $page_counter = 0; $page_counter < $max_pages; $page_counter++ ) {
|
||||
@@ -175,8 +150,9 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider {
|
||||
* @param int $max_entries Entries per sitemap.
|
||||
* @param int $current_page Current page of the sitemap.
|
||||
*
|
||||
* @throws OutOfBoundsException When an invalid page is requested.
|
||||
* @return array
|
||||
*
|
||||
* @throws OutOfBoundsException When an invalid page is requested.
|
||||
*/
|
||||
public function get_sitemap_links( $type, $max_entries, $current_page ) {
|
||||
|
||||
@@ -262,6 +238,8 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider {
|
||||
* Check for relevant post type before invalidation.
|
||||
*
|
||||
* @param int $post_id Post ID to possibly invalidate for.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function save_post( $post_id ) {
|
||||
|
||||
@@ -313,7 +291,7 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider {
|
||||
/**
|
||||
* Filter: 'wpseo_exclude_from_sitemap_by_post_ids' - Allow extending and modifying the posts to exclude.
|
||||
*
|
||||
* @api array $posts_to_exclude The posts to exclude.
|
||||
* @param array $posts_to_exclude The posts to exclude.
|
||||
*/
|
||||
$excluded_posts_ids = apply_filters( 'wpseo_exclude_from_sitemap_by_post_ids', $excluded_posts_ids );
|
||||
if ( ! is_array( $excluded_posts_ids ) ) {
|
||||
@@ -401,6 +379,19 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider {
|
||||
$front_page['chf'] = 'daily';
|
||||
$front_page['pri'] = 1;
|
||||
|
||||
$images = [];
|
||||
|
||||
/**
|
||||
* Filter images to be included for the term in XML sitemap.
|
||||
*
|
||||
* @param array $images Array of image items.
|
||||
* @return array $image_list Array of image items.
|
||||
*/
|
||||
$image_list = apply_filters( 'wpseo_sitemap_urlimages_front_page', $images );
|
||||
if ( isset( $image_list ) && is_array( $image_list ) ) {
|
||||
$front_page['images'] = $image_list;
|
||||
}
|
||||
|
||||
$links[] = $front_page;
|
||||
}
|
||||
elseif ( $post_type !== 'page' ) {
|
||||
@@ -675,4 +666,101 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider {
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all dates for a post type by using the WITH clause for performance.
|
||||
*
|
||||
* @param string $post_type Post type to retrieve dates for.
|
||||
* @param int $max_entries Maximum number of entries to retrieve.
|
||||
*
|
||||
* @return array Array of dates.
|
||||
*/
|
||||
private function get_all_dates_using_with_clause( $post_type, $max_entries ) {
|
||||
global $wpdb;
|
||||
|
||||
$post_statuses = array_map( 'esc_sql', WPSEO_Sitemaps::get_post_statuses( $post_type ) );
|
||||
|
||||
$replacements = array_merge(
|
||||
[
|
||||
'ordering',
|
||||
'post_modified_gmt',
|
||||
$wpdb->posts,
|
||||
'type_status_date',
|
||||
'post_status',
|
||||
],
|
||||
$post_statuses,
|
||||
[
|
||||
'post_type',
|
||||
$post_type,
|
||||
'post_modified_gmt',
|
||||
'post_modified_gmt',
|
||||
'ordering',
|
||||
$max_entries,
|
||||
]
|
||||
);
|
||||
|
||||
//phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- We need to use a direct query here.
|
||||
//phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: No relevant caches.
|
||||
return $wpdb->get_col(
|
||||
//phpcs:disable WordPress.DB.PreparedSQLPlaceholders -- %i placeholder is still not recognized.
|
||||
$wpdb->prepare(
|
||||
'
|
||||
WITH %i AS (SELECT ROW_NUMBER() OVER (ORDER BY %i) AS n, post_modified_gmt
|
||||
FROM %i USE INDEX ( %i )
|
||||
WHERE %i IN (' . implode( ', ', array_fill( 0, count( $post_statuses ), '%s' ) ) . ')
|
||||
AND %i = %s
|
||||
ORDER BY %i)
|
||||
SELECT %i
|
||||
FROM %i
|
||||
WHERE MOD(n, %d) = 0;
|
||||
',
|
||||
$replacements
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all dates for a post type.
|
||||
*
|
||||
* @param string $post_type Post type to retrieve dates for.
|
||||
* @param int $max_entries Maximum number of entries to retrieve.
|
||||
*
|
||||
* @return array Array of dates.
|
||||
*/
|
||||
private function get_all_dates( $post_type, $max_entries ) {
|
||||
global $wpdb;
|
||||
|
||||
$post_statuses = array_map( 'esc_sql', WPSEO_Sitemaps::get_post_statuses( $post_type ) );
|
||||
$replacements = array_merge(
|
||||
[
|
||||
'post_modified_gmt',
|
||||
$wpdb->posts,
|
||||
'type_status_date',
|
||||
'post_status',
|
||||
],
|
||||
$post_statuses,
|
||||
[
|
||||
'post_type',
|
||||
$post_type,
|
||||
$max_entries,
|
||||
'post_modified_gmt',
|
||||
]
|
||||
);
|
||||
|
||||
return $wpdb->get_col(
|
||||
//phpcs:disable WordPress.DB.PreparedSQLPlaceholders -- %i placeholder is still not recognized.
|
||||
$wpdb->prepare(
|
||||
'
|
||||
SELECT %i
|
||||
FROM ( SELECT @rownum:=0 ) init
|
||||
JOIN %i USE INDEX( %i )
|
||||
WHERE %i IN (' . implode( ', ', array_fill( 0, count( $post_statuses ), '%s' ) ) . ')
|
||||
AND %i = %s
|
||||
AND ( @rownum:=@rownum+1 ) %% %d = 0
|
||||
ORDER BY %i ASC
|
||||
',
|
||||
$replacements
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ class WPSEO_Sitemap_Cache_Data implements Serializable, WPSEO_Sitemap_Cache_Data
|
||||
* Set the sitemap XML data
|
||||
*
|
||||
* @param string $sitemap XML Content of the sitemap.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_sitemap( $sitemap ) {
|
||||
|
||||
|
||||
@@ -124,7 +124,10 @@ class WPSEO_Sitemap_Image_Parser {
|
||||
* @param array $images Array of image items.
|
||||
* @param int $post_id ID of the post.
|
||||
*/
|
||||
$images = apply_filters( 'wpseo_sitemap_urlimages', $images, $post->ID );
|
||||
$image_list = apply_filters( 'wpseo_sitemap_urlimages', $images, $post->ID );
|
||||
if ( isset( $image_list ) && is_array( $image_list ) ) {
|
||||
$images = $image_list;
|
||||
}
|
||||
|
||||
return $images;
|
||||
}
|
||||
@@ -147,6 +150,17 @@ class WPSEO_Sitemap_Image_Parser {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter images to be included for the term in XML sitemap.
|
||||
*
|
||||
* @param array $image_list Array of image items.
|
||||
* @param int $term_id ID of the post.
|
||||
*/
|
||||
$image_list = apply_filters( 'wpseo_sitemap_urlimages_term', $images, $term->term_id );
|
||||
if ( isset( $image_list ) && is_array( $image_list ) ) {
|
||||
$images = $image_list;
|
||||
}
|
||||
|
||||
return $images;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,9 +33,11 @@ class WPSEO_Sitemaps_Admin {
|
||||
* if the post is being published, is a post type that a sitemap is built for
|
||||
* and is a post that is included in sitemaps.
|
||||
*
|
||||
* @param string $new_status New post status.
|
||||
* @param string $old_status Old post status.
|
||||
* @param \WP_Post $post Post object.
|
||||
* @param string $new_status New post status.
|
||||
* @param string $old_status Old post status.
|
||||
* @param WP_Post $post Post object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function status_transition( $new_status, $old_status, $post ) {
|
||||
if ( $new_status !== 'publish' ) {
|
||||
@@ -71,6 +73,8 @@ class WPSEO_Sitemaps_Admin {
|
||||
|
||||
/**
|
||||
* Notify Google of the updated sitemap.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function ping_search_engines() {
|
||||
|
||||
@@ -81,7 +85,7 @@ class WPSEO_Sitemaps_Admin {
|
||||
/**
|
||||
* Filter: 'wpseo_allow_xml_sitemap_ping' - Check if pinging is not allowed (allowed by default).
|
||||
*
|
||||
* @api boolean $allow_ping The boolean that is set to true by default.
|
||||
* @param bool $allow_ping The boolean that is set to true by default.
|
||||
*/
|
||||
if ( apply_filters( 'wpseo_allow_xml_sitemap_ping', true ) === false ) {
|
||||
return;
|
||||
@@ -103,9 +107,11 @@ class WPSEO_Sitemaps_Admin {
|
||||
* When importing is done, if we have a post_type that is saved in the sitemap
|
||||
* try to ping the search engines.
|
||||
*
|
||||
* @param string $new_status New post status.
|
||||
* @param string $old_status Old post status.
|
||||
* @param \WP_Post $post Post object.
|
||||
* @param string $new_status New post status.
|
||||
* @param string $old_status Old post status.
|
||||
* @param WP_Post $post Post object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function status_transition_bulk( $new_status, $old_status, $post ) {
|
||||
$this->importing_post_types[] = get_post_type( $post );
|
||||
@@ -114,6 +120,8 @@ class WPSEO_Sitemaps_Admin {
|
||||
|
||||
/**
|
||||
* After import finished, walk through imported post_types and update info.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function status_transition_bulk_finished() {
|
||||
if ( ! defined( 'WP_IMPORTING' ) ) {
|
||||
|
||||
@@ -17,21 +17,21 @@ class WPSEO_Sitemaps_Cache_Validator {
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const STORAGE_KEY_PREFIX = 'yst_sm_';
|
||||
public const STORAGE_KEY_PREFIX = 'yst_sm_';
|
||||
|
||||
/**
|
||||
* Name of the option that holds the global validation value.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VALIDATION_GLOBAL_KEY = 'wpseo_sitemap_cache_validator_global';
|
||||
public const VALIDATION_GLOBAL_KEY = 'wpseo_sitemap_cache_validator_global';
|
||||
|
||||
/**
|
||||
* The format which creates the key of the option that holds the type validation value.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VALIDATION_TYPE_KEY_FORMAT = 'wpseo_sitemap_%s_cache_validator';
|
||||
public const VALIDATION_TYPE_KEY_FORMAT = 'wpseo_sitemap_%s_cache_validator';
|
||||
|
||||
/**
|
||||
* Get the cache key for a certain type and page.
|
||||
@@ -189,8 +189,15 @@ class WPSEO_Sitemaps_Cache_Validator {
|
||||
$where[] = sprintf( "option_name LIKE '%s'", addcslashes( '_transient_timeout_' . $like, '_' ) );
|
||||
|
||||
// Delete transients.
|
||||
$query = sprintf( 'DELETE FROM %1$s WHERE %2$s', $wpdb->options, implode( ' OR ', $where ) );
|
||||
$wpdb->query( $query );
|
||||
//phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- We need to use a direct query here.
|
||||
//phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: No relevant caches.
|
||||
$wpdb->query(
|
||||
$wpdb->prepare(
|
||||
//phpcs:disable WordPress.DB.PreparedSQLPlaceholders -- %i placeholder is still not recognized.
|
||||
'DELETE FROM %i WHERE ' . implode( ' OR', array_fill( 0, count( $where ), '%s' ) ),
|
||||
array_merge( [ $wpdb->options ], $where )
|
||||
)
|
||||
);
|
||||
|
||||
wp_cache_delete( 'alloptions', 'options' );
|
||||
}
|
||||
|
||||
@@ -47,22 +47,24 @@ class WPSEO_Sitemaps_Cache {
|
||||
|
||||
add_action( 'init', [ $this, 'init' ] );
|
||||
|
||||
add_action( 'deleted_term_relationships', [ __CLASS__, 'invalidate' ] );
|
||||
add_action( 'deleted_term_relationships', [ self::class, 'invalidate' ] );
|
||||
|
||||
add_action( 'update_option', [ __CLASS__, 'clear_on_option_update' ] );
|
||||
add_action( 'update_option', [ self::class, 'clear_on_option_update' ] );
|
||||
|
||||
add_action( 'edited_terms', [ __CLASS__, 'invalidate_helper' ], 10, 2 );
|
||||
add_action( 'clean_term_cache', [ __CLASS__, 'invalidate_helper' ], 10, 2 );
|
||||
add_action( 'clean_object_term_cache', [ __CLASS__, 'invalidate_helper' ], 10, 2 );
|
||||
add_action( 'edited_terms', [ self::class, 'invalidate_helper' ], 10, 2 );
|
||||
add_action( 'clean_term_cache', [ self::class, 'invalidate_helper' ], 10, 2 );
|
||||
add_action( 'clean_object_term_cache', [ self::class, 'invalidate_helper' ], 10, 2 );
|
||||
|
||||
add_action( 'user_register', [ __CLASS__, 'invalidate_author' ] );
|
||||
add_action( 'delete_user', [ __CLASS__, 'invalidate_author' ] );
|
||||
add_action( 'user_register', [ self::class, 'invalidate_author' ] );
|
||||
add_action( 'delete_user', [ self::class, 'invalidate_author' ] );
|
||||
|
||||
add_action( 'shutdown', [ __CLASS__, 'clear_queued' ] );
|
||||
add_action( 'shutdown', [ self::class, 'clear_queued' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup context for static calls.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
@@ -294,6 +296,8 @@ class WPSEO_Sitemaps_Cache {
|
||||
|
||||
/**
|
||||
* Invalidate storage for cache types queued to clear.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function clear_queued() {
|
||||
|
||||
@@ -320,6 +324,8 @@ class WPSEO_Sitemaps_Cache {
|
||||
*
|
||||
* @param string $option Option name.
|
||||
* @param string $type Sitemap type.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function register_clear_on_option_update( $option, $type = '' ) {
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ class WPSEO_Sitemaps_Renderer {
|
||||
/**
|
||||
* Filters the `urlset` for a sitemap by type.
|
||||
*
|
||||
* @api string $urlset The output for the sitemap's `urlset`.
|
||||
* @param string $urlset The output for the sitemap's `urlset`.
|
||||
*/
|
||||
$xml = apply_filters( "wpseo_sitemap_{$type}_urlset", $urlset );
|
||||
|
||||
@@ -166,6 +166,8 @@ class WPSEO_Sitemaps_Renderer {
|
||||
* Set a custom stylesheet for this sitemap. Set to empty to just remove the default stylesheet.
|
||||
*
|
||||
* @param string $stylesheet Full XML-stylesheet declaration.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_stylesheet( $stylesheet ) {
|
||||
$this->stylesheet = $stylesheet;
|
||||
@@ -239,9 +241,8 @@ class WPSEO_Sitemaps_Renderer {
|
||||
/**
|
||||
* Filters the output for the sitemap URL tag.
|
||||
*
|
||||
* @api string $output The output for the sitemap url tag.
|
||||
*
|
||||
* @param array $url The sitemap URL array on which the output is based.
|
||||
* @param string $output The output for the sitemap url tag.
|
||||
* @param array $url The sitemap URL array on which the output is based.
|
||||
*/
|
||||
return apply_filters( 'wpseo_sitemap_url', $output, $url );
|
||||
}
|
||||
|
||||
@@ -21,24 +21,51 @@ class WPSEO_Sitemaps_Router {
|
||||
return;
|
||||
}
|
||||
|
||||
add_action( 'init', [ $this, 'init' ], 1 );
|
||||
add_action( 'yoast_add_dynamic_rewrite_rules', [ $this, 'add_rewrite_rules' ] );
|
||||
add_filter( 'query_vars', [ $this, 'add_query_vars' ] );
|
||||
|
||||
add_filter( 'redirect_canonical', [ $this, 'redirect_canonical' ] );
|
||||
add_action( 'template_redirect', [ $this, 'template_redirect' ], 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds rewrite routes for sitemaps.
|
||||
*
|
||||
* @param Yoast_Dynamic_Rewrites $dynamic_rewrites Dynamic rewrites handler instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_rewrite_rules( $dynamic_rewrites ) {
|
||||
$dynamic_rewrites->add_rule( 'sitemap_index\.xml$', 'index.php?sitemap=1', 'top' );
|
||||
$dynamic_rewrites->add_rule( '([^/]+?)-sitemap([0-9]+)?\.xml$', 'index.php?sitemap=$matches[1]&sitemap_n=$matches[2]', 'top' );
|
||||
$dynamic_rewrites->add_rule( '([a-z]+)?-?sitemap\.xsl$', 'index.php?yoast-sitemap-xsl=$matches[1]', 'top' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds query variables for sitemaps.
|
||||
*
|
||||
* @param array $query_vars List of query variables to filter.
|
||||
*
|
||||
* @return array Filtered query variables.
|
||||
*/
|
||||
public function add_query_vars( $query_vars ) {
|
||||
$query_vars[] = 'sitemap';
|
||||
$query_vars[] = 'sitemap_n';
|
||||
$query_vars[] = 'yoast-sitemap-xsl';
|
||||
|
||||
return $query_vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up rewrite rules.
|
||||
*
|
||||
* @deprecated 21.8
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function init() {
|
||||
global $wp;
|
||||
|
||||
$wp->add_query_var( 'sitemap' );
|
||||
$wp->add_query_var( 'sitemap_n' );
|
||||
$wp->add_query_var( 'yoast-sitemap-xsl' );
|
||||
|
||||
add_rewrite_rule( 'sitemap_index\.xml$', 'index.php?sitemap=1', 'top' );
|
||||
add_rewrite_rule( '([^/]+?)-sitemap([0-9]+)?\.xml$', 'index.php?sitemap=$matches[1]&sitemap_n=$matches[2]', 'top' );
|
||||
add_rewrite_rule( '([a-z]+)?-?sitemap\.xsl$', 'index.php?yoast-sitemap-xsl=$matches[1]', 'top' );
|
||||
_deprecated_function( __METHOD__, 'Yoast SEO 21.8' );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,14 +86,15 @@ class WPSEO_Sitemaps_Router {
|
||||
|
||||
/**
|
||||
* Redirects sitemap.xml to sitemap_index.xml.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function template_redirect() {
|
||||
if ( ! $this->needs_sitemap_index_redirect() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_safe_redirect( home_url( '/sitemap_index.xml' ), 301, 'Yoast SEO' );
|
||||
exit;
|
||||
YoastSEO()->helpers->redirect->do_safe_redirect( home_url( '/sitemap_index.xml' ), 301, 'Yoast SEO' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ class WPSEO_Sitemaps {
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const SITEMAP_INDEX_TYPE = '1';
|
||||
public const SITEMAP_INDEX_TYPE = '1';
|
||||
|
||||
/**
|
||||
* Content of the sitemap to output.
|
||||
@@ -115,6 +115,8 @@ class WPSEO_Sitemaps {
|
||||
* Initialize sitemap providers classes.
|
||||
*
|
||||
* @since 5.3
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function init_sitemaps_providers() {
|
||||
|
||||
@@ -135,6 +137,8 @@ class WPSEO_Sitemaps {
|
||||
|
||||
/**
|
||||
* Check the current request URI, if we can determine it's probably an XML sitemap, kill loading the widgets.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function reduce_query_load() {
|
||||
if ( ! isset( $_SERVER['REQUEST_URI'] ) ) {
|
||||
@@ -153,11 +157,13 @@ class WPSEO_Sitemaps {
|
||||
* @param string $name The name of the sitemap.
|
||||
* @param callback $building_function Function to build your sitemap.
|
||||
* @param string $rewrite Optional. Regular expression to match your sitemap with.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_sitemap( $name, $building_function, $rewrite = '' ) {
|
||||
add_action( 'wpseo_do_sitemap_' . $name, $building_function );
|
||||
if ( ! empty( $rewrite ) ) {
|
||||
add_rewrite_rule( $rewrite, 'index.php?sitemap=' . $name, 'top' );
|
||||
if ( $rewrite ) {
|
||||
Yoast_Dynamic_Rewrites::instance()->add_rule( $rewrite, 'index.php?sitemap=' . $name, 'top' );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,11 +175,13 @@ class WPSEO_Sitemaps {
|
||||
* @param string $name The name of the XSL file.
|
||||
* @param callback $building_function Function to build your XSL file.
|
||||
* @param string $rewrite Optional. Regular expression to match your sitemap with.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_xsl( $name, $building_function, $rewrite = '' ) {
|
||||
add_action( 'wpseo_xsl_' . $name, $building_function );
|
||||
if ( ! empty( $rewrite ) ) {
|
||||
add_rewrite_rule( $rewrite, 'index.php?yoast-sitemap-xsl=' . $name, 'top' );
|
||||
if ( $rewrite ) {
|
||||
Yoast_Dynamic_Rewrites::instance()->add_rule( $rewrite, 'index.php?yoast-sitemap-xsl=' . $name, 'top' );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +190,8 @@ class WPSEO_Sitemaps {
|
||||
* in a one-off process.
|
||||
*
|
||||
* @param int $current_page The part that should be generated.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_n( $current_page ) {
|
||||
if ( is_scalar( $current_page ) && intval( $current_page ) > 0 ) {
|
||||
@@ -193,6 +203,8 @@ class WPSEO_Sitemaps {
|
||||
* Set the sitemap content to display after you have generated it.
|
||||
*
|
||||
* @param string $sitemap The generated sitemap to output.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_sitemap( $sitemap ) {
|
||||
$this->sitemap = $sitemap;
|
||||
@@ -202,6 +214,8 @@ class WPSEO_Sitemaps {
|
||||
* Set as true to make the request 404. Used stop the display of empty sitemaps or invalid requests.
|
||||
*
|
||||
* @param bool $is_bad Is this a bad request. True or false.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_bad_sitemap( $is_bad ) {
|
||||
$this->bad_sitemap = (bool) $is_bad;
|
||||
@@ -211,6 +225,8 @@ class WPSEO_Sitemaps {
|
||||
* Prevent stupid plugins from running shutdown scripts when we're obviously not outputting HTML.
|
||||
*
|
||||
* @since 1.4.16
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sitemap_close() {
|
||||
remove_all_actions( 'wp_footer' );
|
||||
@@ -220,7 +236,9 @@ class WPSEO_Sitemaps {
|
||||
/**
|
||||
* Hijack requests for potential sitemaps and XSL files.
|
||||
*
|
||||
* @param \WP_Query $query Main query instance.
|
||||
* @param WP_Query $query Main query instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function redirect( $query ) {
|
||||
|
||||
@@ -332,6 +350,8 @@ class WPSEO_Sitemaps {
|
||||
* Sets $bad_sitemap if this isn't for the root sitemap, a post type or taxonomy.
|
||||
*
|
||||
* @param string $type The requested sitemap's identifier.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function build_sitemap( $type ) {
|
||||
|
||||
@@ -382,6 +402,8 @@ class WPSEO_Sitemaps {
|
||||
|
||||
/**
|
||||
* Build the root sitemap (example.com/sitemap_index.xml) which lists sub-sitemaps for other content types.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function build_root_map() {
|
||||
|
||||
@@ -415,6 +437,8 @@ class WPSEO_Sitemaps {
|
||||
* @since 1.4.13
|
||||
*
|
||||
* @param string $type Type to output.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function xsl_output( $type ) {
|
||||
|
||||
@@ -445,6 +469,8 @@ class WPSEO_Sitemaps {
|
||||
|
||||
/**
|
||||
* Spit out the generated sitemap.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function output() {
|
||||
$this->send_headers();
|
||||
@@ -499,18 +525,41 @@ class WPSEO_Sitemaps {
|
||||
|
||||
if ( ! empty( $post_type_names ) ) {
|
||||
$post_statuses = array_map( 'esc_sql', self::get_post_statuses() );
|
||||
$replacements = array_merge(
|
||||
[
|
||||
'post_type',
|
||||
'post_modified_gmt',
|
||||
'date',
|
||||
$wpdb->posts,
|
||||
'post_status',
|
||||
],
|
||||
$post_statuses,
|
||||
[ 'post_type' ],
|
||||
array_keys( $post_type_names ),
|
||||
[
|
||||
'post_type',
|
||||
'date',
|
||||
]
|
||||
);
|
||||
|
||||
$sql = "
|
||||
SELECT post_type, MAX(post_modified_gmt) AS date
|
||||
FROM $wpdb->posts
|
||||
WHERE post_status IN ('" . implode( "','", $post_statuses ) . "')
|
||||
AND post_type IN ('" . implode( "','", $post_type_names ) . "')
|
||||
GROUP BY post_type
|
||||
ORDER BY date DESC
|
||||
";
|
||||
//phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- We need to use a direct query here.
|
||||
//phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: No relevant caches.
|
||||
$dates = $wpdb->get_results(
|
||||
//phpcs:disable WordPress.DB.PreparedSQLPlaceholders -- %i placeholder is still not recognized.
|
||||
$wpdb->prepare(
|
||||
'
|
||||
SELECT %i, MAX(%i) AS %i
|
||||
FROM %i
|
||||
WHERE %i IN (' . implode( ', ', array_fill( 0, count( $post_statuses ), '%s' ) ) . ')
|
||||
AND %i IN (' . implode( ', ', array_fill( 0, count( $post_type_names ), '%s' ) ) . ')
|
||||
GROUP BY %i
|
||||
ORDER BY %i DESC
|
||||
',
|
||||
$replacements
|
||||
)
|
||||
);
|
||||
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery -- They are prepared on the lines above and a direct query is required.
|
||||
foreach ( $wpdb->get_results( $sql ) as $obj ) {
|
||||
foreach ( $dates as $obj ) {
|
||||
$post_type_dates[ $obj->post_type ] = $obj->date;
|
||||
}
|
||||
}
|
||||
@@ -592,6 +641,8 @@ class WPSEO_Sitemaps {
|
||||
|
||||
/**
|
||||
* Sends all the required HTTP Headers.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function send_headers() {
|
||||
if ( headers_sent() ) {
|
||||
|
||||
@@ -94,10 +94,11 @@ class WPSEO_Taxonomy_Sitemap_Provider implements WPSEO_Sitemap_Provider {
|
||||
$hide_empty_tax = apply_filters( 'wpseo_sitemap_exclude_empty_terms_taxonomy', $hide_empty, $taxonomy_name );
|
||||
|
||||
$term_args = [
|
||||
'taxonomy' => $taxonomy_name,
|
||||
'hide_empty' => $hide_empty_tax,
|
||||
'fields' => 'ids',
|
||||
];
|
||||
$taxonomy_terms = get_terms( $taxonomy_name, $term_args );
|
||||
$taxonomy_terms = get_terms( $term_args );
|
||||
|
||||
if ( count( $taxonomy_terms ) > 0 ) {
|
||||
$all_taxonomies[ $taxonomy_name ] = $taxonomy_terms;
|
||||
@@ -211,24 +212,28 @@ class WPSEO_Taxonomy_Sitemap_Provider implements WPSEO_Sitemap_Provider {
|
||||
|
||||
$post_statuses = array_map( 'esc_sql', WPSEO_Sitemaps::get_post_statuses() );
|
||||
|
||||
// Grab last modified date.
|
||||
$sql = "
|
||||
SELECT MAX(p.post_modified_gmt) AS lastmod
|
||||
FROM $wpdb->posts AS p
|
||||
INNER JOIN $wpdb->term_relationships AS term_rel
|
||||
ON term_rel.object_id = p.ID
|
||||
INNER JOIN $wpdb->term_taxonomy AS term_tax
|
||||
ON term_tax.term_taxonomy_id = term_rel.term_taxonomy_id
|
||||
AND term_tax.taxonomy = %s
|
||||
AND term_tax.term_id = %d
|
||||
WHERE p.post_status IN ('" . implode( "','", $post_statuses ) . "')
|
||||
AND p.post_password = ''
|
||||
";
|
||||
$replacements = array_merge(
|
||||
[
|
||||
'post_modified_gmt',
|
||||
$wpdb->posts,
|
||||
$wpdb->term_relationships,
|
||||
'object_id',
|
||||
'ID',
|
||||
$wpdb->term_taxonomy,
|
||||
'term_taxonomy_id',
|
||||
'term_taxonomy_id',
|
||||
'taxonomy',
|
||||
'term_id',
|
||||
'post_status',
|
||||
],
|
||||
$post_statuses,
|
||||
[ 'post_password' ]
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter: 'wpseo_exclude_from_sitemap_by_term_ids' - Allow excluding terms by ID.
|
||||
*
|
||||
* @api array $terms_to_exclude The terms to exclude.
|
||||
* @param array $terms_to_exclude The terms to exclude.
|
||||
*/
|
||||
$terms_to_exclude = apply_filters( 'wpseo_exclude_from_sitemap_by_term_ids', [] );
|
||||
|
||||
@@ -253,7 +258,30 @@ class WPSEO_Taxonomy_Sitemap_Provider implements WPSEO_Sitemap_Provider {
|
||||
continue;
|
||||
}
|
||||
|
||||
$url['mod'] = $wpdb->get_var( $wpdb->prepare( $sql, $term->taxonomy, $term->term_id ) );
|
||||
$current_replacements = $replacements;
|
||||
array_splice( $current_replacements, 9, 0, $term->taxonomy );
|
||||
array_splice( $current_replacements, 11, 0, $term->term_id );
|
||||
|
||||
//phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- We need to use a direct query here.
|
||||
//phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: No relevant caches.
|
||||
$url['mod'] = $wpdb->get_var(
|
||||
//phpcs:disable WordPress.DB.PreparedSQLPlaceholders -- %i placeholder is still not recognized.
|
||||
$wpdb->prepare(
|
||||
'
|
||||
SELECT MAX(p.%i) AS lastmod
|
||||
FROM %i AS p
|
||||
INNER JOIN %i AS term_rel
|
||||
ON term_rel.%i = p.%i
|
||||
INNER JOIN %i AS term_tax
|
||||
ON term_tax.%i = term_rel.%i
|
||||
AND term_tax.%i = %s
|
||||
AND term_tax.%i = %d
|
||||
WHERE p.%i IN (' . implode( ', ', array_fill( 0, count( $post_statuses ), '%s' ) ) . ")
|
||||
AND p.%i = ''
|
||||
",
|
||||
$current_replacements
|
||||
)
|
||||
);
|
||||
|
||||
if ( $this->include_images ) {
|
||||
$url['images'] = $this->get_image_parser()->get_term_images( $term );
|
||||
|
||||
@@ -15,21 +15,21 @@ interface WPSEO_Sitemap_Cache_Data_Interface {
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const OK = 'ok';
|
||||
public const OK = 'ok';
|
||||
|
||||
/**
|
||||
* Status for unusable sitemap.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const ERROR = 'error';
|
||||
public const ERROR = 'error';
|
||||
|
||||
/**
|
||||
* Status for unusable sitemap because it cannot be identified.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const UNKNOWN = 'unknown';
|
||||
public const UNKNOWN = 'unknown';
|
||||
|
||||
/**
|
||||
* Set the content of the sitemap.
|
||||
|
||||
Reference in New Issue
Block a user