Index: includes/admin/users.php
===================================================================
--- includes/admin/users.php	(revision 4362)
+++ includes/admin/users.php	(working copy)
@@ -50,8 +50,12 @@
 		add_action( 'edit_user_profile', array( $this, 'secondary_role_display' ) );
 
 		// WordPress user screen
+		add_action( 'restrict_manage_users',      array( $this, 'user_role_bulk_dropdown' ) );
 		add_filter( 'manage_users_columns',       array( $this, 'user_role_column' )        );
 		add_filter( 'manage_users_custom_column', array( $this, 'user_role_row'    ), 10, 3 );
+
+		// Process bulk role change
+		add_action( 'load-users.php', array( $this, 'user_role_bulk_change' ) );
 	}
 
 	/**
@@ -107,6 +111,86 @@
 	}
 
 	/**
+	 * Add bulk dropdown forum role dropdown controls to the WordPress 
+	 * Users table
+	 *
+	 * @return bool Always false
+	 */
+	public static function user_role_bulk_dropdown() {
+
+		// Bail if current user cannot promote users 
+		if ( !current_user_can( 'promote_users' ) )
+			return; ?>
+
+		<label class="screen-reader-text" for="bbp_new_role"><?php _e( 'Change forum role to&hellip;', 'bbpress' ) ?></label>
+		<select name="bbp_new_role" id="bbp_new_role" style="display:inline-block;float:none;">
+			<option value=''><?php _e( 'Change forum role to&hellip;', 'bbpress' ) ?></option>
+			<?php foreach ( bbp_get_dynamic_roles() as $role => $details ) : ?>
+
+				<option value="<?php echo esc_attr( $role ); ?>"><?php echo translate_user_role( $details['name'] ); ?></option>
+
+			<?php endforeach; ?>
+		</select>
+		<?php submit_button( __( 'Change Role' ), 'secondary', 'bbp_change_role', false ); ?>
+
+		<?php
+	}
+
+	/**
+	 * Process bulk dropdown form submission from the WordPress Users
+	 * Table
+	 *
+	 * @uses current_user_can() to check for 'promote users' capability
+	 * @uses bbp_get_dynamic_roles() to get forum roles
+	 * @uses bbp_get_user_role() to get a user's current forums role
+	 * @uses bbp_set_user_role() to set the user's new forums role
+	 * @return bool Always false
+	 */
+	public function user_role_bulk_change() {
+		global $current_user, $wp_roles;
+
+		if ( !current_user_can( 'moderate' ) )
+			return;
+
+		// Bail if no users specified
+		if ( !isset( $_REQUEST['users'] ) || empty( $_REQUEST['users'] ) )
+			return;
+
+		// Bail if this isn't a bbPress action
+		if ( !isset( $_REQUEST['bbp_new_role'] ) || empty( $_REQUEST['bbp_new_role'] ) )
+			return;
+
+		// Check that the new role exists
+		$editable_roles = bbp_get_dynamic_roles();
+		if ( empty( $editable_roles[$_REQUEST['bbp_new_role']] ) )
+			return;
+
+		// Run through user ids
+		$user_ids = $_REQUEST['users'];
+		foreach ( (array) $user_ids as $user_id ) {
+
+			// Set up user and role data
+			$user_id = (int) $user_id;
+			$user = get_userdata( $user_id );
+			$current_role = bbp_get_user_role( $user_id );
+			$new_role = sanitize_text_field( $_REQUEST['bbp_new_role'] );
+
+			// Don't let a user demote themselves 
+			if ( $user_id == $current_user->ID ) 
+				continue;
+
+			// Don't let a Moderator change Keymaster roles 
+			if ( bbp_get_user_role( $current_user->ID ) == bbp_get_moderator_role() 
+				&& ( $current_role == bbp_get_keymaster_role() || $new_role == bbp_get_keymaster_role() ) )
+				continue;
+
+			// Set the new forums role
+			if ( $new_role != $current_role )
+				bbp_set_user_role( $user_id, $new_role );
+		}
+	}
+
+	/**
 	 * Add Forum Role column to the WordPress Users table, and change the
 	 * core role title to "Site Role"
 	 *
@@ -117,7 +201,7 @@
 	 */
 	public static function user_role_column( $columns = array() ) {
 		$columns['role']          = __( 'Site Role',  'bbpress' );
-    	$columns['bbp_user_role'] = __( 'Forum Role', 'bbpress' );
+		$columns['bbp_user_role'] = __( 'Forum Role', 'bbpress' );
 
 		return $columns;
 	}
