exists()) continue; if ($action === 'add' && $advausro_role_to_add) { // Fix: Support multi-role assignment by not removing existing roles $advausro_user->add_role($advausro_role_to_add); } $role_manager = ADVAUSRO_RoleManager::advausro_get_instance(); $protected_roles = $role_manager->advausro_get_protected_roles(); if ($action === 'remove' && $advausro_role_to_remove) { if (!in_array($advausro_role_to_remove, $protected_roles) && in_array($advausro_role_to_remove, $advausro_user->roles)) { $advausro_user->remove_role($advausro_role_to_remove); } } if ($bulk_action === 'delete') { if (get_current_user_id() !== $advausro_user_id) { // Determine if user has a protected role BEFORE deleting $is_protected = false; foreach ($protected_roles as $role) { if (in_array($role, $advausro_user->roles)) { $is_protected = true; break; } } if (!$is_protected) { require_once ABSPATH . 'wp-admin/includes/user.php'; wp_delete_user($advausro_user_id); } } } } // Bulk export is handled in ADVAUSRO_Connector::advausro_handle_exports() add_action('admin_notices', function () use ($action, $bulk_action, $advausro_user_ids) { $count = count($advausro_user_ids); if ($bulk_action === 'delete') { echo wp_kses_post('

Selected user(s) deleted successfully.

'); } elseif ($action === 'add') { echo wp_kses_post('

Added role to ' . (int)$count . ' user(s) successfully.

'); } elseif ($action === 'remove') { echo wp_kses_post('

Removed role from ' . (int)$count . ' user(s) successfully.

'); } }); } global $wpdb, $wp_roles; // Handle search and filtering $search_term = isset($_REQUEST['s']) ? sanitize_text_field(wp_unslash($_REQUEST['s'])) : ''; $role_filter = isset($_REQUEST['role_filter']) ? sanitize_text_field(wp_unslash($_REQUEST['role_filter'])) : ''; $paged = isset($_REQUEST['paged']) ? max(1, absint(wp_unslash($_REQUEST['paged']))) : 1; $per_page = 20; $offset = ($paged - 1) * $per_page; $query = "SELECT u.ID, u.user_login, u.user_email, u.display_name FROM {$wpdb->users} u"; $where = []; $params = []; if (!empty($search_term)) { $where[] = "(u.user_login LIKE %s OR u.user_email LIKE %s OR u.display_name LIKE %s)"; $like = '%' . $wpdb->esc_like($search_term) . '%'; $params[] = $like; $params[] = $like; $params[] = $like; } if (!empty($role_filter)) { $query .= " INNER JOIN {$wpdb->usermeta} um ON u.ID = um.user_id AND um.meta_key = %s"; $params[] = $wpdb->prefix . 'capabilities'; $where[] = "um.meta_value LIKE %s"; $params[] = '%' . $wpdb->esc_like('"' . $role_filter . '"') . '%'; } if (!empty($where)) { $query .= " WHERE " . implode(' AND ', $where); } $count_query = "SELECT COUNT(*) FROM {$wpdb->users} u"; if (!empty($role_filter)) { $count_query .= " INNER JOIN {$wpdb->usermeta} um ON u.ID = um.user_id AND um.meta_key = %s"; } if (!empty($where)) { $count_query .= " WHERE " . implode(' AND ', $where); } $query .= " LIMIT %d OFFSET %d"; $query_args = array_merge($params, [$per_page, $offset]); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter -- Query string is prepared immediately here from sanitized parts. $advausro_users = $wpdb->get_results($wpdb->prepare($query, $query_args), ARRAY_A); $total_users = !empty($params) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter -- Count query is prepared immediately here from sanitized parts. ? (int) $wpdb->get_var($wpdb->prepare($count_query, $params)) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter -- No placeholders are present when filters are empty. : (int) $wpdb->get_var($count_query); $total_pages = ceil($total_users / $per_page); $default_expires_at = new \DateTime('now', wp_timezone()); $default_expires_at_value = $default_expires_at->format('Y-m-d\TH:i'); // Define default WordPress roles $default_roles = ['administrator', 'editor', 'author', 'contributor', 'subscriber']; // Get active custom roles from the advausro_custom_roles table - FIXED: Use prepared statement // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name is built from the local WordPress prefix. $custom_roles = $wpdb->get_results("SELECT role_slug, display_name FROM {$wpdb->prefix}advausro_custom_roles", ARRAY_A); $custom_role_slugs = wp_list_pluck($custom_roles, 'role_slug'); $custom_role_names = array_column($custom_roles, 'display_name', 'role_slug'); // Combine default and custom roles for dropdowns $filtered_roles = []; foreach ($wp_roles->roles as $role_key => $role_data) { $filtered_roles[$role_key] = [ 'name' => in_array($role_key, $custom_role_slugs) && isset($custom_role_names[$role_key]) ? $custom_role_names[$role_key] : $role_data['name'] ]; } $role_manager = ADVAUSRO_RoleManager::advausro_get_instance(); $protected_roles = $role_manager->advausro_get_protected_roles(); ?>

Reset
items « ‹ of › »

'linear-gradient(135deg, #4ade80, #3b82f6)', 'B' => 'linear-gradient(135deg, #a3e635, #ecfac4)', // green/yellow 'C' => 'linear-gradient(135deg, #f87171, #fbcfe8)', 'D' => 'linear-gradient(135deg, #a3e635, #4ade80)', 'E' => 'linear-gradient(135deg, #818cf8, #a78bfa)', 'F' => 'linear-gradient(135deg, #fbbf24, #fde68a)', 'G' => 'linear-gradient(135deg, #34d399, #10b981)', 'H' => 'linear-gradient(135deg, #f472b6, #fb7185)', 'I' => 'linear-gradient(135deg, #38bdf8, #7dd3fc)', 'J' => 'linear-gradient(135deg, #fb923c, #818cf8)', // orange/purple 'K' => 'linear-gradient(135deg, #a78bfa, #c084fc)', 'L' => 'linear-gradient(135deg, #f87171, #fca5a5)', 'M' => 'linear-gradient(135deg, #34d399, #3b82f6)', 'N' => 'linear-gradient(135deg, #94a3b8, #cbd5e1)', 'O' => 'linear-gradient(135deg, #fbbf24, #f59e0b)', 'P' => 'linear-gradient(135deg, #a78bfa, #8b5cf6)', 'Q' => 'linear-gradient(135deg, #38bdf8, #0ea5e9)', 'R' => 'linear-gradient(135deg, #f472b6, #ec4899)', 'S' => 'linear-gradient(135deg, #a78bfa, #34d399)', 'T' => 'linear-gradient(135deg, #a3e635, #a78bfa)', 'U' => 'linear-gradient(135deg, #fb923c, #f97316)', 'V' => 'linear-gradient(135deg, #34d399, #059669)', 'W' => 'linear-gradient(135deg, #38bdf8, #0284c7)', 'X' => 'linear-gradient(135deg, #94a3b8, #64748b)', 'Y' => 'linear-gradient(135deg, #fbbf24, #d97706)', 'Z' => 'linear-gradient(135deg, #f87171, #dc2626)', ]; return isset($gradients[$char]) ? $gradients[$char] : 'linear-gradient(135deg, #9ca3af, #d1d5db)'; } function advausro_get_role_style($role) { // predefined styles based on the image if (strpos(strtolower($role), 'administrator') !== false) { return 'background: #fee2e2; color: #ef4444; border: 1px solid #fecaca;'; } if (strpos(strtolower($role), 'editor') !== false) { return 'background: #eff6ff; color: #3b82f6; border: 1px solid #bfdbfe;'; } if (strpos(strtolower($role), 'subscriber') !== false) { return 'background: #f3f4f6; color: #4b5563; border: 1px solid #e5e7eb;'; } if (strpos(strtolower($role), 'ppress') !== false) { return 'background: #f5f3ff; color: #8b5cf6; border: 1px solid #ddd6fe;'; } // default return 'background: #f3f4f6; color: #4b5563; border: 1px solid #e5e7eb;'; } ?> roles : []; $is_protected_user = !empty(array_intersect($user_roles, $protected_roles)); $row_bg = $row_count % 2 === 0 ? '#fcfcfc' : '#ffffff'; $row_count++; $char = substr($advausro_user['user_login'], 0, 1); $bg_gradient = advausro_get_avatar_gradient($char); ?>
Username Name Email Roles Posts
>
roles; foreach ($roles_arr as $r) { $pill_style = advausro_get_role_style($r); echo '' . esc_html($r) . ''; } if (empty($roles_arr)) { echo 'None'; } ?>
get_var($wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_author = %d AND post_status = 'publish'", $advausro_user['ID'] ))); ?>