2016-11-28 21:52:15 -08:00
< ? php
/**
* Sitemap class .
*
* @ package All - in - One - SEO - Pack
2018-01-26 15:50:15 +01:00
* @ version 2.3 . 13
2016-11-28 21:52:15 -08:00
*/
if ( ! class_exists ( 'All_in_One_SEO_Pack_Sitemap' ) ) {
/**
* Class All_in_One_SEO_Pack_Sitemap
2018-01-26 15:50:15 +01:00
*
* @ since ?
* @ since 2.4 Include images in sitemap .
2016-11-28 21:52:15 -08:00
*/
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 $prio ;
var $prio_sel ;
var $freq ;
var $freq_sel ;
var $extra_sitemaps ;
var $excludes = array ();
2018-01-26 15:50:15 +01:00
/**
* The allowed image extensions .
*
* @ var array $image_extensions The allowed image extensions .
*/
private static $image_extensions = array (
'jpg' ,
'jpeg' ,
'png' ,
'gif' ,
);
2016-11-28 21:52:15 -08:00
/**
* 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' ),
'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' ),
2018-01-26 15:50:15 +01:00
'images' => __ ( 'Exclude Images in your sitemap.' , 'all-in-one-seo-pack' ),
2016-11-28 21:52:15 -08:00
'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' ,
'max_posts' => '#enable-sitemap-indexes' ,
'posttypes' => '#post-types-and-taxonomies' ,
'taxonomies' => '#post-types-and-taxonomies' ,
'archive' => '#include-archive-pages' ,
'author' => '#include-archive-pages' ,
2018-01-26 15:50:15 +01:00
'images' => '#exclude-images' ,
2016-11-28 21:52:15 -08:00
'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' ) ),
'max_posts' => array (
2018-01-26 15:50:15 +01:00
'name' => __ ( 'Maximum Posts Per Sitemap Page' , 'all-in-one-seo-pack' ),
2016-11-28 21:52:15 -08:00
'type' => 'text' ,
'default' => 50000 ,
2018-01-26 15:50:15 +01:00
'condshow' => array ( " { $this -> prefix } indexes " => 'on' , " { $this -> prefix } indexes " => 'on' ),
2016-11-28 21:52:15 -08:00
),
'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' ) ),
2018-01-26 15:50:15 +01:00
'images' => array ( 'name' => __ ( 'Exclude Images' , 'all-in-one-seo-pack' ) ),
2016-11-28 21:52:15 -08:00
'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' ) );
2018-01-26 15:50:15 +01:00
add_action ( 'all_admin_notices' , array ( $this , 'sitemap_notices' ) );
2016-11-28 21:52:15 -08:00
}
2018-01-26 15:50:15 +01:00
/**
* Sitemap notices .
*
* @ since 2.4 . 1
*/
function sitemap_notices () {
$sitemap_max_url_notice_dismissed = get_user_meta ( get_current_user_id (), 'aioseop_sitemap_max_url_notice_dismissed' , true );
if ( ! empty ( $sitemap_max_url_notice_dismissed ) ) {
return ;
}
$options = $this -> options ;
if ( isset ( $options [ " { $this -> prefix } indexes " ] ) && 'on ' !== $options [ " { $this -> prefix } indexes " ] &&
1001 < $options [ " { $this -> prefix } max_posts " ] ) {
$post_counts = $num_terms = 0 ;
$post_counts = $this -> get_total_post_count ( array (
'post_type' => $options [ " { $this -> prefix } posttypes " ],
'post_status' => 'publish' ,
) );
$term_counts = $this -> get_all_term_counts ( array ( 'taxonomy' => $options [ " { $this -> prefix } taxonomies " ] ) );
if ( isset ( $term_counts ) && is_array ( $term_counts ) ){
$num_terms = array_sum ( $term_counts );
}
$sitemap_urls = $post_counts + $num_terms ;
if ( 1001 > $sitemap_urls ) {
return ;
}
$aioseop_plugin_dirname = AIOSEOP_PLUGIN_DIRNAME ;
printf ( '
< div id = " message " class = " notice-warning notice is-dismissible aioseop-notice sitemap_max_urls_notice visibility-notice " >
< p >
< strong >% 1 $s </ strong >< br />
% 2 $s
</ p >
</ div > ' ,
__ ( 'Notice: To avoid problems with your XML Sitemap, we strongly recommend you enable Sitemap Indexes and set the Maximum Posts per Sitemap Page to 1000.' , 'all-in-one-seo-pack' ),
sprintf ( __ ( '%s Click here%s to make these recommended changes.' , 'all-in-one-seo-pack' ), sprintf ( '<a href="%s">' , esc_url ( get_admin_url ( null , " admin.php?page= $aioseop_plugin_dirname /modules/aioseop_sitemap.php " ) ) ), '</a>' ) );
}
}
2016-11-28 21:52:15 -08:00
/**
* 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 ();
2018-01-26 15:50:15 +01:00
if ( ! empty ( $this -> options [ " { $this -> prefix } indexes " ] ) ) {
2016-11-28 21:52:15 -08:00
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 .
*
2018-01-26 15:50:15 +01:00
* @ since 2.3 . 6
* @ since 2.3 . 12.3 Refactored to use aioseop_home_url () for compatibility purposes .
*
2016-11-28 21:52:15 -08:00
* @ 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 ;
}
2018-01-26 15:50:15 +01:00
$url = aioseop_home_url ( '/' . $options [ $this -> prefix . 'filename' ] . '.xml' );
2016-11-28 21:52:15 -08:00
$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>' );
2018-01-26 15:50:15 +01:00
$options [ $this -> prefix . 'link' ] .= __ ( ' Your sitemap has been created with content and images.' , 'all-in-one-seo-pack' );
2016-11-28 21:52:15 -08:00
if ( '0' !== get_option ( 'blog_public' ) ){
2018-01-26 15:50:15 +01:00
$options [ $this -> prefix . 'link' ] .= ' ' . __ ( 'Changes are automatically submitted to search engines.' , 'all-in-one-seo-pack' );
2016-11-28 21:52:15 -08:00
}
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 " ;
2018-01-26 15:50:15 +01:00
if ( ! empty ( $this -> options [ " { $this -> prefix } indexes " ] ) ) {
2016-11-28 21:52:15 -08:00
$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 .
*
2018-01-26 15:50:15 +01:00
* @ since 2.3 . 6
* @ since 2.3 . 12.3 Refactored to use aioseop_home_url () for compatibility purposes .
*
2016-11-28 21:52:15 -08:00
* @ return string
*/
function get_sitemap_url () {
2018-01-26 15:50:15 +01:00
$gz = '' ;
2016-11-28 21:52:15 -08:00
if ( $this -> options [ " { $this -> prefix } gzipped " ] ) {
2018-01-26 15:50:15 +01:00
$gz .= '.gz' ;
2016-11-28 21:52:15 -08:00
}
2018-01-26 15:50:15 +01:00
$url = aioseop_home_url ( '/' . $this -> options [ " { $this -> prefix } filename " ] . " .xml $gz " );
2016-11-28 21:52:15 -08:00
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 " \n Sitemap: $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 = '' ) {
2018-01-26 15:50:15 +01:00
if ( ! empty ( $this -> options [ " { $this -> prefix } indexes " ] ) ) {
2016-11-28 21:52:15 -08:00
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 -> 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 .
*
2018-01-26 15:50:15 +01:00
* @ since 2.3 . 6
* @ since 2.3 . 12.3 Refactored to use aioseop_home_url () for compatibility purposes .
*
2016-11-28 21:52:15 -08:00
* @ 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' ) );
2018-01-26 15:50:15 +01:00
$files [] = array ( 'loc' => aioseop_home_url ( '/' . $prefix . '_addl' . $suffix ) );
2016-11-28 21:52:15 -08:00
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 ;
}
2018-01-26 15:50:15 +01:00
if ( ! empty ( $this -> options [ " { $this -> prefix } indexes " ] ) ) {
2016-11-28 21:52:15 -08:00
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 (
2018-01-26 15:50:15 +01:00
'loc' => aioseop_home_url ( '/' . $prefix . '_' . $sm . '_' . ( $count ++ ) . $suffix ),
2016-11-28 21:52:15 -08:00
'priority' => $prio ,
'changefreq' => $freq ,
);
}
} else {
$files [] = array (
2018-01-26 15:50:15 +01:00
'loc' => aioseop_home_url ( '/' . $prefix . '_' . $sm . $suffix ),
2016-11-28 21:52:15 -08:00
'priority' => $prio ,
'changefreq' => $freq ,
);
}
} else {
$files [] = array (
2018-01-26 15:50:15 +01:00
'loc' => aioseop_home_url ( '/' . $prefix . '_' . $sm . $suffix ),
2016-11-28 21:52:15 -08:00
'priority' => $prio ,
'changefreq' => $freq ,
);
}
}
}
if ( $this -> option_isset ( 'archive' ) ) {
$files [] = array (
2018-01-26 15:50:15 +01:00
'loc' => aioseop_home_url ( '/' . $prefix . '_archive' . $suffix ),
2016-11-28 21:52:15 -08:00
'priority' => $this -> get_default_priority ( 'archive' ),
'changefreq' => $this -> get_default_frequency ( 'archive' ),
);
}
if ( $this -> option_isset ( 'author' ) ) {
$files [] = array (
2018-01-26 15:50:15 +01:00
'loc' => aioseop_home_url ( '/' . $prefix . '_author' . $suffix ),
2016-11-28 21:52:15 -08:00
'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 ) ) {
2018-01-26 15:50:15 +01:00
if ( ! empty ( $this -> options [ " { $this -> prefix } indexes " ] ) ) {
2016-11-28 21:52:15 -08:00
if ( $term_count > $this -> max_posts ) {
$count = 1 ;
for ( $tc = 0 ; $tc < $term_count ; $tc += $this -> max_posts ) {
$files [] = array (
2018-01-26 15:50:15 +01:00
'loc' => aioseop_home_url ( '/' . $prefix . '_' . $sm . '_' . ( $count ++ ) . $suffix ),
2016-11-28 21:52:15 -08:00
'priority' => $this -> get_default_priority ( 'taxonomies' ),
'changefreq' => $this -> get_default_frequency ( 'taxonomies' ),
);
}
} else {
$files [] = array (
2018-01-26 15:50:15 +01:00
'loc' => aioseop_home_url ( '/' . $prefix . '_' . $sm . $suffix ),
2016-11-28 21:52:15 -08:00
'priority' => $this -> get_default_priority ( 'taxonomies' ),
'changefreq' => $this -> get_default_frequency ( 'taxonomies' ),
);
}
} else {
$files [] = array (
2018-01-26 15:50:15 +01:00
'loc' => aioseop_home_url ( '/' . $prefix . '_' . $sm . $suffix ),
2016-11-28 21:52:15 -08:00
'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' ),
);
}
2018-01-26 15:50:15 +01:00
$files = apply_filters ( 'aioseop_sitemap_index_filenames' , $files , $prefix , $suffix );
2016-11-28 21:52:15 -08:00
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 ;
}
2018-01-26 15:50:15 +01:00
if ( ! empty ( $this -> options [ " { $this -> prefix } indexes " ] ) && ( $post_counts [ $posttype ] > $this -> max_posts ) ) {
2016-11-28 21:52:15 -08:00
$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 ) ) {
2018-01-26 15:50:15 +01:00
if ( ! empty ( $this -> options [ " { $this -> prefix } indexes " ] ) ) {
2016-11-28 21:52:15 -08:00
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 .
*
2018-01-26 15:50:15 +01:00
* @ since 2.3 . 6
* @ since 2.3 . 12.3 Refactored to use aioseop_home_url () for compatibility purposes .
*
2016-11-28 21:52:15 -08:00
* @ 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 " ] );
2018-01-26 15:50:15 +01:00
$posts = $postspageid = ( int ) get_option ( 'page_for_posts' ); // It's 0 if posts are on homepage, otherwise it's the id of the posts page.
2016-11-28 21:52:15 -08:00
2018-01-26 15:50:15 +01:00
$home = array (
'loc' => aioseop_home_url (),
'priority' => $this -> get_default_priority ( 'homepage' ),
'changefreq' => $this -> get_default_frequency ( 'homepage' ),
'image:image' => $this -> get_images_from_post ( ( int ) get_option ( 'page_on_front' ) ),
);
2016-11-28 21:52:15 -08:00
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
2018-01-26 15:50:15 +01:00
* @ since 2.3 . 12.3 Refactored to use aioseop_home_url () for compatibility purposes .
2016-11-28 21:52:15 -08:00
*/
function get_sitemap_xsl () {
2018-01-26 15:50:15 +01:00
return esc_url ( apply_filters ( 'aioseop_sitemap_xsl_url' , aioseop_home_url ( '/sitemap.xsl' ) ) );
2016-11-28 21:52:15 -08:00
}
/**
* 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 ' ;
2018-01-26 15:50:15 +01:00
$namespaces = apply_filters ( $this -> prefix . 'xml_namespace' , array (
'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9' ,
'xmlns:image' => 'http://www.google.com/schemas/sitemap-image/1.1' ,
) );
2016-11-28 21:52:15 -08:00
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 ;
}
2018-01-26 15:50:15 +01:00
$pr_info [ 'image:image' ] = $this -> get_images_from_term ( $term );
$prio [] = $pr_info ;
2016-11-28 21:52:15 -08:00
}
}
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 .
*
2018-01-26 15:50:15 +01:00
* @ since 2.3 . 6
* @ since 2.3 . 12.3 Refactored to use aioseop_home_url () for compatibility purposes .
*
2016-11-28 21:52:15 -08:00
* @ return array | mixed | void
*/
function get_addl_pages_only () {
$pages = array ();
if ( ! empty ( $this -> options [ $this -> prefix . 'addl_pages' ] ) ) {
2018-01-26 15:50:15 +01:00
$siteurl = parse_url ( aioseop_home_url () );
2016-11-28 21:52:15 -08:00
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 .
*
2018-01-26 15:50:15 +01:00
* @ since 2.3 . 6
* @ since 2.3 . 12.3 Refactored to use aioseop_home_url () for compatibility purposes .
*
2016-11-28 21:52:15 -08:00
* @ return array | mixed | void
*/
function get_addl_pages () {
$home = array ();
$home = array (
2018-01-26 15:50:15 +01:00
'loc' => aioseop_home_url (),
'priority' => $this -> get_default_priority ( 'homepage' ),
'changefreq' => $this -> get_default_frequency ( 'homepage' ),
'image:image' => $this -> get_images_from_post ( ( int ) get_option ( 'page_on_front' ) ),
2016-11-28 21:52:15 -08:00
);
2018-01-26 15:50:15 +01:00
$posts = ( int ) get_option ( 'page_for_posts' );
2016-11-28 21:52:15 -08:00
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 ) {
2018-01-26 15:50:15 +01:00
// Determine if we check the post for images.
$is_single = true ;
2016-11-28 21:52:15 -08:00
$url = '' ;
$post -> filter = 'sample' ;
if ( 'get_permalink' === $linkfunc ) {
$url = $this -> get_permalink ( $post );
} else {
$url = call_user_func ( $linkfunc , $post );
2018-01-26 15:50:15 +01:00
$is_single = false ;
2016-11-28 21:52:15 -08:00
}
$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 ];
}
}
2018-01-26 15:50:15 +01:00
$pr_info = array (
'loc' => $url ,
'image:image' => $is_single ? $this -> get_images_from_post ( $post ) : null ,
) + $pr_info ; // Prepend loc to the array.
2016-11-28 21:52:15 -08:00
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 ;
}
2018-01-26 15:50:15 +01:00
/**
* Return the images attached to the term .
*
* @ param WP_Term $term the term object .
*
* @ since 2.4
*
* @ return array
*/
private function get_images_from_term ( $term ) {
if ( ! aiosp_include_images () ) {
return array ();
}
$images = array ();
$thumbnail_id = get_term_meta ( $term -> term_id , 'thumbnail_id' , true );
if ( $thumbnail_id ) {
$image = wp_get_attachment_url ( $thumbnail_id );
if ( $image ) {
$images [ 'image:image' ] = array (
'image:loc' => $image ,
);
}
}
return $images ;
}
/**
* Return the images from the post .
*
* @ param WP_Post $post the post object .
*
* @ since 2.4
*
* @ return array
*/
private function get_images_from_post ( $post ) {
if ( ! aiosp_include_images () ) {
return array ();
}
$images = array ();
if ( is_numeric ( $post ) ) {
if ( 0 === $post ) {
return null ;
}
$post = get_post ( $post );
}
if ( 'attachment' === $post -> post_type ) {
if ( false === strpos ( $post -> post_mime_type , 'image/' ) ) {
// Ignore all attachments except images.
return null ;
}
$attributes = wp_get_attachment_image_src ( $post -> ID );
if ( $attributes ) {
$images [] = array (
'image:loc' => $this -> clean_url ( $attributes [ 0 ] ),
);
}
return $images ;
}
// Check featured image.
$attached_url = get_the_post_thumbnail_url ( $post -> ID );
if ( false !== $attached_url ) {
$images [] = $attached_url ;
}
$content = '' ;
$content = $post -> post_content ;
// Check images galleries in the content. DO NOT run the_content filter here as it might cause issues with other shortcodes.
if ( has_shortcode ( $content , 'gallery' ) ) {
$galleries = get_post_galleries ( $post , false );
if ( $galleries ) {
foreach ( $galleries as $gallery ) {
$images = array_merge ( $images , $gallery [ 'src' ] );
}
}
}
$this -> parse_content_for_images ( $content , $images );
if ( $images ) {
$tmp = $images ;
if ( 1 < count ( $images ) ) {
// Filter out duplicates.
$tmp = array_unique ( $images );
}
// remove any invalid/empty images.
$tmp = array_filter ( $images , array ( $this , 'is_image_valid' ) );
$images = array ();
foreach ( $tmp as $image ) {
$images [] = array (
'image:loc' => $this -> clean_url ( $image ),
);
}
}
return $images ;
}
/**
* Cleans the URL so that its acceptable in the sitemap .
*
* @ param string $url The image url .
*
* @ since 2.4 . 1
*
* @ return string
*/
function clean_url ( $url ) {
// remove the query string.
$url = strtok ( $url , '?' );
// make the url XML-safe.
$url = htmlspecialchars ( $url );
// Make the url absolute, if its relative.
$url = aiosp_common :: absolutize_url ( $url );
return apply_filters ( 'aioseop_clean_url' , $url );
}
/**
* Validate the image .
*
* @ param string $image The image src .
*
* @ since 2.4 . 1
*
* @ return bool
*/
function is_image_valid ( $image ) {
// Bail if empty image.
if ( empty ( $image ) ) {
return false ;
}
// make the url absolute, if its relative.
$image = aiosp_common :: absolutize_url ( $image );
$extn = pathinfo ( wp_parse_url ( $image , PHP_URL_PATH ), PATHINFO_EXTENSION );
$allowed = apply_filters ( 'aioseop_allowed_image_extensions' , self :: $image_extensions );
// Bail if image does not refer to an image file otherwise google webmaster tools might reject the sitemap.
if ( ! in_array ( $extn , $allowed , true ) ) {
return false ;
}
// Bail if image refers to an external URL.
$image_host = wp_parse_url ( $image , PHP_URL_HOST );
$wp_host = wp_parse_url ( home_url (), PHP_URL_HOST );
if ( $image_host !== $wp_host ) {
return false ;
}
return true ;
}
/**
* Parse the post for images .
*
* @ param string $content the post content .
* @ param array $images the array of images .
*/
function parse_content_for_images ( $content , & $images ) {
$total = substr_count ( $content , '<img ' ) + substr_count ( $content , '<IMG ' );
// no images found.
if ( 0 === $total ) {
return ;
}
if ( class_exists ( 'DOMDocument' ) ) {
$dom = new domDocument ();
// Non-compliant HTML might give errors, so ignore them.
libxml_use_internal_errors ( true );
$dom -> loadHTML ( $content );
libxml_clear_errors ();
$dom -> preserveWhiteSpace = false ;
$matches = $dom -> getElementsByTagName ( 'img' );
foreach ( $matches as $match ) {
$images [] = $match -> getAttribute ( 'src' );
}
} else {
// Fall back to regex, but also report an error.
global $img_err_msg ;
if ( ! isset ( $img_err_msg ) ) {
// we will log this error message only once, not per post.
$img_err_msg = true ;
$this -> debug_message ( 'DOMDocument not found; using REGEX' );
}
preg_match_all ( '/<img.*src=([\'"])?(.*?)\\1/' , $content , $matches );
if ( $matches && isset ( $matches [ 2 ] ) ) {
$images = array_merge ( $images , $matches [ 2 ] );
}
}
}
2016-11-28 21:52:15 -08:00
/**
* 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' ];
}
2018-01-26 15:50:15 +01:00
if ( ! empty ( $this -> options [ " { $this -> prefix } indexes " ] ) ) {
2016-11-28 21:52:15 -08:00
$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 ();
2018-01-26 15:50:15 +01:00
if ( ! empty ( $this -> options [ " { $this -> prefix } indexes " ] ) ) {
2016-11-28 21:52:15 -08:00
$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 ;
}
2018-01-26 15:50:15 +01:00
/*
* Filter to exclude password protected posts .
* TODO : move to its own function and call it from here , returning whatever is appropriate .
* @ since 2.3 . 12
*/
if ( apply_filters ( 'aioseop_sitemap_include_password_posts' , true ) === false ) {
$defaults [ 'has_password' ] = false ;
}
2016-11-28 21:52:15 -08:00
$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 ;
}
}
}