Как работает Карта сайта WordPress

Ниже подробно рассмотрим как работает карта сайта WordPress. Понимание принципа работы, может упростить некоторые моменты при изменении существующей или создании своей Карты сайта.

Обработка запроса

WP_Sitemaps — это главный класс, который отвечает за:

  • Создание правил перезаписи (ЧПУ). См. WP_Sitemaps::register_rewrites().
  • Обработку запросов:
    • /wp-sitemap.xml или /wp-sitemap-posts-post-1.xml — страницы Карты.
    • wp-sitemap-index.xsl или wp-sitemap.xsl — страницы стилей Карты.
  • Регистрацию провайдеров. Смотрите: WP_Sitemaps::register_sitemaps().
  • Ссылку в файле robots.txt. Смотрите: WP_Sitemaps::add_robots().
  • Обработку редиректов на карту сайта. Так например, можно перейти по URL /sitemap-xml (зависит от ЧПУ ваших постов) и вас перенаправит с 302 кодом на страницу Карты сайта /wp-sitemap.xml.

Инициализируется этот класс функцией wp_sitemaps_get_server() в момент события init:

add_action( 'init', 'wp_sitemaps_get_server' );

// wp_sitemaps_get_server() запускает WP_Sitemaps::init()
$wp_sitemaps = new WP_Sitemaps();
$wp_sitemaps->init();

Функция инициализации WP_Sitemaps::init() выглядит так:

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 );
}

Как мы видим из кода, в момент инициализации создаются правила перезаписи (ЧПУ) и на событие template_redirect вешается метод WP_Sitemaps::render_sitemaps().

Далее, метод render_sitemaps(), проверяет параметры запроса и если это:

  • Какая-либо страница Карты сайта (или стилей карты):
    • Если карта отключена, то ставиться статус ответа 404.
    • Если карта включена, то выводится контент страницы и работа PHP обрывается через exit;.
  • Другая страница, то метод прекращает свою работу.

Выглядит это в коде так:

public function render_sitemaps() {

	$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' ) );

	// не страница карты сайта
	if ( ! ( $sitemap || $stylesheet_type ) ) {
		return;
	}

	// карта отключена
	if ( ! $this->sitemaps_enabled() ) {
		$wp_query->set_404();
		status_header( 404 );
		return;
	}

	// карта включена, выводим контент (Карту xml или Стили карты xls).

	exit;
}

Если карта не отключена и мы посещаем любую другую страницу сайта (не карту), то все равно срабатывает регистрация провайдеров Карты, всегда срабатывает вот этот код из метода init().

    $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 );

Зачем нужны хуки понятно, чтобы отредиректить на карту или если это запрос на robots.txt добавить туда ссылку на карту. Но вот зачем нужна регистранция провайдеров на каждой странице WP на фронте, мне что-то непонятно. Этот момент нужно знать, чтобы не выполнять никакой логики в момент регистрации своего провайдера!

ЧПУ правила для Карты сайта

Выше я упоминал что для Карты сайта создаются свои правила перезаписи, вот так выглядит код метода WP_Sitemaps::register_rewrites():

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'
	);
}

Из кода видно какие вообще параметры запроса могут быть на странице Карты сайта. Это:

// провайдер карты сайта
// posts, taxinomies, users, index - это главная страница
get_query_var( 'sitemap' );

// тип у провайдера: тип записи, название таксономии: post, page, category, post_tag
get_query_var( 'sitemap-subtype' );

// страница пагинации: 1, 2, 3 ...
get_query_var( 'paged' );

// тип стилей: index - стили главной, sitemap - стили карты ссылок
get_query_var( 'sitemap-stylesheet' );

Как работают Стили

Если вы посмотрите на исходный код любой страницы карты, то вы не увидите там стилей, однако браузер отображает карту не как XML код.

Так происходит благодаря этой строке:

<?xml-stylesheet type="text/xsl" href="https://example.com/wp-sitemap-index.xsl" ?>

Она указывает на схему стилей. В этом файле (который генерируется налету) схематически объясняется браузеру как нужно отобразить текущий XML код. Например, текст «XML-карта сайта» можно найти на странице стилей.

Страницу стилей можно изменить через следующие фильтры:

Стили (Stylesheets):  
wp_sitemaps_stylesheet_css Фильтрует CSS стили карты сайта.
wp_sitemaps_stylesheet_content Фильтрует внешний вид карты сайта.
wp_sitemaps_stylesheet_index_content Фильтрует внешний вид главной страницы карты сайта.