PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.6.23
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.6.23
2.7.1 2.7.2 2.7.0 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 All 141 releases
metasync / robots-txt / views / scripts.php

scripts.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.6.23, at robots-txt/views/scripts.php

549 lines 22.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Robots.txt Admin Page Scripts
4 *
5 * @package Search Atlas SEO
6 * @copyright Copyright (C) 2021-2025, Search Atlas Group - [email protected]
7 * @since 2.5.6
8 */
9
10 // If this file is called directly, abort.
11 if (!defined('WPINC')) {
12 die;
13 }
14 ?>
15 <script>
16 jQuery(document).ready(function($) {
17 let allowSave = false;
18
19 // Nonce for fetching a paginated page of backups.
20 const backupsPageNonce = '<?php echo esc_js(wp_create_nonce('metasync_get_robots_backups')); ?>';
21
22 // Load a page of the Backup History panel and swap it in place. Keeps the
23 // list, its total count, and pagination consistent with backend storage
24 // after navigation or deletion. Clamps to a valid page if the requested
25 // one no longer exists (e.g. the last item on a page was deleted).
26 function loadBackupsPage(page) {
27 const $panel = $('#metasync-backups-panel');
28 if (!$panel.length) {
29 return;
30 }
31 $panel.css('opacity', 0.5);
32 $.ajax({
33 url: ajaxurl,
34 type: 'POST',
35 data: {
36 action: 'metasync_get_robots_backups',
37 nonce: backupsPageNonce,
38 page: page
39 },
40 success: function(response) {
41 if (response.success && response.data && typeof response.data.html === 'string') {
42 $panel.replaceWith(response.data.html);
43 } else {
44 $panel.css('opacity', 1);
45 }
46 },
47 error: function() {
48 $panel.css('opacity', 1);
49 }
50 });
51 }
52
53 // Pagination controls (Prev/Next).
54 $(document).on('click', '.metasync-backup-page', function() {
55 const $btn = $(this);
56 if ($btn.prop('disabled')) {
57 return;
58 }
59 const page = parseInt($btn.data('page'), 10);
60 if (!isNaN(page) && page >= 1) {
61 loadBackupsPage(page);
62 }
63 });
64
65 // Check for restore success message after page reload
66 const restoreMessage = sessionStorage.getItem('metasync_robots_restore_message');
67 if (restoreMessage) {
68 // Remove the message from sessionStorage
69 sessionStorage.removeItem('metasync_robots_restore_message');
70
71 // Display the success message
72 const $notice = $('<div class="notice notice-success is-dismissible" style="margin: 20px 0;"><p>' + restoreMessage + '</p></div>');
73 $('.metasync-robots-txt-page').prepend($notice);
74
75 // Scroll to top to show the message
76 $('html, body').animate({ scrollTop: 0 }, 300);
77
78 // Auto-dismiss after 5 seconds
79 setTimeout(function() {
80 $notice.fadeOut(300, function() {
81 $(this).remove();
82 });
83 }, 5000);
84 }
85
86 // Modal functions
87 function showModal(type, title, message, showConfirm) {
88 const $modal = $('#robots-validation-modal');
89 const $header = $modal.find('.metasync-modal-header');
90 const $confirmBtn = $('#modal-confirm-btn');
91
92 // Set header style
93 $header.removeClass('error warning success').addClass(type);
94
95 // Set icon
96 let icon = '';
97 if (type === 'error') {
98 icon = '<div class="metasync-modal-icon error"><span class="dashicons dashicons-dismiss"></span></div>';
99 } else if (type === 'warning') {
100 icon = '<div class="metasync-modal-icon warning"><span class="dashicons dashicons-warning"></span></div>';
101 } else {
102 icon = '<div class="metasync-modal-icon success"><span class="dashicons dashicons-yes-alt"></span></div>';
103 }
104
105 // Set content
106 $('#modal-title').html(title);
107 $('#modal-body').html(icon + '<div class="metasync-modal-message">' + message + '</div>');
108
109 // Show/hide confirm button
110 if (showConfirm) {
111 $confirmBtn.show();
112 } else {
113 $confirmBtn.hide();
114 }
115
116 // Show modal
117 $modal.fadeIn(200);
118 }
119
120 function closeModal() {
121 const $modal = $('#robots-validation-modal');
122 const $modalContent = $modal.find('.metasync-modal-content');
123 const $confirmBtn = $('#modal-confirm-btn');
124 const $cancelBtn = $('.metasync-modal-cancel');
125
126 // Remove preview class when closing
127 $modalContent.removeClass('preview');
128
129 // Reset confirm button to original state
130 $confirmBtn.removeClass('button-restore')
131 .addClass('button-primary')
132 .text('<?php esc_html_e('Save Anyway', 'metasync'); ?>')
133 .removeData('backup-id')
134 .removeData('nonce');
135
136 // Reset cancel button
137 $cancelBtn.text('<?php esc_html_e('Cancel', 'metasync'); ?>');
138
139 $modal.fadeOut(200);
140 }
141
142 // Close modal on overlay or close button click
143 $('.metasync-modal-overlay, .metasync-modal-close, .metasync-modal-cancel').on('click', function() {
144 closeModal();
145 });
146
147 // Prevent closing when clicking modal content
148 $('.metasync-modal-content').on('click', function(e) {
149 e.stopPropagation();
150 });
151
152 // Form submission with validation
153 $('#robots-txt-form').on('submit', function(e) {
154 if (allowSave) {
155 allowSave = false;
156 return true; // Allow form submission
157 }
158
159 e.preventDefault();
160
161 const content = $('#robots-txt-editor').val();
162
163 // Validate via AJAX
164 $.ajax({
165 url: ajaxurl,
166 type: 'POST',
167 data: {
168 action: 'metasync_validate_robots',
169 nonce: '<?php echo wp_create_nonce('metasync_nonce'); ?>',
170 content: content
171 },
172 success: function(response) {
173 if (response.success && response.data) {
174 // Check for errors
175 if (response.data.errors && response.data.errors.length > 0) {
176 let errorHtml = '<div><strong><?php esc_html_e('The following errors must be fixed before saving:', 'metasync'); ?></strong><ul style="margin: 16px 0 0 20px; text-align: left;">';
177 response.data.errors.forEach(function(error) {
178 errorHtml += '<li>' + error + '</li>';
179 });
180 errorHtml += '</ul></div>';
181
182 showModal('error', '<?php esc_html_e('Syntax Errors Found', 'metasync'); ?>', errorHtml, false);
183 return;
184 }
185
186 // Check for warnings
187 if (response.data.warnings && response.data.warnings.length > 0) {
188 let warningHtml = '<div><strong><?php esc_html_e('The following warnings were detected:', 'metasync'); ?></strong><ul style="margin: 16px 0 0 20px; text-align: left;">';
189 response.data.warnings.forEach(function(warning) {
190 warningHtml += '<li>' + warning + '</li>';
191 });
192 warningHtml += '</ul><p style="margin-top: 16px;"><strong><?php esc_html_e('Do you want to save anyway?', 'metasync'); ?></strong></p></div>';
193
194 showModal('warning', '<?php esc_html_e('Validation Warnings', 'metasync'); ?>', warningHtml, true);
195 return;
196 }
197
198 // No errors or warnings, submit form
199 allowSave = true;
200 $('#robots-txt-form').submit();
201 }
202 }
203 });
204 });
205
206 // Confirm button handler (for warnings and restore from preview)
207 $('#modal-confirm-btn').on('click', function() {
208 const $btn = $(this);
209
210 // Check if this is a restore action from preview
211 if ($btn.hasClass('button-restore')) {
212 const backupId = $btn.data('backup-id');
213 const nonce = $btn.data('nonce');
214
215 if (!backupId) {
216 alert('<?php esc_html_e('Invalid backup ID', 'metasync'); ?>');
217 return;
218 }
219
220 if (!confirm('<?php esc_html_e('Are you sure you want to restore this backup? Current content will be backed up automatically.', 'metasync'); ?>')) {
221 return;
222 }
223
224 // Show loading state
225 const originalText = $btn.text();
226 $btn.prop('disabled', true).html('<span class="dashicons dashicons-update dashicons-spin"></span> <?php esc_html_e('Restoring...', 'metasync'); ?>');
227
228 // Close the modal
229 closeModal();
230
231 // Perform restore via AJAX
232 $.ajax({
233 url: ajaxurl,
234 type: 'POST',
235 data: {
236 action: 'metasync_restore_robots_backup',
237 backup_id: backupId,
238 nonce: nonce
239 },
240 success: function(response) {
241 if (response.success) {
242 // Store success message in sessionStorage
243 if (response.data && response.data.message) {
244 sessionStorage.setItem('metasync_robots_restore_message', response.data.message);
245 }
246
247 // Reload the page
248 window.location.reload();
249 } else {
250 // Show error message
251 const errorMessage = response.data && response.data.message ? response.data.message : '<?php esc_html_e('Failed to restore backup.', 'metasync'); ?>';
252 alert(errorMessage);
253
254 // Restore button
255 $btn.prop('disabled', false).text(originalText);
256 }
257 },
258 error: function() {
259 alert('<?php esc_html_e('An error occurred while restoring the backup.', 'metasync'); ?>');
260
261 // Restore button
262 $btn.prop('disabled', false).text(originalText);
263 }
264 });
265
266 return;
267 }
268
269 // Original behavior for validation warnings
270 closeModal();
271 allowSave = true;
272 $('#robots-txt-form').submit();
273 });
274
275 // Reset to default
276 $('#reset-to-default').on('click', function() {
277 if (confirm('<?php esc_html_e('Are you sure you want to reset to default content? This will replace your current content.', 'metasync'); ?>')) {
278 $.ajax({
279 url: ajaxurl,
280 type: 'POST',
281 data: {
282 action: 'metasync_get_default_robots',
283 nonce: '<?php echo wp_create_nonce('metasync_nonce'); ?>'
284 },
285 success: function(response) {
286 if (response.success) {
287 $('#robots-txt-editor').val(response.data.content);
288 }
289 }
290 });
291 }
292 });
293
294 // Validate content button
295 $('#validate-content').on('click', function() {
296 const content = $('#robots-txt-editor').val();
297
298 $.ajax({
299 url: ajaxurl,
300 type: 'POST',
301 data: {
302 action: 'metasync_validate_robots',
303 nonce: '<?php echo wp_create_nonce('metasync_nonce'); ?>',
304 content: content
305 },
306 success: function(response) {
307 const $results = $('#validation-results');
308 $results.show();
309
310 if (response.success && response.data && response.data.valid) {
311 $results.removeClass('error warning').addClass('success');
312 $results.html('<strong><?php esc_html_e('Validation passed!', 'metasync'); ?></strong> <?php esc_html_e('Your robots.txt syntax is correct.', 'metasync'); ?>');
313
314 if (response.data.warnings && response.data.warnings.length > 0) {
315 $results.removeClass('success').addClass('warning');
316 let html = '<strong><?php esc_html_e('Validation passed with warnings:', 'metasync'); ?></strong><ul style="margin: 8px 0 0 20px;">';
317
318 response.data.warnings.forEach(function(warning) {
319 html += '<li>' + warning + '</li>';
320 });
321
322 html += '</ul>';
323 $results.html(html);
324 }
325 } else {
326 $results.removeClass('success warning').addClass('error');
327 let html = '<strong><?php esc_html_e('Validation failed:', 'metasync'); ?></strong><ul style="margin: 8px 0 0 20px;">';
328
329 if (response.data.errors) {
330 response.data.errors.forEach(function(error) {
331 html += '<li>' + error + '</li>';
332 });
333 }
334
335 html += '</ul>';
336 $results.html(html);
337 }
338 }
339 });
340 });
341
342 // Auto-resize textarea
343 $('#robots-txt-editor').on('input', function() {
344 this.style.height = 'auto';
345 this.style.height = (this.scrollHeight) + 'px';
346 });
347
348 // Preview backup content
349 $(document).on('click', '.metasync-preview-backup', function(e) {
350 e.preventDefault();
351 const backupId = $(this).data('backup-id');
352
353 // Show loading state
354 const $button = $(this);
355 const originalText = $button.html();
356 $button.prop('disabled', true).html('<span class="dashicons dashicons-update dashicons-spin"></span> <?php esc_html_e('Loading...', 'metasync'); ?>');
357
358 $.ajax({
359 url: ajaxurl,
360 type: 'POST',
361 data: {
362 action: 'metasync_preview_robots_backup',
363 nonce: '<?php echo wp_create_nonce('metasync_nonce'); ?>',
364 backup_id: backupId
365 },
366 success: function(response) {
367 if (response.success && response.data) {
368 // Format the date
369 let dateInfo = '';
370 if (response.data.created_at) {
371 dateInfo = '<p style="margin-bottom: 16px;"><strong><?php esc_html_e('Created:', 'metasync'); ?></strong> ' + response.data.created_at;
372 if (response.data.created_by_name) {
373 dateInfo += ' <?php esc_html_e('by', 'metasync'); ?> ' + response.data.created_by_name;
374 }
375 dateInfo += '</p>';
376 }
377
378 // Create preview content with pre/code block for display
379 const previewContent = dateInfo +
380 '<pre class="metasync-preview-code"><code>' +
381 $('<div>').text(response.data.content).html() +
382 '</code></pre>';
383
384 // Show in modal
385 const $modal = $('#robots-validation-modal');
386 const $modalContent = $modal.find('.metasync-modal-content');
387 const $header = $modal.find('.metasync-modal-header');
388 const $confirmBtn = $('#modal-confirm-btn');
389 const $cancelBtn = $('.metasync-modal-cancel');
390
391 // Add preview class for larger width
392 $modalContent.addClass('preview');
393
394 // Set header style
395 $header.removeClass('error warning success').addClass('preview');
396
397 // Set content
398 $('#modal-title').html('<?php esc_html_e('Backup Preview', 'metasync'); ?>');
399 $('#modal-body').html(previewContent);
400
401 // Configure restore button (on the left)
402 $confirmBtn.html('<span class="dashicons dashicons-backup"></span> <?php esc_html_e('Restore', 'metasync'); ?>')
403 .removeClass('button-primary')
404 .addClass('button-restore')
405 .data('backup-id', backupId)
406 .data('nonce', '<?php echo wp_create_nonce('metasync_restore_robots_backup'); ?>')
407 .show();
408
409 // Hide close button for preview
410 $cancelBtn.hide();
411
412 // Show modal
413 $modal.fadeIn(200);
414 } else {
415 alert('<?php esc_html_e('Failed to load backup content.', 'metasync'); ?>');
416 }
417
418 // Restore button state
419 $button.prop('disabled', false).html(originalText);
420 },
421 error: function() {
422 alert('<?php esc_html_e('An error occurred while loading the backup.', 'metasync'); ?>');
423 // Restore button state
424 $button.prop('disabled', false).html(originalText);
425 }
426 });
427 });
428
429 // Restore backup with AJAX
430 $(document).on('click', '.metasync-restore-backup', function(e) {
431 e.preventDefault();
432
433 if (!confirm('<?php esc_html_e('Are you sure you want to restore this backup? Current content will be backed up automatically.', 'metasync'); ?>')) {
434 return;
435 }
436
437 const $button = $(this);
438 const backupId = $button.data('backup-id');
439 const nonce = $button.data('nonce');
440
441 // Show loading state
442 const originalHtml = $button.html();
443 $button.prop('disabled', true).html('<span class="dashicons dashicons-update dashicons-spin"></span> <?php esc_html_e('Restoring...', 'metasync'); ?>');
444
445 $.ajax({
446 url: ajaxurl,
447 type: 'POST',
448 data: {
449 action: 'metasync_restore_robots_backup',
450 backup_id: backupId,
451 nonce: nonce
452 },
453 success: function(response) {
454 if (response.success) {
455 // Store success message in sessionStorage
456 if (response.data && response.data.message) {
457 sessionStorage.setItem('metasync_robots_restore_message', response.data.message);
458 }
459
460 // Reload the page to show updated content and backup list
461 window.location.reload();
462 } else {
463 // Show error message
464 const errorMessage = response.data && response.data.message ? response.data.message : '<?php esc_html_e('Failed to restore backup.', 'metasync'); ?>';
465 alert(errorMessage);
466
467 // Restore button state
468 $button.prop('disabled', false).html(originalHtml);
469 }
470 },
471 error: function() {
472 alert('<?php esc_html_e('An error occurred while restoring the backup.', 'metasync'); ?>');
473
474 // Restore button state
475 $button.prop('disabled', false).html(originalHtml);
476 }
477 });
478 });
479
480 // Delete backup with AJAX
481 $(document).on('click', '.metasync-delete-backup', function(e) {
482 e.preventDefault();
483
484 if (!confirm('<?php esc_html_e('Are you sure you want to delete this backup?', 'metasync'); ?>')) {
485 return;
486 }
487
488 const $button = $(this);
489 const backupId = $button.data('backup-id');
490 const nonce = $button.data('nonce');
491
492 // Show loading state
493 const originalHtml = $button.html();
494 $button.prop('disabled', true).html('<span class="dashicons dashicons-update dashicons-spin"></span>');
495
496 $.ajax({
497 url: ajaxurl,
498 type: 'POST',
499 data: {
500 action: 'metasync_delete_robots_backup',
501 backup_id: backupId,
502 nonce: nonce
503 },
504 success: function(response) {
505 if (response.success) {
506 // Refresh the panel so the count and pagination reflect the
507 // new backend state. Stay on the current page, but if the
508 // deleted entry was the last one on it, fall back a page.
509 const $panel = $('#metasync-backups-panel');
510 let currentPage = parseInt($panel.data('page'), 10) || 1;
511 const remainingOnPage = $panel.find('.metasync-backup-item').length - 1;
512 if (remainingOnPage <= 0 && currentPage > 1) {
513 currentPage -= 1;
514 }
515 loadBackupsPage(currentPage);
516
517 // Show success message
518 if (response.data && response.data.message) {
519 // Create a temporary success notice
520 const $notice = $('<div class="notice notice-success is-dismissible" style="margin: 20px 0;"><p>' + response.data.message + '</p></div>');
521 $('.metasync-robots-txt-page').prepend($notice);
522
523 // Auto-dismiss after 3 seconds
524 setTimeout(function() {
525 $notice.fadeOut(300, function() {
526 $(this).remove();
527 });
528 }, 3000);
529 }
530 } else {
531 // Show error message
532 const errorMessage = response.data && response.data.message ? response.data.message : '<?php esc_html_e('Failed to delete backup.', 'metasync'); ?>';
533 alert(errorMessage);
534
535 // Restore button state
536 $button.prop('disabled', false).html(originalHtml);
537 }
538 },
539 error: function() {
540 alert('<?php esc_html_e('An error occurred while deleting the backup.', 'metasync'); ?>');
541
542 // Restore button state
543 $button.prop('disabled', false).html(originalHtml);
544 }
545 });
546 });
547 });
548 </script>
549