PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.7.2
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.7.2
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
← All changes | includes/class-metasync-debug-manager.php +155 -47 2.6.12 → 2.7.2 View file →
@@ -72,14 +72,23 @@
72 72 *
73 73 * @param Metasync_Admin $admin The admin instance (needed for header/nav rendering).
74 74 */
75 75 public function metasync_display_error_log($admin) {
76 - $log_file = WP_CONTENT_DIR . '/metasync_data/plugin_errors.log';
76 + $log_file = Metasync_Data_Store::file_path('plugin_errors.log');
77 + if (false === $log_file) {
78 + $log_file = '';
79 + }
77 80 if (!Metasync::current_user_has_plugin_access()) {
78 81 return;
79 82 }
83 +
84 + $can_manage_debug_settings = current_user_can('manage_options');
85 + if (isset($_POST['wp_debug_nonce']) && !$can_manage_debug_settings) {
86 + return;
87 + }
80 88
81 - if (isset($_POST['wp_debug_log_enabled']) &&
89 + if ($can_manage_debug_settings &&
90 + isset($_POST['wp_debug_log_enabled']) &&
82 91 isset($_POST['wp_debug_enabled']) &&
83 92 isset($_POST['wp_debug_display_enabled']) &&
84 93 isset($_POST['wp_debug_nonce']) &&
85 94 wp_verify_nonce($_POST['wp_debug_nonce'], 'metasync_wp_debug_settings')) {
@@ -92,20 +101,30 @@
92 101 update_option('wp_debug_log_enabled', $wp_debug_log);
93 102 update_option('wp_debug_display_enabled', $wp_debug_display);
94 103
95 104 $data = new ConfigControllerMetaSync();
96 - $data->store();
97 -
105 + $saved = $data->store();
106 +
107 + if ($saved) {
108 + add_settings_error(
109 + 'metasync_messages',
110 + 'metasync_message',
111 + 'WordPress debug settings updated successfully.',
112 + 'updated'
113 + );
114 + } else {
115 + add_settings_error(
116 + 'metasync_messages',
117 + 'metasync_message',
118 + 'Debug settings were saved, but wp-config.php could not be updated: '
119 + . ($data->getConfigError() !== '' ? $data->getConfigError() : 'the file is not writable.'),
120 + 'error'
121 + );
122 + }
123 + } elseif ($can_manage_debug_settings && isset($_POST['wp_debug_nonce']) && !wp_verify_nonce($_POST['wp_debug_nonce'], 'metasync_wp_debug_settings')) {
98 124 add_settings_error(
99 125 'metasync_messages',
100 126 'metasync_message',
101 - 'WordPress debug settings updated successfully.',
102 - 'updated'
103 - );
104 - } elseif (isset($_POST['wp_debug_nonce']) && !wp_verify_nonce($_POST['wp_debug_nonce'], 'metasync_wp_debug_settings')) {
105 - add_settings_error(
106 - 'metasync_messages',
107 - 'metasync_message',
108 127 'Security verification failed. Please try again.',
109 128 'error'
110 129 );
111 130 }
@@ -218,9 +237,9 @@
218 237 * Update wp-config.php debug constants.
219 238 */
220 239 public function metasync_update_wp_config() {
221 240 $wp_config_path = ABSPATH . 'wp-config.php';
222 - if (file_exists($wp_config_path) && is_writable($wp_config_path)) {
241 + if (file_exists($wp_config_path) && wp_is_writable($wp_config_path)) {
223 242 $config_file = file_get_contents($wp_config_path);
224 243
225 244 $wp_debug_enabled = get_option('wp_debug_enabled', 'false') === 'true' ? 'true' : 'false';
226 245 if (preg_match("/define\s*\(\s*['\"]WP_DEBUG['\"]\s*,\s*.*?\s*\)\s*;/", $config_file)) {
@@ -242,8 +261,14 @@
242 261 } else {
243 262 $config_file = str_replace("/* That's all, stop editing! Happy publishing. */", "define('WP_DEBUG_DISPLAY', $wp_debug_display_enabled);\n\n/* That's all, stop editing! Happy publishing. */", $config_file);
244 263 }
245 264
265 + // ABSPATH is intentional and verified: the Debug Mode feature
266 + // toggles WP_DEBUG constants in wp-config.php itself, the one
267 + // file whose location ABSPATH exists to describe. It is not a
268 + // plugin-directory or generated-content write, so it stays here
269 + // (Plugin Check's ABSPATHDetected warning is a false positive —
270 + // wp-config.php cannot live in the uploads directory).
246 271 file_put_contents($wp_config_path, $config_file);
247 272 } else {
248 273 wp_die('The wp-config.php file is not writable. Please check the file permissions.');
249 274 }
@@ -280,9 +305,15 @@
280 305 }
281 306 }
282 307
283 308 if ($changed) {
284 - require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-metasync-activator.php';
309 + if (!current_user_can('manage_options')) {
310 + return;
311 + }
312 +
313 + if (!class_exists('Metasync_Activator')) {
314 + require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-metasync-activator.php';
315 + }
285 316 Metasync_Activator::sync_plugin_file_headers();
286 317 }
287 318 }
288 319
@@ -310,9 +341,9 @@
310 341 $status = $debug_manager->get_status();
311 342 ?>
312 343
313 344 <!-- Debug Mode Status Overview -->
314 - <div style="margin-bottom: 30px;">
345 + <div style="margin-bottom: 30px; padding-top: 20px;">
315 346 <h4 style="margin-top: 0; color: var(--dashboard-text-primary);">Current Status</h4>
316 347 <div style="background: rgba(255, 255, 255, 0.05); border: 1px solid var(--dashboard-border); padding: 20px; border-radius: 8px;">
317 348 <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
318 349 <!-- Status Badge -->
@@ -369,9 +400,9 @@
369 400 <!-- Debug Mode Controls -->
370 401 <div style="margin-bottom: 30px;">
371 402 <h4 style="margin-top: 0; color: var(--dashboard-text-primary);">Controls</h4>
372 403
373 - <form method="post" action="<?php echo admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced'); ?>">
404 + <form method="post" action="<?php echo esc_url(admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced')); ?>">
374 405 <input type="hidden" name="metasync_debug_mode_action_advanced" value="1" />
375 406 <?php wp_nonce_field('metasync_debug_mode_action_advanced', 'metasync_debug_mode_nonce_advanced'); ?>
376 407
377 408 <?php if (!$status['enabled']): ?>
@@ -467,9 +498,9 @@
467 498 }
468 499 });
469 500
470 501 <?php if ($status['enabled'] && !$status['indefinite']): ?>
471 - var initialTimeRemaining = <?php echo $status['time_remaining']; ?>;
502 + var initialTimeRemaining = <?php echo (int) $status['time_remaining']; ?>;
472 503 var hasReloaded = false;
473 504
474 505 function updateDebugTimeRemaining() {
475 506 if (initialTimeRemaining <= 0 || hasReloaded) {
@@ -476,12 +507,12 @@
476 507 return;
477 508 }
478 509
479 510 $.ajax({
480 - url: '<?php echo rest_url('metasync/v1/debug-mode/status'); ?>',
511 + url: '<?php echo esc_url(rest_url('metasync/v1/debug-mode/status')); ?>',
481 512 method: 'GET',
482 513 beforeSend: function(xhr) {
483 - xhr.setRequestHeader('X-WP-Nonce', '<?php echo wp_create_nonce('wp_rest'); ?>');
514 + xhr.setRequestHeader('X-WP-Nonce', '<?php echo esc_attr(wp_create_nonce('wp_rest')); ?>');
484 515 },
485 516 success: function(response) {
486 517 console.log('MetaSync Debug Mode Status:', response);
487 518
@@ -523,15 +554,15 @@
523 554 public function render_error_log_content()
524 555 {
525 556 ?>
526 557 <!-- Error Summary Section -->
527 - <div style="margin-bottom: 30px;">
558 + <div style="margin-bottom: 30px; padding-top: 20px;">
528 559 <h4 style="margin-top: 0; color: var(--dashboard-text-primary);">Error Summary</h4>
529 560 <p style="margin-bottom: 15px; color: var(--dashboard-text-secondary);">View categorized error statistics with counts and last occurrence times.</p>
530 561
531 562 <?php
532 563 if (class_exists('Metasync_Error_Logger')) {
533 - $error_summary = Metasync_Error_Logger::get_error_summary();
564 + $error_summary = Metasync_Error_Logger::get_visible_error_summary();
534 565
535 566 if (!empty($error_summary) && is_array($error_summary)) {
536 567 uasort($error_summary, function($a, $b) {
537 568 return strtotime($b['last_seen']) - strtotime($a['last_seen']);
@@ -551,9 +582,9 @@
551 582 <tbody>
552 583 <?php foreach ($error_summary as $key => $error): ?>
553 584 <tr>
554 585 <td style="padding: 10px 12px; color: var(--dashboard-text-primary);">
555 - <strong><?php echo esc_html($error['category']); ?></strong>
586 + <strong><?php echo esc_html(Metasync_Error_Logger::get_display_label($error['category'])); ?></strong>
556 587 </td>
557 588 <td style="padding: 10px 12px; text-align: center; color: var(--dashboard-text-secondary); font-family: monospace;">
558 589 <code style="background: rgba(255, 255, 255, 0.1); padding: 2px 6px; border-radius: 3px;"><?php echo esc_html($error['code']); ?></code>
559 590 </td>
@@ -565,9 +596,9 @@
565 596 <td style="padding: 10px 12px; color: var(--dashboard-text-secondary); font-size: 13px;">
566 597 <?php
567 598 $last_seen = strtotime($error['last_seen']);
568 599 $time_diff = human_time_diff($last_seen, current_time('timestamp'));
569 - echo esc_html($error['last_seen']) . ' <span style="color: var(--dashboard-text-secondary);">(' . $time_diff . ' ago)</span>';
600 + echo esc_html($error['last_seen']) . ' <span style="color: var(--dashboard-text-secondary);">(' . esc_html($time_diff) . ' ago)</span>';
570 601 ?>
571 602 </td>
572 603 <td style="padding: 10px 12px; color: var(--dashboard-text-primary); max-width: 400px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" title="<?php echo esc_attr($error['message']); ?>">
573 604 <?php echo esc_html($error['message']); ?>
@@ -577,9 +608,9 @@
577 608 </tbody>
578 609 </table>
579 610 </div>
580 611
581 - <form method="post" action="<?php echo admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced'); ?>" style="margin-bottom: 20px;">
612 + <form method="post" action="<?php echo esc_url(admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced')); ?>" style="margin-bottom: 20px;">
582 613 <input type="hidden" name="clear_error_summary" value="yes" />
583 614 <?php wp_nonce_field('metasync_clear_error_summary_nonce', 'clear_error_summary_nonce'); ?>
584 615 <button type="submit" class="button button-secondary" style="background: #dc3232; color: #ffffff; border: none; padding: 8px 16px; border-radius: 4px; font-weight: 500; cursor: pointer;">
585 616 <span class="dashicons dashicons-trash" style="margin-top:3px;font-size:15px;width:15px;height:15px;"></span> Clear Error Summary
@@ -611,9 +642,9 @@
611 642 <div style="margin-bottom: 30px;">
612 643 <h4 style="margin-top: 0; color: var(--dashboard-text-primary);">Clear Error Logs</h4>
613 644 <p style="margin-bottom: 15px; color: var(--dashboard-text-secondary);">Clear WordPress error logs to free up space and remove old entries.</p>
614 645
615 - <form method="post" action="<?php echo admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced'); ?>" style="margin-bottom: 20px;">
646 + <form method="post" action="<?php echo esc_url(admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced')); ?>" style="margin-bottom: 20px;">
616 647 <input type="hidden" name="clear_log" value="yes" />
617 648 <?php wp_nonce_field('metasync_clear_log_nonce', 'clear_log_nonce'); ?>
618 649 <button type="submit" class="metasync-btn-primary" style="background: var(--dashboard-gradient-primary); color: #ffffff; border: none; padding: 10px 20px; border-radius: 8px; font-weight: 500; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); display: inline-block; width: auto; min-width: 240px; max-width: fit-content;" onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 4px 8px rgba(0, 0, 0, 0.15)';" onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 2px 4px rgba(0, 0, 0, 0.1)';">
619 650 🧹 Clear Error Logs
@@ -642,11 +673,41 @@
642 673 </ul>
643 674
644 675 <?php if (!$wp_debug): ?>
645 676 <p style="color: var(--dashboard-accent);">💡 To enable error logging, add these lines to your wp-config.php file:</p>
646 - <pre style="background: rgba(255, 255, 255, 0.05); border: 1px solid var(--dashboard-border); padding: 10px; border-radius: 4px; color: var(--dashboard-text-primary);">define('WP_DEBUG', true);
677 + <div class="metasync-copy-wrap"><pre class="metasync-copy-snippet" style="background: rgba(255, 255, 255, 0.05); border: 1px solid var(--dashboard-border); padding: 10px; border-radius: 4px; color: var(--dashboard-text-primary);">define('WP_DEBUG', true);
647 678 define('WP_DEBUG_LOG', true);
648 -define('WP_DEBUG_DISPLAY', false);</pre>
679 +define('WP_DEBUG_DISPLAY', false);</pre><span class="metasync-copy-badge">Copy</span></div>
680 + <?php /* click-to-copy for the wp-config snippet above */ ?>
681 + <style>
682 + .metasync-copy-wrap { position: relative; }
683 + .metasync-copy-snippet { cursor: pointer; outline: 1px solid transparent; transition: outline-color .15s ease; }
684 + .metasync-copy-wrap:hover .metasync-copy-snippet { outline-color: var(--dashboard-border, #374151); }
685 + .metasync-copy-badge { position: absolute; top: 8px; right: 10px; font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 4px; pointer-events: none; opacity: 0; transition: opacity .15s ease; background: var(--dashboard-border, #374151); color: var(--dashboard-text-primary, #fff); }
686 + .metasync-copy-wrap:hover .metasync-copy-badge { opacity: .85; }
687 + .metasync-copy-badge.metasync-copy-done { opacity: 1; background: var(--dashboard-gradient-primary, linear-gradient(135deg, #667eea 0%, #764ba2 100%)); color: #fff; }
688 + </style>
689 + <script>
690 + (function(){
691 + if (window.__metasyncCopyInit) return; window.__metasyncCopyInit = true;
692 + function fallback(text){ var ta=document.createElement('textarea'); ta.value=text; ta.style.position='fixed'; ta.style.opacity='0'; document.body.appendChild(ta); ta.focus(); ta.select(); try{document.execCommand('copy');}catch(e){} document.body.removeChild(ta); }
693 + function attach(){
694 + document.querySelectorAll('.metasync-copy-snippet').forEach(function(pre){
695 + if (pre.dataset.copyBound) return; pre.dataset.copyBound='1';
696 + pre.setAttribute('title','Click to copy');
697 + pre.addEventListener('click', function(){
698 + var text = pre.textContent.trim();
699 + var wrap = pre.closest('.metasync-copy-wrap') || pre.parentNode;
700 + var badge = wrap.querySelector('.metasync-copy-badge');
701 + var done = function(){ if(!badge) return; badge.textContent='Copied!'; badge.classList.add('metasync-copy-done'); clearTimeout(badge._t); badge._t=setTimeout(function(){ badge.textContent='Copy'; badge.classList.remove('metasync-copy-done'); },1500); };
702 + if (navigator.clipboard && navigator.clipboard.writeText){ navigator.clipboard.writeText(text).then(done).catch(function(){ fallback(text); done(); }); }
703 + else { fallback(text); done(); }
704 + });
705 + });
706 + }
707 + if (document.readyState==='loading'){ document.addEventListener('DOMContentLoaded', attach); } else { attach(); }
708 + })();
709 + </script>
649 710 <?php endif; ?>
650 711 </form>
651 712 </div>
652 713
@@ -699,9 +760,9 @@
699 760 {
700 761 if (isset($_POST['metasync_debug_mode_action_advanced'])) {
701 762 if (!wp_verify_nonce($_POST['metasync_debug_mode_nonce_advanced'], 'metasync_debug_mode_action_advanced')) {
702 763 $redirect_url = admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced&debug_error=1');
703 - wp_redirect($redirect_url);
764 + wp_safe_redirect($redirect_url);
704 765 exit;
705 766 }
706 767
707 768 if (!current_user_can('manage_options')) {
@@ -709,9 +770,9 @@
709 770 }
710 771
711 772 if (!class_exists('Metasync_Debug_Mode_Manager')) {
712 773 $redirect_url = admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced&debug_error=1&msg=manager_not_available');
713 - wp_redirect($redirect_url);
774 + wp_safe_redirect($redirect_url);
714 775 exit;
715 776 }
716 777
717 778 $debug_manager = Metasync_Debug_Mode_Manager::get_instance();
@@ -748,9 +809,9 @@
748 809 $redirect_url = add_query_arg('debug_error', '1', $redirect_url);
749 810 break;
750 811 }
751 812
752 - wp_redirect($redirect_url);
813 + wp_safe_redirect($redirect_url);
753 814 exit;
754 815 }
755 816 }
756 817
@@ -758,29 +819,36 @@
758 819 * Handle error log operations (clear).
759 820 */
760 821 public function handle_error_log_operations()
761 822 {
823 + if ((isset($_POST['clear_log']) || isset($_POST['clear_error_summary'])) && !current_user_can('manage_options')) {
824 + return;
825 + }
826 +
762 827 if (isset($_POST['clear_log'])) {
763 828 if (wp_verify_nonce($_POST['clear_log_nonce'], 'metasync_clear_log_nonce')) {
764 - $log_file = WP_CONTENT_DIR . '/metasync_data/plugin_errors.log';
829 + $data_dir = Metasync_Data_Store::base_dir();
830 + $log_file = Metasync_Data_Store::file_path('plugin_errors.log');
765 831
766 - if (file_exists($log_file)) {
832 + if (false !== $log_file && file_exists($log_file)) {
767 833 file_put_contents($log_file, '');
768 834
769 - $backup_files = glob(WP_CONTENT_DIR . '/metasync_data/plugin_errors.log.old.*');
770 - if ($backup_files) {
771 - foreach ($backup_files as $backup_file) {
772 - @unlink($backup_file);
835 + if (false !== $data_dir) {
836 + $backup_files = glob($data_dir . '/plugin_errors.log.old.*');
837 + if ($backup_files) {
838 + foreach ($backup_files as $backup_file) {
839 + @wp_delete_file($backup_file);
840 + }
773 841 }
774 842 }
775 843 }
776 844
777 845 $redirect_url = admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced&log_cleared=1');
778 - wp_redirect($redirect_url);
846 + wp_safe_redirect($redirect_url);
779 847 exit;
780 848 } else {
781 849 $redirect_url = admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced&clear_error=1');
782 - wp_redirect($redirect_url);
850 + wp_safe_redirect($redirect_url);
783 851 exit;
784 852 }
785 853 }
786 854
@@ -788,18 +856,18 @@
788 856 if (wp_verify_nonce($_POST['clear_error_summary_nonce'], 'metasync_clear_error_summary_nonce')) {
789 857 if (class_exists('Metasync_Error_Logger')) {
790 858 Metasync_Error_Logger::clear_error_summary();
791 859 $redirect_url = admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced&error_summary_cleared=1');
792 - wp_redirect($redirect_url);
860 + wp_safe_redirect($redirect_url);
793 861 exit;
794 862 } else {
795 863 $redirect_url = admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced&error_summary_error=1');
796 - wp_redirect($redirect_url);
864 + wp_safe_redirect($redirect_url);
797 865 exit;
798 866 }
799 867 } else {
800 868 $redirect_url = admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced&error_summary_error=1');
801 - wp_redirect($redirect_url);
869 + wp_safe_redirect($redirect_url);
802 870 exit;
803 871 }
804 872 }
805 873 }
@@ -808,8 +876,12 @@
808 876 * Handle clear all settings operations.
809 877 */
810 878 public function handle_clear_all_settings()
811 879 {
880 + if (isset($_POST['clear_all_settings']) && !current_user_can('manage_options')) {
881 + return;
882 + }
883 +
812 884 if (isset($_POST['clear_all_settings'])) {
813 885 if (wp_verify_nonce($_POST['clear_all_settings_nonce'], 'metasync_clear_all_settings_nonce')) {
814 886
815 887 $metasync_options_to_clear = [
@@ -830,8 +902,18 @@
830 902 // Code Minification settings
831 903 'metasync_code_minification',
832 904 ];
833 905
906 + // Capture the complete white-label identity BEFORE the
907 + // destructive clear so it can be restored afterwards. The
908 + // reset is meant to remove operational data and credentials,
909 + // not the reseller's public branding, logos, domains, custom
910 + // OTTO name, visibility/access controls, or recovery settings.
911 + if (!class_exists('Metasync_Whitelabel_Preservation')) {
912 + require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-metasync-whitelabel-preservation.php';
913 + }
914 + $whitelabel_state = Metasync_Whitelabel_Preservation::extract_whitelabel_state();
915 +
834 916 $cleared_count = 0;
835 917 foreach ($metasync_options_to_clear as $option_name) {
836 918 if (get_option($option_name) !== false) {
837 919 delete_option($option_name);
@@ -873,15 +955,41 @@
873 955 'options_cleared_count' => $cleared_count,
874 956 'new_token_prefix' => substr($new_plugin_auth_token, 0, 8) . '...',
875 957 'triggered_by' => 'settings_reset_action'
876 958 ), 'info');
877 -
959 +
960 + // Restore the preserved white-label identity over the freshly
961 + // cleared options. A failed restore must not report success.
962 + $restored = Metasync_Whitelabel_Preservation::restore_whitelabel_state($whitelabel_state);
963 + if (!$restored) {
964 + $redirect_url = admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced&clear_settings_error=1');
965 + wp_redirect($redirect_url);
966 + exit;
967 + }
968 +
969 + // Re-synchronise the branded plugin file headers so the
970 + // WordPress plugin list and the plugin UI stay branded after
971 + // the reset. Only attempted when white-label branding exists,
972 + // and a failed sync is logged as a warning, not reported as a
973 + // reset failure: the reset itself (operational clear + fresh
974 + // token + branding restore) has already succeeded at this
975 + // point, and hosts with read-only plugin files would otherwise
976 + // never see a successful reset.
977 + if (!empty($whitelabel_state['whitelabel']) || !empty($whitelabel_state['general'])) {
978 + if (!class_exists('Metasync_Activator')) {
979 + require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-metasync-activator.php';
980 + }
981 + if (!Metasync_Activator::sync_plugin_file_headers()) {
982 + error_log('MetaSync: failed to re-synchronise branded plugin file headers after the settings reset.');
983 + }
984 + }
985 +
878 986 $redirect_url = admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced&settings_cleared=1');
879 - wp_redirect($redirect_url);
987 + wp_safe_redirect($redirect_url);
880 988 exit;
881 989 } else {
882 990 $redirect_url = admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced&clear_settings_error=1');
883 - wp_redirect($redirect_url);
991 + wp_safe_redirect($redirect_url);
884 992 exit;
885 993 }
886 994 }
887 995 }
@@ -896,9 +1004,9 @@
896 1004 public function get_error_log_content()
897 1005 {
898 1006 $execution_time = $this->get_execution_setting('max_execution_time');
899 1007 if (function_exists('set_time_limit')) {
900 - @set_time_limit($execution_time);
1008 + @set_time_limit($execution_time); // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged -- runtime PHP setting with no WordPress API
901 1009 }
902 1010
903 1011 $log_file = WP_CONTENT_DIR . '/debug.log';
904 1012
@@ -930,9 +1038,9 @@
930 1038 public function get_log_tail($file_path, $lines = null)
931 1039 {
932 1040 $execution_time = $this->get_execution_setting('max_execution_time');
933 1041 if (function_exists('set_time_limit')) {
934 - @set_time_limit($execution_time);
1042 + @set_time_limit($execution_time); // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged -- runtime PHP setting with no WordPress API
935 1043 }
936 1044
937 1045 if ($lines === null) {
938 1046 $lines = $this->get_execution_setting('log_batch_size');
@@ -937,9 +1045,9 @@
937 1045 if ($lines === null) {
938 1046 $lines = $this->get_execution_setting('log_batch_size');
939 1047 }
940 1048
941 - $handle = fopen($file_path, 'r');
1049 + $handle = fopen($file_path, 'r'); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen -- streaming file I/O; WP_Filesystem cannot return a raw stream handle
942 1050 if (!$handle) {
943 1051 return false;
944 1052 }
945 1053
@@ -968,9 +1076,9 @@
968 1076 if (!empty($line) && $line_count < $lines) {
969 1077 array_unshift($result_lines, strrev($line));
970 1078 }
971 1079
972 - fclose($handle);
1080 + fclose($handle); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- operates on a native stream handle
973 1081
974 1082 return implode("\n", $result_lines);
975 1083 }
976 1084 }