[ Index ]

PHP Cross Reference of BBPress

title

Body

[close]

/src/includes/forums/ -> functions.php (source)

   1  <?php
   2  
   3  /**
   4   * bbPress Forum Functions
   5   *
   6   * @package bbPress
   7   * @subpackage Functions
   8   */
   9  
  10  // Exit if accessed directly
  11  defined( 'ABSPATH' ) || exit;
  12  
  13  /** Insert ********************************************************************/
  14  
  15  /**
  16   * A wrapper for wp_insert_post() that also includes the necessary meta values
  17   * for the forum to function properly.
  18   *
  19   * @since 2.0.0 bbPress (r3349)
  20   *
  21   * @param array $forum_data Forum post data
  22   * @param arrap $forum_meta Forum meta data
  23   */
  24  function bbp_insert_forum( $forum_data = array(), $forum_meta = array() ) {
  25  
  26      // Forum
  27      $forum_data = bbp_parse_args( $forum_data, array(
  28          'post_parent'    => 0, // forum ID
  29          'post_status'    => bbp_get_public_status_id(),
  30          'post_type'      => bbp_get_forum_post_type(),
  31          'post_author'    => bbp_get_current_user_id(),
  32          'post_password'  => '',
  33          'post_content'   => '',
  34          'post_title'     => '',
  35          'menu_order'     => 0,
  36          'comment_status' => 'closed'
  37      ), 'insert_forum' );
  38  
  39      // Insert forum
  40      $forum_id = wp_insert_post( $forum_data, false );
  41  
  42      // Bail if no forum was added
  43      if ( empty( $forum_id ) ) {
  44          return false;
  45      }
  46  
  47      // Forum meta
  48      $forum_meta = bbp_parse_args( $forum_meta, array(
  49          'forum_type'           => 'forum',
  50          'status'               => 'open',
  51          'reply_count'          => 0,
  52          'topic_count'          => 0,
  53          'topic_count_hidden'   => 0,
  54          'total_reply_count'    => 0,
  55          'total_topic_count'    => 0,
  56          'last_topic_id'        => 0,
  57          'last_reply_id'        => 0,
  58          'last_active_id'       => 0,
  59          'last_active_time'     => 0,
  60          'forum_subforum_count' => 0,
  61      ), 'insert_forum_meta' );
  62  
  63      // Insert forum meta
  64      foreach ( $forum_meta as $meta_key => $meta_value ) {
  65  
  66          // Prefix if not prefixed
  67          if ( '_bbp_' !== substr( $meta_key, 0, 5 ) ) {
  68              $meta_key = '_bbp_' . $meta_key;
  69          }
  70  
  71          // Update the meta
  72          update_post_meta( $forum_id, $meta_key, $meta_value );
  73      }
  74  
  75      // Update the forum and hierarchy
  76      bbp_update_forum( array(
  77          'forum_id'    => $forum_id,
  78          'post_parent' => $forum_data['post_parent']
  79      ) );
  80  
  81      // Maybe make private
  82      if ( bbp_is_forum_private( $forum_id, false ) ) {
  83          bbp_privatize_forum( $forum_id );
  84  
  85      // Maybe make hidden
  86      } elseif ( bbp_is_forum_hidden( $forum_id, false ) ) {
  87          bbp_hide_forum( $forum_id );
  88  
  89      // Publicize
  90      } else {
  91          bbp_publicize_forum( $forum_id );
  92      }
  93  
  94      /**
  95       * Fires after forum has been inserted via `bbp_insert_forum`.
  96       *
  97       * @since 2.6.0 bbPress (r6036)
  98       *
  99       * @param int $forum_id The forum id.
 100       */
 101      do_action( 'bbp_insert_forum', (int) $forum_id );
 102  
 103      // Bump the last changed cache
 104      wp_cache_set( 'last_changed', microtime(), 'bbpress_posts' );
 105  
 106      // Return forum_id
 107      return $forum_id;
 108  }
 109  
 110  /** Post Form Handlers ********************************************************/
 111  
 112  /**
 113   * Handles the front end forum submission
 114   *
 115   * @param string $action The requested action to compare this function to
 116   */
 117  function bbp_new_forum_handler( $action = '' ) {
 118  
 119      // Bail if action is not bbp-new-forum
 120      if ( 'bbp-new-forum' !== $action ) {
 121          return;
 122      }
 123  
 124      // Nonce check
 125      if ( ! bbp_verify_nonce_request( 'bbp-new-forum' ) ) {
 126          bbp_add_error( 'bbp_new_forum_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
 127          return;
 128      }
 129  
 130      // Define local variable(s)
 131      $view_all = false;
 132      $forum_parent_id = $forum_author = 0;
 133      $forum_title = $forum_content = '';
 134      $anonymous_data = array();
 135  
 136      /** Forum Author **********************************************************/
 137  
 138      // User cannot create forums
 139      if ( ! current_user_can( 'publish_forums' ) ) {
 140          bbp_add_error( 'bbp_forum_permission', __( '<strong>ERROR</strong>: You do not have permission to create new forums.', 'bbpress' ) );
 141          return;
 142      }
 143  
 144      // Forum author is current user
 145      $forum_author = bbp_get_current_user_id();
 146  
 147      // Remove kses filters from title and content for capable users and if the nonce is verified
 148      if ( current_user_can( 'unfiltered_html' ) && ! empty( $_POST['_bbp_unfiltered_html_forum'] ) && wp_create_nonce( 'bbp-unfiltered-html-forum_new' ) === $_POST['_bbp_unfiltered_html_forum'] ) {
 149          remove_filter( 'bbp_new_forum_pre_title',   'wp_filter_kses'      );
 150          remove_filter( 'bbp_new_forum_pre_content', 'bbp_encode_bad',  10 );
 151          remove_filter( 'bbp_new_forum_pre_content', 'bbp_filter_kses', 30 );
 152      }
 153  
 154      /** Forum Title ***********************************************************/
 155  
 156      if ( ! empty( $_POST['bbp_forum_title'] ) ) {
 157          $forum_title = sanitize_text_field( $_POST['bbp_forum_title'] );
 158      }
 159  
 160      // Filter and sanitize
 161      $forum_title = apply_filters( 'bbp_new_forum_pre_title', $forum_title );
 162  
 163      // No forum title
 164      if ( empty( $forum_title ) ) {
 165          bbp_add_error( 'bbp_forum_title', __( '<strong>ERROR</strong>: Your forum needs a title.', 'bbpress' ) );
 166      }
 167  
 168      // Title too long
 169      if ( bbp_is_title_too_long( $forum_title ) ) {
 170          bbp_add_error( 'bbp_forum_title', __( '<strong>ERROR</strong>: Your title is too long.', 'bbpress' ) );
 171      }
 172  
 173      /** Forum Content *********************************************************/
 174  
 175      if ( ! empty( $_POST['bbp_forum_content'] ) ) {
 176          $forum_content = $_POST['bbp_forum_content'];
 177      }
 178  
 179      // Filter and sanitize
 180      $forum_content = apply_filters( 'bbp_new_forum_pre_content', $forum_content );
 181  
 182      // No forum content
 183      if ( empty( $forum_content ) ) {
 184          bbp_add_error( 'bbp_forum_content', __( '<strong>ERROR</strong>: Your forum description cannot be empty.', 'bbpress' ) );
 185      }
 186  
 187      /** Forum Parent **********************************************************/
 188  
 189      // Forum parent was passed (the norm)
 190      if ( ! empty( $_POST['bbp_forum_parent_id'] ) ) {
 191          $forum_parent_id = bbp_get_forum_id( $_POST['bbp_forum_parent_id'] );
 192      }
 193  
 194      // Filter and sanitize
 195      $forum_parent_id = apply_filters( 'bbp_new_forum_pre_parent_id', $forum_parent_id );
 196  
 197      // No forum parent was passed (should never happen)
 198      if ( empty( $forum_parent_id ) ) {
 199          bbp_add_error( 'bbp_new_forum_missing_parent', __( '<strong>ERROR</strong>: Your forum must have a parent.', 'bbpress' ) );
 200  
 201      // Forum exists
 202      } elseif ( ! empty( $forum_parent_id ) ) {
 203  
 204          // Forum is a category
 205          if ( bbp_is_forum_category( $forum_parent_id ) ) {
 206              bbp_add_error( 'bbp_new_forum_forum_category', __( '<strong>ERROR</strong>: This forum is a category. No forums can be created in this forum.', 'bbpress' ) );
 207          }
 208  
 209          // Forum is closed and user cannot access
 210          if ( bbp_is_forum_closed( $forum_parent_id ) && ! current_user_can( 'edit_forum', $forum_parent_id ) ) {
 211              bbp_add_error( 'bbp_new_forum_forum_closed', __( '<strong>ERROR</strong>: This forum has been closed to new forums.', 'bbpress' ) );
 212          }
 213  
 214          // Forum is private and user cannot access
 215          if ( bbp_is_forum_private( $forum_parent_id ) && ! current_user_can( 'read_forum', $forum_parent_id ) ) {
 216              bbp_add_error( 'bbp_new_forum_forum_private', __( '<strong>ERROR</strong>: This forum is private and you do not have the capability to read or create new forums in it.', 'bbpress' ) );
 217          }
 218  
 219          // Forum is hidden and user cannot access
 220          if ( bbp_is_forum_hidden( $forum_parent_id ) && ! current_user_can( 'read_forum', $forum_parent_id ) ) {
 221              bbp_add_error( 'bbp_new_forum_forum_hidden', __( '<strong>ERROR</strong>: This forum is hidden and you do not have the capability to read or create new forums in it.', 'bbpress' ) );
 222          }
 223      }
 224  
 225      /** Forum Flooding ********************************************************/
 226  
 227      if ( ! bbp_check_for_flood( $anonymous_data, $forum_author ) ) {
 228          bbp_add_error( 'bbp_forum_flood', __( '<strong>ERROR</strong>: Slow down; you move too fast.', 'bbpress' ) );
 229      }
 230  
 231      /** Forum Duplicate *******************************************************/
 232  
 233      if ( ! bbp_check_for_duplicate( array( 'post_type' => bbp_get_forum_post_type(), 'post_author' => $forum_author, 'post_content' => $forum_content, 'anonymous_data' => $anonymous_data ) ) ) {
 234          bbp_add_error( 'bbp_forum_duplicate', __( '<strong>ERROR</strong>: This forum already exists.', 'bbpress' ) );
 235      }
 236  
 237      /** Forum Bad Words *******************************************************/
 238  
 239      if ( ! bbp_check_for_moderation( $anonymous_data, $forum_author, $forum_title, $forum_content, true ) ) {
 240          bbp_add_error( 'bbp_forum_moderation', __( '<strong>ERROR</strong>: Your forum cannot be created at this time.', 'bbpress' ) );
 241      }
 242  
 243      /** Forum Moderation ******************************************************/
 244  
 245      $post_status = bbp_get_public_status_id();
 246      if ( ! bbp_check_for_moderation( $anonymous_data, $forum_author, $forum_title, $forum_content ) ) {
 247          $post_status = bbp_get_pending_status_id();
 248      }
 249  
 250      /** Additional Actions (Before Save) **************************************/
 251  
 252      do_action( 'bbp_new_forum_pre_extras', $forum_parent_id );
 253  
 254      // Bail if errors
 255      if ( bbp_has_errors() ) {
 256          return;
 257      }
 258  
 259      /** No Errors *************************************************************/
 260  
 261      // Add the content of the form to $forum_data as an array
 262      // Just in time manipulation of forum data before being created
 263      $forum_data = apply_filters( 'bbp_new_forum_pre_insert', array(
 264          'post_author'    => $forum_author,
 265          'post_title'     => $forum_title,
 266          'post_content'   => $forum_content,
 267          'post_parent'    => $forum_parent_id,
 268          'post_status'    => $post_status,
 269          'post_type'      => bbp_get_forum_post_type(),
 270          'comment_status' => 'closed'
 271      ) );
 272  
 273      // Insert forum
 274      $forum_id = wp_insert_post( $forum_data, true );
 275  
 276      /** No Errors *************************************************************/
 277  
 278      if ( ! empty( $forum_id ) && ! is_wp_error( $forum_id ) ) {
 279  
 280          /** Trash Check *******************************************************/
 281  
 282          // If the forum is trash, or the forum_status is switched to
 283          // trash, trash it properly
 284          if ( ( get_post_field( 'post_status', $forum_id ) === bbp_get_trash_status_id() ) || ( $forum_data['post_status'] === bbp_get_trash_status_id() ) ) {
 285  
 286              // Trash the reply
 287              wp_trash_post( $forum_id );
 288  
 289              // Force view=all
 290              $view_all = true;
 291          }
 292  
 293          /** Spam Check ********************************************************/
 294  
 295          // If reply or forum are spam, officially spam this reply
 296          if ( $forum_data['post_status'] === bbp_get_spam_status_id() ) {
 297              add_post_meta( $forum_id, '_bbp_spam_meta_status', bbp_get_public_status_id() );
 298  
 299              // Force view=all
 300              $view_all = true;
 301          }
 302  
 303          /** Update counts, etc... *********************************************/
 304  
 305          do_action( 'bbp_new_forum', array(
 306              'forum_id'           => $forum_id,
 307              'post_parent'        => $forum_parent_id,
 308              'forum_author'       => $forum_author,
 309              'last_topic_id'      => 0,
 310              'last_reply_id'      => 0,
 311              'last_active_id'     => 0,
 312              'last_active_time'   => 0,
 313              'last_active_status' => bbp_get_public_status_id()
 314          ) );
 315  
 316          /** Additional Actions (After Save) ***********************************/
 317  
 318          do_action( 'bbp_new_forum_post_extras', $forum_id );
 319  
 320          /** Redirect **********************************************************/
 321  
 322          // Redirect to
 323          $redirect_to  = bbp_get_redirect_to();
 324  
 325          // Get the forum URL
 326          $redirect_url = bbp_get_forum_permalink( $forum_id, $redirect_to );
 327  
 328          // Add view all?
 329          if ( bbp_get_view_all() || ! empty( $view_all ) ) {
 330  
 331              // User can moderate, so redirect to forum with view all set
 332              if ( current_user_can( 'moderate', $forum_id ) ) {
 333                  $redirect_url = bbp_add_view_all( $redirect_url );
 334  
 335              // User cannot moderate, so redirect to forum
 336              } else {
 337                  $redirect_url = bbp_get_forum_permalink( $forum_id );
 338              }
 339          }
 340  
 341          // Allow to be filtered
 342          $redirect_url = apply_filters( 'bbp_new_forum_redirect_to', $redirect_url, $redirect_to );
 343  
 344          /** Successful Save ***************************************************/
 345  
 346          // Redirect back to new forum
 347          bbp_redirect( $redirect_url );
 348  
 349      /** Errors ****************************************************************/
 350  
 351      // WP_Error
 352      } elseif ( is_wp_error( $forum_id ) ) {
 353          bbp_add_error( 'bbp_forum_error', sprintf( __( '<strong>ERROR</strong>: The following problem(s) occurred: %s', 'bbpress' ), $forum_id->get_error_message() ) );
 354  
 355      // Generic error
 356      } else {
 357          bbp_add_error( 'bbp_forum_error', __( '<strong>ERROR</strong>: The forum was not created.', 'bbpress' ) );
 358      }
 359  }
 360  
 361  /**
 362   * Handles the front end edit forum submission
 363   *
 364   * @param string $action The requested action to compare this function to
 365   */
 366  function bbp_edit_forum_handler( $action = '' ) {
 367  
 368      // Bail if action is not bbp-edit-forum
 369      if ( 'bbp-edit-forum' !== $action ) {
 370          return;
 371      }
 372  
 373      // Define local variable(s)
 374      $anonymous_data = array();
 375      $forum = $forum_id = $forum_parent_id = 0;
 376      $forum_title = $forum_content = $forum_edit_reason = '';
 377  
 378      /** Forum *****************************************************************/
 379  
 380      // Forum id was not passed
 381      if ( empty( $_POST['bbp_forum_id'] ) ) {
 382          bbp_add_error( 'bbp_edit_forum_id', __( '<strong>ERROR</strong>: Forum ID not found.', 'bbpress' ) );
 383          return;
 384  
 385      // Forum id was passed
 386      } elseif ( is_numeric( $_POST['bbp_forum_id'] ) ) {
 387          $forum_id = (int) $_POST['bbp_forum_id'];
 388          $forum    = bbp_get_forum( $forum_id );
 389      }
 390  
 391      // Nonce check
 392      if ( ! bbp_verify_nonce_request( 'bbp-edit-forum_' . $forum_id ) ) {
 393          bbp_add_error( 'bbp_edit_forum_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
 394          return;
 395  
 396      // Forum does not exist
 397      } elseif ( empty( $forum ) ) {
 398          bbp_add_error( 'bbp_edit_forum_not_found', __( '<strong>ERROR</strong>: The forum you want to edit was not found.', 'bbpress' ) );
 399          return;
 400  
 401      // User cannot edit this forum
 402      } elseif ( ! current_user_can( 'edit_forum', $forum_id ) ) {
 403          bbp_add_error( 'bbp_edit_forum_permission', __( '<strong>ERROR</strong>: You do not have permission to edit that forum.', 'bbpress' ) );
 404          return;
 405      }
 406  
 407      // Remove kses filters from title and content for capable users and if the nonce is verified
 408      if ( current_user_can( 'unfiltered_html' ) && ! empty( $_POST['_bbp_unfiltered_html_forum'] ) && ( wp_create_nonce( 'bbp-unfiltered-html-forum_' . $forum_id ) === $_POST['_bbp_unfiltered_html_forum'] ) ) {
 409          remove_filter( 'bbp_edit_forum_pre_title',   'wp_filter_kses'      );
 410          remove_filter( 'bbp_edit_forum_pre_content', 'bbp_encode_bad',  10 );
 411          remove_filter( 'bbp_edit_forum_pre_content', 'bbp_filter_kses', 30 );
 412      }
 413  
 414      /** Forum Parent ***********************************************************/
 415  
 416      // Forum parent id was passed
 417      if ( ! empty( $_POST['bbp_forum_parent_id'] ) ) {
 418          $forum_parent_id = bbp_get_forum_id( $_POST['bbp_forum_parent_id'] );
 419      }
 420  
 421      // Current forum this forum is in
 422      $current_parent_forum_id = bbp_get_forum_parent_id( $forum_id );
 423  
 424      // Forum exists
 425      if ( ! empty( $forum_parent_id ) && ( $forum_parent_id !== $current_parent_forum_id ) ) {
 426  
 427          // Forum is closed and user cannot access
 428          if ( bbp_is_forum_closed( $forum_parent_id ) && ! current_user_can( 'edit_forum', $forum_parent_id ) ) {
 429              bbp_add_error( 'bbp_edit_forum_forum_closed', __( '<strong>ERROR</strong>: This forum has been closed to new forums.', 'bbpress' ) );
 430          }
 431  
 432          // Forum is private and user cannot access
 433          if ( bbp_is_forum_private( $forum_parent_id ) && ! current_user_can( 'read_forum', $forum_parent_id ) ) {
 434              bbp_add_error( 'bbp_edit_forum_forum_private', __( '<strong>ERROR</strong>: This forum is private and you do not have the capability to read or create new forums in it.', 'bbpress' ) );
 435          }
 436  
 437          // Forum is hidden and user cannot access
 438          if ( bbp_is_forum_hidden( $forum_parent_id ) && ! current_user_can( 'read_forum', $forum_parent_id ) ) {
 439              bbp_add_error( 'bbp_edit_forum_forum_hidden', __( '<strong>ERROR</strong>: This forum is hidden and you do not have the capability to read or create new forums in it.', 'bbpress' ) );
 440          }
 441      }
 442  
 443      /** Forum Title ***********************************************************/
 444  
 445      if ( ! empty( $_POST['bbp_forum_title'] ) ) {
 446          $forum_title = sanitize_text_field( $_POST['bbp_forum_title'] );
 447      }
 448  
 449      // Filter and sanitize
 450      $forum_title = apply_filters( 'bbp_edit_forum_pre_title', $forum_title, $forum_id );
 451  
 452      // No forum title
 453      if ( empty( $forum_title ) ) {
 454          bbp_add_error( 'bbp_edit_forum_title', __( '<strong>ERROR</strong>: Your forum needs a title.', 'bbpress' ) );
 455      }
 456  
 457      // Title too long
 458      if ( bbp_is_title_too_long( $forum_title ) ) {
 459          bbp_add_error( 'bbp_forum_title', __( '<strong>ERROR</strong>: Your title is too long.', 'bbpress' ) );
 460      }
 461  
 462      /** Forum Content *********************************************************/
 463  
 464      if ( ! empty( $_POST['bbp_forum_content'] ) ) {
 465          $forum_content = $_POST['bbp_forum_content'];
 466      }
 467  
 468      // Filter and sanitize
 469      $forum_content = apply_filters( 'bbp_edit_forum_pre_content', $forum_content, $forum_id );
 470  
 471      // No forum content
 472      if ( empty( $forum_content ) ) {
 473          bbp_add_error( 'bbp_edit_forum_content', __( '<strong>ERROR</strong>: Your forum description cannot be empty.', 'bbpress' ) );
 474      }
 475  
 476      /** Forum Bad Words *******************************************************/
 477  
 478      if ( ! bbp_check_for_moderation( $anonymous_data, bbp_get_forum_author_id( $forum_id ), $forum_title, $forum_content, true ) ) {
 479          bbp_add_error( 'bbp_forum_moderation', __( '<strong>ERROR</strong>: Your forum cannot be edited at this time.', 'bbpress' ) );
 480      }
 481  
 482      /** Forum Moderation ******************************************************/
 483  
 484      $post_status = bbp_get_public_status_id();
 485      if ( ! bbp_check_for_moderation( $anonymous_data, bbp_get_forum_author_id( $forum_id ), $forum_title, $forum_content ) ) {
 486          $post_status = bbp_get_pending_status_id();
 487      }
 488  
 489      /** Additional Actions (Before Save) **************************************/
 490  
 491      do_action( 'bbp_edit_forum_pre_extras', $forum_id );
 492  
 493      // Bail if errors
 494      if ( bbp_has_errors() ) {
 495          return;
 496      }
 497  
 498      /** No Errors *************************************************************/
 499  
 500      // Add the content of the form to $forum_data as an array
 501      // Just in time manipulation of forum data before being edited
 502      $forum_data = apply_filters( 'bbp_edit_forum_pre_insert', array(
 503          'ID'           => $forum_id,
 504          'post_title'   => $forum_title,
 505          'post_content' => $forum_content,
 506          'post_status'  => $post_status,
 507          'post_parent'  => $forum_parent_id
 508      ) );
 509  
 510      // Insert forum
 511      $forum_id = wp_update_post( $forum_data );
 512  
 513      /** No Errors *************************************************************/
 514  
 515      if ( ! empty( $forum_id ) && ! is_wp_error( $forum_id ) ) {
 516  
 517          // Update counts, etc...
 518          do_action( 'bbp_edit_forum', array(
 519              'forum_id'           => $forum_id,
 520              'post_parent'        => $forum_parent_id,
 521              'forum_author'       => $forum->post_author,
 522              'last_topic_id'      => 0,
 523              'last_reply_id'      => 0,
 524              'last_active_id'     => 0,
 525              'last_active_time'   => 0,
 526              'last_active_status' => bbp_get_public_status_id()
 527          ) );
 528  
 529          /** Revisions *********************************************************/
 530  
 531          // Update locks
 532          update_post_meta( $forum_id, '_edit_last', bbp_get_current_user_id() );
 533          delete_post_meta( $forum_id, '_edit_lock' );
 534  
 535          /**
 536           * @todo omitted for now
 537          // Revision Reason
 538          if ( ! empty( $_POST['bbp_forum_edit_reason'] ) )
 539              $forum_edit_reason = sanitize_text_field( $_POST['bbp_forum_edit_reason'] );
 540  
 541          // Update revision log
 542          if ( ! empty( $_POST['bbp_log_forum_edit'] ) && ( "1" === $_POST['bbp_log_forum_edit'] ) && ( $revision_id = wp_save_post_revision( $forum_id ) ) ) {
 543              bbp_update_forum_revision_log( array(
 544                  'forum_id'    => $forum_id,
 545                  'revision_id' => $revision_id,
 546                  'author_id'   => bbp_get_current_user_id(),
 547                  'reason'      => $forum_edit_reason
 548              ) );
 549          }
 550  
 551          // If the new forum parent id is not equal to the old forum parent
 552          // id, run the bbp_move_forum action and pass the forum's parent id
 553          // as the first argument and new forum parent id as the second.
 554          // @todo implement
 555          if ( $forum_id !== $forum->post_parent ) {
 556              bbp_move_forum_handler( $forum_parent_id, $forum->post_parent, $forum_id );
 557          }
 558  
 559          */
 560  
 561          /** Additional Actions (After Save) ***********************************/
 562  
 563          do_action( 'bbp_edit_forum_post_extras', $forum_id );
 564  
 565          /** Redirect **********************************************************/
 566  
 567          // Redirect to
 568          $redirect_to = bbp_get_redirect_to();
 569  
 570          // View all?
 571          $view_all = bbp_get_view_all();
 572  
 573          // Get the forum URL
 574          $forum_url = bbp_get_forum_permalink( $forum_id, $redirect_to );
 575  
 576          // Add view all?
 577          if ( ! empty( $view_all ) ) {
 578              $forum_url = bbp_add_view_all( $forum_url );
 579          }
 580  
 581          // Allow to be filtered
 582          $forum_url = apply_filters( 'bbp_edit_forum_redirect_to', $forum_url, $view_all, $redirect_to );
 583  
 584          /** Successful Edit ***************************************************/
 585  
 586          // Redirect back to new forum
 587          bbp_redirect( $forum_url );
 588  
 589      /** Errors ****************************************************************/
 590  
 591      } else {
 592          $append_error = ( is_wp_error( $forum_id ) && $forum_id->get_error_message() ) ? $forum_id->get_error_message() . ' ' : '';
 593          bbp_add_error( 'bbp_forum_error', __( '<strong>ERROR</strong>: The following problem(s) have been found with your forum:' . $append_error . 'Please try again.', 'bbpress' ) );
 594      }
 595  }
 596  
 597  /**
 598   * Handle the saving of core forum metadata (Status, Visibility, and Type)
 599   *
 600   * @since 2.1.0 bbPress (r3678)
 601   *
 602   * @param int $forum_id
 603   * @return If forum ID is empty
 604   */
 605  function bbp_save_forum_extras( $forum_id = 0 ) {
 606  
 607      // Validate the forum ID
 608      $forum_id = bbp_get_forum_id( $forum_id );
 609  
 610      // Bail if forum ID is empty
 611      if ( empty( $forum_id ) || ! bbp_is_forum( $forum_id ) ) {
 612          return;
 613      }
 614  
 615      /** Forum Status **********************************************************/
 616  
 617      if ( ! empty( $_POST['bbp_forum_status'] ) && in_array( $_POST['bbp_forum_status'], array( 'open', 'closed' ), true ) ) {
 618          if ( 'closed' === $_POST['bbp_forum_status'] && ! bbp_is_forum_closed( $forum_id, false ) ) {
 619              bbp_close_forum( $forum_id );
 620          } elseif ( 'open' === $_POST['bbp_forum_status'] && bbp_is_forum_open( $forum_id, false ) ) {
 621              bbp_open_forum( $forum_id );
 622          } elseif ( 'open' === $_POST['bbp_forum_status'] && bbp_is_forum_closed( $forum_id, false ) ) {
 623              bbp_open_forum( $forum_id );
 624          }
 625      }
 626  
 627      /** Forum Type ************************************************************/
 628  
 629      if ( ! empty( $_POST['bbp_forum_type'] ) && in_array( $_POST['bbp_forum_type'], array( 'forum', 'category' ), true ) ) {
 630          if ( 'category' === $_POST['bbp_forum_type'] && ! bbp_is_forum_category( $forum_id ) ) {
 631              bbp_categorize_forum( $forum_id );
 632          } elseif ( 'forum' === $_POST['bbp_forum_type'] && ! bbp_is_forum_category( $forum_id ) ) {
 633              bbp_normalize_forum( $forum_id );
 634          } elseif ( 'forum' === $_POST['bbp_forum_type'] && bbp_is_forum_category( $forum_id ) ) {
 635              bbp_normalize_forum( $forum_id );
 636          }
 637      }
 638  
 639      /** Forum Visibility ******************************************************/
 640  
 641      if ( ! empty( $_POST['bbp_forum_visibility'] ) && in_array( $_POST['bbp_forum_visibility'], array_keys( bbp_get_forum_visibilities() ), true ) ) {
 642  
 643          // Get forums current visibility
 644          $old_visibility = bbp_get_forum_visibility( $forum_id );
 645  
 646          // Sanitize the new visibility
 647          $new_visibility = sanitize_key( $_POST['bbp_forum_visibility'] );
 648  
 649          // What is the new forum visibility setting?
 650          switch ( $new_visibility ) {
 651  
 652              // Hidden
 653              case bbp_get_hidden_status_id()  :
 654                  bbp_hide_forum( $forum_id, $old_visibility );
 655                  break;
 656  
 657              // Private
 658              case bbp_get_private_status_id() :
 659                  bbp_privatize_forum( $forum_id, $old_visibility );
 660                  break;
 661  
 662              // Publish (default)
 663              case bbp_get_public_status_id()  :
 664              default :
 665                  bbp_publicize_forum( $forum_id, $old_visibility );
 666                  break;
 667          }
 668  
 669          /**
 670           * Allow custom forum visibility save actions
 671           *
 672           * @since 2.6.0 bbPress (r5855)
 673           *
 674           * @param int    $forum_id       The forum ID
 675           * @param string $old_visibility The current forum visibility
 676           * @param string $new_visibility The new forum visibility
 677           */
 678          do_action( 'bbp_update_forum_visibility', $forum_id, $old_visibility, $new_visibility );
 679      }
 680  
 681      /** Forum Moderators ******************************************************/
 682  
 683      // Either replace terms
 684      if ( bbp_allow_forum_mods() ) {
 685          if ( current_user_can( 'assign_moderators' ) && ! empty( $_POST['bbp_moderators'] ) ) {
 686  
 687              // Escape tag input
 688              $users    = sanitize_text_field( $_POST['bbp_moderators'] );
 689              $user_ids = bbp_get_user_ids_from_nicenames( $users );
 690  
 691              // Update forum moderators
 692              if ( ! empty( $user_ids ) ) {
 693  
 694                  // Remove all moderators
 695                  bbp_remove_moderator( $forum_id, null );
 696  
 697                  // Add moderators
 698                  foreach ( $user_ids as $user_id ) {
 699                      bbp_add_moderator( $forum_id, $user_id );
 700                  }
 701              }
 702  
 703          // ...or remove them.
 704          } elseif ( isset( $_POST['bbp_moderators'] ) ) {
 705              bbp_remove_moderator( $forum_id, null );
 706          }
 707      }
 708  }
 709  
 710  /** Forum Open/Close **********************************************************/
 711  
 712  /**
 713   * Closes a forum
 714   *
 715   * @since 2.0.0 bbPress (r2746)
 716   *
 717   * @param int $forum_id forum id
 718   * @return mixed False or {@link WP_Error} on failure, forum id on success
 719   */
 720  function bbp_close_forum( $forum_id = 0 ) {
 721  
 722      $forum_id = bbp_get_forum_id( $forum_id );
 723  
 724      do_action( 'bbp_close_forum',  $forum_id );
 725  
 726      update_post_meta( $forum_id, '_bbp_status', 'closed' );
 727  
 728      do_action( 'bbp_closed_forum', $forum_id );
 729  
 730      return $forum_id;
 731  }
 732  
 733  /**
 734   * Opens a forum
 735   *
 736   * @since 2.0.0 bbPress (r2746)
 737   *
 738   * @param int $forum_id forum id
 739   * @return mixed False or {@link WP_Error} on failure, forum id on success
 740   */
 741  function bbp_open_forum( $forum_id = 0 ) {
 742  
 743      $forum_id = bbp_get_forum_id( $forum_id );
 744  
 745      do_action( 'bbp_open_forum',   $forum_id );
 746  
 747      update_post_meta( $forum_id, '_bbp_status', 'open' );
 748  
 749      do_action( 'bbp_opened_forum', $forum_id );
 750  
 751      return $forum_id;
 752  }
 753  
 754  /** Forum Type ****************************************************************/
 755  
 756  /**
 757   * Make the forum a category
 758   *
 759   * @since 2.0.0 bbPress (r2746)
 760   *
 761   * @param int $forum_id Optional. Forum id
 762   * @return bool False on failure, true on success
 763   */
 764  function bbp_categorize_forum( $forum_id = 0 ) {
 765  
 766      $forum_id = bbp_get_forum_id( $forum_id );
 767  
 768      do_action( 'bbp_categorize_forum',  $forum_id );
 769  
 770      update_post_meta( $forum_id, '_bbp_forum_type', 'category' );
 771  
 772      do_action( 'bbp_categorized_forum', $forum_id );
 773  
 774      return $forum_id;
 775  }
 776  
 777  /**
 778   * Remove the category status from a forum
 779   *
 780   * @since 2.0.0 bbPress (r2746)
 781   *
 782   * @param int $forum_id Optional. Forum id
 783   * @return bool False on failure, true on success
 784   */
 785  function bbp_normalize_forum( $forum_id = 0 ) {
 786  
 787      $forum_id = bbp_get_forum_id( $forum_id );
 788  
 789      do_action( 'bbp_normalize_forum',  $forum_id );
 790  
 791      update_post_meta( $forum_id, '_bbp_forum_type', 'forum' );
 792  
 793      do_action( 'bbp_normalized_forum', $forum_id );
 794  
 795      return $forum_id;
 796  }
 797  
 798  /** Forum Visibility **********************************************************/
 799  
 800  /**
 801   * Mark the forum as public
 802   *
 803   * @since 2.0.0 bbPress (r2746)
 804   *
 805   * @param int $forum_id Optional. Forum id
 806   * @return bool False on failure, true on success
 807   */
 808  function bbp_publicize_forum( $forum_id = 0, $current_visibility = '' ) {
 809  
 810      $forum_id = bbp_get_forum_id( $forum_id );
 811  
 812      do_action( 'bbp_publicize_forum',  $forum_id );
 813  
 814      // Get private forums
 815      $private = bbp_get_private_forum_ids();
 816  
 817      // Find this forum in the array
 818      if ( in_array( $forum_id, $private, true ) ) {
 819  
 820          $offset = array_search( $forum_id, $private, true );
 821  
 822          // Splice around it
 823          array_splice( $private, $offset, 1 );
 824  
 825          // Update private forums minus this one
 826          update_option( '_bbp_private_forums', bbp_get_unique_array_values( $private ) );
 827      }
 828  
 829      // Get hidden forums
 830      $hidden = bbp_get_hidden_forum_ids();
 831  
 832      // Find this forum in the array
 833      if ( in_array( $forum_id, $hidden, true ) ) {
 834  
 835          $offset = array_search( $forum_id, $hidden, true );
 836  
 837          // Splice around it
 838          array_splice( $hidden, $offset, 1 );
 839  
 840          // Update hidden forums minus this one
 841          update_option( '_bbp_hidden_forums', bbp_get_unique_array_values( $hidden ) );
 842      }
 843  
 844      // Only run queries if visibility is changing
 845      if ( bbp_get_public_status_id() !== $current_visibility ) {
 846          $bbp_db = bbp_db();
 847          $bbp_db->update( $bbp_db->posts, array( 'post_status' => bbp_get_public_status_id() ), array( 'ID' => $forum_id ) );
 848          wp_transition_post_status( bbp_get_public_status_id(), $current_visibility, get_post( $forum_id ) );
 849          clean_post_cache( $forum_id );
 850      }
 851  
 852      do_action( 'bbp_publicized_forum', $forum_id );
 853  
 854      return $forum_id;
 855  }
 856  
 857  /**
 858   * Mark the forum as private
 859   *
 860   * @since 2.0.0 bbPress (r2746)
 861   *
 862   * @param int $forum_id Optional. Forum id
 863   * @return bool False on failure, true on success
 864   */
 865  function bbp_privatize_forum( $forum_id = 0, $current_visibility = '' ) {
 866  
 867      $forum_id = bbp_get_forum_id( $forum_id );
 868  
 869      do_action( 'bbp_privatize_forum',  $forum_id );
 870  
 871      // Only run queries if visibility is changing
 872      if ( bbp_get_private_status_id() !== $current_visibility ) {
 873  
 874          // Get hidden forums
 875          $hidden = bbp_get_hidden_forum_ids();
 876  
 877          // Find this forum in the array
 878          if ( in_array( $forum_id, $hidden, true ) ) {
 879  
 880              $offset = array_search( $forum_id, $hidden, true );
 881  
 882              // Splice around it
 883              array_splice( $hidden, $offset, 1 );
 884  
 885              // Update hidden forums minus this one
 886              update_option( '_bbp_hidden_forums', bbp_get_unique_array_values( $hidden ) );
 887          }
 888  
 889          // Add to '_bbp_private_forums' site option
 890          $private   = bbp_get_private_forum_ids();
 891          $private[] = $forum_id;
 892          update_option( '_bbp_private_forums', bbp_get_unique_array_values( $private ) );
 893  
 894          // Update forums visibility setting
 895          $bbp_db = bbp_db();
 896          $bbp_db->update( $bbp_db->posts, array( 'post_status' => bbp_get_private_status_id() ), array( 'ID' => $forum_id ) );
 897          wp_transition_post_status( bbp_get_private_status_id(), $current_visibility, get_post( $forum_id ) );
 898          clean_post_cache( $forum_id );
 899      }
 900  
 901      do_action( 'bbp_privatized_forum', $forum_id );
 902  
 903      return $forum_id;
 904  }
 905  
 906  /**
 907   * Mark the forum as hidden
 908   *
 909   * @since 2.0.0 bbPress (r2996)
 910   *
 911   * @param int $forum_id Optional. Forum id
 912   * @return bool False on failure, true on success
 913   */
 914  function bbp_hide_forum( $forum_id = 0, $current_visibility = '' ) {
 915  
 916      $forum_id = bbp_get_forum_id( $forum_id );
 917  
 918      do_action( 'bbp_hide_forum', $forum_id );
 919  
 920      // Only run queries if visibility is changing
 921      if ( bbp_get_hidden_status_id() !== $current_visibility ) {
 922  
 923          // Get private forums
 924          $private = bbp_get_private_forum_ids();
 925  
 926          // Find this forum in the array
 927          if ( in_array( $forum_id, $private, true ) ) {
 928  
 929              $offset = array_search( $forum_id, $private, true );
 930  
 931              // Splice around it
 932              array_splice( $private, $offset, 1 );
 933  
 934              // Update private forums minus this one
 935              update_option( '_bbp_private_forums', bbp_get_unique_array_values( $private ) );
 936          }
 937  
 938          // Add to '_bbp_hidden_forums' site option
 939          $hidden   = bbp_get_hidden_forum_ids();
 940          $hidden[] = $forum_id;
 941          update_option( '_bbp_hidden_forums', bbp_get_unique_array_values( $hidden ) );
 942  
 943          // Update forums visibility setting
 944          $bbp_db = bbp_db();
 945          $bbp_db->update( $bbp_db->posts, array( 'post_status' => bbp_get_hidden_status_id() ), array( 'ID' => $forum_id ) );
 946          wp_transition_post_status( bbp_get_hidden_status_id(), $current_visibility, get_post( $forum_id ) );
 947          clean_post_cache( $forum_id );
 948      }
 949  
 950      do_action( 'bbp_hid_forum',  $forum_id );
 951  
 952      return $forum_id;
 953  }
 954  
 955  /**
 956   * Recaches the private and hidden forums
 957   *
 958   * @since 2.4.0 bbPress (r5017)
 959   *
 960   * @return array An array of the status code and the message
 961   */
 962  function bbp_repair_forum_visibility() {
 963  
 964      // First, delete everything.
 965      delete_option( '_bbp_private_forums' );
 966      delete_option( '_bbp_hidden_forums'  );
 967  
 968      /**
 969       * Don't search for both private/hidden statuses. Since 'pre_get_posts' is an
 970       * action, it's not removed by suppress_filters. We need to make sure that
 971       * we're only searching for the supplied post_status.
 972       *
 973       * @see https://bbpress.trac.wordpress.org/ticket/2512
 974       */
 975      remove_action( 'pre_get_posts', 'bbp_pre_get_posts_normalize_forum_visibility', 4 );
 976  
 977      // Query for private forums
 978      $private_forums = new WP_Query( array(
 979          'fields'         => 'ids',
 980          'post_type'      => bbp_get_forum_post_type(),
 981          'post_status'    => bbp_get_private_status_id(),
 982          'posts_per_page' => -1,
 983  
 984          // Performance
 985          'nopaging'               => true,
 986          'suppress_filters'       => true,
 987          'update_post_term_cache' => false,
 988          'update_post_meta_cache' => false,
 989          'ignore_sticky_posts'    => true,
 990          'no_found_rows'          => true
 991      ) );
 992  
 993      // Query for hidden forums
 994      $hidden_forums = new WP_Query( array(
 995          'fields'           => 'ids',
 996          'suppress_filters' => true,
 997          'post_type'        => bbp_get_forum_post_type(),
 998          'post_status'      => bbp_get_hidden_status_id(),
 999          'posts_per_page'   => -1,
1000  
1001          // Performance
1002          'nopaging'               => true,
1003          'suppress_filters'       => true,
1004          'update_post_term_cache' => false,
1005          'update_post_meta_cache' => false,
1006          'ignore_sticky_posts'    => true,
1007          'no_found_rows'          => true
1008      ) );
1009  
1010      // Enable forum visibilty normalization
1011      add_action( 'pre_get_posts', 'bbp_pre_get_posts_normalize_forum_visibility', 4 );
1012  
1013      // Reset the $post global
1014      wp_reset_postdata();
1015  
1016      // Private
1017      if ( ! is_wp_error( $private_forums ) ) {
1018          update_option( '_bbp_private_forums', $private_forums->posts );
1019      }
1020  
1021      // Hidden forums
1022      if ( ! is_wp_error( $hidden_forums ) ) {
1023          update_option( '_bbp_hidden_forums',  $hidden_forums->posts  );
1024      }
1025  
1026      // Complete results
1027      return true;
1028  }
1029  
1030  /** Subscriptions *************************************************************/
1031  
1032  /**
1033   * Remove a deleted forum from all user subscriptions
1034   *
1035   * @since 2.5.0 bbPress (r5156)
1036   *
1037   * @param int $forum_id Get the forum ID to remove
1038   */
1039  function bbp_remove_forum_from_all_subscriptions( $forum_id = 0 ) {
1040  
1041      // Subscriptions are not active
1042      if ( ! bbp_is_subscriptions_active() ) {
1043          return;
1044      }
1045  
1046      // Bail if no forum
1047      $forum_id = bbp_get_forum_id( $forum_id );
1048      if ( empty( $forum_id ) ) {
1049          return;
1050      }
1051  
1052      // Remove forum from all subscriptions
1053      return bbp_remove_object_from_all_users( $forum_id, '_bbp_subscription', 'post' );
1054  }
1055  
1056  /** Count Bumpers *************************************************************/
1057  
1058  /**
1059   * Bump the total topic count of a forum
1060   *
1061   * @since 2.1.0 bbPress (r3825)
1062   *
1063   * @param int $forum_id Optional. Forum id.
1064   * @param int $difference Optional. Default 1
1065   * @param bool $update_ancestors Optional. Default true
1066   *
1067   * @return int Forum topic count
1068   */
1069  function bbp_bump_forum_topic_count( $forum_id = 0, $difference = 1, $update_ancestors = true ) {
1070  
1071      // Bail if no bump
1072      if ( empty( $difference ) ) {
1073          return false;
1074      }
1075  
1076      // Get some counts
1077      $forum_id          = bbp_get_forum_id( $forum_id );
1078      $topic_count       = bbp_get_forum_topic_count( $forum_id, false, true );
1079      $total_topic_count = bbp_get_forum_topic_count( $forum_id, true,  true );
1080      $difference        = (int) $difference;
1081  
1082      // Update this forum id
1083      update_post_meta( $forum_id, '_bbp_topic_count',       (int) ( $topic_count       + $difference ) );
1084      update_post_meta( $forum_id, '_bbp_total_topic_count', (int) ( $total_topic_count + $difference ) );
1085  
1086      // Check for ancestors
1087      if ( true === $update_ancestors ) {
1088  
1089          // Get post ancestors
1090          $forum     = get_post( $forum_id );
1091          $ancestors = get_post_ancestors( $forum );
1092  
1093          // If has ancestors, loop through them...
1094          if ( ! empty( $ancestors ) ) {
1095              foreach ( (array) $ancestors as $parent_forum_id ) {
1096  
1097                  // Only update topic count when an ancestor is not a category.
1098                  if ( ! bbp_is_forum_category( $parent_forum_id ) ) {
1099  
1100                      $parent_topic_count = bbp_get_forum_topic_count( $parent_forum_id, false, true );
1101                      update_post_meta( $parent_forum_id, '_bbp_topic_count', (int) ( $parent_topic_count + $difference ) );
1102                  }
1103  
1104                  // Update the total topic count.
1105                  $parent_total_topic_count = bbp_get_forum_topic_count( $parent_forum_id, true,  true );
1106                  update_post_meta( $parent_forum_id, '_bbp_total_topic_count', (int) ( $parent_total_topic_count + $difference ) );
1107              }
1108          }
1109      }
1110  
1111      $forum_topic_count = (int) ( $total_topic_count + $difference );
1112  
1113      // Filter & return
1114      return (int) apply_filters( 'bbp_bump_forum_topic_count', $forum_topic_count, $forum_id, $difference, $update_ancestors );
1115  }
1116  
1117  /**
1118   * Increase the total topic count of a forum by one.
1119   *
1120   * @since 2.6.0 bbPress (r6036)
1121   *
1122   * @param int $forum_id The forum id.
1123   * @return void
1124   */
1125  function bbp_increase_forum_topic_count( $forum_id = 0 ) {
1126  
1127      // Bail early if no id is passed.
1128      if ( empty( $forum_id ) ) {
1129          return;
1130      }
1131  
1132      // If it's a topic, get the forum id.
1133      if ( bbp_is_topic( $forum_id ) ) {
1134          $topic_id = $forum_id;
1135          $forum_id = bbp_get_topic_forum_id( $topic_id );
1136  
1137          // Update inverse based on item status
1138          if ( ! bbp_is_topic_public( $topic_id ) ) {
1139              bbp_increase_forum_topic_count_hidden( $forum_id );
1140              return;
1141          }
1142      }
1143  
1144      // Bump up
1145      bbp_bump_forum_topic_count( $forum_id );
1146  }
1147  
1148  /**
1149   * Decrease the total topic count of a forum by one.
1150   *
1151   * @since 2.6.0 bbPress (r6036)
1152   *
1153   * @param int $forum_id The forum id.
1154   *
1155   * @return void
1156   */
1157  function bbp_decrease_forum_topic_count( $forum_id = 0 ) {
1158  
1159      // Bail early if no id is passed.
1160      if ( empty( $forum_id ) ) {
1161          return;
1162      }
1163  
1164      // If it's a topic, get the forum id.
1165      if ( bbp_is_topic( $forum_id ) ) {
1166          $topic_id = $forum_id;
1167          $forum_id = bbp_get_topic_forum_id( $topic_id );
1168  
1169          // Update inverse based on item status
1170          if ( ! bbp_is_topic_public( $topic_id ) ) {
1171              bbp_decrease_forum_topic_count_hidden( $forum_id );
1172              return;
1173          }
1174      }
1175  
1176      // Bump down
1177      bbp_bump_forum_topic_count( $forum_id, -1 );
1178  }
1179  
1180  /**
1181   * Bump the total topic count of a forum
1182   *
1183   * @since 2.1.0 bbPress (r3825)
1184   *
1185   * @param int $forum_id Optional. Forum id.
1186   * @param int $difference Optional. Default 1
1187   * @param bool $update_ancestors Optional. Default true
1188   *
1189   * @return int Forum topic count
1190   */
1191  function bbp_bump_forum_topic_count_hidden( $forum_id = 0, $difference = 1, $update_ancestors = true ) {
1192  
1193      // Bail if no bump
1194      if ( empty( $difference ) ) {
1195          return false;
1196      }
1197  
1198      // Get some counts
1199      $forum_id          = bbp_get_forum_id( $forum_id );
1200      $reply_count       = bbp_get_forum_topic_count_hidden( $forum_id, false, true );
1201      $total_topic_count = bbp_get_forum_topic_count_hidden( $forum_id, true,  true );
1202      $difference        = (int) $difference;
1203  
1204      // Update this forum id
1205      update_post_meta( $forum_id, '_bbp_topic_count_hidden',       (int) ( $reply_count       + $difference ) );
1206      update_post_meta( $forum_id, '_bbp_total_topic_count_hidden', (int) ( $total_topic_count + $difference ) );
1207  
1208      // Check for ancestors
1209      if ( true === $update_ancestors ) {
1210  
1211          // Get post ancestors
1212          $forum     = get_post( $forum_id );
1213          $ancestors = get_post_ancestors( $forum );
1214  
1215          // If has ancestors, loop through them...
1216          if ( ! empty( $ancestors ) ) {
1217              foreach ( (array) $ancestors as $parent_forum_id ) {
1218  
1219                  // Only update topic count when an ancestor is not a category.
1220                  if ( ! bbp_is_forum_category( $parent_forum_id ) ) {
1221  
1222                      $parent_topic_count = bbp_get_forum_topic_count_hidden( $parent_forum_id, false, true );
1223                      update_post_meta( $parent_forum_id, '_bbp_topic_count_hidden', (int) ( $parent_topic_count + $difference ) );
1224                  }
1225  
1226                  // Update the total topic count.
1227                  $parent_total_topic_count = bbp_get_forum_topic_count_hidden( $parent_forum_id, true, true );
1228                  update_post_meta( $parent_forum_id, '_bbp_total_topic_count_hidden', (int) ( $parent_total_topic_count + $difference ) );
1229              }
1230          }
1231      }
1232  
1233      $forum_topic_count = (int) ( $total_topic_count + $difference );
1234  
1235      // Filter & return
1236      return (int) apply_filters( 'bbp_bump_forum_topic_count_hidden', $forum_topic_count, $forum_id, $difference, $update_ancestors );
1237  }
1238  
1239  /**
1240   * Increase the total hidden topic count of a forum by one.
1241   *
1242   * @since 2.6.0 bbPress (r6036)
1243   *
1244   * @param int $forum_id The forum id.
1245   *
1246   * @return void
1247   */
1248  function bbp_increase_forum_topic_count_hidden( $forum_id = 0 ) {
1249  
1250      // Bail early if no id is passed.
1251      if ( empty( $forum_id ) ) {
1252          return;
1253      }
1254  
1255      // If it's a topic, get the forum id.
1256      if ( bbp_is_topic( $forum_id ) ) {
1257          $topic_id = $forum_id;
1258          $forum_id = bbp_get_topic_forum_id( $topic_id );
1259  
1260          // Update inverse based on item status
1261          if ( bbp_is_topic_public( $topic_id ) ) {
1262              bbp_increase_forum_topic_count( $forum_id );
1263              return;
1264          }
1265      }
1266  
1267      // Bump up
1268      bbp_bump_forum_topic_count_hidden( $forum_id );
1269  }
1270  
1271  /**
1272   * Decrease the total hidden topic count of a forum by one.
1273   *
1274   * @since 2.6.0 bbPress (r6036)
1275   *
1276   * @param int $forum_id The forum id.
1277   *
1278   * @return void
1279   */
1280  function bbp_decrease_forum_topic_count_hidden( $forum_id = 0 ) {
1281  
1282      // Bail early if no id is passed.
1283      if ( empty( $forum_id ) ) {
1284          return;
1285      }
1286  
1287      // If it's a topic, get the forum id.
1288      if ( bbp_is_topic( $forum_id ) ) {
1289          $topic_id = $forum_id;
1290          $forum_id = bbp_get_topic_forum_id( $topic_id );
1291  
1292          // Update inverse based on item status
1293          if ( bbp_is_topic_public( $topic_id ) ) {
1294              bbp_decrease_forum_topic_count( $forum_id );
1295              return;
1296          }
1297      }
1298  
1299      // Bump down
1300      bbp_bump_forum_topic_count_hidden( $forum_id, -1 );
1301  }
1302  
1303  /**
1304   * Bump the total topic count of a forum
1305   *
1306   * @since 2.1.0 bbPress (r3825)
1307   *
1308   * @param int $forum_id Optional. Forum id.
1309   * @param int $difference Optional. Default 1
1310   * @param bool $update_ancestors Optional. Default true
1311   *
1312   * @return int Forum topic count
1313   */
1314  function bbp_bump_forum_reply_count( $forum_id = 0, $difference = 1, $update_ancestors = true ) {
1315  
1316      // Bail if no bump
1317      if ( empty( $difference ) ) {
1318          return false;
1319      }
1320  
1321      // Get some counts
1322      $forum_id          = bbp_get_forum_id( $forum_id );
1323      $reply_count       = bbp_get_forum_reply_count( $forum_id, false, true );
1324      $total_reply_count = bbp_get_forum_reply_count( $forum_id, true,  true );
1325      $difference        = (int) $difference;
1326  
1327      // Update this forum id
1328      update_post_meta( $forum_id, '_bbp_reply_count',       (int) ( $reply_count       + $difference ) );
1329      update_post_meta( $forum_id, '_bbp_total_reply_count', (int) ( $total_reply_count + $difference ) );
1330  
1331      // Check for ancestors
1332      if ( true === $update_ancestors ) {
1333  
1334          // Get post ancestors
1335          $forum     = get_post( $forum_id );
1336          $ancestors = get_post_ancestors( $forum );
1337  
1338          // If has ancestors, loop through them...
1339          if ( ! empty( $ancestors ) ) {
1340              foreach ( (array) $ancestors as $parent_forum_id ) {
1341  
1342                  // Only update reply count when an ancestor is not a category.
1343                  if ( ! bbp_is_forum_category( $parent_forum_id ) ) {
1344  
1345                      $parent_reply_count = bbp_get_forum_reply_count( $parent_forum_id, false, true );
1346                      update_post_meta( $parent_forum_id, '_bbp_reply_count', (int) ( $parent_reply_count + $difference ) );
1347                  }
1348  
1349                  // Update the total reply count.
1350                  $parent_total_reply_count = bbp_get_forum_reply_count( $parent_forum_id, true,  true );
1351                  update_post_meta( $parent_forum_id, '_bbp_total_reply_count', (int) ( $parent_total_reply_count + $difference ) );
1352              }
1353          }
1354      }
1355  
1356      $forum_reply_count = (int) ( $total_reply_count + $difference );
1357  
1358      // Filter & return
1359      return (int) apply_filters( 'bbp_bump_forum_reply_count', $forum_reply_count, $forum_id, $difference, $update_ancestors );
1360  }
1361  
1362  /**
1363   * Bump the total topic count of a forum
1364   *
1365   * @since 2.6.0 bbPress (r6922)
1366   *
1367   * @param int $forum_id Optional. Forum id.
1368   * @param int $difference Optional. Default 1
1369   * @param bool $update_ancestors Optional. Default true
1370   *
1371   * @return int Forum topic count
1372   */
1373  function bbp_bump_forum_reply_count_hidden( $forum_id = 0, $difference = 1, $update_ancestors = true ) {
1374  
1375      // Bail if no bump
1376      if ( empty( $difference ) ) {
1377          return false;
1378      }
1379  
1380      // Get some counts
1381      $forum_id          = bbp_get_forum_id( $forum_id );
1382      $reply_count       = bbp_get_forum_reply_count_hidden( $forum_id, false, true );
1383      $total_reply_count = bbp_get_forum_reply_count_hidden( $forum_id, true,  true );
1384      $difference        = (int) $difference;
1385  
1386      // Update this forum id
1387      update_post_meta( $forum_id, '_bbp_reply_count_hidden',       (int) ( $reply_count       + $difference ) );
1388      update_post_meta( $forum_id, '_bbp_total_reply_count_hidden', (int) ( $total_reply_count + $difference ) );
1389  
1390      // Check for ancestors
1391      if ( true === $update_ancestors ) {
1392  
1393          // Get post ancestors
1394          $forum     = get_post( $forum_id );
1395          $ancestors = get_post_ancestors( $forum );
1396  
1397          // If has ancestors, loop through them...
1398          if ( ! empty( $ancestors ) ) {
1399              foreach ( (array) $ancestors as $parent_forum_id ) {
1400  
1401                  // Only update reply count when an ancestor is not a category.
1402                  if ( ! bbp_is_forum_category( $parent_forum_id ) ) {
1403  
1404                      $parent_reply_count = bbp_get_forum_reply_count_hidden( $parent_forum_id, false, true );
1405                      update_post_meta( $parent_forum_id, '_bbp_reply_count_hidden', (int) ( $parent_reply_count + $difference ) );
1406                  }
1407  
1408                  // Update the total reply count.
1409                  $parent_total_reply_count = bbp_get_forum_reply_count_hidden( $parent_forum_id, true,  true );
1410                  update_post_meta( $parent_forum_id, '_bbp_total_reply_count_hidden', (int) ( $parent_total_reply_count + $difference ) );
1411              }
1412          }
1413      }
1414  
1415      $forum_reply_count = (int) ( $total_reply_count + $difference );
1416  
1417      // Filter & return
1418      return (int) apply_filters( 'bbp_bump_forum_reply_count_hidden', $forum_reply_count, $forum_id, $difference, $update_ancestors );
1419  }
1420  
1421  /**
1422   * Increase the total reply count of a forum by one.
1423   *
1424   * @since 2.6.0 bbPress (r6036)
1425   *
1426   * @param int $forum_id The forum id.
1427   *
1428   * @return void
1429   */
1430  function bbp_increase_forum_reply_count( $forum_id = 0 ) {
1431  
1432      // Bail early if no id is passed.
1433      if ( empty( $forum_id ) ) {
1434          return;
1435      }
1436  
1437      // If it's a reply, get the forum id.
1438      if ( bbp_is_reply( $forum_id ) ) {
1439          $reply_id = $forum_id;
1440          $forum_id = bbp_get_reply_forum_id( $reply_id );
1441  
1442          // Update inverse based on item status
1443          if ( ! bbp_is_reply_public( $reply_id ) ) {
1444              bbp_increase_forum_reply_count_hidden( $forum_id );
1445              return;
1446          }
1447      }
1448  
1449      // Bump up
1450      bbp_bump_forum_reply_count( $forum_id );
1451  }
1452  
1453  /**
1454   * Decrease the total reply count of a forum by one.
1455   *
1456   * @since 2.6.0 bbPress (r6036)
1457   *
1458   * @param int $forum_id The forum id.
1459   *
1460   * @return void
1461   */
1462  function bbp_decrease_forum_reply_count( $forum_id = 0 ) {
1463  
1464      // Bail early if no id is passed.
1465      if ( empty( $forum_id ) ) {
1466          return;
1467      }
1468  
1469      // If it's a reply, get the forum id.
1470      if ( bbp_is_reply( $forum_id ) ) {
1471          $reply_id = $forum_id;
1472          $forum_id = bbp_get_reply_forum_id( $reply_id );
1473  
1474          // Update inverse based on item status
1475          if ( ! bbp_is_reply_public( $reply_id ) ) {
1476              bbp_decrease_forum_reply_count_hidden( $forum_id );
1477              return;
1478          }
1479      }
1480  
1481      // Bump down
1482      bbp_bump_forum_reply_count( $forum_id, -1 );
1483  }
1484  
1485  /**
1486   * Increase the total hidden reply count of a forum by one.
1487   *
1488   * @since 2.6.0 bbPress (r6036)
1489   *
1490   * @param int $forum_id The forum id.
1491   *
1492   * @return void
1493   */
1494  function bbp_increase_forum_reply_count_hidden( $forum_id = 0 ) {
1495  
1496      // Bail early if no id is passed.
1497      if ( empty( $forum_id ) ) {
1498          return;
1499      }
1500  
1501      // If it's a reply, get the forum id.
1502      if ( bbp_is_reply( $forum_id ) ) {
1503          $reply_id = $forum_id;
1504          $forum_id = bbp_get_reply_forum_id( $reply_id );
1505  
1506          // Update inverse based on item status
1507          if ( bbp_is_reply_public( $reply_id ) ) {
1508              bbp_increase_forum_reply_count( $forum_id );
1509              return;
1510          }
1511      }
1512  
1513      // Bump up
1514      bbp_bump_forum_reply_count_hidden( $forum_id );
1515  }
1516  
1517  /**
1518   * Decrease the total hidden reply count of a forum by one.
1519   *
1520   * @since 2.6.0 bbPress (r6036)
1521   *
1522   * @param int $forum_id The forum id.
1523   *
1524   * @return void
1525   */
1526  function bbp_decrease_forum_reply_count_hidden( $forum_id = 0 ) {
1527  
1528      // Bail early if no id is passed.
1529      if ( empty( $forum_id ) ) {
1530          return;
1531      }
1532  
1533      // If it's a reply, get the forum id.
1534      if ( bbp_is_reply( $forum_id ) ) {
1535          $reply_id = $forum_id;
1536          $forum_id = bbp_get_reply_forum_id( $reply_id );
1537  
1538          // Update inverse based on item status
1539          if ( bbp_is_reply_public( $reply_id ) ) {
1540              bbp_decrease_forum_reply_count( $forum_id );
1541              return;
1542          }
1543      }
1544  
1545      // Bump down
1546      bbp_bump_forum_reply_count_hidden( $forum_id, -1 );
1547  }
1548  
1549  /**
1550   * Update forum reply counts when a topic is approved or unapproved.
1551   *
1552   * @since 2.6.0 bbPress (r6036)
1553   *
1554   * @param int $topic_id The topic id.
1555   *
1556   * @return void
1557   */
1558  function bbp_approved_unapproved_topic_update_forum_reply_count( $topic_id = 0 ) {
1559  
1560      // Bail early if we don't have a topic id.
1561      if ( empty( $topic_id ) ) {
1562          return;
1563      }
1564  
1565      // Get the topic's replies.
1566      $count = bbp_get_public_child_count( $topic_id, bbp_get_reply_post_type() );
1567  
1568      // If we're unapproving, set count to negative.
1569      if ( 'bbp_unapproved_topic' === current_filter() ) {
1570          $count = -$count;
1571      }
1572  
1573      // Bump up or down
1574      bbp_bump_forum_reply_count( bbp_get_topic_forum_id( $topic_id ), $count );
1575  }
1576  
1577  /** Forum Updaters ************************************************************/
1578  
1579  /**
1580   * Update the forum last topic id
1581   *
1582   * @since 2.0.0 bbPress (r2625)
1583   *
1584   * @param int $forum_id Optional. Forum id.
1585   * @param int $topic_id Optional. Topic id.
1586   * @return int Id of the forums most recent topic
1587   */
1588  function bbp_update_forum_last_topic_id( $forum_id = 0, $topic_id = 0 ) {
1589      $forum_id = bbp_get_forum_id( $forum_id );
1590  
1591      // Define local variable(s)
1592      $children_last_topic = 0;
1593  
1594      // Do some calculation if not manually set
1595      if ( empty( $topic_id ) ) {
1596  
1597          // Loop through children and add together forum reply counts
1598          $children = bbp_forum_query_subforum_ids( $forum_id );
1599          if ( ! empty( $children ) ) {
1600              foreach ( $children as $child ) {
1601                  $children_last_topic = bbp_update_forum_last_topic_id( $child ); // Recursive
1602              }
1603          }
1604  
1605          // Setup recent topic query vars
1606          $post_vars = array(
1607              'post_parent' => $forum_id,
1608              'post_type'   => bbp_get_topic_post_type(),
1609              'meta_key'    => '_bbp_last_active_time',
1610              'meta_type'   => 'DATETIME',
1611              'orderby'     => 'meta_value',
1612              'numberposts' => 1
1613          );
1614  
1615          // Get the most recent topic in this forum_id
1616          $recent_topic = get_posts( $post_vars );
1617          if ( ! empty( $recent_topic ) ) {
1618              $topic_id = $recent_topic[0]->ID;
1619          }
1620      }
1621  
1622      // Cast as integer in case of empty or string
1623      $topic_id            = (int) $topic_id;
1624      $children_last_topic = (int) $children_last_topic;
1625  
1626      // If child forums have higher id, use that instead
1627      if ( ! empty( $children ) && ( $children_last_topic > $topic_id ) ) {
1628          $topic_id = $children_last_topic;
1629      }
1630  
1631      // Update the last public topic ID
1632      update_post_meta( $forum_id, '_bbp_last_topic_id', $topic_id );
1633  
1634      // Filter & return
1635      return (int) apply_filters( 'bbp_update_forum_last_topic_id', $topic_id, $forum_id );
1636  }
1637  
1638  /**
1639   * Update the forum last reply id
1640   *
1641   * @since 2.0.0 bbPress (r2625)
1642   *
1643   * @param int $forum_id Optional. Forum id.
1644   * @param int $reply_id Optional. Reply id.
1645   * @return int Id of the forums most recent reply
1646   */
1647  function bbp_update_forum_last_reply_id( $forum_id = 0, $reply_id = 0 ) {
1648      $forum_id = bbp_get_forum_id( $forum_id );
1649  
1650      // Define local variable(s)
1651      $children_last_reply = 0;
1652  
1653      // Do some calculation if not manually set
1654      if ( empty( $reply_id ) ) {
1655  
1656          // Loop through children and get the most recent reply id
1657          $children = bbp_forum_query_subforum_ids( $forum_id );
1658          if ( ! empty( $children ) ) {
1659              foreach ( $children as $child ) {
1660                  $children_last_reply = bbp_update_forum_last_reply_id( $child ); // Recursive
1661              }
1662          }
1663  
1664          // If this forum has topics...
1665          $topic_ids = bbp_forum_query_topic_ids( $forum_id );
1666          if ( ! empty( $topic_ids ) ) {
1667  
1668              // ...get the most recent reply from those topics...
1669              $reply_id = bbp_forum_query_last_reply_id( $forum_id, $topic_ids );
1670  
1671              // ...and compare it to the most recent topic id...
1672              $reply_id = ( $reply_id > max( $topic_ids ) )
1673                  ? $reply_id
1674                  : max( $topic_ids );
1675          }
1676      }
1677  
1678      // Cast as integer in case of empty or string
1679      $reply_id            = (int) $reply_id;
1680      $children_last_reply = (int) $children_last_reply;
1681  
1682      // If child forums have higher ID, check for newer reply id
1683      if ( ! empty( $children ) && ( $children_last_reply > $reply_id ) ) {
1684          $reply_id = $children_last_reply;
1685      }
1686  
1687      // Update the last public reply ID
1688      update_post_meta( $forum_id, '_bbp_last_reply_id', $reply_id );
1689  
1690      // Filter & return
1691      return (int) apply_filters( 'bbp_update_forum_last_reply_id', $reply_id, $forum_id );
1692  }
1693  
1694  /**
1695   * Update the forum last active post id
1696   *
1697   * @since 2.0.0 bbPress (r2860)
1698   *
1699   * @param int $forum_id Optional. Forum id.
1700   * @param int $active_id Optional. Active post id.
1701   * @return int Id of the forums last active post
1702   */
1703  function bbp_update_forum_last_active_id( $forum_id = 0, $active_id = 0 ) {
1704  
1705      $forum_id = bbp_get_forum_id( $forum_id );
1706  
1707      // Define local variable(s)
1708      $children_last_active = 0;
1709  
1710      // Do some calculation if not manually set
1711      if ( empty( $active_id ) ) {
1712  
1713          // Loop through children and get the last active ID
1714          $children = bbp_forum_query_subforum_ids( $forum_id );
1715          if ( ! empty( $children ) ) {
1716              foreach ( $children as $child ) {
1717                  $children_last_active = bbp_update_forum_last_active_id( $child, $active_id );
1718              }
1719          }
1720  
1721          // Get topic IDs and only accept larger IDs
1722          $topic_ids = bbp_forum_query_topic_ids( $forum_id );
1723          if ( ! empty( $topic_ids ) ) {
1724  
1725              // Make sure ID is larger
1726              $active_id = bbp_forum_query_last_reply_id( $forum_id, $topic_ids );
1727              $active_id = $active_id > max( $topic_ids )
1728                  ? $active_id
1729                  : max( $topic_ids );
1730  
1731          // Forum has no topics
1732          } else {
1733              $active_id = 0;
1734          }
1735      }
1736  
1737      // Cast as integer in case of empty or string
1738      $active_id            = (int) $active_id;
1739      $children_last_active = (int) $children_last_active;
1740  
1741      // If child forums have higher ID, use that instead
1742      if ( ! empty( $children ) && ( $children_last_active > $active_id ) ) {
1743          $active_id = $children_last_active;
1744      }
1745  
1746      update_post_meta( $forum_id, '_bbp_last_active_id', $active_id );
1747  
1748      // Filter & return
1749      return (int) apply_filters( 'bbp_update_forum_last_active_id', $active_id, $forum_id );
1750  }
1751  
1752  /**
1753   * Update the forums last active date/time (aka freshness)
1754   *
1755   * @since 2.0.0 bbPress (r2680)
1756   *
1757   * @param int    $forum_id Optional. Topic id.
1758   * @param string $new_time Optional. New time in mysql format.
1759   *
1760   * @return string MySQL timestamp of last active topic or reply
1761   */
1762  function bbp_update_forum_last_active_time( $forum_id = 0, $new_time = '' ) {
1763      $forum_id = bbp_get_forum_id( $forum_id );
1764  
1765      // Check time and use current if empty
1766      if ( empty( $new_time ) ) {
1767          $new_time = get_post_field( 'post_date', bbp_get_forum_last_active_id( $forum_id ) );
1768      }
1769  
1770      // Update only if there is a time
1771      if ( ! empty( $new_time ) ) {
1772          update_post_meta( $forum_id, '_bbp_last_active_time', $new_time );
1773      }
1774  
1775      // Filter & return
1776      return apply_filters( 'bbp_update_forum_last_active', $new_time, $forum_id );
1777  }
1778  
1779  /**
1780   * Update the forum sub-forum count
1781   *
1782   * @since 2.0.0 bbPress (r2625)
1783   *
1784   * @param int $forum_id Optional. Forum id
1785   * @param int $subforums Optional. Number of subforums
1786   * @return bool True on success, false on failure
1787   */
1788  function bbp_update_forum_subforum_count( $forum_id = 0, $subforums = false ) {
1789      $forum_id = bbp_get_forum_id( $forum_id );
1790  
1791      // Maybe query for counts
1792      $subforums = ! is_int( $subforums )
1793          ? bbp_get_public_child_count( $forum_id, bbp_get_forum_post_type() )
1794          : (int) $subforums;
1795  
1796      update_post_meta( $forum_id, '_bbp_forum_subforum_count', $subforums );
1797  
1798      // Filter & return
1799      return (int) apply_filters( 'bbp_update_forum_subforum_count', $subforums, $forum_id );
1800  }
1801  
1802  /**
1803   * Adjust the total topic count of a forum
1804   *
1805   * @since 2.0.0 bbPress (r2464)
1806   *
1807   * @param int $forum_id Optional. Forum id or topic id. It is checked whether it
1808   *                       is a topic or a forum. If it's a topic, its parent,
1809   *                       i.e. the forum is automatically retrieved.
1810   * @param bool $total_count Optional. To return the total count or normal count?
1811   * @return int Forum topic count
1812   */
1813  function bbp_update_forum_topic_count( $forum_id = 0 ) {
1814      $forum_id = bbp_get_forum_id( $forum_id );
1815      $children_topic_count = 0;
1816  
1817      // Loop through subforums and add together forum topic counts
1818      $children = bbp_forum_query_subforum_ids( $forum_id );
1819      if ( ! empty( $children ) ) {
1820          foreach ( $children as $child ) {
1821              $children_topic_count += bbp_update_forum_topic_count( $child ); // Recursive
1822          }
1823      }
1824  
1825      // Get total topics for this forum
1826      $topics = bbp_get_public_child_count( $forum_id, bbp_get_topic_post_type() );
1827  
1828      // Calculate total topics in this forum
1829      $total_topics = (int) ( $topics + $children_topic_count );
1830  
1831      // Update the count
1832      update_post_meta( $forum_id, '_bbp_topic_count',       $topics       );
1833      update_post_meta( $forum_id, '_bbp_total_topic_count', $total_topics );
1834  
1835      // Filter & return
1836      return (int) apply_filters( 'bbp_update_forum_topic_count', $total_topics, $forum_id );
1837  }
1838  
1839  /**
1840   * Adjust the total hidden topic count of a forum (hidden includes trashed,
1841   * spammed and pending topics)
1842   *
1843   * @since 2.0.0 bbPress (r2888)
1844   * @since 2.6.0 bbPress (r5954) Replace direct queries with WP_Query() objects
1845   *
1846   * @param int $forum_id Optional. Topic id to update.
1847   * @param int $topic_count Optional. Set the topic count manually.
1848   *
1849   * @return int Topic hidden topic count
1850   */
1851  function bbp_update_forum_topic_count_hidden( $forum_id = 0, $topic_count = false ) {
1852  
1853      // If topic_id was passed as $forum_id, then get its forum
1854      if ( bbp_is_topic( $forum_id ) ) {
1855          $topic_id = bbp_get_topic_id( $forum_id );
1856          $forum_id = bbp_get_topic_forum_id( $topic_id );
1857  
1858      // $forum_id is not a topic_id, so validate and proceed
1859      } else {
1860          $forum_id = bbp_get_forum_id( $forum_id );
1861      }
1862  
1863      // Can't update what isn't there
1864      if ( ! empty( $forum_id ) ) {
1865  
1866          // Get topics of forum
1867          if ( ! is_int( $topic_count ) ) {
1868              $query = new WP_Query( array(
1869                  'fields'         => 'ids',
1870                  'post_parent'    => $forum_id,
1871                  'post_status'    => bbp_get_non_public_topic_statuses(),
1872                  'post_type'      => bbp_get_topic_post_type(),
1873                  'posts_per_page' => -1,
1874  
1875                  // Performance
1876                  'nopaging'               => true,
1877                  'suppress_filters'       => true,
1878                  'update_post_term_cache' => false,
1879                  'update_post_meta_cache' => false,
1880                  'ignore_sticky_posts'    => true,
1881                  'no_found_rows'          => true
1882              ) );
1883              $topic_count = $query->post_count;
1884              unset( $query );
1885          }
1886  
1887          $topic_count = (int) $topic_count;
1888  
1889          // Update the count
1890          update_post_meta( $forum_id, '_bbp_topic_count_hidden', $topic_count );
1891      }
1892  
1893      // Filter & return
1894      return (int) apply_filters( 'bbp_update_forum_topic_count_hidden', $topic_count, $forum_id );
1895  }
1896  
1897  /**
1898   * Adjust the total reply count of a forum
1899   *
1900   * @since 2.0.0 bbPress (r2464)
1901   * @since 2.6.0 bbPress (r5954) Replace direct queries with WP_Query() objects
1902   *
1903   * @param int  $forum_id Optional. Forum id or topic id. It is checked whether it
1904   *                       is a topic or a forum. If it's a topic, its parent,
1905   *                       i.e. the forum is automatically retrieved.
1906   *
1907   * @return int Forum reply count
1908   */
1909  function bbp_update_forum_reply_count( $forum_id = 0 ) {
1910  
1911      $forum_id = bbp_get_forum_id( $forum_id );
1912      $children_reply_count = 0;
1913  
1914      // Loop through children and add together forum reply counts
1915      $children = bbp_forum_query_subforum_ids( $forum_id );
1916      if ( ! empty( $children ) ) {
1917          foreach ( (array) $children as $child ) {
1918              $children_reply_count += bbp_update_forum_reply_count( $child );
1919          }
1920      }
1921  
1922      // Don't count replies if the forum is a category
1923      $reply_count = ! bbp_is_forum_category( $forum_id )
1924          ? bbp_get_public_child_count( $forum_id, bbp_get_reply_post_type() )
1925          : 0;
1926  
1927      // Calculate total replies in this forum
1928      $total_replies = (int) ( $reply_count + $children_reply_count );
1929  
1930      // Update the counts
1931      update_post_meta( $forum_id, '_bbp_reply_count',       $reply_count   );
1932      update_post_meta( $forum_id, '_bbp_total_reply_count', $total_replies );
1933  
1934      // Filter & return
1935      return (int) apply_filters( 'bbp_update_forum_reply_count', $total_replies, $forum_id );
1936  }
1937  
1938  /**
1939   * Adjust the total hidden reply count of a forum
1940   *
1941   * @since 2.6.0 bbPress (r6922)
1942   *
1943   * @param int  $forum_id Optional. Forum id or topic id. It is checked whether it
1944   *                       is a topic or a forum. If it's a topic, its parent,
1945   *                       i.e. the forum is automatically retrieved.
1946   *
1947   * @return int Forum reply count
1948   */
1949  function bbp_update_forum_reply_count_hidden( $forum_id = 0 ) {
1950  
1951      $forum_id = bbp_get_forum_id( $forum_id );
1952      $children_reply_count = 0;
1953  
1954      // Loop through children and add together forum reply counts
1955      $children = bbp_forum_query_subforum_ids( $forum_id );
1956      if ( ! empty( $children ) ) {
1957          foreach ( (array) $children as $child ) {
1958              $children_reply_count += bbp_update_forum_reply_count_hidden( $child );
1959          }
1960      }
1961  
1962      // Don't count replies if the forum is a category
1963      $reply_count = ! bbp_is_forum_category( $forum_id )
1964          ? bbp_get_non_public_child_count( $forum_id, bbp_get_reply_post_type() )
1965          : 0;
1966  
1967      // Calculate total replies in this forum
1968      $total_replies = (int) ( $reply_count + $children_reply_count );
1969  
1970      // Update the counts
1971      update_post_meta( $forum_id, '_bbp_reply_count_hidden',       $reply_count   );
1972      update_post_meta( $forum_id, '_bbp_total_reply_count_hidden', $total_replies );
1973  
1974      // Filter & return
1975      return (int) apply_filters( 'bbp_update_forum_reply_count_hidden', $total_replies, $forum_id );
1976  }
1977  
1978  /**
1979   * Updates the counts of a forum.
1980   *
1981   * This calls a few internal functions that all run manual queries against the
1982   * database to get their results. As such, this function can be costly to run
1983   * but is necessary to keep everything accurate.
1984   *
1985   * @since 2.0.0 bbPress (r2908)
1986   *
1987   * @param array $args Supports these arguments:
1988   *  - forum_id: Forum id
1989   *  - last_topic_id: Last topic id
1990   *  - last_reply_id: Last reply id
1991   *  - last_active_id: Last active post id
1992   *  - last_active_time: last active time
1993   */
1994  function bbp_update_forum( $args = array() ) {
1995  
1996      // Parse arguments against default values
1997      $r = bbp_parse_args( $args, array(
1998          'forum_id'           => 0,
1999          'post_parent'        => 0,
2000          'last_topic_id'      => 0,
2001          'last_reply_id'      => 0,
2002          'last_active_id'     => 0,
2003          'last_active_time'   => 0,
2004          'last_active_status' => bbp_get_public_status_id()
2005      ), 'update_forum' );
2006  
2007      // Update the forum parent
2008      bbp_update_forum_id( $r['forum_id'], $r['post_parent'] );
2009  
2010      // Last topic and reply ID's
2011      bbp_update_forum_last_topic_id( $r['forum_id'], $r['last_topic_id'] );
2012      bbp_update_forum_last_reply_id( $r['forum_id'], $r['last_reply_id'] );
2013  
2014      // Active dance
2015      $r['last_active_id'] = bbp_update_forum_last_active_id( $r['forum_id'], $r['last_active_id'] );
2016  
2017      // If no active time was passed, get it from the last_active_id
2018      if ( empty( $r['last_active_time'] ) ) {
2019          $r['last_active_time'] = get_post_field( 'post_date', $r['last_active_id'] );
2020      }
2021  
2022      if ( bbp_get_public_status_id() === $r['last_active_status'] ) {
2023          bbp_update_forum_last_active_time( $r['forum_id'], $r['last_active_time'] );
2024      }
2025  
2026      // Counts
2027      bbp_update_forum_subforum_count( $r['forum_id'] );
2028  
2029      // Only update topic count if we've deleted a topic
2030      if ( in_array( current_filter(), array( 'bbp_deleted_topic', 'save_post' ), true ) ) {
2031          bbp_update_forum_reply_count(        $r['forum_id'] );
2032          bbp_update_forum_topic_count(        $r['forum_id'] );
2033          bbp_update_forum_topic_count_hidden( $r['forum_id'] );
2034          bbp_update_forum_reply_count_hidden( $r['forum_id'] );
2035      }
2036  
2037      // Update the parent forum if one was passed
2038      if ( ! empty( $r['post_parent'] ) && is_numeric( $r['post_parent'] ) ) {
2039          bbp_update_forum( array(
2040              'forum_id'    => $r['post_parent'],
2041              'post_parent' => get_post_field( 'post_parent', $r['post_parent'] )
2042          ) );
2043      }
2044  
2045      // Bump the custom query cache
2046      wp_cache_set( 'last_changed', microtime(), 'bbpress_posts' );
2047  }
2048  
2049  /** Helpers *******************************************************************/
2050  
2051  /**
2052   * Return an associative array of available topic statuses
2053   *
2054   * Developers note: these statuses are actually stored as meta data, and
2055   * Visibilities are stored in post_status.
2056   *
2057   * @since 2.4.0 bbPress (r5059)
2058   *
2059   * @param int $forum_id   Optional. Forum id.
2060   *
2061   * @return array
2062   */
2063  function bbp_get_forum_statuses( $forum_id = 0 ) {
2064  
2065      // Filter & return
2066      return (array) apply_filters( 'bbp_get_forum_statuses', array(
2067          'open'   => _x( 'Open',    'Open the forum',  'bbpress' ),
2068          'closed' => _x( 'Closed',  'Close the forum', 'bbpress' )
2069      ), $forum_id );
2070  }
2071  
2072  /**
2073   * Return an associative array of forum types
2074   *
2075   * @since 2.4.0 bbPress (r5059)
2076   *
2077   * @param int $forum_id   Optional. Forum id.
2078   *
2079   * @return array
2080   */
2081  function bbp_get_forum_types( $forum_id = 0 ) {
2082  
2083      // Filter & return
2084      return (array) apply_filters( 'bbp_get_forum_types', array(
2085          'forum'    => _x( 'Forum',    'Forum accepts new topics', 'bbpress' ),
2086          'category' => _x( 'Category', 'Forum is a category',      'bbpress' )
2087      ), $forum_id );
2088  }
2089  
2090  /**
2091   * Return an associative array of forum visibility
2092   *
2093   * Developers note: these visibilities are actually stored in post_status, and
2094   * Statuses are stored in meta data.
2095   *
2096   * @since 2.4.0 bbPress (r5059)
2097   *
2098   * @param int $forum_id   Optional. Forum id.
2099   *
2100   * @return array
2101   */
2102  function bbp_get_forum_visibilities( $forum_id = 0) {
2103  
2104      // Filter & return
2105      return (array) apply_filters( 'bbp_get_forum_visibilities', array(
2106          bbp_get_public_status_id()  => _x( 'Public',  'Make forum public',  'bbpress' ),
2107          bbp_get_private_status_id() => _x( 'Private', 'Make forum private', 'bbpress' ),
2108          bbp_get_hidden_status_id()  => _x( 'Hidden',  'Make forum hidden',  'bbpress' )
2109      ), $forum_id );
2110  }
2111  
2112  /**
2113   * Return array of public forum statuses.
2114   *
2115   * @since 2.6.0 bbPress (r6921)
2116   *
2117   * @return array
2118   */
2119  function bbp_get_public_forum_statuses() {
2120      $statuses = array(
2121          bbp_get_public_status_id()
2122      );
2123  
2124      // Filter & return
2125      return (array) apply_filters( 'bbp_get_public_forum_statuses', $statuses );
2126  }
2127  
2128  /**
2129   * Return array of non-public forum statuses.
2130   *
2131   * @since 2.6.0 bbPress (r6921)
2132   *
2133   * @return array
2134   */
2135  function bbp_get_non_public_forum_statuses() {
2136      $statuses = array(
2137          bbp_get_private_status_id(),
2138          bbp_get_hidden_status_id()
2139      );
2140  
2141      // Filter & return
2142      return (array) apply_filters( 'bbp_get_non_public_forum_statuses', $statuses );
2143  }
2144  
2145  /** Queries *******************************************************************/
2146  
2147  /**
2148   * Returns the hidden forum ids
2149   *
2150   * Only hidden forum ids are returned. Public and private ids are not.
2151   *
2152   * @since 2.0.0 bbPress (r3007)
2153   */
2154  function bbp_get_hidden_forum_ids() {
2155      $forum_ids = get_option( '_bbp_hidden_forums', array() );
2156      $forum_ids = ! empty( $forum_ids )
2157          ? wp_parse_id_list( $forum_ids )
2158          : array();
2159  
2160      // Filter & return
2161      return (array) apply_filters( 'bbp_get_hidden_forum_ids', $forum_ids );
2162  }
2163  
2164  /**
2165   * Returns the private forum ids
2166   *
2167   * Only private forum ids are returned. Public and hidden ids are not.
2168   *
2169   * @since 2.0.0 bbPress (r3007)
2170   */
2171  function bbp_get_private_forum_ids() {
2172      $forum_ids = get_option( '_bbp_private_forums', array() );
2173      $forum_ids = ! empty( $forum_ids )
2174          ? wp_parse_id_list( $forum_ids )
2175          : array();
2176  
2177      // Filter & return
2178      return (array) apply_filters( 'bbp_get_private_forum_ids', $forum_ids );
2179  }
2180  
2181  /**
2182   * Returns the forum IDs that should be excluded from various views & queries,
2183   * based on the current user's capabilities.
2184   *
2185   * @since 2.6.0 bbPress (r6425)
2186   *
2187   * @return array Forum IDs to exclude, or an empty array
2188   */
2189  function bbp_get_excluded_forum_ids() {
2190  
2191      // Private forums
2192      $private = ! current_user_can( 'read_private_forums' )
2193          ? bbp_get_private_forum_ids()
2194          : array();
2195  
2196      // Hidden forums
2197      $hidden = ! current_user_can( 'read_hidden_forums' )
2198          ? bbp_get_hidden_forum_ids()
2199          : array();
2200  
2201      // Merge private & hidden forums together, and remove any empties
2202      $forum_ids = ( ! empty( $private ) || ! empty( $hidden ) )
2203          ? array_filter( wp_parse_id_list( array_merge( $private, $hidden ) ) )
2204          : array();
2205  
2206      // Filter & return
2207      return (array) apply_filters( 'bbp_get_excluded_forum_ids', $forum_ids, $private, $hidden );
2208  }
2209  
2210  /**
2211   * Returns a meta_query that either includes or excludes hidden forum IDs
2212   * from a query.
2213   *
2214   * @since 2.0.0 bbPress (r3291)
2215   *
2216   * @param string Optional. The type of value to return. (string|array|meta_query)
2217   */
2218  function bbp_exclude_forum_ids( $type = 'string' ) {
2219  
2220      // Setup arrays
2221      $forum_ids = array();
2222  
2223      // Types
2224      $types = array(
2225          'array'      => array(),
2226          'string'     => '',
2227          'meta_query' => array()
2228      );
2229  
2230      // Exclude for everyone but keymasters
2231      if ( ! bbp_is_user_keymaster() ) {
2232  
2233          // Get forum IDs to exclude
2234          $forum_ids = bbp_get_excluded_forum_ids();
2235  
2236          // Store return values in static types array
2237          if ( ! empty( $forum_ids ) ) {
2238  
2239              // Comparison
2240              $compare = ( 1 < count( $forum_ids ) )
2241                  ? 'NOT IN'
2242                  : '!=';
2243  
2244              // Setup types
2245              $types['array']      = $forum_ids;
2246              $types['string']     = implode( ',', $forum_ids );
2247              $types['meta_query'] = array(
2248                  'key'     => '_bbp_forum_id',
2249                  'value'   => $types['string'],
2250                  'type'    => 'NUMERIC',
2251                  'compare' => $compare
2252              );
2253          }
2254      }
2255  
2256      // There are forums that need to be excluded
2257      $retval = $types[ $type ];
2258  
2259      // Filter & return
2260      return apply_filters( 'bbp_exclude_forum_ids', $retval, $forum_ids, $type );
2261  }
2262  
2263  /**
2264   * Adjusts forum, topic, and reply queries to exclude items that might be
2265   * contained inside hidden or private forums that the user does not have the
2266   * capability to view.
2267   *
2268   * Doing it with an action allows us to trap all WP_Query's rather than needing
2269   * to hardcode this logic into each query. It also protects forum content for
2270   * plugins that might be doing their own queries.
2271   *
2272   * @since 2.0.0 bbPress (r3291)
2273   *
2274   * @param WP_Query $posts_query
2275   *
2276   * @return WP_Query
2277   */
2278  function bbp_pre_get_posts_normalize_forum_visibility( $posts_query = null ) {
2279  
2280      // Bail if all forums are explicitly allowed
2281      if ( true === apply_filters( 'bbp_include_all_forums', false, $posts_query ) ) {
2282          return;
2283      }
2284  
2285      // Bail if $posts_query is not an object or of incorrect class
2286      if ( ! is_object( $posts_query ) || ! is_a( $posts_query, 'WP_Query' ) ) {
2287          return;
2288      }
2289  
2290      // Get query post types array .
2291      $post_types = (array) $posts_query->get( 'post_type' );
2292  
2293      // Forums
2294      if ( bbp_get_forum_post_type() === implode( '', $post_types ) ) {
2295  
2296          // Prevent accidental wp-admin post_row override
2297          if ( is_admin() && isset( $_REQUEST['post_status'] ) ) {
2298              return;
2299          }
2300  
2301          /** Default ***********************************************************/
2302  
2303          // Add all supported forum visibilities
2304          $posts_query->set( 'post_status', array_keys( bbp_get_forum_visibilities() ) );
2305  
2306          // Get forums to exclude
2307          $hidden_ids = bbp_exclude_forum_ids( 'array' );
2308  
2309          // Bail if no forums to exclude
2310          if ( empty( $hidden_ids ) ) {
2311              return;
2312          }
2313  
2314          // Get any existing meta queries
2315          $not_in = $posts_query->get( 'post__not_in', array() );
2316  
2317          // Add our meta query to existing
2318          $not_in = array_unique( array_merge( $not_in, $hidden_ids ) );
2319  
2320          // Set the meta_query var
2321          $posts_query->set( 'post__not_in', $not_in );
2322  
2323      // Some other post type besides Forums, Topics, or Replies
2324      } elseif ( ! array_diff( $post_types, bbp_get_post_types() ) ) {
2325  
2326          // Get forums to exclude
2327          $forum_ids = bbp_exclude_forum_ids( 'meta_query' );
2328  
2329          // Bail if no forums to exclude
2330          if ( empty( $forum_ids ) ) {
2331              return;
2332          }
2333  
2334          // Get any existing meta queries
2335          $meta_query   = (array) $posts_query->get( 'meta_query', array() );
2336  
2337          // Add our meta query to existing
2338          $meta_query[] = $forum_ids;
2339  
2340          // Set the meta_query var
2341          $posts_query->set( 'meta_query', $meta_query );
2342      }
2343  }
2344  
2345  /**
2346   * Returns the forum's topic ids
2347   *
2348   * Only topics with published and closed statuses are returned
2349   *
2350   * @since 2.0.0 bbPress (r2908)
2351   *
2352   * @param int $forum_id Forum id
2353   */
2354  function bbp_forum_query_topic_ids( $forum_id ) {
2355      $topic_ids = bbp_get_public_child_ids( $forum_id, bbp_get_topic_post_type() );
2356  
2357      // Filter & return
2358      return (array) apply_filters( 'bbp_forum_query_topic_ids', $topic_ids, $forum_id );
2359  }
2360  
2361  /**
2362   * Returns the forum's subforum ids
2363   *
2364   * Only forums with published status are returned
2365   *
2366   * @since 2.0.0 bbPress (r2908)
2367   *
2368   * @param int $forum_id Forum id
2369   */
2370  function bbp_forum_query_subforum_ids( $forum_id ) {
2371      $subforum_ids = bbp_get_all_child_ids( $forum_id, bbp_get_forum_post_type() );
2372  
2373      // Filter & return
2374      return (array) apply_filters( 'bbp_forum_query_subforum_ids', $subforum_ids, $forum_id );
2375  }
2376  
2377  /**
2378   * Returns the forum's last reply id
2379   *
2380   * @since 2.0.0 bbPress (r2908)
2381   * @since 2.6.0 bbPress (r5954) Replace direct queries with WP_Query() objects
2382   *
2383   * @param int $forum_id Forum id.
2384   * @param int $topic_ids Optional. Topic ids.
2385   */
2386  function bbp_forum_query_last_reply_id( $forum_id = 0, $topic_ids = 0 ) {
2387  
2388      // Validate forum
2389      $forum_id = bbp_get_forum_id( $forum_id );
2390  
2391      // Get topic ID's if none were passed
2392      if ( empty( $topic_ids ) ) {
2393          $topic_ids = bbp_forum_query_topic_ids( $forum_id );
2394      }
2395  
2396      $query = new WP_Query( array(
2397          'fields'           => 'ids',
2398          'suppress_filters' => true,
2399          'post_parent__in'  => $topic_ids,
2400          'post_status'      => bbp_get_public_status_id(),
2401          'post_type'        => bbp_get_reply_post_type(),
2402          'posts_per_page'   => 1,
2403          'orderby'          => array(
2404              'post_date' => 'DESC',
2405              'ID'        => 'DESC'
2406          ),
2407  
2408          // Performance
2409          'update_post_term_cache' => false,
2410          'update_post_meta_cache' => false,
2411          'ignore_sticky_posts'    => true,
2412          'no_found_rows'          => true
2413      ) );
2414  
2415      $reply_id = array_shift( $query->posts );
2416  
2417      unset( $query );
2418  
2419      // Filter & return
2420      return (int) apply_filters( 'bbp_forum_query_last_reply_id', $reply_id, $forum_id );
2421  }
2422  
2423  /** Listeners *****************************************************************/
2424  
2425  /**
2426   * Check if it's a hidden forum or a topic or reply of a hidden forum and if
2427   * the user can't view it, then sets a 404
2428   *
2429   * @since 2.0.0 bbPress (r2996)
2430   */
2431  function bbp_forum_enforce_hidden() {
2432  
2433      // Bail if not viewing a single item or if user has caps
2434      if ( ! is_singular() || bbp_is_user_keymaster() || current_user_can( 'read_hidden_forums' ) ) {
2435          return;
2436      }
2437  
2438      // Define local variables
2439      $forum_id = 0;
2440      $wp_query = bbp_get_wp_query();
2441  
2442      // Check post type
2443      switch ( $wp_query->get( 'post_type' ) ) {
2444  
2445          // Forum
2446          case bbp_get_forum_post_type() :
2447              $forum_id = bbp_get_forum_id( $wp_query->post->ID );
2448              break;
2449  
2450          // Topic
2451          case bbp_get_topic_post_type() :
2452              $forum_id = bbp_get_topic_forum_id( $wp_query->post->ID );
2453              break;
2454  
2455          // Reply
2456          case bbp_get_reply_post_type() :
2457              $forum_id = bbp_get_reply_forum_id( $wp_query->post->ID );
2458              break;
2459      }
2460  
2461      // If forum is explicitly hidden and user not capable, set 404
2462      if ( ! empty( $forum_id ) && bbp_is_forum_hidden( $forum_id ) && ! current_user_can( 'read_forum', $forum_id ) ) {
2463          bbp_set_404( $wp_query );
2464      }
2465  }
2466  
2467  /**
2468   * Check if it's a private forum or a topic or reply of a private forum and if
2469   * the user can't view it, then sets a 404
2470   *
2471   * @since 2.0.0 bbPress (r2996)
2472   */
2473  function bbp_forum_enforce_private() {
2474  
2475      // Bail if not viewing a single item or if user has caps
2476      if ( ! is_singular() || bbp_is_user_keymaster() || current_user_can( 'read_private_forums' ) ) {
2477          return;
2478      }
2479  
2480      // Define local variables
2481      $forum_id = 0;
2482      $wp_query = bbp_get_wp_query();
2483  
2484      // Check post type
2485      switch ( $wp_query->get( 'post_type' ) ) {
2486  
2487          // Forum
2488          case bbp_get_forum_post_type() :
2489              $forum_id = bbp_get_forum_id( $wp_query->post->ID );
2490              break;
2491  
2492          // Topic
2493          case bbp_get_topic_post_type() :
2494              $forum_id = bbp_get_topic_forum_id( $wp_query->post->ID );
2495              break;
2496  
2497          // Reply
2498          case bbp_get_reply_post_type() :
2499              $forum_id = bbp_get_reply_forum_id( $wp_query->post->ID );
2500              break;
2501  
2502      }
2503  
2504      // If forum is explicitly hidden and user not capable, set 404
2505      if ( ! empty( $forum_id ) && bbp_is_forum_private( $forum_id ) && ! current_user_can( 'read_forum', $forum_id ) ) {
2506          bbp_set_404( $wp_query );
2507      }
2508  }
2509  
2510  /** Permissions ***************************************************************/
2511  
2512  /**
2513   * Redirect if unauthorized user is attempting to edit a forum
2514   *
2515   * @since 2.1.0 bbPress (r3607)
2516   */
2517  function bbp_check_forum_edit() {
2518  
2519      // Bail if not editing a topic
2520      if ( ! bbp_is_forum_edit() ) {
2521          return;
2522      }
2523  
2524      // User cannot edit topic, so redirect back to reply
2525      if ( ! current_user_can( 'edit_forum', bbp_get_forum_id() ) ) {
2526          bbp_redirect( bbp_get_forum_permalink() );
2527      }
2528  }
2529  
2530  /**
2531   * Delete all topics (and their replies) for a specific forum ID
2532   *
2533   * @since 2.1.0 bbPress (r3668)
2534   *
2535   * @param int $forum_id
2536   * @return If forum is not valid
2537   */
2538  function bbp_delete_forum_topics( $forum_id = 0 ) {
2539  
2540      // Validate forum ID
2541      $forum_id = bbp_get_forum_id( $forum_id );
2542      if ( empty( $forum_id ) ) {
2543          return;
2544      }
2545  
2546      // Forum is being permanently deleted, so its content has go too
2547      // Note that we get all post statuses here
2548      $topics = new WP_Query( array(
2549          'fields'         => 'id=>parent',
2550          'post_type'      => bbp_get_topic_post_type(),
2551          'post_parent'    => $forum_id,
2552          'post_status'    => array_keys( get_post_stati() ),
2553          'posts_per_page' => -1,
2554  
2555          // Performance
2556          'nopaging'               => true,
2557          'suppress_filters'       => true,
2558          'update_post_term_cache' => false,
2559          'update_post_meta_cache' => false,
2560          'ignore_sticky_posts'    => true,
2561          'no_found_rows'          => true
2562      ) );
2563  
2564      // Loop through and delete child topics. Topic replies will get deleted by
2565      // the bbp_delete_topic() action.
2566      if ( ! empty( $topics->posts ) ) {
2567          foreach ( $topics->posts as $topic ) {
2568              wp_delete_post( $topic->ID, true );
2569          }
2570  
2571          // Reset the $post global
2572          wp_reset_postdata();
2573      }
2574  
2575      // Cleanup
2576      unset( $topics );
2577  }
2578  
2579  /**
2580   * Trash all topics inside a forum
2581   *
2582   * @since 2.1.0 bbPress (r3668)
2583   *
2584   * @param int $forum_id
2585   * @return If forum is not valid
2586   */
2587  function bbp_trash_forum_topics( $forum_id = 0 ) {
2588  
2589      // Validate forum ID
2590      $forum_id = bbp_get_forum_id( $forum_id );
2591      if ( empty( $forum_id ) ) {
2592          return;
2593      }
2594  
2595      // Allowed post statuses to pre-trash
2596      $post_stati = array(
2597          bbp_get_public_status_id(),
2598          bbp_get_closed_status_id(),
2599          bbp_get_pending_status_id()
2600      );
2601  
2602      // Forum is being trashed, so its topics (and replies) are trashed too
2603      $topics = new WP_Query( array(
2604          'fields'         => 'id=>parent',
2605          'post_type'      => bbp_get_topic_post_type(),
2606          'post_parent'    => $forum_id,
2607          'post_status'    => $post_stati,
2608          'posts_per_page' => -1,
2609  
2610          // Performance
2611          'nopaging'               => true,
2612          'suppress_filters'       => true,
2613          'update_post_term_cache' => false,
2614          'update_post_meta_cache' => false,
2615          'ignore_sticky_posts'    => true,
2616          'no_found_rows'          => true
2617      ) );
2618  
2619      // Loop through and trash child topics. Topic replies will get trashed by
2620      // the bbp_trash_topic() action.
2621      if ( ! empty( $topics->posts ) ) {
2622  
2623          // Prevent debug notices
2624          $pre_trashed_topics = array();
2625  
2626          // Loop through topics, trash them, and add them to array
2627          foreach ( $topics->posts as $topic ) {
2628              wp_trash_post( $topic->ID, true );
2629              $pre_trashed_topics[] = $topic->ID;
2630          }
2631  
2632          // Set a post_meta entry of the topics that were trashed by this action.
2633          // This is so we can possibly untrash them, without untrashing topics
2634          // that were purposefully trashed before.
2635          update_post_meta( $forum_id, '_bbp_pre_trashed_topics', $pre_trashed_topics );
2636  
2637          // Reset the $post global
2638          wp_reset_postdata();
2639      }
2640  
2641      // Cleanup
2642      unset( $topics );
2643  }
2644  
2645  /**
2646   * Untrash all topics inside a forum
2647   *
2648   * @since 2.1.0 bbPress (r3668)
2649   *
2650   * @param int $forum_id
2651   * @return If forum is not valid
2652   */
2653  function bbp_untrash_forum_topics( $forum_id = 0 ) {
2654  
2655      // Validate forum ID
2656      $forum_id = bbp_get_forum_id( $forum_id );
2657  
2658      if ( empty( $forum_id ) ) {
2659          return;
2660      }
2661  
2662      // Get the topics that were not previously trashed
2663      $pre_trashed_topics = get_post_meta( $forum_id, '_bbp_pre_trashed_topics', true );
2664  
2665      // There are topics to untrash
2666      if ( ! empty( $pre_trashed_topics ) ) {
2667  
2668          // Maybe reverse the trashed topics array
2669          if ( is_array( $pre_trashed_topics ) ) {
2670              $pre_trashed_topics = array_reverse( $pre_trashed_topics );
2671          }
2672  
2673          // Loop through topics
2674          foreach ( (array) $pre_trashed_topics as $topic ) {
2675              wp_untrash_post( $topic );
2676          }
2677      }
2678  }
2679  
2680  /** Before Delete/Trash/Untrash ***********************************************/
2681  
2682  /**
2683   * Called before deleting a forum.
2684   *
2685   * This function is supplemental to the actual forum deletion which is
2686   * handled by WordPress core API functions. It is used to clean up after
2687   * a forum that is being deleted.
2688   *
2689   * @since 2.1.0 bbPress (r3668)
2690   */
2691  function bbp_delete_forum( $forum_id = 0 ) {
2692      $forum_id = bbp_get_forum_id( $forum_id );
2693  
2694      if ( empty( $forum_id ) || ! bbp_is_forum( $forum_id ) ) {
2695          return false;
2696      }
2697  
2698      do_action( 'bbp_delete_forum', $forum_id );
2699  }
2700  
2701  /**
2702   * Called before trashing a forum
2703   *
2704   * This function is supplemental to the actual forum being trashed which is
2705   * handled by WordPress core API functions. It is used to clean up after
2706   * a forum that is being trashed.
2707   *
2708   * @since 2.1.0 bbPress (r3668)
2709   */
2710  function bbp_trash_forum( $forum_id = 0 ) {
2711      $forum_id = bbp_get_forum_id( $forum_id );
2712  
2713      if ( empty( $forum_id ) || ! bbp_is_forum( $forum_id ) ) {
2714          return false;
2715      }
2716  
2717      do_action( 'bbp_trash_forum', $forum_id );
2718  }
2719  
2720  /**
2721   * Called before untrashing a forum
2722   *
2723   * @since 2.1.0 bbPress (r3668)
2724   */
2725  function bbp_untrash_forum( $forum_id = 0 ) {
2726      $forum_id = bbp_get_forum_id( $forum_id );
2727  
2728      if ( empty( $forum_id ) || ! bbp_is_forum( $forum_id ) ) {
2729          return false;
2730      }
2731  
2732      do_action( 'bbp_untrash_forum', $forum_id );
2733  }
2734  
2735  /** After Delete/Trash/Untrash ************************************************/
2736  
2737  /**
2738   * Called after deleting a forum
2739   *
2740   * Try not to use this action. All meta & taxonomy terms have already been
2741   * deleted, making them impossible to use.
2742   *
2743   * @since 2.1.0 bbPress (r3668)
2744   * @since 2.6.0 bbPress (r6526) Not recommend for usage
2745   */
2746  function bbp_deleted_forum( $forum_id = 0 ) {
2747      $forum_id = bbp_get_forum_id( $forum_id );
2748  
2749      if ( empty( $forum_id ) || ! bbp_is_forum( $forum_id ) ) {
2750          return false;
2751      }
2752  
2753      do_action( 'bbp_deleted_forum', $forum_id );
2754  }
2755  
2756  /**
2757   * Called after trashing a forum
2758   *
2759   * @since 2.1.0 bbPress (r3668)
2760   */
2761  function bbp_trashed_forum( $forum_id = 0 ) {
2762      $forum_id = bbp_get_forum_id( $forum_id );
2763  
2764      if ( empty( $forum_id ) || ! bbp_is_forum( $forum_id ) ) {
2765          return false;
2766      }
2767  
2768      do_action( 'bbp_trashed_forum', $forum_id );
2769  }
2770  
2771  /**
2772   * Called after untrashing a forum
2773   *
2774   * @since 2.1.0 bbPress (r3668)
2775   */
2776  function bbp_untrashed_forum( $forum_id = 0 ) {
2777      $forum_id = bbp_get_forum_id( $forum_id );
2778  
2779      if ( empty( $forum_id ) || ! bbp_is_forum( $forum_id ) ) {
2780          return false;
2781      }
2782  
2783      do_action( 'bbp_untrashed_forum', $forum_id );
2784  }


Generated: Tue Nov 19 01:01:25 2019 Cross-referenced by PHPXref 0.7.1