You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2962 lines
94 KiB
2962 lines
94 KiB
8 years ago
|
<?php
|
||
|
/**
|
||
|
* Sitemap class.
|
||
|
*
|
||
|
* @package All-in-One-SEO-Pack
|
||
|
*/
|
||
|
|
||
|
if ( ! class_exists( 'All_in_One_SEO_Pack_Sitemap' ) ) {
|
||
|
|
||
|
/**
|
||
|
* Class All_in_One_SEO_Pack_Sitemap
|
||
|
*/
|
||
|
class All_in_One_SEO_Pack_Sitemap extends All_in_One_SEO_Pack_Module {
|
||
|
var $cache_struct = null;
|
||
|
var $cache_home = null;
|
||
|
var $comment_string;
|
||
|
var $start_memory_usage = 0;
|
||
|
var $max_posts = 50000;
|
||
|
var $paginate = false;
|
||
|
var $prio;
|
||
|
var $prio_sel;
|
||
|
var $freq;
|
||
|
var $freq_sel;
|
||
|
var $extra_sitemaps;
|
||
|
var $excludes = array();
|
||
|
|
||
|
/**
|
||
|
* All_in_One_SEO_Pack_Sitemap constructor.
|
||
|
*/
|
||
|
function __construct() {
|
||
|
if ( get_class( $this ) === 'All_in_One_SEO_Pack_Sitemap' ) { // Set this up only when instantiated as this class.
|
||
|
$this->name = __( 'XML Sitemap', 'all-in-one-seo-pack' ); // Human-readable name of the plugin.
|
||
|
$this->prefix = 'aiosp_sitemap_'; // Option prefix.
|
||
|
$this->file = __FILE__; // The current file.
|
||
|
$this->extra_sitemaps = array();
|
||
|
$this->extra_sitemaps = apply_filters( $this->prefix . 'extra', $this->extra_sitemaps );
|
||
|
}
|
||
|
parent::__construct();
|
||
|
$this->comment_string = 'Sitemap %s generated by All in One SEO Pack %s by Michael Torbert of Semper Fi Web Design on %s';
|
||
|
|
||
|
$this->help_text = array(
|
||
|
'filename' => __( "Specifies the name of your sitemap file. This will default to 'sitemap'.", 'all-in-one-seo-pack' ),
|
||
|
'daily_cron' => __( 'Notify search engines based on the selected schedule, and also update static sitemap daily if in use. (this uses WP-Cron, so make sure this is working properly on your server as well)', 'all-in-one-seo-pack' ),
|
||
|
'indexes' => __( 'Organize sitemap entries into distinct files in your sitemap. Enable this only if your sitemap contains over 50,000 URLs or the file is over 5MB in size.', 'all-in-one-seo-pack' ),
|
||
|
'paginate' => __( 'Split long sitemaps into separate files.', 'all-in-one-seo-pack' ),
|
||
|
'max_posts' => __( 'Allows you to specify the maximum number of posts in a sitemap (up to 50,000).', 'all-in-one-seo-pack' ),
|
||
|
'posttypes' => __( 'Select which Post Types appear in your sitemap.', 'all-in-one-seo-pack' ),
|
||
|
'taxonomies' => __( 'Select which taxonomy archives appear in your sitemap', 'all-in-one-seo-pack' ),
|
||
|
'archive' => __( 'Include Date Archives in your sitemap.', 'all-in-one-seo-pack' ),
|
||
|
'author' => __( 'Include Author Archives in your sitemap.', 'all-in-one-seo-pack' ),
|
||
|
'gzipped' => __( 'Create a compressed sitemap file in .xml.gz format.', 'all-in-one-seo-pack' ),
|
||
|
'robots' => __( 'Places a link to your Sitemap.xml into your virtual Robots.txt file.', 'all-in-one-seo-pack' ),
|
||
|
'rewrite' => __( 'Dynamically creates the XML sitemap instead of using a static file.', 'all-in-one-seo-pack' ),
|
||
|
'addl_url' => __( 'URL to the page.', 'all-in-one-seo-pack' ),
|
||
|
'addl_prio' => __( 'The priority of the page.', 'all-in-one-seo-pack' ),
|
||
|
'addl_freq' => __( 'The frequency of the page.', 'all-in-one-seo-pack' ),
|
||
|
'addl_mod' => __( 'Last modified date of the page.', 'all-in-one-seo-pack' ),
|
||
|
'excl_categories' => __( 'Entries from these categories will be excluded from the sitemap.', 'all-in-one-seo-pack' ),
|
||
|
'excl_pages' => __( 'Use page slugs or page IDs, seperated by commas, to exclude pages from the sitemap.', 'all-in-one-seo-pack' ),
|
||
|
);
|
||
|
|
||
|
$this->help_anchors = array(
|
||
|
'filename' => '#filename-prefix',
|
||
|
'daily_cron' => '#schedule-updates',
|
||
|
'indexes' => '#enable-sitemap-indexes',
|
||
|
'paginate' => '#enable-sitemap-indexes',
|
||
|
'max_posts' => '#enable-sitemap-indexes',
|
||
|
'posttypes' => '#post-types-and-taxonomies',
|
||
|
'taxonomies' => '#post-types-and-taxonomies',
|
||
|
'archive' => '#include-archive-pages',
|
||
|
'author' => '#include-archive-pages',
|
||
|
'gzipped' => '#create-compressed-sitemap',
|
||
|
'robots' => '#link-from-virtual-robots',
|
||
|
'rewrite' => '#dynamically-generate-sitemap',
|
||
|
'addl_url' => '#additional-pages',
|
||
|
'addl_prio' => '#additional-pages',
|
||
|
'addl_freq' => '#additional-pages',
|
||
|
'addl_mod' => '#additional-pages',
|
||
|
'excl_categories' => '#excluded-items',
|
||
|
'excl_pages' => '#excluded-items',
|
||
|
);
|
||
|
|
||
|
$this->default_options = array(
|
||
|
'filename' => array(
|
||
|
'name' => __( 'Filename Prefix', 'all-in-one-seo-pack' ),
|
||
|
'default' => 'sitemap',
|
||
|
'type' => 'text',
|
||
|
'sanitize' => 'filename',
|
||
|
),
|
||
|
'daily_cron' => array(
|
||
|
'name' => __( 'Schedule Updates', 'all-in-one-seo-pack' ),
|
||
|
'type' => 'select',
|
||
|
'initial_options' => array(
|
||
|
0 => __( 'No Schedule', 'all-in-one-seo-pack' ),
|
||
|
'daily' => __( 'Daily', 'all-in-one-seo-pack' ),
|
||
|
'weekly' => __( 'Weekly', 'all-in-one-seo-pack' ),
|
||
|
'monthly' => __( 'Monthly', 'all-in-one-seo-pack' ),
|
||
|
),
|
||
|
'default' => 0,
|
||
|
),
|
||
|
'indexes' => array( 'name' => __( 'Enable Sitemap Indexes', 'all-in-one-seo-pack' ) ),
|
||
|
'paginate' => array(
|
||
|
'name' => __( 'Paginate Sitemap Indexes', 'all-in-one-seo-pack' ),
|
||
|
'condshow' => array( "{$this->prefix}indexes" => 'on' ),
|
||
|
),
|
||
|
'max_posts' => array(
|
||
|
'name' => __( 'Maximum Posts Per Sitemap', 'all-in-one-seo-pack' ),
|
||
|
'type' => 'text',
|
||
|
'default' => 50000,
|
||
|
'condshow' => array( "{$this->prefix}indexes" => 'on', "{$this->prefix}paginate" => 'on' ),
|
||
|
),
|
||
|
'posttypes' => array(
|
||
|
'name' => __( 'Post Types', 'all-in-one-seo-pack' ),
|
||
|
'type' => 'multicheckbox',
|
||
|
'default' => 'all',
|
||
|
),
|
||
|
'taxonomies' => array(
|
||
|
'name' => __( 'Taxonomies', 'all-in-one-seo-pack' ),
|
||
|
'type' => 'multicheckbox',
|
||
|
'default' => 'all',
|
||
|
),
|
||
|
'archive' => array( 'name' => __( 'Include Date Archive Pages', 'all-in-one-seo-pack' ) ),
|
||
|
'author' => array( 'name' => __( 'Include Author Pages', 'all-in-one-seo-pack' ) ),
|
||
|
'gzipped' => array(
|
||
|
'name' => __( 'Create Compressed Sitemap', 'all-in-one-seo-pack' ),
|
||
|
'default' => 'On',
|
||
|
),
|
||
|
'robots' => array(
|
||
|
'name' => __( 'Link From Virtual Robots.txt', 'all-in-one-seo-pack' ),
|
||
|
'default' => 'On',
|
||
|
),
|
||
|
'rewrite' => array(
|
||
|
'name' => __( 'Dynamically Generate Sitemap', 'all-in-one-seo-pack' ),
|
||
|
'default' => 'On',
|
||
|
),
|
||
|
);
|
||
|
|
||
|
$status_options = array(
|
||
|
'link' => array( 'default' => '', 'type' => 'html', 'label' => 'none', 'save' => false ),
|
||
|
);
|
||
|
|
||
|
$this->layout = array(
|
||
|
'status' => array(
|
||
|
'name' => __( 'Sitemap Status', 'all-in-one-seo-pack' ),
|
||
|
'help_link' => 'https://semperplugins.com/documentation/xml-sitemaps-module/',
|
||
|
'options' => array_keys( $status_options ),
|
||
|
),
|
||
|
'default' => array(
|
||
|
'name' => $this->name,
|
||
|
'help_link' => 'https://semperplugins.com/documentation/xml-sitemaps-module/',
|
||
|
'options' => array_keys( $this->default_options ),
|
||
|
),
|
||
|
);
|
||
|
|
||
|
$prio = array();
|
||
|
for ( $i = 0; $i <= 10; $i ++ ) {
|
||
|
$str = sprintf( '%0.1f', $i / 10.0 );
|
||
|
$prio[ $str ] = $str;
|
||
|
}
|
||
|
$arr_no = array( 'no' => __( 'Do Not Override', 'all-in-one-seo-pack' ) );
|
||
|
$arr_sel = array( 'sel' => __( 'Select Individual', 'all-in-one-seo-pack' ) );
|
||
|
$this->prio_sel = array_merge( $arr_no, $arr_sel, $prio );
|
||
|
$this->prio = array_merge( $arr_no, $prio );
|
||
|
|
||
|
$freq = array();
|
||
|
foreach ( array( 'always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never' ) as $f ) {
|
||
|
$freq[ $f ] = $f;
|
||
|
}
|
||
|
$this->freq_sel = array_merge( $arr_no, $arr_sel, $freq );
|
||
|
$this->freq = array_merge( $arr_no, $freq );
|
||
|
|
||
|
foreach (
|
||
|
array(
|
||
|
'prio' => __( 'priority', 'all-in-one-seo-pack' ),
|
||
|
'freq' => __( 'frequency', 'all-in-one-seo-pack' ),
|
||
|
) as $k => $v
|
||
|
) {
|
||
|
$s = "{$k}_options";
|
||
|
$$s = array();
|
||
|
foreach (
|
||
|
array(
|
||
|
'homepage' => __( 'homepage', 'all-in-one-seo-pack' ),
|
||
|
'post' => __( 'posts', 'all-in-one-seo-pack' ),
|
||
|
'taxonomies' => __( 'taxonomies', 'all-in-one-seo-pack' ),
|
||
|
'archive' => __( 'archive pages', 'all-in-one-seo-pack' ),
|
||
|
'author' => __( 'author pages', 'all-in-one-seo-pack' ),
|
||
|
) as $opt => $val
|
||
|
) {
|
||
|
$arr = $$s;
|
||
|
if ( ( 'post' === $opt ) || ( 'taxonomies' === $opt ) ) {
|
||
|
$iopts = $this->{"{$k}_sel"};
|
||
|
} else {
|
||
|
$iopts = $this->$k;
|
||
|
}
|
||
|
|
||
|
$arr[ $k . '_' . $opt ] = array(
|
||
|
'name' => $this->ucwords( $val ),
|
||
|
'help_text' => sprintf( __( 'Manually set the %s of your %s.', 'all-in-one-seo-pack' ), $v, $val ),
|
||
|
'type' => 'select',
|
||
|
'initial_options' => $iopts,
|
||
|
'default' => 'no',
|
||
|
);
|
||
|
if ( ( 'archive' === $opt ) || ( 'author' === $opt ) ) {
|
||
|
$arr[ $k . '_' . $opt ]['condshow'] = array( $this->prefix . $opt => 'on' );
|
||
|
}
|
||
|
$$s = $arr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$addl_options = array(
|
||
|
'addl_instructions' => array(
|
||
|
'default' => '<div>' . __( 'Enter information below for any additional links for your sitemap not already managed through WordPress.', 'all-in-one-seo-pack' ) . '</div><br />',
|
||
|
'type' => 'html',
|
||
|
'label' => 'none',
|
||
|
'save' => false,
|
||
|
),
|
||
|
'addl_url' => array(
|
||
|
'name' => __( 'Page URL', 'all-in-one-seo-pack' ),
|
||
|
'type' => 'text',
|
||
|
'label' => 'top',
|
||
|
'save' => false,
|
||
|
),
|
||
|
'addl_prio' => array(
|
||
|
'name' => __( 'Page Priority', 'all-in-one-seo-pack' ),
|
||
|
'type' => 'select',
|
||
|
'initial_options' => $prio,
|
||
|
'label' => 'top',
|
||
|
'save' => false,
|
||
|
),
|
||
|
'addl_freq' => array(
|
||
|
'name' => __( 'Page Frequency', 'all-in-one-seo-pack' ),
|
||
|
'type' => 'select',
|
||
|
'initial_options' => $freq,
|
||
|
'label' => 'top',
|
||
|
'save' => false,
|
||
|
),
|
||
|
'addl_mod' => array(
|
||
|
'name' => __( 'Last Modified', 'all-in-one-seo-pack' ),
|
||
|
'type' => 'text',
|
||
|
'label' => 'top',
|
||
|
'save' => false,
|
||
|
),
|
||
|
'addl_pages' => array(
|
||
|
'name' => __( 'Additional Pages', 'all-in-one-seo-pack' ),
|
||
|
'type' => 'custom',
|
||
|
'save' => true,
|
||
|
),
|
||
|
'Submit' => array(
|
||
|
'type' => 'submit',
|
||
|
'class' => 'button-primary',
|
||
|
'name' => __( 'Add URL', 'all-in-one-seo-pack' ) . ' »',
|
||
|
'style' => 'margin-left: 20px;',
|
||
|
'label' => 'none',
|
||
|
'save' => false,
|
||
|
'value' => 1,
|
||
|
),
|
||
|
);
|
||
|
|
||
|
$excl_options = array(
|
||
|
'excl_categories' => array(
|
||
|
'name' => __( 'Excluded Categories', 'all-in-one-seo-pack' ),
|
||
|
'type' => 'multicheckbox',
|
||
|
'initial_options' => '',
|
||
|
),
|
||
|
'excl_pages' => array( 'name' => __( 'Excluded Pages', 'all-in-one-seo-pack' ), 'type' => 'text' ),
|
||
|
);
|
||
|
|
||
|
$this->layout['addl_pages'] = array(
|
||
|
'name' => __( 'Additional Pages', 'all-in-one-seo-pack' ),
|
||
|
'help_link' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#additional-pages',
|
||
|
'options' => array_keys( $addl_options ),
|
||
|
);
|
||
|
|
||
|
$this->layout['excl_pages'] = array(
|
||
|
'name' => __( 'Excluded Items', 'all-in-one-seo-pack' ),
|
||
|
'help_link' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#excluded-items',
|
||
|
'options' => array_keys( $excl_options ),
|
||
|
);
|
||
|
|
||
|
$this->layout['priorities'] = array(
|
||
|
'name' => __( 'Priorities', 'all-in-one-seo-pack' ),
|
||
|
'help_link' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies',
|
||
|
'options' => array_keys( $prio_options ),
|
||
|
);
|
||
|
|
||
|
$this->layout['frequencies'] = array(
|
||
|
'name' => __( 'Frequencies', 'all-in-one-seo-pack' ),
|
||
|
'help_link' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies',
|
||
|
'options' => array_keys( $freq_options ),
|
||
|
);
|
||
|
|
||
|
$this->default_options = array_merge( $status_options, $this->default_options, $addl_options, $excl_options, $prio_options, $freq_options );
|
||
|
|
||
|
$this->add_help_text_links();
|
||
|
|
||
|
add_action( 'after_doing_aioseop_updates', array(
|
||
|
$this,
|
||
|
'do_sitemaps',
|
||
|
) ); // Update static sitemap when AIOSEOP is upgrade to new version.
|
||
|
add_action( 'init', array( $this, 'load_sitemap_options' ) );
|
||
|
add_action( $this->prefix . 'settings_update', array( $this, 'do_sitemaps' ) );
|
||
|
add_filter( $this->prefix . 'display_settings', array( $this, 'update_post_data' ) );
|
||
|
add_filter( $this->prefix . 'display_options', array( $this, 'filter_display_options' ) );
|
||
|
add_filter( $this->prefix . 'update_options', array( $this, 'filter_options' ) );
|
||
|
add_filter( $this->prefix . 'output_option', array( $this, 'display_custom_options' ), 10, 2 );
|
||
|
add_action( $this->prefix . 'daily_update_cron', array( $this, 'daily_update' ) );
|
||
|
add_action( 'init', array( $this, 'make_dynamic_xsl' ) );
|
||
|
add_action( 'transition_post_status', array( $this, 'update_sitemap_from_posts' ), 10, 3 );
|
||
|
add_action( 'after_doing_aioseop_updates', array( $this, 'scan_sitemaps' ) );
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Update sitemap from posts.
|
||
|
*
|
||
|
* @param $new_status
|
||
|
* @param $old_status
|
||
|
* @param $post
|
||
|
*/
|
||
|
function update_sitemap_from_posts( $new_status, $old_status, $post ) {
|
||
|
|
||
|
if ( $this->option_isset( 'rewrite' ) ) {
|
||
|
// TODO if dynamic, delete transient (we currently don't do transients).
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$posttypes = array();
|
||
|
if ( ! empty( $this->options["{$this->prefix}posttypes"] ) ) {
|
||
|
$posttypes = $this->options["{$this->prefix}posttypes"];
|
||
|
}
|
||
|
|
||
|
if ( ! in_array( $post->post_type, $posttypes, true ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$statuses_for_updating = array( 'new', 'publish', 'trash' );
|
||
|
if ( ! in_array( $new_status, $statuses_for_updating, true ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$this->do_sitemaps();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add cron schedules.
|
||
|
*
|
||
|
* Add new intervals of a week and a month.
|
||
|
*
|
||
|
* @link https://codex.wordpress.org/Plugin_API/Filter_Reference/cron_schedules
|
||
|
*
|
||
|
* @param $schedules
|
||
|
*
|
||
|
* @return mixed
|
||
|
*/
|
||
|
function add_cron_schedules( $schedules ) {
|
||
|
$schedules['weekly'] = array(
|
||
|
'interval' => 604800, // 1 week in seconds.
|
||
|
'display' => __( 'Once Weekly', 'all-in-one-seo-pack' ),
|
||
|
);
|
||
|
$schedules['monthly'] = array(
|
||
|
'interval' => 2629740, // 1 month in seconds.
|
||
|
'display' => __( 'Once Monthly', 'all-in-one-seo-pack' ),
|
||
|
);
|
||
|
|
||
|
return $schedules;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Cron update.
|
||
|
*/
|
||
|
function cron_update() {
|
||
|
add_filter( 'cron_schedules', array( $this, 'add_cron_schedules' ) );
|
||
|
if ( ! wp_next_scheduled( $this->prefix . 'daily_update_cron' ) ) {
|
||
|
wp_schedule_event( time(), $this->options[ $this->prefix . 'daily_cron' ], $this->prefix . 'daily_update_cron' );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Daily update.
|
||
|
*/
|
||
|
function daily_update() {
|
||
|
$last_run = get_option( $this->prefix . 'cron_last_run' );
|
||
|
if ( empty( $last_run ) || ( time() - $last_run > 23.5 * 60 * 60 ) ) {
|
||
|
// Sanity check.
|
||
|
$this->do_sitemaps( __( 'Daily scheduled sitemap check has finished.', 'all-in-one-seo-pack' ) );
|
||
|
}
|
||
|
$last_run = time();
|
||
|
update_option( $this->prefix . 'cron_last_run', $last_run );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Initialize options, after constructor.
|
||
|
*/
|
||
|
function load_sitemap_options() {
|
||
|
// Load initial options / set defaults.
|
||
|
$this->update_options();
|
||
|
if ( ! empty( $this->options["{$this->prefix}indexes"] ) && ! empty( $this->options["{$this->prefix}paginate"] ) ) {
|
||
|
$this->paginate = true;
|
||
|
if ( $this->options["{$this->prefix}max_posts"] && ( $this->options["{$this->prefix}max_posts"] > 0 ) && ( $this->options["{$this->prefix}max_posts"] < 50000 ) ) {
|
||
|
$this->max_posts = $this->options["{$this->prefix}max_posts"];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( is_multisite() ) {
|
||
|
$this->options["{$this->prefix}rewrite"] = 'On';
|
||
|
}
|
||
|
|
||
|
if ( $this->options["{$this->prefix}rewrite"] ) {
|
||
|
$this->setup_rewrites();
|
||
|
}
|
||
|
|
||
|
if ( $this->option_isset( 'robots' ) ) {
|
||
|
add_action( 'do_robots', array( $this, 'do_robots' ), 100 );
|
||
|
}
|
||
|
|
||
|
if ( isset( $this->options[ $this->prefix . 'daily_cron' ] ) && $this->options[ $this->prefix . 'daily_cron' ] ) {
|
||
|
add_action( 'wp', array( $this, 'cron_update' ) );
|
||
|
} else {
|
||
|
if ( $time = wp_next_scheduled( $this->prefix . 'daily_update_cron' ) ) {
|
||
|
wp_unschedule_event( $time, $this->prefix . 'daily_update_cron' );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Custom settings.
|
||
|
*
|
||
|
* Displays boxes for add pages to sitemap option. Requires WordPress 4.1.
|
||
|
*
|
||
|
* @param $buf
|
||
|
* @param $args
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
function display_custom_options( $buf, $args ) {
|
||
|
if ( "{$this->prefix}addl_pages" === $args['name'] ) {
|
||
|
$buf .= "<div id='{$this->prefix}addl_pages'>";
|
||
|
if ( ! empty( $args['value'] ) ) {
|
||
|
$buf .= "<table class='aioseop_table' cellpadding=0 cellspacing=0>\n";
|
||
|
foreach ( $args['value'] as $k => $v ) {
|
||
|
if ( is_object( $v ) ) {
|
||
|
$v = (Array) $v;
|
||
|
}
|
||
|
$buf .= "\t<tr><td><a href='#' title='$k' class='aiosp_delete_url'></a> {$k}</td><td>{$v['prio']}</td><td>{$v['freq']}</td><td>{$v['mod']}</td></tr>\n";
|
||
|
}
|
||
|
$buf .= "</table>\n";
|
||
|
}
|
||
|
}
|
||
|
$args['options']['type'] = 'hidden';
|
||
|
if ( ! empty( $args['value'] ) ) {
|
||
|
$args['value'] = wp_json_encode( $args['value'] );
|
||
|
} else {
|
||
|
$args['options']['type'] = 'html';
|
||
|
}
|
||
|
if ( empty( $args['value'] ) ) {
|
||
|
$args['value'] = '';
|
||
|
}
|
||
|
$buf .= $this->get_option_html( $args );
|
||
|
$buf .= '</div>';
|
||
|
|
||
|
return $buf;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add post type details for settings once post types have been registered.
|
||
|
*/
|
||
|
function add_post_types() {
|
||
|
$post_type_titles = $this->get_post_type_titles( array( 'public' => true ) );
|
||
|
$taxonomy_titles = $this->get_taxonomy_titles( array( 'public' => true ) );
|
||
|
if ( isset( $post_type_titles['attachment'] ) ) {
|
||
|
$post_type_titles['attachment'] = __( 'Media / Attachments', 'all-in-one-seo-pack' );
|
||
|
}
|
||
|
$this->default_options['posttypes']['initial_options'] = array_merge( array( 'all' => __( 'All Post Types', 'all-in-one-seo-pack' ) ), $post_type_titles );
|
||
|
$this->default_options['taxonomies']['initial_options'] = array_merge( array( 'all' => __( 'All Taxonomies', 'all-in-one-seo-pack' ) ), $taxonomy_titles );
|
||
|
$this->default_options['posttypes']['default'] = array_keys( $this->default_options['posttypes']['initial_options'] );
|
||
|
$this->default_options['taxonomies']['default'] = array_keys( $this->default_options['taxonomies']['initial_options'] );
|
||
|
$this->default_options['excl_categories']['initial_options'] = $this->get_category_titles();
|
||
|
$prio_help = __( 'Manually set the priority for the ', 'all-in-one-seo-pack' );
|
||
|
$freq_help = __( 'Manually set the frequency for the ', 'all-in-one-seo-pack' );
|
||
|
$post_name = __( ' Post Type', 'all-in-one-seo-pack' );
|
||
|
$tax_name = __( ' Taxonomy', 'all-in-one-seo-pack' );
|
||
|
foreach ( $post_type_titles as $k => $v ) {
|
||
|
$key = 'prio_post_' . $k;
|
||
|
$this->default_options = aioseop_array_insert_after( $this->default_options, 'prio_post', array(
|
||
|
$key => array(
|
||
|
'name' => $v . $post_name,
|
||
|
'help_text' => $prio_help . $v . $post_name,
|
||
|
'type' => 'select',
|
||
|
'initial_options' => $this->prio,
|
||
|
'default' => 'no',
|
||
|
'condshow' => array( "{$this->prefix}prio_post" => 'sel' ),
|
||
|
),
|
||
|
) );
|
||
|
$this->layout['priorities']['options'][] = $key;
|
||
|
$key = 'freq_post_' . $k;
|
||
|
$this->default_options = aioseop_array_insert_after( $this->default_options, 'freq_post', array(
|
||
|
$key => array(
|
||
|
'name' => $v . $post_name,
|
||
|
'help_text' => $freq_help . $v . $post_name,
|
||
|
'type' => 'select',
|
||
|
'initial_options' => $this->freq,
|
||
|
'default' => 'no',
|
||
|
'condshow' => array( "{$this->prefix}freq_post" => 'sel' ),
|
||
|
),
|
||
|
) );
|
||
|
$this->layout['frequencies']['options'][] = $key;
|
||
|
}
|
||
|
foreach ( $taxonomy_titles as $k => $v ) {
|
||
|
$key = 'prio_taxonomies_' . $k;
|
||
|
$this->default_options = aioseop_array_insert_after( $this->default_options, 'prio_taxonomies', array(
|
||
|
$key => array(
|
||
|
'name' => $v . $tax_name,
|
||
|
'help_text' => $prio_help . $v . $tax_name,
|
||
|
'type' => 'select',
|
||
|
'initial_options' => $this->prio,
|
||
|
'default' => 'no',
|
||
|
'condshow' => array( "{$this->prefix}prio_taxonomies" => 'sel' ),
|
||
|
),
|
||
|
) );
|
||
|
$this->layout['priorities']['options'][] = $key;
|
||
|
$key = 'freq_taxonomies_' . $k;
|
||
|
$this->default_options = aioseop_array_insert_after( $this->default_options, 'freq_taxonomies', array(
|
||
|
$key => array(
|
||
|
'name' => $v . $tax_name,
|
||
|
'help_text' => $freq_help . $v . $tax_name,
|
||
|
'type' => 'select',
|
||
|
'initial_options' => $this->freq,
|
||
|
'default' => 'no',
|
||
|
'condshow' => array( "{$this->prefix}freq_taxonomies" => 'sel' ),
|
||
|
),
|
||
|
) );
|
||
|
$this->layout['frequencies']['options'][] = $key;
|
||
|
}
|
||
|
$this->update_options();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set up settings, checking for sitemap conflicts, on settings page.
|
||
|
*/
|
||
|
function add_page_hooks() {
|
||
|
$this->flush_rules_hook();
|
||
|
$this->add_post_types();
|
||
|
parent::add_page_hooks();
|
||
|
add_action( $this->prefix . 'settings_header', array( $this, 'do_sitemap_scan' ), 5 );
|
||
|
add_filter( "{$this->prefix}submit_options", array( $this, 'filter_submit' ) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Filter submit button.
|
||
|
*
|
||
|
* Change settings page submit button to read "Update Sitemap".
|
||
|
*
|
||
|
* @param $submit
|
||
|
*
|
||
|
* @return mixed
|
||
|
*/
|
||
|
function filter_submit( $submit ) {
|
||
|
$submit['Submit']['value'] = __( 'Update Sitemap', 'all-in-one-seo-pack' ) . ' »';
|
||
|
|
||
|
return $submit;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Updates post data.
|
||
|
*
|
||
|
* Disable writing sitemaps to the filesystem for multisite.
|
||
|
*
|
||
|
* @param $options
|
||
|
*
|
||
|
* @return mixed
|
||
|
*/
|
||
|
function update_post_data( $options ) {
|
||
|
if ( is_multisite() ) {
|
||
|
$options[ $this->prefix . 'rewrite' ]['disabled'] = 'disabled';
|
||
|
}
|
||
|
|
||
|
return $options;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param $url
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
function get_rewrite_url( $url ) {
|
||
|
global $wp_rewrite;
|
||
|
$url = parse_url( esc_url( $url ), PHP_URL_PATH );
|
||
|
$url = ltrim( $url, '/' );
|
||
|
if ( ! empty( $wp_rewrite ) ) {
|
||
|
$rewrite_rules = $wp_rewrite->rewrite_rules();
|
||
|
foreach ( $rewrite_rules as $k => $v ) {
|
||
|
if ( preg_match( "@^$k@", $url ) ) {
|
||
|
return $v;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Filter display options.
|
||
|
*
|
||
|
* Add in options for status display on settings page, sitemap rewriting on multisite.
|
||
|
*
|
||
|
* @param $options
|
||
|
*
|
||
|
* @return mixed
|
||
|
*/
|
||
|
function filter_display_options( $options ) {
|
||
|
if ( is_multisite() ) {
|
||
|
$options[ $this->prefix . 'rewrite' ] = 'On';
|
||
|
}
|
||
|
if ( isset( $options[ $this->prefix . 'max_posts' ] ) && ( ( $options[ $this->prefix . 'max_posts' ] <= 0 ) || ( $options[ $this->prefix . 'max_posts' ] >= 50000 ) ) ) {
|
||
|
$options[ $this->prefix . 'max_posts' ] = 50000;
|
||
|
}
|
||
|
$url = trailingslashit( get_home_url() ) . $options[ $this->prefix . 'filename' ] . '.xml';
|
||
|
|
||
|
$options[ $this->prefix . 'link' ] = sprintf( __( 'Click here to %s.', 'all-in-one-seo-pack' ), '<a href="' . esc_url( $url ) . '" target="_blank">' . __( 'view your sitemap', 'all-in-one-seo-pack' ) . '</a>' );
|
||
|
$options[ $this->prefix . 'link' ] .= __( ' Your sitemap has been created', 'all-in-one-seo-pack' );
|
||
|
if ( '0' !== get_option( 'blog_public' ) ){
|
||
|
$options[ $this->prefix . 'link' ] .= __( ' and changes are automatically submitted to search engines' );
|
||
|
}
|
||
|
$options[ $this->prefix . 'link' ] .= '.';
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
if ( $this->option_isset( 'rewrite' ) ) {
|
||
|
$rule = $this->get_rewrite_url( $url );
|
||
|
$rules = $this->get_rewrite_rules();
|
||
|
if ( ! in_array( $rule, $rules ) ) {
|
||
|
$options[ $this->prefix . 'link' ] .= '<p>' . __( 'Dynamic sitemap generation does not appear to be using the correct rewrite rules; please disable any other sitemap plugins or functionality on your site and reset your permalinks.', 'all-in-one-seo-pack' ) . '</p>';
|
||
|
}
|
||
|
}
|
||
|
if ( ! get_option( 'blog_public' ) ) {
|
||
|
global $wp_version;
|
||
|
if ( version_compare( $wp_version, '3.5.0', '>=' ) || function_exists( 'set_url_scheme' ) ) {
|
||
|
$privacy_link = '<a href="options-reading.php">' . __( 'Reading Settings', 'all-in-one-seo-pack' ) . '</a>';
|
||
|
} else {
|
||
|
$privacy_link = '<a href="options-privacy.php">' . __( 'Privacy Settings', 'all-in-one-seo-pack' ) . '</a>';
|
||
|
}
|
||
|
$options[ $this->prefix . 'link' ] .= '<p class="aioseop_error_notice">' . sprintf( __( 'Warning: your privacy settings are configured to ask search engines to not index your site; you can change this under %s for your blog.', 'all-in-one-seo-pack' ), $privacy_link );
|
||
|
}
|
||
|
return $options;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Filter options.
|
||
|
*
|
||
|
* Handle 'all' option for post types / taxonomies, further sanitization of filename, rewrites on for multisite, setting up addl pages option.
|
||
|
*
|
||
|
* @param $options
|
||
|
*
|
||
|
* @return mixed
|
||
|
*/
|
||
|
function filter_options( $options ) {
|
||
|
if ( ! isset( $this->default_options['posttypes']['initial_options'] ) ) {
|
||
|
$this->add_post_types();
|
||
|
}
|
||
|
if ( is_array( $options["{$this->prefix}posttypes"] ) && in_array( 'all', $options["{$this->prefix}posttypes"] ) && is_array( $this->default_options['posttypes']['initial_options'] ) ) {
|
||
|
$options["{$this->prefix}posttypes"] = array_keys( $this->default_options['posttypes']['initial_options'] );
|
||
|
}
|
||
|
if ( is_array( $options["{$this->prefix}taxonomies"] ) && in_array( 'all', $options["{$this->prefix}taxonomies"] ) && is_array( $this->default_options['taxonomies']['initial_options'] ) ) {
|
||
|
$options["{$this->prefix}taxonomies"] = array_keys( $this->default_options['taxonomies']['initial_options'] );
|
||
|
}
|
||
|
$opt = $this->prefix . 'filename';
|
||
|
if ( isset( $options[ $opt ] ) && ! empty( $options[ $opt ] ) ) {
|
||
|
$options[ $opt ] = str_replace( '/', '', $options[ $opt ] );
|
||
|
} else {
|
||
|
$options[ $opt ] = 'sitemap';
|
||
|
}
|
||
|
if ( is_multisite() ) {
|
||
|
$options[ $this->prefix . 'rewrite' ] = 'On';
|
||
|
}
|
||
|
if ( ! is_array( $options[ $this->prefix . 'addl_pages' ] ) ) {
|
||
|
$options[ $this->prefix . 'addl_pages' ] = wp_specialchars_decode( stripslashes_deep( $options[ $this->prefix . 'addl_pages' ] ), ENT_QUOTES );
|
||
|
$decoded = json_decode( $options[ $this->prefix . 'addl_pages' ] );
|
||
|
if ( null === $decoded ) {
|
||
|
$decoded = maybe_unserialize( $options[ $this->prefix . 'addl_pages' ] );
|
||
|
}
|
||
|
if ( ! is_array( $decoded ) ) {
|
||
|
$decoded = (Array) $decoded;
|
||
|
}
|
||
|
if ( null === $decoded ) {
|
||
|
$decoded = $options[ $this->prefix . 'addl_pages' ];
|
||
|
}
|
||
|
$options[ $this->prefix . 'addl_pages' ] = $decoded;
|
||
|
}
|
||
|
if ( is_array( $options[ $this->prefix . 'addl_pages' ] ) ) {
|
||
|
foreach ( $options[ $this->prefix . 'addl_pages' ] as $k => $v ) {
|
||
|
if ( is_object( $v ) ) {
|
||
|
$options[ $this->prefix . 'addl_pages' ][ $k ] = (Array) $v;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ( isset( $options[ $this->prefix . 'addl_pages' ][0] ) ) {
|
||
|
unset( $options[ $this->prefix . 'addl_pages' ][0] );
|
||
|
}
|
||
|
// TODO Refactor all these... use a nonce, dump the incoming _Post into an array and use that.
|
||
|
if ( ! empty( $_POST[ $this->prefix . 'addl_url' ] ) ) {
|
||
|
foreach ( array( 'addl_url', 'addl_prio', 'addl_freq', 'addl_mod' ) as $field ) {
|
||
|
if ( ! empty( $_POST[ $this->prefix . $field ] ) ) {
|
||
|
$_POST[ $this->prefix . $field ] = esc_attr( wp_kses_post( $_POST[ $this->prefix . $field ] ) );
|
||
|
} else {
|
||
|
$_POST[ $this->prefix . $field ] = '';
|
||
|
}
|
||
|
}
|
||
|
if ( ! is_array( $options[ $this->prefix . 'addl_pages' ] ) ) {
|
||
|
$options[ $this->prefix . 'addl_pages' ] = array();
|
||
|
}
|
||
|
$options[ $this->prefix . 'addl_pages' ][ $_POST[ $this->prefix . 'addl_url' ] ] = array(
|
||
|
'prio' => $_POST[ $this->prefix . 'addl_prio' ],
|
||
|
'freq' => $_POST[ $this->prefix . 'addl_freq' ],
|
||
|
'mod' => $_POST[ $this->prefix . 'addl_mod' ],
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return $options;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get sitemap urls of child blogs, if any.
|
||
|
*
|
||
|
* @return mixed|void
|
||
|
*/
|
||
|
function get_child_sitemap_urls() {
|
||
|
$siteurls = array();
|
||
|
$blogs = $this->get_child_blogs();
|
||
|
if ( ! empty( $blogs ) ) {
|
||
|
$option_name = $this->get_option_name();
|
||
|
foreach ( $blogs as $blog_id ) {
|
||
|
if ( $this->is_aioseop_active_on_blog( $blog_id ) ) {
|
||
|
$options = get_blog_option( $blog_id, $this->parent_option );
|
||
|
if ( ! empty( $options ) && ! empty( $options['modules'] ) && ! empty( $options['modules']['aiosp_feature_manager_options'] )
|
||
|
&& ! empty( $options['modules']['aiosp_feature_manager_options']['aiosp_feature_manager_enable_sitemap'] )
|
||
|
&& ! empty( $options['modules'][ $option_name ] )
|
||
|
) {
|
||
|
global $wpdb;
|
||
|
$sitemap_options = $options['modules'][ $option_name ];
|
||
|
$siteurl = '';
|
||
|
if ( defined( 'SUNRISE' ) && SUNRISE && is_object( $wpdb ) && isset( $wpdb->dmtable ) && ! empty( $wpdb->dmtable ) ) {
|
||
|
$domain = $wpdb->get_var( "SELECT domain FROM {$wpdb->dmtable} WHERE blog_id = '$blog_id' AND active = 1 LIMIT 1" );
|
||
|
if ( $domain ) {
|
||
|
if ( false == isset( $_SERVER['HTTPS'] ) ) {
|
||
|
$_SERVER['HTTPS'] = 'Off';
|
||
|
}
|
||
|
$protocol = ( 'on' == strtolower( $_SERVER['HTTPS'] ) ) ? 'https://' : 'http://';
|
||
|
$siteurl = untrailingslashit( $protocol . $domain );
|
||
|
}
|
||
|
}
|
||
|
if ( ! $siteurl ) {
|
||
|
$siteurl = get_home_url( $blog_id );
|
||
|
}
|
||
|
$url = $siteurl . '/' . $sitemap_options["{$this->prefix}filename"] . '.xml';
|
||
|
if ( $sitemap_options["{$this->prefix}gzipped"] ) {
|
||
|
$url .= '.gz';
|
||
|
}
|
||
|
$siteurls[] = $url;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
$siteurls = apply_filters( $this->prefix . 'sitemap_urls', $siteurls ); // Legacy.
|
||
|
return apply_filters( $this->prefix . 'child_urls', $siteurls );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the home path.
|
||
|
*
|
||
|
* If we're in wp-admin, use the WordPress function, otherwise we user our own version here.
|
||
|
* This only applies to static sitemaps.
|
||
|
*
|
||
|
* @since 2.3.6.1
|
||
|
*
|
||
|
* @return mixed|string
|
||
|
*/
|
||
|
function get_home_path() {
|
||
|
|
||
|
if ( function_exists( 'get_home_path' ) ) {
|
||
|
return get_home_path();
|
||
|
}
|
||
|
|
||
|
$home = set_url_scheme( get_option( 'home' ), 'http' );
|
||
|
$siteurl = set_url_scheme( get_option( 'siteurl' ), 'http' );
|
||
|
if ( ! empty( $home ) && 0 !== strcasecmp( $home, $siteurl ) ) {
|
||
|
$wp_path_rel_to_home = str_ireplace( $home, '', $siteurl ); /* $siteurl - $home */
|
||
|
$pos = strripos( str_replace( '\\', '/', $_SERVER['SCRIPT_FILENAME'] ), trailingslashit( $wp_path_rel_to_home ) );
|
||
|
$home_path = substr( $_SERVER['SCRIPT_FILENAME'], 0, $pos );
|
||
|
$home_path = trailingslashit( $home_path );
|
||
|
} else {
|
||
|
$home_path = ABSPATH;
|
||
|
}
|
||
|
|
||
|
return str_replace( '\\', '/', $home_path );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Whitelists files from static sitemap conflict warning.
|
||
|
*
|
||
|
* For right now, this is just externally produced news sitemaps until we figure out something better.
|
||
|
*
|
||
|
* @param $file
|
||
|
*
|
||
|
* @since 2.3.10.2
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
function whitelist_static_sitemaps( $file ) {
|
||
|
|
||
|
$whitelist = array( 'sitemap_news.xml', 'sitemap-news.xml' );
|
||
|
|
||
|
if ( in_array( $file, $whitelist, true ) ) {
|
||
|
return '';
|
||
|
}
|
||
|
|
||
|
return $file;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Scan for sitemaps on filesystem.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function scan_match_files() {
|
||
|
$scan1 = $scan2 = '';
|
||
|
$files = array();
|
||
|
|
||
|
if ( ! empty( $this->options["{$this->prefix}filename"] ) ) {
|
||
|
$scan1 = get_home_path() . $this->options["{$this->prefix}filename"] . '*.xml';
|
||
|
if ( ! empty( $this->options["{$this->prefix}gzipped"] ) ) {
|
||
|
$scan2 .= get_home_path() . $this->options["{$this->prefix}filename"] . '*.xml.gz';
|
||
|
}
|
||
|
|
||
|
if ( empty( $scan1 ) && empty( $scan2 ) ) {
|
||
|
return $files;
|
||
|
}
|
||
|
$home_path = get_home_path();
|
||
|
$filescan = $this->scandir( $home_path );
|
||
|
if ( ! empty( $filescan ) ) {
|
||
|
foreach ( $filescan as $f ) {
|
||
|
if ( ! empty( $scan1 ) && fnmatch( $scan1, $home_path . $f ) ) {
|
||
|
|
||
|
$f = $this->whitelist_static_sitemaps( $f );
|
||
|
$files[] = $home_path . $f;
|
||
|
continue;
|
||
|
}
|
||
|
if ( ! empty( $scan2 ) && fnmatch( $scan2, $home_path . $f ) ) {
|
||
|
$files[] = $home_path . $f;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $files;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Scan for sitemaps.
|
||
|
*
|
||
|
* Handle deleting / renaming of conflicting sitemap files.
|
||
|
*/
|
||
|
function do_sitemap_scan() {
|
||
|
$msg = '';
|
||
|
if ( ! empty( $this->options["{$this->prefix}rewrite"] ) && ( get_option( 'permalink_structure' ) === '' ) ) {
|
||
|
$msg = '<p>' . __( 'Warning: dynamic sitemap generation must have permalinks enabled.', 'all-in-one-seo-pack' ) . '</p>';
|
||
|
}
|
||
|
if ( ! empty( $_POST['aioseop_sitemap_rename_files'] ) || ! empty( $_POST['aioseop_sitemap_delete_files'] ) ) {
|
||
|
$nonce = $_POST['nonce-aioseop'];
|
||
|
if ( ! wp_verify_nonce( $nonce, 'aioseop-nonce' ) ) {
|
||
|
die ( __( 'Security Check - If you receive this in error, log out and back in to WordPress', 'all-in-one-seo-pack' ) );
|
||
|
}
|
||
|
if ( ! empty( $_POST['aioseop_sitemap_conflict'] ) ) {
|
||
|
$files = $this->scan_match_files();
|
||
|
foreach ( $files as $f => $file ) {
|
||
|
$files[ $f ] = realpath( $file );
|
||
|
}
|
||
|
foreach ( $_POST['aioseop_sitemap_conflict'] as $ren_file ) {
|
||
|
$ren_file = realpath( get_home_path() . $ren_file );
|
||
|
if ( in_array( $ren_file, $files ) ) {
|
||
|
if ( ! empty( $_POST['aioseop_sitemap_delete_files'] ) ) {
|
||
|
if ( $this->delete_file( $ren_file ) ) {
|
||
|
$msg .= '<p>' . sprintf( __( 'Deleted %s.', 'all-in-one-seo-pack' ), $ren_file ) . '</p>';
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
$count = 0;
|
||
|
do {
|
||
|
$ren_to = $ren_file . '._' . sprintf( '%03d', $count ) . '.old';
|
||
|
$count ++;
|
||
|
} while ( $this->file_exists( $ren_to ) && ( $count < 1000 ) );
|
||
|
if ( $count >= 1000 ) {
|
||
|
$msg .= '<p>' . sprintf( __( "Couldn't rename file %s!", 'all-in-one-seo-pack' ), $ren_file ) . '</p>';
|
||
|
} else {
|
||
|
$ren = $this->rename_file( $ren_file, $ren_to );
|
||
|
if ( $ren ) {
|
||
|
$msg .= '<p>' . sprintf( __( 'Renamed %s to %s.', 'all-in-one-seo-pack' ), $ren_file, $ren_to ) . '</p>';
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
$msg .= '<p>' . sprintf( __( "Couldn't find file %s!", 'all-in-one-seo-pack' ), $ren_file ) . '</p>';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
$msg .= $this->scan_sitemaps();
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $msg ) ) {
|
||
|
$this->output_error( $msg );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Do the scan, return the results.
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
function scan_sitemaps() {
|
||
|
$msg = '';
|
||
|
$files = $this->scan_match_files();
|
||
|
if ( ! empty( $files ) ) {
|
||
|
$msg = $this->sitemap_warning( $files );
|
||
|
}
|
||
|
|
||
|
return $msg;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get problem files.
|
||
|
*
|
||
|
* Get the list of potentially conflicting sitemap files, identify whether they came from us, are blank, or are of unknown origin.
|
||
|
*
|
||
|
* @param $files
|
||
|
* @param $msg
|
||
|
*
|
||
|
* In 2.3.10 we added the ability to see empty sitemap files as well.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_problem_files( $files, &$msg ) {
|
||
|
$problem_files = array();
|
||
|
$use_wpfs = true;
|
||
|
$wpfs = $this->get_filesystem_object();
|
||
|
if ( ! is_object( $wpfs ) ) {
|
||
|
$use_wpfs = false;
|
||
|
} else {
|
||
|
if ( 'direct' === $wpfs->method ) {
|
||
|
$use_wpfs = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
foreach ( $files as $f ) {
|
||
|
if ( $this->is_file( $f ) ) {
|
||
|
$fn = $f;
|
||
|
$compressed = false;
|
||
|
if ( $this->substr( $f, - 3 ) === '.gz' ) {
|
||
|
$compressed = true;
|
||
|
}
|
||
|
if ( $use_wpfs ) {
|
||
|
if ( $compressed ) { // Inefficient but necessary.
|
||
|
$file = $this->load_file( $fn );
|
||
|
if ( ! empty( $file ) ) {
|
||
|
$file = gzuncompress( $file, 4096 );
|
||
|
}
|
||
|
} else {
|
||
|
$file = $this->load_file( $fn, false, null, - 1, 4096 );
|
||
|
}
|
||
|
} else {
|
||
|
if ( $compressed ) {
|
||
|
$fn = 'compress.zlib://' . $fn;
|
||
|
}
|
||
|
$file = file_get_contents( $fn, false, null, - 1, 4096 );
|
||
|
}
|
||
|
if ( ! empty( $file ) ) {
|
||
|
$matches = array();
|
||
|
if ( preg_match( '/<!-- ' . sprintf( $this->comment_string, '(.*)', '(.*)', '(.*)' ) . ' -->/',
|
||
|
$file, $matches ) ) {
|
||
|
if ( ! empty( $this->options["{$this->prefix}rewrite"] ) ) {
|
||
|
$msg .= '<p>' . sprintf( __( "Warning: a static sitemap '%s' generated by All in One SEO Pack %s on %s already exists that may conflict with dynamic sitemap generation.", 'all-in-one-seo-pack' ),
|
||
|
$f, $matches[2], $matches[3] ) . "</p>\n";
|
||
|
$problem_files[] = $f;
|
||
|
}
|
||
|
} else {
|
||
|
$msg .= '<p>' . sprintf( __( 'Potential conflict with unknown file %s.', 'all-in-one-seo-pack' ), $f ) . "</p>\n";
|
||
|
$problem_files[] = $f;
|
||
|
}
|
||
|
} else {
|
||
|
$msg .= '<p>' . sprintf( __( 'Removed empty file %s.', 'all-in-one-seo-pack' ), $f ) . "</p>\n";
|
||
|
$problem_files[] = $f;
|
||
|
|
||
|
foreach ( $problem_files as $f => $file ) {
|
||
|
$files[ $f ] = realpath( $file );
|
||
|
$this->delete_file( realpath( $file ) );
|
||
|
}
|
||
|
$problem_files = false; // Don't return anything. If it's blank, we'll take care of it here.
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $problem_files;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Display sitemap warning.
|
||
|
*
|
||
|
* Display the warning and the form for conflicting sitemap files.
|
||
|
*
|
||
|
* @param $files
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
function sitemap_warning( $files ) {
|
||
|
$msg = '';
|
||
|
$conflict = false;
|
||
|
$problem_files = $this->get_problem_files( $files, $msg );
|
||
|
if ( ! empty( $problem_files ) ) {
|
||
|
$conflict = true;
|
||
|
}
|
||
|
if ( $conflict ) {
|
||
|
foreach ( $problem_files as $p ) {
|
||
|
$msg .= "<input type='hidden' name='aioseop_sitemap_conflict[]' value='" . esc_attr( basename( realpath( $p ) ) ) . "'>\n";
|
||
|
}
|
||
|
$msg .= "<input type='hidden' name='nonce-aioseop' value='" . wp_create_nonce( 'aioseop-nonce' ) . "'>\n";
|
||
|
$msg .= "<input type='submit' name='aioseop_sitemap_rename_files' value='" . __( 'Rename Conflicting Files', 'all-in-one-seo-pack' ) . "'> ";
|
||
|
$msg .= "<input type='submit' name='aioseop_sitemap_delete_files' value='" . __( 'Delete Conflicting Files', 'all-in-one-seo-pack' ) . "'>";
|
||
|
$msg = '<form action="" method="post">' . $msg . '</form>';
|
||
|
}
|
||
|
|
||
|
return $msg;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Updates debug log messages.
|
||
|
*
|
||
|
* Deprecated as of 2.3.10 in favor of WP debug log. We should eventually remove this.
|
||
|
*
|
||
|
* @param $msg
|
||
|
*/
|
||
|
function debug_message( $msg ) {
|
||
|
aiosp_log( $msg );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set up hooks for rewrite rules for dynamic sitemap generation.
|
||
|
*/
|
||
|
function setup_rewrites() {
|
||
|
add_action( 'rewrite_rules_array', array( $this, 'rewrite_hook' ) );
|
||
|
add_filter( 'query_vars', array( $this, 'query_var_hook' ) );
|
||
|
add_action( 'parse_query', array( $this, 'sitemap_output_hook' ) );
|
||
|
if ( ! get_transient( "{$this->prefix}rules_flushed" ) ) {
|
||
|
add_action( 'wp_loaded', array( $this, 'flush_rules_hook' ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Build and return our rewrite rules.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_rewrite_rules() {
|
||
|
$sitemap_rules_normal = $sitemap_rules_gzipped = array();
|
||
|
$sitemap_rules_normal = array(
|
||
|
$this->options["{$this->prefix}filename"] . '.xml' => "index.php?{$this->prefix}path=root",
|
||
|
$this->options["{$this->prefix}filename"] . '_(.+)_(\d+).xml' => 'index.php?' . $this->prefix . 'path=$matches[1]&' . $this->prefix . 'page=$matches[2]',
|
||
|
$this->options["{$this->prefix}filename"] . '_(.+).xml' => 'index.php?' . $this->prefix . 'path=$matches[1]',
|
||
|
);
|
||
|
if ( $this->options["{$this->prefix}gzipped"] ) {
|
||
|
$sitemap_rules_gzipped = array(
|
||
|
$this->options["{$this->prefix}filename"] . '.xml.gz' => "index.php?{$this->prefix}gzipped=1&{$this->prefix}path=root.gz",
|
||
|
$this->options["{$this->prefix}filename"] . '_(.+)_(\d+).xml.gz' => 'index.php?' . $this->prefix . 'path=$matches[1].gz&' . $this->prefix . 'page=$matches[2]',
|
||
|
$this->options["{$this->prefix}filename"] . '_(.+).xml.gz' => 'index.php?' . $this->prefix . 'path=$matches[1].gz',
|
||
|
);
|
||
|
}
|
||
|
$sitemap_rules = $sitemap_rules_gzipped + $sitemap_rules_normal;
|
||
|
|
||
|
return $sitemap_rules;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add in our rewrite rules.
|
||
|
*
|
||
|
* @param $rules
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function rewrite_hook( $rules ) {
|
||
|
$sitemap_rules = $this->get_rewrite_rules();
|
||
|
if ( ! empty( $sitemap_rules ) ) {
|
||
|
$rules = $sitemap_rules + $rules;
|
||
|
}
|
||
|
|
||
|
return $rules;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Flush rewrite rules when necessary.
|
||
|
*/
|
||
|
function flush_rules_hook() {
|
||
|
global $wp_rewrite;
|
||
|
$sitemap_rules = $this->get_rewrite_rules( $wp_rewrite );
|
||
|
if ( ! empty( $sitemap_rules ) ) {
|
||
|
$rules = get_option( 'rewrite_rules' );
|
||
|
$rule = key( $sitemap_rules );
|
||
|
if ( ! isset( $rules[ $rule ] ) || ( $rules[ $rule ] !== $sitemap_rules[ $rule ] ) ) {
|
||
|
$wp_rewrite->flush_rules();
|
||
|
set_transient( "{$this->prefix}rules_flushed", true, 43200 );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add our query variable for sitemap generation.
|
||
|
*
|
||
|
* @param $vars
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function query_var_hook( $vars ) {
|
||
|
$vars[] = "{$this->prefix}path";
|
||
|
if ( $this->paginate ) {
|
||
|
$vars[] = "{$this->prefix}page";
|
||
|
}
|
||
|
|
||
|
return $vars;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Start timing and get initial memory usage for debug info.
|
||
|
*/
|
||
|
function log_start() {
|
||
|
$this->start_memory_usage = memory_get_peak_usage();
|
||
|
timer_start();
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Stop timing and log memory usage for debug info.
|
||
|
*
|
||
|
* @param string $sitemap_type
|
||
|
* @param bool $compressed
|
||
|
* @param bool $dynamic
|
||
|
*/
|
||
|
function log_stats( $sitemap_type = 'static', $compressed = false, $dynamic = true ) {
|
||
|
$time = timer_stop();
|
||
|
$end_memory_usage = memory_get_peak_usage();
|
||
|
$sitemap_memory_usage = $end_memory_usage - $this->start_memory_usage;
|
||
|
$end_memory_usage = $end_memory_usage / 1024.0 / 1024.0;
|
||
|
$sitemap_memory_usage = $sitemap_memory_usage / 1024.0 / 1024.0;
|
||
|
$sitemap_type = __( 'static', 'all-in-one-seo-pack ' );
|
||
|
if ( $compressed ) {
|
||
|
$sitemap_type = __( 'compressed', 'all-in-one-seo-pack' );
|
||
|
}
|
||
|
if ( $dynamic ) {
|
||
|
$sitemap_type = __( 'dynamic', 'all-in-one-seo-pack ' );
|
||
|
}
|
||
|
$this->debug_message( sprintf( ' %01.2f MB memory used generating the %s sitemap in %01.3f seconds, %01.2f MB total memory used.', $sitemap_memory_usage, $sitemap_type, $time, $end_memory_usage ) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handle outputting of dynamic sitemaps, logging.
|
||
|
*
|
||
|
* @param $query
|
||
|
*/
|
||
|
function sitemap_output_hook( $query ) {
|
||
|
$page = 0;
|
||
|
if ( $this->options["{$this->prefix}rewrite"] && ! empty( $query->query_vars["{$this->prefix}path"] ) ) {
|
||
|
|
||
|
// Make dynamic sitemap.
|
||
|
|
||
|
if ( ! empty( $query->query_vars["{$this->prefix}page"] ) ) {
|
||
|
$page = $query->query_vars["{$this->prefix}page"] - 1;
|
||
|
}
|
||
|
$this->start_memory_usage = memory_get_peak_usage();
|
||
|
$sitemap_type = $query->query_vars["{$this->prefix}path"];
|
||
|
$gzipped = false;
|
||
|
if ( $this->substr( $sitemap_type, - 3 ) === '.gz' ) {
|
||
|
$gzipped = true;
|
||
|
$sitemap_type = $this->substr( $sitemap_type, 0, - 3 );
|
||
|
}
|
||
|
$blog_charset = get_option( 'blog_charset' );
|
||
|
if ( $this->options["{$this->prefix}gzipped"] && $gzipped ) {
|
||
|
header( "Content-Type: application/x-gzip; charset=$blog_charset", true );
|
||
|
} else {
|
||
|
$gzipped = false;
|
||
|
header( "Content-Type: text/xml; charset=$blog_charset", true );
|
||
|
}
|
||
|
|
||
|
// Always follow and noindex the sitemap.
|
||
|
header( 'X-Robots-Tag: noindex, follow', true );
|
||
|
|
||
|
if ( $gzipped ) {
|
||
|
ob_start();
|
||
|
}
|
||
|
$this->do_rewrite_sitemap( $sitemap_type, $page );
|
||
|
if ( $gzipped ) {
|
||
|
echo gzencode( ob_get_clean() );
|
||
|
}
|
||
|
$this->log_stats( $sitemap_type, $gzipped );
|
||
|
exit();
|
||
|
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Make dynamic xsl.
|
||
|
*/
|
||
|
function make_dynamic_xsl() {
|
||
|
// Make dynamic xsl file.
|
||
|
if ( preg_match( '#(/sitemap\.xsl)$#i', $_SERVER['REQUEST_URI'] ) ) {
|
||
|
$blog_charset = get_option( 'blog_charset' );
|
||
|
header( "Content-Type: text/xml; charset=$blog_charset", true );
|
||
|
include_once( AIOSEOP_PLUGIN_DIR . '/inc/sitemap-xsl.php' );
|
||
|
exit();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get sitemap data.
|
||
|
*
|
||
|
* @param $sitemap_type
|
||
|
* @param int $page
|
||
|
*
|
||
|
* @return mixed|void
|
||
|
*/
|
||
|
function get_sitemap_data( $sitemap_type, $page = 0 ) {
|
||
|
$sitemap_data = array();
|
||
|
if ( $this->options["{$this->prefix}indexes"] ) {
|
||
|
$posttypes = $this->options["{$this->prefix}posttypes"];
|
||
|
if ( empty( $posttypes ) ) {
|
||
|
$posttypes = array();
|
||
|
}
|
||
|
$taxonomies = $this->options["{$this->prefix}taxonomies"];
|
||
|
if ( empty( $taxonomies ) ) {
|
||
|
$taxonomies = array();
|
||
|
}
|
||
|
if ( 'root' === $sitemap_type ) {
|
||
|
$sitemap_data = array_merge( $this->get_sitemap_index_filenames() );
|
||
|
} elseif ( 'addl' === $sitemap_type ) {
|
||
|
$sitemap_data = $this->get_addl_pages();
|
||
|
} elseif ( 'archive' === $sitemap_type && $this->option_isset( 'archive' ) ) {
|
||
|
$sitemap_data = $this->get_archive_prio_data();
|
||
|
} elseif ( 'author' === $sitemap_type && $this->option_isset( 'author' ) ) {
|
||
|
$sitemap_data = $this->get_author_prio_data();
|
||
|
} elseif ( in_array( $sitemap_type, $posttypes ) ) {
|
||
|
$sitemap_data = $this->get_all_post_priority_data( $sitemap_type, 'publish', $page );
|
||
|
} elseif ( in_array( $sitemap_type, $taxonomies ) ) {
|
||
|
$sitemap_data = $this->get_term_priority_data( get_terms( $sitemap_type, $this->get_tax_args( $page ) ) );
|
||
|
} else {
|
||
|
if ( is_array( $this->extra_sitemaps ) && in_array( $sitemap_type, $this->extra_sitemaps ) ) {
|
||
|
$sitemap_data = apply_filters( $this->prefix . 'custom_' . $sitemap_type, $sitemap_data, $page, $this_options );
|
||
|
}
|
||
|
}
|
||
|
} elseif ( 'root' === $sitemap_type ) {
|
||
|
$sitemap_data = $this->get_simple_sitemap();
|
||
|
}
|
||
|
|
||
|
return apply_filters( $this->prefix . 'data', $sitemap_data, $sitemap_type, $page, $this->options );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Rewrite sitemap.
|
||
|
*
|
||
|
* Output sitemaps dynamically based on rewrite rules.
|
||
|
*
|
||
|
* @param $sitemap_type
|
||
|
* @param int $page
|
||
|
*/
|
||
|
function do_rewrite_sitemap( $sitemap_type, $page = 0 ) {
|
||
|
$this->add_post_types();
|
||
|
$comment = 'dynamically';
|
||
|
echo $this->do_build_sitemap( $sitemap_type, $page, '', $comment );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Build a url to the sitemap.
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
function get_sitemap_url() {
|
||
|
$url = get_home_url() . '/' . $this->options["{$this->prefix}filename"] . '.xml';
|
||
|
if ( $this->options["{$this->prefix}gzipped"] ) {
|
||
|
$url .= '.gz';
|
||
|
}
|
||
|
|
||
|
return $url;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Notify search engines, do logging.
|
||
|
*/
|
||
|
function do_notify() {
|
||
|
|
||
|
if ( '0' === get_option( 'blog_public' ) ) {
|
||
|
// Don't ping search engines if blog is set to not public.
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( apply_filters( 'aioseo_sitemap_ping', true ) === false ) {
|
||
|
// API filter hook to disable sending sitemaps to search engines.
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$notify_url = array(
|
||
|
'google' => 'https://www.google.com/webmasters/sitemaps/ping?sitemap=',
|
||
|
'bing' => 'https://www.bing.com/webmaster/ping.aspx?siteMap=',
|
||
|
);
|
||
|
|
||
|
$notify_url = apply_filters( 'aioseo_sitemap_ping_urls', $notify_url );
|
||
|
|
||
|
$url = $this->get_sitemap_url();
|
||
|
if ( ! empty( $url ) ) {
|
||
|
foreach ( $notify_url as $k => $v ) {
|
||
|
$response = wp_remote_get( $notify_url[ $k ] . urlencode( $url ) );
|
||
|
if ( is_array( $response ) && ! empty( $response['response'] ) && ! empty( $response['response']['code'] ) ) {
|
||
|
if ( 200 != $response['response']['code'] ) {
|
||
|
$this->debug_message( sprintf( __( 'Failed to notify %s about changes to your sitemap at %s, error code %s.', 'all-in-one-seo-pack' ), $k, $url, $response['response']['code'] ) );
|
||
|
}
|
||
|
} else {
|
||
|
$this->debug_message( sprintf( __( 'Failed to notify %s about changes to your sitemap at %s, unable to access via wp_remote_get().', 'all-in-one-seo-pack' ), $k, $url ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add Sitemap parameter to virtual robots.txt file.
|
||
|
*/
|
||
|
function do_robots() {
|
||
|
$url = $this->get_sitemap_url();
|
||
|
echo "\nSitemap: $url\n";
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Build static sitemaps.
|
||
|
*
|
||
|
* Build static sitemaps on submit if rewrite rules are not in use, do logging.
|
||
|
*
|
||
|
* @param string $message
|
||
|
*/
|
||
|
function do_sitemaps( $message = '' ) {
|
||
|
if ( ! empty( $this->options["{$this->prefix}indexes"] ) && ! empty( $this->options["{$this->prefix}paginate"] ) ) {
|
||
|
$this->paginate = true;
|
||
|
if ( $this->options["{$this->prefix}max_posts"] && ( $this->options["{$this->prefix}max_posts"] > 0 ) && ( $this->options["{$this->prefix}max_posts"] < 50000 ) ) {
|
||
|
$this->max_posts = $this->options["{$this->prefix}max_posts"];
|
||
|
} else {
|
||
|
$this->max_posts = 50000;
|
||
|
}
|
||
|
} else {
|
||
|
$this->paginate = false;
|
||
|
$this->max_posts = 50000;
|
||
|
}
|
||
|
if ( ! $this->options["{$this->prefix}rewrite"] ) {
|
||
|
if ( $this->options["{$this->prefix}indexes"] ) {
|
||
|
$this->do_indexed_sitemaps();
|
||
|
} else {
|
||
|
$this->log_start();
|
||
|
$comment = sprintf( "file '%s' statically", $this->options["{$this->prefix}filename"] );
|
||
|
$sitemap = $this->do_simple_sitemap( $comment );
|
||
|
$this->write_sitemaps( $this->options["{$this->prefix}filename"], $sitemap );
|
||
|
$this->log_stats( 'root', $this->options["{$this->prefix}gzipped"], false );
|
||
|
}
|
||
|
} else {
|
||
|
delete_transient( "{$this->prefix}rules_flushed" );
|
||
|
}
|
||
|
$this->do_notify();
|
||
|
if ( ! empty( $message ) && is_string( $message ) ) {
|
||
|
$this->debug_message( $message );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add mime type.
|
||
|
*
|
||
|
* @param $mime
|
||
|
*
|
||
|
* @return mixed
|
||
|
*/
|
||
|
function add_xml_mime_type( $mime ) {
|
||
|
if ( ! empty( $mime ) ) {
|
||
|
$mime['xml'] = 'text/xml';
|
||
|
}
|
||
|
|
||
|
return $mime;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Write multiple sitemaps.
|
||
|
*
|
||
|
* Write sitemaps (compressed or otherwise) to the filesystem.
|
||
|
*
|
||
|
* @param $filename
|
||
|
* @param $contents
|
||
|
*/
|
||
|
function write_sitemaps( $filename, $contents ) {
|
||
|
$this->write_sitemap( $filename . '.xml', $contents );
|
||
|
if ( $this->options["{$this->prefix}gzipped"] ) {
|
||
|
$this->write_sitemap( $filename . '.xml.gz', $contents, true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Write single sitemap.
|
||
|
*
|
||
|
* Write a single sitemap to the filesystem, handle compression.
|
||
|
*
|
||
|
* @param $filename
|
||
|
* @param $contents
|
||
|
* @param bool $gzip
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
function write_sitemap( $filename, $contents, $gzip = false ) {
|
||
|
if ( $gzip ) {
|
||
|
$contents = gzencode( $contents );
|
||
|
}
|
||
|
add_filter( 'upload_mimes', array( $this, 'add_xml_mime_type' ) );
|
||
|
$filename = $this->get_home_path() . sanitize_file_name( $filename );
|
||
|
remove_filter( 'upload_mimes', array( $this, 'add_xml_mime_type' ) );
|
||
|
|
||
|
return $this->save_file( $filename, $contents );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the default values.
|
||
|
*
|
||
|
* Helper function for handling default values.
|
||
|
*
|
||
|
* @param $defaults
|
||
|
* @param $prefix
|
||
|
* @param $cache
|
||
|
* @param $item
|
||
|
* @param bool $nodefaults
|
||
|
* @param string $type
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
function get_default_values( $defaults, $prefix, &$cache, $item, $nodefaults = false, $type = '' ) {
|
||
|
if ( ! empty( $cache[ $item . $type ] ) ) {
|
||
|
return $cache[ $item . $type ];
|
||
|
}
|
||
|
if ( ! empty( $defaults[ $item ] ) ) {
|
||
|
$field = $this->prefix . $prefix . $item;
|
||
|
if ( $this->option_isset( $prefix . $item ) && 'no' != $this->options[ $field ] ) {
|
||
|
if ( ( 'sel' === $this->options[ $field ] ) && ! empty( $type ) && isset( $this->options[ $this->prefix . $prefix . $item . '_' . $type ] ) ) {
|
||
|
if ( 'no' == $this->options[ $this->prefix . $prefix . $item . '_' . $type ] ) {
|
||
|
return false;
|
||
|
}
|
||
|
if ( 'sel' === $this->options[ $this->prefix . $prefix . $item . '_' . $type ] ) {
|
||
|
return false;
|
||
|
}
|
||
|
$cache[ $item . $type ] = $this->options[ $this->prefix . $prefix . $item . '_' . $type ];
|
||
|
} else {
|
||
|
if ( 'no' == $this->options[ $field ] ) {
|
||
|
return false;
|
||
|
}
|
||
|
if ( 'sel' === $this->options[ $field ] ) {
|
||
|
return false;
|
||
|
}
|
||
|
$cache[ $item . $type ] = $this->options[ $field ];
|
||
|
}
|
||
|
|
||
|
return $cache[ $item . $type ];
|
||
|
}
|
||
|
if ( $nodefaults ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return $defaults[ $item ];
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get priority settings for sitemap entries.
|
||
|
*
|
||
|
* @param $item
|
||
|
* @param bool $nodefaults
|
||
|
* @param string $type
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
function get_default_priority( $item, $nodefaults = false, $type = '' ) {
|
||
|
$defaults = array(
|
||
|
'homepage' => '1.0',
|
||
|
'blog' => '0.9',
|
||
|
'sitemap' => '0.8',
|
||
|
'post' => '0.7',
|
||
|
'archive' => '0.5',
|
||
|
'author' => '0.3',
|
||
|
'taxonomies' => '0.3',
|
||
|
);
|
||
|
static $cache = array();
|
||
|
|
||
|
return $this->get_default_values( $defaults, 'prio_', $cache, $item, $nodefaults, $type );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get frequency settings for sitemap entries.
|
||
|
*
|
||
|
* @param $item
|
||
|
* @param bool $nodefaults
|
||
|
* @param string $type
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
function get_default_frequency( $item, $nodefaults = false, $type = '' ) {
|
||
|
$defaults = array(
|
||
|
'homepage' => 'always',
|
||
|
'blog' => 'daily',
|
||
|
'sitemap' => 'hourly',
|
||
|
'post' => 'weekly',
|
||
|
'archive' => 'monthly',
|
||
|
'author' => 'weekly',
|
||
|
'taxonomies' => 'monthly',
|
||
|
);
|
||
|
static $cache = array();
|
||
|
|
||
|
return $this->get_default_values( $defaults, 'freq_', $cache, $item, $nodefaults, $type );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Build an index of sitemaps used.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_sitemap_index_filenames() {
|
||
|
$files = array();
|
||
|
$options = $this->options;
|
||
|
$prefix = $options["{$this->prefix}filename"];
|
||
|
$suffix = '.xml';
|
||
|
if ( $options["{$this->prefix}gzipped"] ) {
|
||
|
$suffix .= '.gz';
|
||
|
}
|
||
|
if ( empty( $options["{$this->prefix}posttypes"] ) ) {
|
||
|
$options["{$this->prefix}posttypes"] = array();
|
||
|
}
|
||
|
if ( empty( $options["{$this->prefix}taxonomies"] ) ) {
|
||
|
$options["{$this->prefix}taxonomies"] = array();
|
||
|
}
|
||
|
$options["{$this->prefix}posttypes"] = array_diff( $options["{$this->prefix}posttypes"], array( 'all' ) );
|
||
|
$options["{$this->prefix}taxonomies"] = array_diff( $options["{$this->prefix}taxonomies"], array( 'all' ) );
|
||
|
$url_base = trailingslashit( get_home_url() );
|
||
|
$files[] = array( 'loc' => $url_base . $prefix . '_addl' . $suffix );
|
||
|
if ( ! empty( $options["{$this->prefix}posttypes"] ) ) {
|
||
|
$prio = $this->get_default_priority( 'post' );
|
||
|
$freq = $this->get_default_frequency( 'post' );
|
||
|
$post_counts = $this->get_all_post_counts( array(
|
||
|
'post_type' => $options["{$this->prefix}posttypes"],
|
||
|
'post_status' => 'publish',
|
||
|
) );
|
||
|
if ( ! is_array( $post_counts ) && is_array( $options["{$this->prefix}posttypes"] ) && count( $options["{$this->prefix}posttypes"] ) == 1 ) {
|
||
|
$post_counts = array( $options["{$this->prefix}posttypes"][0] => $post_counts );
|
||
|
}
|
||
|
foreach ( $options["{$this->prefix}posttypes"] as $sm ) {
|
||
|
if ( 0 == $post_counts[ $sm ] ) {
|
||
|
continue;
|
||
|
}
|
||
|
if ( $this->paginate ) {
|
||
|
if ( $post_counts[ $sm ] > $this->max_posts ) {
|
||
|
$count = 1;
|
||
|
for ( $post_count = 0; $post_count < $post_counts[ $sm ]; $post_count += $this->max_posts ) {
|
||
|
$files[] = array(
|
||
|
'loc' => $url_base . $prefix . '_' . $sm . '_' . ( $count ++ ) . $suffix,
|
||
|
'priority' => $prio,
|
||
|
'changefreq' => $freq,
|
||
|
);
|
||
|
}
|
||
|
} else {
|
||
|
$files[] = array(
|
||
|
'loc' => $url_base . $prefix . '_' . $sm . $suffix,
|
||
|
'priority' => $prio,
|
||
|
'changefreq' => $freq,
|
||
|
);
|
||
|
}
|
||
|
} else {
|
||
|
$files[] = array(
|
||
|
'loc' => $url_base . $prefix . '_' . $sm . $suffix,
|
||
|
'priority' => $prio,
|
||
|
'changefreq' => $freq,
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ( $this->option_isset( 'archive' ) ) {
|
||
|
$files[] = array(
|
||
|
'loc' => $url_base . $prefix . '_archive' . $suffix,
|
||
|
'priority' => $this->get_default_priority( 'archive' ),
|
||
|
'changefreq' => $this->get_default_frequency( 'archive' ),
|
||
|
);
|
||
|
}
|
||
|
if ( $this->option_isset( 'author' ) ) {
|
||
|
$files[] = array(
|
||
|
'loc' => $url_base . $prefix . '_author' . $suffix,
|
||
|
'priority' => $this->get_default_priority( 'author' ),
|
||
|
'changefreq' => $this->get_default_frequency( 'author' ),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $options["{$this->prefix}taxonomies"] ) ) {
|
||
|
foreach ( $options["{$this->prefix}taxonomies"] as $sm ) {
|
||
|
$term_count = wp_count_terms( $sm, array( 'hide_empty' => true ) );
|
||
|
if ( ! is_wp_error( $term_count ) && ( $term_count > 0 ) ) {
|
||
|
if ( $this->paginate ) {
|
||
|
if ( $term_count > $this->max_posts ) {
|
||
|
$count = 1;
|
||
|
for ( $tc = 0; $tc < $term_count; $tc += $this->max_posts ) {
|
||
|
$files[] = array(
|
||
|
'loc' => $url_base . $prefix . '_' . $sm . '_' . ( $count ++ ) . $suffix,
|
||
|
'priority' => $this->get_default_priority( 'taxonomies' ),
|
||
|
'changefreq' => $this->get_default_frequency( 'taxonomies' ),
|
||
|
);
|
||
|
}
|
||
|
} else {
|
||
|
$files[] = array(
|
||
|
'loc' => $url_base . $prefix . '_' . $sm . $suffix,
|
||
|
'priority' => $this->get_default_priority( 'taxonomies' ),
|
||
|
'changefreq' => $this->get_default_frequency( 'taxonomies' ),
|
||
|
);
|
||
|
}
|
||
|
} else {
|
||
|
$files[] = array(
|
||
|
'loc' => $url_base . $prefix . '_' . $sm . $suffix,
|
||
|
'priority' => $this->get_default_priority( 'taxonomies' ),
|
||
|
'changefreq' => $this->get_default_frequency( 'taxonomies' ),
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
foreach ( $this->get_child_sitemap_urls() as $csm ) {
|
||
|
$files[] = array(
|
||
|
'loc' => $csm,
|
||
|
'priority' => $this->get_default_priority( 'sitemap' ),
|
||
|
'changefreq' => $this->get_default_frequency( 'sitemap' ),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return $files;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Build the sitemap.
|
||
|
*
|
||
|
* @param $sitemap_type
|
||
|
* @param int $page
|
||
|
* @param string $filename
|
||
|
* @param string $comment
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
function do_build_sitemap( $sitemap_type, $page = 0, $filename = '', $comment = '' ) {
|
||
|
if ( empty( $filename ) ) {
|
||
|
if ( 'root' === $sitemap_type ) {
|
||
|
$filename = $this->options["{$this->prefix}filename"];
|
||
|
} else {
|
||
|
$filename = $this->options["{$this->prefix}filename"] . '_' . $sitemap_type;
|
||
|
}
|
||
|
}
|
||
|
if ( empty( $comment ) ) {
|
||
|
$comment = "file '%s' statically";
|
||
|
}
|
||
|
$sitemap_data = $this->get_sitemap_data( $sitemap_type, $page );
|
||
|
if ( ( 'root' === $sitemap_type ) && ! empty( $this->options["{$this->prefix}indexes"] ) ) {
|
||
|
return $this->build_sitemap_index( $sitemap_data, sprintf( $comment, $filename ) );
|
||
|
} else {
|
||
|
return $this->build_sitemap( $sitemap_data, sprintf( $comment, $filename ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Write the sitemap.
|
||
|
*
|
||
|
* @param $sitemap_type
|
||
|
* @param int $page
|
||
|
* @param string $filename
|
||
|
* @param string $comment
|
||
|
*/
|
||
|
function do_write_sitemap( $sitemap_type, $page = 0, $filename = '', $comment = '' ) {
|
||
|
if ( empty( $filename ) ) {
|
||
|
if ( 'root' === $sitemap_type ) {
|
||
|
$filename = $this->options["{$this->prefix}filename"];
|
||
|
} else {
|
||
|
$filename = $this->options["{$this->prefix}filename"] . '_' . $sitemap_type;
|
||
|
}
|
||
|
}
|
||
|
if ( empty( $comment ) ) {
|
||
|
$comment = "file '%s' statically";
|
||
|
}
|
||
|
$this->write_sitemaps( $filename, $this->do_build_sitemap( $sitemap_type, $page, $filename, $comment ) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Build all the indexes.
|
||
|
*/
|
||
|
function do_indexed_sitemaps() {
|
||
|
$this->start_memory_usage = memory_get_peak_usage();
|
||
|
$options = $this->options;
|
||
|
|
||
|
$this->do_write_sitemap( 'root' );
|
||
|
$this->do_write_sitemap( 'addl' );
|
||
|
|
||
|
if ( $this->option_isset( 'archive' ) ) {
|
||
|
$this->do_write_sitemap( 'archive' );
|
||
|
}
|
||
|
if ( $this->option_isset( 'author' ) ) {
|
||
|
$this->do_write_sitemap( 'author' );
|
||
|
}
|
||
|
|
||
|
if ( ( ! isset( $options["{$this->prefix}posttypes"] ) ) || ( ! is_array( $options["{$this->prefix}posttypes"] ) ) ) {
|
||
|
$options["{$this->prefix}posttypes"] = array();
|
||
|
}
|
||
|
if ( ( ! isset( $options["{$this->prefix}taxonomies"] ) ) || ( ! is_array( $options["{$this->prefix}taxonomies"] ) ) ) {
|
||
|
$options["{$this->prefix}taxonomies"] = array();
|
||
|
}
|
||
|
$options["{$this->prefix}posttypes"] = array_diff( $options["{$this->prefix}posttypes"], array( 'all' ) );
|
||
|
$options["{$this->prefix}taxonomies"] = array_diff( $options["{$this->prefix}taxonomies"], array( 'all' ) );
|
||
|
|
||
|
if ( ! empty( $options["{$this->prefix}posttypes"] ) ) {
|
||
|
$post_counts = $this->get_all_post_counts( array(
|
||
|
'post_type' => $options["{$this->prefix}posttypes"],
|
||
|
'post_status' => 'publish',
|
||
|
) );
|
||
|
foreach ( $options["{$this->prefix}posttypes"] as $posttype ) {
|
||
|
if ( 0 === $post_counts[ $posttype ] ) {
|
||
|
continue;
|
||
|
}
|
||
|
if ( $this->paginate && ( $post_counts[ $posttype ] > $this->max_posts ) ) {
|
||
|
$count = 1;
|
||
|
for ( $post_count = 0; $post_count < $post_counts[ $posttype ]; $post_count += $this->max_posts ) {
|
||
|
$this->do_write_sitemap( $posttype, $count - 1, $options["{$this->prefix}filename"] . "_{$posttype}_{$count}" );
|
||
|
$count ++;
|
||
|
}
|
||
|
} else {
|
||
|
$this->do_write_sitemap( $posttype );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $options["{$this->prefix}taxonomies"] ) ) {
|
||
|
foreach ( $options["{$this->prefix}taxonomies"] as $taxonomy ) {
|
||
|
$term_count = wp_count_terms( $taxonomy, array( 'hide_empty' => true ) );
|
||
|
if ( ! is_wp_error( $term_count ) && ( $term_count > 0 ) ) {
|
||
|
if ( $this->paginate ) {
|
||
|
if ( $term_count > $this->max_posts ) {
|
||
|
$count = 1;
|
||
|
for ( $tc = 0; $tc < $term_count; $tc += $this->max_posts ) {
|
||
|
$this->do_write_sitemap( $taxonomy, $tc, $options["{$this->prefix}filename"] . "_{$taxonomy}_{$count}" );
|
||
|
$count ++;
|
||
|
}
|
||
|
} else {
|
||
|
$this->do_write_sitemap( $taxonomy );
|
||
|
}
|
||
|
} else {
|
||
|
$this->do_write_sitemap( $taxonomy );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
$this->log_stats( 'indexed', $options["{$this->prefix}gzipped"], false );
|
||
|
}
|
||
|
|
||
|
function remove_posts_page( $postspageid ) {
|
||
|
if ( in_array( $postspageid, $this->excludes ) ) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if ( in_array( get_post_field( 'post_name', $postspageid ), $this->excludes ) ) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
function remove_homepage( $homepage_id ) {
|
||
|
if ( in_array( $homepage_id, $this->excludes ) ) {
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
if ( in_array( get_post_field( 'post_name', $homepage_id ), $this->excludes ) ) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get simple sitemap.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_simple_sitemap() {
|
||
|
$child = $this->get_child_sitemap_urls();
|
||
|
$options = $this->options;
|
||
|
if ( is_array( $options["{$this->prefix}posttypes"] ) ) {
|
||
|
$options["{$this->prefix}posttypes"] = array_diff( $options["{$this->prefix}posttypes"], array( 'all' ) );
|
||
|
}
|
||
|
if ( is_array( $options["{$this->prefix}taxonomies"] ) ) {
|
||
|
$options["{$this->prefix}taxonomies"] = array_diff( $options["{$this->prefix}taxonomies"], array( 'all' ) );
|
||
|
}
|
||
|
$prio = $this->get_all_post_priority_data( $options["{$this->prefix}posttypes"] );
|
||
|
|
||
|
$home = array(
|
||
|
'loc' => get_home_url(),
|
||
|
'priority' => $this->get_default_priority( 'homepage' ),
|
||
|
'changefreq' => $this->get_default_frequency( 'homepage' ),
|
||
|
);
|
||
|
|
||
|
$posts = $postspageid = get_option( 'page_for_posts' ); // It's 0 if posts are on homepage, otherwise it's the id of the posts page.
|
||
|
|
||
|
$this->paginate = false;
|
||
|
if ( $posts ) {
|
||
|
$posts = $this->get_permalink( $posts );
|
||
|
if ( $posts == $home['loc'] ) {
|
||
|
$posts = null;
|
||
|
} else {
|
||
|
$posts = array(
|
||
|
'loc' => $posts,
|
||
|
'priority' => $this->get_default_priority( 'blog' ),
|
||
|
'changefreq' => $this->get_default_frequency( 'blog' ),
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( $this->option_isset( 'archive' ) ) {
|
||
|
$prio = array_merge( $prio, $this->get_archive_prio_data() );
|
||
|
}
|
||
|
if ( $this->option_isset( 'author' ) ) {
|
||
|
$prio = array_merge( $prio, $this->get_author_prio_data() );
|
||
|
}
|
||
|
foreach ( $prio as $k => $p ) {
|
||
|
if ( untrailingslashit( $p['loc'] ) === untrailingslashit( $home['loc'] ) ) {
|
||
|
$prio[ $k ]['priority'] = '1.0';
|
||
|
$home = null;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if ( ( null != $posts ) && isset( $posts['loc'] ) ) {
|
||
|
foreach ( $prio as $k => $p ) {
|
||
|
if ( $p['loc'] === $posts['loc'] ) {
|
||
|
$prio[ $k ]['priority'] = $this->get_default_priority( 'blog' );
|
||
|
$prio[ $k ]['changefreq'] = $this->get_default_frequency( 'blog' );
|
||
|
$posts = null;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ( is_array( $posts ) && $this->remove_posts_page( $postspageid ) !== true ) {
|
||
|
array_unshift( $prio, $posts );
|
||
|
}
|
||
|
|
||
|
if ( is_array( $home ) ) {
|
||
|
array_unshift( $prio, $home );
|
||
|
}
|
||
|
$terms = get_terms( $options["{$this->prefix}taxonomies"], $this->get_tax_args() );
|
||
|
$prio2 = $this->get_term_priority_data( $terms );
|
||
|
$prio3 = $this->get_addl_pages_only();
|
||
|
$prio = array_merge( $child, $prio, $prio2, $prio3 );
|
||
|
if ( is_array( $this->extra_sitemaps ) ) {
|
||
|
foreach ( $this->extra_sitemaps as $sitemap_type ) {
|
||
|
$sitemap_data = array();
|
||
|
$sitemap_data = apply_filters( $this->prefix . 'custom_' . $sitemap_type, $sitemap_data, $page, $this_options );
|
||
|
$prio = array_merge( $prio, $sitemap_data );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $prio;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Build a single, stand-alone sitemap without indexes.
|
||
|
*
|
||
|
* @param string $comment
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
function do_simple_sitemap( $comment = '' ) {
|
||
|
$sitemap_data = $this->get_simple_sitemap();
|
||
|
$sitemap_data = apply_filters( $this->prefix . 'data', $sitemap_data, 'root', 0, $this->options );
|
||
|
|
||
|
return $this->build_sitemap( $sitemap_data, $comment );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the sitemap URL.
|
||
|
*
|
||
|
* Has a filter for using something other than the dynamically generated one.
|
||
|
* Using the filter you need the full path to the custom xsl file.
|
||
|
*
|
||
|
* @see https://semperplugins.com/documentation/aioseop_sitemap_xsl_url/
|
||
|
*
|
||
|
* @since 2.3.6
|
||
|
*/
|
||
|
function get_sitemap_xsl() {
|
||
|
|
||
|
return esc_url( apply_filters( 'aioseop_sitemap_xsl_url', home_url( '/sitemap.xsl' ) ) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Output the XML for a sitemap.
|
||
|
*
|
||
|
* @param $urls
|
||
|
* @param string $comment
|
||
|
*
|
||
|
* @return null
|
||
|
*/
|
||
|
function output_sitemap( $urls, $comment = '' ) {
|
||
|
$max_items = 50000;
|
||
|
if ( ! is_array( $urls ) ) {
|
||
|
return null;
|
||
|
}
|
||
|
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n\r\n";
|
||
|
echo '<!-- ' . sprintf( $this->comment_string, $comment, AIOSEOP_VERSION, date( 'D, d M Y H:i:s e' ) ) . " -->\r\n";
|
||
|
$plugin_path = $this->plugin_path['url'];
|
||
|
$plugin_url = parse_url( $plugin_path );
|
||
|
$current_host = $_SERVER['HTTP_HOST'];
|
||
|
if ( empty( $current_host ) ) {
|
||
|
$current_host = $_SERVER['SERVER_NAME'];
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $current_host ) && ( $current_host !== $plugin_url['host'] ) ) {
|
||
|
$plugin_url['host'] = $current_host;
|
||
|
}
|
||
|
|
||
|
// Code unset( $plugin_url['scheme'] );.
|
||
|
$plugin_path = $this->unparse_url( $plugin_url );
|
||
|
|
||
|
// Using the filter you need the full path to the custom xsl file.
|
||
|
$xsl_url = $this->get_sitemap_xsl();
|
||
|
|
||
|
$xml_header = '<?xml-stylesheet type="text/xsl" href="' . $xsl_url . '"?>' . "\r\n"
|
||
|
. '<urlset ';
|
||
|
$namespaces = apply_filters( $this->prefix . 'xml_namespace', array( 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9' ) );
|
||
|
if ( ! empty( $namespaces ) ) {
|
||
|
$ns = array();
|
||
|
foreach ( $namespaces as $k => $v ) {
|
||
|
$ns[] = esc_attr( $k ) . '=' . '"' . esc_url( $v, array( 'http', 'https' ) ) . '"';
|
||
|
}
|
||
|
$xml_header .= join( "\r\n\t", $ns );
|
||
|
}
|
||
|
$xml_header .= '>' . "\r\n";
|
||
|
echo $xml_header;
|
||
|
$count = 0;
|
||
|
foreach ( $urls as $url ) {
|
||
|
echo "\t<url>\r\n";
|
||
|
if ( is_array( $url ) ) {
|
||
|
foreach ( $url as $k => $v ) {
|
||
|
if ( ! empty( $v ) ) {
|
||
|
if ( 'loc' === $k ) {
|
||
|
$v = esc_url( $v );
|
||
|
}
|
||
|
if ( is_array( $v ) ) {
|
||
|
$buf = "\t\t\t<$k>\r\n";
|
||
|
foreach ( $v as $ext => $attr ) {
|
||
|
if ( is_array( $attr ) ) {
|
||
|
$buf = '';
|
||
|
echo "\t\t<$k>\r\n";
|
||
|
foreach ( $attr as $a => $nested ) {
|
||
|
if ( is_array( $nested ) ) {
|
||
|
echo "\t\t\t<$a>\r\n";
|
||
|
foreach ( $nested as $next => $nattr ) {
|
||
|
echo "\t\t\t\t<$next>$nattr</$next>\r\n";
|
||
|
}
|
||
|
echo "\t\t\t</$a>\r\n";
|
||
|
} else {
|
||
|
echo "\t\t\t<$a>$nested</$a>\r\n";
|
||
|
}
|
||
|
}
|
||
|
echo "\t\t</$k>\r\n";
|
||
|
} else {
|
||
|
$buf .= "\t\t\t<$ext>$attr</$ext>\r\n";
|
||
|
}
|
||
|
}
|
||
|
if ( ! empty( $buf ) ) {
|
||
|
echo $buf . "\t\t</$k>\r\n";
|
||
|
}
|
||
|
} else {
|
||
|
echo "\t\t<$k>$v</$k>\r\n";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
echo "\t\t<loc>" . esc_url( $url ) . "</loc>\r\n";
|
||
|
}
|
||
|
echo "\t</url>\r\n";
|
||
|
if ( $count >= $max_items ) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
echo '</urlset>';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Output the XML for a sitemap index.
|
||
|
*
|
||
|
* @param $urls
|
||
|
* @param string $comment
|
||
|
*
|
||
|
* @return null
|
||
|
*/
|
||
|
function output_sitemap_index( $urls, $comment = '' ) {
|
||
|
$max_items = 50000;
|
||
|
if ( ! is_array( $urls ) ) {
|
||
|
return null;
|
||
|
}
|
||
|
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n\r\n";
|
||
|
echo '<!-- ' . sprintf( $this->comment_string, $comment, AIOSEOP_VERSION, date( 'D, d M Y H:i:s e' ) ) . " -->\r\n";
|
||
|
$xsl_url = $this->get_sitemap_xsl();
|
||
|
echo '<?xml-stylesheet type="text/xsl" href="' . $xsl_url . '"?>' . "\r\n";
|
||
|
echo '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\r\n";
|
||
|
$count = 0;
|
||
|
foreach ( $urls as $url ) {
|
||
|
echo "\t<sitemap>\r\n";
|
||
|
if ( is_array( $url ) ) {
|
||
|
foreach ( $url as $k => $v ) {
|
||
|
if ( 'loc' === $k ) {
|
||
|
echo "\t\t<$k>" . esc_url( $v ) . "</$k>\r\n";
|
||
|
} elseif ( 'lastmod' === $k ) {
|
||
|
echo "\t\t<$k>$v</$k>\r\n";
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
echo "\t\t<loc>" . esc_url( $url ) . "</loc>\r\n";
|
||
|
}
|
||
|
echo "\t</sitemap>\r\n";
|
||
|
$count ++;
|
||
|
if ( $count >= $max_items ) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
echo '</sitemapindex>';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return an XML sitemap index as a string.
|
||
|
*
|
||
|
* @param $urls
|
||
|
* @param string $comment
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
function build_sitemap_index( $urls, $comment = '' ) {
|
||
|
ob_start();
|
||
|
$this->output_sitemap_index( $urls, $comment );
|
||
|
|
||
|
return ob_get_clean();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return an XML sitemap as a string.
|
||
|
*
|
||
|
* @param $urls
|
||
|
* @param string $comment
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
function build_sitemap( $urls, $comment = '' ) {
|
||
|
ob_start();
|
||
|
$this->output_sitemap( $urls, $comment );
|
||
|
|
||
|
return ob_get_clean();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return sitemap data for an array of terms.
|
||
|
*
|
||
|
* @param $terms
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_term_priority_data( $terms ) {
|
||
|
$prio = array();
|
||
|
if ( is_array( $terms ) ) {
|
||
|
$def_prio = $this->get_default_priority( 'taxonomies' );
|
||
|
$def_freq = $this->get_default_frequency( 'taxonomies' );
|
||
|
foreach ( $terms as $term ) {
|
||
|
$pr_info = array();
|
||
|
$pr_info['loc'] = $this->get_term_link( $term, $term->taxonomy );
|
||
|
if ( ( 'sel' === $this->options[ $this->prefix . 'prio_taxonomies' ] ) && isset( $this->options[ $this->prefix . 'prio_taxonomies_' . $term->taxonomy ] ) && ( 'no' != $this->options[ $this->prefix . 'prio_taxonomies_' . $term->taxonomy ] ) ) {
|
||
|
$pr_info['priority'] = $this->options[ $this->prefix . 'prio_taxonomies_' . $term->taxonomy ];
|
||
|
} else {
|
||
|
$pr_info['priority'] = $def_prio;
|
||
|
}
|
||
|
if ( ( 'sel' === $this->options[ $this->prefix . 'freq_taxonomies' ] ) && isset( $this->options[ $this->prefix . 'freq_taxonomies_' . $term->taxonomy ] ) && ( 'no' != $this->options[ $this->prefix . 'freq_taxonomies_' . $term->taxonomy ] ) ) {
|
||
|
$pr_info['changefreq'] = $this->options[ $this->prefix . 'freq_taxonomies_' . $term->taxonomy ];
|
||
|
} else {
|
||
|
$pr_info['changefreq'] = $def_freq;
|
||
|
}
|
||
|
$prio[] = $pr_info;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $prio;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return a list of permalinks for an array of terms.
|
||
|
*
|
||
|
* @param $terms
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_term_permalinks( $terms ) {
|
||
|
$links = array();
|
||
|
if ( is_array( $terms ) ) {
|
||
|
foreach ( $terms as $term ) {
|
||
|
$url = $this->get_term_link( $term );
|
||
|
$links[] = $url;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $links;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return permalinks for archives.
|
||
|
*
|
||
|
* @param $posts
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_archive_permalinks( $posts ) {
|
||
|
$links = array();
|
||
|
$archives = array();
|
||
|
if ( is_array( $posts ) ) {
|
||
|
foreach ( $posts as $post ) {
|
||
|
$date = mysql2date( 'U', $post->post_date );
|
||
|
$year = date( 'Y', $date );
|
||
|
$month = date( 'm', $date );
|
||
|
$archives[ $year . '-' . $month ] = array( $year, $month );
|
||
|
}
|
||
|
}
|
||
|
$archives = array_keys( $archives );
|
||
|
foreach ( $archives as $d ) {
|
||
|
$links[] = get_month_link( $d[0], $d[1] );
|
||
|
}
|
||
|
|
||
|
return $links;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return permalinks for authors.
|
||
|
*
|
||
|
* @param $posts
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_author_permalinks( $posts ) {
|
||
|
$links = array();
|
||
|
$authors = array();
|
||
|
if ( is_array( $posts ) ) {
|
||
|
foreach ( $posts as $post ) {
|
||
|
$authors[ $post->author_id ] = 1;
|
||
|
}
|
||
|
}
|
||
|
$authors = array_keys( $authors );
|
||
|
foreach ( $authors as $auth_id ) {
|
||
|
$links[] = get_author_posts_url( $auth_id );
|
||
|
}
|
||
|
|
||
|
return $links;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return permalinks for posts.
|
||
|
*
|
||
|
* @param $posts
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_post_permalinks( $posts ) {
|
||
|
$links = array();
|
||
|
if ( is_array( $posts ) ) {
|
||
|
foreach ( $posts as $post ) {
|
||
|
$post->filter = 'sample';
|
||
|
$url = $this->get_permalink( $post );
|
||
|
$links[] = $url;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $links;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Convert back from parse_url.
|
||
|
*
|
||
|
* Props to thomas at gielfeldt dot com.
|
||
|
*
|
||
|
* @link http://www.php.net/manual/en/function.parse-url.php#106731
|
||
|
*
|
||
|
* @param $parsed_url
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
function unparse_url( $parsed_url ) {
|
||
|
$scheme = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] . '://' : '';
|
||
|
$host = isset( $parsed_url['host'] ) ? $parsed_url['host'] : '';
|
||
|
if ( ! empty( $host ) && empty( $scheme ) ) {
|
||
|
$scheme = '//';
|
||
|
}
|
||
|
$port = isset( $parsed_url['port'] ) ? ':' . $parsed_url['port'] : '';
|
||
|
$user = isset( $parsed_url['user'] ) ? $parsed_url['user'] : '';
|
||
|
$pass = isset( $parsed_url['pass'] ) ? ':' . $parsed_url['pass'] : '';
|
||
|
$pass = ( $user || $pass ) ? "$pass@" : '';
|
||
|
$path = isset( $parsed_url['path'] ) ? $parsed_url['path'] : '';
|
||
|
$query = isset( $parsed_url['query'] ) ? '?' . $parsed_url['query'] : '';
|
||
|
$fragment = isset( $parsed_url['fragment'] ) ? '#' . $parsed_url['fragment'] : '';
|
||
|
|
||
|
return "$scheme$user$pass$host$port$path$query$fragment";
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets additional pages.
|
||
|
*
|
||
|
* Return data for user entered additional pages.
|
||
|
*
|
||
|
* @return array|mixed|void
|
||
|
*/
|
||
|
function get_addl_pages_only() {
|
||
|
$pages = array();
|
||
|
if ( ! empty( $this->options[ $this->prefix . 'addl_pages' ] ) ) {
|
||
|
$siteurl = parse_url( get_home_url() );
|
||
|
foreach ( $this->options[ $this->prefix . 'addl_pages' ] as $k => $v ) {
|
||
|
$url = parse_url( $k );
|
||
|
if ( empty( $url['scheme'] ) ) {
|
||
|
$url['scheme'] = $siteurl['scheme'];
|
||
|
}
|
||
|
if ( empty( $url['host'] ) ) {
|
||
|
$url['host'] = $siteurl['host'];
|
||
|
}
|
||
|
if ( ! empty( $url['path'] ) && substr( $url['path'], 0, 1 ) !== '/' ) {
|
||
|
$url['path'] = '/' . $url['path'];
|
||
|
}
|
||
|
$freq = $prio = $mod = '';
|
||
|
if ( ! empty( $v['mod'] ) ) {
|
||
|
$mod = $v['mod'];
|
||
|
}
|
||
|
if ( ! empty( $v['freq'] ) ) {
|
||
|
$freq = $v['freq'];
|
||
|
}
|
||
|
if ( ! empty( $v['prio'] ) ) {
|
||
|
$prio = $v['prio'];
|
||
|
}
|
||
|
if ( 'no' == $freq ) {
|
||
|
$freq = '';
|
||
|
}
|
||
|
if ( 'no' == $prio ) {
|
||
|
$prio = '';
|
||
|
}
|
||
|
$mod = date( 'Y-m-d\TH:i:s\Z', mysql2date( 'U', $mod ) );
|
||
|
$pages[] = array(
|
||
|
'loc' => $this->unparse_url( $url ),
|
||
|
'lastmod' => $mod,
|
||
|
'changefreq' => $freq,
|
||
|
'priority' => $prio,
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
$pages = apply_filters( $this->prefix . 'addl_pages_only', $pages );
|
||
|
|
||
|
return $pages;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return data for user entered additional pages and extra pages.
|
||
|
*
|
||
|
* @return array|mixed|void
|
||
|
*/
|
||
|
function get_addl_pages() {
|
||
|
$home = array();
|
||
|
$home = array(
|
||
|
'loc' => get_home_url(),
|
||
|
'priority' => $this->get_default_priority( 'homepage' ),
|
||
|
'changefreq' => $this->get_default_frequency( 'homepage' ),
|
||
|
);
|
||
|
$posts = get_option( 'page_for_posts' );
|
||
|
if ( $posts ) {
|
||
|
$posts = $this->get_permalink( $posts );
|
||
|
if ( $posts == $home['loc'] ) {
|
||
|
$posts = array();
|
||
|
} else {
|
||
|
$posts = array(
|
||
|
'loc' => $posts,
|
||
|
'priority' => $this->get_default_priority( 'blog' ),
|
||
|
'changefreq' => $this->get_default_frequency( 'blog' ),
|
||
|
);
|
||
|
}
|
||
|
} else {
|
||
|
$posts = array();
|
||
|
}
|
||
|
$pages = $this->get_addl_pages_only();
|
||
|
if ( ! empty( $home ) ) {
|
||
|
$pages[] = $home;
|
||
|
}
|
||
|
if ( ! empty( $posts ) ) {
|
||
|
$pages[] = $posts;
|
||
|
}
|
||
|
$pages = apply_filters( $this->prefix . 'addl_pages', $pages );
|
||
|
|
||
|
return $pages;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return links for user entered additional pages.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_addl_page_links() {
|
||
|
if ( ! empty( $this->options[ $this->prefix . 'addl_pages' ] ) ) {
|
||
|
return array_keys( $this->options[ $this->prefix . 'addl_pages' ] );
|
||
|
}
|
||
|
|
||
|
return array();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Scores posts based on date and relative comment count, if any.
|
||
|
*
|
||
|
* @param $date
|
||
|
* @param int $stats
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_prio_calc( $date, $stats = 0 ) {
|
||
|
static $cur_time = null;
|
||
|
if ( null === $cur_time ) {
|
||
|
$cur_time = time();
|
||
|
}
|
||
|
$time = $cur_time - mysql2date( 'U', $date );
|
||
|
if ( ! empty( $stats ) && isset( $stats['max'] ) && $stats['max'] ) {
|
||
|
$minadj = $time >> 3;
|
||
|
$maxadj = $time >> 1;
|
||
|
$avg = $stats['count'] / $stats['total'];
|
||
|
$calc = ( $stats['comment_count'] - $stats['min'] ) / $stats['max'];
|
||
|
$calc = $maxadj * $calc;
|
||
|
if ( $avg < $stats['comment_count'] ) {
|
||
|
$minadj = $time >> 2;
|
||
|
} else {
|
||
|
$maxadj = $time >> 2;
|
||
|
}
|
||
|
if ( $calc > $maxadj ) {
|
||
|
$calc = $maxadj;
|
||
|
}
|
||
|
if ( $calc < $minadj ) {
|
||
|
$calc = $minadj;
|
||
|
}
|
||
|
$time -= $calc;
|
||
|
}
|
||
|
$days = $time / ( 60 * 60 * 24 );
|
||
|
$prio_table = array(
|
||
|
'daily' => 7,
|
||
|
'weekly' => 30,
|
||
|
'monthly' => 210,
|
||
|
'yearly' => null,
|
||
|
);
|
||
|
$interval = 1.0;
|
||
|
$prev_days = 0;
|
||
|
foreach ( $prio_table as $change => $max_days ) {
|
||
|
$interval -= 0.3;
|
||
|
if ( null === $max_days ) {
|
||
|
$changefreq = $change;
|
||
|
$prio = 0.1;
|
||
|
break;
|
||
|
}
|
||
|
if ( $days < $max_days ) {
|
||
|
$int_days_max = $max_days - $prev_days;
|
||
|
$int_days = $days - $prev_days;
|
||
|
$prio = $interval + ( ( int ) ( 3 * ( ( $max_days - $int_days ) / $int_days_max ) ) / 10.0 );
|
||
|
$changefreq = $change;
|
||
|
break;
|
||
|
}
|
||
|
$prev_days = $max_days;
|
||
|
}
|
||
|
|
||
|
return array( 'lastmod' => $date, 'changefreq' => $changefreq, 'priority' => $prio );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generate sitemap priority data for archives from an array of posts.
|
||
|
*
|
||
|
* @param $posts
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_archive_prio_from_posts( $posts ) {
|
||
|
$archives = array();
|
||
|
if ( is_array( $posts ) ) {
|
||
|
foreach ( $posts as $p ) {
|
||
|
if ( 'post' !== $p->post_type ) {
|
||
|
continue;
|
||
|
}
|
||
|
$date = date( 'Y-m', mysql2date( 'U', $p->post_date ) );
|
||
|
if ( empty( $archives[ $date ] ) ) {
|
||
|
$archives[ $date ] = $p;
|
||
|
} else {
|
||
|
if ( $p->post_modified > $archives[ $date ]->post_modified ) {
|
||
|
$archives[ $date ] = $p;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ( ! empty( $archives ) ) {
|
||
|
return $this->get_prio_from_posts( $archives, $this->get_default_priority( 'archive', true ), $this->get_default_frequency( 'archive', true ), array(
|
||
|
$this,
|
||
|
'get_archive_link_from_post',
|
||
|
) );
|
||
|
}
|
||
|
|
||
|
return $archives;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return an archive link from a post.
|
||
|
*
|
||
|
* @param $post
|
||
|
*
|
||
|
* @return bool|string
|
||
|
*/
|
||
|
function get_archive_link_from_post( $post ) {
|
||
|
if ( 'post' !== $post->post_type ) {
|
||
|
return false;
|
||
|
}
|
||
|
$date = mysql2date( 'U', $post->post_date );
|
||
|
|
||
|
return get_month_link( date( 'Y', $date ), date( 'm', $date ) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generate sitemap priority data for authors from an array of posts.
|
||
|
*
|
||
|
* @param $posts
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_author_prio_from_posts( $posts ) {
|
||
|
$authors = array();
|
||
|
if ( is_array( $posts ) ) {
|
||
|
foreach ( $posts as $p ) {
|
||
|
if ( 'post' !== $p->post_type ) {
|
||
|
continue;
|
||
|
}
|
||
|
if ( empty( $authors[ $p->post_author ] ) ) {
|
||
|
$authors[ $p->post_author ] = $p;
|
||
|
} else {
|
||
|
if ( $p->post_modified > $authors[ $p->post_author ]->post_modified ) {
|
||
|
$authors[ $p->post_author ] = $p;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $this->get_prio_from_posts( $authors, $this->get_default_priority( 'author', true ), $this->get_default_frequency( 'author', true ), array(
|
||
|
$this,
|
||
|
'get_author_link_from_post',
|
||
|
) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return an author link from a post.
|
||
|
*
|
||
|
* @param $post
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
function get_author_link_from_post( $post ) {
|
||
|
return get_author_posts_url( $post->post_author );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return comment statistics on an array of posts.
|
||
|
*
|
||
|
* @param $posts
|
||
|
*
|
||
|
* @return array|int
|
||
|
*/
|
||
|
function get_comment_count_stats( $posts ) {
|
||
|
$count = 0;
|
||
|
$total = 0.0;
|
||
|
$min = null;
|
||
|
$max = 0;
|
||
|
if ( is_array( $posts ) ) {
|
||
|
foreach ( $posts as $post ) {
|
||
|
if ( ! empty( $post->comment_count ) ) {
|
||
|
$cnt = $post->comment_count;
|
||
|
$count ++;
|
||
|
$total += $cnt;
|
||
|
if ( null === $min ) {
|
||
|
$min = $cnt;
|
||
|
}
|
||
|
if ( $max < $cnt ) {
|
||
|
$max = $cnt;
|
||
|
}
|
||
|
if ( $min > $cnt ) {
|
||
|
$min = $cnt;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ( $count ) {
|
||
|
return array( 'max' => $max, 'min' => $min, 'total' => $total, 'count' => $cnt );
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generate sitemap priority data from an array of posts.
|
||
|
*
|
||
|
* @param $posts
|
||
|
* @param bool $prio_override
|
||
|
* @param bool $freq_override
|
||
|
* @param string $linkfunc
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_prio_from_posts( $posts, $prio_override = false, $freq_override = false, $linkfunc = 'get_permalink' ) {
|
||
|
$prio = array();
|
||
|
$args = array(
|
||
|
'prio_override' => $prio_override,
|
||
|
'freq_override' => $freq_override,
|
||
|
'linkfunc' => $linkfunc,
|
||
|
);
|
||
|
if ( $prio_override && $freq_override ) {
|
||
|
$stats = 0;
|
||
|
} else {
|
||
|
$stats = $this->get_comment_count_stats( $posts );
|
||
|
}
|
||
|
if ( is_array( $posts ) ) {
|
||
|
foreach ( $posts as $post ) {
|
||
|
$url = '';
|
||
|
$post->filter = 'sample';
|
||
|
if ( 'get_permalink' === $linkfunc ) {
|
||
|
$url = $this->get_permalink( $post );
|
||
|
} else {
|
||
|
$url = call_user_func( $linkfunc, $post );
|
||
|
}
|
||
|
$date = $post->post_modified;
|
||
|
if ( '0000-00-00 00:00:00' === $date ) {
|
||
|
$date = $post->post_date;
|
||
|
}
|
||
|
if ( '0000-00-00 00:00:00' !== $date ) {
|
||
|
$date = date( 'Y-m-d\TH:i:s\Z', mysql2date( 'U', $date ) );
|
||
|
} else {
|
||
|
$date = 0;
|
||
|
}
|
||
|
if ( $prio_override && $freq_override ) {
|
||
|
$pr_info = array( 'lastmod' => $date, 'changefreq' => null, 'priority' => null );
|
||
|
} else {
|
||
|
if ( empty( $post->comment_count ) ) {
|
||
|
$stat = 0;
|
||
|
} else {
|
||
|
$stat = $stats;
|
||
|
}
|
||
|
if ( ! empty( $stat ) ) {
|
||
|
$stat['comment_count'] = $post->comment_count;
|
||
|
}
|
||
|
$pr_info = $this->get_prio_calc( $date, $stat );
|
||
|
}
|
||
|
if ( $prio_override ) {
|
||
|
$pr_info['priority'] = $prio_override;
|
||
|
}
|
||
|
if ( $freq_override ) {
|
||
|
$pr_info['changefreq'] = $freq_override;
|
||
|
}
|
||
|
if ( ( 'sel' === $this->options[ $this->prefix . 'prio_post' ] ) && isset( $this->options[ $this->prefix . 'prio_post_' . $post->post_type ] ) ) {
|
||
|
if ( ( 'no' != $this->options[ $this->prefix . 'prio_post_' . $post->post_type ] ) && ( 'sel' !== $this->options[ $this->prefix . 'prio_post_' . $post->post_type ] ) ) {
|
||
|
$pr_info['priority'] = $this->options[ $this->prefix . 'prio_post_' . $post->post_type ];
|
||
|
}
|
||
|
}
|
||
|
if ( ( 'sel' === $this->options[ $this->prefix . 'freq_post' ] ) && isset( $this->options[ $this->prefix . 'freq_post_' . $post->post_type ] ) ) {
|
||
|
if ( ( 'no' != $this->options[ $this->prefix . 'freq_post_' . $post->post_type ] ) && ( 'sel' !== $this->options[ $this->prefix . 'freq_post_' . $post->post_type ] ) ) {
|
||
|
$pr_info['changefreq'] = $this->options[ $this->prefix . 'freq_post_' . $post->post_type ];
|
||
|
}
|
||
|
}
|
||
|
$pr_info = array( 'loc' => $url ) + $pr_info; // Prepend loc to the array.
|
||
|
if ( is_float( $pr_info['priority'] ) ) {
|
||
|
$pr_info['priority'] = sprintf( '%0.1F', $pr_info['priority'] );
|
||
|
}
|
||
|
$pr_info = apply_filters( $this->prefix . 'prio_item_filter', $pr_info, $post, $args );
|
||
|
if ( ! empty( $pr_info ) ) {
|
||
|
$prio[] = $pr_info;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $prio;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return excluded categories for taxonomy queries.
|
||
|
*
|
||
|
* @param int $page
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_tax_args( $page = 0 ) {
|
||
|
$args = array();
|
||
|
if ( $this->option_isset( 'excl_categories' ) ) {
|
||
|
$args['exclude'] = $this->options[ $this->prefix . 'excl_categories' ];
|
||
|
}
|
||
|
if ( $this->paginate ) {
|
||
|
$args['number'] = $this->max_posts;
|
||
|
$args['offset'] = $page * $this->max_posts;
|
||
|
|
||
|
}
|
||
|
|
||
|
return $args;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return excluded categories and pages for post queries.
|
||
|
*
|
||
|
* @param $args
|
||
|
*
|
||
|
* @return mixed
|
||
|
*/
|
||
|
function set_post_args( $args ) {
|
||
|
if ( $this->option_isset( 'excl_categories' ) ) {
|
||
|
$cats = array();
|
||
|
foreach ( $this->options[ $this->prefix . 'excl_categories' ] as $c ) {
|
||
|
$cats[] = - $c;
|
||
|
}
|
||
|
$args['category'] = implode( ',', $cats );
|
||
|
}
|
||
|
if ( $this->option_isset( 'excl_pages' ) ) {
|
||
|
$args['exclude'] = $this->options[ $this->prefix . 'excl_pages' ];
|
||
|
}
|
||
|
|
||
|
return $args;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return sitemap data for archives.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_archive_prio_data() {
|
||
|
$args = array( 'numberposts' => 50000, 'post_type' => 'post' );
|
||
|
$args = $this->set_post_args( $args );
|
||
|
$posts = $this->get_all_post_type_data( $args );
|
||
|
|
||
|
return $this->get_archive_prio_from_posts( $posts );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return sitemap data for authors.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_author_prio_data() {
|
||
|
$args = array( 'numberposts' => 50000, 'post_type' => 'post' );
|
||
|
$args = $this->set_post_args( $args );
|
||
|
$posts = $this->get_all_post_type_data( $args );
|
||
|
|
||
|
return $this->get_author_prio_from_posts( $posts );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return sitemap data for posts.
|
||
|
*
|
||
|
* @param string $include
|
||
|
* @param string $status
|
||
|
* @param int $page
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_all_post_priority_data( $include = 'any', $status = 'publish', $page = 0 ) {
|
||
|
$posts = $page_query = array();
|
||
|
if ( $this->paginate ) {
|
||
|
$page_query = array( 'offset' => $page * $this->max_posts );
|
||
|
}
|
||
|
if ( ( 'publish' === $status ) && ( 'attachment' === $include ) ) {
|
||
|
$status = 'inherit';
|
||
|
}
|
||
|
if ( is_array( $include ) && ( ( $pos = array_search( 'attachment', $include ) ) !== false ) ) {
|
||
|
unset( $include[ $pos ] );
|
||
|
$att_args = array( 'post_type' => 'attachment', 'post_status' => 'inherit' );
|
||
|
$att_args = array_merge( $att_args, $page_query );
|
||
|
$posts = $this->get_all_post_type_data( $att_args );
|
||
|
}
|
||
|
$args = array( 'post_type' => $include, 'post_status' => $status );
|
||
|
$args = array_merge( $args, $page_query );
|
||
|
$args = $this->set_post_args( $args );
|
||
|
$posts = array_merge( $this->get_all_post_type_data( $args ), $posts );
|
||
|
|
||
|
return $this->get_prio_from_posts( $posts, $this->get_default_priority( 'post', true ), $this->get_default_frequency( 'post', true ) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return a list of all permalinks.
|
||
|
*
|
||
|
* @param string $include
|
||
|
* @param string $status
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_all_permalinks( $include = 'any', $status = 'publish' ) {
|
||
|
$args = array( 'post_type' => $include, 'post_status' => $status );
|
||
|
$args = $this->set_post_args( $args );
|
||
|
$posts = $this->get_all_post_type_data( $args );
|
||
|
$links = $this->get_post_permalinks( $posts );
|
||
|
if ( $this->option_isset( 'archive' ) ) {
|
||
|
$links = array_merge( $links, $this->get_archive_permalinks( $posts ) );
|
||
|
}
|
||
|
if ( $this->option_isset( 'author' ) ) {
|
||
|
$links = array_merge( $links, $this->get_author_permalinks( $posts ) );
|
||
|
}
|
||
|
|
||
|
return $links;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Static memory cache for permalink_structure option.
|
||
|
*
|
||
|
* @param $pre
|
||
|
*
|
||
|
* @return null
|
||
|
*/
|
||
|
function cache_structure( $pre ) {
|
||
|
return $this->cache_struct;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Static memory cache for home option.
|
||
|
*
|
||
|
* @param $pre
|
||
|
*
|
||
|
* @return null
|
||
|
*/
|
||
|
function cache_home( $pre ) {
|
||
|
return $this->cache_home;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Cache permalink_structure and home for repeated sitemap queries.
|
||
|
*/
|
||
|
function cache_options() {
|
||
|
static $start = true;
|
||
|
if ( $start ) {
|
||
|
$this->cache_struct = get_option( 'permalink_structure' );
|
||
|
if ( ! empty( $this->cache_struct ) ) {
|
||
|
add_filter( 'pre_option_permalink_structure', array( $this, 'cache_structure' ) );
|
||
|
}
|
||
|
$this->cache_home = get_option( 'home' );
|
||
|
if ( ! empty( $this->cache_home ) ) {
|
||
|
add_filter( 'pre_option_home', array( $this, 'cache_home' ) );
|
||
|
}
|
||
|
$start = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Call get_term_link with caching in place.
|
||
|
*
|
||
|
* @param $term
|
||
|
* @param string $taxonomy
|
||
|
*
|
||
|
* @return string|WP_Error
|
||
|
*/
|
||
|
function get_term_link( $term, $taxonomy = '' ) {
|
||
|
static $start = true;
|
||
|
if ( $start ) {
|
||
|
$this->cache_options();
|
||
|
$start = false;
|
||
|
}
|
||
|
|
||
|
return get_term_link( $term, $taxonomy );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Call get_permalink with caching in place.
|
||
|
*
|
||
|
* @param $post
|
||
|
*
|
||
|
* @return false|string
|
||
|
*/
|
||
|
function get_permalink( $post ) {
|
||
|
static $start = true;
|
||
|
if ( $start ) {
|
||
|
$this->cache_options();
|
||
|
$start = false;
|
||
|
}
|
||
|
|
||
|
return get_permalink( $post );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return term counts using wp_count_terms().
|
||
|
*
|
||
|
* @param $args
|
||
|
*
|
||
|
* @return array|int|mixed|null|void|WP_Error
|
||
|
*/
|
||
|
function get_all_term_counts( $args ) {
|
||
|
$term_counts = null;
|
||
|
if ( ! empty( $args ) && ! empty( $args['taxonomy'] ) ) {
|
||
|
if ( ! is_array( $args['taxonomy'] ) || ( count( $args['taxonomy'] ) == 1 ) ) {
|
||
|
if ( is_array( $args['taxonomy'] ) ) {
|
||
|
$args['taxonomy'] = array_shift( $args['taxonomy'] );
|
||
|
}
|
||
|
$term_counts = wp_count_terms( $args['taxonomy'], array( 'hide_empty' => true ) );
|
||
|
} else {
|
||
|
foreach ( $args['taxonomy'] as $taxonomy ) {
|
||
|
if ( 'all' === $taxonomy ) {
|
||
|
continue;
|
||
|
}
|
||
|
$term_counts[ $taxonomy ] = wp_count_terms( $taxonomy, array( 'hide_empty' => true ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
$term_counts = apply_filters( $this->prefix . 'term_counts', $term_counts, $args );
|
||
|
|
||
|
return $term_counts;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return post counts using wp_count_posts().
|
||
|
*
|
||
|
* @param $args
|
||
|
*
|
||
|
* @return mixed|null|void
|
||
|
*/
|
||
|
function get_all_post_counts( $args ) {
|
||
|
$post_counts = null;
|
||
|
$status = 'inherit';
|
||
|
if ( ! empty( $args['post_status'] ) ) {
|
||
|
$status = $args['post_status'];
|
||
|
}
|
||
|
if ( ! empty( $args ) && ! empty( $args['post_type'] ) ) {
|
||
|
if ( ! is_array( $args['post_type'] ) || ( count( $args['post_type'] ) == 1 ) ) {
|
||
|
if ( is_array( $args['post_type'] ) ) {
|
||
|
$args['post_type'] = array_shift( $args['post_type'] );
|
||
|
}
|
||
|
$count = (Array) wp_count_posts( $args['post_type'] );
|
||
|
$post_counts = $count[ $status ];
|
||
|
} else {
|
||
|
foreach ( $args['post_type'] as $post_type ) {
|
||
|
if ( 'all' === $post_type ) {
|
||
|
continue;
|
||
|
}
|
||
|
$count = (Array) wp_count_posts( $post_type );
|
||
|
|
||
|
if ( empty( $count ) ) {
|
||
|
$post_counts[ $post_type ] = 0;
|
||
|
} else {
|
||
|
if ( 'attachment' === $post_type ) {
|
||
|
$post_counts[ $post_type ] = $count['inherit'];
|
||
|
} else {
|
||
|
$post_counts[ $post_type ] = $count[ $status ];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
$post_counts = apply_filters( $this->prefix . 'post_counts', $post_counts, $args );
|
||
|
|
||
|
return $post_counts;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get total post count.
|
||
|
*
|
||
|
* @param $args
|
||
|
*
|
||
|
* @return int|mixed|null|void
|
||
|
*/
|
||
|
function get_total_post_count( $args ) {
|
||
|
$total = 0;
|
||
|
$counts = $this->get_all_post_counts( $args );
|
||
|
if ( ! empty( $counts ) ) {
|
||
|
if ( is_array( $counts ) ) {
|
||
|
foreach ( $counts as $count ) {
|
||
|
$total += $count;
|
||
|
}
|
||
|
} else {
|
||
|
$total = $counts;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $total;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return post data using get_posts().
|
||
|
*
|
||
|
* @param $args
|
||
|
*
|
||
|
* @return array|mixed|void
|
||
|
*/
|
||
|
function get_all_post_type_data( $args ) {
|
||
|
$defaults = array(
|
||
|
'numberposts' => $this->max_posts,
|
||
|
'offset' => 0,
|
||
|
'category' => 0,
|
||
|
'orderby' => 'post_date',
|
||
|
'order' => 'DESC',
|
||
|
'include' => array(),
|
||
|
'exclude' => array(),
|
||
|
'post_type' => 'any',
|
||
|
'meta_key' => '',
|
||
|
'meta_value' => '',
|
||
|
'meta_compare' => '',
|
||
|
'meta_query' => '',
|
||
|
'cache_results' => false,
|
||
|
'no_found_rows' => true,
|
||
|
);
|
||
|
if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
|
||
|
$defaults['suppress_filters'] = false;
|
||
|
}
|
||
|
$args = wp_parse_args( $args, $defaults );
|
||
|
if ( empty( $args['post_type'] ) ) {
|
||
|
return apply_filters( $this->prefix . 'post_filter', array(), $args );
|
||
|
}
|
||
|
$exclude_slugs = array();
|
||
|
if ( ! empty( $args['exclude'] ) ) {
|
||
|
$exclude = preg_split( '/[\s,]+/', trim( $args['exclude'] ) );
|
||
|
if ( ! empty( $exclude ) ) {
|
||
|
foreach ( $exclude as $k => $v ) {
|
||
|
if ( ! is_numeric( $v ) || ( $v != (int) $v ) ) {
|
||
|
$exclude_slugs[] = $v;
|
||
|
unset( $exclude[ $k ] );
|
||
|
}
|
||
|
}
|
||
|
if ( ! empty( $exclude_slugs ) ) {
|
||
|
$args['exclude'] = implode( ',', $exclude );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$ex_args = $args;
|
||
|
$ex_args['meta_key'] = '_aioseop_sitemap_exclude';
|
||
|
$ex_args['meta_value'] = 'on';
|
||
|
$ex_args['meta_compare'] = '=';
|
||
|
$ex_args['fields'] = 'ids';
|
||
|
$ex_args['posts_per_page'] = - 1;
|
||
|
$q = new WP_Query( $ex_args );
|
||
|
if ( ! is_array( $args['exclude'] ) ) {
|
||
|
$args['exclude'] = explode( ',', $args['exclude'] );
|
||
|
}
|
||
|
if ( ! empty( $q->posts ) ) {
|
||
|
$args['exclude'] = array_merge( $args['exclude'], $q->posts );
|
||
|
}
|
||
|
$this->excludes = array_merge( $args['exclude'] , $exclude_slugs ); // Add excluded slugs and IDs to class var.
|
||
|
|
||
|
$posts = get_posts( apply_filters( $this->prefix . 'post_query', $args ) );
|
||
|
if ( ! empty( $exclude_slugs ) ) {
|
||
|
foreach ( $posts as $k => $v ) {
|
||
|
if ( in_array( $v->post_name, $exclude_slugs ) ) {
|
||
|
unset( $posts[ $k ] );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
$posts = apply_filters( $this->prefix . 'post_filter', $posts, $args );
|
||
|
|
||
|
return $posts;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|