[ Index ]

PHP Cross Reference of BBPress

title

Body

[close]

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

   1  <?php
   2  
   3  /**
   4   * bbPress Topic 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 topic to function properly.
  18   *
  19   * @since 2.0.0 bbPress (r3349)
  20   *
  21   * @param array $topic_data Forum post data
  22   * @param array $topic_meta Forum meta data
  23   */
  24  function bbp_insert_topic( $topic_data = array(), $topic_meta = array() ) {
  25  
  26      // Parse arguments against default values
  27      $topic_data = bbp_parse_args( $topic_data, array(
  28          'post_parent'    => 0, // forum ID
  29          'post_status'    => bbp_get_public_status_id(),
  30          'post_type'      => bbp_get_topic_post_type(),
  31          'post_author'    => bbp_get_current_user_id(),
  32          'post_password'  => '',
  33          'post_content'   => '',
  34          'post_title'     => '',
  35          'comment_status' => 'closed',
  36          'menu_order'     => 0
  37      ), 'insert_topic' );
  38  
  39      // Insert topic
  40      $topic_id = wp_insert_post( $topic_data, false );
  41  
  42      // Bail if no topic was added
  43      if ( empty( $topic_id ) ) {
  44          return false;
  45      }
  46  
  47      // Parse arguments against default values
  48      $topic_meta = bbp_parse_args( $topic_meta, array(
  49          'author_ip'          => bbp_current_author_ip(),
  50          'forum_id'           => 0,
  51          'topic_id'           => $topic_id,
  52          'voice_count'        => 1,
  53          'reply_count'        => 0,
  54          'reply_count_hidden' => 0,
  55          'last_reply_id'      => 0,
  56          'last_active_id'     => $topic_id,
  57          'last_active_time'   => get_post_field( 'post_date', $topic_id, 'db' )
  58      ), 'insert_topic_meta' );
  59  
  60      // Insert topic meta
  61      foreach ( $topic_meta as $meta_key => $meta_value ) {
  62  
  63          // Prefix if not prefixed
  64          if ( '_bbp_' !== substr( $meta_key, 0, 5 ) ) {
  65              $meta_key = '_bbp_' . $meta_key;
  66          }
  67  
  68          // Update the meta
  69          update_post_meta( $topic_id, $meta_key, $meta_value );
  70      }
  71  
  72      // Update the topic and hierarchy
  73      bbp_update_topic( $topic_id, $topic_meta['forum_id'], array(), $topic_data['post_author'], false );
  74  
  75      /**
  76       * Fires after topic has been inserted via `bbp_insert_topic`.
  77       *
  78       * @since 2.6.0 bbPress (r6036)
  79       *
  80       * @param int $topic_id               The topic id.
  81       * @param int $topic_meta['forum_id'] The topic forum meta.
  82       */
  83      do_action( 'bbp_insert_topic', (int) $topic_id, (int) $topic_meta['forum_id'] );
  84  
  85      // Return topic_id
  86      return $topic_id;
  87  }
  88  
  89  /** Post Form Handlers ********************************************************/
  90  
  91  /**
  92   * Handles the front end topic submission
  93   *
  94   * @param string $action The requested action to compare this function to
  95   */
  96  function bbp_new_topic_handler( $action = '' ) {
  97  
  98      // Bail if action is not bbp-new-topic
  99      if ( 'bbp-new-topic' !== $action ) {
 100          return;
 101      }
 102  
 103      // Nonce check
 104      if ( ! bbp_verify_nonce_request( 'bbp-new-topic' ) ) {
 105          bbp_add_error( 'bbp_new_topic_nonce', __( '<strong>Error</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
 106          return;
 107      }
 108  
 109      // Define local variable(s)
 110      $view_all = false;
 111      $forum_id = $topic_author = 0;
 112      $topic_title = $topic_content = '';
 113      $anonymous_data = array();
 114      $terms = array( bbp_get_topic_tag_tax_id() => array() );
 115  
 116      /** Topic Author **********************************************************/
 117  
 118      // User is anonymous
 119      if ( bbp_is_anonymous() ) {
 120  
 121          // Filter anonymous data (variable is used later)
 122          $anonymous_data = bbp_filter_anonymous_post_data();
 123  
 124          // Anonymous data checks out, so set cookies, etc...
 125          bbp_set_current_anonymous_user_data( $anonymous_data );
 126  
 127      // User is logged in
 128      } else {
 129  
 130          // User cannot create topics
 131          if ( ! current_user_can( 'publish_topics' ) ) {
 132              bbp_add_error( 'bbp_topic_permission', __( '<strong>Error</strong>: You do not have permission to create new topics.', 'bbpress' ) );
 133              return;
 134          }
 135  
 136          // Topic author is current user
 137          $topic_author = bbp_get_current_user_id();
 138      }
 139  
 140      // Remove kses filters from title and content for capable users and if the nonce is verified
 141      if ( current_user_can( 'unfiltered_html' ) && ! empty( $_POST['_bbp_unfiltered_html_topic'] ) && wp_create_nonce( 'bbp-unfiltered-html-topic_new' ) === $_POST['_bbp_unfiltered_html_topic'] ) {
 142          remove_filter( 'bbp_new_topic_pre_title',   'wp_filter_kses'      );
 143          remove_filter( 'bbp_new_topic_pre_content', 'bbp_encode_bad',  10 );
 144          remove_filter( 'bbp_new_topic_pre_content', 'bbp_filter_kses', 30 );
 145      }
 146  
 147      /** Topic Title ***********************************************************/
 148  
 149      if ( ! empty( $_POST['bbp_topic_title'] ) ) {
 150          $topic_title = sanitize_text_field( $_POST['bbp_topic_title'] );
 151      }
 152  
 153      // Filter and sanitize
 154      $topic_title = apply_filters( 'bbp_new_topic_pre_title', $topic_title );
 155  
 156      // No topic title
 157      if ( empty( $topic_title ) ) {
 158          bbp_add_error( 'bbp_topic_title', __( '<strong>Error</strong>: Your topic needs a title.', 'bbpress' ) );
 159      }
 160  
 161      // Title too long
 162      if ( bbp_is_title_too_long( $topic_title ) ) {
 163          bbp_add_error( 'bbp_topic_title', __( '<strong>Error</strong>: Your title is too long.', 'bbpress' ) );
 164      }
 165  
 166      /** Topic Content *********************************************************/
 167  
 168      if ( ! empty( $_POST['bbp_topic_content'] ) ) {
 169          $topic_content = $_POST['bbp_topic_content'];
 170      }
 171  
 172      // Filter and sanitize
 173      $topic_content = apply_filters( 'bbp_new_topic_pre_content', $topic_content );
 174  
 175      // No topic content
 176      if ( empty( $topic_content ) ) {
 177          bbp_add_error( 'bbp_topic_content', __( '<strong>Error</strong>: Your topic cannot be empty.', 'bbpress' ) );
 178      }
 179  
 180      /** Topic Forum ***********************************************************/
 181  
 182      // Error check the POST'ed topic id
 183      if ( isset( $_POST['bbp_forum_id'] ) ) {
 184  
 185          // Empty Forum id was passed
 186          if ( empty( $_POST['bbp_forum_id'] ) ) {
 187              bbp_add_error( 'bbp_topic_forum_id', __( '<strong>Error</strong>: Forum ID is missing.', 'bbpress' ) );
 188  
 189          // Forum id is not a number
 190          } elseif ( ! is_numeric( $_POST['bbp_forum_id'] ) ) {
 191              bbp_add_error( 'bbp_topic_forum_id', __( '<strong>Error</strong>: Forum ID must be a number.', 'bbpress' ) );
 192  
 193          // Forum id might be valid
 194          } else {
 195  
 196              // Get the forum id
 197              $posted_forum_id = intval( $_POST['bbp_forum_id'] );
 198  
 199              // Forum id is empty
 200              if ( 0 === $posted_forum_id ) {
 201                  bbp_add_error( 'bbp_topic_forum_id', __( '<strong>Error</strong>: Forum ID is missing.', 'bbpress' ) );
 202  
 203              // Forum id is a negative number
 204              } elseif ( 0 > $posted_forum_id ) {
 205                  bbp_add_error( 'bbp_topic_forum_id', __( '<strong>Error</strong>: Forum ID cannot be a negative number.', 'bbpress' ) );
 206  
 207              // Forum does not exist
 208              } elseif ( ! bbp_get_forum( $posted_forum_id ) ) {
 209                  bbp_add_error( 'bbp_topic_forum_id', __( '<strong>Error</strong>: Forum does not exist.', 'bbpress' ) );
 210  
 211              // Use the POST'ed forum id
 212              } else {
 213                  $forum_id = $posted_forum_id;
 214              }
 215          }
 216      }
 217  
 218      // Forum exists
 219      if ( ! empty( $forum_id ) ) {
 220  
 221          // Forum is a category
 222          if ( bbp_is_forum_category( $forum_id ) ) {
 223              bbp_add_error( 'bbp_new_topic_forum_category', __( '<strong>Error</strong>: This forum is a category. No topics can be created in this forum.', 'bbpress' ) );
 224  
 225          // Forum is not a category
 226          } else {
 227  
 228              // Forum is closed and user cannot access
 229              if ( bbp_is_forum_closed( $forum_id ) && ! current_user_can( 'edit_forum', $forum_id ) ) {
 230                  bbp_add_error( 'bbp_new_topic_forum_closed', __( '<strong>Error</strong>: This forum has been closed to new topics.', 'bbpress' ) );
 231              }
 232  
 233              // Forum is private and user cannot access
 234              if ( bbp_is_forum_private( $forum_id ) && ! current_user_can( 'read_forum', $forum_id ) ) {
 235                  bbp_add_error( 'bbp_new_topic_forum_private', __( '<strong>Error</strong>: This forum is private and you do not have the capability to read or create new topics in it.', 'bbpress' ) );
 236  
 237              // Forum is hidden and user cannot access
 238              } elseif ( bbp_is_forum_hidden( $forum_id ) && ! current_user_can( 'read_forum', $forum_id ) ) {
 239                  bbp_add_error( 'bbp_new_topic_forum_hidden', __( '<strong>Error</strong>: This forum is hidden and you do not have the capability to read or create new topics in it.', 'bbpress' ) );
 240              }
 241          }
 242      }
 243  
 244      /** Topic Flooding ********************************************************/
 245  
 246      if ( ! bbp_check_for_flood( $anonymous_data, $topic_author ) ) {
 247          bbp_add_error( 'bbp_topic_flood', __( '<strong>Error</strong>: Slow down; you move too fast.', 'bbpress' ) );
 248      }
 249  
 250      /** Topic Duplicate *******************************************************/
 251  
 252      $dupe_args = array(
 253          'post_type'      => bbp_get_topic_post_type(),
 254          'post_author'    => $topic_author,
 255          'post_content'   => $topic_content,
 256          'post_parent'    => $forum_id,
 257          'anonymous_data' => $anonymous_data
 258      );
 259  
 260      if ( ! bbp_check_for_duplicate( $dupe_args ) ) {
 261          bbp_add_error( 'bbp_topic_duplicate', __( '<strong>Error</strong>: Duplicate topic detected; it looks as though you&#8217;ve already said that.', 'bbpress' ) );
 262      }
 263  
 264      /** Topic Bad Words *******************************************************/
 265  
 266      if ( ! bbp_check_for_moderation( $anonymous_data, $topic_author, $topic_title, $topic_content, true ) ) {
 267          bbp_add_error( 'bbp_topic_moderation', __( '<strong>Error</strong>: Your topic cannot be created at this time.', 'bbpress' ) );
 268      }
 269  
 270      /** Topic Status **********************************************************/
 271  
 272      // Get available topic statuses
 273      $topic_statuses = bbp_get_topic_statuses();
 274  
 275      // Default to published
 276      $topic_status = bbp_get_public_status_id();
 277  
 278      // Maybe force into pending
 279      if ( ! bbp_check_for_moderation( $anonymous_data, $topic_author, $topic_title, $topic_content ) ) {
 280          $topic_status = bbp_get_pending_status_id();
 281  
 282      // Check for possible posted topic status
 283      } elseif ( ! empty( $_POST['bbp_topic_status'] ) && in_array( $_POST['bbp_topic_status'], array_keys( $topic_statuses ), true ) ) {
 284  
 285          // Allow capable users to explicitly override the status
 286          if ( current_user_can( 'moderate', $forum_id ) ) {
 287              $topic_status = sanitize_key( $_POST['bbp_topic_status'] );
 288  
 289          // Not capable
 290          } else {
 291              bbp_add_error( 'bbp_new_topic_status', __( '<strong>Error</strong>: You do not have permission to do that.', 'bbpress' ) );
 292          }
 293      }
 294  
 295      /** Topic Tags ************************************************************/
 296  
 297      if ( bbp_allow_topic_tags() && ! empty( $_POST['bbp_topic_tags'] ) ) {
 298  
 299          // Escape tag input
 300          $terms = sanitize_text_field( $_POST['bbp_topic_tags'] );
 301  
 302          // Explode by comma
 303          if ( strstr( $terms, ',' ) ) {
 304              $terms = explode( ',', $terms );
 305          }
 306  
 307          // Add topic tag ID as main key
 308          $terms = array( bbp_get_topic_tag_tax_id() => $terms );
 309      }
 310  
 311      /** Additional Actions (Before Save) **************************************/
 312  
 313      do_action( 'bbp_new_topic_pre_extras', $forum_id );
 314  
 315      // Bail if errors
 316      if ( bbp_has_errors() ) {
 317          return;
 318      }
 319  
 320      /** No Errors *************************************************************/
 321  
 322      // Add the content of the form to $topic_data as an array.
 323      // Just in time manipulation of topic data before being created
 324      $topic_data = apply_filters( 'bbp_new_topic_pre_insert', array(
 325          'post_author'    => $topic_author,
 326          'post_title'     => $topic_title,
 327          'post_content'   => $topic_content,
 328          'post_status'    => $topic_status,
 329          'post_parent'    => $forum_id,
 330          'post_type'      => bbp_get_topic_post_type(),
 331          'tax_input'      => $terms,
 332          'comment_status' => 'closed'
 333      ) );
 334  
 335      // Insert topic
 336      $topic_id = wp_insert_post( $topic_data, true );
 337  
 338      /** No Errors *************************************************************/
 339  
 340      if ( ! empty( $topic_id ) && ! is_wp_error( $topic_id ) ) {
 341  
 342          /** Close Check *******************************************************/
 343  
 344          // If the topic is closed, close it properly
 345          if ( ( get_post_field( 'post_status', $topic_id ) === bbp_get_closed_status_id() ) || ( $topic_data['post_status'] === bbp_get_closed_status_id() ) ) {
 346  
 347              // Close the topic
 348              bbp_close_topic( $topic_id );
 349          }
 350  
 351          /** Trash Check *******************************************************/
 352  
 353          // If the forum is trash, or the topic_status is switched to
 354          // trash, trash the topic properly
 355          if ( ( get_post_field( 'post_status', $forum_id ) === bbp_get_trash_status_id() ) || ( $topic_data['post_status'] === bbp_get_trash_status_id() ) ) {
 356  
 357              // Trash the topic
 358              wp_trash_post( $topic_id );
 359  
 360              // Force view=all
 361              $view_all = true;
 362          }
 363  
 364          /** Spam Check ********************************************************/
 365  
 366          // If the topic is spam, officially spam this topic
 367          if ( $topic_data['post_status'] === bbp_get_spam_status_id() ) {
 368              add_post_meta( $topic_id, '_bbp_spam_meta_status', bbp_get_public_status_id() );
 369  
 370              // Force view=all
 371              $view_all = true;
 372          }
 373  
 374          /** Update counts, etc... *********************************************/
 375  
 376          do_action( 'bbp_new_topic', $topic_id, $forum_id, $anonymous_data, $topic_author );
 377  
 378          /** Additional Actions (After Save) ***********************************/
 379  
 380          do_action( 'bbp_new_topic_post_extras', $topic_id );
 381  
 382          /** Redirect **********************************************************/
 383  
 384          // Redirect to
 385          $redirect_to = bbp_get_redirect_to();
 386  
 387          // Get the topic URL
 388          $redirect_url = bbp_get_topic_permalink( $topic_id, $redirect_to );
 389  
 390          // Add view all?
 391          if ( bbp_get_view_all() || ! empty( $view_all ) ) {
 392  
 393              // User can moderate, so redirect to topic with view all set
 394              if ( current_user_can( 'moderate', $topic_id ) ) {
 395                  $redirect_url = bbp_add_view_all( $redirect_url );
 396  
 397              // User cannot moderate, so redirect to forum
 398              } else {
 399                  $redirect_url = bbp_get_forum_permalink( $forum_id );
 400              }
 401          }
 402  
 403          // Allow to be filtered
 404          $redirect_url = apply_filters( 'bbp_new_topic_redirect_to', $redirect_url, $redirect_to, $topic_id );
 405  
 406          /** Successful Save ***************************************************/
 407  
 408          // Redirect back to new topic
 409          bbp_redirect( $redirect_url );
 410  
 411      /** Errors ****************************************************************/
 412  
 413      // WP_Error
 414      } elseif ( is_wp_error( $topic_id ) ) {
 415          bbp_add_error( 'bbp_topic_error', sprintf( __( '<strong>Error</strong>: The following problem(s) occurred: %s', 'bbpress' ), $topic_id->get_error_message() ) );
 416  
 417      // Generic error
 418      } else {
 419          bbp_add_error( 'bbp_topic_error', __( '<strong>Error</strong>: The topic was not created.', 'bbpress' ) );
 420      }
 421  }
 422  
 423  /**
 424   * Handles the front end edit topic submission
 425   *
 426   * @param string $action The requested action to compare this function to
 427   */
 428  function bbp_edit_topic_handler( $action = '' ) {
 429  
 430      // Bail if action is not bbp-edit-topic
 431      if ( 'bbp-edit-topic' !== $action ) {
 432          return;
 433      }
 434  
 435      // Define local variable(s)
 436      $revisions_removed = false;
 437      $topic = $topic_id = $topic_author = $forum_id = 0;
 438      $topic_title = $topic_content = $topic_edit_reason = '';
 439      $anonymous_data = array();
 440  
 441      /** Topic *****************************************************************/
 442  
 443      // Topic id was not passed
 444      if ( empty( $_POST['bbp_topic_id'] ) ) {
 445          bbp_add_error( 'bbp_edit_topic_id', __( '<strong>Error</strong>: Topic ID not found.', 'bbpress' ) );
 446          return;
 447  
 448      // Topic id was passed
 449      } elseif ( is_numeric( $_POST['bbp_topic_id'] ) ) {
 450          $topic_id = (int) $_POST['bbp_topic_id'];
 451          $topic    = bbp_get_topic( $topic_id );
 452      }
 453  
 454      // Topic does not exist
 455      if ( empty( $topic ) ) {
 456          bbp_add_error( 'bbp_edit_topic_not_found', __( '<strong>Error</strong>: The topic you want to edit was not found.', 'bbpress' ) );
 457          return;
 458  
 459      // Topic exists
 460      } else {
 461  
 462          // Check users ability to create new topic
 463          if ( ! bbp_is_topic_anonymous( $topic_id ) ) {
 464  
 465              // User cannot edit this topic
 466              if ( ! current_user_can( 'edit_topic', $topic_id ) ) {
 467                  bbp_add_error( 'bbp_edit_topic_permission', __( '<strong>Error</strong>: You do not have permission to edit that topic.', 'bbpress' ) );
 468              }
 469  
 470              // Set topic author
 471              $topic_author = bbp_get_topic_author_id( $topic_id );
 472  
 473          // It is an anonymous post
 474          } else {
 475  
 476              // Filter anonymous data
 477              $anonymous_data = bbp_filter_anonymous_post_data();
 478          }
 479      }
 480  
 481      // Nonce check
 482      if ( ! bbp_verify_nonce_request( 'bbp-edit-topic_' . $topic_id ) ) {
 483          bbp_add_error( 'bbp_edit_topic_nonce', __( '<strong>Error</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
 484          return;
 485      }
 486  
 487      // Remove kses filters from title and content for capable users and if the nonce is verified
 488      if ( current_user_can( 'unfiltered_html' ) && ! empty( $_POST['_bbp_unfiltered_html_topic'] ) && ( wp_create_nonce( 'bbp-unfiltered-html-topic_' . $topic_id ) === $_POST['_bbp_unfiltered_html_topic'] ) ) {
 489          remove_filter( 'bbp_edit_topic_pre_title',   'wp_filter_kses'      );
 490          remove_filter( 'bbp_edit_topic_pre_content', 'bbp_encode_bad',  10 );
 491          remove_filter( 'bbp_edit_topic_pre_content', 'bbp_filter_kses', 30 );
 492      }
 493  
 494      /** Topic Forum ***********************************************************/
 495  
 496      // Forum id was not passed
 497      if ( empty( $_POST['bbp_forum_id'] ) ) {
 498          bbp_add_error( 'bbp_topic_forum_id', __( '<strong>Error</strong>: Forum ID is missing.', 'bbpress' ) );
 499  
 500      // Forum id was passed
 501      } elseif ( is_numeric( $_POST['bbp_forum_id'] ) ) {
 502          $forum_id = (int) $_POST['bbp_forum_id'];
 503      }
 504  
 505      // Current forum this topic is in
 506      $current_forum_id = bbp_get_topic_forum_id( $topic_id );
 507  
 508      // Forum exists
 509      if ( ! empty( $forum_id ) && ( $forum_id !== $current_forum_id ) ) {
 510  
 511          // Forum is a category
 512          if ( bbp_is_forum_category( $forum_id ) ) {
 513              bbp_add_error( 'bbp_edit_topic_forum_category', __( '<strong>Error</strong>: This forum is a category. No topics can be created in it.', 'bbpress' ) );
 514  
 515          // Forum is not a category
 516          } else {
 517  
 518              // Forum is closed and user cannot access
 519              if ( bbp_is_forum_closed( $forum_id ) && ! current_user_can( 'edit_forum', $forum_id ) ) {
 520                  bbp_add_error( 'bbp_edit_topic_forum_closed', __( '<strong>Error</strong>: This forum has been closed to new topics.', 'bbpress' ) );
 521              }
 522  
 523              // Forum is private and user cannot access
 524              if ( bbp_is_forum_private( $forum_id ) && ! current_user_can( 'read_forum', $forum_id ) ) {
 525                  bbp_add_error( 'bbp_edit_topic_forum_private', __( '<strong>Error</strong>: This forum is private and you do not have the capability to read or create new topics in it.', 'bbpress' ) );
 526  
 527              // Forum is hidden and user cannot access
 528              } elseif ( bbp_is_forum_hidden( $forum_id ) && ! current_user_can( 'read_forum', $forum_id ) ) {
 529                  bbp_add_error( 'bbp_edit_topic_forum_hidden', __( '<strong>Error</strong>: This forum is hidden and you do not have the capability to read or create new topics in it.', 'bbpress' ) );
 530              }
 531          }
 532      }
 533  
 534      /** Topic Title ***********************************************************/
 535  
 536      if ( ! empty( $_POST['bbp_topic_title'] ) ) {
 537          $topic_title = sanitize_text_field( $_POST['bbp_topic_title'] );
 538      }
 539  
 540      // Filter and sanitize
 541      $topic_title = apply_filters( 'bbp_edit_topic_pre_title', $topic_title, $topic_id );
 542  
 543      // No topic title
 544      if ( empty( $topic_title ) ) {
 545          bbp_add_error( 'bbp_edit_topic_title', __( '<strong>Error</strong>: Your topic needs a title.', 'bbpress' ) );
 546      }
 547  
 548      // Title too long
 549      if ( bbp_is_title_too_long( $topic_title ) ) {
 550          bbp_add_error( 'bbp_topic_title', __( '<strong>Error</strong>: Your title is too long.', 'bbpress' ) );
 551      }
 552  
 553      /** Topic Content *********************************************************/
 554  
 555      if ( ! empty( $_POST['bbp_topic_content'] ) ) {
 556          $topic_content = $_POST['bbp_topic_content'];
 557      }
 558  
 559      // Filter and sanitize
 560      $topic_content = apply_filters( 'bbp_edit_topic_pre_content', $topic_content, $topic_id );
 561  
 562      // No topic content
 563      if ( empty( $topic_content ) ) {
 564          bbp_add_error( 'bbp_edit_topic_content', __( '<strong>Error</strong>: Your topic cannot be empty.', 'bbpress' ) );
 565      }
 566  
 567      /** Topic Bad Words *******************************************************/
 568  
 569      if ( ! bbp_check_for_moderation( $anonymous_data, $topic_author, $topic_title, $topic_content, true ) ) {
 570          bbp_add_error( 'bbp_topic_moderation', __( '<strong>Error</strong>: Your topic cannot be edited at this time.', 'bbpress' ) );
 571      }
 572  
 573      /** Topic Status **********************************************************/
 574  
 575      // Get available topic statuses
 576      $topic_statuses = bbp_get_topic_statuses( $topic_id );
 577  
 578      // Use existing post_status
 579      $topic_status = $topic->post_status;
 580  
 581      // Maybe force into pending
 582      if ( bbp_is_topic_public( $topic->ID ) && ! bbp_check_for_moderation( $anonymous_data, $topic_author, $topic_title, $topic_content ) ) {
 583          $topic_status = bbp_get_pending_status_id();
 584  
 585      // Check for possible posted topic status
 586      } elseif ( ! empty( $_POST['bbp_topic_status'] ) && in_array( $_POST['bbp_topic_status'], array_keys( $topic_statuses ), true ) ) {
 587  
 588          // Allow capable users to explicitly override the status
 589          if ( current_user_can( 'moderate', $forum_id ) ) {
 590              $topic_status = sanitize_key( $_POST['bbp_topic_status'] );
 591  
 592          // Not capable
 593          } else {
 594              bbp_add_error( 'bbp_edit_topic_status', __( '<strong>Error</strong>: You do not have permission to do that.', 'bbpress' ) );
 595          }
 596      }
 597  
 598      /** Topic Tags ************************************************************/
 599  
 600      // Either replace terms
 601      if ( bbp_allow_topic_tags() && current_user_can( 'assign_topic_tags', $topic_id ) && ! empty( $_POST['bbp_topic_tags'] ) ) {
 602  
 603          // Escape tag input
 604          $terms = sanitize_text_field( $_POST['bbp_topic_tags'] );
 605  
 606          // Explode by comma
 607          if ( strstr( $terms, ',' ) ) {
 608              $terms = explode( ',', $terms );
 609          }
 610  
 611          // Add topic tag ID as main key
 612          $terms = array( bbp_get_topic_tag_tax_id() => $terms );
 613  
 614      // ...or remove them.
 615      } elseif ( isset( $_POST['bbp_topic_tags'] ) ) {
 616          $terms = array( bbp_get_topic_tag_tax_id() => array() );
 617  
 618      // Existing terms
 619      } else {
 620          $terms = array( bbp_get_topic_tag_tax_id() => explode( ',', bbp_get_topic_tag_names( $topic_id, ',' ) ) );
 621      }
 622  
 623      /** Additional Actions (Before Save) **************************************/
 624  
 625      do_action( 'bbp_edit_topic_pre_extras', $topic_id );
 626  
 627      // Bail if errors
 628      if ( bbp_has_errors() ) {
 629          return;
 630      }
 631  
 632      /** No Errors *************************************************************/
 633  
 634      // Add the content of the form to $topic_data as an array
 635      // Just in time manipulation of topic data before being edited
 636      $topic_data = apply_filters( 'bbp_edit_topic_pre_insert', array(
 637          'ID'           => $topic_id,
 638          'post_title'   => $topic_title,
 639          'post_content' => $topic_content,
 640          'post_status'  => $topic_status,
 641          'post_parent'  => $forum_id,
 642          'post_author'  => $topic_author,
 643          'post_type'    => bbp_get_topic_post_type(),
 644          'tax_input'    => $terms,
 645      ) );
 646  
 647      // Toggle revisions to avoid duplicates
 648      if ( post_type_supports( bbp_get_topic_post_type(), 'revisions' ) ) {
 649          $revisions_removed = true;
 650          remove_post_type_support( bbp_get_topic_post_type(), 'revisions' );
 651      }
 652  
 653      // Insert topic
 654      $topic_id = wp_update_post( $topic_data );
 655  
 656      // Toggle revisions back on
 657      if ( true === $revisions_removed ) {
 658          $revisions_removed = false;
 659          add_post_type_support( bbp_get_topic_post_type(), 'revisions' );
 660      }
 661  
 662      /** No Errors *************************************************************/
 663  
 664      if ( ! empty( $topic_id ) && ! is_wp_error( $topic_id ) ) {
 665  
 666          // Update counts, etc...
 667          do_action( 'bbp_edit_topic', $topic_id, $forum_id, $anonymous_data, $topic_author, true /* Is edit */ );
 668  
 669          /** Revisions *********************************************************/
 670  
 671          // Revision Reason
 672          if ( ! empty( $_POST['bbp_topic_edit_reason'] ) ) {
 673              $topic_edit_reason = sanitize_text_field( $_POST['bbp_topic_edit_reason'] );
 674          }
 675  
 676          // Update revision log
 677          if ( ! empty( $_POST['bbp_log_topic_edit'] ) && ( '1' === $_POST['bbp_log_topic_edit'] ) ) {
 678              $revision_id = wp_save_post_revision( $topic_id );
 679              if ( ! empty( $revision_id ) ) {
 680                  bbp_update_topic_revision_log( array(
 681                      'topic_id'    => $topic_id,
 682                      'revision_id' => $revision_id,
 683                      'author_id'   => bbp_get_current_user_id(),
 684                      'reason'      => $topic_edit_reason
 685                  ) );
 686              }
 687          }
 688  
 689          /** Move Topic ********************************************************/
 690  
 691          // If the new forum id is not equal to the old forum id, run the
 692          // bbp_move_topic action and pass the topic's forum id as the
 693          // first arg and topic id as the second to update counts.
 694          if ( $forum_id !== $topic->post_parent ) {
 695              bbp_move_topic_handler( $topic_id, $topic->post_parent, $forum_id );
 696          }
 697  
 698          /** Additional Actions (After Save) ***********************************/
 699  
 700          do_action( 'bbp_edit_topic_post_extras', $topic_id );
 701  
 702          /** Redirect **********************************************************/
 703  
 704          // Redirect to
 705          $redirect_to = bbp_get_redirect_to();
 706  
 707          // View all?
 708          $view_all = bbp_get_view_all( 'edit_others_replies' );
 709  
 710          // Get the topic URL
 711          $topic_url = bbp_get_topic_permalink( $topic_id, $redirect_to );
 712  
 713          // Add view all?
 714          if ( ! empty( $view_all ) ) {
 715              $topic_url = bbp_add_view_all( $topic_url );
 716          }
 717  
 718          // Allow to be filtered
 719          $topic_url = apply_filters( 'bbp_edit_topic_redirect_to', $topic_url, $view_all, $redirect_to );
 720  
 721          /** Successful Edit ***************************************************/
 722  
 723          // Redirect back to new topic
 724          bbp_redirect( $topic_url );
 725  
 726      /** Errors ****************************************************************/
 727  
 728      } else {
 729          $append_error = ( is_wp_error( $topic_id ) && $topic_id->get_error_message() ) ? $topic_id->get_error_message() . ' ' : '';
 730          bbp_add_error( 'bbp_topic_error', __( '<strong>Error</strong>: The following problem(s) have been found with your topic:' . $append_error . 'Please try again.', 'bbpress' ) );
 731      }
 732  }
 733  
 734  /**
 735   * Handle all the extra meta stuff from posting a new topic
 736   *
 737   * @param int $topic_id Optional. Topic id
 738   * @param int $forum_id Optional. Forum id
 739   * @param array $anonymous_data Optional - if it's an anonymous post. Do not
 740   *                              supply if supplying $author_id. Should be
 741   *                              sanitized (see {@link bbp_filter_anonymous_post_data()}
 742   * @param int $author_id Author id
 743   * @param bool $is_edit Optional. Is the post being edited? Defaults to false.
 744   */
 745  function bbp_update_topic( $topic_id = 0, $forum_id = 0, $anonymous_data = array(), $author_id = 0, $is_edit = false ) {
 746  
 747      // Validate the ID's passed from 'bbp_new_topic' action
 748      $topic_id = bbp_get_topic_id( $topic_id );
 749      $forum_id = bbp_get_forum_id( $forum_id );
 750  
 751      // Get the current user ID
 752      $user_id  = bbp_get_current_user_id();
 753  
 754      // Bail if there is no topic
 755      if ( empty( $topic_id ) ) {
 756          return;
 757      }
 758  
 759      // Check author_id, fallback to current user ID
 760      if ( empty( $author_id ) ) {
 761          $author_id = $user_id;
 762      }
 763  
 764      // Check forum_id, fallback to post_parent or meta
 765      if ( empty( $forum_id ) ) {
 766          $forum_id = bbp_get_topic_forum_id( $topic_id );
 767      }
 768  
 769      // Update locks
 770      update_post_meta( $topic_id, '_edit_last', $user_id );
 771      delete_post_meta( $topic_id, '_edit_lock' );
 772  
 773      // Forum/Topic meta (early, for use in downstream functions)
 774      bbp_update_topic_forum_id( $topic_id, $forum_id );
 775      bbp_update_topic_topic_id( $topic_id, $topic_id );
 776  
 777      // If anonymous post, store name, email, website and ip in post_meta.
 778      if ( ! empty( $anonymous_data ) ) {
 779  
 780          // Update anonymous meta data (not cookies)
 781          bbp_update_anonymous_post_author( $topic_id, $anonymous_data, bbp_get_topic_post_type() );
 782  
 783          // Set transient for throttle check (only on new, not edit)
 784          if ( empty( $is_edit ) ) {
 785              set_transient( '_bbp_' . bbp_current_author_ip() . '_last_posted', time(), HOUR_IN_SECONDS );
 786          }
 787      }
 788  
 789      // Handle Subscription Checkbox
 790      if ( bbp_is_subscriptions_active() && ! empty( $author_id ) ) {
 791  
 792          // Check if subscribed
 793          $subscribed = bbp_is_user_subscribed( $author_id, $topic_id );
 794  
 795          // Check for action
 796          $subscheck  = ( ! empty( $_POST['bbp_topic_subscription'] ) && ( 'bbp_subscribe' === $_POST['bbp_topic_subscription'] ) )
 797              ? true
 798              : false;
 799  
 800          // Subscribed and unsubscribing
 801          if ( ( true === $subscribed ) && ( false === $subscheck ) ) {
 802              bbp_remove_user_subscription( $author_id, $topic_id );
 803  
 804          // Not subscribed and subscribing
 805          } elseif ( ( false === $subscribed ) && ( true === $subscheck ) ) {
 806              bbp_add_user_subscription( $author_id, $topic_id );
 807          }
 808      }
 809  
 810      // Get the topic types
 811      $topic_types = bbp_get_topic_types( $topic_id );
 812  
 813      // Sticky check after 'bbp_new_topic' action so forum ID meta is set
 814      if ( ! empty( $_POST['bbp_stick_topic'] ) && in_array( $_POST['bbp_stick_topic'], array_keys( $topic_types ), true ) ) {
 815  
 816          // What's the caps?
 817          if ( current_user_can( 'moderate', $topic_id ) ) {
 818  
 819              // What's the haps?
 820              switch ( $_POST['bbp_stick_topic'] ) {
 821  
 822                  // Sticky in this forum
 823                  case 'stick'   :
 824                      bbp_stick_topic( $topic_id );
 825                      break;
 826  
 827                  // Super sticky in all forums
 828                  case 'super'   :
 829                      bbp_stick_topic( $topic_id, true );
 830                      break;
 831  
 832                  // Unsticky from everywhere
 833                  case 'unstick' :
 834                  default        :
 835                      bbp_unstick_topic( $topic_id );
 836                      break;
 837              }
 838          }
 839      }
 840  
 841      // Update associated topic values if this is a new topic
 842      if ( empty( $is_edit ) ) {
 843  
 844          // Update poster activity time
 845          bbp_update_user_last_posted( $author_id );
 846  
 847          // Update poster IP
 848          update_post_meta( $topic_id, '_bbp_author_ip', bbp_current_author_ip(), false );
 849  
 850          // Last active time
 851          $last_active = get_post_field( 'post_date', $topic_id );
 852  
 853          // Reply topic meta
 854          bbp_update_topic_last_reply_id      ( $topic_id, 0            );
 855          bbp_update_topic_last_active_id     ( $topic_id, $topic_id    );
 856          bbp_update_topic_last_active_time   ( $topic_id, $last_active );
 857          bbp_update_topic_reply_count        ( $topic_id, 0            );
 858          bbp_update_topic_reply_count_hidden ( $topic_id, 0            );
 859          bbp_update_topic_voice_count        ( $topic_id               );
 860  
 861          // Walk up ancestors and do the dirty work
 862          bbp_update_topic_walker( $topic_id, $last_active, $forum_id, 0, false );
 863      }
 864  
 865      // Bump the custom query cache
 866      wp_cache_set( 'last_changed', microtime(), 'bbpress_posts' );
 867  }
 868  
 869  /**
 870   * Walks up the post_parent tree from the current topic_id, and updates the
 871   * meta data of forums above it. This calls several functions that all run
 872   * manual queries against the database to get their results. As such, this
 873   * function can be costly to run but is necessary to keep everything accurate.
 874   *
 875   * @since 2.0.0 bbPress (r2800)
 876   *
 877   * @param int $topic_id Topic id
 878   * @param string $last_active_time Optional. Last active time
 879   * @param int $forum_id Optional. Forum id
 880   * @param int $reply_id Optional. Reply id
 881   * @param bool $refresh Reset all the previous parameters? Defaults to true.
 882   */
 883  function bbp_update_topic_walker( $topic_id, $last_active_time = '', $forum_id = 0, $reply_id = 0, $refresh = true ) {
 884  
 885      // Validate topic_id
 886      $topic_id  = bbp_get_topic_id( $topic_id );
 887  
 888      // Define local variable(s)
 889      $active_id = 0;
 890  
 891      // Topic was passed
 892      if ( ! empty( $topic_id ) ) {
 893  
 894          // Get the forum ID if none was passed
 895          if ( empty( $forum_id ) ) {
 896              $forum_id = bbp_get_topic_forum_id( $topic_id );
 897          }
 898  
 899          // Set the active_id based on topic_id/reply_id
 900          $active_id = empty( $reply_id ) ? $topic_id : $reply_id;
 901      }
 902  
 903      // Get topic ancestors
 904      $ancestors = array_values( array_unique( array_merge( array( $forum_id ), (array) get_post_ancestors( $topic_id ) ) ) );
 905  
 906      // Topic status
 907      $topic_status = get_post_status( $topic_id );
 908  
 909      // If we want a full refresh, unset any of the possibly passed variables
 910      if ( true === $refresh ) {
 911          $forum_id = $topic_id = $reply_id = $active_id = $last_active_time = 0;
 912          $topic_status = bbp_get_public_status_id();
 913      }
 914  
 915      // Loop through ancestors
 916      if ( ! empty( $ancestors ) ) {
 917          foreach ( $ancestors as $ancestor ) {
 918  
 919              // If ancestor is a forum, update counts
 920              if ( bbp_is_forum( $ancestor ) ) {
 921  
 922                  // Get the forum
 923                  $forum = bbp_get_forum( $ancestor );
 924  
 925                  // Update the forum
 926                  bbp_update_forum( array(
 927                      'forum_id'           => $forum->ID,
 928                      'post_parent'        => $forum->post_parent,
 929                      'last_topic_id'      => $topic_id,
 930                      'last_reply_id'      => $reply_id,
 931                      'last_active_id'     => $active_id,
 932                      'last_active_time'   => $last_active_time,
 933                      'last_active_status' => $topic_status
 934                  ) );
 935              }
 936          }
 937      }
 938  }
 939  
 940  /**
 941   * Handle the moving of a topic from one forum to another. This includes walking
 942   * up the old and new branches and updating the counts.
 943   *
 944   * @since 2.0.0 bbPress (r2907)
 945   *
 946   * @param int $topic_id     The topic id.
 947   * @param int $old_forum_id Old forum id.
 948   * @param int $new_forum_id New forum id.
 949   */
 950  function bbp_move_topic_handler( $topic_id, $old_forum_id, $new_forum_id ) {
 951  
 952      // Validate parameters
 953      $topic_id     = bbp_get_topic_id( $topic_id     );
 954      $old_forum_id = bbp_get_forum_id( $old_forum_id );
 955      $new_forum_id = bbp_get_forum_id( $new_forum_id );
 956  
 957      // Clean old and new forum caches before proceeding, to ensure subsequent
 958      // calls to forum objects are using updated data.
 959      clean_post_cache( $old_forum_id );
 960      clean_post_cache( $new_forum_id );
 961  
 962      // Update topic forum's ID
 963      bbp_update_topic_forum_id( $topic_id, $new_forum_id );
 964  
 965      // Update topic post parent with the new forum ID
 966      wp_update_post( array(
 967          'ID'          => $topic_id,
 968          'post_parent' => $new_forum_id,
 969      ) );
 970  
 971      /** Stickies **************************************************************/
 972  
 973      // Get forum stickies
 974      $old_stickies = bbp_get_stickies( $old_forum_id );
 975  
 976      // Only proceed if stickies are found
 977      if ( ! empty( $old_stickies ) ) {
 978  
 979          // Define local variables
 980          $updated_stickies = array();
 981  
 982          // Loop through stickies of forum and add misses to the updated array
 983          foreach ( (array) $old_stickies as $sticky_topic_id ) {
 984              if ( $topic_id !== $sticky_topic_id ) {
 985                  $updated_stickies[] = $sticky_topic_id;
 986              }
 987          }
 988  
 989          // If stickies are different, update or delete them
 990          if ( $updated_stickies !== $old_stickies ) {
 991  
 992              // No more stickies so delete the meta
 993              if ( empty( $updated_stickies ) ) {
 994                  delete_post_meta( $old_forum_id, '_bbp_sticky_topics' );
 995  
 996              // Still stickies so update the meta
 997              } else {
 998                  update_post_meta( $old_forum_id, '_bbp_sticky_topics', $updated_stickies );
 999              }
1000  
1001              // Topic was sticky, so restick in new forum
1002              bbp_stick_topic( $topic_id );
1003          }
1004      }
1005  
1006      /** Topic Replies *********************************************************/
1007  
1008      // Get the topics replies
1009      $replies = bbp_get_all_child_ids( $topic_id, bbp_get_reply_post_type() );
1010  
1011      // Update the forum_id of all replies in the topic
1012      foreach ( $replies as $reply_id ) {
1013          bbp_update_reply_forum_id( $reply_id, $new_forum_id );
1014      }
1015  
1016      /** Old forum_id **********************************************************/
1017  
1018      // Get topic ancestors
1019      $old_forum_ancestors = array_values( array_unique( array_merge( array( $old_forum_id ), (array) get_post_ancestors( $old_forum_id ) ) ) );
1020  
1021      // Public counts
1022      if ( bbp_is_topic_public( $topic_id ) ) {
1023  
1024          // Update old forum counts.
1025          bbp_decrease_forum_topic_count( $old_forum_id );
1026  
1027          // Update new forum counts.
1028          bbp_increase_forum_topic_count( $new_forum_id );
1029  
1030      // Non-public counts
1031      } else {
1032  
1033          // Update old forum counts.
1034          bbp_decrease_forum_topic_count_hidden( $old_forum_id );
1035  
1036          // Update new forum counts.
1037          bbp_increase_forum_topic_count_hidden( $new_forum_id );
1038      }
1039  
1040      // Get reply counts.
1041      $public_reply_count = bbp_get_public_child_count( $topic_id, bbp_get_reply_post_type() );
1042      $hidden_reply_count = bbp_get_non_public_child_count( $topic_id, bbp_get_reply_post_type() );
1043  
1044      // Bump reply counts.
1045      bbp_bump_forum_reply_count( $old_forum_id, -$public_reply_count );
1046      bbp_bump_forum_reply_count( $new_forum_id, $public_reply_count );
1047      bbp_bump_forum_reply_count_hidden( $old_forum_id, -$hidden_reply_count );
1048      bbp_bump_forum_reply_count_hidden( $new_forum_id, $hidden_reply_count );
1049  
1050      // Loop through ancestors and update them
1051      if ( ! empty( $old_forum_ancestors ) ) {
1052          foreach ( $old_forum_ancestors as $ancestor ) {
1053              if ( bbp_is_forum( $ancestor ) ) {
1054                  bbp_update_forum( array(
1055                      'forum_id' => $ancestor,
1056                  ) );
1057              }
1058          }
1059      }
1060  
1061      /** New forum_id **********************************************************/
1062  
1063      // Make sure we're not walking twice
1064      if ( ! in_array( $new_forum_id, $old_forum_ancestors, true ) ) {
1065  
1066          // Get topic ancestors
1067          $new_forum_ancestors = array_values( array_unique( array_merge( array( $new_forum_id ), (array) get_post_ancestors( $new_forum_id ) ) ) );
1068  
1069          // Make sure we're not walking twice
1070          $new_forum_ancestors = array_diff( $new_forum_ancestors, $old_forum_ancestors );
1071  
1072          // Loop through ancestors and update them
1073          if ( ! empty( $new_forum_ancestors ) ) {
1074              foreach ( $new_forum_ancestors as $ancestor ) {
1075                  if ( bbp_is_forum( $ancestor ) ) {
1076                      bbp_update_forum( array(
1077                          'forum_id' => $ancestor,
1078                      ) );
1079                  }
1080              }
1081          }
1082      }
1083  }
1084  
1085  /**
1086   * Merge topic handler
1087   *
1088   * Handles the front end merge topic submission
1089   *
1090   * @since 2.0.0 bbPress (r2756)
1091   *
1092   * @param string $action The requested action to compare this function to
1093   */
1094  function bbp_merge_topic_handler( $action = '' ) {
1095  
1096      // Bail if action is not bbp-merge-topic
1097      if ( 'bbp-merge-topic' !== $action ) {
1098          return;
1099      }
1100  
1101      // Define local variable(s)
1102      $source_topic_id = $destination_topic_id = 0;
1103      $source_topic = $destination_topic = 0;
1104      $subscribers = $favoriters = $replies = array();
1105  
1106      /** Source Topic **********************************************************/
1107  
1108      // Topic id
1109      if ( empty( $_POST['bbp_topic_id'] ) ) {
1110          bbp_add_error( 'bbp_merge_topic_source_id', __( '<strong>Error</strong>: Topic ID not found.', 'bbpress' ) );
1111      } else {
1112          $source_topic_id = (int) $_POST['bbp_topic_id'];
1113      }
1114  
1115      // Nonce check
1116      if ( ! bbp_verify_nonce_request( 'bbp-merge-topic_' . $source_topic_id ) ) {
1117          bbp_add_error( 'bbp_merge_topic_nonce', __( '<strong>Error</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
1118          return;
1119  
1120      // Source topic not found
1121      } elseif ( ! $source_topic = bbp_get_topic( $source_topic_id ) ) {
1122          bbp_add_error( 'bbp_merge_topic_source_not_found', __( '<strong>Error</strong>: The topic you want to merge was not found.', 'bbpress' ) );
1123          return;
1124      }
1125  
1126      // Cannot edit source topic
1127      if ( ! current_user_can( 'edit_topic', $source_topic->ID ) ) {
1128          bbp_add_error( 'bbp_merge_topic_source_permission', __( '<strong>Error</strong>: You do not have permission to edit the source topic.', 'bbpress' ) );
1129          return;
1130      }
1131  
1132      /** Destination Topic *****************************************************/
1133  
1134      // Topic id
1135      if ( empty( $_POST['bbp_destination_topic'] ) ) {
1136          bbp_add_error( 'bbp_merge_topic_destination_id', __( '<strong>Error</strong>: Destination topic ID not found.', 'bbpress' ) );
1137      } else {
1138          $destination_topic_id = (int) $_POST['bbp_destination_topic'];
1139      }
1140  
1141      // Destination topic not found
1142      if ( ! $destination_topic = bbp_get_topic( $destination_topic_id ) ) {
1143          bbp_add_error( 'bbp_merge_topic_destination_not_found', __( '<strong>Error</strong>: The topic you want to merge to was not found.', 'bbpress' ) );
1144      }
1145  
1146      // Cannot edit destination topic
1147      if ( ! current_user_can( 'edit_topic', $destination_topic->ID ) ) {
1148          bbp_add_error( 'bbp_merge_topic_destination_permission', __( '<strong>Error</strong>: You do not have permission to edit the destination topic.', 'bbpress' ) );
1149      }
1150  
1151      // Bail if errors
1152      if ( bbp_has_errors() ) {
1153          return;
1154      }
1155  
1156      /** No Errors *************************************************************/
1157  
1158      // Update counts, etc...
1159      do_action( 'bbp_merge_topic', $destination_topic->ID, $source_topic->ID );
1160  
1161      /** Date Check ************************************************************/
1162  
1163      // Check if the destination topic is older than the source topic
1164      if ( strtotime( $source_topic->post_date ) < strtotime( $destination_topic->post_date ) ) {
1165  
1166          // Set destination topic post_date to 1 second before source topic
1167          $destination_post_date = date( 'Y-m-d H:i:s', strtotime( $source_topic->post_date ) - 1 );
1168  
1169          // Update destination topic
1170          wp_update_post( array(
1171              'ID'            => $destination_topic_id,
1172              'post_date'     => $destination_post_date,
1173              'post_date_gmt' => get_gmt_from_date( $destination_post_date )
1174          ) );
1175      }
1176  
1177      /** Engagements ***********************************************************/
1178  
1179      // Get engagements from source topic
1180      $engagements = bbp_get_topic_engagements( $source_topic->ID );
1181  
1182      // Maybe migrate engagements
1183      if ( ! empty( $engagements ) ) {
1184          foreach ( $engagements as $engager ) {
1185              bbp_add_user_engagement( $engager, $destination_topic->ID );
1186          }
1187      }
1188  
1189      /** Subscriptions *********************************************************/
1190  
1191      // Get subscribers from source topic
1192      $subscribers = bbp_get_subscribers( $source_topic->ID );
1193  
1194      // Maybe migrate subscriptions
1195      if ( ! empty( $subscribers ) && ! empty( $_POST['bbp_topic_subscribers'] ) && ( '1' === $_POST['bbp_topic_subscribers'] ) ) {
1196          foreach ( $subscribers as $subscriber ) {
1197              bbp_add_user_subscription( $subscriber, $destination_topic->ID );
1198          }
1199      }
1200  
1201      /** Favorites *************************************************************/
1202  
1203      // Get favoriters from source topic
1204      $favoriters = bbp_get_topic_favoriters( $source_topic->ID );
1205  
1206      // Maybe migrate favorites
1207      if ( ! empty( $favoriters ) && ! empty( $_POST['bbp_topic_favoriters'] ) && ( '1' === $_POST['bbp_topic_favoriters'] ) ) {
1208          foreach ( $favoriters as $favoriter ) {
1209              bbp_add_user_favorite( $favoriter, $destination_topic->ID );
1210          }
1211      }
1212  
1213      /** Tags ******************************************************************/
1214  
1215      // Get the source topic tags
1216      $source_topic_tags = wp_get_post_terms( $source_topic->ID, bbp_get_topic_tag_tax_id(), array( 'fields' => 'names' ) );
1217  
1218      // Tags to possibly merge
1219      if ( ! empty( $source_topic_tags ) && ! is_wp_error( $source_topic_tags ) ) {
1220  
1221          // Shift the tags if told to
1222          if ( ! empty( $_POST['bbp_topic_tags'] ) && ( '1' === $_POST['bbp_topic_tags'] ) ) {
1223              wp_set_post_terms( $destination_topic->ID, $source_topic_tags, bbp_get_topic_tag_tax_id(), true );
1224          }
1225  
1226          // Delete the tags from the source topic
1227          wp_delete_object_term_relationships( $source_topic->ID, bbp_get_topic_tag_tax_id() );
1228      }
1229  
1230      /** Source Topic **********************************************************/
1231  
1232      // Status
1233      bbp_open_topic( $source_topic->ID );
1234  
1235      // Sticky
1236      bbp_unstick_topic( $source_topic->ID );
1237  
1238      // Delete source topic's last & count meta data
1239      delete_post_meta( $source_topic->ID, '_bbp_last_reply_id'      );
1240      delete_post_meta( $source_topic->ID, '_bbp_last_active_id'     );
1241      delete_post_meta( $source_topic->ID, '_bbp_last_active_time'   );
1242      delete_post_meta( $source_topic->ID, '_bbp_voice_count'        );
1243      delete_post_meta( $source_topic->ID, '_bbp_reply_count'        );
1244      delete_post_meta( $source_topic->ID, '_bbp_reply_count_hidden' );
1245  
1246      // Delete source topics user relationships
1247      delete_post_meta( $source_topic->ID, '_bbp_favorite'     );
1248      delete_post_meta( $source_topic->ID, '_bbp_subscription' );
1249      delete_post_meta( $source_topic->ID, '_bbp_engagement'   );
1250  
1251      // Get the replies of the source topic
1252      $replies = (array) get_posts( array(
1253          'post_parent'    => $source_topic->ID,
1254          'post_type'      => bbp_get_reply_post_type(),
1255          'posts_per_page' => -1,
1256          'order'          => 'ASC'
1257      ) );
1258  
1259      // Prepend the source topic to its replies array for processing
1260      array_unshift( $replies, $source_topic );
1261  
1262      if ( ! empty( $replies ) ) {
1263  
1264          /** Merge Replies *****************************************************/
1265  
1266          // Change the post_parent of each reply to the destination topic id
1267          foreach ( $replies as $reply ) {
1268  
1269              // Update the reply
1270              wp_update_post( array(
1271                  'ID'          => $reply->ID,
1272                  'post_title'  => '',
1273                  'post_name'   => false,
1274                  'post_type'   => bbp_get_reply_post_type(),
1275                  'post_parent' => $destination_topic->ID,
1276                  'guid'        => ''
1277              ) );
1278  
1279              // Adjust reply meta values
1280              bbp_update_reply_topic_id( $reply->ID, $destination_topic->ID                           );
1281              bbp_update_reply_forum_id( $reply->ID, bbp_get_topic_forum_id( $destination_topic->ID ) );
1282  
1283              // Update the reply position
1284              bbp_update_reply_position( $reply->ID );
1285  
1286              // Do additional actions per merged reply
1287              do_action( 'bbp_merged_topic_reply', $reply->ID, $destination_topic->ID );
1288          }
1289      }
1290  
1291      /** Successful Merge ******************************************************/
1292  
1293      // Update topic's last meta data
1294      bbp_update_topic_last_reply_id   ( $destination_topic->ID );
1295      bbp_update_topic_last_active_id  ( $destination_topic->ID );
1296      bbp_update_topic_last_active_time( $destination_topic->ID );
1297  
1298      // Send the post parent of the source topic as it has been shifted
1299      // (possibly to a new forum) so we need to update the counts of the
1300      // old forum as well as the new one
1301      do_action( 'bbp_merged_topic', $destination_topic->ID, $source_topic->ID, $source_topic->post_parent );
1302  
1303      // Redirect back to new topic
1304      bbp_redirect( bbp_get_topic_permalink( $destination_topic->ID ) );
1305  }
1306  
1307  /**
1308   * Fix counts on topic merge
1309   *
1310   * When a topic is merged, update the counts of source and destination topic
1311   * and their forums.
1312   *
1313   * @since 2.0.0 bbPress (r2756)
1314   *
1315   * @param int $destination_topic_id Destination topic id
1316   * @param int $source_topic_id Source topic id
1317   * @param int $source_topic_forum_id Source topic's forum id
1318   */
1319  function bbp_merge_topic_count( $destination_topic_id, $source_topic_id, $source_topic_forum_id ) {
1320  
1321      /** Source Topic **********************************************************/
1322  
1323      // Forum Topic Counts
1324      bbp_update_forum_topic_count( $source_topic_forum_id );
1325  
1326      // Forum Reply Counts
1327      bbp_update_forum_reply_count( $source_topic_forum_id );
1328  
1329      /** Destination Topic *****************************************************/
1330  
1331      // Topic Reply Counts
1332      bbp_update_topic_reply_count( $destination_topic_id );
1333  
1334      // Topic Hidden Reply Counts
1335      bbp_update_topic_reply_count_hidden( $destination_topic_id );
1336  
1337      // Topic Voice Counts
1338      bbp_update_topic_voice_count( $destination_topic_id );
1339  
1340      do_action( 'bbp_merge_topic_count', $destination_topic_id, $source_topic_id, $source_topic_forum_id );
1341  }
1342  
1343  /**
1344   * Split topic handler
1345   *
1346   * Handles the front end split topic submission
1347   *
1348   * @since 2.0.0 bbPress (r2756)
1349   *
1350   * @param string $action The requested action to compare this function to
1351   */
1352  function bbp_split_topic_handler( $action = '' ) {
1353  
1354      // Bail if action is not 'bbp-split-topic'
1355      if ( 'bbp-split-topic' !== $action ) {
1356          return;
1357      }
1358  
1359      // Prevent debug notices
1360      $from_reply_id = $destination_topic_id = 0;
1361      $destination_topic_title = '';
1362      $destination_topic = $from_reply = $source_topic = '';
1363      $split_option = false;
1364  
1365      /** Split Reply ***********************************************************/
1366  
1367      if ( empty( $_POST['bbp_reply_id'] ) ) {
1368          bbp_add_error( 'bbp_split_topic_reply_id', __( '<strong>Error</strong>: A reply ID is required.', 'bbpress' ) );
1369      } else {
1370          $from_reply_id = (int) $_POST['bbp_reply_id'];
1371      }
1372  
1373      $from_reply = bbp_get_reply( $from_reply_id );
1374  
1375      // Reply exists
1376      if ( empty( $from_reply ) ) {
1377          bbp_add_error( 'bbp_split_topic_r_not_found', __( '<strong>Error</strong>: The reply you want to split from was not found.', 'bbpress' ) );
1378      }
1379  
1380      /** Topic to Split ********************************************************/
1381  
1382      // Get the topic being split
1383      $source_topic = bbp_get_topic( $from_reply->post_parent );
1384  
1385      // No topic
1386      if ( empty( $source_topic ) ) {
1387          bbp_add_error( 'bbp_split_topic_source_not_found', __( '<strong>Error</strong>: The topic you want to split was not found.', 'bbpress' ) );
1388      }
1389  
1390      // Nonce check failed
1391      if ( ! bbp_verify_nonce_request( 'bbp-split-topic_' . $source_topic->ID ) ) {
1392          bbp_add_error( 'bbp_split_topic_nonce', __( '<strong>Error</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
1393          return;
1394      }
1395  
1396      // Use cannot edit topic
1397      if ( ! current_user_can( 'edit_topic', $source_topic->ID ) ) {
1398          bbp_add_error( 'bbp_split_topic_source_permission', __( '<strong>Error</strong>: You do not have permission to edit the source topic.', 'bbpress' ) );
1399      }
1400  
1401      // How to Split
1402      if ( ! empty( $_POST['bbp_topic_split_option'] ) ) {
1403          $split_option = sanitize_key( $_POST['bbp_topic_split_option'] );
1404      }
1405  
1406      // Invalid split option
1407      if ( empty( $split_option ) || ! in_array( $split_option, array( 'existing', 'reply' ), true ) ) {
1408          bbp_add_error( 'bbp_split_topic_option', __( '<strong>Error</strong>: You need to choose a valid split option.', 'bbpress' ) );
1409  
1410      // Valid Split Option
1411      } else {
1412  
1413          // What kind of split
1414          switch ( $split_option ) {
1415  
1416              // Into an existing topic
1417              case 'existing' :
1418  
1419                  // Get destination topic id
1420                  if ( empty( $_POST['bbp_destination_topic'] ) ) {
1421                      bbp_add_error( 'bbp_split_topic_destination_id', __( '<strong>Error</strong>: A topic ID is required.', 'bbpress' ) );
1422                  } else {
1423                      $destination_topic_id = (int) $_POST['bbp_destination_topic'];
1424                  }
1425  
1426                  // Get the destination topic
1427                  $destination_topic = bbp_get_topic( $destination_topic_id );
1428  
1429                  // No destination topic
1430                  if ( empty( $destination_topic ) ) {
1431                      bbp_add_error( 'bbp_split_topic_destination_not_found', __( '<strong>Error</strong>: The topic you want to split to was not found.', 'bbpress' ) );
1432                  }
1433  
1434                  // User cannot edit the destination topic
1435                  if ( ! current_user_can( 'edit_topic', $destination_topic->ID ) ) {
1436                      bbp_add_error( 'bbp_split_topic_destination_permission', __( '<strong>Error</strong>: You do not have permission to edit the destination topic.', 'bbpress' ) );
1437                  }
1438  
1439                  break;
1440  
1441              // Split at reply into a new topic
1442              case 'reply' :
1443              default :
1444  
1445                  // User needs to be able to publish topics
1446                  if ( current_user_can( 'publish_topics' ) ) {
1447  
1448                      // Use the new title that was passed
1449                      if ( ! empty( $_POST['bbp_topic_split_destination_title'] ) ) {
1450                          $destination_topic_title = sanitize_text_field( $_POST['bbp_topic_split_destination_title'] );
1451  
1452                      // Use the source topic title
1453                      } else {
1454                          $destination_topic_title = $source_topic->post_title;
1455                      }
1456  
1457                      // Update the topic
1458                      $destination_topic_id = wp_update_post( array(
1459                          'ID'          => $from_reply->ID,
1460                          'post_title'  => $destination_topic_title,
1461                          'post_name'   => false,
1462                          'post_type'   => bbp_get_topic_post_type(),
1463                          'post_parent' => $source_topic->post_parent,
1464                          'menu_order'  => 0,
1465                          'guid'        => ''
1466                      ) );
1467                      $destination_topic = bbp_get_topic( $destination_topic_id );
1468  
1469                      // Make sure the new topic knows its a topic
1470                      bbp_update_topic_topic_id( $from_reply->ID );
1471  
1472                      // Shouldn't happen
1473                      if ( false === $destination_topic_id || is_wp_error( $destination_topic_id ) || empty( $destination_topic ) ) {
1474                          bbp_add_error( 'bbp_split_topic_destination_reply', __( '<strong>Error</strong>: There was a problem converting the reply into the topic. Please try again.', 'bbpress' ) );
1475                      }
1476  
1477                  // User cannot publish posts
1478                  } else {
1479                      bbp_add_error( 'bbp_split_topic_destination_permission', __( '<strong>Error</strong>: You do not have permission to create new topics. The reply could not be converted into a topic.', 'bbpress' ) );
1480                  }
1481  
1482                  break;
1483          }
1484      }
1485  
1486      // Bail if there are errors
1487      if ( bbp_has_errors() ) {
1488          return;
1489      }
1490  
1491      /** No Errors - Do the Spit ***********************************************/
1492  
1493      // Update counts, etc...
1494      do_action( 'bbp_pre_split_topic', $from_reply->ID, $source_topic->ID, $destination_topic->ID );
1495  
1496      /** Date Check ************************************************************/
1497  
1498      // Check if the destination topic is older than the from reply
1499      if ( strtotime( $from_reply->post_date ) < strtotime( $destination_topic->post_date ) ) {
1500  
1501          // Set destination topic post_date to 1 second before from reply
1502          $destination_post_date = date( 'Y-m-d H:i:s', strtotime( $from_reply->post_date ) - 1 );
1503  
1504          // Update destination topic
1505          wp_update_post( array(
1506              'ID'            => $destination_topic_id,
1507              'post_date'     => $destination_post_date,
1508              'post_date_gmt' => get_gmt_from_date( $destination_post_date )
1509          ) );
1510      }
1511  
1512      /** Subscriptions *********************************************************/
1513  
1514      // Copy the subscribers
1515      if ( ! empty( $_POST['bbp_topic_subscribers'] ) && '1' === $_POST['bbp_topic_subscribers'] && bbp_is_subscriptions_active() ) {
1516  
1517          // Get the subscribers
1518          $subscribers = bbp_get_subscribers( $source_topic->ID );
1519  
1520          if ( ! empty( $subscribers ) ) {
1521  
1522              // Add subscribers to new topic
1523              foreach ( (array) $subscribers as $subscriber ) {
1524                  bbp_add_user_subscription( $subscriber, $destination_topic->ID );
1525              }
1526          }
1527      }
1528  
1529      /** Favorites *************************************************************/
1530  
1531      // Copy the favoriters if told to
1532      if ( ! empty( $_POST['bbp_topic_favoriters'] ) && ( '1' === $_POST['bbp_topic_favoriters'] ) ) {
1533  
1534          // Get the favoriters
1535          $favoriters = bbp_get_topic_favoriters( $source_topic->ID );
1536  
1537          if ( ! empty( $favoriters ) ) {
1538  
1539              // Add the favoriters to new topic
1540              foreach ( (array) $favoriters as $favoriter ) {
1541                  bbp_add_user_favorite( $favoriter, $destination_topic->ID );
1542              }
1543          }
1544      }
1545  
1546      /** Tags ******************************************************************/
1547  
1548      // Copy the tags if told to
1549      if ( ! empty( $_POST['bbp_topic_tags'] ) && ( '1' === $_POST['bbp_topic_tags'] ) ) {
1550  
1551          // Get the source topic tags
1552          $source_topic_tags = wp_get_post_terms( $source_topic->ID, bbp_get_topic_tag_tax_id(), array( 'fields' => 'names' ) );
1553  
1554          if ( ! empty( $source_topic_tags ) ) {
1555              wp_set_post_terms( $destination_topic->ID, $source_topic_tags, bbp_get_topic_tag_tax_id(), true );
1556          }
1557      }
1558  
1559      /** Split Replies *********************************************************/
1560  
1561      // get_posts() is not used because it doesn't allow us to use '>='
1562      // comparision without a filter.
1563      $bbp_db  = bbp_db();
1564      $query   = $bbp_db->prepare( "SELECT * FROM {$bbp_db->posts} WHERE {$bbp_db->posts}.post_date >= %s AND {$bbp_db->posts}.post_parent = %d AND {$bbp_db->posts}.post_type = %s ORDER BY {$bbp_db->posts}.post_date ASC", $from_reply->post_date, $source_topic->ID, bbp_get_reply_post_type() );
1565      $replies = (array) $bbp_db->get_results( $query );
1566  
1567      // Make sure there are replies to loop through
1568      if ( ! empty( $replies ) && ! is_wp_error( $replies ) ) {
1569  
1570          // Save reply ids
1571          $reply_ids = array();
1572  
1573          // Change the post_parent of each reply to the destination topic id
1574          foreach ( $replies as $reply ) {
1575  
1576              // Update the reply
1577              wp_update_post( array(
1578                  'ID'          => $reply->ID,
1579                  'post_title'  => '',
1580                  'post_name'   => false, // will be automatically generated
1581                  'post_parent' => $destination_topic->ID,
1582                  'guid'        => ''
1583              ) );
1584  
1585              // Gather reply ids
1586              $reply_ids[] = $reply->ID;
1587  
1588              // Adjust reply meta values
1589              bbp_update_reply_topic_id( $reply->ID, $destination_topic->ID                           );
1590              bbp_update_reply_forum_id( $reply->ID, bbp_get_topic_forum_id( $destination_topic->ID ) );
1591  
1592              // Adjust reply position
1593              bbp_update_reply_position( $reply->ID );
1594  
1595              // Adjust reply to values
1596              $reply_to = bbp_get_reply_to( $reply->ID );
1597  
1598              // Not a reply to a reply that moved over
1599              if ( ! in_array( $reply_to, $reply_ids, true ) ) {
1600                  bbp_update_reply_to( $reply->ID, 0 );
1601              }
1602  
1603              // New topic from reply can't be a reply to
1604              if ( ( $from_reply->ID === $destination_topic->ID ) && ( $from_reply->ID === $reply_to ) ) {
1605                  bbp_update_reply_to( $reply->ID, 0 );
1606              }
1607  
1608              // Do additional actions per split reply
1609              do_action( 'bbp_split_topic_reply', $reply->ID, $destination_topic->ID );
1610          }
1611  
1612          // Remove reply to from new topic
1613          if ( $from_reply->ID === $destination_topic->ID ) {
1614              delete_post_meta( $from_reply->ID, '_bbp_reply_to' );
1615          }
1616  
1617          // Set the last reply ID and freshness
1618          $last_reply_id = $reply->ID;
1619          $freshness     = $reply->post_date;
1620  
1621      // Set the last reply ID and freshness to the from_reply
1622      } else {
1623          $last_reply_id = $from_reply->ID;
1624          $freshness     = $from_reply->post_date;
1625      }
1626  
1627      // It is a new topic and we need to set some default metas to make
1628      // the topic display in bbp_has_topics() list
1629      if ( 'reply' === $split_option ) {
1630          bbp_update_topic_last_reply_id   ( $destination_topic->ID, $last_reply_id );
1631          bbp_update_topic_last_active_id  ( $destination_topic->ID, $last_reply_id );
1632          bbp_update_topic_last_active_time( $destination_topic->ID, $freshness     );
1633      }
1634  
1635      // Update source topic ID last active
1636      bbp_update_topic_last_reply_id   ( $source_topic->ID );
1637      bbp_update_topic_last_active_id  ( $source_topic->ID );
1638      bbp_update_topic_last_active_time( $source_topic->ID );
1639  
1640      /** Successful Split ******************************************************/
1641  
1642      // Update counts, etc...
1643      do_action( 'bbp_post_split_topic', $from_reply->ID, $source_topic->ID, $destination_topic->ID );
1644  
1645      // Redirect back to the topic
1646      bbp_redirect( bbp_get_topic_permalink( $destination_topic->ID ) );
1647  }
1648  
1649  /**
1650   * Fix counts on topic split
1651   *
1652   * When a topic is split, update the counts of source and destination topic
1653   * and their forums.
1654   *
1655   * @since 2.0.0 bbPress (r2756)
1656   *
1657   * @param int $from_reply_id From reply id
1658   * @param int $source_topic_id Source topic id
1659   * @param int $destination_topic_id Destination topic id
1660   */
1661  function bbp_split_topic_count( $from_reply_id, $source_topic_id, $destination_topic_id ) {
1662  
1663      // Forum Topic Counts
1664      bbp_update_forum_topic_count( bbp_get_topic_forum_id( $destination_topic_id ) );
1665  
1666      // Forum Reply Counts
1667      bbp_update_forum_reply_count( bbp_get_topic_forum_id( $destination_topic_id ) );
1668  
1669      // Topic Reply Counts
1670      bbp_update_topic_reply_count( $source_topic_id      );
1671      bbp_update_topic_reply_count( $destination_topic_id );
1672  
1673      // Topic Hidden Reply Counts
1674      bbp_update_topic_reply_count_hidden( $source_topic_id      );
1675      bbp_update_topic_reply_count_hidden( $destination_topic_id );
1676  
1677      // Topic Voice Counts
1678      bbp_update_topic_voice_count( $source_topic_id      );
1679      bbp_update_topic_voice_count( $destination_topic_id );
1680  
1681      do_action( 'bbp_split_topic_count', $from_reply_id, $source_topic_id, $destination_topic_id );
1682  }
1683  
1684  /**
1685   * Handles the front end tag management (renaming, merging, destroying)
1686   *
1687   * @since 2.0.0 bbPress (r2768)
1688   *
1689   * @param string $action The requested action to compare this function to
1690   */
1691  function bbp_edit_topic_tag_handler( $action = '' ) {
1692  
1693      // Bail if required POST actions aren't passed
1694      if ( empty( $_POST['tag-id'] ) ) {
1695          return;
1696      }
1697  
1698      // Setup possible get actions
1699      $possible_actions = array(
1700          'bbp-update-topic-tag',
1701          'bbp-merge-topic-tag',
1702          'bbp-delete-topic-tag'
1703      );
1704  
1705      // Bail if actions aren't meant for this function
1706      if ( ! in_array( $action, $possible_actions, true ) ) {
1707          return;
1708      }
1709  
1710      // Setup vars
1711      $tag_id = (int) $_POST['tag-id'];
1712      $tag    = get_term( $tag_id, bbp_get_topic_tag_tax_id() );
1713  
1714      // Tag does not exist
1715      if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
1716          bbp_add_error( 'bbp_manage_topic_invalid_tag', sprintf( __( '<strong>Error</strong>: The following problem(s) have been found while getting the tag: %s', 'bbpress' ), $tag->get_error_message() ) );
1717          return;
1718      }
1719  
1720      // What action are we trying to perform?
1721      switch ( $action ) {
1722  
1723          // Update tag
1724          case 'bbp-update-topic-tag' :
1725  
1726              // Nonce check
1727              if ( ! bbp_verify_nonce_request( 'update-tag_' . $tag_id ) ) {
1728                  bbp_add_error( 'bbp_manage_topic_tag_update_nonce', __( '<strong>Error</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
1729                  return;
1730              }
1731  
1732              // Can user edit topic tags?
1733              if ( ! current_user_can( 'edit_topic_tag', $tag_id ) ) {
1734                  bbp_add_error( 'bbp_manage_topic_tag_update_permission', __( '<strong>Error</strong>: You do not have permission to edit the topic tags.', 'bbpress' ) );
1735                  return;
1736              }
1737  
1738              // No tag name was provided
1739              if ( empty( $_POST['tag-name'] ) || ! $name = $_POST['tag-name'] ) {
1740                  bbp_add_error( 'bbp_manage_topic_tag_update_name', __( '<strong>Error</strong>: You need to enter a tag name.', 'bbpress' ) );
1741                  return;
1742              }
1743  
1744              // Attempt to update the tag
1745              $slug        = ! empty( $_POST['tag-slug']        ) ? $_POST['tag-slug']        : '';
1746              $description = ! empty( $_POST['tag-description'] ) ? $_POST['tag-description'] : '';
1747              $tag         = wp_update_term( $tag_id, bbp_get_topic_tag_tax_id(), array(
1748                  'name'        => $name,
1749                  'slug'        => $slug,
1750                  'description' => $description
1751              ) );
1752  
1753              // Cannot update tag
1754              if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
1755                  bbp_add_error( 'bbp_manage_topic_tag_update_error', sprintf( __( '<strong>Error</strong>: The following problem(s) have been found while updating the tag: %s', 'bbpress' ), $tag->get_error_message() ) );
1756                  return;
1757              }
1758  
1759              // Redirect
1760              $redirect = get_term_link( $tag_id, bbp_get_topic_tag_tax_id() );
1761  
1762              // Update counts, etc...
1763              do_action( 'bbp_update_topic_tag', $tag_id, $tag, $name, $slug, $description );
1764  
1765              break;
1766  
1767          // Merge two tags
1768          case 'bbp-merge-topic-tag'  :
1769  
1770              // Nonce check
1771              if ( ! bbp_verify_nonce_request( 'merge-tag_' . $tag_id ) ) {
1772                  bbp_add_error( 'bbp_manage_topic_tag_merge_nonce', __( '<strong>Error</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
1773                  return;
1774              }
1775  
1776              // Can user edit topic tags?
1777              if ( ! current_user_can( 'edit_topic_tags' ) ) {
1778                  bbp_add_error( 'bbp_manage_topic_tag_merge_permission', __( '<strong>Error</strong>: You do not have permission to edit the topic tags.', 'bbpress' ) );
1779                  return;
1780              }
1781  
1782              // No tag name was provided
1783              if ( empty( $_POST['tag-existing-name'] ) || ! $name = $_POST['tag-existing-name'] ) {
1784                  bbp_add_error( 'bbp_manage_topic_tag_merge_name', __( '<strong>Error</strong>: You need to enter a tag name.', 'bbpress' ) );
1785                  return;
1786              }
1787  
1788              // If term does not exist, create it
1789              if ( ! $tag = term_exists( $name, bbp_get_topic_tag_tax_id() ) ) {
1790                  $tag = wp_insert_term( $name, bbp_get_topic_tag_tax_id() );
1791              }
1792  
1793              // Problem inserting the new term
1794              if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
1795                  bbp_add_error( 'bbp_manage_topic_tag_merge_error', sprintf( __( '<strong>Error</strong>: The following problem(s) have been found while merging the tags: %s', 'bbpress' ), $tag->get_error_message() ) );
1796                  return;
1797              }
1798  
1799              // Merging in to...
1800              $to_tag = $tag['term_id'];
1801  
1802              // Attempting to merge a tag into itself
1803              if ( $tag_id === $to_tag ) {
1804                  bbp_add_error( 'bbp_manage_topic_tag_merge_same', __( '<strong>Error</strong>: The tags which are being merged can not be the same.', 'bbpress' ) );
1805                  return;
1806              }
1807  
1808              // Delete the old term
1809              $tag = wp_delete_term( $tag_id, bbp_get_topic_tag_tax_id(), array(
1810                  'default'       => $to_tag,
1811                  'force_default' => true
1812              ) );
1813  
1814              // Error merging the terms
1815              if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
1816                  bbp_add_error( 'bbp_manage_topic_tag_merge_error', sprintf( __( '<strong>Error</strong>: The following problem(s) have been found while merging the tags: %s', 'bbpress' ), $tag->get_error_message() ) );
1817                  return;
1818              }
1819  
1820              // Redirect
1821              $redirect = get_term_link( (int) $to_tag, bbp_get_topic_tag_tax_id() );
1822  
1823              // Update counts, etc...
1824              do_action( 'bbp_merge_topic_tag', $tag_id, $to_tag, $tag );
1825  
1826              break;
1827  
1828          // Delete tag
1829          case 'bbp-delete-topic-tag' :
1830  
1831              // Nonce check
1832              if ( ! bbp_verify_nonce_request( 'delete-tag_' . $tag_id ) ) {
1833                  bbp_add_error( 'bbp_manage_topic_tag_delete_nonce', __( '<strong>Error</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
1834                  return;
1835              }
1836  
1837              // Can user delete topic tags?
1838              if ( ! current_user_can( 'delete_topic_tag', $tag_id ) ) {
1839                  bbp_add_error( 'bbp_manage_topic_tag_delete_permission', __( '<strong>Error</strong>: You do not have permission to delete the topic tags.', 'bbpress' ) );
1840                  return;
1841              }
1842  
1843              // Attempt to delete term
1844              $tag = wp_delete_term( $tag_id, bbp_get_topic_tag_tax_id() );
1845  
1846              // Error deleting term
1847              if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
1848                  bbp_add_error( 'bbp_manage_topic_tag_delete_error', sprintf( __( '<strong>Error</strong>: The following problem(s) have been found while deleting the tag: %s', 'bbpress' ), $tag->get_error_message() ) );
1849                  return;
1850              }
1851  
1852              // We don't have any other place to go other than home! Or we may die because of the 404 disease
1853              $redirect = bbp_get_forums_url();
1854  
1855              // Update counts, etc...
1856              do_action( 'bbp_delete_topic_tag', $tag_id, $tag );
1857  
1858              break;
1859      }
1860  
1861      /** Successful Moderation *************************************************/
1862  
1863      // Redirect back
1864      $redirect = ( ! empty( $redirect ) && ! is_wp_error( $redirect ) ) ? $redirect : home_url();
1865      bbp_redirect( $redirect );
1866  }
1867  
1868  /** Helpers *******************************************************************/
1869  
1870  /**
1871   * Return an associative array of available topic statuses
1872   *
1873   * @since 2.4.0 bbPress (r5059)
1874   *
1875   * @param int $topic_id   Optional. Topic id.
1876   *
1877   * @return array
1878   */
1879  function bbp_get_topic_statuses( $topic_id = 0 ) {
1880  
1881      // Filter & return
1882      return (array) apply_filters( 'bbp_get_topic_statuses', array(
1883          bbp_get_public_status_id()  => _x( 'Open',    'Open the topic',      'bbpress' ),
1884          bbp_get_closed_status_id()  => _x( 'Closed',  'Close the topic',     'bbpress' ),
1885          bbp_get_spam_status_id()    => _x( 'Spam',    'Spam the topic',      'bbpress' ),
1886          bbp_get_trash_status_id()   => _x( 'Trash',   'Trash the topic',     'bbpress' ),
1887          bbp_get_pending_status_id() => _x( 'Pending', 'Unapprove the topic', 'bbpress' )
1888      ), $topic_id );
1889  }
1890  
1891  /**
1892   * Return an associative array of topic sticky types
1893   *
1894   * @since 2.4.0 bbPress (r5059)
1895   *
1896   * @param int $topic_id   Optional. Topic id.
1897   *
1898   * @return array
1899   */
1900  function bbp_get_topic_types( $topic_id = 0 ) {
1901  
1902      // Filter & return
1903      return (array) apply_filters( 'bbp_get_topic_types', array(
1904          'unstick' => _x( 'Normal',       'Unstick a topic',         'bbpress' ),
1905          'stick'   => _x( 'Sticky',       'Make topic sticky',       'bbpress' ),
1906          'super'   => _x( 'Super Sticky', 'Make topic super sticky', 'bbpress' )
1907      ), $topic_id );
1908  }
1909  
1910  /**
1911   * Return array of available topic toggle actions
1912   *
1913   * @since 2.6.0 bbPress (r6133)
1914   *
1915   * @param int $topic_id   Optional. Topic id.
1916   *
1917   * @return array
1918   */
1919  function bbp_get_topic_toggles( $topic_id = 0 ) {
1920  
1921      // Filter & return
1922      return (array) apply_filters( 'bbp_get_toggle_topic_actions', array(
1923          'bbp_toggle_topic_close',
1924          'bbp_toggle_topic_stick',
1925          'bbp_toggle_topic_spam',
1926          'bbp_toggle_topic_trash',
1927          'bbp_toggle_topic_approve'
1928      ), $topic_id );
1929  }
1930  
1931  /**
1932   * Return array of public topic statuses.
1933   *
1934   * @since 2.6.0 bbPress (r6383)
1935   *
1936   * @return array
1937   */
1938  function bbp_get_public_topic_statuses() {
1939      $statuses = array(
1940          bbp_get_public_status_id(),
1941          bbp_get_closed_status_id()
1942      );
1943  
1944      // Filter & return
1945      return (array) apply_filters( 'bbp_get_public_topic_statuses', $statuses );
1946  }
1947  
1948  /**
1949   * Return array of non-public topic statuses.
1950   *
1951   * @since 2.6.0 bbPress (r6642)
1952   *
1953   * @return array
1954   */
1955  function bbp_get_non_public_topic_statuses() {
1956      $statuses = array(
1957          bbp_get_trash_status_id(),
1958          bbp_get_spam_status_id(),
1959          bbp_get_pending_status_id()
1960      );
1961  
1962      // Filter & return
1963      return (array) apply_filters( 'bbp_get_non_public_topic_statuses', $statuses );
1964  }
1965  
1966  /** Stickies ******************************************************************/
1967  
1968  /**
1969   * Return sticky topics of a forum
1970   *
1971   * @since 2.0.0 bbPress (r2592)
1972   *
1973   * @param int $forum_id Optional. If not passed, super stickies are returned.
1974   * @return array IDs of sticky topics of a forum or super stickies
1975   */
1976  function bbp_get_stickies( $forum_id = 0 ) {
1977  
1978      // Get stickies (maybe super if empty)
1979      $stickies = empty( $forum_id )
1980          ? bbp_get_super_stickies()
1981          : get_post_meta( $forum_id, '_bbp_sticky_topics', true );
1982  
1983      // Cast as array
1984      $stickies = ( empty( $stickies ) || ! is_array( $stickies ) )
1985          ? array()
1986          : wp_parse_id_list( $stickies );
1987  
1988      // Filter & return
1989      return (array) apply_filters( 'bbp_get_stickies', $stickies, $forum_id );
1990  }
1991  
1992  /**
1993   * Return topics stuck to front page of the forums
1994   *
1995   * @since 2.0.0 bbPress (r2592)
1996   *
1997   * @return array IDs of super sticky topics
1998   */
1999  function bbp_get_super_stickies() {
2000  
2001      // Get super stickies
2002      $stickies = get_option( '_bbp_super_sticky_topics', array() );
2003  
2004      // Cast as array
2005      $stickies = ( empty( $stickies ) || ! is_array( $stickies ) )
2006          ? array()
2007          : wp_parse_id_list( $stickies );
2008  
2009      // Filter & return
2010      return (array) apply_filters( 'bbp_get_super_stickies', $stickies );
2011  }
2012  
2013  /** Topics Actions ************************************************************/
2014  
2015  /**
2016   * Handles the front end opening/closing, spamming/unspamming,
2017   * sticking/unsticking and trashing/untrashing/deleting of topics
2018   *
2019   * @since 2.0.0 bbPress (r2727)
2020   *
2021   * @param string $action The requested action to compare this function to
2022   */
2023  function bbp_toggle_topic_handler( $action = '' ) {
2024  
2025      // Bail if required GET actions aren't passed
2026      if ( empty( $_GET['topic_id'] ) ) {
2027          return;
2028      }
2029  
2030      // What's the topic id?
2031      $topic_id = bbp_get_topic_id( (int) $_GET['topic_id'] );
2032  
2033      // Get possible topic-handler toggles
2034      $toggles = bbp_get_topic_toggles( $topic_id );
2035  
2036      // Bail if actions aren't meant for this function
2037      if ( ! in_array( $action, $toggles, true ) ) {
2038          return;
2039      }
2040  
2041      // Make sure topic exists
2042      $topic = bbp_get_topic( $topic_id );
2043      if ( empty( $topic ) ) {
2044          bbp_add_error( 'bbp_toggle_topic_missing', __( '<strong>Error</strong>: This topic could not be found or no longer exists.', 'bbpress' ) );
2045          return;
2046      }
2047  
2048      // What is the user doing here?
2049      if ( ! current_user_can( 'edit_topic', $topic_id ) || ( 'bbp_toggle_topic_trash' === $action && ! current_user_can( 'delete_topic', $topic_id ) ) ) {
2050          bbp_add_error( 'bbp_toggle_topic_permission', __( '<strong>Error</strong>: You do not have permission to do that.', 'bbpress' ) );
2051          return;
2052      }
2053  
2054      // Sub-action?
2055      $sub_action = ! empty( $_GET['sub_action'] )
2056          ? sanitize_key( $_GET['sub_action'] )
2057          : false;
2058  
2059      // Preliminary array
2060      $post_data = array( 'ID' => $topic_id );
2061  
2062      // Do the topic toggling
2063      $retval = bbp_toggle_topic( array(
2064          'id'         => $topic_id,
2065          'action'     => $action,
2066          'sub_action' => $sub_action,
2067          'data'       => $post_data
2068      ) );
2069  
2070      // Do additional topic toggle actions
2071      do_action( 'bbp_toggle_topic_handler', $retval['status'], $post_data, $action );
2072  
2073      // No errors
2074      if ( ( false !== $retval['status'] ) && ! is_wp_error( $retval['status'] ) ) {
2075          bbp_redirect( $retval['redirect_to'] );
2076  
2077      // Handle errors
2078      } else {
2079          bbp_add_error( 'bbp_toggle_topic', $retval['message'] );
2080      }
2081  }
2082  
2083  /**
2084   * Do the actual topic toggling
2085   *
2086   * This function is used by `bbp_toggle_topic_handler()` to do the actual heavy
2087   * lifting when it comes to toggling topic. It only really makes sense to call
2088   * within that context, so if you need to call this function directly, make sure
2089   * you're also doing what the handler does too.
2090   *
2091   * @since 2.6.0  bbPress (r6133)
2092   * @access private
2093   *
2094   * @param array $args
2095   */
2096  function bbp_toggle_topic( $args = array() ) {
2097  
2098      // Parse the arguments
2099      $r = bbp_parse_args( $args, array(
2100          'id'         => 0,
2101          'action'     => '',
2102          'sub_action' => '',
2103          'data'       => array()
2104      ) );
2105  
2106      // Build the nonce suffix
2107      $nonce_suffix = bbp_get_topic_post_type() . '_' . (int) $r['id'];
2108  
2109      // Default return values
2110      $retval = array(
2111          'status'      => 0,
2112          'message'     => '',
2113          'redirect_to' => bbp_get_topic_permalink( $r['id'], bbp_get_redirect_to() ),
2114          'view_all'    => false
2115      );
2116  
2117      // What action are we trying to perform?
2118      switch ( $r['action'] ) {
2119  
2120          // Toggle approve/unapprove
2121          case 'bbp_toggle_topic_approve' :
2122              check_ajax_referer( "approve-{$nonce_suffix}" );
2123  
2124              $is_pending         = bbp_is_topic_pending( $r['id'] );
2125              $retval['view_all'] = ! $is_pending;
2126  
2127              // Toggle
2128              $retval['status'] = ( true === $is_pending )
2129                  ? bbp_approve_topic( $r['id'] )
2130                  : bbp_unapprove_topic( $r['id'] );
2131  
2132              // Feedback
2133              $retval['message'] = ( true === $is_pending )
2134                  ? __( '<strong>Error</strong>: There was a problem approving the topic.',   'bbpress' )
2135                  : __( '<strong>Error</strong>: There was a problem unapproving the topic.', 'bbpress' );
2136  
2137              break;
2138  
2139          // Toggle open/close
2140          case 'bbp_toggle_topic_close' :
2141              check_ajax_referer( "close-{$nonce_suffix}" );
2142  
2143              $is_open = bbp_is_topic_open( $r['id'] );
2144  
2145              // Toggle
2146              $retval['status'] = ( true === $is_open )
2147                  ? bbp_close_topic( $r['id'] )
2148                  : bbp_open_topic( $r['id'] );
2149  
2150              // Feedback
2151              $retval['message'] = ( true === $is_open )
2152                  ? __( '<strong>Error</strong>: There was a problem closing the topic.', 'bbpress' )
2153                  : __( '<strong>Error</strong>: There was a problem opening the topic.', 'bbpress' );
2154  
2155              break;
2156  
2157          // Toggle sticky/super-sticky/unstick
2158          case 'bbp_toggle_topic_stick' :
2159              check_ajax_referer( "stick-{$nonce_suffix}" );
2160  
2161              $is_sticky = bbp_is_topic_sticky( $r['id'] );
2162              $is_super  = false === $is_sticky && ! empty( $_GET['super'] ) && ( '1' === $_GET['super'] ) ? true : false;
2163  
2164              // Toggle
2165              $retval['status'] = ( true === $is_sticky )
2166                  ? bbp_unstick_topic( $r['id'] )
2167                  : bbp_stick_topic( $r['id'], $is_super );
2168  
2169              // Feedback
2170              $retval['message'] = ( true === $is_sticky )
2171                  ? __( '<strong>Error</strong>: There was a problem unsticking the topic.', 'bbpress' )
2172                  : __( '<strong>Error</strong>: There was a problem sticking the topic.',   'bbpress' );
2173  
2174              break;
2175  
2176          // Toggle spam
2177          case 'bbp_toggle_topic_spam' :
2178              check_ajax_referer( "spam-{$nonce_suffix}" );
2179  
2180              $is_spam            = bbp_is_topic_spam( $r['id'] );
2181              $retval['view_all'] = ! $is_spam;
2182  
2183              // Toggle
2184              $retval['status'] = ( true === $is_spam )
2185                  ? bbp_unspam_topic( $r['id'] )
2186                  : bbp_spam_topic( $r['id'] );
2187  
2188              // Feedback
2189              $retval['message'] = ( true === $is_spam )
2190                  ? __( '<strong>Error</strong>: There was a problem unmarking the topic as spam.', 'bbpress' )
2191                  : __( '<strong>Error</strong>: There was a problem marking the topic as spam.',   'bbpress' );
2192  
2193              break;
2194  
2195          // Toggle trash
2196          case 'bbp_toggle_topic_trash' :
2197  
2198              switch ( $r['sub_action'] ) {
2199                  case 'trash':
2200                      check_ajax_referer( "trash-{$nonce_suffix}" );
2201  
2202                      $retval['view_all']    = true;
2203                      $retval['status']      = wp_trash_post( $r['id'] );
2204                      $retval['message']     = __( '<strong>Error</strong>: There was a problem trashing the topic.', 'bbpress' );
2205                      $retval['redirect_to'] = current_user_can( 'view_trash' )
2206                          ? bbp_get_topic_permalink( $r['id'] )
2207                          : bbp_get_forum_permalink( bbp_get_topic_forum_id( $r['id'] ) );
2208  
2209                      break;
2210  
2211                  case 'untrash':
2212                      check_ajax_referer( "untrash-{$nonce_suffix}" );
2213  
2214                      $retval['status']      = wp_untrash_post( $r['id'] );
2215                      $retval['message']     = __( '<strong>Error</strong>: There was a problem untrashing the topic.', 'bbpress' );
2216                      $retval['redirect_to'] = bbp_get_topic_permalink( $r['id'] );
2217  
2218                      break;
2219  
2220                  case 'delete':
2221                      check_ajax_referer( "delete-{$nonce_suffix}" );
2222  
2223                      $retval['status']      = wp_delete_post( $r['id'] );
2224                      $retval['message']     = __( '<strong>Error</strong>: There was a problem deleting the topic.', 'bbpress' );
2225                      $retval['redirect_to'] = bbp_get_forum_permalink( $retval['status']->post_parent );
2226  
2227                      break;
2228              }
2229  
2230              break;
2231      }
2232  
2233      // Add view all if needed
2234      if ( ! empty( $retval['view_all'] ) ) {
2235          $retval['redirect_to'] = bbp_add_view_all( $retval['redirect_to'], true );
2236      }
2237  
2238      // Filter & return
2239      return apply_filters( 'bbp_toggle_topic', $retval, $r, $args );
2240  }
2241  
2242  /** Favorites & Subscriptions *************************************************/
2243  
2244  /**
2245   * Remove a deleted topic from all user favorites
2246   *
2247   * @since 2.0.0 bbPress (r2652)
2248   *
2249   * @param int $topic_id Get the topic id to remove
2250   */
2251  function bbp_remove_topic_from_all_favorites( $topic_id = 0 ) {
2252      $topic_id = bbp_get_topic_id( $topic_id );
2253  
2254      // Bail if no topic
2255      if ( empty( $topic_id ) ) {
2256          return;
2257      }
2258  
2259      // Get users
2260      $users = (array) bbp_get_topic_favoriters( $topic_id );
2261  
2262      // Users exist
2263      if ( ! empty( $users ) ) {
2264  
2265          // Loop through users
2266          foreach ( $users as $user ) {
2267  
2268              // Remove each user
2269              bbp_remove_user_favorite( $user, $topic_id );
2270          }
2271      }
2272  }
2273  
2274  /**
2275   * Remove a deleted topic from all user subscriptions
2276   *
2277   * @since 2.0.0 bbPress (r2652)
2278   *
2279   * @param int $topic_id Get the topic id to remove
2280   */
2281  function bbp_remove_topic_from_all_subscriptions( $topic_id = 0 ) {
2282  
2283      // Subscriptions are not active
2284      if ( ! bbp_is_subscriptions_active() ) {
2285          return;
2286      }
2287  
2288      // Bail if no topic
2289      $topic_id = bbp_get_topic_id( $topic_id );
2290      if ( empty( $topic_id ) ) {
2291          return;
2292      }
2293  
2294      // Remove all users
2295      return bbp_remove_object_from_all_users( $topic_id, '_bbp_subscription', 'post' );
2296  }
2297  
2298  /** Count Bumpers *************************************************************/
2299  
2300  /**
2301   * Bump the total reply count of a topic
2302   *
2303   * @since 2.1.0 bbPress (r3825)
2304   *
2305   * @param int $topic_id   Optional. Topic id.
2306   * @param int $difference Optional. Default 1
2307   * @return int Topic reply count
2308   */
2309  function bbp_bump_topic_reply_count( $topic_id = 0, $difference = 1 ) {
2310  
2311      // Bail if no bump
2312      if ( empty( $difference ) ) {
2313          return false;
2314      }
2315  
2316      // Get counts
2317      $topic_id    = bbp_get_topic_id( $topic_id );
2318      $reply_count = bbp_get_topic_reply_count( $topic_id, true );
2319      $difference  = (int) $difference;
2320      $new_count   = (int) ( $reply_count + $difference );
2321  
2322      // Update this topic id's reply count
2323      update_post_meta( $topic_id, '_bbp_reply_count', $new_count );
2324  
2325      // Filter & return
2326      return (int) apply_filters( 'bbp_bump_topic_reply_count', $new_count, $topic_id, $difference );
2327  }
2328  
2329  /**
2330   * Increase the total reply count of a topic by one.
2331   *
2332   * @since 2.6.0 bbPress (r6036)
2333   *
2334   * @param int $topic_id The topic id.
2335   *
2336   * @return void
2337   */
2338  function bbp_increase_topic_reply_count( $topic_id = 0 ) {
2339  
2340      // Bail early if no id is passed.
2341      if ( empty( $topic_id ) ) {
2342          return;
2343      }
2344  
2345      // If it's a reply, get the topic id.
2346      if ( bbp_is_reply( $topic_id ) ) {
2347          $reply_id = $topic_id;
2348          $topic_id = bbp_get_reply_topic_id( $reply_id );
2349  
2350          // Update inverse based on item status
2351          if ( ! bbp_is_reply_public( $reply_id ) ) {
2352              bbp_increase_topic_reply_count_hidden( $topic_id );
2353              return;
2354          }
2355      }
2356  
2357      // Bump up
2358      bbp_bump_topic_reply_count( $topic_id );
2359  }
2360  
2361  /**
2362   * Decrease the total reply count of a topic by one.
2363   *
2364   * @since 2.6.0 bbPress (r6036)
2365   *
2366   * @param int $topic_id The topic id.
2367   *
2368   * @return void
2369   */
2370  function bbp_decrease_topic_reply_count( $topic_id = 0 ) {
2371  
2372      // Bail early if no id is passed.
2373      if ( empty( $topic_id ) ) {
2374          return;
2375      }
2376  
2377      // If it's a reply, get the topic id.
2378      if ( bbp_is_reply( $topic_id ) ) {
2379          $reply_id = $topic_id;
2380          $topic_id = bbp_get_reply_topic_id( $reply_id );
2381  
2382          // Update inverse based on item status
2383          if ( ! bbp_is_reply_public( $reply_id ) ) {
2384              bbp_decrease_topic_reply_count_hidden( $topic_id );
2385              return;
2386          }
2387      }
2388  
2389      // Bump down
2390      bbp_bump_topic_reply_count( $topic_id, -1 );
2391  }
2392  
2393  /**
2394   * Bump the total hidden reply count of a topic
2395   *
2396   * @since 2.1.0 bbPress (r3825)
2397   *
2398   * @param int $topic_id   Optional. Topic id.
2399   * @param int $difference Optional. Default 1
2400   * @return int Topic hidden reply count
2401   */
2402  function bbp_bump_topic_reply_count_hidden( $topic_id = 0, $difference = 1 ) {
2403  
2404      // Bail if no bump
2405      if ( empty( $difference ) ) {
2406          return false;
2407      }
2408  
2409      // Get counts
2410      $topic_id    = bbp_get_topic_id( $topic_id );
2411      $reply_count = bbp_get_topic_reply_count_hidden( $topic_id, true );
2412      $difference  = (int) $difference;
2413      $new_count   = (int) ( $reply_count + $difference );
2414  
2415      // Update this topic id's hidden reply count
2416      update_post_meta( $topic_id, '_bbp_reply_count_hidden', $new_count );
2417  
2418      // Filter & return
2419      return (int) apply_filters( 'bbp_bump_topic_reply_count_hidden', $new_count, $topic_id, $difference );
2420  }
2421  
2422  /**
2423   * Increase the total hidden reply count of a topic by one.
2424   *
2425   * @since 2.6.0 bbPress (r6036)
2426   *
2427   * @param int $topic_id The topic id.
2428   *
2429   * @return void
2430   */
2431  function bbp_increase_topic_reply_count_hidden( $topic_id = 0 ) {
2432  
2433      // Bail early if no id is passed.
2434      if ( empty( $topic_id ) ) {
2435          return;
2436      }
2437  
2438      // If it's a reply, get the topic id.
2439      if ( bbp_is_reply( $topic_id ) ) {
2440          $reply_id = $topic_id;
2441          $topic_id = bbp_get_reply_topic_id( $reply_id );
2442  
2443          // Update inverse based on item status
2444          if ( bbp_is_reply_public( $reply_id ) ) {
2445              bbp_increase_topic_reply_count( $topic_id );
2446              return;
2447          }
2448      }
2449  
2450      // Bump up
2451      bbp_bump_topic_reply_count_hidden( $topic_id );
2452  }
2453  
2454  /**
2455   * Decrease the total hidden reply count of a topic by one.
2456   *
2457   * @since 2.6.0 bbPress (r6036)
2458   *
2459   * @param int $topic_id The topic id.
2460   *
2461   * @return void
2462   */
2463  function bbp_decrease_topic_reply_count_hidden( $topic_id = 0 ) {
2464  
2465      // Bail early if no id is passed.
2466      if ( empty( $topic_id ) ) {
2467          return;
2468      }
2469  
2470      // If it's a reply, get the topic id.
2471      if ( bbp_is_reply( $topic_id ) ) {
2472          $reply_id = $topic_id;
2473          $topic_id = bbp_get_reply_topic_id( $reply_id );
2474  
2475          // Update inverse based on item status
2476          if ( bbp_is_reply_public( $reply_id ) ) {
2477              bbp_decrease_topic_reply_count( $topic_id );
2478              return;
2479          }
2480      }
2481  
2482      // Bump down
2483      bbp_bump_topic_reply_count_hidden( $topic_id, -1 );
2484  }
2485  
2486  /**
2487   * Update counts after a topic is inserted via `bbp_insert_topic`.
2488   *
2489   * @since 2.6.0 bbPress (r6036)
2490   *
2491   * @param int $topic_id The topic id.
2492   * @param int $forum_id The forum id.
2493   *
2494   * @return void
2495   */
2496  function bbp_insert_topic_update_counts( $topic_id = 0, $forum_id = 0 ) {
2497  
2498      // If the topic is public, update the forum topic counts.
2499      if ( bbp_is_topic_public( $topic_id ) ) {
2500          bbp_increase_forum_topic_count( $forum_id );
2501  
2502      // If the topic isn't public only update the forum topic hidden count.
2503      } else {
2504          bbp_increase_forum_topic_count_hidden( $forum_id );
2505      }
2506  }
2507  
2508  /** Topic Updaters ************************************************************/
2509  
2510  /**
2511   * Update the topic's forum id
2512   *
2513   * @since 2.0.0 bbPress (r2855)
2514   *
2515   * @param int $topic_id Optional. Topic id to update
2516   * @param int $forum_id Optional. Forum id
2517   * @return int Forum id
2518   */
2519  function bbp_update_topic_forum_id( $topic_id = 0, $forum_id = 0 ) {
2520  
2521      // If it's a reply, then get the parent (topic id)
2522      $topic_id = bbp_is_reply( $topic_id )
2523          ? bbp_get_reply_topic_id( $topic_id )
2524          : bbp_get_topic_id( $topic_id );
2525  
2526      // Forum ID fallback
2527      if ( empty( $forum_id ) ) {
2528          $forum_id = get_post_field( 'post_parent', $topic_id );
2529      }
2530  
2531      // Update the forum ID
2532      $forum_id = bbp_update_forum_id( $topic_id, $forum_id );
2533  
2534      // Filter & return
2535      return (int) apply_filters( 'bbp_update_topic_forum_id', $forum_id, $topic_id );
2536  }
2537  
2538  /**
2539   * Update the topic's topic id
2540   *
2541   * @since 2.0.0 bbPress (r2954)
2542   *
2543   * @param int $topic_id Optional. Topic id to update
2544   * @return int Topic id
2545   */
2546  function bbp_update_topic_topic_id( $topic_id = 0 ) {
2547      $topic_id = bbp_get_topic_id( $topic_id );
2548      $topic_id = bbp_update_topic_id( $topic_id, $topic_id );
2549  
2550      // Filter & return
2551      return (int) apply_filters( 'bbp_update_topic_topic_id', $topic_id );
2552  }
2553  
2554  /**
2555   * Adjust the total reply count of a topic
2556   *
2557   * @since 2.0.0 bbPress (r2467)
2558   *
2559   * @param int $topic_id Optional. Topic id to update
2560   * @param int $reply_count Optional. Set the reply count manually.
2561   * @return int Topic reply count
2562   */
2563  function bbp_update_topic_reply_count( $topic_id = 0, $reply_count = false ) {
2564  
2565      // If it's a reply, then get the parent (topic id)
2566      $topic_id = bbp_is_reply( $topic_id )
2567          ? bbp_get_reply_topic_id( $topic_id )
2568          : bbp_get_topic_id( $topic_id );
2569  
2570      // Get replies of topic if not passed
2571      $reply_count = ! is_int( $reply_count )
2572          ? bbp_get_public_child_count( $topic_id, bbp_get_reply_post_type() )
2573          : (int) $reply_count;
2574  
2575      update_post_meta( $topic_id, '_bbp_reply_count', $reply_count );
2576  
2577      // Filter & return
2578      return (int) apply_filters( 'bbp_update_topic_reply_count', $reply_count, $topic_id );
2579  }
2580  
2581  /**
2582   * Adjust the total hidden reply count of a topic (hidden includes trashed,
2583   * spammed and pending replies)
2584   *
2585   * @since 2.0.0 bbPress (r2740)
2586   *
2587   * @param int $topic_id Optional. Topic id to update
2588   * @param int $reply_count Optional. Set the reply count manually
2589   * @return int Topic hidden reply count
2590   */
2591  function bbp_update_topic_reply_count_hidden( $topic_id = 0, $reply_count = false ) {
2592  
2593      // If it's a reply, then get the parent (topic id)
2594      $topic_id = bbp_is_reply( $topic_id )
2595          ? bbp_get_reply_topic_id( $topic_id )
2596          : bbp_get_topic_id( $topic_id );
2597  
2598      // Get replies of topic
2599      $reply_count = ! is_int( $reply_count )
2600          ? bbp_get_non_public_child_count( $topic_id, bbp_get_reply_post_type() )
2601          : (int) $reply_count;
2602  
2603      update_post_meta( $topic_id, '_bbp_reply_count_hidden', $reply_count );
2604  
2605      // Filter & return
2606      return (int) apply_filters( 'bbp_update_topic_reply_count_hidden', $reply_count, $topic_id );
2607  }
2608  
2609  /**
2610   * Update the topic with the last active post ID
2611   *
2612   * @since 2.0.0 bbPress (r2888)
2613   *
2614   * @param int $topic_id Optional. Topic id to update
2615   * @param int $active_id Optional. active id
2616   * @return int Active id
2617   */
2618  function bbp_update_topic_last_active_id( $topic_id = 0, $active_id = 0 ) {
2619  
2620      // If it's a reply, then get the parent (topic id)
2621      $topic_id = bbp_is_reply( $topic_id )
2622          ? bbp_get_reply_topic_id( $topic_id )
2623          : bbp_get_topic_id( $topic_id );
2624  
2625      // Get last public active id if not passed
2626      if ( empty( $active_id ) ) {
2627          $active_id = bbp_get_public_child_last_id( $topic_id, bbp_get_reply_post_type() );
2628      }
2629  
2630      // Adjust last_id's based on last_reply post_type
2631      if ( empty( $active_id ) || ! bbp_is_reply( $active_id ) ) {
2632          $active_id = $topic_id;
2633      }
2634  
2635      $active_id = (int) $active_id;
2636  
2637      // Update only if published
2638      update_post_meta( $topic_id, '_bbp_last_active_id', $active_id );
2639  
2640      // Filter & return
2641      return (int) apply_filters( 'bbp_update_topic_last_active_id', $active_id, $topic_id );
2642  }
2643  
2644  /**
2645   * Update the topics last active date/time (aka freshness)
2646   *
2647   * @since 2.0.0 bbPress (r2680)
2648   *
2649   * @param int    $topic_id Optional. Topic id.
2650   * @param string $new_time Optional. New time in mysql format.
2651   * @return string MySQL timestamp of last active reply
2652   */
2653  function bbp_update_topic_last_active_time( $topic_id = 0, $new_time = '' ) {
2654  
2655      // If it's a reply, then get the parent (topic id)
2656      $topic_id = bbp_is_reply( $topic_id )
2657          ? bbp_get_reply_topic_id( $topic_id )
2658          : bbp_get_topic_id( $topic_id );
2659  
2660      // Check time and use current if empty
2661      if ( empty( $new_time ) ) {
2662          $new_time = get_post_field( 'post_date', bbp_get_public_child_last_id( $topic_id, bbp_get_reply_post_type() ) );
2663      }
2664  
2665      // Update only if published
2666      if ( ! empty( $new_time ) ) {
2667          update_post_meta( $topic_id, '_bbp_last_active_time', $new_time );
2668      }
2669  
2670      // Filter & return
2671      return apply_filters( 'bbp_update_topic_last_active_time', $new_time, $topic_id );
2672  }
2673  
2674  /**
2675   * Update the topic with the most recent reply ID
2676   *
2677   * @since 2.0.0 bbPress (r2625)
2678   *
2679   * @param int $topic_id Optional. Topic id to update
2680   * @param int $reply_id Optional. Reply id
2681   * @return int Reply id
2682   */
2683  function bbp_update_topic_last_reply_id( $topic_id = 0, $reply_id = 0 ) {
2684  
2685      // If it's a reply, then get the parent (topic id)
2686      if ( empty( $reply_id ) && bbp_is_reply( $topic_id ) ) {
2687          $reply_id = bbp_get_reply_id( $topic_id );
2688          $topic_id = bbp_get_reply_topic_id( $reply_id );
2689      } else {
2690          $reply_id = bbp_get_reply_id( $reply_id );
2691          $topic_id = bbp_get_topic_id( $topic_id );
2692      }
2693  
2694      if ( empty( $reply_id ) ) {
2695          $reply_id = bbp_get_public_child_last_id( $topic_id, bbp_get_reply_post_type() );
2696      }
2697  
2698      // Adjust last_id's based on last_reply post_type
2699      if ( empty( $reply_id ) || ! bbp_is_reply( $reply_id ) ) {
2700          $reply_id = 0;
2701      }
2702  
2703      $reply_id = (int) $reply_id;
2704  
2705      // Update if reply is published
2706      update_post_meta( $topic_id, '_bbp_last_reply_id', $reply_id );
2707  
2708      // Filter & return
2709      return (int) apply_filters( 'bbp_update_topic_last_reply_id', $reply_id, $topic_id );
2710  }
2711  
2712  /**
2713   * Adjust the total voice count of a topic
2714   *
2715   * @since 2.0.0 bbPress (r2567)
2716   * @since 2.6.0 bbPress (r6515) This must be called after any engagement changes
2717   *
2718   * @param int $topic_id Optional. Topic id to update
2719   * @return int Voice count
2720   */
2721  function bbp_update_topic_voice_count( $topic_id = 0 ) {
2722  
2723      // If it's a reply, then get the parent (topic id)
2724      $topic_id = bbp_is_reply( $topic_id )
2725          ? bbp_get_reply_topic_id( $topic_id )
2726          : bbp_get_topic_id( $topic_id );
2727  
2728      // Bail if no topic ID
2729      if ( empty( $topic_id ) ) {
2730          return;
2731      }
2732  
2733      // Count the engagements
2734      $count = count( bbp_get_topic_engagements( $topic_id ) );
2735  
2736      // Update the voice count for this topic id
2737      update_post_meta( $topic_id, '_bbp_voice_count', $count );
2738  
2739      // Filter & return
2740      return (int) apply_filters( 'bbp_update_topic_voice_count', $count, $topic_id );
2741  }
2742  
2743  /**
2744   * Adjust the total anonymous reply count of a topic
2745   *
2746   * @since 2.0.0 bbPress (r2567)
2747   *
2748   * @param int $topic_id Optional. Topic id to update
2749   * @return int Anonymous reply count
2750   */
2751  function bbp_update_topic_anonymous_reply_count( $topic_id = 0 ) {
2752  
2753      // If it's a reply, then get the parent (topic id)
2754      $topic_id = bbp_is_reply( $topic_id )
2755          ? bbp_get_reply_topic_id( $topic_id )
2756          : bbp_get_topic_id( $topic_id );
2757  
2758      // Query the DB to get anonymous replies in this topic
2759      $bbp_db  = bbp_db();
2760      $query   = $bbp_db->prepare( "SELECT COUNT( ID ) FROM {$bbp_db->posts} WHERE ( post_parent = %d AND post_status = %s AND post_type = %s AND post_author = 0 ) OR ( ID = %d AND post_type = %s AND post_author = 0 )", $topic_id, bbp_get_public_status_id(), bbp_get_reply_post_type(), $topic_id, bbp_get_topic_post_type() );
2761      $replies = (int) $bbp_db->get_var( $query );
2762  
2763      update_post_meta( $topic_id, '_bbp_anonymous_reply_count', $replies );
2764  
2765      // Filter & return
2766      return (int) apply_filters( 'bbp_update_topic_anonymous_reply_count', $replies, $topic_id );
2767  }
2768  
2769  /**
2770   * Update the revision log of the topic
2771   *
2772   * @since 2.0.0 bbPress (r2782)
2773   *
2774   * @param array $args Supports these args:
2775   *  - topic_id: Topic id
2776   *  - author_id: Author id
2777   *  - reason: Reason for editing
2778   *  - revision_id: Revision id
2779   * @return mixed False on failure, true on success
2780   */
2781  function bbp_update_topic_revision_log( $args = array() ) {
2782  
2783      // Parse arguments against default values
2784      $r = bbp_parse_args( $args, array(
2785          'reason'      => '',
2786          'topic_id'    => 0,
2787          'author_id'   => 0,
2788          'revision_id' => 0
2789      ), 'update_topic_revision_log' );
2790  
2791      // Populate the variables
2792      $r['reason']      = bbp_format_revision_reason( $r['reason'] );
2793      $r['topic_id']    = bbp_get_topic_id( $r['topic_id'] );
2794      $r['author_id']   = bbp_get_user_id ( $r['author_id'], false, true );
2795      $r['revision_id'] = (int) $r['revision_id'];
2796  
2797      // Get the logs and append the new one to those
2798      $revision_log                      = bbp_get_topic_raw_revision_log( $r['topic_id'] );
2799      $revision_log[ $r['revision_id'] ] = array( 'author' => $r['author_id'], 'reason' => $r['reason'] );
2800  
2801      // Finally, update
2802      return update_post_meta( $r['topic_id'], '_bbp_revision_log', $revision_log );
2803  }
2804  
2805  /** Topic Actions *************************************************************/
2806  
2807  /**
2808   * Closes a topic
2809   *
2810   * @since 2.0.0 bbPress (r2740)
2811   *
2812   * @param int $topic_id Topic id
2813   * @return mixed False or {@link WP_Error} on failure, topic id on success
2814   */
2815  function bbp_close_topic( $topic_id = 0 ) {
2816  
2817      // Get topic
2818      $topic = bbp_get_topic( $topic_id );
2819      if ( empty( $topic ) ) {
2820          return $topic;
2821      }
2822  
2823      // Get previous topic status meta
2824      $status       = bbp_get_closed_status_id();
2825      $topic_status = get_post_meta( $topic_id, '_bbp_status', true );
2826  
2827      // Bail if already closed and topic status meta exists
2828      if ( $status === $topic->post_status && ! empty( $topic_status ) ) {
2829          return false;
2830      }
2831  
2832      // Set status meta public
2833      $topic_status = $topic->post_status;
2834  
2835      // Execute pre close code
2836      do_action( 'bbp_close_topic', $topic_id );
2837  
2838      // Add pre close status
2839      add_post_meta( $topic_id, '_bbp_status', $topic_status );
2840  
2841      // Set closed status
2842      $topic->post_status = $status;
2843  
2844      // Toggle revisions off as we are not altering content
2845      if ( post_type_supports( bbp_get_topic_post_type(), 'revisions' ) ) {
2846          $revisions_removed = true;
2847          remove_post_type_support( bbp_get_topic_post_type(), 'revisions' );
2848      }
2849  
2850      // Update topic
2851      $topic_id = wp_update_post( $topic );
2852  
2853      // Toggle revisions back on
2854      if ( true === $revisions_removed ) {
2855          $revisions_removed = false;
2856          add_post_type_support( bbp_get_topic_post_type(), 'revisions' );
2857      }
2858  
2859      // Execute post close code
2860      do_action( 'bbp_closed_topic', $topic_id );
2861  
2862      // Return topic_id
2863      return $topic_id;
2864  }
2865  
2866  /**
2867   * Opens a topic
2868   *
2869   * @since 2.0.0 bbPress (r2740)
2870   *
2871   * @param int $topic_id Topic id
2872   * @return mixed False or {@link WP_Error} on failure, topic id on success
2873   */
2874  function bbp_open_topic( $topic_id = 0 ) {
2875  
2876      // Get topic
2877      $topic = bbp_get_topic( $topic_id );
2878      if ( empty( $topic ) ) {
2879          return $topic;
2880      }
2881  
2882      // Bail if not closed
2883      if ( bbp_get_closed_status_id() !== $topic->post_status ) {
2884          return false;
2885      }
2886  
2887      // Execute pre open code
2888      do_action( 'bbp_open_topic', $topic_id );
2889  
2890      // Get previous status
2891      $topic_status = get_post_meta( $topic_id, '_bbp_status', true );
2892  
2893      // If no previous status, default to publish
2894      if ( empty( $topic_status ) ) {
2895          $topic_status = bbp_get_public_status_id();
2896      }
2897  
2898      // Set previous status
2899      $topic->post_status = $topic_status;
2900  
2901      // Remove old status meta
2902      delete_post_meta( $topic_id, '_bbp_status' );
2903  
2904      // Toggle revisions off as we are not altering content
2905      if ( post_type_supports( bbp_get_topic_post_type(), 'revisions' ) ) {
2906          $revisions_removed = true;
2907          remove_post_type_support( bbp_get_topic_post_type(), 'revisions' );
2908      }
2909  
2910      // Update topic
2911      $topic_id = wp_update_post( $topic );
2912  
2913      // Toggle revisions back on
2914      if ( true === $revisions_removed ) {
2915          $revisions_removed = false;
2916          add_post_type_support( bbp_get_topic_post_type(), 'revisions' );
2917      }
2918  
2919      // Execute post open code
2920      do_action( 'bbp_opened_topic', $topic_id );
2921  
2922      // Return topic_id
2923      return $topic_id;
2924  }
2925  
2926  /**
2927   * Marks a topic as spam
2928   *
2929   * @since 2.0.0 bbPress (r2740)
2930   *
2931   * @param int $topic_id Topic id
2932   * @return mixed False or {@link WP_Error} on failure, topic id on success
2933   */
2934  function bbp_spam_topic( $topic_id = 0 ) {
2935  
2936      // Get the topic
2937      $topic = bbp_get_topic( $topic_id );
2938      if ( empty( $topic ) ) {
2939          return $topic;
2940      }
2941  
2942      // Get new status
2943      $status = bbp_get_spam_status_id();
2944  
2945      // Bail if topic is spam
2946      if ( $status === $topic->post_status ) {
2947          return false;
2948      }
2949  
2950      // Add the original post status as post meta for future restoration
2951      add_post_meta( $topic_id, '_bbp_spam_meta_status', $topic->post_status );
2952  
2953      // Execute pre spam code
2954      do_action( 'bbp_spam_topic', $topic_id );
2955  
2956      // Set post status to spam
2957      $topic->post_status = $status;
2958  
2959      // Empty the topic of its tags
2960      $topic->tax_input = bbp_spam_topic_tags( $topic_id );
2961  
2962      // No revisions
2963      remove_action( 'pre_post_update', 'wp_save_post_revision' );
2964  
2965      // Update the topic
2966      $topic_id = wp_update_post( $topic );
2967  
2968      // Execute post spam code
2969      do_action( 'bbp_spammed_topic', $topic_id );
2970  
2971      // Return topic_id
2972      return $topic_id;
2973  }
2974  
2975  /**
2976   * Trash replies to a topic when it's marked as spam
2977   *
2978   * Usually you'll want to do this before the topic itself is marked as spam.
2979   *
2980   * @since 2.6.0 bbPress (r5405)
2981   *
2982   * @param int $topic_id
2983   */
2984  function bbp_spam_topic_replies( $topic_id = 0 ) {
2985  
2986      // Validation
2987      $topic_id = bbp_get_topic_id( $topic_id );
2988  
2989      // Topic is being spammed, so its replies are trashed
2990      $replies = new WP_Query( array(
2991          'fields'         => 'id=>parent',
2992          'post_type'      => bbp_get_reply_post_type(),
2993          'post_status'    => bbp_get_public_status_id(),
2994          'post_parent'    => $topic_id,
2995          'posts_per_page' => -1,
2996  
2997          // Performance
2998          'nopaging'               => true,
2999          'suppress_filters'       => true,
3000          'update_post_term_cache' => false,
3001          'update_post_meta_cache' => false,
3002          'ignore_sticky_posts'    => true,
3003          'no_found_rows'          => true
3004      ) );
3005  
3006      if ( ! empty( $replies->posts ) ) {
3007  
3008          // Prevent debug notices
3009          $pre_spammed_replies = array();
3010  
3011          // Loop through replies, trash them, and add them to array
3012          foreach ( $replies->posts as $reply ) {
3013              wp_trash_post( $reply->ID );
3014              $pre_spammed_replies[] = $reply->ID;
3015          }
3016  
3017          // Set a post_meta entry of the replies that were trashed by this action.
3018          // This is so we can possibly untrash them, without untrashing replies
3019          // that were purposefully trashed before.
3020          update_post_meta( $topic_id, '_bbp_pre_spammed_replies', $pre_spammed_replies );
3021  
3022          // Reset the global post data after looping through the above WP_Query
3023          wp_reset_postdata();
3024      }
3025  }
3026  
3027  /**
3028   * Store the tags to a topic in post meta before it's marked as spam so they
3029   * can be retrieved and unspammed later.
3030   *
3031   * Usually you'll want to do this before the topic itself is marked as spam.
3032   *
3033   * @since 2.6.0 bbPress (r5405)
3034   *
3035   * @param int $topic_id
3036   */
3037  function bbp_spam_topic_tags( $topic_id = 0 ) {
3038  
3039      // Validation
3040      $topic_id = bbp_get_topic_id( $topic_id );
3041  
3042      // Get topic tags
3043      $terms = get_the_terms( $topic_id, bbp_get_topic_tag_tax_id() );
3044  
3045      // Define local variable(s)
3046      $term_names = array();
3047  
3048      // Topic has tags
3049      if ( ! empty( $terms ) ) {
3050  
3051          // Loop through and collect term names
3052          foreach ( $terms as $term ) {
3053              $term_names[] = $term->name;
3054          }
3055  
3056          // Topic terms have slugs
3057          if ( ! empty( $term_names ) ) {
3058  
3059              // Add the original post status as post meta for future restoration
3060              add_post_meta( $topic_id, '_bbp_spam_topic_tags', $term_names );
3061          }
3062      }
3063  
3064      return array( bbp_get_topic_tag_tax_id() => '' );
3065  }
3066  
3067  /**
3068   * Unspams a topic
3069   *
3070   * @since 2.0.0 bbPress (r2740)
3071   *
3072   * @param int $topic_id Topic id
3073   * @return mixed False or {@link WP_Error} on failure, topic id on success
3074   */
3075  function bbp_unspam_topic( $topic_id = 0 ) {
3076  
3077      // Get the topic
3078      $topic = bbp_get_topic( $topic_id );
3079      if ( empty( $topic ) ) {
3080          return $topic;
3081      }
3082  
3083      // Bail if already not spam
3084      if ( bbp_get_spam_status_id() !== $topic->post_status ) {
3085          return false;
3086      }
3087  
3088      // Execute pre unspam code
3089      do_action( 'bbp_unspam_topic', $topic_id );
3090  
3091      // Get pre spam status
3092      $topic_status = get_post_meta( $topic_id, '_bbp_spam_meta_status', true );
3093  
3094      // If no previous status, default to publish
3095      if ( empty( $topic_status ) ) {
3096          $topic_status = bbp_get_public_status_id();
3097      }
3098  
3099      // Set post status to pre spam
3100      $topic->post_status = $topic_status;
3101      $topic->tax_input   = bbp_unspam_topic_tags( $topic_id );
3102  
3103      // Delete pre spam meta
3104      delete_post_meta( $topic_id, '_bbp_spam_meta_status' );
3105  
3106      // No revisions
3107      remove_action( 'pre_post_update', 'wp_save_post_revision' );
3108  
3109      // Update the topic
3110      $topic_id = wp_update_post( $topic );
3111  
3112      // Execute post unspam code
3113      do_action( 'bbp_unspammed_topic', $topic_id );
3114  
3115      // Return topic_id
3116      return $topic_id;
3117  }
3118  
3119  /**
3120   * Untrash replies to a topic previously marked as spam.
3121   *
3122   * Usually you'll want to do this after the topic is unspammed.
3123   *
3124   * @since 2.6.0 bbPress (r5405)
3125   *
3126   * @param int $topic_id
3127   */
3128  function bbp_unspam_topic_replies( $topic_id = 0 ) {
3129  
3130      // Validation
3131      $topic_id = bbp_get_topic_id( $topic_id );
3132  
3133      // Get the replies that were not previously trashed
3134      $pre_spammed_replies = get_post_meta( $topic_id, '_bbp_pre_spammed_replies', true );
3135  
3136      // There are replies to untrash
3137      if ( ! empty( $pre_spammed_replies ) ) {
3138  
3139          // Maybe reverse the trashed replies array
3140          if ( is_array( $pre_spammed_replies ) ) {
3141              $pre_spammed_replies = array_reverse( $pre_spammed_replies );
3142          }
3143  
3144          // Loop through replies
3145          foreach ( (array) $pre_spammed_replies as $reply ) {
3146              wp_untrash_post( $reply );
3147          }
3148      }
3149  
3150      // Clear the trasheed reply meta for the topic
3151      delete_post_meta( $topic_id, '_bbp_pre_spammed_replies' );
3152  }
3153  
3154  /**
3155   * Retrieve tags to a topic from post meta before it's unmarked as spam so they.
3156   *
3157   * Usually you'll want to do this before the topic itself is unmarked as spam.
3158   *
3159   * @since 2.6.0 bbPress (r5405)
3160   *
3161   * @param int $topic_id
3162   */
3163  function bbp_unspam_topic_tags( $topic_id = 0 ) {
3164  
3165      // Validation
3166      $topic_id = bbp_get_topic_id( $topic_id );
3167  
3168      // Get pre-spam topic tags
3169      $terms = get_post_meta( $topic_id, '_bbp_spam_topic_tags', true );
3170  
3171      // Delete pre-spam topic tag meta
3172      if ( ! empty( $terms ) ) {
3173          delete_post_meta( $topic_id, '_bbp_spam_topic_tags' );
3174      }
3175  
3176      return array( bbp_get_topic_tag_tax_id() => $terms );
3177  }
3178  
3179  /**
3180   * Sticks a topic to a forum or front
3181   *
3182   * @since 2.0.0 bbPress (r2754)
3183   *
3184   * @param int $topic_id Optional. Topic id
3185   * @param int $super Should we make the topic a super sticky?
3186   * @return bool True on success, false on failure
3187   */
3188  function bbp_stick_topic( $topic_id = 0, $super = false ) {
3189  
3190      // Validation
3191      $topic_id = bbp_get_topic_id( $topic_id );
3192  
3193      // Bail if a topic is not a topic (prevents revisions as stickies)
3194      if ( ! bbp_is_topic( $topic_id ) ) {
3195          return false;
3196      }
3197  
3198      do_action( 'bbp_stick_topic', $topic_id, $super );
3199  
3200      // Maybe get the forum ID if not getting supers
3201      $forum_id = empty( $super )
3202          ? bbp_get_topic_forum_id( $topic_id )
3203          : 0;
3204  
3205      // Get the stickies, maybe from the forum ID
3206      $stickies = bbp_get_stickies( $forum_id );
3207  
3208      // Add the topic to the stickies
3209      $stickies[] = $topic_id;
3210  
3211      // Pull out duplicates and empties
3212      $stickies = array_unique( array_filter( $stickies ) );
3213  
3214      // Unset incorrectly stuck revisions
3215      foreach ( (array) $stickies as $key => $id ) {
3216          if ( ! bbp_is_topic( $id ) ) {
3217              unset( $stickies[ $key ] );
3218          }
3219      }
3220  
3221      // Reset keys
3222      $stickies = array_values( $stickies );
3223  
3224      // Update
3225      $success  = ! empty( $super )
3226          ? update_option( '_bbp_super_sticky_topics', $stickies )
3227          : update_post_meta( $forum_id, '_bbp_sticky_topics', $stickies );
3228  
3229      do_action( 'bbp_stuck_topic', $topic_id, $super, $success );
3230  
3231      return (bool) $success;
3232  }
3233  
3234  /**
3235   * Approves a pending topic
3236   *
3237   * @since 2.6.0 bbPress (r5503)
3238   *
3239   * @param int $topic_id Topic id
3240   * @return mixed False or {@link WP_Error} on failure, topic id on success
3241   */
3242  function bbp_approve_topic( $topic_id = 0 ) {
3243  
3244      // Get topic
3245      $topic = bbp_get_topic( $topic_id );
3246      if ( empty( $topic ) ) {
3247          return $topic;
3248      }
3249  
3250      // Get new status
3251      $status = bbp_get_public_status_id();
3252  
3253      // Bail if already approved
3254      if ( $status === $topic->post_status ) {
3255          return false;
3256      }
3257  
3258      // Execute pre pending code
3259      do_action( 'bbp_approve_topic', $topic_id );
3260  
3261      // Set publish status
3262      $topic->post_status = $status;
3263  
3264      // Set post date GMT - prevents post_date override in wp_update_post()
3265      $topic->post_date_gmt = get_gmt_from_date( $topic->post_date );
3266  
3267      // No revisions
3268      remove_action( 'pre_post_update', 'wp_save_post_revision' );
3269  
3270      // Update topic
3271      $topic_id = wp_update_post( $topic );
3272  
3273      // Execute post pending code
3274      do_action( 'bbp_approved_topic', $topic_id );
3275  
3276      // Return topic_id
3277      return $topic_id;
3278  }
3279  
3280  /**
3281   * Unapproves a topic
3282   *
3283   * @since 2.6.0 bbPress (r5503)
3284   *
3285   * @param int $topic_id Topic id
3286   * @return mixed False or {@link WP_Error} on failure, topic id on success
3287   */
3288  function bbp_unapprove_topic( $topic_id = 0 ) {
3289  
3290      // Get topic
3291      $topic = bbp_get_topic( $topic_id );
3292      if ( empty( $topic ) ) {
3293          return $topic;
3294      }
3295  
3296      // Get new status
3297      $status = bbp_get_pending_status_id();
3298  
3299      // Bail if already unapproved
3300      if ( ! bbp_is_topic_public( $topic_id ) ) {
3301          return false;
3302      }
3303  
3304      // Execute pre open code
3305      do_action( 'bbp_unapprove_topic', $topic_id );
3306  
3307      // Set pending status
3308      $topic->post_status = $status;
3309  
3310      // No revisions
3311      remove_action( 'pre_post_update', 'wp_save_post_revision' );
3312  
3313      // Update topic
3314      $topic_id = wp_update_post( $topic );
3315  
3316      // Execute post open code
3317      do_action( 'bbp_unapproved_topic', $topic_id );
3318  
3319      // Return topic_id
3320      return $topic_id;
3321  }
3322  
3323  /**
3324   * Unsticks a topic both from front and it's forum
3325   *
3326   * @since 2.0.0 bbPress (r2754)
3327   *
3328   * @param int $topic_id Optional. Topic id
3329   * @return bool Always true.
3330   */
3331  function bbp_unstick_topic( $topic_id = 0 ) {
3332  
3333      // Get topic sticky status
3334      $topic_id = bbp_get_topic_id( $topic_id );
3335      $super    = bbp_is_topic_super_sticky( $topic_id );
3336      $forum_id = empty( $super ) ? bbp_get_topic_forum_id( $topic_id ) : 0;
3337      $stickies = bbp_get_stickies( $forum_id );
3338      $offset   = array_search( $topic_id, $stickies );
3339  
3340      do_action( 'bbp_unstick_topic', $topic_id );
3341  
3342      // Nothing to unstick
3343      if ( empty( $stickies ) ) {
3344          $success = true;
3345  
3346      // Topic not in stickies
3347      } elseif ( ! in_array( $topic_id, $stickies, true ) ) {
3348          $success = true;
3349  
3350      // Topic not in stickies
3351      } elseif ( false === $offset ) {
3352          $success = true;
3353  
3354      // Splice out the offset
3355      } else {
3356          array_splice( $stickies, $offset, 1 );
3357  
3358          if ( empty( $stickies ) ) {
3359              $success = ! empty( $super )
3360                  ? delete_option( '_bbp_super_sticky_topics' )
3361                  : delete_post_meta( $forum_id, '_bbp_sticky_topics' );
3362          } else {
3363              $success = ! empty( $super )
3364                  ? update_option( '_bbp_super_sticky_topics', $stickies )
3365                  : update_post_meta( $forum_id, '_bbp_sticky_topics', $stickies );
3366          }
3367      }
3368  
3369      do_action( 'bbp_unstuck_topic', $topic_id, $success );
3370  
3371      return (bool) $success;
3372  }
3373  
3374  /** Before Delete/Trash/Untrash ***********************************************/
3375  
3376  /**
3377   * Called before deleting a topic.
3378   *
3379   * This function is supplemental to the actual topic deletion which is
3380   * handled by WordPress core API functions. It is used to clean up after
3381   * a topic that is being deleted.
3382   */
3383  function bbp_delete_topic( $topic_id = 0 ) {
3384  
3385      // Validate topic ID
3386      $topic_id = bbp_get_topic_id( $topic_id );
3387  
3388      if ( empty( $topic_id ) || ! bbp_is_topic( $topic_id ) ) {
3389          return false;
3390      }
3391  
3392      do_action( 'bbp_delete_topic', $topic_id );
3393  }
3394  
3395  /**
3396   * Delete replies to a topic when it's deleted
3397   *
3398   * Usually you'll want to do this before the topic itself is deleted.
3399   *
3400   * @since 2.6.0 bbPress (r5405)
3401   *
3402   * @param int $topic_id
3403   */
3404  function bbp_delete_topic_replies( $topic_id = 0 ) {
3405  
3406      // Validate topic ID
3407      $topic_id = bbp_get_topic_id( $topic_id );
3408  
3409      // Topic is being permanently deleted, so its replies gotta go too
3410      // Note that we get all post statuses here
3411      $replies = new WP_Query( array(
3412          'fields'         => 'id=>parent',
3413          'post_type'      => bbp_get_reply_post_type(),
3414          'post_status'    => array_keys( get_post_stati() ),
3415          'post_parent'    => $topic_id,
3416          'posts_per_page' => -1,
3417  
3418          // Performance
3419          'nopaging'               => true,
3420          'suppress_filters'       => true,
3421          'update_post_term_cache' => false,
3422          'update_post_meta_cache' => false,
3423          'ignore_sticky_posts'    => true,
3424          'no_found_rows'          => true
3425      ) );
3426  
3427      // Loop through and delete child replies
3428      if ( ! empty( $replies->posts ) ) {
3429          foreach ( $replies->posts as $reply ) {
3430              wp_delete_post( $reply->ID, true );
3431          }
3432  
3433          // Reset the $post global
3434          wp_reset_postdata();
3435      }
3436  }
3437  
3438  /**
3439   * Called before trashing a topic
3440   *
3441   * This function is supplemental to the actual topic being trashed which is
3442   * handled by WordPress core API functions. It is used to clean up after
3443   * a topic that is being trashed.
3444   */
3445  function bbp_trash_topic( $topic_id = 0 ) {
3446  
3447      // Validate topic ID
3448      $topic_id = bbp_get_topic_id( $topic_id );
3449  
3450      if ( empty( $topic_id ) || ! bbp_is_topic( $topic_id ) ) {
3451          return false;
3452      }
3453  
3454      do_action( 'bbp_trash_topic', $topic_id );
3455  }
3456  
3457  /**
3458   * Trash replies to a topic when it's trashed.
3459   *
3460   * Usually you'll want to do this before the topic itself is marked as spam.
3461   *
3462   * @since 2.6.0 bbPress (r5405)
3463   *
3464   * @param int $topic_id
3465   */
3466  function bbp_trash_topic_replies( $topic_id = 0 ) {
3467  
3468      // Validate topic ID
3469      $topic_id = bbp_get_topic_id( $topic_id );
3470  
3471      // Topic is being trashed, so its replies are trashed too
3472      $replies = new WP_Query( array(
3473          'fields'         => 'id=>parent',
3474          'post_type'      => bbp_get_reply_post_type(),
3475          'post_status'    => bbp_get_public_status_id(),
3476          'post_parent'    => $topic_id,
3477          'posts_per_page' => -1,
3478  
3479          // Performance
3480          'nopaging'               => true,
3481          'suppress_filters'       => true,
3482          'update_post_term_cache' => false,
3483          'update_post_meta_cache' => false,
3484          'ignore_sticky_posts'    => true,
3485          'no_found_rows'          => true
3486      ) );
3487  
3488      if ( ! empty( $replies->posts ) ) {
3489  
3490          // Prevent debug notices
3491          $pre_trashed_replies = array();
3492  
3493          // Loop through replies, trash them, and add them to array
3494          foreach ( $replies->posts as $reply ) {
3495              wp_trash_post( $reply->ID );
3496              $pre_trashed_replies[] = $reply->ID;
3497          }
3498  
3499          // Set a post_meta entry of the replies that were trashed by this action.
3500          // This is so we can possibly untrash them, without untrashing replies
3501          // that were purposefully trashed before.
3502          update_post_meta( $topic_id, '_bbp_pre_trashed_replies', $pre_trashed_replies );
3503  
3504          // Reset the $post global
3505          wp_reset_postdata();
3506      }
3507  }
3508  
3509  /**
3510   * Called before untrashing a topic
3511   */
3512  function bbp_untrash_topic( $topic_id = 0 ) {
3513      $topic_id = bbp_get_topic_id( $topic_id );
3514  
3515      if ( empty( $topic_id ) || ! bbp_is_topic( $topic_id ) ) {
3516          return false;
3517      }
3518  
3519      do_action( 'bbp_untrash_topic', $topic_id );
3520  }
3521  
3522  /**
3523   * Untrash replies to a topic previously trashed.
3524   *
3525   * Usually you'll want to do this after the topic is unspammed.
3526   *
3527   * @since 2.6.0 bbPress (r5405)
3528   *
3529   * @param int $topic_id
3530   */
3531  function bbp_untrash_topic_replies( $topic_id = 0 ) {
3532  
3533      // Validation
3534      $topic_id = bbp_get_topic_id( $topic_id );
3535  
3536      // Get the replies that were not previously trashed
3537      $pre_trashed_replies = get_post_meta( $topic_id, '_bbp_pre_trashed_replies', true );
3538  
3539      // There are replies to untrash
3540      if ( ! empty( $pre_trashed_replies ) ) {
3541  
3542          // Maybe reverse the trashed replies array
3543          if ( is_array( $pre_trashed_replies ) ) {
3544              $pre_trashed_replies = array_reverse( $pre_trashed_replies );
3545          }
3546  
3547          // Loop through replies
3548          foreach ( (array) $pre_trashed_replies as $reply ) {
3549              wp_untrash_post( $reply );
3550          }
3551      }
3552  
3553      // Clear the trashed reply meta for the topic
3554      delete_post_meta( $topic_id, '_bbp_pre_trashed_replies' );
3555  }
3556  
3557  /** After Delete/Trash/Untrash ************************************************/
3558  
3559  /**
3560   * Called after deleting a topic
3561   *
3562   * @since 2.0.0 bbPress (r2993)
3563   */
3564  function bbp_deleted_topic( $topic_id = 0 ) {
3565      $topic_id = bbp_get_topic_id( $topic_id );
3566  
3567      if ( empty( $topic_id ) || ! bbp_is_topic( $topic_id ) ) {
3568          return false;
3569      }
3570  
3571      do_action( 'bbp_deleted_topic', $topic_id );
3572  }
3573  
3574  /**
3575   * Called after trashing a topic
3576   *
3577   * @since 2.0.0 bbPress (r2993)
3578   */
3579  function bbp_trashed_topic( $topic_id = 0 ) {
3580      $topic_id = bbp_get_topic_id( $topic_id );
3581  
3582      if ( empty( $topic_id ) || ! bbp_is_topic( $topic_id ) ) {
3583          return false;
3584      }
3585  
3586      do_action( 'bbp_trashed_topic', $topic_id );
3587  }
3588  
3589  /**
3590   * Called after untrashing a topic
3591   *
3592   * @since 2.0.0 bbPress (r2993)
3593   */
3594  function bbp_untrashed_topic( $topic_id = 0 ) {
3595      $topic_id = bbp_get_topic_id( $topic_id );
3596  
3597      if ( empty( $topic_id ) || ! bbp_is_topic( $topic_id ) ) {
3598          return false;
3599      }
3600  
3601      do_action( 'bbp_untrashed_topic', $topic_id );
3602  }
3603  
3604  /** Settings ******************************************************************/
3605  
3606  /**
3607   * Return the topics per page setting
3608   *
3609   * @since 2.0.0 bbPress (r3540)
3610   * @return int
3611   */
3612  function bbp_get_topics_per_page( $default = 15 ) {
3613  
3614      // Get database option and cast as integer
3615      $retval = get_option( '_bbp_topics_per_page', $default );
3616  
3617      // If return val is empty, set it to default
3618      if ( empty( $retval ) ) {
3619          $retval = $default;
3620      }
3621  
3622      // Filter & return
3623      return (int) apply_filters( 'bbp_get_topics_per_page', $retval, $default );
3624  }
3625  
3626  /**
3627   * Return the topics per RSS page setting
3628   *
3629   * @since 2.0.0 bbPress (r3540)
3630   *
3631   * @param int $default Default replies per page (25)
3632   * @return int
3633   */
3634  function bbp_get_topics_per_rss_page( $default = 25 ) {
3635  
3636      // Get database option and cast as integer
3637      $retval = get_option( '_bbp_topics_per_rss_page', $default );
3638  
3639      // If return val is empty, set it to default
3640      if ( empty( $retval ) ) {
3641          $retval = $default;
3642      }
3643  
3644      // Filter & return
3645      return (int) apply_filters( 'bbp_get_topics_per_rss_page', $retval, $default );
3646  }
3647  
3648  /** Topic Tags ****************************************************************/
3649  
3650  /**
3651   * Get topic tags for a specific topic ID
3652   *
3653   * @since 2.6.0 bbPress (r5836)
3654   *
3655   * @param int $topic_id
3656   *
3657   * @return string
3658   */
3659  function bbp_get_topic_tags( $topic_id = 0 ) {
3660      $topic_id   = bbp_get_topic_id( $topic_id );
3661      $terms      = (array) get_the_terms( $topic_id, bbp_get_topic_tag_tax_id() );
3662      $topic_tags = array_filter( $terms );
3663  
3664      // Filter & return
3665      return apply_filters( 'bbp_get_topic_tags', $topic_tags, $topic_id );
3666  }
3667  
3668  /**
3669   * Get topic tags for a specific topic ID
3670   *
3671   * @since 2.2.0 bbPress (r4165)
3672   *
3673   * @param int    $topic_id
3674   * @param string $sep
3675   *
3676   * @return string
3677   */
3678  function bbp_get_topic_tag_names( $topic_id = 0, $sep = ', ' ) {
3679      $topic_tags = bbp_get_topic_tags( $topic_id );
3680      $pluck      = wp_list_pluck( $topic_tags, 'name' );
3681      $terms      = ! empty( $pluck )
3682          ? implode( $sep, $pluck )
3683          : '';
3684  
3685      // Filter & return
3686      return apply_filters( 'bbp_get_topic_tag_names', $terms, $topic_id, $sep );
3687  }
3688  
3689  /**
3690   * Will update topic-tag count based on object type.
3691   *
3692   * Function for the default callback for topic-tag taxonomies.
3693   *
3694   * @see https://bbpress.trac.wordpress.org/ticket/3043
3695   * @access private
3696   *
3697   * @since 2.6.0 bbPress (r6253)
3698   *
3699   * @param array  $terms    List of Term taxonomy IDs.
3700   * @param object $taxonomy Current taxonomy object of terms.
3701   */
3702  function bbp_update_topic_tag_count( $terms, $taxonomy ) {
3703  
3704      // Bail if no object types are available
3705      if ( empty( $terms ) || empty( $taxonomy->object_type ) ) {
3706          return;
3707      }
3708  
3709      // Get object types
3710      $object_types = (array) $taxonomy->object_type;
3711  
3712      foreach ( $object_types as &$object_type ) {
3713          list( $object_type ) = explode( ':', $object_type );
3714      }
3715  
3716      $object_types = array_unique( $object_types );
3717  
3718      if ( ! empty( $object_types ) ) {
3719          $object_types = esc_sql( array_filter( $object_types, 'post_type_exists' ) );
3720      }
3721  
3722      // Statuses to count
3723      $object_statuses = bbp_get_public_topic_statuses();
3724  
3725      // Get database
3726      $bbp_db = bbp_db();
3727  
3728      // Loop through terms, maybe update counts
3729      foreach ( (array) $terms as $term ) {
3730          $count = 0;
3731  
3732          // Get count, and bump it
3733          if ( ! empty( $object_types ) ) {
3734              $query    = "SELECT COUNT(*) FROM {$bbp_db->term_relationships}, {$bbp_db->posts} WHERE {$bbp_db->posts}.ID = {$bbp_db->term_relationships}.object_id AND post_status IN ('" . implode("', '", $object_statuses ) . "') AND post_type IN ('" . implode("', '", $object_types ) . "') AND term_taxonomy_id = %d";
3735              $prepare  = $bbp_db->prepare( $query, $term );
3736              $count   += (int) $bbp_db->get_var( $prepare );
3737          }
3738  
3739          /** This action is documented in wp-includes/taxonomy.php */
3740          do_action( 'edit_term_taxonomy', $term, $taxonomy->name );
3741          $bbp_db->update( $bbp_db->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) );
3742  
3743          /** This action is documented in wp-includes/taxonomy.php */
3744          do_action( 'edited_term_taxonomy', $term, $taxonomy->name );
3745      }
3746  }
3747  
3748  /** Autoembed *****************************************************************/
3749  
3750  /**
3751   * Check if autoembeds are enabled and hook them in if so
3752   *
3753   * @since 2.1.0 bbPress (r3752)
3754   *
3755   * @global WP_Embed $wp_embed
3756   */
3757  function bbp_topic_content_autoembed() {
3758      global $wp_embed;
3759  
3760      if ( bbp_use_autoembed() && is_a( $wp_embed, 'WP_Embed' ) ) {
3761          add_filter( 'bbp_get_topic_content', array( $wp_embed, 'autoembed' ), 2 );
3762      }
3763  }
3764  
3765  /** Feeds *********************************************************************/
3766  
3767  /**
3768   * Output an RSS2 feed of topics, based on the query passed.
3769   *
3770   * @since 2.0.0 bbPress (r3171)
3771   *
3772   * @param array $topics_query
3773   */
3774  function bbp_display_topics_feed_rss2( $topics_query = array() ) {
3775  
3776      // User cannot access this forum
3777      if ( bbp_is_single_forum() && ! bbp_user_can_view_forum( array( 'forum_id' => bbp_get_forum_id() ) ) ) {
3778          return;
3779      }
3780  
3781      // Feed title
3782      $title = get_bloginfo_rss( 'name' ) . ' &#187; ' . esc_html__( 'All Topics', 'bbpress' );
3783      $title = apply_filters( 'wp_title_rss', $title );
3784  
3785      // Display the feed
3786      header( 'Content-Type: ' . feed_content_type( 'rss2' ) . '; charset=' . get_option( 'blog_charset' ), true );
3787      header( 'Status: 200 OK' );
3788      echo '<?xml version="1.0" encoding="' . get_option( 'blog_charset' ) . '"?' . '>'; ?>
3789  
3790      <rss version="2.0"
3791          xmlns:content="http://purl.org/rss/1.0/modules/content/"
3792          xmlns:wfw="http://wellformedweb.org/CommentAPI/"
3793          xmlns:dc="http://purl.org/dc/elements/1.1/"
3794          xmlns:atom="http://www.w3.org/2005/Atom"
3795  
3796          <?php do_action( 'bbp_feed' ); ?>
3797      >
3798  
3799      <channel>
3800  
3801          <title><?php echo $title; // Already escaped ?></title>
3802          <atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
3803          <link><?php self_link(); ?></link>
3804          <description><?php //?></description><?php // phpcs:ignore ?>
3805          <lastBuildDate><?php echo date( 'r' ); ?></lastBuildDate>
3806          <generator><?php echo esc_url_raw( 'https://bbpress.org/?v=' . convert_chars( bbp_get_version() ) ); ?></generator>
3807          <language><?php bloginfo_rss( 'language' ); ?></language>
3808  
3809          <?php do_action( 'bbp_feed_head' ); ?>
3810  
3811          <?php if ( bbp_has_topics( $topics_query ) ) : ?>
3812  
3813              <?php while ( bbp_topics() ) : bbp_the_topic(); ?>
3814  
3815                  <item>
3816                      <guid><?php bbp_topic_permalink(); ?></guid>
3817                      <title><![CDATA[<?php bbp_topic_title(); ?>]]></title>
3818                      <link><?php bbp_topic_permalink(); ?></link>
3819                      <pubDate><?php echo mysql2date( 'D, d M Y H:i:s +0000', get_post_meta( bbp_get_topic_id(), '_bbp_last_active_time', true ), false ); ?></pubDate>
3820                      <dc:creator><?php the_author(); ?></dc:creator>
3821  
3822                      <?php if ( !post_password_required() ) : ?>
3823  
3824                      <description>
3825                          <![CDATA[
3826                          <p><?php printf( esc_html__( 'Replies: %s', 'bbpress' ), bbp_get_topic_reply_count() ); ?></p>
3827                          <?php bbp_topic_content(); ?>
3828                          ]]>
3829                      </description>
3830  
3831                      <?php rss_enclosure(); ?>
3832  
3833                      <?php endif; ?>
3834  
3835                      <?php do_action( 'bbp_feed_item' ); ?>
3836  
3837                  </item>
3838  
3839                  <?php endwhile; ?>
3840              <?php endif; ?>
3841  
3842          <?php do_action( 'bbp_feed_footer' ); ?>
3843  
3844      </channel>
3845      </rss>
3846  
3847  <?php
3848      exit();
3849  }
3850  
3851  /** Permissions ***************************************************************/
3852  
3853  /**
3854   * Redirect if unauthorized user is attempting to edit a topic
3855   *
3856   * @since 2.1.0 bbPress (r3605)
3857   */
3858  function bbp_check_topic_edit() {
3859  
3860      // Bail if not editing a topic
3861      if ( ! bbp_is_topic_edit() ) {
3862          return;
3863      }
3864  
3865      // User cannot edit topic, so redirect back to topic
3866      if ( ! current_user_can( 'edit_topic', bbp_get_topic_id() ) ) {
3867          bbp_redirect( bbp_get_topic_permalink() );
3868      }
3869  }
3870  
3871  /**
3872   * Redirect if unauthorized user is attempting to edit a topic tag
3873   *
3874   * @since 2.1.0 bbPress (r3605)
3875   */
3876  function bbp_check_topic_tag_edit() {
3877  
3878      // Bail if not editing a topic tag
3879      if ( ! bbp_is_topic_tag_edit() ) {
3880          return;
3881      }
3882  
3883      // Bail if current user cannot edit topic tags
3884      if ( ! current_user_can( 'edit_topic_tag', bbp_get_topic_tag_id() ) ) {
3885          bbp_redirect( bbp_get_topic_tag_link() );
3886      }
3887  }


Generated: Thu Apr 25 01:01:05 2024 Cross-referenced by PHPXref 0.7.1