123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- <?php
- /**
- * Sitemaps: WP_Sitemaps class
- *
- * This is the main class integrating all other classes.
- *
- * @package WordPress
- * @subpackage Sitemaps
- * @since 5.5.0
- */
- /**
- * Class WP_Sitemaps.
- *
- * @since 5.5.0
- */
- #[AllowDynamicProperties]
- class WP_Sitemaps {
- /**
- * The main index of supported sitemaps.
- *
- * @since 5.5.0
- *
- * @var WP_Sitemaps_Index
- */
- public $index;
- /**
- * The main registry of supported sitemaps.
- *
- * @since 5.5.0
- *
- * @var WP_Sitemaps_Registry
- */
- public $registry;
- /**
- * An instance of the renderer class.
- *
- * @since 5.5.0
- *
- * @var WP_Sitemaps_Renderer
- */
- public $renderer;
- /**
- * WP_Sitemaps constructor.
- *
- * @since 5.5.0
- */
- public function __construct() {
- $this->registry = new WP_Sitemaps_Registry();
- $this->renderer = new WP_Sitemaps_Renderer();
- $this->index = new WP_Sitemaps_Index( $this->registry );
- }
- /**
- * Initiates all sitemap functionality.
- *
- * If sitemaps are disabled, only the rewrite rules will be registered
- * by this method, in order to properly send 404s.
- *
- * @since 5.5.0
- */
- public function init() {
- // These will all fire on the init hook.
- $this->register_rewrites();
- add_action( 'template_redirect', array( $this, 'render_sitemaps' ) );
- if ( ! $this->sitemaps_enabled() ) {
- return;
- }
- $this->register_sitemaps();
- // Add additional action callbacks.
- add_filter( 'pre_handle_404', array( $this, 'redirect_sitemapxml' ), 10, 2 );
- add_filter( 'robots_txt', array( $this, 'add_robots' ), 0, 2 );
- }
- /**
- * Determines whether sitemaps are enabled or not.
- *
- * @since 5.5.0
- *
- * @return bool Whether sitemaps are enabled.
- */
- public function sitemaps_enabled() {
- $is_enabled = (bool) get_option( 'blog_public' );
- /**
- * Filters whether XML Sitemaps are enabled or not.
- *
- * When XML Sitemaps are disabled via this filter, rewrite rules are still
- * in place to ensure a 404 is returned.
- *
- * @see WP_Sitemaps::register_rewrites()
- *
- * @since 5.5.0
- *
- * @param bool $is_enabled Whether XML Sitemaps are enabled or not. Defaults
- * to true for public sites.
- */
- return (bool) apply_filters( 'wp_sitemaps_enabled', $is_enabled );
- }
- /**
- * Registers and sets up the functionality for all supported sitemaps.
- *
- * @since 5.5.0
- */
- public function register_sitemaps() {
- $providers = array(
- 'posts' => new WP_Sitemaps_Posts(),
- 'taxonomies' => new WP_Sitemaps_Taxonomies(),
- 'users' => new WP_Sitemaps_Users(),
- );
- /* @var WP_Sitemaps_Provider $provider */
- foreach ( $providers as $name => $provider ) {
- $this->registry->add_provider( $name, $provider );
- }
- }
- /**
- * Registers sitemap rewrite tags and routing rules.
- *
- * @since 5.5.0
- */
- public function register_rewrites() {
- // Add rewrite tags.
- add_rewrite_tag( '%sitemap%', '([^?]+)' );
- add_rewrite_tag( '%sitemap-subtype%', '([^?]+)' );
- // Register index route.
- add_rewrite_rule( '^wp-sitemap\.xml$', 'index.php?sitemap=index', 'top' );
- // Register rewrites for the XSL stylesheet.
- add_rewrite_tag( '%sitemap-stylesheet%', '([^?]+)' );
- add_rewrite_rule( '^wp-sitemap\.xsl$', 'index.php?sitemap-stylesheet=sitemap', 'top' );
- add_rewrite_rule( '^wp-sitemap-index\.xsl$', 'index.php?sitemap-stylesheet=index', 'top' );
- // Register routes for providers.
- add_rewrite_rule(
- '^wp-sitemap-([a-z]+?)-([a-z\d_-]+?)-(\d+?)\.xml$',
- 'index.php?sitemap=$matches[1]&sitemap-subtype=$matches[2]&paged=$matches[3]',
- 'top'
- );
- add_rewrite_rule(
- '^wp-sitemap-([a-z]+?)-(\d+?)\.xml$',
- 'index.php?sitemap=$matches[1]&paged=$matches[2]',
- 'top'
- );
- }
- /**
- * Renders sitemap templates based on rewrite rules.
- *
- * @since 5.5.0
- *
- * @global WP_Query $wp_query WordPress Query object.
- */
- public function render_sitemaps() {
- global $wp_query;
- $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' ) );
- // Bail early if this isn't a sitemap or stylesheet route.
- if ( ! ( $sitemap || $stylesheet_type ) ) {
- return;
- }
- if ( ! $this->sitemaps_enabled() ) {
- $wp_query->set_404();
- status_header( 404 );
- return;
- }
- // Render stylesheet if this is stylesheet route.
- if ( $stylesheet_type ) {
- $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 );
- if ( ! $provider ) {
- 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 ) ) {
- $wp_query->set_404();
- status_header( 404 );
- return;
- }
- $this->renderer->render_sitemap( $url_list );
- exit;
- }
- /**
- * Redirects a URL to the wp-sitemap.xml
- *
- * @since 5.5.0
- *
- * @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 ) {
- // 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 $public Whether the site is public.
- * @return string The robots.txt output.
- */
- public function add_robots( $output, $public ) {
- if ( $public ) {
- $output .= "\nSitemap: " . esc_url( $this->index->get_index_url() ) . "\n";
- }
- return $output;
- }
- }
|