forked from LiveCarta/LiveCartaWP
2928 lines
82 KiB
PHP
2928 lines
82 KiB
PHP
<?php
|
|
/**
|
|
* Default sitemap core class
|
|
*
|
|
* @package Sitemap
|
|
* @author Arne Brachhold
|
|
* @since 4.0
|
|
*/
|
|
|
|
use function Bhittani\StarRating\functions\sanitize;
|
|
/**
|
|
* $Id: sitemap-core.php 3105873 2024-06-22 03:26:37Z 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;
|
|
}
|
|
}
|