@@ -43,6 +43,13 @@ class Settings {
4343 */
4444 private bool $ create_org_modal_queued = false ;
4545
46+ /**
47+ * Whether the role-sync form has been queued for footer render.
48+ *
49+ * @var bool
50+ */
51+ private bool $ role_sync_form_queued = false ;
52+
4653 /**
4754 * Constructor.
4855 */
@@ -1430,6 +1437,24 @@ public function render_create_org_modal(): void {
14301437 <?php
14311438 }
14321439
1440+ /**
1441+ * Render the hidden "Sync Roles to WorkOS" form.
1442+ *
1443+ * Hooked to admin_footer so its <form> sits at body level rather than nested
1444+ * inside the settings form on the Users tab. The visible submit button stays
1445+ * in the role-map actions row and is wired to this form via the HTML5 `form`
1446+ * attribute.
1447+ */
1448+ public function render_role_sync_form (): void {
1449+ ?>
1450+ <form method="post" action="<?php echo esc_url ( admin_url ( 'admin-post.php ' ) ); ?> " id="workos-role-sync-form" style="display:none">
1451+ <?php wp_nonce_field ( 'workos_sync_roles_to_workos ' ); ?>
1452+ <input type="hidden" name="action" value="workos_sync_roles_to_workos" />
1453+ <input type="hidden" name="editing_env" value="<?php echo esc_attr ( $ this ->get_editing_environment () ); ?> " />
1454+ </form>
1455+ <?php
1456+ }
1457+
14331458 /**
14341459 * Flush the organizations transient cache.
14351460 */
@@ -1650,16 +1675,19 @@ public function render_role_map(): void {
16501675 echo '</button> ' ;
16511676
16521677 // Sync Roles to WorkOS button — only when plugin is enabled and org is configured.
1678+ // The actual <form> is deferred to admin_footer (see render_role_sync_form) so it is
1679+ // not nested inside the outer options.php settings form. A nested <form> closes the
1680+ // settings form early, orphaning the "Save Settings" button so nothing persists.
16531681 if ( workos ()->is_enabled () && ! empty ( Config::get_organization_id () ) ) {
1654- echo '<form method="post" action=" ' . esc_url ( admin_url ( 'admin-post.php ' ) ) . '" id="workos-role-sync-form"> ' ;
1655- wp_nonce_field ( 'workos_sync_roles_to_workos ' );
1656- echo '<input type="hidden" name="action" value="workos_sync_roles_to_workos" /> ' ;
1657- echo '<input type="hidden" name="editing_env" value=" ' . esc_attr ( $ this ->get_editing_environment () ) . '" /> ' ;
1658- echo '<button type="submit" class="button"> ' ;
1682+ echo '<button type="submit" form="workos-role-sync-form" class="button"> ' ;
16591683 echo '<span class="dashicons dashicons-update"></span> ' ;
16601684 echo esc_html__ ( 'Sync Roles to WorkOS ' , 'integration-workos ' );
16611685 echo '</button> ' ;
1662- echo '</form> ' ;
1686+
1687+ if ( ! $ this ->role_sync_form_queued ) {
1688+ add_action ( 'admin_footer ' , [ $ this , 'render_role_sync_form ' ] );
1689+ $ this ->role_sync_form_queued = true ;
1690+ }
16631691 }
16641692
16651693 echo '</div> ' ;
0 commit comments