Plugin Directory

Changeset 3459095


Ignore:
Timestamp:
02/11/2026 03:42:10 PM (6 weeks ago)
Author:
jhimross
Message:

version 1.3.2 - Resolved a UI conflict where the confirmation modal appeared automatically upon page load due to CSS class interference from other plugins.

Location:
debugger-troubleshooter/trunk
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • debugger-troubleshooter/trunk/assets/css/admin.css

    r3325892 r3459095  
    11/* This is a simplified set for basic layout and styling */
    2 .flex { display: flex; }
    3 .justify-between { justify-content: space-between; }
    4 .items-center { align-items: center; }
    5 .p-2 { padding: 0.5rem; }
    6 .ml-2 { margin-left: 0.5rem; }
    7 .rounded-md { border-radius: 0.375rem; }
    8 .transition-colors { transition-property: background-color, border-color, color, fill, stroke; }
    9 .duration-200 { transition-duration: 200ms; }
    10 .bg-gray-100 { background-color: #f3f4f6; }
    11 .hover\:bg-gray-200:hover { background-color: #e5e7eb; }
    12 .text-gray-700 { color: #374151; }
    13 .text-xl { font-size: 1.25rem; }
    14 .font-bold { font-weight: 700; }
    15 .mb-4 { margin-bottom: 1rem; }
    16 .mb-6 { margin-bottom: 1.5rem; }
    17 .fixed { position: fixed; }
    18 .inset-0 { top: 0; right: 0; bottom: 0; left: 0; }
    19 .bg-gray-600 { background-color: #4b5563; }
    20 .bg-opacity-50 { background-color: rgba(75, 85, 99, 0.5); }
    21 .z-50 { z-index: 50; }
    22 .max-w-sm { max-width: 24rem; }
    23 .w-full { width: 100%; }
    24 .text-center { text-align: center; }
    25 .bg-white { background-color: #fff; margin-left: auto; margin-right: auto; }
    26 .p-6 { padding: 1.5rem; }
    27 .shadow-xl { box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); }
    28 .hidden { display: none; }
     2.flex {
     3    display: flex;
     4}
     5
     6.justify-between {
     7    justify-content: space-between;
     8}
     9
     10.items-center {
     11    align-items: center;
     12}
     13
     14.p-2 {
     15    padding: 0.5rem;
     16}
     17
     18.ml-2 {
     19    margin-left: 0.5rem;
     20}
     21
     22.rounded-md {
     23    border-radius: 0.375rem;
     24}
     25
     26.transition-colors {
     27    transition-property: background-color, border-color, color, fill, stroke;
     28}
     29
     30.duration-200 {
     31    transition-duration: 200ms;
     32}
     33
     34.bg-gray-100 {
     35    background-color: #f3f4f6;
     36}
     37
     38.hover\:bg-gray-200:hover {
     39    background-color: #e5e7eb;
     40}
     41
     42.text-gray-700 {
     43    color: #374151;
     44}
     45
     46.text-xl {
     47    font-size: 1.25rem;
     48}
     49
     50.font-bold {
     51    font-weight: 700;
     52}
     53
     54.mb-4 {
     55    margin-bottom: 1rem;
     56}
     57
     58.mb-6 {
     59    margin-bottom: 1.5rem;
     60}
     61
     62.fixed {
     63    position: fixed;
     64}
     65
     66.inset-0 {
     67    top: 0;
     68    right: 0;
     69    bottom: 0;
     70    left: 0;
     71}
     72
     73.bg-gray-600 {
     74    background-color: #4b5563;
     75}
     76
     77.bg-opacity-50 {
     78    background-color: rgba(75, 85, 99, 0.5);
     79}
     80
     81.z-50 {
     82    z-index: 50;
     83}
     84
     85.max-w-sm {
     86    max-width: 24rem;
     87}
     88
     89.w-full {
     90    width: 100%;
     91}
     92
     93.text-center {
     94    text-align: center;
     95}
     96
     97.bg-white {
     98    background-color: #fff;
     99    margin-left: auto;
     100    margin-right: auto;
     101}
     102
     103.p-6 {
     104    padding: 1.5rem;
     105}
     106
     107.shadow-xl {
     108    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
     109}
     110
     111.hidden {
     112    display: none;
     113    !important
     114}
    29115
    30116/* Custom styles for the plugin UI */
     117#debug-troubleshoot-alert-modal {
     118    z-index: 60 !important;
     119}
     120
     121#debug-troubleshoot-confirm-modal {
     122    z-index: 50 !important;
     123}
     124
    31125.debug-troubleshooter-wrap {
    32     margin-top: 20px;
    33 }
     126    margin-top: 20px;
     127}
     128
    34129.debug-troubleshooter-content {
    35     display: grid;
    36     grid-template-columns: 1fr;
    37     gap: 20px;
    38     margin-top: 20px;
    39 }
    40 @media (min-width: 782px) { /* WordPress admin breakpoint */
    41     .debug-troubleshooter-content {
    42         grid-template-columns: 1fr 1fr;
    43     }
    44     .full-width-section {
    45         grid-column: 1 / -1;
    46     }
    47 }
     130    display: grid;
     131    grid-template-columns: 1fr;
     132    gap: 20px;
     133    margin-top: 20px;
     134}
     135
     136@media (min-width: 782px) {
     137
     138    /* WordPress admin breakpoint */
     139    .debug-troubleshooter-content {
     140        grid-template-columns: 1fr 1fr;
     141    }
     142
     143    .full-width-section {
     144        grid-column: 1 / -1;
     145    }
     146}
     147
    48148.debug-troubleshooter-section {
    49     background: #fff;
    50     border: 1px solid #c3c4c7;
    51     box-shadow: 0 1px 1px rgba(0,0,0,.04);
    52     padding: 0;
    53     border-radius: 5px;
    54 }
     149    background: #fff;
     150    border: 1px solid #c3c4c7;
     151    box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
     152    padding: 0;
     153    border-radius: 5px;
     154}
     155
    55156.debug-troubleshooter-section.standalone-section {
    56157    padding: 20px;
    57158}
     159
    58160.section-header {
    59161    display: flex;
     
    63165    border-bottom: 1px solid #c3c4c7;
    64166}
     167
    65168.section-header h2 {
    66169    margin: 0 !important;
     
    69172    font-size: 1.3em;
    70173}
     174
    71175.section-content {
    72176    padding: 20px;
    73177}
     178
    74179.standalone-section .section-header {
    75180    padding: 0 0 15px 0;
     
    86191
    87192.debug-troubleshooter-card {
    88     background: #fff;
    89     border: 1px solid #e0e0e0;
    90     padding: 0;
    91     border-radius: 4px;
    92     margin-bottom: 15px;
    93 }
     193    background: #fff;
     194    border: 1px solid #e0e0e0;
     195    padding: 0;
     196    border-radius: 4px;
     197    margin-bottom: 15px;
     198}
     199
    94200.debug-troubleshooter-card:last-child {
    95     margin-bottom: 0;
    96 }
     201    margin-bottom: 0;
     202}
     203
    97204.debug-troubleshooter-card h3 {
    98     margin: 0;
    99     font-size: 1.1em;
    100     color: #2c3338;
    101 }
     205    margin: 0;
     206    font-size: 1.1em;
     207    color: #2c3338;
     208}
     209
    102210.debug-troubleshooter-card h4 {
    103211    font-size: 1em;
     
    108216    border-bottom: 1px solid #eee;
    109217}
     218
    110219.debug-troubleshooter-card p,
    111220.debug-troubleshooter-card li {
    112     margin-bottom: 8px;
    113     padding: 5px 0;
    114     border-bottom: 1px dashed #f0f0f0;
    115     font-size: 13px;
    116 }
     221    margin-bottom: 8px;
     222    padding: 5px 0;
     223    border-bottom: 1px dashed #f0f0f0;
     224    font-size: 13px;
     225}
     226
    117227.debug-troubleshooter-card ul {
    118     margin: 0;
    119     padding: 0;
    120     list-style: none;
    121 }
     228    margin: 0;
     229    padding: 0;
     230    list-style: none;
     231}
     232
    122233.debug-troubleshooter-card li:last-child {
    123     border-bottom: none;
     234    border-bottom: none;
    124235}
    125236
     
    153264    text-decoration: none;
    154265}
     266
    155267.info-sub-list-toggle:hover {
    156268    text-decoration: underline;
    157269}
    158270
    159 .status-active, .status-network-active, .status-inactive {
     271.status-active,
     272.status-network-active,
     273.status-inactive {
    160274    padding: 2px 6px;
    161275    border-radius: 3px;
     
    190304    background: #f9f9f9;
    191305}
     306
    192307.debug-troubleshooter-card.collapsible .card-collapsible-header {
    193     border-bottom: 1px solid #e0e0e0;
    194 }
     308    border-bottom: 1px solid #e0e0e0;
     309}
     310
    195311.card-collapsible-header:hover {
    196312    background: #f1f1f1;
    197313}
     314
    198315.card-collapsible-header .dashicons {
    199316    transition: transform 0.2s ease-in-out;
    200317}
     318
    201319.card-collapsible-header.collapsed .dashicons {
    202320    transform: rotate(-90deg);
    203321}
     322
    204323.card-collapsible-content {
    205324    padding: 15px;
    206325}
     326
    207327.card-collapsible-content.hidden {
    208328    display: none;
    209329}
     330
    210331.debug-troubleshooter-card:not(.collapsible) {
    211332    padding: 15px;
    212333}
     334
    213335.debug-troubleshooter-card:not(.collapsible) h3 {
    214336    padding-bottom: 5px;
     
    218340
    219341#troubleshoot-mode-controls {
    220     margin-top: 20px;
    221     padding-top: 20px;
    222     border-top: 1px solid #eee;
    223 }
     342    margin-top: 20px;
     343    padding-top: 20px;
     344    border-top: 1px solid #eee;
     345}
     346
    224347#troubleshoot-theme-select {
    225     width: 100%;
    226     max-width: 300px;
    227 }
     348    width: 100%;
     349    max-width: 300px;
     350}
     351
    228352.plugin-list {
    229     max-height: 400px; /* Scrollable area for plugins */
    230     overflow-y: auto;
    231     border: 1px solid #e0e0e0;
    232     border-radius: 4px;
    233     padding: 10px;
    234     background: #fefefe;
    235 }
     353    max-height: 400px;
     354    /* Scrollable area for plugins */
     355    overflow-y: auto;
     356    border: 1px solid #e0e0e0;
     357    border-radius: 4px;
     358    padding: 10px;
     359    background: #fefefe;
     360}
     361
    236362.plugin-list .plugin-item {
    237     display: flex;
    238     align-items: center;
    239     padding: 8px 10px;
    240     border-bottom: 1px solid #eee;
    241 }
     363    display: flex;
     364    align-items: center;
     365    padding: 8px 10px;
     366    border-bottom: 1px solid #eee;
     367}
     368
    242369.plugin-list .plugin-item:last-child {
    243     border-bottom: none;
    244 }
     370    border-bottom: none;
     371}
     372
    245373.plugin-list .plugin-item:hover {
    246     background-color: #f8f8f8;
    247 }
     374    background-color: #f8f8f8;
     375}
     376
    248377.plugin-list .plugin-item input[type="checkbox"] {
    249     margin-right: 10px;
    250 }
     378    margin-right: 10px;
     379}
     380
    251381.button-danger {
    252382    background: #dc3232;
    253383    border-color: #dc3232;
    254384    color: #fff;
    255     box-shadow: 0 1px 0 rgba(0,0,0,.08);
    256 }
     385    box-shadow: 0 1px 0 rgba(0, 0, 0, .08);
     386}
     387
    257388.button-danger:hover {
    258389    background: #e25b5b;
     
    260391    color: #fff;
    261392}
     393
    262394.debug-troubleshoot-notice {
    263     border-left-color: #fbc02d !important; /* Yellow for warning */
     395    border-left-color: #fbc02d !important;
     396    /* Yellow for warning */
    264397}
    265398
    266399/* Debug Log Viewer */
    267400.debug-log-viewer-wrapper {
    268     margin-top: 20px;
    269 }
     401    margin-top: 20px;
     402}
     403
    270404.debug-log-header {
    271     display: flex;
    272     justify-content: space-between;
    273     align-items: center;
    274     margin-bottom: 10px;
    275 }
     405    display: flex;
     406    justify-content: space-between;
     407    align-items: center;
     408    margin-bottom: 10px;
     409}
     410
    276411.debug-log-header h3 {
    277     margin: 0;
    278     font-size: 1.2em;
    279 }
     412    margin: 0;
     413    font-size: 1.2em;
     414}
     415
    280416#debug-log-viewer {
    281     width: 100%;
    282     background-color: #282c34;
    283     color: #abb2bf;
    284     font-family: monospace;
    285     font-size: 13px;
    286     line-height: 1.5;
    287     border: 1px solid #ccc;
    288     border-radius: 4px;
    289     padding: 10px;
    290     white-space: pre;
    291     overflow-wrap: normal;
    292     overflow-x: auto;
     417    width: 100%;
     418    background-color: #282c34;
     419    color: #abb2bf;
     420    font-family: monospace;
     421    font-size: 13px;
     422    line-height: 1.5;
     423    border: 1px solid #ccc;
     424    border-radius: 4px;
     425    padding: 10px;
     426    white-space: pre;
     427    overflow-wrap: normal;
     428    overflow-x: auto;
    293429}
    294430
  • debugger-troubleshooter/trunk/assets/js/admin.js

    r3400206 r3459095  
    1 jQuery(document).ready(function($) {
     1jQuery(document).ready(function ($) {
    22    var isTroubleshooting = debugTroubleshoot.is_troubleshooting;
    33    var troubleshootState = debugTroubleshoot.current_state;
     
    2222
    2323    // Close alert modal
    24     $('#debug-troubleshoot-alert-close').on('click', function() {
     24    $('#debug-troubleshoot-alert-close').on('click', function () {
    2525        $('#debug-troubleshoot-alert-modal').addClass('hidden');
    2626    });
    2727
    2828    // Close confirmation modal
    29     $('#debug-troubleshoot-confirm-cancel').on('click', function() {
     29    $('#debug-troubleshoot-confirm-cancel').on('click', function () {
    3030        $('#debug-troubleshoot-confirm-modal').addClass('hidden');
    3131    });
     
    3535
    3636    // Handle toggle button for troubleshooting mode
    37     $('#troubleshoot-mode-toggle').on('click', function() {
     37    $('#troubleshoot-mode-toggle').on('click', function () {
    3838        var $button = $(this);
    3939        var enableMode = !isTroubleshooting; // Determine if we are enabling or disabling
     
    4949                enable: enableMode ? 1 : 0
    5050            },
    51             success: function(response) {
     51            success: function (response) {
    5252                if (response.success) {
    5353                    showAlert(debugTroubleshoot.alert_title_success, response.data.message);
    5454                    isTroubleshooting = enableMode; // Update state
    5555                    // Refresh the page to apply cookie changes immediately
    56                     setTimeout(function() { location.reload(); }, 500);
     56                    setTimeout(function () { location.reload(); }, 500);
    5757                } else {
    5858                    showAlert(debugTroubleshoot.alert_title_error, response.data.message, 'error');
     
    6060                }
    6161            },
    62             error: function() {
     62            error: function () {
    6363                showAlert(debugTroubleshoot.alert_title_error, 'An AJAX error occurred.', 'error');
    6464                $button.prop('disabled', false);
     
    6868
    6969    // Handle toggle button for Live Debug mode
    70     $('#debug-mode-toggle').on('click', function() {
     70    $('#debug-mode-toggle').on('click', function () {
    7171        var $button = $(this);
    7272        var enableMode = !isDebugMode;
     
    8181                nonce: debugTroubleshoot.nonce,
    8282            },
    83             success: function(response) {
     83            success: function (response) {
    8484                if (response.success) {
    8585                    showAlert(debugTroubleshoot.alert_title_success, response.data.message);
     
    9595                }
    9696            },
    97             error: function() {
    98                 showAlert(debugTroubleshoot.alert_title_error, 'An AJAX error occurred.', 'error');
    99             },
    100             complete: function() {
     97            error: function () {
     98                showAlert(debugTroubleshoot.alert_title_error, 'An AJAX error occurred.', 'error');
     99            },
     100            complete: function () {
    101101                $button.prop('disabled', false);
    102102            }
     
    105105
    106106    // Handle Clear Log button - Show confirmation modal
    107     $('#clear-debug-log').on('click', function() {
     107    $('#clear-debug-log').on('click', function () {
    108108        var modal = $('#debug-troubleshoot-confirm-modal');
    109109        $('#debug-troubleshoot-confirm-title').text('Confirm Action');
     
    111111        modal.removeClass('hidden');
    112112    });
    113    
     113
    114114    // Handle the actual log clearing after confirmation
    115     $('#debug-troubleshoot-confirm-ok').on('click', function() {
     115    $('#debug-troubleshoot-confirm-ok').on('click', function () {
    116116        var $button = $('#clear-debug-log');
    117117        $button.prop('disabled', true);
     118
     119        // IMMEDIATELY hide the confirm modal before showing the alert
    118120        $('#debug-troubleshoot-confirm-modal').addClass('hidden');
    119121
    120122        $.ajax({
    121             url: debugTroubleshoot.ajax_url,
    122             type: 'POST',
    123             data: {
    124                 action: 'debug_troubleshoot_clear_debug_log',
    125                 nonce: debugTroubleshoot.nonce
    126             },
    127             success: function(response) {
     123            // ... existing ajax code ...
     124            success: function (response) {
    128125                if (response.success) {
    129126                    $('#debug-log-viewer').val('Debug log cleared successfully.');
     
    133130                }
    134131            },
    135             error: function() {
    136                 showAlert(debugTroubleshoot.alert_title_error, 'An AJAX error occurred.', 'error');
    137             },
    138             complete: function() {
     132            error: function () {
     133                showAlert(debugTroubleshoot.alert_title_error, 'An AJAX error occurred.', 'error');
     134            },
     135            complete: function () {
    139136                $button.prop('disabled', false);
    140137            }
     
    153150
    154151        // Check plugins based on troubleshooting state
    155         $('.plugin-list input[type="checkbox"]').each(function() {
     152        $('.plugin-list input[type="checkbox"]').each(function () {
    156153            var $checkbox = $(this);
    157154            var pluginFile = $checkbox.val();
     
    171168
    172169    // Handle applying troubleshooting changes
    173     $('#apply-troubleshoot-changes').on('click', function() {
     170    $('#apply-troubleshoot-changes').on('click', function () {
    174171        if (!isTroubleshooting) {
    175172            showAlert(debugTroubleshoot.alert_title_error, 'Please enter troubleshooting mode first.', 'error');
     
    182179        var selectedTheme = $('#troubleshoot-theme-select').val();
    183180        var selectedPlugins = [];
    184         $('.plugin-list input[type="checkbox"]:checked').each(function() {
     181        $('.plugin-list input[type="checkbox"]:checked').each(function () {
    185182            selectedPlugins.push($(this).val());
    186183        });
     
    195192                plugins: selectedPlugins
    196193            },
    197             success: function(response) {
     194            success: function (response) {
    198195                if (response.success) {
    199196                    showAlert(debugTroubleshoot.alert_title_success, response.data.message);
    200197                    // Refresh the page to apply cookie changes immediately
    201                     setTimeout(function() { location.reload(); }, 500);
    202                 } else {
    203                     showAlert(debugTroubleshoot.alert_title_error, response.data.message, 'error');
    204                 }
    205             },
    206             error: function() {
    207                 showAlert(debugTroubleshoot.alert_title_error, 'An AJAX error occurred.', 'error');
    208             },
    209             complete: function() {
     198                    setTimeout(function () { location.reload(); }, 500);
     199                } else {
     200                    showAlert(debugTroubleshoot.alert_title_error, response.data.message, 'error');
     201                }
     202            },
     203            error: function () {
     204                showAlert(debugTroubleshoot.alert_title_error, 'An AJAX error occurred.', 'error');
     205            },
     206            complete: function () {
    210207                $button.prop('disabled', false).text('Apply Troubleshooting Changes');
    211208            }
     
    216213
    217214    // Collapsible Site Info Cards
    218     $('.card-collapsible-header').on('click', function() {
     215    $('.card-collapsible-header').on('click', function () {
    219216        var $header = $(this);
    220217        var $content = $header.siblings('.card-collapsible-content');
    221        
     218
    222219        $content.slideToggle(200);
    223220        $header.toggleClass('collapsed');
     
    225222
    226223    // Toggle for theme/plugin sub-lists
    227     $('.info-sub-list-toggle').on('click', function(e) {
     224    $('.info-sub-list-toggle').on('click', function (e) {
    228225        e.preventDefault();
    229226        var $link = $(this);
     
    241238
    242239    // Copy Site Info to Clipboard
    243     $('#copy-site-info').on('click', function(e) {
     240    $('#copy-site-info').on('click', function (e) {
    244241        e.stopPropagation(); // Prevent any other click events
    245242        var $button = $(this);
     
    252249            var infoList = card.querySelectorAll('p, li, h4');
    253250            siteInfoText += '### ' + title + ' ###\n';
    254             infoList.forEach(function(item) {
    255                 if (item.tagName.toLowerCase() === 'h4') {
    256                     siteInfoText += '\n--- ' + item.textContent.trim() + ' ---\n';
    257                 } else {
    258                     var key = item.querySelector('strong') ? item.querySelector('strong').textContent.trim() : '';
    259                     var itemClone = item.cloneNode(true);
    260                     if (itemClone.querySelector('strong')) {
    261                         itemClone.querySelector('strong').remove();
    262                     }
    263                     var value = itemClone.textContent.trim().replace(/\s+/g, ' ');
    264                     if (key) {
    265                         siteInfoText += key + ' ' + value + '\n';
    266                     } else {
    267                         siteInfoText += value + '\n';
    268                     }
    269                 }
     251            infoList.forEach(function (item) {
     252                if (item.tagName.toLowerCase() === 'h4') {
     253                    siteInfoText += '\n--- ' + item.textContent.trim() + ' ---\n';
     254                } else {
     255                    var key = item.querySelector('strong') ? item.querySelector('strong').textContent.trim() : '';
     256                    var itemClone = item.cloneNode(true);
     257                    if (itemClone.querySelector('strong')) {
     258                        itemClone.querySelector('strong').remove();
     259                    }
     260                    var value = itemClone.textContent.trim().replace(/\s+/g, ' ');
     261                    if (key) {
     262                        siteInfoText += key + ' ' + value + '\n';
     263                    } else {
     264                        siteInfoText += value + '\n';
     265                    }
     266                }
    270267            });
    271268            siteInfoText += '\n';
     
    276273
    277274        // Use modern Clipboard API
    278         navigator.clipboard.writeText(siteInfoText.trim()).then(function() {
     275        navigator.clipboard.writeText(siteInfoText.trim()).then(function () {
    279276            var originalText = debugTroubleshoot.copy_button_text;
    280277            $button.text(debugTroubleshoot.copied_button_text);
    281             setTimeout(function() {
     278            setTimeout(function () {
    282279                $button.text(originalText);
    283280            }, 2000);
    284         }).catch(function(err) {
     281        }).catch(function (err) {
    285282            // Fallback for older browsers
    286283            var textArea = document.createElement("textarea");
     
    304301                    var originalText = debugTroubleshoot.copy_button_text;
    305302                    $button.text(debugTroubleshoot.copied_button_text);
    306                     setTimeout(function() {
     303                    setTimeout(function () {
    307304                        $button.text(originalText);
    308305                    }, 2000);
     
    317314    });
    318315    // Handle User Simulation
    319     $('#simulate-user-btn').on('click', function() {
     316    $('#simulate-user-btn').on('click', function () {
    320317        var $button = $(this);
    321318        var userId = $('#simulate-user-select').val();
     
    337334                user_id: userId
    338335            },
    339             success: function(response) {
    340                 if (response.success) {
    341                     showAlert(debugTroubleshoot.alert_title_success, response.data.message);
    342                     setTimeout(function() { location.reload(); }, 500);
     336            success: function (response) {
     337                if (response.success) {
     338                    showAlert(debugTroubleshoot.alert_title_success, response.data.message);
     339                    setTimeout(function () { location.reload(); }, 500);
    343340                } else {
    344341                    showAlert(debugTroubleshoot.alert_title_error, response.data.message, 'error');
     
    346343                }
    347344            },
    348             error: function() {
     345            error: function () {
    349346                showAlert(debugTroubleshoot.alert_title_error, 'An AJAX error occurred.', 'error');
    350347                $button.prop('disabled', false).text('Simulate User');
  • debugger-troubleshooter/trunk/debug-troubleshooter.php

    r3400548 r3459095  
    44 * Plugin URI:        https://wordpress.org/plugins/debugger-troubleshooter
    55 * Description:       A WordPress plugin for debugging and troubleshooting, allowing simulated plugin deactivation and theme switching without affecting the live site.
    6  * Version:           1.3.1
     6 * Version:           1.3.2
    77 * Author:            Jhimross
    88 * Author URI:        https://profiles.wordpress.org/jhimross
     
    1515
    1616// Exit if accessed directly.
    17 if ( ! defined( 'ABSPATH' ) ) {
     17if (!defined('ABSPATH')) {
    1818    exit;
    1919}
     
    2222 * Define plugin constants.
    2323 */
    24 define( 'DBGTBL_VERSION', '1.3.1' );
    25 define( 'DBGTBL_DIR', plugin_dir_path( __FILE__ ) );
    26 define( 'DBGTBL_URL', plugin_dir_url( __FILE__ ) );
    27 define( 'DBGTBL_BASENAME', plugin_basename( __FILE__ ) );
     24define('DBGTBL_VERSION', '1.3.2');
     25define('DBGTBL_DIR', plugin_dir_path(__FILE__));
     26define('DBGTBL_URL', plugin_dir_url(__FILE__));
     27define('DBGTBL_BASENAME', plugin_basename(__FILE__));
    2828
    2929/**
    3030 * The main plugin class.
    3131 */
    32 class Debug_Troubleshooter {
     32class Debug_Troubleshooter
     33{
    3334
    3435    /**
     
    3637     */
    3738    const TROUBLESHOOT_COOKIE = 'wp_debug_troubleshoot_mode';
    38     const DEBUG_MODE_OPTION   = 'wp_debug_troubleshoot_debug_mode';
     39    const DEBUG_MODE_OPTION = 'wp_debug_troubleshoot_debug_mode';
    3940    const SIMULATE_USER_COOKIE = 'wp_debug_troubleshoot_simulate_user';
    4041
     
    5657     * Constructor.
    5758     */
    58     public function __construct() {
     59    public function __construct()
     60    {
    5961        // Load text domain for internationalization.
    6062        // Load text domain for internationalization.
     
    6264
    6365        // Initialize admin hooks.
    64         add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
    65         add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
    66         add_action( 'wp_ajax_debug_troubleshoot_toggle_mode', array( $this, 'ajax_toggle_troubleshoot_mode' ) );
    67         add_action( 'wp_ajax_debug_troubleshoot_update_state', array( $this, 'ajax_update_troubleshoot_state' ) );
    68         add_action( 'wp_ajax_debug_troubleshoot_toggle_debug_mode', array( $this, 'ajax_toggle_debug_mode' ) );
    69         add_action( 'wp_ajax_debug_troubleshoot_clear_debug_log', array( $this, 'ajax_clear_debug_log' ) );
    70         add_action( 'wp_ajax_debug_troubleshoot_toggle_simulate_user', array( $this, 'ajax_toggle_simulate_user' ) );
     66        add_action('admin_menu', array($this, 'add_admin_menu'));
     67        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
     68        add_action('wp_ajax_debug_troubleshoot_toggle_mode', array($this, 'ajax_toggle_troubleshoot_mode'));
     69        add_action('wp_ajax_debug_troubleshoot_update_state', array($this, 'ajax_update_troubleshoot_state'));
     70        add_action('wp_ajax_debug_troubleshoot_toggle_debug_mode', array($this, 'ajax_toggle_debug_mode'));
     71        add_action('wp_ajax_debug_troubleshoot_clear_debug_log', array($this, 'ajax_clear_debug_log'));
     72        add_action('wp_ajax_debug_troubleshoot_toggle_simulate_user', array($this, 'ajax_toggle_simulate_user'));
    7173
    7274        // Core troubleshooting logic (very early hook).
    73         add_action( 'plugins_loaded', array( $this, 'init_troubleshooting_mode' ), 0 );
    74         add_action( 'plugins_loaded', array( $this, 'init_live_debug_mode' ), 0 );
    75         add_action( 'plugins_loaded', array( $this, 'init_user_simulation' ), 0 );
     75        add_action('plugins_loaded', array($this, 'init_troubleshooting_mode'), 0);
     76        add_action('plugins_loaded', array($this, 'init_live_debug_mode'), 0);
     77        add_action('plugins_loaded', array($this, 'init_user_simulation'), 0);
    7678
    7779        // Admin notice for troubleshooting mode.
    78         add_action( 'admin_notices', array( $this, 'troubleshooting_mode_notice' ) );
    79         add_action( 'admin_bar_menu', array( $this, 'admin_bar_exit_simulation' ), 999 );
     80        add_action('admin_notices', array($this, 'troubleshooting_mode_notice'));
     81        add_action('admin_bar_menu', array($this, 'admin_bar_exit_simulation'), 999);
    8082    }
    8183
     
    8587     * Add admin menu page.
    8688     */
    87     public function add_admin_menu() {
     89    public function add_admin_menu()
     90    {
    8891        add_management_page(
    89             __( 'Debugger & Troubleshooter', 'debugger-troubleshooter' ),
    90             __( 'Debugger & Troubleshooter', 'debugger-troubleshooter' ),
     92            __('Debugger & Troubleshooter', 'debugger-troubleshooter'),
     93            __('Debugger & Troubleshooter', 'debugger-troubleshooter'),
    9194            'manage_options',
    9295            'debugger-troubleshooter',
    93             array( $this, 'render_admin_page' )
     96            array($this, 'render_admin_page')
    9497        );
    9598    }
     
    100103     * @param string $hook The current admin page hook.
    101104     */
    102     public function enqueue_admin_scripts( $hook ) {
    103         if ( 'tools_page_debugger-troubleshooter' !== $hook ) {
     105    public function enqueue_admin_scripts($hook)
     106    {
     107        if ('tools_page_debugger-troubleshooter' !== $hook) {
    104108            return;
    105109        }
    106110
    107111        // Enqueue the main admin stylesheet.
    108         wp_enqueue_style( 'debug-troubleshooter-admin', DBGTBL_URL . 'assets/css/admin.css', array(), DBGTBL_VERSION );
     112        wp_enqueue_style('debug-troubleshooter-admin', DBGTBL_URL . 'assets/css/admin.css', array(), DBGTBL_VERSION);
    109113        // Enqueue the main admin JavaScript.
    110         wp_enqueue_script( 'debug-troubleshooter-admin', DBGTBL_URL . 'assets/js/admin.js', array( 'jquery' ), DBGTBL_VERSION, true );
     114        wp_enqueue_script('debug-troubleshooter-admin', DBGTBL_URL . 'assets/js/admin.js', array('jquery'), DBGTBL_VERSION, true);
    111115
    112116        // Localize script with necessary data.
     
    115119            'debugTroubleshoot',
    116120            array(
    117                 'ajax_url'            => admin_url( 'admin-ajax.php' ),
    118                 'nonce'               => wp_create_nonce( 'debug_troubleshoot_nonce' ),
    119                 'is_troubleshooting'  => $this->is_troubleshooting_active(),
    120                 'current_state'       => $this->get_troubleshoot_state(),
    121                 'is_debug_mode'       => get_option( self::DEBUG_MODE_OPTION, 'disabled' ) === 'enabled',
    122                 'active_plugins'      => get_option( 'active_plugins', array() ),
    123                 'active_sitewide_plugins' => is_multisite() ? array_keys( get_site_option( 'active_sitewide_plugins', array() ) ) : array(),
    124                 'current_theme'       => get_stylesheet(),
    125                 'alert_title_success' => __( 'Success', 'debugger-troubleshooter' ),
    126                 'alert_title_error'   => __( 'Error', 'debugger-troubleshooter' ),
    127                 'copy_button_text'    => __( 'Copy to Clipboard', 'debugger-troubleshooter' ),
    128                 'copied_button_text'  => __( 'Copied!', 'debugger-troubleshooter' ),
    129                 'show_all_text'       => __( 'Show All', 'debugger-troubleshooter' ),
    130                 'hide_text'           => __( 'Hide', 'debugger-troubleshooter' ),
    131                 'is_simulating_user'  => $this->is_simulating_user(),
     121                'ajax_url' => admin_url('admin-ajax.php'),
     122                'nonce' => wp_create_nonce('debug_troubleshoot_nonce'),
     123                'is_troubleshooting' => $this->is_troubleshooting_active(),
     124                'current_state' => $this->get_troubleshoot_state(),
     125                'is_debug_mode' => get_option(self::DEBUG_MODE_OPTION, 'disabled') === 'enabled',
     126                'active_plugins' => get_option('active_plugins', array()),
     127                'active_sitewide_plugins' => is_multisite() ? array_keys(get_site_option('active_sitewide_plugins', array())) : array(),
     128                'current_theme' => get_stylesheet(),
     129                'alert_title_success' => __('Success', 'debugger-troubleshooter'),
     130                'alert_title_error' => __('Error', 'debugger-troubleshooter'),
     131                'copy_button_text' => __('Copy to Clipboard', 'debugger-troubleshooter'),
     132                'copied_button_text' => __('Copied!', 'debugger-troubleshooter'),
     133                'show_all_text' => __('Show All', 'debugger-troubleshooter'),
     134                'hide_text' => __('Hide', 'debugger-troubleshooter'),
     135                'is_simulating_user' => $this->is_simulating_user(),
    132136            )
    133137        );
     
    137141     * Renders the admin page content.
    138142     */
    139     public function render_admin_page() {
    140         $is_debug_mode_enabled = get_option( self::DEBUG_MODE_OPTION, 'disabled' ) === 'enabled';
     143    public function render_admin_page()
     144    {
     145        $is_debug_mode_enabled = get_option(self::DEBUG_MODE_OPTION, 'disabled') === 'enabled';
    141146        ?>
    142147        <div class="wrap debug-troubleshooter-wrap">
    143             <h1 class="wp-heading-inline"><?php esc_html_e( 'Debugger & Troubleshooter', 'debugger-troubleshooter' ); ?></h1>
     148            <h1 class="wp-heading-inline"><?php esc_html_e('Debugger & Troubleshooter', 'debugger-troubleshooter'); ?></h1>
    144149            <hr class="wp-header-end">
    145150
     
    147152                <div class="debug-troubleshooter-section">
    148153                    <div class="section-header">
    149                         <h2><?php esc_html_e( 'Site Information', 'debugger-troubleshooter' ); ?></h2>
    150                         <button id="copy-site-info" class="button button-secondary"><?php esc_html_e( 'Copy to Clipboard', 'debugger-troubleshooter' ); ?></button>
     154                        <h2><?php esc_html_e('Site Information', 'debugger-troubleshooter'); ?></h2>
     155                        <button id="copy-site-info"
     156                            class="button button-secondary"><?php esc_html_e('Copy to Clipboard', 'debugger-troubleshooter'); ?></button>
    151157                    </div>
    152158                    <div id="site-info-content" class="section-content">
     
    157163                <div class="debug-troubleshooter-section standalone-section">
    158164                    <div class="section-header">
    159                         <h2><?php esc_html_e( 'Troubleshooting Mode', 'debugger-troubleshooter' ); ?></h2>
    160                         <button id="troubleshoot-mode-toggle" class="button button-large <?php echo $this->is_troubleshooting_active() ? 'button-danger' : 'button-primary'; ?>">
    161                             <?php echo $this->is_troubleshooting_active() ? esc_html__( 'Exit Troubleshooting Mode', 'debugger-troubleshooter' ) : esc_html__( 'Enter Troubleshooting Mode', 'debugger-troubleshooter' ); ?>
     165                        <h2><?php esc_html_e('Troubleshooting Mode', 'debugger-troubleshooter'); ?></h2>
     166                        <button id="troubleshoot-mode-toggle"
     167                            class="button button-large <?php echo $this->is_troubleshooting_active() ? 'button-danger' : 'button-primary'; ?>">
     168                            <?php echo $this->is_troubleshooting_active() ? esc_html__('Exit Troubleshooting Mode', 'debugger-troubleshooter') : esc_html__('Enter Troubleshooting Mode', 'debugger-troubleshooter'); ?>
    162169                        </button>
    163170                    </div>
    164171                    <div class="section-content">
    165172                        <p class="description">
    166                             <?php esc_html_e( 'Enter Troubleshooting Mode to simulate deactivating plugins and switching themes without affecting your live website for other visitors. This mode uses browser cookies and only applies to your session.', 'debugger-troubleshooter' ); ?>
     173                            <?php esc_html_e('Enter Troubleshooting Mode to simulate deactivating plugins and switching themes without affecting your live website for other visitors. This mode uses browser cookies and only applies to your session.', 'debugger-troubleshooter'); ?>
    167174                        </p>
    168175
    169                         <div id="troubleshoot-mode-controls" class="troubleshoot-mode-controls <?php echo $this->is_troubleshooting_active() ? '' : 'hidden'; ?>">
     176                        <div id="troubleshoot-mode-controls"
     177                            class="troubleshoot-mode-controls <?php echo $this->is_troubleshooting_active() ? '' : 'hidden'; ?>">
    170178                            <div class="debug-troubleshooter-card">
    171                                 <h3><?php esc_html_e( 'Simulate Theme Switch', 'debugger-troubleshooter' ); ?></h3>
    172                                 <p class="description"><?php esc_html_e( 'Select a theme to preview. This will change the theme for your session only.', 'debugger-troubleshooter' ); ?></p>
     179                                <h3><?php esc_html_e('Simulate Theme Switch', 'debugger-troubleshooter'); ?></h3>
     180                                <p class="description">
     181                                    <?php esc_html_e('Select a theme to preview. This will change the theme for your session only.', 'debugger-troubleshooter'); ?>
     182                                </p>
    173183                                <select id="troubleshoot-theme-select" class="regular-text">
    174184                                    <?php
    175                                     $themes           = wp_get_themes();
    176                                     $current_active   = get_stylesheet();
    177                                     $troubleshoot_theme = $this->troubleshoot_state && ! empty( $this->troubleshoot_state['theme'] ) ? $this->troubleshoot_state['theme'] : $current_active;
    178 
    179                                     foreach ( $themes as $slug => $theme ) {
    180                                         echo '<option value="' . esc_attr( $slug ) . '"' . selected( $slug, $troubleshoot_theme, false ) . '>' . esc_html( $theme->get( 'Name' ) ) . '</option>';
     185                                    $themes = wp_get_themes();
     186                                    $current_active = get_stylesheet();
     187                                    $troubleshoot_theme = $this->troubleshoot_state && !empty($this->troubleshoot_state['theme']) ? $this->troubleshoot_state['theme'] : $current_active;
     188
     189                                    foreach ($themes as $slug => $theme) {
     190                                        echo '<option value="' . esc_attr($slug) . '"' . selected($slug, $troubleshoot_theme, false) . '>' . esc_html($theme->get('Name')) . '</option>';
    181191                                    }
    182192                                    ?>
     
    185195
    186196                            <div class="debug-troubleshooter-card">
    187                                 <h3><?php esc_html_e( 'Simulate Plugin Deactivation', 'debugger-troubleshooter' ); ?></h3>
    188                                 <p class="description"><?php esc_html_e( 'Check plugins to simulate deactivating them for your session. Unchecked plugins will remain active.', 'debugger-troubleshooter' ); ?></p>
     197                                <h3><?php esc_html_e('Simulate Plugin Deactivation', 'debugger-troubleshooter'); ?></h3>
     198                                <p class="description">
     199                                    <?php esc_html_e('Check plugins to simulate deactivating them for your session. Unchecked plugins will remain active.', 'debugger-troubleshooter'); ?>
     200                                </p>
    189201                                <?php
    190                                 $plugins                = get_plugins();
    191                                 $troubleshoot_active_plugins = $this->troubleshoot_state && ! empty( $this->troubleshoot_state['plugins'] ) ? $this->troubleshoot_state['plugins'] : get_option( 'active_plugins', array() );
    192                                 $troubleshoot_active_sitewide_plugins = $this->troubleshoot_state && ! empty( $this->troubleshoot_state['sitewide_plugins'] ) ? $this->troubleshoot_state['sitewide_plugins'] : ( is_multisite() ? array_keys( get_site_option( 'active_sitewide_plugins', array() ) ) : array() );
    193 
    194                                 if ( ! empty( $plugins ) ) {
     202                                $plugins = get_plugins();
     203                                $troubleshoot_active_plugins = $this->troubleshoot_state && !empty($this->troubleshoot_state['plugins']) ? $this->troubleshoot_state['plugins'] : get_option('active_plugins', array());
     204                                $troubleshoot_active_sitewide_plugins = $this->troubleshoot_state && !empty($this->troubleshoot_state['sitewide_plugins']) ? $this->troubleshoot_state['sitewide_plugins'] : (is_multisite() ? array_keys(get_site_option('active_sitewide_plugins', array())) : array());
     205
     206                                if (!empty($plugins)) {
    195207                                    echo '<div class="plugin-list">';
    196                                     foreach ( $plugins as $plugin_file => $plugin_data ) {
    197                                         $is_active_for_site = in_array( $plugin_file, get_option( 'active_plugins', array() ) ) || ( is_multisite() && array_key_exists( $plugin_file, get_site_option( 'active_sitewide_plugins', array() ) ) );
     208                                    foreach ($plugins as $plugin_file => $plugin_data) {
     209                                        $is_active_for_site = in_array($plugin_file, get_option('active_plugins', array())) || (is_multisite() && array_key_exists($plugin_file, get_site_option('active_sitewide_plugins', array())));
    198210                                        $is_checked_in_troubleshoot_mode = (
    199                                             in_array( $plugin_file, $troubleshoot_active_plugins ) ||
    200                                             ( is_multisite() && in_array( $plugin_file, $troubleshoot_active_sitewide_plugins ) )
     211                                            in_array($plugin_file, $troubleshoot_active_plugins) ||
     212                                            (is_multisite() && in_array($plugin_file, $troubleshoot_active_sitewide_plugins))
    201213                                        );
    202214                                        ?>
    203215                                        <label class="plugin-item flex items-center p-2 rounded-md transition-colors duration-200">
    204                                             <input type="checkbox" name="troubleshoot_plugins[]" value="<?php echo esc_attr( $plugin_file ); ?>" <?php checked( $is_checked_in_troubleshoot_mode ); ?> data-original-state="<?php echo $is_active_for_site ? 'active' : 'inactive'; ?>">
     216                                            <input type="checkbox" name="troubleshoot_plugins[]"
     217                                                value="<?php echo esc_attr($plugin_file); ?>" <?php checked($is_checked_in_troubleshoot_mode); ?>
     218                                                data-original-state="<?php echo $is_active_for_site ? 'active' : 'inactive'; ?>">
    205219                                            <span class="ml-2">
    206                                                 <strong><?php echo esc_html( $plugin_data['Name'] ); ?></strong>
    207                                                 <br><small><?php echo esc_html( $plugin_data['Version'] ); ?> | <?php echo esc_html( $plugin_data['AuthorName'] ); ?></small>
     220                                                <strong><?php echo esc_html($plugin_data['Name']); ?></strong>
     221                                                <br><small><?php echo esc_html($plugin_data['Version']); ?> |
     222                                                    <?php echo esc_html($plugin_data['AuthorName']); ?></small>
    208223                                            </span>
    209224                                        </label>
     
    212227                                    echo '</div>';
    213228                                } else {
    214                                     echo '<p>' . esc_html__( 'No plugins found.', 'debugger-troubleshooter' ) . '</p>';
     229                                    echo '<p>' . esc_html__('No plugins found.', 'debugger-troubleshooter') . '</p>';
    215230                                }
    216231                                ?>
    217232                            </div>
    218233
    219                             <button id="apply-troubleshoot-changes" class="button button-primary button-large"><?php esc_html_e( 'Apply Troubleshooting Changes', 'debugger-troubleshooter' ); ?></button>
    220                             <p class="description"><?php esc_html_e( 'Applying changes will refresh the page to reflect your simulated theme and plugin states.', 'debugger-troubleshooter' ); ?></p>
     234                            <button id="apply-troubleshoot-changes"
     235                                class="button button-primary button-large"><?php esc_html_e('Apply Troubleshooting Changes', 'debugger-troubleshooter'); ?></button>
     236                            <p class="description">
     237                                <?php esc_html_e('Applying changes will refresh the page to reflect your simulated theme and plugin states.', 'debugger-troubleshooter'); ?>
     238                            </p>
    221239                        </div><!-- #troubleshoot-mode-controls -->
    222240                    </div>
     
    227245                <div class="debug-troubleshooter-section standalone-section full-width-section">
    228246                    <div class="section-header">
    229                         <h2><?php esc_html_e( 'User Role Simulator', 'debugger-troubleshooter' ); ?></h2>
     247                        <h2><?php esc_html_e('User Role Simulator', 'debugger-troubleshooter'); ?></h2>
    230248                    </div>
    231249                    <div class="section-content">
    232250                        <p class="description">
    233                             <?php esc_html_e( 'View the site as a specific user or role. This allows you to test permissions and user-specific content without logging out. This only affects your session.', 'debugger-troubleshooter' ); ?>
     251                            <?php esc_html_e('View the site as a specific user or role. This allows you to test permissions and user-specific content without logging out. This only affects your session.', 'debugger-troubleshooter'); ?>
    234252                        </p>
    235253                        <?php $this->render_user_simulation_section(); ?>
     
    239257                <div class="debug-troubleshooter-section standalone-section full-width-section">
    240258                    <div class="section-header">
    241                         <h2><?php esc_html_e( 'Live Debugging', 'debugger-troubleshooter' ); ?></h2>
    242                         <button id="debug-mode-toggle" class="button button-large <?php echo $is_debug_mode_enabled ? 'button-danger' : 'button-primary'; ?>">
    243                             <?php echo $is_debug_mode_enabled ? esc_html__( 'Disable Live Debug', 'debugger-troubleshooter' ) : esc_html__( 'Enable Live Debug', 'debugger-troubleshooter' ); ?>
     259                        <h2><?php esc_html_e('Live Debugging', 'debugger-troubleshooter'); ?></h2>
     260                        <button id="debug-mode-toggle"
     261                            class="button button-large <?php echo $is_debug_mode_enabled ? 'button-danger' : 'button-primary'; ?>">
     262                            <?php echo $is_debug_mode_enabled ? esc_html__('Disable Live Debug', 'debugger-troubleshooter') : esc_html__('Enable Live Debug', 'debugger-troubleshooter'); ?>
    244263                        </button>
    245264                    </div>
    246265                    <div class="section-content">
    247266                        <p class="description">
    248                             <?php esc_html_e( 'Enable this to turn on WP_DEBUG without editing your wp-config.php file. Errors will be logged to the debug.log file below, not displayed on the site.', 'debugger-troubleshooter' ); ?>
     267                            <?php esc_html_e('Enable this to turn on WP_DEBUG without editing your wp-config.php file. Errors will be logged to the debug.log file below, not displayed on the site.', 'debugger-troubleshooter'); ?>
    249268                        </p>
    250269
    251270                        <div class="debug-log-viewer-wrapper">
    252271                            <div class="debug-log-header">
    253                                 <h3><?php esc_html_e( 'Debug Log Viewer', 'debugger-troubleshooter' ); ?></h3>
    254                                 <button id="clear-debug-log" class="button button-secondary"><?php esc_html_e( 'Clear Log', 'debugger-troubleshooter' ); ?></button>
     272                                <h3><?php esc_html_e('Debug Log Viewer', 'debugger-troubleshooter'); ?></h3>
     273                                <button id="clear-debug-log"
     274                                    class="button button-secondary"><?php esc_html_e('Clear Log', 'debugger-troubleshooter'); ?></button>
    255275                            </div>
    256                             <textarea id="debug-log-viewer" readonly class="large-text" rows="15"><?php echo esc_textarea( $this->get_debug_log_content() ); ?></textarea>
     276                            <textarea id="debug-log-viewer" readonly class="large-text"
     277                                rows="15"><?php echo esc_textarea($this->get_debug_log_content()); ?></textarea>
    257278                        </div>
    258279                    </div>
     
    262283        </div>
    263284
    264         <div id="debug-troubleshoot-alert-modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 flex items-center justify-center z-50">
     285        <div id="debug-troubleshoot-alert-modal"
     286            class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 flex items-center justify-center z-50">
    265287            <div class="bg-white p-6 rounded-lg shadow-xl max-w-sm w-full text-center">
    266288                <h3 id="debug-troubleshoot-alert-title" class="text-xl font-bold mb-4"></h3>
    267289                <p id="debug-troubleshoot-alert-message" class="text-gray-700 mb-6"></p>
    268                 <button id="debug-troubleshoot-alert-close" class="button button-primary"><?php esc_html_e( 'OK', 'debugger-troubleshooter' ); ?></button>
     290                <button id="debug-troubleshoot-alert-close"
     291                    class="button button-primary"><?php esc_html_e('OK', 'debugger-troubleshooter'); ?></button>
    269292            </div>
    270293        </div>
    271294
    272         <div id="debug-troubleshoot-confirm-modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 flex items-center justify-center z-50">
     295        <div id="debug-troubleshoot-confirm-modal"
     296            class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 flex items-center justify-center z-50">
    273297            <div class="bg-white p-6 rounded-lg shadow-xl max-w-sm w-full text-center">
    274298                <h3 id="debug-troubleshoot-confirm-title" class="text-xl font-bold mb-4"></h3>
    275299                <p id="debug-troubleshoot-confirm-message" class="text-gray-700 mb-6"></p>
    276300                <div class="confirm-buttons">
    277                     <button id="debug-troubleshoot-confirm-cancel" class="button button-secondary"><?php esc_html_e( 'Cancel', 'debugger-troubleshooter' ); ?></button>
    278                     <button id="debug-troubleshoot-confirm-ok" class="button button-danger"><?php esc_html_e( 'Confirm', 'debugger-troubleshooter' ); ?></button>
     301                    <button id="debug-troubleshoot-confirm-cancel"
     302                        class="button button-secondary"><?php esc_html_e('Cancel', 'debugger-troubleshooter'); ?></button>
     303                    <button id="debug-troubleshoot-confirm-ok"
     304                        class="button button-danger"><?php esc_html_e('Confirm', 'debugger-troubleshooter'); ?></button>
    279305                </div>
    280306            </div>
     
    287313     * Displays useful site information.
    288314     */
    289     private function display_site_info() {
     315    private function display_site_info()
     316    {
    290317        global $wpdb;
    291318        echo '<div class="site-info-grid">';
     
    293320        // WordPress Information Card
    294321        echo '<div class="debug-troubleshooter-card collapsible">';
    295         echo '<div class="card-collapsible-header collapsed"><h3>' . esc_html__( 'WordPress Information', 'debugger-troubleshooter' ) . '</h3><span class="dashicons dashicons-arrow-down-alt2"></span></div>';
     322        echo '<div class="card-collapsible-header collapsed"><h3>' . esc_html__('WordPress Information', 'debugger-troubleshooter') . '</h3><span class="dashicons dashicons-arrow-down-alt2"></span></div>';
    296323        echo '<div class="card-collapsible-content hidden">';
    297         echo '<p><strong>' . esc_html__( 'WordPress Version:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( get_bloginfo( 'version' ) ) . '</p>';
    298         echo '<p><strong>' . esc_html__( 'Site Language:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( get_locale() ) . '</p>';
    299         echo '<p><strong>' . esc_html__( 'Permalink Structure:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( get_option( 'permalink_structure' ) ?: 'Plain' ) . '</p>';
    300         echo '<p><strong>' . esc_html__( 'Multisite:', 'debugger-troubleshooter' ) . '</strong> ' . ( is_multisite() ? 'Yes' : 'No' ) . '</p>';
     324        echo '<p><strong>' . esc_html__('WordPress Version:', 'debugger-troubleshooter') . '</strong> ' . esc_html(get_bloginfo('version')) . '</p>';
     325        echo '<p><strong>' . esc_html__('Site Language:', 'debugger-troubleshooter') . '</strong> ' . esc_html(get_locale()) . '</p>';
     326        echo '<p><strong>' . esc_html__('Permalink Structure:', 'debugger-troubleshooter') . '</strong> ' . esc_html(get_option('permalink_structure') ?: 'Plain') . '</p>';
     327        echo '<p><strong>' . esc_html__('Multisite:', 'debugger-troubleshooter') . '</strong> ' . (is_multisite() ? 'Yes' : 'No') . '</p>';
    301328
    302329        // Themes List
    303         $all_themes            = wp_get_themes();
    304         $active_theme_obj      = wp_get_theme();
    305         $inactive_themes_count = count( $all_themes ) - 1;
    306 
    307         echo '<h4>' . esc_html__( 'Themes', 'debugger-troubleshooter' ) . '</h4>';
    308         echo '<p><strong>' . esc_html__( 'Active Theme:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( $active_theme_obj->get( 'Name' ) ) . ' (' . esc_html( $active_theme_obj->get( 'Version' ) ) . ')</p>';
    309         if ( $inactive_themes_count > 0 ) {
    310             echo '<p><strong>' . esc_html__( 'Inactive Themes:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( $inactive_themes_count ) . ' <a href="#" class="info-sub-list-toggle" data-target="themes-list">' . esc_html__( 'Show All', 'debugger-troubleshooter' ) . '</a></p>';
    311         }
    312 
    313         if ( ! empty( $all_themes ) ) {
     330        $all_themes = wp_get_themes();
     331        $active_theme_obj = wp_get_theme();
     332        $inactive_themes_count = count($all_themes) - 1;
     333
     334        echo '<h4>' . esc_html__('Themes', 'debugger-troubleshooter') . '</h4>';
     335        echo '<p><strong>' . esc_html__('Active Theme:', 'debugger-troubleshooter') . '</strong> ' . esc_html($active_theme_obj->get('Name')) . ' (' . esc_html($active_theme_obj->get('Version')) . ')</p>';
     336        if ($inactive_themes_count > 0) {
     337            echo '<p><strong>' . esc_html__('Inactive Themes:', 'debugger-troubleshooter') . '</strong> ' . esc_html($inactive_themes_count) . ' <a href="#" class="info-sub-list-toggle" data-target="themes-list">' . esc_html__('Show All', 'debugger-troubleshooter') . '</a></p>';
     338        }
     339
     340        if (!empty($all_themes)) {
    314341            echo '<ul id="themes-list" class="info-sub-list hidden">';
    315             foreach ( $all_themes as $stylesheet => $theme ) {
    316                 $status = ( $stylesheet === $active_theme_obj->get_stylesheet() ) ? '<span class="status-active">Active</span>' : '<span class="status-inactive">Inactive</span>';
    317                 echo '<li><div>' . esc_html( $theme->get( 'Name' ) ) . ' (' . esc_html( $theme->get( 'Version' ) ) . ')</div>' . wp_kses_post( $status ) . '</li>';
     342            foreach ($all_themes as $stylesheet => $theme) {
     343                $status = ($stylesheet === $active_theme_obj->get_stylesheet()) ? '<span class="status-active">Active</span>' : '<span class="status-inactive">Inactive</span>';
     344                echo '<li><div>' . esc_html($theme->get('Name')) . ' (' . esc_html($theme->get('Version')) . ')</div>' . wp_kses_post($status) . '</li>';
    318345            }
    319346            echo '</ul>';
     
    321348
    322349        // Plugins List
    323         $all_plugins            = get_plugins();
    324         $active_plugins         = (array) get_option( 'active_plugins', array() );
    325         $network_active_plugins = is_multisite() ? array_keys( get_site_option( 'active_sitewide_plugins', array() ) ) : array();
    326         $inactive_plugins_count = count( $all_plugins ) - count( $active_plugins ) - count( $network_active_plugins );
    327 
    328         echo '<h4>' . esc_html__( 'Plugins', 'debugger-troubleshooter' ) . '</h4>';
    329         echo '<p><strong>' . esc_html__( 'Active Plugins:', 'debugger-troubleshooter' ) . '</strong> ' . count( $active_plugins ) . '</p>';
    330         if ( is_multisite() ) {
    331             echo '<p><strong>' . esc_html__( 'Network Active Plugins:', 'debugger-troubleshooter' ) . '</strong> ' . count( $network_active_plugins ) . '</p>';
    332         }
    333         echo '<p><strong>' . esc_html__( 'Inactive Plugins:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( $inactive_plugins_count ) . ' <a href="#" class="info-sub-list-toggle" data-target="plugins-list">' . esc_html__( 'Show All', 'debugger-troubleshooter' ) . '</a></p>';
    334 
    335         if ( ! empty( $all_plugins ) ) {
     350        $all_plugins = get_plugins();
     351        $active_plugins = (array) get_option('active_plugins', array());
     352        $network_active_plugins = is_multisite() ? array_keys(get_site_option('active_sitewide_plugins', array())) : array();
     353        $inactive_plugins_count = count($all_plugins) - count($active_plugins) - count($network_active_plugins);
     354
     355        echo '<h4>' . esc_html__('Plugins', 'debugger-troubleshooter') . '</h4>';
     356        echo '<p><strong>' . esc_html__('Active Plugins:', 'debugger-troubleshooter') . '</strong> ' . count($active_plugins) . '</p>';
     357        if (is_multisite()) {
     358            echo '<p><strong>' . esc_html__('Network Active Plugins:', 'debugger-troubleshooter') . '</strong> ' . count($network_active_plugins) . '</p>';
     359        }
     360        echo '<p><strong>' . esc_html__('Inactive Plugins:', 'debugger-troubleshooter') . '</strong> ' . esc_html($inactive_plugins_count) . ' <a href="#" class="info-sub-list-toggle" data-target="plugins-list">' . esc_html__('Show All', 'debugger-troubleshooter') . '</a></p>';
     361
     362        if (!empty($all_plugins)) {
    336363            echo '<ul id="plugins-list" class="info-sub-list hidden">';
    337             foreach ( $all_plugins as $plugin_file => $plugin_data ) {
     364            foreach ($all_plugins as $plugin_file => $plugin_data) {
    338365                $status = '<span class="status-inactive">Inactive</span>';
    339                 if ( in_array( $plugin_file, $active_plugins, true ) ) {
     366                if (in_array($plugin_file, $active_plugins, true)) {
    340367                    $status = '<span class="status-active">Active</span>';
    341                 } elseif ( in_array( $plugin_file, $network_active_plugins, true ) ) {
     368                } elseif (in_array($plugin_file, $network_active_plugins, true)) {
    342369                    $status = '<span class="status-network-active">Network Active</span>';
    343370                }
    344                 echo '<li><div>' . esc_html( $plugin_data['Name'] ) . ' (' . esc_html( $plugin_data['Version'] ) . ')</div>' . wp_kses_post( $status ) . '</li>';
     371                echo '<li><div>' . esc_html($plugin_data['Name']) . ' (' . esc_html($plugin_data['Version']) . ')</div>' . wp_kses_post($status) . '</li>';
    345372            }
    346373            echo '</ul>';
     
    351378        // PHP Information Card
    352379        echo '<div class="debug-troubleshooter-card collapsible">';
    353         echo '<div class="card-collapsible-header collapsed"><h3>' . esc_html__( 'PHP Information', 'debugger-troubleshooter' ) . '</h3><span class="dashicons dashicons-arrow-down-alt2"></span></div>';
     380        echo '<div class="card-collapsible-header collapsed"><h3>' . esc_html__('PHP Information', 'debugger-troubleshooter') . '</h3><span class="dashicons dashicons-arrow-down-alt2"></span></div>';
    354381        echo '<div class="card-collapsible-content hidden">';
    355         echo '<p><strong>' . esc_html__( 'PHP Version:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( phpversion() ) . '</p>';
    356         echo '<p><strong>' . esc_html__( 'Memory Limit:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( ini_get( 'memory_limit' ) ) . '</p>';
    357         echo '<p><strong>' . esc_html__( 'Peak Memory Usage:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( size_format( memory_get_peak_usage( true ) ) ) . '</p>';
    358         echo '<p><strong>' . esc_html__( 'Post Max Size:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( ini_get( 'post_max_size' ) ) . '</p>';
    359         echo '<p><strong>' . esc_html__( 'Upload Max Filesize:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( ini_get( 'upload_max_filesize' ) ) . '</p>';
    360         echo '<p><strong>' . esc_html__( 'Max Execution Time:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( ini_get( 'max_execution_time' ) ) . 's</p>';
    361         echo '<p><strong>' . esc_html__( 'Max Input Vars:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( ini_get( 'max_input_vars' ) ) . '</p>';
    362         echo '<p><strong>' . esc_html__( 'cURL Extension:', 'debugger-troubleshooter' ) . '</strong> ' . ( extension_loaded( 'curl' ) ? 'Enabled' : 'Disabled' ) . '</p>';
    363         echo '<p><strong>' . esc_html__( 'GD Library:', 'debugger-troubleshooter' ) . '</strong> ' . ( extension_loaded( 'gd' ) ? 'Enabled' : 'Disabled' ) . '</p>';
    364         echo '<p><strong>' . esc_html__( 'Imagick Library:', 'debugger-troubleshooter' ) . '</strong> ' . ( extension_loaded( 'imagick' ) ? 'Enabled' : 'Disabled' ) . '</p>';
     382        echo '<p><strong>' . esc_html__('PHP Version:', 'debugger-troubleshooter') . '</strong> ' . esc_html(phpversion()) . '</p>';
     383        echo '<p><strong>' . esc_html__('Memory Limit:', 'debugger-troubleshooter') . '</strong> ' . esc_html(ini_get('memory_limit')) . '</p>';
     384        echo '<p><strong>' . esc_html__('Peak Memory Usage:', 'debugger-troubleshooter') . '</strong> ' . esc_html(size_format(memory_get_peak_usage(true))) . '</p>';
     385        echo '<p><strong>' . esc_html__('Post Max Size:', 'debugger-troubleshooter') . '</strong> ' . esc_html(ini_get('post_max_size')) . '</p>';
     386        echo '<p><strong>' . esc_html__('Upload Max Filesize:', 'debugger-troubleshooter') . '</strong> ' . esc_html(ini_get('upload_max_filesize')) . '</p>';
     387        echo '<p><strong>' . esc_html__('Max Execution Time:', 'debugger-troubleshooter') . '</strong> ' . esc_html(ini_get('max_execution_time')) . 's</p>';
     388        echo '<p><strong>' . esc_html__('Max Input Vars:', 'debugger-troubleshooter') . '</strong> ' . esc_html(ini_get('max_input_vars')) . '</p>';
     389        echo '<p><strong>' . esc_html__('cURL Extension:', 'debugger-troubleshooter') . '</strong> ' . (extension_loaded('curl') ? 'Enabled' : 'Disabled') . '</p>';
     390        echo '<p><strong>' . esc_html__('GD Library:', 'debugger-troubleshooter') . '</strong> ' . (extension_loaded('gd') ? 'Enabled' : 'Disabled') . '</p>';
     391        echo '<p><strong>' . esc_html__('Imagick Library:', 'debugger-troubleshooter') . '</strong> ' . (extension_loaded('imagick') ? 'Enabled' : 'Disabled') . '</p>';
    365392        echo '</div></div>';
    366393
    367394        // Database Information Card
    368395        echo '<div class="debug-troubleshooter-card collapsible">';
    369         echo '<div class="card-collapsible-header collapsed"><h3>' . esc_html__( 'Database Information', 'debugger-troubleshooter' ) . '</h3><span class="dashicons dashicons-arrow-down-alt2"></span></div>';
     396        echo '<div class="card-collapsible-header collapsed"><h3>' . esc_html__('Database Information', 'debugger-troubleshooter') . '</h3><span class="dashicons dashicons-arrow-down-alt2"></span></div>';
    370397        echo '<div class="card-collapsible-content hidden">';
    371         echo '<p><strong>' . esc_html__( 'Database Engine:', 'debugger-troubleshooter' ) . '</strong> MySQL</p>';
     398        echo '<p><strong>' . esc_html__('Database Engine:', 'debugger-troubleshooter') . '</strong> MySQL</p>';
    372399        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    373400        // Direct query is necessary to get the MySQL server version. Caching is not beneficial for this one-off diagnostic read.
    374         echo '<p><strong>' . esc_html__( 'MySQL Version:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( $wpdb->get_var( 'SELECT VERSION()' ) ) . '</p>';
     401        echo '<p><strong>' . esc_html__('MySQL Version:', 'debugger-troubleshooter') . '</strong> ' . esc_html($wpdb->get_var('SELECT VERSION()')) . '</p>';
    375402        // phpcs:enable
    376         echo '<p><strong>' . esc_html__( 'DB Name:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( DB_NAME ) . '</p>';
    377         echo '<p><strong>' . esc_html__( 'DB Host:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( DB_HOST ) . '</p>';
    378         echo '<p><strong>' . esc_html__( 'DB Charset:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( DB_CHARSET ) . '</p>';
    379         echo '<p><strong>' . esc_html__( 'DB Collate:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( DB_COLLATE ) . '</p>';
     403        echo '<p><strong>' . esc_html__('DB Name:', 'debugger-troubleshooter') . '</strong> ' . esc_html(DB_NAME) . '</p>';
     404        echo '<p><strong>' . esc_html__('DB Host:', 'debugger-troubleshooter') . '</strong> ' . esc_html(DB_HOST) . '</p>';
     405        echo '<p><strong>' . esc_html__('DB Charset:', 'debugger-troubleshooter') . '</strong> ' . esc_html(DB_CHARSET) . '</p>';
     406        echo '<p><strong>' . esc_html__('DB Collate:', 'debugger-troubleshooter') . '</strong> ' . esc_html(DB_COLLATE) . '</p>';
    380407        echo '</div></div>';
    381408
    382409        // Server Information Card
    383410        echo '<div class="debug-troubleshooter-card collapsible">';
    384         echo '<div class="card-collapsible-header collapsed"><h3>' . esc_html__( 'Server Information', 'debugger-troubleshooter' ) . '</h3><span class="dashicons dashicons-arrow-down-alt2"></span></div>';
     411        echo '<div class="card-collapsible-header collapsed"><h3>' . esc_html__('Server Information', 'debugger-troubleshooter') . '</h3><span class="dashicons dashicons-arrow-down-alt2"></span></div>';
    385412        echo '<div class="card-collapsible-content hidden">';
    386         echo '<p><strong>' . esc_html__( 'Web Server:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : 'N/A' ) . '</p>';
    387         echo '<p><strong>' . esc_html__( 'Server Protocol:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( isset( $_SERVER['SERVER_PROTOCOL'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_PROTOCOL'] ) ) : 'N/A' ) . '</p>';
    388         echo '<p><strong>' . esc_html__( 'Server Address:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( isset( $_SERVER['SERVER_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_ADDR'] ) ) : 'N/A' ) . '</p>';
    389         echo '<p><strong>' . esc_html__( 'Document Root:', 'debugger-troubleshooter' ) . '</strong> ' . esc_html( isset( $_SERVER['DOCUMENT_ROOT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['DOCUMENT_ROOT'] ) ) : 'N/A' ) . '</p>';
    390         echo '<p><strong>' . esc_html__( 'HTTPS:', 'debugger-troubleshooter' ) . '</strong> ' . ( is_ssl() ? 'On' : 'Off' ) . '</p>';
     413        echo '<p><strong>' . esc_html__('Web Server:', 'debugger-troubleshooter') . '</strong> ' . esc_html(isset($_SERVER['SERVER_SOFTWARE']) ? sanitize_text_field(wp_unslash($_SERVER['SERVER_SOFTWARE'])) : 'N/A') . '</p>';
     414        echo '<p><strong>' . esc_html__('Server Protocol:', 'debugger-troubleshooter') . '</strong> ' . esc_html(isset($_SERVER['SERVER_PROTOCOL']) ? sanitize_text_field(wp_unslash($_SERVER['SERVER_PROTOCOL'])) : 'N/A') . '</p>';
     415        echo '<p><strong>' . esc_html__('Server Address:', 'debugger-troubleshooter') . '</strong> ' . esc_html(isset($_SERVER['SERVER_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['SERVER_ADDR'])) : 'N/A') . '</p>';
     416        echo '<p><strong>' . esc_html__('Document Root:', 'debugger-troubleshooter') . '</strong> ' . esc_html(isset($_SERVER['DOCUMENT_ROOT']) ? sanitize_text_field(wp_unslash($_SERVER['DOCUMENT_ROOT'])) : 'N/A') . '</p>';
     417        echo '<p><strong>' . esc_html__('HTTPS:', 'debugger-troubleshooter') . '</strong> ' . (is_ssl() ? 'On' : 'Off') . '</p>';
    391418        echo '</div></div>';
    392419
    393420        // WordPress Constants Card
    394421        echo '<div class="debug-troubleshooter-card collapsible">';
    395         echo '<div class="card-collapsible-header collapsed"><h3>' . esc_html__( 'WordPress Constants', 'debugger-troubleshooter' ) . '</h3><span class="dashicons dashicons-arrow-down-alt2"></span></div>';
     422        echo '<div class="card-collapsible-header collapsed"><h3>' . esc_html__('WordPress Constants', 'debugger-troubleshooter') . '</h3><span class="dashicons dashicons-arrow-down-alt2"></span></div>';
    396423        echo '<div class="card-collapsible-content hidden">';
    397424        echo '<ul>';
     
    416443            'FS_CHMOD_FILE',
    417444        );
    418         foreach ( $wp_constants as $constant ) {
    419             echo '<li><strong>' . esc_html( $constant ) . ':</strong> ';
    420             if ( defined( $constant ) ) {
    421                 $value = constant( $constant );
    422                 if ( is_bool( $value ) ) {
    423                     echo esc_html( $value ? 'true' : 'false' );
    424                 } elseif ( is_numeric( $value ) ) {
    425                     echo esc_html( $value );
    426                 } elseif ( is_string( $value ) && ! empty( $value ) ) {
    427                     echo '"' . esc_html( $value ) . '"';
     445        foreach ($wp_constants as $constant) {
     446            echo '<li><strong>' . esc_html($constant) . ':</strong> ';
     447            if (defined($constant)) {
     448                $value = constant($constant);
     449                if (is_bool($value)) {
     450                    echo esc_html($value ? 'true' : 'false');
     451                } elseif (is_numeric($value)) {
     452                    echo esc_html($value);
     453                } elseif (is_string($value) && !empty($value)) {
     454                    echo '"' . esc_html($value) . '"';
    428455                } else {
    429                     echo esc_html__( 'Defined but empty/non-scalar', 'debugger-troubleshooter' );
     456                    echo esc_html__('Defined but empty/non-scalar', 'debugger-troubleshooter');
    430457                }
    431458            } else {
    432                 echo esc_html__( 'Undefined', 'debugger-troubleshooter' );
     459                echo esc_html__('Undefined', 'debugger-troubleshooter');
    433460            }
    434461            echo '</li>';
     
    444471     * This hook runs very early to ensure filters are applied before most of WP loads.
    445472     */
    446     public function init_troubleshooting_mode() {
    447         if ( isset( $_COOKIE[ self::TROUBLESHOOT_COOKIE ] ) ) {
     473    public function init_troubleshooting_mode()
     474    {
     475        if (isset($_COOKIE[self::TROUBLESHOOT_COOKIE])) {
    448476            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
    449             $this->troubleshoot_state = json_decode( wp_unslash( $_COOKIE[ self::TROUBLESHOOT_COOKIE ] ), true );
    450 
    451             if ( ! empty( $this->troubleshoot_state ) ) {
     477            $this->troubleshoot_state = json_decode(wp_unslash($_COOKIE[self::TROUBLESHOOT_COOKIE]), true);
     478
     479            if (!empty($this->troubleshoot_state)) {
    452480                // Define DONOTCACHEPAGE to prevent caching plugins from interfering.
    453                 if ( ! defined( 'DONOTCACHEPAGE' ) ) {
     481                if (!defined('DONOTCACHEPAGE')) {
    454482                    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
    455                     define( 'DONOTCACHEPAGE', true );
     483                    define('DONOTCACHEPAGE', true);
    456484                }
    457485                // Send no-cache headers as a secondary measure.
     
    459487
    460488                // Filter active plugins.
    461                 add_filter( 'option_active_plugins', array( $this, 'filter_active_plugins' ) );
    462                 if ( is_multisite() ) {
    463                     add_filter( 'site_option_active_sitewide_plugins', array( $this, 'filter_active_sitewide_plugins' ) );
     489                add_filter('option_active_plugins', array($this, 'filter_active_plugins'));
     490                if (is_multisite()) {
     491                    add_filter('site_option_active_sitewide_plugins', array($this, 'filter_active_sitewide_plugins'));
    464492                }
    465493
    466494                // Filter theme.
    467                 add_filter( 'pre_option_template', array( $this, 'filter_theme' ) );
    468                 add_filter( 'pre_option_stylesheet', array( $this, 'filter_theme' ) );
     495                add_filter('pre_option_template', array($this, 'filter_theme'));
     496                add_filter('pre_option_stylesheet', array($this, 'filter_theme'));
    469497            }
    470498        }
     
    474502     * Initializes the live debug mode.
    475503     */
    476     public function init_live_debug_mode() {
    477         if ( get_option( self::DEBUG_MODE_OPTION, 'disabled' ) === 'enabled' ) {
    478             if ( ! defined( 'WP_DEBUG' ) ) {
    479                 define( 'WP_DEBUG', true );
    480             }
    481             if ( ! defined( 'WP_DEBUG_LOG' ) ) {
    482                 define( 'WP_DEBUG_LOG', true );
    483             }
    484             if ( ! defined( 'WP_DEBUG_DISPLAY' ) ) {
    485                 define( 'WP_DEBUG_DISPLAY', false );
     504    public function init_live_debug_mode()
     505    {
     506        if (get_option(self::DEBUG_MODE_OPTION, 'disabled') === 'enabled') {
     507            if (!defined('WP_DEBUG')) {
     508                define('WP_DEBUG', true);
     509            }
     510            if (!defined('WP_DEBUG_LOG')) {
     511                define('WP_DEBUG_LOG', true);
     512            }
     513            if (!defined('WP_DEBUG_DISPLAY')) {
     514                define('WP_DEBUG_DISPLAY', false);
    486515            }
    487516            // This is necessary for the feature to function as intended.
    488517            // phpcs:ignore WordPress.PHP.IniSet.display_errors_Disallowed, Squiz.PHP.DiscouragedFunctions.Discouraged
    489             @ini_set( 'display_errors', 0 );
     518            @ini_set('display_errors', 0);
    490519        }
    491520    }
     
    496525     * @return bool
    497526     */
    498     public function is_troubleshooting_active() {
    499         return ! empty( $this->troubleshoot_state );
     527    public function is_troubleshooting_active()
     528    {
     529        return !empty($this->troubleshoot_state);
    500530    }
    501531
     
    505535     * @return array|false
    506536     */
    507     public function get_troubleshoot_state() {
     537    public function get_troubleshoot_state()
     538    {
    508539        return $this->troubleshoot_state;
    509540    }
     
    515546     * @return string
    516547     */
    517     private function get_debug_log_content( $lines_count = 200 ) {
     548    private function get_debug_log_content($lines_count = 200)
     549    {
    518550        $log_file = WP_CONTENT_DIR . '/debug.log';
    519551
    520         if ( ! file_exists( $log_file ) || ! is_readable( $log_file ) ) {
    521             return __( 'debug.log file does not exist or is not readable.', 'debugger-troubleshooter' );
    522         }
    523 
    524         if ( 0 === filesize( $log_file ) ) {
    525             return __( 'debug.log is empty.', 'debugger-troubleshooter' );
     552        if (!file_exists($log_file) || !is_readable($log_file)) {
     553            return __('debug.log file does not exist or is not readable.', 'debugger-troubleshooter');
     554        }
     555
     556        if (0 === filesize($log_file)) {
     557            return __('debug.log is empty.', 'debugger-troubleshooter');
    526558        }
    527559
    528560        // More efficient way to read last N lines of a large file.
    529         $file = new SplFileObject( $log_file, 'r' );
    530         $file->seek( PHP_INT_MAX );
     561        $file = new SplFileObject($log_file, 'r');
     562        $file->seek(PHP_INT_MAX);
    531563        $last_line = $file->key();
    532         $lines     = new LimitIterator( $file, max( 0, $last_line - $lines_count ), $last_line );
    533 
    534         return implode( '', iterator_to_array( $lines ) );
     564        $lines = new LimitIterator($file, max(0, $last_line - $lines_count), $last_line);
     565
     566        return implode('', iterator_to_array($lines));
    535567    }
    536568
     
    538570     * AJAX handler to toggle Live Debug mode.
    539571     */
    540     public function ajax_toggle_debug_mode() {
    541         check_ajax_referer( 'debug_troubleshoot_nonce', 'nonce' );
    542 
    543         if ( ! current_user_can( 'manage_options' ) ) {
    544             wp_send_json_error( array( 'message' => __( 'Permission denied.', 'debugger-troubleshooter' ) ) );
    545         }
    546 
    547         $current_status = get_option( self::DEBUG_MODE_OPTION, 'disabled' );
    548         $new_status     = ( 'enabled' === $current_status ) ? 'disabled' : 'enabled';
    549         update_option( self::DEBUG_MODE_OPTION, $new_status );
    550 
    551         if ( 'enabled' === $new_status ) {
    552             wp_send_json_success( array( 'message' => __( 'Live Debug mode enabled.', 'debugger-troubleshooter' ) ) );
     572    public function ajax_toggle_debug_mode()
     573    {
     574        check_ajax_referer('debug_troubleshoot_nonce', 'nonce');
     575
     576        if (!current_user_can('manage_options')) {
     577            wp_send_json_error(array('message' => __('Permission denied.', 'debugger-troubleshooter')));
     578        }
     579
     580        $current_status = get_option(self::DEBUG_MODE_OPTION, 'disabled');
     581        $new_status = ('enabled' === $current_status) ? 'disabled' : 'enabled';
     582        update_option(self::DEBUG_MODE_OPTION, $new_status);
     583
     584        if ('enabled' === $new_status) {
     585            wp_send_json_success(array('message' => __('Live Debug mode enabled.', 'debugger-troubleshooter')));
    553586        } else {
    554             wp_send_json_success( array( 'message' => __( 'Live Debug mode disabled.', 'debugger-troubleshooter' ) ) );
     587            wp_send_json_success(array('message' => __('Live Debug mode disabled.', 'debugger-troubleshooter')));
    555588        }
    556589    }
     
    559592     * AJAX handler to clear the debug log.
    560593     */
    561     public function ajax_clear_debug_log() {
    562         check_ajax_referer( 'debug_troubleshoot_nonce', 'nonce' );
    563 
    564         if ( ! current_user_can( 'manage_options' ) ) {
    565             wp_send_json_error( array( 'message' => __( 'Permission denied.', 'debugger-troubleshooter' ) ) );
     594    public function ajax_clear_debug_log()
     595    {
     596        check_ajax_referer('debug_troubleshoot_nonce', 'nonce');
     597
     598        if (!current_user_can('manage_options')) {
     599            wp_send_json_error(array('message' => __('Permission denied.', 'debugger-troubleshooter')));
    566600        }
    567601
    568602        global $wp_filesystem;
    569         if ( ! $wp_filesystem ) {
     603        if (!$wp_filesystem) {
    570604            require_once ABSPATH . 'wp-admin/includes/file.php';
    571605            WP_Filesystem();
     
    574608        $log_file = WP_CONTENT_DIR . '/debug.log';
    575609
    576         if ( $wp_filesystem->exists( $log_file ) ) {
    577             if ( ! $wp_filesystem->is_writable( $log_file ) ) {
    578                 wp_send_json_error( array( 'message' => __( 'Debug log is not writable.', 'debugger-troubleshooter' ) ) );
    579             }
    580             if ( $wp_filesystem->put_contents( $log_file, '' ) ) {
    581                 wp_send_json_success( array( 'message' => __( 'Debug log cleared successfully.', 'debugger-troubleshooter' ) ) );
     610        if ($wp_filesystem->exists($log_file)) {
     611            if (!$wp_filesystem->is_writable($log_file)) {
     612                wp_send_json_error(array('message' => __('Debug log is not writable.', 'debugger-troubleshooter')));
     613            }
     614            if ($wp_filesystem->put_contents($log_file, '')) {
     615                wp_send_json_success(array('message' => __('Debug log cleared successfully.', 'debugger-troubleshooter')));
    582616            } else {
    583                 wp_send_json_error( array( 'message' => __( 'Could not clear the debug log.', 'debugger-troubleshooter' ) ) );
     617                wp_send_json_error(array('message' => __('Could not clear the debug log.', 'debugger-troubleshooter')));
    584618            }
    585619        } else {
    586             wp_send_json_success( array( 'message' => __( 'Debug log does not exist.', 'debugger-troubleshooter' ) ) );
     620            wp_send_json_success(array('message' => __('Debug log does not exist.', 'debugger-troubleshooter')));
    587621        }
    588622    }
     
    595629     * @return array Filtered array of active plugins.
    596630     */
    597     public function filter_active_plugins( $plugins ) {
    598         if ( $this->is_troubleshooting_active() && isset( $this->troubleshoot_state['plugins'] ) ) {
     631    public function filter_active_plugins($plugins)
     632    {
     633        if ($this->is_troubleshooting_active() && isset($this->troubleshoot_state['plugins'])) {
    599634            return $this->troubleshoot_state['plugins'];
    600635        }
     
    608643     * @return array Filtered array of active sitewide plugins.
    609644     */
    610     public function filter_active_sitewide_plugins( $plugins ) {
    611         if ( $this->is_troubleshooting_active() && isset( $this->troubleshoot_state['sitewide_plugins'] ) ) {
     645    public function filter_active_sitewide_plugins($plugins)
     646    {
     647        if ($this->is_troubleshooting_active() && isset($this->troubleshoot_state['sitewide_plugins'])) {
    612648            // Convert indexed array from cookie back to associative array expected by 'active_sitewide_plugins'.
    613649            $new_plugins = array();
    614             foreach ( $this->troubleshoot_state['sitewide_plugins'] as $plugin_file ) {
    615                 $new_plugins[ $plugin_file ] = time(); // Value doesn't matter much for activation state.
     650            foreach ($this->troubleshoot_state['sitewide_plugins'] as $plugin_file) {
     651                $new_plugins[$plugin_file] = time(); // Value doesn't matter much for activation state.
    616652            }
    617653            return $new_plugins;
     
    626662     * @return string|false Filtered theme stylesheet or template.
    627663     */
    628     public function filter_theme( $theme ) {
    629         if ( $this->is_troubleshooting_active() && isset( $this->troubleshoot_state['theme'] ) ) {
     664    public function filter_theme($theme)
     665    {
     666        if ($this->is_troubleshooting_active() && isset($this->troubleshoot_state['theme'])) {
    630667            return $this->troubleshoot_state['theme'];
    631668        }
     
    636673     * AJAX handler to toggle troubleshooting mode on/off.
    637674     */
    638     public function ajax_toggle_troubleshoot_mode() {
    639         check_ajax_referer( 'debug_troubleshoot_nonce', 'nonce' );
    640 
    641         if ( ! current_user_can( 'manage_options' ) ) {
    642             wp_send_json_error( array( 'message' => __( 'Permission denied.', 'debugger-troubleshooter' ) ) );
    643         }
    644 
    645         $enable_mode = isset( $_POST['enable'] ) ? (bool) $_POST['enable'] : false;
    646 
    647         if ( $enable_mode ) {
     675    public function ajax_toggle_troubleshoot_mode()
     676    {
     677        check_ajax_referer('debug_troubleshoot_nonce', 'nonce');
     678
     679        if (!current_user_can('manage_options')) {
     680            wp_send_json_error(array('message' => __('Permission denied.', 'debugger-troubleshooter')));
     681        }
     682
     683        $enable_mode = isset($_POST['enable']) ? (bool) $_POST['enable'] : false;
     684
     685        if ($enable_mode) {
    648686            // Get current active plugins and theme to initialize the troubleshooting state.
    649             $current_active_plugins = get_option( 'active_plugins', array() );
    650             $current_theme          = get_stylesheet();
    651             $current_sitewide_plugins = is_multisite() ? array_keys( get_site_option( 'active_sitewide_plugins', array() ) ) : array();
     687            $current_active_plugins = get_option('active_plugins', array());
     688            $current_theme = get_stylesheet();
     689            $current_sitewide_plugins = is_multisite() ? array_keys(get_site_option('active_sitewide_plugins', array())) : array();
    652690
    653691            $state = array(
    654                 'theme'          => $current_theme,
    655                 'plugins'        => $current_active_plugins,
     692                'theme' => $current_theme,
     693                'plugins' => $current_active_plugins,
    656694                'sitewide_plugins' => $current_sitewide_plugins,
    657                 'timestamp'      => time(),
     695                'timestamp' => time(),
    658696            );
    659697            // Set cookie with HttpOnly flag for security, and secure flag if site is HTTPS.
    660             setcookie( self::TROUBLESHOOT_COOKIE, wp_json_encode( $state ), array(
    661                 'expires'  => time() + DAY_IN_SECONDS,
    662                 'path'     => COOKIEPATH,
    663                 'domain'   => COOKIE_DOMAIN,
     698            setcookie(self::TROUBLESHOOT_COOKIE, wp_json_encode($state), array(
     699                'expires' => time() + DAY_IN_SECONDS,
     700                'path' => COOKIEPATH,
     701                'domain' => COOKIE_DOMAIN,
    664702                'samesite' => 'Lax', // or 'Strict' if preferred, 'Lax' is a good balance.
    665703                'httponly' => true,
    666                 'secure'   => is_ssl(),
    667             ) );
    668             wp_send_json_success( array( 'message' => __( 'Troubleshooting mode activated.', 'debugger-troubleshooter' ) ) );
     704                'secure' => is_ssl(),
     705            ));
     706            wp_send_json_success(array('message' => __('Troubleshooting mode activated.', 'debugger-troubleshooter')));
    669707        } else {
    670708            // Unset the cookie to exit troubleshooting mode.
    671             setcookie( self::TROUBLESHOOT_COOKIE, '', array(
    672                 'expires'  => time() - 3600, // Expire the cookie.
    673                 'path'     => COOKIEPATH,
    674                 'domain'   => COOKIE_DOMAIN,
     709            setcookie(self::TROUBLESHOOT_COOKIE, '', array(
     710                'expires' => time() - 3600, // Expire the cookie.
     711                'path' => COOKIEPATH,
     712                'domain' => COOKIE_DOMAIN,
    675713                'samesite' => 'Lax',
    676714                'httponly' => true,
    677                 'secure'   => is_ssl(),
    678             ) );
    679             wp_send_json_success( array( 'message' => __( 'Troubleshooting mode deactivated.', 'debugger-troubleshooter' ) ) );
     715                'secure' => is_ssl(),
     716            ));
     717            wp_send_json_success(array('message' => __('Troubleshooting mode deactivated.', 'debugger-troubleshooter')));
    680718        }
    681719    }
     
    684722     * AJAX handler to update troubleshooting state (theme/plugins).
    685723     */
    686     public function ajax_update_troubleshoot_state() {
    687         check_ajax_referer( 'debug_troubleshoot_nonce', 'nonce' );
    688 
    689         if ( ! current_user_can( 'manage_options' ) ) {
    690             wp_send_json_error( array( 'message' => __( 'Permission denied.', 'debugger-troubleshooter' ) ) );
     724    public function ajax_update_troubleshoot_state()
     725    {
     726        check_ajax_referer('debug_troubleshoot_nonce', 'nonce');
     727
     728        if (!current_user_can('manage_options')) {
     729            wp_send_json_error(array('message' => __('Permission denied.', 'debugger-troubleshooter')));
    691730        }
    692731
    693732        // Sanitize inputs.
    694         $selected_theme   = isset( $_POST['theme'] ) ? sanitize_text_field( wp_unslash( $_POST['theme'] ) ) : get_stylesheet();
    695         $selected_plugins = isset( $_POST['plugins'] ) && is_array( $_POST['plugins'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['plugins'] ) ) : array();
     733        $selected_theme = isset($_POST['theme']) ? sanitize_text_field(wp_unslash($_POST['theme'])) : get_stylesheet();
     734        $selected_plugins = isset($_POST['plugins']) && is_array($_POST['plugins']) ? array_map('sanitize_text_field', wp_unslash($_POST['plugins'])) : array();
    696735
    697736        // For multisite, we need to distinguish regular active plugins from network active ones.
    698737        $all_plugins = get_plugins(); // Get all installed plugins to validate existence.
    699         $current_sitewide_plugins = is_multisite() ? array_keys( get_site_option( 'active_sitewide_plugins', array() ) ) : array();
     738        $current_sitewide_plugins = is_multisite() ? array_keys(get_site_option('active_sitewide_plugins', array())) : array();
    700739
    701740        $new_active_plugins = array();
    702741        $new_active_sitewide_plugins = array();
    703742
    704         foreach ( $selected_plugins as $plugin_file ) {
     743        foreach ($selected_plugins as $plugin_file) {
    705744            // Check if the plugin file actually exists in the plugin directory.
    706             if ( isset( $all_plugins[ $plugin_file ] ) ) {
     745            if (isset($all_plugins[$plugin_file])) {
    707746                // If it's a network active plugin, add it to the sitewide array.
    708                 if ( is_multisite() && in_array( $plugin_file, $current_sitewide_plugins, true ) ) {
     747                if (is_multisite() && in_array($plugin_file, $current_sitewide_plugins, true)) {
    709748                    $new_active_sitewide_plugins[] = $plugin_file;
    710749                } else {
     
    716755
    717756        $state = array(
    718             'theme'          => $selected_theme,
    719             'plugins'        => $new_active_plugins,
     757            'theme' => $selected_theme,
     758            'plugins' => $new_active_plugins,
    720759            'sitewide_plugins' => $new_active_sitewide_plugins,
    721             'timestamp'      => time(),
     760            'timestamp' => time(),
    722761        );
    723762
    724763        // Set cookie with HttpOnly flag for security, and secure flag if site is HTTPS.
    725         setcookie( self::TROUBLESHOOT_COOKIE, wp_json_encode( $state ), array(
    726             'expires'  => time() + DAY_IN_SECONDS,
    727             'path'     => COOKIEPATH,
    728             'domain'   => COOKIE_DOMAIN,
     764        setcookie(self::TROUBLESHOOT_COOKIE, wp_json_encode($state), array(
     765            'expires' => time() + DAY_IN_SECONDS,
     766            'path' => COOKIEPATH,
     767            'domain' => COOKIE_DOMAIN,
    729768            'samesite' => 'Lax',
    730769            'httponly' => true,
    731             'secure'   => is_ssl(),
    732         ) );
    733         wp_send_json_success( array( 'message' => __( 'Troubleshooting state updated successfully. Refreshing page...', 'debugger-troubleshooter' ) ) );
     770            'secure' => is_ssl(),
     771        ));
     772        wp_send_json_success(array('message' => __('Troubleshooting state updated successfully. Refreshing page...', 'debugger-troubleshooter')));
    734773    }
    735774
     
    737776     * Display an admin notice if troubleshooting mode is active.
    738777     */
    739     public function troubleshooting_mode_notice() {
    740         if ( $this->is_troubleshooting_active() ) {
    741             $troubleshoot_url = admin_url( 'tools.php?page=debug-troubleshooter' );
     778    public function troubleshooting_mode_notice()
     779    {
     780        if ($this->is_troubleshooting_active()) {
     781            $troubleshoot_url = admin_url('tools.php?page=debug-troubleshooter');
    742782            ?>
    743783            <div class="notice notice-warning is-dismissible debug-troubleshoot-notice">
    744784                <p>
    745                     <strong><?php esc_html_e( 'Troubleshooting Mode is Active!', 'debugger-troubleshooter' ); ?></strong>
    746                     <?php esc_html_e( 'You are currently in a special troubleshooting session. Your simulated theme and plugin states are not affecting the live site for other visitors.', 'debugger-troubleshooter' ); ?>
    747                     <a href="<?php echo esc_url( $troubleshoot_url ); ?>"><?php esc_html_e( 'Go to Debugger & Troubleshooter page to manage.', 'debugger-troubleshooter' ); ?></a>
     785                    <strong><?php esc_html_e('Troubleshooting Mode is Active!', 'debugger-troubleshooter'); ?></strong>
     786                    <?php esc_html_e('You are currently in a special troubleshooting session. Your simulated theme and plugin states are not affecting the live site for other visitors.', 'debugger-troubleshooter'); ?>
     787                    <a
     788                        href="<?php echo esc_url($troubleshoot_url); ?>"><?php esc_html_e('Go to Debugger & Troubleshooter page to manage.', 'debugger-troubleshooter'); ?></a>
    748789                </p>
    749790            </div>
     
    754795     * Initializes the user simulation mode.
    755796     */
    756     public function init_user_simulation() {
    757         if ( isset( $_COOKIE[ self::SIMULATE_USER_COOKIE ] ) ) {
    758             $this->simulated_user_id = (int) $_COOKIE[ self::SIMULATE_USER_COOKIE ];
    759            
     797    public function init_user_simulation()
     798    {
     799        if (isset($_COOKIE[self::SIMULATE_USER_COOKIE])) {
     800            $this->simulated_user_id = (int) $_COOKIE[self::SIMULATE_USER_COOKIE];
     801
    760802            // Hook into determine_current_user to override the user ID.
    761803            // Priority 20 ensures we run after most standard authentication checks.
    762             add_filter( 'determine_current_user', array( $this, 'simulate_user_filter' ), 20 );
     804            add_filter('determine_current_user', array($this, 'simulate_user_filter'), 20);
    763805        }
    764806    }
     
    770812     * @return int|false The simulated user ID or the original ID.
    771813     */
    772     public function simulate_user_filter( $user_id ) {
    773         if ( $this->simulated_user_id ) {
     814    public function simulate_user_filter($user_id)
     815    {
     816        if ($this->simulated_user_id) {
    774817            return $this->simulated_user_id;
    775818        }
     
    782825     * @return bool
    783826     */
    784     public function is_simulating_user() {
    785         return ! empty( $this->simulated_user_id );
     827    public function is_simulating_user()
     828    {
     829        return !empty($this->simulated_user_id);
    786830    }
    787831
     
    789833     * Renders the User Role Simulator section content.
    790834     */
    791     public function render_user_simulation_section() {
    792         $users = get_users( array( 'fields' => array( 'ID', 'display_name', 'user_login' ), 'number' => 50 ) ); // Limit to 50 for performance in dropdown
     835    public function render_user_simulation_section()
     836    {
     837        $users = get_users(array('fields' => array('ID', 'display_name', 'user_login'), 'number' => 50)); // Limit to 50 for performance in dropdown
    793838        $roles = wp_roles()->get_names();
    794839        ?>
    795840        <div class="user-simulation-controls">
    796841            <div class="debug-troubleshooter-card">
    797                 <h3><?php esc_html_e( 'Select User to Simulate', 'debugger-troubleshooter' ); ?></h3>
     842                <h3><?php esc_html_e('Select User to Simulate', 'debugger-troubleshooter'); ?></h3>
    798843                <div class="flex items-center gap-4">
    799844                    <select id="simulate-user-select" class="regular-text">
    800                         <option value=""><?php esc_html_e( '-- Select a User --', 'debugger-troubleshooter' ); ?></option>
    801                         <?php foreach ( $users as $user ) : ?>
    802                             <option value="<?php echo esc_attr( $user->ID ); ?>">
    803                                 <?php echo esc_html( $user->display_name . ' (' . $user->user_login . ')' ); ?>
     845                        <option value=""><?php esc_html_e('-- Select a User --', 'debugger-troubleshooter'); ?></option>
     846                        <?php foreach ($users as $user): ?>
     847                            <option value="<?php echo esc_attr($user->ID); ?>">
     848                                <?php echo esc_html($user->display_name . ' (' . $user->user_login . ')'); ?>
    804849                            </option>
    805850                        <?php endforeach; ?>
    806851                    </select>
    807                     <button id="simulate-user-btn" class="button button-primary"><?php esc_html_e( 'Simulate User', 'debugger-troubleshooter' ); ?></button>
     852                    <button id="simulate-user-btn"
     853                        class="button button-primary"><?php esc_html_e('Simulate User', 'debugger-troubleshooter'); ?></button>
    808854                </div>
    809855                <p class="description mt-2">
    810                     <?php esc_html_e( 'Note: You can exit the simulation at any time using the "Exit Simulation" button in the Admin Bar.', 'debugger-troubleshooter' ); ?>
     856                    <?php esc_html_e('Note: You can exit the simulation at any time using the "Exit Simulation" button in the Admin Bar.', 'debugger-troubleshooter'); ?>
    811857                </p>
    812858            </div>
     
    820866     * @param WP_Admin_Bar $wp_admin_bar The admin bar object.
    821867     */
    822     public function admin_bar_exit_simulation( $wp_admin_bar ) {
    823         if ( $this->is_simulating_user() ) {
    824             $wp_admin_bar->add_node( array(
    825                 'id'    => 'debug-troubleshooter-exit-sim',
    826                 'title' => '<span style="color: #ff4444; font-weight: bold;">' . __( 'Exit User Simulation', 'debugger-troubleshooter' ) . '</span>',
    827                 'href'  => '#',
    828                 'meta'  => array(
     868    public function admin_bar_exit_simulation($wp_admin_bar)
     869    {
     870        if ($this->is_simulating_user()) {
     871            $wp_admin_bar->add_node(array(
     872                'id' => 'debug-troubleshooter-exit-sim',
     873                'title' => '<span style="color: #ff4444; font-weight: bold;">' . __('Exit User Simulation', 'debugger-troubleshooter') . '</span>',
     874                'href' => '#',
     875                'meta' => array(
    829876                    'onclick' => 'debugTroubleshootExitSimulation(); return false;',
    830                     'title'   => __( 'Click to return to your original user account', 'debugger-troubleshooter' ),
     877                    'title' => __('Click to return to your original user account', 'debugger-troubleshooter'),
    831878                ),
    832             ) );
     879            ));
    833880
    834881            // Add inline script for the exit action since we might be on the frontend
    835882            // where our admin.js isn't enqueued, or we need a global handler.
    836             add_action( 'wp_footer', array( $this, 'print_exit_simulation_script' ) );
    837             add_action( 'admin_footer', array( $this, 'print_exit_simulation_script' ) );
     883            add_action('wp_footer', array($this, 'print_exit_simulation_script'));
     884            add_action('admin_footer', array($this, 'print_exit_simulation_script'));
    838885        }
    839886    }
     
    842889     * Prints the inline script for exiting simulation from the admin bar.
    843890     */
    844     public function print_exit_simulation_script() {
     891    public function print_exit_simulation_script()
     892    {
    845893        ?>
    846894        <script type="text/javascript">
    847         function debugTroubleshootExitSimulation() {
    848             if (confirm('<?php echo esc_js( __( 'Are you sure you want to exit User Simulation?', 'debugger-troubleshooter' ) ); ?>')) {
    849                 var data = new FormData();
    850                 data.append('action', 'debug_troubleshoot_toggle_simulate_user');
    851                 data.append('enable', '0');
    852                 // We might not have the nonce available globally on frontend, so we rely on cookie check in backend mostly,
    853                 // but for AJAX we need it. If we are on frontend, we might need to expose it.
    854                 // For simplicity in this MVP, we'll assume admin-ajax is accessible.
    855                 // SECURITY NOTE: In a real scenario, we should localize the nonce on wp_enqueue_scripts as well if we want frontend support.
    856                 // For now, let's try to fetch it from a global if available, or just rely on the cookie clearing which is less secure but functional for a dev tool.
    857                 // BETTER APPROACH: Use a dedicated endpoint or just a simple GET parameter that we intercept on init to clear the cookie.
    858                
    859                 // Let's use a simple redirect to a URL that handles the exit.
    860                 window.location.href = '<?php echo esc_url( admin_url( 'admin-ajax.php?action=debug_troubleshoot_toggle_simulate_user&enable=0' ) ); ?>';
    861             }
    862         }
     895            function debugTroubleshootExitSimulation() {
     896                if (confirm('<?php echo esc_js(__('Are you sure you want to exit User Simulation?', 'debugger-troubleshooter')); ?>')) {
     897                    var data = new FormData();
     898                    data.append('action', 'debug_troubleshoot_toggle_simulate_user');
     899                    data.append('enable', '0');
     900                    // We might not have the nonce available globally on frontend, so we rely on cookie check in backend mostly,
     901                    // but for AJAX we need it. If we are on frontend, we might need to expose it.
     902                    // For simplicity in this MVP, we'll assume admin-ajax is accessible.
     903                    // SECURITY NOTE: In a real scenario, we should localize the nonce on wp_enqueue_scripts as well if we want frontend support.
     904                    // For now, let's try to fetch it from a global if available, or just rely on the cookie clearing which is less secure but functional for a dev tool.
     905                    // BETTER APPROACH: Use a dedicated endpoint or just a simple GET parameter that we intercept on init to clear the cookie.
     906
     907                    // Let's use a simple redirect to a URL that handles the exit.
     908                    window.location.href = '<?php echo esc_url(admin_url('admin-ajax.php?action=debug_troubleshoot_toggle_simulate_user&enable=0')); ?>';
     909                }
     910            }
    863911        </script>
    864912        <?php
     
    868916     * AJAX handler to toggle User Simulation.
    869917     */
    870     public function ajax_toggle_simulate_user() {
     918    public function ajax_toggle_simulate_user()
     919    {
    871920        // Note: For the "Exit" action via GET request (from Admin Bar), we might not have a nonce.
    872921        // Since this is a dev tool and we are just clearing a cookie, the risk is low, but ideally we'd check a nonce.
    873922        // For the "Enter" action (POST), we definitely check the nonce.
    874        
    875         $is_post = isset( $_SERVER['REQUEST_METHOD'] ) && 'POST' === $_SERVER['REQUEST_METHOD'];
    876         if ( $is_post ) {
    877             check_ajax_referer( 'debug_troubleshoot_nonce', 'nonce' );
    878         }
    879 
    880         if ( ! current_user_can( 'manage_options' ) && ! $this->is_simulating_user() ) {
     923
     924        $is_post = isset($_SERVER['REQUEST_METHOD']) && 'POST' === $_SERVER['REQUEST_METHOD'];
     925        if ($is_post) {
     926            check_ajax_referer('debug_troubleshoot_nonce', 'nonce');
     927        }
     928
     929        if (!current_user_can('manage_options') && !$this->is_simulating_user()) {
    881930            // Only allow admins to START simulation.
    882931            // Anyone (simulated user) can STOP simulation.
    883             wp_send_json_error( array( 'message' => __( 'Permission denied.', 'debugger-troubleshooter' ) ) );
    884         }
    885 
    886         $enable = isset( $_REQUEST['enable'] ) ? (bool) $_REQUEST['enable'] : false;
    887         $user_id = isset( $_REQUEST['user_id'] ) ? (int) $_REQUEST['user_id'] : 0;
    888 
    889         if ( $enable && $user_id ) {
     932            wp_send_json_error(array('message' => __('Permission denied.', 'debugger-troubleshooter')));
     933        }
     934
     935        $enable = isset($_REQUEST['enable']) ? (bool) $_REQUEST['enable'] : false;
     936        $user_id = isset($_REQUEST['user_id']) ? (int) $_REQUEST['user_id'] : 0;
     937
     938        if ($enable && $user_id) {
    890939            // Set cookie
    891             setcookie( self::SIMULATE_USER_COOKIE, $user_id, array(
    892                 'expires'  => time() + DAY_IN_SECONDS,
    893                 'path'     => COOKIEPATH,
    894                 'domain'   => COOKIE_DOMAIN,
     940            setcookie(self::SIMULATE_USER_COOKIE, $user_id, array(
     941                'expires' => time() + DAY_IN_SECONDS,
     942                'path' => COOKIEPATH,
     943                'domain' => COOKIE_DOMAIN,
    895944                'samesite' => 'Lax',
    896945                'httponly' => true,
    897                 'secure'   => is_ssl(),
    898             ) );
    899             wp_send_json_success( array( 'message' => __( 'User simulation activated. Reloading...', 'debugger-troubleshooter' ) ) );
     946                'secure' => is_ssl(),
     947            ));
     948            wp_send_json_success(array('message' => __('User simulation activated. Reloading...', 'debugger-troubleshooter')));
    900949        } else {
    901950            // Clear cookie
    902             setcookie( self::SIMULATE_USER_COOKIE, '', array(
    903                 'expires'  => time() - 3600,
    904                 'path'     => COOKIEPATH,
    905                 'domain'   => COOKIE_DOMAIN,
     951            setcookie(self::SIMULATE_USER_COOKIE, '', array(
     952                'expires' => time() - 3600,
     953                'path' => COOKIEPATH,
     954                'domain' => COOKIE_DOMAIN,
    906955                'samesite' => 'Lax',
    907956                'httponly' => true,
    908                 'secure'   => is_ssl(),
    909             ) );
    910            
    911             if ( ! $is_post ) {
     957                'secure' => is_ssl(),
     958            ));
     959
     960            if (!$is_post) {
    912961                // If it was a GET request (from Admin Bar), redirect back to home or dashboard.
    913                 wp_safe_redirect( admin_url() );
     962                wp_safe_redirect(admin_url());
    914963                exit;
    915964            }
    916            
    917             wp_send_json_success( array( 'message' => __( 'User simulation deactivated.', 'debugger-troubleshooter' ) ) );
     965
     966            wp_send_json_success(array('message' => __('User simulation deactivated.', 'debugger-troubleshooter')));
    918967        }
    919968    }
  • debugger-troubleshooter/trunk/readme.txt

    r3400548 r3459095  
    55Requires PHP: 7.4
    66Tested up to: 6.8
    7 Stable tag: 1.3.1
     7Stable tag: 1.3.2
    88License: GPL-2.0+
    99License URI: http://www.gnu.org/licenses/gpl-2.0.txt
     
    9292== Changelog ==
    9393
     94=1.3.2 - 2026-02-11 =
     95* **Fix:** Resolved a UI conflict where the confirmation modal appeared automatically upon page load due to CSS class interference from other plugins.
     96* **Fix:** Improved modal layering (z-index) to ensure the Success/Error alert modal correctly appears above the confirmation modal.
     97* **Fix:** Updated the "Confirm" action in the Debug Log viewer to automatically close the confirmation dialog before showing the result, preventing the UI from becoming unclickable.
     98* **Enhancement:** Hardened the .hidden CSS utility with !important to prevent external themes or plugins from forcing hidden elements to display.
     99
    94100= 1.3.1 - 2025-11-21 =
    95101* **Fix:** Resolved a critical issue where admin scripts were not loading due to a hook name mismatch.
     
    125131== Upgrade Notice ==
    126132
     133= 1.3.2 =
     134This release fixes a UI conflict where the confirmation modal appeared automatically upon page load due to CSS class interference from other plugins.
     135
    127136= 1.3.1 =
    128137This release fixes a critical bug affecting the plugin's layout and functionality, and improves code standards.
     
    136145= 1.2.0 =
    137146This version adds a major new feature: "Live Debugging." You can now enable WP_DEBUG and view the debug.log file directly from the plugin's admin page without editing any files.
     147
Note: See TracChangeset for help on using the changeset viewer.