init_default_settings(); $this->init_hooks(); } /** * Initialize WordPress hooks */ private function init_hooks() { // Handle sitemap generation add_action('init', array($this, 'register_sitemap_endpoints')); // Handle admin form submissions add_action('admin_post_tigerstyle_save_sitemap_xml', array($this, 'save_settings')); // Add admin scripts add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts')); // Flush rewrite rules when settings change add_action('update_option_' . $this->option_name, array($this, 'flush_rewrite_rules')); } /** * Initialize default sitemap settings */ private function init_default_settings() { $this->default_settings = array( 'enabled' => true, 'include_posts' => true, 'include_pages' => true, 'include_categories' => true, 'include_tags' => true, 'include_custom_post_types' => array(), 'exclude_post_ids' => '', 'max_entries' => 50000, 'split_by_post_type' => false, 'include_images' => true, 'include_lastmod' => true, 'include_changefreq' => true, 'include_priority' => true, 'default_changefreq' => 'monthly', 'ping_search_engines' => true, 'cache_duration' => 24, // hours 'exclude_noindex' => true ); } /** * Register sitemap endpoints */ public function register_sitemap_endpoints() { $settings = $this->get_settings(); if (!$settings['enabled']) { return; } // Main sitemap index add_rewrite_rule('^sitemap\.xml$', 'index.php?tigerstyle_sitemap=index', 'top'); add_rewrite_rule('^sitemap_index\.xml$', 'index.php?tigerstyle_sitemap=index', 'top'); // Individual sitemaps add_rewrite_rule('^sitemap-([^/]+)\.xml$', 'index.php?tigerstyle_sitemap=$matches[1]', 'top'); // Add query vars add_filter('query_vars', array($this, 'add_query_vars')); // Handle template redirects add_action('template_redirect', array($this, 'handle_sitemap_request')); } /** * Add query vars */ public function add_query_vars($vars) { $vars[] = 'tigerstyle_sitemap'; return $vars; } /** * Handle sitemap requests */ public function handle_sitemap_request() { $sitemap = get_query_var('tigerstyle_sitemap'); if (empty($sitemap)) { return; } // Set XML headers header('Content-Type: application/xml; charset=utf-8'); if ($sitemap === 'index') { $this->generate_sitemap_index(); } else { $this->generate_sitemap($sitemap); } exit; } /** * Generate sitemap index */ private function generate_sitemap_index() { $settings = $this->get_settings(); echo '' . "\n"; echo '' . "\n"; // Posts sitemap if ($settings['include_posts']) { $this->add_sitemap_to_index('posts'); } // Pages sitemap if ($settings['include_pages']) { $this->add_sitemap_to_index('pages'); } // Categories sitemap if ($settings['include_categories']) { $this->add_sitemap_to_index('categories'); } // Tags sitemap if ($settings['include_tags']) { $this->add_sitemap_to_index('tags'); } // Custom post types if (!empty($settings['include_custom_post_types'])) { foreach ($settings['include_custom_post_types'] as $post_type) { $this->add_sitemap_to_index($post_type); } } echo '' . "\n"; } /** * Add sitemap to index */ private function add_sitemap_to_index($type) { $url = home_url("/sitemap-{$type}.xml"); $lastmod = date('c'); echo " \n"; echo " " . esc_xml($url) . "\n"; echo " " . esc_xml($lastmod) . "\n"; echo " \n"; } /** * Generate individual sitemap */ private function generate_sitemap($type) { $settings = $this->get_settings(); echo '' . "\n"; echo '' . "\n"; switch ($type) { case 'posts': $this->generate_posts_sitemap(); break; case 'pages': $this->generate_pages_sitemap(); break; case 'categories': $this->generate_categories_sitemap(); break; case 'tags': $this->generate_tags_sitemap(); break; default: // Handle custom post types $this->generate_custom_post_type_sitemap($type); break; } echo '' . "\n"; } /** * Generate posts sitemap */ private function generate_posts_sitemap() { $settings = $this->get_settings(); $exclude_ids = array_filter(array_map('trim', explode(',', $settings['exclude_post_ids']))); $posts = get_posts(array( 'post_type' => 'post', 'post_status' => 'publish', 'numberposts' => $settings['max_entries'], 'exclude' => $exclude_ids, 'meta_query' => $settings['exclude_noindex'] ? array( array( 'key' => '_yoast_wpseo_meta-robots-noindex', 'value' => '1', 'compare' => '!=' ) ) : array() )); foreach ($posts as $post) { $this->add_url_to_sitemap($post); } } /** * Generate pages sitemap */ private function generate_pages_sitemap() { $settings = $this->get_settings(); $exclude_ids = array_filter(array_map('trim', explode(',', $settings['exclude_post_ids']))); $pages = get_posts(array( 'post_type' => 'page', 'post_status' => 'publish', 'numberposts' => $settings['max_entries'], 'exclude' => $exclude_ids, 'meta_query' => $settings['exclude_noindex'] ? array( array( 'key' => '_yoast_wpseo_meta-robots-noindex', 'value' => '1', 'compare' => '!=' ) ) : array() )); foreach ($pages as $page) { $this->add_url_to_sitemap($page); } } /** * Generate categories sitemap */ private function generate_categories_sitemap() { $categories = get_categories(array( 'hide_empty' => true, 'number' => $this->get_settings()['max_entries'] )); foreach ($categories as $category) { $this->add_taxonomy_url_to_sitemap($category); } } /** * Generate tags sitemap */ private function generate_tags_sitemap() { $tags = get_tags(array( 'hide_empty' => true, 'number' => $this->get_settings()['max_entries'] )); foreach ($tags as $tag) { $this->add_taxonomy_url_to_sitemap($tag); } } /** * Generate custom post type sitemap */ private function generate_custom_post_type_sitemap($post_type) { $settings = $this->get_settings(); if (!in_array($post_type, $settings['include_custom_post_types'])) { return; } $posts = get_posts(array( 'post_type' => $post_type, 'post_status' => 'publish', 'numberposts' => $settings['max_entries'] )); foreach ($posts as $post) { $this->add_url_to_sitemap($post); } } /** * Add URL to sitemap for posts/pages */ private function add_url_to_sitemap($post) { $settings = $this->get_settings(); $url = get_permalink($post); echo " \n"; echo " " . esc_xml($url) . "\n"; if ($settings['include_lastmod']) { echo " " . esc_xml(date('c', strtotime($post->post_modified))) . "\n"; } if ($settings['include_changefreq']) { echo " " . esc_xml($settings['default_changefreq']) . "\n"; } if ($settings['include_priority']) { $priority = ($post->post_type === 'page') ? '0.8' : '0.6'; echo " " . esc_xml($priority) . "\n"; } // Add images if enabled if ($settings['include_images']) { $this->add_post_images_to_sitemap($post); } echo " \n"; } /** * Add URL to sitemap for taxonomy terms */ private function add_taxonomy_url_to_sitemap($term) { $settings = $this->get_settings(); $url = get_term_link($term); if (is_wp_error($url)) { return; } echo " \n"; echo " " . esc_xml($url) . "\n"; if ($settings['include_changefreq']) { echo " weekly\n"; } if ($settings['include_priority']) { echo " 0.5\n"; } echo " \n"; } /** * Add post images to sitemap */ private function add_post_images_to_sitemap($post) { // Get featured image $featured_image_id = get_post_thumbnail_id($post->ID); if ($featured_image_id) { $image_url = wp_get_attachment_image_url($featured_image_id, 'full'); if ($image_url) { echo " \n"; echo " " . esc_xml($image_url) . "\n"; echo " \n"; } } // Get images from content preg_match_all('/]+src=[\'"]([^\'"]+)[\'"][^>]*>/i', $post->post_content, $matches); if (!empty($matches[1])) { foreach (array_slice($matches[1], 0, 10) as $image_url) { if (filter_var($image_url, FILTER_VALIDATE_URL)) { echo " \n"; echo " " . esc_xml($image_url) . "\n"; echo " \n"; } } } } /** * Get current settings */ private function get_settings() { $settings = get_option($this->option_name, array()); return wp_parse_args($settings, $this->default_settings); } /** * Save settings from admin form */ public function save_settings() { // Verify nonce if (!wp_verify_nonce($_POST['tigerstyle_sitemap_nonce'], 'tigerstyle_sitemap_save')) { wp_die('Security check failed'); } // Check user permissions if (!current_user_can('manage_options')) { wp_die('Insufficient permissions'); } $settings = array(); // Basic settings $settings['enabled'] = isset($_POST['enabled']) ? true : false; $settings['include_posts'] = isset($_POST['include_posts']) ? true : false; $settings['include_pages'] = isset($_POST['include_pages']) ? true : false; $settings['include_categories'] = isset($_POST['include_categories']) ? true : false; $settings['include_tags'] = isset($_POST['include_tags']) ? true : false; $settings['include_custom_post_types'] = isset($_POST['include_custom_post_types']) ? $_POST['include_custom_post_types'] : array(); $settings['exclude_post_ids'] = sanitize_text_field($_POST['exclude_post_ids']); $settings['max_entries'] = intval($_POST['max_entries']); $settings['split_by_post_type'] = isset($_POST['split_by_post_type']) ? true : false; $settings['include_images'] = isset($_POST['include_images']) ? true : false; $settings['include_lastmod'] = isset($_POST['include_lastmod']) ? true : false; $settings['include_changefreq'] = isset($_POST['include_changefreq']) ? true : false; $settings['include_priority'] = isset($_POST['include_priority']) ? true : false; $settings['default_changefreq'] = sanitize_text_field($_POST['default_changefreq']); $settings['ping_search_engines'] = isset($_POST['ping_search_engines']) ? true : false; $settings['cache_duration'] = intval($_POST['cache_duration']); $settings['exclude_noindex'] = isset($_POST['exclude_noindex']) ? true : false; // Save settings update_option($this->option_name, $settings); // Flush rewrite rules flush_rewrite_rules(); // Redirect back with success message wp_redirect(add_query_arg(array( 'page' => 'tigerstyle-heat', 'message' => 'sitemap_xml_updated' ), admin_url('admin.php'))); exit; } /** * Flush rewrite rules when settings change */ public function flush_rewrite_rules() { flush_rewrite_rules(); } /** * Enqueue admin scripts */ public function enqueue_admin_scripts($hook) { if ($hook !== 'toplevel_page_tigerstyle-heat') { return; } wp_enqueue_script('tigerstyle-sitemap-admin', TIGERSTYLE_HEAT_PLUGIN_URL . 'admin/js/sitemap-admin.js', array('jquery'), TIGERSTYLE_HEAT_VERSION, true); } /** * Render admin page */ public function render_admin_page() { $settings = $this->get_settings(); $sitemap_index_url = home_url('/sitemap.xml'); $available_post_types = get_post_types(array('public' => true), 'objects'); unset($available_post_types['attachment']); ?>





name, array('post', 'page'))): ?>