stylesheet = ''; if ( ! empty( $_SERVER['SERVER_PROTOCOL'] ) ) { $this->http_protocol = sanitize_text_field( $_SERVER['SERVER_PROTOCOL'] ); } $this->init(); add_action( 'wpforo_before_init', array($this, 'before_init') ); } public function init() { $this->init_defaults(); $this->init_options(); $this->init_hooks(); } private function init_defaults() { $this->default = new stdClass(); $this->default->options = array( 'members_sitemap' => 1, 'forums_sitemap' => 1, 'topics_sitemap' => 1, 'sitemap_items_per_page' => 1000, 'allow_ping' => 1, 'ping_immediately' => 0 ); } private function init_options() { $this->options = apply_filters( 'wpforo_seo_options', get_wpf_option( 'wpforo_seo_options', $this->default->options ) ); } private function init_hooks() { add_filter( 'wpforo_before_init_current_object', array( $this, 'redirect' ), 10, 2 ); add_action( 'wpforo_ping_search_engines', array( $this, 'ping_search_engines' ) ); add_action( 'wpforo_hit_sitemap_index', array( $this, 'hit_sitemap_index' ) ); } public function before_init(){ if( !wpforo_feature('seo-profile') ) $this->options['members_sitemap'] = 0; } public function sitemap_url($url) { $date = ( !empty($url['lastmod']) ? date('c', strtotime($url['lastmod']) ) : null ); $url['loc'] = htmlspecialchars($url['loc']); $output = "\t\n"; $output .= "\t\t" . $this->encode_url_rfc3986($url['loc']) . "\n"; $output .= empty($date) ? '' : "\t\t" . htmlspecialchars($date) . "\n"; $output .= "\t\n"; return apply_filters('wpforo_sitemap_url', $output, $url); } public function members_sitemap($paged){ $paged = absint($paged); $sitemap = ''; if( $paged && $profiles = $this->get_public_profiles($paged) ){ foreach ( $profiles as $profile ){ if( $profile['loc'] = wpforo_member($profile['userid'], 'profile_url') ){ $sitemap .= $this->sitemap_url($profile); } } } return $sitemap; } public function forums_sitemap(){ $sitemap = ''; if( $forums = $this->get_public_forums() ){ foreach ( $forums as $forum ){ $forum['loc'] = wpforo_forum($forum['forumid'], 'url'); $sitemap .= $this->sitemap_url($forum); } } return $sitemap; } public function topics_sitemap($paged){ $paged = absint($paged); $sitemap = ''; if( $paged && $topics = $this->get_public_topics($paged) ){ foreach ( $topics as $topic ){ $topic['loc'] = wpforo_topic($topic['topicid'], 'url'); $sitemap .= $this->sitemap_url($topic); } } return $sitemap; } private function encode_url_rfc3986($url) { if (filter_var($url, FILTER_VALIDATE_URL)) { return $url; } $path = wp_parse_url($url, PHP_URL_PATH); if (!empty($path) && '/' !== $path) { $encoded_path = explode('/', $path); $encoded_path = array_map('rawurldecode', $encoded_path); $encoded_path = array_map('rawurlencode', $encoded_path); $encoded_path = implode('/', $encoded_path); $encoded_path = str_replace('%7E', '~', $encoded_path); // PHP <5.3. $url = str_replace($path, $encoded_path, $url); } $query = wp_parse_url($url, PHP_URL_QUERY); if (!empty($query)) { parse_str($query, $parsed_query); if (defined('PHP_QUERY_RFC3986')) { // PHP 5.4+. $parsed_query = http_build_query($parsed_query, null, '&', PHP_QUERY_RFC3986); } else { $parsed_query = http_build_query($parsed_query, null, '&'); $parsed_query = str_replace('+', '%20', $parsed_query); $parsed_query = str_replace('%7E', '~', $parsed_query); } $url = str_replace($query, $parsed_query, $url); } return $url; } private function get_public_profiles($paged = 0) { $profiles = array(); if( $groupids = WPF()->usergroup->get_visible_usergroup_ids() ){ $items_per_page = $this->options['sitemap_items_per_page']; $sql = "SELECT `userid`, FROM_UNIXTIME( IFNULL(`online_time`, UNIX_TIMESTAMP()) ) AS lastmod FROM " . WPF()->tables->profiles . " WHERE `groupid` IN(" . implode(',', $groupids) . ") OR `secondary_groups` REGEXP '(,|^)(" . implode('|', $groupids) . ")(,|$)' ORDER BY `userid` ASC"; if ($paged) $sql .= " LIMIT " . (--$paged * $items_per_page) . ", $items_per_page"; $profiles = (array) WPF()->db->get_results($sql, ARRAY_A); } return $profiles; } private function get_public_forums() { $forums = array(); if( $forumids = $this->get_public_forumids() ){ $sql = "SELECT `forumid`, CASE WHEN `last_post_date` = '0000-00-00 00:00:00' THEN NOW() ELSE `last_post_date` END AS lastmod FROM " . WPF()->tables->forums . " WHERE `forumid` IN(" . implode(',', $forumids) . ") ORDER BY `parentid` ASC, `title` ASC"; $forums = (array) WPF()->db->get_results($sql, ARRAY_A); } return $forums; } private function get_public_forumids() { $forumids = array(); $sql = "SELECT `forumid` FROM " . WPF()->tables->forums . " ORDER BY `parentid` ASC, `title` ASC"; if ($_forumids = WPF()->db->get_col($sql)) { foreach ($_forumids as $_forumid) { if (WPF()->perm->forum_can('vf', $_forumid)) { $forumids[] = $_forumid; } } } return $forumids; } private function get_public_topics($paged = 0) { $topics = array(); if( $forumids = $this->get_public_forumids() ){ $items_per_page = $this->options['sitemap_items_per_page']; $sql = "SELECT `topicid`, `modified` as lastmod FROM " . WPF()->tables->topics . " WHERE `private` = 0 AND `status` = 0 AND `forumid` IN(" . implode(',', $forumids) . ") ORDER BY `topicid` ASC"; if ($paged) $sql .= " LIMIT " . (--$paged * $items_per_page) . ", $items_per_page"; $topics = (array) WPF()->db->get_results($sql, ARRAY_A); } return $topics; } private function get_public_profiles_count(){ $count = 0; if( $groupids = WPF()->usergroup->get_visible_usergroup_ids() ){ $sql = "SELECT COUNT(*) FROM " . WPF()->tables->profiles . " WHERE `groupid` IN(" . implode(',', $groupids) . ") OR `secondary_groups` REGEXP '(,|^)(" . implode('|', $groupids) . ")(,|$)'"; $count = (int) WPF()->db->get_var($sql); } return $count; } private function get_public_topics_count(){ $count = 0; if( $forumids = $this->get_public_forumids() ){ $sql = "SELECT COUNT(*) FROM " . WPF()->tables->topics . " WHERE `private` = 0 AND `status` = 0 AND `forumid` IN(" . implode(',', $forumids) . ")"; $count = (int) WPF()->db->get_var($sql); } return $count; } public function get_root_map() { $links = array(); $items_per_page = $this->options['sitemap_items_per_page']; if( $this->options['topics_sitemap'] ){ if( $topics_count = $this->get_public_topics_count() ){ $pages_count = ceil($topics_count/$items_per_page); for( $i = 1; $i <= $pages_count; $i++ ){ $links[] = trim( wpforo_home_url('topic-sitemap' . $i . '.xml'), '/' ); } } } if( $this->options['members_sitemap'] ){ if( $profiles_count = $this->get_public_profiles_count() ){ $pages_count = ceil($profiles_count/$items_per_page); for( $i = 1; $i <= $pages_count; $i++ ){ $links[] = trim( wpforo_home_url('profile-sitemap' . $i . '.xml'), '/' ); } } } $links[] = trim( wpforo_home_url('forum-sitemap.xml'), '/' ); // make sitemap index $xml = '' . "\n"; foreach ( $links as $link ) { $link = htmlspecialchars( $link ); $xml .= "\t\n"; $xml .= "\t\t" . $link . "\n"; $xml .= "\t\n"; } $xml .= apply_filters( 'wpforo_sitemap_index', '' ); $xml .= ''; return $xml; } public function get_sitemap( $type, $paged ) { $transient_key = 'wpforo_seo_sitemap_' . $type . $paged; if( !$xml = get_transient($transient_key) ){ if( $type ){ $urls = ''; switch ($type){ case 'topic': if( $this->options['topics_sitemap'] ) $urls = $this->topics_sitemap($paged); break; case 'forum': if( $this->options['forums_sitemap'] ) $urls = $this->forums_sitemap(); break; case 'profile': if( $this->options['members_sitemap'] ) $urls = $this->members_sitemap($paged); break; } if($urls){ $urlset = '' . "\n"; $xml = apply_filters( "wpforo_sitemap_{$type}_urlset", $urlset ); $xml .= $urls; $xml .= ''; } }else{ $xml = $this->get_root_map(); } set_transient($transient_key, $xml, DAY_IN_SECONDS); } return (string)$xml; } public function get_output( $sitemap ) { $output = ''; if ( $this->stylesheet ) { $output .= apply_filters( 'wpforo_stylesheet_url', $this->stylesheet ) . "\n"; } $output .= $sitemap; $output .= "\n"; return $output; } public function output( $sitemap ) { if ( ! headers_sent() ) { header( $this->http_protocol . ' 200 OK', true, 200 ); // Prevent the search engines from indexing the XML Sitemap. header( 'X-Robots-Tag: noindex, follow', true ); header( 'Content-Type: text/xml; charset=UTF-8' ); } echo $this->get_output($sitemap); } public function sitemap_close() { remove_all_actions( 'wp_footer' ); die(); } public function redirect($current_object, $wpf_url_parse){ $pattern = '#^[\r\n\t\s\0]*(?\w*)-?sitemap(?:(?\d*)|_index)\.xml[\r\n\t\s\0]*$#iu'; if( !empty($wpf_url_parse[0]) && preg_match($pattern, basename($wpf_url_parse[0]), $match) ){ $current_object['template'] = 'sitemap'; $query = array('type' => '', 'paged' => 1); $query = wpforo_parse_args($match, $query); $type = trim($query['type']); $paged = absint($query['paged']); if(!$paged) $paged = 1; if( $sitemap = $this->get_sitemap($type, $paged) ){ $this->output($sitemap); $this->sitemap_close(); }else{ $current_object['is_404'] = true; } } return $current_object; } public function hit_sitemap_index() { wp_remote_get( trim( wpforo_home_url('sitemap_index.xml'), '/' ) ); } public function ping_search_engines( $url = '' ) { if( !$this->options['allow_ping'] || !$this->get_public_forumids() ) return; if(!$url) $url = urlencode( trim( wpforo_home_url('sitemap_index.xml'), '/' ) ); wp_remote_get( 'http://www.google.com/webmasters/tools/ping?sitemap=' . $url, array( 'blocking' => false ) ); wp_remote_get( 'http://www.bing.com/ping?sitemap=' . $url, array( 'blocking' => false ) ); } public function clear_cache( $type = '', $paged = 1 ) { if( $type == '' && $paged = 1 ){ $like = 'wpforo_seo_sitemap_%'; $wheres = array(); $wheres[] = sprintf( "option_name LIKE '%s'", addcslashes( '_transient_' . $like, '_' ) ); $wheres[] = sprintf( "option_name LIKE '%s'", addcslashes( '_transient_timeout_' . $like, '_' ) ); // Delete transients. $sql = sprintf( 'DELETE FROM %1$s WHERE %2$s', WPF()->db->options, implode( ' OR ', $wheres ) ); WPF()->db->query($sql); }else{ $transient_key = 'wpforo_seo_sitemap_' . $type . $paged; delete_transient($transient_key); } switch ($type){ case 'profile': if( !$this->options['members_sitemap'] ) return; break; case 'forum': if( !$this->options['forums_sitemap'] ) return; break; case 'topic': if( !$this->options['topics_sitemap'] ) return; break; case '': break; default: return; } wp_schedule_single_event( ( time() + 300 ), 'wpforo_hit_sitemap_index' ); if(!$this->options['allow_ping']) return; if ( $this->options['ping_immediately'] ) { $this->ping_search_engines(); }elseif ( !wp_next_scheduled('wpforo_ping_search_engines') ) { wp_schedule_single_event( ( time() + 300 ), 'wpforo_ping_search_engines' ); } } }