diff --git bp-groups/bp-groups-classes.php bp-groups/bp-groups-classes.php
index 6106e46..0315704 100644
--- bp-groups/bp-groups-classes.php
+++ bp-groups/bp-groups-classes.php
@@ -1447,6 +1447,14 @@ class BP_Groups_Group {
 /**
  * Query for the members of a group.
  *
+ * Special notes about the group members data schema:
+ * - *Members* are entries with is_confirmed = 1
+ * - *Pending requests* are entries with is_confirmed = 0 and inviter_id = 0
+ * - *Pending and sent invitations* are entries with is_confirmed = 0 and
+ *   inviter_id != 0 and invite_sent = 1
+ * - *Pending and unsent invitations* are entries with is_confirmed = 0 and
+ *   inviter_id != 0 and invite_sent = 0
+ *
  * @since BuddyPress (1.8.0)
  */
 class BP_Group_Member_Query extends BP_User_Query {
@@ -1501,6 +1509,8 @@ class BP_Group_Member_Query extends BP_User_Query {
 			'group_id'     => 0,
 			'group_role'   => array( 'member' ),
 			'is_confirmed' => true,
+			'invite_sent'  => null,
+			'inviter_id'   => null,
 			'type'         => 'last_joined',
 		) );
 
@@ -1550,6 +1560,35 @@ class BP_Group_Member_Query extends BP_User_Query {
 		$is_confirmed = ! empty( $this->query_vars['is_confirmed'] ) ? 1 : 0;
 		$sql['where'][] = $wpdb->prepare( "is_confirmed = %d", $is_confirmed );
 
+		// invite_sent
+		if ( ! is_null( $this->query_vars['invite_sent'] ) ) {
+			$invite_sent = ! empty( $this->query_vars['invite_sent'] ) ? 1 : 0;
+			$sql['where'][] = $wpdb->prepare( "invite_sent = %d", $invite_sent );
+		}
+
+		// inviter_id
+		if ( ! is_null( $this->query_vars['inviter_id'] ) ) {
+			$inviter_id = $this->query_vars['inviter_id'];
+
+			// Empty: inviter_id = 0. (pass false, 0, or empty array)
+			if ( empty( $inviter_id ) ) {
+				$sql['where'][] = "inviter_id = 0";
+
+			// The string 'any' matches any non-zero value (inviter_id != 0)
+			} else if ( 'any' === $inviter_id ) {
+				$sql['where'][] = "inviter_id != 0";
+
+			// Assume that a list of inviter IDs has been passed
+			} else {
+				// Parse and sanitize
+				$inviter_ids = wp_parse_id_list( $inviter_id );
+				if ( ! empty( $inviter_ids ) ) {
+					$inviter_ids_sql = implode( ',', $inviter_ids );
+					$sql['where'][] = "inviter_id IN ({$inviter_ids_sql})";
+				}
+			}
+		}
+
 		// Role information is stored as follows: admins have
 		// is_admin = 1, mods have is_mod = 1, banned have is_banned =
 		// 1, and members have all three set to 0.
diff --git bp-groups/bp-groups-template.php bp-groups/bp-groups-template.php
index fe6c837..70f4350 100644
--- bp-groups/bp-groups-template.php
+++ bp-groups/bp-groups-template.php
@@ -3085,9 +3085,56 @@ class BP_Groups_Invite_Template {
 	var $pag_links;
 	var $total_invite_count;
 
-	function __construct( $user_id, $group_id ) {
-		$this->invites      = groups_get_invites_for_group( $user_id, $group_id );
-		$this->invite_count = count( $this->invites );
+	public function __construct( $args = array() ) {
+
+		// Backward compatibility with old method of passing arguments
+		if ( ! is_array( $args ) || func_num_args() > 1 ) {
+			_deprecated_argument( __METHOD__, '2.0.0', sprintf( __( 'Arguments passed to %1$s should be in an associative array. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) );
+
+			$old_args_keys = array(
+				0  => 'user_id',
+				1  => 'group_id',
+			);
+
+			$func_args = func_get_args();
+			$args      = bp_core_parse_args_array( $old_args_keys, $func_args );
+		}
+
+		$r = wp_parse_args( $args, array(
+			'user_id'  => bp_loggedin_user_id(),
+			'group_id' => bp_get_current_group_id(),
+			'page'     => 1,
+			'per_page' => 10,
+		) );
+
+		$this->pag_num  = intval( $r['per_page'] );
+		$this->pag_page = isset( $_REQUEST['invitepage'] ) ? intval( $_REQUEST['invitepage'] ) : $r['page'];
+
+		$iquery = new BP_Group_Member_Query( array(
+			'group_id' => $r['group_id'],
+			'type'     => 'first_joined',
+			'per_page' => $this->pag_num,
+			'page'     => $this->pag_page,
+
+			// These filters ensure we get only pending invites
+			'is_confirmed' => false,
+			'inviter_id'   => $r['user_id'],
+		) );
+		$this->invite_data = $iquery->results;
+
+		$this->total_invite_count = $iquery->total_users;
+		$this->invites		  = array_values( wp_list_pluck( $this->invite_data, 'ID' ) );
+		$this->invite_count       = count( $this->invites );
+
+		$this->pag_links = paginate_links( array(
+			'base'      => add_query_arg( 'invitepage', '%#%' ),
+			'format'    => '',
+			'total'     => ceil( $this->total_invite_count / $this->pag_num ),
+			'current'   => $this->pag_page,
+			'prev_text' => '&larr;',
+			'next_text' => '&rarr;',
+			'mid_size'  => 1,
+		) );
 	}
 
 	function has_invites() {
@@ -3125,11 +3172,24 @@ class BP_Groups_Invite_Template {
 
 	function the_invite() {
 		global $group_id;
-
 		$this->in_the_loop      = true;
 		$user_id                = $this->next_invite();
+
 		$this->invite           = new stdClass;
-		$this->invite->user     = new BP_Core_User( $user_id );
+		$this->invite->user     = $this->invite_data[ $user_id ];
+
+		// This method previously populated the user object with
+		// BP_Core_User. We manually configure BP_Core_User data for
+		// backward compatibility.
+		$this->invite->user->profile_data = BP_XProfile_ProfileData::get_all_for_user( $user_id );
+		$this->invite->user->avatar       = bp_core_fetch_avatar( array( 'item_id' => $user_id, 'type' => 'full', 'alt' => sprintf( __( 'Avatar of %s', 'buddypress' ), $this->invite->user->fullname ) ) );
+		$this->invite->user->avatar_thumb = bp_core_fetch_avatar( array( 'item_id' => $user_id, 'type' => 'thumb', 'alt' => sprintf( __( 'Avatar of %s', 'buddypress' ), $this->invite->user->fullname ) ) );
+		$this->invite->user->avatar_mini  = bp_core_fetch_avatar( array( 'item_id' => $user_id, 'type' => 'thumb', 'alt' => sprintf( __( 'Avatar of %s', 'buddypress' ), $this->invite->user->fullname ), 'width' => 30, 'height' => 30 ) );
+		$this->invite->user->email        = $this->invite->user->user_email;
+		$this->invite->user->user_url     = bp_core_get_user_domain( $user_id, $this->invite->user->user_nicename, $this->invite->user->user_login );
+		$this->invite->user->user_link    = "<a href='{$this->invite->user->user_url}' title='{$this->invite->user->fullname}'>{$this->invite->user->fullname}</a>";
+		$this->invite->user->last_active  = bp_core_get_last_activity( $this->invite->user->last_activity, __( 'active %s', 'buddypress' ) );
+
 		$this->invite->group_id = $group_id; // Globaled in bp_group_has_invites()
 
 		if ( 0 == $this->current_invite ) // loop has just started
@@ -3138,29 +3198,31 @@ class BP_Groups_Invite_Template {
 }
 
 function bp_group_has_invites( $args = '' ) {
-	global $bp, $invites_template, $group_id;
+	global $invites_template, $group_id;
+	$bp = buddypress();
 
 	$defaults = array(
-		'group_id' => false,
-		'user_id' => bp_loggedin_user_id()
+		'group_id' 	=> false,
+		'user_id' 	=> bp_loggedin_user_id(),
+		'per_page' 	=> 10,
+		'page'     	=> 1
 	);
 
 	$r = wp_parse_args( $args, $defaults );
-	extract( $r, EXTR_SKIP );
 
-	if ( !$group_id ) {
+	if ( !$r['group_id'] ) {
 		// Backwards compatibility
 		if ( !empty( $bp->groups->current_group ) )
-			$group_id = $bp->groups->current_group->id;
+			$r['group_id'] = $bp->groups->current_group->id;
 
 		if ( !empty( $bp->groups->new_group_id ) )
-			$group_id = $bp->groups->new_group_id;
+			$r['group_id'] = $bp->groups->new_group_id;
 	}
 
-	if ( !$group_id )
+	if ( !$r['group_id'] )
 		return false;
 
-	$invites_template = new BP_Groups_Invite_Template( $user_id, $group_id );
+	$invites_template = new BP_Groups_Invite_Template( $r );
 	return apply_filters( 'bp_group_has_invites', $invites_template->has_invites(), $invites_template );
 }
 
@@ -3221,6 +3283,48 @@ function bp_group_invite_user_remove_invite_url() {
 		return wp_nonce_url( site_url( bp_get_groups_slug() . '/' . $invites_template->invite->group_id . '/invites/remove/' . $invites_template->invite->user->id ), 'groups_invite_uninvite_user' );
 	}
 
+/**
+ * Output pagination links for group invitations.
+ *
+ * @since BuddyPress (2.0.0)
+ */
+function bp_group_invite_pagination_links() {
+	echo bp_get_group_invite_pagination_links();
+}
+	/**
+	 * Get pagination links for group invitations.
+	 *
+	 * @since BuddyPress (2.0.0)
+	 */
+	function bp_get_group_invite_pagination_links() {
+		global $invites_template;
+		return apply_filters( 'bp_get_group_invite_pagination_links', $invites_template->pag_links );
+	}
+
+/**
+ * Output pagination count text for group invitations.
+ *
+ * @since BuddyPress (2.0.0)
+ */
+function bp_group_invite_pagination_count() {
+	echo bp_get_group_invite_pagination_count();
+}
+	/**
+	 * Get pagination count text for group invitations.
+	 *
+	 * @since BuddyPress (2.0.0)
+	 */
+	function bp_get_group_invite_pagination_count() {
+		global $invites_template;
+
+		$start_num = intval( ( $invites_template->pag_page - 1 ) * $invites_template->pag_num ) + 1;
+		$from_num  = bp_core_number_format( $start_num );
+		$to_num    = bp_core_number_format( ( $start_num + ( $invites_template->pag_num - 1 ) > $invites_template->total_invite_count ) ? $invites_template->total_invite_count : $start_num + ( $invites_template->pag_num - 1 ) );
+		$total     = bp_core_number_format( $invites_template->total_invite_count );
+
+		return apply_filters( 'bp_get_groups_pagination_count', sprintf( _n( 'Viewing invitation %1$s to %2$s (of %3$s invitation)', 'Viewing invitation %1$s to %2$s (of %3$s invitations)', $total, 'buddypress' ), $from_num, $to_num, $total ), $from_num, $to_num, $total );
+	}
+
 /***
  * Groups RSS Feed Template Tags
  */
diff --git bp-templates/bp-legacy/buddypress-functions.php bp-templates/bp-legacy/buddypress-functions.php
index d8963f5..93efcef 100644
--- bp-templates/bp-legacy/buddypress-functions.php
+++ bp-templates/bp-legacy/buddypress-functions.php
@@ -139,6 +139,7 @@ class BP_Legacy extends BP_Theme_Compat {
 			'groups_filter'   => 'bp_legacy_theme_object_template_loader',
 			'members_filter'  => 'bp_legacy_theme_object_template_loader',
 			'messages_filter' => 'bp_legacy_theme_messages_template_loader',
+			'invite_filter'   => 'bp_legacy_theme_invite_template_loader',
 
 			// Friends
 			'accept_friendship' => 'bp_legacy_theme_ajax_accept_friendship',
@@ -601,6 +602,16 @@ function bp_legacy_theme_messages_template_loader() {
 }
 
 /**
+ * Load group invitations loop to handle pagination requests sent via AJAX.
+ *
+ * @since BuddyPress (2.0.0)
+ */
+function bp_legacy_theme_invite_template_loader() {
+	bp_get_template_part( 'groups/single/invites-loop' );
+	exit();
+}
+
+/**
  * Load the activity loop template when activity is requested via AJAX,
  *
  * @return string JSON object containing 'contents' (output of the template loop
diff --git bp-templates/bp-legacy/buddypress/groups/single/invites-loop.php bp-templates/bp-legacy/buddypress/groups/single/invites-loop.php
new file mode 100644
index 0000000..5df7144
--- /dev/null
+++ bp-templates/bp-legacy/buddypress/groups/single/invites-loop.php
@@ -0,0 +1,93 @@
+<div class="left-menu">
+
+	<div id="invite-list">
+
+		<ul>
+			<?php bp_new_group_invite_friend_list(); ?>
+		</ul>
+
+		<?php wp_nonce_field( 'groups_invite_uninvite_user', '_wpnonce_invite_uninvite_user' ); ?>
+
+	</div>
+
+</div><!-- .left-menu -->
+
+<div class="main-column">
+
+	<div id="message" class="info">
+		<p><?php _e('Select people to invite from your friends list.', 'buddypress' ); ?></p>
+	</div>
+
+	<?php do_action( 'bp_before_group_send_invites_list' ); ?>
+
+	<?php if ( bp_group_has_invites( bp_ajax_querystring( 'invite' ) ) ) : ?>
+
+		<div id="pag-top" class="pagination">
+
+			<div class="pag-count" id="group-invite-count-top">
+
+				<?php bp_group_invite_pagination_count(); ?>
+
+			</div>
+
+			<div class="pagination-links" id="group-invite-pag-top">
+
+				<?php bp_group_invite_pagination_links(); ?>
+
+			</div>
+
+		</div>
+
+		<?php /* The ID 'friend-list' is important for AJAX support. */ ?>
+		<ul id="friend-list" class="item-list">
+
+		<?php while ( bp_group_invites() ) : bp_group_the_invite(); ?>
+
+			<li id="<?php bp_group_invite_item_id(); ?>">
+				<?php bp_group_invite_user_avatar(); ?>
+
+				<h4><?php bp_group_invite_user_link(); ?></h4>
+				<span class="activity"><?php bp_group_invite_user_last_active(); ?></span>
+
+				<?php do_action( 'bp_group_send_invites_item' ); ?>
+
+				<div class="action">
+					<a class="button remove" href="<?php bp_group_invite_user_remove_invite_url(); ?>" id="<?php bp_group_invite_item_id(); ?>"><?php _e( 'Remove Invite', 'buddypress' ); ?></a>
+
+					<?php do_action( 'bp_group_send_invites_item_action' ); ?>
+				</div>
+			</li>
+
+		<?php endwhile; ?>
+
+		</ul><!-- #friend-list -->
+
+		<div id="pag-bottom" class="pagination">
+
+			<div class="pag-count" id="group-invite-count-bottom">
+
+				<?php bp_group_invite_pagination_count(); ?>
+
+			</div>
+
+			<div class="pagination-links" id="group-invite-pag-bottom">
+
+				<?php bp_group_invite_pagination_links(); ?>
+
+			</div>
+
+		</div>
+
+	<?php endif; ?>
+
+<?php do_action( 'bp_after_group_send_invites_list' ); ?>
+
+</div><!-- .main-column -->
+
+<div class="clear"></div>
+
+<div class="submit">
+	<input type="submit" name="submit" id="submit" value="<?php esc_attr_e( 'Send Invites', 'buddypress' ); ?>" />
+</div>
+
+<?php wp_nonce_field( 'groups_send_invites', '_wpnonce_send_invites' ); ?>
\ No newline at end of file
diff --git bp-templates/bp-legacy/buddypress/groups/single/send-invites.php bp-templates/bp-legacy/buddypress/groups/single/send-invites.php
index c2f0500..6f3d9ef 100644
--- bp-templates/bp-legacy/buddypress/groups/single/send-invites.php
+++ bp-templates/bp-legacy/buddypress/groups/single/send-invites.php
@@ -2,77 +2,20 @@
 
 <?php if ( bp_get_total_friend_count( bp_loggedin_user_id() ) ) : ?>
 
+	<?php /* 'send-invite-form' is important for AJAX support */ ?>
 	<form action="<?php bp_group_send_invite_form_action(); ?>" method="post" id="send-invite-form" class="standard-form" role="main">
 
-		<div class="left-menu">
+		<div class="invite">
 
-			<div id="invite-list">
-				<ul>
-					<?php bp_new_group_invite_friend_list(); ?>
-				</ul>
+			<?php bp_get_template_part( 'groups/single/invites-loop' ); ?>
 
-				<?php wp_nonce_field( 'groups_invite_uninvite_user', '_wpnonce_invite_uninvite_user' ); ?>
-			</div>
-
-		</div><!-- .left-menu -->
-
-		<div class="main-column">
-
-			<div id="message" class="info">
-				<p><?php _e('Select people to invite from your friends list.', 'buddypress' ); ?></p>
-			</div>
-
-			<?php do_action( 'bp_before_group_send_invites_list' ); ?>
-
-			<?php /* The ID 'friend-list' is important for AJAX support. */ ?>
-			<ul id="friend-list" class="item-list">
-			<?php if ( bp_group_has_invites() ) : ?>
-
-				<?php while ( bp_group_invites() ) : bp_group_the_invite(); ?>
-
-					<li id="<?php bp_group_invite_item_id(); ?>">
-						<?php bp_group_invite_user_avatar(); ?>
-
-						<h4><?php bp_group_invite_user_link(); ?></h4>
-						<span class="activity"><?php bp_group_invite_user_last_active(); ?></span>
-
-						<?php do_action( 'bp_group_send_invites_item' ); ?>
-
-						<div class="action">
-							<a class="button remove" href="<?php bp_group_invite_user_remove_invite_url(); ?>" id="<?php bp_group_invite_item_id(); ?>"><?php _e( 'Remove Invite', 'buddypress' ); ?></a>
-
-							<?php do_action( 'bp_group_send_invites_item_action' ); ?>
-						</div>
-					</li>
-
-				<?php endwhile; ?>
-
-			<?php endif; ?>
-			</ul><!-- #friend-list -->
-
-			<?php do_action( 'bp_after_group_send_invites_list' ); ?>
-
-		</div><!-- .main-column -->
-
-		<div class="clear"></div>
-
-		<div class="submit">
-			<input type="submit" name="submit" id="submit" value="<?php esc_attr_e( 'Send Invites', 'buddypress' ); ?>" />
 		</div>
 
-		<?php wp_nonce_field( 'groups_send_invites', '_wpnonce_send_invites' ); ?>
-
 		<?php /* This is important, don't forget it */ ?>
 		<input type="hidden" name="group_id" id="group_id" value="<?php bp_group_id(); ?>" />
 
 	</form><!-- #send-invite-form -->
 
-<?php else : ?>
-
-	<div id="message" class="info" role="main">
-		<p><?php _e( 'Once you have built up friend connections you will be able to invite others to your group.', 'buddypress' ); ?></p>
-	</div>
-
 <?php endif; ?>
 
 <?php do_action( 'bp_after_group_send_invites_content' ); ?>
diff --git bp-templates/bp-legacy/css/buddypress.css bp-templates/bp-legacy/css/buddypress.css
index 6c13c70..feed445 100644
--- bp-templates/bp-legacy/css/buddypress.css
+++ bp-templates/bp-legacy/css/buddypress.css
@@ -764,6 +764,7 @@ a.bp-title-button {
 
 #buddypress form.standard-form .main-column ul#friend-list {
 	clear:none;
+	float: left;
 }
 
 #buddypress form.standard-form .main-column ul#friend-list h4 {
@@ -1087,7 +1088,7 @@ a.bp-title-button {
 	background-color: #ffd;
 	border: 1px solid #cb2;
 	color: #440;
-	
+
 }
 #buddypress div#item-header {
 	overflow: hidden;
diff --git bp-templates/bp-legacy/js/buddypress.js bp-templates/bp-legacy/js/buddypress.js
index 3afc762..5b84784 100644
--- bp-templates/bp-legacy/js/buddypress.js
+++ bp-templates/bp-legacy/js/buddypress.js
@@ -901,9 +901,12 @@ jq(document).ready( function() {
 	/** Invite Friends Interface ****************************************/
 
 	/* Select a user from the list of friends and add them to the invite list */
-	jq("#invite-list input").on( 'click', function() {
+	jq("#send-invite-form").on( 'click', '#invite-list input', function() {
 		jq('.ajax-loader').toggle();
 
+		// Dim the form until the response arrives
+		jq( this ).parents( 'ul' ).find( 'input' ).prop( 'disabled', true );
+
 		var friend_id = jq(this).val();
 
 		if ( jq(this).prop('checked') == true )
@@ -926,20 +929,13 @@ jq(document).ready( function() {
 			if ( jq("#message") )
 				jq("#message").hide();
 
-			jq('.ajax-loader').toggle();
-
-			if ( friend_action == 'invite' ) {
-				jq('#friend-list').append(response);
-			} else if ( friend_action == 'uninvite' ) {
-				jq('#friend-list li#uid-' + friend_id).remove();
-			}
-
-			jq('.item-list-tabs li.selected').removeClass('loading');
+			// Refresh entire list (keeps pagination and totals up to date)
+			bp_filter_request( 'invite', 'bp-invite-filter', 'bp-invite-scope', 'div.invite', false, 1, '', '', '' );
 		});
 	});
 
 	/* Remove a user from the list of users to invite to a group */
-	jq("#friend-list").on('click', 'li a.remove', function() {
+	jq("#send-invite-form").on('click', 'a.remove', function() {
 		jq('.ajax-loader').toggle();
 
 		var friend_id = jq(this).attr('id');
@@ -956,9 +952,8 @@ jq(document).ready( function() {
 		},
 		function(response)
 		{
-			jq('.ajax-loader').toggle();
-			jq('#friend-list #uid-' + friend_id).remove();
-			jq('#invite-list #f-' + friend_id).prop('checked', false);
+			// Refresh entire list (keeps pagination and totals up to date)
+			bp_filter_request( 'invite', 'bp-invite-filter', 'bp-invite-scope', 'div.invite', false, 1, '', '', '' );
 		});
 
 		return false;
diff --git tests/includes/testcase.php tests/includes/testcase.php
index 2556db1..aa91133 100644
--- tests/includes/testcase.php
+++ tests/includes/testcase.php
@@ -241,6 +241,8 @@ class BP_UnitTestCase extends WP_UnitTestCase {
 		$r = wp_parse_args( $args, array(
 			'date_modified' => bp_core_current_time(),
 			'is_confirmed' => 1,
+			'invite_sent' => 0,
+			'inviter_id' => 0,
 		) );
 
 		$new_member                = new BP_Groups_Member;
@@ -251,6 +253,8 @@ class BP_UnitTestCase extends WP_UnitTestCase {
 		$new_member->user_title    = '';
 		$new_member->date_modified = $r['date_modified'];
 		$new_member->is_confirmed  = $r['is_confirmed'];
+		$new_member->invite_sent   = $r['invite_sent'];
+		$new_member->inviter_id    = $r['inviter_id'];
 
 		$new_member->save();
 		return $new_member->id;
diff --git tests/testcases/groups/class-bp-group-member-query.php tests/testcases/groups/class-bp-group-member-query.php
index b38943f..955a86b 100644
--- tests/testcases/groups/class-bp-group-member-query.php
+++ tests/testcases/groups/class-bp-group-member-query.php
@@ -422,4 +422,174 @@ class BP_Tests_BP_Group_Member_Query_TestCases extends BP_UnitTestCase {
 		$ids = wp_parse_id_list( array_keys( $query_members->results ) );
 		$this->assertEquals( array( $u1, $u3, $u2 ), $ids );
 	}
+
+	/**
+	 * @group invite_sent
+	 */
+	public function test_with_invite_sent_true() {
+		$g = $this->factory->group->create();
+		$u1 = $this->create_user();
+		$u2 = $this->create_user();
+		$time = time();
+
+		$this->add_user_to_group( $u1, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 100 ),
+			'is_confirmed' => 0,
+			'invite_sent' => 0,
+		) );
+
+		$this->add_user_to_group( $u2, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 100 ),
+			'is_confirmed' => 0,
+			'invite_sent' => 1,
+		) );
+
+		$query_members = new BP_Group_Member_Query( array(
+			'group_id' => $g,
+			'is_confirmed' => false,
+			'invite_sent' => true,
+		) );
+
+		$ids = wp_parse_id_list( array_keys( $query_members->results ) );
+		$this->assertEquals( array( $u2 ), $ids );
+	}
+
+	/**
+	 * @group invite_sent
+	 */
+	public function test_with_invite_sent_false() {
+		$g = $this->factory->group->create();
+		$u1 = $this->create_user();
+		$u2 = $this->create_user();
+		$time = time();
+
+		$this->add_user_to_group( $u1, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 100 ),
+			'is_confirmed' => 0,
+			'invite_sent' => 0,
+		) );
+
+		$this->add_user_to_group( $u2, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 100 ),
+			'is_confirmed' => 0,
+			'invite_sent' => 1,
+		) );
+
+		$query_members = new BP_Group_Member_Query( array(
+			'group_id' => $g,
+			'is_confirmed' => false,
+			'invite_sent' => false,
+		) );
+
+		$ids = wp_parse_id_list( array_keys( $query_members->results ) );
+		$this->assertEquals( array( $u1 ), $ids );
+	}
+
+	/**
+	 * @group inviter_id
+	 */
+	public function test_with_inviter_id_false() {
+		$g = $this->factory->group->create();
+		$u1 = $this->create_user();
+		$u2 = $this->create_user();
+		$time = time();
+
+		$this->add_user_to_group( $u1, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 100 ),
+			'inviter_id' => 0,
+		) );
+
+		$this->add_user_to_group( $u2, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 100 ),
+			'inviter_id' => 1,
+		) );
+
+		$query_members = new BP_Group_Member_Query( array(
+			'group_id' => $g,
+			'inviter_id' => false,
+		) );
+
+		$ids = wp_parse_id_list( array_keys( $query_members->results ) );
+		$this->assertEquals( array( $u1 ), $ids );
+	}
+
+	/**
+	 * @group inviter_id
+	 */
+	public function test_with_inviter_id_specific() {
+		$g = $this->factory->group->create();
+		$u1 = $this->create_user();
+		$u2 = $this->create_user();
+		$u3 = $this->create_user();
+		$u4 = $this->create_user();
+		$time = time();
+
+		$this->add_user_to_group( $u1, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 100 ),
+			'inviter_id' => 0,
+		) );
+
+		$this->add_user_to_group( $u2, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 200 ),
+			'inviter_id' => 1,
+		) );
+
+		$this->add_user_to_group( $u3, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 300 ),
+			'inviter_id' => 6,
+		) );
+
+		$this->add_user_to_group( $u4, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 400 ),
+			'inviter_id' => 2,
+		) );
+
+		$query_members = new BP_Group_Member_Query( array(
+			'group_id' => $g,
+			'inviter_id' => array( 2, 6 ),
+		) );
+
+		$ids = wp_parse_id_list( array_keys( $query_members->results ) );
+		$this->assertEquals( array( $u3, $u4 ), $ids );
+	}
+
+	/**
+	 * @group inviter_id
+	 */
+	public function test_with_inviter_id_any() {
+		$g = $this->factory->group->create();
+		$u1 = $this->create_user();
+		$u2 = $this->create_user();
+		$u3 = $this->create_user();
+		$u4 = $this->create_user();
+		$time = time();
+
+		$this->add_user_to_group( $u1, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 100 ),
+			'inviter_id' => 0,
+		) );
+
+		$this->add_user_to_group( $u2, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 200 ),
+			'inviter_id' => 1,
+		) );
+
+		$this->add_user_to_group( $u3, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 300 ),
+			'inviter_id' => 6,
+		) );
+
+		$this->add_user_to_group( $u4, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 400 ),
+			'inviter_id' => 2,
+		) );
+
+		$query_members = new BP_Group_Member_Query( array(
+			'group_id' => $g,
+			'inviter_id' => 'any',
+		) );
+
+		$ids = wp_parse_id_list( array_keys( $query_members->results ) );
+		$this->assertEquals( array( $u2, $u3, $u4 ), $ids );
+	}
 }
diff --git tests/testcases/groups/template.php tests/testcases/groups/template.php
index 8a5c279..b335317 100644
--- tests/testcases/groups/template.php
+++ tests/testcases/groups/template.php
@@ -407,4 +407,44 @@ class BP_Tests_Groups_Template extends BP_UnitTestCase {
 		$ids = wp_parse_id_list( wp_list_pluck( $members_template->members, 'user_id' ) );
 		$this->assertEquals( array( $u1, $u3, $u2, ), $ids );
 	}
+
+	/**
+	 * @group bp_group_has_invites
+	 * @group BP_Groups_Invite_Template
+	 */
+	public function test_bp_group_has_invites_pagination() {
+		$u1 = $this->create_user( array(
+			'last_activity' => gmdate( 'Y-m-d H:i:s', time() - 60 ),
+		) );
+
+		$g = $this->factory->group->create( array(
+			'creator_id' => $u1,
+		) );
+
+		$users = array();
+		for ( $i = 1; $i < 15; $i++ ) {
+			$users[ $i ] = $this->create_user( array(
+				'last_activity' => gmdate( 'Y-m-d H:i:s', time() - $i ),
+			) );
+
+			$this->add_user_to_group( $users[ $i ], $g, array(
+				'date_modified' => gmdate( 'Y-m-d H:i:s', time() - $i ),
+				'is_confirmed' => 0,
+				'inviter_id' => $u1,
+				'invite_sent' => true,
+			) );
+		}
+
+		// Populate the global
+		bp_group_has_invites( array(
+			'group_id' => $g,
+			'user_id' => $u1,
+			'page' => 2,
+			'per_page' => 5,
+		) );
+
+		global $invites_template;
+
+		$this->assertEquals( array( $users[ 9 ], $users[ 8 ], $users[ 7 ], $users[ 6 ], $users[ 5 ], ), $invites_template->invites );
+	}
 }
diff --git tests/testcases/groups/template.php.orig tests/testcases/groups/template.php.orig
new file mode 100644
index 0000000..8a5c279
--- /dev/null
+++ tests/testcases/groups/template.php.orig
@@ -0,0 +1,410 @@
+<?php
+/**
+ * @group groups
+ * @group template
+ */
+class BP_Tests_Groups_Template extends BP_UnitTestCase {
+	public function setUp() {
+		parent::setUp();
+	}
+
+	public function tearDown() {
+		parent::tearDown();
+	}
+
+	/**
+	 * Integration test to make sure meta_query is getting passed through
+	 *
+	 * @group bp_has_groups
+	 */
+	public function test_bp_has_groups_with_meta_query() {
+		$g1 = $this->factory->group->create();
+		$g2 = $this->factory->group->create();
+		groups_update_groupmeta( $g1, 'foo', 'bar' );
+
+		global $groups_template;
+		bp_has_groups( array(
+			'meta_query' => array(
+				array(
+					'key' => 'foo',
+					'value' => 'bar',
+				),
+			),
+		) );
+
+		$ids = wp_list_pluck( $groups_template->groups, 'id' );
+		$this->assertEquals( $ids, array( $g1, ) );
+	}
+
+	/**
+	 * Integration test to make sure order and orderby are interpreted when
+	 * no 'type' value has been passed
+	 *
+	 * @group bp_has_groups
+	 */
+	public function test_bp_has_groups_with_order_orderby_with_null_type() {
+		$g1 = $this->factory->group->create( array(
+			'name' => 'AAAAA',
+			'date_created' => gmdate( 'Y-m-d H:i:s', time() - 100 ),
+			'last_activity' => gmdate( 'Y-m-d H:i:s', time() - 1000000 ),
+		) );
+		$g2 = $this->factory->group->create( array(
+			'name' => 'BBBBB',
+			'date_created' => gmdate( 'Y-m-d H:i:s', time() - 1000000 ),
+			'last_activity' => gmdate( 'Y-m-d H:i:s', time() - 10000 ),
+		) );
+		$g3 = $this->factory->group->create( array(
+			'name' => 'CCCCC',
+			'date_created' => gmdate( 'Y-m-d H:i:s', time() - 10000 ),
+			'last_activity' => gmdate( 'Y-m-d H:i:s', time() - 10 ),
+		) );
+
+		global $groups_template;
+		bp_has_groups( array(
+			'order' => 'ASC',
+			'orderby' => 'name',
+		) );
+
+		$ids = wp_parse_id_list( wp_list_pluck( $groups_template->groups, 'id' ) );
+		$this->assertEquals( array( $g1, $g2, $g3, ), $ids );
+	}
+
+	/**
+	 * Integration test to make sure 'order' is set to 'DESC' and 'orderby'
+	 * to 'last_activity' when no type or order/orderby params are passed.
+	 * This ensures backpat with the old system, where 'active' was the
+	 * default type param, and there were no order/orderby params.
+	 *
+	 * @group bp_has_groups
+	 */
+	public function test_bp_has_groups_defaults_to_DESC_last_activity_for_default_type_active_backpat() {
+		$g1 = $this->factory->group->create( array(
+			'name' => 'AAAAA',
+			'last_activity' => gmdate( 'Y-m-d H:i:s', time() - 100 ),
+		) );
+		$g2 = $this->factory->group->create( array(
+			'name' => 'BBBBB',
+			'last_activity' => gmdate( 'Y-m-d H:i:s', time() - 1000000 ),
+		) );
+		$g3 = $this->factory->group->create( array(
+			'name' => 'CCCCC',
+			'last_activity' => gmdate( 'Y-m-d H:i:s', time() - 10000 ),
+		) );
+
+		global $groups_template;
+		bp_has_groups();
+
+		$ids = wp_parse_id_list( wp_list_pluck( $groups_template->groups, 'id' ) );
+		$this->assertEquals( array( $g1, $g3, $g2, ), $ids );
+	}
+
+	/**
+	 * @group bp_group_has_members
+	 */
+	public function test_bp_group_has_members_vanilla() {
+		$g = $this->factory->group->create();
+		$u1 = $this->create_user();
+		$u2 = $this->create_user();
+
+		$this->add_user_to_group( $u1, $g );
+
+		global $members_template;
+		bp_group_has_members( array(
+			'group_id' => $g,
+			'exclude_admins_mods' => false,
+		) );
+
+		$ids = wp_parse_id_list( wp_list_pluck( $members_template->members, 'user_id' ) );
+		$this->assertEquals( array( $u1, ), $ids );
+	}
+
+	/**
+	 * Switching from BP_Groups_Member to BP_Group_Member_Query meant a
+	 * change in the format of the values returned from the query. For
+	 * backward compatibility, we translate some of the return values
+	 * of BP_Group_Member_Query to the older format. This test makes sure
+	 * that the translation happens properly.
+	 *
+	 * @group bp_group_has_members
+	 */
+	public function test_bp_group_has_members_backpat_retval_format() {
+		$u1 = $this->create_user();
+		$u2 = $this->create_user();
+		$g = $this->factory->group->create( array( 'creator_id' => $u2 ) );
+
+		$date_modified = gmdate( 'Y-m-d H:i:s', time() - 100 );
+
+		$this->add_user_to_group( $u1, $g, array( 'date_modified' => $date_modified ) );
+
+		global $members_template;
+		bp_group_has_members( array(
+			'group_id' => $g,
+		) );
+
+		$u1_object = new WP_User( $u1 );
+
+		$expected = new stdClass;
+		$expected->user_id = $u1;
+		$expected->date_modified = $date_modified;
+		$expected->is_banned = 0;
+		$expected->user_login = $u1_object->user_login;
+		$expected->user_nicename = $u1_object->user_nicename;
+		$expected->user_email = $u1_object->user_email;
+		$expected->display_name = $u1_object->display_name;
+
+		// In order to use assertEquals, we need to discard the
+		// irrelevant properties of the found object. Hack alert
+		$found = new stdClass;
+		foreach ( array( 'user_id', 'date_modified', 'is_banned', 'user_login', 'user_nicename', 'user_email', 'display_name' ) as $key ) {
+			if ( isset( $members_template->members[0]->{$key} ) ) {
+				$found->{$key} = $members_template->members[0]->{$key};
+			}
+		}
+
+		$this->assertEquals( $expected, $found );
+	}
+
+	/**
+	 * @group bp_group_has_members
+	 */
+	public function test_bp_group_has_members_with_per_page() {
+		$g = $this->factory->group->create();
+
+		$users = array();
+		for ( $i = 1; $i <= 10; $i++ ) {
+			$users[ $i ] = $this->create_user();
+		}
+
+		$expected = array();
+		$now = time();
+		for ( $i = 3; $i <= 10; $i++ ) {
+			$this->add_user_to_group( $users[ $i ], $g, array(
+				'date_modified' => $now - 60 * $i,
+			) );
+			$expected[] = $users[ $i ];
+		}
+
+		// hack it down to 5 (per page arg below)
+		$expected = array_slice( $expected, 0, 5 );
+
+		global $members_template;
+		bp_group_has_members( array(
+			'group_id' => $g,
+			'per_page' => 5,
+		) );
+
+		$ids = wp_parse_id_list( wp_list_pluck( $members_template->members, 'user_id' ) );
+		$this->assertEquals( $expected, $ids );
+	}
+
+	/**
+	 * Note: 'max' is a weird parameter. It just changes the member_count
+	 * in the global - not the sql query at all. I'm testing what it
+	 * appears to be designed to do, not what it feels like it ought to do
+	 * if it made any sense. Programming is fun, QED.
+	 *
+	 * @group bp_group_has_members
+	 */
+	public function test_bp_group_has_members_with_max() {
+		$g = $this->factory->group->create();
+
+		$users = array();
+		for ( $i = 1; $i <= 10; $i++ ) {
+			$users[ $i ] = $this->create_user();
+		}
+
+		$expected = array();
+		for ( $i = 3; $i <= 10; $i++ ) {
+			$this->add_user_to_group( $users[ $i ], $g );
+			$expected[] = $users[ $i ];
+		}
+
+		global $members_template;
+		bp_group_has_members( array(
+			'group_id' => $g,
+			'max' => 5,
+		) );
+
+		$this->assertEquals( 5, $members_template->member_count );
+	}
+
+	/**
+	 * @group bp_group_has_members
+	 */
+	public function test_bp_group_has_members_with_exclude() {
+		$g = $this->factory->group->create();
+		$u1 = $this->create_user();
+		$u2 = $this->create_user();
+
+		$this->add_user_to_group( $u1, $g );
+		$this->add_user_to_group( $u2, $g );
+
+		global $members_template;
+		bp_group_has_members( array(
+			'group_id' => $g,
+			'exclude' => $u1,
+		) );
+
+		$ids = wp_parse_id_list( wp_list_pluck( $members_template->members, 'user_id' ) );
+		$this->assertEquals( array( $u2 ), $ids );
+	}
+
+	/**
+	 * @group bp_group_has_members
+	 */
+	public function test_bp_group_has_members_with_exclude_admins_mods_1() {
+		$g = $this->factory->group->create();
+		$u1 = $this->create_user();
+		$u2 = $this->create_user();
+		$u3 = $this->create_user();
+
+		$this->add_user_to_group( $u1, $g );
+		$this->add_user_to_group( $u2, $g );
+		$this->add_user_to_group( $u3, $g );
+
+		$m1 = new BP_Groups_Member( $u1, $g );
+		$m1->promote( 'admin' );
+		$m2 = new BP_Groups_Member( $u2, $g );
+		$m2->promote( 'mod' );
+
+		global $members_template;
+		bp_group_has_members( array(
+			'group_id' => $g,
+			'exclude_admins_mods' => 1,
+		) );
+
+		$ids = wp_parse_id_list( wp_list_pluck( $members_template->members, 'user_id' ) );
+		$this->assertEquals( array( $u3 ), $ids );
+	}
+
+	/**
+	 * @group bp_group_has_members
+	 */
+	public function test_bp_group_has_members_with_exclude_admins_mods_0() {
+		$u1 = $this->create_user();
+		$u2 = $this->create_user();
+		$u3 = $this->create_user();
+		$g = $this->factory->group->create( array(
+			'creator_id' => $u1,
+		) );
+
+		$now = time();
+		$this->add_user_to_group( $u2, $g, array(
+			'date_modified' => $now - 60,
+		) );
+		$this->add_user_to_group( $u3, $g, array(
+			'date_modified' => $now - 60*60,
+		) );
+
+		$m1 = new BP_Groups_Member( $u1, $g );
+		$m1->promote( 'admin' );
+		$m2 = new BP_Groups_Member( $u2, $g );
+		$m2->promote( 'mod' );
+
+		global $members_template;
+		bp_group_has_members( array(
+			'group_id' => $g,
+			'exclude_admins_mods' => 0,
+		) );
+
+		$ids = wp_parse_id_list( wp_list_pluck( $members_template->members, 'user_id' ) );
+		$this->assertEquals( array( $u1, $u2, $u3 ), $ids );
+	}
+
+	/**
+	 * @group bp_group_has_members
+	 */
+	public function test_bp_group_has_members_with_exclude_banned_1() {
+		$g = $this->factory->group->create();
+		$u1 = $this->create_user();
+		$u2 = $this->create_user();
+
+		$this->add_user_to_group( $u1, $g );
+		$this->add_user_to_group( $u2, $g );
+
+		$m1 = new BP_Groups_Member( $u1, $g );
+		$m1->ban();
+
+		global $members_template;
+		bp_group_has_members( array(
+			'group_id' => $g,
+			'exclude_banned' => 1,
+		) );
+
+		$ids = wp_parse_id_list( wp_list_pluck( $members_template->members, 'user_id' ) );
+		$this->assertEquals( array( $u2, ), $ids );
+	}
+
+	/**
+	 * @group bp_group_has_members
+	 */
+	public function test_bp_group_has_members_with_exclude_banned_0() {
+		$u1 = $this->create_user();
+		$u2 = $this->create_user();
+		$u3 = $this->create_user();
+
+		$g = $this->factory->group->create( array(
+			'creator_id' => $u1,
+		) );
+
+		$this->add_user_to_group( $u2, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', time() - 60*60*24 ),
+		) );
+		$this->add_user_to_group( $u3, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', time() - 60*60*12 ),
+		) );
+
+		$m2 = new BP_Groups_Member( $u2, $g );
+		$m2->ban();
+
+		global $members_template;
+		bp_group_has_members( array(
+			'group_id' => $g,
+			'exclude_banned' => 0,
+			'exclude_admins_mods' => false,
+		) );
+
+		$ids = wp_parse_id_list( wp_list_pluck( $members_template->members, 'user_id' ) );
+		$this->assertEquals( array( $u1, $u3, $u2 ), $ids );
+	}
+
+	/**
+	 * Default sort order should be the joined date
+	 *
+	 * @tickett BP5106
+	 * @group bp_group_has_members
+	 */
+	public function test_bp_group_has_members_default_order() {
+		$u1 = $this->create_user( array(
+			'last_activity' => gmdate( 'Y-m-d H:i:s', time() - 60 ),
+		) );
+		$u2 = $this->create_user( array(
+			'last_activity' => gmdate( 'Y-m-d H:i:s', time() - 600 ),
+		) );
+		$u3 = $this->create_user( array(
+			'last_activity' => gmdate( 'Y-m-d H:i:s', time() - 6000 ),
+		) );
+
+		$g = $this->factory->group->create( array(
+			'creator_id' => $u1,
+		) );
+
+		$this->add_user_to_group( $u2, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', time() - 60*60*24 ),
+		) );
+
+		$this->add_user_to_group( $u3, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', time() - 60*60*12 ),
+		) );
+
+		global $members_template;
+		bp_group_has_members( array(
+			'group_id' => $g,
+			'exclude_banned' => 0,
+			'exclude_admins_mods' => false,
+		) );
+
+		$ids = wp_parse_id_list( wp_list_pluck( $members_template->members, 'user_id' ) );
+		$this->assertEquals( array( $u1, $u3, $u2, ), $ids );
+	}
+}
