namespace = STOREENGINE_PLUGIN_SLUG . '/v1'; $this->rest_base = 'roles'; } public static function init() { $self = new self(); add_action( 'rest_api_init', [ $self, 'register_routes' ] ); } public function register_routes() { register_rest_route( $this->namespace, '/' . $this->rest_base, [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_items' ], 'permission_callback' => [ $this, 'permissions_check' ], ], ] ); } public function permissions_check(): bool { return current_user_can( 'manage_options' ); } /** * @param \WP_REST_Request $request * * @return \WP_REST_Response */ public function get_items( $request ) { if ( ! class_exists( '\WP_Roles' ) ) { return rest_ensure_response( [] ); } $wp_roles = wp_roles(); // One query for all per-role user counts (WP populates `avail_roles`). $counts = count_users(); $avail = $counts['avail_roles'] ?? []; $data = []; foreach ( $wp_roles->roles as $slug => $role ) { $caps = array_filter( (array) ( $role['capabilities'] ?? [] ) ); if ( in_array( $slug, self::CORE_ROLES, true ) ) { $type = 'wordpress'; } elseif ( 0 === strpos( $slug, 'storeengine_' ) ) { $type = 'storeengine'; } else { $type = 'custom'; } $data[] = [ 'slug' => $slug, 'name' => translate_user_role( $role['name'] ?? $slug ), 'type' => $type, 'user_count' => (int) ( $avail[ $slug ] ?? 0 ), 'capability_count' => count( $caps ), ]; } // Alphabetical by display name for a stable, scannable list. usort( $data, static fn( $a, $b ) => strcasecmp( $a['name'], $b['name'] ) ); return rest_ensure_response( $data ); } }