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 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' ); $this->default_options = array( 'filename' => Array( 'name' => __( 'Filename Prefix', 'all_in_one_seo_pack' ), 'help_text' => __( 'The prefix for your sitemap file name. This will default to "sitemap."', 'all_in_one_seo_pack' ), 'default' => 'sitemap', 'type' => 'text', 'sanitize' => 'filename' ), 'google' => Array( 'name' => __( 'Notify Google', 'all_in_one_seo_pack'), 'help_text' => __( 'Notify Google when you update your sitemap settings.', 'all_in_one_seo_pack' ) ), 'bing' => Array( 'name' => __( 'Notify Bing', 'all_in_one_seo_pack'), 'help_text' => __('Notify Bing when you update your sitemap settings.', 'all_in_one_seo_pack' ) ), 'indexes' => Array( 'name' => __( 'Enable Sitemap Indexes', 'all_in_one_seo_pack' ), 'help_text' => __( 'Organize sitemap entries into distinct files in your sitemap.', 'all_in_one_seo_pack' ) ), 'paginate' => Array( 'name' => __( 'Paginate Sitemap Indexes', 'all_in_one_seo_pack' ), 'help_text' => __( 'Splits long sitemaps into separate files.', 'all_in_one_seo_pack' ), 'condshow' => Array( "aiosp_sitemap_indexes" => 'on' ) ), 'max_posts' => Array( 'name' => __( 'Maximum Posts Per Sitemap', 'all_in_one_seo_pack' ), 'help_text' => __( 'Allows you to specify the maximum number of posts in a sitemap (up to 50,000).', 'all_in_one_seo_pack' ), 'type' => 'text', 'default' => 50000, 'condshow' => Array( "aiosp_sitemap_indexes" => 'on', "aiosp_sitemap_paginate" => 'on' ) ), 'posttypes' => Array( 'name' => __( 'Post Types', 'all_in_one_seo_pack'), 'help_text' => __( 'Select which post types appear in your sitemap.', 'all_in_one_seo_pack' ), 'type' => 'multicheckbox', 'default' => 'all' ), 'taxonomies'=> Array( 'name' => __( 'Taxonomies', 'all_in_one_seo_pack' ), 'help_text' => __( 'Select which taxonomy archives appear in your sitemap.', 'all_in_one_seo_pack' ), 'type' => 'multicheckbox', 'default' => 'all' ), 'archive' => Array( 'name' => __( 'Include Date Archive Pages', 'all_in_one_seo_pack' ), 'help_text' => __( 'Include date archive pages in your sitemap.', 'all_in_one_seo_pack' ) ), 'author' => Array( 'name' => __( 'Include Author Pages', 'all_in_one_seo_pack' ), 'help_text' => __( 'Include author archive pages in your sitemap.', 'all_in_one_seo_pack' ) ), 'gzipped' => Array( 'name' => __( 'Create Compressed Sitemap', 'all_in_one_seo_pack' ), 'default' => 'On', 'help_text' => __( 'Create a compressed sitemap file in .xml.gz format', 'all_in_one_seo_pack' ) ), 'robots' => Array( 'name' => __( 'Link From Virtual Robots.txt', 'all_in_one_seo_pack' ), 'default' => 'On', 'help_text' => __( 'Places a link to your Sitemap.xml into your virtual Robots.txt file.', 'all_in_one_seo_pack' ) ), 'rewrite' => Array( 'name' => __( 'Dynamically Generate Sitemap', 'all_in_one_seo_pack' ), 'default' => 'On', 'help_text' => __( 'Use rewrites to generate your sitemap on the fly. NOTE: This is required for WordPress Multisite.', 'all_in_one_seo_pack') ) ); $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', 'help_text' => __( 'Debug messages and status information for sitemap.', 'all_in_one_seo_pack' ) ) ); $this->layout = Array( 'status' => Array( 'name' => __( 'Sitemap Status', 'all_in_one_seo_pack' ), 'options' => array_keys( $status_options ) ), 'default' => Array( 'name' => $this->name, 'options' => array_keys( $this->default_options ) ) ); $prio = Array( 'no' => 'Do Not Override' ); for( $i = 0; $i <= 10; $i++ ) { $str = sprintf( "%0.1f", $i / 10.0 ); $prio[ $str ] = $str; } $freq = Array( 'no' => 'Do Not Override' ); foreach ( Array( 'always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never' ) as $f ) $freq[ $f ] = $f; 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; $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' => $$k, '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['aiosp_sitemap_debug'] = '
' . $options['aiosp_sitemap_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 ( is_array( $options['aiosp_sitemap_posttypes'] ) && in_array( 'all', $options['aiosp_sitemap_posttypes'] ) ) $options['aiosp_sitemap_posttypes'] = array_keys( $this->default_options['posttypes' ]['initial_options'] ); if ( is_array( $options['aiosp_sitemap_taxonomies'] ) && in_array( 'all', $options['aiosp_sitemap_taxonomies'] ) ) $options['aiosp_sitemap_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 ); $options[ $this->prefix . 'addl_pages' ] = maybe_unserialize( $options[ $this->prefix . 'addl_pages' ] ); } 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["aiosp_sitemap_filename"] . '.xml'; if ( $sitemap_options['aiosp_sitemap_gzipped'] ) $url .= '.gz'; $siteurls[] = $url; } } } return apply_filters( $this->prefix . 'sitemap_urls', $siteurls ); } /** Scan for sitemaps on filesystem. **/ function scan_match_files() { $scan1 = $scan2 = ''; $files = Array(); if ( !empty( $this->options['aiosp_sitemap_filename'] ) ) { $scan1 = get_home_path() . $this->options['aiosp_sitemap_filename'] . '*.xml'; if ( !empty( $this->options['aiosp_sitemap_gzipped'] ) ) $scan2 .= get_home_path() . $this->options['aiosp_sitemap_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['aiosp_sitemap_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['aiosp_sitemap_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["aiosp_sitemap_debug"] ) ) $this->options["aiosp_sitemap_debug"] = ''; $this->options["aiosp_sitemap_debug"] = date( 'Y-m-d H:i:s' ) . " {$msg}\n" . $this->options["aiosp_sitemap_debug"]; if ( $this->strlen( $this->options["aiosp_sitemap_debug"] ) > 2048 ) { $end = $this->strrpos( $this->options["aiosp_sitemap_debug"], "\n" ); if ( $end === false ) $end = 2048; $this->options["aiosp_sitemap_debug"] = $this->substr( $this->options["aiosp_sitemap_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( 'aiosp_sitemap_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["aiosp_sitemap_filename"] . '.xml' => 'index.php?aioseop_sitemap_path=root', $this->options["aiosp_sitemap_filename"] . '_(.+)_(\d+).xml'=> 'index.php?aioseop_sitemap_path=$matches[1]&aioseop_sitemap_page=$matches[2]', $this->options["aiosp_sitemap_filename"] . '_(.+).xml' => 'index.php?aioseop_sitemap_path=$matches[1]' ); if ( $this->options['aiosp_sitemap_gzipped'] ) { $sitemap_rules_gzipped = array( $this->options["aiosp_sitemap_filename"] . '.xml.gz' => 'index.php?aiosp_sitemap_gzipped=1&aioseop_sitemap_path=root.gz', $this->options["aiosp_sitemap_filename"] . '_(.+)_(\d+).xml.gz' => 'index.php?aioseop_sitemap_path=$matches[1].gz&aioseop_sitemap_page=$matches[2]', $this->options["aiosp_sitemap_filename"] . '_(.+).xml.gz' => 'index.php?aioseop_sitemap_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( 'aiosp_sitemap_rules_flushed', true, 43200 ); } } } /** Add our query variable for sitemap generation. **/ function query_var_hook($vars) { $vars[] = 'aioseop_sitemap_path'; if ( $this->paginate ) $vars[] = 'aioseop_sitemap_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['aiosp_sitemap_rewrite'] ) ) if( !empty( $query->query_vars['aioseop_sitemap_path'] ) ) { if( !empty( $query->query_vars['aioseop_sitemap_page'] ) ) $page = $query->query_vars['aioseop_sitemap_page'] - 1; $this->start_memory_usage = memory_get_peak_usage(); $sitemap_type = $query->query_vars['aioseop_sitemap_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['aiosp_sitemap_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(); } } /** 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' ); if ( $this->options['aiosp_sitemap_indexes'] ) { $posttypes = $this->options['aiosp_sitemap_posttypes']; if ( empty( $posttypes ) ) $posttypes = Array(); $taxonomies = $this->options['aiosp_sitemap_taxonomies']; if ( empty( $taxonomies ) ) $taxonomies = Array(); if ( $sitemap_type === 'root' ) { $this->output_sitemap_index( array_merge( $this->get_sitemap_index_filenames() ), $comment ); } elseif ( $sitemap_type === 'addl' ) { $this->output_sitemap( $this->get_addl_pages(), $comment ); } elseif ( $sitemap_type === 'archive' && $this->option_isset( 'archive' ) ) { $this->output_sitemap( $this->get_archive_prio_data(), $comment ); } elseif ( $sitemap_type === 'author' && $this->option_isset( 'author' ) ) { $this->output_sitemap( $this->get_author_prio_data(), $comment ); } elseif ( in_array( $sitemap_type, $posttypes ) ) { $this->output_sitemap( $this->get_all_post_priority_data( $sitemap_type, 'publish', $page ), $comment ); } elseif ( in_array( $sitemap_type, $taxonomies ) ) { $this->output_sitemap( $this->get_term_priority_data( get_terms( $sitemap_type, $this->get_tax_args() ) ), $comment ); } } elseif ( $sitemap_type === 'root' ) echo $this->do_simple_sitemap( $comment ); } /** Build a url to the sitemap. **/ function get_sitemap_url() { $url = get_home_url() . '/' . $this->options["aiosp_sitemap_filename"] . '.xml'; if ( $this->options['aiosp_sitemap_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['aiosp_sitemap_paginate'] ) ) { $this->paginate = true; if ( ( $this->options['aiosp_sitemap_max_posts'] ) && ( $this->options['aiosp_sitemap_max_posts'] > 0 ) && ( $this->options['aiosp_sitemap_max_posts'] < 50000 ) ) $this->max_posts = $this->options['aiosp_sitemap_max_posts']; else $this->max_posts = 50000; } else { $this->paginate = false; $this->max_posts = 50000; } if ( !$this->options['aiosp_sitemap_rewrite'] ) { if ( $this->options['aiosp_sitemap_indexes'] ) { $this->do_indexed_sitemaps(); } else { $this->log_start(); $comment = sprintf( __( "file '%s' statically", 'all_in_one_seo_pack' ), $this->options['aiosp_sitemap_filename'] ); $sitemap = $this->do_simple_sitemap( $comment ); $this->write_sitemaps( $this->options['aiosp_sitemap_filename'], $sitemap ); $this->log_stats( 'root', $this->options['aiosp_sitemap_gzipped'], false ); } } else { delete_transient( 'aiosp_sitemap_rules_flushed' ); } $this->do_notify(); $this->debug_message( __( 'Updated sitemap settings.', 'all_in_one_seo_pack' ) ); } /** Write sitemaps (compressed or otherwise) to the filesystem. **/ function write_sitemaps( $filename, $contents ) { $this->write_sitemap( $filename . ".xml", $contents ); if ( $this->options['aiosp_sitemap_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 ); $filename = get_home_path() . sanitize_file_name( $filename ); return $this->save_file( $filename, $contents ); } /** Get priority settings for sitemap entries. **/ function get_default_priority( $item, $nodefaults = false ) { $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(); if ( !empty( $cache[ $item ] ) ) return $cache[ $item ]; if ( !empty( $defaults[ $item ] ) ) { $field = $this->prefix . 'prio_' . $item; if ( $this->option_isset( 'prio_' . $item ) && $this->options[ $field ] != 'no' ) { $cache[ $item ] = $this->options[ $field ]; return $this->options[ $field ]; } if ( $nodefaults ) return false; return $defaults[ $item ]; } return false; } /** Get frequency settings for sitemap entries. **/ function get_default_frequency( $item, $nodefaults = false ) { $defaults = Array( 'homepage' => 'always', 'blog' => 'daily', 'sitemap' => 'hourly', 'post' => 'weekly', 'archive' => 'monthly', 'author' => 'weekly', 'taxonomies' => 'monthly' ); static $cache = Array(); if ( !empty( $cache[ $item ] ) ) return $cache[ $item ]; if ( !empty( $defaults[ $item ] ) ) { $field = $this->prefix . 'freq_' . $item; if ( $this->option_isset( 'freq_' . $item ) && $this->options[ $field ] != 'no' ) { $cache[ $item ] = $this->options[ $field ]; return $this->options[ $field ]; } if ( $nodefaults ) return false; return $defaults[ $item ]; } return false; } /** Build an index of sitemaps used. **/ function get_sitemap_index_filenames() { $files = Array(); $options = $this->options; $prefix = $options["aiosp_sitemap_filename"]; $suffix = '.xml'; if ( $options['aiosp_sitemap_gzipped'] ) $suffix .= '.gz'; if ( empty( $options['aiosp_sitemap_posttypes'] ) ) $options['aiosp_sitemap_posttypes'] = Array(); if ( empty( $options['aiosp_sitemap_taxonomies'] ) ) $options['aiosp_sitemap_taxonomies'] = Array(); $options['aiosp_sitemap_posttypes'] = array_diff( $options['aiosp_sitemap_posttypes'], Array( 'all' ) ); $options['aiosp_sitemap_taxonomies'] = array_diff( $options['aiosp_sitemap_taxonomies'], Array( 'all' ) ); $url_base = trailingslashit( get_home_url() ); $files[] = Array( 'loc' => $url_base . $prefix . '_addl' . $suffix ); if ( !empty( $options['aiosp_sitemap_posttypes'] ) ) { $prio = $this->get_default_priority( 'post' ); $freq = $this->get_default_frequency( 'post' ); if ( $this->paginate ) { $post_counts = $this->get_all_post_counts( Array('post_type' => $options['aiosp_sitemap_posttypes'], 'post_status' => 'publish') ); } foreach( $options['aiosp_sitemap_posttypes'] as $sm ) { 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['aiosp_sitemap_taxonomies'] ) ) foreach( $options['aiosp_sitemap_taxonomies'] as $sm ) $files[] = Array( 'loc' => $url_base . $prefix . '_' . $sm . $suffix, 'priority' => $this->get_default_priority( 'taxonomies' ), 'changefreq' => $this->get_default_frequency( 'taxonomies' ) ); foreach( $this->get_child_sitemap_urls() as $csm ) $files[] = Array( 'loc' => $csm, 'priority' => $this->get_default_priority( 'sitemap' ), 'changefreq' => $this->get_default_frequency( 'sitemap' ) ); return $files; } /** Build all the indexes. **/ function do_indexed_sitemaps() { $this->start_memory_usage = memory_get_peak_usage(); $options = $this->options; $comment = __( "file '%s' statically", 'all_in_one_seo_pack' ); $this->write_sitemaps( $options['aiosp_sitemap_filename'], $this->build_sitemap_index( $this->get_sitemap_index_filenames() ), sprintf( $comment, $options['aiosp_sitemap_filename'] ) ); $this->write_sitemaps( $options['aiosp_sitemap_filename'] . "_addl", $this->build_sitemap( $this->get_addl_pages(), sprintf( $comment, $options['aiosp_sitemap_filename'] . "_addl" ) ) ); if ( ( !isset( $options['aiosp_sitemap_posttypes'] ) ) || ( !is_array( $options['aiosp_sitemap_posttypes'] ) ) ) $options['aiosp_sitemap_posttypes'] = Array(); if ( ( !isset( $options['aiosp_sitemap_taxonomies'] ) ) || ( !is_array( $options['aiosp_sitemap_taxonomies'] ) ) ) $options['aiosp_sitemap_taxonomies'] = Array(); $options['aiosp_sitemap_posttypes'] = array_diff( $options['aiosp_sitemap_posttypes'], Array( 'all' ) ); $options['aiosp_sitemap_taxonomies'] = array_diff( $options['aiosp_sitemap_taxonomies'], Array( 'all' ) ); if ( !empty( $options['aiosp_sitemap_posttypes'] ) ) { if ( $this->paginate ) $post_counts = $this->get_all_post_counts( Array('post_type' => $options['aiosp_sitemap_posttypes'], 'post_status' => 'publish') ); foreach ( $options['aiosp_sitemap_posttypes'] as $posttype ) { 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 ) { $comment = sprintf( $comment, $options['aiosp_sitemap_filename'] . "_{$posttype}_{$count}" ); $this->write_sitemaps( $options['aiosp_sitemap_filename'] . "_{$posttype}_{$count}", $this->build_sitemap( $this->get_all_post_priority_data( $posttype, 'publish', ( $count - 1 ) ), $comment ) ); $count++; } } else { $comment = sprintf( $comment, $options['aiosp_sitemap_filename'] . "_$posttype" ); $this->write_sitemaps( $options['aiosp_sitemap_filename'] . "_$posttype", $this->build_sitemap( $this->get_all_post_priority_data( $posttype ), $comment ) ); } } } if ( $this->option_isset( 'archive') ) { $comment = sprintf( $comment, $options['aiosp_sitemap_filename'] . "_archive" ); $this->write_sitemaps( $options['aiosp_sitemap_filename'] . "_archive", $this->build_sitemap( $this->get_archive_prio_data(), $comment ) ); } if ( $this->option_isset( 'author') ) { $comment = sprintf( $comment, $options['aiosp_sitemap_filename'] . "_author" ); $this->write_sitemaps( $options['aiosp_sitemap_filename'] . "_author", $this->build_sitemap( $this->get_author_prio_data(), $comment ) ); } if ( !empty( $options['aiosp_sitemap_taxonomies'] ) ) foreach ( $options['aiosp_sitemap_taxonomies'] as $taxonomy ) { $comment = sprintf( $comment, $options['aiosp_sitemap_filename'] . "_$taxonomy" ); $this->write_sitemaps( $options['aiosp_sitemap_filename'] . "_$taxonomy", $this->build_sitemap( $this->get_term_priority_data( get_terms( $taxonomy, $this->get_tax_args() ), $comment ) ) ); } $this->log_stats( 'indexed', $options['aiosp_sitemap_gzipped'], false ); } /** Build a single, stand-alone sitemap without indexes. **/ function do_simple_sitemap( $comment = '' ) { $home = Array( 'loc' => get_home_url(), 'priority' => $this->get_default_priority( 'homepage' ), 'changefreq' => $this->get_default_frequency( 'homepage' ) ); $posts = get_option( 'page_for_posts' ); if ( $posts ) { $posts = $this->get_permalink( $posts ); if ( $posts == $home['loc'] ) $posts = 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['aiosp_sitemap_posttypes'] ) ) $options['aiosp_sitemap_posttypes'] = array_diff( $options['aiosp_sitemap_posttypes'], Array( 'all' ) ); if ( is_array( $options['aiosp_sitemap_taxonomies'] ) ) $options['aiosp_sitemap_taxonomies'] = array_diff( $options['aiosp_sitemap_taxonomies'], Array( 'all' ) ); $prio = $this->get_all_post_priority_data( $options['aiosp_sitemap_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['aiosp_sitemap_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 ); return $this->build_sitemap( $prio, $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"; echo 'plugin_path['url'] . 'sitemap.xsl"?>' . "\r\n"; echo '