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