| @@ -76,10 +76,16 @@ | ||
| 76 | 76 | $log_file = WP_CONTENT_DIR . '/metasync_data/plugin_errors.log'; |
| 77 | 77 | if (!Metasync::current_user_has_plugin_access()) { |
| 78 | 78 | return; |
| 79 | 79 | } |
| 80 | + | |
| 81 | + $can_manage_debug_settings = current_user_can('manage_options'); | |
| 82 | + if (isset($_POST['wp_debug_nonce']) && !$can_manage_debug_settings) { | |
| 83 | + return; | |
| 84 | + } | |
| 80 | 85 | |
| 81 | - if (isset($_POST['wp_debug_log_enabled']) && | |
| 86 | + if ($can_manage_debug_settings && | |
| 87 | + isset($_POST['wp_debug_log_enabled']) && | |
| 82 | 88 | isset($_POST['wp_debug_enabled']) && |
| 83 | 89 | isset($_POST['wp_debug_display_enabled']) && |
| 84 | 90 | isset($_POST['wp_debug_nonce']) && |
| 85 | 91 | wp_verify_nonce($_POST['wp_debug_nonce'], 'metasync_wp_debug_settings')) { |
| @@ -92,20 +98,30 @@ | ||
| 92 | 98 | update_option('wp_debug_log_enabled', $wp_debug_log); |
| 93 | 99 | update_option('wp_debug_display_enabled', $wp_debug_display); |
| 94 | 100 | |
| 95 | 101 | $data = new ConfigControllerMetaSync(); |
| 96 | - $data->store(); | |
| 97 | - | |
| 102 | + $saved = $data->store(); | |
| 103 | + | |
| 104 | + if ($saved) { | |
| 105 | + add_settings_error( | |
| 106 | + 'metasync_messages', | |
| 107 | + 'metasync_message', | |
| 108 | + 'WordPress debug settings updated successfully.', | |
| 109 | + 'updated' | |
| 110 | + ); | |
| 111 | + } else { | |
| 112 | + add_settings_error( | |
| 113 | + 'metasync_messages', | |
| 114 | + 'metasync_message', | |
| 115 | + 'Debug settings were saved, but wp-config.php could not be updated: ' | |
| 116 | + . ($data->getConfigError() !== '' ? $data->getConfigError() : 'the file is not writable.'), | |
| 117 | + 'error' | |
| 118 | + ); | |
| 119 | + } | |
| 120 | + } elseif ($can_manage_debug_settings && isset($_POST['wp_debug_nonce']) && !wp_verify_nonce($_POST['wp_debug_nonce'], 'metasync_wp_debug_settings')) { | |
| 98 | 121 | add_settings_error( |
| 99 | 122 | 'metasync_messages', |
| 100 | 123 | '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 | 124 | 'Security verification failed. Please try again.', |
| 109 | 125 | 'error' |
| 110 | 126 | ); |
| 111 | 127 | } |
| @@ -280,9 +296,15 @@ | ||
| 280 | 296 | } |
| 281 | 297 | } |
| 282 | 298 | |
| 283 | 299 | if ($changed) { |
| 284 | - require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-metasync-activator.php'; | |
| 300 | + if (!current_user_can('manage_options')) { | |
| 301 | + return; | |
| 302 | + } | |
| 303 | + | |
| 304 | + if (!class_exists('Metasync_Activator')) { | |
| 305 | + require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-metasync-activator.php'; | |
| 306 | + } | |
| 285 | 307 | Metasync_Activator::sync_plugin_file_headers(); |
| 286 | 308 | } |
| 287 | 309 | } |
| 288 | 310 | |
| @@ -310,9 +332,9 @@ | ||
| 310 | 332 | $status = $debug_manager->get_status(); |
| 311 | 333 | ?> |
| 312 | 334 | |
| 313 | 335 | <!-- Debug Mode Status Overview --> |
| 314 | - <div style="margin-bottom: 30px;"> | |
| 336 | + <div style="margin-bottom: 30px; padding-top: 20px;"> | |
| 315 | 337 | <h4 style="margin-top: 0; color: var(--dashboard-text-primary);">Current Status</h4> |
| 316 | 338 | <div style="background: rgba(255, 255, 255, 0.05); border: 1px solid var(--dashboard-border); padding: 20px; border-radius: 8px;"> |
| 317 | 339 | <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> |
| 318 | 340 | <!-- Status Badge --> |
| @@ -523,15 +545,15 @@ | ||
| 523 | 545 | public function render_error_log_content() |
| 524 | 546 | { |
| 525 | 547 | ?> |
| 526 | 548 | <!-- Error Summary Section --> |
| 527 | - <div style="margin-bottom: 30px;"> | |
| 549 | + <div style="margin-bottom: 30px; padding-top: 20px;"> | |
| 528 | 550 | <h4 style="margin-top: 0; color: var(--dashboard-text-primary);">Error Summary</h4> |
| 529 | 551 | <p style="margin-bottom: 15px; color: var(--dashboard-text-secondary);">View categorized error statistics with counts and last occurrence times.</p> |
| 530 | 552 | |
| 531 | 553 | <?php |
| 532 | 554 | if (class_exists('Metasync_Error_Logger')) { |
| 533 | - $error_summary = Metasync_Error_Logger::get_error_summary(); | |
| 555 | + $error_summary = Metasync_Error_Logger::get_visible_error_summary(); | |
| 534 | 556 | |
| 535 | 557 | if (!empty($error_summary) && is_array($error_summary)) { |
| 536 | 558 | uasort($error_summary, function($a, $b) { |
| 537 | 559 | return strtotime($b['last_seen']) - strtotime($a['last_seen']); |
| @@ -551,9 +573,9 @@ | ||
| 551 | 573 | <tbody> |
| 552 | 574 | <?php foreach ($error_summary as $key => $error): ?> |
| 553 | 575 | <tr> |
| 554 | 576 | <td style="padding: 10px 12px; color: var(--dashboard-text-primary);"> |
| 555 | - <strong><?php echo esc_html($error['category']); ?></strong> | |
| 577 | + <strong><?php echo esc_html(Metasync_Error_Logger::get_display_label($error['category'])); ?></strong> | |
| 556 | 578 | </td> |
| 557 | 579 | <td style="padding: 10px 12px; text-align: center; color: var(--dashboard-text-secondary); font-family: monospace;"> |
| 558 | 580 | <code style="background: rgba(255, 255, 255, 0.1); padding: 2px 6px; border-radius: 3px;"><?php echo esc_html($error['code']); ?></code> |
| 559 | 581 | </td> |
| @@ -642,11 +664,41 @@ | ||
| 642 | 664 | </ul> |
| 643 | 665 | |
| 644 | 666 | <?php if (!$wp_debug): ?> |
| 645 | 667 | <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); | |
| 668 | + <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 | 669 | define('WP_DEBUG_LOG', true); |
| 648 | -define('WP_DEBUG_DISPLAY', false);</pre> | |
| 670 | +define('WP_DEBUG_DISPLAY', false);</pre><span class="metasync-copy-badge">Copy</span></div> | |
| 671 | + <?php /* click-to-copy for the wp-config snippet above */ ?> | |
| 672 | + <style> | |
| 673 | + .metasync-copy-wrap { position: relative; } | |
| 674 | + .metasync-copy-snippet { cursor: pointer; outline: 1px solid transparent; transition: outline-color .15s ease; } | |
| 675 | + .metasync-copy-wrap:hover .metasync-copy-snippet { outline-color: var(--dashboard-border, #374151); } | |
| 676 | + .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); } | |
| 677 | + .metasync-copy-wrap:hover .metasync-copy-badge { opacity: .85; } | |
| 678 | + .metasync-copy-badge.metasync-copy-done { opacity: 1; background: var(--dashboard-gradient-primary, linear-gradient(135deg, #667eea 0%, #764ba2 100%)); color: #fff; } | |
| 679 | + </style> | |
| 680 | + <script> | |
| 681 | + (function(){ | |
| 682 | + if (window.__metasyncCopyInit) return; window.__metasyncCopyInit = true; | |
| 683 | + 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); } | |
| 684 | + function attach(){ | |
| 685 | + document.querySelectorAll('.metasync-copy-snippet').forEach(function(pre){ | |
| 686 | + if (pre.dataset.copyBound) return; pre.dataset.copyBound='1'; | |
| 687 | + pre.setAttribute('title','Click to copy'); | |
| 688 | + pre.addEventListener('click', function(){ | |
| 689 | + var text = pre.textContent.trim(); | |
| 690 | + var wrap = pre.closest('.metasync-copy-wrap') || pre.parentNode; | |
| 691 | + var badge = wrap.querySelector('.metasync-copy-badge'); | |
| 692 | + 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); }; | |
| 693 | + if (navigator.clipboard && navigator.clipboard.writeText){ navigator.clipboard.writeText(text).then(done).catch(function(){ fallback(text); done(); }); } | |
| 694 | + else { fallback(text); done(); } | |
| 695 | + }); | |
| 696 | + }); | |
| 697 | + } | |
| 698 | + if (document.readyState==='loading'){ document.addEventListener('DOMContentLoaded', attach); } else { attach(); } | |
| 699 | + })(); | |
| 700 | + </script> | |
| 649 | 701 | <?php endif; ?> |
| 650 | 702 | </form> |
| 651 | 703 | </div> |
| 652 | 704 | |
| @@ -758,8 +810,12 @@ | ||
| 758 | 810 | * Handle error log operations (clear). |
| 759 | 811 | */ |
| 760 | 812 | public function handle_error_log_operations() |
| 761 | 813 | { |
| 814 | + if ((isset($_POST['clear_log']) || isset($_POST['clear_error_summary'])) && !current_user_can('manage_options')) { | |
| 815 | + return; | |
| 816 | + } | |
| 817 | + | |
| 762 | 818 | if (isset($_POST['clear_log'])) { |
| 763 | 819 | if (wp_verify_nonce($_POST['clear_log_nonce'], 'metasync_clear_log_nonce')) { |
| 764 | 820 | $log_file = WP_CONTENT_DIR . '/metasync_data/plugin_errors.log'; |
| 765 | 821 | |
| @@ -808,8 +864,12 @@ | ||
| 808 | 864 | * Handle clear all settings operations. |
| 809 | 865 | */ |
| 810 | 866 | public function handle_clear_all_settings() |
| 811 | 867 | { |
| 868 | + if (isset($_POST['clear_all_settings']) && !current_user_can('manage_options')) { | |
| 869 | + return; | |
| 870 | + } | |
| 871 | + | |
| 812 | 872 | if (isset($_POST['clear_all_settings'])) { |
| 813 | 873 | if (wp_verify_nonce($_POST['clear_all_settings_nonce'], 'metasync_clear_all_settings_nonce')) { |
| 814 | 874 | |
| 815 | 875 | $metasync_options_to_clear = [ |
| @@ -821,8 +881,15 @@ | ||
| 821 | 881 | 'metasync_wp_sa_connect_token', |
| 822 | 882 | 'wp_debug_enabled', |
| 823 | 883 | 'wp_debug_log_enabled', |
| 824 | 884 | 'wp_debug_display_enabled', |
| 885 | + // Media Optimization settings & cache | |
| 886 | + 'metasync_media_optimization', | |
| 887 | + 'metasync_batch_optimize_queue', | |
| 888 | + 'metasync_batch_optimize_progress', | |
| 889 | + 'metasync_batch_optimize_settings', | |
| 890 | + // Code Minification settings | |
| 891 | + 'metasync_code_minification', | |
| 825 | 892 | ]; |
| 826 | 893 | |
| 827 | 894 | $cleared_count = 0; |
| 828 | 895 | foreach ($metasync_options_to_clear as $option_name) { |
| @@ -839,11 +906,18 @@ | ||
| 839 | 906 | foreach ($transients_to_clear as $transient_name) { |
| 840 | 907 | delete_transient($transient_name); |
| 841 | 908 | } |
| 842 | 909 | |
| 843 | - $timestamp = wp_next_scheduled('metasync_heartbeat_cron_check'); | |
| 844 | - if ($timestamp) { | |
| 845 | - wp_unschedule_event($timestamp, 'metasync_heartbeat_cron_check'); | |
| 910 | + $cron_hooks_to_clear = [ | |
| 911 | + 'metasync_heartbeat_cron_check', | |
| 912 | + 'metasync_media_batch_optimize_cron', | |
| 913 | + ]; | |
| 914 | + | |
| 915 | + foreach ($cron_hooks_to_clear as $cron_hook) { | |
| 916 | + $timestamp = wp_next_scheduled($cron_hook); | |
| 917 | + if ($timestamp) { | |
| 918 | + wp_unschedule_event($timestamp, $cron_hook); | |
| 919 | + } | |
| 846 | 920 | } |
| 847 | 921 | |
| 848 | 922 | $new_plugin_auth_token = wp_generate_password(32, false, false); |
| 849 | 923 | |