Index: src/includes/admin/replies.php
===================================================================
--- src/includes/admin/replies.php	(revision 5446)
+++ src/includes/admin/replies.php	(working copy)
@@ -158,11 +158,12 @@
 			'content'	=>
 				'<p>' . __( 'Hovering over a row in the replies list will display action links that allow you to manage your reply. You can perform the following actions:', 'bbpress' ) . '</p>' .
 				'<ul>' .
-					'<li>' . __( '<strong>Edit</strong> takes you to the editing screen for that reply. You can also reach that screen by clicking on the reply title.',                                                                                 'bbpress' ) . '</li>' .
-					//'<li>' . __( '<strong>Quick Edit</strong> provides inline access to the metadata of your reply, allowing you to update reply details without leaving this screen.',                                                                  'bbpress' ) . '</li>' .
-					'<li>' . __( '<strong>Trash</strong> removes your reply from this list and places it in the trash, from which you can permanently delete it.',                                                                                       'bbpress' ) . '</li>' .
-					'<li>' . __( '<strong>Spam</strong> removes your reply from this list and places it in the spam queue, from which you can permanently delete it.',                                                                                   'bbpress' ) . '</li>' .
-					'<li>' . __( '<strong>Preview</strong> will show you what your draft reply will look like if you publish it. View will take you to your live site to view the reply. Which link is available depends on your reply&#8217;s status.', 'bbpress' ) . '</li>' .
+					'<li>' . __( '<strong>Edit</strong> takes you to the editing screen for that reply. You can also reach that screen by clicking on the reply title.',                  'bbpress' ) . '</li>' .
+					//'<li>' . __( '<strong>Quick Edit</strong> provides inline access to the metadata of your reply, allowing you to update reply details without leaving this screen.', 'bbpress' ) . '</li>' .
+					'<li>' . __( '<strong>Trash</strong> removes your reply from this list and places it in the trash, from which you can permanently delete it.',                        'bbpress' ) . '</li>' .
+					'<li>' . __( '<strong>Spam</strong> removes your reply from this list and places it in the spam queue, from which you can permanently delete it.',                    'bbpress' ) . '</li>' .
+					'<li>' . __( '<strong>View</strong> will take you to your live site to view the reply.',                                                                              'bbpress' ) . '</li>' .
+					'<li>' . __( '<strong>Approve</strong> will change the status from pending to publish.',                                                                              'bbpress' ) . '</li>' .
 				'</ul>'
 		) );
 
@@ -434,6 +435,10 @@
 				background-color: #faeaea;
 			}
 
+			.status-pending {
+				background-color: #fef7f1;
+			}
+
 		/*]]>*/
 		</style>
 
@@ -468,7 +473,7 @@
 		}
 
 		// Only proceed if GET is a reply toggle action
-		if ( bbp_is_get_request() && !empty( $_GET['action'] ) && in_array( $_GET['action'], array( 'bbp_toggle_reply_spam' ) ) && !empty( $_GET['reply_id'] ) ) {
+		if ( bbp_is_get_request() && ! empty( $_GET['action'] ) && in_array( $_GET['action'], array( 'bbp_toggle_reply_spam', 'bbp_toggle_reply_approve' ) ) && ! empty( $_GET['reply_id'] ) ) {
 			$action    = $_GET['action'];            // What action is taking place?
 			$reply_id  = (int) $_GET['reply_id'];    // What's the reply id?
 			$success   = false;                      // Flag
@@ -486,6 +491,15 @@
 			}
 
 			switch ( $action ) {
+				case 'bbp_toggle_reply_approve' :
+					check_admin_referer( 'approve-reply_' . $reply_id );
+
+					$is_approve = bbp_is_reply_pending( $reply_id );
+					$message    = $is_approve ? 'approved' : 'unapproved';
+					$success    = $is_approve ? bbp_approve_reply( $reply_id ) : bbp_unapprove_reply( $reply_id );
+
+					break;
+
 				case 'bbp_toggle_reply_spam' :
 					check_admin_referer( 'spam-reply_' . $reply_id );
 
@@ -496,7 +510,6 @@
 					break;
 			}
 
-			$success = wp_update_post( $post_data );
 			$message = array( 'bbp_reply_toggle_notice' => $message, 'reply_id' => $reply->ID );
 
 			if ( false === $success || is_wp_error( $success ) ) {
@@ -536,7 +549,7 @@
 		}
 
 		// Only proceed if GET is a reply toggle action
-		if ( bbp_is_get_request() && !empty( $_GET['bbp_reply_toggle_notice'] ) && in_array( $_GET['bbp_reply_toggle_notice'], array( 'spammed', 'unspammed' ) ) && !empty( $_GET['reply_id'] ) ) {
+		if ( bbp_is_get_request() && ! empty( $_GET['bbp_reply_toggle_notice'] ) && in_array( $_GET['bbp_reply_toggle_notice'], array( 'spammed', 'unspammed', 'approved', 'unapproved' ) ) && ! empty( $_GET['reply_id'] ) ) {
 			$notice     = $_GET['bbp_reply_toggle_notice'];         // Which notice?
 			$reply_id   = (int) $_GET['reply_id'];                  // What's the reply id?
 			$is_failure = !empty( $_GET['failed'] ) ? true : false; // Was that a failure?
@@ -566,6 +579,18 @@
 						? sprintf( __( 'There was a problem unmarking the reply "%1$s" as spam.', 'bbpress' ), $reply_title )
 						: sprintf( __( 'Reply "%1$s" successfully unmarked as spam.',             'bbpress' ), $reply_title );
 					break;
+
+				case 'approved' :
+					$message = ( $is_failure === true )
+						? sprintf( __( 'There was a problem approving the reply "%1$s".', 'bbpress' ), $reply_title )
+						: sprintf( __( 'Reply "%1$s" successfully approved.',             'bbpress' ), $reply_title );
+					break;
+
+				case 'unapproved' :
+					$message = ( $is_failure === true )
+						? sprintf( __( 'There was a problem unapproving the reply "%1$s".', 'bbpress' ), $reply_title )
+						: sprintf( __( 'Reply "%1$s" successfully unapproved.',             'bbpress' ), $reply_title );
+					break;
 			}
 
 			// Do additional reply toggle notice filters (admin side)
@@ -767,6 +792,15 @@
 			unset( $actions['view'] );
 		}
 
+			// Pending
+			// Show the 'approve' and 'view' link on pending posts only and 'unapprove' on published posts only
+			$approve_uri = wp_nonce_url( add_query_arg( array( 'reply_id' => $reply->ID, 'action' => 'bbp_toggle_reply_approve' ), remove_query_arg( array( 'bbp_reply_toggle_notice', 'reply_id', 'failed', 'super' ) ) ), 'approve-reply_' . $reply->ID );
+			if ( bbp_is_reply_published( $reply->ID ) ) {
+				$actions['unapproved'] = '<a href="' . esc_url( $approve_uri ) . '" title="' . esc_attr__( 'Unapprove this reply', 'bbpress' ) . '">' . _x( 'Unapprove', 'Unapprove reply', 'bbpress' ) . '</a>';
+			} elseif ( ! bbp_is_reply_private( $reply->ID ) ) {
+				$actions['approved']   = '<a href="' . esc_url( $approve_uri ) . '" title="' . esc_attr__( 'Approve this reply',   'bbpress' ) . '">' . _x( 'Approve',   'Approve reply',   'bbpress' ) . '</a>';
+			}
+
 		// Only show the actions if the user is capable of viewing them
 		if ( current_user_can( 'moderate', $reply->ID ) ) {
 			if ( in_array( $reply->post_status, array( bbp_get_public_status_id(), bbp_get_spam_status_id() ) ) ) {
Index: src/includes/admin/topics.php
===================================================================
--- src/includes/admin/topics.php	(revision 5446)
+++ src/includes/admin/topics.php	(working copy)
@@ -157,13 +157,14 @@
 			'content'	=>
 				'<p>' . __( 'Hovering over a row in the topics list will display action links that allow you to manage your topic. You can perform the following actions:', 'bbpress' ) . '</p>' .
 				'<ul>' .
-					'<li>' . __( '<strong>Edit</strong> takes you to the editing screen for that topic. You can also reach that screen by clicking on the topic title.',                                                                                 'bbpress' ) . '</li>' .
-					'<li>' . __( '<strong>Trash</strong> removes your topic from this list and places it in the trash, from which you can permanently delete it.',                                                                                       'bbpress' ) . '</li>' .
-					'<li>' . __( '<strong>Spam</strong> removes your topic from this list and places it in the spam queue, from which you can permanently delete it.',                                                                                   'bbpress' ) . '</li>' .
-					'<li>' . __( '<strong>Preview</strong> will show you what your draft topic will look like if you publish it. View will take you to your live site to view the topic. Which link is available depends on your topic&#8217;s status.', 'bbpress' ) . '</li>' .
-					'<li>' . __( '<strong>Close</strong> will mark the selected topic as &#8217;closed&#8217; and disable the option to post new replies to the topic.',                                                                                 'bbpress' ) . '</li>' .
-					'<li>' . __( '<strong>Stick</strong> will keep the selected topic &#8217;pinned&#8217; to the top the parent forum topic list.',                                                                                                     'bbpress' ) . '</li>' .
-					'<li>' . __( '<strong>Stick <em>(to front)</em></strong> will keep the selected topic &#8217;pinned&#8217; to the top of ALL forums and be visable in any forums topics list.',                                                      'bbpress' ) . '</li>' .
+					'<li>' . __( '<strong>Edit</strong> takes you to the editing screen for that topic. You can also reach that screen by clicking on the topic title.',                            'bbpress' ) . '</li>' .
+					'<li>' . __( '<strong>Trash</strong> removes your topic from this list and places it in the trash, from which you can permanently delete it.',                                  'bbpress' ) . '</li>' .
+					'<li>' . __( '<strong>Spam</strong> removes your topic from this list and places it in the spam queue, from which you can permanently delete it.',                              'bbpress' ) . '</li>' .
+					'<li>' . __( '<strong>View</strong> will take you to your live site to view the topic.',                                                                                        'bbpress' ) . '</li>' .
+					'<li>' . __( '<strong>Approve</strong> will change the status from pending to publish.',                                                                                        'bbpress' ) . '</li>' .
+					'<li>' . __( '<strong>Close</strong> will mark the selected topic as &#8217;closed&#8217; and disable the option to post new replies to the topic.',                            'bbpress' ) . '</li>' .
+					'<li>' . __( '<strong>Stick</strong> will keep the selected topic &#8217;pinned&#8217; to the top the parent forum topic list.',                                                'bbpress' ) . '</li>' .
+					'<li>' . __( '<strong>Stick <em>(to front)</em></strong> will keep the selected topic &#8217;pinned&#8217; to the top of ALL forums and be visable in any forums topics list.', 'bbpress' ) . '</li>' .
 				'</ul>'
 		) );
 
@@ -449,6 +450,10 @@
 				background-color: #faeaea;
 			}
 
+			.status-pending {
+				background-color: #fef7f1;
+			}
+
 		/*]]>*/
 		</style>
 
@@ -491,12 +496,12 @@
 		}
 
 		// Only proceed if GET is a topic toggle action
-		if ( bbp_is_get_request() && !empty( $_GET['action'] ) && in_array( $_GET['action'], array( 'bbp_toggle_topic_close', 'bbp_toggle_topic_stick', 'bbp_toggle_topic_spam' ) ) && !empty( $_GET['topic_id'] ) ) {
+		if ( bbp_is_get_request() && !empty( $_GET['action'] ) && in_array( $_GET['action'], array( 'bbp_toggle_topic_close', 'bbp_toggle_topic_stick', 'bbp_toggle_topic_spam', 'bbp_toggle_topic_approve' ) ) && !empty( $_GET['topic_id'] ) ) {
 			$action    = $_GET['action'];            // What action is taking place?
 			$topic_id  = (int) $_GET['topic_id'];    // What's the topic id?
 			$success   = false;                      // Flag
 			$post_data = array( 'ID' => $topic_id ); // Prelim array
-			$topic     = bbp_get_topic( $topic_id );
+			$topic     = bbp_get_topic( $topic_id ); // Verify the topic id
 
 			// Bail if topic is missing
 			if ( empty( $topic ) ) {
@@ -509,6 +514,19 @@
 			}
 
 			switch ( $action ) {
+				case 'bbp_toggle_topic_approve' :
+					check_admin_referer( 'approve-topic_' . $topic_id );
+
+					$is_approve = bbp_is_topic_pending( $topic_id );
+					$message    = ( true === $is_approve )
+						? 'approved'
+						: 'unapproved';
+					$success    = ( true === $is_approve )
+						? bbp_approve_topic( $topic_id )
+						: bbp_unapprove_topic( $topic_id );
+
+					break;
+
 				case 'bbp_toggle_topic_close' :
 					check_admin_referer( 'close-topic_' . $topic_id );
 
@@ -594,17 +612,17 @@
 		}
 
 		// Only proceed if GET is a topic toggle action
-		if ( bbp_is_get_request() && !empty( $_GET['bbp_topic_toggle_notice'] ) && in_array( $_GET['bbp_topic_toggle_notice'], array( 'opened', 'closed', 'super_sticked', 'sticked', 'unsticked', 'spammed', 'unspammed' ) ) && !empty( $_GET['topic_id'] ) ) {
+		if ( bbp_is_get_request() && ! empty( $_GET['bbp_topic_toggle_notice'] ) && in_array( $_GET['bbp_topic_toggle_notice'], array( 'opened', 'closed', 'super_sticked', 'sticked', 'unsticked', 'spammed', 'unspammed', 'approved', 'unapproved' ) ) && ! empty( $_GET['topic_id'] ) ) {
 			$notice     = $_GET['bbp_topic_toggle_notice'];         // Which notice?
 			$topic_id   = (int) $_GET['topic_id'];                  // What's the topic id?
 			$is_failure = !empty( $_GET['failed'] ) ? true : false; // Was that a failure?
 
-			// Bais if no topic_id or notice
+			// Bail if no topic_id or notice
 			if ( empty( $notice ) || empty( $topic_id ) ) {
 				return;
 			}
 
-			// Bail if topic is missing
+			// Get topic and bail if empty
 			$topic = bbp_get_topic( $topic_id );
 			if ( empty( $topic ) ) {
 				return;
@@ -654,6 +672,18 @@
 						? sprintf( __( 'There was a problem unmarking the topic "%1$s" as spam.', 'bbpress' ), $topic_title )
 						: sprintf( __( 'Topic "%1$s" successfully unmarked as spam.',             'bbpress' ), $topic_title );
 					break;
+
+				case 'approved'   :
+					$message = ( $is_failure === true )
+						? sprintf( __( 'There was a problem approving the topic "%1$s".', 'bbpress' ), $topic_title )
+						: sprintf( __( 'Topic "%1$s" successfully approved.',             'bbpress' ), $topic_title );
+					break;
+
+				case 'unapproved' :
+					$message = ( $is_failure === true )
+						? sprintf( __( 'There was a problem unapproving the topic "%1$s".', 'bbpress' ), $topic_title )
+						: sprintf( __( 'Topic "%1$s" successfully unapproved.',             'bbpress' ), $topic_title );
+					break;
 			}
 
 			// Do additional topic toggle notice filters (admin side)
@@ -842,6 +872,16 @@
 		// Only show the actions if the user is capable of viewing them :)
 		if ( current_user_can( 'moderate', $topic->ID ) ) {
 
+			// Pending
+			// Show the 'approve' and 'view' link on pending posts only and 'unapprove' on published posts only
+			$approve_uri = wp_nonce_url( add_query_arg( array( 'topic_id' => $topic->ID, 'action' => 'bbp_toggle_topic_approve' ), remove_query_arg( array( 'bbp_topic_toggle_notice', 'topic_id', 'failed', 'super' ) ) ), 'approve-topic_' . $topic->ID );
+			if ( bbp_is_topic_published( $topic->ID ) ) {
+				$actions['unapproved'] = '<a href="' . esc_url( $approve_uri ) . '" title="' . esc_attr__( 'Unapprove this topic', 'bbpress' ) . '">' . _x( 'Unapprove', 'Unapprove Topic', 'bbpress' ) . '</a>';
+			} elseif ( ! bbp_is_topic_private( $topic->ID ) ) {
+				$actions['approved']   = '<a href="' . esc_url( $approve_uri ) . '" title="' . esc_attr__( 'Approve this topic',   'bbpress' ) . '">' . _x( 'Approve',   'Approve Topic',   'bbpress' ) . '</a>';
+				$actions['view']       = '<a href="' . esc_url( bbp_get_topic_permalink( $topic->ID ) ) . '" title="' . esc_attr( sprintf( __( 'View &#8220;%s&#8221;', 'bbpress' ), bbp_get_topic_title( $topic->ID ) ) ) . '" rel="permalink">' . esc_html__( 'View', 'bbpress' ) . '</a>';
+			}
+
 			// Close
 			// Show the 'close' and 'open' link on published and closed posts only
 			if ( in_array( $topic->post_status, array( bbp_get_public_status_id(), bbp_get_closed_status_id() ) ) ) {
@@ -853,8 +893,8 @@
 				}
 			}
 
-			// Dont show sticky if topic links is spam or trash
-			if ( !bbp_is_topic_spam( $topic->ID ) && !bbp_is_topic_trash( $topic->ID ) ) {
+			// Dont show sticky if topic links is spam, trash or pending
+			if ( ! bbp_is_topic_spam( $topic->ID ) && ! bbp_is_topic_trash( $topic->ID ) && ! bbp_is_topic_pending( $topic->ID ) ) {
 
 				// Sticky
 				$stick_uri  = wp_nonce_url( add_query_arg( array( 'topic_id' => $topic->ID, 'action' => 'bbp_toggle_topic_stick' ), remove_query_arg( array( 'bbp_topic_toggle_notice', 'topic_id', 'failed', 'super' ) ) ), 'stick-topic_'  . $topic->ID );
Index: src/includes/core/actions.php
===================================================================
--- src/includes/core/actions.php	(revision 5446)
+++ src/includes/core/actions.php	(working copy)
@@ -155,13 +155,13 @@
 add_action( 'bbp_template_notices', 'bbp_notice_edit_user_success'           );
 add_action( 'bbp_template_notices', 'bbp_notice_edit_user_is_super_admin', 2 );
 
-// Before Delete/Trash/Untrash Topic
+// Before Delete/Trash/Untrash Forum
 add_action( 'wp_trash_post', 'bbp_trash_forum'   );
 add_action( 'trash_post',    'bbp_trash_forum'   );
 add_action( 'untrash_post',  'bbp_untrash_forum' );
 add_action( 'delete_post',   'bbp_delete_forum'  );
 
-// After Deleted/Trashed/Untrashed Topic
+// After Deleted/Trashed/Untrashed Forum
 add_action( 'trashed_post',   'bbp_trashed_forum'   );
 add_action( 'untrashed_post', 'bbp_untrashed_forum' );
 add_action( 'deleted_post',   'bbp_deleted_forum'   );
@@ -242,6 +242,8 @@
 add_action( 'bbp_deleted_topic',   'bbp_update_topic_walker' );
 add_action( 'bbp_spammed_topic',   'bbp_update_topic_walker' );
 add_action( 'bbp_unspammed_topic', 'bbp_update_topic_walker' );
+add_action( 'bbp_approve_topic',   'bbp_update_topic_walker' );
+add_action( 'bbp_unapprove_topic', 'bbp_update_topic_walker' );
 
 // Update reply branch
 add_action( 'bbp_trashed_reply',   'bbp_update_reply_walker' );
@@ -249,6 +251,8 @@
 add_action( 'bbp_deleted_reply',   'bbp_update_reply_walker' );
 add_action( 'bbp_spammed_reply',   'bbp_update_reply_walker' );
 add_action( 'bbp_unspammed_reply', 'bbp_update_reply_walker' );
+add_action( 'bbp_approve_reply',   'bbp_update_reply_walker' );
+add_action( 'bbp_unapprove_reply', 'bbp_update_reply_walker' );
 
 // Users topic & reply counts
 add_action( 'bbp_new_topic',     'bbp_increase_user_topic_count' );
@@ -267,7 +271,7 @@
 add_action( 'bbp_untrash_topic', 'bbp_untrash_topic_replies' );
 add_action( 'bbp_delete_topic',  'bbp_delete_topic_replies'  );
 add_action( 'bbp_spam_topic',    'bbp_spam_topic_replies'    );
-add_action( 'bbp_unspam_topic', ' bbp_unspam_topic_replies'  );
+add_action( 'bbp_unspam_topic',  'bbp_unspam_topic_replies'  );
 
 // User status
 // @todo make these sub-actions
@@ -332,4 +336,4 @@
 // Maybe convert the users password
 add_action( 'bbp_login_form_login', 'bbp_user_maybe_convert_pass' );
 
-add_action( 'bbp_activation', 'bbp_add_activation_redirect' );
\ No newline at end of file
+add_action( 'bbp_activation', 'bbp_add_activation_redirect' );
Index: src/includes/forums/functions.php
===================================================================
--- src/includes/forums/functions.php	(revision 5446)
+++ src/includes/forums/functions.php	(working copy)
@@ -949,10 +949,10 @@
 	// First, delete everything.
 	delete_option( '_bbp_private_forums' );
 	delete_option( '_bbp_hidden_forums'  );
-	
+
 	/**
 	 * Don't search for both private/hidden statuses. Since 'pre_get_posts' is an
-	 * action, it's not removed by suppress_filters. We need to make sure that 
+	 * action, it's not removed by suppress_filters. We need to make sure that
 	 * we're only searching for the supplied post_status.
 	 *
 	 * @see https://bbpress.trac.wordpress.org/ticket/2512
@@ -974,7 +974,7 @@
 		'post_status'      => bbp_get_hidden_status_id(),
 		'fields'           => 'ids'
 	) );
-	
+
 	// Enable forum visibilty normalization
 	add_action( 'pre_get_posts', 'bbp_pre_get_posts_normalize_forum_visibility', 4 );
 
@@ -1096,6 +1096,7 @@
  * @param int $forum_id Optional. Forum id.
  * @param int $difference Optional. Default 1
  * @uses bbp_get_forum_id() To get the forum id
+ * @uses bbp_get_forum_topic_count_hidden To get the forum's hidden topic count
  * @uses update_post_meta() To update the forum's topic count meta
  * @uses apply_filters() Calls 'bbp_bump_forum_topic_count_hidden' with the
  *                        topic count, forum id, and difference
@@ -1462,7 +1463,8 @@
 }
 
 /**
- * Adjust the total hidden topic count of a forum (hidden includes trashed and spammed topics)
+ * Adjust the total hidden topic count of a forum (hidden includes trashed,
+ * spammed and pending topics)
  *
  * @since bbPress (r2888)
  *
@@ -1472,8 +1474,11 @@
  * @uses bbp_get_topic_id() To get the topic id
  * @uses bbp_get_topic_forum_id() To get the topic forum id
  * @uses bbp_get_forum_id() To get the forum id
+ * @uses bbp_get_trash_status_id() To get the trash status id
+ * @uses bbp_get_spam_status_id() To get the spam status id
+ * @uses bbp_get_pending_status_id() To get the pending status id
  * @uses wpdb::prepare() To prepare our sql query
- * @uses wpdb::get_col() To execute our query and get the column back
+ * @uses wpdb::get_var() To execute our query and get the var back
  * @uses update_post_meta() To update the forum hidden topic count meta
  * @uses apply_filters() Calls 'bbp_update_forum_topic_count_hidden' with the
  *                        hidden topic count and forum id
@@ -1493,11 +1498,11 @@
 	}
 
 	// Can't update what isn't there
-	if ( !empty( $forum_id ) ) {
+	if ( ! empty( $forum_id ) ) {
 
 		// Get topics of forum
 		if ( empty( $topic_count ) ) {
-			$post_status = "'" . implode( "','", array( bbp_get_trash_status_id(), bbp_get_spam_status_id() ) ) . "'";
+			$post_status = "'" . implode( "','", array( bbp_get_trash_status_id(), bbp_get_spam_status_id(), bbp_get_pending_status_id() ) ) . "'";
 			$topic_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(ID) FROM {$wpdb->posts} WHERE post_parent = %d AND post_status IN ( {$post_status} ) AND post_type = '%s';", $forum_id, bbp_get_topic_post_type() ) );
 		}
 
Index: src/includes/forums/template.php
===================================================================
--- src/includes/forums/template.php	(revision 5446)
+++ src/includes/forums/template.php	(working copy)
@@ -1427,8 +1427,8 @@
 	}
 
 /**
- * Output total hidden topic count of a forum (hidden includes trashed and
- * spammed topics)
+ * Output total hidden topic count of a forum (hidden includes trashed, spammed,
+ * and pending topics)
  *
  * @since bbPress (r2883)
  *
@@ -1440,8 +1440,8 @@
 	echo bbp_get_forum_topic_count_hidden( $forum_id, $integer );
 }
 	/**
-	 * Return total hidden topic count of a forum (hidden includes trashed
-	 * and spammed topics)
+	 * Return total hidden topic count of a forum (hidden includes trashed,
+	 * spammed and pending topics)
 	 *
 	 * @since bbPress (r2883)
 	 *
@@ -2245,7 +2245,7 @@
 
 		return apply_filters( 'bbp_get_form_forum_visibility', esc_attr( $forum_visibility ) );
 	}
-	
+
 /**
  * Output checked value of forum subscription
  *
Index: src/includes/replies/functions.php
===================================================================
--- src/includes/replies/functions.php	(revision 5446)
+++ src/includes/replies/functions.php	(working copy)
@@ -1163,7 +1163,7 @@
  * @return array
  */
 function bbp_get_reply_ancestors( $reply_id = 0 ) {
-	
+
 	// Validation
 	$reply_id  = bbp_get_reply_id( $reply_id );
 	$ancestors = array();
@@ -1469,7 +1469,7 @@
 	}
 
 	// Remove reply_to from moved reply
-	delete_post_meta( $move_reply->ID, '_bbp_reply_to' ); 
+	delete_post_meta( $move_reply->ID, '_bbp_reply_to' );
 
 	// It is a new topic and we need to set some default metas to make
 	// the topic display in bbp_has_topics() list
@@ -1582,7 +1582,8 @@
 	// Setup possible get actions
 	$possible_actions = array(
 		'bbp_toggle_reply_spam',
-		'bbp_toggle_reply_trash'
+		'bbp_toggle_reply_trash',
+		'bbp_toggle_reply_approve'
 	);
 
 	// Bail if actions aren't meant for this function
@@ -1611,6 +1612,17 @@
 	// What action are we trying to perform?
 	switch ( $action ) {
 
+		// Toggle approve
+		case 'bbp_toggle_reply_approve' :
+			check_ajax_referer( 'approve-reply_' . $reply_id );
+
+			$is_approve  = bbp_is_reply_pending( $reply_id );
+			$success  = $is_approve ? bbp_approve_reply( $reply_id ) : bbp_unapprove_reply( $reply_id );
+			$failure  = $is_approve ? __( '<strong>ERROR</strong>: There was a problem approving the reply!', 'bbpress' ) : __( '<strong>ERROR</strong>: There was a problem unapproving thereply!', 'bbpress' );
+			$view_all = !$is_approve;
+
+			break;
+
 		// Toggle spam
 		case 'bbp_toggle_reply_spam' :
 			check_ajax_referer( 'spam-reply_' . $reply_id );
@@ -1814,6 +1826,98 @@
 	return $reply_id;
 }
 
+/**
+ * Approves a reply
+ *
+ * @since bbPress (rXXXX)
+ *
+ * @param int $reply_id Reply id
+ * @uses bbp_get_reply() To get the reply
+ * @uses do_action() Calls 'bbp_approve_reply' with the reply id
+ /* @uses add_post_meta() To add the previous status to a meta
+ /* @uses delete_post_meta() To delete the previous status meta
+ * @uses wp_update_post() To update the reply with the new status
+ * @uses do_action() Calls 'bbp_approved_reply' with the reply id
+ * @return mixed False or {@link WP_Error} on failure, reply id on success
+ */
+function bbp_approve_reply( $reply_id = 0 ) {
+
+	// Get reply
+	$reply = bbp_get_reply( $reply_id );
+	if ( empty( $reply ) ) {
+		return $reply;
+	}
+
+	// Bail if already approved
+	if ( bbp_get_pending_status_id() !== $reply->post_status ) {
+		return false;
+	}
+
+	// Execute pre pending code
+	do_action( 'bbp_approve_reply', $reply_id );
+
+	// Set publish status
+	$reply->post_status = bbp_get_public_status_id();
+
+	// No revisions
+	remove_action( 'pre_post_update', 'wp_save_post_revision' );
+
+	// Update reply
+	$reply_id = wp_update_post( $reply );
+
+	// Execute post pending code
+	do_action( 'bbp_approved_reply', $reply_id );
+
+	// Return reply_id
+	return $reply_id;
+}
+
+/**
+ * Unapproves a reply
+ *
+ * @since bbPress (rXXXX)
+ *
+ * @param int $reply_id Reply id
+ * @uses bbp_get_reply() To get the reply
+ * @uses do_action() Calls 'bbp_unapprove_reply' with the reply id
+ /* @uses get_post_meta() To get the previous status
+ /* @uses delete_post_meta() To delete the previous status meta
+ * @uses wp_update_post() To update the reply with the new status
+ * @uses do_action() Calls 'bbp_unapproved_reply' with the reply id
+ * @return mixed False or {@link WP_Error} on failure, reply id on success
+ */
+function bbp_unapprove_reply( $reply_id = 0 ) {
+
+	// Get reply
+	$reply = bbp_get_reply( $reply_id );
+	if ( empty( $reply ) ) {
+		return $reply;
+	}
+
+	// Bail if already pending
+	if ( bbp_get_pending_status_id() === $reply->post_status ) {
+		return false;
+	}
+
+	// Execute pre open code
+	do_action( 'bbp_unapprove_reply', $reply_id );
+
+	// Set pending status
+	$reply->post_status = bbp_get_pending_status_id();
+
+	// No revisions
+	remove_action( 'pre_post_update', 'wp_save_post_revision' );
+
+	// Update reply
+	$reply_id = wp_update_post( $reply );
+
+	// Execute post open code
+	do_action( 'bbp_unapproved_reply', $reply_id );
+
+	// Return reply_id
+	return $reply_id;
+}
+
 /** Before Delete/Trash/Untrash ***********************************************/
 
 /**
@@ -2334,7 +2438,7 @@
 
 /**
  * Validate a `reply_to` field for hierarchical replies
- * 
+ *
  * Checks for 2 scenarios:
  * -- The reply to ID is actually a reply
  * -- The reply to ID does not match the current reply
Index: src/includes/replies/template.php
===================================================================
--- src/includes/replies/template.php	(revision 5446)
+++ src/includes/replies/template.php	(working copy)
@@ -150,7 +150,8 @@
 			bbp_get_public_status_id(),
 			bbp_get_closed_status_id(),
 			bbp_get_spam_status_id(),
-			bbp_get_trash_status_id()
+			bbp_get_trash_status_id(),
+			bbp_get_pending_status_id()
 		);
 
 		// Add support for private status
@@ -952,6 +953,38 @@
 }
 
 /**
+ * Is the reply pending?
+ *
+ * @since bbPress (rXXXX)
+ *
+ * @param int $reply_id Optional. Topic id
+ * @uses bbp_get_reply_id() To get the reply id
+ * @uses bbp_get_reply_status() To get the reply status
+ * @uses apply_filters() Calls 'bbp_is_reply_pending' with the reply id
+ * @return bool True if pending, false if not.
+ */
+function bbp_is_reply_pending( $reply_id = 0 ) {
+	$reply_status = bbp_get_reply_status( bbp_get_reply_id( $reply_id ) ) === bbp_get_pending_status_id();
+	return (bool) apply_filters( 'bbp_is_reply_pending', (bool) $reply_status, $reply_id );
+}
+
+/**
+ * Is the reply private?
+ *
+ * @since bbPress (rXXXX)
+ *
+ * @param int $reply_id Optional. Topic id
+ * @uses bbp_get_reply_id() To get the reply id
+ * @uses bbp_get_reply_status() To get the reply status
+ * @uses apply_filters() Calls 'bbp_is_reply_private' with the reply id
+ * @return bool True if private, false if not.
+ */
+function bbp_is_reply_private( $reply_id = 0 ) {
+	$reply_status = bbp_get_reply_status( bbp_get_reply_id( $reply_id ) ) === bbp_get_private_status_id();
+	return (bool) apply_filters( 'bbp_is_reply_private', (bool) $reply_status, $reply_id );
+}
+
+/**
  * Is the reply by an anonymous user?
  *
  * @since bbPress (r2753)
@@ -1853,18 +1886,19 @@
 		// If no links were passed, default to the standard
 		if ( empty( $r['links'] ) ) {
 			$r['links'] = apply_filters( 'bbp_reply_admin_links', array(
-				'edit'  => bbp_get_reply_edit_link ( $r ),
-				'move'  => bbp_get_reply_move_link ( $r ),
-				'split' => bbp_get_topic_split_link( $r ),
-				'trash' => bbp_get_reply_trash_link( $r ),
-				'spam'  => bbp_get_reply_spam_link ( $r ),
-				'reply' => bbp_get_reply_to_link   ( $r )
+				'edit'    => bbp_get_reply_edit_link   ( $r ),
+				'move'    => bbp_get_reply_move_link   ( $r ),
+				'split'   => bbp_get_topic_split_link  ( $r ),
+				'trash'   => bbp_get_reply_trash_link  ( $r ),
+				'spam'    => bbp_get_reply_spam_link   ( $r ),
+				'approve' => bbp_get_reply_approve_link( $r ),
+				'reply'   => bbp_get_reply_to_link     ( $r )
 			), $r['id'] );
 		}
 
 		// See if links need to be unset
 		$reply_status = bbp_get_reply_status( $r['id'] );
-		if ( in_array( $reply_status, array( bbp_get_spam_status_id(), bbp_get_trash_status_id() ) ) ) {
+		if ( in_array( $reply_status, array( bbp_get_spam_status_id(), bbp_get_trash_status_id(), bbp_get_pending_status_id() ) ) ) {
 
 			// Spam link shouldn't be visible on trashed topics
 			if ( bbp_get_trash_status_id() === $reply_status ) {
@@ -2273,6 +2307,66 @@
 	}
 
 /**
+ * Output the approve link of the reply
+ *
+ * @since bbPress (rXXXX)
+ *
+ * @param mixed $args See {@link bbp_get_reply_approve_link()}
+ * @uses bbp_get_reply_approve_link() To get the reply approve link
+ */
+function bbp_reply_approve_link( $args = '' ) {
+	echo bbp_get_reply_approve_link( $args );
+}
+
+	/**
+	 * Return the approve link of the reply
+	 *
+	 * @since bbPress (rXXXX)
+	 *
+	 * @param mixed $args This function supports these args:
+	 *  - id: Optional. Reply id
+	 *  - link_before: Before the link
+	 *  - link_after: After the link
+	 *  - sep: Separator between links
+	 *  - approve_text: Approve text
+	 *  - unapprove_text: Unapprove text
+	 * @uses bbp_get_reply_id() To get the reply id
+	 * @uses bbp_get_reply() To get the reply
+	 * @uses current_user_can() To check if the current user can approve the reply
+	 * @uses bbp_is_reply_pending() To check if the reply is pending
+	 * @uses add_query_arg() To add custom args to the url
+	 * @uses wp_nonce_url() To nonce the url
+	 * @uses esc_url() To escape the url
+	 * @uses apply_filters() Calls 'bbp_get_reply_approve_link' with the link
+	 *                        and args
+	 * @return string Reply approve link
+	 */
+	function bbp_get_reply_approve_link( $args = '' ) {
+
+		// Parse arguments against default values
+		$r = bbp_parse_args( $args, array(
+			'id'             => 0,
+			'link_before'    => '',
+			'link_after'     => '',
+			'sep'            => ' | ',
+			'approve_text'   => _x( 'Approve', 'Pending Status', 'bbpress' ),
+			'unapprove_text' => _x( 'Unapprove',  'Pending Status', 'bbpress' )
+		), 'get_reply_approve_link' );
+
+		$reply = bbp_get_reply( bbp_get_reply_id( (int) $r['id'] ) );
+
+		if ( empty( $reply ) || !current_user_can( 'moderate', $reply->ID ) )
+			return;
+
+		$display = bbp_is_reply_pending( $reply->ID ) ? $r['approve_text'] : $r['unapprove_text'];
+		$uri     = add_query_arg( array( 'action' => 'bbp_toggle_reply_approve', 'reply_id' => $reply->ID ) );
+		$uri     = wp_nonce_url( $uri, 'approve-reply_' . $reply->ID );
+		$retval  = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-reply-approve-link">' . $display . '</a>' . $r['link_after'];
+
+		return apply_filters( 'bbp_get_reply_approve_link', $retval, $r );
+	}
+
+/**
  * Output the row class of a reply
  *
  * @since bbPress (r2678)
Index: src/includes/search/template.php
===================================================================
--- src/includes/search/template.php	(revision 5446)
+++ src/includes/search/template.php	(working copy)
@@ -64,7 +64,8 @@
 			bbp_get_public_status_id(),
 			bbp_get_closed_status_id(),
 			bbp_get_spam_status_id(),
-			bbp_get_trash_status_id()
+			bbp_get_trash_status_id(),
+			bbp_get_pending_status_id()
 		);
 
 		// Add support for private status
@@ -141,7 +142,7 @@
 				'prev_text' => is_rtl() ? '&rarr;' : '&larr;',
 				'next_text' => is_rtl() ? '&larr;' : '&rarr;',
 				'mid_size'  => 1,
-				'add_args'  => $add_args, 
+				'add_args'  => $add_args,
 			) )
 		);
 
Index: src/includes/topics/functions.php
===================================================================
--- src/includes/topics/functions.php	(revision 5446)
+++ src/includes/topics/functions.php	(working copy)
@@ -2112,7 +2112,8 @@
 		'bbp_toggle_topic_close',
 		'bbp_toggle_topic_stick',
 		'bbp_toggle_topic_spam',
-		'bbp_toggle_topic_trash'
+		'bbp_toggle_topic_trash',
+		'bbp_toggle_topic_approve'
 	);
 
 	// Bail if actions aren't meant for this function
@@ -2142,6 +2143,16 @@
 	// What action are we trying to perform?
 	switch ( $action ) {
 
+		// Toggle approve/unapprove
+		case 'bbp_toggle_topic_approve' :
+			check_ajax_referer( 'approve-topic_' . $topic_id );
+
+			$is_pending = bbp_is_topic_pending( $topic_id );
+			$success    = true === $is_pending ? bbp_approve_topic( $topic_id ) : bbp_unapprove_topic( $topic_id );
+			$failure    = true === $is_pending ? __( '<strong>ERROR</strong>: There was a problem approving the topic.', 'bbpress' ) : __( '<strong>ERROR</strong>: There was a problem unapproving the topic.', 'bbpress' );
+
+			break;
+
 		// Toggle open/close
 		case 'bbp_toggle_topic_close' :
 			check_ajax_referer( 'close-topic_' . $topic_id );
@@ -2354,6 +2365,7 @@
  * @param int $topic_id Optional. Forum id.
  * @param int $difference Optional. Default 1
  * @uses bbp_get_topic_id() To get the topic id
+ * @uses bbp_get_topic_reply_count_hidden To get the topic's hidden reply count
  * @uses update_post_meta() To update the topic's reply count meta
  * @uses apply_filters() Calls 'bbp_bump_topic_reply_count_hidden' with the
  *                        reply count, topic id, and difference
@@ -2465,7 +2477,8 @@
 }
 
 /**
- * Adjust the total hidden reply count of a topic (hidden includes trashed and spammed replies)
+ * Adjust the total hidden reply count of a topic (hidden includes trashed,
+ * spammed and pending replies)
  *
  * @since bbPress (r2740)
  *
@@ -2474,6 +2487,9 @@
  * @uses bbp_is_reply() To check if the passed topic id is a reply
  * @uses bbp_get_reply_topic_id() To get the reply topic id
  * @uses bbp_get_topic_id() To get the topic id
+ * @uses bbp_get_trash_status_id() To get the trash status id
+ * @uses bbp_get_spam_status_id() To get the spam status id
+ * @uses bbp_get_pending_status_id() To get the pending status id
  * @uses bbp_get_reply_post_type() To get the reply post type
  * @uses wpdb::prepare() To prepare our sql query
  * @uses wpdb::get_var() To execute our query and get the var back
@@ -2494,7 +2510,7 @@
 
 	// Get replies of topic
 	if ( empty( $reply_count ) ) {
-		$post_status = "'" . implode( "','", array( bbp_get_trash_status_id(), bbp_get_spam_status_id() ) ) . "'";
+		$post_status = "'" . implode( "','", array( bbp_get_trash_status_id(), bbp_get_spam_status_id(), bbp_get_pending_status_id() ) ) . "'";
 		$reply_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(ID) FROM {$wpdb->posts} WHERE post_parent = %d AND post_status IN ( {$post_status} ) AND post_type = '%s';", $topic_id, bbp_get_reply_post_type() ) );
 	}
 
@@ -3174,6 +3190,98 @@
 }
 
 /**
+ * Approves a topic
+ *
+ * @since bbPress (rXXXX)
+ *
+ * @param int $topic_id Topic id
+ * @uses bbp_get_topic() To get the topic
+ * @uses do_action() Calls 'bbp_approve_topic' with the topic id
+ /* @uses add_post_meta() To add the previous status to a meta
+ /* @uses delete_post_meta() To delete the previous status meta
+ * @uses wp_update_post() To update the topic with the new status
+ * @uses do_action() Calls 'bbp_approved_topic' with the topic id
+ * @return mixed False or {@link WP_Error} on failure, topic id on success
+ */
+function bbp_approve_topic( $topic_id = 0 ) {
+
+	// Get topic
+	$topic = bbp_get_topic( $topic_id );
+	if ( empty( $topic ) ) {
+		return $topic;
+	}
+
+	// Bail if already approved
+	if ( bbp_get_pending_status_id() !== $topic->post_status ) {
+		return false;
+	}
+
+	// Execute pre pending code
+	do_action( 'bbp_approve_topic', $topic_id );
+
+	// Set publish status
+	$topic->post_status = bbp_get_public_status_id();
+
+	// No revisions
+	remove_action( 'pre_post_update', 'wp_save_post_revision' );
+
+	// Update topic
+	$topic_id = wp_update_post( $topic );
+
+	// Execute post pending code
+	do_action( 'bbp_approved_topic', $topic_id );
+
+	// Return topic_id
+	return $topic_id;
+}
+
+/**
+ * Unapproves a topic
+ *
+ * @since bbPress (rXXXX)
+ *
+ * @param int $topic_id Topic id
+ * @uses bbp_get_topic() To get the topic
+ * @uses do_action() Calls 'bbp_unapprove_topic' with the topic id
+ /* @uses get_post_meta() To get the previous status
+ /* @uses delete_post_meta() To delete the previous status meta
+ * @uses wp_update_post() To update the topic with the new status
+ * @uses do_action() Calls 'bbp_unapproved_topic' with the topic id
+ * @return mixed False or {@link WP_Error} on failure, topic id on success
+ */
+function bbp_unapprove_topic( $topic_id = 0 ) {
+
+	// Get topic
+	$topic = bbp_get_topic( $topic_id );
+	if ( empty( $topic ) ) {
+		return $topic;
+	}
+
+	// Bail if already pending
+	if ( bbp_get_pending_status_id() === $topic->post_status ) {
+		return false;
+	}
+
+	// Execute pre open code
+	do_action( 'bbp_unapprove_topic', $topic_id );
+
+	// Set pending status
+	$topic->post_status = bbp_get_pending_status_id();
+
+	// No revisions
+	remove_action( 'pre_post_update', 'wp_save_post_revision' );
+
+	// Update topic
+	$topic_id = wp_update_post( $topic );
+
+	// Execute post open code
+	do_action( 'bbp_unapproved_topic', $topic_id );
+
+	// Return topic_id
+	return $topic_id;
+}
+
+/**
  * Unsticks a topic both from front and it's forum
  *
  * @since bbPress (r2754)
Index: src/includes/topics/template.php
===================================================================
--- src/includes/topics/template.php	(revision 5446)
+++ src/includes/topics/template.php	(working copy)
@@ -171,7 +171,8 @@
 			bbp_get_public_status_id(),
 			bbp_get_closed_status_id(),
 			bbp_get_spam_status_id(),
-			bbp_get_trash_status_id()
+			bbp_get_trash_status_id(),
+			bbp_get_pending_status_id()
 		);
 
 		// Add support for private status
@@ -1226,6 +1227,38 @@
 }
 
 /**
+ * Is the topic pending?
+ *
+ * @since bbPress (rXXXX)
+ *
+ * @param int $topic_id Optional. Topic id
+ * @uses bbp_get_topic_id() To get the topic id
+ * @uses bbp_get_topic_status() To get the topic status
+ * @uses apply_filters() Calls 'bbp_is_topic_pending' with the topic id
+ * @return bool True if pending, false if not.
+ */
+function bbp_is_topic_pending( $topic_id = 0 ) {
+	$topic_status = bbp_get_topic_status( bbp_get_topic_id( $topic_id ) ) === bbp_get_pending_status_id();
+	return (bool) apply_filters( 'bbp_is_topic_pending', (bool) $topic_status, $topic_id );
+}
+
+/**
+ * Is the topic private?
+ *
+ * @since bbPress (rXXXX)
+ *
+ * @param int $topic_id Optional. Topic id
+ * @uses bbp_get_topic_id() To get the topic id
+ * @uses bbp_get_topic_status() To get the topic status
+ * @uses apply_filters() Calls 'bbp_is_topic_private' with the topic id
+ * @return bool True if private, false if not.
+ */
+function bbp_is_topic_private( $topic_id = 0 ) {
+	$topic_status = bbp_get_topic_status( bbp_get_topic_id( $topic_id ) ) === bbp_get_private_status_id();
+	return (bool) apply_filters( 'bbp_is_topic_private', (bool) $topic_status, $topic_id );
+}
+
+/**
  * Is the posted by an anonymous user?
  *
  * @since bbPress (r2753)
@@ -2441,21 +2474,22 @@
 
 		if ( empty( $r['links'] ) ) {
 			$r['links'] = apply_filters( 'bbp_topic_admin_links', array(
-				'edit'  => bbp_get_topic_edit_link ( $r ),
-				'close' => bbp_get_topic_close_link( $r ),
-				'stick' => bbp_get_topic_stick_link( $r ),
-				'merge' => bbp_get_topic_merge_link( $r ),
-				'trash' => bbp_get_topic_trash_link( $r ),
-				'spam'  => bbp_get_topic_spam_link ( $r ),
-				'reply' => bbp_get_topic_reply_link( $r )
+				'edit'    => bbp_get_topic_edit_link   ( $r ),
+				'close'   => bbp_get_topic_close_link  ( $r ),
+				'stick'   => bbp_get_topic_stick_link  ( $r ),
+				'merge'   => bbp_get_topic_merge_link  ( $r ),
+				'trash'   => bbp_get_topic_trash_link  ( $r ),
+				'spam'    => bbp_get_topic_spam_link   ( $r ),
+				'approve' => bbp_get_topic_approve_link( $r ),
+				'reply'   => bbp_get_topic_reply_link  ( $r )
 			), $r['id'] );
 		}
 
 		// See if links need to be unset
 		$topic_status = bbp_get_topic_status( $r['id'] );
-		if ( in_array( $topic_status, array( bbp_get_spam_status_id(), bbp_get_trash_status_id() ) ) ) {
+		if ( in_array( $topic_status, array( bbp_get_spam_status_id(), bbp_get_trash_status_id(), bbp_get_pending_status_id() ) ) ) {
 
-			// Close link shouldn't be visible on trashed/spammed topics
+			// Close link shouldn't be visible on trashed/spammed/pending topics
 			unset( $r['links']['close'] );
 
 			// Spam link shouldn't be visible on trashed topics
@@ -2728,6 +2762,66 @@
 	}
 
 /**
+ * Output the approve link of the topic
+ *
+ * @since bbPress (rXXXX)
+ *
+ * @param mixed $args See {@link bbp_get_topic_approve_link()}
+ * @uses bbp_get_topic_approve_link() To get the topic approve link
+ */
+function bbp_topic_approve_link( $args = '' ) {
+	echo bbp_get_topic_approve_link( $args );
+}
+
+	/**
+	 * Return the approve link of the topic
+	 *
+	 * @since bbPress (rXXXX)
+	 *
+	 * @param mixed $args This function supports these args:
+	 *  - id: Optional. Topic id
+	 *  - link_before: Before the link
+	 *  - link_after: After the link
+	 *  - sep: Separator between links
+	 *  - approve_text: Approve text
+	 *  - unapprove_text: Unapprove text
+	 * @uses bbp_get_topic_id() To get the topic id
+	 * @uses bbp_get_topic() To get the topic
+	 * @uses current_user_can() To check if the current user can approve the topic
+	 * @uses bbp_is_topic_pending() To check if the topic is pending
+	 * @uses add_query_arg() To add custom args to the url
+	 * @uses wp_nonce_url() To nonce the url
+	 * @uses esc_url() To escape the url
+	 * @uses apply_filters() Calls 'bbp_get_topic_approve_link' with the link
+	 *                        and args
+	 * @return string Topic approve link
+	 */
+	function bbp_get_topic_approve_link( $args = '' ) {
+
+		// Parse arguments against default values
+		$r = bbp_parse_args( $args, array(
+			'id'             => 0,
+			'link_before'    => '',
+			'link_after'     => '',
+			'sep'            => ' | ',
+			'approve_text'   => _x( 'Approve', 'Pending Status', 'bbpress' ),
+			'unapprove_text' => _x( 'Unapprove',  'Pending Status', 'bbpress' )
+		), 'get_topic_approve_link' );
+
+		$topic = bbp_get_topic( bbp_get_topic_id( (int) $r['id'] ) );
+
+		if ( empty( $topic ) || !current_user_can( 'moderate', $topic->ID ) )
+			return;
+
+		$display = bbp_is_topic_pending( $topic->ID ) ? $r['approve_text'] : $r['unapprove_text'];
+		$uri     = add_query_arg( array( 'action' => 'bbp_toggle_topic_approve', 'topic_id' => $topic->ID ) );
+		$uri     = wp_nonce_url( $uri, 'approve-topic_' . $topic->ID );
+		$retval  = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-topic-approve-link">' . $display . '</a>' . $r['link_after'];
+
+		return apply_filters( 'bbp_get_topic_approve_link', $retval, $r );
+	}
+
+/**
  * Output the stick link of the topic
  *
  * @since bbPress (r2754)
Index: src/templates/default/css/bbpress.css
===================================================================
--- src/templates/default/css/bbpress.css	(revision 5446)
+++ src/templates/default/css/bbpress.css	(working copy)
@@ -54,6 +54,12 @@
 	background-color: #fdd;
 }
 
+#bbpress-forums .status-pending.even,
+#bbpress-forums .status-pending.odd,
+#bbpress-forums ul.status-pending a {
+	background-color: #fef7f1;
+}
+
 #bbpress-forums ul.status-closed,
 #bbpress-forums ul.status-closed a {
 	color: #ccc;
