[FIXED] bbPress Threaded (nested) Replies with Paging

I would like to share a guide on how I implemented bbPress threaded (nested) replies with paging, using the latest version of bbPress (2.5.8 as of this post).

A couple of weeks ago, I was working on a membership site project for a client, where we decided to implement bbPress as our community forum. Initially, we launched the forum using only paging and displaying 20 replies per page. As the community grew, and users were starting to engage, we noticed that replies to replies (nested replies) were added to the end of the list and were appearing on the last page. This was considered “bad” user experience and we decided to implement threaded (nested) replies feature of bbPress.

After a few styling changes, the threaded replies looked great however now, we were faced with a new problem – all topic replies were loading on the same page. After a quick research, it turned out that this is by design. When you enable threaded replies, pagination was automatically turned off:

bbPress enable threaded replies

While this maybe fine on smaller community forums, we had topics holding more that 600 replies. Not only, it was really long to scroll trough those pages but the loading times went trough the roof. Some users were even getting 503 Unavailable errors.

It was time for more research, to find a solution.

The first solution I found in this post was a JSFiddle on how to simulate paging with jQuery and a simple hide / show function. It looked really interesting and after some customization for our site, we were up and running.

While it was really elegant – ajax like paging, it did not solve our load times challenge. This solution would read the total number of replies on page load, divide them by the number of replies you wanted to show per page and hide all but the initial set of replies. Paging back and forth, simply shows the previous/next set and hides the previous/next set based on your click action.

Not a good solution for topics with over 600 replies. It was time for more research or some custom code.

After browsing some more support threads, it quickly became apparent that it is time for some custom code. Users have been posting questions about bbPress threaded (nested) replies with pagination for the past few years, with no real solution posted and/or some experiments in modifying the core. Just look here, here and here. We all know that modifying the core plugin files is a big “No, no” for number of reasons.

Time to custom code bbPress threaded (nested) replies with paging.

Please note that in order to complete the following few steps, you need to be comfortable with PHP, HTML, CSS, WordPress themes and bbPress templates file structure. This guide assumes that you have copied or have knowledge on how to copy the appropriate bbPress template files to your own theme or child theme. If you are unsure on how to do that, here is a detailed link that talks about bbPress template structure and how you can safely modify it’s file, without affecting the core plugin files:

https://codex.bbpress.org/themes/theme-compatibility/getting-started-in-modifying-the-main-bbpress-template/

Step 1: Copy the below function to your functions.php file. This is modified from the original bbp_list_replies(), found in /includes/replies/functions.php and is responsible for querying nested replies. The function is called in loop-replies.php, when you enable threaded (nested) replies under Settings -> Forums. The modification will allow us to pass the current page and number of replies per page, so the query returns the correct reply posts.

function wpup_bbp_list_replies( $args = array() ) {

	// Reset the reply depth
	bbpress()->reply_query->reply_depth = 0;

	// In reply loop
	bbpress()->reply_query->in_the_loop = true;

	$r = bbp_parse_args( $args, array(
		'walker'       => null,
		'max_depth'    => bbp_thread_replies_depth(),
		'style'        => 'ul',
		'callback'     => null,
		'end_callback' => null
	), 'list_replies' );

	// Get replies to loop through in $_replies
	$walker = new BBP_Walker_Reply;
	$walker->paged_walk( bbpress()->reply_query->posts, $r['max_depth'], $r['page'], $r['per_page'], $r );

	bbpress()->max_num_pages = $walker->max_pages;
	bbpress()->reply_query->in_the_loop = false;
}

Step 2: Next copy the below function to your functions.php file, right after the previous one from Step 1. This piece of code is responsible for displaying the page number navigation. The 2 important variables here are $numeplies – the total number of replies of the currently displayed topic and $paged – the current page number the visitor is displaying. You will find out how we are going to pass those values in the next few steps.

//Custom Pagination function
function wpup_custom_pagination($numreplies='', $pagerange='', $paged='', $repliesperpage='') {

  /**
   * $pagerange
   * How many pages to display after the current page
   * Used in combination with 'shaw_all' => false
   */
  if (empty($pagerange)) {
    $pagerange = 3;
  }
  
  /**
   * $numreplies
   * What is the total number of replies in the current topic
   * $numpages
   * Calculate total number of pages to display based on number of replies and replies per page
   */
  if ($numreplies != '') {
	$numpages = ceil($numreplies / $repliesperpage);
  }
  
  //assign value of 1 to $paged variable in case it's not passed on 
  global $paged;
  if (empty($paged)) {
    $paged = 1;
  }

  /** 
   * We construct the pagination arguments to enter into our paginate_links
   * function. 
   */
 $pagination_args = array(
    'base'            => get_pagenum_link(1) . '%_%',
    'format'          => 'page/%#%',
    'total'           => $numpages,
    'current'         => $paged,
    'show_all'        => False,
    'end_size'        => 1,
    'mid_size'        => $pagerange,
    'prev_next'       => True,
    'prev_text'       => __('<'),
    'next_text'       => __('>'),
    'type'            => 'plain',
    'add_args'        => false,
    'add_fragment'    => ''
  );

  $paginate_links = paginate_links($pagination_args);

  if ($paginate_links) {
    echo "<nav class='custom-pagination'>";
      echo $paginate_links;
    echo "</nav>";
  }

}

Step 3: If you haven’t done so already, copy loop-replies.php from /plugins/bbpress/templates/default/bbpress/ to /yourtheme/bbpress/ This step is necessary as we don’t want to modify the core plugin files and avoid loosing our changes on plugin update. The file is responsible for displaying a list of replies inside a topic.

Step 4: Edit loop-replies.php. On top of the file and right after the opening <?php tag, add this line of code:

$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;

Here we are checking/setting the $paged variable based on the page the user is on, so that we can use it further below.

Step 5: Replace the default bbp_list_replies() with our own custom function that we created in Step 1. Scroll down and look at around line 45 for

<?php bbp_list_replies(); ?>

and replace it with

<?php 
//Change 15 to number of replies you want users to see per page 
wpup_bbp_list_replies(array('page' => $paged, 'per_page' => 15)); 
?>

*Remember to change 15 with the number of replies you want to see per page. Also, please note that only the main replies are considered when specifying the number per page, since the nested replies are children of the main reply.

Here is a before and after:

Before:
default bbpress nested replies function

After:
modified bbpress nested replies function

Step 6: Next we want to call our pagination function, to display the page navigation. To do that, scroll down to around line 84 and include the following, right after the </ul> closing tag:

<div id="pagination-links"><?php  
//Change 15 to number of replies you specified in wpup_bbp_list_replies
//First find the number of parent posts only and pass that to the custom pagination function
$replyposts = bbpress()->reply_query->posts;
$numparentreplies = 0;
foreach($replyposts as $value){
if($value->reply_to == 0) {
    $numparentreplies++;
  }
}
wpup_custom_pagination($numparentreplies,"",$paged, 15); ?></div>

*Remember to change 15 with the number of replies you specified in Step 5. Thy need to match or the page links won’t work.

Here is a before and after:

Before:
bbpress custom pagination

After:
bbpress custom pagination

Step 7: Finally, lets add some css to style the pagination. You are welcome to style it anyway you want, but I also included some basic styles and what it should look like if you decide to use them.

/*Replies Pagination*/
#pagination-links {
    text-align: right;
}

#pagination-links .page-numbers {
    display: inline-block;
    margin: 0 2px;
}

#pagination-links a.page-numbers{
    display: inline-block;
    padding: 5px;
    background: #000;
    color: #FFF;
    text-align: center;
    text-decoration: none;
    width: 20px;
}

#pagination-links span.page-numbers.current{
    display: inline-block;
    padding: 5px;
    background: #F00;
    color: #FFF;
    text-align: center;
    text-decoration: none;
    width: 20px;
}

#pagination-links .prev, #pagination-links .next {
    width: 40px
}

#pagination-links a.page-numbers:hover {
    background: #555;
}

And here is what it looks like:
bbpress nested replies pagination

In Closing

While using these 2 separate functions and passing similar parameters, we were able to achieve bbPress threaded (nested) replies with paging. I’ve tested it and the outcome has been fairly fast for a live site with over 1000 members, and I hope that it will help you implement pagination for your community forum. Both functions are easy to understand, quick to implement and offer a certain level of customization.

I welcome all comments, questions and/or suggestions for improvement, so if you have any, please leave me a note below and I will do my best to answer or make modifications for future readers. Happy coding!