Index: src/includes/users/capabilities.php
===================================================================
--- src/includes/users/capabilities.php	(revision 6061)
+++ src/includes/users/capabilities.php	(working copy)
@@ -811,7 +811,7 @@
  * @return @mixed
  */
 function bbp_add_moderator( $object_id = 0, $user_id = 0 ) {
-	return add_post_meta( $object_id, '_bbp_moderator_id', $user_id );
+	return bbp_add_object_user_term( $object_id, $user_id, '_bbp_moderator_id' );
 }
 
 /**
@@ -825,7 +825,7 @@
  * @return mixed
  */
 function bbp_remove_moderator( $object_id = 0, $user_id = 0 ) {
-	return delete_post_meta( $object_id, '_bbp_moderator_id', $user_id );
+	return bbp_remove_object_user_term( $object_id, $user_id, '_bbp_moderator_id' );
 }
 
 /**
@@ -838,7 +838,7 @@
  * @return mixed
  */
 function bbp_get_moderator_ids( $object_id = 0 ) {
-	return get_post_meta( $object_id, '_bbp_moderator_id', false );
+	return bbp_get_user_terms_by_object( $object_id, '_bbp_moderator_id' );
 }
 
 /**
@@ -865,6 +865,7 @@
 			'include' => bbp_get_moderator_ids( $object_id ),
 		) );
 	}
+	error_log( print_r( $users, true ) );
 
 	return apply_filters( 'bbp_get_moderators', $users, $object_id );
 }
Index: src/includes/users/functions.php
===================================================================
--- src/includes/users/functions.php	(revision 6061)
+++ src/includes/users/functions.php	(working copy)
@@ -169,6 +169,141 @@
 	return apply_filters( 'bbp_current_author_ua', $retval );
 }
 
+/** User Taxonomy Terms *******************************************************/
+
+/**
+ * Check if the user term is set on an object
+ *
+ * @since 2.7 bbPress ()
+ *
+ * @param int $object_id The object id
+ * @param int $user_id The user id
+ * @param string $taxonomy The object user taxonomy
+ * @uses get_post_meta() To check if the user term is set on the object
+ * @uses apply_filters() Calls 'bbp_object_has_user_term' with the object id,
+ *                        user id, and taxonomy
+ * @return bool Returns true if the user term is set on the object for the
+ *               taxonomy, otherwise false
+ */
+function bbp_object_has_user_term( $object_id = 0, $user_id = 0, $taxonomy = '' ) {
+	if ( empty( $object_id ) || empty( $user_id ) || empty( $taxonomy ) ) {
+		return;
+	}
+
+	$user_ids = get_post_meta( $object_id, $taxonomy, false );
+	$retval = (bool) in_array( $user_id, $user_ids );
+	return apply_filters( 'bbp_object_has_user_term', $retval, $object_id, $user_id, $taxonomy );
+}
+
+/**
+ * Set a user term on an object
+ *
+ * @since 2.7 bbPress ()
+ *
+ * @param int $object_id The object id
+ * @param int $user_id The user id
+ * @param string $taxonomy The user term taxonomy
+ * @uses bbp_object_has_user_term() To check if the term has already been set
+ * @uses add_post_meta() To set the term on the object
+ * @uses apply_filters() Calls 'bbp_add_object_user_term' with the object id, user
+ *                        id, and taxonomy
+ * @return bool Returns true if the user taxonomy term is added to the object,
+ *               otherwise false
+ */
+function bbp_add_object_user_term( $object_id = 0, $user_id = 0, $taxonomy = '' ) {
+	if ( empty( $object_id ) || empty( $user_id ) || empty( $taxonomy ) ) {
+		return;
+	}
+
+	if ( bbp_object_has_user_term( $object_id, $user_id, $taxonomy ) ) {
+		$retval = false;
+	} else {
+		$retval = (bool) add_post_meta( $object_id, $taxonomy, $user_id, false );
+	}
+	return apply_filters( 'bbp_add_object_user_term', $retval, $object_id, $user_id, $taxonomy );
+}
+
+/**
+ * Remove a user term from an object
+ *
+ * @since 2.7 bbPress ()
+ *
+ * @param int $object_id The post id
+ * @param int $user_id The user id
+ * @param string $taxonomy The user term taxonomy
+ * @uses bbp_object_has_user_term() To check if the term is set
+ * @uses delete_post_meta() To remove the term from the object
+ * @uses apply_filters() Calls 'bbp_remove_object_user_term' with the object
+ *                        id, user id, and taxonomy
+ * @return bool Returns true is the user taxonomy term is removed from the object,
+ *               otherwise false
+ */
+function bbp_remove_object_user_term( $object_id = 0, $user_id = 0, $taxonomy = '' ) {
+	if ( empty( $object_id ) || empty( $user_id ) || empty( $taxonomy ) ) {
+		return;
+	}
+
+	if ( ! bbp_object_has_user_term( $object_id, $user_id, $taxonomy ) ) {
+		$retval = false;
+	} else {
+		$retval = delete_post_meta( $object_id, $taxonomy, $user_id );
+	}
+	return apply_filters( 'bbp_remove_object_user_term', $retval, $object_id, $user_id, $taxonomy );
+}
+
+/**
+ * Get objects for a user taxonomy term
+ *
+ * @since 2.7 bbPress ()
+ *
+ * @param int $user_id The user id
+ * @param string $taxonomy The user term taxonomy
+ * @param string $object_type Optional. The object type
+ * @uses post_type_exists() To validate the object type
+ * @uses get_posts() To get the objects with a meta query
+ * @uses apply_filters() Calls 'bbp_get_objects_by_user_term' with the objects,
+ *                        user_id, taxonomy, and object type
+ * @return array Returns the objects with the user taxonomy term
+ */
+function bbp_get_objects_by_user_term( $user_id = 0, $taxonomy = '', $object_type = null ) {
+	if ( empty( $user_id ) || empty( $taxonomy ) || $object_type && ! post_type_exists( $object_type ) ) {
+		return;
+	}
+
+	$args = array(
+		'meta_key'    => $taxonomy,
+		'meta_type'   => 'NUMERIC',
+		'meta_value'  => $user_id,
+		'numberposts' => -1
+	);
+	if ( $object_type ) {
+		$args['post_type'] = $object_type;
+	}
+	$objects = get_posts( $args );
+	return apply_filters( 'bbp_get_objects_by_user_term', $objects, $user_id, $taxonomy, $object_type );
+}
+
+/**
+ * Get user taxonomy terms for an object
+ *
+ * @since 2.7 bbPress ()
+ *
+ * @param int $object_id The object id
+ * @param string $taxonomy The user term taxonomy
+ * @uses get_post_meta() To get the user taxonomy terms
+ * @uses apply_filters() Calls 'bbp_get_user_terms_by_object' with the user
+ *                        taxonomy terms, object id, and taxonomy
+ * @return array Returns the user taxonomy terms of the object
+ */
+function bbp_get_user_terms_by_object( $object_id = 0, $taxonomy = '' ) {
+	if ( empty( $object_id ) || empty( $taxonomy ) ) {
+		return;
+	}
+
+	$retval = wp_parse_id_list( get_post_meta( $object_id, $taxonomy, false ) );
+	return apply_filters( 'bbp_get_user_terms_by_object', $retval, $object_id, $taxonomy );
+}
+
 /** Favorites *****************************************************************/
 
 /**
@@ -188,13 +323,7 @@
 		return;
 	}
 
-	$bbp_db = bbp_db();
-	$key    = $bbp_db->prefix . '_bbp_favorites';
-	$users  = wp_cache_get( 'bbp_get_topic_favoriters_' . $topic_id, 'bbpress_users' );
-	if ( false === $users ) {
-		$users = $bbp_db->get_col( "SELECT user_id FROM {$bbp_db->usermeta} WHERE meta_key = '{$key}' and FIND_IN_SET('{$topic_id}', meta_value) > 0" );
-		wp_cache_set( 'bbp_get_topic_favoriters_' . $topic_id, $users, 'bbpress_users' );
-	}
+	$users = bbp_get_user_terms_by_object( $topic_id, '_bbp_favorite' );
 
 	return apply_filters( 'bbp_get_topic_favoriters', $users, $topic_id );
 }
@@ -235,7 +364,8 @@
  *
  * @param int $user_id Optional. User id
  * @uses bbp_get_user_id() To get the user id
- * @uses get_user_option() To get the user favorites
+ * @uses bbp_get_objects_by_user_term() To get the user favorites
+ * @uses bbp_get_topic_post_type() To get the topic post type
  * @uses apply_filters() Calls 'bbp_get_user_favorites_topic_ids' with
  *                        the favorites and user id
  * @return array|bool Results if user has favorites, otherwise false
@@ -246,10 +376,10 @@
 		return false;
 	}
 
-	$favorites = get_user_option( '_bbp_favorites', $user_id );
-	$favorites = array_filter( wp_parse_id_list( $favorites ) );
+	$favorites = bbp_get_objects_by_user_term( $user_id, '_bbp_favorite', bbp_get_topic_post_type() );
+	$favorites_ids = array_map( function ( $o ) { return (int) $o->ID; }, $favorites );
 
-	return (array) apply_filters( 'bbp_get_user_favorites_topic_ids', $favorites, $user_id );
+	return (array) apply_filters( 'bbp_get_user_favorites_topic_ids', $favorites_ids, $user_id );
 }
 
 /**
@@ -263,18 +393,18 @@
  * @uses bbp_get_user_favorites_topic_ids() To get the user favorites
  * @uses bbp_get_topic() To get the topic
  * @uses bbp_get_topic_id() To get the topic id
+ * @uses bbp_object_has_user_term() To check if the user has a favorite
  * @uses apply_filters() Calls 'bbp_is_user_favorite' with the bool, user id,
  *                        topic id and favorites
  * @return bool True if the topic is in user's favorites, otherwise false
  */
 function bbp_is_user_favorite( $user_id = 0, $topic_id = 0 ) {
-
 	$user_id = bbp_get_user_id( $user_id, true, true );
 	if ( empty( $user_id ) ) {
 		return false;
 	}
 
-	$retval    = false;
+	$retval = false;
 	$favorites = bbp_get_user_favorites_topic_ids( $user_id );
 
 	if ( ! empty( $favorites ) ) {
@@ -295,7 +425,7 @@
 
 		// Is topic_id in the user's favorites
 		if ( ! empty( $topic_id ) ) {
-			$retval = in_array( $topic_id, $favorites );
+			$retval = bbp_object_has_user_term( $topic_id, $user_id, '_bbp_favorite' );
 		}
 	}
 
@@ -309,8 +439,7 @@
  *
  * @param int $user_id Optional. User id
  * @param int $topic_id Optional. Topic id
- * @uses bbp_get_user_favorites_topic_ids() To get the user favorites
- * @uses update_user_option() To update the user favorites
+ * @uses bbp_is_user_favorite() To check if the topic is a user favorite
  * @uses do_action() Calls 'bbp_add_user_favorite' with the user id and topic id
  * @return bool Always true
  */
@@ -324,14 +453,8 @@
 		return false;
 	}
 
-	$favorites = bbp_get_user_favorites_topic_ids( $user_id );
-	if ( ! in_array( $topic_id, $favorites ) ) {
-		$favorites[] = $topic_id;
-		$favorites   = implode( ',', wp_parse_id_list( array_filter( $favorites ) ) );
-		update_user_option( $user_id, '_bbp_favorites', $favorites );
-
-		// Purge cache
-		wp_cache_delete( 'bbp_get_topic_favoriters_' . $topic_id, 'bbpress_users' );
+	if ( ! bbp_is_user_favorite( $user_id, $topic_id ) ) {
+		bbp_add_object_user_term( $topic_id, $user_id, '_bbp_favorite' );
 	}
 
 	do_action( 'bbp_add_user_favorite', $user_id, $topic_id );
@@ -346,9 +469,7 @@
  *
  * @param int $user_id Optional. User id
  * @param int $topic_id Optional. Topic id
- * @uses bbp_get_user_favorites_topic_ids() To get the user favorites
- * @uses update_user_option() To update the user favorites
- * @uses delete_user_option() To delete the user favorites meta
+ * @uses bbp_is_user_favorite() To check if the topic is a user favorite
  * @uses do_action() Calls 'bbp_remove_user_favorite' with the user & topic id
  * @return bool True if the topic was removed from user's favorites, otherwise
  *               false
@@ -358,25 +479,12 @@
 		return false;
 	}
 
-	$favorites = (array) bbp_get_user_favorites_topic_ids( $user_id );
-	if ( empty( $favorites ) ) {
+	if ( ! bbp_is_user_favorite( $user_id, $topic_id ) ) {
 		return false;
 	}
 
-	$pos = array_search( $topic_id, $favorites );
-	if ( is_numeric( $pos ) ) {
-		array_splice( $favorites, $pos, 1 );
-		$favorites = array_filter( $favorites );
-
-		if ( ! empty( $favorites ) ) {
-			$favorites = implode( ',', wp_parse_id_list( $favorites ) );
-			update_user_option( $user_id, '_bbp_favorites', $favorites );
-		} else {
-			delete_user_option( $user_id, '_bbp_favorites' );
-		}
-
-		// Purge cache
-		wp_cache_delete( 'bbp_get_topic_favoriters_' . $topic_id, 'bbpress_users' );
+	if ( ! bbp_remove_object_user_term( $topic_id, $user_id, '_bbp_favorite' ) ) {
+		return false;
 	}
 
 	do_action( 'bbp_remove_user_favorite', $user_id, $topic_id );
@@ -494,7 +602,7 @@
  * @since 2.5.0 bbPress (r5156)
  *
  * @param int $forum_id Optional. forum id
- * @uses wpdb::get_col() To execute our query and get the column back
+ * @uses bbp_get_user_terms_by_object() To get the forum subscribers
  * @uses apply_filters() Calls 'bbp_get_forum_subscribers' with the subscribers
  * @return array|bool Results if the forum has any subscribers, otherwise false
  */
@@ -504,13 +612,7 @@
 		return;
 	}
 
-	$bbp_db = bbp_db();
-	$key    = $bbp_db->prefix . '_bbp_forum_subscriptions';
-	$users  = wp_cache_get( 'bbp_get_forum_subscribers_' . $forum_id, 'bbpress_users' );
-	if ( false === $users ) {
-		$users = $bbp_db->get_col( "SELECT user_id FROM {$bbp_db->usermeta} WHERE meta_key = '{$key}' and FIND_IN_SET('{$forum_id}', meta_value) > 0" );
-		wp_cache_set( 'bbp_get_forum_subscribers_' . $forum_id, $users, 'bbpress_users' );
-	}
+	$users = bbp_get_user_terms_by_object( $forum_id, '_bbp_subscription' );
 
 	return apply_filters( 'bbp_get_forum_subscribers', $users, $forum_id );
 }
@@ -521,7 +623,7 @@
  * @since 2.0.0 bbPress (r2668)
  *
  * @param int $topic_id Optional. Topic id
- * @uses wpdb::get_col() To execute our query and get the column back
+ * @uses bbp_get_user_terms_by_objet() To get the topic subscribers
  * @uses apply_filters() Calls 'bbp_get_topic_subscribers' with the subscribers
  * @return array|bool Results if the topic has any subscribers, otherwise false
  */
@@ -531,13 +633,7 @@
 		return;
 	}
 
-	$bbp_db = bbp_db();
-	$key    = $bbp_db->prefix . '_bbp_subscriptions';
-	$users  = wp_cache_get( 'bbp_get_topic_subscribers_' . $topic_id, 'bbpress_users' );
-	if ( false === $users ) {
-		$users = $bbp_db->get_col( "SELECT user_id FROM {$bbp_db->usermeta} WHERE meta_key = '{$key}' and FIND_IN_SET('{$topic_id}', meta_value) > 0" );
-		wp_cache_set( 'bbp_get_topic_subscribers_' . $topic_id, $users, 'bbpress_users' );
-	}
+	$users = bbp_get_user_terms_by_object( $topic_id, '_bbp_subscription' );
 
 	return apply_filters( 'bbp_get_topic_subscribers', $users, $topic_id );
 }
@@ -628,7 +724,8 @@
  *
  * @param int $user_id Optional. User id
  * @uses bbp_get_user_id() To get the user id
- * @uses get_user_option() To get the user's subscriptions
+ * @uses bbp_get_objects_by_user_term() To get the user's subscriptions
+ * @uses bbp_get_forum_post_type() To get the forum post type
  * @uses apply_filters() Calls 'bbp_get_user_subscribed_forum_ids' with
  *                        the subscriptions and user id
  * @return array|bool Results if user has subscriptions, otherwise false
@@ -639,8 +736,8 @@
 		return false;
 	}
 
-	$subscriptions = get_user_option( '_bbp_forum_subscriptions', $user_id );
-	$subscriptions = array_filter( wp_parse_id_list( $subscriptions ) );
+	$subscriptions = bbp_get_objects_by_user_term( $user_id, '_bbp_subscription', bbp_get_forum_post_type() );
+	$subscriptions = array_map( function ( $o ) { return $o->ID; }, $subscriptions);
 
 	return (array) apply_filters( 'bbp_get_user_subscribed_forum_ids', $subscriptions, $user_id );
 }
@@ -652,7 +749,8 @@
  *
  * @param int $user_id Optional. User id
  * @uses bbp_get_user_id() To get the user id
- * @uses get_user_option() To get the user's subscriptions
+ * @uses bbp_get_objects_by_user_term() To get the user's subscriptions
+ * @uses bbp_get_topic_post_type() To get the topic post type
  * @uses apply_filters() Calls 'bbp_get_user_subscribed_topic_ids' with
  *                        the subscriptions and user id
  * @return array|bool Results if user has subscriptions, otherwise false
@@ -663,8 +761,8 @@
 		return false;
 	}
 
-	$subscriptions = get_user_option( '_bbp_subscriptions', $user_id );
-	$subscriptions = array_filter( wp_parse_id_list( $subscriptions ) );
+	$subscriptions = bbp_get_objects_by_user_term( $user_id, '_bbp_subscription', bbp_get_topic_post_type() );
+	$subscriptions = array_map( function ( $o ) { return $o->ID; }, $subscriptions);
 
 	return (array) apply_filters( 'bbp_get_user_subscribed_topic_ids', $subscriptions, $user_id );
 }
@@ -706,15 +804,15 @@
 
 				// Forum
 				case bbp_get_forum_post_type() :
-					$subscribed_ids = bbp_get_user_subscribed_forum_ids( $user_id );
-					$retval         = bbp_is_user_subscribed_to_forum( $user_id, $object_id, $subscribed_ids );
+					$subscribed_ids = bbp_get_user_subscribed_forum_ids();
+					$retval = bbp_object_has_user_term( $object_id, $user_id, '_bbp_subscription' );
 					break;
 
 				// Topic (default)
 				case bbp_get_topic_post_type() :
 				default :
-					$subscribed_ids = bbp_get_user_subscribed_topic_ids( $user_id );
-					$retval         = bbp_is_user_subscribed_to_topic( $user_id, $object_id, $subscribed_ids );
+					$subscribed_ids = bbp_get_user_subscribed_topic_ids();
+					$retval = bbp_object_has_user_term( $object_id, $user_id, '_bbp_subscription' );
 					break;
 			}
 		}
@@ -732,9 +830,9 @@
  * @param int $forum_id Optional. Topic id
  * @param array $subscribed_ids Optional. Array of forum ID's to check
  * @uses bbp_get_user_id() To get the user id
- * @uses bbp_get_user_subscribed_forum_ids() To get the user's subscriptions
  * @uses bbp_get_forum() To get the forum
  * @uses bbp_get_forum_id() To get the forum id
+ * @uses bbp_object_has_user_term() To check if the user has a subscription
  * @uses apply_filters() Calls 'bbp_is_user_subscribed' with the bool, user id,
  *                        forum id and subsriptions
  * @return bool True if the forum is in user's subscriptions, otherwise false
@@ -770,9 +868,9 @@
 				$forum_id = get_the_ID();
 			}
 
-			// Is forum_id in the user's favorites
+			// Is forum_id in the user's subscriptions
 			if ( ! empty( $forum_id ) ) {
-				$retval = in_array( $forum_id, $subscribed_ids );
+				$retval = bbp_object_has_user_term( $forum_id, $user_id, '_bbp_subscription' );
 			}
 		}
 	}
@@ -789,9 +887,9 @@
  * @param int $topic_id Optional. Topic id
  * @param array $subscribed_ids Optional. Array of topic ID's to check
  * @uses bbp_get_user_id() To get the user id
- * @uses bbp_get_user_subscribed_topic_ids() To get the user's subscriptions
  * @uses bbp_get_topic() To get the topic
  * @uses bbp_get_topic_id() To get the topic id
+ * @uses bbp_object_has_user_term() To check if the user is subscribed
  * @uses apply_filters() Calls 'bbp_is_user_subscribed' with the bool, user id,
  *                        topic id and subsriptions
  * @return bool True if the topic is in user's subscriptions, otherwise false
@@ -827,9 +925,9 @@
 				$topic_id = get_the_ID();
 			}
 
-			// Is topic_id in the user's favorites
+			// Is topic_id in the user's subscriptions
 			if ( ! empty( $topic_id ) ) {
-				$retval = in_array( $topic_id, $subscribed_ids );
+				$retval = bbp_object_has_user_term( $topic_id, $user_id, '_bbp_subscription' );
 			}
 		}
 	}
@@ -838,19 +936,14 @@
 }
 
 /**
- * Add a topic to user's subscriptions
+ * Add a user subscription
  *
  * @since 2.5.0 bbPress (r5156)
  *
  * @param int $user_id Optional. User id
  * @param int $object_id Optional. Topic id
  * @uses get_post() To get the post object
- * @uses bbp_get_user_subscribed_forum_ids() To get the user's forum subscriptions
- * @uses bbp_get_user_subscribed_topic_ids() To get the user's topic subscriptions
- * @uses bbp_get_forum_post_type() To get the forum post type
- * @uses bbp_get_topic_post_type() To get the topic post type
- * @uses update_user_option() To update the user's subscriptions
- * @uses do_action() Calls 'bbp_add_user_subscription' with the user & topic id
+ * @uses do_action() Calls 'bbp_add_user_subscription' with the user & object id
  * @return bool Always true
  */
 function bbp_add_user_subscription( $user_id = 0, $object_id = 0 ) {
@@ -864,18 +957,8 @@
 		return false;
 	}
 
-	switch( $post_type ) {
-
-		// Forum
-		case bbp_get_forum_post_type() :
-			bbp_add_user_forum_subscription( $user_id, $object_id );
-			break;
-
-		// Topic
-		case bbp_get_topic_post_type() :
-		default :
-			bbp_add_user_topic_subscription( $user_id, $object_id );
-			break;
+	if ( ! bbp_is_user_subscribed( $user_id, $object_id ) ) {
+		bbp_add_object_user_term( $object_id, $user_id, '_bbp_subscription' );
 	}
 
 	do_action( 'bbp_add_user_subscription', $user_id, $object_id, $post_type );
@@ -890,9 +973,8 @@
  *
  * @param int $user_id Optional. User id
  * @param int $forum_id Optional. forum id
- * @uses bbp_get_user_subscribed_forum_ids() To get the user's subscriptions
  * @uses bbp_get_forum() To get the forum
- * @uses update_user_option() To update the user's subscriptions
+ * @uses bbp_add_user_subscription() To add the user subscription
  * @uses do_action() Calls 'bbp_add_user_subscription' with the user & forum id
  * @return bool Always true
  */
@@ -906,15 +988,8 @@
 		return false;
 	}
 
-	$subscriptions = (array) bbp_get_user_subscribed_forum_ids( $user_id );
-	if ( ! in_array( $forum_id, $subscriptions ) ) {
-		$subscriptions[] = $forum_id;
-		$subscriptions   = implode( ',', wp_parse_id_list( array_filter( $subscriptions ) ) );
-		update_user_option( $user_id, '_bbp_forum_subscriptions', $subscriptions );
+	bbp_add_user_subscription( $user_id, $forum_id );
 
-		wp_cache_delete( 'bbp_get_forum_subscribers_' . $forum_id, 'bbpress_users' );
-	}
-
 	do_action( 'bbp_add_user_forum_subscription', $user_id, $forum_id );
 
 	return true;
@@ -927,9 +1002,8 @@
  *
  * @param int $user_id Optional. User id
  * @param int $topic_id Optional. Topic id
- * @uses bbp_get_user_subscribed_topic_ids() To get the user's subscriptions
  * @uses bbp_get_topic() To get the topic
- * @uses update_user_option() To update the user's subscriptions
+ * @uses bbp_add_user_subscription() To add the subscription
  * @uses do_action() Calls 'bbp_add_user_subscription' with the user & topic id
  * @return bool Always true
  */
@@ -943,32 +1017,22 @@
 		return false;
 	}
 
-	$subscriptions = (array) bbp_get_user_subscribed_topic_ids( $user_id );
-	if ( ! in_array( $topic_id, $subscriptions ) ) {
-		$subscriptions[] = $topic_id;
-		$subscriptions   = implode( ',', wp_parse_id_list( array_filter( $subscriptions ) ) );
-		update_user_option( $user_id, '_bbp_subscriptions', $subscriptions );
+	bbp_add_user_subscription( $user_id, $topic_id );
 
-		wp_cache_delete( 'bbp_get_topic_subscribers_' . $topic_id, 'bbpress_users' );
-	}
-
 	do_action( 'bbp_add_user_topic_subscription', $user_id, $topic_id );
 
 	return true;
 }
 
 /**
- * Remove a topic from user's subscriptions
+ * Remove a user subscription
  *
  * @since 2.0.0 bbPress (r2668)
  *
  * @param int $user_id Optional. User id
  * @param int $object_id Optional. Topic id
  * @uses get_post() To get the post object
- * @uses bbp_get_forum_post_type() To get the forum post type
- * @uses bbp_get_topic_post_type() To get the topic post type
- * @uses bbp_remove_user_forum_subscription() To remove the user's subscription
- * @uses bbp_remove_user_topic_subscription() To remove the user's subscription
+ * @uses bbp_is_user_subscribed() To check if the user is already subscribed
  * @uses do_action() Calls 'bbp_remove_user_subscription' with the user id and
  *                    topic id
  * @return bool True if the topic was removed from user's subscriptions,
@@ -984,18 +1048,8 @@
 		return false;
 	}
 
-	switch( $post_type ) {
-
-		// Forum
-		case bbp_get_forum_post_type() :
-			bbp_remove_user_forum_subscription( $user_id, $object_id );
-			break;
-
-		// Topic
-		case bbp_get_topic_post_type() :
-		default :
-			bbp_remove_user_topic_subscription( $user_id, $object_id );
-			break;
+	if ( bbp_is_user_subscribed( $user_id, $object_id ) ) {
+		bbp_remove_object_user_term( $object_id, $user_id, '_bbp_subscription' );
 	}
 
 	do_action( 'bbp_remove_user_subscription', $user_id, $object_id, $post_type );
@@ -1010,9 +1064,7 @@
  *
  * @param int $user_id Optional. User id
  * @param int $forum_id Optional. forum id
- * @uses bbp_get_user_subscribed_forum_ids() To get the user's subscriptions
- * @uses update_user_option() To update the user's subscriptions
- * @uses delete_user_option() To delete the user's subscriptions meta
+ * @uses bbp_remove_user_subscription() To remove the subscription
  * @uses do_action() Calls 'bbp_remove_user_subscription' with the user id and
  *                    forum id
  * @return bool True if the forum was removed from user's subscriptions,
@@ -1023,28 +1075,8 @@
 		return false;
 	}
 
-	$subscriptions = (array) bbp_get_user_subscribed_forum_ids( $user_id );
-	if ( empty( $subscriptions ) ) {
-		return false;
-	}
+	bbp_remove_user_subscription( $user_id, $forum_id );
 
-	$pos = array_search( $forum_id, $subscriptions );
-	if ( false === $pos ) {
-		return false;
-	}
-
-	array_splice( $subscriptions, $pos, 1 );
-	$subscriptions = array_filter( $subscriptions );
-
-	if ( ! empty( $subscriptions ) ) {
-		$subscriptions = implode( ',', wp_parse_id_list( $subscriptions ) );
-		update_user_option( $user_id, '_bbp_forum_subscriptions', $subscriptions );
-	} else {
-		delete_user_option( $user_id, '_bbp_forum_subscriptions' );
-	}
-
-	wp_cache_delete( 'bbp_get_forum_subscribers_' . $forum_id, 'bbpress_users' );
-
 	do_action( 'bbp_remove_user_forum_subscription', $user_id, $forum_id );
 
 	return true;
@@ -1057,9 +1089,7 @@
  *
  * @param int $user_id Optional. User id
  * @param int $topic_id Optional. Topic id
- * @uses bbp_get_user_subscribed_topic_ids() To get the user's subscriptions
- * @uses update_user_option() To update the user's subscriptions
- * @uses delete_user_option() To delete the user's subscriptions meta
+ * @uses bbp_remove_user_subscription() To remove the subscription
  * @uses do_action() Calls 'bbp_remove_user_topic_subscription' with the user id and
  *                    topic id
  * @return bool True if the topic was removed from user's subscriptions,
@@ -1070,28 +1100,8 @@
 		return false;
 	}
 
-	$subscriptions = (array) bbp_get_user_subscribed_topic_ids( $user_id );
-	if ( empty( $subscriptions ) ) {
-		return false;
-	}
+	bbp_remove_user_subscription( $user_id, $topic_id );
 
-	$pos = array_search( $topic_id, $subscriptions );
-	if ( false === $pos ) {
-		return false;
-	}
-
-	array_splice( $subscriptions, $pos, 1 );
-	$subscriptions = array_filter( $subscriptions );
-
-	if ( ! empty( $subscriptions ) ) {
-		$subscriptions = implode( ',', wp_parse_id_list( $subscriptions ) );
-		update_user_option( $user_id, '_bbp_subscriptions', $subscriptions );
-	} else {
-		delete_user_option( $user_id, '_bbp_subscriptions' );
-	}
-
-	wp_cache_delete( 'bbp_get_topic_subscribers_' . $topic_id, 'bbpress_users' );
-
 	do_action( 'bbp_remove_user_topic_subscription', $user_id, $topic_id );
 
 	return true;
@@ -1154,7 +1164,7 @@
 
 	// Check current user's ability to edit the user
 	} elseif ( ! current_user_can( 'edit_user', $user_id ) ) {
-		bbp_add_error( 'bbp_subscription_permissions', __( '<strong>ERROR</strong>: You don\'t have the permission to edit favorites of that user!', 'bbpress' ) );
+		bbp_add_error( 'bbp_subscription_permissions', __( '<strong>ERROR</strong>: You don\'t have the permission to edit subscriptions of that user!', 'bbpress' ) );
 	}
 
 	// Bail if we have errors
@@ -1259,7 +1269,7 @@
 
 	// Check current user's ability to edit the user
 	} elseif ( ! current_user_can( 'edit_user', $user_id ) ) {
-		bbp_add_error( 'bbp_subscription_permissions', __( '<strong>ERROR</strong>: You don\'t have the permission to edit favorites of that user!', 'bbpress' ) );
+		bbp_add_error( 'bbp_subscription_permissions', __( '<strong>ERROR</strong>: You don\'t have the permission to edit subscriptions of that user!', 'bbpress' ) );
 	}
 
 	// Bail if we have errors
Index: tests/phpunit/testcases/users/functions/favorites.php
===================================================================
--- tests/phpunit/testcases/users/functions/favorites.php	(revision 6061)
+++ tests/phpunit/testcases/users/functions/favorites.php	(working copy)
@@ -119,7 +119,7 @@
 		$t = $this->factory->topic->create_many( 3 );
 
 		// Add topic favorites.
-		update_user_option( $u, '_bbp_favorites', $t[0] );
+		add_post_meta( $t[0], '_bbp_favorite', $u, false );
 
 		// Add user favorite.
 		bbp_add_user_favorite( $u, $t[1] );
@@ -144,7 +144,9 @@
 		$t = $this->factory->topic->create_many( 3 );
 
 		// Add topic favorites.
-		update_user_option( $u, '_bbp_favorites', implode( ',', $t ) );
+		foreach ( $t as $topic ) {
+			add_post_meta( $topic, '_bbp_favorite', $u );
+		}
 
 		// Remove user favorite.
 		bbp_remove_user_favorite( $u, $t[2] );
Index: tests/phpunit/testcases/users/functions/functions.php
===================================================================
--- tests/phpunit/testcases/users/functions/functions.php	(revision 6061)
+++ tests/phpunit/testcases/users/functions/functions.php	(working copy)
@@ -86,6 +86,99 @@
 	}
 
 	/**
+	 * @covers ::bbp_object_has_user_term
+	 */
+	public function test_bbp_object_has_user_term() {
+		$u = $this->factory->user->create();
+		$t = $this->factory->topic->create();
+
+		$r = bbp_object_has_user_term( $t, $u, $this->user_taxonomy );
+
+		$this->assertFalse( $r );
+
+		// Add user term.
+		add_post_meta( $t, $this->user_taxonomy, $u, false );
+
+		$r = bbp_object_has_user_term( $t, $u, $this->user_taxonomy );
+
+		$this->assertTrue( $r );
+	}
+
+	/**
+	 * @covers ::bbp_add_object_user_term
+	 */
+	public function test_bbp_add_object_user_term() {
+		$u = $this->factory->user->create_many( 3 );
+		$t = $this->factory->topic->create();
+
+		// Add object terms.
+		foreach ( $u as $k => $v ) {
+			bbp_add_object_user_term( $t, $v, $this->user_taxonomy );
+		}
+
+		$r = get_post_meta( $t, $this->user_taxonomy, false );
+
+		$this->assertCount( 3, $r );
+	}
+
+	/**
+	 * @covers ::bbp_remove_object_user_term
+	 */
+	public function test_bbp_remove_object_user_term() {
+		$u = $this->factory->user->create();
+		$t = $this->factory->topic->create();
+
+		// Add object terms.
+		add_post_meta( $t, $this->user_taxonomy, $u, false );
+
+		$r = get_post_meta( $t, $this->user_taxonomy, false );
+
+		$this->assertCount( 1, $r );
+
+		$r = bbp_remove_object_user_term( $t, $u, $this->user_taxonomy );
+
+		$this->assertTrue( $r );
+
+		$r = get_post_meta( $t, $this->user_taxonomy, false );
+
+		$this->assertCount( 0, $r );
+	}
+
+	/**
+	 * @covers ::bbp_get_objects_by_user_term
+	 */
+	public function test_bbp_get_objects_by_user_term() {
+		$u = $this->factory->user->create();
+		$t = $this->factory->topic->create_many( 3 );
+
+		// Add object terms.
+		foreach ( $t as $k => $v ) {
+			add_post_meta( $v, $this->user_taxonomy, $u, false );
+		}
+
+		$r = bbp_get_objects_by_user_term( $u, $this->user_taxonomy, 'topic' );
+
+		$this->assertCount( 3, $r );
+	}
+
+	/**
+	 * @covers ::bbp_get_user_terms_by_object
+	 */
+	public function test_bbp_get_user_terms_by_object() {
+		$u = $this->factory->user->create_many( 3 );
+		$t = $this->factory->topic->create();
+
+		// Add object terms.
+		foreach ( $u as $k => $v ) {
+			add_post_meta( $t, $this->user_taxonomy, $u, false );
+		}
+
+		$r = bbp_get_user_terms_by_object( $t, $this->user_taxonomy );
+
+		$this->assertCount( 3, $r );
+	}
+
+ 	/**
 	 * @covers ::bbp_edit_user_handler
 	 * @todo   Implement test_bbp_edit_user_handler().
 	 */
@@ -172,4 +265,10 @@
 			'This test has not been implemented yet.'
 		);
 	}
+
+	public function setUp() {
+		parent::setUp();
+
+		$this->user_taxonomy = '_bbp_test_user_taxonomy';
+	}
 }
