Tag Archives: forums

“Posts per page” dropdown for BuddyPress single forum topic view

This morning I whipped up a little BuddyPress ditty for the CUNY Academic Commons that allows your members to select how many posts they’d like to see at a time when viewing a single forum topic. It’s not particularly beautiful (for one thing, it requires Javascript to work correctly, though it degrades gracefully by not showing up when no jQuery is available). For that reason, it’s probably not really appropriate for distribution in BuddyPress itself, at least not without some heavy cleanup. Anyway, here it is:

In your theme’s functions.php, place the following function:

[code language=”php”]
/**
* Echoes the markup for the “number of posts per page” dropdown on forum topics
*/
function cac_forums_show_per_page_dropdown() {
global $topic_template;

// Get the current number, so we can preselect the dropdown
$selected = in_array( $topic_template->pag_num, array( 5, 15, 30 ) ) ? $topic_template->pag_num : $topic_template->total_post_count;

// Inject the javascript
?>

jQuery(document).ready( function() {
jQuery(‘div#posts-per-page-wrapper’).show();
jQuery(‘select#posts-per-page’).change(function(){
var url = ‘?topic_page=1&num=’ + jQuery(this).val();
window.location = url;
});
});

Posts per page:

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.

[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!

Upgrading from BuddyPress 1.0 to 1.1

The upgrade from BuddyPress 1.0.x to BuddyPress 1.1 on the CUNY Academic Commons posed a number of challenges. Between the big changes to theme structure, the one-click installation of bbPress forums, and ongoing plugin compatibility issues, a lot of planning and testing was required. This week, I and the rest of the CAC development team finally made the switch. Over the course of a few practice upgrades in development environments, followed by an upgrade on the production site, I developed a pretty detailed set of instructions for myself. I thought I’d write up an annotated version of those instructions, for the benefit of anyone who might be facing a similar upgrade.

The Academic Commons had previously been set up roughly along the same lines as Jim Groom describes here: with bbPress storing its data in a separate database, but through the cunning use of various clever plugins, sharing user data, cookies, and BP group info with the WPMU installation. BP 1.1 does things differently: the one click installation of BP forums expects to store its data in tables that exist in the BP/WP database. In order to save the old data, we had two choices: move the old data into the new structure, or make BP 1.1 recognize the old db setup. Fellow dev team member Chris Stein and I decided that the former choice would be the easiest and most future proof. Here’s how it was done.

    Dealing with bbPress forums

  1. Move orphan forums into groups. Strictly speaking, this doesn’t have to be done first, but if you’ve got bbPress forums that aren’t attached to groups, you’ve got to get them in a group in order for them to display in BP. To the best of my knowledge, there’s no really way to do this from the bbPress or BP admin panels, but it’s easy to do manually. Set up a new group for each forum (a “Help” forum might get a “Help” group, for example), make sure the group has discussion forums enabled, and then find the line in table wp_bp_groups_groupmeta corresponding to the group_id of the new group and meta key `forum_id`, and change the meta_value to match the forum number of the orphan group. Rinse and repeat.
  2. Export your bbPress database to a local file.
  3. Replace HTML markup. bbPress (my installation at least) stored formatting in HTML. The most common markup has to do with line breaks: bbPress interprets a single line break in a forum post as <br />, and double line breaks as </p> and <p>. Opening the local version of the bbPress db in a plain text editor, I did a couple big search-and-replaces:
    • </p>\n<p> became nrnr (redundant UNIX newlines)
    • Some <p> and </p> tags still remain (single paragraph posts), which I replaced with an empty string
    • <br /> became nr

    You’ll also need to make sure that all references to tables in the SQL dump are replaced with the proper names. For me, that meant replacing things like bb_posts with wp_bb_posts, but it might be different depending on the prefixes you use for bbPress and WP. If you’re not sure about how BP will name the tables, do the one-button forum setup in BP 1.1 (as a new installation) and post a test forum item, to make sure the forums get created. Then check out the database to see how BP formats table names on your install.

  4. Upgrading

    The instructions at buddypress.org are quite helpful. Here’s a short version:

  5. Deactivate BP-dependent plugins. I once neglected to do this. If you do, and then deactivate BP, there is a very good chance that your entire site will go white-screen-of-death, as the plugins will be making reference to BP functions that do not exist. Check your plugin list three or four times to make sure you’ve deactivated each one that has to do with BuddyPress. I like to make a list, so that I remember which ones to activate after the upgrade (though some, like the bbPress integration plugins, won’t be necessary).
  6. Back up all your data. Always! I like to take a snapshot of the whole database, and then an individual export of the wp_sitemeta table. That way, if I screw anything up (say, by deactivating plugins in the wrong order!) I can bring the site back to life by reverting to a previous state that is known to work.
  7. Upgrade BuddyPress. Deactivate, upload, reactivate.
  8. Reactivate BP dependent plugins. I didn’t have too many issues with plugin compatibility, but you might, depending on what you use. Some plugins will not be necessary anymore, while others (like Forum Attachments for BuddyPress) become useful.
  9. Themes

    The CUNY Academic Commons was in the midst of a redesign, so it made sense to have the new design implemented in BuddyPress’s new, parent-child theme environment. Buddypress.org has some instructions that you might find helpful. Our theme consists of a highly customized home page, header, and footer, with interior BuddyPress pages that are more or less similar in terms of markup to the BuddyPress parent theme. Thus it made sense for us to create a child theme in wp-content/themes (by copying and renaming the bp-default folder that comes with BuddyPress), make our CSS changes, and fill our child theme with only those templates where our markup had to differ from bp-sn-parent. For us that means home.php, header.php, footer.php, functions.php (which does not override but adds to bp-sn-parent/functions.php), and a few other miscellaneous files. How to implement:

  10. Rename bp-themes. If BuddyPress sees the bp-themes folder, it will assume that you’re going to use the older, deprecated theme structure. I renamed it to bp-themes-old, and will remove it altogether once we’re 100% done with the migration.
  11. Move bp-sn-parent, bp-default, and your child theme to the main WP themes folder. In most cases this is wp-content/themes.
  12. Activate the themes in Dashboard > Site Admin > Themes. No need to activate bp-sn-parent, since it’s not used directly.
  13. Apply the child theme of your choice (either bp-default or your custom theme) to the main blog.
  14. Setting up the forums

    You’ve exported and modified the forum data from the bbPress standalone version, but you’ll still need to get them into BP.

  15. Rename /forums. In our case, our previous installation of bbPress just happened to live at [BP install dir]/forums – exactly where the BP 1.1 forum directory goes. I don’t think it’d hurt anything to leave that folder named the way it is (because of the order in which BP handles URL arguments), but just to be safe I changed it to forums-old.
  16. Set up BP forums. In Dashboard > BuddyPress > Forum Setup, set up forums as a new installation.
  17. Drop the empty forum tables from the BP database. I can’t remember whether BP creates the forum tables upon installation or upon the first forum post, but in any case you won’t be able to import your old data properly without first dropping any table prefixed with wp_bb_.
  18. Import the modified local version of your forum data. I did it in PHPMyAdmin, which was easy because the file had been exported in the form of a huge INSERT command. If all goes well – and it should! – you should now be able to navigate to your groups and see the proper forum posts for that group.

There are kinks we’re still trying to work out of the system. Some strange things happened to some users’ avatars after the upgrade. And tweaking the theme is turning out to be a hassle in a lot of ways. But overall, the migration of data – which I had lost a bit of sleep over – went extremely smoothly. Good luck!

Forum Attachments for BuddyPress

I posted about this a while ago, but I have ported _ck_’s bb_attachments plugin to BP 1.1.x. I took some time today to clean up the readme files and submit the plugin to the wordpress.com plugin database. Nothing about the plugin itself, or the hooks you’ll have to put into your theme, has changed since my last post; but at least now you’ll receive the file with full documentation and can use the WP plugin installer to install and maintain this bad boy.

Get it here or by searching for “forum attachments” on WP’s Add New Plugin page.

Bug reports (and especially patches!) are welcome.