PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.6.13
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.6.13
2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 2.6.4 2.6.3 2.5.23 All 138 releases
metasync / views / metasync-xml-sitemap.php

metasync-xml-sitemap.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.6.13, at views/metasync-xml-sitemap.php

991 lines 62.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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(' &amp; ', $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 ?>
591
592 <!-- News Sitemap Status -->
593 <div class="dashboard-card" style="margin-bottom: 20px;">
594 <h2><?php esc_html_e('News Sitemap Status', 'metasync'); ?></h2>
595 <div style="display: flex; gap: 24px; align-items: center; margin-top: 16px; flex-wrap: wrap;">
596 <div style="display: flex; align-items: center; gap: 10px;">
597 <span style="font-size: 20px;">📄</span>
598 <div>
599 <div style="color: var(--dashboard-text-secondary); font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em;"><?php esc_html_e('Status', 'metasync'); ?></div>
600 <?php if (!empty($news_settings['enabled']) && $news_has_content && empty($news_conflicts)): ?>
601 <div style="color: var(--dashboard-success, #10b981); font-weight: 600;"><?php esc_html_e('Generated', 'metasync'); ?></div>
602 <?php elseif (!empty($news_settings['enabled']) && !$news_has_content && empty($news_conflicts)): ?>
603 <div style="color: var(--dashboard-warning, #f59e0b); font-weight: 600;"><?php esc_html_e('Not Generated', 'metasync'); ?></div>
604 <?php elseif (!empty($news_conflicts)): ?>
605 <div style="color: var(--dashboard-error, #ef4444); font-weight: 600;"><?php esc_html_e('Conflict Detected', 'metasync'); ?></div>
606 <?php else: ?>
607 <div style="color: var(--dashboard-text-secondary); font-weight: 600;"><?php esc_html_e('Disabled', 'metasync'); ?></div>
608 <?php endif; ?>
609 </div>
610 </div>
611 <?php if (!empty($news_settings['enabled']) && $news_has_content && empty($news_conflicts)): ?>
612 <div style="display: flex; align-items: center; gap: 10px;">
613 <span style="font-size: 20px;">🔗</span>
614 <div>
615 <div style="color: var(--dashboard-text-secondary); font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em;"><?php esc_html_e('URL', 'metasync'); ?></div>
616 <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;">
617 <?php echo esc_html(home_url('/news-sitemap.xml')); ?>
618 <span class="dashicons dashicons-external" style="font-size: 14px; width: 14px; height: 14px; vertical-align: middle;"></span>
619 </a>
620 </div>
621 </div>
622 <?php endif; ?>
623 </div>
624
625 <?php if (!empty($news_settings['enabled']) && empty($news_conflicts)): ?>
626 <div style="margin-top: 20px;">
627 <form method="post" style="display: inline;">
628 <?php wp_nonce_field('metasync_news_sitemap_action', 'metasync_news_sitemap_nonce'); ?>
629 <button type="submit" name="generate_news_sitemap" class="button button-primary button-hero metasync-sitemap-button-large">
630 <span class="dashicons dashicons-update"></span>
631 <?php $news_has_content ? esc_html_e('Regenerate News Sitemap', 'metasync') : esc_html_e('Generate News Sitemap Now', 'metasync'); ?>
632 </button>
633 </form>
634 <p style="margin-top: 8px; color: var(--dashboard-text-secondary); font-size: 13px;">
635 <?php esc_html_e('Generates the news sitemap with articles from the last 2 days (max 1,000 URLs).', 'metasync'); ?>
636 </p>
637 </div>
638 <?php endif; ?>
639 </div>
640
641 <?php foreach ($news_conflicts as $notice) {
642 $notice_type = (strpos($notice, 'can coexist') !== false) ? 'notice-info' : 'notice-warning';
643 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;">&#9888; ' . esc_html($notice) . '</p></div>';
644 } ?>
645
646 <div class="dashboard-card">
647 <h2><?php esc_html_e('News Sitemap Settings', 'metasync'); ?></h2>
648 <p style="color: var(--dashboard-text-secondary); margin-bottom: 20px;">
649 <?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'); ?>
650 </p>
651
652 <form method="post">
653 <?php wp_nonce_field('metasync_news_sitemap_action', 'metasync_news_sitemap_nonce'); ?>
654
655 <table class="form-table">
656 <tr>
657 <th scope="row"><?php esc_html_e('Enable News Sitemap', 'metasync'); ?></th>
658 <td>
659 <label>
660 <input type="checkbox" name="news_enabled" value="1" <?php checked(!empty($news_settings['enabled'])); ?> />
661 <?php esc_html_e('Enable Google News Sitemap at /news-sitemap.xml', 'metasync'); ?>
662 </label>
663 </td>
664 </tr>
665 <tr>
666 <th scope="row"><?php esc_html_e('Post Types', 'metasync'); ?></th>
667 <td>
668 <?php
669 $public_post_types = get_post_types(['public' => true], 'objects');
670 $filtered_pts = [];
671 foreach ($public_post_types as $pt) {
672 if ($pt->name !== 'attachment') $filtered_pts[] = $pt;
673 }
674 $selected_post_types = isset($news_settings['post_types']) ? (array) $news_settings['post_types'] : ['post'];
675 $pts_scrollable = count($filtered_pts) > 10;
676 if ($pts_scrollable) : ?>
677 <input type="text" class="metasync-checkbox-search" placeholder="<?php esc_attr_e('Filter post types...', 'metasync'); ?>">
678 <?php endif; ?>
679 <div class="metasync-checkbox-list <?php echo $pts_scrollable ? 'metasync-checkbox-scroll' : ''; ?>">
680 <?php foreach ($filtered_pts as $pt) : ?>
681 <label>
682 <input type="checkbox" name="news_post_types[]" value="<?php echo esc_attr($pt->name); ?>"
683 <?php checked(in_array($pt->name, $selected_post_types, true)); ?> />
684 <?php echo esc_html($pt->label); ?>
685 </label>
686 <?php endforeach; ?>
687 <p class="metasync-no-results"><?php esc_html_e('No post types match your search.', 'metasync'); ?></p>
688 </div>
689 </td>
690 </tr>
691 <tr>
692 <th scope="row">
693 <?php esc_html_e('Categories', 'metasync'); ?>
694 <?php $categories = get_categories(['hide_empty' => false]); ?>
695 <span class="metasync-checkbox-count">(<?php echo count($categories); ?>)</span>
696 </th>
697 <td>
698 <?php
699 $selected_cats = isset($news_settings['categories']) ? (array) $news_settings['categories'] : [];
700 $cats_scrollable = count($categories) > 10;
701 if ($cats_scrollable) : ?>
702 <input type="text" class="metasync-checkbox-search" placeholder="<?php esc_attr_e('Filter categories...', 'metasync'); ?>">
703 <?php endif; ?>
704 <div class="metasync-checkbox-list <?php echo $cats_scrollable ? 'metasync-checkbox-scroll' : ''; ?>">
705 <?php foreach ($categories as $cat) : ?>
706 <label>
707 <input type="checkbox" name="news_categories[]" value="<?php echo esc_attr($cat->term_id); ?>"
708 <?php checked(in_array($cat->term_id, $selected_cats)); ?> />
709 <?php echo esc_html($cat->name); ?>
710 </label>
711 <?php endforeach; ?>
712 <p class="metasync-no-results"><?php esc_html_e('No categories match your search.', 'metasync'); ?></p>
713 </div>
714 <p class="description"><?php esc_html_e('Leave empty to include all categories.', 'metasync'); ?></p>
715 </td>
716 </tr>
717 <tr>
718 <th scope="row">
719 <?php esc_html_e('Tags', 'metasync'); ?>
720 <?php $tags = get_tags(['hide_empty' => false]); ?>
721 <span class="metasync-checkbox-count">(<?php echo count($tags); ?>)</span>
722 </th>
723 <td>
724 <?php
725 $selected_tags = isset($news_settings['tags']) ? (array) $news_settings['tags'] : [];
726 if (!empty($tags)) :
727 $tags_scrollable = count($tags) > 10;
728 if ($tags_scrollable) : ?>
729 <input type="text" class="metasync-checkbox-search" placeholder="<?php esc_attr_e('Filter tags...', 'metasync'); ?>">
730 <?php endif; ?>
731 <div class="metasync-checkbox-list <?php echo $tags_scrollable ? 'metasync-checkbox-scroll' : ''; ?>">
732 <?php foreach ($tags as $tag) : ?>
733 <label>
734 <input type="checkbox" name="news_tags[]" value="<?php echo esc_attr($tag->term_id); ?>"
735 <?php checked(in_array($tag->term_id, $selected_tags)); ?> />
736 <?php echo esc_html($tag->name); ?>
737 </label>
738 <?php endforeach; ?>
739 <p class="metasync-no-results"><?php esc_html_e('No tags match your search.', 'metasync'); ?></p>
740 </div>
741 <?php else : ?>
742 <p class="description"><?php esc_html_e('No tags found.', 'metasync'); ?></p>
743 <?php endif; ?>
744 <p class="description"><?php esc_html_e('Leave empty to include all tags.', 'metasync'); ?></p>
745 </td>
746 </tr>
747 <?php
748 // Generic taxonomy filters for news sitemap
749 $news_custom_taxonomies = get_taxonomies(['public' => true, '_builtin' => false], 'objects');
750 $news_saved_taxonomies = isset($news_settings['taxonomies']) ? (array) $news_settings['taxonomies'] : [];
751 if (!empty($news_custom_taxonomies)) :
752 foreach ($news_custom_taxonomies as $tax) :
753 $tax_terms = get_terms(['taxonomy' => $tax->name, 'hide_empty' => false]);
754 if (empty($tax_terms) || is_wp_error($tax_terms)) continue;
755 $selected_term_ids = isset($news_saved_taxonomies[$tax->name]) ? (array) $news_saved_taxonomies[$tax->name] : [];
756 ?>
757 <tr>
758 <th scope="row">
759 <?php echo esc_html($tax->label); ?>
760 <span class="metasync-checkbox-count">(<?php echo count($tax_terms); ?>)</span>
761 </th>
762 <td>
763 <?php
764 $tax_scrollable = count($tax_terms) > 10;
765 if ($tax_scrollable) : ?>
766 <input type="text" class="metasync-checkbox-search" placeholder="<?php echo esc_attr(sprintf(__('Filter %s...', 'metasync'), strtolower($tax->label))); ?>">
767 <?php endif; ?>
768 <div class="metasync-checkbox-list <?php echo $tax_scrollable ? 'metasync-checkbox-scroll' : ''; ?>">
769 <?php foreach ($tax_terms as $term) : ?>
770 <label>
771 <input type="checkbox" name="news_taxonomies[<?php echo esc_attr($tax->name); ?>][]" value="<?php echo esc_attr($term->term_id); ?>"
772 <?php checked(in_array($term->term_id, $selected_term_ids)); ?> />
773 <?php echo esc_html($term->name); ?>
774 </label>
775 <?php endforeach; ?>
776 <p class="metasync-no-results"><?php esc_html_e('No items match your search.', 'metasync'); ?></p>
777 </div>
778 <p class="description"><?php esc_html_e('Leave empty to include all.', 'metasync'); ?></p>
779 </td>
780 </tr>
781 <?php
782 endforeach;
783 endif;
784 ?>
785 <tr>
786 <th scope="row"><?php esc_html_e('Exclude URLs', 'metasync'); ?></th>
787 <td>
788 <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>
789 <p class="description"><?php esc_html_e('Enter one URL per line. These URLs will be excluded from the news sitemap.', 'metasync'); ?></p>
790 </td>
791 </tr>
792 <tr>
793 <th scope="row"><?php esc_html_e('Publication Name', 'metasync'); ?></th>
794 <td>
795 <input type="text" name="publication_name" class="regular-text"
796 value="<?php echo esc_attr(!empty($news_settings['publication_name']) ? $news_settings['publication_name'] : get_bloginfo('name')); ?>" />
797 <p class="description"><?php esc_html_e('Defaults to your site name.', 'metasync'); ?></p>
798 </td>
799 </tr>
800 <tr>
801 <th scope="row"><?php esc_html_e('Publication Language', 'metasync'); ?></th>
802 <td>
803 <input type="text" name="publication_language" class="small-text"
804 value="<?php echo esc_attr(!empty($news_settings['publication_language']) ? $news_settings['publication_language'] : substr(get_locale(), 0, 2)); ?>" />
805 <p class="description"><?php esc_html_e('ISO 639 language code (e.g. en, fr, de). Defaults to site language.', 'metasync'); ?></p>
806 </td>
807 </tr>
808 </table>
809
810 <?php submit_button(esc_html__('Save & Generate Sitemap', 'metasync'), 'primary', 'save_news_sitemap'); ?>
811 </form>
812 </div>
813 </div>
814 </div>
815 </div><!-- /#metasync-sitemap-news -->
816
817 <!-- Video Sitemap Tab -->
818 <div id="metasync-sitemap-video" class="metasync-sitemap-tab-content">
819 <div class="metasync-sitemap-outer">
820 <div class="metasync-sitemap-container">
821
822 <?php
823 require_once plugin_dir_path(dirname(__FILE__)) . 'sitemap/class-metasync-sitemap-video.php';
824 $video_checker = new Metasync_Sitemap_Video();
825 $video_conflicts = $video_checker->get_conflict_notices();
826 $video_has_content = false !== get_transient('metasync_vsm_' . md5('video-sitemap.xml'))
827 || file_exists(ABSPATH . 'video-sitemap.xml');
828 ?>
829
830 <!-- Video Sitemap Status -->
831 <div class="dashboard-card" style="margin-bottom: 20px;">
832 <h2><?php esc_html_e('Video Sitemap Status', 'metasync'); ?></h2>
833 <div style="display: flex; gap: 24px; align-items: center; margin-top: 16px; flex-wrap: wrap;">
834 <div style="display: flex; align-items: center; gap: 10px;">
835 <span style="font-size: 20px;">📄</span>
836 <div>
837 <div style="color: var(--dashboard-text-secondary); font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em;"><?php esc_html_e('Status', 'metasync'); ?></div>
838 <?php if (!empty($video_settings['enabled']) && $video_has_content && empty($video_conflicts)): ?>
839 <div style="color: var(--dashboard-success, #10b981); font-weight: 600;"><?php esc_html_e('Generated', 'metasync'); ?></div>
840 <?php elseif (!empty($video_settings['enabled']) && !$video_has_content && empty($video_conflicts)): ?>
841 <div style="color: var(--dashboard-warning, #f59e0b); font-weight: 600;"><?php esc_html_e('Not Generated', 'metasync'); ?></div>
842 <?php elseif (!empty($video_conflicts)): ?>
843 <div style="color: var(--dashboard-error, #ef4444); font-weight: 600;"><?php esc_html_e('Conflict Detected', 'metasync'); ?></div>
844 <?php else: ?>
845 <div style="color: var(--dashboard-text-secondary); font-weight: 600;"><?php esc_html_e('Disabled', 'metasync'); ?></div>
846 <?php endif; ?>
847 </div>
848 </div>
849 <?php if (!empty($video_settings['enabled']) && $video_has_content && empty($video_conflicts)): ?>
850 <div style="display: flex; align-items: center; gap: 10px;">
851 <span style="font-size: 20px;">🔗</span>
852 <div>
853 <div style="color: var(--dashboard-text-secondary); font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em;"><?php esc_html_e('URL', 'metasync'); ?></div>
854 <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;">
855 <?php echo esc_html(home_url('/video-sitemap.xml')); ?>
856 <span class="dashicons dashicons-external" style="font-size: 14px; width: 14px; height: 14px; vertical-align: middle;"></span>
857 </a>
858 </div>
859 </div>
860 <?php endif; ?>
861 </div>
862
863 <?php if (!empty($video_settings['enabled']) && empty($video_conflicts)): ?>
864 <div style="margin-top: 20px;">
865 <form method="post" style="display: inline;">
866 <?php wp_nonce_field('metasync_video_sitemap_action', 'metasync_video_sitemap_nonce'); ?>
867 <button type="submit" name="generate_video_sitemap" class="button button-primary button-hero metasync-sitemap-button-large">
868 <span class="dashicons dashicons-update"></span>
869 <?php $video_has_content ? esc_html_e('Regenerate Video Sitemap', 'metasync') : esc_html_e('Generate Video Sitemap Now', 'metasync'); ?>
870 </button>
871 </form>
872 <p style="margin-top: 8px; color: var(--dashboard-text-secondary); font-size: 13px;">
873 <?php esc_html_e('Scans all posts for embedded videos and generates the video sitemap.', 'metasync'); ?>
874 </p>
875 </div>
876 <?php endif; ?>
877 </div>
878
879 <?php foreach ($video_conflicts as $notice) {
880 $notice_type = (strpos($notice, 'can coexist') !== false) ? 'notice-info' : 'notice-warning';
881 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;">&#9888; ' . esc_html($notice) . '</p></div>';
882 } ?>
883
884 <div class="dashboard-card">
885 <h2><?php esc_html_e('Video Sitemap Settings', 'metasync'); ?></h2>
886 <p style="color: var(--dashboard-text-secondary); margin-bottom: 20px;">
887 <?php esc_html_e('Configure the Video Sitemap. Auto-detects YouTube, Vimeo, VideoPress, and self-hosted videos in your content.', 'metasync'); ?>
888 </p>
889
890 <form method="post">
891 <?php wp_nonce_field('metasync_video_sitemap_action', 'metasync_video_sitemap_nonce'); ?>
892
893 <table class="form-table">
894 <tr>
895 <th scope="row"><?php esc_html_e('Enable Video Sitemap', 'metasync'); ?></th>
896 <td>
897 <label>
898 <input type="checkbox" name="video_enabled" value="1" <?php checked(!empty($video_settings['enabled'])); ?> />
899 <?php esc_html_e('Enable Video Sitemap at /video-sitemap.xml', 'metasync'); ?>
900 </label>
901 </td>
902 </tr>
903 <tr>
904 <th scope="row"><?php esc_html_e('Post Types', 'metasync'); ?></th>
905 <td>
906 <?php
907 $public_post_types = get_post_types(['public' => true], 'objects');
908 $vid_filtered_pts = [];
909 foreach ($public_post_types as $pt) {
910 if ($pt->name !== 'attachment') $vid_filtered_pts[] = $pt;
911 }
912 $selected_video_pts = isset($video_settings['post_types']) ? (array) $video_settings['post_types'] : ['post', 'page'];
913 $vid_pts_scrollable = count($vid_filtered_pts) > 10;
914 if ($vid_pts_scrollable) : ?>
915 <input type="text" class="metasync-checkbox-search" placeholder="<?php esc_attr_e('Filter post types...', 'metasync'); ?>">
916 <?php endif; ?>
917 <div class="metasync-checkbox-list <?php echo $vid_pts_scrollable ? 'metasync-checkbox-scroll' : ''; ?>">
918 <?php foreach ($vid_filtered_pts as $pt) : ?>
919 <label>
920 <input type="checkbox" name="video_post_types[]" value="<?php echo esc_attr($pt->name); ?>"
921 <?php checked(in_array($pt->name, $selected_video_pts, true)); ?> />
922 <?php echo esc_html($pt->label); ?>
923 </label>
924 <?php endforeach; ?>
925 <p class="metasync-no-results"><?php esc_html_e('No post types match your search.', 'metasync'); ?></p>
926 </div>
927 </td>
928 </tr>
929 <tr>
930 <th scope="row"><?php esc_html_e('Auto-Detect Videos', 'metasync'); ?></th>
931 <td>
932 <label>
933 <input type="checkbox" name="auto_detect" value="1" <?php checked(!empty($video_settings['auto_detect'])); ?> />
934 <?php esc_html_e('Automatically detect embedded videos from post content', 'metasync'); ?>
935 </label>
936 <p class="description"><?php esc_html_e('Detects YouTube, Vimeo, VideoPress, and self-hosted &lt;video&gt; tags.', 'metasync'); ?></p>
937 </td>
938 </tr>
939 <?php
940 // Taxonomy filters for video sitemap
941 $video_all_taxonomies = get_taxonomies(['public' => true], 'objects');
942 $video_saved_taxonomies = isset($video_settings['taxonomies']) ? (array) $video_settings['taxonomies'] : [];
943 // Show categories, tags, and custom taxonomies
944 foreach ($video_all_taxonomies as $tax) :
945 $tax_terms = get_terms(['taxonomy' => $tax->name, 'hide_empty' => false]);
946 if (empty($tax_terms) || is_wp_error($tax_terms)) continue;
947 $selected_term_ids = isset($video_saved_taxonomies[$tax->name]) ? (array) $video_saved_taxonomies[$tax->name] : [];
948 ?>
949 <tr>
950 <th scope="row">
951 <?php echo esc_html($tax->label); ?>
952 <span class="metasync-checkbox-count">(<?php echo count($tax_terms); ?>)</span>
953 </th>
954 <td>
955 <?php
956 $vtax_scrollable = count($tax_terms) > 10;
957 if ($vtax_scrollable) : ?>
958 <input type="text" class="metasync-checkbox-search" placeholder="<?php echo esc_attr(sprintf(__('Filter %s...', 'metasync'), strtolower($tax->label))); ?>">
959 <?php endif; ?>
960 <div class="metasync-checkbox-list <?php echo $vtax_scrollable ? 'metasync-checkbox-scroll' : ''; ?>">
961 <?php foreach ($tax_terms as $term) : ?>
962 <label>
963 <input type="checkbox" name="video_taxonomies[<?php echo esc_attr($tax->name); ?>][]" value="<?php echo esc_attr($term->term_id); ?>"
964 <?php checked(in_array($term->term_id, $selected_term_ids)); ?> />
965 <?php echo esc_html($term->name); ?>
966 </label>
967 <?php endforeach; ?>
968 <p class="metasync-no-results"><?php esc_html_e('No items match your search.', 'metasync'); ?></p>
969 </div>
970 <p class="description"><?php esc_html_e('Leave empty to include all.', 'metasync'); ?></p>
971 </td>
972 </tr>
973 <?php endforeach; ?>
974 <tr>
975 <th scope="row"><?php esc_html_e('Exclude URLs', 'metasync'); ?></th>
976 <td>
977 <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>
978 <p class="description"><?php esc_html_e('Enter one URL per line. These URLs will be excluded from the video sitemap.', 'metasync'); ?></p>
979 </td>
980 </tr>
981 </table>
982
983 <?php submit_button(esc_html__('Save & Generate Sitemap', 'metasync'), 'primary', 'save_video_sitemap'); ?>
984 </form>
985 </div>
986 </div>
987 </div>
988 </div><!-- /#metasync-sitemap-video -->
989
990 <?php $this->render_layout_close(); ?>
991