관리-도구
편집 파일: RequestParser.php
<?php namespace AIOSEO\Plugin\Common\Sitemap; // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) { exit; } /** * Parses the current request and checks whether we need to serve a sitemap or a stylesheet. * * @since 4.2.1 */ class RequestParser { /** * The cleaned slug of the current request. * * @since 4.2.1 * * @var string */ public $slug; /** * Whether we've checked if the page needs to be redirected. * * @since 4.2.3 * * @var bool */ protected $checkedForRedirects = false; /** * CLass constructor. * * @since 4.2.1 */ public function __construct() { if ( is_admin() ) { return; } add_action( 'parse_request', [ $this, 'checkRequest' ] ); } /** * Checks whether we need to serve a sitemap or related stylesheet. * * @since 4.2.1 * * @param \WP $wp The main WordPress environment instance. * @return void */ public function checkRequest( $wp ) { $this->slug = $wp->request ?? $this->cleanSlug( $wp->request ); if ( ! $this->slug && isset( $_SERVER['REQUEST_URI'] ) ) { // We must fallback to the REQUEST URI in case the site uses plain permalinks. $this->slug = $this->cleanSlug( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ); } if ( ! $this->slug ) { return; } // Check if we need to remove the trailing slash or redirect another sitemap URL like "wp-sitemap.xml". $this->maybeRedirect(); $this->checkForXsl(); if ( aioseo()->options->sitemap->general->enable ) { $this->checkForGeneralSitemap(); } if ( aioseo()->options->sitemap->rss->enable ) { $this->checkForRssSitemap(); } } /** * Cleans the slug of the current request before we use it. * * @since 4.2.3 * * @param string $slug The slug. * @return string The cleaned slug. */ public function cleanSlug( $slug ) { $slug = strtolower( $slug ); $slug = aioseo()->helpers->unleadingSlashIt( $slug ); $slug = untrailingslashit( $slug ); return $slug; } /** * Checks whether the general XML sitemap needs to be served. * * @since 4.2.1 * * @return void */ private function checkForGeneralSitemap() { $fileName = aioseo()->sitemap->helpers->filename( 'general' ); $indexesEnabled = aioseo()->options->sitemap->general->indexes; if ( ! $indexesEnabled ) { // If indexes are disabled, check for the root index. if ( preg_match( "/^{$fileName}\.xml(\.gz)?$/i", (string) $this->slug, $match ) ) { $this->setContext( 'general', $fileName ); aioseo()->sitemap->generate(); } return; } // First, check for the root index. if ( preg_match( "/^{$fileName}\.xml(\.gz)?$/i", (string) $this->slug, $match ) ) { $this->setContext( 'general', $fileName ); aioseo()->sitemap->generate(); return; } if ( // Now, check for the other indexes. preg_match( "/^(?P<objectName>.+)-{$fileName}\.xml(\.gz)?$/i", (string) $this->slug, $match ) || preg_match( "/^(?P<objectName>.+)-{$fileName}(?P<pageNumber>\d+)\.xml(\.gz)?$/i", (string) $this->slug, $match ) ) { $pageNumber = ! empty( $match['pageNumber'] ) ? $match['pageNumber'] : 0; $this->setContext( 'general', $fileName, $match['objectName'], $pageNumber ); aioseo()->sitemap->generate(); } } /** * Checks whether the RSS sitemap needs to be served. * * @since 4.2.1 * * @return void */ private function checkForRssSitemap() { if ( ! preg_match( '/^sitemap(\.latest)?\.rss$/i', (string) $this->slug, $match ) ) { return; } $this->setContext( 'rss' ); aioseo()->sitemap->generate(); } /** * Checks if we need to serve a stylesheet. * * @since 4.2.1 * * @return void */ protected function checkForXsl() { // Trim off the URL params. $newSlug = preg_replace( '/\?.*$/', '', (string) $this->slug ); if ( preg_match( '/^default-sitemap\.xsl$/i', (string) $newSlug ) ) { aioseo()->sitemap->xsl->generate(); } } /** * Sets the context for the requested sitemap. * * @since 4.2.1 * * @param string $type The sitemap type (e.g. "general" or "rss"). * @param string $fileName The sitemap filename. * @param string $indexName The index name ("root" or an object name like "post", "page", "post_tag", etc.). * @param int $pageNumber The index number. * @return void|never */ public function setContext( $type, $fileName = 'sitemap', $indexName = 'root', $pageNumber = 0 ) { $indexesEnabled = aioseo()->options->sitemap->{$type}->indexes; aioseo()->sitemap->type = $type; aioseo()->sitemap->filename = $fileName; aioseo()->sitemap->indexes = $indexesEnabled; aioseo()->sitemap->indexName = $indexName; aioseo()->sitemap->linksPerIndex = aioseo()->options->sitemap->{$type}->linksPerIndex <= 50000 ? aioseo()->options->sitemap->{$type}->linksPerIndex : 50000; aioseo()->sitemap->pageNumber = $pageNumber >= 1 ? $pageNumber - 1 : 0; aioseo()->sitemap->offset = aioseo()->sitemap->linksPerIndex * aioseo()->sitemap->pageNumber; aioseo()->sitemap->isStatic = false; } /** * Redirects or alters the current request if: * 1. The request includes our deprecated "aiosp_sitemap_path" URL param. * 2. The request is for one of our sitemaps, but has a trailing slash. * 3. The request is for the first index of a type, but has a page number. * 4. The request is for a sitemap from WordPress Core/other plugin. * * @since 4.2.1 */ protected function maybeRedirect() { if ( $this->checkedForRedirects ) { return; } $requestUri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; if ( ! $requestUri ) { return; } $this->checkedForRedirects = true; // The request includes our deprecated "aiosp_sitemap_path" URL param. if ( preg_match( '/^\/\?aiosp_sitemap_path=root/i', (string) $requestUri ) ) { wp_safe_redirect( home_url( 'sitemap.xml' ) ); exit; } // The request is for one of our sitemaps, but has a trailing slash. if ( preg_match( '/\/(.*sitemap[0-9]*?\.xml(\.gz)?|.*sitemap(\.latest)?\.rss)\/$/i', (string) $requestUri ) ) { wp_safe_redirect( home_url() . untrailingslashit( $requestUri ) ); exit; } // The request is for the first index of a type, but has a page number. if ( preg_match( '/.*sitemap(0|1){1}?\.xml(\.gz)?$/i', (string) $requestUri ) ) { $pathWithoutNumber = preg_replace( '/(.*sitemap)(0|1){1}?(\.xml(\.gz)?)$/i', '$1$3', $requestUri ); wp_safe_redirect( home_url() . $pathWithoutNumber ); exit; } // The request is for a sitemap from WordPress Core/other plugin, but the general sitemap is enabled. if ( ! aioseo()->options->sitemap->general->enable ) { return; } $sitemapPatterns = [ 'general' => [ 'sitemap\.txt', 'sitemaps\.xml', 'sitemap-xml\.xml', 'sitemap[0-9]+\.xml', 'sitemap(|[-_\/])?index[0-9]*\.xml', 'wp-sitemap\.xml', ], 'rss' => [ 'rss[0-9]*\.xml', ] ]; $addonSitemapPatterns = aioseo()->addons->doAddonFunction( 'helpers', 'getOtherSitemapPatterns' ); if ( ! empty( $addonSitemapPatterns ) ) { $sitemapPatterns = array_merge( $sitemapPatterns, $addonSitemapPatterns ); } foreach ( $sitemapPatterns as $type => $patterns ) { foreach ( $patterns as $pattern ) { if ( preg_match( "/^$pattern$/i", (string) $this->slug ) ) { wp_safe_redirect( aioseo()->sitemap->helpers->getUrl( $type ) ); exit; } } } } }