Plugin Directory

Changeset 3396598


Ignore:
Timestamp:
11/16/2025 01:14:20 PM (3 months ago)
Author:
prakharb88
Message:

Version 1.1.0 - Added file and folder ownership reset functionality with automatic server detection, smart recommendations, and tab-based navigation

Location:
reset-file-and-folder-permissions
Files:
12 edited
1 copied

Legend:

Unmodified
Added
Removed
  • reset-file-and-folder-permissions/tags/1.1.0/assets/admin.css

    r3345847 r3396598  
    44 * @package FilePermissionsReset
    55 */
     6
     7/* Tab Navigation */
     8.nav-tab-wrapper {
     9    margin: 20px 0;
     10    border-bottom: 1px solid #ccc;
     11}
     12
     13.nav-tab {
     14    background: #f1f1f1;
     15    border: 1px solid #ccc;
     16    border-bottom: none;
     17    color: #555;
     18    text-decoration: none;
     19    padding: 10px 15px;
     20    margin-right: 5px;
     21    display: inline-block;
     22    font-weight: 600;
     23    transition: all 0.3s ease;
     24}
     25
     26.nav-tab:hover {
     27    background: #fff;
     28    color: #333;
     29}
     30
     31.nav-tab-active,
     32.nav-tab-active:hover {
     33    background: #fff;
     34    border-bottom-color: #fff;
     35    color: #000;
     36    margin-bottom: -1px;
     37    padding-bottom: 11px;
     38}
     39
     40/* Compatibility Warning */
     41.notice.notice-error h3 {
     42    margin-top: 0;
     43    color: #d63638;
     44}
     45
     46.notice.notice-error code {
     47    background: #fff;
     48    padding: 2px 6px;
     49    border-radius: 3px;
     50    font-size: 13px;
     51    color: #d63638;
     52    font-weight: 600;
     53}
     54
     55.notice.notice-error ul {
     56    margin: 10px 0;
     57    padding-left: 20px;
     58}
     59
     60.notice.notice-error li {
     61    margin-bottom: 8px;
     62    line-height: 1.6;
     63}
    664
    765/* Main Layout */
  • reset-file-and-folder-permissions/tags/1.1.0/assets/admin.js

    r3345847 r3396598  
    1919        errorMessages: [],
    2020
     21        // Ownership-specific state
     22        ownershipIsProcessing: false,
     23        ownershipTotalItems: 0,
     24        ownershipProcessedItems: 0,
     25        ownershipCurrentOffset: 0,
     26        ownershipBatchSize: 100,
     27        ownershipFilesUpdated: 0,
     28        ownershipDirsUpdated: 0,
     29        ownershipTotalErrors: 0,
     30        ownershipErrorMessages: [],
     31
    2132        init: function() {
    2233            this.bindEvents();
     34            this.loadServerInfo();
    2335        },
    2436
    2537        bindEvents: function() {
     38            // Permissions tab events
    2639            $('#resetfileperm-scan-btn').on('click', this.scanDirectory.bind(this));
    2740            $('#resetfileperm-reset-btn').on('click', this.resetPermissions.bind(this));
    2841            $('#resetfileperm-directory').on('change', this.onDirectoryChange.bind(this));
    2942            $('#resetfileperm-batch-size').on('change', this.onBatchSizeChange.bind(this));
     43
     44            // Ownership tab events
     45            $('#resetfileperm-ownership-scan-btn').on('click', this.scanDirectoryForOwnership.bind(this));
     46            $('#resetfileperm-ownership-reset-btn').on('click', this.resetOwnership.bind(this));
     47            $('#resetfileperm-ownership-directory').on('change', this.onOwnershipDirectoryChange.bind(this));
     48            $('#resetfileperm-ownership-batch-size').on('change', this.onOwnershipBatchSizeChange.bind(this));
     49        },
     50
     51        loadServerInfo: function() {
     52            // Only load if we're on the ownership tab
     53            if ($('#resetfileperm-ownership-server-info').length === 0) {
     54                return;
     55            }
     56
     57            var data = {
     58                action: 'resetfileperm_get_server_info',
     59                nonce: resetfilepermAjax.nonce
     60            };
     61
     62            $.post(resetfilepermAjax.ajaxUrl, data)
     63                .done(this.onServerInfoLoaded.bind(this))
     64                .fail(function() {
     65                    $('#resetfileperm-ownership-server-info').html(
     66                        '<div class="notice notice-error"><p>Failed to load server information.</p></div>'
     67                    );
     68                });
     69        },
     70
     71        onServerInfoLoaded: function(response) {
     72            if (!response.success || !response.data.functions_available) {
     73                return;
     74            }
     75
     76            var data = response.data;
     77            var html = '<table class="form-table">';
     78           
     79            if (data.recommended_owner) {
     80                html += '<tr>';
     81                html += '<th scope="row">Recommended Owner:</th>';
     82                html += '<td><code>' + $('<div>').text(data.recommended_owner).html() + '</code> <span class="description">(Current web server user)</span></td>';
     83                html += '</tr>';
     84            }
     85           
     86            if (data.recommended_group) {
     87                html += '<tr>';
     88                html += '<th scope="row">Recommended Group:</th>';
     89                html += '<td><code>' + $('<div>').text(data.recommended_group).html() + '</code> <span class="description">(Current web server group)</span></td>';
     90                html += '</tr>';
     91            }
     92           
     93            html += '</table>';
     94            $('#resetfileperm-ownership-server-info').html(html);
     95
     96            // Populate owner dropdown
     97            if (data.available_users && data.available_users.length > 0) {
     98                var ownerSelect = $('#resetfileperm-owner');
     99                ownerSelect.empty().append('<option value="">Select owner...</option>');
     100               
     101                data.available_users.forEach(function(user) {
     102                    var isRecommended = user === data.recommended_owner;
     103                    var label = user + (isRecommended ? ' (Recommended)' : '');
     104                    var option = $('<option></option>')
     105                        .val(user)
     106                        .text(label);
     107                   
     108                    if (isRecommended) {
     109                        option.prop('selected', true);
     110                    }
     111                   
     112                    ownerSelect.append(option);
     113                });
     114            }
     115
     116            // Populate group dropdown
     117            if (data.available_groups && data.available_groups.length > 0) {
     118                var groupSelect = $('#resetfileperm-group');
     119                groupSelect.empty().append('<option value="">Select group...</option>');
     120               
     121                data.available_groups.forEach(function(group) {
     122                    var isRecommended = group === data.recommended_group;
     123                    var label = group + (isRecommended ? ' (Recommended)' : '');
     124                    var option = $('<option></option>')
     125                        .val(group)
     126                        .text(label);
     127                   
     128                    if (isRecommended) {
     129                        option.prop('selected', true);
     130                    }
     131                   
     132                    groupSelect.append(option);
     133                });
     134            }
    30135        },
    31136
     
    36141        onBatchSizeChange: function() {
    37142            this.batchSize = parseInt($('#resetfileperm-batch-size').val(), 10);
     143        },
     144
     145        onOwnershipDirectoryChange: function() {
     146            this.resetOwnershipUI();
     147        },
     148
     149        onOwnershipBatchSizeChange: function() {
     150            this.ownershipBatchSize = parseInt($('#resetfileperm-ownership-batch-size').val(), 10);
    38151        },
    39152
     
    47160        },
    48161
     162        resetOwnershipUI: function() {
     163            $('#resetfileperm-ownership-scan-results').hide();
     164            $('#resetfileperm-ownership-progress-section').hide();
     165            $('#resetfileperm-ownership-error-log').hide();
     166            $('#resetfileperm-ownership-results-section').hide();
     167            $('#resetfileperm-ownership-reset-btn').prop('disabled', true);
     168            this.resetOwnershipProgress();
     169        },
     170
    49171        resetProgress: function() {
    50172            this.processedItems = 0;
     
    63185        },
    64186
     187        resetOwnershipProgress: function() {
     188            this.ownershipProcessedItems = 0;
     189            this.ownershipCurrentOffset = 0;
     190            this.ownershipFilesUpdated = 0;
     191            this.ownershipDirsUpdated = 0;
     192            this.ownershipTotalErrors = 0;
     193            this.ownershipErrorMessages = [];
     194
     195            $('#resetfileperm-ownership-progress-fill').css('width', '0%');
     196            $('#resetfileperm-ownership-progress-text').text('0%');
     197            $('#resetfileperm-ownership-current-status').text(resetfilepermAjax.strings.scanning);
     198            $('#resetfileperm-ownership-files-count').text('0');
     199            $('#resetfileperm-ownership-dirs-count').text('0');
     200            $('#resetfileperm-ownership-errors-count').text('0');
     201        },
     202
    65203        scanDirectory: function() {
    66204            if (this.isProcessing) {
     
    90228        },
    91229
     230        scanDirectoryForOwnership: function() {
     231            if (this.ownershipIsProcessing) {
     232                return;
     233            }
     234
     235            this.ownershipIsProcessing = true;
     236            this.resetOwnershipUI();
     237           
     238            $('#resetfileperm-ownership-scan-btn').prop('disabled', true).text(resetfilepermAjax.strings.scanning);
     239            $('#resetfileperm-ownership-progress-section').show();
     240            $('#resetfileperm-ownership-current-status').text(resetfilepermAjax.strings.scanning);
     241
     242            var data = {
     243                action: 'resetfileperm_scan_directory',
     244                nonce: resetfilepermAjax.nonce,
     245                directory: $('#resetfileperm-ownership-directory').val()
     246            };
     247
     248            $.post(resetfilepermAjax.ajaxUrl, data)
     249                .done(this.onOwnershipScanComplete.bind(this))
     250                .fail(this.onOwnershipScanError.bind(this))
     251                .always(function() {
     252                    this.ownershipIsProcessing = false;
     253                    $('#resetfileperm-ownership-scan-btn').prop('disabled', false).html('<span class="dashicons dashicons-search"></span> Scan Directory');
     254                }.bind(this));
     255        },
     256
    92257        onScanComplete: function(response) {
    93258            if (response.success) {
     
    114279        },
    115280
     281        onOwnershipScanComplete: function(response) {
     282            if (response.success) {
     283                var data = response.data;
     284                this.ownershipTotalItems = data.files + data.directories;
     285
     286                $('#resetfileperm-ownership-scan-files').text(data.files.toLocaleString());
     287                $('#resetfileperm-ownership-scan-dirs').text(data.directories.toLocaleString());
     288                $('#resetfileperm-ownership-scan-results').show();
     289
     290                if (data.errors.length > 0) {
     291                    this.showOwnershipErrors(data.errors);
     292                }
     293
     294                if (this.ownershipTotalItems > 0) {
     295                    $('#resetfileperm-ownership-reset-btn').prop('disabled', false);
     296                    $('#resetfileperm-ownership-current-status').text('Scan completed. Ready to reset ownership.');
     297                } else {
     298                    $('#resetfileperm-ownership-current-status').text('No files or directories found to process.');
     299                }
     300            } else {
     301                this.showOwnershipError('Scan failed: ' + (response.data || 'Unknown error'));
     302            }
     303        },
     304
    116305        onScanError: function(xhr, status, error) {
    117306            this.showError('Scan request failed: ' + error);
     307        },
     308
     309        onOwnershipScanError: function(xhr, status, error) {
     310            this.showOwnershipError('Scan request failed: ' + error);
    118311        },
    119312
     
    137330            this.batchSize = parseInt($('#resetfileperm-batch-size').val(), 10);
    138331            this.processNextBatch();
     332        },
     333
     334        resetOwnership: function() {
     335            if (this.ownershipIsProcessing || this.ownershipTotalItems === 0) {
     336                return;
     337            }
     338
     339            var owner = $('#resetfileperm-owner').val();
     340            var group = $('#resetfileperm-group').val();
     341
     342            if (!owner || !group) {
     343                alert('Please select both owner and group.');
     344                return;
     345            }
     346
     347            if (!confirm(resetfilepermAjax.strings.confirmOwnership)) {
     348                return;
     349            }
     350
     351            this.ownershipIsProcessing = true;
     352            this.resetOwnershipProgress();
     353           
     354            $('#resetfileperm-ownership-reset-btn').prop('disabled', true).text(resetfilepermAjax.strings.processingOwnership);
     355            $('#resetfileperm-ownership-scan-btn').prop('disabled', true);
     356            $('#resetfileperm-ownership-progress-section').show();
     357            $('#resetfileperm-ownership-current-status').text(resetfilepermAjax.strings.processingOwnership);
     358
     359            this.ownershipBatchSize = parseInt($('#resetfileperm-ownership-batch-size').val(), 10);
     360            this.processNextOwnershipBatch();
    139361        },
    140362
     
    153375        },
    154376
     377        processNextOwnershipBatch: function() {
     378            var data = {
     379                action: 'resetfileperm_reset_ownership',
     380                nonce: resetfilepermAjax.nonce,
     381                directory: $('#resetfileperm-ownership-directory').val(),
     382                owner: $('#resetfileperm-owner').val(),
     383                group: $('#resetfileperm-group').val(),
     384                batch_size: this.ownershipBatchSize,
     385                offset: this.ownershipCurrentOffset
     386            };
     387
     388            $.post(resetfilepermAjax.ajaxUrl, data)
     389                .done(this.onOwnershipBatchComplete.bind(this))
     390                .fail(this.onOwnershipBatchError.bind(this));
     391        },
     392
    155393        onBatchComplete: function(response) {
    156394            if (response.success) {
     
    180418        },
    181419
     420        onOwnershipBatchComplete: function(response) {
     421            if (response.success) {
     422                var data = response.data;
     423
     424                this.ownershipProcessedItems += data.processed;
     425                this.ownershipFilesUpdated += data.files_updated;
     426                this.ownershipDirsUpdated += data.directories_updated;
     427                this.ownershipCurrentOffset = data.next_offset;
     428
     429                if (data.errors.length > 0) {
     430                    this.ownershipTotalErrors += data.errors.length;
     431                    this.ownershipErrorMessages = this.ownershipErrorMessages.concat(data.errors);
     432                }
     433
     434                this.updateOwnershipProgress();
     435
     436                if (data.completed || data.processed === 0) {
     437                    this.onOwnershipProcessingComplete();
     438                } else {
     439                    // Continue with next batch
     440                    setTimeout(this.processNextOwnershipBatch.bind(this), 100);
     441                }
     442            } else {
     443                this.onOwnershipBatchError(null, null, response.data || 'Unknown error');
     444            }
     445        },
     446
    182447        onBatchError: function(xhr, status, error) {
    183448            this.isProcessing = false;
     
    186451        },
    187452
     453        onOwnershipBatchError: function(xhr, status, error) {
     454            this.ownershipIsProcessing = false;
     455            this.showOwnershipError('Processing failed: ' + error);
     456            this.enableOwnershipButtons();
     457        },
     458
    188459        onProcessingComplete: function() {
    189460            this.isProcessing = false;
     
    198469            if (this.errorMessages.length > 0) {
    199470                this.showErrors(this.errorMessages);
     471            }
     472        },
     473
     474        onOwnershipProcessingComplete: function() {
     475            this.ownershipIsProcessing = false;
     476           
     477            $('#resetfileperm-ownership-progress-fill').css('width', '100%');
     478            $('#resetfileperm-ownership-progress-text').text('100%');
     479            $('#resetfileperm-ownership-current-status').text(resetfilepermAjax.strings.ownershipCompleted);
     480
     481            this.showOwnershipResults();
     482            this.enableOwnershipButtons();
     483
     484            if (this.ownershipErrorMessages.length > 0) {
     485                this.showOwnershipErrors(this.ownershipErrorMessages);
    200486            }
    201487        },
     
    212498            var status = 'Processing... (' + this.processedItems.toLocaleString() + ' of ' + this.totalItems.toLocaleString() + ' items)';
    213499            $('#resetfileperm-current-status').text(status);
     500        },
     501
     502        updateOwnershipProgress: function() {
     503            var percentage = this.ownershipTotalItems > 0 ? Math.round((this.ownershipProcessedItems / this.ownershipTotalItems) * 100) : 0;
     504           
     505            $('#resetfileperm-ownership-progress-fill').css('width', percentage + '%');
     506            $('#resetfileperm-ownership-progress-text').text(percentage + '%');
     507            $('#resetfileperm-ownership-files-count').text(this.ownershipFilesUpdated.toLocaleString());
     508            $('#resetfileperm-ownership-dirs-count').text(this.ownershipDirsUpdated.toLocaleString());
     509            $('#resetfileperm-ownership-errors-count').text(this.ownershipTotalErrors.toLocaleString());
     510
     511            var status = 'Processing... (' + this.ownershipProcessedItems.toLocaleString() + ' of ' + this.ownershipTotalItems.toLocaleString() + ' items)';
     512            $('#resetfileperm-ownership-current-status').text(status);
    214513        },
    215514
     
    229528        },
    230529
     530        showOwnershipResults: function() {
     531            var html = '<div class="resetfileperm-results-summary">';
     532            html += '<h3>Summary</h3>';
     533            html += '<ul>';
     534            html += '<li><strong>Total items processed:</strong> ' + this.ownershipProcessedItems.toLocaleString() + '</li>';
     535            html += '<li><strong>Files updated:</strong> ' + this.ownershipFilesUpdated.toLocaleString() + '</li>';
     536            html += '<li><strong>Directories updated:</strong> ' + this.ownershipDirsUpdated.toLocaleString() + '</li>';
     537            html += '<li><strong>Errors encountered:</strong> ' + this.ownershipTotalErrors.toLocaleString() + '</li>';
     538            html += '</ul>';
     539            html += '</div>';
     540
     541            $('#resetfileperm-ownership-final-results').html(html);
     542            $('#resetfileperm-ownership-results-section').show();
     543        },
     544
    231545        showErrors: function(errors) {
    232546            if (errors.length === 0) {
     
    244558        },
    245559
     560        showOwnershipErrors: function(errors) {
     561            if (errors.length === 0) {
     562                return;
     563            }
     564
     565            var html = '<div class="notice notice-error"><ul>';
     566            errors.forEach(function(error) {
     567                html += '<li>' + $('<div>').text(error).html() + '</li>';
     568            });
     569            html += '</ul></div>';
     570
     571            $('#resetfileperm-ownership-error-messages').html(html);
     572            $('#resetfileperm-ownership-error-log').show();
     573        },
     574
    246575        showError: function(message) {
    247576            var html = '<div class="notice notice-error"><p>' + $('<div>').text(message).html() + '</p></div>';
     
    250579        },
    251580
     581        showOwnershipError: function(message) {
     582            var html = '<div class="notice notice-error"><p>' + $('<div>').text(message).html() + '</p></div>';
     583            $('#resetfileperm-ownership-error-messages').html(html);
     584            $('#resetfileperm-ownership-error-log').show();
     585        },
     586
    252587        enableButtons: function() {
    253588            $('#resetfileperm-scan-btn').prop('disabled', false).html('<span class="dashicons dashicons-search"></span> Scan Directory');
    254589            $('#resetfileperm-reset-btn').prop('disabled', this.totalItems === 0).html('<span class="dashicons dashicons-admin-tools"></span> Reset Permissions');
     590        },
     591
     592        enableOwnershipButtons: function() {
     593            $('#resetfileperm-ownership-scan-btn').prop('disabled', false).html('<span class="dashicons dashicons-search"></span> Scan Directory');
     594            $('#resetfileperm-ownership-reset-btn').prop('disabled', this.ownershipTotalItems === 0).html('<span class="dashicons dashicons-admin-tools"></span> Reset Ownership');
    255595        }
    256596    };
     
    261601    });
    262602
    263 })(jQuery); 
     603})(jQuery);
  • reset-file-and-folder-permissions/tags/1.1.0/file-permissions-reset.php

    r3345847 r3396598  
    44 * Plugin URI: https://nandann.com/contact
    55 * Description: A WordPress plugin to reset all file permissions to 0644 and all directory permissions to 0755 for security and maintenance purposes.
    6  * Version: 1.0.0
     6 * Version: 1.1.0
    77 * Author: Prakhar Bhatia
    88 * Author URI: https://nandann.com
     
    2626
    2727// Define plugin constants
    28 define( 'RESETFILEPERM_PLUGIN_VERSION', '1.0.0' );
     28define( 'RESETFILEPERM_PLUGIN_VERSION', '1.1.0' );
    2929define( 'RESETFILEPERM_PLUGIN_FILE', __FILE__ );
    3030define( 'RESETFILEPERM_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
     
    6565        add_action( 'wp_ajax_resetfileperm_reset_permissions', array( $this, 'ajax_reset_permissions' ) );
    6666        add_action( 'wp_ajax_resetfileperm_scan_directory', array( $this, 'ajax_scan_directory' ) );
     67        add_action( 'wp_ajax_resetfileperm_reset_ownership', array( $this, 'ajax_reset_ownership' ) );
     68        add_action( 'wp_ajax_resetfileperm_get_server_info', array( $this, 'ajax_get_server_info' ) );
    6769       
    6870        // Add settings link to plugins page
     
    129131                'error' => __( 'An error occurred', 'reset-file-and-folder-permissions' ),
    130132                'confirm' => __( 'Are you sure you want to reset file permissions? This action cannot be undone.', 'reset-file-and-folder-permissions' ),
     133                'processingOwnership' => __( 'Processing ownership...', 'reset-file-and-folder-permissions' ),
     134                'ownershipCompleted' => __( 'Ownership reset completed!', 'reset-file-and-folder-permissions' ),
     135                'confirmOwnership' => __( 'Are you sure you want to reset file and folder ownership? This action cannot be undone and may affect site functionality if incorrect values are used.', 'reset-file-and-folder-permissions' ),
    131136            )
    132137        ) );
     
    331336        return current_user_can( 'manage_options' ) && function_exists( 'chmod' );
    332337    }
     338
     339    /**
     340     * AJAX handler for getting server information
     341     */
     342    public function ajax_get_server_info() {
     343        // Verify nonce
     344        if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ?? '' ) ), 'resetfileperm_nonce' ) ) {
     345            wp_die( esc_html__( 'Security check failed', 'reset-file-and-folder-permissions' ) );
     346        }
     347
     348        // Check user capabilities
     349        if ( ! current_user_can( 'manage_options' ) ) {
     350            wp_die( esc_html__( 'Insufficient permissions', 'reset-file-and-folder-permissions' ) );
     351        }
     352
     353        $server_info = $this->get_server_info();
     354        wp_send_json_success( $server_info );
     355    }
     356
     357    /**
     358     * AJAX handler for resetting ownership
     359     */
     360    public function ajax_reset_ownership() {
     361        // Verify nonce
     362        if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ?? '' ) ), 'resetfileperm_nonce' ) ) {
     363            wp_die( esc_html__( 'Security check failed', 'reset-file-and-folder-permissions' ) );
     364        }
     365
     366        // Check user capabilities
     367        if ( ! current_user_can( 'manage_options' ) ) {
     368            wp_die( esc_html__( 'Insufficient permissions', 'reset-file-and-folder-permissions' ) );
     369        }
     370
     371        $directory = isset( $_POST['directory'] ) ? sanitize_text_field( wp_unslash( $_POST['directory'] ) ) : ABSPATH;
     372        $owner = isset( $_POST['owner'] ) ? sanitize_text_field( wp_unslash( $_POST['owner'] ) ) : '';
     373        $group = isset( $_POST['group'] ) ? sanitize_text_field( wp_unslash( $_POST['group'] ) ) : '';
     374        $batch_size = isset( $_POST['batch_size'] ) ? intval( $_POST['batch_size'] ) : 100;
     375        $offset = isset( $_POST['offset'] ) ? intval( $_POST['offset'] ) : 0;
     376       
     377        // Ensure we're within the WordPress installation
     378        $directory = realpath( $directory );
     379        $wp_root = realpath( ABSPATH );
     380       
     381        if ( ! $directory || strpos( $directory, $wp_root ) !== 0 ) {
     382            wp_send_json_error( __( 'Invalid directory path', 'reset-file-and-folder-permissions' ) );
     383        }
     384
     385        // Validate owner and group
     386        if ( empty( $owner ) || empty( $group ) ) {
     387            wp_send_json_error( __( 'Owner and group must be specified', 'reset-file-and-folder-permissions' ) );
     388        }
     389
     390        $result = $this->reset_ownership_batch( $directory, $owner, $group, $batch_size, $offset );
     391       
     392        wp_send_json_success( $result );
     393    }
     394
     395    /**
     396     * Get server information including recommended owner/group
     397     */
     398    private function get_server_info() {
     399        $info = array(
     400            'functions_available' => $this->check_ownership_functions(),
     401            'recommended_owner' => '',
     402            'recommended_group' => '',
     403            'available_users' => array(),
     404            'available_groups' => array(),
     405        );
     406
     407        if ( ! $info['functions_available'] ) {
     408            return $info;
     409        }
     410
     411        // Get recommended owner (current process user)
     412        if ( function_exists( 'posix_geteuid' ) && function_exists( 'posix_getpwuid' ) ) {
     413            $process_user = posix_getpwuid( posix_geteuid() );
     414            if ( $process_user ) {
     415                $info['recommended_owner'] = $process_user['name'];
     416                $info['recommended_group'] = posix_getgrgid( $process_user['gid'] )['name'] ?? '';
     417            }
     418        }
     419
     420        // Get available users (limited to common web server users for security)
     421        if ( function_exists( 'posix_getpwnam' ) ) {
     422            $common_users = array( 'www-data', 'apache', 'nginx', 'httpd', 'nobody', '_www' );
     423            foreach ( $common_users as $user ) {
     424                $user_info = posix_getpwnam( $user );
     425                if ( $user_info ) {
     426                    $info['available_users'][] = $user;
     427                }
     428            }
     429            // Add current user if not in list
     430            if ( ! empty( $info['recommended_owner'] ) && ! in_array( $info['recommended_owner'], $info['available_users'], true ) ) {
     431                $info['available_users'][] = $info['recommended_owner'];
     432            }
     433        }
     434
     435        // Get available groups (limited to common web server groups)
     436        if ( function_exists( 'posix_getgrnam' ) ) {
     437            $common_groups = array( 'www-data', 'apache', 'nginx', 'httpd', 'nobody', '_www', 'web' );
     438            foreach ( $common_groups as $group ) {
     439                $group_info = posix_getgrnam( $group );
     440                if ( $group_info ) {
     441                    $info['available_groups'][] = $group;
     442                }
     443            }
     444            // Add current group if not in list
     445            if ( ! empty( $info['recommended_group'] ) && ! in_array( $info['recommended_group'], $info['available_groups'], true ) ) {
     446                $info['available_groups'][] = $info['recommended_group'];
     447            }
     448        }
     449
     450        return $info;
     451    }
     452
     453    /**
     454     * Check if ownership functions are available
     455     */
     456    public static function check_ownership_functions() {
     457        return function_exists( 'chown' ) &&
     458               function_exists( 'chgrp' ) &&
     459               function_exists( 'posix_getpwnam' ) &&
     460               function_exists( 'posix_getgrnam' );
     461    }
     462
     463    /**
     464     * Reset ownership for a batch of files/directories
     465     */
     466    private function reset_ownership_batch( $directory, $owner, $group, $batch_size, $offset ) {
     467        $processed = 0;
     468        $files_updated = 0;
     469        $directories_updated = 0;
     470        $errors = array();
     471        $current_item = 0;
     472
     473        // Get owner and group IDs
     474        $owner_info = posix_getpwnam( $owner );
     475        $group_info = posix_getgrnam( $group );
     476
     477        if ( ! $owner_info ) {
     478            return array(
     479                'processed' => 0,
     480                'files_updated' => 0,
     481                'directories_updated' => 0,
     482                /* translators: %s: Owner name */
     483                'errors' => array( sprintf( __( 'Invalid owner: %s', 'reset-file-and-folder-permissions' ), $owner ) ),
     484                'next_offset' => $offset,
     485                'completed' => true,
     486            );
     487        }
     488
     489        if ( ! $group_info ) {
     490            return array(
     491                'processed' => 0,
     492                'files_updated' => 0,
     493                'directories_updated' => 0,
     494                /* translators: %s: Group name */
     495                'errors' => array( sprintf( __( 'Invalid group: %s', 'reset-file-and-folder-permissions' ), $group ) ),
     496                'next_offset' => $offset,
     497                'completed' => true,
     498            );
     499        }
     500
     501        $owner_uid = $owner_info['uid'];
     502        $group_gid = $group_info['gid'];
     503
     504        try {
     505            $iterator = new RecursiveIteratorIterator(
     506                new RecursiveDirectoryIterator( $directory, RecursiveDirectoryIterator::SKIP_DOTS ),
     507                RecursiveIteratorIterator::SELF_FIRST
     508            );
     509
     510            foreach ( $iterator as $item ) {
     511                // Skip items before the offset
     512                if ( $current_item < $offset ) {
     513                    $current_item++;
     514                    continue;
     515                }
     516
     517                // Stop processing if we've reached the batch size
     518                if ( $processed >= $batch_size ) {
     519                    break;
     520                }
     521
     522                $path = $item->getRealPath();
     523                $success = true;
     524
     525                // Change ownership
     526                // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_chown -- Direct file operations required for ownership changes
     527                if ( ! @chown( $path, $owner_uid ) ) {
     528                    $success = false;
     529                    /* translators: %s: File or directory path */
     530                    $errors[] = sprintf( __( 'Failed to change owner for: %s', 'reset-file-and-folder-permissions' ), $path );
     531                }
     532
     533                // Change group
     534                // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_chgrp -- Direct file operations required for ownership changes
     535                if ( ! @chgrp( $path, $group_gid ) ) {
     536                    $success = false;
     537                    /* translators: %s: File or directory path */
     538                    $errors[] = sprintf( __( 'Failed to change group for: %s', 'reset-file-and-folder-permissions' ), $path );
     539                }
     540
     541                if ( $success ) {
     542                    if ( $item->isDir() ) {
     543                        $directories_updated++;
     544                    } else {
     545                        $files_updated++;
     546                    }
     547                }
     548
     549                $processed++;
     550                $current_item++;
     551            }
     552        } catch ( Exception $e ) {
     553            /* translators: %s: Error message */
     554            $errors[] = sprintf( __( 'Error processing ownership: %s', 'reset-file-and-folder-permissions' ), $e->getMessage() );
     555        }
     556
     557        return array(
     558            'processed' => $processed,
     559            'files_updated' => $files_updated,
     560            'directories_updated' => $directories_updated,
     561            'errors' => $errors,
     562            'next_offset' => $current_item,
     563            'completed' => $processed < $batch_size,
     564        );
     565    }
    333566}
    334567
  • reset-file-and-folder-permissions/tags/1.1.0/includes/admin-page.php

    r3345847 r3396598  
    1616}
    1717
    18 $wp_root = realpath( ABSPATH );
    19 $wp_content = realpath( WP_CONTENT_DIR );
    20 $wp_plugins = realpath( WP_PLUGIN_DIR );
    21 $wp_themes = realpath( get_theme_root() );
    22 $wp_uploads = wp_upload_dir();
    23 $wp_uploads_dir = realpath( $wp_uploads['basedir'] );
     18$resetfileperm_wp_root = realpath( ABSPATH );
     19$resetfileperm_wp_content = realpath( WP_CONTENT_DIR );
     20$resetfileperm_wp_plugins = realpath( WP_PLUGIN_DIR );
     21$resetfileperm_wp_themes = realpath( get_theme_root() );
     22$resetfileperm_wp_uploads = wp_upload_dir();
     23$resetfileperm_wp_uploads_dir = realpath( $resetfileperm_wp_uploads['basedir'] );
     24
     25// Get current tab
     26// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Tab parameter is for navigation only, no data modification
     27$resetfileperm_current_tab = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : 'permissions';
     28
     29// Check ownership functions availability
     30$resetfileperm_ownership_available = RESETFILEPERM_File_Permissions_Reset::check_ownership_functions();
    2431?>
    2532
     
    2734    <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
    2835   
    29     <!-- Security Warning -->
    30     <div class="notice notice-warning">
    31         <p><strong><?php esc_html_e( 'Warning:', 'reset-file-and-folder-permissions' ); ?></strong></p>
    32         <ul>
    33             <li><?php esc_html_e( 'This action will reset ALL file permissions to 0644 and directory permissions to 0755.', 'reset-file-and-folder-permissions' ); ?></li>
    34             <li><?php esc_html_e( 'This process cannot be undone. Make sure you have a backup of your site.', 'reset-file-and-folder-permissions' ); ?></li>
    35             <li><?php esc_html_e( 'Only run this tool if you understand the implications of changing file permissions.', 'reset-file-and-folder-permissions' ); ?></li>
    36         </ul>
    37     </div>
    38 
    39     <!-- Main Content Layout -->
    40     <div class="resetfileperm-main-layout">
    41         <!-- Left Column - Plugin Functionality -->
    42         <div class="resetfileperm-left-column">
    43 
    44     <!-- System Information -->
    45     <div class="resetfileperm-system-info">
    46         <h2><?php esc_html_e( 'System Information', 'reset-file-and-folder-permissions' ); ?></h2>
    47         <table class="form-table">
    48             <tr>
    49                 <th scope="row"><?php esc_html_e( 'WordPress Root', 'reset-file-and-folder-permissions' ); ?></th>
    50                 <td>
    51                     <code><?php echo esc_html( $wp_root ); ?></code>
    52                     <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $wp_root ) ); ?>)</span>
    53                 </td>
    54             </tr>
    55             <tr>
    56                 <th scope="row"><?php esc_html_e( 'WP Content Directory', 'reset-file-and-folder-permissions' ); ?></th>
    57                 <td>
    58                     <code><?php echo esc_html( $wp_content ); ?></code>
    59                     <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $wp_content ) ); ?>)</span>
    60                 </td>
    61             </tr>
    62             <tr>
    63                 <th scope="row"><?php esc_html_e( 'Plugins Directory', 'reset-file-and-folder-permissions' ); ?></th>
    64                 <td>
    65                     <code><?php echo esc_html( $wp_plugins ); ?></code>
    66                     <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $wp_plugins ) ); ?>)</span>
    67                 </td>
    68             </tr>
    69             <tr>
    70                 <th scope="row"><?php esc_html_e( 'Themes Directory', 'reset-file-and-folder-permissions' ); ?></th>
    71                 <td>
    72                     <code><?php echo esc_html( $wp_themes ); ?></code>
    73                     <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $wp_themes ) ); ?>)</span>
    74                 </td>
    75             </tr>
    76             <?php if ( $wp_uploads_dir ) : ?>
    77             <tr>
    78                 <th scope="row"><?php esc_html_e( 'Uploads Directory', 'reset-file-and-folder-permissions' ); ?></th>
    79                 <td>
    80                     <code><?php echo esc_html( $wp_uploads_dir ); ?></code>
    81                     <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $wp_uploads_dir ) ); ?>)</span>
    82                 </td>
    83             </tr>
    84             <?php endif; ?>
    85             <tr>
    86                 <th scope="row"><?php esc_html_e( 'PHP chmod() Function', 'reset-file-and-folder-permissions' ); ?></th>
    87                 <td>
    88                     <?php if ( function_exists( 'chmod' ) ) : ?>
    89                         <span class="resetfileperm-status-ok"><?php esc_html_e( 'Available', 'reset-file-and-folder-permissions' ); ?></span>
    90                     <?php else : ?>
    91                         <span class="resetfileperm-status-error"><?php esc_html_e( 'Not Available', 'reset-file-and-folder-permissions' ); ?></span>
    92                     <?php endif; ?>
    93                 </td>
    94             </tr>
    95         </table>
    96     </div>
    97 
    98     <!-- Directory Selection -->
    99     <div class="resetfileperm-directory-selection">
    100         <h2><?php esc_html_e( 'Directory Selection', 'reset-file-and-folder-permissions' ); ?></h2>
    101         <form id="resetfileperm-main-form">
     36    <!-- Tab Navigation -->
     37    <h2 class="nav-tab-wrapper">
     38        <a href="?page=resetfileperm-reset-file-folder-permissions&tab=permissions"
     39           class="nav-tab <?php echo 'permissions' === $resetfileperm_current_tab ? 'nav-tab-active' : ''; ?>">
     40            <?php esc_html_e( 'Reset Permissions', 'reset-file-and-folder-permissions' ); ?>
     41        </a>
     42        <a href="?page=resetfileperm-reset-file-folder-permissions&tab=ownership"
     43           class="nav-tab <?php echo 'ownership' === $resetfileperm_current_tab ? 'nav-tab-active' : ''; ?>">
     44            <?php esc_html_e( 'Reset Ownership', 'reset-file-and-folder-permissions' ); ?>
     45        </a>
     46    </h2>
     47
     48    <?php if ( 'permissions' === $resetfileperm_current_tab ) : ?>
     49        <!-- PERMISSIONS TAB -->
     50       
     51        <!-- Security Warning -->
     52        <div class="notice notice-warning">
     53            <p><strong><?php esc_html_e( 'Warning:', 'reset-file-and-folder-permissions' ); ?></strong></p>
     54            <ul>
     55                <li><?php esc_html_e( 'This action will reset ALL file permissions to 0644 and directory permissions to 0755.', 'reset-file-and-folder-permissions' ); ?></li>
     56                <li><?php esc_html_e( 'This process cannot be undone. Make sure you have a backup of your site.', 'reset-file-and-folder-permissions' ); ?></li>
     57                <li><?php esc_html_e( 'Only run this tool if you understand the implications of changing file permissions.', 'reset-file-and-folder-permissions' ); ?></li>
     58            </ul>
     59        </div>
     60
     61        <!-- Main Content Layout -->
     62        <div class="resetfileperm-main-layout">
     63            <!-- Left Column - Plugin Functionality -->
     64            <div class="resetfileperm-left-column">
     65
     66        <!-- System Information -->
     67        <div class="resetfileperm-system-info">
     68            <h2><?php esc_html_e( 'System Information', 'reset-file-and-folder-permissions' ); ?></h2>
    10269            <table class="form-table">
    10370                <tr>
    104                     <th scope="row">
    105                         <label for="resetfileperm-directory"><?php esc_html_e( 'Target Directory', 'reset-file-and-folder-permissions' ); ?></label>
    106                     </th>
     71                    <th scope="row"><?php esc_html_e( 'WordPress Root', 'reset-file-and-folder-permissions' ); ?></th>
    10772                    <td>
    108                         <select id="resetfileperm-directory" name="directory" class="regular-text">
    109                             <option value="<?php echo esc_attr( $wp_root ); ?>"><?php esc_html_e( 'Entire WordPress Installation', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $wp_root ); ?>)</option>
    110                             <option value="<?php echo esc_attr( $wp_content ); ?>"><?php esc_html_e( 'WP Content Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $wp_content ); ?>)</option>
    111                             <option value="<?php echo esc_attr( $wp_plugins ); ?>"><?php esc_html_e( 'Plugins Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $wp_plugins ); ?>)</option>
    112                             <option value="<?php echo esc_attr( $wp_themes ); ?>"><?php esc_html_e( 'Themes Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $wp_themes ); ?>)</option>
    113                             <?php if ( $wp_uploads_dir ) : ?>
    114                             <option value="<?php echo esc_attr( $wp_uploads_dir ); ?>"><?php esc_html_e( 'Uploads Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $wp_uploads_dir ); ?>)</option>
    115                             <?php endif; ?>
    116                         </select>
    117                         <p class="description"><?php esc_html_e( 'Select which directory to process. Choose carefully as this operation affects all subdirectories.', 'reset-file-and-folder-permissions' ); ?></p>
     73                        <code><?php echo esc_html( $resetfileperm_wp_root ); ?></code>
     74                        <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $resetfileperm_wp_root ) ); ?>)</span>
    11875                    </td>
    11976                </tr>
    12077                <tr>
    121                     <th scope="row">
    122                         <label for="resetfileperm-batch-size"><?php esc_html_e( 'Batch Size', 'reset-file-and-folder-permissions' ); ?></label>
    123                     </th>
     78                    <th scope="row"><?php esc_html_e( 'WP Content Directory', 'reset-file-and-folder-permissions' ); ?></th>
    12479                    <td>
    125                         <select id="resetfileperm-batch-size" name="batch_size">
    126                             <option value="50">50 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
    127                             <option value="100" selected>100 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
    128                             <option value="200">200 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
    129                             <option value="500">500 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
    130                         </select>
    131                         <p class="description"><?php esc_html_e( 'Smaller batch sizes are safer for large directories but take longer. Larger batches are faster but may timeout.', 'reset-file-and-folder-permissions' ); ?></p>
     80                        <code><?php echo esc_html( $resetfileperm_wp_content ); ?></code>
     81                        <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $resetfileperm_wp_content ) ); ?>)</span>
     82                    </td>
     83                </tr>
     84                <tr>
     85                    <th scope="row"><?php esc_html_e( 'Plugins Directory', 'reset-file-and-folder-permissions' ); ?></th>
     86                    <td>
     87                        <code><?php echo esc_html( $resetfileperm_wp_plugins ); ?></code>
     88                        <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $resetfileperm_wp_plugins ) ); ?>)</span>
     89                    </td>
     90                </tr>
     91                <tr>
     92                    <th scope="row"><?php esc_html_e( 'Themes Directory', 'reset-file-and-folder-permissions' ); ?></th>
     93                    <td>
     94                        <code><?php echo esc_html( $resetfileperm_wp_themes ); ?></code>
     95                        <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $resetfileperm_wp_themes ) ); ?>)</span>
     96                    </td>
     97                </tr>
     98                <?php if ( $resetfileperm_wp_uploads_dir ) : ?>
     99                <tr>
     100                    <th scope="row"><?php esc_html_e( 'Uploads Directory', 'reset-file-and-folder-permissions' ); ?></th>
     101                    <td>
     102                        <code><?php echo esc_html( $resetfileperm_wp_uploads_dir ); ?></code>
     103                        <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $resetfileperm_wp_uploads_dir ) ); ?>)</span>
     104                    </td>
     105                </tr>
     106                <?php endif; ?>
     107                <tr>
     108                    <th scope="row"><?php esc_html_e( 'PHP chmod() Function', 'reset-file-and-folder-permissions' ); ?></th>
     109                    <td>
     110                        <?php if ( function_exists( 'chmod' ) ) : ?>
     111                            <span class="resetfileperm-status-ok"><?php esc_html_e( 'Available', 'reset-file-and-folder-permissions' ); ?></span>
     112                        <?php else : ?>
     113                            <span class="resetfileperm-status-error"><?php esc_html_e( 'Not Available', 'reset-file-and-folder-permissions' ); ?></span>
     114                        <?php endif; ?>
    132115                    </td>
    133116                </tr>
    134117            </table>
    135 
    136             <!-- Action Buttons -->
    137             <p class="submit">
    138                 <button type="button" id="resetfileperm-scan-btn" class="button button-secondary">
    139                     <span class="dashicons dashicons-search"></span>
    140                     <?php esc_html_e( 'Scan Directory', 'reset-file-and-folder-permissions' ); ?>
    141                 </button>
    142                 <button type="button" id="resetfileperm-reset-btn" class="button button-primary" disabled>
    143                     <span class="dashicons dashicons-admin-tools"></span>
    144                     <?php esc_html_e( 'Reset Permissions', 'reset-file-and-folder-permissions' ); ?>
    145                 </button>
    146             </p>
    147         </form>
    148     </div>
    149 
    150     <!-- Progress Section -->
    151     <div id="resetfileperm-progress-section" class="resetfileperm-progress-section" style="display: none;">
    152         <h2><?php esc_html_e( 'Progress', 'reset-file-and-folder-permissions' ); ?></h2>
    153         <div class="resetfileperm-progress-container">
    154             <div class="resetfileperm-progress-bar">
    155                 <div id="resetfileperm-progress-fill" class="resetfileperm-progress-fill" style="width: 0%;"></div>
    156             </div>
    157             <div id="resetfileperm-progress-text" class="resetfileperm-progress-text">0%</div>
    158         </div>
    159         <div id="resetfileperm-progress-details" class="resetfileperm-progress-details">
    160             <p id="resetfileperm-current-status"><?php esc_html_e( 'Ready to start...', 'reset-file-and-folder-permissions' ); ?></p>
    161             <div class="resetfileperm-stats">
    162                 <span><?php esc_html_e( 'Files processed:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-files-count">0</strong></span>
    163                 <span><?php esc_html_e( 'Directories processed:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-dirs-count">0</strong></span>
    164                 <span><?php esc_html_e( 'Errors:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-errors-count">0</strong></span>
    165             </div>
    166         </div>
    167     </div>
    168 
    169     <!-- Scan Results -->
    170     <div id="resetfileperm-scan-results" class="resetfileperm-scan-results" style="display: none;">
    171         <h2><?php esc_html_e( 'Scan Results', 'reset-file-and-folder-permissions' ); ?></h2>
    172         <div class="resetfileperm-scan-summary">
    173             <p><?php esc_html_e( 'Found:', 'reset-file-and-folder-permissions' ); ?>
    174                 <strong id="resetfileperm-scan-files">0</strong> <?php esc_html_e( 'files', 'reset-file-and-folder-permissions' ); ?>
    175                 <?php esc_html_e( 'and', 'reset-file-and-folder-permissions' ); ?>
    176                 <strong id="resetfileperm-scan-dirs">0</strong> <?php esc_html_e( 'directories', 'reset-file-and-folder-permissions' ); ?>
    177             </p>
    178         </div>
    179     </div>
    180 
    181     <!-- Error Log -->
    182     <div id="resetfileperm-error-log" class="resetfileperm-error-log" style="display: none;">
    183         <h2><?php esc_html_e( 'Error Log', 'reset-file-and-folder-permissions' ); ?></h2>
    184         <div id="resetfileperm-error-messages" class="resetfileperm-error-messages"></div>
    185     </div>
    186 
    187     <!-- Results Section -->
    188     <div id="resetfileperm-results-section" class="resetfileperm-results-section" style="display: none;">
    189         <h2><?php esc_html_e( 'Operation Complete', 'reset-file-and-folder-permissions' ); ?></h2>
    190         <div class="notice notice-success">
    191             <p><strong><?php esc_html_e( 'Permissions reset completed!', 'reset-file-and-folder-permissions' ); ?></strong></p>
    192         </div>
    193         <div id="resetfileperm-final-results" class="resetfileperm-final-results"></div>
    194     </div>
    195 
    196         </div><!-- End Left Column -->
    197 
    198         <!-- Right Column - Developer Profile -->
    199         <div class="resetfileperm-right-column">
    200             <div class="resetfileperm-developer-profile">
    201                 <div class="resetfileperm-profile-content">
    202                     <div class="resetfileperm-profile-card">
    203                         <div class="resetfileperm-profile-header">
    204                             <?php
    205                                         $logo_path = RESETFILEPERM_PLUGIN_DIR . 'assets/nandann-logo.png';
    206             $logo_url = RESETFILEPERM_PLUGIN_URL . 'assets/nandann-logo.png';
    207                             if ( file_exists( $logo_path ) && function_exists( 'getimagesize' ) && getimagesize( $logo_path ) !== false ) : ?>
    208                                 <div class="resetfileperm-logo-container">
    209                                     <img src="<?php echo esc_url( $logo_url ); ?>"
    210                                          alt="<?php esc_attr_e( 'Nandann Creative Agency Logo', 'reset-file-and-folder-permissions' ); ?>"
    211                                          class="resetfileperm-logo"
    212                                          width="120"
    213                                          height="auto" />
     118        </div>
     119
     120        <!-- Directory Selection -->
     121        <div class="resetfileperm-directory-selection">
     122            <h2><?php esc_html_e( 'Directory Selection', 'reset-file-and-folder-permissions' ); ?></h2>
     123            <form id="resetfileperm-main-form">
     124                <table class="form-table">
     125                    <tr>
     126                        <th scope="row">
     127                            <label for="resetfileperm-directory"><?php esc_html_e( 'Target Directory', 'reset-file-and-folder-permissions' ); ?></label>
     128                        </th>
     129                        <td>
     130                            <select id="resetfileperm-directory" name="directory" class="regular-text">
     131                                <option value="<?php echo esc_attr( $resetfileperm_wp_root ); ?>"><?php esc_html_e( 'Entire WordPress Installation', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_root ); ?>)</option>
     132                                <option value="<?php echo esc_attr( $resetfileperm_wp_content ); ?>"><?php esc_html_e( 'WP Content Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_content ); ?>)</option>
     133                                <option value="<?php echo esc_attr( $resetfileperm_wp_plugins ); ?>"><?php esc_html_e( 'Plugins Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_plugins ); ?>)</option>
     134                                <option value="<?php echo esc_attr( $resetfileperm_wp_themes ); ?>"><?php esc_html_e( 'Themes Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_themes ); ?>)</option>
     135                                <?php if ( $resetfileperm_wp_uploads_dir ) : ?>
     136                                <option value="<?php echo esc_attr( $resetfileperm_wp_uploads_dir ); ?>"><?php esc_html_e( 'Uploads Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_uploads_dir ); ?>)</option>
     137                                <?php endif; ?>
     138                            </select>
     139                            <p class="description"><?php esc_html_e( 'Select which directory to process. Choose carefully as this operation affects all subdirectories.', 'reset-file-and-folder-permissions' ); ?></p>
     140                        </td>
     141                    </tr>
     142                    <tr>
     143                        <th scope="row">
     144                            <label for="resetfileperm-batch-size"><?php esc_html_e( 'Batch Size', 'reset-file-and-folder-permissions' ); ?></label>
     145                        </th>
     146                        <td>
     147                            <select id="resetfileperm-batch-size" name="batch_size">
     148                                <option value="50">50 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     149                                <option value="100" selected>100 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     150                                <option value="200">200 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     151                                <option value="500">500 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     152                            </select>
     153                            <p class="description"><?php esc_html_e( 'Smaller batch sizes are safer for large directories but take longer. Larger batches are faster but may timeout.', 'reset-file-and-folder-permissions' ); ?></p>
     154                        </td>
     155                    </tr>
     156                </table>
     157
     158                <!-- Action Buttons -->
     159                <p class="submit">
     160                    <button type="button" id="resetfileperm-scan-btn" class="button button-secondary">
     161                        <span class="dashicons dashicons-search"></span>
     162                        <?php esc_html_e( 'Scan Directory', 'reset-file-and-folder-permissions' ); ?>
     163                    </button>
     164                    <button type="button" id="resetfileperm-reset-btn" class="button button-primary" disabled>
     165                        <span class="dashicons dashicons-admin-tools"></span>
     166                        <?php esc_html_e( 'Reset Permissions', 'reset-file-and-folder-permissions' ); ?>
     167                    </button>
     168                </p>
     169            </form>
     170        </div>
     171
     172        <!-- Scan Results -->
     173        <div id="resetfileperm-scan-results" class="resetfileperm-scan-results" style="display: none;">
     174            <h2><?php esc_html_e( 'Scan Results', 'reset-file-and-folder-permissions' ); ?></h2>
     175            <div class="resetfileperm-scan-summary">
     176                <p><?php esc_html_e( 'Found:', 'reset-file-and-folder-permissions' ); ?>
     177                    <strong id="resetfileperm-scan-files">0</strong> <?php esc_html_e( 'files', 'reset-file-and-folder-permissions' ); ?>
     178                    <?php esc_html_e( 'and', 'reset-file-and-folder-permissions' ); ?>
     179                    <strong id="resetfileperm-scan-dirs">0</strong> <?php esc_html_e( 'directories', 'reset-file-and-folder-permissions' ); ?>
     180                </p>
     181            </div>
     182        </div>
     183
     184        <!-- Progress Section -->
     185        <div id="resetfileperm-progress-section" class="resetfileperm-progress-section" style="display: none;">
     186            <h2><?php esc_html_e( 'Progress', 'reset-file-and-folder-permissions' ); ?></h2>
     187            <div class="resetfileperm-progress-container">
     188                <div class="resetfileperm-progress-bar">
     189                    <div id="resetfileperm-progress-fill" class="resetfileperm-progress-fill" style="width: 0%;"></div>
     190                </div>
     191                <div id="resetfileperm-progress-text" class="resetfileperm-progress-text">0%</div>
     192            </div>
     193            <div id="resetfileperm-progress-details" class="resetfileperm-progress-details">
     194                <p id="resetfileperm-current-status"><?php esc_html_e( 'Ready to start...', 'reset-file-and-folder-permissions' ); ?></p>
     195                <div class="resetfileperm-stats">
     196                    <span><?php esc_html_e( 'Files processed:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-files-count">0</strong></span>
     197                    <span><?php esc_html_e( 'Directories processed:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-dirs-count">0</strong></span>
     198                    <span><?php esc_html_e( 'Errors:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-errors-count">0</strong></span>
     199                </div>
     200            </div>
     201        </div>
     202
     203        <!-- Error Log -->
     204        <div id="resetfileperm-error-log" class="resetfileperm-error-log" style="display: none;">
     205            <h2><?php esc_html_e( 'Error Log', 'reset-file-and-folder-permissions' ); ?></h2>
     206            <div id="resetfileperm-error-messages" class="resetfileperm-error-messages"></div>
     207        </div>
     208
     209        <!-- Results Section -->
     210        <div id="resetfileperm-results-section" class="resetfileperm-results-section" style="display: none;">
     211            <h2><?php esc_html_e( 'Operation Complete', 'reset-file-and-folder-permissions' ); ?></h2>
     212            <div class="notice notice-success">
     213                <p><strong><?php esc_html_e( 'Permissions reset completed!', 'reset-file-and-folder-permissions' ); ?></strong></p>
     214            </div>
     215            <div id="resetfileperm-final-results" class="resetfileperm-final-results"></div>
     216        </div>
     217
     218            </div><!-- End Left Column -->
     219
     220            <!-- Right Column - Developer Profile -->
     221            <div class="resetfileperm-right-column">
     222                <div class="resetfileperm-developer-profile">
     223                    <div class="resetfileperm-profile-content">
     224                        <div class="resetfileperm-profile-card">
     225                            <div class="resetfileperm-profile-header">
     226                                <?php
     227                                            $resetfileperm_logo_path = RESETFILEPERM_PLUGIN_DIR . 'assets/nandann-logo.png';
     228                $resetfileperm_logo_url = RESETFILEPERM_PLUGIN_URL . 'assets/nandann-logo.png';
     229                                if ( file_exists( $resetfileperm_logo_path ) && function_exists( 'getimagesize' ) && getimagesize( $resetfileperm_logo_path ) !== false ) : ?>
     230                                    <div class="resetfileperm-logo-container">
     231                                        <img src="<?php echo esc_url( $resetfileperm_logo_url ); ?>"
     232                                             alt="<?php esc_attr_e( 'Nandann Creative Agency Logo', 'reset-file-and-folder-permissions' ); ?>"
     233                                             class="resetfileperm-logo"
     234                                             width="120"
     235                                             height="auto" />
     236                                    </div>
     237                                <?php else : ?>
     238                                    <div class="resetfileperm-logo-container">
     239                                        <h2 class="resetfileperm-logo-text"><?php esc_html_e( 'Nandann', 'reset-file-and-folder-permissions' ); ?></h2>
     240                                    </div>
     241                                <?php endif; ?>
     242                                <p class="resetfileperm-agency-text"><?php esc_html_e( 'Creative Agency', 'reset-file-and-folder-permissions' ); ?></p>
     243                                <h3><?php esc_html_e( 'Professional WordPress Development & Troubleshooting', 'reset-file-and-folder-permissions' ); ?></h3>
     244                                <p class="resetfileperm-tagline"><?php esc_html_e( 'Expert solutions for complex WordPress challenges', 'reset-file-and-folder-permissions' ); ?></p>
     245                            </div>
     246                           
     247                            <div class="resetfileperm-profile-cta">
     248                                <p class="resetfileperm-cta-text"><?php esc_html_e( 'Facing WordPress challenges? Get professional help from an experienced developer who understands the complexities of WordPress development and can provide reliable, efficient solutions.', 'reset-file-and-folder-permissions' ); ?></p>
     249                               
     250                                <div class="resetfileperm-contact-buttons">
     251                                    <a href="mailto:[email protected]?subject=WordPress Development Help Request" class="button button-primary resetfileperm-contact-btn">
     252                                        <span class="dashicons dashicons-email-alt"></span>
     253                                        <span class="resetfileperm-btn-text">
     254                                            <span class="resetfileperm-btn-line1"><?php esc_html_e( 'Get Expert Help', 'reset-file-and-folder-permissions' ); ?></span>
     255                                            <span class="resetfileperm-btn-line2">[email protected]</span>
     256                                        </span>
     257                                    </a>
     258                                    <a href="https://nandann.com" target="_blank" class="button button-secondary resetfileperm-website-btn">
     259                                        <span class="dashicons dashicons-external"></span>
     260                                        <?php esc_html_e( 'Visit nandann.com', 'reset-file-and-folder-permissions' ); ?>
     261                                    </a>
    214262                                </div>
    215                             <?php else : ?>
    216                                 <div class="resetfileperm-logo-container">
    217                                     <h2 class="resetfileperm-logo-text"><?php esc_html_e( 'Nandann', 'reset-file-and-folder-permissions' ); ?></h2>
    218                                 </div>
    219                             <?php endif; ?>
    220                             <p class="resetfileperm-agency-text"><?php esc_html_e( 'Creative Agency', 'reset-file-and-folder-permissions' ); ?></p>
    221                             <h3><?php esc_html_e( 'Professional WordPress Development & Troubleshooting', 'reset-file-and-folder-permissions' ); ?></h3>
    222                             <p class="resetfileperm-tagline"><?php esc_html_e( 'Expert solutions for complex WordPress challenges', 'reset-file-and-folder-permissions' ); ?></p>
    223                         </div>
    224                        
    225                         <div class="resetfileperm-profile-cta">
    226                             <p class="resetfileperm-cta-text"><?php esc_html_e( 'Facing WordPress challenges? Get professional help from an experienced developer who understands the complexities of WordPress development and can provide reliable, efficient solutions.', 'reset-file-and-folder-permissions' ); ?></p>
     263                            </div>
    227264                           
    228                             <div class="resetfileperm-contact-buttons">
    229                                 <a href="mailto:[email protected]?subject=WordPress Development Help Request" class="button button-primary resetfileperm-contact-btn">
    230                                     <span class="dashicons dashicons-email-alt"></span>
    231                                     <span class="resetfileperm-btn-text">
    232                                         <span class="resetfileperm-btn-line1"><?php esc_html_e( 'Get Expert Help', 'reset-file-and-folder-permissions' ); ?></span>
    233                                         <span class="resetfileperm-btn-line2">[email protected]</span>
    234                                     </span>
    235                                 </a>
    236                                 <a href="https://nandann.com" target="_blank" class="button button-secondary resetfileperm-website-btn">
    237                                     <span class="dashicons dashicons-external"></span>
    238                                     <?php esc_html_e( 'Visit nandann.com', 'reset-file-and-folder-permissions' ); ?>
    239                                 </a>
    240                             </div>
    241                         </div>
    242                        
    243                         <div class="resetfileperm-profile-services">
    244                             <div class="resetfileperm-service-grid">
    245                                 <div class="resetfileperm-service-item">
    246                                     <span class="dashicons dashicons-admin-tools"></span>
    247                                     <h4><?php esc_html_e( 'WordPress Troubleshooting', 'reset-file-and-folder-permissions' ); ?></h4>
    248                                     <p><?php esc_html_e( 'Expert diagnosis and resolution of complex WordPress issues, performance optimization, and security hardening.', 'reset-file-and-folder-permissions' ); ?></p>
    249                                 </div>
    250                                
    251                                 <div class="resetfileperm-service-item">
    252                                     <span class="dashicons dashicons-desktop"></span>
    253                                     <h4><?php esc_html_e( 'Custom Development', 'reset-file-and-folder-permissions' ); ?></h4>
    254                                     <p><?php esc_html_e( 'Bespoke WordPress plugins, themes, and custom functionality tailored to your specific business needs.', 'reset-file-and-folder-permissions' ); ?></p>
    255                                 </div>
    256                                
    257                                 <div class="resetfileperm-service-item">
    258                                     <span class="dashicons dashicons-migrate"></span>
    259                                     <h4><?php esc_html_e( 'Site Migration & Hosting', 'reset-file-and-folder-permissions' ); ?></h4>
    260                                     <p><?php esc_html_e( 'Seamless website migrations, hosting optimization, and server configuration for peak performance.', 'reset-file-and-folder-permissions' ); ?></p>
    261                                 </div>
    262                                
    263                                 <div class="resetfileperm-service-item">
    264                                     <span class="dashicons dashicons-shield"></span>
    265                                     <h4><?php esc_html_e( 'Security & Maintenance', 'reset-file-and-folder-permissions' ); ?></h4>
    266                                     <p><?php esc_html_e( 'Comprehensive security audits, malware removal, and ongoing maintenance to keep your site secure.', 'reset-file-and-folder-permissions' ); ?></p>
     265                            <div class="resetfileperm-profile-services">
     266                                <div class="resetfileperm-service-grid">
     267                                    <div class="resetfileperm-service-item">
     268                                        <span class="dashicons dashicons-admin-tools"></span>
     269                                        <h4><?php esc_html_e( 'WordPress Troubleshooting', 'reset-file-and-folder-permissions' ); ?></h4>
     270                                        <p><?php esc_html_e( 'Expert diagnosis and resolution of complex WordPress issues, performance optimization, and security hardening.', 'reset-file-and-folder-permissions' ); ?></p>
     271                                    </div>
     272                                   
     273                                    <div class="resetfileperm-service-item">
     274                                        <span class="dashicons dashicons-desktop"></span>
     275                                        <h4><?php esc_html_e( 'Custom Development', 'reset-file-and-folder-permissions' ); ?></h4>
     276                                        <p><?php esc_html_e( 'Bespoke WordPress plugins, themes, and custom functionality tailored to your specific business needs.', 'reset-file-and-folder-permissions' ); ?></p>
     277                                    </div>
     278                                   
     279                                    <div class="resetfileperm-service-item">
     280                                        <span class="dashicons dashicons-migrate"></span>
     281                                        <h4><?php esc_html_e( 'Site Migration & Hosting', 'reset-file-and-folder-permissions' ); ?></h4>
     282                                        <p><?php esc_html_e( 'Seamless website migrations, hosting optimization, and server configuration for peak performance.', 'reset-file-and-folder-permissions' ); ?></p>
     283                                    </div>
     284                                   
     285                                    <div class="resetfileperm-service-item">
     286                                        <span class="dashicons dashicons-shield"></span>
     287                                        <h4><?php esc_html_e( 'Security & Maintenance', 'reset-file-and-folder-permissions' ); ?></h4>
     288                                        <p><?php esc_html_e( 'Comprehensive security audits, malware removal, and ongoing maintenance to keep your site secure.', 'reset-file-and-folder-permissions' ); ?></p>
     289                                    </div>
    267290                                </div>
    268291                            </div>
     
    270293                    </div>
    271294                </div>
    272             </div>
    273         </div><!-- End Right Column -->
    274 
    275     </div><!-- End Main Layout -->
    276 
    277     <!-- Help Section -->
    278     <div class="resetfileperm-help-section">
    279         <h2><?php esc_html_e( 'About File Permissions', 'reset-file-and-folder-permissions' ); ?></h2>
    280         <div class="resetfileperm-help-content">
    281             <h3><?php esc_html_e( 'Standard WordPress Permissions', 'reset-file-and-folder-permissions' ); ?></h3>
    282             <ul>
    283                 <li><strong>0644</strong> - <?php esc_html_e( 'Files: Owner can read/write, group and others can read only', 'reset-file-and-folder-permissions' ); ?></li>
    284                 <li><strong>0755</strong> - <?php esc_html_e( 'Directories: Owner can read/write/execute, group and others can read/execute', 'reset-file-and-folder-permissions' ); ?></li>
    285             </ul>
    286            
    287             <h3><?php esc_html_e( 'When to Use This Tool', 'reset-file-and-folder-permissions' ); ?></h3>
    288             <ul>
    289                 <li><?php esc_html_e( 'After migrating your WordPress site to a new server', 'reset-file-and-folder-permissions' ); ?></li>
    290                 <li><?php esc_html_e( 'When files have incorrect permissions causing functionality issues', 'reset-file-and-folder-permissions' ); ?></li>
    291                 <li><?php esc_html_e( 'For security hardening when permissions are too permissive', 'reset-file-and-folder-permissions' ); ?></li>
    292                 <li><?php esc_html_e( 'When troubleshooting file access problems', 'reset-file-and-folder-permissions' ); ?></li>
    293             </ul>
    294 
    295             <h3><?php esc_html_e( 'Important Notes', 'reset-file-and-folder-permissions' ); ?></h3>
    296             <ul>
    297                 <li><?php esc_html_e( 'Some files (like wp-config.php) may need special permissions', 'reset-file-and-folder-permissions' ); ?></li>
    298                 <li><?php esc_html_e( 'Always test your site functionality after running this tool', 'reset-file-and-folder-permissions' ); ?></li>
    299                 <li><?php esc_html_e( 'Make sure your web server user has appropriate access', 'reset-file-and-folder-permissions' ); ?></li>
    300             </ul>
    301         </div>
    302     </div>
    303 </div>
     295            </div><!-- End Right Column -->
     296
     297        </div><!-- End Main Layout -->
     298
     299        <!-- Help Section -->
     300        <div class="resetfileperm-help-section">
     301            <h2><?php esc_html_e( 'About File Permissions', 'reset-file-and-folder-permissions' ); ?></h2>
     302            <div class="resetfileperm-help-content">
     303                <h3><?php esc_html_e( 'Standard WordPress Permissions', 'reset-file-and-folder-permissions' ); ?></h3>
     304                <ul>
     305                    <li><strong>0644</strong> - <?php esc_html_e( 'Files: Owner can read/write, group and others can read only', 'reset-file-and-folder-permissions' ); ?></li>
     306                    <li><strong>0755</strong> - <?php esc_html_e( 'Directories: Owner can read/write/execute, group and others can read/execute', 'reset-file-and-folder-permissions' ); ?></li>
     307                </ul>
     308               
     309                <h3><?php esc_html_e( 'When to Use This Tool', 'reset-file-and-folder-permissions' ); ?></h3>
     310                <ul>
     311                    <li><?php esc_html_e( 'After migrating your WordPress site to a new server', 'reset-file-and-folder-permissions' ); ?></li>
     312                    <li><?php esc_html_e( 'When files have incorrect permissions causing functionality issues', 'reset-file-and-folder-permissions' ); ?></li>
     313                    <li><?php esc_html_e( 'For security hardening when permissions are too permissive', 'reset-file-and-folder-permissions' ); ?></li>
     314                    <li><?php esc_html_e( 'When troubleshooting file access problems', 'reset-file-and-folder-permissions' ); ?></li>
     315                </ul>
     316
     317                <h3><?php esc_html_e( 'Important Notes', 'reset-file-and-folder-permissions' ); ?></h3>
     318                <ul>
     319                    <li><?php esc_html_e( 'Some files (like wp-config.php) may need special permissions', 'reset-file-and-folder-permissions' ); ?></li>
     320                    <li><?php esc_html_e( 'Always test your site functionality after running this tool', 'reset-file-and-folder-permissions' ); ?></li>
     321                    <li><?php esc_html_e( 'Make sure your web server user has appropriate access', 'reset-file-and-folder-permissions' ); ?></li>
     322                </ul>
     323            </div>
     324        </div>
     325
     326    <?php else : ?>
     327        <!-- OWNERSHIP TAB -->
     328       
     329        <?php if ( ! $resetfileperm_ownership_available ) : ?>
     330            <!-- Compatibility Warning -->
     331            <div class="notice notice-error">
     332                <h3><?php esc_html_e( 'Ownership Functions Not Available', 'reset-file-and-folder-permissions' ); ?></h3>
     333                <p><?php esc_html_e( 'The file and folder ownership reset feature requires PHP functions that are not available on your server:', 'reset-file-and-folder-permissions' ); ?></p>
     334                <ul>
     335                    <li><code>chown()</code> - <?php esc_html_e( 'Change file owner', 'reset-file-and-folder-permissions' ); ?></li>
     336                    <li><code>chgrp()</code> - <?php esc_html_e( 'Change file group', 'reset-file-and-folder-permissions' ); ?></li>
     337                    <li><code>posix_getpwnam()</code> - <?php esc_html_e( 'Get user information', 'reset-file-and-folder-permissions' ); ?></li>
     338                    <li><code>posix_getgrnam()</code> - <?php esc_html_e( 'Get group information', 'reset-file-and-folder-permissions' ); ?></li>
     339                </ul>
     340                <p><strong><?php esc_html_e( 'Why are these functions unavailable?', 'reset-file-and-folder-permissions' ); ?></strong></p>
     341                <p><?php esc_html_e( 'These functions are often disabled on shared hosting environments for security reasons. They require elevated server privileges and are typically only available on VPS, dedicated servers, or hosting environments where you have more control.', 'reset-file-and-folder-permissions' ); ?></p>
     342                <p><strong><?php esc_html_e( 'What can you do?', 'reset-file-and-folder-permissions' ); ?></strong></p>
     343                <ul>
     344                    <li><?php esc_html_e( 'Contact your hosting provider to enable these functions (if possible)', 'reset-file-and-folder-permissions' ); ?></li>
     345                    <li><?php esc_html_e( 'Use SSH/terminal access to change ownership manually', 'reset-file-and-folder-permissions' ); ?></li>
     346                    <li><?php esc_html_e( 'Consider upgrading to a VPS or dedicated server for more control', 'reset-file-and-folder-permissions' ); ?></li>
     347                </ul>
     348                <p><?php esc_html_e( 'You can still use the "Reset Permissions" tab to fix file permission issues.', 'reset-file-and-folder-permissions' ); ?></p>
     349            </div>
     350        <?php else : ?>
     351            <!-- Security Warning -->
     352            <div class="notice notice-warning">
     353                <p><strong><?php esc_html_e( 'Warning:', 'reset-file-and-folder-permissions' ); ?></strong></p>
     354                <ul>
     355                    <li><?php esc_html_e( 'This action will change the ownership of ALL files and directories to the specified user and group.', 'reset-file-and-folder-permissions' ); ?></li>
     356                    <li><?php esc_html_e( 'Incorrect ownership can break your WordPress site and prevent file access.', 'reset-file-and-folder-permissions' ); ?></li>
     357                    <li><?php esc_html_e( 'This process cannot be undone. Make sure you have a backup of your site.', 'reset-file-and-folder-permissions' ); ?></li>
     358                    <li><?php esc_html_e( 'Only run this tool if you understand the implications of changing file ownership.', 'reset-file-and-folder-permissions' ); ?></li>
     359                </ul>
     360            </div>
     361
     362            <!-- Main Content Layout -->
     363            <div class="resetfileperm-main-layout">
     364                <!-- Left Column - Plugin Functionality -->
     365                <div class="resetfileperm-left-column">
     366
     367            <!-- Server Information -->
     368            <div class="resetfileperm-system-info">
     369                <h2><?php esc_html_e( 'Server Information', 'reset-file-and-folder-permissions' ); ?></h2>
     370                <table class="form-table">
     371                    <tr>
     372                        <th scope="row"><?php esc_html_e( 'PHP chown() Function', 'reset-file-and-folder-permissions' ); ?></th>
     373                        <td>
     374                            <?php if ( function_exists( 'chown' ) ) : ?>
     375                                <span class="resetfileperm-status-ok"><?php esc_html_e( 'Available', 'reset-file-and-folder-permissions' ); ?></span>
     376                            <?php else : ?>
     377                                <span class="resetfileperm-status-error"><?php esc_html_e( 'Not Available', 'reset-file-and-folder-permissions' ); ?></span>
     378                            <?php endif; ?>
     379                        </td>
     380                    </tr>
     381                    <tr>
     382                        <th scope="row"><?php esc_html_e( 'PHP chgrp() Function', 'reset-file-and-folder-permissions' ); ?></th>
     383                        <td>
     384                            <?php if ( function_exists( 'chgrp' ) ) : ?>
     385                                <span class="resetfileperm-status-ok"><?php esc_html_e( 'Available', 'reset-file-and-folder-permissions' ); ?></span>
     386                            <?php else : ?>
     387                                <span class="resetfileperm-status-error"><?php esc_html_e( 'Not Available', 'reset-file-and-folder-permissions' ); ?></span>
     388                            <?php endif; ?>
     389                        </td>
     390                    </tr>
     391                    <tr>
     392                        <th scope="row"><?php esc_html_e( 'PHP POSIX Functions', 'reset-file-and-folder-permissions' ); ?></th>
     393                        <td>
     394                            <?php if ( function_exists( 'posix_getpwnam' ) && function_exists( 'posix_getgrnam' ) ) : ?>
     395                                <span class="resetfileperm-status-ok"><?php esc_html_e( 'Available', 'reset-file-and-folder-permissions' ); ?></span>
     396                            <?php else : ?>
     397                                <span class="resetfileperm-status-error"><?php esc_html_e( 'Not Available', 'reset-file-and-folder-permissions' ); ?></span>
     398                            <?php endif; ?>
     399                        </td>
     400                    </tr>
     401                </table>
     402                <div id="resetfileperm-ownership-server-info">
     403                    <p><?php esc_html_e( 'Loading server information...', 'reset-file-and-folder-permissions' ); ?></p>
     404                </div>
     405            </div>
     406
     407            <!-- Ownership Selection -->
     408            <div class="resetfileperm-directory-selection">
     409                <h2><?php esc_html_e( 'Ownership Configuration', 'reset-file-and-folder-permissions' ); ?></h2>
     410                <form id="resetfileperm-ownership-form">
     411                    <table class="form-table">
     412                        <tr>
     413                            <th scope="row">
     414                                <label for="resetfileperm-owner"><?php esc_html_e( 'File Owner', 'reset-file-and-folder-permissions' ); ?></label>
     415                            </th>
     416                            <td>
     417                                <select id="resetfileperm-owner" name="owner" class="regular-text" required>
     418                                    <option value=""><?php esc_html_e( 'Select owner...', 'reset-file-and-folder-permissions' ); ?></option>
     419                                </select>
     420                                <p class="description"><?php esc_html_e( 'Select the user that should own the files. The recommended value is your web server user.', 'reset-file-and-folder-permissions' ); ?></p>
     421                            </td>
     422                        </tr>
     423                        <tr>
     424                            <th scope="row">
     425                                <label for="resetfileperm-group"><?php esc_html_e( 'File Group', 'reset-file-and-folder-permissions' ); ?></label>
     426                            </th>
     427                            <td>
     428                                <select id="resetfileperm-group" name="group" class="regular-text" required>
     429                                    <option value=""><?php esc_html_e( 'Select group...', 'reset-file-and-folder-permissions' ); ?></option>
     430                                </select>
     431                                <p class="description"><?php esc_html_e( 'Select the group that should own the files. The recommended value is your web server group.', 'reset-file-and-folder-permissions' ); ?></p>
     432                            </td>
     433                        </tr>
     434                        <tr>
     435                            <th scope="row">
     436                                <label for="resetfileperm-ownership-directory"><?php esc_html_e( 'Target Directory', 'reset-file-and-folder-permissions' ); ?></label>
     437                            </th>
     438                            <td>
     439                                <select id="resetfileperm-ownership-directory" name="directory" class="regular-text">
     440                                    <option value="<?php echo esc_attr( $resetfileperm_wp_root ); ?>"><?php esc_html_e( 'Entire WordPress Installation', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_root ); ?>)</option>
     441                                    <option value="<?php echo esc_attr( $resetfileperm_wp_content ); ?>"><?php esc_html_e( 'WP Content Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_content ); ?>)</option>
     442                                    <option value="<?php echo esc_attr( $resetfileperm_wp_plugins ); ?>"><?php esc_html_e( 'Plugins Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_plugins ); ?>)</option>
     443                                    <option value="<?php echo esc_attr( $resetfileperm_wp_themes ); ?>"><?php esc_html_e( 'Themes Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_themes ); ?>)</option>
     444                                    <?php if ( $resetfileperm_wp_uploads_dir ) : ?>
     445                                    <option value="<?php echo esc_attr( $resetfileperm_wp_uploads_dir ); ?>"><?php esc_html_e( 'Uploads Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_uploads_dir ); ?>)</option>
     446                                    <?php endif; ?>
     447                                </select>
     448                                <p class="description"><?php esc_html_e( 'Select which directory to process. Choose carefully as this operation affects all subdirectories.', 'reset-file-and-folder-permissions' ); ?></p>
     449                            </td>
     450                        </tr>
     451                        <tr>
     452                            <th scope="row">
     453                                <label for="resetfileperm-ownership-batch-size"><?php esc_html_e( 'Batch Size', 'reset-file-and-folder-permissions' ); ?></label>
     454                            </th>
     455                            <td>
     456                                <select id="resetfileperm-ownership-batch-size" name="batch_size">
     457                                    <option value="50">50 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     458                                    <option value="100" selected>100 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     459                                    <option value="200">200 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     460                                    <option value="500">500 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     461                                </select>
     462                                <p class="description"><?php esc_html_e( 'Smaller batch sizes are safer for large directories but take longer. Larger batches are faster but may timeout.', 'reset-file-and-folder-permissions' ); ?></p>
     463                            </td>
     464                        </tr>
     465                    </table>
     466
     467                    <!-- Action Buttons -->
     468                    <p class="submit">
     469                        <button type="button" id="resetfileperm-ownership-scan-btn" class="button button-secondary">
     470                            <span class="dashicons dashicons-search"></span>
     471                            <?php esc_html_e( 'Scan Directory', 'reset-file-and-folder-permissions' ); ?>
     472                        </button>
     473                        <button type="button" id="resetfileperm-ownership-reset-btn" class="button button-primary" disabled>
     474                            <span class="dashicons dashicons-admin-tools"></span>
     475                            <?php esc_html_e( 'Reset Ownership', 'reset-file-and-folder-permissions' ); ?>
     476                        </button>
     477                    </p>
     478                </form>
     479            </div>
     480
     481            <!-- Scan Results -->
     482            <div id="resetfileperm-ownership-scan-results" class="resetfileperm-scan-results" style="display: none;">
     483                <h2><?php esc_html_e( 'Scan Results', 'reset-file-and-folder-permissions' ); ?></h2>
     484                <div class="resetfileperm-scan-summary">
     485                    <p><?php esc_html_e( 'Found:', 'reset-file-and-folder-permissions' ); ?>
     486                        <strong id="resetfileperm-ownership-scan-files">0</strong> <?php esc_html_e( 'files', 'reset-file-and-folder-permissions' ); ?>
     487                        <?php esc_html_e( 'and', 'reset-file-and-folder-permissions' ); ?>
     488                        <strong id="resetfileperm-ownership-scan-dirs">0</strong> <?php esc_html_e( 'directories', 'reset-file-and-folder-permissions' ); ?>
     489                    </p>
     490                </div>
     491            </div>
     492
     493            <!-- Progress Section -->
     494            <div id="resetfileperm-ownership-progress-section" class="resetfileperm-progress-section" style="display: none;">
     495                <h2><?php esc_html_e( 'Progress', 'reset-file-and-folder-permissions' ); ?></h2>
     496                <div class="resetfileperm-progress-container">
     497                    <div class="resetfileperm-progress-bar">
     498                        <div id="resetfileperm-ownership-progress-fill" class="resetfileperm-progress-fill" style="width: 0%;"></div>
     499                    </div>
     500                    <div id="resetfileperm-ownership-progress-text" class="resetfileperm-progress-text">0%</div>
     501                </div>
     502                <div id="resetfileperm-ownership-progress-details" class="resetfileperm-progress-details">
     503                    <p id="resetfileperm-ownership-current-status"><?php esc_html_e( 'Ready to start...', 'reset-file-and-folder-permissions' ); ?></p>
     504                    <div class="resetfileperm-stats">
     505                        <span><?php esc_html_e( 'Files processed:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-ownership-files-count">0</strong></span>
     506                        <span><?php esc_html_e( 'Directories processed:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-ownership-dirs-count">0</strong></span>
     507                        <span><?php esc_html_e( 'Errors:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-ownership-errors-count">0</strong></span>
     508                    </div>
     509                </div>
     510            </div>
     511
     512            <!-- Error Log -->
     513            <div id="resetfileperm-ownership-error-log" class="resetfileperm-error-log" style="display: none;">
     514                <h2><?php esc_html_e( 'Error Log', 'reset-file-and-folder-permissions' ); ?></h2>
     515                <div id="resetfileperm-ownership-error-messages" class="resetfileperm-error-messages"></div>
     516            </div>
     517
     518            <!-- Results Section -->
     519            <div id="resetfileperm-ownership-results-section" class="resetfileperm-results-section" style="display: none;">
     520                <h2><?php esc_html_e( 'Operation Complete', 'reset-file-and-folder-permissions' ); ?></h2>
     521                <div class="notice notice-success">
     522                    <p><strong><?php esc_html_e( 'Ownership reset completed!', 'reset-file-and-folder-permissions' ); ?></strong></p>
     523                </div>
     524                <div id="resetfileperm-ownership-final-results" class="resetfileperm-final-results"></div>
     525            </div>
     526
     527                </div><!-- End Left Column -->
     528
     529                <!-- Right Column - Developer Profile (same as permissions tab) -->
     530                <div class="resetfileperm-right-column">
     531                    <div class="resetfileperm-developer-profile">
     532                    <div class="resetfileperm-profile-content">
     533                        <div class="resetfileperm-profile-card">
     534                            <div class="resetfileperm-profile-header">
     535                                <?php
     536                                            $resetfileperm_logo_path_2 = RESETFILEPERM_PLUGIN_DIR . 'assets/nandann-logo.png';
     537                $resetfileperm_logo_url_2 = RESETFILEPERM_PLUGIN_URL . 'assets/nandann-logo.png';
     538                                if ( file_exists( $resetfileperm_logo_path_2 ) && function_exists( 'getimagesize' ) && getimagesize( $resetfileperm_logo_path_2 ) !== false ) : ?>
     539                                    <div class="resetfileperm-logo-container">
     540                                        <img src="<?php echo esc_url( $resetfileperm_logo_url_2 ); ?>"
     541                                                 alt="<?php esc_attr_e( 'Nandann Creative Agency Logo', 'reset-file-and-folder-permissions' ); ?>"
     542                                                 class="resetfileperm-logo"
     543                                                 width="120"
     544                                                 height="auto" />
     545                                        </div>
     546                                    <?php else : ?>
     547                                        <div class="resetfileperm-logo-container">
     548                                            <h2 class="resetfileperm-logo-text"><?php esc_html_e( 'Nandann', 'reset-file-and-folder-permissions' ); ?></h2>
     549                                        </div>
     550                                    <?php endif; ?>
     551                                    <p class="resetfileperm-agency-text"><?php esc_html_e( 'Creative Agency', 'reset-file-and-folder-permissions' ); ?></p>
     552                                    <h3><?php esc_html_e( 'Professional WordPress Development & Troubleshooting', 'reset-file-and-folder-permissions' ); ?></h3>
     553                                    <p class="resetfileperm-tagline"><?php esc_html_e( 'Expert solutions for complex WordPress challenges', 'reset-file-and-folder-permissions' ); ?></p>
     554                                </div>
     555                               
     556                                <div class="resetfileperm-profile-cta">
     557                                    <p class="resetfileperm-cta-text"><?php esc_html_e( 'Facing WordPress challenges? Get professional help from an experienced developer who understands the complexities of WordPress development and can provide reliable, efficient solutions.', 'reset-file-and-folder-permissions' ); ?></p>
     558                                   
     559                                    <div class="resetfileperm-contact-buttons">
     560                                        <a href="mailto:[email protected]?subject=WordPress Development Help Request" class="button button-primary resetfileperm-contact-btn">
     561                                            <span class="dashicons dashicons-email-alt"></span>
     562                                            <span class="resetfileperm-btn-text">
     563                                                <span class="resetfileperm-btn-line1"><?php esc_html_e( 'Get Expert Help', 'reset-file-and-folder-permissions' ); ?></span>
     564                                                <span class="resetfileperm-btn-line2">[email protected]</span>
     565                                            </span>
     566                                        </a>
     567                                        <a href="https://nandann.com" target="_blank" class="button button-secondary resetfileperm-website-btn">
     568                                            <span class="dashicons dashicons-external"></span>
     569                                            <?php esc_html_e( 'Visit nandann.com', 'reset-file-and-folder-permissions' ); ?>
     570                                        </a>
     571                                    </div>
     572                                </div>
     573                               
     574                                <div class="resetfileperm-profile-services">
     575                                    <div class="resetfileperm-service-grid">
     576                                        <div class="resetfileperm-service-item">
     577                                            <span class="dashicons dashicons-admin-tools"></span>
     578                                            <h4><?php esc_html_e( 'WordPress Troubleshooting', 'reset-file-and-folder-permissions' ); ?></h4>
     579                                            <p><?php esc_html_e( 'Expert diagnosis and resolution of complex WordPress issues, performance optimization, and security hardening.', 'reset-file-and-folder-permissions' ); ?></p>
     580                                        </div>
     581                                       
     582                                        <div class="resetfileperm-service-item">
     583                                            <span class="dashicons dashicons-desktop"></span>
     584                                            <h4><?php esc_html_e( 'Custom Development', 'reset-file-and-folder-permissions' ); ?></h4>
     585                                            <p><?php esc_html_e( 'Bespoke WordPress plugins, themes, and custom functionality tailored to your specific business needs.', 'reset-file-and-folder-permissions' ); ?></p>
     586                                        </div>
     587                                       
     588                                        <div class="resetfileperm-service-item">
     589                                            <span class="dashicons dashicons-migrate"></span>
     590                                            <h4><?php esc_html_e( 'Site Migration & Hosting', 'reset-file-and-folder-permissions' ); ?></h4>
     591                                            <p><?php esc_html_e( 'Seamless website migrations, hosting optimization, and server configuration for peak performance.', 'reset-file-and-folder-permissions' ); ?></p>
     592                                        </div>
     593                                       
     594                                        <div class="resetfileperm-service-item">
     595                                            <span class="dashicons dashicons-shield"></span>
     596                                            <h4><?php esc_html_e( 'Security & Maintenance', 'reset-file-and-folder-permissions' ); ?></h4>
     597                                            <p><?php esc_html_e( 'Comprehensive security audits, malware removal, and ongoing maintenance to keep your site secure.', 'reset-file-and-folder-permissions' ); ?></p>
     598                                        </div>
     599                                    </div>
     600                                </div>
     601                            </div>
     602                        </div>
     603                    </div>
     604                </div><!-- End Right Column -->
     605
     606            </div><!-- End Main Layout -->
     607
     608            <!-- Help Section -->
     609            <div class="resetfileperm-help-section">
     610                <h2><?php esc_html_e( 'About File Ownership', 'reset-file-and-folder-permissions' ); ?></h2>
     611                <div class="resetfileperm-help-content">
     612                    <h3><?php esc_html_e( 'What is File Ownership?', 'reset-file-and-folder-permissions' ); ?></h3>
     613                    <p><?php esc_html_e( 'File ownership determines which user and group have control over files and directories. In WordPress, files should typically be owned by the web server user (like www-data, apache, or nginx) to ensure proper functionality.', 'reset-file-and-folder-permissions' ); ?></p>
     614                   
     615                    <h3><?php esc_html_e( 'When to Use This Tool', 'reset-file-and-folder-permissions' ); ?></h3>
     616                    <ul>
     617                        <li><?php esc_html_e( 'After migrating to a new server with a different web server user', 'reset-file-and-folder-permissions' ); ?></li>
     618                        <li><?php esc_html_e( 'When WordPress cannot write files or install plugins/themes', 'reset-file-and-folder-permissions' ); ?></li>
     619                        <li><?php esc_html_e( 'After manually uploading files via FTP with incorrect ownership', 'reset-file-and-folder-permissions' ); ?></li>
     620                        <li><?php esc_html_e( 'When troubleshooting "permission denied" errors', 'reset-file-and-folder-permissions' ); ?></li>
     621                    </ul>
     622
     623                    <h3><?php esc_html_e( 'Important Warnings', 'reset-file-and-folder-permissions' ); ?></h3>
     624                    <ul>
     625                        <li><strong><?php esc_html_e( 'Incorrect ownership can break your site', 'reset-file-and-folder-permissions' ); ?></strong> - <?php esc_html_e( 'Always use the recommended values', 'reset-file-and-folder-permissions' ); ?></li>
     626                        <li><strong><?php esc_html_e( 'This operation requires elevated privileges', 'reset-file-and-folder-permissions' ); ?></strong> - <?php esc_html_e( 'Not available on all hosting environments', 'reset-file-and-folder-permissions' ); ?></li>
     627                        <li><strong><?php esc_html_e( 'Test after running', 'reset-file-and-folder-permissions' ); ?></strong> - <?php esc_html_e( 'Verify your site works correctly after changing ownership', 'reset-file-and-folder-permissions' ); ?></li>
     628                    </ul>
     629                </div>
     630            </div>
     631
     632        <?php endif; ?>
     633
     634    <?php endif; ?>
     635</div>
  • reset-file-and-folder-permissions/tags/1.1.0/readme.txt

    r3345847 r3396598  
    55Requires at least: 5.0
    66Tested up to: 6.8
    7 Stable tag: 1.0.0
     7Stable tag: 1.1.0
    88Requires PHP: 7.4
    99License: GPLv2 or later
     
    1212Author URI: https://nandann.com
    1313
    14 A WordPress plugin to reset all file permissions to 0644 and all directory permissions to 0755 for security and maintenance purposes.
     14A WordPress plugin to reset file permissions to 0644, directory permissions to 0755, and file/folder ownership for security and maintenance purposes.
    1515
    1616== Description ==
    1717
    18 Reset file and folder permissions is a powerful yet safe WordPress plugin designed to help administrators reset file and directory permissions to their recommended secure values. This tool is particularly useful after site migrations, server changes, or when dealing with permission-related issues.
     18Reset file and folder permissions is a powerful yet safe WordPress plugin designed to help administrators reset file and directory permissions to their recommended secure values, and optionally reset file/folder ownership. This tool is particularly useful after site migrations, server changes, or when dealing with permission-related issues.
    1919
    2020= Key Features =
    2121
     22* **Dual Functionality**: Reset both permissions (0644/0755) and ownership (user/group) in separate tabs
     23* **Ownership Management**: Change file and folder ownership to the correct web server user (VPS/dedicated servers)
     24* **Server Compatibility Check**: Automatically detects if ownership functions are available on your server
    2225* **Batch Processing**: Handles large directory structures efficiently with configurable batch sizes
    2326* **Real-time Progress**: Visual progress bar with detailed statistics during processing
    2427* **Safety First**: Multiple security checks and confirmations before making changes
    2528* **Selective Processing**: Choose specific directories to process (entire site, wp-content, plugins, themes, or uploads)
     29* **Smart Recommendations**: Automatically detects and recommends the correct owner/group for your server
    2630* **Error Handling**: Comprehensive error logging and reporting
    2731* **Responsive Interface**: Works seamlessly on desktop and mobile devices
     
    3539= When to Use This Plugin =
    3640
     41**For Permission Reset:**
    3742* After migrating your WordPress site to a new server
    3843* When files have incorrect permissions causing functionality issues
     
    4045* When troubleshooting file access problems
    4146* During routine maintenance to ensure proper permissions
     47
     48**For Ownership Reset:**
     49* After migrating to a new server with a different web server user
     50* When WordPress cannot write files or install plugins/themes
     51* After manually uploading files via FTP with incorrect ownership
     52* When troubleshooting "permission denied" errors despite correct permissions
     53* When switching hosting providers or server configurations
    4254
    4355= Safety Features =
     
    6577= System Requirements =
    6678
     79**For Permission Reset:**
    6780* PHP `chmod()` function must be available
    6881* WordPress 5.0 or higher
    6982* PHP 7.4 or higher
    7083* Administrator access
     84
     85**For Ownership Reset (Additional Requirements):**
     86* PHP `chown()` and `chgrp()` functions must be available
     87* PHP POSIX functions (`posix_getpwnam`, `posix_getgrnam`, etc.)
     88* VPS, dedicated server, or hosting with elevated privileges
     89* Note: Ownership features are typically NOT available on shared hosting
    7190
    7291== Frequently Asked Questions ==
     
    106125- Uploads directory only
    107126
     127= What is file ownership and why does it matter? =
     128
     129File ownership determines which user and group have control over files. In WordPress, files should typically be owned by the web server user (like www-data, apache, or nginx) to ensure proper functionality. Incorrect ownership can prevent WordPress from writing files, installing plugins/themes, or updating content.
     130
     131= Why can't I see the ownership reset feature? =
     132
     133The ownership reset feature requires PHP functions (`chown`, `chgrp`, and POSIX functions) that are often disabled on shared hosting for security reasons. These functions typically require elevated server privileges and are only available on VPS, dedicated servers, or hosting environments where you have more control. If you don't see the ownership tab or see a compatibility warning, contact your hosting provider or consider upgrading to a more flexible hosting solution.
     134
     135= How do I know which owner and group to use? =
     136
     137The plugin automatically detects your web server's user and group and recommends them. In most cases, you should use the recommended values. Common web server users include: www-data (Ubuntu/Debian), apache (CentOS/RHEL), nginx (Nginx servers), or _www (macOS).
     138
     139= Can incorrect ownership break my site? =
     140
     141Yes, setting incorrect ownership can prevent WordPress from functioning properly. Always use the recommended values provided by the plugin. If you're unsure, contact your hosting provider or a WordPress professional before making ownership changes.
     142
     143= What's the difference between permissions and ownership? =
     144
     145**Permissions** (0644/0755) control what actions can be performed on files (read, write, execute) by the owner, group, and others. **Ownership** determines which user and group "own" the files. Both need to be correct for WordPress to function properly. You can have correct permissions but still face issues if ownership is wrong.
     146
    108147== Screenshots ==
    109148
     
    114153
    115154== Changelog ==
     155
     156= 1.1.0 =
     157* Added: File and folder ownership reset functionality
     158* Added: Separate "Reset Ownership" tab for ownership management
     159* Added: Automatic detection of web server user and group
     160* Added: Server compatibility check for ownership functions
     161* Added: Smart recommendations for owner/group selection
     162* Added: Dropdown menus for selecting owner and group
     163* Added: Comprehensive warnings and help text for ownership operations
     164* Added: Separate confirmation dialogs for ownership changes
     165* Improved: Tab-based navigation for better organization
     166* Improved: Enhanced error messages and logging
     167* Improved: Better compatibility warnings for shared hosting
     168* Note: Ownership features require VPS/dedicated server with elevated privileges
    116169
    117170= 1.0.0 =
     
    125178== Upgrade Notice ==
    126179
     180= 1.1.0 =
     181Major update: Added file and folder ownership reset functionality with automatic server detection and smart recommendations. New tab-based interface for better organization. Ownership features require VPS/dedicated server.
     182
    127183= 1.0.0 =
    128184Initial release of Reset file and folder permissions plugin. Safely reset file and directory permissions to WordPress standards.
  • reset-file-and-folder-permissions/tags/1.1.0/uninstall.php

    r3345847 r3396598  
    1515
    1616// Clean up log directory if it exists
    17 $log_dir = WP_CONTENT_DIR . '/resetfileperm-logs';
    18 if ( file_exists( $log_dir ) ) {
     17$resetfileperm_log_dir = WP_CONTENT_DIR . '/resetfileperm-logs';
     18if ( file_exists( $resetfileperm_log_dir ) ) {
    1919    // Remove all files in the log directory using WordPress filesystem
    2020    if ( ! function_exists( 'WP_Filesystem' ) ) {
     
    2424    global $wp_filesystem;
    2525   
    26     if ( $wp_filesystem && $wp_filesystem->is_dir( $log_dir ) ) {
    27         $wp_filesystem->rmdir( $log_dir, true );
     26    if ( $wp_filesystem && $wp_filesystem->is_dir( $resetfileperm_log_dir ) ) {
     27        $wp_filesystem->rmdir( $resetfileperm_log_dir, true );
    2828    }
    2929}
  • reset-file-and-folder-permissions/trunk/assets/admin.css

    r3345847 r3396598  
    44 * @package FilePermissionsReset
    55 */
     6
     7/* Tab Navigation */
     8.nav-tab-wrapper {
     9    margin: 20px 0;
     10    border-bottom: 1px solid #ccc;
     11}
     12
     13.nav-tab {
     14    background: #f1f1f1;
     15    border: 1px solid #ccc;
     16    border-bottom: none;
     17    color: #555;
     18    text-decoration: none;
     19    padding: 10px 15px;
     20    margin-right: 5px;
     21    display: inline-block;
     22    font-weight: 600;
     23    transition: all 0.3s ease;
     24}
     25
     26.nav-tab:hover {
     27    background: #fff;
     28    color: #333;
     29}
     30
     31.nav-tab-active,
     32.nav-tab-active:hover {
     33    background: #fff;
     34    border-bottom-color: #fff;
     35    color: #000;
     36    margin-bottom: -1px;
     37    padding-bottom: 11px;
     38}
     39
     40/* Compatibility Warning */
     41.notice.notice-error h3 {
     42    margin-top: 0;
     43    color: #d63638;
     44}
     45
     46.notice.notice-error code {
     47    background: #fff;
     48    padding: 2px 6px;
     49    border-radius: 3px;
     50    font-size: 13px;
     51    color: #d63638;
     52    font-weight: 600;
     53}
     54
     55.notice.notice-error ul {
     56    margin: 10px 0;
     57    padding-left: 20px;
     58}
     59
     60.notice.notice-error li {
     61    margin-bottom: 8px;
     62    line-height: 1.6;
     63}
    664
    765/* Main Layout */
  • reset-file-and-folder-permissions/trunk/assets/admin.js

    r3345847 r3396598  
    1919        errorMessages: [],
    2020
     21        // Ownership-specific state
     22        ownershipIsProcessing: false,
     23        ownershipTotalItems: 0,
     24        ownershipProcessedItems: 0,
     25        ownershipCurrentOffset: 0,
     26        ownershipBatchSize: 100,
     27        ownershipFilesUpdated: 0,
     28        ownershipDirsUpdated: 0,
     29        ownershipTotalErrors: 0,
     30        ownershipErrorMessages: [],
     31
    2132        init: function() {
    2233            this.bindEvents();
     34            this.loadServerInfo();
    2335        },
    2436
    2537        bindEvents: function() {
     38            // Permissions tab events
    2639            $('#resetfileperm-scan-btn').on('click', this.scanDirectory.bind(this));
    2740            $('#resetfileperm-reset-btn').on('click', this.resetPermissions.bind(this));
    2841            $('#resetfileperm-directory').on('change', this.onDirectoryChange.bind(this));
    2942            $('#resetfileperm-batch-size').on('change', this.onBatchSizeChange.bind(this));
     43
     44            // Ownership tab events
     45            $('#resetfileperm-ownership-scan-btn').on('click', this.scanDirectoryForOwnership.bind(this));
     46            $('#resetfileperm-ownership-reset-btn').on('click', this.resetOwnership.bind(this));
     47            $('#resetfileperm-ownership-directory').on('change', this.onOwnershipDirectoryChange.bind(this));
     48            $('#resetfileperm-ownership-batch-size').on('change', this.onOwnershipBatchSizeChange.bind(this));
     49        },
     50
     51        loadServerInfo: function() {
     52            // Only load if we're on the ownership tab
     53            if ($('#resetfileperm-ownership-server-info').length === 0) {
     54                return;
     55            }
     56
     57            var data = {
     58                action: 'resetfileperm_get_server_info',
     59                nonce: resetfilepermAjax.nonce
     60            };
     61
     62            $.post(resetfilepermAjax.ajaxUrl, data)
     63                .done(this.onServerInfoLoaded.bind(this))
     64                .fail(function() {
     65                    $('#resetfileperm-ownership-server-info').html(
     66                        '<div class="notice notice-error"><p>Failed to load server information.</p></div>'
     67                    );
     68                });
     69        },
     70
     71        onServerInfoLoaded: function(response) {
     72            if (!response.success || !response.data.functions_available) {
     73                return;
     74            }
     75
     76            var data = response.data;
     77            var html = '<table class="form-table">';
     78           
     79            if (data.recommended_owner) {
     80                html += '<tr>';
     81                html += '<th scope="row">Recommended Owner:</th>';
     82                html += '<td><code>' + $('<div>').text(data.recommended_owner).html() + '</code> <span class="description">(Current web server user)</span></td>';
     83                html += '</tr>';
     84            }
     85           
     86            if (data.recommended_group) {
     87                html += '<tr>';
     88                html += '<th scope="row">Recommended Group:</th>';
     89                html += '<td><code>' + $('<div>').text(data.recommended_group).html() + '</code> <span class="description">(Current web server group)</span></td>';
     90                html += '</tr>';
     91            }
     92           
     93            html += '</table>';
     94            $('#resetfileperm-ownership-server-info').html(html);
     95
     96            // Populate owner dropdown
     97            if (data.available_users && data.available_users.length > 0) {
     98                var ownerSelect = $('#resetfileperm-owner');
     99                ownerSelect.empty().append('<option value="">Select owner...</option>');
     100               
     101                data.available_users.forEach(function(user) {
     102                    var isRecommended = user === data.recommended_owner;
     103                    var label = user + (isRecommended ? ' (Recommended)' : '');
     104                    var option = $('<option></option>')
     105                        .val(user)
     106                        .text(label);
     107                   
     108                    if (isRecommended) {
     109                        option.prop('selected', true);
     110                    }
     111                   
     112                    ownerSelect.append(option);
     113                });
     114            }
     115
     116            // Populate group dropdown
     117            if (data.available_groups && data.available_groups.length > 0) {
     118                var groupSelect = $('#resetfileperm-group');
     119                groupSelect.empty().append('<option value="">Select group...</option>');
     120               
     121                data.available_groups.forEach(function(group) {
     122                    var isRecommended = group === data.recommended_group;
     123                    var label = group + (isRecommended ? ' (Recommended)' : '');
     124                    var option = $('<option></option>')
     125                        .val(group)
     126                        .text(label);
     127                   
     128                    if (isRecommended) {
     129                        option.prop('selected', true);
     130                    }
     131                   
     132                    groupSelect.append(option);
     133                });
     134            }
    30135        },
    31136
     
    36141        onBatchSizeChange: function() {
    37142            this.batchSize = parseInt($('#resetfileperm-batch-size').val(), 10);
     143        },
     144
     145        onOwnershipDirectoryChange: function() {
     146            this.resetOwnershipUI();
     147        },
     148
     149        onOwnershipBatchSizeChange: function() {
     150            this.ownershipBatchSize = parseInt($('#resetfileperm-ownership-batch-size').val(), 10);
    38151        },
    39152
     
    47160        },
    48161
     162        resetOwnershipUI: function() {
     163            $('#resetfileperm-ownership-scan-results').hide();
     164            $('#resetfileperm-ownership-progress-section').hide();
     165            $('#resetfileperm-ownership-error-log').hide();
     166            $('#resetfileperm-ownership-results-section').hide();
     167            $('#resetfileperm-ownership-reset-btn').prop('disabled', true);
     168            this.resetOwnershipProgress();
     169        },
     170
    49171        resetProgress: function() {
    50172            this.processedItems = 0;
     
    63185        },
    64186
     187        resetOwnershipProgress: function() {
     188            this.ownershipProcessedItems = 0;
     189            this.ownershipCurrentOffset = 0;
     190            this.ownershipFilesUpdated = 0;
     191            this.ownershipDirsUpdated = 0;
     192            this.ownershipTotalErrors = 0;
     193            this.ownershipErrorMessages = [];
     194
     195            $('#resetfileperm-ownership-progress-fill').css('width', '0%');
     196            $('#resetfileperm-ownership-progress-text').text('0%');
     197            $('#resetfileperm-ownership-current-status').text(resetfilepermAjax.strings.scanning);
     198            $('#resetfileperm-ownership-files-count').text('0');
     199            $('#resetfileperm-ownership-dirs-count').text('0');
     200            $('#resetfileperm-ownership-errors-count').text('0');
     201        },
     202
    65203        scanDirectory: function() {
    66204            if (this.isProcessing) {
     
    90228        },
    91229
     230        scanDirectoryForOwnership: function() {
     231            if (this.ownershipIsProcessing) {
     232                return;
     233            }
     234
     235            this.ownershipIsProcessing = true;
     236            this.resetOwnershipUI();
     237           
     238            $('#resetfileperm-ownership-scan-btn').prop('disabled', true).text(resetfilepermAjax.strings.scanning);
     239            $('#resetfileperm-ownership-progress-section').show();
     240            $('#resetfileperm-ownership-current-status').text(resetfilepermAjax.strings.scanning);
     241
     242            var data = {
     243                action: 'resetfileperm_scan_directory',
     244                nonce: resetfilepermAjax.nonce,
     245                directory: $('#resetfileperm-ownership-directory').val()
     246            };
     247
     248            $.post(resetfilepermAjax.ajaxUrl, data)
     249                .done(this.onOwnershipScanComplete.bind(this))
     250                .fail(this.onOwnershipScanError.bind(this))
     251                .always(function() {
     252                    this.ownershipIsProcessing = false;
     253                    $('#resetfileperm-ownership-scan-btn').prop('disabled', false).html('<span class="dashicons dashicons-search"></span> Scan Directory');
     254                }.bind(this));
     255        },
     256
    92257        onScanComplete: function(response) {
    93258            if (response.success) {
     
    114279        },
    115280
     281        onOwnershipScanComplete: function(response) {
     282            if (response.success) {
     283                var data = response.data;
     284                this.ownershipTotalItems = data.files + data.directories;
     285
     286                $('#resetfileperm-ownership-scan-files').text(data.files.toLocaleString());
     287                $('#resetfileperm-ownership-scan-dirs').text(data.directories.toLocaleString());
     288                $('#resetfileperm-ownership-scan-results').show();
     289
     290                if (data.errors.length > 0) {
     291                    this.showOwnershipErrors(data.errors);
     292                }
     293
     294                if (this.ownershipTotalItems > 0) {
     295                    $('#resetfileperm-ownership-reset-btn').prop('disabled', false);
     296                    $('#resetfileperm-ownership-current-status').text('Scan completed. Ready to reset ownership.');
     297                } else {
     298                    $('#resetfileperm-ownership-current-status').text('No files or directories found to process.');
     299                }
     300            } else {
     301                this.showOwnershipError('Scan failed: ' + (response.data || 'Unknown error'));
     302            }
     303        },
     304
    116305        onScanError: function(xhr, status, error) {
    117306            this.showError('Scan request failed: ' + error);
     307        },
     308
     309        onOwnershipScanError: function(xhr, status, error) {
     310            this.showOwnershipError('Scan request failed: ' + error);
    118311        },
    119312
     
    137330            this.batchSize = parseInt($('#resetfileperm-batch-size').val(), 10);
    138331            this.processNextBatch();
     332        },
     333
     334        resetOwnership: function() {
     335            if (this.ownershipIsProcessing || this.ownershipTotalItems === 0) {
     336                return;
     337            }
     338
     339            var owner = $('#resetfileperm-owner').val();
     340            var group = $('#resetfileperm-group').val();
     341
     342            if (!owner || !group) {
     343                alert('Please select both owner and group.');
     344                return;
     345            }
     346
     347            if (!confirm(resetfilepermAjax.strings.confirmOwnership)) {
     348                return;
     349            }
     350
     351            this.ownershipIsProcessing = true;
     352            this.resetOwnershipProgress();
     353           
     354            $('#resetfileperm-ownership-reset-btn').prop('disabled', true).text(resetfilepermAjax.strings.processingOwnership);
     355            $('#resetfileperm-ownership-scan-btn').prop('disabled', true);
     356            $('#resetfileperm-ownership-progress-section').show();
     357            $('#resetfileperm-ownership-current-status').text(resetfilepermAjax.strings.processingOwnership);
     358
     359            this.ownershipBatchSize = parseInt($('#resetfileperm-ownership-batch-size').val(), 10);
     360            this.processNextOwnershipBatch();
    139361        },
    140362
     
    153375        },
    154376
     377        processNextOwnershipBatch: function() {
     378            var data = {
     379                action: 'resetfileperm_reset_ownership',
     380                nonce: resetfilepermAjax.nonce,
     381                directory: $('#resetfileperm-ownership-directory').val(),
     382                owner: $('#resetfileperm-owner').val(),
     383                group: $('#resetfileperm-group').val(),
     384                batch_size: this.ownershipBatchSize,
     385                offset: this.ownershipCurrentOffset
     386            };
     387
     388            $.post(resetfilepermAjax.ajaxUrl, data)
     389                .done(this.onOwnershipBatchComplete.bind(this))
     390                .fail(this.onOwnershipBatchError.bind(this));
     391        },
     392
    155393        onBatchComplete: function(response) {
    156394            if (response.success) {
     
    180418        },
    181419
     420        onOwnershipBatchComplete: function(response) {
     421            if (response.success) {
     422                var data = response.data;
     423
     424                this.ownershipProcessedItems += data.processed;
     425                this.ownershipFilesUpdated += data.files_updated;
     426                this.ownershipDirsUpdated += data.directories_updated;
     427                this.ownershipCurrentOffset = data.next_offset;
     428
     429                if (data.errors.length > 0) {
     430                    this.ownershipTotalErrors += data.errors.length;
     431                    this.ownershipErrorMessages = this.ownershipErrorMessages.concat(data.errors);
     432                }
     433
     434                this.updateOwnershipProgress();
     435
     436                if (data.completed || data.processed === 0) {
     437                    this.onOwnershipProcessingComplete();
     438                } else {
     439                    // Continue with next batch
     440                    setTimeout(this.processNextOwnershipBatch.bind(this), 100);
     441                }
     442            } else {
     443                this.onOwnershipBatchError(null, null, response.data || 'Unknown error');
     444            }
     445        },
     446
    182447        onBatchError: function(xhr, status, error) {
    183448            this.isProcessing = false;
     
    186451        },
    187452
     453        onOwnershipBatchError: function(xhr, status, error) {
     454            this.ownershipIsProcessing = false;
     455            this.showOwnershipError('Processing failed: ' + error);
     456            this.enableOwnershipButtons();
     457        },
     458
    188459        onProcessingComplete: function() {
    189460            this.isProcessing = false;
     
    198469            if (this.errorMessages.length > 0) {
    199470                this.showErrors(this.errorMessages);
     471            }
     472        },
     473
     474        onOwnershipProcessingComplete: function() {
     475            this.ownershipIsProcessing = false;
     476           
     477            $('#resetfileperm-ownership-progress-fill').css('width', '100%');
     478            $('#resetfileperm-ownership-progress-text').text('100%');
     479            $('#resetfileperm-ownership-current-status').text(resetfilepermAjax.strings.ownershipCompleted);
     480
     481            this.showOwnershipResults();
     482            this.enableOwnershipButtons();
     483
     484            if (this.ownershipErrorMessages.length > 0) {
     485                this.showOwnershipErrors(this.ownershipErrorMessages);
    200486            }
    201487        },
     
    212498            var status = 'Processing... (' + this.processedItems.toLocaleString() + ' of ' + this.totalItems.toLocaleString() + ' items)';
    213499            $('#resetfileperm-current-status').text(status);
     500        },
     501
     502        updateOwnershipProgress: function() {
     503            var percentage = this.ownershipTotalItems > 0 ? Math.round((this.ownershipProcessedItems / this.ownershipTotalItems) * 100) : 0;
     504           
     505            $('#resetfileperm-ownership-progress-fill').css('width', percentage + '%');
     506            $('#resetfileperm-ownership-progress-text').text(percentage + '%');
     507            $('#resetfileperm-ownership-files-count').text(this.ownershipFilesUpdated.toLocaleString());
     508            $('#resetfileperm-ownership-dirs-count').text(this.ownershipDirsUpdated.toLocaleString());
     509            $('#resetfileperm-ownership-errors-count').text(this.ownershipTotalErrors.toLocaleString());
     510
     511            var status = 'Processing... (' + this.ownershipProcessedItems.toLocaleString() + ' of ' + this.ownershipTotalItems.toLocaleString() + ' items)';
     512            $('#resetfileperm-ownership-current-status').text(status);
    214513        },
    215514
     
    229528        },
    230529
     530        showOwnershipResults: function() {
     531            var html = '<div class="resetfileperm-results-summary">';
     532            html += '<h3>Summary</h3>';
     533            html += '<ul>';
     534            html += '<li><strong>Total items processed:</strong> ' + this.ownershipProcessedItems.toLocaleString() + '</li>';
     535            html += '<li><strong>Files updated:</strong> ' + this.ownershipFilesUpdated.toLocaleString() + '</li>';
     536            html += '<li><strong>Directories updated:</strong> ' + this.ownershipDirsUpdated.toLocaleString() + '</li>';
     537            html += '<li><strong>Errors encountered:</strong> ' + this.ownershipTotalErrors.toLocaleString() + '</li>';
     538            html += '</ul>';
     539            html += '</div>';
     540
     541            $('#resetfileperm-ownership-final-results').html(html);
     542            $('#resetfileperm-ownership-results-section').show();
     543        },
     544
    231545        showErrors: function(errors) {
    232546            if (errors.length === 0) {
     
    244558        },
    245559
     560        showOwnershipErrors: function(errors) {
     561            if (errors.length === 0) {
     562                return;
     563            }
     564
     565            var html = '<div class="notice notice-error"><ul>';
     566            errors.forEach(function(error) {
     567                html += '<li>' + $('<div>').text(error).html() + '</li>';
     568            });
     569            html += '</ul></div>';
     570
     571            $('#resetfileperm-ownership-error-messages').html(html);
     572            $('#resetfileperm-ownership-error-log').show();
     573        },
     574
    246575        showError: function(message) {
    247576            var html = '<div class="notice notice-error"><p>' + $('<div>').text(message).html() + '</p></div>';
     
    250579        },
    251580
     581        showOwnershipError: function(message) {
     582            var html = '<div class="notice notice-error"><p>' + $('<div>').text(message).html() + '</p></div>';
     583            $('#resetfileperm-ownership-error-messages').html(html);
     584            $('#resetfileperm-ownership-error-log').show();
     585        },
     586
    252587        enableButtons: function() {
    253588            $('#resetfileperm-scan-btn').prop('disabled', false).html('<span class="dashicons dashicons-search"></span> Scan Directory');
    254589            $('#resetfileperm-reset-btn').prop('disabled', this.totalItems === 0).html('<span class="dashicons dashicons-admin-tools"></span> Reset Permissions');
     590        },
     591
     592        enableOwnershipButtons: function() {
     593            $('#resetfileperm-ownership-scan-btn').prop('disabled', false).html('<span class="dashicons dashicons-search"></span> Scan Directory');
     594            $('#resetfileperm-ownership-reset-btn').prop('disabled', this.ownershipTotalItems === 0).html('<span class="dashicons dashicons-admin-tools"></span> Reset Ownership');
    255595        }
    256596    };
     
    261601    });
    262602
    263 })(jQuery); 
     603})(jQuery);
  • reset-file-and-folder-permissions/trunk/file-permissions-reset.php

    r3345847 r3396598  
    44 * Plugin URI: https://nandann.com/contact
    55 * Description: A WordPress plugin to reset all file permissions to 0644 and all directory permissions to 0755 for security and maintenance purposes.
    6  * Version: 1.0.0
     6 * Version: 1.1.0
    77 * Author: Prakhar Bhatia
    88 * Author URI: https://nandann.com
     
    2626
    2727// Define plugin constants
    28 define( 'RESETFILEPERM_PLUGIN_VERSION', '1.0.0' );
     28define( 'RESETFILEPERM_PLUGIN_VERSION', '1.1.0' );
    2929define( 'RESETFILEPERM_PLUGIN_FILE', __FILE__ );
    3030define( 'RESETFILEPERM_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
     
    6565        add_action( 'wp_ajax_resetfileperm_reset_permissions', array( $this, 'ajax_reset_permissions' ) );
    6666        add_action( 'wp_ajax_resetfileperm_scan_directory', array( $this, 'ajax_scan_directory' ) );
     67        add_action( 'wp_ajax_resetfileperm_reset_ownership', array( $this, 'ajax_reset_ownership' ) );
     68        add_action( 'wp_ajax_resetfileperm_get_server_info', array( $this, 'ajax_get_server_info' ) );
    6769       
    6870        // Add settings link to plugins page
     
    129131                'error' => __( 'An error occurred', 'reset-file-and-folder-permissions' ),
    130132                'confirm' => __( 'Are you sure you want to reset file permissions? This action cannot be undone.', 'reset-file-and-folder-permissions' ),
     133                'processingOwnership' => __( 'Processing ownership...', 'reset-file-and-folder-permissions' ),
     134                'ownershipCompleted' => __( 'Ownership reset completed!', 'reset-file-and-folder-permissions' ),
     135                'confirmOwnership' => __( 'Are you sure you want to reset file and folder ownership? This action cannot be undone and may affect site functionality if incorrect values are used.', 'reset-file-and-folder-permissions' ),
    131136            )
    132137        ) );
     
    331336        return current_user_can( 'manage_options' ) && function_exists( 'chmod' );
    332337    }
     338
     339    /**
     340     * AJAX handler for getting server information
     341     */
     342    public function ajax_get_server_info() {
     343        // Verify nonce
     344        if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ?? '' ) ), 'resetfileperm_nonce' ) ) {
     345            wp_die( esc_html__( 'Security check failed', 'reset-file-and-folder-permissions' ) );
     346        }
     347
     348        // Check user capabilities
     349        if ( ! current_user_can( 'manage_options' ) ) {
     350            wp_die( esc_html__( 'Insufficient permissions', 'reset-file-and-folder-permissions' ) );
     351        }
     352
     353        $server_info = $this->get_server_info();
     354        wp_send_json_success( $server_info );
     355    }
     356
     357    /**
     358     * AJAX handler for resetting ownership
     359     */
     360    public function ajax_reset_ownership() {
     361        // Verify nonce
     362        if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ?? '' ) ), 'resetfileperm_nonce' ) ) {
     363            wp_die( esc_html__( 'Security check failed', 'reset-file-and-folder-permissions' ) );
     364        }
     365
     366        // Check user capabilities
     367        if ( ! current_user_can( 'manage_options' ) ) {
     368            wp_die( esc_html__( 'Insufficient permissions', 'reset-file-and-folder-permissions' ) );
     369        }
     370
     371        $directory = isset( $_POST['directory'] ) ? sanitize_text_field( wp_unslash( $_POST['directory'] ) ) : ABSPATH;
     372        $owner = isset( $_POST['owner'] ) ? sanitize_text_field( wp_unslash( $_POST['owner'] ) ) : '';
     373        $group = isset( $_POST['group'] ) ? sanitize_text_field( wp_unslash( $_POST['group'] ) ) : '';
     374        $batch_size = isset( $_POST['batch_size'] ) ? intval( $_POST['batch_size'] ) : 100;
     375        $offset = isset( $_POST['offset'] ) ? intval( $_POST['offset'] ) : 0;
     376       
     377        // Ensure we're within the WordPress installation
     378        $directory = realpath( $directory );
     379        $wp_root = realpath( ABSPATH );
     380       
     381        if ( ! $directory || strpos( $directory, $wp_root ) !== 0 ) {
     382            wp_send_json_error( __( 'Invalid directory path', 'reset-file-and-folder-permissions' ) );
     383        }
     384
     385        // Validate owner and group
     386        if ( empty( $owner ) || empty( $group ) ) {
     387            wp_send_json_error( __( 'Owner and group must be specified', 'reset-file-and-folder-permissions' ) );
     388        }
     389
     390        $result = $this->reset_ownership_batch( $directory, $owner, $group, $batch_size, $offset );
     391       
     392        wp_send_json_success( $result );
     393    }
     394
     395    /**
     396     * Get server information including recommended owner/group
     397     */
     398    private function get_server_info() {
     399        $info = array(
     400            'functions_available' => $this->check_ownership_functions(),
     401            'recommended_owner' => '',
     402            'recommended_group' => '',
     403            'available_users' => array(),
     404            'available_groups' => array(),
     405        );
     406
     407        if ( ! $info['functions_available'] ) {
     408            return $info;
     409        }
     410
     411        // Get recommended owner (current process user)
     412        if ( function_exists( 'posix_geteuid' ) && function_exists( 'posix_getpwuid' ) ) {
     413            $process_user = posix_getpwuid( posix_geteuid() );
     414            if ( $process_user ) {
     415                $info['recommended_owner'] = $process_user['name'];
     416                $info['recommended_group'] = posix_getgrgid( $process_user['gid'] )['name'] ?? '';
     417            }
     418        }
     419
     420        // Get available users (limited to common web server users for security)
     421        if ( function_exists( 'posix_getpwnam' ) ) {
     422            $common_users = array( 'www-data', 'apache', 'nginx', 'httpd', 'nobody', '_www' );
     423            foreach ( $common_users as $user ) {
     424                $user_info = posix_getpwnam( $user );
     425                if ( $user_info ) {
     426                    $info['available_users'][] = $user;
     427                }
     428            }
     429            // Add current user if not in list
     430            if ( ! empty( $info['recommended_owner'] ) && ! in_array( $info['recommended_owner'], $info['available_users'], true ) ) {
     431                $info['available_users'][] = $info['recommended_owner'];
     432            }
     433        }
     434
     435        // Get available groups (limited to common web server groups)
     436        if ( function_exists( 'posix_getgrnam' ) ) {
     437            $common_groups = array( 'www-data', 'apache', 'nginx', 'httpd', 'nobody', '_www', 'web' );
     438            foreach ( $common_groups as $group ) {
     439                $group_info = posix_getgrnam( $group );
     440                if ( $group_info ) {
     441                    $info['available_groups'][] = $group;
     442                }
     443            }
     444            // Add current group if not in list
     445            if ( ! empty( $info['recommended_group'] ) && ! in_array( $info['recommended_group'], $info['available_groups'], true ) ) {
     446                $info['available_groups'][] = $info['recommended_group'];
     447            }
     448        }
     449
     450        return $info;
     451    }
     452
     453    /**
     454     * Check if ownership functions are available
     455     */
     456    public static function check_ownership_functions() {
     457        return function_exists( 'chown' ) &&
     458               function_exists( 'chgrp' ) &&
     459               function_exists( 'posix_getpwnam' ) &&
     460               function_exists( 'posix_getgrnam' );
     461    }
     462
     463    /**
     464     * Reset ownership for a batch of files/directories
     465     */
     466    private function reset_ownership_batch( $directory, $owner, $group, $batch_size, $offset ) {
     467        $processed = 0;
     468        $files_updated = 0;
     469        $directories_updated = 0;
     470        $errors = array();
     471        $current_item = 0;
     472
     473        // Get owner and group IDs
     474        $owner_info = posix_getpwnam( $owner );
     475        $group_info = posix_getgrnam( $group );
     476
     477        if ( ! $owner_info ) {
     478            return array(
     479                'processed' => 0,
     480                'files_updated' => 0,
     481                'directories_updated' => 0,
     482                /* translators: %s: Owner name */
     483                'errors' => array( sprintf( __( 'Invalid owner: %s', 'reset-file-and-folder-permissions' ), $owner ) ),
     484                'next_offset' => $offset,
     485                'completed' => true,
     486            );
     487        }
     488
     489        if ( ! $group_info ) {
     490            return array(
     491                'processed' => 0,
     492                'files_updated' => 0,
     493                'directories_updated' => 0,
     494                /* translators: %s: Group name */
     495                'errors' => array( sprintf( __( 'Invalid group: %s', 'reset-file-and-folder-permissions' ), $group ) ),
     496                'next_offset' => $offset,
     497                'completed' => true,
     498            );
     499        }
     500
     501        $owner_uid = $owner_info['uid'];
     502        $group_gid = $group_info['gid'];
     503
     504        try {
     505            $iterator = new RecursiveIteratorIterator(
     506                new RecursiveDirectoryIterator( $directory, RecursiveDirectoryIterator::SKIP_DOTS ),
     507                RecursiveIteratorIterator::SELF_FIRST
     508            );
     509
     510            foreach ( $iterator as $item ) {
     511                // Skip items before the offset
     512                if ( $current_item < $offset ) {
     513                    $current_item++;
     514                    continue;
     515                }
     516
     517                // Stop processing if we've reached the batch size
     518                if ( $processed >= $batch_size ) {
     519                    break;
     520                }
     521
     522                $path = $item->getRealPath();
     523                $success = true;
     524
     525                // Change ownership
     526                // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_chown -- Direct file operations required for ownership changes
     527                if ( ! @chown( $path, $owner_uid ) ) {
     528                    $success = false;
     529                    /* translators: %s: File or directory path */
     530                    $errors[] = sprintf( __( 'Failed to change owner for: %s', 'reset-file-and-folder-permissions' ), $path );
     531                }
     532
     533                // Change group
     534                // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_chgrp -- Direct file operations required for ownership changes
     535                if ( ! @chgrp( $path, $group_gid ) ) {
     536                    $success = false;
     537                    /* translators: %s: File or directory path */
     538                    $errors[] = sprintf( __( 'Failed to change group for: %s', 'reset-file-and-folder-permissions' ), $path );
     539                }
     540
     541                if ( $success ) {
     542                    if ( $item->isDir() ) {
     543                        $directories_updated++;
     544                    } else {
     545                        $files_updated++;
     546                    }
     547                }
     548
     549                $processed++;
     550                $current_item++;
     551            }
     552        } catch ( Exception $e ) {
     553            /* translators: %s: Error message */
     554            $errors[] = sprintf( __( 'Error processing ownership: %s', 'reset-file-and-folder-permissions' ), $e->getMessage() );
     555        }
     556
     557        return array(
     558            'processed' => $processed,
     559            'files_updated' => $files_updated,
     560            'directories_updated' => $directories_updated,
     561            'errors' => $errors,
     562            'next_offset' => $current_item,
     563            'completed' => $processed < $batch_size,
     564        );
     565    }
    333566}
    334567
  • reset-file-and-folder-permissions/trunk/includes/admin-page.php

    r3345847 r3396598  
    1616}
    1717
    18 $wp_root = realpath( ABSPATH );
    19 $wp_content = realpath( WP_CONTENT_DIR );
    20 $wp_plugins = realpath( WP_PLUGIN_DIR );
    21 $wp_themes = realpath( get_theme_root() );
    22 $wp_uploads = wp_upload_dir();
    23 $wp_uploads_dir = realpath( $wp_uploads['basedir'] );
     18$resetfileperm_wp_root = realpath( ABSPATH );
     19$resetfileperm_wp_content = realpath( WP_CONTENT_DIR );
     20$resetfileperm_wp_plugins = realpath( WP_PLUGIN_DIR );
     21$resetfileperm_wp_themes = realpath( get_theme_root() );
     22$resetfileperm_wp_uploads = wp_upload_dir();
     23$resetfileperm_wp_uploads_dir = realpath( $resetfileperm_wp_uploads['basedir'] );
     24
     25// Get current tab
     26// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Tab parameter is for navigation only, no data modification
     27$resetfileperm_current_tab = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : 'permissions';
     28
     29// Check ownership functions availability
     30$resetfileperm_ownership_available = RESETFILEPERM_File_Permissions_Reset::check_ownership_functions();
    2431?>
    2532
     
    2734    <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
    2835   
    29     <!-- Security Warning -->
    30     <div class="notice notice-warning">
    31         <p><strong><?php esc_html_e( 'Warning:', 'reset-file-and-folder-permissions' ); ?></strong></p>
    32         <ul>
    33             <li><?php esc_html_e( 'This action will reset ALL file permissions to 0644 and directory permissions to 0755.', 'reset-file-and-folder-permissions' ); ?></li>
    34             <li><?php esc_html_e( 'This process cannot be undone. Make sure you have a backup of your site.', 'reset-file-and-folder-permissions' ); ?></li>
    35             <li><?php esc_html_e( 'Only run this tool if you understand the implications of changing file permissions.', 'reset-file-and-folder-permissions' ); ?></li>
    36         </ul>
    37     </div>
    38 
    39     <!-- Main Content Layout -->
    40     <div class="resetfileperm-main-layout">
    41         <!-- Left Column - Plugin Functionality -->
    42         <div class="resetfileperm-left-column">
    43 
    44     <!-- System Information -->
    45     <div class="resetfileperm-system-info">
    46         <h2><?php esc_html_e( 'System Information', 'reset-file-and-folder-permissions' ); ?></h2>
    47         <table class="form-table">
    48             <tr>
    49                 <th scope="row"><?php esc_html_e( 'WordPress Root', 'reset-file-and-folder-permissions' ); ?></th>
    50                 <td>
    51                     <code><?php echo esc_html( $wp_root ); ?></code>
    52                     <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $wp_root ) ); ?>)</span>
    53                 </td>
    54             </tr>
    55             <tr>
    56                 <th scope="row"><?php esc_html_e( 'WP Content Directory', 'reset-file-and-folder-permissions' ); ?></th>
    57                 <td>
    58                     <code><?php echo esc_html( $wp_content ); ?></code>
    59                     <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $wp_content ) ); ?>)</span>
    60                 </td>
    61             </tr>
    62             <tr>
    63                 <th scope="row"><?php esc_html_e( 'Plugins Directory', 'reset-file-and-folder-permissions' ); ?></th>
    64                 <td>
    65                     <code><?php echo esc_html( $wp_plugins ); ?></code>
    66                     <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $wp_plugins ) ); ?>)</span>
    67                 </td>
    68             </tr>
    69             <tr>
    70                 <th scope="row"><?php esc_html_e( 'Themes Directory', 'reset-file-and-folder-permissions' ); ?></th>
    71                 <td>
    72                     <code><?php echo esc_html( $wp_themes ); ?></code>
    73                     <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $wp_themes ) ); ?>)</span>
    74                 </td>
    75             </tr>
    76             <?php if ( $wp_uploads_dir ) : ?>
    77             <tr>
    78                 <th scope="row"><?php esc_html_e( 'Uploads Directory', 'reset-file-and-folder-permissions' ); ?></th>
    79                 <td>
    80                     <code><?php echo esc_html( $wp_uploads_dir ); ?></code>
    81                     <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $wp_uploads_dir ) ); ?>)</span>
    82                 </td>
    83             </tr>
    84             <?php endif; ?>
    85             <tr>
    86                 <th scope="row"><?php esc_html_e( 'PHP chmod() Function', 'reset-file-and-folder-permissions' ); ?></th>
    87                 <td>
    88                     <?php if ( function_exists( 'chmod' ) ) : ?>
    89                         <span class="resetfileperm-status-ok"><?php esc_html_e( 'Available', 'reset-file-and-folder-permissions' ); ?></span>
    90                     <?php else : ?>
    91                         <span class="resetfileperm-status-error"><?php esc_html_e( 'Not Available', 'reset-file-and-folder-permissions' ); ?></span>
    92                     <?php endif; ?>
    93                 </td>
    94             </tr>
    95         </table>
    96     </div>
    97 
    98     <!-- Directory Selection -->
    99     <div class="resetfileperm-directory-selection">
    100         <h2><?php esc_html_e( 'Directory Selection', 'reset-file-and-folder-permissions' ); ?></h2>
    101         <form id="resetfileperm-main-form">
     36    <!-- Tab Navigation -->
     37    <h2 class="nav-tab-wrapper">
     38        <a href="?page=resetfileperm-reset-file-folder-permissions&tab=permissions"
     39           class="nav-tab <?php echo 'permissions' === $resetfileperm_current_tab ? 'nav-tab-active' : ''; ?>">
     40            <?php esc_html_e( 'Reset Permissions', 'reset-file-and-folder-permissions' ); ?>
     41        </a>
     42        <a href="?page=resetfileperm-reset-file-folder-permissions&tab=ownership"
     43           class="nav-tab <?php echo 'ownership' === $resetfileperm_current_tab ? 'nav-tab-active' : ''; ?>">
     44            <?php esc_html_e( 'Reset Ownership', 'reset-file-and-folder-permissions' ); ?>
     45        </a>
     46    </h2>
     47
     48    <?php if ( 'permissions' === $resetfileperm_current_tab ) : ?>
     49        <!-- PERMISSIONS TAB -->
     50       
     51        <!-- Security Warning -->
     52        <div class="notice notice-warning">
     53            <p><strong><?php esc_html_e( 'Warning:', 'reset-file-and-folder-permissions' ); ?></strong></p>
     54            <ul>
     55                <li><?php esc_html_e( 'This action will reset ALL file permissions to 0644 and directory permissions to 0755.', 'reset-file-and-folder-permissions' ); ?></li>
     56                <li><?php esc_html_e( 'This process cannot be undone. Make sure you have a backup of your site.', 'reset-file-and-folder-permissions' ); ?></li>
     57                <li><?php esc_html_e( 'Only run this tool if you understand the implications of changing file permissions.', 'reset-file-and-folder-permissions' ); ?></li>
     58            </ul>
     59        </div>
     60
     61        <!-- Main Content Layout -->
     62        <div class="resetfileperm-main-layout">
     63            <!-- Left Column - Plugin Functionality -->
     64            <div class="resetfileperm-left-column">
     65
     66        <!-- System Information -->
     67        <div class="resetfileperm-system-info">
     68            <h2><?php esc_html_e( 'System Information', 'reset-file-and-folder-permissions' ); ?></h2>
    10269            <table class="form-table">
    10370                <tr>
    104                     <th scope="row">
    105                         <label for="resetfileperm-directory"><?php esc_html_e( 'Target Directory', 'reset-file-and-folder-permissions' ); ?></label>
    106                     </th>
     71                    <th scope="row"><?php esc_html_e( 'WordPress Root', 'reset-file-and-folder-permissions' ); ?></th>
    10772                    <td>
    108                         <select id="resetfileperm-directory" name="directory" class="regular-text">
    109                             <option value="<?php echo esc_attr( $wp_root ); ?>"><?php esc_html_e( 'Entire WordPress Installation', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $wp_root ); ?>)</option>
    110                             <option value="<?php echo esc_attr( $wp_content ); ?>"><?php esc_html_e( 'WP Content Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $wp_content ); ?>)</option>
    111                             <option value="<?php echo esc_attr( $wp_plugins ); ?>"><?php esc_html_e( 'Plugins Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $wp_plugins ); ?>)</option>
    112                             <option value="<?php echo esc_attr( $wp_themes ); ?>"><?php esc_html_e( 'Themes Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $wp_themes ); ?>)</option>
    113                             <?php if ( $wp_uploads_dir ) : ?>
    114                             <option value="<?php echo esc_attr( $wp_uploads_dir ); ?>"><?php esc_html_e( 'Uploads Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $wp_uploads_dir ); ?>)</option>
    115                             <?php endif; ?>
    116                         </select>
    117                         <p class="description"><?php esc_html_e( 'Select which directory to process. Choose carefully as this operation affects all subdirectories.', 'reset-file-and-folder-permissions' ); ?></p>
     73                        <code><?php echo esc_html( $resetfileperm_wp_root ); ?></code>
     74                        <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $resetfileperm_wp_root ) ); ?>)</span>
    11875                    </td>
    11976                </tr>
    12077                <tr>
    121                     <th scope="row">
    122                         <label for="resetfileperm-batch-size"><?php esc_html_e( 'Batch Size', 'reset-file-and-folder-permissions' ); ?></label>
    123                     </th>
     78                    <th scope="row"><?php esc_html_e( 'WP Content Directory', 'reset-file-and-folder-permissions' ); ?></th>
    12479                    <td>
    125                         <select id="resetfileperm-batch-size" name="batch_size">
    126                             <option value="50">50 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
    127                             <option value="100" selected>100 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
    128                             <option value="200">200 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
    129                             <option value="500">500 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
    130                         </select>
    131                         <p class="description"><?php esc_html_e( 'Smaller batch sizes are safer for large directories but take longer. Larger batches are faster but may timeout.', 'reset-file-and-folder-permissions' ); ?></p>
     80                        <code><?php echo esc_html( $resetfileperm_wp_content ); ?></code>
     81                        <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $resetfileperm_wp_content ) ); ?>)</span>
     82                    </td>
     83                </tr>
     84                <tr>
     85                    <th scope="row"><?php esc_html_e( 'Plugins Directory', 'reset-file-and-folder-permissions' ); ?></th>
     86                    <td>
     87                        <code><?php echo esc_html( $resetfileperm_wp_plugins ); ?></code>
     88                        <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $resetfileperm_wp_plugins ) ); ?>)</span>
     89                    </td>
     90                </tr>
     91                <tr>
     92                    <th scope="row"><?php esc_html_e( 'Themes Directory', 'reset-file-and-folder-permissions' ); ?></th>
     93                    <td>
     94                        <code><?php echo esc_html( $resetfileperm_wp_themes ); ?></code>
     95                        <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $resetfileperm_wp_themes ) ); ?>)</span>
     96                    </td>
     97                </tr>
     98                <?php if ( $resetfileperm_wp_uploads_dir ) : ?>
     99                <tr>
     100                    <th scope="row"><?php esc_html_e( 'Uploads Directory', 'reset-file-and-folder-permissions' ); ?></th>
     101                    <td>
     102                        <code><?php echo esc_html( $resetfileperm_wp_uploads_dir ); ?></code>
     103                        <span class="resetfileperm-permission">(<?php echo esc_html( RESETFILEPERM_File_Permissions_Reset::get_file_permissions( $resetfileperm_wp_uploads_dir ) ); ?>)</span>
     104                    </td>
     105                </tr>
     106                <?php endif; ?>
     107                <tr>
     108                    <th scope="row"><?php esc_html_e( 'PHP chmod() Function', 'reset-file-and-folder-permissions' ); ?></th>
     109                    <td>
     110                        <?php if ( function_exists( 'chmod' ) ) : ?>
     111                            <span class="resetfileperm-status-ok"><?php esc_html_e( 'Available', 'reset-file-and-folder-permissions' ); ?></span>
     112                        <?php else : ?>
     113                            <span class="resetfileperm-status-error"><?php esc_html_e( 'Not Available', 'reset-file-and-folder-permissions' ); ?></span>
     114                        <?php endif; ?>
    132115                    </td>
    133116                </tr>
    134117            </table>
    135 
    136             <!-- Action Buttons -->
    137             <p class="submit">
    138                 <button type="button" id="resetfileperm-scan-btn" class="button button-secondary">
    139                     <span class="dashicons dashicons-search"></span>
    140                     <?php esc_html_e( 'Scan Directory', 'reset-file-and-folder-permissions' ); ?>
    141                 </button>
    142                 <button type="button" id="resetfileperm-reset-btn" class="button button-primary" disabled>
    143                     <span class="dashicons dashicons-admin-tools"></span>
    144                     <?php esc_html_e( 'Reset Permissions', 'reset-file-and-folder-permissions' ); ?>
    145                 </button>
    146             </p>
    147         </form>
    148     </div>
    149 
    150     <!-- Progress Section -->
    151     <div id="resetfileperm-progress-section" class="resetfileperm-progress-section" style="display: none;">
    152         <h2><?php esc_html_e( 'Progress', 'reset-file-and-folder-permissions' ); ?></h2>
    153         <div class="resetfileperm-progress-container">
    154             <div class="resetfileperm-progress-bar">
    155                 <div id="resetfileperm-progress-fill" class="resetfileperm-progress-fill" style="width: 0%;"></div>
    156             </div>
    157             <div id="resetfileperm-progress-text" class="resetfileperm-progress-text">0%</div>
    158         </div>
    159         <div id="resetfileperm-progress-details" class="resetfileperm-progress-details">
    160             <p id="resetfileperm-current-status"><?php esc_html_e( 'Ready to start...', 'reset-file-and-folder-permissions' ); ?></p>
    161             <div class="resetfileperm-stats">
    162                 <span><?php esc_html_e( 'Files processed:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-files-count">0</strong></span>
    163                 <span><?php esc_html_e( 'Directories processed:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-dirs-count">0</strong></span>
    164                 <span><?php esc_html_e( 'Errors:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-errors-count">0</strong></span>
    165             </div>
    166         </div>
    167     </div>
    168 
    169     <!-- Scan Results -->
    170     <div id="resetfileperm-scan-results" class="resetfileperm-scan-results" style="display: none;">
    171         <h2><?php esc_html_e( 'Scan Results', 'reset-file-and-folder-permissions' ); ?></h2>
    172         <div class="resetfileperm-scan-summary">
    173             <p><?php esc_html_e( 'Found:', 'reset-file-and-folder-permissions' ); ?>
    174                 <strong id="resetfileperm-scan-files">0</strong> <?php esc_html_e( 'files', 'reset-file-and-folder-permissions' ); ?>
    175                 <?php esc_html_e( 'and', 'reset-file-and-folder-permissions' ); ?>
    176                 <strong id="resetfileperm-scan-dirs">0</strong> <?php esc_html_e( 'directories', 'reset-file-and-folder-permissions' ); ?>
    177             </p>
    178         </div>
    179     </div>
    180 
    181     <!-- Error Log -->
    182     <div id="resetfileperm-error-log" class="resetfileperm-error-log" style="display: none;">
    183         <h2><?php esc_html_e( 'Error Log', 'reset-file-and-folder-permissions' ); ?></h2>
    184         <div id="resetfileperm-error-messages" class="resetfileperm-error-messages"></div>
    185     </div>
    186 
    187     <!-- Results Section -->
    188     <div id="resetfileperm-results-section" class="resetfileperm-results-section" style="display: none;">
    189         <h2><?php esc_html_e( 'Operation Complete', 'reset-file-and-folder-permissions' ); ?></h2>
    190         <div class="notice notice-success">
    191             <p><strong><?php esc_html_e( 'Permissions reset completed!', 'reset-file-and-folder-permissions' ); ?></strong></p>
    192         </div>
    193         <div id="resetfileperm-final-results" class="resetfileperm-final-results"></div>
    194     </div>
    195 
    196         </div><!-- End Left Column -->
    197 
    198         <!-- Right Column - Developer Profile -->
    199         <div class="resetfileperm-right-column">
    200             <div class="resetfileperm-developer-profile">
    201                 <div class="resetfileperm-profile-content">
    202                     <div class="resetfileperm-profile-card">
    203                         <div class="resetfileperm-profile-header">
    204                             <?php
    205                                         $logo_path = RESETFILEPERM_PLUGIN_DIR . 'assets/nandann-logo.png';
    206             $logo_url = RESETFILEPERM_PLUGIN_URL . 'assets/nandann-logo.png';
    207                             if ( file_exists( $logo_path ) && function_exists( 'getimagesize' ) && getimagesize( $logo_path ) !== false ) : ?>
    208                                 <div class="resetfileperm-logo-container">
    209                                     <img src="<?php echo esc_url( $logo_url ); ?>"
    210                                          alt="<?php esc_attr_e( 'Nandann Creative Agency Logo', 'reset-file-and-folder-permissions' ); ?>"
    211                                          class="resetfileperm-logo"
    212                                          width="120"
    213                                          height="auto" />
     118        </div>
     119
     120        <!-- Directory Selection -->
     121        <div class="resetfileperm-directory-selection">
     122            <h2><?php esc_html_e( 'Directory Selection', 'reset-file-and-folder-permissions' ); ?></h2>
     123            <form id="resetfileperm-main-form">
     124                <table class="form-table">
     125                    <tr>
     126                        <th scope="row">
     127                            <label for="resetfileperm-directory"><?php esc_html_e( 'Target Directory', 'reset-file-and-folder-permissions' ); ?></label>
     128                        </th>
     129                        <td>
     130                            <select id="resetfileperm-directory" name="directory" class="regular-text">
     131                                <option value="<?php echo esc_attr( $resetfileperm_wp_root ); ?>"><?php esc_html_e( 'Entire WordPress Installation', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_root ); ?>)</option>
     132                                <option value="<?php echo esc_attr( $resetfileperm_wp_content ); ?>"><?php esc_html_e( 'WP Content Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_content ); ?>)</option>
     133                                <option value="<?php echo esc_attr( $resetfileperm_wp_plugins ); ?>"><?php esc_html_e( 'Plugins Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_plugins ); ?>)</option>
     134                                <option value="<?php echo esc_attr( $resetfileperm_wp_themes ); ?>"><?php esc_html_e( 'Themes Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_themes ); ?>)</option>
     135                                <?php if ( $resetfileperm_wp_uploads_dir ) : ?>
     136                                <option value="<?php echo esc_attr( $resetfileperm_wp_uploads_dir ); ?>"><?php esc_html_e( 'Uploads Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_uploads_dir ); ?>)</option>
     137                                <?php endif; ?>
     138                            </select>
     139                            <p class="description"><?php esc_html_e( 'Select which directory to process. Choose carefully as this operation affects all subdirectories.', 'reset-file-and-folder-permissions' ); ?></p>
     140                        </td>
     141                    </tr>
     142                    <tr>
     143                        <th scope="row">
     144                            <label for="resetfileperm-batch-size"><?php esc_html_e( 'Batch Size', 'reset-file-and-folder-permissions' ); ?></label>
     145                        </th>
     146                        <td>
     147                            <select id="resetfileperm-batch-size" name="batch_size">
     148                                <option value="50">50 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     149                                <option value="100" selected>100 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     150                                <option value="200">200 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     151                                <option value="500">500 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     152                            </select>
     153                            <p class="description"><?php esc_html_e( 'Smaller batch sizes are safer for large directories but take longer. Larger batches are faster but may timeout.', 'reset-file-and-folder-permissions' ); ?></p>
     154                        </td>
     155                    </tr>
     156                </table>
     157
     158                <!-- Action Buttons -->
     159                <p class="submit">
     160                    <button type="button" id="resetfileperm-scan-btn" class="button button-secondary">
     161                        <span class="dashicons dashicons-search"></span>
     162                        <?php esc_html_e( 'Scan Directory', 'reset-file-and-folder-permissions' ); ?>
     163                    </button>
     164                    <button type="button" id="resetfileperm-reset-btn" class="button button-primary" disabled>
     165                        <span class="dashicons dashicons-admin-tools"></span>
     166                        <?php esc_html_e( 'Reset Permissions', 'reset-file-and-folder-permissions' ); ?>
     167                    </button>
     168                </p>
     169            </form>
     170        </div>
     171
     172        <!-- Scan Results -->
     173        <div id="resetfileperm-scan-results" class="resetfileperm-scan-results" style="display: none;">
     174            <h2><?php esc_html_e( 'Scan Results', 'reset-file-and-folder-permissions' ); ?></h2>
     175            <div class="resetfileperm-scan-summary">
     176                <p><?php esc_html_e( 'Found:', 'reset-file-and-folder-permissions' ); ?>
     177                    <strong id="resetfileperm-scan-files">0</strong> <?php esc_html_e( 'files', 'reset-file-and-folder-permissions' ); ?>
     178                    <?php esc_html_e( 'and', 'reset-file-and-folder-permissions' ); ?>
     179                    <strong id="resetfileperm-scan-dirs">0</strong> <?php esc_html_e( 'directories', 'reset-file-and-folder-permissions' ); ?>
     180                </p>
     181            </div>
     182        </div>
     183
     184        <!-- Progress Section -->
     185        <div id="resetfileperm-progress-section" class="resetfileperm-progress-section" style="display: none;">
     186            <h2><?php esc_html_e( 'Progress', 'reset-file-and-folder-permissions' ); ?></h2>
     187            <div class="resetfileperm-progress-container">
     188                <div class="resetfileperm-progress-bar">
     189                    <div id="resetfileperm-progress-fill" class="resetfileperm-progress-fill" style="width: 0%;"></div>
     190                </div>
     191                <div id="resetfileperm-progress-text" class="resetfileperm-progress-text">0%</div>
     192            </div>
     193            <div id="resetfileperm-progress-details" class="resetfileperm-progress-details">
     194                <p id="resetfileperm-current-status"><?php esc_html_e( 'Ready to start...', 'reset-file-and-folder-permissions' ); ?></p>
     195                <div class="resetfileperm-stats">
     196                    <span><?php esc_html_e( 'Files processed:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-files-count">0</strong></span>
     197                    <span><?php esc_html_e( 'Directories processed:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-dirs-count">0</strong></span>
     198                    <span><?php esc_html_e( 'Errors:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-errors-count">0</strong></span>
     199                </div>
     200            </div>
     201        </div>
     202
     203        <!-- Error Log -->
     204        <div id="resetfileperm-error-log" class="resetfileperm-error-log" style="display: none;">
     205            <h2><?php esc_html_e( 'Error Log', 'reset-file-and-folder-permissions' ); ?></h2>
     206            <div id="resetfileperm-error-messages" class="resetfileperm-error-messages"></div>
     207        </div>
     208
     209        <!-- Results Section -->
     210        <div id="resetfileperm-results-section" class="resetfileperm-results-section" style="display: none;">
     211            <h2><?php esc_html_e( 'Operation Complete', 'reset-file-and-folder-permissions' ); ?></h2>
     212            <div class="notice notice-success">
     213                <p><strong><?php esc_html_e( 'Permissions reset completed!', 'reset-file-and-folder-permissions' ); ?></strong></p>
     214            </div>
     215            <div id="resetfileperm-final-results" class="resetfileperm-final-results"></div>
     216        </div>
     217
     218            </div><!-- End Left Column -->
     219
     220            <!-- Right Column - Developer Profile -->
     221            <div class="resetfileperm-right-column">
     222                <div class="resetfileperm-developer-profile">
     223                    <div class="resetfileperm-profile-content">
     224                        <div class="resetfileperm-profile-card">
     225                            <div class="resetfileperm-profile-header">
     226                                <?php
     227                                            $resetfileperm_logo_path = RESETFILEPERM_PLUGIN_DIR . 'assets/nandann-logo.png';
     228                $resetfileperm_logo_url = RESETFILEPERM_PLUGIN_URL . 'assets/nandann-logo.png';
     229                                if ( file_exists( $resetfileperm_logo_path ) && function_exists( 'getimagesize' ) && getimagesize( $resetfileperm_logo_path ) !== false ) : ?>
     230                                    <div class="resetfileperm-logo-container">
     231                                        <img src="<?php echo esc_url( $resetfileperm_logo_url ); ?>"
     232                                             alt="<?php esc_attr_e( 'Nandann Creative Agency Logo', 'reset-file-and-folder-permissions' ); ?>"
     233                                             class="resetfileperm-logo"
     234                                             width="120"
     235                                             height="auto" />
     236                                    </div>
     237                                <?php else : ?>
     238                                    <div class="resetfileperm-logo-container">
     239                                        <h2 class="resetfileperm-logo-text"><?php esc_html_e( 'Nandann', 'reset-file-and-folder-permissions' ); ?></h2>
     240                                    </div>
     241                                <?php endif; ?>
     242                                <p class="resetfileperm-agency-text"><?php esc_html_e( 'Creative Agency', 'reset-file-and-folder-permissions' ); ?></p>
     243                                <h3><?php esc_html_e( 'Professional WordPress Development & Troubleshooting', 'reset-file-and-folder-permissions' ); ?></h3>
     244                                <p class="resetfileperm-tagline"><?php esc_html_e( 'Expert solutions for complex WordPress challenges', 'reset-file-and-folder-permissions' ); ?></p>
     245                            </div>
     246                           
     247                            <div class="resetfileperm-profile-cta">
     248                                <p class="resetfileperm-cta-text"><?php esc_html_e( 'Facing WordPress challenges? Get professional help from an experienced developer who understands the complexities of WordPress development and can provide reliable, efficient solutions.', 'reset-file-and-folder-permissions' ); ?></p>
     249                               
     250                                <div class="resetfileperm-contact-buttons">
     251                                    <a href="mailto:[email protected]?subject=WordPress Development Help Request" class="button button-primary resetfileperm-contact-btn">
     252                                        <span class="dashicons dashicons-email-alt"></span>
     253                                        <span class="resetfileperm-btn-text">
     254                                            <span class="resetfileperm-btn-line1"><?php esc_html_e( 'Get Expert Help', 'reset-file-and-folder-permissions' ); ?></span>
     255                                            <span class="resetfileperm-btn-line2">[email protected]</span>
     256                                        </span>
     257                                    </a>
     258                                    <a href="https://nandann.com" target="_blank" class="button button-secondary resetfileperm-website-btn">
     259                                        <span class="dashicons dashicons-external"></span>
     260                                        <?php esc_html_e( 'Visit nandann.com', 'reset-file-and-folder-permissions' ); ?>
     261                                    </a>
    214262                                </div>
    215                             <?php else : ?>
    216                                 <div class="resetfileperm-logo-container">
    217                                     <h2 class="resetfileperm-logo-text"><?php esc_html_e( 'Nandann', 'reset-file-and-folder-permissions' ); ?></h2>
    218                                 </div>
    219                             <?php endif; ?>
    220                             <p class="resetfileperm-agency-text"><?php esc_html_e( 'Creative Agency', 'reset-file-and-folder-permissions' ); ?></p>
    221                             <h3><?php esc_html_e( 'Professional WordPress Development & Troubleshooting', 'reset-file-and-folder-permissions' ); ?></h3>
    222                             <p class="resetfileperm-tagline"><?php esc_html_e( 'Expert solutions for complex WordPress challenges', 'reset-file-and-folder-permissions' ); ?></p>
    223                         </div>
    224                        
    225                         <div class="resetfileperm-profile-cta">
    226                             <p class="resetfileperm-cta-text"><?php esc_html_e( 'Facing WordPress challenges? Get professional help from an experienced developer who understands the complexities of WordPress development and can provide reliable, efficient solutions.', 'reset-file-and-folder-permissions' ); ?></p>
     263                            </div>
    227264                           
    228                             <div class="resetfileperm-contact-buttons">
    229                                 <a href="mailto:[email protected]?subject=WordPress Development Help Request" class="button button-primary resetfileperm-contact-btn">
    230                                     <span class="dashicons dashicons-email-alt"></span>
    231                                     <span class="resetfileperm-btn-text">
    232                                         <span class="resetfileperm-btn-line1"><?php esc_html_e( 'Get Expert Help', 'reset-file-and-folder-permissions' ); ?></span>
    233                                         <span class="resetfileperm-btn-line2">[email protected]</span>
    234                                     </span>
    235                                 </a>
    236                                 <a href="https://nandann.com" target="_blank" class="button button-secondary resetfileperm-website-btn">
    237                                     <span class="dashicons dashicons-external"></span>
    238                                     <?php esc_html_e( 'Visit nandann.com', 'reset-file-and-folder-permissions' ); ?>
    239                                 </a>
    240                             </div>
    241                         </div>
    242                        
    243                         <div class="resetfileperm-profile-services">
    244                             <div class="resetfileperm-service-grid">
    245                                 <div class="resetfileperm-service-item">
    246                                     <span class="dashicons dashicons-admin-tools"></span>
    247                                     <h4><?php esc_html_e( 'WordPress Troubleshooting', 'reset-file-and-folder-permissions' ); ?></h4>
    248                                     <p><?php esc_html_e( 'Expert diagnosis and resolution of complex WordPress issues, performance optimization, and security hardening.', 'reset-file-and-folder-permissions' ); ?></p>
    249                                 </div>
    250                                
    251                                 <div class="resetfileperm-service-item">
    252                                     <span class="dashicons dashicons-desktop"></span>
    253                                     <h4><?php esc_html_e( 'Custom Development', 'reset-file-and-folder-permissions' ); ?></h4>
    254                                     <p><?php esc_html_e( 'Bespoke WordPress plugins, themes, and custom functionality tailored to your specific business needs.', 'reset-file-and-folder-permissions' ); ?></p>
    255                                 </div>
    256                                
    257                                 <div class="resetfileperm-service-item">
    258                                     <span class="dashicons dashicons-migrate"></span>
    259                                     <h4><?php esc_html_e( 'Site Migration & Hosting', 'reset-file-and-folder-permissions' ); ?></h4>
    260                                     <p><?php esc_html_e( 'Seamless website migrations, hosting optimization, and server configuration for peak performance.', 'reset-file-and-folder-permissions' ); ?></p>
    261                                 </div>
    262                                
    263                                 <div class="resetfileperm-service-item">
    264                                     <span class="dashicons dashicons-shield"></span>
    265                                     <h4><?php esc_html_e( 'Security & Maintenance', 'reset-file-and-folder-permissions' ); ?></h4>
    266                                     <p><?php esc_html_e( 'Comprehensive security audits, malware removal, and ongoing maintenance to keep your site secure.', 'reset-file-and-folder-permissions' ); ?></p>
     265                            <div class="resetfileperm-profile-services">
     266                                <div class="resetfileperm-service-grid">
     267                                    <div class="resetfileperm-service-item">
     268                                        <span class="dashicons dashicons-admin-tools"></span>
     269                                        <h4><?php esc_html_e( 'WordPress Troubleshooting', 'reset-file-and-folder-permissions' ); ?></h4>
     270                                        <p><?php esc_html_e( 'Expert diagnosis and resolution of complex WordPress issues, performance optimization, and security hardening.', 'reset-file-and-folder-permissions' ); ?></p>
     271                                    </div>
     272                                   
     273                                    <div class="resetfileperm-service-item">
     274                                        <span class="dashicons dashicons-desktop"></span>
     275                                        <h4><?php esc_html_e( 'Custom Development', 'reset-file-and-folder-permissions' ); ?></h4>
     276                                        <p><?php esc_html_e( 'Bespoke WordPress plugins, themes, and custom functionality tailored to your specific business needs.', 'reset-file-and-folder-permissions' ); ?></p>
     277                                    </div>
     278                                   
     279                                    <div class="resetfileperm-service-item">
     280                                        <span class="dashicons dashicons-migrate"></span>
     281                                        <h4><?php esc_html_e( 'Site Migration & Hosting', 'reset-file-and-folder-permissions' ); ?></h4>
     282                                        <p><?php esc_html_e( 'Seamless website migrations, hosting optimization, and server configuration for peak performance.', 'reset-file-and-folder-permissions' ); ?></p>
     283                                    </div>
     284                                   
     285                                    <div class="resetfileperm-service-item">
     286                                        <span class="dashicons dashicons-shield"></span>
     287                                        <h4><?php esc_html_e( 'Security & Maintenance', 'reset-file-and-folder-permissions' ); ?></h4>
     288                                        <p><?php esc_html_e( 'Comprehensive security audits, malware removal, and ongoing maintenance to keep your site secure.', 'reset-file-and-folder-permissions' ); ?></p>
     289                                    </div>
    267290                                </div>
    268291                            </div>
     
    270293                    </div>
    271294                </div>
    272             </div>
    273         </div><!-- End Right Column -->
    274 
    275     </div><!-- End Main Layout -->
    276 
    277     <!-- Help Section -->
    278     <div class="resetfileperm-help-section">
    279         <h2><?php esc_html_e( 'About File Permissions', 'reset-file-and-folder-permissions' ); ?></h2>
    280         <div class="resetfileperm-help-content">
    281             <h3><?php esc_html_e( 'Standard WordPress Permissions', 'reset-file-and-folder-permissions' ); ?></h3>
    282             <ul>
    283                 <li><strong>0644</strong> - <?php esc_html_e( 'Files: Owner can read/write, group and others can read only', 'reset-file-and-folder-permissions' ); ?></li>
    284                 <li><strong>0755</strong> - <?php esc_html_e( 'Directories: Owner can read/write/execute, group and others can read/execute', 'reset-file-and-folder-permissions' ); ?></li>
    285             </ul>
    286            
    287             <h3><?php esc_html_e( 'When to Use This Tool', 'reset-file-and-folder-permissions' ); ?></h3>
    288             <ul>
    289                 <li><?php esc_html_e( 'After migrating your WordPress site to a new server', 'reset-file-and-folder-permissions' ); ?></li>
    290                 <li><?php esc_html_e( 'When files have incorrect permissions causing functionality issues', 'reset-file-and-folder-permissions' ); ?></li>
    291                 <li><?php esc_html_e( 'For security hardening when permissions are too permissive', 'reset-file-and-folder-permissions' ); ?></li>
    292                 <li><?php esc_html_e( 'When troubleshooting file access problems', 'reset-file-and-folder-permissions' ); ?></li>
    293             </ul>
    294 
    295             <h3><?php esc_html_e( 'Important Notes', 'reset-file-and-folder-permissions' ); ?></h3>
    296             <ul>
    297                 <li><?php esc_html_e( 'Some files (like wp-config.php) may need special permissions', 'reset-file-and-folder-permissions' ); ?></li>
    298                 <li><?php esc_html_e( 'Always test your site functionality after running this tool', 'reset-file-and-folder-permissions' ); ?></li>
    299                 <li><?php esc_html_e( 'Make sure your web server user has appropriate access', 'reset-file-and-folder-permissions' ); ?></li>
    300             </ul>
    301         </div>
    302     </div>
    303 </div>
     295            </div><!-- End Right Column -->
     296
     297        </div><!-- End Main Layout -->
     298
     299        <!-- Help Section -->
     300        <div class="resetfileperm-help-section">
     301            <h2><?php esc_html_e( 'About File Permissions', 'reset-file-and-folder-permissions' ); ?></h2>
     302            <div class="resetfileperm-help-content">
     303                <h3><?php esc_html_e( 'Standard WordPress Permissions', 'reset-file-and-folder-permissions' ); ?></h3>
     304                <ul>
     305                    <li><strong>0644</strong> - <?php esc_html_e( 'Files: Owner can read/write, group and others can read only', 'reset-file-and-folder-permissions' ); ?></li>
     306                    <li><strong>0755</strong> - <?php esc_html_e( 'Directories: Owner can read/write/execute, group and others can read/execute', 'reset-file-and-folder-permissions' ); ?></li>
     307                </ul>
     308               
     309                <h3><?php esc_html_e( 'When to Use This Tool', 'reset-file-and-folder-permissions' ); ?></h3>
     310                <ul>
     311                    <li><?php esc_html_e( 'After migrating your WordPress site to a new server', 'reset-file-and-folder-permissions' ); ?></li>
     312                    <li><?php esc_html_e( 'When files have incorrect permissions causing functionality issues', 'reset-file-and-folder-permissions' ); ?></li>
     313                    <li><?php esc_html_e( 'For security hardening when permissions are too permissive', 'reset-file-and-folder-permissions' ); ?></li>
     314                    <li><?php esc_html_e( 'When troubleshooting file access problems', 'reset-file-and-folder-permissions' ); ?></li>
     315                </ul>
     316
     317                <h3><?php esc_html_e( 'Important Notes', 'reset-file-and-folder-permissions' ); ?></h3>
     318                <ul>
     319                    <li><?php esc_html_e( 'Some files (like wp-config.php) may need special permissions', 'reset-file-and-folder-permissions' ); ?></li>
     320                    <li><?php esc_html_e( 'Always test your site functionality after running this tool', 'reset-file-and-folder-permissions' ); ?></li>
     321                    <li><?php esc_html_e( 'Make sure your web server user has appropriate access', 'reset-file-and-folder-permissions' ); ?></li>
     322                </ul>
     323            </div>
     324        </div>
     325
     326    <?php else : ?>
     327        <!-- OWNERSHIP TAB -->
     328       
     329        <?php if ( ! $resetfileperm_ownership_available ) : ?>
     330            <!-- Compatibility Warning -->
     331            <div class="notice notice-error">
     332                <h3><?php esc_html_e( 'Ownership Functions Not Available', 'reset-file-and-folder-permissions' ); ?></h3>
     333                <p><?php esc_html_e( 'The file and folder ownership reset feature requires PHP functions that are not available on your server:', 'reset-file-and-folder-permissions' ); ?></p>
     334                <ul>
     335                    <li><code>chown()</code> - <?php esc_html_e( 'Change file owner', 'reset-file-and-folder-permissions' ); ?></li>
     336                    <li><code>chgrp()</code> - <?php esc_html_e( 'Change file group', 'reset-file-and-folder-permissions' ); ?></li>
     337                    <li><code>posix_getpwnam()</code> - <?php esc_html_e( 'Get user information', 'reset-file-and-folder-permissions' ); ?></li>
     338                    <li><code>posix_getgrnam()</code> - <?php esc_html_e( 'Get group information', 'reset-file-and-folder-permissions' ); ?></li>
     339                </ul>
     340                <p><strong><?php esc_html_e( 'Why are these functions unavailable?', 'reset-file-and-folder-permissions' ); ?></strong></p>
     341                <p><?php esc_html_e( 'These functions are often disabled on shared hosting environments for security reasons. They require elevated server privileges and are typically only available on VPS, dedicated servers, or hosting environments where you have more control.', 'reset-file-and-folder-permissions' ); ?></p>
     342                <p><strong><?php esc_html_e( 'What can you do?', 'reset-file-and-folder-permissions' ); ?></strong></p>
     343                <ul>
     344                    <li><?php esc_html_e( 'Contact your hosting provider to enable these functions (if possible)', 'reset-file-and-folder-permissions' ); ?></li>
     345                    <li><?php esc_html_e( 'Use SSH/terminal access to change ownership manually', 'reset-file-and-folder-permissions' ); ?></li>
     346                    <li><?php esc_html_e( 'Consider upgrading to a VPS or dedicated server for more control', 'reset-file-and-folder-permissions' ); ?></li>
     347                </ul>
     348                <p><?php esc_html_e( 'You can still use the "Reset Permissions" tab to fix file permission issues.', 'reset-file-and-folder-permissions' ); ?></p>
     349            </div>
     350        <?php else : ?>
     351            <!-- Security Warning -->
     352            <div class="notice notice-warning">
     353                <p><strong><?php esc_html_e( 'Warning:', 'reset-file-and-folder-permissions' ); ?></strong></p>
     354                <ul>
     355                    <li><?php esc_html_e( 'This action will change the ownership of ALL files and directories to the specified user and group.', 'reset-file-and-folder-permissions' ); ?></li>
     356                    <li><?php esc_html_e( 'Incorrect ownership can break your WordPress site and prevent file access.', 'reset-file-and-folder-permissions' ); ?></li>
     357                    <li><?php esc_html_e( 'This process cannot be undone. Make sure you have a backup of your site.', 'reset-file-and-folder-permissions' ); ?></li>
     358                    <li><?php esc_html_e( 'Only run this tool if you understand the implications of changing file ownership.', 'reset-file-and-folder-permissions' ); ?></li>
     359                </ul>
     360            </div>
     361
     362            <!-- Main Content Layout -->
     363            <div class="resetfileperm-main-layout">
     364                <!-- Left Column - Plugin Functionality -->
     365                <div class="resetfileperm-left-column">
     366
     367            <!-- Server Information -->
     368            <div class="resetfileperm-system-info">
     369                <h2><?php esc_html_e( 'Server Information', 'reset-file-and-folder-permissions' ); ?></h2>
     370                <table class="form-table">
     371                    <tr>
     372                        <th scope="row"><?php esc_html_e( 'PHP chown() Function', 'reset-file-and-folder-permissions' ); ?></th>
     373                        <td>
     374                            <?php if ( function_exists( 'chown' ) ) : ?>
     375                                <span class="resetfileperm-status-ok"><?php esc_html_e( 'Available', 'reset-file-and-folder-permissions' ); ?></span>
     376                            <?php else : ?>
     377                                <span class="resetfileperm-status-error"><?php esc_html_e( 'Not Available', 'reset-file-and-folder-permissions' ); ?></span>
     378                            <?php endif; ?>
     379                        </td>
     380                    </tr>
     381                    <tr>
     382                        <th scope="row"><?php esc_html_e( 'PHP chgrp() Function', 'reset-file-and-folder-permissions' ); ?></th>
     383                        <td>
     384                            <?php if ( function_exists( 'chgrp' ) ) : ?>
     385                                <span class="resetfileperm-status-ok"><?php esc_html_e( 'Available', 'reset-file-and-folder-permissions' ); ?></span>
     386                            <?php else : ?>
     387                                <span class="resetfileperm-status-error"><?php esc_html_e( 'Not Available', 'reset-file-and-folder-permissions' ); ?></span>
     388                            <?php endif; ?>
     389                        </td>
     390                    </tr>
     391                    <tr>
     392                        <th scope="row"><?php esc_html_e( 'PHP POSIX Functions', 'reset-file-and-folder-permissions' ); ?></th>
     393                        <td>
     394                            <?php if ( function_exists( 'posix_getpwnam' ) && function_exists( 'posix_getgrnam' ) ) : ?>
     395                                <span class="resetfileperm-status-ok"><?php esc_html_e( 'Available', 'reset-file-and-folder-permissions' ); ?></span>
     396                            <?php else : ?>
     397                                <span class="resetfileperm-status-error"><?php esc_html_e( 'Not Available', 'reset-file-and-folder-permissions' ); ?></span>
     398                            <?php endif; ?>
     399                        </td>
     400                    </tr>
     401                </table>
     402                <div id="resetfileperm-ownership-server-info">
     403                    <p><?php esc_html_e( 'Loading server information...', 'reset-file-and-folder-permissions' ); ?></p>
     404                </div>
     405            </div>
     406
     407            <!-- Ownership Selection -->
     408            <div class="resetfileperm-directory-selection">
     409                <h2><?php esc_html_e( 'Ownership Configuration', 'reset-file-and-folder-permissions' ); ?></h2>
     410                <form id="resetfileperm-ownership-form">
     411                    <table class="form-table">
     412                        <tr>
     413                            <th scope="row">
     414                                <label for="resetfileperm-owner"><?php esc_html_e( 'File Owner', 'reset-file-and-folder-permissions' ); ?></label>
     415                            </th>
     416                            <td>
     417                                <select id="resetfileperm-owner" name="owner" class="regular-text" required>
     418                                    <option value=""><?php esc_html_e( 'Select owner...', 'reset-file-and-folder-permissions' ); ?></option>
     419                                </select>
     420                                <p class="description"><?php esc_html_e( 'Select the user that should own the files. The recommended value is your web server user.', 'reset-file-and-folder-permissions' ); ?></p>
     421                            </td>
     422                        </tr>
     423                        <tr>
     424                            <th scope="row">
     425                                <label for="resetfileperm-group"><?php esc_html_e( 'File Group', 'reset-file-and-folder-permissions' ); ?></label>
     426                            </th>
     427                            <td>
     428                                <select id="resetfileperm-group" name="group" class="regular-text" required>
     429                                    <option value=""><?php esc_html_e( 'Select group...', 'reset-file-and-folder-permissions' ); ?></option>
     430                                </select>
     431                                <p class="description"><?php esc_html_e( 'Select the group that should own the files. The recommended value is your web server group.', 'reset-file-and-folder-permissions' ); ?></p>
     432                            </td>
     433                        </tr>
     434                        <tr>
     435                            <th scope="row">
     436                                <label for="resetfileperm-ownership-directory"><?php esc_html_e( 'Target Directory', 'reset-file-and-folder-permissions' ); ?></label>
     437                            </th>
     438                            <td>
     439                                <select id="resetfileperm-ownership-directory" name="directory" class="regular-text">
     440                                    <option value="<?php echo esc_attr( $resetfileperm_wp_root ); ?>"><?php esc_html_e( 'Entire WordPress Installation', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_root ); ?>)</option>
     441                                    <option value="<?php echo esc_attr( $resetfileperm_wp_content ); ?>"><?php esc_html_e( 'WP Content Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_content ); ?>)</option>
     442                                    <option value="<?php echo esc_attr( $resetfileperm_wp_plugins ); ?>"><?php esc_html_e( 'Plugins Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_plugins ); ?>)</option>
     443                                    <option value="<?php echo esc_attr( $resetfileperm_wp_themes ); ?>"><?php esc_html_e( 'Themes Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_themes ); ?>)</option>
     444                                    <?php if ( $resetfileperm_wp_uploads_dir ) : ?>
     445                                    <option value="<?php echo esc_attr( $resetfileperm_wp_uploads_dir ); ?>"><?php esc_html_e( 'Uploads Directory Only', 'reset-file-and-folder-permissions' ); ?> (<?php echo esc_html( $resetfileperm_wp_uploads_dir ); ?>)</option>
     446                                    <?php endif; ?>
     447                                </select>
     448                                <p class="description"><?php esc_html_e( 'Select which directory to process. Choose carefully as this operation affects all subdirectories.', 'reset-file-and-folder-permissions' ); ?></p>
     449                            </td>
     450                        </tr>
     451                        <tr>
     452                            <th scope="row">
     453                                <label for="resetfileperm-ownership-batch-size"><?php esc_html_e( 'Batch Size', 'reset-file-and-folder-permissions' ); ?></label>
     454                            </th>
     455                            <td>
     456                                <select id="resetfileperm-ownership-batch-size" name="batch_size">
     457                                    <option value="50">50 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     458                                    <option value="100" selected>100 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     459                                    <option value="200">200 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     460                                    <option value="500">500 <?php esc_html_e( 'items per batch', 'reset-file-and-folder-permissions' ); ?></option>
     461                                </select>
     462                                <p class="description"><?php esc_html_e( 'Smaller batch sizes are safer for large directories but take longer. Larger batches are faster but may timeout.', 'reset-file-and-folder-permissions' ); ?></p>
     463                            </td>
     464                        </tr>
     465                    </table>
     466
     467                    <!-- Action Buttons -->
     468                    <p class="submit">
     469                        <button type="button" id="resetfileperm-ownership-scan-btn" class="button button-secondary">
     470                            <span class="dashicons dashicons-search"></span>
     471                            <?php esc_html_e( 'Scan Directory', 'reset-file-and-folder-permissions' ); ?>
     472                        </button>
     473                        <button type="button" id="resetfileperm-ownership-reset-btn" class="button button-primary" disabled>
     474                            <span class="dashicons dashicons-admin-tools"></span>
     475                            <?php esc_html_e( 'Reset Ownership', 'reset-file-and-folder-permissions' ); ?>
     476                        </button>
     477                    </p>
     478                </form>
     479            </div>
     480
     481            <!-- Scan Results -->
     482            <div id="resetfileperm-ownership-scan-results" class="resetfileperm-scan-results" style="display: none;">
     483                <h2><?php esc_html_e( 'Scan Results', 'reset-file-and-folder-permissions' ); ?></h2>
     484                <div class="resetfileperm-scan-summary">
     485                    <p><?php esc_html_e( 'Found:', 'reset-file-and-folder-permissions' ); ?>
     486                        <strong id="resetfileperm-ownership-scan-files">0</strong> <?php esc_html_e( 'files', 'reset-file-and-folder-permissions' ); ?>
     487                        <?php esc_html_e( 'and', 'reset-file-and-folder-permissions' ); ?>
     488                        <strong id="resetfileperm-ownership-scan-dirs">0</strong> <?php esc_html_e( 'directories', 'reset-file-and-folder-permissions' ); ?>
     489                    </p>
     490                </div>
     491            </div>
     492
     493            <!-- Progress Section -->
     494            <div id="resetfileperm-ownership-progress-section" class="resetfileperm-progress-section" style="display: none;">
     495                <h2><?php esc_html_e( 'Progress', 'reset-file-and-folder-permissions' ); ?></h2>
     496                <div class="resetfileperm-progress-container">
     497                    <div class="resetfileperm-progress-bar">
     498                        <div id="resetfileperm-ownership-progress-fill" class="resetfileperm-progress-fill" style="width: 0%;"></div>
     499                    </div>
     500                    <div id="resetfileperm-ownership-progress-text" class="resetfileperm-progress-text">0%</div>
     501                </div>
     502                <div id="resetfileperm-ownership-progress-details" class="resetfileperm-progress-details">
     503                    <p id="resetfileperm-ownership-current-status"><?php esc_html_e( 'Ready to start...', 'reset-file-and-folder-permissions' ); ?></p>
     504                    <div class="resetfileperm-stats">
     505                        <span><?php esc_html_e( 'Files processed:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-ownership-files-count">0</strong></span>
     506                        <span><?php esc_html_e( 'Directories processed:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-ownership-dirs-count">0</strong></span>
     507                        <span><?php esc_html_e( 'Errors:', 'reset-file-and-folder-permissions' ); ?> <strong id="resetfileperm-ownership-errors-count">0</strong></span>
     508                    </div>
     509                </div>
     510            </div>
     511
     512            <!-- Error Log -->
     513            <div id="resetfileperm-ownership-error-log" class="resetfileperm-error-log" style="display: none;">
     514                <h2><?php esc_html_e( 'Error Log', 'reset-file-and-folder-permissions' ); ?></h2>
     515                <div id="resetfileperm-ownership-error-messages" class="resetfileperm-error-messages"></div>
     516            </div>
     517
     518            <!-- Results Section -->
     519            <div id="resetfileperm-ownership-results-section" class="resetfileperm-results-section" style="display: none;">
     520                <h2><?php esc_html_e( 'Operation Complete', 'reset-file-and-folder-permissions' ); ?></h2>
     521                <div class="notice notice-success">
     522                    <p><strong><?php esc_html_e( 'Ownership reset completed!', 'reset-file-and-folder-permissions' ); ?></strong></p>
     523                </div>
     524                <div id="resetfileperm-ownership-final-results" class="resetfileperm-final-results"></div>
     525            </div>
     526
     527                </div><!-- End Left Column -->
     528
     529                <!-- Right Column - Developer Profile (same as permissions tab) -->
     530                <div class="resetfileperm-right-column">
     531                    <div class="resetfileperm-developer-profile">
     532                    <div class="resetfileperm-profile-content">
     533                        <div class="resetfileperm-profile-card">
     534                            <div class="resetfileperm-profile-header">
     535                                <?php
     536                                            $resetfileperm_logo_path_2 = RESETFILEPERM_PLUGIN_DIR . 'assets/nandann-logo.png';
     537                $resetfileperm_logo_url_2 = RESETFILEPERM_PLUGIN_URL . 'assets/nandann-logo.png';
     538                                if ( file_exists( $resetfileperm_logo_path_2 ) && function_exists( 'getimagesize' ) && getimagesize( $resetfileperm_logo_path_2 ) !== false ) : ?>
     539                                    <div class="resetfileperm-logo-container">
     540                                        <img src="<?php echo esc_url( $resetfileperm_logo_url_2 ); ?>"
     541                                                 alt="<?php esc_attr_e( 'Nandann Creative Agency Logo', 'reset-file-and-folder-permissions' ); ?>"
     542                                                 class="resetfileperm-logo"
     543                                                 width="120"
     544                                                 height="auto" />
     545                                        </div>
     546                                    <?php else : ?>
     547                                        <div class="resetfileperm-logo-container">
     548                                            <h2 class="resetfileperm-logo-text"><?php esc_html_e( 'Nandann', 'reset-file-and-folder-permissions' ); ?></h2>
     549                                        </div>
     550                                    <?php endif; ?>
     551                                    <p class="resetfileperm-agency-text"><?php esc_html_e( 'Creative Agency', 'reset-file-and-folder-permissions' ); ?></p>
     552                                    <h3><?php esc_html_e( 'Professional WordPress Development & Troubleshooting', 'reset-file-and-folder-permissions' ); ?></h3>
     553                                    <p class="resetfileperm-tagline"><?php esc_html_e( 'Expert solutions for complex WordPress challenges', 'reset-file-and-folder-permissions' ); ?></p>
     554                                </div>
     555                               
     556                                <div class="resetfileperm-profile-cta">
     557                                    <p class="resetfileperm-cta-text"><?php esc_html_e( 'Facing WordPress challenges? Get professional help from an experienced developer who understands the complexities of WordPress development and can provide reliable, efficient solutions.', 'reset-file-and-folder-permissions' ); ?></p>
     558                                   
     559                                    <div class="resetfileperm-contact-buttons">
     560                                        <a href="mailto:[email protected]?subject=WordPress Development Help Request" class="button button-primary resetfileperm-contact-btn">
     561                                            <span class="dashicons dashicons-email-alt"></span>
     562                                            <span class="resetfileperm-btn-text">
     563                                                <span class="resetfileperm-btn-line1"><?php esc_html_e( 'Get Expert Help', 'reset-file-and-folder-permissions' ); ?></span>
     564                                                <span class="resetfileperm-btn-line2">[email protected]</span>
     565                                            </span>
     566                                        </a>
     567                                        <a href="https://nandann.com" target="_blank" class="button button-secondary resetfileperm-website-btn">
     568                                            <span class="dashicons dashicons-external"></span>
     569                                            <?php esc_html_e( 'Visit nandann.com', 'reset-file-and-folder-permissions' ); ?>
     570                                        </a>
     571                                    </div>
     572                                </div>
     573                               
     574                                <div class="resetfileperm-profile-services">
     575                                    <div class="resetfileperm-service-grid">
     576                                        <div class="resetfileperm-service-item">
     577                                            <span class="dashicons dashicons-admin-tools"></span>
     578                                            <h4><?php esc_html_e( 'WordPress Troubleshooting', 'reset-file-and-folder-permissions' ); ?></h4>
     579                                            <p><?php esc_html_e( 'Expert diagnosis and resolution of complex WordPress issues, performance optimization, and security hardening.', 'reset-file-and-folder-permissions' ); ?></p>
     580                                        </div>
     581                                       
     582                                        <div class="resetfileperm-service-item">
     583                                            <span class="dashicons dashicons-desktop"></span>
     584                                            <h4><?php esc_html_e( 'Custom Development', 'reset-file-and-folder-permissions' ); ?></h4>
     585                                            <p><?php esc_html_e( 'Bespoke WordPress plugins, themes, and custom functionality tailored to your specific business needs.', 'reset-file-and-folder-permissions' ); ?></p>
     586                                        </div>
     587                                       
     588                                        <div class="resetfileperm-service-item">
     589                                            <span class="dashicons dashicons-migrate"></span>
     590                                            <h4><?php esc_html_e( 'Site Migration & Hosting', 'reset-file-and-folder-permissions' ); ?></h4>
     591                                            <p><?php esc_html_e( 'Seamless website migrations, hosting optimization, and server configuration for peak performance.', 'reset-file-and-folder-permissions' ); ?></p>
     592                                        </div>
     593                                       
     594                                        <div class="resetfileperm-service-item">
     595                                            <span class="dashicons dashicons-shield"></span>
     596                                            <h4><?php esc_html_e( 'Security & Maintenance', 'reset-file-and-folder-permissions' ); ?></h4>
     597                                            <p><?php esc_html_e( 'Comprehensive security audits, malware removal, and ongoing maintenance to keep your site secure.', 'reset-file-and-folder-permissions' ); ?></p>
     598                                        </div>
     599                                    </div>
     600                                </div>
     601                            </div>
     602                        </div>
     603                    </div>
     604                </div><!-- End Right Column -->
     605
     606            </div><!-- End Main Layout -->
     607
     608            <!-- Help Section -->
     609            <div class="resetfileperm-help-section">
     610                <h2><?php esc_html_e( 'About File Ownership', 'reset-file-and-folder-permissions' ); ?></h2>
     611                <div class="resetfileperm-help-content">
     612                    <h3><?php esc_html_e( 'What is File Ownership?', 'reset-file-and-folder-permissions' ); ?></h3>
     613                    <p><?php esc_html_e( 'File ownership determines which user and group have control over files and directories. In WordPress, files should typically be owned by the web server user (like www-data, apache, or nginx) to ensure proper functionality.', 'reset-file-and-folder-permissions' ); ?></p>
     614                   
     615                    <h3><?php esc_html_e( 'When to Use This Tool', 'reset-file-and-folder-permissions' ); ?></h3>
     616                    <ul>
     617                        <li><?php esc_html_e( 'After migrating to a new server with a different web server user', 'reset-file-and-folder-permissions' ); ?></li>
     618                        <li><?php esc_html_e( 'When WordPress cannot write files or install plugins/themes', 'reset-file-and-folder-permissions' ); ?></li>
     619                        <li><?php esc_html_e( 'After manually uploading files via FTP with incorrect ownership', 'reset-file-and-folder-permissions' ); ?></li>
     620                        <li><?php esc_html_e( 'When troubleshooting "permission denied" errors', 'reset-file-and-folder-permissions' ); ?></li>
     621                    </ul>
     622
     623                    <h3><?php esc_html_e( 'Important Warnings', 'reset-file-and-folder-permissions' ); ?></h3>
     624                    <ul>
     625                        <li><strong><?php esc_html_e( 'Incorrect ownership can break your site', 'reset-file-and-folder-permissions' ); ?></strong> - <?php esc_html_e( 'Always use the recommended values', 'reset-file-and-folder-permissions' ); ?></li>
     626                        <li><strong><?php esc_html_e( 'This operation requires elevated privileges', 'reset-file-and-folder-permissions' ); ?></strong> - <?php esc_html_e( 'Not available on all hosting environments', 'reset-file-and-folder-permissions' ); ?></li>
     627                        <li><strong><?php esc_html_e( 'Test after running', 'reset-file-and-folder-permissions' ); ?></strong> - <?php esc_html_e( 'Verify your site works correctly after changing ownership', 'reset-file-and-folder-permissions' ); ?></li>
     628                    </ul>
     629                </div>
     630            </div>
     631
     632        <?php endif; ?>
     633
     634    <?php endif; ?>
     635</div>
  • reset-file-and-folder-permissions/trunk/readme.txt

    r3345847 r3396598  
    55Requires at least: 5.0
    66Tested up to: 6.8
    7 Stable tag: 1.0.0
     7Stable tag: 1.1.0
    88Requires PHP: 7.4
    99License: GPLv2 or later
     
    1212Author URI: https://nandann.com
    1313
    14 A WordPress plugin to reset all file permissions to 0644 and all directory permissions to 0755 for security and maintenance purposes.
     14A WordPress plugin to reset file permissions to 0644, directory permissions to 0755, and file/folder ownership for security and maintenance purposes.
    1515
    1616== Description ==
    1717
    18 Reset file and folder permissions is a powerful yet safe WordPress plugin designed to help administrators reset file and directory permissions to their recommended secure values. This tool is particularly useful after site migrations, server changes, or when dealing with permission-related issues.
     18Reset file and folder permissions is a powerful yet safe WordPress plugin designed to help administrators reset file and directory permissions to their recommended secure values, and optionally reset file/folder ownership. This tool is particularly useful after site migrations, server changes, or when dealing with permission-related issues.
    1919
    2020= Key Features =
    2121
     22* **Dual Functionality**: Reset both permissions (0644/0755) and ownership (user/group) in separate tabs
     23* **Ownership Management**: Change file and folder ownership to the correct web server user (VPS/dedicated servers)
     24* **Server Compatibility Check**: Automatically detects if ownership functions are available on your server
    2225* **Batch Processing**: Handles large directory structures efficiently with configurable batch sizes
    2326* **Real-time Progress**: Visual progress bar with detailed statistics during processing
    2427* **Safety First**: Multiple security checks and confirmations before making changes
    2528* **Selective Processing**: Choose specific directories to process (entire site, wp-content, plugins, themes, or uploads)
     29* **Smart Recommendations**: Automatically detects and recommends the correct owner/group for your server
    2630* **Error Handling**: Comprehensive error logging and reporting
    2731* **Responsive Interface**: Works seamlessly on desktop and mobile devices
     
    3539= When to Use This Plugin =
    3640
     41**For Permission Reset:**
    3742* After migrating your WordPress site to a new server
    3843* When files have incorrect permissions causing functionality issues
     
    4045* When troubleshooting file access problems
    4146* During routine maintenance to ensure proper permissions
     47
     48**For Ownership Reset:**
     49* After migrating to a new server with a different web server user
     50* When WordPress cannot write files or install plugins/themes
     51* After manually uploading files via FTP with incorrect ownership
     52* When troubleshooting "permission denied" errors despite correct permissions
     53* When switching hosting providers or server configurations
    4254
    4355= Safety Features =
     
    6577= System Requirements =
    6678
     79**For Permission Reset:**
    6780* PHP `chmod()` function must be available
    6881* WordPress 5.0 or higher
    6982* PHP 7.4 or higher
    7083* Administrator access
     84
     85**For Ownership Reset (Additional Requirements):**
     86* PHP `chown()` and `chgrp()` functions must be available
     87* PHP POSIX functions (`posix_getpwnam`, `posix_getgrnam`, etc.)
     88* VPS, dedicated server, or hosting with elevated privileges
     89* Note: Ownership features are typically NOT available on shared hosting
    7190
    7291== Frequently Asked Questions ==
     
    106125- Uploads directory only
    107126
     127= What is file ownership and why does it matter? =
     128
     129File ownership determines which user and group have control over files. In WordPress, files should typically be owned by the web server user (like www-data, apache, or nginx) to ensure proper functionality. Incorrect ownership can prevent WordPress from writing files, installing plugins/themes, or updating content.
     130
     131= Why can't I see the ownership reset feature? =
     132
     133The ownership reset feature requires PHP functions (`chown`, `chgrp`, and POSIX functions) that are often disabled on shared hosting for security reasons. These functions typically require elevated server privileges and are only available on VPS, dedicated servers, or hosting environments where you have more control. If you don't see the ownership tab or see a compatibility warning, contact your hosting provider or consider upgrading to a more flexible hosting solution.
     134
     135= How do I know which owner and group to use? =
     136
     137The plugin automatically detects your web server's user and group and recommends them. In most cases, you should use the recommended values. Common web server users include: www-data (Ubuntu/Debian), apache (CentOS/RHEL), nginx (Nginx servers), or _www (macOS).
     138
     139= Can incorrect ownership break my site? =
     140
     141Yes, setting incorrect ownership can prevent WordPress from functioning properly. Always use the recommended values provided by the plugin. If you're unsure, contact your hosting provider or a WordPress professional before making ownership changes.
     142
     143= What's the difference between permissions and ownership? =
     144
     145**Permissions** (0644/0755) control what actions can be performed on files (read, write, execute) by the owner, group, and others. **Ownership** determines which user and group "own" the files. Both need to be correct for WordPress to function properly. You can have correct permissions but still face issues if ownership is wrong.
     146
    108147== Screenshots ==
    109148
     
    114153
    115154== Changelog ==
     155
     156= 1.1.0 =
     157* Added: File and folder ownership reset functionality
     158* Added: Separate "Reset Ownership" tab for ownership management
     159* Added: Automatic detection of web server user and group
     160* Added: Server compatibility check for ownership functions
     161* Added: Smart recommendations for owner/group selection
     162* Added: Dropdown menus for selecting owner and group
     163* Added: Comprehensive warnings and help text for ownership operations
     164* Added: Separate confirmation dialogs for ownership changes
     165* Improved: Tab-based navigation for better organization
     166* Improved: Enhanced error messages and logging
     167* Improved: Better compatibility warnings for shared hosting
     168* Note: Ownership features require VPS/dedicated server with elevated privileges
    116169
    117170= 1.0.0 =
     
    125178== Upgrade Notice ==
    126179
     180= 1.1.0 =
     181Major update: Added file and folder ownership reset functionality with automatic server detection and smart recommendations. New tab-based interface for better organization. Ownership features require VPS/dedicated server.
     182
    127183= 1.0.0 =
    128184Initial release of Reset file and folder permissions plugin. Safely reset file and directory permissions to WordPress standards.
  • reset-file-and-folder-permissions/trunk/uninstall.php

    r3345847 r3396598  
    1515
    1616// Clean up log directory if it exists
    17 $log_dir = WP_CONTENT_DIR . '/resetfileperm-logs';
    18 if ( file_exists( $log_dir ) ) {
     17$resetfileperm_log_dir = WP_CONTENT_DIR . '/resetfileperm-logs';
     18if ( file_exists( $resetfileperm_log_dir ) ) {
    1919    // Remove all files in the log directory using WordPress filesystem
    2020    if ( ! function_exists( 'WP_Filesystem' ) ) {
     
    2424    global $wp_filesystem;
    2525   
    26     if ( $wp_filesystem && $wp_filesystem->is_dir( $log_dir ) ) {
    27         $wp_filesystem->rmdir( $log_dir, true );
     26    if ( $wp_filesystem && $wp_filesystem->is_dir( $resetfileperm_log_dir ) ) {
     27        $wp_filesystem->rmdir( $resetfileperm_log_dir, true );
    2828    }
    2929}
Note: See TracChangeset for help on using the changeset viewer.