@@ -226,10 +226,17 @@ private function enqueue_role_mapping_assets(): void {
226226 $ asset ['version ' ]
227227 );
228228
229- $ wp_roles = \WorkOS \Sync \RoleMapper::get_wp_roles ();
229+ $ wp_roles = \WorkOS \Sync \RoleMapper::get_wp_roles ();
230+ $ workos_roles = $ this ->get_workos_org_roles ();
230231 wp_add_inline_script (
231232 'workos-role-mapping ' ,
232- 'window.workosRoleMapping = ' . wp_json_encode ( [ 'wpRoles ' => $ wp_roles ] ) . '; ' ,
233+ 'window.workosRoleMapping = ' . wp_json_encode (
234+ [
235+ 'wpRoles ' => $ wp_roles ,
236+ 'workosRoles ' => $ workos_roles ,
237+ 'env ' => $ this ->get_editing_environment (),
238+ ]
239+ ) . '; ' ,
233240 'before '
234241 );
235242 }
@@ -1258,13 +1265,88 @@ private function render_webhook_events_modal(): void {
12581265 echo '</div> ' ;
12591266 }
12601267
1268+ /**
1269+ * Fetch WorkOS organization roles for the editing environment.
1270+ *
1271+ * Calls the WorkOS API and caches the result in a 5-minute transient.
1272+ * Returns a slug => name map, or empty array on error.
1273+ *
1274+ * @return array<string, string> WorkOS role slug => role name.
1275+ */
1276+ private function get_workos_org_roles (): array {
1277+ $ env = $ this ->get_editing_environment ();
1278+ $ options = get_option ( "workos_ {$ env }" , [] );
1279+ $ org_id = $ options ['organization_id ' ] ?? '' ;
1280+
1281+ if ( empty ( $ org_id ) ) {
1282+ return [];
1283+ }
1284+
1285+ $ cache_key = 'workos_org_roles_ ' . $ org_id ;
1286+ $ cached = get_transient ( $ cache_key );
1287+
1288+ if ( false !== $ cached ) {
1289+ return is_array ( $ cached ) ? $ cached : [];
1290+ }
1291+
1292+ if ( ! workos ()->is_enabled () ) {
1293+ return [];
1294+ }
1295+
1296+ $ result = workos ()->api ()->list_organization_roles ( $ org_id );
1297+
1298+ if ( is_wp_error ( $ result ) || empty ( $ result ['data ' ] ) ) {
1299+ // Cache empty result briefly to avoid repeated failing calls.
1300+ set_transient ( $ cache_key , [], MINUTE_IN_SECONDS );
1301+ return [];
1302+ }
1303+
1304+ $ roles = [];
1305+ foreach ( $ result ['data ' ] as $ role ) {
1306+ $ slug = $ role ['slug ' ] ?? '' ;
1307+ $ name = $ role ['name ' ] ?? $ slug ;
1308+ if ( $ slug ) {
1309+ $ roles [ $ slug ] = $ name ;
1310+ }
1311+ }
1312+
1313+ set_transient ( $ cache_key , $ roles , 5 * MINUTE_IN_SECONDS );
1314+
1315+ return $ roles ;
1316+ }
1317+
12611318 /**
12621319 * Render the role mapping table.
12631320 */
12641321 public function render_role_map (): void {
1265- $ map = \WorkOS \Sync \RoleMapper::get_role_map ();
1266- $ wp_roles = \WorkOS \Sync \RoleMapper::get_wp_roles ();
1267- $ env = $ this ->get_editing_environment ();
1322+ $ map = \WorkOS \Sync \RoleMapper::get_role_map ();
1323+ $ wp_roles = \WorkOS \Sync \RoleMapper::get_wp_roles ();
1324+ $ workos_roles = $ this ->get_workos_org_roles ();
1325+ $ env = $ this ->get_editing_environment ();
1326+ $ has_dropdown = ! empty ( $ workos_roles );
1327+
1328+ // Out-of-sync warning banner.
1329+ $ out_of_sync = \WorkOS \Sync \RoleMapper::get_out_of_sync_users ();
1330+ if ( ! empty ( $ out_of_sync ) ) {
1331+ $ count = count ( $ out_of_sync );
1332+ printf (
1333+ '<div class="notice notice-warning inline" id="workos-role-sync-warning"><p>%s <a href="%s">%s</a></p></div> ' ,
1334+ esc_html (
1335+ sprintf (
1336+ /* translators: %d: number of out-of-sync users */
1337+ _n (
1338+ '%d user has a WordPress role that doesn \'t match their WorkOS role mapping. ' ,
1339+ '%d users have a WordPress role that doesn \'t match their WorkOS role mapping. ' ,
1340+ $ count ,
1341+ 'workos '
1342+ ),
1343+ $ count
1344+ )
1345+ ),
1346+ esc_url ( admin_url ( 'users.php?workos_sync_status=out_of_sync ' ) ),
1347+ esc_html__ ( 'View affected users ' , 'workos ' )
1348+ );
1349+ }
12681350
12691351 echo '<table id="workos-role-map-table" class="widefat"><thead><tr> ' ;
12701352 echo '<th> ' . esc_html__ ( 'WorkOS Role ' , 'workos ' ) . '</th> ' ;
@@ -1274,13 +1356,28 @@ public function render_role_map(): void {
12741356
12751357 foreach ( $ map as $ workos_role => $ wp_role ) {
12761358 echo '<tr class="workos-role-map-row"><td> ' ;
1277- printf (
1278- '<input type="text" name="workos_%s[role_map][keys][]" value="%s" class="regular-text" /> ' ,
1279- esc_attr ( $ env ),
1280- esc_attr ( $ workos_role )
1281- );
1359+ if ( $ has_dropdown ) {
1360+ printf ( '<select name="workos_%s[role_map][keys][]"> ' , esc_attr ( $ env ) );
1361+ echo '<option value=""> ' . esc_html__ ( '— No Role — ' , 'workos ' ) . '</option> ' ;
1362+ foreach ( $ workos_roles as $ slug => $ name ) {
1363+ printf (
1364+ '<option value="%s" %s>%s</option> ' ,
1365+ esc_attr ( $ slug ),
1366+ selected ( $ workos_role , $ slug , false ),
1367+ esc_html ( $ name )
1368+ );
1369+ }
1370+ echo '</select> ' ;
1371+ } else {
1372+ printf (
1373+ '<input type="text" name="workos_%s[role_map][keys][]" value="%s" class="regular-text" /> ' ,
1374+ esc_attr ( $ env ),
1375+ esc_attr ( $ workos_role )
1376+ );
1377+ }
12821378 echo '</td><td> ' ;
12831379 printf ( '<select name="workos_%s[role_map][values][]"> ' , esc_attr ( $ env ) );
1380+ echo '<option value=""> ' . esc_html__ ( '— No Role — ' , 'workos ' ) . '</option> ' ;
12841381 foreach ( $ wp_roles as $ slug => $ name ) {
12851382 printf (
12861383 '<option value="%s" %s>%s</option> ' ,
@@ -1295,14 +1392,23 @@ public function render_role_map(): void {
12951392
12961393 // Empty row for no-JS fallback.
12971394 echo '<tr class="workos-role-map-row"><td> ' ;
1298- printf (
1299- '<input type="text" name="workos_%s[role_map][keys][]" value="" class="regular-text" placeholder="%s" /> ' ,
1300- esc_attr ( $ env ),
1301- esc_attr__ ( 'New WorkOS role... ' , 'workos ' )
1302- );
1395+ if ( $ has_dropdown ) {
1396+ printf ( '<select name="workos_%s[role_map][keys][]"> ' , esc_attr ( $ env ) );
1397+ echo '<option value=""> ' . esc_html__ ( '— No Role — ' , 'workos ' ) . '</option> ' ;
1398+ foreach ( $ workos_roles as $ slug => $ name ) {
1399+ printf ( '<option value="%s">%s</option> ' , esc_attr ( $ slug ), esc_html ( $ name ) );
1400+ }
1401+ echo '</select> ' ;
1402+ } else {
1403+ printf (
1404+ '<input type="text" name="workos_%s[role_map][keys][]" value="" class="regular-text" placeholder="%s" /> ' ,
1405+ esc_attr ( $ env ),
1406+ esc_attr__ ( 'New WorkOS role... ' , 'workos ' )
1407+ );
1408+ }
13031409 echo '</td><td> ' ;
13041410 printf ( '<select name="workos_%s[role_map][values][]"> ' , esc_attr ( $ env ) );
1305- echo '<option value=""> ' . esc_html__ ( '— Select — ' , 'workos ' ) . '</option> ' ;
1411+ echo '<option value=""> ' . esc_html__ ( '— No Role — ' , 'workos ' ) . '</option> ' ;
13061412 foreach ( $ wp_roles as $ slug => $ name ) {
13071413 printf ( '<option value="%s">%s</option> ' , esc_attr ( $ slug ), esc_html ( $ name ) );
13081414 }
0 commit comments