| @@ -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 --> |
| @@ -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> |
| @@ -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 = [ |
| @@ -821,8 +893,15 @@ | ||
| 821 | 893 | 'metasync_wp_sa_connect_token', |
| 822 | 894 | 'wp_debug_enabled', |
| 823 | 895 | 'wp_debug_log_enabled', |
| 824 | 896 | 'wp_debug_display_enabled', |
| 897 | + // Media Optimization settings & cache | |
| 898 | + 'metasync_media_optimization', | |
| 899 | + 'metasync_batch_optimize_queue', | |
| 900 | + 'metasync_batch_optimize_progress', | |
| 901 | + 'metasync_batch_optimize_settings', | |
| 902 | + // Code Minification settings | |
| 903 | + 'metasync_code_minification', | |
| 825 | 904 | ]; |
| 826 | 905 | |
| 827 | 906 | $cleared_count = 0; |
| 828 | 907 | foreach ($metasync_options_to_clear as $option_name) { |
| @@ -839,11 +918,18 @@ | ||
| 839 | 918 | foreach ($transients_to_clear as $transient_name) { |
| 840 | 919 | delete_transient($transient_name); |
| 841 | 920 | } |
| 842 | 921 | |
| 843 | - $timestamp = wp_next_scheduled('metasync_heartbeat_cron_check'); | |
| 844 | - if ($timestamp) { | |
| 845 | - wp_unschedule_event($timestamp, 'metasync_heartbeat_cron_check'); | |
| 922 | + $cron_hooks_to_clear = [ | |
| 923 | + 'metasync_heartbeat_cron_check', | |
| 924 | + 'metasync_media_batch_optimize_cron', | |
| 925 | + ]; | |
| 926 | + | |
| 927 | + foreach ($cron_hooks_to_clear as $cron_hook) { | |
| 928 | + $timestamp = wp_next_scheduled($cron_hook); | |
| 929 | + if ($timestamp) { | |
| 930 | + wp_unschedule_event($timestamp, $cron_hook); | |
| 931 | + } | |
| 846 | 932 | } |
| 847 | 933 | |
| 848 | 934 | $new_plugin_auth_token = wp_generate_password(32, false, false); |
| 849 | 935 | |
| @@ -861,13 +947,13 @@ | ||
| 861 | 947 | 'triggered_by' => 'settings_reset_action' |
| 862 | 948 | ), 'info'); |
| 863 | 949 | |
| 864 | 950 | $redirect_url = admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced&settings_cleared=1'); |
| 865 | - wp_redirect($redirect_url); | |
| 951 | + wp_safe_redirect($redirect_url); | |
| 866 | 952 | exit; |
| 867 | 953 | } else { |
| 868 | 954 | $redirect_url = admin_url('admin.php?page=' . $this->get_page_slug() . '&tab=advanced&clear_settings_error=1'); |
| 869 | - wp_redirect($redirect_url); | |
| 955 | + wp_safe_redirect($redirect_url); | |
| 870 | 956 | exit; |
| 871 | 957 | } |
| 872 | 958 | } |
| 873 | 959 | } |
| @@ -882,9 +968,9 @@ | ||
| 882 | 968 | public function get_error_log_content() |
| 883 | 969 | { |
| 884 | 970 | $execution_time = $this->get_execution_setting('max_execution_time'); |
| 885 | 971 | if (function_exists('set_time_limit')) { |
| 886 | - @set_time_limit($execution_time); | |
| 972 | + @set_time_limit($execution_time); // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged -- runtime PHP setting with no WordPress API | |
| 887 | 973 | } |
| 888 | 974 | |
| 889 | 975 | $log_file = WP_CONTENT_DIR . '/debug.log'; |
| 890 | 976 | |
| @@ -916,9 +1002,9 @@ | ||
| 916 | 1002 | public function get_log_tail($file_path, $lines = null) |
| 917 | 1003 | { |
| 918 | 1004 | $execution_time = $this->get_execution_setting('max_execution_time'); |
| 919 | 1005 | if (function_exists('set_time_limit')) { |
| 920 | - @set_time_limit($execution_time); | |
| 1006 | + @set_time_limit($execution_time); // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged -- runtime PHP setting with no WordPress API | |
| 921 | 1007 | } |
| 922 | 1008 | |
| 923 | 1009 | if ($lines === null) { |
| 924 | 1010 | $lines = $this->get_execution_setting('log_batch_size'); |
| @@ -923,9 +1009,9 @@ | ||
| 923 | 1009 | if ($lines === null) { |
| 924 | 1010 | $lines = $this->get_execution_setting('log_batch_size'); |
| 925 | 1011 | } |
| 926 | 1012 | |
| 927 | - $handle = fopen($file_path, 'r'); | |
| 1013 | + $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 | |
| 928 | 1014 | if (!$handle) { |
| 929 | 1015 | return false; |
| 930 | 1016 | } |
| 931 | 1017 | |
| @@ -954,9 +1040,9 @@ | ||
| 954 | 1040 | if (!empty($line) && $line_count < $lines) { |
| 955 | 1041 | array_unshift($result_lines, strrev($line)); |
| 956 | 1042 | } |
| 957 | 1043 | |
| 958 | - fclose($handle); | |
| 1044 | + fclose($handle); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- operates on a native stream handle | |
| 959 | 1045 | |
| 960 | 1046 | return implode("\n", $result_lines); |
| 961 | 1047 | } |
| 962 | 1048 | } |