관리-도구
편집 파일: sitemap-core.php
<?php /** * Default sitemap core class * * @package Sitemap * @author Arne Brachhold * @since 4.0 */ use function Bhittani\StarRating\functions\sanitize; /** * $Id: sitemap-core.php 2823802 2022-11-24 18:12:38Z auctollo $ */ // Enable for dev! Good code doesn't generate any notices... // error_reporting(E_ALL); // ini_set('display_errors', 1); . /** * Represents the status (successes and failures) of a ping process * * @author Arne Brachhold * @package sitemap * @since 3.0b5 */ class GoogleSitemapGeneratorStatus { /** * Var start time of building process . * * @var float $_start_time The start time of the building process . */ private $start_time = 0; /** * The end time of the building process. * * @var float $_end_time The end time of the building process */ private $end_time = 0; /** * Holding an array with the results and information of the last ping . * * @var array Holding an array with the results and information of the last ping */ private $ping_results = array(); /** * If the status should be saved to the database automatically . * * @var bool If the status should be saved to the database automatically */ private $auto_save = true; /** * Constructs a new status ued for saving the ping results * * @param string $auto_save . */ public function __construct( $auto_save = true ) { $this->start_time = microtime( true ); $this->auto_save = $auto_save; if ( $auto_save ) { $exists = get_option( 'sm_status' ); if ( false === $exists ) { add_option( 'sm_status', '', '', 'no' ); } $this->save(); } } /** * Saves the status back to the database */ public function save() { update_option( 'sm_status', $this ); } /** * Returns the last saved status object or null * * @return GoogleSitemapGeneratorStatus */ public static function load() { $status = get_option( 'sm_status' ); if ( is_a( $status, 'GoogleSitemapGeneratorStatus' ) ) { return $status; } else { return null; } } /** * Ends the ping process */ public function end() { $this->end_time = microtime( true ); if ( $this->auto_save ) { $this->save(); } } /** * Returns the duration of the ping process * * @return int */ public function get_duration() { return round( $this->end_time - $this->start_time, 2 ); } /** * Returns the time when the pings were started * * @return int */ public function get_start_time() { return round( $this->start_time, 2 ); } /** * Start ping . * * @param string $service string The internal name of the ping service . * @param string $url string The URL to ping . * @param string $name string The display name of the service . * @return void */ public function start_ping( $service, $url, $name = null ) { $this->ping_results[ $service ] = array( 'start_time' => microtime( true ), 'end_time' => 0, 'success' => false, 'url' => $url, 'name' => $name ? $name : $service, ); if ( $this->auto_save ) { $this->save(); } } /** * End ping . * * @param string $service string The internal name of the ping service . * @param string $success boolean If the ping was successful . * @return void */ public function end_ping( $service, $success ) { $this->ping_results[ $service ]['end_time'] = microtime( true ); $this->ping_results[ $service ]['success'] = $success; if ( $this->auto_save ) { $this->save(); } } /** * Returns the duration of the last ping of a specific ping service * * @param string $service string The internal name of the ping service . * @return float */ public function get_ping_duration( $service ) { $res = $this->ping_results[ $service ]; return round( $res['end_time'] - $res['start_time'], 2 ); } /** * Returns the last result for a specific ping service * * @param string $service string The internal name of the ping service . * @return array */ public function get_ping_result( $service ) { return $this->ping_results[ $service ]['success']; } /** * Returns the URL for a specific ping service * * @param string $service string The internal name of the ping service . * @return array */ public function get_ping_url( $service ) { return $this->ping_results[ $service ]['url']; } /** * Returns the name for a specific ping service * * @param string $service string The internal name of the ping service . * @return array */ public function get_service_name( $service ) { return $this->ping_results[ $service ]['name']; } /** * Returns if a service was used in the last ping * * @param string $service string The internal name of the ping service . * @return bool */ public function used_ping_service( $service ) { return array_key_exists( $service, $this->ping_results ); } /** * Returns the services which were used in the last ping * * @return array */ public function get_used_ping_services() { return array_keys( $this->ping_results ); } } /** * Represents an item in the page list * * @author Arne Brachhold * @package sitemap * @since 3.0 */ class GoogleSitemapGeneratorPage { /** * Sets the URL or the relative path to the site dir of the page . * * @var string $_url Sets the URL or the relative path to the site dir of the page */ public $url; /** * Sets the priority of this page . * * @var float $_priority Sets the priority of this page */ public $priority; /** * Sets the chanfe frequency of the page. I want Enums! . * * @var string $_change_freq Sets the chanfe frequency of the page. I want Enums! */ public $change_freq; /** * Sets the last_mod date as a UNIX timestamp. . * * @var int $_last_mod Sets the last_mod date as a UNIX timestamp. */ public $last_mod; /** * Sets the post ID in case this item is a WordPress post or page . * * @var int $_post_id Sets the post ID in case this item is a WordPress post or page */ public $post_id; /** * Initialize a new page object * * @since 3.0 * @param string $url The URL or path of the file . * @param float $priority The Priority of the page 0.0 to 1.0 . * @param string $change_freq The change frequency like daily, hourly, weekly . * @param int $last_mod The last mod date as a unix timestamp . * @param int $post_id The post ID of this page . */ public function __construct( $url = '', $priority = 0.0, $change_freq = 'never', $last_mod = 0, $post_id = 0 ) { $this->set_url( $url ); $this->set_priority( $priority ); $this->set_change_freq( $change_freq ); $this->set_last_mod( $last_mod ); $this->set_post_id( $post_id ); } /** * Returns the URL of the page * * @return string The URL */ public function get_url() { return $this->url; } /** * Sets the URL of the page * * @param string $url The new URL . */ public function set_url( $url ) { $this->url = (string) $url; } /** * Returns the priority of this page * * @return float the priority, from 0.0 to 1.0 */ public function get_priority() { return $this->priority; } /** * Sets the priority of the page * * @param float $priority The new priority from 0.1 to 1.0 . */ public function set_priority( $priority ) { $this->priority = floatval( $priority ); } /** * Returns the change frequency of the page * * @return string The change frequncy like hourly, weekly, monthly etc. */ public function get_change_freq() { return $this->change_freq; } /** * Sets the change frequency of the page * * @param string $change_freq The new change frequency . */ public function set_change_freq( $change_freq ) { $this->change_freq = (string) $change_freq; } /** * Returns the last mod of the page * * @return int The lastmod value in seconds */ public function get_last_mod() { return $this->last_mod; } /** * Sets the last mod of the page * * @param int $last_mod The lastmod of the page . */ public function set_last_mod( $last_mod ) { $this->last_mod = intval( $last_mod ); } /** * Returns the ID of the post * * @return int The post ID */ public function get_post_id() { return $this->post_id; } /** * Sets the ID of the post * * @param int $post_id The new ID . */ public function set_post_id( $post_id ) { $this->post_id = intval( $post_id ); } /** * Render method . */ public function render() { if ( '/' === $this->url || empty( $this->url ) ) { return ''; } $r = ''; $r .= "\t<url>\n"; $r .= "\t\t<loc>" . $this->escape_xml( esc_url_raw( $this->url ) ) . "</loc>\n"; if ( $this->last_mod > 0 ) { //$r .= "\t\t<lastmod>" . gmdate( 'Y-m-d\TH:i:s+00:00', $this->last_mod ) . "</lastmod>\n"; $r .= "\t\t<lastmod>" . gmdate( 'Y-m-d\TH:i:sP', $this->last_mod ) . "</lastmod>\n"; } if ( ! empty( $this->change_freq ) ) { $r .= "\t\t<changefreq>" . $this->change_freq . "</changefreq>\n"; } if ( false !== $this->priority && '' !== $this->priority ) { $r .= "\t\t<priority>" . number_format( $this->priority, 1 ) . "</priority>\n"; } $r .= "\t</url>\n"; return $r; } /** * Escape xml . * * @param string $string . */ protected function escape_xml( $string ) { return str_replace( array( '&', '"', '\'', '<', '>' ), array( '&', '"', ''', '<', '>' ), $string ); } } /** * Represents an XML entry, like definitions * * @author Arne Brachhold * @package sitemap * @since 3.0 */ class GoogleSitemapGeneratorXmlEntry { /** * Xml * * @var string $_xml . */ protected $xml; /** * Constructor function * * @param string $xml . */ public function __construct( $xml ) { $this->xml = $xml; } /** * Render function */ public function render() { return $this->xml; } } /** * Represents an comment * * @author Arne Brachhold * @package sitemap * @since 3.0 * @uses GoogleSitemapGeneratorXmlEntry */ class GoogleSitemapGeneratorDebugEntry extends GoogleSitemapGeneratorXmlEntry { /** * Render function */ public function render() { return '<!-- ' . $this->xml . " -->\n"; } } /** * Represents an item in the sitemap * * @author Arne Brachhold * @package sitemap * @since 3.0 */ class GoogleSitemapGeneratorSitemapEntry { /** * Sets the URL or the relative path to the site dir of the page . * * @var string $_url Sets the URL or the relative path to the site dir of the page */ protected $url; /** * Sets the last_mod date as a UNIX timestamp. . * * @var int $_last_mod Sets the last_mod date as a UNIX timestamp. */ protected $last_mod; /** * Returns the URL of the page * * @return string The URL */ public function get_url() { return $this->url; } /** * Sets the URL of the page * * @param string $url The new URL . */ public function set_url( $url ) { $this->url = (string) $url; } /** * Returns the last mod of the page * * @return int The lastmod value in seconds */ public function get_last_mod() { return $this->last_mod; } /** * Sets the last mod of the page * * @param int $last_mod The lastmod of the page . */ public function set_last_mod( $last_mod ) { $this->last_mod = intval( $last_mod ); } /** * Constructor * * @param string $url . * @param int $last_mod . */ public function __construct( $url = '', $last_mod = 0 ) { $this->set_url( $url ); $this->set_last_mod( $last_mod ); } /** * Render function */ public function render() { if ( '/' === $this->url || empty( $this->url ) ) { return ''; } $r = ''; $r .= "\t<sitemap>\n"; $r .= "\t\t<loc>" . $this->escape_xml( esc_url_raw( $this->url ) ) . "</loc>\n"; if ( $this->last_mod > 0 ) { $r .= "\t\t<lastmod>" . gmdate( 'Y-m-d\TH:i:s+00:00', $this->last_mod ) . "</lastmod>\n"; } $r .= "\t</sitemap>\n"; return $r; } /** * Escape_xml function . * * @param string $string . */ protected function escape_xml( $string ) { return str_replace( array( '&', '\'', '\'', '<', '>' ), array( '&', '"', ''', '<', '>' ), $string ); } } /** * Interface for all priority providers * * @author Arne Brachhold * @package sitemap * @since 3.0 */ interface Google_Sitemap_Generator_Prio_Provider_Base { /** * Initializes a new priority provider * * @param int $total_comments int The total number of comments of all posts . * @param int $total_posts int The total number of posts . * @since 3.0 */ public function __construct( $total_comments, $total_posts ); /** * Returns the (translated) name of this priority provider * * @since 3.0 * @return string The translated name */ public static function get_name(); /** * Returns the (translated) description of this priority provider * * @since 3.0 * @return string The translated description */ public static function get_description(); /** * Returns the priority for a specified post * * @param int $post_id int The ID of the post . * @param int $comment_count int The number of comments for this post . * @since 3.0 * @return int The calculated priority */ public function get_post_priority( $post_id, $comment_count ); } /** * Priority Provider which calculates the priority based on the number of comments * * @author Arne Brachhold * @package sitemap * @since 3.0 */ class GoogleSitemapGeneratorPrioByCountProvider implements Google_Sitemap_Generator_Prio_Provider_Base { /** * The total number of comments of all posts . * * @var int $total_comments The total number of comments of all posts */ protected $total_comments = 0; /** * The total number of posts . * * @var int $total_posts The total number of posts */ protected $total_posts = 0; /** * Initializes a new priority provider * * @param int $total_comments int The total number of comments of all posts . * @param int $total_posts int The total number of posts . * @since 3.0 */ public function __construct( $total_comments, $total_posts ) { $this->total_comments = $total_comments; $this->total_posts = $total_posts; } /** * Returns the (translated) name of this priority provider * * @since 3.0 * @return string The translated name */ public static function get_name() { return __( 'Comment Count', 'google-sitemap-generator' ); } /** * Returns the (translated) description of this priority provider * * @since 3.0 * @return string The translated description */ public static function get_description() { return __( 'Uses the number of comments of the post to calculate the priority', 'google-sitemap-generator' ); } /** * Returns the priority for a specified post * * @param int $post_id int The ID of the post . * @param int $comment_count int The number of comments for this post . * @since 3.0 * @return int The calculated priority */ public function get_post_priority( $post_id, $comment_count ) { if ( $this->total_comments > 0 && $comment_count > 0 ) { return round( ( $comment_count * 100 / $this->total_comments ) / 100, 1 ); } else { return 0; } } } /** * Priority Provider which calculates the priority based on the average number of comments * * @author Arne Brachhold * @package sitemap * @since 3.0 */ class GoogleSitemapGeneratorPrioByAverageProvider implements Google_Sitemap_Generator_Prio_Provider_Base { /** * The total number of comments of all posts . * * @var int $total_comments The total number of comments of all posts */ protected $total_comments = 0; /** * The total number of posts . * * @var int $total_comments The total number of posts */ protected $total_posts = 0; /** * The average number of comments per post . * * @var int $average The average number of comments per post */ protected $average = 0.0; /** * Returns the (translated) name of this priority provider * * @since 3.0 * @return string The translated name */ public static function get_name() { return __( 'Comment Average', 'google-sitemap-generator' ); } /** * Returns the (translated) description of this priority provider * * @since 3.0 * @return string The translated description */ public static function get_description() { return __( 'Uses the average comment count to calculate the priority', 'google-sitemap-generator' ); } /** * Initializes a new priority provider which calculates the post priority based on the average number of comments * * @param int $total_comments int The total number of comments of all posts . * @param int $total_posts int The total number of posts . * @since 3.0 */ public function __construct( $total_comments, $total_posts ) { $this->total_comments = $total_comments; $this->total_posts = $total_posts; if ( $this->total_comments > 0 && $this->total_posts > 0 ) { $this->average = (float) $this->total_comments / $this->total_posts; } } /** * Returns the priority for a specified post * * @param int $post_id int The ID of the post . * @param int $comment_count int The number of comments for this post . * @since 3.0 * @return int The calculated priority */ public function get_post_priority( $post_id, $comment_count ) { // Do not divide by zero ! if ( 0 === $this->average|| 0.0 === $this->average ) { if ( $comment_count > 0 ) { $priority = 1; } else { $priority = 0; } } else { $priority = $comment_count / $this->average; if ( $priority > 1 ) { $priority = 1; } elseif ( $priority < 0 ) { $priority = 0; } } return round( $priority, 1 ); } } /** * Class to generate a sitemaps.org Sitemaps compliant sitemap of a WordPress site. * * @package sitemap * @author Arne Brachhold * @since 3.0 */ final class GoogleSitemapGenerator { /** * The unserialized array with the stored options . * * @var array The unserialized array with the stored options */ private $options = array(); /** * The saved additional pages . * * @var array The saved additional pages */ private $pages = array(); /** * The values and names of the change frequencies . * * @var array The values and names of the change frequencies */ private $freq_names = array(); /** * A list of class names which my be called for priority calculation . * * @var array A list of class names which my be called for priority calculation */ private $prio_providers = array(); /** * True if init complete (options loaded etc) . * * @var bool True if init complete (options loaded etc) */ private $is_initiated = false; /** * Defines if the sitemap building process is active at the moment . * * @var bool Defines if the sitemap building process is active at the moment */ private $is_active = false; /** * Holds options like output format and compression for the current request . * * @var array Holds options like output format and compression for the current request */ private $build_options = array(); /** * Holds the user interface object * * @since 3.1.1 * @var GoogleSitemapGeneratorUI */ private $ui = null; /** * Defines if the simulation mode is on. In this case, data is not echoed but saved instead. * * @var boolean */ private $sim_mode = false; /** * Holds the data if simulation mode is on * * @var array */ private $sim_data = array( 'sitemaps' => array(), 'content' => array(), ); /** * Defines if the options have been loaded. * * @var bool Defines if the options have been loaded */ private $options_loaded = false; /*************************************** CONSTRUCTION AND INITIALIZING ***************************************/ /** * Initializes a new Google Sitemap Generator * * @since 4.0 */ private function __construct() { } /** * Returns the instance of the Sitemap Generator * * @since 3.0 * @return GoogleSitemapGenerator The instance or null if not available. */ public static function get_instance() { if ( isset( $GLOBALS['sm_instance'] ) ) { return $GLOBALS['sm_instance']; } else { return null; } } /** * Enables the Google Sitemap Generator and registers the WordPress hooks * * @since 3.0 */ public static function enable() { if ( ! isset( $GLOBALS['sm_instance'] ) ) { $GLOBALS['sm_instance'] = new GoogleSitemapGenerator(); } } /** * Loads up the configuration and validates the prioity providers * * This method is only called if the sitemaps needs to be build or the admin page is displayed. * * @since 3.0 */ public function initate() { if ( ! $this->is_initiated ) { load_plugin_textdomain( 'sitemap', false, dirname( plugin_basename( __FILE__ ) ) . '/lang' ); $this->freq_names = array( 'always' => __( 'Always', 'google-sitemap-generator' ), 'hourly' => __( 'Hourly', 'google-sitemap-generator' ), 'daily' => __( 'Daily', 'google-sitemap-generator' ), 'weekly' => __( 'Weekly', 'google-sitemap-generator' ), 'monthly' => __( 'Monthly', 'google-sitemap-generator' ), 'yearly' => __( 'Yearly', 'google-sitemap-generator' ), 'never' => __( 'Never', 'google-sitemap-generator' ), ); $this->load_options(); $this->load_pages(); // Register our own priority providers. add_filter( 'sm_add_prio_provider', array( $this, 'add_default_prio_providers' ) ); // Let other plugins register their providers. $r = apply_filters( 'sm_add_prio_provider', $this->prio_providers ); // Check if no plugin return null. if ( null !== $r ) { $this->prio_providers = $r; } $this->validate_prio_providers(); $this->is_initiated = true; } } /*************************************** VERSION AND LINK HELPERS ***************************************/ /** * Returns the version of the generator * * @since 3.0 * @return int The version */ public static function get_version() { return GoogleSitemapGeneratorLoader::get_version(); } /** * Returns the SVN version of the generator * * @since 4.0 * @return string The SVN version string */ public static function get_svn_version() { return GoogleSitemapGeneratorLoader::get_svn_version(); } /** * Returns a link pointing to a specific page of the authors website * * @since 3.0 * @param string $redir string The to link to . * @return string The full url */ public static function get_redirect_link( $redir ) { return trailingslashit( 'http://url.auctollo.com/' . $redir ); } /** * Returns a link pointing back to the plugin page in WordPress * * @since 3.0 * @param string $extra . * @return string The full url */ public static function get_back_link( $extra = '' ) { global $wp_version; $url = admin_url( 'options-general.php?page=' . GoogleSitemapGeneratorLoader::get_base_name() . $extra ); return $url; } /** * Converts a mysql datetime value into a unix timestamp * * @param string $mysql_date_time string The timestamp in the mysql datetime format . * @return int The time in seconds */ public static function get_timestamp_from_my_sql( $mysql_date_time ) { list( $date, $hours) = explode( ' ', $mysql_date_time ); list( $year, $month, $day) = explode( '-', $date ); list( $hour, $min, $sec) = explode( ':', $hours ); return mktime( intval( $hour ), intval( $min ), intval( $sec ), intval( $month ), intval( $day ), intval( $year ) ); } /*************************************** SIMPLE GETTERS ***************************************/ /** * Returns the names for the frequency values * * @return array */ public function get_freq_names() { return $this->freq_names; } /** * Returns if the site is running in multi site mode * * @since 4.0 * @return bool */ public function is_multi_site() { return ( function_exists( 'is_multisite' ) && is_multisite() ); } /** * Returns if the sitemap building process is currently active * * @since 3.0 * @return bool true if active */ public function is_active() { $inst = self::get_instance(); return ( null !== $inst && $inst->is_active ); } /** * Returns if the compressed sitemap was activated * * @since 3.0b8 * @return true if compressed */ public function is_gzip_enabled() { return ( function_exists( 'gzwrite' ) && $this->get_option( 'b_autozip' ) ); } /** * Returns if the XML Dom and XSLT functions are enabled * * @since 4.0b1 * @return true if compressed */ public function is_xsl_enabled() { return ( class_exists( 'DomDocument' ) && class_exists( 'XSLTProcessor' ) ); } /** * Returns if Nginx is used as the server software * * @since 4.0.3 * * @return bool */ public function is_nginx() { if ( isset( $_SERVER['SERVER_SOFTWARE'] ) && stristr( sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ), 'nginx' ) !== false ) { return true; } return false; } /*************************************** TAXONOMIES AND CUSTOM POST TYPES ***************************************/ /** * Returns if this version of WordPress supports the new taxonomy system * * @since 3.0b8 * @return true if supported */ public function is_taxonomy_supported() { return ( function_exists( 'get_taxonomy' ) && function_exists( 'get_terms' ) && function_exists( 'get_taxonomies' ) ); } /** * Returns the list of custom taxonomies. These are basically all taxonomies without categories and post tags * * @since 3.1.7 * @return array Array of names of user-defined taxonomies */ public function get_custom_taxonomies() { $taxonomies = get_taxonomies( array( 'public' => 1 ) ); return array_diff( $taxonomies, array( 'category', 'product_cat', 'post_tag', 'nav_menu', 'link_category', 'post_format' ) ); } /** * Returns if this version of WordPress supports custom post types * * @since 3.2.5 * @return true if supported */ public function is_custom_post_types_supported() { return ( function_exists( 'get_post_types' ) && function_exists( 'register_post_type' ) ); } /** * Returns the list of custom post types. These are all custom post types except post, page and attachment * * @since 3.2.5 * @return array Array of custom post types as per get_post_types */ public function get_custom_post_types() { $post_types = get_post_types( array( 'public' => 1 ) ); $post_types = array_diff( $post_types, array( 'post', 'page', 'attachment' ) ); return $post_types; } /** * Returns the list of active post types, built-in and custom ones. * * @since 4.0b5 * @return array Array of custom post types as per get_post_types */ public function get_active_post_types() { $cache_key = __CLASS__ . '::get_active_post_types'; $active_post_types = wp_cache_get( $cache_key, 'sitemap' ); if ( false === $active_post_types ) { $all_post_types = get_post_types(); $enabled_post_types = $this->get_option( 'in_customtypes' ); if ( $this->get_option( 'in_posts' ) ) { $enabled_post_types[] = 'post'; } if ( $this->get_option( 'in_pages' ) ) { $enabled_post_types[] = 'page'; } $active_post_types = array(); foreach ( $enabled_post_types as $post_type ) { if ( ! empty( $post_type ) && in_array( $post_type, $all_post_types, true ) ) { $active_post_types[] = $post_type; } } /** * Filter: 'sm_sitemap_exclude_post_type' - Allow extending and modifying the post types to exclude. * * @param array $post_types_to_exclude The post types to exclude. */ $post_types_to_exclude = []; $post_types_to_exclude = apply_filters( 'sm_sitemap_exclude_post_types', $post_types_to_exclude ); if ( ! is_array( $post_types_to_exclude ) ) { $post_types_to_exclude = []; } if ( ! empty( $post_types_to_exclude ) ) { foreach ( $active_post_types as $key => $active_post_type ) { if ( in_array( $active_post_type, $post_types_to_exclude ) ) { unset( $active_post_types[ $key ] ); } } } /** * Filter: 'sm_sitemap_include_post_type' - Allow extending and modifying the post types to include. * * @param array $post_types_to_include The post types to include. */ $post_types_to_include = []; $post_types_to_include = apply_filters( 'sm_sitemap_include_post_type', $post_types_to_include ); if ( ! is_array( $post_types_to_include ) ) { $post_types_to_include = []; } if ( ! empty( $post_types_to_include ) ) { $active_post_types = array_merge( $active_post_types, $post_types_to_include ); $active_post_types = array_unique( $active_post_types ); } wp_cache_set( $cache_key, $active_post_types, 'sitemap', 20 ); } return $active_post_types; } /** * Returns an array with all excluded post IDs * * @since 4.0b11 * @return int[] Array with excluded post IDs */ public function get_excluded_post_ids() { $posts_to_exclude = []; $excludes = (array) $this->get_option( 'b_exclude' ); $excluded_posts_ids = array_filter( array_map( 'intval', $excludes ), array( $this, 'is_greater_zero' ) ); /** * Filter: 'sm_exclude_from_sitemap_by_post_ids' - Allow extending and modifying the posts to exclude. * * @param array $posts_to_exclude The posts to exclude. */ $posts_to_exclude = apply_filters( 'sm_exclude_from_sitemap_by_post_ids', $posts_to_exclude ); if ( ! is_array( $posts_to_exclude ) ) { $posts_to_exclude = []; } $excluded_posts_ids = array_merge( $excluded_posts_ids, $posts_to_exclude ); return array_unique( $excluded_posts_ids ); } /** * Robots disallowed */ public function robots_disallowed() { // parse url to retrieve host and path. $parsed = home_url(); $rules = array(); // location of robots.txt file. try { if ( file_exists( $parsed . '/robots.txt' ) ) { $robotstxt = file( $parsed . '/robots.txt' ); } elseif ( file_exists( ABSPATH . '/robots.txt' ) ) { // if there isn't a robots, then we're allowed in. $robotstxt = file( ABSPATH . '/robots.txt' ); } } catch ( Exception $e ) { return $rules; } if ( empty( $robotstxt ) ) { return $rules; } foreach ( $robotstxt as $line ) { $line = trim( $line ); // Skip blank lines . if ( ! $line ) { continue; } if ( preg_match( '/^\s*Disallow:(.*)/i', $line, $regs ) ) { // An empty rule implies full access - no further tests required . if ( ! $regs[1] ) { continue; } // Add rules that apply to array for testing . $id = url_to_postid( home_url( trim( $regs[1] ) ) ); if ( $id > 0 ) { $rules[] = $id; } } } $rules = apply_filters( 'sm_robots_disallowed_ids', array_unique( $rules ) ); return $rules; } /** * Returns an array with all excluded category IDs. * * @since 4.0b11 * @return int[] Array with excluded category IDs */ public function get_excluded_category_i_ds() { $excl_cats = (array) $this->get_option( 'b_exclude_cats' ); return array_filter( array_map( 'intval', $excl_cats ), array( $this, 'is_greater_zero' ) ); } /*************************************** PRIORITY PROVIDERS ***************************************/ /** * Returns the list of PriorityProviders * * @return array */ public function get_prio_providers() { return $this->prio_providers; } /** * Adds the default Priority Providers to the provider list * * @since 3.0 * @param array $providers . * @return array */ public function add_default_prio_providers( $providers ) { array_push( $providers, 'GoogleSitemapGeneratorPrioByCountProvider' ); array_push( $providers, 'GoogleSitemapGeneratorPrioByAverageProvider' ); if ( class_exists( 'ak_popularity_contest' ) ) { array_push( $providers, 'GoogleSitemapGeneratorPrioByPopularityContestProvider' ); } return $providers; } /** * Validates all given Priority Providers by checking them for required methods and existence * * @since 3.0 */ private function validate_prio_providers() { $valid_providers = array(); $len = count( $this->prio_providers ); for ( $i = 0; $i < $len; $i++ ) { if ( class_exists( $this->prio_providers[ $i ] ) ) { if ( class_implements( $this->prio_providers[ $i ], 'Google_Sitemap_Generator_Prio_Provider_Base' ) ) { array_push( $valid_providers, $this->prio_providers[ $i ] ); } } } $this->prio_providers = $valid_providers; if ( ! $this->get_option( 'b_prio_provider' ) ) { if ( ! in_array( $this->get_option( 'b_prio_provider' ), $this->prio_providers, true ) ) { $this->set_option( 'b_prio_provider', '' ); } } } /*************************************** COMMENT HANDLING FOR PRIO. PROVIDERS ***************************************/ /** * Retrieves the number of comments of a post in a asso. array * The key is the post_id, the value the number of comments * * @since 3.0 * @return array An array with post_ids and their comment count */ public function get_comments() { // @var $wpdb wpdb . global $wpdb; $comments = array(); // Query comments and add them into the array . $comment_res = $wpdb->get_results( 'SELECT `comment_post_ID` as `post_id`, COUNT( comment_ID ) as `comment_count` FROM `' . $wpdb->comments . '` WHERE `comment_approved`=\'1\' GROUP BY `comment_post_ID`' ); // db call ok; no-cache ok. if ( $comment_res ) { foreach ( $comment_res as $comment ) { $comments[ $comment->post_id ] = $comment->comment_count; } } return $comments; } /** * Calculates the full number of comments from an sm_getComments() generated array * * @since 3.0 * @param object $comments array The Array with posts and c0mment count . * @see sm_getComments * @return int The full number of comments */ public function get_comment_count( $comments ) { $comment_count = 0; foreach ( $comments as $k => $v ) { $comment_count += $v; } return $comment_count; } /*************************************** OPTION HANDLING ***************************************/ /** * Sets up the default configuration * * @since 3.0 */ public function init_options() { $this->options = array(); $this->options['sm_b_prio_provider'] = 'GoogleSitemapGeneratorPrioByCountProvider'; // Provider for automatic priority calculation . $this->options['sm_b_ping'] = true; // Auto ping Google . $this->options['sm_b_stats'] = false; // Send anonymous stats . $this->options['sm_b_autozip'] = true; // Try to gzip the output . $this->options['sm_b_memory'] = ''; // Set Memory Limit (e.g. 16M) . $this->options['sm_b_time'] = -1; // Set time limit in seconds, 0 for unlimited, -1 for disabled . $this->options['sm_b_style_default'] = true; // Use default style . $this->options['sm_b_style'] = ''; // Include a stylesheet in the XML . $this->options['sm_b_baseurl'] = ''; // The base URL of the sitemap . $this->options['sm_b_rewrites2'] = false; //status updating url rules $this->options['sm_b_indexnow'] = true; //On indexnow functionality $this->options['sm_b_activate_indexnow'] = false; //On indexnow functionality $this->options['sm_b_index_date'] = ''; //On indexnow date $this->options['sm_b_robots'] = true; // Add sitemap location to WordPress' virtual robots.txt file . $this->options['sm_b_html'] = true; // Include a link to a html version of the sitemap in the XML sitemap . $this->options['sm_b_exclude'] = array(); // List of post / page IDs to exclude . $this->options['sm_b_exclude_cats'] = array(); // List of post / page IDs to exclude . $this->options['sm_in_home'] = true; // Include homepage . $this->options['sm_in_posts'] = true; // Include posts . $this->options['sm_in_posts_sub'] = false; // Include post pages (<!--nextpage--> tag) . $this->options['sm_in_pages'] = true; // Include static pages . $this->options['sm_in_cats'] = false; // Include categories . $this->options['sm_product_tags'] = true; // Hide product tags in sitemap . $this->options['sm_in_product_cat'] = true; // Include product categories . $this->options['sm_in_product_assortment'] = true; // Include products . $this->options['sm_in_arch'] = false; // Include archives . $this->options['sm_in_auth'] = false; // Include author pages . $this->options['sm_in_tags'] = false; // Include tag pages . $this->options['sm_in_tax'] = array(); // Include additional taxonomies . $this->options['sm_in_customtypes'] = array(); // Include custom post types . $this->options['sm_in_lastmod'] = true; // Include the last modification date . $this->options['sm_b_sitemap_name'] = 'sitemap'; // Name of custom sitemap. $this->options['sm_b_old_sm_name'] = 'sitemap'; // Name of previously defined sitemap. $this->options['sm_cf_home'] = 'daily'; // Change frequency of the homepage . $this->options['sm_cf_posts'] = 'monthly'; // Change frequency of posts . $this->options['sm_cf_pages'] = 'weekly'; // Change frequency of static pages . $this->options['sm_cf_cats'] = 'weekly'; // Change frequency of categories . $this->options['sm_cf_product_cat'] = 'weekly'; // Change frequency of categories . $this->options['sm_cf_auth'] = 'weekly'; // Change frequency of author pages . $this->options['sm_cf_arch_curr'] = 'daily'; // Change frequency of the current archive (this month) . $this->options['sm_cf_arch_old'] = 'yearly'; // Change frequency of older archives . $this->options['sm_cf_tags'] = 'weekly'; // Change frequency of tags . $this->options['sm_pr_home'] = 1.0; // Priority of the homepage . $this->options['sm_pr_posts'] = 0.6; // Priority of posts (if auto prio is disabled) . $this->options['sm_pr_posts_min'] = 0.2; // Minimum Priority of posts, even if autocalc is enabled . $this->options['sm_pr_pages'] = 0.6; // Priority of static pages . $this->options['sm_pr_cats'] = 0.3; // Priority of categories . $this->options['sm_pr_product_cat'] = 0.3; // Priority of categories . $this->options['sm_pr_arch'] = 0.3; // Priority of archives . $this->options['sm_pr_auth'] = 0.3; // Priority of author pages . $this->options['sm_pr_tags'] = 0.3; // Priority of tags . $this->options['sm_i_donated'] = false; // Did you donate? Thank you! :) . $this->options['sm_i_hide_donated'] = false; // And hide the thank you.. . $this->options['sm_i_install_date'] = time(); // The installation date . $this->options['sm_i_hide_survey'] = false; // Hide the survey note . $this->options['sm_i_hide_note'] = false; // Hide the note which appears after 30 days . $this->options['sm_i_hide_works'] = false; // Hide the 'works?' message which appears after 15 days . $this->options['sm_i_hide_donors'] = false; // Hide the list of donations . $this->options['sm_i_hash'] = substr( sha1( sha1( get_bloginfo( 'url' ) ) ), 0, 20 ); // Partial hash for GA stats, NOT identifiable! . $this->options['sm_i_tid'] = ''; $this->options['sm_i_lastping'] = 0; // When was the last ping . $this->options['sm_i_supportfeed'] = true; // shows the support feed . $this->options['sm_i_supportfeed_cache'] = 0; // Last refresh of support feed . $this->options['sm_links_page'] = 1000; // Link per page support with default value 1000. . $this->options['sm_user_consent'] = false; $this->options['sm_wp_sitemap_status'] = true; } /** * Loads the configuration from the database * * @since 3.0 */ private function load_options() { if ( $this->options_loaded ) { return; } $this->init_options(); // First init default values, then overwrite it with stored values so we can add default // values with an update which get stored by the next edit. $stored_options = get_option( 'sm_options' ); // Custom Taxonomies if ( !empty( $stored_options['sm_in_tax'] ) ) { foreach ( $stored_options['sm_in_tax'] as $custom_tax ) { $this->options[ "sm_cf_" . $custom_tax ] = 'weekly'; // Change frequency of custom taxonomy . $this->options[ "sm_pr_" . $custom_tax ] = 0.3; // Priority of custom taxonomy . } } if ( $stored_options && is_array( $stored_options ) ) { foreach ( $stored_options as $k => $v ) { if ( array_key_exists( $k, $this->options ) ) { $this->options[ $k ] = $v; } } } else { update_option( 'sm_options', $this->options ); // First time use, store default values . } $this->options_loaded = true; } /** * Returns the option value for the given key * * @since 3.0 * @param string $key string The Configuration Key . * @return mixed The value */ public function get_option( $key ) { $key = 'sm_' . $key; if ( array_key_exists( $key, $this->options ) ) { return $this->options[ $key ]; } else { return null; } } /** * Get options . */ public function get_options() { return $this->options; } /** * Sets an option to a new value * * @since 3.0 * @param string $key string The configuration key . * @param string $value mixed The new object . */ public function set_option( $key, $value ) { if ( 0 !== strpos( $key, 'sm_' ) ) { $key = 'sm_' . $key; } $this->options[ $key ] = $value; } /** * Saves the options back to the database * * @since 3.0 * @return bool true on success */ public function save_options() { $oldvalue = get_option( 'sm_options' ); // add_filter('pre_update_option_sm_options', [$this,'modify_excluded_sitemap_ids'], 10, 2); if ( $oldvalue === $this->options ) { return true; } else { return update_option( 'sm_options', $this->options ); } } /** * Excluded posts via code */ public function modify_excluded_sitemap_ids($new_value, $old_value) { $hidden_product_ids = $this->exclude_hidden_products_from_sitemap(); $new_value['sm_b_exclude'] = array_unique($hidden_product_ids); return $new_value; } public function exclude_hidden_products_from_sitemap(){ $excludedArray = []; // here array of posts ID return $excludedArray; } /** * Returns the additional pages * * @since 4.0 * @return GoogleSitemapGeneratorPage[] */ public function get_pages() { return $this->pages; } /** * Returns the additional pages * * @since 4.0 * @param array $pages . */ public function set_pages( array $pages ) { $this->pages = $pages; } /** * Loads the stored pages from the database * * @since 3.0 */ private function load_pages() { // @var $wpdb wpdb . global $wpdb; $needs_update = false; $pages_string = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'sm_cpages'" ); // db call ok; no-cache ok. // Class sm_page was renamed with 3.0 -> rename it in serialized value for compatibility . if ( ! empty( $pages_string ) && strpos( $pages_string, 'sm_page' ) !== false ) { $pages_string = str_replace( 'O:7:\'sm_page\'', 'O:26:\'GoogleSitemapGeneratorPage\'', $pages_string ); $needs_update = true; } if ( ! empty( $pages_string ) ) { $storedpages = unserialize( $pages_string ); $this->pages = $storedpages; } else { $this->pages = array(); } if ( $needs_update ) { $this->save_pages(); } } /** * Saved the additional pages back to the database * * @since 3.0 * @return true on success */ public function save_pages() { $oldvalue = get_option( 'sm_cpages' ); if ( $oldvalue === $this->pages ) { return true; } else { delete_option( 'sm_cpages' ); // Add the option, Note the autoload=false because when the autoload happens, our class GoogleSitemapGeneratorPage doesn't exist . add_option( 'sm_cpages', $this->pages, '', 'no' ); return true; } } /** * Get the maximum number of entries per XML sitemap. * * @return int The maximum number of entries. */ public function get_entries_per_page() { /** * Filter the maximum number of entries per XML sitemap. * * @param int $entries The maximum number of entries per XML sitemap. */ $entries = (int) apply_filters( 'sm_sitemap_entries_per_page', $this->get_option( 'links_page' ) ); return $entries; } /*************************************** URL AND PATH FUNCTIONS ***************************************/ /** * Returns the URL to the directory where the plugin file is located * * @since 3.0b5 * @return string The URL to the plugin directory */ public function get_plugin_url() { $url = trailingslashit( plugins_url( '', __FILE__ ) ); return $url; } /** * Returns the path to the directory where the plugin file is located * * @since 3.0b5 * @return string The path to the plugin directory */ public function get_plugin_path() { $path = dirname( __FILE__ ); return trailingslashit( str_replace( '\\', '/', $path ) ); } /** * Returns the URL to default XSLT style if it exists * * @since 3.0b5 * @return string The URL to the default stylesheet, empty string if not available. */ public function get_default_style() { $p = $this->get_plugin_path(); if ( file_exists( $p . 'sitemap.xsl' ) ) { $url = $this->get_plugin_url(); // If called over the admin area using HTTPS, the stylesheet would also be https url, even if the site frontend is not. if ( substr( get_bloginfo( 'url' ), 0, 5 ) !== 'https' && substr( $url, 0, 5 ) === 'https' ) { $url = 'http' . substr( $url, 5 ); } if ( isset( $_SERVER['HTTP_HOST'] ) ) { $host = sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ); } $url = $this->get_xsl_url( $url, $host ); return $url . 'sitemap.xsl'; } return ''; } /** * Returns of Permalinks are used * * @return bool */ public function is_using_permalinks() { // @var $wp_rewrite WP_Rewrite . global $wp_rewrite; return $wp_rewrite->using_mod_rewrite_permalinks(); } /** * Registers the plugin specific rewrite rules * * Combined: sitemap(-+([a-zA-Z0-9_-]+))?\.(xml|html)(.gz)?$ * * @since 4.0 * @param string $wp_rules Array of existing rewrite rules. * @return Array An array containing the new rewrite rules. */ public static function add_rewrite_rules( $wp_rules ) { $sm_sitemap_name = $GLOBALS['sm_instance']->get_option( 'b_sitemap_name' ); $sm_rules = array( $sm_sitemap_name . '(-+([a-zA-Z0-9_-]+))?\.xml$' => 'index.php?xml_sitemap=params=$matches[2]', $sm_sitemap_name . '(-+([a-zA-Z0-9_-]+))?\.xml\.gz$' => 'index.php?xml_sitemap=params=$matches[2];zip=true', $sm_sitemap_name . '(-+([a-zA-Z0-9_-]+))?\.html$' => 'index.php?xml_sitemap=params=$matches[2];html=true', $sm_sitemap_name . '(-+([a-zA-Z0-9_-]+))?\.html.gz$' => 'index.php?xml_sitemap=params=$matches[2];html=true;zip=true', ); return array_merge( $sm_rules, $wp_rules ); } /** * Adds the filters for wp rewrite rule adding * * @since 4.0 * @uses add_filter() */ public static function setup_rewrite_hooks() { add_filter( 'rewrite_rules_array', array( __CLASS__, 'add_rewrite_rules' ), 1, 1 ); } /** * Removes the filters for wp rewrite rule adding * * @since 4.0 * @uses remove_filter() */ public static function remove_rewrite_hooks() { add_filter( 'rewrite_rules_array', array( __CLASS__, 'remove_rewrite_rules' ), 1, 1 ); } /** * Deregisters the plugin specific rewrite rules * * Combined: sitemap(-+([a-zA-Z0-9_-]+))?\.(xml|html)(.gz)?$ * * @since 4.0 * @param array $wp_rules Array of existing rewrite rules. * @return Array An array containing the new rewrite rules */ public static function remove_rewrite_rules( $wp_rules ) { $sm_rules = array( 'sitemap(-+([a-zA-Z0-9_-]+))?\.xml$' => 'index.php?xml_sitemap=params=$matches[2]', 'sitemap(-+([a-zA-Z0-9_-]+))?\.xml\.gz$' => 'index.php?xml_sitemap=params=$matches[2];zip=true', 'sitemap(-+([a-zA-Z0-9_-]+))?\.html$' => 'index.php?xml_sitemap=params=$matches[2];html=true', 'sitemap(-+([a-zA-Z0-9_-]+))?\.html.gz$' => 'index.php?xml_sitemap=params=$matches[2];html=true;zip=true', 'post(-+([a-zA-Z0-9_-]+))?\.xml$' => 'index.php?xml_sitemap=params=$matches[2]', ); foreach ( $wp_rules as $key => $value ) { if ( array_key_exists( $key, $sm_rules ) ) { unset( $wp_rules[ $key ] ); } } return $wp_rules; } /** * Returns the URL for the sitemap file * * @since 3.0 * * @param string $type . * @param string $params . * @param array $build_options . * @return string The URL to the Sitemap file */ public function get_xml_url( $type = '', $params = '', $build_options = array() ) { $pl = $this->is_using_permalinks(); $options = ''; if ( ! empty( $type ) ) { if($type != 'pt') $options .= $type; if ( ! empty( $params ) ) { //$options .= '-' . $params; $options .= $params; } } $build_options = array_merge( $this->build_options, $build_options ); $html = ( isset( $build_options['html'] ) ? $build_options['html'] : false ); $zip = ( isset( $build_options['zip'] ) ? $build_options['zip'] : false ); $base_url = get_bloginfo( 'url' ); // Manual override for root URL . $base_url_settings = $this->get_option( 'b_baseurl' ); $sm_sitemap_name = $this->get_option( 'b_sitemap_name' ); $old_sm_name = $this->get_option( 'b_old_sm_name' ); if ( ! empty( $base_url_settings ) ) { $base_url = $base_url_settings; } elseif ( defined( 'SM_BASE_URL' ) && SM_BASE_URL ) { $base_url = SM_BASE_URL; } global $wp_rewrite; if ( $old_sm_name !== $sm_sitemap_name ) { $this->set_option( 'sm_b_old_sm_name', $sm_sitemap_name ); delete_option( 'sm_rewrite_done' ); wp_clear_scheduled_hook( 'sm_ping_daily' ); self::remove_rewrite_hooks(); $wp_rewrite->flush_rules( false ); self::setup_rewrite_hooks(); GoogleSitemapGeneratorLoader::activate_rewrite(); } if ( $pl ) { //return trailingslashit( $base_url ) . ( '' === $sm_sitemap_name ? 'sitemap' : $sm_sitemap_name ) . ( $options ? '-' . $options : '' ) . ( $html // ? '.html' : '.xml' ) . ( $zip ? '.gz' : '' ); if($type === 'misc') return trailingslashit( $base_url ) . ( '' === $sm_sitemap_name ? 'sitemap' : $sm_sitemap_name ) . ( $options ? '-' . $options : '' ) . ( $html ? '.html' : '.xml' ) . ( $zip ? '.gz' : '' ); else if($type === 'main') return trailingslashit( $base_url ). ( substr($_SERVER['REQUEST_URI'], -4) === '.xml' ? '.html' : '.html' ) . ( $zip ? '.gz' : '' ); else return trailingslashit( $base_url ) . ( '' !== $sm_sitemap_name ? '' : $sm_sitemap_name ) . ( $options ? '' . $options : '' ) . ( $html ? '.html' : '.xml' ) . ( $zip ? '.gz' : '' ); } else { return trailingslashit( $base_url ) . 'index.php?xml_sitemap=params=' . $options . ( $html ? ';html=true' : '' ) . ( $zip ? ';zip=true' : '' ); } } /* Returns base sitemap url */ public function get_base_sitemap_url(){ $build_options = []; $build_options = array_merge( $this->build_options, $build_options ); $html = ( isset( $build_options['html'] ) ? $build_options['html'] : false ); $zip = ( isset( $build_options['zip'] ) ? $build_options['zip'] : false ); $base_url = get_bloginfo( 'url' ); if($this->get_options()['sm_b_sitemap_name']) $file_name = $this->get_options()['sm_b_sitemap_name']; return trailingslashit( $base_url ) . ($file_name?$file_name:'sitemap') . ( $html ? '.html' : '.xml' ) . ( $zip ? '.gz' : '' ); } /** * Returns if there is still an old sitemap file in the site directory * * @return Boolean True if a sitemap file still exists */ public function old_file_exists() { $sm_sitemap_name = $this->get_option( 'b_sitemap_name' ); $path = trailingslashit( get_home_path() ); return ( file_exists( $path . $sm_sitemap_name . '.xml' ) || file_exists( $path . 'sitemap.xml.gz' ) ); } /** * Renames old sitemap files in the site directory from previous versions of this plugin * * @return bool True on success */ public function delete_old_files() { $path = trailingslashit( get_home_path() ); $res = true; $f = $path . 'sitemap.xml'; if ( file_exists( $f ) ) { if ( ! rename( $f, $path . 'sitemap.backup.xml' ) ) { $res = false; } } $f = $path . 'sitemap.xml.gz'; if ( file_exists( $f ) ) { if ( ! rename( $f, $path . 'sitemap.backup.xml.gz' ) ) { $res = false; } } return $res; } /*************************************** SITEMAP SIMULATION ***************************************/ /** * Simulates the building of the sitemap index file. * * @see GoogleSitemapGenerator::simulate_sitemap * @since 4.0 * @return array The data of the sitemap index file */ public function simulate_index() { $this->sim_mode = true; require_once trailingslashit( dirname( __FILE__ ) ) . 'class-googlesitemapgeneratorstandardbuilder.php'; do_action( 'sm_build_index', $this ); $this->sim_mode = false; $r = $this->sim_data['sitemaps']; $this->clear_sim_data( 'sitemaps' ); return $r; } /** * Simulates the building of the sitemap file. * * @see GoogleSitemapGenerator::simulate_index * @since 4.0 * @param string $type string The type of the sitemap . * @param string $params string Additional parameters for this type . * @return array The data of the sitemap file */ public function simulate_sitemap( $type, $params ) { $this->sim_mode = true; require_once trailingslashit( dirname( __FILE__ ) ) . 'class-googlesitemapgeneratorstandardbuilder.php'; do_action( 'sm_build_content', $this, $type, $params ); $this->sim_mode = false; $r = $this->sim_data['content']; $this->clear_sim_data( 'content' ); return $r; } /** * Clears the data of the simulation * * @param string $what Defines what to clear, either both, sitemaps or content . * @see GoogleSitemapGenerator::simulate_index * @see GoogleSitemapGenerator::simulate_sitemap * @since 4.0 */ public function clear_sim_data( $what ) { if ( 'both' === $what || 'sitemaps' === $what ) { $this->sim_data['sitemaps'] = array(); } if ( 'both' === $what || 'content' === $what ) { $this->sim_data['content'] = array(); } } /** * Returns the first caller outside of this __CLASS__ * * @param array $trace The backtrace . * @return array The caller information */ private function get_external_backtrace( $trace ) { $caller = null; foreach ( $trace as $b ) { if ( __CLASS__ !== $b['class'] ) { $caller = $b; break; } } return $caller; } /*************************************** SITEMAP BUILDING ***************************************/ /** * Shows the sitemap. Main entry point from HTTP * * @param string $options Options for the sitemap. What type, what parameters. * @since 4.0 */ public function show_sitemap( $options ) { $start_time = microtime( true ); $start_queries = $GLOBALS['wpdb']->num_queries; $start_memory = memory_get_peak_usage( true ); $disable_functions = ini_get( 'disable_functions' ); // Raise memory and time limits . if ( $this->get_option( 'b_memory' ) !== '' ) { wp_raise_memory_limit( $this->get_option( 'b_memory' ) ); } if ( $this->get_option( 'b_time' ) !== -1 && $this->get_option( 'b_time' ) !== null ) { if ( strpos( $disable_functions, 'set_time_limit' ) === false ) { set_time_limit( $this->get_option( 'b_time' ) ); } } do_action( 'sm_init', $this ); $this->is_active = true; $parsed_options = array(); $options = explode( ';', $options ); foreach ( $options as $k ) { $kv = explode( '=', $k ); $parsed_options[ $kv[0] ] = $kv[1]; } $options = $parsed_options; $this->build_options = $options; // Do not index the actual XML pages, only process them. // This avoids that the XML sitemaps show up in the search results. if ( ! headers_sent() && isset( $this->build_options['html'] ) ) { if ( $this->build_options['html'] == "true" ) { header( 'X-Robots-Tag: index, follow', true, 200 ); } } $this->initate(); $html = ( isset( $options['html'] ) ? $options['html'] : false ) && $this->is_xsl_enabled(); if ( $html && ! $this->get_option( 'b_html' ) ) { $GLOBALS['wp_query']->is_404 = true; return; } // Don't zip if anything happened before which could break the output or if the client does not support gzip. // If there are already other output filters, there might be some content on another // filter level already, which we can't detect. Zipping then would lead to invalid content. $pack = ( isset( $options['zip'] ) ? $options['zip'] : $this->get_option( 'b_autozip' ) ); if ( empty( $_SERVER['HTTP_ACCEPT_ENCODING'] ) // No encoding support. || strpos( sanitize_text_field( wp_unslash( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ), 'gzip' ) === false // or no gzip. || ! $this->is_gzip_enabled() // No PHP gzip support. || headers_sent() // Headers already sent. || ob_get_contents() // there was already some output.... || in_array( 'ob_gzhandler', ob_list_handlers(), true ) // Some other plugin (or PHP) is already gzipping. || $this->get_php_ini_boolean( ini_get( 'zlib.output_compression' ) ) // Zlib compression in php.ini enabled. || ob_get_level() > ( ! $this->get_php_ini_boolean( ini_get( 'output_buffering' ) ) ? 0 : 1 ) // Another output buffer (beside of the default one) is already active. || ( isset( $_SERVER['HTTP_X_VARNISH'] ) && is_numeric( $_SERVER['HTTP_X_VARNISH'] ) ) // Behind a Varnish proxy. ) { $pack = false; } $packed = false; if ( $pack ) { $packed = ob_start( 'ob_gzhandler' ); } $builders = array( 'class-googlesitemapgeneratorstandardbuilder.php' ); foreach ( $builders as $b ) { $f = trailingslashit( dirname( __FILE__ ) ) . $b; if ( file_exists( $f ) ) { require_once $f; } } if ( $html ) { ob_start(); } else { header( 'Content-Type: text/xml; charset=utf-8' ); } if ( empty( $options['params'] ) || 'index' === $options['params'] ) { $this->build_sitemap_header( 'index' ); do_action( 'sm_build_index', $this ); $this->build_sitemap_footer( 'index' ); $this->add_end_commend( $start_time, $start_queries, $start_memory ); } else { $all_params = $options['params']; $type = null; $params = null; if ( strpos( $all_params, '-' ) !== false ) { $type = substr( $all_params, 0, strpos( $all_params, '-' ) ); if($type === 'pt' && explode("-", $all_params)[1] === 'externals' ) $type = 'externals'; $params = substr( $all_params, strpos( $all_params, '-' ) + 1 ); } else { $type = $all_params; } $this->build_sitemap_header( 'sitemap' ); do_action( 'sm_build_content', $this, $type, $params ); $this->build_sitemap_footer( 'sitemap' ); $this->add_end_commend( $start_time, $start_queries, $start_memory ); } if ( $html ) { $xml_source = ob_get_clean(); // Load the XML source. $xml = new DOMDocument(); $xml->loadXML( $xml_source ); $xsl = new DOMDocument(); $xsl->load( $this->get_plugin_path() . 'sitemap.xsl' ); // Configure the transformer. $proc = new XSLTProcessor(); $proc->importStyleSheet( $xsl ); // Attach the xsl rules. $dom_tran_obj = $proc->transformToDoc( $xml ); // This will also output doctype and comments at top level. // phpcs:disable global $allowedposttags; $allowed_atts = array( 'align' => array(), 'class' => array(), 'type' => array(), 'id' => array(), 'dir' => array(), 'lang' => array(), 'style' => array(), 'xml:lang' => array(), 'src' => array(), 'alt' => array(), 'href' => array(), 'rel' => array(), 'rev' => array(), 'target' => array(), 'novalidate' => array(), 'type' => array(), 'value' => array(), 'name' => array(), 'tabindex' => array(), 'action' => array(), 'method' => array(), 'for' => array(), 'width' => array(), 'height' => array(), 'data' => array(), 'title' => array(), ); $allowedposttags['form'] = $allowed_atts; $allowedposttags['label'] = $allowed_atts; $allowedposttags['input'] = $allowed_atts; $allowedposttags['textarea'] = $allowed_atts; $allowedposttags['iframe'] = $allowed_atts; $allowedposttags['script'] = $allowed_atts; $allowedposttags['style'] = $allowed_atts; $allowedposttags['strong'] = $allowed_atts; $allowedposttags['small'] = $allowed_atts; $allowedposttags['table'] = $allowed_atts; $allowedposttags['span'] = $allowed_atts; $allowedposttags['abbr'] = $allowed_atts; $allowedposttags['code'] = $allowed_atts; $allowedposttags['pre'] = $allowed_atts; $allowedposttags['div'] = $allowed_atts; $allowedposttags['img'] = $allowed_atts; $allowedposttags['h1'] = $allowed_atts; $allowedposttags['h2'] = $allowed_atts; $allowedposttags['h3'] = $allowed_atts; $allowedposttags['h4'] = $allowed_atts; $allowedposttags['h5'] = $allowed_atts; $allowedposttags['h6'] = $allowed_atts; $allowedposttags['ol'] = $allowed_atts; $allowedposttags['ul'] = $allowed_atts; $allowedposttags['li'] = $allowed_atts; $allowedposttags['em'] = $allowed_atts; $allowedposttags['hr'] = $allowed_atts; $allowedposttags['br'] = $allowed_atts; $allowedposttags['tr'] = $allowed_atts; $allowedposttags['td'] = $allowed_atts; $allowedposttags['p'] = $allowed_atts; $allowedposttags['a'] = $allowed_atts; $allowedposttags['b'] = $allowed_atts; $allowedposttags['i'] = $allowed_atts; foreach ( $dom_tran_obj->childNodes as $node ) { // phpcs:enable echo wp_kses( $dom_tran_obj->saveXML( $node ), $allowedposttags ) . "\n"; } } if ( $packed ) { ob_end_flush(); } $this->is_active = false; exit; } /** * Generates the header for the sitemap with XML declarations, stylesheet and so on. * * @since 4.0 * @param string $format The format, either sitemap for a sitemap or index for the sitemap index . */ private function build_sitemap_header( $format ) { if ( ! in_array( $format, array( 'sitemap', 'index' ), true ) ) { $format = 'sitemap'; } $this->add_element( new GoogleSitemapGeneratorXmlEntry( '<?xml version=\'1.0\' encoding=\'UTF-8\'?>' ) ); $style_sheet = ( $this->get_default_style() && $this->get_option( 'b_style_default' ) === true ? $this->get_default_style() : $this->get_option( 'b_style' ) ); if ( ! empty( $style_sheet ) ) { $this->add_element( new GoogleSitemapGeneratorXmlEntry( '<' . '?xml-stylesheet type=\'text/xsl\' href=\'' . esc_url( $style_sheet ) . '\'?>' ) ); } $this->add_element( new GoogleSitemapGeneratorDebugEntry( 'sitemap-generator-url=\'http://www.arnebrachhold.de\' sitemap-generator-version=\'' . $this->get_version() . '\'' ) ); $this->add_element( new GoogleSitemapGeneratorDebugEntry( 'generated-on=\'' . gmdate( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ) . '\'' ) ); switch ( $format ) { case 'sitemap': $urlset = '<urlset xmlns:xsi=\'http://www.w3.org/2001/XMLSchema-instance\' xsi:schemaLocation=\'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\' xmlns=\'http://www.sitemaps.org/schemas/sitemap/0.9\'>'; $urlset = apply_filters( 'sm_sitemap_urlset', $urlset ); $this->add_element( new GoogleSitemapGeneratorXmlEntry( $urlset ) ); break; case 'index': $urlset = '<sitemapindex xmlns:xsi=\'http://www.w3.org/2001/XMLSchema-instance\' xsi:schemaLocation=\'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd\' xmlns=\'http://www.sitemaps.org/schemas/sitemap/0.9\'>'; $this->add_element( new GoogleSitemapGeneratorXmlEntry( $urlset ) ); break; } } /** * Generates the footer for the sitemap with XML ending tag * * @since 4.0 * @param string $format The format, either sitemap for a sitemap or index for the sitemap index. */ private function build_sitemap_footer( $format ) { if ( ! in_array( $format, array( 'sitemap', 'index' ), true ) ) { $format = 'sitemap'; } switch ( $format ) { case 'sitemap': $this->add_element( new GoogleSitemapGeneratorXmlEntry( '</urlset>' ) ); break; case 'index': $this->add_element( new GoogleSitemapGeneratorXmlEntry( '</sitemapindex>' ) ); break; } } /** * Adds information about time and memory usage to the sitemap * * @since 4.0 * @param float $start_time The microtime of the start . * @param int $start_queries . * @param int $start_memory . */ private function add_end_commend( $start_time, $start_queries = 0, $start_memory = 0 ) { if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { echo '<!-- '; if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) { echo '<pre>'; // phpcs:disable WordPress.PHP.DevelopmentFunctions var_dump( $GLOBALS['wpdb']->queries ); // phpcs:enable echo '</pre>'; $total = 0; foreach ( $GLOBALS['wpdb']->queries as $q ) { $total += $q[1]; } echo '<h4>Total Query Time</h4>'; echo '<pre>' . count( $GLOBALS['wpdb']->queries ) . ' queries in ' . esc_html( round( $total, 2 ) ) . ' seconds.</pre>'; } else { echo '<p>Please edit wp-db.inc.php in wp-includes and set SAVEQUERIES to true if you want to see the queries.</p>'; } echo ' --> '; } $end_time = microtime( true ); $end_time = round( $end_time - $start_time, 2 ); $spent_memory = intval((memory_get_peak_usage( true ) - $start_memory) / 1024); if ($spent_memory > 1023) { $spent_memory = intval($spent_memory / 1024) . 'MB'; } else { $spent_memory = ceil($spent_memory) + 1 . 'KB'; } //$this->add_element( new GoogleSitemapGeneratorDebugEntry( 'Request ID: ' . md5( microtime() ) . '; Queries for sitemap: ' . ( $GLOBALS['wpdb']->num_queries - $start_queries ) . '; Total queries: ' . $GLOBALS['wpdb']->num_queries . "; Seconds: $end_time; Memory for sitemap: " . ( ( memory_get_peak_usage( true ) - $start_memory ) / 1024 / 1024 ) . 'MB; Total memory: ' . ( memory_get_peak_usage( true ) / 1024 / 1024 ) . 'MB' ) ); $this->add_element( new GoogleSitemapGeneratorDebugEntry( 'Request ID: ' . md5( microtime() ) . '; Queries for sitemap: ' . ( $GLOBALS['wpdb']->num_queries - $start_queries ) . '; Total queries: ' . $GLOBALS['wpdb']->num_queries . "; Seconds: $end_time; Memory for sitemap: " . $spent_memory. '; Total memory: ' . ( memory_get_peak_usage( true ) / 1024 / 1024 ) . 'MB' ) ); } /** * Adds the sitemap to the virtual robots.txt file * This function is executed by WordPress with the do_robots hook * * @since 3.1.2 */ public function do_robots() { $this->initate(); if ( $this->get_option( 'b_robots' ) === true ) { //$sm_url = $this->get_xml_url(); // $html = ( isset( $build_options['html'] ) ? $build_options['html'] : false ); $zip = ( isset( $build_options['zip'] ) ? $build_options['zip'] : false ); $b_html = ( null !== $this->get_option('b_html') ? $this->get_option('b_html') : false ); if ( $this->get_option( 'b_sitemap_name' ) ) { $sm_url = trailingslashit( get_bloginfo( 'url' ) ) . ( '' === $this->get_option( 'b_sitemap_name' ) ? '' : $this->get_option( 'b_sitemap_name' ) ) . '.xml' . ( $zip ? '.gz' : '' ); $sm_html_url = trailingslashit( get_bloginfo( 'url' ) ) . ( '' === $this->get_option( 'b_sitemap_name' ) ? '' : $this->get_option( 'b_sitemap_name' ) ) . '.html' . ( $zip ? '.gz' : '' ); } else { $sm_url = get_bloginfo( 'url' ) . '/sitemap.xml'; $sm_html_url = get_bloginfo( 'url' ) . '/sitemap.html'; } echo "\nSitemap: " . esc_url( $sm_url ) . "\n"; if ( $b_html ) echo "Sitemap: " . esc_url( $sm_html_url ) . "\n"; } } /*************************************** SITEMAP CONTENT BUILDING ***************************************/ /** * Outputs an element in the sitemap * * @since 3.0 * @param object $page GoogleSitemapGeneratorXmlEntry The element . */ public function add_element( $page ) { if ( empty( $page ) ) { return; } // phpcs:disable echo $page->render(); // phpcs:enable } /** * Adds a url to the sitemap. You can use this method or call add_element directly. * * @since 3.0 * @param int $loc string The location (url) of the page . * @param int $last_mod int The last Modification time as a UNIX timestamp . * @param string $change_freq string The change frequenty of the page, Valid values are 'always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly' and 'never'. . * @param float $priority float The priority of the page, between 0.0 and 1.0 . * @param int $post_id int The post ID in case this is a post or page . * @see add_element */ public function add_url( $loc, $last_mod = 0, $change_freq = 'monthly', $priority = 0.5, $post_id = 0 ) { // Strip out the last modification time if activated . if ( $this->get_option( 'in_lastmod' ) === false ) { $last_mod = 0; } $page = new GoogleSitemapGeneratorPage( $loc, $priority, $change_freq, $last_mod, $post_id ); do_action( 'sm_addurl', $page ); if ( $this->sim_mode ) { // phpcs:disable WordPress.PHP.DevelopmentFunctions $caller = $this->get_external_backtrace( debug_backtrace() ); // phpcs:enable $this->sim_data['content'][] = array( 'data' => $page, 'caller' => $caller, ); } else { $this->add_element( $page ); } } /** * Add a sitemap entry to the index file * * @param string $type . * @param string $params . * @param int $last_mod . */ public function add_sitemap( $type, $params = '', $last_mod = 0 ) { $url = $this->get_xml_url( $type, $params ); $sitemap = new GoogleSitemapGeneratorSitemapEntry( $url, $last_mod ); do_action( 'sm_addsitemap', $sitemap ); if ( $this->sim_mode ) { // phpcs:disable WordPress.PHP.DevelopmentFunctions $caller = $this->get_external_backtrace( debug_backtrace() ); // phpcs:enable $this->sim_data['sitemaps'][] = array( 'data' => $sitemap, 'type' => $type, 'params' => $params, 'caller' => $caller, ); } else { $this->add_element( $sitemap ); } } /*************************************** PINGS ***************************************/ /** * Sends the pings to the search engines * * @return GoogleSitemapGeneratorStatus The status object */ public function send_ping() { $this->load_options(); $ping_url = $this->get_xml_url(); $baseUrl = substr($ping_url, 0, -4); $kind = substr($ping_url, -4); $ping_url = $baseUrl . $this->get_options()['sm_b_sitemap_name'] . $kind; $result = $this->execute_ping( $ping_url, true ); $post_id = get_transient( 'sm_ping_post_id' ); if ( $post_id ) { require_once trailingslashit( dirname( __FILE__ ) ) . 'class-googlesitemapgeneratorstandardbuilder.php'; $urls = array(); $urls = apply_filters( 'sm_sitemap_for_post', $urls, $this, $post_id ); if ( is_array( $urls ) && count( $urls ) > 0 ) { foreach ( $urls as $url ) { $this->execute_ping( $url, false ); } } delete_transient( 'sm_ping_post_id' ); } return $result; } /** * Execute Ping * * @param string $ping_url string The Sitemap URL to ping . * @param bool $update_status If the global ping status should be updated . * * @return \GoogleSitemapGeneratorStatus */ protected function execute_ping( $ping_url, $update_status = true ) { $status = new GoogleSitemapGeneratorStatus( $update_status ); if ( $ping_url ) { $pings = array(); if ( $this->get_option( 'b_ping' ) ) { $pings['bing'] = array( 'name' => 'Bing', 'check' => 'successfully', ); } if ($pings) { foreach ( $pings as $service_id => $service ) { //$url = rawurlencode( $ping_url ); $url = $ping_url; $status->start_ping( $service_id, $url, $service['name'] ); $newUrlToIndex = new GoogleSitemapGeneratorIndexNow(); $pingres = $newUrlToIndex->start( $url ); if ( null === $pingres || false === $pingres || false === strpos( $pingres, $service['check'] ) ) { $status->end_ping( $service_id, false ); } else { $status->end_ping( $service_id, true ); } } } $this->set_option( 'i_lastping', time() ); $this->save_options(); } $status->end(); return $status; } /** * Tries to ping a specific service showing as much as debug output as possible * * @since 4.1 * @return array */ public function send_ping_all() { $this->load_options(); $sitemaps = $this->simulate_index(); $urls = array(); $ping_url = $this->get_xml_url(); $baseUrl = substr($ping_url, 0, -4); $kind = substr($ping_url, -4); $urls[] = $baseUrl . $this->get_options()['sm_b_sitemap_name'] . $kind; //$urls[] = $this->get_xml_url(); foreach ( $sitemaps as $sitemap ) { // @var $s GoogleSitemapGeneratorSitemapEntry . $s = $sitemap['data']; $urls[] = $s->get_url(); } $results = array(); $first = true; foreach ( $urls as $url ) { $status = $this->execute_ping( $url, $first ); $results[] = array( 'sitemap' => $url, 'status' => $status, ); $first = false; } return $results; } /** * Tries to ping a specific service showing as much as debug output as possible * * @since 3.1.9 * @return null */ public function show_ping_result() { check_admin_referer( 'sitemap' ); if ( ! current_user_can( 'administrator' ) ) { echo '<p>Please log in as admin</p>'; return; } $service = ! empty( $_GET['sm_ping_service'] ) ? sanitize_text_field( wp_unslash( $_GET['sm_ping_service'] ) ) : null; $status = GoogleSitemapGeneratorStatus::load(); if ( ! $status ) { die( 'No build status yet. Write something first.' ); } $url = null; $services = $status->get_used_ping_services(); if ( ! in_array( $service, $services, true ) ) { die( 'Invalid service' ); } $url = $status->get_ping_url( $service ); if ( empty( $url ) ) { die( 'Invalid ping url' ); } echo '<html><head><title>Ping Test</title>'; if ( function_exists( 'wp_admin_css' ) ) { wp_admin_css( 'css/global', true ); } echo '</head><body><h1>Ping Test</h1>'; echo '<p>Trying to ping: <a href=\'' . esc_url( $url ) . '\'>' . esc_html( $url ) . '</a>. The sections below should give you an idea whats going on.</p>'; // Try to get as much as debug / error output as possible . $err_level = error_reporting( E_ALL ); if ( ! defined( 'WP_DEBUG_DISPLAY' ) ) { define( 'WP_DEBUG_DISPLAY', true ); } if ( ! defined( 'WP_DEBUG' ) ) { define( 'WP_DEBUG', true ); } echo '<h2>Errors, Warnings, Notices:</h2>'; if ( WP_DEBUG === false ) { echo '<i>WP_DEBUG was set to false somewhere before. You might not see all debug information until you remove this declaration!</i><br />'; } if ( ini_get( 'display_errors' ) !== 1 ) { echo '<i>Your display_errors setting currently prevents the plugin from showing errors here. Please check your webserver logfile instead.</i><br />'; } $res = $this->remote_open( $url ); echo '<h2>Result (text only):</h2>'; echo wp_kses( $res, array( 'a' => array( 'href' => array() ), 'p' => array(), 'ul' => array(), 'ol' => array(), 'li' => array(), ) ); echo '<h2>Result (HTML):</h2>'; esc_html( htmlspecialchars( $res ) ); // Revert back old values . // error_reporting( $err_level ); . echo '</body></html>'; exit; } /** * Opens a remote file using the WordPress API * * @since 3.0 * @param string $url string The URL to open . * @param string $method string get or post . * @param object $post_data array An array with key=>value paris . * @param int $timeout int Timeout for the request, by default 10 . * @return mixed False on error, the body of the response on success */ public static function remote_open( $url, $method = 'get', $post_data = null, $timeout = 10 ) { $options = array(); $options['timeout'] = $timeout; if ( 'get' === $method ) { $response = wp_remote_get( $url, $options ); } else { $response = wp_remote_post( $url, array_merge( $options, array( 'body' => $post_data, ) ) ); } if ( is_wp_error( $response ) ) { $errs = $response->get_error_messages(); $errs = htmlspecialchars( implode( '; ', $errs ) ); // phpcs:disable WordPress.PHP.DevelopmentFunctions trigger_error( 'WP HTTP API Web Request failed: ' . esc_html( $errs ), E_USER_NOTICE ); // phpcs:enable return false; } return $response['body']; } /** * Sends anonymous statistics (disabled by default) */ private function send_stats() { global $wp_version, $wpdb; $post_count = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->posts} p WHERE p.post_status='publish'" ); // db call ok; no-cache ok. // Send simple post count statistic to get an idea in which direction this plugin should be optimized . // Only a rough number is required, so we are rounding things up . if ( $post_count <= 5 ) { $post_count = 5; } elseif ( $post_count < 25 ) { $post_count = 10; } elseif ( $post_count < 35 ) { $post_count = 25; } elseif ( $post_count < 75 ) { $post_count = 50; } elseif ( $post_count < 125 ) { $post_count = 100; } elseif ( $post_count < 2000 ) { $post_count = round( $post_count / 200 ) * 200; } elseif ( $post_count < 10000 ) { $post_count = round( $post_count / 1000 ) * 1000; } else { $post_count = round( $post_count / 10000 ) * 10000; } $user = wp_get_current_user(); $post_data = array( 'v' => 1, 'tid' => $this->get_option( 'i_tid' ), 'cid' => $this->get_option( 'i_hash' ), 'aip' => 1, // Anonymize . 't' => 'event', 'ec' => 'ping', 'el' => 'settings_saved', 'ea' => 'auto', 'ev' => 1, 'cd1' => $wp_version, 'cd2' => $this->get_version(), 'cd3' => PHP_VERSION, 'cd4' => $post_count, 'cd5' => $user->user_email, 'cd6' => 'https://' . $_SERVER['HTTP_HOST'], 'ul' => get_bloginfo( 'language' ), ); $this->remote_open( 'http://www.google-analytics.com/collect', 'post', $post_data ); } /** * Returns the number of seconds the support feed should be cached (1 week) * * @return int The number of seconds */ public static function get_support_feed_cache_lifetime() { return 60 * 60 * 24 * 7; } /** * Returns the SimplePie instance of the support feed * The feed is cached for one week * * @return SimplePie|WP_Error */ public function get_support_feed() { $call_back = array( __CLASS__, 'get_support_feed_cache_lifetime' ); // Extend cache lifetime so we don't request the feed to often . add_filter( 'wp_feed_cache_transient_lifetime', $call_back ); $result = fetch_feed( SM_SUPPORTFEED_URL ); remove_filter( 'wp_feed_cache_transient_lifetime', $call_back ); return $result; } /** * Handles daily ping */ public function send_ping_daily() { $this->load_options(); $blog_update = strtotime( get_lastpostdate( 'blog' ) ); $last_ping = $this->get_option( 'i_lastping' ); $yesterday = time() - ( 60 * 60 * 24 ); if ( $blog_update >= $yesterday && ( 0 === $last_ping || $last_ping <= $yesterday ) ) { $this->send_ping(); } // Send statistics if enabled (disabled by default) . if ( $this->get_option( 'b_stats' ) ) { $this->send_stats(); } // Cache the support feed so there is no delay when loading the user interface . if ( $this->get_option( 'i_supportfeed' ) ) { $last = $this->get_option( 'i_supportfeed_cache' ); if ( $last <= ( time() - $this->get_support_feed_cache_lifetime() ) ) { $support_feed = $this->get_support_feed(); if ( ! is_wp_error( $support_feed ) && $support_feed ) { $this->set_option( 'i_supportfeed_cache', time() ); $this->save_options(); } } } } /*************************************** USER INTERFACE ***************************************/ /** * Includes the user interface class and initializes it * * @since 3.1.1 * @see GoogleSitemapGeneratorUI * @return GoogleSitemapGeneratorUI */ private function get_ui() { if ( null === $this->ui ) { $class_name = 'GoogleSitemapGeneratorUI'; $file_name = 'class-googlesitemapgeneratorui.php'; if ( ! class_exists( $class_name ) ) { $path = trailingslashit( dirname( __FILE__ ) ); if ( ! file_exists( $path . $file_name ) ) { return false; } require_once $path . $file_name; } $this->ui = new $class_name( $this, new GoogleSitemapGeneratorIndexNow() ); } return $this->ui; } /** * Shows the option page of the plugin. Before 3.1.1, this function was basically the UI, afterwards the UI was outsourced to another class * * @see GoogleSitemapGeneratorUI * @since 3.0 * @return bool */ public function html_show_options_page() { $ui = $this->get_ui(); if ( $ui ) { $ui->html_show_options_page(); return true; } return false; } /*************************************** HELPERS ***************************************/ /** * Returns if the given value is greater than zero * * @param int $value int The value to check . * @since 4.0b10 * @return bool True if greater than zero */ public function is_greater_zero( $value ) { return ( $value > 0 ); } /** * Converts the various possible php.ini values for true and false to boolean * * @param string $value string The value from ini_get . * * @return bool The converted value */ public function get_php_ini_boolean( $value ) { if ( is_string( $value ) ) { switch ( strtolower( $value ) ) { case '+': case '1': case 'y': case 'on': case 'yes': case 'true': case 'enabled': return true; case '-': case '0': case 'n': case 'no': case 'off': case 'false': case 'disabled': return false; } } return (bool) $value; } /** * Show surevey method . */ public function show_survey() { $this->load_options(); if ( isset( $_REQUEST['sm_survey'] ) ) { return ( sanitize_text_field( wp_unslash( $_REQUEST['sm_survey'] ) ) ) || ! $this->get_option( 'i_hide_survey' ); } } /** * Html survey method . */ public function html_survey() { ?> <div class='updated'> <strong> <p> <?php esc_html( str_replace( '%s', 'https://w3edge.wufoo.com/forms/mex338s1ysw3i0/', /* translators: %s: search term */ __( 'Thank you for using Google XML Sitemaps! <a href=\'%s\' target=\'_blank\'>Please help us improve by taking this short survey!</a>', 'google-sitemap-generator' ) ) ); ?> <a href='<?php esc_url( $this->get_back_link() ) . '&sm_hide_survey=true'; ?>' style='float:right; display:block; border:none;'><small style='font-weight:normal; '><?php esc_html_e( 'Don\'t show this anymore', 'google-sitemap-generator' ); ?></small></a> </p> </strong> <div style='clear:right;'></div> </div> <?php } /** * Get xsl url method . * * @param string $url . * @param string $host . */ public function get_xsl_url( $url, $host ) { if ( substr( $host, 0, 4 ) === 'www.' ) { if ( substr( get_bloginfo( 'url' ), 0, 5 ) !== 'https' ) { if ( strpos( $url, 'www.' ) === false ) { $url = str_replace( 'http://', 'http://www.', $url ); } } else { if ( strpos( $url, 'www.' ) === false ) { $url = str_replace( 'https://', 'https://www.', $url ); } } } else { if ( strpos( $url, 'www.' ) !== false ) { $url = str_replace( '://www.', '://', $url ); } } return $url; } }