render();
header( 'Content-Type: application/xml; charset=UTF-8' );
header( 'X-Robots-Tag: noindex, follow', true );
echo $xml; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- render() escapes every value it writes and the result is a complete XML document.
exit;
}
/**
* Print the sitemap discovery link in
.
*
* @return void
*/
public function output_discovery_tag() {
if ( ! ACSSEO_Settings::get( 'sitemap_enabled' ) ) {
return;
}
if ( ! is_front_page() && ! is_home() ) {
return;
}
printf(
'' . "\n",
esc_attr__( 'Sitemap', 'acs-seo-plus' ),
esc_url( self::url() )
);
}
/**
* Build the sitemap, using a one hour cache.
*
* @return string
*/
public function render() {
$cached = get_transient( self::CACHE_KEY );
if ( is_string( $cached ) && '' !== $cached ) {
return $cached;
}
$post_types = (array) ACSSEO_Settings::get( 'sitemap_post_types', array( 'post', 'page' ) );
$allowed = array_keys( ACSSEO_Settings::selectable_post_types() );
$post_types = array_values( array_intersect( $post_types, $allowed ) );
$lines = array();
$lines[] = '';
$lines[] = '';
$lines[] = "\t";
$lines[] = "\t\t" . esc_url( home_url( '/' ) ) . '';
$lines[] = "\t\tdaily";
$lines[] = "\t\t1.0";
$lines[] = "\t";
if ( ! empty( $post_types ) ) {
$query = new WP_Query(
array(
'post_type' => $post_types,
'post_status' => 'publish',
'posts_per_page' => 2000,
'orderby' => 'modified',
'order' => 'DESC',
'ignore_sticky_posts' => true,
'no_found_rows' => true,
'update_post_term_cache' => false,
'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- the result is cached for an hour and the sitemap has to skip entries the author marked noindex.
'relation' => 'OR',
array(
'key' => '_acsseo_noindex',
'compare' => 'NOT EXISTS',
),
array(
'key' => '_acsseo_noindex',
'value' => '1',
'compare' => '!=',
),
),
)
);
$front_page_id = ( 'page' === get_option( 'show_on_front' ) ) ? (int) get_option( 'page_on_front' ) : 0;
foreach ( $query->posts as $post ) {
// The home address is already listed first, so a static front
// page is not listed a second time.
if ( $front_page_id && (int) $post->ID === $front_page_id ) {
continue;
}
$permalink = get_permalink( $post );
if ( ! $permalink ) {
continue;
}
$modified = get_post_modified_time( DATE_W3C, true, $post );
$lines[] = "\t";
$lines[] = "\t\t" . esc_url( $permalink ) . '';
if ( $modified ) {
$lines[] = "\t\t" . esc_html( $modified ) . '';
}
$lines[] = "\t\t" . esc_html( $this->changefreq_for( $post ) ) . '';
$lines[] = "\t\t" . esc_html( $this->priority_for( $post ) ) . '';
$lines[] = "\t";
}
wp_reset_postdata();
}
$lines[] = '';
$xml = implode( "\n", $lines ) . "\n";
set_transient( self::CACHE_KEY, $xml, HOUR_IN_SECONDS );
return $xml;
}
/**
* Suggested crawl frequency, based on how recent the entry is.
*
* @param WP_Post $post Post object.
* @return string
*/
private function changefreq_for( $post ) {
$age_in_days = ( time() - (int) get_post_time( 'U', true, $post ) ) / DAY_IN_SECONDS;
return $age_in_days < 180 ? 'weekly' : 'monthly';
}
/**
* Suggested priority, based on how recent the entry is.
*
* @param WP_Post $post Post object.
* @return string
*/
private function priority_for( $post ) {
$age_in_days = ( time() - (int) get_post_time( 'U', true, $post ) ) / DAY_IN_SECONDS;
if ( $age_in_days < 30 ) {
return '0.9';
}
if ( $age_in_days < 180 ) {
return '0.8';
}
return '0.7';
}
/**
* Drop the cached sitemap.
*
* @return void
*/
public function clear_cache() {
delete_transient( self::CACHE_KEY );
}
}