Plugin Directory

Changeset 3392035


Ignore:
Timestamp:
11/08/2025 05:04:23 AM (5 months ago)
Author:
ayonm
Message:

Update to version 3.2

Location:
enable-classic-editor
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • enable-classic-editor

    • Property svn:ignore set to
      .claude
      .git
      .gitignore
  • enable-classic-editor/trunk

    • Property svn:ignore set to
      .claude
  • enable-classic-editor/trunk/assets/js/admin.js

    r3295721 r3392035  
    33 */
    44jQuery(document).ready(function($) {
     5    // Constants for timing delays (in milliseconds)
     6    const TOAST_SHOW_DELAY = 100;
     7    const TOAST_AUTO_HIDE_DELAY = 3000;
     8    const TOAST_FADE_OUT_DELAY = 300;
     9    const BUTTON_RESET_DELAY = 2000;
     10    const MODAL_FADE_DURATION = 200;
     11    const SETTINGS_SCROLL_DURATION = 300;
     12    const ADVANCED_SETTINGS_FADE_DURATION = 300;
     13
     14    // Quick Edit functionality for editor choice column
     15    if (typeof inlineEditPost !== 'undefined') {
     16        // Save the original quick edit function
     17        var $wp_inline_edit = inlineEditPost.edit;
     18
     19        // Override the quick edit function
     20        inlineEditPost.edit = function(id) {
     21            // Call the original function
     22            $wp_inline_edit.apply(this, arguments);
     23
     24            // Get the post ID
     25            var post_id = 0;
     26            if (typeof(id) === 'object') {
     27                post_id = parseInt(this.getId(id));
     28            }
     29
     30            if (post_id > 0) {
     31                // Get the row
     32                var $row = $('#post-' + post_id);
     33
     34                // Get the editor choice
     35                var editor_choice = '';
     36                var $editor_icon = $row.find('td.editor_choice .dashicons');
     37
     38                if ($editor_icon.hasClass('dashicons-editor-kitchensink')) {
     39                    editor_choice = 'classic';
     40                } else if ($editor_icon.hasClass('dashicons-block-default')) {
     41                    editor_choice = 'block';
     42                } else {
     43                    editor_choice = 'default';
     44                }
     45
     46                // Set the value in the quick edit form
     47                var $edit_row = $('#edit-' + post_id);
     48                $edit_row.find('select[name="ecew_editor_choice"]').val(editor_choice);
     49            }
     50        };
     51    }
     52
    553    // Toggle advanced settings visibility
    654    $('#ecew_show_settings').on('change', function() {
    755        if ($(this).is(':checked')) {
    8             $('.advanced-settings').fadeIn(300);
     56            $('.advanced-settings').fadeIn(ADVANCED_SETTINGS_FADE_DURATION);
    957        } else {
    10             $('.advanced-settings').fadeOut(300);
    11         }
    12     });
    13    
    14     // Reset defaults button
     58            $('.advanced-settings').fadeOut(ADVANCED_SETTINGS_FADE_DURATION);
     59        }
     60    });
     61
     62    // Per-Post Toggle is now independent of Advanced Settings
     63    // No need to auto-enable Advanced Settings when Per-Post Toggle is checked
     64    // Both features work independently in simple and advanced modes
     65
     66    // Handle dependency: Per-Post Toggle requires main plugin to be enabled
     67    function updatePerPostToggleState() {
     68        var $perPostToggle = $('#ecew_per_post_toggle');
     69        var $perPostRow = $perPostToggle.closest('tr');
     70
     71        if (!$('#ecew_enabled').is(':checked')) {
     72            // Main plugin is disabled, visually disable per-post toggle
     73            // NOTE: We don't use .prop('disabled', true) because disabled fields
     74            // are excluded from form submission, causing save bugs
     75            $perPostRow.addClass('disabled-setting');
     76
     77            // If it was checked, uncheck it
     78            if ($perPostToggle.is(':checked')) {
     79                $perPostToggle.prop('checked', false);
     80            }
     81        } else {
     82            // Main plugin is enabled, enable per-post toggle
     83            $perPostRow.removeClass('disabled-setting');
     84        }
     85    }
     86
     87    // Handle dependency: Advanced Settings requires main plugin to be enabled
     88    function updateAdvancedSettingsState() {
     89        var $advancedToggle = $('#ecew_show_settings');
     90        var $advancedRow = $advancedToggle.closest('tr');
     91
     92        if (!$('#ecew_enabled').is(':checked')) {
     93            // Main plugin is disabled, visually disable advanced settings
     94            // NOTE: We don't use .prop('disabled', true) because disabled fields
     95            // are excluded from form submission, causing save bugs
     96            $advancedRow.addClass('disabled-setting');
     97
     98            // If it was checked, uncheck it and trigger change to hide sections
     99            if ($advancedToggle.is(':checked')) {
     100                $advancedToggle.prop('checked', false).trigger('change');
     101            }
     102        } else {
     103            // Main plugin is enabled, enable advanced settings
     104            $advancedRow.removeClass('disabled-setting');
     105        }
     106    }
     107
     108    // Run on page load
     109    updatePerPostToggleState();
     110    updateAdvancedSettingsState();
     111
     112    // Run when main toggle changes
     113    $('#ecew_enabled').on('change', function() {
     114        updatePerPostToggleState();
     115        updateAdvancedSettingsState();
     116    });
     117
     118    // Toast notification function
     119    function showToast(message, type) {
     120        var $toast = $('<div class="ecew-toast ecew-toast-' + type + '">' + message + '</div>');
     121        $('body').append($toast);
     122
     123        setTimeout(function() {
     124            $toast.addClass('show');
     125        }, TOAST_SHOW_DELAY);
     126
     127        setTimeout(function() {
     128            $toast.removeClass('show');
     129            setTimeout(function() {
     130                $toast.remove();
     131            }, TOAST_FADE_OUT_DELAY);
     132        }, TOAST_AUTO_HIDE_DELAY);
     133    }
     134
     135    // Unsaved changes detection
     136    var formChanged = false;
     137    var originalFormData = $('.classic-editor-plus-settings form').serialize();
     138
     139    function updateUnsavedIndicator() {
     140        if (formChanged) {
     141            if ($('.unsaved-indicator').length === 0) {
     142                $('.submit-buttons #submit').before('<span class="unsaved-indicator">● Unsaved changes</span>');
     143            }
     144        } else {
     145            $('.unsaved-indicator').remove();
     146        }
     147    }
     148
     149    // Track form changes
     150    $('.classic-editor-plus-settings form :input').on('change', function() {
     151        var currentFormData = $('.classic-editor-plus-settings form').serialize();
     152        formChanged = (originalFormData !== currentFormData);
     153        updateUnsavedIndicator();
     154    });
     155
     156    // Warn on navigation if there are unsaved changes
     157    $(window).on('beforeunload', function(e) {
     158        if (formChanged) {
     159            var message = ecewSettings.i18n.unsavedChanges;
     160            e.returnValue = message;
     161            return message;
     162        }
     163    });
     164
     165    // Animated save button
     166    $('.classic-editor-plus-settings form').on('submit', function(e) {
     167        var $form = $(this);
     168        var $submitBtn = $('#submit');
     169        var originalText = $submitBtn.val();
     170
     171        // Disable button and show loading
     172        $submitBtn.prop('disabled', true).val('Saving...').addClass('saving');
     173
     174        // Clear the unsaved changes flag (form is being saved)
     175        formChanged = false;
     176
     177        // Note: Form will submit normally, we just show the animation
     178        // The page will reload, showing WordPress's success message
     179        // We can't prevent default here because we need WordPress to save the settings
     180
     181        // Store that we're saving (for after page reload) with error handling
     182        try {
     183            sessionStorage.setItem('ecew_just_saved', 'true');
     184        } catch (e) {
     185            // Silently fail if sessionStorage is not available (privacy mode, etc.)
     186        }
     187    });
     188
     189    // Check if we just saved (after page reload) with error handling
     190    var justSaved = false;
     191    try {
     192        justSaved = (sessionStorage.getItem('ecew_just_saved') === 'true');
     193        if (justSaved) {
     194            sessionStorage.removeItem('ecew_just_saved');
     195        }
     196    } catch (e) {
     197        // Silently fail if sessionStorage is not available
     198    }
     199
     200    if (justSaved) {
     201
     202        // Show success animation on the save button
     203        var $submitBtn = $('#submit');
     204        var originalText = $submitBtn.val();
     205
     206        $submitBtn.val('✓ Settings Saved!').addClass('saved');
     207        showToast(ecewSettings.i18n.settingsSaved, 'success');
     208
     209        // Reset button after delay
     210        setTimeout(function() {
     211            $submitBtn.removeClass('saved').val(originalText);
     212        }, BUTTON_RESET_DELAY);
     213
     214        // Scroll to top to show any messages
     215        $('html, body').animate({ scrollTop: 0 }, SETTINGS_SCROLL_DURATION);
     216    }
     217
     218    // Post Type/Role Selection Improvements
     219    function updatePostTypeCount() {
     220        var checked = $('input[name="ecew_settings[post_types][]"]:checked').length;
     221        var total = $('input[name="ecew_settings[post_types][]"]').length;
     222        $('.post-types-count').text(ecewSettings.i18n.postTypesSelected.replace('%d', checked).replace('%d', total));
     223    }
     224
     225    function updateRoleCount() {
     226        var checked = $('input[name="ecew_settings[user_roles][]"]:checked').length;
     227        var total = $('input[name="ecew_settings[user_roles][]"]').length;
     228        $('.roles-count').text(ecewSettings.i18n.userRolesSelected.replace('%d', checked).replace('%d', total));
     229    }
     230
     231    // Select All / Deselect All for post types
     232    $('.select-all-post-types').on('click', function() {
     233        $('input[name="ecew_settings[post_types][]"]').prop('checked', true).trigger('change');
     234        updatePostTypeCount();
     235    });
     236
     237    $('.deselect-all-post-types').on('click', function() {
     238        $('input[name="ecew_settings[post_types][]"]').prop('checked', false).trigger('change');
     239        updatePostTypeCount();
     240    });
     241
     242    // Update count when checkboxes change
     243    $('input[name="ecew_settings[post_types][]"]').on('change', function() {
     244        updatePostTypeCount();
     245    });
     246
     247    // Select All / Deselect All for user roles
     248    $('.select-all-roles').on('click', function() {
     249        $('input[name="ecew_settings[user_roles][]"]').prop('checked', true).trigger('change');
     250        updateRoleCount();
     251    });
     252
     253    $('.deselect-all-roles').on('click', function() {
     254        $('input[name="ecew_settings[user_roles][]"]').prop('checked', false).trigger('change');
     255        updateRoleCount();
     256    });
     257
     258    // Update count when checkboxes change
     259    $('input[name="ecew_settings[user_roles][]"]').on('change', function() {
     260        updateRoleCount();
     261    });
     262
     263    // Reset defaults button with custom modal
    15264    $('#reset-defaults').on('click', function(e) {
    16265        e.preventDefault();
    17        
    18         if (confirm(ecewSettings.resetConfirmMessage)) {
     266
     267        // Create modal HTML with accessibility attributes
     268        var modalHTML = `
     269            <div class="ecew-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="ecew-modal-title">
     270                <div class="ecew-modal">
     271                    <div class="ecew-modal-header">
     272                        <h2 id="ecew-modal-title">Reset All Settings to Defaults?</h2>
     273                    </div>
     274                    <div class="ecew-modal-body">
     275                        <p>This will reset all plugin settings to their default values:</p>
     276                        <ul>
     277                            <li><strong>Classic Editor:</strong> Enabled</li>
     278                            <li><strong>Advanced Settings:</strong> Disabled (Simple Mode)</li>
     279                            <li><strong>Per-Post Toggle:</strong> Enabled</li>
     280                            <li><strong>Classic Widgets:</strong> Enabled</li>
     281                            <li><strong>All post types:</strong> Selected</li>
     282                            <li><strong>All user roles:</strong> Selected</li>
     283                        </ul>
     284                        <p><strong>Note:</strong> Per-post editor preferences will not be affected.</p>
     285                    </div>
     286                    <div class="ecew-modal-footer">
     287                        <button type="button" class="button ecew-modal-cancel" aria-label="Cancel reset">Cancel</button>
     288                        <button type="button" class="button button-primary button-danger ecew-modal-confirm" aria-label="Confirm reset">Reset All Settings</button>
     289                    </div>
     290                </div>
     291            </div>
     292        `;
     293
     294        $('body').append(modalHTML);
     295        $('.ecew-modal-overlay').fadeIn(MODAL_FADE_DURATION);
     296
     297        // Set focus to the confirm button for accessibility
     298        $('.ecew-modal-confirm').focus();
     299
     300        // Handle cancel (clicking cancel button or overlay)
     301        $('.ecew-modal-cancel, .ecew-modal-overlay').on('click', function(e) {
     302            if (e.target === this) {
     303                $('.ecew-modal-overlay').fadeOut(MODAL_FADE_DURATION, function() {
     304                    $(this).remove();
     305                });
     306            }
     307        });
     308
     309        // Handle confirm
     310        $('.ecew-modal-confirm').on('click', function() {
    19311            // Reset all form elements
    20             $('#ecew_enabled').prop('checked', true);
     312            $('#ecew_enabled').prop('checked', true).trigger('change');
    21313            $('#ecew_show_settings').prop('checked', false).trigger('change');
    22314            $('#ecew_per_post_toggle').prop('checked', true);
    23             $('#ecew_classic_widgets').prop('checked', true);
    24            
     315            $('#ecew_classic_widgets_global').prop('checked', true);
     316
    25317            // Check all post type checkboxes
    26318            $('input[name="ecew_settings[post_types][]"]').prop('checked', true);
    27            
     319            updatePostTypeCount();
     320
    28321            // Check all role checkboxes
    29322            $('input[name="ecew_settings[user_roles][]"]').prop('checked', true);
    30         }
     323            updateRoleCount();
     324
     325            // Close modal
     326            $('.ecew-modal-overlay').fadeOut(MODAL_FADE_DURATION, function() {
     327                $(this).remove();
     328            });
     329
     330            // Show toast
     331            showToast(ecewSettings.i18n.resetToDefaults, 'success');
     332        });
    31333    });
    32334});
  • enable-classic-editor/trunk/classic-editor-admin.css

    r3295733 r3392035  
    55.classic-editor-plus-settings {
    66    max-width: 950px;
     7}
     8
     9/* Mode Indicator */
     10.ecew-mode-indicator {
     11    margin-bottom: 20px;
     12    padding: 12px 15px;
     13    border-left: 4px solid #dcdcde;
     14    background-color: #f6f7f7;
     15    border-radius: 4px;
     16}
     17
     18.ecew-mode-indicator.advanced {
     19    border-left-color: #2271b1;
     20    background-color: #e7f3ff;
     21}
     22
     23.ecew-mode-indicator.simple {
     24    border-left-color: #7cb342;
     25    background-color: #f0f5eb;
     26}
     27
     28.mode-badge {
     29    display: inline-block;
     30    padding: 4px 12px;
     31    border-radius: 3px;
     32    font-weight: 600;
     33    font-size: 12px;
     34    text-transform: uppercase;
     35    letter-spacing: 0.5px;
     36    margin-bottom: 8px;
     37}
     38
     39.ecew-mode-indicator.advanced .mode-badge {
     40    background-color: #2271b1;
     41    color: white;
     42}
     43
     44.ecew-mode-indicator.simple .mode-badge {
     45    background-color: #7cb342;
     46    color: white;
     47}
     48
     49.mode-description {
     50    margin: 0;
     51    color: #50575e;
     52    font-size: 13px;
     53    line-height: 1.5;
    754}
    855
     
    162209        flex: 0 0 100%;
    163210    }
    164    
     211
    165212    .submit-buttons {
    166213        flex-direction: column;
    167214    }
    168    
     215
    169216    .submit-buttons .button {
    170217        width: 100%;
     
    172219    }
    173220}
     221
     222/* Disabled setting style (for dependency management) */
     223.classic-editor-plus-settings .form-table tr.disabled-setting {
     224    opacity: 0.5;
     225    pointer-events: none;
     226}
     227
     228.classic-editor-plus-settings .form-table tr.disabled-setting th,
     229.classic-editor-plus-settings .form-table tr.disabled-setting td {
     230    color: #a7aaad;
     231}
     232
     233/* Save button states */
     234.classic-editor-plus-settings #submit {
     235    transition: all 0.3s ease;
     236    min-width: 120px;
     237}
     238
     239.classic-editor-plus-settings #submit.saving {
     240    background: #2271b1;
     241    border-color: #2271b1;
     242    opacity: 0.8;
     243    cursor: wait;
     244}
     245
     246.classic-editor-plus-settings #submit.saved {
     247    background: #00a32a !important;
     248    border-color: #00a32a !important;
     249    box-shadow: none !important;
     250}
     251
     252.classic-editor-plus-settings #submit.error {
     253    background: #d63638;
     254    border-color: #d63638;
     255}
     256
     257/* Toast notifications */
     258.ecew-toast {
     259    position: fixed;
     260    top: 50px;
     261    right: 20px;
     262    background: white;
     263    border-left: 4px solid #00a32a;
     264    padding: 15px 20px;
     265    box-shadow: 0 3px 10px rgba(0,0,0,0.2);
     266    border-radius: 4px;
     267    z-index: 999999;
     268    transform: translateX(400px);
     269    transition: transform 0.3s ease;
     270    font-size: 14px;
     271    font-weight: 500;
     272    max-width: 350px;
     273}
     274
     275.ecew-toast.show {
     276    transform: translateX(0);
     277}
     278
     279.ecew-toast.ecew-toast-error {
     280    border-left-color: #d63638;
     281    color: #d63638;
     282}
     283
     284.ecew-toast.ecew-toast-warning {
     285    border-left-color: #dba617;
     286    color: #dba617;
     287}
     288
     289.ecew-toast.ecew-toast-success {
     290    border-left-color: #00a32a;
     291    color: #1d2327;
     292}
     293
     294/* Unsaved changes indicator */
     295.unsaved-indicator {
     296    color: #dba617;
     297    margin-right: 10px;
     298    font-size: 13px;
     299    animation: pulse 2s infinite;
     300    display: inline-block;
     301}
     302
     303@keyframes pulse {
     304    0%, 100% { opacity: 1; }
     305    50% { opacity: 0.5; }
     306}
     307
     308/* Modal overlay and dialog */
     309.ecew-modal-overlay {
     310    display: none;
     311    position: fixed;
     312    top: 0;
     313    left: 0;
     314    right: 0;
     315    bottom: 0;
     316    background: rgba(0, 0, 0, 0.7);
     317    z-index: 999998;
     318    align-items: center;
     319    justify-content: center;
     320}
     321
     322.ecew-modal {
     323    background: white;
     324    border-radius: 4px;
     325    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
     326    max-width: 550px;
     327    width: 90%;
     328    margin: 50px auto;
     329    position: relative;
     330    top: 50%;
     331    transform: translateY(-50%);
     332}
     333
     334.ecew-modal-header {
     335    padding: 20px 24px;
     336    border-bottom: 1px solid #dcdcde;
     337}
     338
     339.ecew-modal-header h2 {
     340    margin: 0;
     341    font-size: 18px;
     342    color: #1d2327;
     343}
     344
     345.ecew-modal-body {
     346    padding: 20px 24px;
     347    color: #1d2327;
     348}
     349
     350.ecew-modal-body p {
     351    margin: 12px 0;
     352    line-height: 1.6;
     353}
     354
     355.ecew-modal-body ul {
     356    margin: 15px 0;
     357    padding-left: 25px;
     358}
     359
     360.ecew-modal-body li {
     361    margin: 10px 0;
     362    line-height: 1.5;
     363}
     364
     365.ecew-modal-footer {
     366    padding: 15px 24px;
     367    border-top: 1px solid #dcdcde;
     368    text-align: right;
     369    display: flex;
     370    gap: 10px;
     371    justify-content: flex-end;
     372    background: #f6f7f7;
     373}
     374
     375.button-danger {
     376    background: #d63638 !important;
     377    border-color: #d63638 !important;
     378    color: white !important;
     379    text-shadow: none !important;
     380}
     381
     382.button-danger:hover,
     383.button-danger:focus {
     384    background: #c92c2f !important;
     385    border-color: #c92c2f !important;
     386    color: white !important;
     387}
     388
     389@media screen and (max-width: 600px) {
     390    .ecew-modal {
     391        width: 95%;
     392        margin: 20px auto;
     393    }
     394
     395    .ecew-modal-footer {
     396        flex-direction: column;
     397    }
     398
     399    .ecew-modal-footer .button {
     400        width: 100%;
     401        text-align: center;
     402    }
     403}
     404
     405/* Help tooltips */
     406.ecew-help-tooltip {
     407    position: relative;
     408    display: inline-block;
     409    cursor: help;
     410    color: #787c82;
     411    margin-left: 5px;
     412    vertical-align: middle;
     413}
     414
     415.ecew-help-tooltip .dashicons {
     416    width: 16px;
     417    height: 16px;
     418    font-size: 16px;
     419}
     420
     421.ecew-help-tooltip:hover {
     422    color: #2271b1;
     423}
     424
     425.ecew-help-tooltip::after {
     426    content: attr(data-tooltip);
     427    position: absolute;
     428    bottom: 125%;
     429    left: 50%;
     430    transform: translateX(-50%);
     431    padding: 10px 14px;
     432    background: #1d2327;
     433    color: white;
     434    font-size: 13px;
     435    line-height: 1.5;
     436    border-radius: 4px;
     437    white-space: normal;
     438    width: 280px;
     439    max-width: 280px;
     440    opacity: 0;
     441    pointer-events: none;
     442    transition: opacity 0.2s ease;
     443    z-index: 10000;
     444    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
     445    text-align: left;
     446}
     447
     448.ecew-help-tooltip::before {
     449    content: '';
     450    position: absolute;
     451    bottom: 115%;
     452    left: 50%;
     453    transform: translateX(-50%);
     454    border: 6px solid transparent;
     455    border-top-color: #1d2327;
     456    opacity: 0;
     457    pointer-events: none;
     458    transition: opacity 0.2s ease;
     459    z-index: 10000;
     460}
     461
     462.ecew-help-tooltip:hover::after,
     463.ecew-help-tooltip:hover::before {
     464    opacity: 1;
     465}
     466
     467@media screen and (max-width: 782px) {
     468    .ecew-help-tooltip::after {
     469        width: 220px;
     470        max-width: 220px;
     471    }
     472}
  • enable-classic-editor/trunk/enable-classic-editor.php

    r3301448 r3392035  
    44Plugin URI: https://www.ayonm.com
    55Description: A simple & lightweight plugin to enable the classic editor on WordPress with advanced configuration options.
    6 Version: 3.1
     6Version: 3.2
    77Author: ayonm
    88Author URI: https://www.ayonm.com
     
    2525 */
    2626
    27 defined( 'ABSPATH' ) || die( 'No Entry!' );
     27defined( 'ABSPATH' ) || die( 'No Entry!' );
     28
     29// Define plugin constants
     30if (!defined('ECEW_VERSION')) {
     31    define('ECEW_VERSION', '3.4');
     32}
     33if (!defined('ECEW_PLUGIN_DIR')) {
     34    define('ECEW_PLUGIN_DIR', plugin_dir_path(__FILE__));
     35}
     36if (!defined('ECEW_PLUGIN_URL')) {
     37    define('ECEW_PLUGIN_URL', plugin_dir_url(__FILE__));
     38}
     39if (!defined('ECEW_TEXT_DOMAIN')) {
     40    define('ECEW_TEXT_DOMAIN', 'enable-classic-editor');
     41}
    2842
    2943/**
     
    4256
    4357    /**
     58     * Cached current user for performance
     59     */
     60    private $current_user_cache = null;
     61
     62    /**
    4463     * Get plugin instance
    4564     */
     
    5574     */
    5675    private function __construct() {
    57         // Get plugin settings or use defaults
     76        // Get plugin settings with safe defaults (no function calls that may not be available yet)
    5877        $this->settings = get_option('ecew_settings', array(
    5978            'enabled' => true,
    60             'post_types' => array_keys(get_post_types(array('public' => true), 'names')),
    61             'user_roles' => array_keys(wp_roles()->roles),
     79            'post_types' => array(),  // Will be populated with actual post types if empty
     80            'user_roles' => array(),  // Will be populated with actual roles if empty
    6281            'use_classic_widgets' => true,
    6382            'show_settings_page' => false,
     
    6584        ));
    6685
     86        // Populate empty post_types and user_roles with safe defaults
     87        if (empty($this->settings['post_types']) && function_exists('get_post_types')) {
     88            $this->settings['post_types'] = array_keys(get_post_types(array('public' => true), 'names'));
     89        }
     90        if (empty($this->settings['user_roles']) && function_exists('wp_roles')) {
     91            $this->settings['user_roles'] = array_keys(wp_roles()->roles);
     92        }
     93
    6794        // Initialize plugin
    6895        $this->init();
     
    75102        // Legacy mode - if settings page is not enabled, use the original simple behavior
    76103        if (empty($this->settings['show_settings_page'])) {
    77             add_filter('use_block_editor_for_post', '__return_false');
    78             add_action('after_setup_theme', array($this, 'disable_block_widgets'));
     104            // In simple mode, check per-post overrides if enabled, otherwise default to classic
     105            if (!empty($this->settings['allow_per_post_toggle'])) {
     106                add_filter('use_block_editor_for_post', array($this, 'disable_gutenberg_for_post_simple_mode'), 10, 2);
     107            } else {
     108                // Use a callback that checks enabled state instead of __return_false
     109                add_filter('use_block_editor_for_post', array($this, 'disable_gutenberg_simple_mode_no_toggle'), 10, 2);
     110            }
    79111        } else {
    80112            // Advanced mode - use settings to determine behavior
    81113            add_filter('use_block_editor_for_post', array($this, 'disable_gutenberg_for_post'), 10, 2);
    82114            add_filter('use_block_editor_for_post_type', array($this, 'disable_gutenberg_for_post_type'), 10, 2);
    83            
    84             if (!empty($this->settings['use_classic_widgets'])) {
    85                 add_action('after_setup_theme', array($this, 'disable_block_widgets'));
    86             }
    87            
    88             // Add per-post toggle if enabled
    89             if (!empty($this->settings['allow_per_post_toggle'])) {
    90                 // Add meta box to post edit screen
    91                 add_action('add_meta_boxes', array($this, 'add_editor_choice_meta_box'));
    92                 // Save post meta
    93                 add_action('save_post', array($this, 'save_editor_choice'));
    94                 // Add column to post list
    95                 add_filter('manage_posts_columns', array($this, 'add_editor_column'));
    96                 add_filter('manage_pages_columns', array($this, 'add_editor_column'));
    97                 add_action('manage_posts_custom_column', array($this, 'display_editor_column'), 10, 2);
    98                 add_action('manage_pages_custom_column', array($this, 'display_editor_column'), 10, 2);
    99                 // Add quick edit option
    100                 add_action('quick_edit_custom_box', array($this, 'add_quick_edit_field'), 10, 2);
    101                 add_action('admin_footer', array($this, 'quick_edit_javascript'));
    102             }
    103         }
    104        
     115        }
     116
     117        // Classic Widgets toggle is now independent - works in both simple and advanced modes
     118        // Only disable block widgets if the setting is enabled
     119        if (!empty($this->settings['use_classic_widgets'])) {
     120            add_action('after_setup_theme', array($this, 'disable_block_widgets'));
     121        }
     122
     123        // Per-post toggle is now independent of advanced settings
     124        // It works in both simple and advanced modes
     125        // BUT it requires the main plugin to be enabled to have any effect
     126        if (!empty($this->settings['allow_per_post_toggle']) && !empty($this->settings['enabled'])) {
     127            // Add meta box to post edit screen
     128            add_action('add_meta_boxes', array($this, 'add_editor_choice_meta_box'));
     129            // Save post meta
     130            add_action('save_post', array($this, 'save_editor_choice'));
     131            // Add column to post list
     132            add_filter('manage_posts_columns', array($this, 'add_editor_column'));
     133            add_filter('manage_pages_columns', array($this, 'add_editor_column'));
     134            add_action('manage_posts_custom_column', array($this, 'display_editor_column'), 10, 2);
     135            add_action('manage_pages_custom_column', array($this, 'display_editor_column'), 10, 2);
     136            // Add quick edit option
     137            add_action('quick_edit_custom_box', array($this, 'add_quick_edit_field'), 10, 2);
     138            add_action('admin_enqueue_scripts', array($this, 'quick_edit_javascript'));
     139        }
     140
    105141        // Always add settings page and links
    106142        add_action('admin_menu', array($this, 'add_settings_page'));
    107143        add_action('admin_init', array($this, 'register_settings'));
    108144        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_styles'));
    109        
     145
    110146        // Add settings link to plugins page
    111147        add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($this, 'add_settings_link'));
     
    120156
    121157    /**
    122      * Check if post should use classic editor based on post meta
    123      */
    124     public function disable_gutenberg_for_post($use_block_editor, $post) {
     158     * Simple mode without per-post toggle - always use classic editor if plugin is enabled
     159     */
     160    public function disable_gutenberg_simple_mode_no_toggle($use_block_editor, $post) {
     161        // If classic editor is not enabled, don't change the status
     162        if (empty($this->settings['enabled'])) {
     163            return $use_block_editor;
     164        }
     165
     166        // Plugin is enabled, use classic editor
     167        return false;
     168    }
     169
     170    /**
     171     * Handle per-post overrides in simple mode
     172     * In simple mode, classic editor is default but per-post toggle allows overrides
     173     */
     174    public function disable_gutenberg_for_post_simple_mode($use_block_editor, $post) {
     175        // If classic editor is not enabled, don't change the status
     176        if (empty($this->settings['enabled'])) {
     177            return $use_block_editor;
     178        }
     179
    125180        // Check if we have a post-specific setting
    126181        $editor_choice = get_post_meta($post->ID, '_ecew_editor_choice', true);
    127        
     182
    128183        if ($editor_choice === 'block') {
    129184            // Post explicitly wants to use block editor
     
    133188            return false;
    134189        }
    135        
    136         // No post-specific setting, use post type setting
     190
     191        // No post-specific setting, default to classic editor in simple mode
     192        return false;
     193    }
     194
     195    /**
     196     * Check if post should use classic editor based on post meta
     197     */
     198    public function disable_gutenberg_for_post($use_block_editor, $post) {
     199        // If classic editor is not enabled, don't change the status
     200        if (empty($this->settings['enabled'])) {
     201            return $use_block_editor;
     202        }
     203
     204        // Check if we have a post-specific setting (only if per-post toggle is enabled)
     205        if (!empty($this->settings['allow_per_post_toggle'])) {
     206            $editor_choice = get_post_meta($post->ID, '_ecew_editor_choice', true);
     207
     208            if ($editor_choice === 'block') {
     209                // Post explicitly wants to use block editor
     210                return true;
     211            } elseif ($editor_choice === 'classic') {
     212                // Post explicitly wants to use classic editor
     213                return false;
     214            }
     215        }
     216
     217        // No post-specific setting, use post type setting (advanced mode only)
     218        // In simple mode with per-post toggle, we already return false in init()
    137219        return $this->disable_gutenberg_for_post_type($use_block_editor, $post->post_type);
    138220    }
     
    188270        // Add nonce for security
    189271        wp_nonce_field('ecew_editor_choice_nonce', 'ecew_editor_choice_nonce');
    190        
     272
    191273        // Get current value
    192274        $editor_choice = get_post_meta($post->ID, '_ecew_editor_choice', true);
    193        
     275
    194276        // Default to post type setting if not set
    195277        if (empty($editor_choice)) {
    196278            $editor_choice = 'default';
    197279        }
     280
     281        // Determine what "default" means for this post
     282        $default_editor = $this->get_actual_editor_for_post($post);
     283        $default_editor_label = $default_editor === 'classic' ? __('Classic Editor', 'enable-classic-editor') : __('Block Editor', 'enable-classic-editor');
    198284        ?>
    199285        <p>
     
    201287                <input type="radio" name="ecew_editor_choice" value="default" <?php checked($editor_choice, 'default'); ?>>
    202288                <?php _e('Use default setting', 'enable-classic-editor'); ?>
     289                <span class="description">(<?php echo esc_html($default_editor_label); ?>)</span>
    203290            </label>
    204291        </p>
     
    225312     */
    226313    public function save_editor_choice($post_id) {
    227         // Check if nonce is set
    228         if (!isset($_POST['ecew_editor_choice_nonce'])) {
    229             return;
    230         }
    231        
    232         // Verify nonce
    233         if (!wp_verify_nonce($_POST['ecew_editor_choice_nonce'], 'ecew_editor_choice_nonce')) {
    234             return;
    235         }
    236        
    237314        // Check if autosave
    238315        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
    239316            return;
    240317        }
    241        
     318
    242319        // Check permissions
    243320        if (!current_user_can('edit_post', $post_id)) {
    244321            return;
    245322        }
    246        
     323
     324        // Determine if this is a quick edit or meta box save
     325        $is_quick_edit = isset($_POST['_inline_edit']);
     326        $is_meta_box = isset($_POST['ecew_editor_choice_nonce']);
     327
     328        // Verify nonces based on the save type
     329        if ($is_quick_edit) {
     330            // Quick edit uses WordPress's built-in nonce
     331            if (!check_ajax_referer('inlineeditnonce', '_inline_edit', false)) {
     332                return;
     333            }
     334        } elseif ($is_meta_box) {
     335            // Meta box uses our custom nonce
     336            if (!wp_verify_nonce($_POST['ecew_editor_choice_nonce'], 'ecew_editor_choice_nonce')) {
     337                return;
     338            }
     339        } else {
     340            // No valid nonce found, exit
     341            return;
     342        }
     343
    247344        // Save editor choice
    248345        if (isset($_POST['ecew_editor_choice'])) {
     
    276373            return;
    277374        }
    278        
     375
    279376        $editor_choice = get_post_meta($post_id, '_ecew_editor_choice', true);
    280        
     377        $post = get_post($post_id);
     378
     379        // Determine actual editor that will be used
     380        $actual_editor = $this->get_actual_editor_for_post($post);
     381
    281382        switch ($editor_choice) {
    282383            case 'classic':
    283                 echo '<span class="dashicons dashicons-editor-kitchensink" title="' . esc_attr__('Classic Editor', 'enable-classic-editor') . '"></span>';
     384                echo '<span class="dashicons dashicons-editor-kitchensink" title="' . esc_attr__('Classic Editor (Forced)', 'enable-classic-editor') . '" style="color: #2271b1;"></span>';
    284385                break;
    285386            case 'block':
    286                 echo '<span class="dashicons dashicons-block-default" title="' . esc_attr__('Block Editor', 'enable-classic-editor') . '"></span>';
     387                echo '<span class="dashicons dashicons-block-default" title="' . esc_attr__('Block Editor (Forced)', 'enable-classic-editor') . '" style="color: #2271b1;"></span>';
    287388                break;
    288389            default:
    289                 echo '<span class="dashicons dashicons-admin-generic" title="' . esc_attr__('Default Editor', 'enable-classic-editor') . '"></span>';
     390                // Show the actual editor that will be used
     391                $icon = $actual_editor === 'classic' ? 'editor-kitchensink' : 'block-default';
     392                $editor_name = $actual_editor === 'classic' ? __('Classic Editor', 'enable-classic-editor') : __('Block Editor', 'enable-classic-editor');
     393                $title = sprintf(
     394                    __('Default (%s)', 'enable-classic-editor'),
     395                    $editor_name
     396                );
     397                echo '<span class="dashicons dashicons-' . esc_attr($icon) . '" title="' . esc_attr($title) . '" style="opacity: 0.6;"></span>';
    290398                break;
    291399        }
     
    316424
    317425    /**
    318      * Add JavaScript for quick edit
     426     * Enqueue JavaScript for quick edit on post list screens
    319427     */
    320428    public function quick_edit_javascript() {
    321429        $screen = get_current_screen();
    322        
     430
    323431        if (!$screen || !in_array($screen->base, array('edit', 'edit-tags'))) {
    324432            return;
    325433        }
    326         ?>
    327         <script type="text/javascript">
    328             jQuery(document).ready(function($) {
    329                 // Save the original quick edit function
    330                 var $wp_inline_edit = inlineEditPost.edit;
    331                
    332                 // Override the quick edit function
    333                 inlineEditPost.edit = function(id) {
    334                     // Call the original function
    335                     $wp_inline_edit.apply(this, arguments);
    336                    
    337                     // Get the post ID
    338                     var post_id = 0;
    339                     if (typeof(id) === 'object') {
    340                         post_id = parseInt(this.getId(id));
    341                     }
    342                    
    343                     if (post_id > 0) {
    344                         // Get the row
    345                         var $row = $('#post-' + post_id);
    346                        
    347                         // Get the editor choice
    348                         var editor_choice = '';
    349                         var $editor_icon = $row.find('td.editor_choice .dashicons');
    350                        
    351                         if ($editor_icon.hasClass('dashicons-editor-kitchensink')) {
    352                             editor_choice = 'classic';
    353                         } else if ($editor_icon.hasClass('dashicons-block-default')) {
    354                             editor_choice = 'block';
    355                         } else {
    356                             editor_choice = 'default';
    357                         }
    358                        
    359                         // Set the value in the quick edit form
    360                         var $edit_row = $('#edit-' + post_id);
    361                         $edit_row.find('select[name="ecew_editor_choice"]').val(editor_choice);
    362                     }
    363                 };
    364             });
    365         </script>
    366         <?php
     434
     435        // Check if user has capability to edit posts
     436        if (!current_user_can('edit_posts')) {
     437            return;
     438        }
     439
     440        // Enqueue the admin.js file which contains the quick edit functionality
     441        wp_enqueue_script(
     442            'classic-editor-admin-js',
     443            ECEW_PLUGIN_URL . 'assets/js/admin.js',
     444            array('jquery', 'inline-edit-post'),
     445            ECEW_VERSION,
     446            true
     447        );
    367448    }
    368449
     
    408489    public function sanitize_settings($input) {
    409490        $sanitized_input = array();
    410        
     491
    411492        // Sanitize enabled status
    412493        $sanitized_input['enabled'] = isset($input['enabled']) ? 1 : 0;
    413        
    414         // Sanitize post types
     494
     495        // Sanitize post types with validation against actual registered post types
    415496        if (isset($input['post_types']) && is_array($input['post_types'])) {
    416             $sanitized_input['post_types'] = array_map('sanitize_text_field', $input['post_types']);
     497            $valid_post_types = array_keys(get_post_types(array('public' => true), 'names'));
     498            $sanitized_input['post_types'] = array_intersect(
     499                array_map('sanitize_text_field', $input['post_types']),
     500                $valid_post_types
     501            );
    417502        } else {
    418503            $sanitized_input['post_types'] = array();
    419504        }
    420        
    421         // Sanitize user roles
     505
     506        // Sanitize user roles with validation against actual registered roles
    422507        if (isset($input['user_roles']) && is_array($input['user_roles'])) {
    423             $sanitized_input['user_roles'] = array_map('sanitize_text_field', $input['user_roles']);
     508            $valid_roles = array_keys(wp_roles()->roles);
     509            $sanitized_input['user_roles'] = array_intersect(
     510                array_map('sanitize_text_field', $input['user_roles']),
     511                $valid_roles
     512            );
    424513        } else {
    425514            $sanitized_input['user_roles'] = array();
    426515        }
    427        
     516
    428517        // Sanitize classic widgets toggle
    429518        $sanitized_input['use_classic_widgets'] = isset($input['use_classic_widgets']) ? 1 : 0;
    430        
    431         // Sanitize settings page toggle
     519
     520        // Sanitize settings page toggle (Advanced Settings)
    432521        $sanitized_input['show_settings_page'] = isset($input['show_settings_page']) ? 1 : 0;
    433        
     522
    434523        // Sanitize per-post toggle
    435524        $sanitized_input['allow_per_post_toggle'] = isset($input['allow_per_post_toggle']) ? 1 : 0;
    436        
     525
     526        // Enforce dependencies: If main plugin is disabled, force dependent features OFF
     527        // This ensures data integrity regardless of JavaScript state or disabled form fields
     528        if (empty($sanitized_input['enabled'])) {
     529            $sanitized_input['allow_per_post_toggle'] = 0;
     530            $sanitized_input['show_settings_page'] = 0;
     531        }
     532
     533        // Store last saved timestamp
     534        update_option('ecew_settings_last_saved', current_time('timestamp'));
     535
    437536        return $sanitized_input;
    438537    }
     
    448547        wp_enqueue_style(
    449548            'classic-editor-admin',
    450             plugin_dir_url(__FILE__) . 'classic-editor-admin.css',
    451             array()
     549            ECEW_PLUGIN_URL . 'classic-editor-admin.css',
     550            array(),
     551            ECEW_VERSION
    452552        );
    453553
     
    455555        wp_enqueue_script(
    456556            'classic-editor-admin-js',
    457             plugin_dir_url(__FILE__) . 'assets/js/admin.js',
     557            ECEW_PLUGIN_URL . 'assets/js/admin.js',
    458558            array('jquery'),
    459             null,
     559            ECEW_VERSION,
    460560            true
    461561        );
    462562       
    463         // Pass settings to JavaScript
     563        // Pass translatable strings and settings to JavaScript
    464564        wp_localize_script(
    465565            'classic-editor-admin-js',
    466566            'ecewSettings',
    467567            array(
    468                 'resetConfirmMessage' => __('Are you sure you want to reset all settings to default values?', 'enable-classic-editor')
     568                // Legacy setting (kept for compatibility)
     569                'resetConfirmMessage' => __('Are you sure you want to reset all settings to default values?', ECEW_TEXT_DOMAIN),
     570
     571                // Translatable strings for admin.js
     572                'i18n' => array(
     573                    'unsavedChanges' => __('You have unsaved changes. Leave anyway?', ECEW_TEXT_DOMAIN),
     574                    'postTypesSelected' => __('%d of %d post types selected', ECEW_TEXT_DOMAIN),
     575                    'userRolesSelected' => __('%d of %d user roles selected', ECEW_TEXT_DOMAIN),
     576                    'settingsSaved' => __('Settings saved successfully!', ECEW_TEXT_DOMAIN),
     577                    'resetToDefaults' => __('Settings reset to defaults. Click "Save Settings" to apply.', ECEW_TEXT_DOMAIN)
     578                )
    469579            )
    470580        );
     
    481591
    482592    /**
     593     * Helper function to output help tooltip
     594     */
     595    private function help_tooltip($text) {
     596        $tooltip_id = 'ecew-tooltip-' . md5($text);
     597        ?>
     598        <span class="ecew-help-tooltip"
     599              data-tooltip="<?php echo esc_attr($text); ?>"
     600              tabindex="0"
     601              role="button"
     602              aria-label="<?php echo esc_attr__('Help', ECEW_TEXT_DOMAIN); ?>"
     603              aria-describedby="<?php echo esc_attr($tooltip_id); ?>">
     604            <span class="dashicons dashicons-editor-help"></span>
     605            <span id="<?php echo esc_attr($tooltip_id); ?>" class="screen-reader-text"><?php echo esc_html($text); ?></span>
     606        </span>
     607        <?php
     608    }
     609
     610    /**
     611     * Helper to determine actual editor for a post
     612     * This is what will actually be used when "Default" is selected
     613     */
     614    private function get_actual_editor_for_post($post) {
     615        // If plugin is disabled, WordPress default is Block Editor
     616        if (empty($this->settings['enabled'])) {
     617            return 'block';
     618        }
     619
     620        // Simple mode - Classic Editor for everything
     621        if (empty($this->settings['show_settings_page'])) {
     622            return 'classic';
     623        }
     624
     625        // Advanced mode - check post type and user role
     626        $post_type = is_object($post) ? $post->post_type : get_post_type($post);
     627
     628        // Cache current user for performance (avoids multiple wp_get_current_user() calls)
     629        if ($this->current_user_cache === null) {
     630            $this->current_user_cache = wp_get_current_user();
     631        }
     632
     633        $post_type_enabled = in_array($post_type, $this->settings['post_types']);
     634        $user_role_enabled = !empty(array_intersect($this->current_user_cache->roles, $this->settings['user_roles']));
     635
     636        return ($post_type_enabled && $user_role_enabled) ? 'classic' : 'block';
     637    }
     638
     639    /**
     640     * Get validation warnings for current settings
     641     */
     642    private function get_settings_warnings() {
     643        $warnings = array();
     644
     645        // Check if plugin is disabled
     646        if (empty($this->settings['enabled'])) {
     647            $warnings[] = array(
     648                'type' => 'info',
     649                'message' => __('Classic Editor is currently disabled. WordPress will use the Block Editor by default.', 'enable-classic-editor')
     650            );
     651        }
     652
     653        // Check Advanced Mode with no selections
     654        if (!empty($this->settings['show_settings_page']) && !empty($this->settings['enabled'])) {
     655            if (empty($this->settings['post_types'])) {
     656                $warnings[] = array(
     657                    'type' => 'warning',
     658                    'message' => __('Advanced Mode is enabled but no post types are selected. Classic Editor will not be applied to any content.', ECEW_TEXT_DOMAIN)
     659                );
     660            }
     661            if (empty($this->settings['user_roles'])) {
     662                $warnings[] = array(
     663                    'type' => 'warning',
     664                    'message' => __('Advanced Mode is enabled but no user roles are selected. Classic Editor will not be applied to any users.', ECEW_TEXT_DOMAIN)
     665                );
     666            }
     667
     668            // Check if per-post toggle is enabled with Advanced Mode
     669            if (!empty($this->settings['allow_per_post_toggle'])) {
     670                $warnings[] = array(
     671                    'type' => 'info',
     672                    'message' => __('Per-Post Toggle is enabled in Advanced Mode. Individual post editor preferences can override Post Type and User Role restrictions. Consider disabling Per-Post Toggle if you want strict role-based control.', ECEW_TEXT_DOMAIN)
     673                );
     674            }
     675        }
     676
     677        return $warnings;
     678    }
     679
     680    /**
     681     * Render mode indicator section
     682     */
     683    private function render_mode_indicator($is_advanced_mode) {
     684        $current_mode = $is_advanced_mode ? __('Advanced Mode', ECEW_TEXT_DOMAIN) : __('Simple Mode', ECEW_TEXT_DOMAIN);
     685        ?>
     686        <div class="ecew-mode-indicator <?php echo esc_attr($is_advanced_mode ? 'advanced' : 'simple'); ?>">
     687            <span class="mode-badge"><?php echo esc_html($current_mode); ?></span>
     688            <p class="mode-description">
     689                <?php if ($is_advanced_mode): ?>
     690                    <?php _e('You are using Advanced Mode. Configure specific post types and user roles.', ECEW_TEXT_DOMAIN); ?>
     691                <?php else: ?>
     692                    <?php _e('You are using Simple Mode. Classic editor is enabled for all content. Enable "Advanced Settings" for granular control.', ECEW_TEXT_DOMAIN); ?>
     693                <?php endif; ?>
     694            </p>
     695        </div>
     696        <?php
     697    }
     698
     699    /**
     700     * Render validation warnings
     701     */
     702    private function render_validation_warnings() {
     703        $warnings = $this->get_settings_warnings();
     704        if (empty($warnings)) {
     705            return;
     706        }
     707
     708        foreach ($warnings as $warning):
     709            $notice_class = $warning['type'] === 'warning' ? 'notice-warning' : 'notice-info';
     710        ?>
     711            <div class="notice <?php echo esc_attr($notice_class); ?> inline">
     712                <p><?php echo esc_html($warning['message']); ?></p>
     713            </div>
     714        <?php
     715        endforeach;
     716    }
     717
     718    /**
     719     * Render global settings section
     720     */
     721    private function render_global_settings_section() {
     722        ?>
     723        <div class="postbox">
     724            <h2 class="hndle"><span><?php _e('Global Settings', ECEW_TEXT_DOMAIN); ?></span></h2>
     725            <div class="inside">
     726                <table class="form-table">
     727                    <tbody>
     728                        <tr>
     729                            <th scope="row">
     730                                <label for="ecew_enabled">
     731                                    <?php _e('Enable Classic Editor', ECEW_TEXT_DOMAIN); ?>
     732                                    <?php $this->help_tooltip(__('When enabled, WordPress will use the Classic Editor instead of the Block Editor (Gutenberg) based on your configuration below.', ECEW_TEXT_DOMAIN)); ?>
     733                                </label>
     734                            </th>
     735                            <td>
     736                                <label class="toggle-switch" for="ecew_enabled" aria-label="<?php esc_attr_e('Toggle Classic Editor', ECEW_TEXT_DOMAIN); ?>">
     737                                    <input type="checkbox"
     738                                           id="ecew_enabled"
     739                                           name="ecew_settings[enabled]"
     740                                           value="1"
     741                                           <?php checked(!empty($this->settings['enabled'])); ?>>
     742                                    <span class="slider round"></span>
     743                                </label>
     744                                <p class="description">
     745                                    <?php _e('Uncheck to use Block Editor as the default editor.', ECEW_TEXT_DOMAIN); ?>
     746                                </p>
     747                            </td>
     748                        </tr>
     749                        <tr>
     750                            <th scope="row">
     751                                <label for="ecew_show_settings">
     752                                    <?php _e('Advanced Settings', ECEW_TEXT_DOMAIN); ?>
     753                                    <?php $this->help_tooltip(__('Enable this to configure Classic Editor by specific post types and user roles. When disabled, Classic Editor is enabled for all content (Simple Mode).', ECEW_TEXT_DOMAIN)); ?>
     754                                </label>
     755                            </th>
     756                            <td>
     757                                <label class="toggle-switch" for="ecew_show_settings" aria-label="<?php esc_attr_e('Toggle Advanced Settings', ECEW_TEXT_DOMAIN); ?>">
     758                                    <input type="checkbox"
     759                                           id="ecew_show_settings"
     760                                           name="ecew_settings[show_settings_page]"
     761                                           value="1"
     762                                           <?php checked(!empty($this->settings['show_settings_page'])); ?>
     763                                           <?php disabled(empty($this->settings['enabled'])); ?>>
     764                                    <span class="slider round"></span>
     765                                </label>
     766                                <p class="description">
     767                                    <?php _e('Enable to configure the classic editor by specific post types and user roles. When disabled, the plugin uses the classic editor for all content and users (Simple Mode).', ECEW_TEXT_DOMAIN); ?>
     768                                    <?php if (empty($this->settings['enabled'])): ?>
     769                                        <br><strong style="color: #d63638;">⚠️ <?php _e('Note: Advanced Settings requires "Enable Classic Editor" to be ON.', ECEW_TEXT_DOMAIN); ?></strong>
     770                                    <?php endif; ?>
     771                                </p>
     772                            </td>
     773                        </tr>
     774                        <tr>
     775                            <th scope="row">
     776                                <label for="ecew_classic_widgets_global">
     777                                    <?php _e('Classic Widgets', ECEW_TEXT_DOMAIN); ?>
     778                                    <?php $this->help_tooltip(__('Restores the traditional widgets interface from before WordPress 5.8. This is independent of the editor settings and works in both Simple and Advanced modes.', ECEW_TEXT_DOMAIN)); ?>
     779                                </label>
     780                            </th>
     781                            <td>
     782                                <label class="toggle-switch" for="ecew_classic_widgets_global" aria-label="<?php esc_attr_e('Toggle Classic Widgets', ECEW_TEXT_DOMAIN); ?>">
     783                                    <input type="checkbox"
     784                                           id="ecew_classic_widgets_global"
     785                                           name="ecew_settings[use_classic_widgets]"
     786                                           value="1"
     787                                           <?php checked(!empty($this->settings['use_classic_widgets'])); ?>>
     788                                    <span class="slider round"></span>
     789                                </label>
     790                                <p class="description">
     791                                    <?php _e('Use Classic Widgets interface instead of block-based widgets (applies in all modes).', ECEW_TEXT_DOMAIN); ?>
     792                                    <br>
     793                                    <em style="color: #646970; font-size: 12px;">
     794                                        <?php _e('Note: This setting only applies to themes that support widgets. Most themes include widget areas, but some modern block themes may not have widget support.', ECEW_TEXT_DOMAIN); ?>
     795                                    </em>
     796                                </p>
     797                            </td>
     798                        </tr>
     799                        <tr>
     800                            <th scope="row">
     801                                <label for="ecew_per_post_toggle">
     802                                    <?php _e('Per-Post Toggle', ECEW_TEXT_DOMAIN); ?>
     803                                    <?php $this->help_tooltip(__('Adds a meta box to each post/page edit screen allowing you to override the default editor choice for that specific post. Works in both Simple and Advanced modes. Priority: Per-post settings override Advanced Settings (Post Type & User Role).', ECEW_TEXT_DOMAIN)); ?>
     804                                </label>
     805                            </th>
     806                            <td>
     807                                <label class="toggle-switch" for="ecew_per_post_toggle" aria-label="<?php esc_attr_e('Toggle Per-Post Editor Selection', ECEW_TEXT_DOMAIN); ?>">
     808                                    <input type="checkbox"
     809                                           id="ecew_per_post_toggle"
     810                                           name="ecew_settings[allow_per_post_toggle]"
     811                                           value="1"
     812                                           <?php checked(!empty($this->settings['allow_per_post_toggle'])); ?>
     813                                           <?php disabled(empty($this->settings['enabled'])); ?>>
     814                                    <span class="slider round"></span>
     815                                </label>
     816                                <p class="description">
     817                                    <?php _e('Allows you to choose which editor (Classic or Block) to use for individual posts/pages. A meta box will appear on post edit screens. Works in both simple and advanced modes.', ECEW_TEXT_DOMAIN); ?>
     818                                    <?php if (empty($this->settings['enabled'])): ?>
     819                                        <br><strong style="color: #d63638;">⚠️ <?php _e('Note: This feature requires "Enable Classic Editor" to be ON.', ECEW_TEXT_DOMAIN); ?></strong>
     820                                    <?php endif; ?>
     821                                    <?php if (!empty($this->settings['show_settings_page'])): ?>
     822                                        <br><strong style="color: #d63638;">⚠️ <?php _e('Important: Per-post overrides take precedence over Advanced Settings (Post Type and User Role restrictions).', ECEW_TEXT_DOMAIN); ?></strong>
     823                                    <?php endif; ?>
     824                                </p>
     825                            </td>
     826                        </tr>
     827                    </tbody>
     828                </table>
     829            </div>
     830        </div>
     831        <?php
     832    }
     833
     834    /**
     835     * Render post type control section
     836     */
     837    private function render_post_type_control_section($post_types) {
     838        ?>
     839        <div class="postbox">
     840            <h2 class="hndle"><span><?php _e('Post Type Control', ECEW_TEXT_DOMAIN); ?></span></h2>
     841            <div class="inside">
     842                <?php if (!empty($this->settings['allow_per_post_toggle'])): ?>
     843                <div class="notice notice-info inline" style="margin: 0 0 15px 0; padding: 8px 12px;">
     844                    <p style="margin: 0.5em 0;">
     845                        <span class="dashicons dashicons-info" style="color: #2271b1;"></span>
     846                        <strong><?php _e('Note:', ECEW_TEXT_DOMAIN); ?></strong>
     847                        <?php _e('Per-Post Toggle is enabled. Individual post editor preferences will override the Post Type and User Role settings below.', ECEW_TEXT_DOMAIN); ?>
     848                    </p>
     849                </div>
     850                <?php endif; ?>
     851                <div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 15px; gap: 15px;">
     852                    <p class="description" style="margin: 0; flex: 1;">
     853                        <?php _e('Select which post types should use the Classic Editor instead of Gutenberg.', ECEW_TEXT_DOMAIN); ?>
     854                    </p>
     855                    <div class="selection-controls" style="display: flex; gap: 8px; flex-shrink: 0;">
     856                        <button type="button" class="button button-small select-all-post-types"><?php _e('Select All', ECEW_TEXT_DOMAIN); ?></button>
     857                        <button type="button" class="button button-small deselect-all-post-types"><?php _e('Deselect All', ECEW_TEXT_DOMAIN); ?></button>
     858                    </div>
     859                </div>
     860                <div class="selection-count" style="margin-bottom: 12px; font-size: 13px; color: #646970;">
     861                    <span class="post-types-count">
     862                        <?php
     863                        $selected_count = count($this->settings['post_types']);
     864                        $total_count = count($post_types);
     865                        printf(__('%d of %d post types selected', ECEW_TEXT_DOMAIN), $selected_count, $total_count);
     866                        ?>
     867                    </span>
     868                </div>
     869                <div class="post-type-checkboxes">
     870                    <?php foreach ($post_types as $post_type) : ?>
     871                    <div class="checkbox-item">
     872                        <label for="ecew_post_type_<?php echo esc_attr($post_type->name); ?>">
     873                            <input type="checkbox"
     874                                id="ecew_post_type_<?php echo esc_attr($post_type->name); ?>"
     875                                name="ecew_settings[post_types][]"
     876                                value="<?php echo esc_attr($post_type->name); ?>"
     877                                <?php checked(in_array($post_type->name, $this->settings['post_types'])); ?>>
     878                            <?php echo esc_html($post_type->label); ?>
     879                        </label>
     880                    </div>
     881                    <?php endforeach; ?>
     882                </div>
     883            </div>
     884        </div>
     885        <?php
     886    }
     887
     888    /**
     889     * Render user role control section
     890     */
     891    private function render_user_role_control_section($roles) {
     892        ?>
     893        <div class="postbox">
     894            <h2 class="hndle"><span><?php _e('User Role Control', ECEW_TEXT_DOMAIN); ?></span></h2>
     895            <div class="inside">
     896                <div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 15px; gap: 15px;">
     897                    <p class="description" style="margin: 0; flex: 1;">
     898                        <?php _e('Select which user roles should use the Classic Editor instead of Gutenberg.', ECEW_TEXT_DOMAIN); ?>
     899                    </p>
     900                    <div class="selection-controls" style="display: flex; gap: 8px; flex-shrink: 0;">
     901                        <button type="button" class="button button-small select-all-roles"><?php _e('Select All', ECEW_TEXT_DOMAIN); ?></button>
     902                        <button type="button" class="button button-small deselect-all-roles"><?php _e('Deselect All', ECEW_TEXT_DOMAIN); ?></button>
     903                    </div>
     904                </div>
     905                <div class="selection-count" style="margin-bottom: 12px; font-size: 13px; color: #646970;">
     906                    <span class="roles-count">
     907                        <?php
     908                        $selected_count_roles = count($this->settings['user_roles']);
     909                        $total_count_roles = count($roles);
     910                        printf(__('%d of %d user roles selected', ECEW_TEXT_DOMAIN), $selected_count_roles, $total_count_roles);
     911                        ?>
     912                    </span>
     913                </div>
     914                <div class="role-checkboxes">
     915                    <?php foreach ($roles as $role_key => $role) : ?>
     916                    <div class="checkbox-item">
     917                        <label for="ecew_role_<?php echo esc_attr($role_key); ?>">
     918                            <input type="checkbox"
     919                                id="ecew_role_<?php echo esc_attr($role_key); ?>"
     920                                name="ecew_settings[user_roles][]"
     921                                value="<?php echo esc_attr($role_key); ?>"
     922                                <?php checked(in_array($role_key, $this->settings['user_roles'])); ?>>
     923                            <?php echo esc_html(translate_user_role($role['name'])); ?>
     924                        </label>
     925                    </div>
     926                    <?php endforeach; ?>
     927                </div>
     928            </div>
     929        </div>
     930        <?php
     931    }
     932
     933    /**
    483934     * Render settings page
    484935     */
    485936    public function render_settings_page() {
    486         // Get all registered post types
     937        // Get all registered post types and roles
    487938        $post_types = get_post_types(array('public' => true), 'objects');
    488        
    489         // Get all user roles
    490939        $roles = wp_roles()->roles;
     940        $is_advanced_mode = !empty($this->settings['show_settings_page']);
    491941        ?>
    492942        <div class="wrap classic-editor-plus-settings">
    493             <h1><?php _e('Enable Classic Editor Settings', 'enable-classic-editor'); ?></h1>
    494            
     943            <!-- Page Header -->
     944            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
     945                <h1 style="margin: 0;"><?php _e('Enable Classic Editor Settings', ECEW_TEXT_DOMAIN); ?></h1>
     946                <?php
     947                $last_saved = get_option('ecew_settings_last_saved', false);
     948                if ($last_saved):
     949                ?>
     950                <div class="ecew-last-saved" style="color: #646970; font-size: 13px;">
     951                    <?php
     952                    printf(
     953                        __('Last saved: %s ago', ECEW_TEXT_DOMAIN),
     954                        human_time_diff($last_saved, current_time('timestamp'))
     955                    );
     956                    ?>
     957                </div>
     958                <?php endif; ?>
     959            </div>
     960
     961            <!-- Mode Indicator -->
     962            <?php $this->render_mode_indicator($is_advanced_mode); ?>
     963
     964            <!-- Validation Warnings -->
     965            <?php $this->render_validation_warnings(); ?>
     966
     967            <!-- WordPress Settings Errors -->
    495968            <?php settings_errors('ecew_settings'); ?>
    496            
     969
     970            <!-- Settings Form -->
    497971            <form method="post" action="options.php">
    498972                <?php settings_fields('ecew_settings_group'); ?>
    499                
     973
    500974                <div class="metabox-holder">
    501975                    <!-- Global Settings Section -->
    502                     <div class="postbox">
    503                         <h2 class="hndle"><span><?php _e('Global Settings', 'enable-classic-editor'); ?></span></h2>
    504                         <div class="inside">
    505                             <table class="form-table">
    506                                 <tbody>
    507                                     <tr>
    508                                         <th scope="row">
    509                                             <label for="ecew_enabled">
    510                                                 <?php _e('Enable Classic Editor', 'enable-classic-editor'); ?>
    511                                             </label>
    512                                         </th>
    513                                         <td>
    514                                             <label class="toggle-switch" for="ecew_enabled">
    515                                                 <input type="checkbox"
    516                                                        id="ecew_enabled"
    517                                                        name="ecew_settings[enabled]"
    518                                                        value="1"
    519                                                        <?php checked(!empty($this->settings['enabled'])); ?>>
    520                                                 <span class="slider round"></span>
    521                                             </label>
    522                                             <p class="description">
    523                                                 <?php _e('Uncheck to use Block Editor as the default editor.', 'enable-classic-editor'); ?>
    524                                             </p>
    525                                         </td>
    526                                     </tr>
    527                                     <tr>
    528                                         <th scope="row">
    529                                             <label for="ecew_show_settings">
    530                                                 <?php _e('Advanced Settings', 'enable-classic-editor'); ?>
    531                                             </label>
    532                                         </th>
    533                                         <td>
    534                                             <label class="toggle-switch" for="ecew_show_settings">
    535                                                 <input type="checkbox"
    536                                                        id="ecew_show_settings"
    537                                                        name="ecew_settings[show_settings_page]"
    538                                                        value="1"
    539                                                        <?php checked(!empty($this->settings['show_settings_page'])); ?>>
    540                                                 <span class="slider round"></span>
    541                                             </label>
    542                                             <p class="description">
    543                                                 <?php _e('When disabled, the plugin will use the classic editor for all content (original behavior).', 'enable-classic-editor'); ?>
    544                                             </p>
    545                                         </td>
    546                                     </tr>
    547                                     <tr>
    548                                         <th scope="row">
    549                                             <label for="ecew_per_post_toggle">
    550                                                 <?php _e('Per-Post Toggle', 'enable-classic-editor'); ?>
    551                                             </label>
    552                                         </th>
    553                                         <td>
    554                                             <label class="toggle-switch" for="ecew_per_post_toggle">
    555                                                 <input type="checkbox"
    556                                                        id="ecew_per_post_toggle"
    557                                                        name="ecew_settings[allow_per_post_toggle]"
    558                                                        value="1"
    559                                                        <?php checked(!empty($this->settings['allow_per_post_toggle'])); ?>>
    560                                                 <span class="slider round"></span>
    561                                             </label>
    562                                             <p class="description">
    563                                                 <?php _e('When enabled, a meta box will be added to the post/page edit screen to select which editor to use.', 'enable-classic-editor'); ?>
    564                                             </p>
    565                                         </td>
    566                                     </tr>
    567                                 </tbody>
    568                             </table>
    569                         </div>
    570                     </div>
    571                    
     976                    <?php $this->render_global_settings_section(); ?>
     977
    572978                    <!-- Advanced Settings Sections -->
    573979                    <div class="advanced-settings" <?php echo empty($this->settings['show_settings_page']) ? 'style="display:none;"' : ''; ?>>
    574                         <!-- Post Type Control Section -->
    575                         <div class="postbox">
    576                             <h2 class="hndle"><span><?php _e('Post Type Control', 'enable-classic-editor'); ?></span></h2>
    577                             <div class="inside">
    578                                 <p class="description">
    579                                     <?php _e('Select which post types should use the Classic Editor instead of Gutenberg.', 'enable-classic-editor'); ?>
    580                                 </p>
    581                                 <div class="post-type-checkboxes">
    582                                     <?php foreach ($post_types as $post_type) : ?>
    583                                     <div class="checkbox-item">
    584                                         <label for="ecew_post_type_<?php echo esc_attr($post_type->name); ?>">
    585                                             <input type="checkbox"
    586                                                 id="ecew_post_type_<?php echo esc_attr($post_type->name); ?>"
    587                                                 name="ecew_settings[post_types][]"
    588                                                 value="<?php echo esc_attr($post_type->name); ?>"
    589                                                 <?php checked(in_array($post_type->name, $this->settings['post_types'])); ?>>
    590                                             <?php echo esc_html($post_type->label); ?>
    591                                         </label>
    592                                     </div>
    593                                     <?php endforeach; ?>
    594                                 </div>
    595                             </div>
    596                         </div>
    597                        
    598                         <!-- User Role Control Section -->
    599                         <div class="postbox">
    600                             <h2 class="hndle"><span><?php _e('User Role Control', 'enable-classic-editor'); ?></span></h2>
    601                             <div class="inside">
    602                                 <p class="description">
    603                                     <?php _e('Select which user roles should use the Classic Editor instead of Gutenberg.', 'enable-classic-editor'); ?>
    604                                 </p>
    605                                 <div class="role-checkboxes">
    606                                     <?php foreach ($roles as $role_key => $role) : ?>
    607                                     <div class="checkbox-item">
    608                                         <label for="ecew_role_<?php echo esc_attr($role_key); ?>">
    609                                             <input type="checkbox"
    610                                                 id="ecew_role_<?php echo esc_attr($role_key); ?>"
    611                                                 name="ecew_settings[user_roles][]"
    612                                                 value="<?php echo esc_attr($role_key); ?>"
    613                                                 <?php checked(in_array($role_key, $this->settings['user_roles'])); ?>>
    614                                             <?php echo esc_html(translate_user_role($role['name'])); ?>
    615                                         </label>
    616                                     </div>
    617                                     <?php endforeach; ?>
    618                                 </div>
    619                             </div>
    620                         </div>
    621                        
    622                         <!-- Classic Widgets Toggle Section -->
    623                         <div class="postbox">
    624                             <h2 class="hndle"><span><?php _e('Classic Widgets Control', 'enable-classic-editor'); ?></span></h2>
    625                             <div class="inside">
    626                                 <table class="form-table">
    627                                     <tbody>
    628                                         <tr>
    629                                             <th scope="row">
    630                                                 <label for="ecew_classic_widgets">
    631                                                     <?php _e('Widget Interface', 'enable-classic-editor'); ?>
    632                                                 </label>
    633                                             </th>
    634                                             <td>
    635                                                 <label class="toggle-switch" for="ecew_classic_widgets">
    636                                                     <input type="checkbox"
    637                                                            id="ecew_classic_widgets"
    638                                                            name="ecew_settings[use_classic_widgets]"
    639                                                            value="1"
    640                                                            <?php checked(!empty($this->settings['use_classic_widgets'])); ?>>
    641                                                     <span class="slider round"></span>
    642                                                 </label>
    643                                                 <p class="description">
    644                                                     <?php _e('Use Classic Widgets interface instead of block-based widgets', 'enable-classic-editor'); ?>
    645                                                 </p>
    646                                             </td>
    647                                         </tr>
    648                                     </tbody>
    649                                 </table>
    650                             </div>
    651                         </div>
     980                        <?php $this->render_post_type_control_section($post_types); ?>
     981                        <?php $this->render_user_role_control_section($roles); ?>
    652982                    </div>
    653983                </div>
    654                
     984
     985                <!-- Submit Buttons -->
    655986                <div class="submit-buttons">
    656                     <button type="button" class="button button-secondary" id="reset-defaults"><?php _e('Reset Defaults', 'enable-classic-editor'); ?></button>
    657                     <?php submit_button(__('Save Settings', 'enable-classic-editor'), 'primary', 'submit', false); ?>
     987                    <button type="button" class="button button-secondary" id="reset-defaults"><?php _e('Reset Defaults', ECEW_TEXT_DOMAIN); ?></button>
     988                    <?php submit_button(__('Save Settings', ECEW_TEXT_DOMAIN), 'primary', 'submit', false); ?>
    658989                </div>
    659990            </form>
  • enable-classic-editor/trunk/readme.txt

    r3301448 r3392035  
    55Requires at least: 4.9
    66Requires PHP: 5.6
    7 Tested up to: 6.8.1
     7Tested up to: 6.8.3
    88Stable tag: trunk
    99License: GPLv2+
     
    5353== Changelog ==
    5454
    55 = 3.1 =
     55= 3.2 =
     56* New Feature: Animated save button with success confirmation
     57* New Feature: Toast notifications for better user feedback
     58* New Feature: Unsaved changes detection with warning before navigating away
     59* New Feature: Select All/Deselect All buttons for post types and user roles
     60* New Feature: Dynamic selection count for post types and user roles
     61* New Feature: Contextual help tooltips with detailed explanations
     62* New Feature: Last saved timestamp display
     63* Improvement: Per-Post Toggle now properly disabled when main plugin is OFF
     64* Improvement: Advanced Settings now properly disabled when main plugin is OFF
     65* Improvement: Settings validation warnings for conflicting configurations
     66* Improvement: "Default" editor choice now shows what editor will actually be used
     67* Improvement: Post list column shows actual editor (not just setting) with visual distinction
     68* Improvement: Classic Widgets setting includes theme compatibility note
     69* Improvement: Custom modal dialog for Reset Defaults (replaces browser confirm)
     70* Improvement: Better visual feedback with disabled setting styling
     71* Code quality: Improved inline documentation and code organization
     72* Major refactoring: Per-Post Toggle and Classic Widgets toggles are now truly independent
     73* Fixed critical bug: Classic Widgets toggle now works correctly in simple mode
     74* Fixed critical bug: Per-Post Toggle now works correctly in simple mode when Advanced Settings is disabled
     75* Improved UX: Added visual mode indicator (Simple vs Advanced) on settings page
     76* Improved UX: Enhanced help text for all settings
     77* Improved UX: Better JavaScript to prevent auto-enabling Advanced Settings
     78* Fixed: Reset Defaults button now correctly resets all toggles including Classic Widgets
     79* Code quality improvements and better inline documentation
     80* And of course, General maintenance
     81
     82= 3.1 =
    5683* General maintenance
    5784
  • enable-classic-editor/trunk/uninstall.php

    r3295733 r3392035  
    1313// Delete plugin options
    1414delete_option('ecew_settings');
     15delete_option('ecew_settings_last_saved');
    1516
    16 // Delete post meta data
     17// Delete post meta data using prepared statement for security
    1718global $wpdb;
    18 $wpdb->query("DELETE FROM {$wpdb->postmeta} WHERE meta_key = '_ecew_editor_choice'");
     19$wpdb->query(
     20    $wpdb->prepare(
     21        "DELETE FROM {$wpdb->postmeta} WHERE meta_key = %s",
     22        '_ecew_editor_choice'
     23    )
     24);
Note: See TracChangeset for help on using the changeset viewer.