Linux webm002.cluster126.gra.hosting.ovh.net 6.18.39-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Tue Jul 21 12:03:15 CEST 2026 x86_64
/
home
/
ariannadhf
/
www
/
wp-content
/
plugins
/
xml-sitemap-feed
/
inc
/
/home/ariannadhf/www/wp-content/plugins/xml-sitemap-feed/inc/class-sitemap-plugin.php
<?php /** * Plugin Sitemap * * @package XML Sitemap & Google News */ namespace XMLSF; /** * XMLSF Sitemap Plugin CLASS. */ class Sitemap_Plugin extends Sitemap { /** * CONSTRUCTOR * * Runs on init */ public function __construct() { $this->slug = \sanitize_key( (string) \apply_filters( 'xmlsf_sitemap_slug', 'sitemap' ) ); $this->server_type = 'plugin'; $this->post_type_settings = (array) \get_option( 'xmlsf_post_type_settings', array() ); // Cache clearance. \add_action( 'clean_post_cache', array( $this, 'clean_post_cache' ), 99, 2 ); // Update term meta lastmod date. \add_action( 'transition_post_status', array( $this, 'update_term_modified_meta' ), 10, 3 ); // Update user meta lastmod date. \add_action( 'transition_post_status', array( $this, 'update_user_modified_meta' ), 10, 3 ); // Update images post meta. \add_action( 'transition_post_status', array( $this, 'update_post_images_meta' ), 10, 3 ); // Update last comment date post meta. \add_action( 'transition_comment_status', array( $this, 'update_post_comment_meta' ), 10, 3 ); \add_action( 'comment_post', array( $this, 'update_post_comment_meta_cp' ), 10, 3 ); // When comment is not held for moderation. // MAIN REQUEST filter. \add_filter( 'request', array( $this, 'filter_request' ), 1 ); // Add index archive data filter. \add_filter( 'xmlsf_index_archive_data', array( $this, 'index_archive_data' ), 10, 3 ); // Add RT Camp Nginx Helper NGINX HELPER PURGE URLS filter. \add_filter( 'rt_nginx_helper_purge_urls', array( $this, 'nginx_helper_purge_urls' ) ); // Add sitemap image tags. \add_action( 'xmlsf_urlset', array( $this, 'image_schema' ) ); \add_action( 'xmlsf_tags_after', array( $this, 'image_tag' ), 10, 2 ); // Add sitemap in Robots TXT. add_filter( 'robots_txt', array( $this, 'robots_txt' ), 8 ); // Compatibility hooks. $this->compat(); } /** * Plugin compatibility hooks and filters. * Called from constructor. */ public function compat() { $active_plugins = (array) \get_option( 'active_plugins', array() ); // Polylang compatibility. if ( in_array( 'polylang/polylang.php', $active_plugins, true ) || in_array( 'polylang-pro/polylang.php', $active_plugins, true ) ) { \add_filter( 'xmlsf_blogpages', array( __NAMESPACE__ . '\Compat\Polylang', 'get_translations' ) ); \add_filter( 'xmlsf_frontpages', array( __NAMESPACE__ . '\Compat\Polylang', 'get_translations' ) ); \add_filter( 'xmlsf_request', array( __NAMESPACE__ . '\Compat\Polylang', 'filter_request' ) ); \add_action( 'xmlsf_sitemap_loaded', array( __NAMESPACE__ . '\Compat\Polylang', 'request_actions' ) ); \add_filter( 'xmlsf_root_data', array( __NAMESPACE__ . '\Compat\Polylang', 'root_data' ) ); \add_filter( 'xmlsf_url_after', array( __NAMESPACE__ . '\Compat\Polylang', 'author_archive_translations' ), 10, 3 ); } // WPML compatibility. if ( in_array( 'sitepress-multilingual-cms/sitepress.php', $active_plugins, true ) ) { // Make sure we get the correct sitemap URL in language context. \add_filter( 'xmlsf_sitemap_url', array( __NAMESPACE__ . '\Compat\WPML', 'convert_url' ), 10, 2 ); // Add sitemap in Robots TXT. \add_filter( 'robots_txt', array( __NAMESPACE__ . '\Compat\WPML', 'sitemap_robots' ), 9 ); } // bbPress compatibility. if ( in_array( 'bbpress/bbpress.php', $active_plugins, true ) ) { \add_filter( 'xmlsf_request', array( __NAMESPACE__ . '\Compat\BBPress', 'filter_request' ) ); } // XMLSM compatibility. if ( in_array( 'xml-sitemaps-manager/xml-sitemaps-manager.php', $active_plugins, true ) ) { \add_filter( 'plugins_loaded', array( __NAMESPACE__ . '\Compat\XMLSM', 'disable' ), 11 ); } } /** * Registers sitemap rewrite tags and routing rules. * * @since 5.4.5 */ public function register_rewrites() { global $wp_rewrite; if ( ! $wp_rewrite->using_permalinks() || 0 === strpos( \get_option( 'permalink_structure' ), '/index.php' ) ) { // Nothing to do. return; } $slug = $this->slug(); \add_rewrite_rule( '^' . $slug . '\.xml$', 'index.php?feed=sitemap', 'top' ); \add_rewrite_rule( '^' . $slug . '-([a-z]+?)?(-[a-z0-9\-_]+?)?(?:\.([0-9]{4,8}))?(?:\.([0-9]{1,2}))?\.xml$', 'index.php?feed=sitemap-$matches[1]$matches[2]&m=$matches[3]&w=$matches[4]', 'top' ); \add_rewrite_rule( 'wp-sitemap\.xml', 'index.php?feed=sitemap', 'top' ); } /** * Unregisters sitemap rewrite tags and routing rules. * * @since 5.5 */ public function unregister_rewrites() { global $wp_rewrite; if ( ! $wp_rewrite->using_permalinks() || 0 === strpos( \get_option( 'permalink_structure' ), '/index.php' ) ) { // Nothing to do. return; } $slug = $this->slug(); unset( $wp_rewrite->extra_rules_top[ '^' . $slug . '\.xml$' ] ); unset( $wp_rewrite->extra_rules_top[ '^' . $slug . '-([a-z]+?)?(-[a-z0-9\-_]+?)?(?:\.([0-9]{4,8}))?(?:\.([0-9]{1,2}))?\.xml$' ] ); unset( $wp_rewrite->extra_rules_top['wp-sitemap\.xml'] ); } /** * Get the public XML sitemap url. * * @since 5.5 * * @param string $sitemap Sitemap name. * @param array $args Arguments array: * $type - post_type or taxonomy, default false * $m - YYYY, YYYYMM, YYYYMMDD * $w - week of the year ($m must be YYYY format) * $gz - bool for GZ extension (triggers compression verification). * * @return string|false The sitemap URL or false if the sitemap doesn't exist. */ public function get_sitemap_url( $sitemap = 'index', $args = array() ) { // Get our arguments. $args = \apply_filters( 'xmlsf_index_url_args', \wp_parse_args( $args, array( 'type' => false, 'm' => false, 'w' => false, ) ) ); if ( xmlsf()->using_permalinks() ) { // Construct file name. $basename = $this->slug(); if ( 'index' !== $sitemap ) { $basename .= '-' . $sitemap; $basename .= $args['type'] ? '-' . $args['type'] : ''; $basename .= $args['m'] ? '.' . $args['m'] : ''; $basename .= $args['w'] ? '.' . $args['w'] : ''; } $basename .= '.xml'; } else { // Construct request string. $basename = '?feed=sitemap'; if ( 'index' !== $sitemap ) { $basename .= '-' . $sitemap; $basename .= $args['type'] ? '-' . $args['type'] : ''; $basename .= $args['m'] ? '&m=' . $args['m'] : ''; $basename .= $args['w'] ? '&w=' . $args['w'] : ''; } } $sitemap_url = \apply_filters( 'xmlsf_sitemap_url', \home_url( $basename ), $sitemap, $args ); return \esc_url( $sitemap_url ); } /** * Filter request * * @param array $request Original request. * * @return array $request Filtered request. */ public function filter_request( $request ) { global $wp_rewrite; // Short-circuit if request was already filtered by this plugin. if ( \xmlsf()->request_filtered ) { return $request; } else { \xmlsf()->request_filtered = true; } // Short-circuit if request is not a feed, does not start with 'sitemap' or is a news sitemap. if ( empty( $request['feed'] ) || \strpos( $request['feed'], 'sitemap' ) !== 0 || 'sitemap-news' === $request['feed'] ) { return $request; } /** IT'S A SITEMAP */ $feed = \explode( '-', $request['feed'], 3 ); $type = isset( $feed[1] ) ? $feed[1] : ''; \do_action( 'xmlsf_sitemap_loaded', 'plugin', $type ); /** MODIFY REQUEST PARAMETERS */ switch ( $type ) { case 'posttype': if ( ! isset( $feed[2] ) || ! $this->active_post_type( $feed[2] ) ) { return $request; } // Try to raise memory limit, context added for filters. \wp_raise_memory_limit( 'sitemap-posttype-' . $feed[2] ); // Setup filters. \add_filter( 'post_limits', function () { return 'LIMIT 0, 50000'; } ); // Modify request. $request['post_type'] = $feed[2]; // Prevent term cache update query unless needed for permalinks. if ( \strpos( \get_option( 'permalink_structure' ), '%category%' ) === false ) { $request['update_post_term_cache'] = false; } // Make sure to update meta cache for: // 1. excluded posts. // 2. image data (if activated). $request['update_post_meta_cache'] = true; break; case 'taxonomy': $disabled = \get_option( 'xmlsf_disabled_providers', get_default_settings( 'disabled_providers' ) ); if ( ! isset( $feed[2] ) || ( ! empty( $disabled ) && in_array( 'taxonomies', (array) $disabled, true ) ) ) { return $request; } $taxonomies = \get_option( 'xmlsf_taxonomies' ); if ( ! empty( $taxonomies ) && ! \in_array( $feed[2], (array) $taxonomies, true ) ) { return $request; } // Try to raise memory limit, context added for filters. \wp_raise_memory_limit( 'sitemap-taxonomy-' . $feed[2] ); // Pass on taxonomy name via request. $request['taxonomy'] = $feed[2]; // Set terms args. \add_filter( 'get_terms_args', array( $this, 'set_terms_args' ), 9 ); break; case 'author': $disabled = \get_option( 'xmlsf_disabled_providers', get_default_settings( 'disabled_providers' ) ); if ( ! empty( $disabled ) && \in_array( 'users', (array) $disabled, true ) ) { return $request; } // Set users args. \add_filter( 'xmlsf_get_author_args', array( $this, 'set_authors_args' ), 9 ); // Set user filter for multisite. \add_filter( 'xmlsf_skip_user', array( $this, 'skip_deleted_or_spam_authors' ), 10, 2 ); break; default: // We're on the index. Do nothing. } $request['post_status'] = 'publish'; $request['no_found_rows'] = true; // Found rows calc is slow and only needed for pagination. // SPECIFIC REQUEST FILTERING AND PREPARATIONS. /** FILTER HOOK FOR PLUGIN COMPATIBILITIES */ /** * Filters the request. * * Use add_filter( 'xmlsf_request', 'your_filter_function' ); * * Possible filters hooked here: * XMLSF\Compat/Polylang->filter_request - Polylang compatibility * XMLSF\Compat\WPML->filter_request - WPML compatibility * XMLSF\Compat/BBPress->filter_request - bbPress compatibility */ $request = \apply_filters( 'xmlsf_request', $request ); /** PREPARE TO LOAD TEMPLATE */ \add_action( 'do_feed_' . $request['feed'], array( $this, 'load_template' ), 10, 2 ); return $request; } /** * Load feed template * * Hooked into do_feed_{sitemap...}. First checks for a child/parent theme template file, then falls back to plugin template * * @since 5.3 * * @param bool $is_comment_feed Unused. * @param string $feed Feed type. */ public function load_template( $is_comment_feed, $feed ) { /** * GET TEMPLATE FILE * * DEVELOPERS: a custom template file in the active (parent or child) theme directory will be used when found there * * Must start with 'sitemap', optionally folowed by other designators, serperated by hyphens. * It should always end with the php extension. * * Examples: * sitemap.php * sitemap-posttype.php * * sitemap-posttype-post.php * * sitemap-posttype-page.php * * sitemap-posttype-[custom_post_type].php * sitemap-taxonomy.php * * sitemap-taxonomy-category.php * * sitemap-taxonomy-post_tag.php * * sitemap-taxonomy-[custom_taxonomy].php * sitemap-authors.php * sitemap-custom.php */ $parts = \explode( '-', $feed, 3 ); $templates = array(); // Possible theme template file names. if ( ! empty( $parts[1] ) && \in_array( $parts[1], array( 'posttype', 'taxonomy', 'author', 'custom' ), true ) ) { if ( ! empty( $parts[2] ) ) { $templates[] = "sitemap-{$parts[1]}-{$parts[2]}.php"; } $templates[] = "sitemap-{$parts[1]}.php"; } $templates[] = 'sitemap.php'; // Locate and load theme template file or use plugin template. if ( ! \locate_template( $templates, true ) ) { foreach ( $templates as $template ) { $file = XMLSF_DIR . '/views/feed-' . $template; if ( \file_exists( $file ) ) { \load_template( $file ); break; } } } } /** * Terms arguments filter * Does not check if we are really in a sitemap feed. * * @param array $args Term arguments. * * @return array */ public function set_terms_args( $args ) { // Read more on https://developer.wordpress.org/reference/classes/wp_term_query/__construct/. $options = \get_option( 'xmlsf_taxonomy_settings', get_default_settings( 'taxonomy_settings' ) ); $args['number'] = isset( $options['limit'] ) && \is_numeric( $options['limit'] ) && $options['limit'] > 0 ? \intval( $options['limit'] ) : 2000; if ( $args['number'] > 50000 ) { $args['number'] = 50000; } $args['order'] = 'DESC'; $args['orderby'] = 'count'; $args['pad_counts'] = true; $args['lang'] = ''; $args['hierarchical'] = false; $args['suppress_filter'] = true; $args['hide_empty'] = true; $args['update_term_meta_cache'] = false; return $args; } /** * Authors arguments filter * Does not check if we are really in a sitemap feed. * * @param array $args Author arguments. * * @return array */ public function set_authors_args( $args ) { $post_types = \get_post_types( array( 'public' => true ) ); // We're not supporting sitemaps for author pages for attachments and pages. unset( $post_types['attachment'] ); unset( $post_types['page'] ); /** * Filters the has_published_posts query argument in the author archive. Must return a boolean or an array of one or multiple post types. * Allows to add or change post type when theme author archive page shows custom post types. * * @since 5.4 * * @param array Array with post type slugs. Default array('post'). * * @return mixed */ $post_types = \apply_filters( 'xmlsf_author_has_published_posts', $post_types ); $options = \get_option( 'xmlsf_author_settings', get_default_settings( 'author_settings' ) ); $args['has_published_posts'] = $post_types; $args['number'] = ! empty( $options['limit'] ) && \is_numeric( $options['limit'] ) && $options['limit'] > 0 ? \intval( $options['limit'] ) : 2000; if ( $args['number'] > 50000 ) { $args['number'] = 50000; } $include = \get_option( 'xmlsf_authors' ); if ( ! empty( $include ) ) { $args['include'] = (array) $include; } return $args; } /** * Exclude spammed or deleted Authors in a multisite environment. * Does not check if we are really in a sitemap feed. * * @param bool $skip Skip or not skip. * @param obj $user User object. * * @uses is_multisite() * * @return bool */ public function skip_deleted_or_spam_authors( $skip, $user ) { if ( ! \is_multisite() ) { return $skip; } if ( \property_exists( $user, 'deleted' ) && $user->deleted ) { return true; } if ( \property_exists( $user, 'spam' ) && $user->spam ) { return true; } return $skip; } /** * Post archives data * * @param array $data Data. * @param string $post_type Post type. * @param string $archive_type Archive type. * * @return array $data */ public function index_archive_data( $data, $post_type = 'post', $archive_type = '' ) { return \array_merge( $data, $this->get_index_archive_data( $post_type, $archive_type ) ); } /** * Get post archives data * * @param string $post_type Post type. * @param string $archive_type Archive type. * * @return array */ public function get_index_archive_data( $post_type, $archive_type ) { global $wpdb; $return = array(); $where = $wpdb->prepare( "WHERE post_type = %s AND post_status = 'publish'", $post_type ); if ( 'weekly' === $archive_type ) : $week = \_wp_mysql_week( '`post_date`' ); $query = "SELECT DISTINCT $week AS `week`, YEAR( `post_date` ) AS `year`, count( `ID` ) AS `posts` FROM `$wpdb->posts` $where GROUP BY $week, YEAR( `post_date` ) ORDER BY `year` DESC, `week` DESC"; $arcresults = $this->cache_get_archives( $query ); foreach ( (array) $arcresults as $arcresult ) { $url = $this->get_sitemap_url( 'posttype', array( 'type' => $post_type, 'm' => $arcresult->year, 'w' => $arcresult->week, ) ); $return[ $url ] = \get_date_from_gmt( \get_lastmodified( 'GMT', $post_type, $arcresult->year, $arcresult->week ), DATE_W3C ); } elseif ( 'monthly' === $archive_type ) : $query = "SELECT YEAR(post_date) AS `year`, LPAD(MONTH(post_date), 2, '0') AS `month`, count(ID) as `posts` FROM `$wpdb->posts` $where GROUP BY YEAR(post_date), LPAD(MONTH(post_date), 2, '0') ORDER BY `year` DESC, `month` DESC"; $arcresults = $this->cache_get_archives( $query ); foreach ( (array) $arcresults as $arcresult ) { $url = $this->get_sitemap_url( 'posttype', array( 'type' => $post_type, 'm' => $arcresult->year . $arcresult->month, ) ); $return[ $url ] = \get_date_from_gmt( \get_lastmodified( 'GMT', $post_type, $arcresult->year . $arcresult->month ), DATE_W3C ); } elseif ( 'yearly' === $archive_type ) : $query = "SELECT YEAR(post_date) AS `year`, count(ID) as `posts` FROM `$wpdb->posts` $where GROUP BY YEAR(post_date) ORDER BY `year` DESC"; $arcresults = $this->cache_get_archives( $query ); foreach ( (array) $arcresults as $arcresult ) { $url = $this->get_sitemap_url( 'posttype', array( 'type' => $post_type, 'm' => $arcresult->year, ) ); $return[ $url ] = \get_date_from_gmt( \get_lastmodified( 'GMT', $post_type, $arcresult->year ), DATE_W3C ); } else : $query = "SELECT COUNT(ID) AS `posts` FROM `$wpdb->posts` $where ORDER BY `post_date` DESC"; $arcresults = $this->cache_get_archives( $query ); if ( is_object( $arcresults[0] ) && $arcresults[0]->posts > 0 ) { $url = $this->get_sitemap_url( 'posttype', array( 'type' => $post_type ) ); $return[ $url ] = \get_date_from_gmt( \get_lastmodified( 'GMT', $post_type ), DATE_W3C ); } endif; return $return; } /** * Get archives from wp_cache * * @param string $sql The prepared query. * * @return array */ private function cache_get_archives( $sql ) { global $wpdb; $key = \md5( $sql ); $_cache = \wp_cache_get( 'xmlsf_get_archives', 'general' ); $cache = false === $_cache ? array() : $_cache; if ( ! isset( $cache[ $key ] ) ) { $cache[ $key ] = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery \wp_cache_set( 'xmlsf_get_archives', $cache, 'general' ); } return $cache[ $key ]; } /** * Do image tag * * @param string $type Post type. * @param WP_Post $post Post object. * * @return void */ public function image_tag( $type, $post = null ) { if ( 'post_type' !== $type || null === $post || ! $this->active_post_type( $post->post_type ) ) { return; } $settings = $this->post_type_settings( $post->post_type ); if ( isset( $settings['tags'] ) && \is_array( $settings['tags'] ) && ! empty( $settings['tags']['image'] ) && \is_string( $settings['tags']['image'] ) ) { $images = \get_post_meta( $post->ID, '_xmlsf_image_' . $settings['tags']['image'], false ); foreach ( $images as $img ) { if ( empty( $img['loc'] ) ) { continue; } echo '<image:image><image:loc>' . \esc_xml( \utf8_uri_encode( $img['loc'] ) ) . '</image:loc>'; if ( ! empty( $img['title'] ) ) { echo '<image:title><![CDATA[' . \esc_xml( $img['title'] ) . ']]></image:title>'; } if ( ! empty( $img['caption'] ) ) { echo '<image:caption><![CDATA[' . \esc_xml( $img['caption'] ) . ']]></image:caption>'; } \do_action( 'xmlsf_image_tags_inner', 'post_type' ); echo '</image:image>'; } } } /** * Image schema * * @param string $type Type. * @uses WP_Post $post * @return void */ public function image_schema( $type ) { global $wp_query; if ( 'post_type' !== $type || empty( $wp_query->query_vars['post_type'] ) || ! $this->active_post_type( $wp_query->query_vars['post_type'] ) ) { return; } $settings = $this->post_type_settings( $wp_query->query_vars['post_type'] ); if ( isset( $settings['tags'] ) && \is_array( $settings['tags'] ) && ! empty( $settings['tags']['image'] ) ) { echo 'xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"'; } } /** * Nginx helper purge urls * adds sitemap urls to the purge array. * * @param array $urls URLs array. * @param bool $wildcard Use wildcard or not. * * @return $urls array */ public function nginx_helper_purge_urls( $urls = array(), $wildcard = false ) { $slug = $this->slug(); if ( $wildcard ) { // Wildcard makes everything simple. $urls[] = '/' . $slug . '*.xml'; } else { // No wildcard, go through the motions. $urls[] = '/' . $slug . '.xml'; $urls[] = '/' . $slug . '-author.xml'; $urls[] = '/' . $slug . '-custom.xml'; // Add public post types sitemaps. $post_types = $this->get_post_types(); foreach ( $post_types as $post_type ) : $settings = $this->post_type_settings( $post_type ); $archive = isset( $settings['archive'] ) ? $settings['archive'] : ( $post_type->hierarchical ? 'yearly' : '' ) ; $archive_data = \apply_filters( 'xmlsf_index_archive_data', array(), $post_type, $archive ); foreach ( $archive_data as $url => $lastmod ) { $path = \wp_parse_url( $url, PHP_URL_PATH ); if ( $path ) { $urls[] = $path; } } endforeach; // Add public post taxonomies sitemaps. $taxonomies = $this->get_taxonomies(); foreach ( $taxonomies as $taxonomy ) { $path = \wp_parse_url( $this->get_sitemap_url( 'taxonomy', array( 'type' => $taxonomy ) ), PHP_URL_PATH ); if ( $path ) { $urls[] = $path; } } } \do_action( 'xmlsf_nginx_helper_purge_urls', $urls ); return $urls; } /** * Filter robots.txt rules * * @since 5.5 * * @param string $output Output. * @return string */ public function robots_txt( $output ) { return $output . PHP_EOL . 'Sitemap: ' . $this->get_sitemap_url() . PHP_EOL; } }