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", 'all_in_one_seo_pack' );
$help_text = Array(
"filename" => __( "Specifies the name of your sitemap file. This will default to 'sitemap'.
Click here for documentation on this setting", 'all_in_one_seo_pack' ),
"google" => __( "Notify Google when you update your sitemap settings.
Click here for documentation on this setting", 'all_in_one_seo_pack' ),
"bing" => __("Notify Bing when you update your sitemap settings.
Click here for documentation on this setting", '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.
Click here for documentation on this setting", 'all_in_one_seo_pack' ),
"paginate" => __( "Split long sitemaps into separate files.
Click here for documentation on this setting", 'all_in_one_seo_pack' ),
"max_posts" => __( "Allows you to specify the maximum number of posts in a sitemap (up to 50,000).
Click here for documentation on this setting", 'all_in_one_seo_pack' ),
"posttypes" => __( "Select which Post Types appear in your sitemap.
Click here for documentation on this setting", 'all_in_one_seo_pack' ),
"taxonomies" => __( "Select which taxonomy archives appear in your sitemap.
Click here for documentation on this setting", 'all_in_one_seo_pack' ),
"archive" => __( "Include Date Archives in your sitemap.
Click here for documentation on this setting", 'all_in_one_seo_pack' ),
"author" => __( "Include Author Archives in your sitemap.
Click here for documentation on this setting", 'all_in_one_seo_pack' ),
"gzipped" => __( "Create a compressed sitemap file in .xml.gz format.
Click here for documentation on this setting", 'all_in_one_seo_pack' ),
"robots" => __( "Places a link to your Sitemap.xml into your virtual Robots.txt file.
Click here for documentation on this setting", 'all_in_one_seo_pack' ),
"rewrite" => __( "Places a link to the sitemap file in your virtual Robots.txt file which WordPress creates.
Click here for documentation on this setting", 'all_in_one_seo_pack' ),
"debug" => __( "Use rewrites to generate your sitemap on the fly. NOTE: This is required for WordPress Multisite.
Click here for documentation on this setting", '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.
Click here for documentation on this setting", 'all_in_one_seo_pack' ),
"excl_pages" => __( "Use page slugs or page IDs, seperated by commas, to exclude pages from the sitemap.
Click here for documentation on this setting", 'all_in_one_seo_pack' )
);
$this->default_options = array(
'filename' => Array( 'name' => __( 'Filename Prefix', 'all_in_one_seo_pack' ),
'default' => 'sitemap', 'type' => 'text', 'sanitize' => 'filename' ),
'google' => Array( 'name' => __( 'Notify Google', 'all_in_one_seo_pack') ),
'bing' => Array( 'name' => __( 'Notify Bing', 'all_in_one_seo_pack') ),
'indexes' => Array( 'name' => __( 'Enable Sitemap Indexes', 'all_in_one_seo_pack' ) ),
'paginate' => Array( 'name' => __( 'Paginate Sitemap Indexes', 'all_in_one_seo_pack' ),
'condshow' => Array( "{$this->prefix}indexes" => 'on' ) ),
'max_posts' => Array( 'name' => __( 'Maximum Posts Per Sitemap', 'all_in_one_seo_pack' ),
'type' => 'text', 'default' => 50000,
'condshow' => Array( "{$this->prefix}indexes" => 'on', "{$this->prefix}paginate" => 'on' ) ),
'posttypes' => Array( 'name' => __( 'Post Types', 'all_in_one_seo_pack'),
'type' => 'multicheckbox', 'default' => 'all' ),
'taxonomies'=> Array( 'name' => __( 'Taxonomies', 'all_in_one_seo_pack' ),
'type' => 'multicheckbox', 'default' => 'all' ),
'archive' => Array( 'name' => __( 'Include Date Archive Pages', 'all_in_one_seo_pack' ) ),
'author' => Array( 'name' => __( 'Include Author Pages', 'all_in_one_seo_pack' ) ),
'gzipped' => Array( 'name' => __( 'Create Compressed Sitemap', 'all_in_one_seo_pack' ), 'default' => 'On' ),
'robots' => Array( 'name' => __( 'Link From Virtual Robots.txt', 'all_in_one_seo_pack' ), 'default' => 'On' ),
'rewrite' => Array( 'name' => __( 'Dynamically Generate Sitemap', 'all_in_one_seo_pack' ), 'default' => 'On' )
);
$status_options = Array(
'link' => Array( 'default' => '', 'type' => 'html', 'label' => 'none', 'save' => false ),
'debug' => Array( 'name' => __( 'Debug Log', 'all_in_one_seo_pack' ), 'default' => '', 'type' => 'html', 'disabled' => 'disabled', 'save' => false, 'label' => 'none', 'rows' => 5, 'cols' => 120, 'style' => 'min-width:950px' )
);
$this->layout = Array(
'status' => Array(
'name' => __( 'Sitemap Status', 'all_in_one_seo_pack' ),
'help_link' => 'http://semperplugins.com/documentation/xml-sitemaps-module/',
'options' => array_keys( $status_options ) ),
'default' => Array(
'name' => $this->name,
'help_link' => 'http://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 ( ( $opt == 'post' ) || ( $opt == 'taxonomies' ) ) {
$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 ( ( $opt == 'archive' ) || ( $opt == 'author' ) ) $arr[ $k . '_' . $opt ][ 'condshow' ] = Array( $this->prefix . $opt => 'on' );
$$s = $arr;
}
}
$addl_options = Array(
'addl_instructions' => Array( 'default' => '
| {$k} | {$v['prio']} | {$v['freq']} | {$v['mod']} |
' . __( "Note: you are using dynamic sitemap generation to keep your sitemap current; this will not generate a static sitemap file.", 'all_in_one_seo_pack' ) . '
'; $rule = $this->get_rewrite_url( $url ); $rules = $this->get_rewrite_rules(); if ( in_array( $rule, $rules ) ) $options[ $this->prefix . 'link' ] .= '' . __( "Dynamic sitemap generation appears to be using the correct rewrite rules.", 'all_in_one_seo_pack' ) . '
'; else $options[ $this->prefix . 'link' ] .= '' . __( "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' ) . '
'; } if ( !get_option( 'blog_public' ) ) { global $wp_version; if ( ( version_compare( $wp_version, '3.5.0', '>=' ) ) || ( function_exists( 'set_url_scheme' ) ) ) { $privacy_link = '' . __( 'Reading Settings', 'all_in_one_seo_pack' ) . ''; } else { $privacy_link = '' . __( 'Privacy Settings', 'all_in_one_seo_pack' ) . ''; } $options[ $this->prefix . 'link' ] .= '' . 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 ); } if ( $this->option_isset( 'debug' ) ) $options["{$this->prefix}debug"] = '
' . $options["{$this->prefix}debug"] . '';
return $options;
}
/** Handle 'all' option for post types / taxonomies, further sanitization of filename, rewrites on for multisite, setting up addl pages option. **/
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 ( $decoded === NULL )
$decoded = maybe_unserialize( $options[ $this->prefix . 'addl_pages' ] );
if ( !is_array( $decoded ) ) $decoded = (Array)$decoded;
if ( $decoded === NULL )
$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] );
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. **/
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 );
}
/** Scan for sitemaps on filesystem. **/
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 ) ) {
$files[] = $home_path . $f;
continue;
}
if ( !empty($scan2) && fnmatch($scan2, $home_path . $f ) )
$files[] = $home_path . $f;
}
return $files;
}
}
/** Handle deleting / renaming of conflicting sitemap files. **/
function do_sitemap_scan() {
$msg = '';
if ( !empty( $this->options["{$this->prefix}rewrite"] ) && ( get_option('permalink_structure') == '' ) ) {
$msg = '' . __( 'Warning: dynamic sitemap generation must have permalinks enabled.', 'all_in_one_seo_pack' ) . '
'; } 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 .= "" . sprintf( __( "Deleted %s.", 'all_in_one_seo_pack' ), $ren_file ) . "
"; 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 .= "" . sprintf( __( "Couldn't rename file %s!", 'all_in_one_seo_pack' ), $ren_file) . "
"; else { $ren = $this->rename_file( $ren_file, $ren_to ); if ( $ren ) $msg .= "" . sprintf( __( "Renamed %s to %s.", 'all_in_one_seo_pack' ), $ren_file, $ren_to) . "
"; } } else $msg .= "" . sprintf( __( "Couldn't find file %s!", 'all_in_one_seo_pack' ), $ren_file) . "
"; } } } else { $msg .= $this->scan_sitemaps(); } if ( !empty( $msg ) ) $this->output_error( $msg ); } /** Do the scan, return the results. **/ function scan_sitemaps() { $msg = ''; $files = $this->scan_match_files(); if ( !empty( $files ) ) $msg = $this->sitemap_warning( $files ); return $msg; } /** Get the list of potentially conflicting sitemap files. **/ 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 ( $wpfs->method == 'direct' ) $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( "//", $file, $matches ) ) { if ( !empty( $this->options["{$this->prefix}rewrite"] ) ) { $msg .= '' . 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] ) . "
\n"; $problem_files[] = $f; } } else { $msg .= '' . sprintf( __( "Potential conflict with unknown file %s.", 'all_in_one_seo_pack' ), $f ) . "
\n"; $problem_files[] = $f; } } } } return $problem_files; } /** Display the warning and the form for conflicting sitemap files. **/ 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 .= "\n"; $msg .= "\n"; $msg .= " "; $msg .= ""; $msg = ''; } return $msg; } /** Updates debug log messages. **/ function debug_message( $msg ) { if ( empty( $this->options["{$this->prefix}debug"] ) ) $this->options["{$this->prefix}debug"] = ''; $this->options["{$this->prefix}debug"] = date( 'Y-m-d H:i:s' ) . " {$msg}\n" . $this->options["{$this->prefix}debug"]; if ( $this->strlen( $this->options["{$this->prefix}debug"] ) > 2048 ) { $end = $this->strrpos( $this->options["{$this->prefix}debug"], "\n" ); if ( $end === false ) $end = 2048; $this->options["{$this->prefix}debug"] = $this->substr( $this->options["{$this->prefix}debug"], 0, $end ); } $this->update_class_option( $this->options ); } /** 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. **/ 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. **/ 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. **/ function query_var_hook($vars) { $vars[] = "{$this->prefix}path"; if ( $this->paginate ) $vars[] = "{$this->prefix}page"; return $vars; } /** Start timing and get initial memory usage for debug info. **/ function log_start() { $this->start_memory_usage = memory_get_peak_usage(); timer_start(); } /** Stop timing and log memory usage for debug info. **/ function log_stats( $sitemap_type = 'root', $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; if ( $compressed ) $sitemap_type = __( 'compressed', 'all_in_one_seo_pack' ) . " $sitemap_type"; if ( $dynamic ) $sitemap_type = __( 'dynamic', 'all_in_one_seo_pack ') . " $sitemap_type"; else $sitemap_type = __( 'static', 'all_in_one_seo_pack ') . " $sitemap_type"; $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. **/ function sitemap_output_hook($query) { $page = 0; if ( ( $this->options["{$this->prefix}rewrite"] ) ) if( !empty( $query->query_vars["{$this->prefix}path"] ) ) { 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 ); } 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(); } } 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 ( $sitemap_type === 'root' ) { $sitemap_data = array_merge( $this->get_sitemap_index_filenames() ); } elseif ( $sitemap_type === 'addl' ) { $sitemap_data = $this->get_addl_pages(); } elseif ( $sitemap_type === 'archive' && $this->option_isset( 'archive' ) ) { $sitemap_data = $this->get_archive_prio_data(); } elseif ( $sitemap_type === 'author' && $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 ( $sitemap_type === 'root' ) $sitemap_data = $this->get_simple_sitemap(); return apply_filters( $this->prefix . 'data', $sitemap_data, $sitemap_type, $page, $this->options ); } /** Output sitemaps dynamically based on rewrite rules. **/ function do_rewrite_sitemap( $sitemap_type, $page = 0 ) { $this->add_post_types(); $comment = __( "dynamically", 'all_in_one_seo_pack' ); $this->output_sitemap( $this->get_sitemap_data( $sitemap_type, $page ), $comment ); } /** Build a url to the sitemap. **/ function get_sitemap_url() { $url = get_home_url() . '/' . $this->options["{$this->prefix}filename"] . '.xml'; if ( $this->options["{$this->prefix}gzipped"] ) $url .= '.gz'; return $url; } /** Notify search engines, do logging. **/ function do_notify() { $notify_url = Array( 'google' => 'http://www.google.com/webmasters/sitemaps/ping?sitemap=', 'bing' => 'http://www.bing.com/webmaster/ping.aspx?siteMap=' ); $url = $this->get_sitemap_url(); if ( !empty( $url ) ) foreach ( $notify_url as $k => $v ) if ( isset( $this->options[$this->prefix . $k] ) && $this->options[$this->prefix . $k] ) { $response = wp_remote_get( $notify_url[$k] . urlencode( $url ) ); if ( is_array( $response ) && !empty( $response['response'] ) && !empty( $response['response']['code'] ) ) { if ( $response['response']['code'] == 200 ) { $this->debug_message( sprintf( __( 'Successfully notified %s about changes to your sitemap at %s.', 'all_in_one_seo_pack' ), $k, $url ) ); } else { $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 ) ); } } else { $this->debug_message( sprintf( __( 'Did not notify %s about changes to your sitemap.', 'all_in_one_seo_pack' ), $k, $url ) ); } } /** Add Sitemap parameter to virtual robots.txt file. **/ function do_robots() { $url = $this->get_sitemap_url(); echo "\nSitemap: $url\n"; } /** Build static sitemaps on submit if rewrite rules are not in use, do logging. **/ function do_sitemaps() { if ( !empty( $this->options["{$this->prefix}indexes"] ) && !empty( $this->options["{$this->prefix}paginate"] ) ) { $this->paginate = true; if ( ( $this->options["{$this->prefix}max_posts"] ) && ( $this->options["{$this->prefix}max_posts"] > 0 ) && ( $this->options["{$this->prefix}max_posts"] < 50000 ) ) $this->max_posts = $this->options["{$this->prefix}max_posts"]; else $this->max_posts = 50000; } else { $this->paginate = false; $this->max_posts = 50000; } if ( !$this->options["{$this->prefix}rewrite"] ) { if ( $this->options["{$this->prefix}indexes"] ) { $this->do_indexed_sitemaps(); } else { $this->log_start(); $comment = sprintf( __( "file '%s' statically", 'all_in_one_seo_pack' ), $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(); $this->debug_message( __( 'Updated sitemap settings.', 'all_in_one_seo_pack' ) ); } function add_xml_mime_type( $mime ) { if ( !empty( $mime ) ) { $mime['xml'] = 'text/xml'; } return $mime; } /** Write sitemaps (compressed or otherwise) to the filesystem. **/ 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 a single sitemap to the filesystem, handle compression. **/ function write_sitemap($filename, $contents, $gzip = false) { if ( $gzip ) $contents = gzencode( $contents ); add_filter( 'upload_mimes', Array( $this, 'add_xml_mime_type' ) ); $filename = get_home_path() . sanitize_file_name( $filename ); remove_filter( 'upload_mimes', Array( $this, 'add_xml_mime_type' ) ); return $this->save_file( $filename, $contents ); } /*** Helper function for handling default values ***/ 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 ) && $this->options[ $field ] != 'no' ) { if ( ( $this->options[ $field ] == 'sel' ) && !empty( $type ) && ( isset( $this->options[ $this->prefix . $prefix . $item . '_' . $type ] ) ) ) { if ( $this->options[ $this->prefix . $prefix . $item . '_' . $type ] == 'no' ) return false; if ( $this->options[ $this->prefix . $prefix . $item . '_' . $type ] == 'sel' ) return false; $cache[ $item . $type ] = $this->options[ $this->prefix . $prefix . $item . '_' . $type ]; } else { if ( $this->options[ $field ] == 'no' ) return false; if ( $this->options[ $field ] == 'sel' ) 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. **/ 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. **/ 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. **/ function get_sitemap_index_filenames() { $files = Array(); $options = $this->options; $prefix = $options["{$this->prefix}filename"]; $suffix = '.xml'; if ( $options["{$this->prefix}gzipped"] ) $suffix .= '.gz'; if ( empty( $options["{$this->prefix}posttypes"] ) ) $options["{$this->prefix}posttypes"] = Array(); if ( empty( $options["{$this->prefix}taxonomies"] ) ) $options["{$this->prefix}taxonomies"] = Array(); $options["{$this->prefix}posttypes"] = array_diff( $options["{$this->prefix}posttypes"], Array( 'all' ) ); $options["{$this->prefix}taxonomies"] = array_diff( $options["{$this->prefix}taxonomies"], Array( 'all' ) ); $url_base = trailingslashit( get_home_url() ); $files[] = Array( 'loc' => $url_base . $prefix . '_addl' . $suffix ); if ( !empty( $options["{$this->prefix}posttypes"] ) ) { $prio = $this->get_default_priority( 'post' ); $freq = $this->get_default_frequency( 'post' ); $post_counts = $this->get_all_post_counts( Array('post_type' => $options["{$this->prefix}posttypes"], 'post_status' => 'publish') ); if ( !is_array( $post_counts ) && is_array( $options["{$this->prefix}posttypes"] ) && count( $options["{$this->prefix}posttypes"] ) == 1 ) { $post_counts = Array( $options["{$this->prefix}posttypes"][0] => $post_counts ); } foreach( $options["{$this->prefix}posttypes"] as $sm ) { if ( $post_counts[$sm] == 0 ) continue; if ( $this->paginate ) { if ( $post_counts[$sm] > $this->max_posts ) { $count = 1; for( $post_count = 0; $post_count < $post_counts[$sm]; $post_count += $this->max_posts ) { $files[] = Array( 'loc' => $url_base . $prefix . '_' . $sm . '_' . ( $count++ ) . $suffix, 'priority' => $prio, 'changefreq' => $freq ); } } else $files[] = Array( 'loc' => $url_base . $prefix . '_' . $sm . $suffix, 'priority' => $prio, 'changefreq' => $freq ); } else $files[] = Array( 'loc' => $url_base . $prefix . '_' . $sm . $suffix, 'priority' => $prio, 'changefreq' => $freq ); } } if ( $this->option_isset( 'archive' ) ) $files[] = Array( 'loc' => $url_base . $prefix . '_archive' . $suffix, 'priority' => $this->get_default_priority( 'archive' ), 'changefreq' => $this->get_default_frequency( 'archive' ) ); if ( $this->option_isset( 'author' ) ) $files[] = Array( 'loc' => $url_base . $prefix . '_author' . $suffix, 'priority' => $this->get_default_priority( 'author' ), 'changefreq' => $this->get_default_frequency( 'author' ) ); if ( !empty( $options["{$this->prefix}taxonomies"] ) ) foreach( $options["{$this->prefix}taxonomies"] as $sm ) { $term_count = wp_count_terms( $sm, array('hide_empty' => true) ); if ( !is_wp_error( $term_count ) && ( $term_count > 0 ) ) { if ( $this->paginate ) { if ( $term_count > $this->max_posts ) { $count = 1; for( $tc = 0; $tc < $term_count; $tc += $this->max_posts ) { $files[] = Array( 'loc' => $url_base . $prefix . '_' . $sm . '_' . ( $count++ ) . $suffix, 'priority' => $this->get_default_priority( 'taxonomies' ), 'changefreq' => $this->get_default_frequency( 'taxonomies' ) ); } } else $files[] = Array( 'loc' => $url_base . $prefix . '_' . $sm . $suffix, 'priority' => $this->get_default_priority( 'taxonomies' ), 'changefreq' => $this->get_default_frequency( 'taxonomies' ) ); } else $files[] = Array( 'loc' => $url_base . $prefix . '_' . $sm . $suffix, 'priority' => $this->get_default_priority( 'taxonomies' ), 'changefreq' => $this->get_default_frequency( 'taxonomies' ) ); } } foreach( $this->get_child_sitemap_urls() as $csm ) $files[] = Array( 'loc' => $csm, 'priority' => $this->get_default_priority( 'sitemap' ), 'changefreq' => $this->get_default_frequency( 'sitemap' ) ); return $files; } function do_build_sitemap( $sitemap_type, $page = 0, $filename = '', $comment = '' ) { if ( empty( $filename ) ) { if ( $sitemap_type == 'root' ) { $filename = $this->options["{$this->prefix}filename"]; } else { $filename = $this->options["{$this->prefix}filename"] . '_' . $sitemap_type; } } if ( empty( $comment ) ) $comment = __( "file '%s' statically", 'all_in_one_seo_pack' ); $sitemap_data = $this->get_sitemap_data( $sitemap_type, $page ); if ( $sitemap_type == 'root' ) { return $this->build_sitemap_index( $sitemap_data, sprintf( $comment, $filename ) ); } else { return $this->build_sitemap( $sitemap_data, sprintf( $comment, $filename ) ); } } function do_write_sitemap( $sitemap_type, $page = 0, $filename = '', $comment = '' ) { if ( empty( $filename ) ) { if ( $sitemap_type == 'root' ) { $filename = $this->options["{$this->prefix}filename"]; } else { $filename = $this->options["{$this->prefix}filename"] . '_' . $sitemap_type; } } if ( empty( $comment ) ) $comment = __( "file '%s' statically", 'all_in_one_seo_pack' ); $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 ( $post_counts[$posttype] === 0 ) continue; if ( $this->paginate && ( $post_counts[$posttype] > $this->max_posts ) ) { $count = 1; for( $post_count = 0; $post_count < $post_counts[$posttype]; $post_count += $this->max_posts ) { $this->do_write_sitemap( $posttype, $count - 1, $options["{$this->prefix}filename"] . "_{$posttype}_{$count}" ); $count++; } } else { $this->do_write_sitemap( $posttype ); } } } if ( !empty( $options["{$this->prefix}taxonomies"] ) ) foreach( $options["{$this->prefix}taxonomies"] as $taxonomy ) { $term_count = wp_count_terms( $taxonomy, array('hide_empty' => true) ); if ( !is_wp_error( $term_count ) && ( $term_count > 0 ) ) { if ( $this->paginate ) { if ( $term_count > $this->max_posts ) { $count = 1; for( $tc = 0; $tc < $term_count; $tc += $this->max_posts ) { $this->do_write_sitemap( $taxonomy, $tc, $options["{$this->prefix}filename"] . "_{$taxonomy}_{$count}" ); $count++; } } else { $this->do_write_sitemap( $taxonomy ); } } else { $this->do_write_sitemap( $taxonomy ); } } } $this->log_stats( 'indexed', $options["{$this->prefix}gzipped"], false ); } function get_simple_sitemap() { $home = Array( 'loc' => get_home_url(), 'priority' => $this->get_default_priority( 'homepage' ), 'changefreq' => $this->get_default_frequency( 'homepage' ) ); $posts = get_option( 'page_for_posts' ); $this->paginate = false; if ( $posts ) { $posts = $this->get_permalink( $posts ); if ( $posts == $home['loc'] ) $posts = null; else $posts = Array( 'loc' => $posts, 'priority' => $this->get_default_priority( 'blog' ), 'changefreq' => $this->get_default_frequency( 'blog' ) ); } $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"] ); 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 ( ( $posts != null ) && 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 ) ) 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. **/ 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 ); } /** Output the XML for a sitemap. **/ function output_sitemap( $urls, $comment = '' ) { $max_items = 50000; if ( !is_array( $urls ) ) return null; echo '' . "\r\n\r\n"; echo "\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; unset( $plugin_url['scheme'] ); $plugin_path = $this->unparse_url( $plugin_url ); $xml_header = '' . "\r\n" . '