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']);
?>