| 1 |
<?php |
| 2 |
/** |
| 3 |
* The XML Sitemap admin page view |
| 4 |
* |
| 5 |
* @link https://searchatlas.com |
| 6 |
* @since 1.0.0 |
| 7 |
* |
| 8 |
* @package Metasync |
| 9 |
* @subpackage Metasync/views |
| 10 |
*/ |
| 11 |
|
| 12 |
if (!defined('ABSPATH')) { |
| 13 |
exit; // Exit if accessed directly |
| 14 |
} |
| 15 |
?> |
| 16 |
|
| 17 |
<?php $this->render_layout_open('XML Sitemap', 'xml_sitemap', 'Manage your XML sitemap settings and status.'); ?> |
| 18 |
|
| 19 |
<div class="metasync-sitemap-tabs"> |
| 20 |
<ul class="metasync-tab-nav"> |
| 21 |
<li> |
| 22 |
<a href="<?php echo esc_url(admin_url('admin.php?page=' . Metasync_Admin::$page_slug . '-xml-sitemap&tab=general')); ?>" |
| 23 |
data-tab="general"> |
| 24 |
<?php esc_html_e('General', 'metasync'); ?> |
| 25 |
</a> |
| 26 |
</li> |
| 27 |
<li> |
| 28 |
<a href="<?php echo esc_url(admin_url('admin.php?page=' . Metasync_Admin::$page_slug . '-xml-sitemap&tab=news')); ?>" |
| 29 |
data-tab="news"> |
| 30 |
<?php esc_html_e('News Sitemap', 'metasync'); ?> |
| 31 |
</a> |
| 32 |
</li> |
| 33 |
<li> |
| 34 |
<a href="<?php echo esc_url(admin_url('admin.php?page=' . Metasync_Admin::$page_slug . '-xml-sitemap&tab=video')); ?>" |
| 35 |
data-tab="video"> |
| 36 |
<?php esc_html_e('Video Sitemap', 'metasync'); ?> |
| 37 |
</a> |
| 38 |
</li> |
| 39 |
</ul> |
| 40 |
</div> |
| 41 |
|
| 42 |
<!-- General Tab --> |
| 43 |
<div id="metasync-sitemap-general" class="metasync-sitemap-tab-content"> |
| 44 |
|
| 45 |
<div class="metasync-sitemap-outer"> |
| 46 |
<div class="metasync-sitemap-container"> |
| 47 |
|
| 48 |
<!-- Sitemap Status Card --> |
| 49 |
<div class="dashboard-card metasync-sitemap-status-card"> |
| 50 |
<h2>Sitemap Status</h2> |
| 51 |
<p style="color: var(--dashboard-text-secondary); margin-bottom: 20px;">Monitor your sitemap generation and status.</p> |
| 52 |
|
| 53 |
<?php |
| 54 |
$sitemap_files = $sitemap_generator->get_sitemap_files(); |
| 55 |
$sitemap_count = count($sitemap_files); |
| 56 |
|
| 57 |
// Check news/video sitemap status |
| 58 |
$news_sm_enabled = !empty($news_settings['enabled']); |
| 59 |
$video_sm_enabled = !empty($video_settings['enabled']); |
| 60 |
$news_sm_exists = false !== get_transient('metasync_vsm_' . md5('news-sitemap.xml')) |
| 61 |
|| file_exists(ABSPATH . 'news-sitemap.xml'); |
| 62 |
$video_sm_exists = false !== get_transient('metasync_vsm_' . md5('video-sitemap.xml')) |
| 63 |
|| file_exists(ABSPATH . 'video-sitemap.xml'); |
| 64 |
$extra_sitemap_count = ($news_sm_exists ? 1 : 0) + ($video_sm_exists ? 1 : 0); |
| 65 |
$total_sitemap_count = $sitemap_count + $extra_sitemap_count; |
| 66 |
|
| 67 |
// Count URLs in news/video sitemaps for total |
| 68 |
$news_url_count = 0; |
| 69 |
$video_url_count = 0; |
| 70 |
if ($news_sm_exists) { |
| 71 |
$news_xml = get_transient('metasync_vsm_' . md5('news-sitemap.xml')); |
| 72 |
if (!$news_xml && file_exists(ABSPATH . 'news-sitemap.xml')) { |
| 73 |
$news_xml = file_get_contents(ABSPATH . 'news-sitemap.xml'); |
| 74 |
} |
| 75 |
if ($news_xml) { |
| 76 |
$news_url_count = substr_count($news_xml, '<url>'); |
| 77 |
} |
| 78 |
} |
| 79 |
if ($video_sm_exists) { |
| 80 |
$video_xml = get_transient('metasync_vsm_' . md5('video-sitemap.xml')); |
| 81 |
if (!$video_xml && file_exists(ABSPATH . 'video-sitemap.xml')) { |
| 82 |
$video_xml = file_get_contents(ABSPATH . 'video-sitemap.xml'); |
| 83 |
} |
| 84 |
if ($video_xml) { |
| 85 |
$video_url_count = substr_count($video_xml, '<url>'); |
| 86 |
} |
| 87 |
} |
| 88 |
$total_url_count = $url_count + $news_url_count + $video_url_count; |
| 89 |
$any_sitemap_exists = $sitemap_exists || $news_sm_exists || $video_sm_exists; |
| 90 |
?> |
| 91 |
|
| 92 |
<div class="metasync-sitemap-status-grid"> |
| 93 |
<div class="metasync-sitemap-stat"> |
| 94 |
<div class="stat-icon"><span class="dashicons dashicons-media-default"></span></div> |
| 95 |
<div class="stat-content"> |
| 96 |
<div class="stat-label">Status</div> |
| 97 |
<div class="stat-value <?php echo $any_sitemap_exists ? 'status-active' : 'status-inactive'; ?>"> |
| 98 |
<?php |
| 99 |
echo $any_sitemap_exists ? 'Generated' : 'Not Generated'; |
| 100 |
if ($sitemap_exists && $sitemap_generator->is_virtual_mode()): ?> |
| 101 |
<span style="color: #2271b1; font-size: 12px; margin-left: 5px;">(Virtual)</span> |
| 102 |
<?php endif; ?> |
| 103 |
</div> |
| 104 |
</div> |
| 105 |
</div> |
| 106 |
|
| 107 |
<div class="metasync-sitemap-stat"> |
| 108 |
<div class="stat-icon"><span class="dashicons dashicons-admin-links"></span></div> |
| 109 |
<div class="stat-content"> |
| 110 |
<div class="stat-label">Total URLs</div> |
| 111 |
<div class="stat-value"><?php echo number_format($total_url_count); ?></div> |
| 112 |
</div> |
| 113 |
</div> |
| 114 |
|
| 115 |
<div class="metasync-sitemap-stat"> |
| 116 |
<div class="stat-icon"><span class="dashicons dashicons-list-view"></span></div> |
| 117 |
<div class="stat-content"> |
| 118 |
<div class="stat-label">Sitemap Files</div> |
| 119 |
<div class="stat-value"><?php echo $total_sitemap_count; ?></div> |
| 120 |
</div> |
| 121 |
</div> |
| 122 |
|
| 123 |
<div class="metasync-sitemap-stat"> |
| 124 |
<div class="stat-icon"><span class="dashicons dashicons-update"></span></div> |
| 125 |
<div class="stat-content"> |
| 126 |
<div class="stat-label">Auto-Update</div> |
| 127 |
<div class="stat-value <?php echo $auto_update_enabled ? 'status-active' : 'status-inactive'; ?>"> |
| 128 |
<?php echo $auto_update_enabled ? 'Enabled' : 'Disabled'; ?> |
| 129 |
</div> |
| 130 |
</div> |
| 131 |
</div> |
| 132 |
|
| 133 |
<div class="metasync-sitemap-stat"> |
| 134 |
<div class="stat-icon"><span class="dashicons dashicons-clock"></span></div> |
| 135 |
<div class="stat-content"> |
| 136 |
<div class="stat-label">Last Generated</div> |
| 137 |
<div class="stat-value stat-value-small"> |
| 138 |
<?php |
| 139 |
if ($last_generated) { |
| 140 |
$time_diff = human_time_diff(strtotime($last_generated), current_time('timestamp')); |
| 141 |
echo esc_html($time_diff) . ' ago'; |
| 142 |
} else { |
| 143 |
echo 'Never'; |
| 144 |
} |
| 145 |
?> |
| 146 |
</div> |
| 147 |
</div> |
| 148 |
</div> |
| 149 |
</div> |
| 150 |
|
| 151 |
<?php if ($sitemap_exists): ?> |
| 152 |
<div class="metasync-sitemap-url-box"> |
| 153 |
<strong>Sitemap Index URL:</strong> |
| 154 |
<a href="<?php echo esc_url($sitemap_url); ?>" target="_blank" class="metasync-sitemap-link"> |
| 155 |
<?php echo esc_url($sitemap_url); ?> |
| 156 |
<span class="dashicons dashicons-external"></span> |
| 157 |
</a> |
| 158 |
<p style="margin: 10px 0 0 0; color: var(--dashboard-text-secondary); font-size: 13px;"> |
| 159 |
<em>Submit this URL to Google Search Console for indexing.</em> |
| 160 |
</p> |
| 161 |
</div> |
| 162 |
<?php endif; ?> |
| 163 |
</div> |
| 164 |
|
| 165 |
<?php if (!empty($active_sitemap_plugins)): ?> |
| 166 |
<!-- Info notice about other sitemap plugins --> |
| 167 |
<div class="dashboard-card metasync-sitemap-info-notice"> |
| 168 |
<div class="metasync-info-notice-content"> |
| 169 |
<span class="dashicons dashicons-info" style="font-size: 20px; color: var(--dashboard-text-secondary);"></span> |
| 170 |
<div> |
| 171 |
<strong>Other Sitemap Plugins Detected:</strong> |
| 172 |
<p style="margin: 5px 0 0 0; color: var(--dashboard-text-secondary); font-size: 14px;"> |
| 173 |
<?php |
| 174 |
$plugin_names = array_values($active_sitemap_plugins); |
| 175 |
echo esc_html(implode(', ', $plugin_names)); |
| 176 |
?> |
| 177 |
<?php if (count($active_sitemap_plugins) === 1): ?> |
| 178 |
is active. This plugin's sitemap will be automatically disabled when you generate the sitemap below. |
| 179 |
<?php else: ?> |
| 180 |
are active. These plugins' sitemaps will be automatically disabled when you generate the sitemap below. |
| 181 |
<?php endif; ?> |
| 182 |
</p> |
| 183 |
</div> |
| 184 |
</div> |
| 185 |
</div> |
| 186 |
<?php endif; ?> |
| 187 |
|
| 188 |
<!-- Content Settings Card --> |
| 189 |
<div class="dashboard-card metasync-sitemap-content-settings-card"> |
| 190 |
<h2><?php esc_html_e('Content Settings', 'metasync'); ?></h2> |
| 191 |
<p style="color: var(--dashboard-text-secondary); margin-bottom: 20px;"> |
| 192 |
<?php esc_html_e('Control which content types and URLs are included in the main sitemap.', 'metasync'); ?> |
| 193 |
</p> |
| 194 |
|
| 195 |
<form method="post"> |
| 196 |
<?php wp_nonce_field('metasync_sitemap_settings_action', 'metasync_sitemap_settings_nonce'); ?> |
| 197 |
|
| 198 |
<table class="form-table"> |
| 199 |
<tr> |
| 200 |
<th scope="row"><?php esc_html_e('Post Types', 'metasync'); ?></th> |
| 201 |
<td> |
| 202 |
<?php |
| 203 |
$all_public_pts = get_post_types(['public' => true], 'objects'); |
| 204 |
$general_filtered_pts = []; |
| 205 |
$general_excluded = ['attachment', 'revision', 'nav_menu_item', 'elementor_library', 'ct_template', 'oxy_user_library', 'brizy-template', 'fusion_template', 'fusion_tb_section', 'ae_global_templates', 'custom_css', 'customize_changeset', 'oembed_cache', 'user_request', 'wp_block', 'wp_template', 'wp_template_part', 'wp_global_styles', 'wp_navigation', 'acf-field-group', 'acf-field', 'fl-builder-template', 'fl-theme-layout']; |
| 206 |
foreach ($all_public_pts as $pt) { |
| 207 |
if (!in_array($pt->name, $general_excluded, true)) { |
| 208 |
$general_filtered_pts[] = $pt; |
| 209 |
} |
| 210 |
} |
| 211 |
$sitemap_configured = !empty($sitemap_settings['_configured']); |
| 212 |
$selected_sitemap_pts = !empty($sitemap_settings['post_types']) ? (array) $sitemap_settings['post_types'] : []; |
| 213 |
$gen_pts_scrollable = count($general_filtered_pts) > 10; |
| 214 |
if ($gen_pts_scrollable) : ?> |
| 215 |
<input type="text" class="metasync-checkbox-search" placeholder="<?php esc_attr_e('Filter post types...', 'metasync'); ?>"> |
| 216 |
<?php endif; ?> |
| 217 |
<div class="metasync-checkbox-list <?php echo $gen_pts_scrollable ? 'metasync-checkbox-scroll' : ''; ?>"> |
| 218 |
<?php foreach ($general_filtered_pts as $pt) : ?> |
| 219 |
<label> |
| 220 |
<input type="checkbox" name="sitemap_post_types[]" value="<?php echo esc_attr($pt->name); ?>" |
| 221 |
<?php checked(!$sitemap_configured || in_array($pt->name, $selected_sitemap_pts, true)); ?> /> |
| 222 |
<?php echo esc_html($pt->label); ?> |
| 223 |
</label> |
| 224 |
<?php endforeach; ?> |
| 225 |
<p class="metasync-no-results"><?php esc_html_e('No post types match your search.', 'metasync'); ?></p> |
| 226 |
</div> |
| 227 |
<p class="description"><?php esc_html_e('Select which post types to include. All are included by default.', 'metasync'); ?></p> |
| 228 |
</td> |
| 229 |
</tr> |
| 230 |
<tr> |
| 231 |
<th scope="row"> |
| 232 |
<?php esc_html_e('Categories', 'metasync'); ?> |
| 233 |
<?php $gen_categories = get_categories(['hide_empty' => false]); ?> |
| 234 |
<span class="metasync-checkbox-count">(<?php echo count($gen_categories); ?>)</span> |
| 235 |
</th> |
| 236 |
<td> |
| 237 |
<?php |
| 238 |
$selected_gen_cats = isset($sitemap_settings['categories']) ? (array) $sitemap_settings['categories'] : []; |
| 239 |
$gen_cats_scrollable = count($gen_categories) > 10; |
| 240 |
if ($gen_cats_scrollable) : ?> |
| 241 |
<input type="text" class="metasync-checkbox-search" placeholder="<?php esc_attr_e('Filter categories...', 'metasync'); ?>"> |
| 242 |
<?php endif; ?> |
| 243 |
<div class="metasync-checkbox-list <?php echo $gen_cats_scrollable ? 'metasync-checkbox-scroll' : ''; ?>"> |
| 244 |
<?php foreach ($gen_categories as $cat) : ?> |
| 245 |
<label> |
| 246 |
<input type="checkbox" name="sitemap_categories[]" value="<?php echo esc_attr($cat->term_id); ?>" |
| 247 |
<?php checked(in_array($cat->term_id, $selected_gen_cats)); ?> /> |
| 248 |
<?php echo esc_html($cat->name); ?> |
| 249 |
</label> |
| 250 |
<?php endforeach; ?> |
| 251 |
<p class="metasync-no-results"><?php esc_html_e('No categories match your search.', 'metasync'); ?></p> |
| 252 |
</div> |
| 253 |
<p class="description"><?php esc_html_e('Leave empty to include all categories.', 'metasync'); ?></p> |
| 254 |
</td> |
| 255 |
</tr> |
| 256 |
<tr> |
| 257 |
<th scope="row"> |
| 258 |
<?php esc_html_e('Tags', 'metasync'); ?> |
| 259 |
<?php $gen_tags = get_tags(['hide_empty' => false]); ?> |
| 260 |
<span class="metasync-checkbox-count">(<?php echo count($gen_tags); ?>)</span> |
| 261 |
</th> |
| 262 |
<td> |
| 263 |
<?php |
| 264 |
$selected_gen_tags = isset($sitemap_settings['tags']) ? (array) $sitemap_settings['tags'] : []; |
| 265 |
if (!empty($gen_tags)) : |
| 266 |
$gen_tags_scrollable = count($gen_tags) > 10; |
| 267 |
if ($gen_tags_scrollable) : ?> |
| 268 |
<input type="text" class="metasync-checkbox-search" placeholder="<?php esc_attr_e('Filter tags...', 'metasync'); ?>"> |
| 269 |
<?php endif; ?> |
| 270 |
<div class="metasync-checkbox-list <?php echo $gen_tags_scrollable ? 'metasync-checkbox-scroll' : ''; ?>"> |
| 271 |
<?php foreach ($gen_tags as $tag) : ?> |
| 272 |
<label> |
| 273 |
<input type="checkbox" name="sitemap_tags[]" value="<?php echo esc_attr($tag->term_id); ?>" |
| 274 |
<?php checked(in_array($tag->term_id, $selected_gen_tags)); ?> /> |
| 275 |
<?php echo esc_html($tag->name); ?> |
| 276 |
</label> |
| 277 |
<?php endforeach; ?> |
| 278 |
<p class="metasync-no-results"><?php esc_html_e('No tags match your search.', 'metasync'); ?></p> |
| 279 |
</div> |
| 280 |
<?php else : ?> |
| 281 |
<p class="description"><?php esc_html_e('No tags found.', 'metasync'); ?></p> |
| 282 |
<?php endif; ?> |
| 283 |
<p class="description"><?php esc_html_e('Leave empty to include all tags.', 'metasync'); ?></p> |
| 284 |
</td> |
| 285 |
</tr> |
| 286 |
<tr> |
| 287 |
<th scope="row"><?php esc_html_e('Taxonomies', 'metasync'); ?></th> |
| 288 |
<td> |
| 289 |
<?php |
| 290 |
$all_taxonomies = get_taxonomies(['public' => true], 'objects'); |
| 291 |
$selected_sitemap_taxes = !empty($sitemap_settings['taxonomies']) ? (array) $sitemap_settings['taxonomies'] : []; |
| 292 |
$gen_tax_scrollable = count($all_taxonomies) > 10; |
| 293 |
if ($gen_tax_scrollable) : ?> |
| 294 |
<input type="text" class="metasync-checkbox-search" placeholder="<?php esc_attr_e('Filter taxonomies...', 'metasync'); ?>"> |
| 295 |
<?php endif; ?> |
| 296 |
<div class="metasync-checkbox-list <?php echo $gen_tax_scrollable ? 'metasync-checkbox-scroll' : ''; ?>"> |
| 297 |
<?php foreach ($all_taxonomies as $tax) : ?> |
| 298 |
<label> |
| 299 |
<input type="checkbox" name="sitemap_taxonomies[]" value="<?php echo esc_attr($tax->name); ?>" |
| 300 |
<?php checked(!$sitemap_configured || in_array($tax->name, $selected_sitemap_taxes, true)); ?> /> |
| 301 |
<?php echo esc_html($tax->label); ?> <code><?php echo esc_html($tax->name); ?></code> |
| 302 |
</label> |
| 303 |
<?php endforeach; ?> |
| 304 |
<p class="metasync-no-results"><?php esc_html_e('No taxonomies match your search.', 'metasync'); ?></p> |
| 305 |
</div> |
| 306 |
<p class="description"><?php esc_html_e('Select which taxonomy archive pages to include. All are included by default.', 'metasync'); ?></p> |
| 307 |
</td> |
| 308 |
</tr> |
| 309 |
<tr> |
| 310 |
<th scope="row"><?php esc_html_e('Exclude URLs', 'metasync'); ?></th> |
| 311 |
<td> |
| 312 |
<textarea name="sitemap_excluded_urls" rows="5" class="large-text code" placeholder="<?php esc_attr_e("https://example.com/page-to-exclude/\nhttps://example.com/another-page/", 'metasync'); ?>"><?php echo esc_textarea($sitemap_settings['excluded_urls'] ?? ''); ?></textarea> |
| 313 |
<p class="description"><?php esc_html_e('Enter one URL per line. These URLs will be excluded from the main sitemap.', 'metasync'); ?></p> |
| 314 |
</td> |
| 315 |
</tr> |
| 316 |
</table> |
| 317 |
|
| 318 |
<?php submit_button(esc_html__('Save & Generate Sitemap', 'metasync'), 'primary', 'save_sitemap_settings'); ?> |
| 319 |
</form> |
| 320 |
</div> |
| 321 |
|
| 322 |
<!-- Generate Sitemap Card --> |
| 323 |
<div class="dashboard-card metasync-sitemap-actions-card"> |
| 324 |
<h2>Sitemap Actions</h2> |
| 325 |
<p style="color: var(--dashboard-text-secondary); margin-bottom: 20px;"> |
| 326 |
Generate or manage your XML sitemap with the controls below. |
| 327 |
</p> |
| 328 |
|
| 329 |
|
| 330 |
|
| 331 |
<div class="metasync-sitemap-actions-grid"> |
| 332 |
<form method="post" action="" class="metasync-sitemap-action-form"> |
| 333 |
<?php wp_nonce_field('metasync_sitemap_action', 'metasync_sitemap_nonce'); ?> |
| 334 |
<button type="submit" name="generate_sitemap" class="button button-primary button-hero metasync-sitemap-button-large"> |
| 335 |
<span class="dashicons dashicons-update"></span> |
| 336 |
Generate Sitemaps Now |
| 337 |
</button> |
| 338 |
<p class="metasync-button-description"> |
| 339 |
<?php |
| 340 |
$urls_per_sitemap = $sitemap_generator->get_urls_per_sitemap(); |
| 341 |
if (!empty($active_sitemap_plugins)): ?> |
| 342 |
Creates sitemap files (split into <?php echo number_format($urls_per_sitemap); ?> URLs each) and disables conflicting sitemaps. |
| 343 |
<?php else: ?> |
| 344 |
Creates sitemap index and individual sitemap files (split into <?php echo number_format($urls_per_sitemap); ?> URLs each). |
| 345 |
<?php endif; ?> |
| 346 |
</p> |
| 347 |
</form> |
| 348 |
|
| 349 |
<form method="post" action="" class="metasync-sitemap-action-form"> |
| 350 |
<?php wp_nonce_field('metasync_sitemap_action', 'metasync_sitemap_nonce'); ?> |
| 351 |
<?php if ($auto_update_enabled): ?> |
| 352 |
<button type="submit" name="disable_auto_update" class="button button-secondary button-hero metasync-sitemap-button-large"> |
| 353 |
<span class="dashicons dashicons-no"></span> |
| 354 |
Disable Auto-Update |
| 355 |
</button> |
| 356 |
<p class="metasync-button-description"> |
| 357 |
Currently enabled - sitemap updates automatically when posts change. |
| 358 |
</p> |
| 359 |
<?php else: ?> |
| 360 |
<button type="submit" name="enable_auto_update" class="button button-secondary button-hero metasync-sitemap-button-large"> |
| 361 |
<span class="dashicons dashicons-yes"></span> |
| 362 |
Enable Auto-Update |
| 363 |
</button> |
| 364 |
<p class="metasync-button-description"> |
| 365 |
Automatically regenerate sitemap when posts are created or updated. |
| 366 |
</p> |
| 367 |
<?php endif; ?> |
| 368 |
</form> |
| 369 |
|
| 370 |
<?php if ($any_sitemap_exists): ?> |
| 371 |
<form method="post" action="" class="metasync-sitemap-action-form" onsubmit="return confirm('Are you sure you want to delete all sitemap files? This action cannot be undone.');"> |
| 372 |
<?php wp_nonce_field('metasync_sitemap_action', 'metasync_sitemap_nonce'); ?> |
| 373 |
<button type="submit" name="delete_sitemap" class="button button-secondary button-hero metasync-sitemap-button-large" style="border-color: #dc3232; color: #dc3232;"> |
| 374 |
<span class="dashicons dashicons-trash"></span> |
| 375 |
Delete All Sitemaps |
| 376 |
</button> |
| 377 |
<p class="metasync-button-description"> |
| 378 |
Permanently delete all sitemap files from your server. |
| 379 |
</p> |
| 380 |
</form> |
| 381 |
<?php endif; ?> |
| 382 |
|
| 383 |
<?php if (!empty($active_sitemap_plugins)): ?> |
| 384 |
<form method="post" action="" class="metasync-sitemap-action-form"> |
| 385 |
<?php wp_nonce_field('metasync_sitemap_action', 'metasync_sitemap_nonce'); ?> |
| 386 |
<button type="submit" name="enable_other_sitemaps" class="button button-secondary button-hero metasync-sitemap-button-large" style="border-color: #00a32a; color: #00a32a;"> |
| 387 |
<span class="dashicons dashicons-controls-repeat"></span> |
| 388 |
Re-enable Other Sitemaps |
| 389 |
</button> |
| 390 |
<p class="metasync-button-description"> |
| 391 |
Re-enable sitemap generation from <?php echo esc_html(implode(', ', array_values($active_sitemap_plugins))); ?>. |
| 392 |
</p> |
| 393 |
</form> |
| 394 |
<?php endif; ?> |
| 395 |
|
| 396 |
<!-- Import from SEO Plugins Button (Always visible) --> |
| 397 |
<div > |
| 398 |
<a href="<?php echo esc_url(admin_url('admin.php?page=' . Metasync_Admin::$page_slug . '-import-external&tab=sitemap')); ?>" class="button button-secondary button-hero metasync-sitemap-button-large"> |
| 399 |
<span class="dashicons dashicons-download" style="margin-top:3px;font-size:15px;width:15px;height:15px;"></span> Import from SEO Plugins |
| 400 |
</a> |
| 401 |
<p class="metasync-button-description"> |
| 402 |
Import sitemap settings from other SEO plugins like Yoast, Rank Math, or AIOSEO. |
| 403 |
</p> |
| 404 |
</div> |
| 405 |
</div> |
| 406 |
|
| 407 |
</div> |
| 408 |
|
| 409 |
<?php if (($sitemap_exists && !empty($sitemap_files)) || $news_sm_exists || $video_sm_exists || $news_sm_enabled || $video_sm_enabled): ?> |
| 410 |
<!-- Sitemap Files List Card --> |
| 411 |
<div class="dashboard-card metasync-sitemap-files-card"> |
| 412 |
<h2>Sitemap Files</h2> |
| 413 |
<p style="color: var(--dashboard-text-secondary); margin-bottom: 20px;"> |
| 414 |
<?php if ($total_sitemap_count > 0): ?> |
| 415 |
Your sitemap has <?php echo $total_sitemap_count; ?> file<?php echo $total_sitemap_count > 1 ? 's' : ''; ?> — <?php echo $sitemap_count; ?> main (up to <?php echo number_format($sitemap_generator->get_urls_per_sitemap()); ?> URLs each)<?php |
| 416 |
if ($news_sm_exists || $video_sm_exists) { |
| 417 |
$extras = []; |
| 418 |
if ($news_sm_exists) $extras[] = 'news'; |
| 419 |
if ($video_sm_exists) $extras[] = 'video'; |
| 420 |
echo ', plus ' . implode(' & ', $extras); |
| 421 |
} |
| 422 |
?>. |
| 423 |
<?php else: ?> |
| 424 |
<?php esc_html_e('No sitemap files generated yet. Use "Generate Sitemaps Now" above to create them.', 'metasync'); ?> |
| 425 |
<?php endif; ?> |
| 426 |
</p> |
| 427 |
|
| 428 |
<table class="metasync-sitemap-table"> |
| 429 |
<thead> |
| 430 |
<tr> |
| 431 |
<th><?php esc_html_e('Sitemap File', 'metasync'); ?></th> |
| 432 |
<th><?php esc_html_e('URLs', 'metasync'); ?></th> |
| 433 |
<th><?php esc_html_e('Last Modified', 'metasync'); ?></th> |
| 434 |
<th><?php esc_html_e('Actions', 'metasync'); ?></th> |
| 435 |
</tr> |
| 436 |
</thead> |
| 437 |
<tbody> |
| 438 |
<?php if ($sitemap_exists && !empty($sitemap_files)): |
| 439 |
$urls_per_file = $sitemap_generator->get_urls_per_sitemap(); |
| 440 |
$total_urls = $url_count; |
| 441 |
foreach ($sitemap_files as $index => $sitemap_file): |
| 442 |
// Calculate URLs in this file |
| 443 |
$start_url = ($index * $urls_per_file) + 1; |
| 444 |
$end_url = min(($index + 1) * $urls_per_file, $total_urls); |
| 445 |
$urls_in_file = $end_url - $start_url + 1; |
| 446 |
?> |
| 447 |
<tr> |
| 448 |
<td> |
| 449 |
<div class="sitemap-filename"><?php echo esc_html($sitemap_file['filename']); ?></div> |
| 450 |
<div class="sitemap-url-range"> |
| 451 |
URLs <?php echo number_format($start_url); ?> - <?php echo number_format($end_url); ?> |
| 452 |
</div> |
| 453 |
</td> |
| 454 |
<td><?php echo number_format($urls_in_file); ?></td> |
| 455 |
<td> |
| 456 |
<?php |
| 457 |
if ($last_generated) { |
| 458 |
echo esc_html(date('M j, Y g:i A', strtotime($last_generated))); |
| 459 |
} else { |
| 460 |
echo '—'; |
| 461 |
} |
| 462 |
?> |
| 463 |
</td> |
| 464 |
<td> |
| 465 |
<a href="<?php echo esc_url($sitemap_file['url']); ?>" target="_blank" class="button-view"> |
| 466 |
<span class="dashicons dashicons-external"></span> |
| 467 |
View |
| 468 |
</a> |
| 469 |
<?php if ($index === 0): ?> |
| 470 |
<form method="post" action="" style="display:inline;" onsubmit="return confirm('Are you sure you want to delete the General sitemap? This action cannot be undone.');"> |
| 471 |
<?php wp_nonce_field('metasync_sitemap_action', 'metasync_sitemap_nonce'); ?> |
| 472 |
<button type="submit" name="delete_general_sitemap" class="button-delete"> |
| 473 |
<span class="dashicons dashicons-trash"></span> |
| 474 |
<?php esc_html_e('Delete', 'metasync'); ?> |
| 475 |
</button> |
| 476 |
</form> |
| 477 |
<?php endif; ?> |
| 478 |
</td> |
| 479 |
</tr> |
| 480 |
<?php endforeach; endif; ?> |
| 481 |
|
| 482 |
<?php if ($news_sm_enabled): ?> |
| 483 |
<tr> |
| 484 |
<td> |
| 485 |
<div class="sitemap-filename">news-sitemap.xml</div> |
| 486 |
<div class="sitemap-url-range"><?php esc_html_e('Google News Sitemap', 'metasync'); ?></div> |
| 487 |
</td> |
| 488 |
<td><?php echo $news_sm_exists ? $news_url_count : '<em style="color:var(--dashboard-text-secondary);">Not generated</em>'; ?></td> |
| 489 |
<td><?php echo ($news_sm_exists && $last_generated) ? esc_html(date('M j, Y g:i A', strtotime($last_generated))) : '—'; ?></td> |
| 490 |
<td> |
| 491 |
<?php if ($news_sm_exists): ?> |
| 492 |
<a href="<?php echo esc_url(home_url('/news-sitemap.xml')); ?>" target="_blank" class="button-view"> |
| 493 |
<span class="dashicons dashicons-external"></span> |
| 494 |
View |
| 495 |
</a> |
| 496 |
<form method="post" action="" style="display:inline;" onsubmit="return confirm('Are you sure you want to delete the News sitemap? This action cannot be undone.');"> |
| 497 |
<?php wp_nonce_field('metasync_sitemap_action', 'metasync_sitemap_nonce'); ?> |
| 498 |
<button type="submit" name="delete_news_sitemap" class="button-delete"> |
| 499 |
<span class="dashicons dashicons-trash"></span> |
| 500 |
<?php esc_html_e('Delete', 'metasync'); ?> |
| 501 |
</button> |
| 502 |
</form> |
| 503 |
<?php else: ?> |
| 504 |
<span style="color:var(--dashboard-text-secondary); font-style:italic;"><?php esc_html_e('Enabled — generate to create file', 'metasync'); ?></span> |
| 505 |
<?php endif; ?> |
| 506 |
</td> |
| 507 |
</tr> |
| 508 |
<?php endif; ?> |
| 509 |
|
| 510 |
<?php if ($video_sm_enabled): ?> |
| 511 |
<tr> |
| 512 |
<td> |
| 513 |
<div class="sitemap-filename">video-sitemap.xml</div> |
| 514 |
<div class="sitemap-url-range"><?php esc_html_e('Video Sitemap', 'metasync'); ?></div> |
| 515 |
</td> |
| 516 |
<td><?php echo $video_sm_exists ? $video_url_count : '<em style="color:var(--dashboard-text-secondary);">Not generated</em>'; ?></td> |
| 517 |
<td><?php echo ($video_sm_exists && $last_generated) ? esc_html(date('M j, Y g:i A', strtotime($last_generated))) : '—'; ?></td> |
| 518 |
<td> |
| 519 |
<?php if ($video_sm_exists): ?> |
| 520 |
<a href="<?php echo esc_url(home_url('/video-sitemap.xml')); ?>" target="_blank" class="button-view"> |
| 521 |
<span class="dashicons dashicons-external"></span> |
| 522 |
View |
| 523 |
</a> |
| 524 |
<form method="post" action="" style="display:inline;" onsubmit="return confirm('Are you sure you want to delete the Video sitemap? This action cannot be undone.');"> |
| 525 |
<?php wp_nonce_field('metasync_sitemap_action', 'metasync_sitemap_nonce'); ?> |
| 526 |
<button type="submit" name="delete_video_sitemap" class="button-delete"> |
| 527 |
<span class="dashicons dashicons-trash"></span> |
| 528 |
<?php esc_html_e('Delete', 'metasync'); ?> |
| 529 |
</button> |
| 530 |
</form> |
| 531 |
<?php else: ?> |
| 532 |
<span style="color:var(--dashboard-text-secondary); font-style:italic;"><?php esc_html_e('Enabled — generate to create file', 'metasync'); ?></span> |
| 533 |
<?php endif; ?> |
| 534 |
</td> |
| 535 |
</tr> |
| 536 |
<?php endif; ?> |
| 537 |
</tbody> |
| 538 |
</table> |
| 539 |
</div> |
| 540 |
|
| 541 |
<!-- Sitemap Index Preview Card --> |
| 542 |
<div class="dashboard-card metasync-sitemap-preview-card"> |
| 543 |
<h2>Sitemap Index Preview</h2> |
| 544 |
<p style="color: var(--dashboard-text-secondary); margin-bottom: 20px;"> |
| 545 |
Preview the sitemap index file that references all individual sitemaps. |
| 546 |
</p> |
| 547 |
|
| 548 |
<div class="metasync-sitemap-preview-container"> |
| 549 |
<div class="metasync-sitemap-preview-header"> |
| 550 |
<span class="metasync-preview-label">sitemap_index.xml</span> |
| 551 |
<a href="<?php echo esc_url($sitemap_url); ?>" target="_blank" class="button button-small"> |
| 552 |
<span class="dashicons dashicons-external"></span> |
| 553 |
View Sitemap Index |
| 554 |
</a> |
| 555 |
</div> |
| 556 |
<div class="metasync-sitemap-code-block"> |
| 557 |
<pre><?php |
| 558 |
$content = $sitemap_generator->get_sitemap_content(); |
| 559 |
if ($content) { |
| 560 |
$lines = explode("\n", $content); |
| 561 |
$preview_lines = array_slice($lines, 0, 50); |
| 562 |
echo esc_html(implode("\n", $preview_lines)); |
| 563 |
if (count($lines) > 50) { |
| 564 |
echo "\n... [" . (count($lines) - 50) . " more lines]"; |
| 565 |
} |
| 566 |
} else { |
| 567 |
echo "Unable to read sitemap index content."; |
| 568 |
} |
| 569 |
?></pre> |
| 570 |
</div> |
| 571 |
</div> |
| 572 |
</div> |
| 573 |
<?php endif; ?> |
| 574 |
|
| 575 |
</div> |
| 576 |
</div> |
| 577 |
</div><!-- /#metasync-sitemap-general --> |
| 578 |
|
| 579 |
<!-- News Sitemap Tab --> |
| 580 |
<div id="metasync-sitemap-news" class="metasync-sitemap-tab-content"> |
| 581 |
<div class="metasync-sitemap-outer"> |
| 582 |
<div class="metasync-sitemap-container"> |
| 583 |
|
| 584 |
<?php |
| 585 |
require_once plugin_dir_path(dirname(__FILE__)) . 'sitemap/class-metasync-sitemap-news.php'; |
| 586 |
$news_checker = new Metasync_Sitemap_News(); |
| 587 |
$news_conflicts = $news_checker->get_conflict_notices(); |
| 588 |
$news_has_content = false !== get_transient('metasync_vsm_' . md5('news-sitemap.xml')) |
| 589 |
|| file_exists(ABSPATH . 'news-sitemap.xml'); |
| 590 |
$news_conflict_name = $news_checker->get_conflict_plugin_name(); |
| 591 |
$mss_brand = Metasync::get_effective_plugin_name(); |
| 592 |
|
| 593 |
# Flag a generated-but-empty news sitemap. $news_url_count is already |
| 594 |
# computed once near the top of this file for the status card, so reuse it |
| 595 |
# rather than re-reading and re-scanning the XML on the same page load. |
| 596 |
$news_empty_warning = !empty($news_settings['enabled']) |
| 597 |
&& empty($news_conflicts) |
| 598 |
&& $news_has_content |
| 599 |
&& $news_url_count === 0; |
| 600 |
?> |
| 601 |
|
| 602 |
<?php if (!empty($news_conflict_name)): ?> |
| 603 |
<div class="metasync-sitemap-conflict-note" style="display:flex; gap:7px; align-items:center; margin:0 0 16px; padding:8px 12px; border-radius:7px; background:rgba(245,158,11,0.08); border:1px solid rgba(245,158,11,0.28); font-size:12px; line-height:1.5; color:var(--dashboard-text-secondary,#6b7280);"> |
| 604 |
<span style="font-size:13px; line-height:1;">⚠️</span> |
| 605 |
<span><strong style="color:#8a5a00;"><?php echo esc_html($news_conflict_name); ?></strong> <?php printf(esc_html__('is also active — its news sitemap settings may conflict with %s\'s.', 'metasync'), esc_html($mss_brand)); ?></span> |
| 606 |
</div> |
| 607 |
<?php endif; ?> |
| 608 |
|
| 609 |
<!-- News Sitemap Status --> |
| 610 |
<div class="dashboard-card" style="margin-bottom: 20px;"> |
| 611 |
<h2><?php esc_html_e('News Sitemap Status', 'metasync'); ?></h2> |
| 612 |
<div style="display: flex; gap: 24px; align-items: center; margin-top: 16px; flex-wrap: wrap;"> |
| 613 |
<div style="display: flex; align-items: center; gap: 10px;"> |
| 614 |
<span style="font-size: 20px;">📄</span> |
| 615 |
<div> |
| 616 |
<div style="color: var(--dashboard-text-secondary); font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em;"><?php esc_html_e('Status', 'metasync'); ?></div> |
| 617 |
<?php if (!empty($news_settings['enabled']) && $news_has_content && empty($news_conflicts)): ?> |
| 618 |
<div style="color: var(--dashboard-success, #10b981); font-weight: 600;"><?php esc_html_e('Generated', 'metasync'); ?></div> |
| 619 |
<?php elseif (!empty($news_settings['enabled']) && !$news_has_content && empty($news_conflicts)): ?> |
| 620 |
<div style="color: var(--dashboard-warning, #f59e0b); font-weight: 600;"><?php esc_html_e('Not Generated', 'metasync'); ?></div> |
| 621 |
<?php elseif (!empty($news_conflicts)): ?> |
| 622 |
<div style="color: var(--dashboard-error, #ef4444); font-weight: 600;"><?php esc_html_e('Conflict Detected', 'metasync'); ?></div> |
| 623 |
<?php else: ?> |
| 624 |
<div style="color: var(--dashboard-text-secondary); font-weight: 600;"><?php esc_html_e('Disabled', 'metasync'); ?></div> |
| 625 |
<?php endif; ?> |
| 626 |
</div> |
| 627 |
</div> |
| 628 |
<?php if (!empty($news_settings['enabled']) && $news_has_content && empty($news_conflicts)): ?> |
| 629 |
<div style="display: flex; align-items: center; gap: 10px;"> |
| 630 |
<span style="font-size: 20px;">🔗</span> |
| 631 |
<div> |
| 632 |
<div style="color: var(--dashboard-text-secondary); font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em;"><?php esc_html_e('URL', 'metasync'); ?></div> |
| 633 |
<a href="<?php echo esc_url(home_url('/news-sitemap.xml')); ?>" target="_blank" style="color: var(--dashboard-accent, #3b82f6); font-weight: 500; text-decoration: none;"> |
| 634 |
<?php echo esc_html(home_url('/news-sitemap.xml')); ?> |
| 635 |
<span class="dashicons dashicons-external" style="font-size: 14px; width: 14px; height: 14px; vertical-align: middle;"></span> |
| 636 |
</a> |
| 637 |
</div> |
| 638 |
</div> |
| 639 |
<?php endif; ?> |
| 640 |
</div> |
| 641 |
|
| 642 |
<?php if (!empty($news_settings['enabled']) && empty($news_conflicts)): ?> |
| 643 |
<div style="margin-top: 20px;"> |
| 644 |
<form method="post" style="display: inline;"> |
| 645 |
<?php wp_nonce_field('metasync_news_sitemap_action', 'metasync_news_sitemap_nonce'); ?> |
| 646 |
<button type="submit" name="generate_news_sitemap" class="button button-primary button-hero metasync-sitemap-button-large"> |
| 647 |
<span class="dashicons dashicons-update"></span> |
| 648 |
<?php $news_has_content ? esc_html_e('Regenerate News Sitemap', 'metasync') : esc_html_e('Generate News Sitemap Now', 'metasync'); ?> |
| 649 |
</button> |
| 650 |
</form> |
| 651 |
<p style="margin-top: 8px; color: var(--dashboard-text-secondary); font-size: 13px;"> |
| 652 |
<?php esc_html_e('Generates the news sitemap with articles from the last 2 days (max 1,000 URLs).', 'metasync'); ?> |
| 653 |
</p> |
| 654 |
</div> |
| 655 |
<?php endif; ?> |
| 656 |
</div> |
| 657 |
|
| 658 |
<?php foreach ($news_conflicts as $notice) { |
| 659 |
$notice_type = (strpos($notice, 'can coexist') !== false) ? 'notice-info' : 'notice-warning'; |
| 660 |
echo '<div class="notice ' . $notice_type . ' inline" style="margin-bottom: 12px; padding: 12px 16px; border-radius: 8px; background: rgba(255, 152, 0, 0.1); border-left: 4px solid var(--dashboard-warning, #f59e0b); color: var(--dashboard-text-primary, #fff);"><p style="margin: 0;">⚠ ' . esc_html($notice) . '</p></div>'; |
| 661 |
} ?> |
| 662 |
|
| 663 |
<?php if ($news_empty_warning): ?> |
| 664 |
<div class="notice notice-warning inline" style="margin-bottom: 12px; padding: 12px 40px 12px 16px; border-radius: 8px; background: rgba(255, 152, 0, 0.1); border-left: 4px solid var(--dashboard-warning, #f59e0b); color: var(--dashboard-text-primary, #fff);"> |
| 665 |
<p style="margin: 0;"> |
| 666 |
⚠ <?php esc_html_e('The last generated news sitemap contains 0 URLs. A news sitemap only includes posts published in the last 2 days, so this can be normal. If you expected entries here, regenerate it above and review the Post Types and filters below.', 'metasync'); ?> |
| 667 |
</p> |
| 668 |
</div> |
| 669 |
<?php endif; ?> |
| 670 |
|
| 671 |
<div class="dashboard-card"> |
| 672 |
<h2><?php esc_html_e('News Sitemap Settings', 'metasync'); ?></h2> |
| 673 |
<p style="color: var(--dashboard-text-secondary); margin-bottom: 20px;"> |
| 674 |
<?php esc_html_e('Configure the Google News Sitemap. Only articles published within the last 2 days will be included (max 1,000 URLs).', 'metasync'); ?> |
| 675 |
</p> |
| 676 |
|
| 677 |
<form method="post"> |
| 678 |
<?php wp_nonce_field('metasync_news_sitemap_action', 'metasync_news_sitemap_nonce'); ?> |
| 679 |
|
| 680 |
<table class="form-table"> |
| 681 |
<tr> |
| 682 |
<th scope="row"><?php esc_html_e('Enable News Sitemap', 'metasync'); ?><?php Metasync::render_tooltip_icon('news_sitemap_enable_info', 'A News sitemap is a special list of your recent news articles (published in the last 48 hours) that helps Google News find and show them quickly. Only turn this on if your site publishes news-style content and is accepted into Google News.'); ?></th> |
| 683 |
<td> |
| 684 |
<label> |
| 685 |
<input type="checkbox" name="news_enabled" value="1" <?php checked(!empty($news_settings['enabled'])); ?> /> |
| 686 |
<?php esc_html_e('Enable Google News Sitemap at /news-sitemap.xml', 'metasync'); ?> |
| 687 |
</label> |
| 688 |
</td> |
| 689 |
</tr> |
| 690 |
<tr> |
| 691 |
<th scope="row"><?php esc_html_e('Post Types', 'metasync'); ?><?php Metasync::render_tooltip_icon('news_sitemap_post_types', 'Choose which content types are included in your Google News sitemap. Only select types that qualify as news content — including everything can hurt News eligibility.'); ?></th> |
| 692 |
<td> |
| 693 |
<?php |
| 694 |
$public_post_types = get_post_types(['public' => true], 'objects'); |
| 695 |
$filtered_pts = []; |
| 696 |
foreach ($public_post_types as $pt) { |
| 697 |
if ($pt->name !== 'attachment') $filtered_pts[] = $pt; |
| 698 |
} |
| 699 |
$selected_post_types = isset($news_settings['post_types']) ? (array) $news_settings['post_types'] : ['post']; |
| 700 |
$pts_scrollable = count($filtered_pts) > 10; |
| 701 |
if ($pts_scrollable) : ?> |
| 702 |
<input type="text" class="metasync-checkbox-search" placeholder="<?php esc_attr_e('Filter post types...', 'metasync'); ?>"> |
| 703 |
<?php endif; ?> |
| 704 |
<div class="metasync-checkbox-list <?php echo $pts_scrollable ? 'metasync-checkbox-scroll' : ''; ?>"> |
| 705 |
<?php foreach ($filtered_pts as $pt) : ?> |
| 706 |
<label> |
| 707 |
<input type="checkbox" name="news_post_types[]" value="<?php echo esc_attr($pt->name); ?>" |
| 708 |
<?php checked(in_array($pt->name, $selected_post_types, true)); ?> /> |
| 709 |
<?php echo esc_html($pt->label); ?> |
| 710 |
</label> |
| 711 |
<?php endforeach; ?> |
| 712 |
<p class="metasync-no-results"><?php esc_html_e('No post types match your search.', 'metasync'); ?></p> |
| 713 |
</div> |
| 714 |
</td> |
| 715 |
</tr> |
| 716 |
<tr> |
| 717 |
<th scope="row"> |
| 718 |
<?php esc_html_e('Categories', 'metasync'); ?> |
| 719 |
<?php $categories = get_categories(['hide_empty' => false]); ?> |
| 720 |
<span class="metasync-checkbox-count">(<?php echo count($categories); ?>)</span> |
| 721 |
</th> |
| 722 |
<td> |
| 723 |
<?php |
| 724 |
$selected_cats = isset($news_settings['categories']) ? (array) $news_settings['categories'] : []; |
| 725 |
$cats_scrollable = count($categories) > 10; |
| 726 |
if ($cats_scrollable) : ?> |
| 727 |
<input type="text" class="metasync-checkbox-search" placeholder="<?php esc_attr_e('Filter categories...', 'metasync'); ?>"> |
| 728 |
<?php endif; ?> |
| 729 |
<div class="metasync-checkbox-list <?php echo $cats_scrollable ? 'metasync-checkbox-scroll' : ''; ?>"> |
| 730 |
<?php foreach ($categories as $cat) : ?> |
| 731 |
<label> |
| 732 |
<input type="checkbox" name="news_categories[]" value="<?php echo esc_attr($cat->term_id); ?>" |
| 733 |
<?php checked(in_array($cat->term_id, $selected_cats)); ?> /> |
| 734 |
<?php echo esc_html($cat->name); ?> |
| 735 |
</label> |
| 736 |
<?php endforeach; ?> |
| 737 |
<p class="metasync-no-results"><?php esc_html_e('No categories match your search.', 'metasync'); ?></p> |
| 738 |
</div> |
| 739 |
<p class="description"><?php esc_html_e('Leave empty to include all categories.', 'metasync'); ?></p> |
| 740 |
</td> |
| 741 |
</tr> |
| 742 |
<tr> |
| 743 |
<th scope="row"> |
| 744 |
<?php esc_html_e('Tags', 'metasync'); ?> |
| 745 |
<?php $tags = get_tags(['hide_empty' => false]); ?> |
| 746 |
<span class="metasync-checkbox-count">(<?php echo count($tags); ?>)</span> |
| 747 |
</th> |
| 748 |
<td> |
| 749 |
<?php |
| 750 |
$selected_tags = isset($news_settings['tags']) ? (array) $news_settings['tags'] : []; |
| 751 |
if (!empty($tags)) : |
| 752 |
$tags_scrollable = count($tags) > 10; |
| 753 |
if ($tags_scrollable) : ?> |
| 754 |
<input type="text" class="metasync-checkbox-search" placeholder="<?php esc_attr_e('Filter tags...', 'metasync'); ?>"> |
| 755 |
<?php endif; ?> |
| 756 |
<div class="metasync-checkbox-list <?php echo $tags_scrollable ? 'metasync-checkbox-scroll' : ''; ?>"> |
| 757 |
<?php foreach ($tags as $tag) : ?> |
| 758 |
<label> |
| 759 |
<input type="checkbox" name="news_tags[]" value="<?php echo esc_attr($tag->term_id); ?>" |
| 760 |
<?php checked(in_array($tag->term_id, $selected_tags)); ?> /> |
| 761 |
<?php echo esc_html($tag->name); ?> |
| 762 |
</label> |
| 763 |
<?php endforeach; ?> |
| 764 |
<p class="metasync-no-results"><?php esc_html_e('No tags match your search.', 'metasync'); ?></p> |
| 765 |
</div> |
| 766 |
<?php else : ?> |
| 767 |
<p class="description"><?php esc_html_e('No tags found.', 'metasync'); ?></p> |
| 768 |
<?php endif; ?> |
| 769 |
<p class="description"><?php esc_html_e('Leave empty to include all tags.', 'metasync'); ?></p> |
| 770 |
</td> |
| 771 |
</tr> |
| 772 |
<?php |
| 773 |
// Generic taxonomy filters for news sitemap |
| 774 |
$news_custom_taxonomies = get_taxonomies(['public' => true, '_builtin' => false], 'objects'); |
| 775 |
$news_saved_taxonomies = isset($news_settings['taxonomies']) ? (array) $news_settings['taxonomies'] : []; |
| 776 |
if (!empty($news_custom_taxonomies)) : |
| 777 |
foreach ($news_custom_taxonomies as $tax) : |
| 778 |
$tax_terms = get_terms(['taxonomy' => $tax->name, 'hide_empty' => false]); |
| 779 |
if (empty($tax_terms) || is_wp_error($tax_terms)) continue; |
| 780 |
$selected_term_ids = isset($news_saved_taxonomies[$tax->name]) ? (array) $news_saved_taxonomies[$tax->name] : []; |
| 781 |
?> |
| 782 |
<tr> |
| 783 |
<th scope="row"> |
| 784 |
<?php echo esc_html($tax->label); ?> |
| 785 |
<span class="metasync-checkbox-count">(<?php echo count($tax_terms); ?>)</span> |
| 786 |
</th> |
| 787 |
<td> |
| 788 |
<?php |
| 789 |
$tax_scrollable = count($tax_terms) > 10; |
| 790 |
if ($tax_scrollable) : ?> |
| 791 |
<input type="text" class="metasync-checkbox-search" placeholder="<?php echo esc_attr(sprintf(__('Filter %s...', 'metasync'), strtolower($tax->label))); ?>"> |
| 792 |
<?php endif; ?> |
| 793 |
<div class="metasync-checkbox-list <?php echo $tax_scrollable ? 'metasync-checkbox-scroll' : ''; ?>"> |
| 794 |
<?php foreach ($tax_terms as $term) : ?> |
| 795 |
<label> |
| 796 |
<input type="checkbox" name="news_taxonomies[<?php echo esc_attr($tax->name); ?>][]" value="<?php echo esc_attr($term->term_id); ?>" |
| 797 |
<?php checked(in_array($term->term_id, $selected_term_ids)); ?> /> |
| 798 |
<?php echo esc_html($term->name); ?> |
| 799 |
</label> |
| 800 |
<?php endforeach; ?> |
| 801 |
<p class="metasync-no-results"><?php esc_html_e('No items match your search.', 'metasync'); ?></p> |
| 802 |
</div> |
| 803 |
<p class="description"><?php esc_html_e('Leave empty to include all.', 'metasync'); ?></p> |
| 804 |
</td> |
| 805 |
</tr> |
| 806 |
<?php |
| 807 |
endforeach; |
| 808 |
endif; |
| 809 |
?> |
| 810 |
<tr> |
| 811 |
<th scope="row"><?php esc_html_e('Exclude URLs', 'metasync'); ?></th> |
| 812 |
<td> |
| 813 |
<textarea name="news_excluded_urls" rows="4" class="large-text code" placeholder="<?php esc_attr_e("https://example.com/post-to-exclude/\nhttps://example.com/another-post/", 'metasync'); ?>"><?php echo esc_textarea($news_settings['excluded_urls'] ?? ''); ?></textarea> |
| 814 |
<p class="description"><?php esc_html_e('Enter one URL per line. These URLs will be excluded from the news sitemap.', 'metasync'); ?></p> |
| 815 |
</td> |
| 816 |
</tr> |
| 817 |
<tr> |
| 818 |
<th scope="row"><?php esc_html_e('Publication Name', 'metasync'); ?></th> |
| 819 |
<td> |
| 820 |
<input type="text" name="publication_name" class="regular-text" |
| 821 |
value="<?php echo esc_attr(!empty($news_settings['publication_name']) ? $news_settings['publication_name'] : get_bloginfo('name')); ?>" /> |
| 822 |
<p class="description"><?php esc_html_e('Defaults to your site name.', 'metasync'); ?></p> |
| 823 |
</td> |
| 824 |
</tr> |
| 825 |
<tr> |
| 826 |
<th scope="row"><?php esc_html_e('Publication Language', 'metasync'); ?></th> |
| 827 |
<td> |
| 828 |
<input type="text" name="publication_language" class="small-text" |
| 829 |
value="<?php echo esc_attr(!empty($news_settings['publication_language']) ? $news_settings['publication_language'] : substr(get_locale(), 0, 2)); ?>" /> |
| 830 |
<p class="description"><?php esc_html_e('ISO 639 language code (e.g. en, fr, de). Defaults to site language.', 'metasync'); ?></p> |
| 831 |
</td> |
| 832 |
</tr> |
| 833 |
</table> |
| 834 |
|
| 835 |
<?php submit_button(esc_html__('Save & Generate Sitemap', 'metasync'), 'primary', 'save_news_sitemap'); ?> |
| 836 |
</form> |
| 837 |
</div> |
| 838 |
</div> |
| 839 |
</div> |
| 840 |
</div><!-- /#metasync-sitemap-news --> |
| 841 |
|
| 842 |
<!-- Video Sitemap Tab --> |
| 843 |
<div id="metasync-sitemap-video" class="metasync-sitemap-tab-content"> |
| 844 |
<div class="metasync-sitemap-outer"> |
| 845 |
<div class="metasync-sitemap-container"> |
| 846 |
|
| 847 |
<?php |
| 848 |
require_once plugin_dir_path(dirname(__FILE__)) . 'sitemap/class-metasync-sitemap-video.php'; |
| 849 |
$video_checker = new Metasync_Sitemap_Video(); |
| 850 |
$video_conflicts = $video_checker->get_conflict_notices(); |
| 851 |
$video_has_content = false !== get_transient('metasync_vsm_' . md5('video-sitemap.xml')) |
| 852 |
|| file_exists(ABSPATH . 'video-sitemap.xml'); |
| 853 |
$video_conflict_name = $video_checker->get_conflict_plugin_name(); |
| 854 |
$mss_brand = Metasync::get_effective_plugin_name(); |
| 855 |
|
| 856 |
# Flag a generated-but-empty video sitemap. $video_url_count is already |
| 857 |
# computed once near the top of this file for the status card, so reuse it |
| 858 |
# rather than re-reading and re-scanning the XML on the same page load. |
| 859 |
$video_empty_warning = !empty($video_settings['enabled']) |
| 860 |
&& empty($video_conflicts) |
| 861 |
&& $video_has_content |
| 862 |
&& $video_url_count === 0; |
| 863 |
?> |
| 864 |
|
| 865 |
<?php if (!empty($video_conflict_name)): ?> |
| 866 |
<div class="metasync-sitemap-conflict-note" style="display:flex; gap:7px; align-items:center; margin:0 0 16px; padding:8px 12px; border-radius:7px; background:rgba(245,158,11,0.08); border:1px solid rgba(245,158,11,0.28); font-size:12px; line-height:1.5; color:var(--dashboard-text-secondary,#6b7280);"> |
| 867 |
<span style="font-size:13px; line-height:1;">⚠️</span> |
| 868 |
<span><strong style="color:#8a5a00;"><?php echo esc_html($video_conflict_name); ?></strong> <?php printf(esc_html__('is also active — its video sitemap settings may conflict with %s\'s.', 'metasync'), esc_html($mss_brand)); ?></span> |
| 869 |
</div> |
| 870 |
<?php endif; ?> |
| 871 |
|
| 872 |
<!-- Video Sitemap Status --> |
| 873 |
<div class="dashboard-card" style="margin-bottom: 20px;"> |
| 874 |
<h2><?php esc_html_e('Video Sitemap Status', 'metasync'); ?></h2> |
| 875 |
<div style="display: flex; gap: 24px; align-items: center; margin-top: 16px; flex-wrap: wrap;"> |
| 876 |
<div style="display: flex; align-items: center; gap: 10px;"> |
| 877 |
<span style="font-size: 20px;">📄</span> |
| 878 |
<div> |
| 879 |
<div style="color: var(--dashboard-text-secondary); font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em;"><?php esc_html_e('Status', 'metasync'); ?></div> |
| 880 |
<?php if (!empty($video_settings['enabled']) && $video_has_content && empty($video_conflicts)): ?> |
| 881 |
<div style="color: var(--dashboard-success, #10b981); font-weight: 600;"><?php esc_html_e('Generated', 'metasync'); ?></div> |
| 882 |
<?php elseif (!empty($video_settings['enabled']) && !$video_has_content && empty($video_conflicts)): ?> |
| 883 |
<div style="color: var(--dashboard-warning, #f59e0b); font-weight: 600;"><?php esc_html_e('Not Generated', 'metasync'); ?></div> |
| 884 |
<?php elseif (!empty($video_conflicts)): ?> |
| 885 |
<div style="color: var(--dashboard-error, #ef4444); font-weight: 600;"><?php esc_html_e('Conflict Detected', 'metasync'); ?></div> |
| 886 |
<?php else: ?> |
| 887 |
<div style="color: var(--dashboard-text-secondary); font-weight: 600;"><?php esc_html_e('Disabled', 'metasync'); ?></div> |
| 888 |
<?php endif; ?> |
| 889 |
</div> |
| 890 |
</div> |
| 891 |
<?php if (!empty($video_settings['enabled']) && $video_has_content && empty($video_conflicts)): ?> |
| 892 |
<div style="display: flex; align-items: center; gap: 10px;"> |
| 893 |
<span style="font-size: 20px;">🔗</span> |
| 894 |
<div> |
| 895 |
<div style="color: var(--dashboard-text-secondary); font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em;"><?php esc_html_e('URL', 'metasync'); ?></div> |
| 896 |
<a href="<?php echo esc_url(home_url('/video-sitemap.xml')); ?>" target="_blank" style="color: var(--dashboard-accent, #3b82f6); font-weight: 500; text-decoration: none;"> |
| 897 |
<?php echo esc_html(home_url('/video-sitemap.xml')); ?> |
| 898 |
<span class="dashicons dashicons-external" style="font-size: 14px; width: 14px; height: 14px; vertical-align: middle;"></span> |
| 899 |
</a> |
| 900 |
</div> |
| 901 |
</div> |
| 902 |
<?php endif; ?> |
| 903 |
</div> |
| 904 |
|
| 905 |
<?php if (!empty($video_settings['enabled']) && empty($video_conflicts)): ?> |
| 906 |
<div style="margin-top: 20px;"> |
| 907 |
<form method="post" style="display: inline;"> |
| 908 |
<?php wp_nonce_field('metasync_video_sitemap_action', 'metasync_video_sitemap_nonce'); ?> |
| 909 |
<button type="submit" name="generate_video_sitemap" class="button button-primary button-hero metasync-sitemap-button-large"> |
| 910 |
<span class="dashicons dashicons-update"></span> |
| 911 |
<?php $video_has_content ? esc_html_e('Regenerate Video Sitemap', 'metasync') : esc_html_e('Generate Video Sitemap Now', 'metasync'); ?> |
| 912 |
</button> |
| 913 |
</form> |
| 914 |
<p style="margin-top: 8px; color: var(--dashboard-text-secondary); font-size: 13px;"> |
| 915 |
<?php esc_html_e('Scans all posts for embedded videos and generates the video sitemap.', 'metasync'); ?> |
| 916 |
</p> |
| 917 |
</div> |
| 918 |
<?php endif; ?> |
| 919 |
</div> |
| 920 |
|
| 921 |
<?php foreach ($video_conflicts as $notice) { |
| 922 |
$notice_type = (strpos($notice, 'can coexist') !== false) ? 'notice-info' : 'notice-warning'; |
| 923 |
echo '<div class="notice ' . $notice_type . ' inline" style="margin-bottom: 12px; padding: 12px 16px; border-radius: 8px; background: rgba(255, 152, 0, 0.1); border-left: 4px solid var(--dashboard-warning, #f59e0b); color: var(--dashboard-text-primary, #fff);"><p style="margin: 0;">⚠ ' . esc_html($notice) . '</p></div>'; |
| 924 |
} ?> |
| 925 |
|
| 926 |
<?php if ($video_empty_warning): ?> |
| 927 |
<div class="notice notice-warning inline" style="margin-bottom: 12px; padding: 12px 40px 12px 16px; border-radius: 8px; background: rgba(255, 152, 0, 0.1); border-left: 4px solid var(--dashboard-warning, #f59e0b); color: var(--dashboard-text-primary, #fff);"> |
| 928 |
<p style="margin: 0;"> |
| 929 |
⚠ <?php esc_html_e('The last generated video sitemap contains 0 URLs. A video sitemap only includes posts that contain an embedded video, so this can be normal. If you expected entries here, regenerate it above and review the Post Types and filters below.', 'metasync'); ?> |
| 930 |
</p> |
| 931 |
</div> |
| 932 |
<?php endif; ?> |
| 933 |
|
| 934 |
<div class="dashboard-card"> |
| 935 |
<h2><?php esc_html_e('Video Sitemap Settings', 'metasync'); ?></h2> |
| 936 |
<p style="color: var(--dashboard-text-secondary); margin-bottom: 20px;"> |
| 937 |
<?php esc_html_e('Configure the Video Sitemap. Auto-detects YouTube, Vimeo, VideoPress, and self-hosted videos in your content.', 'metasync'); ?> |
| 938 |
</p> |
| 939 |
|
| 940 |
<form method="post"> |
| 941 |
<?php wp_nonce_field('metasync_video_sitemap_action', 'metasync_video_sitemap_nonce'); ?> |
| 942 |
|
| 943 |
<table class="form-table"> |
| 944 |
<tr> |
| 945 |
<th scope="row"><?php esc_html_e('Enable Video Sitemap', 'metasync'); ?><?php Metasync::render_tooltip_icon('video_sitemap_enable_info', 'A Video sitemap lists the videos embedded on your pages (with their title, description, thumbnail, and duration) so search engines can understand them and show them in video search results. Turn this on if your pages contain videos you want discovered.'); ?></th> |
| 946 |
<td> |
| 947 |
<label> |
| 948 |
<input type="checkbox" name="video_enabled" value="1" <?php checked(!empty($video_settings['enabled'])); ?> /> |
| 949 |
<?php esc_html_e('Enable Video Sitemap at /video-sitemap.xml', 'metasync'); ?> |
| 950 |
</label> |
| 951 |
</td> |
| 952 |
</tr> |
| 953 |
<tr> |
| 954 |
<th scope="row"><?php esc_html_e('Post Types', 'metasync'); ?><?php Metasync::render_tooltip_icon('video_sitemap_post_types', 'Choose which content types are scanned for embedded videos to include in your video sitemap.'); ?></th> |
| 955 |
<td> |
| 956 |
<?php |
| 957 |
$public_post_types = get_post_types(['public' => true], 'objects'); |
| 958 |
$vid_filtered_pts = []; |
| 959 |
foreach ($public_post_types as $pt) { |
| 960 |
if ($pt->name !== 'attachment') $vid_filtered_pts[] = $pt; |
| 961 |
} |
| 962 |
$selected_video_pts = isset($video_settings['post_types']) ? (array) $video_settings['post_types'] : ['post', 'page']; |
| 963 |
$vid_pts_scrollable = count($vid_filtered_pts) > 10; |
| 964 |
if ($vid_pts_scrollable) : ?> |
| 965 |
<input type="text" class="metasync-checkbox-search" placeholder="<?php esc_attr_e('Filter post types...', 'metasync'); ?>"> |
| 966 |
<?php endif; ?> |
| 967 |
<div class="metasync-checkbox-list <?php echo $vid_pts_scrollable ? 'metasync-checkbox-scroll' : ''; ?>"> |
| 968 |
<?php foreach ($vid_filtered_pts as $pt) : ?> |
| 969 |
<label> |
| 970 |
<input type="checkbox" name="video_post_types[]" value="<?php echo esc_attr($pt->name); ?>" |
| 971 |
<?php checked(in_array($pt->name, $selected_video_pts, true)); ?> /> |
| 972 |
<?php echo esc_html($pt->label); ?> |
| 973 |
</label> |
| 974 |
<?php endforeach; ?> |
| 975 |
<p class="metasync-no-results"><?php esc_html_e('No post types match your search.', 'metasync'); ?></p> |
| 976 |
</div> |
| 977 |
</td> |
| 978 |
</tr> |
| 979 |
<tr> |
| 980 |
<th scope="row"><?php esc_html_e('Auto-Detect Videos', 'metasync'); ?></th> |
| 981 |
<td> |
| 982 |
<label> |
| 983 |
<input type="checkbox" name="auto_detect" value="1" <?php checked(!empty($video_settings['auto_detect'])); ?> /> |
| 984 |
<?php esc_html_e('Automatically detect embedded videos from post content', 'metasync'); ?> |
| 985 |
</label> |
| 986 |
<p class="description"><?php esc_html_e('Detects YouTube, Vimeo, VideoPress, and self-hosted <video> tags.', 'metasync'); ?></p> |
| 987 |
</td> |
| 988 |
</tr> |
| 989 |
<?php |
| 990 |
// Taxonomy filters for video sitemap |
| 991 |
$video_all_taxonomies = get_taxonomies(['public' => true], 'objects'); |
| 992 |
$video_saved_taxonomies = isset($video_settings['taxonomies']) ? (array) $video_settings['taxonomies'] : []; |
| 993 |
// Show categories, tags, and custom taxonomies |
| 994 |
foreach ($video_all_taxonomies as $tax) : |
| 995 |
$tax_terms = get_terms(['taxonomy' => $tax->name, 'hide_empty' => false]); |
| 996 |
if (empty($tax_terms) || is_wp_error($tax_terms)) continue; |
| 997 |
$selected_term_ids = isset($video_saved_taxonomies[$tax->name]) ? (array) $video_saved_taxonomies[$tax->name] : []; |
| 998 |
?> |
| 999 |
<tr> |
| 1000 |
<th scope="row"> |
| 1001 |
<?php echo esc_html($tax->label); ?> |
| 1002 |
<span class="metasync-checkbox-count">(<?php echo count($tax_terms); ?>)</span> |
| 1003 |
</th> |
| 1004 |
<td> |
| 1005 |
<?php |
| 1006 |
$vtax_scrollable = count($tax_terms) > 10; |
| 1007 |
if ($vtax_scrollable) : ?> |
| 1008 |
<input type="text" class="metasync-checkbox-search" placeholder="<?php echo esc_attr(sprintf(__('Filter %s...', 'metasync'), strtolower($tax->label))); ?>"> |
| 1009 |
<?php endif; ?> |
| 1010 |
<div class="metasync-checkbox-list <?php echo $vtax_scrollable ? 'metasync-checkbox-scroll' : ''; ?>"> |
| 1011 |
<?php foreach ($tax_terms as $term) : ?> |
| 1012 |
<label> |
| 1013 |
<input type="checkbox" name="video_taxonomies[<?php echo esc_attr($tax->name); ?>][]" value="<?php echo esc_attr($term->term_id); ?>" |
| 1014 |
<?php checked(in_array($term->term_id, $selected_term_ids)); ?> /> |
| 1015 |
<?php echo esc_html($term->name); ?> |
| 1016 |
</label> |
| 1017 |
<?php endforeach; ?> |
| 1018 |
<p class="metasync-no-results"><?php esc_html_e('No items match your search.', 'metasync'); ?></p> |
| 1019 |
</div> |
| 1020 |
<p class="description"><?php esc_html_e('Leave empty to include all.', 'metasync'); ?></p> |
| 1021 |
</td> |
| 1022 |
</tr> |
| 1023 |
<?php endforeach; ?> |
| 1024 |
<tr> |
| 1025 |
<th scope="row"><?php esc_html_e('Exclude URLs', 'metasync'); ?></th> |
| 1026 |
<td> |
| 1027 |
<textarea name="video_excluded_urls" rows="4" class="large-text code" placeholder="<?php esc_attr_e("https://example.com/post-to-exclude/\nhttps://example.com/another-post/", 'metasync'); ?>"><?php echo esc_textarea($video_settings['excluded_urls'] ?? ''); ?></textarea> |
| 1028 |
<p class="description"><?php esc_html_e('Enter one URL per line. These URLs will be excluded from the video sitemap.', 'metasync'); ?></p> |
| 1029 |
</td> |
| 1030 |
</tr> |
| 1031 |
</table> |
| 1032 |
|
| 1033 |
<?php submit_button(esc_html__('Save & Generate Sitemap', 'metasync'), 'primary', 'save_video_sitemap'); ?> |
| 1034 |
</form> |
| 1035 |
</div> |
| 1036 |
</div> |
| 1037 |
</div> |
| 1038 |
</div><!-- /#metasync-sitemap-video --> |
| 1039 |
|
| 1040 |
<?php $this->render_layout_close(); ?> |
| 1041 |
|