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.
[code language=”php”]
/**
* 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;
}
[/code]
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.
[code language=”html”]
[/code]
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.
[code language=”css”]
.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;
}
[/code]
Good luck!