Redirect BuddyPress activity reply links to forum’s “Leave a Reply”

Activity stream replies in BuddyPress are pretty cool, but they have the potential to be confusing. On the CUNY Academic Commons, we have disabled activity replies for activity entries related to blogs and forums, because allowing replies in these cases has the potential to confuse users and fracture conversation.

There are a number of ways that this could (and should, and will!) be improved in future versions of BuddyPress. But, for now, here’s a trick. The following code will change the behavior of the Reply buttons for forum-related activity entries (new forum topics, and forum topic replies), so that instead of sliding down the inline activity comment box, it goes to the Reply form on the forum topic itself.

Side note: This seems like it’d be an easy thing to do, but it turns out to be somewhat complex. As I explain in the inline documentation, the issue of pagination means that there’s no predictable way to easily concatenate a URL for a topic’s reply box (this is one of the things I want to fix in BP core) – you have to fetch the number of total replies and figure out the last page from there. Also, in the case of topic replies, you have to do an additional query to get the id of the topic that the post belongs to, because that info is not stored in the activity table. The function cac_insert_comment_reply_links() below tries to consolidate these lookups to add as few queries as possible to the pageload.

Second side note: This code is not particularly beautiful. It makes direct queries to the bbPress database tables. So sue me.

OK, so the code itself. First, put this chunk into your bp-custom.php file.

/**
 * Gets accurate reply URLs for the activity stream
 *
 * Getting accurate Reply links for forum topics is tricky because of pagination - you need to know
 * how many total posts are in the topic so that you can figure out what the last page should be.
 * Moreover, the forum reply activity items don't have the topic_id stored with them. This function
 * attempts to minimize DB queries by looking up all topic_ids at once, then looking up all post
 * counts at once - adding 2 queries for the activity loop is better than 20.
 *
 * Todo: Get a real redirecter into BuddyPress itself
 */
function cac_insert_comment_reply_links( $has_comments ) {
	global $activities_template, $wpdb, $bbdb;

	do_action( 'bbpress_init' );

	$topics_data = array();
	$posts_data = array();
	foreach( $activities_template->activities as $key => $activity ) {
		if ( $activity->type == 'new_forum_topic' ) {
			$topic_id = $activity->secondary_item_id;
			$topics_data[$topic_id]['url'] = $activity->primary_link;
			$topics_data[$topic_id]['activity_key'] = $key;	
		}

		if ( $activity->type == 'new_forum_post' ) {
			$post_id = $activity->secondary_item_id;
			$posts_data[$post_id]['url'] = array_pop( array_reverse( explode( '#', $activity->primary_link ) ) );
			$posts_data[$post_id]['activity_key'] = $key; 
		}
	}

	// In cases where we only have the post id, we must do an extra query to get topic ids
	if ( !empty( $posts_data ) ) {
		$post_ids 	= array_keys( $posts_data );
		$post_ids_sql 	= implode( ',', $post_ids );
		$sql 		= $wpdb->prepare( "SELECT topic_id, post_id FROM {$bbdb->posts} WHERE post_id IN ({$post_ids_sql})" );
		$post_topic_ids = $wpdb->get_results( $sql );

		// Now that we have the topic IDs, we can add that info to $topics_data for the main query
		foreach( $post_topic_ids as $post_topic ) {
			$topics_data[$post_topic->topic_id] = $posts_data[$post_topic->post_id];
		}
	}

	// Now for the main event
	// First, make a topic list and get all the associated posts
	$topic_ids 	= implode( ',', array_keys( $topics_data ) );
	$sql		= $wpdb->prepare( "SELECT topic_id, post_id FROM {$bbdb->posts} WHERE topic_id IN ({$topic_ids})" );
	$posts		= $wpdb->get_results( $sql );

	// Now we get counts. BTW it sucks to do it this way
	$counter	= array();
	foreach( $posts as $post ) {
		if ( empty( $counter[$post->topic_id] ) )
			$counter[$post->topic_id] = 1;
		else
			$counter[$post->topic_id]++;
	}

	// Finally, concatenate the reply url and put it in the activities_template
	foreach( $topics_data as $topic_id => $data ) {
		$total_pages = ceil( $counter[$topic_id] / 15 );	
		$reply_url = cac_forum_reply_url( $data['url'], $total_pages, 15 );
		$key = $data['activity_key'];
		$activities_template->activities[$key]->reply_url = $reply_url;
	}

	return $has_comments;
}
add_action( 'bp_has_activities', 'cac_insert_comment_reply_links' );

/**
 * Filters the url of the activity reply link to use reply_url, if present
 */
function cac_filter_activity_reply_link( $link ) {
	global $activities_template;

	if ( !empty( $activities_template->activity->reply_url ) )
		return $activities_template->activity->reply_url;
	else
		return $link;
}
add_action( 'bp_get_activity_comment_link', 'cac_filter_activity_reply_link' );

/**
 * Echoes the proper CSS class for the activity reply link. This is necessary to ensure that 
 * the JS slider does not appear when we have a custom reply_url.
 */
function cac_activity_reply_link_class() {
	global $activities_template;

	if ( !empty( $activities_template->activity->reply_url ) )
		echo 'class="acomment-reply-nojs"';
	else
		echo 'class="acomment-reply"';
}

/**
 * A replacement for bp_activity_can_comment(). Todo: deprecate into a filter when BP 1.3 comes out
 */
function cac_activity_can_comment() {
	global $activities_template, $bp;

	if ( false === $activities_template->disable_blogforum_replies || (int)$activities_template->disable_blogforum_replies ) {
		// If we've got a manually created reply_url (see cac_insert_comment_reply_links(), return true
		if ( !empty( $activities_template->activity->reply_url ) )
			return true;

		if ( 'new_blog_post' == bp_get_activity_action_name() || 'new_blog_comment' == bp_get_activity_action_name() || 'new_forum_topic' == bp_get_activity_action_name() || 'new_forum_post' == bp_get_activity_action_name() )
			return false;
	}
	
	return true;
}

You’ll note that there are a few places in that code where the number 15 is mentioned explicitly. I’m assuming that you’re using 15 posts-per-page for your single topic pagination. You can change this number accordingly if you want.

Next, you’ll have to make a few changes in your theme’s activity/entry.php to account for the changes. There are two relevant changes. First, you’ll be removing the activity reply button’s CSS class (hardcoded by default) and replacing it with the dynamically generated version in cac_activity_reply_link_class(). Second, you’ll be swapping out the checks for bp_activity_can_comment() with cac_activity_can_comment(), so that you can still block blog-activity comments. The code below is lines 27-29 of my activity/entry.php – you should be able to figure out which lines to replace with the following, as I haven’t changed much.

<?php if ( is_user_logged_in() &amp;&amp; cac_activity_can_comment() ) : ?>
	<a href="<?php bp_activity_comment_link() ?>" <?php cac_activity_reply_link_class() ?> id="acomment-comment-<?php bp_activity_id() ?>"><?php _e( 'Reply', 'buddypress' ) ?> (<span><?php bp_activity_comment_count() ?></span>)</a>
<?php endif; ?>

Finally, because you’ve changed the CSS selector on some of the reply buttons, you’ll want to add some styles to your stylesheet. These are borrowed right from bp-default.

.activity-list div.activity-meta a.acomment-reply-nojs {
	background: #fff9db;
	border-bottom: 1px solid #ffe8c4;
	border-right: 1px solid #ffe8c4;
	color: #ffa200;
}

div.activity-meta a.acomment-reply-nojs:hover {
	background: #f7740a;
	color: #fff;
    border-color: #f7740a;
}

Good luck!

13 thoughts on “Redirect BuddyPress activity reply links to forum’s “Leave a Reply””

  1. This code has fixed one of the problems I was having on one of my sites – thank you – i just hope that this will be implimented in a future version of BP so that i dont have to make this change on any new sites I have using BP

  2. I agree with Deryk, there has to be an easier way to do this… at least we have a work around at the moment though so thanks for that 🙂

  3. I was having on one of my sites – thank you – i just hope that this will be implimented in a future version of BP so that i dont have to make this change on any new sites I have using BPīŧŸīŧŸīŧŸ

  4. I’m working on implementing this current. It appears that only the most recent forum topic and/or forum reply is being affected by this. Is that the intended effect?

    If so, how would I adjust to affect all forum topics / forum replies in the activity stream?

  5. eric…the link doesn’t work. it gives a 404 error.

    does anyone else have knowledge of a plugin that works? please help!

  6. This code has settled one of the issues I was having on one of my locales – thank you – I simply trust that this will be actualized in a future rendition of BP with the goal that I don’t need to roll out this improvement on any new destinations I have utilizing BP

Leave a Reply

Your email address will not be published. Required fields are marked *

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Anti-spam image