option_name, array( $this, 'handle_settings_update' ), 10, 2 ); // Apply some security services on init add_action( 'init', array( $this, 'apply_security_services' ), 20 ); // Apply some security services early on plugins_loaded add_action( 'plugins_loaded', array( $this, 'apply_early_security_services' ), 20 ); //rest api init hook for rest api disabling add_action( 'rest_api_init', array( $this, 'apply_rest_api_disabling' ), 0 ); } //function to disable rest api for non-authenticated users public function apply_rest_api_disabling() { $settings = get_option( 'ADALC_settings', [] ); if ( ! empty( $settings['disable_rest_api'] ) ) { add_filter( 'rest_authentication_errors', function( $result ) { if ( ! empty( $result ) ) { return $result; } if ( ! is_user_logged_in() ) { return new WP_Error( 'rest_cannot_access', __( 'REST API restricted to authenticated users only.', 'accessdoor-smart-admin-login-url-control' ), array( 'status' => 401 ) ); } return $result; }); } } //function to handle settings update for xmlrpc services public function apply_early_security_services() { $settings = get_option( 'ADALC_settings', [] ); // Disable File Editing in Dashboard if ( isset( $settings['disable_file_editing'] ) && $settings['disable_file_editing'] ) { if ( ! defined( 'DISALLOW_FILE_EDIT' ) ) { define( 'DISALLOW_FILE_EDIT', true ); } } //disable xmlrpc completely if ( ! empty( $settings['disable_xmlrpc'] ) ) { add_filter( 'xmlrpc_enabled', '__return_false' ); if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) { status_header( 403 ); header( 'Content-Type: text/plain; charset=UTF-8' ); echo 'XML-RPC is disabled.'; exit; } } // Disable XML-RPC Pingbacks if ( ! empty( $settings['disable_xmlrpc_pingback'] ) ) { add_filter( 'xmlrpc_methods', function( $methods ) { unset( $methods['pingback.ping'] ); unset( $methods['pingback.extensions.getPingbacks'] ); return $methods; }); add_action( 'xmlrpc_call', function( $method ) { if ( strpos( $method, 'pingback' ) !== false ) { status_header( 403 ); header( 'Content-Type: text/plain; charset=UTF-8' ); echo 'Pingbacks are disabled.'; exit; } }); } } //function handle_settings_update to check if any security-related settings were changed and apply changes immediately public function handle_settings_update( $old_value, $new_value ) { // print_r($old_value); // Stop if no security settings changed if ( $old_value === $new_value ) { return; } if ( ! function_exists( 'request_filesystem_credentials' ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; } global $wp_filesystem; if ( empty( $wp_filesystem ) ) { $creds = request_filesystem_credentials( '', '', false, false, null ); if ( ! WP_Filesystem( $creds ) ) { return; } } /** * ----------------------------- * BLOCK DIRECTORY BROWSING * ----------------------------- */ $htaccess_path = ABSPATH . '.htaccess'; if ( $wp_filesystem->exists( $htaccess_path ) && $wp_filesystem->is_writable( $htaccess_path ) ) { $htaccess = $wp_filesystem->get_contents( $htaccess_path ); $block = "\n# BEGIN Accessdoor Directory Protection\nOptions -Indexes\n# END Accessdoor Directory Protection\n"; // Enable if ( ! empty( $new_value['block_directory_browsing'] ) ) { if ( strpos( $htaccess, 'BEGIN Accessdoor Directory Protection' ) === false ) { $htaccess .= $block; } } // Disable else { $htaccess = preg_replace( '/# BEGIN Accessdoor Directory Protection.*?# END Accessdoor Directory Protection\n?/s', '', $htaccess ); } $wp_filesystem->put_contents( $htaccess_path, $htaccess, FS_CHMOD_FILE ); } /** * ----------------------------- * BLOCK PHP IN UPLOADS * ----------------------------- */ $uploads_dir = wp_get_upload_dir(); $uploads_path = trailingslashit( $uploads_dir['basedir'] ); $uploads_htaccess = $uploads_path . '.htaccess'; $php_block = "# BEGIN Accessdoor Upload Protection\n\nDeny from all\n\n# END Accessdoor Upload Protection\n"; $existing = $wp_filesystem->exists( $uploads_htaccess ) ? $wp_filesystem->get_contents( $uploads_htaccess ) : ''; // Enable if ( ! empty( $new_value['forbid_php_uploads'] ) ) { if ( strpos( $existing, '# BEGIN Accessdoor Upload Protection' ) === false ) { // Remove any old block first, then append the new one $cleaned = preg_replace( '/# BEGIN Accessdoor Upload Protection.*?# END Accessdoor Upload Protection\n?/s', '', $existing ); $wp_filesystem->put_contents( $uploads_htaccess, $cleaned . $php_block, FS_CHMOD_FILE ); } } // Disable else { $cleaned = preg_replace( '/# BEGIN Accessdoor Upload Protection.*?# END Accessdoor Upload Protection\n?/s', '', $existing ); $wp_filesystem->put_contents( $uploads_htaccess, $cleaned, FS_CHMOD_FILE ); } } /** * Apply selected security services based on plugin settings. * * @since 1.0.0 */ public function apply_security_services() { $settings = get_option( $this->option_name, array() ); // Disable Comments if ( isset( $settings['disable_comments'] ) && $settings['disable_comments'] ) { add_filter( 'comments_open', '__return_false', 20, 2 ); add_filter( 'pings_open', '__return_false', 20, 2 ); } // Turn Off Pingbacks (XML-RPC + for all posts) if ( isset( $settings['turn_off_pingbacks'] ) && $settings['turn_off_pingbacks'] ) { // 1. Disable pingback & trackback XML-RPC methods add_filter( 'xmlrpc_methods', function( $methods ) { unset( $methods['pingback.ping'] ); unset( $methods['pingback.extensions.getPingbacks'] ); return $methods; }); // 2. Remove X-Pingback HTTP header add_filter( 'wp_headers', function( $headers ) { unset( $headers['X-Pingback'] ); return $headers; }); // 3. Remove pingback discovery links from remove_action( 'wp_head', 'rsd_link' ); remove_action( 'wp_head', 'wlwmanifest_link' ); // 4. Disable pingbacks & trackbacks in settings (default behavior) add_filter( 'pre_option_default_ping_status', '__return_zero' ); add_filter( 'pre_option_default_comment_status', '__return_zero' ); // 5. Disable trackback rewrite rules add_filter( 'rewrite_rules_array', function( $rules ) { foreach ( $rules as $rule => $rewrite ) { if ( strpos( $rewrite, 'trackback' ) !== false ) { unset( $rules[ $rule ] ); } } return $rules; }); // 6. Force close pings on all existing posts // add_filter( 'comments_open', function( $open, $post_id ) { // return false; // }, 10, 2 ); add_filter( 'pings_open', function() { return false; }); } } /** * Add settings page to WordPress admin menu. */ public function add_settings_page() { // Do nothing if multisite, so no settings page is added if ( is_multisite() ) { return; } add_options_page( __( 'AccessDoor Smart Admin Login & Security', 'accessdoor-smart-admin-login-url-control' ), __( 'AccessDoor Smart Admin Login & Security', 'accessdoor-smart-admin-login-url-control' ), 'manage_options', 'accessdoor-smart-admin-login-url-control', array( $this, 'render_settings_page' ) ); } /** * Register plugin settings. */ public function register_settings() { // Register the same option for both tabs with proper sanitization register_setting( 'ADALC_general_group', $this->option_name, array( $this, 'sanitize_settings' ) ); register_setting( 'ADALC_branding_group', $this->option_name, array( $this, 'sanitize_settings' ) ); register_setting( 'ADALC_admin_group', $this->option_name, array( $this, 'sanitize_settings' ) ); // General Settings Section. add_settings_section( 'ADALC_general_section', __( 'General Settings', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'general_section_callback' ), 'adalc-general-settings' ); add_settings_field( 'enable_custom_login', ''. __( 'Enable Custom Login URL', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'enable_custom_login_callback' ), 'adalc-general-settings', 'ADALC_general_section' ); add_settings_field( 'role_login_urls', '' . __( 'Role-Based Login URLs', 'accessdoor-smart-admin-login-url-control' ) . ' ' . '' . __( 'Set a custom login slug for each role. Leave empty to use the Administrator login URL.', 'accessdoor-smart-admin-login-url-control' ) . '' . '', array( $this, 'role_login_urls_callback' ), 'adalc-general-settings', 'ADALC_general_section' ); // Redirect Settings Section. add_settings_section( 'ADALC_redirect_section', __( 'Redirect wp-login.php', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'redirect_section_callback' ), 'adalc-general-settings' ); add_settings_field( 'redirect_wp_login', ''. __( 'Redirect Default WordPress Login', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'redirect_wp_login_callback' ), 'adalc-general-settings', 'ADALC_redirect_section' ); add_settings_field( 'redirect_url', '' . __( 'Custom Redirect URL', 'accessdoor-smart-admin-login-url-control' ) . ' ' . '' . __( 'Set the URL where users will be redirected if they try to access wp-login.php directly.', 'accessdoor-smart-admin-login-url-control' ) . '' . '', array( $this, 'redirect_url_callback' ), 'adalc-general-settings', 'ADALC_redirect_section' ); // Custom Branding Section. add_settings_section( 'ADALC_branding_section', __( 'Custom Branding per Role', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'branding_section_callback' ), 'adalc-branding-settings' ); add_settings_field( 'custom_branding', '', array( $this, 'role_branding_callback' ), 'adalc-branding-settings', 'ADALC_branding_section' ); // Change Admin Info. add_settings_section( 'ADALC_admin_info_section', __( 'Change Admin Info', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'admin_info_section_callback' ), 'adalc-admin-settings' ); // Move admin email field to Admin Settings tab (last/third tab) add_settings_field( 'change_admin_email', ''. __( 'Change Admin Email Address', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'admin_email_field_callback' ), 'adalc-admin-settings', 'ADALC_admin_info_section' ); // User email and username remain in Admin Settings add_settings_field( 'change_user_email', ''. __( 'Change Admin User Email', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'current_user_email_field_callback' ), 'adalc-admin-settings', 'ADALC_admin_info_section' ); add_settings_field( 'change_admin_username', ''. __( 'Change Admin Username', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'admin_username_field_callback' ), 'adalc-admin-settings', 'ADALC_admin_info_section' ); // Security Measures Section (new tab) register_setting( 'ADALC_security_group', $this->option_name, array( $this, 'sanitize_settings' ) ); add_settings_section( 'ADALC_security_section', __( 'Security Measures', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'security_section_callback' ), 'adalc-security-settings' ); // Security options fields add_settings_field( 'disable_comments', __( 'Disable Comments', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'disable_comments_callback' ), 'adalc-security-settings', 'ADALC_security_section' ); add_settings_field( 'disable_xmlrpc_pingback', __( 'Disable XML-RPC Pingback', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'disable_xmlrpc_pingback_callback' ), 'adalc-security-settings', 'ADALC_security_section' ); add_settings_field( 'disable_rest_api', __( 'Disable REST API', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'disable_rest_api_callback' ), 'adalc-security-settings', 'ADALC_security_section' ); add_settings_field( 'disable_xmlrpc', __( 'Disable XML-RPC', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'disable_xmlrpc_callback' ), 'adalc-security-settings', 'ADALC_security_section' ); // Block Directory Browsing add_settings_field( 'block_directory_browsing', __( 'Block Directory Browsing', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'block_directory_browsing_callback' ), 'adalc-security-settings', 'ADALC_security_section' ); // Forbid PHP in Uploads add_settings_field( 'forbid_php_uploads', __( 'Forbid PHP in Uploads', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'forbid_php_uploads_callback' ), 'adalc-security-settings', 'ADALC_security_section' ); // Turn Off Pingbacks add_settings_field( 'turn_off_pingbacks', __( 'Turn Off Pingbacks', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'turn_off_pingbacks_callback' ), 'adalc-security-settings', 'ADALC_security_section' ); // Disable File Editing add_settings_field( 'disable_file_editing', __( 'Disable File Editing in Dashboard', 'accessdoor-smart-admin-login-url-control' ), array( $this, 'disable_file_editing_callback' ), 'adalc-security-settings', 'ADALC_security_section' ); } /** * Get all roles that have at least one user. * * @return array Array of role slugs and names with user counts. */ public function get_roles_with_users() { $roles_with_users = array(); $user_counts = count_users(); $all_roles = wp_roles()->get_names(); foreach ( $user_counts['avail_roles'] as $role_slug => $count ) { if ( $count > 0 && isset( $all_roles[ $role_slug ] ) ) { $roles_with_users[ $role_slug ] = array( 'name' => $all_roles[ $role_slug ], 'count' => $count, ); } } return $roles_with_users; } /** * Role-based login URLs callback. */ public function role_login_urls_callback() { $settings = get_option( $this->option_name, array() ); $roles = $this->get_roles_with_users(); if ( empty( $roles ) ) { echo '

' . esc_html__( 'No roles with users found.', 'accessdoor-smart-admin-login-url-control' ) . '

'; return; } echo '
'; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; foreach ( $roles as $role_slug => $role_data ) { $slug_value = isset( $settings['role_slugs'][ $role_slug ] ) ? $settings['role_slugs'][ $role_slug ] : ''; $login_url = $slug_value ? home_url( $slug_value ) : __( 'Not set (Uses administrator login URL)', 'accessdoor-smart-admin-login-url-control' ); if($role_data['name'] == 'Administrator'){ $login_url = $slug_value ? home_url( $slug_value ) : __( 'Not set', 'accessdoor-smart-admin-login-url-control' ); } echo ''; echo ''; echo ''; $url_to_copy = is_string( $login_url ) ? $login_url : home_url( $slug_value ); echo ''; echo ''; echo ''; } echo ''; echo '
' . esc_html__( 'Role', 'accessdoor-smart-admin-login-url-control' ) . '' . esc_html__( 'Custom Login Slug', 'accessdoor-smart-admin-login-url-control' ) . '' . esc_html__( 'Login URL', 'accessdoor-smart-admin-login-url-control' ) . '' . esc_html__( 'Users', 'accessdoor-smart-admin-login-url-control' ) . '
' . esc_html( $role_data['name'] ) . ''; printf( '', esc_attr( $this->option_name ), esc_attr( $role_slug ), esc_attr( $slug_value ), esc_attr( strtolower( str_replace( ' ', '-', $role_data['name'] ) ) . '-login' ) ); echo ''; echo '' . esc_html( $url_to_copy ) . ''; echo ' '; echo '' . esc_html( $role_data['count'] ) . '
'; echo '

' . esc_html__( 'Do not use any of the following slugs as custom login URLs:', 'accessdoor-smart-admin-login-url-control' ) . ' wp-admin, wp-login, wp-login.php, login, admin, logout, lostpassword, resetpassword, register, wp-json, xmlrpc, xmlrpc.php, my-account, cart, checkout, shop, account, profile, signin, signup, etc.

'; echo '
'; } /** * Sanitize settings before saving. * * @param array $input Settings input. * @return array Sanitized settings. */ public function sanitize_settings( $input ) { // Get existing settings to merge with new input $existing = get_option( $this->option_name, array() ); $sanitized = $existing; // Start with existing data if ( isset( $input['enable_custom_login'] ) ) { $sanitized['enable_custom_login'] = 1; } elseif ( isset( $input['redirect_wp_login'] ) || isset( $input['role_slugs'] ) ) { // Only set to 0 if we're saving the general tab (has these fields) $sanitized['enable_custom_login'] = 0; } // Sanitize role-based slugs and block restricted/existing slugs. if ( isset( $input['role_slugs'] ) && is_array( $input['role_slugs'] ) ) { $sanitized['role_slugs'] = array(); $restricted_slugs = array( 'wp-admin', 'wp-login', 'wp-login.php', 'login', 'admin', 'logout', 'lostpassword', 'resetpassword', 'register', 'wp-json', 'xmlrpc', 'xmlrpc.php', 'my-account', 'cart', 'checkout', 'shop', 'account', 'profile', 'signin', 'signup', ); foreach ( $input['role_slugs'] as $role => $slug ) { if ( empty( $slug ) ) { continue; } $slug = sanitize_title( $slug ); // Block restricted slugs if ( in_array( $slug, $restricted_slugs, true ) ) { add_settings_error( $this->option_name, 'restricted_slug_' . $role, /* translators: %s: The slug entered by the user */ sprintf( __( 'The slug "%s" is not allowed for security reasons.', 'accessdoor-smart-admin-login-url-control' ), esc_html( $slug ) ), 'error' ); continue; } // Block if slug matches an existing page if ( get_page_by_path( $slug ) ) { add_settings_error( $this->option_name, 'existing_page_slug_' . $role, /* translators: %s: The slug entered by the user */ sprintf( __( 'The slug "%s" is already used by a page. Please choose another.', 'accessdoor-smart-admin-login-url-control' ), esc_html( $slug ) ), 'error' ); continue; } $sanitized['role_slugs'][ $role ] = $slug; } } if ( isset( $input['redirect_wp_login'] ) ) { $sanitized['redirect_wp_login'] = 1; } elseif ( isset( $input['role_slugs'] ) ) { // Only set to 0 if we're saving the general tab $sanitized['redirect_wp_login'] = 0; } if ( isset( $input['redirect_url'] ) ) { $sanitized['redirect_url'] = esc_url_raw( $input['redirect_url'] ); } // Sanitize role logo IDs. if ( isset( $input['role_logo'] ) && is_array( $input['role_logo'] ) ) { if ( ! isset( $sanitized['role_logo'] ) ) { $sanitized['role_logo'] = array(); } foreach ( $input['role_logo'] as $role => $attachment_id ) { if ( ! empty( $attachment_id ) ) { $sanitized['role_logo'][ $role ] = absint( $attachment_id ); } else { // Remove if empty unset( $sanitized['role_logo'][ $role ] ); } } } // Save Security tab options, but validate .htaccess changes for relevant features $security_fields = array( 'disable_comments', 'disable_xmlrpc_pingback', 'disable_rest_api', 'disable_xmlrpc', 'block_directory_browsing', 'forbid_php_uploads', 'turn_off_pingbacks', 'disable_file_editing', ); foreach ( $security_fields as $field ) { // Default: set from input $sanitized[$field] = isset($input[$field]) ? 1 : 0; } // Sanitize role background image IDs. if ( isset( $input['role_bg_image'] ) && is_array( $input['role_bg_image'] ) ) { if ( ! isset( $sanitized['role_bg_image'] ) ) { $sanitized['role_bg_image'] = array(); } foreach ( $input['role_bg_image'] as $role => $attachment_id ) { if ( ! empty( $attachment_id ) ) { $sanitized['role_bg_image'][ $role ] = absint( $attachment_id ); } else { // Remove if empty unset( $sanitized['role_bg_image'][ $role ] ); } } } // Sanitize role background colors. if ( isset( $input['role_bg_color'] ) && is_array( $input['role_bg_color'] ) ) { if ( ! isset( $sanitized['role_bg_color'] ) ) { $sanitized['role_bg_color'] = array(); } foreach ( $input['role_bg_color'] as $role => $color ) { if ( ! empty( $color ) ) { $sanitized['role_bg_color'][ $role ] = sanitize_hex_color( $color ); } else { // Remove if empty unset( $sanitized['role_bg_color'][ $role ] ); } } } if ( isset( $input['change_admin_email'] ) || isset( $input['change_user_email'] ) || isset( $input['change_admin_username'] ) ) { $current_user = wp_get_current_user(); $user_id = $current_user->ID; $is_admin = user_can( $current_user, 'manage_options' ); if ( empty( $user_id ) || ! $is_admin ) { return $sanitized; } // Track which fields were actually changed $changed_fields = array(); /** * --------------------------------------- * 1. Update ADMIN EMAIL (Settings → General) * No confirmation email * --------------------------------------- */ if ( isset( $input['change_admin_email'] ) ) { $new_admin_email = sanitize_email( $input['change_admin_email'] ); $current_admin_email = get_option( 'admin_email' ); if($new_admin_email != $current_admin_email){ if ( ! is_email( $new_admin_email ) ) { add_settings_error( $this->option_name, 'invalid_admin_email', __( 'Please enter a valid admin email address.', 'accessdoor-smart-admin-login-url-control' ), 'error' ); }else { // Force update without confirmation, allow any email (even if used by another user) update_option( 'admin_email', $new_admin_email ); delete_option( 'new_admin_email' ); remove_action( 'update_option_admin_email', 'wp_send_new_admin_email', 10 ); add_settings_error( $this->option_name, 'admin_email_updated', __( 'Admin email updated successfully.', 'accessdoor-smart-admin-login-url-control' ), 'updated' ); } $sanitized['change_admin_email'] = $new_admin_email; } } /** * --------------------------------------- * 2. Update ADMIN USER EMAIL * --------------------------------------- */ if ( isset( $input['change_user_email'] ) ) { $new_user_email = sanitize_email( $input['change_user_email'] ); // Only process if username is changed if ( $new_user_email !== $current_user->user_email ) { if ( ! is_email( $new_user_email ) ) { add_settings_error( $this->option_name, 'invalid_user_email', __( 'Please enter a valid user email address.', 'accessdoor-smart-admin-login-url-control' ), 'error' ); $sanitized['change_user_email'] = $current_user->user_email; } elseif ( email_exists( $new_user_email ) && $new_user_email !== $current_user->user_email ) { add_settings_error( $this->option_name, 'user_email_exists', __( 'This email is already in use by another user.', 'accessdoor-smart-admin-login-url-control' ), 'error' ); $sanitized['change_user_email'] = $current_user->user_email; }else { $result = wp_update_user( array( 'ID' => $user_id, 'user_email' => $new_user_email, ) ); if ( is_wp_error( $result ) ) { add_settings_error( $this->option_name, 'user_email_update_failed', __( 'Failed to update user email: ', 'accessdoor-smart-admin-login-url-control' ) . $result->get_error_message(), 'error' ); $sanitized['change_user_email'] = $current_user->user_email; } else { add_settings_error( $this->option_name, 'user_email_updated', __( 'User email updated successfully.', 'accessdoor-smart-admin-login-url-control' ), 'updated' ); $sanitized['change_user_email'] = $new_user_email; } } } } /** * --------------------------------------- * 3. Update ADMIN USERNAME (Advanced) * --------------------------------------- */ if ( isset( $input['change_admin_username'] ) ) { $new_username = sanitize_user( $input['change_admin_username'], true ); // Only process if username is changed if ( $new_username !== $current_user->user_login ) { // Block for super admins in multisite if ( is_multisite() && is_super_admin( $user_id ) ) { add_settings_error( $this->option_name, 'superadmin_username_change_blocked', __( 'Changing the username for a network (super) admin is not allowed for security reasons.', 'accessdoor-smart-admin-login-url-control' ), 'error' ); $sanitized['change_admin_username'] = $current_user->user_login; } elseif ( empty( $new_username ) ) { add_settings_error( $this->option_name, 'invalid_username', __( 'Username cannot be empty.', 'accessdoor-smart-admin-login-url-control' ), 'error' ); $sanitized['change_admin_username'] = $current_user->user_login; } elseif ( username_exists( $new_username ) ) { add_settings_error( $this->option_name, 'username_exists', __( 'This username already exists.', 'accessdoor-smart-admin-login-url-control' ), 'error' ); $sanitized['change_admin_username'] = $current_user->user_login; } else { global $wpdb; $updated = $wpdb->update( $wpdb->users, array( 'user_login' => $new_username ), array( 'ID' => $user_id ), array( '%s' ), array( '%d' ) ); if ( false === $updated ) { add_settings_error( $this->option_name, 'username_update_failed', __( 'Failed to update username.', 'accessdoor-smart-admin-login-url-control' ), 'error' ); $sanitized['change_admin_username'] = $current_user->user_login; } else { // Refresh login session wp_clear_auth_cookie(); wp_set_current_user( $user_id ); wp_set_auth_cookie( $user_id ); add_settings_error( $this->option_name, 'username_updated', __( 'Username updated successfully.', 'accessdoor-smart-admin-login-url-control' ), 'updated' ); $sanitized['change_admin_username'] = $new_username; } } } } } // Improved: Only set transient if values actually changed (robust for unset/empty cases) $settings_changed = false; // Compare role_slugs $old_slugs = isset( $existing['role_slugs'] ) ? $existing['role_slugs'] : array(); $new_slugs = isset( $sanitized['role_slugs'] ) ? $sanitized['role_slugs'] : array(); if ( $old_slugs !== $new_slugs ) { $settings_changed = true; } // Compare enable_custom_login $old_enable = isset( $existing['enable_custom_login'] ) ? (int)$existing['enable_custom_login'] : 0; $new_enable = isset( $sanitized['enable_custom_login'] ) ? (int)$sanitized['enable_custom_login'] : 0; if ( $old_enable !== $new_enable ) { $settings_changed = true; } if ( $settings_changed ) { set_transient( 'ADALC_permalinks_flush_needed', true, 60 ); set_transient( 'ADALC_permalinks_flushed', true, 30 ); } return $sanitized; } /** * Display admin notices. */ public function display_admin_notices() { static $notice_shown = false; if ( $notice_shown ) { return; } // Check if we just flushed permalinks. if ( get_transient( 'ADALC_permalinks_flushed' ) ) { delete_transient( 'ADALC_permalinks_flushed' ); $notice_shown = true; ?>

' . esc_html__( 'Configure your custom login URL settings below.', 'accessdoor-smart-admin-login-url-control' ) . '

'; } /** * Redirect settings section callback. */ public function redirect_section_callback() { // echo '

' . esc_html__( 'Configure what happens when someone tries to access the default wp-login.php directly.', 'accessdoor-smart-admin-login-url-control' ) . '

'; } /** * Branding settings section callback. */ public function branding_section_callback() { // echo '

' . esc_html__( 'Customize the login page design for each user role. Set a custom logo and background.', 'accessdoor-smart-admin-login-url-control' ) . '

'; } /** * Admin Information settings section callback. */ public function admin_info_section_callback() { // echo '

' . esc_html__( 'Change Admin Information below.', 'accessdoor-smart-admin-login-url-control' ) . '

'; } /** * Admin email change callback. */ public function admin_email_field_callback() { $current_admin_email = get_option('admin_email'); ?>

General).', 'accessdoor-smart-admin-login-url-control' ); ?>

user_email : ''; ?>

user_login : ''; ?>

option_name, array() ); $value = isset( $settings['enable_custom_login'] ) ? $settings['enable_custom_login'] : 0; ?>

option_name, array() ); $value = isset( $settings['custom_login_slug'] ) ? $settings['custom_login_slug'] : 'custom-login'; ?>

' . esc_html( home_url( $value ) ) . '' ); ?>

option_name, array() ); $value = isset( $settings['redirect_wp_login'] ) ? $settings['redirect_wp_login'] : 0; ?>

option_name, array() ); $value = isset( $settings['redirect_url'] ) ? $settings['redirect_url'] : home_url(); ?>

option_name, array() ); $roles = $this->get_roles_with_users(); if ( empty( $roles ) ) { echo '

' . esc_html__( 'No roles with users found.', 'accessdoor-smart-admin-login-url-control' ) . '

'; return; } $first_role = true; ?>
$role_data ) : $is_administrator = false; $logo_id = isset( $settings['role_logo'][ $role_slug ] ) ? $settings['role_logo'][ $role_slug ] : ''; $bg_image_id = isset( $settings['role_bg_image'][ $role_slug ] ) ? $settings['role_bg_image'][ $role_slug ] : ''; $bg_color = isset( $settings['role_bg_color'][ $role_slug ] ) ? $settings['role_bg_color'][ $role_slug ] : '#f0f0f1'; $logo_url = $logo_id ? wp_get_attachment_url( $logo_id ) : ''; $bg_image_url = $bg_image_id ? wp_get_attachment_url( $bg_image_id ) : ''; if($role_data['name'] == 'Administrator'){ $is_administrator = true; } ?>


roles, true ) ) { // wp_die( esc_html__( 'You do not have permission to access this page.', 'accessdoor-smart-admin-login-url-control' ) ); // } // } // phpcs:ignore WordPress.Security.NonceVerification.Recommended $active_tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'general'; $current_user = wp_get_current_user(); $username = $current_user ? $current_user->user_login : ''; $user_tab_title = 'Account Settings'; ?>

'; settings_fields( 'ADALC_security_group' ); do_settings_sections( 'adalc-security-settings' ); echo '
'; } submit_button( __( 'Save Settings', 'accessdoor-smart-admin-login-url-control' ) ); ?> ' . esc_html__( 'Security Settings', 'accessdoor-smart-admin-login-url-control' ) . ''; /** * Disable Comments field callback. */ } public function disable_comments_callback() { $settings = get_option( $this->option_name, array() ); $status = ''; $value = !empty($settings) && isset($settings['disable_comments']) ? (int)$settings['disable_comments'] : 0; if ( has_filter( 'comments_open', '__return_false' ) && ! $value ) { $status = 'disabled'; } ?>

option_name, array() ); $status = ''; $value = !empty($settings) && isset($settings['disable_xmlrpc_pingback']) ? (int)$settings['disable_xmlrpc_pingback'] : 0; if ( has_filter( 'xmlrpc_methods', '__return_false' ) && ! $value ) { $status = 'disabled'; } ?>

option_name, array() ); $status = ''; $value = !empty($settings) && isset($settings['disable_rest_api']) ? (int)$settings['disable_rest_api'] : 0; if ( has_filter( 'rest_authentication_errors', '__return_false' ) && ! $value ) { $status = 'disabled'; } ?>

option_name, array() ); $status = ''; $value = !empty($settings) && isset($settings['disable_xmlrpc']) ? (int)$settings['disable_xmlrpc'] : 0; if ( has_filter( 'xmlrpc_enabled', '__return_false' ) && ! $value ) { $status = 'disabled'; } ?>

option_name, array() ); $value = !empty($settings) && isset($settings['block_directory_browsing']) ? (int)$settings['block_directory_browsing'] : 0; $htaccess_path = ABSPATH . '.htaccess'; $htaccess_error = false; if ( ! function_exists( 'request_filesystem_credentials' ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; } global $wp_filesystem; if ( empty( $wp_filesystem ) ) { $creds = request_filesystem_credentials( '', '', false, false, null ); if ( ! WP_Filesystem( $creds ) ) { $wp_filesystem = null; } } if ( ! $wp_filesystem || ! $wp_filesystem->exists( $htaccess_path ) || ! $wp_filesystem->is_writable( $htaccess_path ) ) { $htaccess_error = true; $value = 0; // Prevent enabling the feature } ?>

option_name, array() ); $value = !empty($settings) && isset($settings['forbid_php_uploads']) ? (int)$settings['forbid_php_uploads'] : 0; $uploads_dir = wp_get_upload_dir(); $uploads_path = trailingslashit( $uploads_dir['basedir'] ); $uploads_htaccess = $uploads_path . '.htaccess'; $uploads_error = false; if ( ! function_exists( 'request_filesystem_credentials' ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; } global $wp_filesystem; if ( empty( $wp_filesystem ) ) { $creds = request_filesystem_credentials( '', '', false, false, null ); if ( ! WP_Filesystem( $creds ) ) { $wp_filesystem = null; } } if ( ! $wp_filesystem || ! $wp_filesystem->exists( $uploads_htaccess ) || ! $wp_filesystem->is_writable( $uploads_htaccess ) ) { $uploads_error = true; $value = 0; // Prevent enabling the feature } ?>

option_name, array() ); $status = ''; $value = !empty($settings) && isset($settings['turn_off_pingbacks']) ? (int)$settings['turn_off_pingbacks'] : 0; // Check if pingbacks are already disabled by another plugin or code $pingback_disabled = has_filter( 'xmlrpc_methods', '__return_false' ); if ( $pingback_disabled && ! $value ) { $status = 'disabled'; } ?>

option_name, array() ); $status = ''; $value = !empty($settings) && isset($settings['disable_file_editing']) ? (int)$settings['disable_file_editing'] : 0; // Check if DISALLOW_FILE_EDIT is already defined and true if ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT && ! $value ) { $status = 'disabled'; } ?>

' . __( 'Settings', 'accessdoor-smart-admin-login-url-control' ) . ''; array_unshift( $links, $settings_link ); return $links; } public function change_admin_email( $new_email ) { // 1. Validate email if ( ! is_email( $new_email ) ) { return new WP_Error( 'invalid_email', 'Invalid email address.' ); } update_option('admin_email', sanitize_email( $new_email )); update_option('new_admin_email', sanitize_email($new_email)); // Remove WordPress pending confirmation delete_option( 'new_admin_email' ); delete_option( 'adminhash' ); return true; } }