web/wp-content/plugins/bbpress/includes/replies/functions.php
changeset 196 5e8dcbe22c24
equal deleted inserted replaced
195:c7c0fbc09788 196:5e8dcbe22c24
       
     1 <?php
       
     2 
       
     3 /**
       
     4  * bbPress Reply 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 reply to function properly.
       
    18  *
       
    19  * @since bbPress (r3349)
       
    20  *
       
    21  * @uses bbp_parse_args()
       
    22  * @uses bbp_get_reply_post_type()
       
    23  * @uses wp_insert_post()
       
    24  * @uses update_post_meta()
       
    25  *
       
    26  * @param array $reply_data Forum post data
       
    27  * @param arrap $reply_meta Forum meta data
       
    28  */
       
    29 function bbp_insert_reply( $reply_data = array(), $reply_meta = array() ) {
       
    30 
       
    31 	// Forum
       
    32 	$default_reply = array(
       
    33 		'post_parent'    => 0, // topic ID
       
    34 		'post_status'    => bbp_get_public_status_id(),
       
    35 		'post_type'      => bbp_get_reply_post_type(),
       
    36 		'post_author'    => bbp_get_current_user_id(),
       
    37 		'post_password'  => '',
       
    38 		'post_content'   => '',
       
    39 		'post_title'     => '',
       
    40 		'menu_order'     => 0,
       
    41 		'comment_status' => 'closed'
       
    42 	);
       
    43 	$reply_data = bbp_parse_args( $reply_data, $default_reply, 'insert_reply' );
       
    44 
       
    45 	// Insert reply
       
    46 	$reply_id   = wp_insert_post( $reply_data );
       
    47 
       
    48 	// Bail if no reply was added
       
    49 	if ( empty( $reply_id ) )
       
    50 		return false;
       
    51 
       
    52 	// Forum meta
       
    53 	$default_meta = array(
       
    54 		'author_ip' => bbp_current_author_ip(),
       
    55 		'forum_id'  => 0,
       
    56 		'topic_id'  => 0,
       
    57 	);
       
    58 	$reply_meta = bbp_parse_args( $reply_meta, $default_meta, 'insert_reply_meta' );
       
    59 
       
    60 	// Insert reply meta
       
    61 	foreach ( $reply_meta as $meta_key => $meta_value )
       
    62 		update_post_meta( $reply_id, '_bbp_' . $meta_key, $meta_value );
       
    63 
       
    64 	// Update the topic
       
    65 	$topic_id = bbp_get_reply_topic_id( $reply_id );
       
    66 	if ( !empty( $topic_id ) )
       
    67 		bbp_update_topic( $topic_id );
       
    68 
       
    69 	// Return new reply ID
       
    70 	return $reply_id;
       
    71 }
       
    72 
       
    73 /** Post Form Handlers ********************************************************/
       
    74 
       
    75 /**
       
    76  * Handles the front end reply submission
       
    77  *
       
    78  * @since bbPress (r2574)
       
    79  *
       
    80  * @uses bbp_add_error() To add an error message
       
    81  * @uses bbp_verify_nonce_request() To verify the nonce and check the request
       
    82  * @uses bbp_is_anonymous() To check if an anonymous post is being made
       
    83  * @uses current_user_can() To check if the current user can publish replies
       
    84  * @uses bbp_get_current_user_id() To get the current user id
       
    85  * @uses bbp_filter_anonymous_post_data() To filter anonymous data
       
    86  * @uses bbp_set_current_anonymous_user_data() To set the anonymous user
       
    87  *                                                cookies
       
    88  * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error}
       
    89  * @uses remove_filter() To remove 'wp_filter_kses' filters if needed
       
    90  * @uses esc_attr() For sanitization
       
    91  * @uses bbp_check_for_flood() To check for flooding
       
    92  * @uses bbp_check_for_duplicate() To check for duplicates
       
    93  * @uses apply_filters() Calls 'bbp_new_reply_pre_title' with the title
       
    94  * @uses apply_filters() Calls 'bbp_new_reply_pre_content' with the content
       
    95  * @uses bbp_get_reply_post_type() To get the reply post type
       
    96  * @uses wp_set_post_terms() To set the topic tags
       
    97  * @uses wp_insert_post() To insert the reply
       
    98  * @uses do_action() Calls 'bbp_new_reply' with the reply id, topic id, forum
       
    99  *                    id, anonymous data and reply author
       
   100  * @uses bbp_get_reply_url() To get the paginated url to the reply
       
   101  * @uses wp_safe_redirect() To redirect to the reply url
       
   102  * @uses bbPress::errors::get_error_message() To get the {@link WP_Error} error
       
   103  *                                              message
       
   104  */
       
   105 function bbp_new_reply_handler() {
       
   106 
       
   107 	// Bail if not a POST action
       
   108 	if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) )
       
   109 		return;
       
   110 
       
   111 	// Bail if action is not bbp-new-reply
       
   112 	if ( empty( $_POST['action'] ) || ( 'bbp-new-reply' !== $_POST['action'] ) )
       
   113 		return;
       
   114 
       
   115 	// Nonce check
       
   116 	if ( ! bbp_verify_nonce_request( 'bbp-new-reply' ) ) {
       
   117 		bbp_add_error( 'bbp_rew_reply_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
       
   118 		return;
       
   119 	}
       
   120 
       
   121 	// Define local variable(s)
       
   122 	$topic_id = $forum_id = $reply_author = $anonymous_data = 0;
       
   123 	$reply_title = $reply_content = $terms = '';
       
   124 
       
   125 	/** Reply Author **********************************************************/
       
   126 
       
   127 	// User is anonymous
       
   128 	if ( bbp_is_anonymous() ) {
       
   129 
       
   130 		// Filter anonymous data
       
   131 		$anonymous_data = bbp_filter_anonymous_post_data();
       
   132 
       
   133 		// Anonymous data checks out, so set cookies, etc...
       
   134 		if ( !empty( $anonymous_data ) && is_array( $anonymous_data ) ) {
       
   135 			bbp_set_current_anonymous_user_data( $anonymous_data );
       
   136 		}
       
   137 
       
   138 	// User is logged in
       
   139 	} else {
       
   140 
       
   141 		// User cannot create replies
       
   142 		if ( !current_user_can( 'publish_replies' ) ) {
       
   143 			bbp_add_error( 'bbp_reply_permissions', __( '<strong>ERROR</strong>: You do not have permission to reply.', 'bbpress' ) );
       
   144 		}
       
   145 
       
   146 		// Reply author is current user
       
   147 		$reply_author = bbp_get_current_user_id();
       
   148 
       
   149 	}
       
   150 
       
   151 	/** Topic ID **************************************************************/
       
   152 
       
   153 	// Handle Topic ID to append reply to
       
   154 	if ( isset( $_POST['bbp_topic_id'] ) ) {
       
   155 		$topic_id = (int) $_POST['bbp_topic_id'];
       
   156 	} else {
       
   157 		bbp_add_error( 'bbp_reply_topic_id', __( '<strong>ERROR</strong>: Topic ID is missing.', 'bbpress' ) );
       
   158 	}
       
   159 
       
   160 	/** Forum ID **************************************************************/
       
   161 
       
   162 	// Handle Forum ID to adjust counts of
       
   163 	if ( isset( $_POST['bbp_forum_id'] ) ) {
       
   164 		$forum_id = (int) $_POST['bbp_forum_id'];
       
   165 	} elseif ( !empty( $topic_id ) ) {
       
   166 		$forum_id = bbp_get_topic_forum_id( $topic_id );
       
   167 	} else {
       
   168 		bbp_add_error( 'bbp_reply_forum_id', __( '<strong>ERROR</strong>: Forum ID is missing.', 'bbpress' ) );
       
   169 	}
       
   170 
       
   171 	/** Unfiltered HTML *******************************************************/
       
   172 
       
   173 	// Remove wp_filter_kses filters from title and content for capable users and if the nonce is verified
       
   174 	if ( current_user_can( 'unfiltered_html' ) && !empty( $_POST['_bbp_unfiltered_html_reply'] ) && wp_create_nonce( 'bbp-unfiltered-html-reply_' . $topic_id ) == $_POST['_bbp_unfiltered_html_reply'] ) {
       
   175 		remove_filter( 'bbp_new_reply_pre_title',   'wp_filter_kses' );
       
   176 		remove_filter( 'bbp_new_reply_pre_content', 'wp_filter_kses' );
       
   177 	}
       
   178 
       
   179 	/** Reply Title ***********************************************************/
       
   180 
       
   181 	if ( !empty( $_POST['bbp_reply_title'] ) )
       
   182 		$reply_title = esc_attr( strip_tags( $_POST['bbp_reply_title'] ) );
       
   183 
       
   184 	// Filter and sanitize
       
   185 	$reply_title = apply_filters( 'bbp_new_reply_pre_title', $reply_title );
       
   186 
       
   187 	// No reply title
       
   188 	if ( empty( $reply_title ) )
       
   189 		bbp_add_error( 'bbp_reply_title', __( '<strong>ERROR</strong>: Your reply needs a title.', 'bbpress' ) );
       
   190 
       
   191 	/** Reply Content *********************************************************/
       
   192 
       
   193 	if ( !empty( $_POST['bbp_reply_content'] ) )
       
   194 		$reply_content = $_POST['bbp_reply_content'];
       
   195 
       
   196 	// Filter and sanitize
       
   197 	$reply_content = apply_filters( 'bbp_new_reply_pre_content', $reply_content );
       
   198 
       
   199 	// No reply content
       
   200 	if ( empty( $reply_content ) )
       
   201 		bbp_add_error( 'bbp_reply_content', __( '<strong>ERROR</strong>: Your reply cannot be empty.', 'bbpress' ) );
       
   202 
       
   203 	/** Reply Flooding ********************************************************/
       
   204 
       
   205 	if ( !bbp_check_for_flood( $anonymous_data, $reply_author ) )
       
   206 		bbp_add_error( 'bbp_reply_flood', __( '<strong>ERROR</strong>: Slow down; you move too fast.', 'bbpress' ) );
       
   207 
       
   208 	/** Reply Duplicate *******************************************************/
       
   209 
       
   210 	if ( !bbp_check_for_duplicate( array( 'post_type' => bbp_get_reply_post_type(), 'post_author' => $reply_author, 'post_content' => $reply_content, 'post_parent' => $topic_id, 'anonymous_data' => $anonymous_data ) ) )
       
   211 		bbp_add_error( 'bbp_reply_duplicate', __( '<strong>ERROR</strong>: Duplicate reply detected; it looks as though you&#8217;ve already said that!', 'bbpress' ) );
       
   212 
       
   213 	/** Reply Blacklist *******************************************************/
       
   214 
       
   215 	if ( !bbp_check_for_blacklist( $anonymous_data, $reply_author, $reply_title, $reply_content ) )
       
   216 		bbp_add_error( 'bbp_reply_blacklist', __( '<strong>ERROR</strong>: Your reply cannot be created at this time.', 'bbpress' ) );
       
   217 
       
   218 	/** Reply Status **********************************************************/
       
   219 
       
   220 	// Maybe put into moderation
       
   221 	if ( !bbp_check_for_moderation( $anonymous_data, $reply_author, $reply_title, $reply_content ) ) {
       
   222 		$reply_status = bbp_get_pending_status_id();
       
   223 
       
   224 	// Default
       
   225 	} else {
       
   226 		$reply_status = bbp_get_public_status_id();
       
   227 	}
       
   228 
       
   229 	/** Topic Tags ************************************************************/
       
   230 
       
   231 	// Either replace terms
       
   232 	if ( bbp_allow_topic_tags() && current_user_can( 'assign_topic_tags' ) && ! empty( $_POST['bbp_topic_tags'] ) ) {
       
   233 		$terms = esc_attr( strip_tags( $_POST['bbp_topic_tags'] ) );
       
   234 
       
   235 	// ...or remove them.
       
   236 	} elseif ( isset( $_POST['bbp_topic_tags'] ) ) {
       
   237 		$terms = '';
       
   238 
       
   239 	// Existing terms
       
   240 	} else {
       
   241 		$terms = bbp_get_topic_tag_names( $topic_id );
       
   242 	}
       
   243 
       
   244 	/** Additional Actions (Before Save) **************************************/
       
   245 
       
   246 	do_action( 'bbp_new_reply_pre_extras', $topic_id, $forum_id );
       
   247 
       
   248 	// Bail if errors
       
   249 	if ( bbp_has_errors() )
       
   250 		return;
       
   251 
       
   252 	/** No Errors *************************************************************/
       
   253 
       
   254 	// Add the content of the form to $reply_data as an array
       
   255 	// Just in time manipulation of reply data before being created
       
   256 	$reply_data = apply_filters( 'bbp_new_reply_pre_insert', array(
       
   257 		'post_author'    => $reply_author,
       
   258 		'post_title'     => $reply_title,
       
   259 		'post_content'   => $reply_content,
       
   260 		'post_status'    => $reply_status,
       
   261 		'post_parent'    => $topic_id,
       
   262 		'post_type'      => bbp_get_reply_post_type(),
       
   263 		'comment_status' => 'closed',
       
   264 		'menu_order'     => bbp_get_topic_reply_count( $topic_id, false ) + 1
       
   265 	) );
       
   266 
       
   267 	// Insert reply
       
   268 	$reply_id = wp_insert_post( $reply_data );
       
   269 
       
   270 	/** No Errors *************************************************************/
       
   271 
       
   272 	// Check for missing reply_id or error
       
   273 	if ( !empty( $reply_id ) && !is_wp_error( $reply_id ) ) {
       
   274 
       
   275 		/** Topic Tags ********************************************************/
       
   276 
       
   277 		// Just in time manipulation of reply terms before being edited
       
   278 		$terms = apply_filters( 'bbp_new_reply_pre_set_terms', $terms, $topic_id, $reply_id );
       
   279 
       
   280 		// Insert terms
       
   281 		$terms = wp_set_post_terms( $topic_id, $terms, bbp_get_topic_tag_tax_id(), false );
       
   282 
       
   283 		// Term error
       
   284 		if ( is_wp_error( $terms ) ) {
       
   285 			bbp_add_error( 'bbp_reply_tags', __( '<strong>ERROR</strong>: There was a problem adding the tags to the topic.', 'bbpress' ) );
       
   286 		}
       
   287 
       
   288 		/** Trash Check *******************************************************/
       
   289 
       
   290 		// If this reply starts as trash, add it to pre_trashed_replies
       
   291 		// for the topic, so it is properly restored.
       
   292 		if ( bbp_is_topic_trash( $topic_id ) || ( $reply_data['post_status'] == bbp_get_trash_status_id() ) ) {
       
   293 
       
   294 			// Trash the reply
       
   295 			wp_trash_post( $reply_id );
       
   296 
       
   297 			// Get pre_trashed_replies for topic
       
   298 			$pre_trashed_replies = get_post_meta( $topic_id, '_bbp_pre_trashed_replies', true );
       
   299 
       
   300 			// Add this reply to the end of the existing replies
       
   301 			$pre_trashed_replies[] = $reply_id;
       
   302 
       
   303 			// Update the pre_trashed_reply post meta
       
   304 			update_post_meta( $topic_id, '_bbp_pre_trashed_replies', $pre_trashed_replies );
       
   305 		}
       
   306 
       
   307 		/** Spam Check ********************************************************/
       
   308 
       
   309 		// If reply or topic are spam, officially spam this reply
       
   310 		if ( bbp_is_topic_spam( $topic_id ) || ( $reply_data['post_status'] == bbp_get_spam_status_id() ) )
       
   311 			add_post_meta( $reply_id, '_bbp_spam_meta_status', bbp_get_public_status_id() );
       
   312 
       
   313 		/** Update counts, etc... *********************************************/
       
   314 
       
   315 		do_action( 'bbp_new_reply', $reply_id, $topic_id, $forum_id, $anonymous_data, $reply_author );
       
   316 
       
   317 		/** Additional Actions (After Save) ***********************************/
       
   318 
       
   319 		do_action( 'bbp_new_reply_post_extras', $reply_id );
       
   320 
       
   321 		/** Redirect **********************************************************/
       
   322 
       
   323 		// Redirect to
       
   324 		$redirect_to = !empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
       
   325 
       
   326 		// Get the reply URL
       
   327 		$reply_url = bbp_get_reply_url( $reply_id, $redirect_to );
       
   328 
       
   329 		// Allow to be filtered
       
   330 		$reply_url = apply_filters( 'bbp_new_reply_redirect_to', $reply_url, $redirect_to, $reply_id );
       
   331 
       
   332 		/** Successful Save ***************************************************/
       
   333 
       
   334 		// Redirect back to new reply
       
   335 		wp_safe_redirect( $reply_url );
       
   336 
       
   337 		// For good measure
       
   338 		exit();
       
   339 
       
   340 	/** Errors ****************************************************************/
       
   341 
       
   342 	} else {
       
   343 		$append_error = ( is_wp_error( $reply_id ) && $reply_id->get_error_message() ) ? $reply_id->get_error_message() . ' ' : '';
       
   344 		bbp_add_error( 'bbp_reply_error', __( '<strong>ERROR</strong>: The following problem(s) have been found with your reply:' . $append_error . 'Please try again.', 'bbpress' ) );
       
   345 	}
       
   346 }
       
   347 
       
   348 /**
       
   349  * Handles the front end edit reply submission
       
   350  *
       
   351  * @uses bbp_add_error() To add an error message
       
   352  * @uses bbp_get_reply() To get the reply
       
   353  * @uses bbp_verify_nonce_request() To verify the nonce and check the request
       
   354  * @uses bbp_is_reply_anonymous() To check if the reply was by an anonymous user
       
   355  * @uses current_user_can() To check if the current user can edit that reply
       
   356  * @uses bbp_filter_anonymous_post_data() To filter anonymous data
       
   357  * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error}
       
   358  * @uses remove_filter() To remove 'wp_filter_kses' filters if needed
       
   359  * @uses esc_attr() For sanitization
       
   360  * @uses apply_filters() Calls 'bbp_edit_reply_pre_title' with the title and
       
   361  *                       reply id
       
   362  * @uses apply_filters() Calls 'bbp_edit_reply_pre_content' with the content
       
   363  *                        reply id
       
   364  * @uses wp_set_post_terms() To set the topic tags
       
   365  * @uses bbp_has_errors() To get the {@link WP_Error} errors
       
   366  * @uses wp_save_post_revision() To save a reply revision
       
   367  * @uses bbp_update_reply_revision_log() To update the reply revision log
       
   368  * @uses wp_update_post() To update the reply
       
   369  * @uses bbp_get_reply_topic_id() To get the reply topic id
       
   370  * @uses bbp_get_topic_forum_id() To get the topic forum id
       
   371  * @uses do_action() Calls 'bbp_edit_reply' with the reply id, topic id, forum
       
   372  *                    id, anonymous data, reply author and bool true (for edit)
       
   373  * @uses bbp_get_reply_url() To get the paginated url to the reply
       
   374  * @uses wp_safe_redirect() To redirect to the reply url
       
   375  * @uses bbPress::errors::get_error_message() To get the {@link WP_Error} error
       
   376  *                                             message
       
   377  */
       
   378 function bbp_edit_reply_handler() {
       
   379 
       
   380 	// Bail if not a POST action
       
   381 	if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) )
       
   382 		return;
       
   383 
       
   384 	// Bail if action is not bbp-edit-reply
       
   385 	if ( empty( $_POST['action'] ) || ( 'bbp-edit-reply' !== $_POST['action'] ) )
       
   386 		return;
       
   387 
       
   388 	// Define local variable(s)
       
   389 	$revisions_removed = false;
       
   390 	$reply = $reply_id = $reply_author = $topic_id = $forum_id = $anonymous_data = 0;
       
   391 	$reply_title = $reply_content = $reply_edit_reason = $terms = '';
       
   392 
       
   393 	/** Reply *****************************************************************/
       
   394 
       
   395 	// Reply id was not passed
       
   396 	if ( empty( $_POST['bbp_reply_id'] ) ) {
       
   397 		bbp_add_error( 'bbp_edit_reply_id', __( '<strong>ERROR</strong>: Reply ID not found.', 'bbpress' ) );
       
   398 		return;
       
   399 
       
   400 	// Reply id was passed
       
   401 	} elseif ( is_numeric( $_POST['bbp_reply_id'] ) ) {
       
   402 		$reply_id = (int) $_POST['bbp_reply_id'];
       
   403 		$reply    = bbp_get_reply( $reply_id );
       
   404 	}
       
   405 
       
   406 	// Nonce check
       
   407 	if ( ! bbp_verify_nonce_request( 'bbp-edit-reply_' . $reply_id ) ) {
       
   408 		bbp_add_error( 'bbp_edit_reply_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
       
   409 		return;
       
   410 	}
       
   411 
       
   412 	// Reply does not exist
       
   413 	if ( empty( $reply ) ) {
       
   414 		bbp_add_error( 'bbp_edit_reply_not_found', __( '<strong>ERROR</strong>: The reply you want to edit was not found.', 'bbpress' ) );
       
   415 		return;
       
   416 
       
   417 	// Reply exists
       
   418 	} else {
       
   419 
       
   420 		// Check users ability to create new reply
       
   421 		if ( ! bbp_is_reply_anonymous( $reply_id ) ) {
       
   422 
       
   423 			// User cannot edit this reply
       
   424 			if ( !current_user_can( 'edit_reply', $reply_id ) ) {
       
   425 				bbp_add_error( 'bbp_edit_reply_permissions', __( '<strong>ERROR</strong>: You do not have permission to edit that reply.', 'bbpress' ) );
       
   426 				return;
       
   427 			}
       
   428 
       
   429 			// Set reply author
       
   430 			$reply_author = bbp_get_reply_author_id( $reply_id );
       
   431 
       
   432 		// It is an anonymous post
       
   433 		} else {
       
   434 
       
   435 			// Filter anonymous data
       
   436 			$anonymous_data = bbp_filter_anonymous_post_data();
       
   437 		}
       
   438 	}
       
   439 
       
   440 	// Remove wp_filter_kses filters from title and content for capable users and if the nonce is verified
       
   441 	if ( current_user_can( 'unfiltered_html' ) && !empty( $_POST['_bbp_unfiltered_html_reply'] ) && wp_create_nonce( 'bbp-unfiltered-html-reply_' . $reply_id ) == $_POST['_bbp_unfiltered_html_reply'] ) {
       
   442 		remove_filter( 'bbp_edit_reply_pre_title',   'wp_filter_kses' );
       
   443 		remove_filter( 'bbp_edit_reply_pre_content', 'wp_filter_kses' );
       
   444 	}
       
   445 
       
   446 	/** Reply Topic ***********************************************************/
       
   447 
       
   448 	$topic_id = bbp_get_reply_topic_id( $reply_id );
       
   449 
       
   450 	/** Topic Forum ***********************************************************/
       
   451 
       
   452 	$forum_id = bbp_get_topic_forum_id( $topic_id );
       
   453 
       
   454 	// Forum exists
       
   455 	if ( !empty( $forum_id ) && ( $forum_id !== bbp_get_reply_forum_id( $reply_id ) ) ) {
       
   456 
       
   457 		// Forum is a category
       
   458 		if ( bbp_is_forum_category( $forum_id ) )
       
   459 			bbp_add_error( 'bbp_edit_reply_forum_category', __( '<strong>ERROR</strong>: This forum is a category. No topics or replies can be created in it.', 'bbpress' ) );
       
   460 
       
   461 		// Forum is closed and user cannot access
       
   462 		if ( bbp_is_forum_closed( $forum_id ) && !current_user_can( 'edit_forum', $forum_id ) )
       
   463 			bbp_add_error( 'bbp_edit_reply_forum_closed', __( '<strong>ERROR</strong>: This forum has been closed to new topics and replies.', 'bbpress' ) );
       
   464 
       
   465 		// Forum is private and user cannot access
       
   466 		if ( bbp_is_forum_private( $forum_id ) && !current_user_can( 'read_private_forums' ) )
       
   467 			bbp_add_error( 'bbp_edit_reply_forum_private', __( '<strong>ERROR</strong>: This forum is private and you do not have the capability to read or create new replies in it.', 'bbpress' ) );
       
   468 
       
   469 		// Forum is hidden and user cannot access
       
   470 		if ( bbp_is_forum_hidden( $forum_id ) && !current_user_can( 'read_hidden_forums' ) )
       
   471 			bbp_add_error( 'bbp_edit_reply_forum_hidden', __( '<strong>ERROR</strong>: This forum is hidden and you do not have the capability to read or create new replies in it.', 'bbpress' ) );
       
   472 	}
       
   473 
       
   474 	/** Reply Title ***********************************************************/
       
   475 
       
   476 	if ( !empty( $_POST['bbp_reply_title'] ) )
       
   477 		$reply_title = esc_attr( strip_tags( $_POST['bbp_reply_title'] ) );
       
   478 
       
   479 	// Filter and sanitize
       
   480 	$reply_title = apply_filters( 'bbp_edit_reply_pre_title', $reply_title, $reply_id );
       
   481 
       
   482 	/** Reply Content *********************************************************/
       
   483 
       
   484 	if ( !empty( $_POST['bbp_reply_content'] ) )
       
   485 		$reply_content = $_POST['bbp_reply_content'];
       
   486 
       
   487 	// Filter and sanitize
       
   488 	$reply_content = apply_filters( 'bbp_edit_reply_pre_content', $reply_content, $reply_id );
       
   489 
       
   490 	// No reply content
       
   491 	if ( empty( $reply_content ) )
       
   492 		bbp_add_error( 'bbp_edit_reply_content', __( '<strong>ERROR</strong>: Your reply cannot be empty.', 'bbpress' ) );
       
   493 
       
   494 	/** Reply Blacklist *******************************************************/
       
   495 
       
   496 	if ( !bbp_check_for_blacklist( $anonymous_data, $reply_author, $reply_title, $reply_content ) )
       
   497 		bbp_add_error( 'bbp_reply_blacklist', __( '<strong>ERROR</strong>: Your reply cannot be edited at this time.', 'bbpress' ) );
       
   498 
       
   499 	/** Reply Status **********************************************************/
       
   500 
       
   501 	// Maybe put into moderation
       
   502 	if ( !bbp_check_for_moderation( $anonymous_data, $reply_author, $reply_title, $reply_content ) ) {
       
   503 
       
   504 		// Set post status to pending if public
       
   505 		if ( bbp_get_public_status_id() == $reply->post_status ) {
       
   506 			$reply_status = bbp_get_pending_status_id();
       
   507 		}
       
   508 
       
   509 	// Use existing post_status
       
   510 	} else {
       
   511 		$reply_status = $reply->post_status;
       
   512 	}
       
   513 
       
   514 	/** Topic Tags ************************************************************/
       
   515 
       
   516 	// Either replace terms
       
   517 	if ( bbp_allow_topic_tags() && current_user_can( 'assign_topic_tags' ) && ! empty( $_POST['bbp_topic_tags'] ) ) {
       
   518 		$terms = esc_attr( strip_tags( $_POST['bbp_topic_tags'] ) );
       
   519 
       
   520 	// ...or remove them.
       
   521 	} elseif ( isset( $_POST['bbp_topic_tags'] ) ) {
       
   522 		$terms = '';
       
   523 
       
   524 	// Existing terms
       
   525 	} else {
       
   526 		$terms = bbp_get_topic_tag_names( $topic_id );
       
   527 	}
       
   528 
       
   529 	/** Additional Actions (Before Save) **************************************/
       
   530 
       
   531 	do_action( 'bbp_edit_reply_pre_extras', $reply_id );
       
   532 
       
   533 	// Bail if errors
       
   534 	if ( bbp_has_errors() )
       
   535 		return;
       
   536 
       
   537 	/** No Errors *************************************************************/
       
   538 
       
   539 	// Add the content of the form to $reply_data as an array
       
   540 	// Just in time manipulation of reply data before being edited
       
   541 	$reply_data = apply_filters( 'bbp_edit_reply_pre_insert', array(
       
   542 		'ID'           => $reply_id,
       
   543 		'post_title'   => $reply_title,
       
   544 		'post_content' => $reply_content,
       
   545 		'post_status'  => $reply_status,
       
   546 		'post_parent'  => $topic_id,
       
   547 		'post_author'  => $reply_author,
       
   548 		'post_type'    => bbp_get_reply_post_type()
       
   549 	) );
       
   550 
       
   551 	// Toggle revisions to avoid duplicates
       
   552 	if ( post_type_supports( bbp_get_reply_post_type(), 'revisions' ) ) {
       
   553 		$revisions_removed = true;
       
   554 		remove_post_type_support( bbp_get_reply_post_type(), 'revisions' );
       
   555 	}
       
   556 
       
   557 	// Insert topic
       
   558 	$reply_id = wp_update_post( $reply_data );
       
   559 
       
   560 	// Toggle revisions back on
       
   561 	if ( true === $revisions_removed ) {
       
   562 		$revisions_removed = true;
       
   563 		add_post_type_support( bbp_get_reply_post_type(), 'revisions' );
       
   564 	}
       
   565 
       
   566 	/** Topic Tags ************************************************************/
       
   567 
       
   568 	// Just in time manipulation of reply terms before being edited
       
   569 	$terms = apply_filters( 'bbp_edit_reply_pre_set_terms', $terms, $topic_id, $reply_id );
       
   570 
       
   571 	// Insert terms
       
   572 	$terms = wp_set_post_terms( $topic_id, $terms, bbp_get_topic_tag_tax_id(), false );
       
   573 
       
   574 	// Term error
       
   575 	if ( is_wp_error( $terms ) ) {
       
   576 		bbp_add_error( 'bbp_reply_tags', __( '<strong>ERROR</strong>: There was a problem adding the tags to the topic.', 'bbpress' ) );
       
   577 	}
       
   578 
       
   579 	/** Revisions *************************************************************/
       
   580 
       
   581 	// Revision Reason
       
   582 	if ( !empty( $_POST['bbp_reply_edit_reason'] ) )
       
   583 		$reply_edit_reason = esc_attr( strip_tags( $_POST['bbp_reply_edit_reason'] ) );
       
   584 
       
   585 	// Update revision log
       
   586 	if ( !empty( $_POST['bbp_log_reply_edit'] ) && ( 1 == $_POST['bbp_log_reply_edit'] ) ) {
       
   587 		$revision_id = wp_is_post_revision( $reply_id );
       
   588 		if ( !empty( $revision_id ) ) {
       
   589 			bbp_update_reply_revision_log( array(
       
   590 				'reply_id'    => $reply_id,
       
   591 				'revision_id' => $revision_id,
       
   592 				'author_id'   => bbp_get_current_user_id(),
       
   593 				'reason'      => $reply_edit_reason
       
   594 			) );
       
   595 		}
       
   596 	}
       
   597 
       
   598 	/** No Errors *************************************************************/
       
   599 
       
   600 	if ( !empty( $reply_id ) && !is_wp_error( $reply_id ) ) {
       
   601 
       
   602 		// Update counts, etc...
       
   603 		do_action( 'bbp_edit_reply', $reply_id, $topic_id, $forum_id, $anonymous_data, $reply_author , true /* Is edit */ );
       
   604 
       
   605 		/** Additional Actions (After Save) ***********************************/
       
   606 
       
   607 		do_action( 'bbp_edit_reply_post_extras', $reply_id );
       
   608 
       
   609 		/** Redirect **********************************************************/
       
   610 
       
   611 		// Redirect to
       
   612 		$redirect_to = !empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
       
   613 
       
   614 		// Get the reply URL
       
   615 		$reply_url = bbp_get_reply_url( $reply_id, $redirect_to );
       
   616 
       
   617 		// Allow to be filtered
       
   618 		$reply_url = apply_filters( 'bbp_edit_reply_redirect_to', $reply_url, $redirect_to );
       
   619 
       
   620 		/** Successful Edit ***************************************************/
       
   621 
       
   622 		// Redirect back to new reply
       
   623 		wp_safe_redirect( $reply_url );
       
   624 
       
   625 		// For good measure
       
   626 		exit();
       
   627 
       
   628 	/** Errors ****************************************************************/
       
   629 
       
   630 	} else {
       
   631 		$append_error = ( is_wp_error( $reply_id ) && $reply_id->get_error_message() ) ? $reply_id->get_error_message() . ' ' : '';
       
   632 		bbp_add_error( 'bbp_reply_error', __( '<strong>ERROR</strong>: The following problem(s) have been found with your reply:' . $append_error . 'Please try again.', 'bbpress' ) );
       
   633 	}
       
   634 }
       
   635 
       
   636 /**
       
   637  * Handle all the extra meta stuff from posting a new reply or editing a reply
       
   638  *
       
   639  * @param int $reply_id Optional. Reply id
       
   640  * @param int $topic_id Optional. Topic id
       
   641  * @param int $forum_id Optional. Forum id
       
   642  * @param bool|array $anonymous_data Optional. If it is an array, it is
       
   643  *                    extracted and anonymous user info is saved
       
   644  * @param int $author_id Author id
       
   645  * @param bool $is_edit Optional. Is the post being edited? Defaults to false.
       
   646  * @uses bbp_get_reply_id() To get the reply id
       
   647  * @uses bbp_get_topic_id() To get the topic id
       
   648  * @uses bbp_get_forum_id() To get the forum id
       
   649  * @uses bbp_get_current_user_id() To get the current user id
       
   650  * @uses bbp_get_reply_topic_id() To get the reply topic id
       
   651  * @uses bbp_get_topic_forum_id() To get the topic forum id
       
   652  * @uses update_post_meta() To update the reply metas
       
   653  * @uses set_transient() To update the flood check transient for the ip
       
   654  * @uses bbp_update_user_last_posted() To update the users last posted time
       
   655  * @uses bbp_is_subscriptions_active() To check if the subscriptions feature is
       
   656  *                                      activated or not
       
   657  * @uses bbp_is_user_subscribed() To check if the user is subscribed
       
   658  * @uses bbp_remove_user_subscription() To remove the user's subscription
       
   659  * @uses bbp_add_user_subscription() To add the user's subscription
       
   660  * @uses bbp_update_reply_forum_id() To update the reply forum id
       
   661  * @uses bbp_update_reply_topic_id() To update the reply topic id
       
   662  * @uses bbp_update_reply_walker() To update the reply's ancestors' counts
       
   663  */
       
   664 function bbp_update_reply( $reply_id = 0, $topic_id = 0, $forum_id = 0, $anonymous_data = false, $author_id = 0, $is_edit = false ) {
       
   665 
       
   666 	// Validate the ID's passed from 'bbp_new_reply' action
       
   667 	$reply_id = bbp_get_reply_id( $reply_id );
       
   668 	$topic_id = bbp_get_topic_id( $topic_id );
       
   669 	$forum_id = bbp_get_forum_id( $forum_id );
       
   670 
       
   671 	// Bail if there is no reply
       
   672 	if ( empty( $reply_id ) )
       
   673 		return;
       
   674 
       
   675 	// Check author_id
       
   676 	if ( empty( $author_id ) )
       
   677 		$author_id = bbp_get_current_user_id();
       
   678 
       
   679 	// Check topic_id
       
   680 	if ( empty( $topic_id ) )
       
   681 		$topic_id = bbp_get_reply_topic_id( $reply_id );
       
   682 
       
   683 	// Check forum_id
       
   684 	if ( !empty( $topic_id ) && empty( $forum_id ) )
       
   685 		$forum_id = bbp_get_topic_forum_id( $topic_id );
       
   686 
       
   687 	// If anonymous post, store name, email, website and ip in post_meta.
       
   688 	// It expects anonymous_data to be sanitized.
       
   689 	// Check bbp_filter_anonymous_post_data() for sanitization.
       
   690 	if ( !empty( $anonymous_data ) && is_array( $anonymous_data ) ) {
       
   691 
       
   692 		// Always set at least these three values to empty
       
   693 		$defaults = array(
       
   694 			'bbp_anonymous_name'    => '',
       
   695 			'bbp_anonymous_email'   => '',
       
   696 			'bbp_anonymous_website' => '',
       
   697 		);
       
   698 		$r = bbp_parse_args( $anonymous_data, $defaults, 'update_reply' );
       
   699 
       
   700 		// Update all anonymous metas
       
   701 		foreach( $r as $anon_key => $anon_value ) {
       
   702 			update_post_meta( $reply_id, '_' . $anon_key, (string) $anon_value, false );
       
   703 		}
       
   704 
       
   705 		// Set transient for throttle check (only on new, not edit)
       
   706 		if ( empty( $is_edit ) ) {
       
   707 			set_transient( '_bbp_' . bbp_current_author_ip() . '_last_posted', time() );
       
   708 		}
       
   709 
       
   710 	} else {
       
   711 		if ( empty( $is_edit ) && !current_user_can( 'throttle' ) ) {
       
   712 			bbp_update_user_last_posted( $author_id );
       
   713 		}
       
   714 	}
       
   715 
       
   716 	// Handle Subscription Checkbox
       
   717 	if ( bbp_is_subscriptions_active() && !empty( $author_id ) && !empty( $topic_id ) ) {
       
   718 		$subscribed = bbp_is_user_subscribed( $author_id, $topic_id );
       
   719 		$subscheck  = ( !empty( $_POST['bbp_topic_subscription'] ) && ( 'bbp_subscribe' == $_POST['bbp_topic_subscription'] ) ) ? true : false;
       
   720 
       
   721 		// Subscribed and unsubscribing
       
   722 		if ( true == $subscribed && false == $subscheck ) {
       
   723 			bbp_remove_user_subscription( $author_id, $topic_id );
       
   724 
       
   725 		// Subscribing
       
   726 		} elseif ( false == $subscribed && true == $subscheck ) {
       
   727 			bbp_add_user_subscription( $author_id, $topic_id );
       
   728 		}
       
   729 	}
       
   730 
       
   731 	// Reply meta relating to reply position in tree
       
   732 	bbp_update_reply_forum_id( $reply_id, $forum_id );
       
   733 	bbp_update_reply_topic_id( $reply_id, $topic_id );
       
   734 
       
   735 	// Update associated topic values if this is a new reply
       
   736 	if ( empty( $is_edit ) ) {
       
   737 
       
   738 		// Update poster IP if not editing
       
   739 		update_post_meta( $reply_id, '_bbp_author_ip', bbp_current_author_ip(), false );
       
   740 
       
   741 		// Last active time
       
   742 		$last_active_time = current_time( 'mysql' );
       
   743 
       
   744 		// Walk up ancestors and do the dirty work
       
   745 		bbp_update_reply_walker( $reply_id, $last_active_time, $forum_id, $topic_id, false );
       
   746 	}
       
   747 }
       
   748 
       
   749 /**
       
   750  * Walk up the ancestor tree from the current reply, and update all the counts
       
   751  *
       
   752  * @since bbPress (r2884)
       
   753  *
       
   754  * @param int $reply_id Optional. Reply id
       
   755  * @param string $last_active_time Optional. Last active time
       
   756  * @param int $forum_id Optional. Forum id
       
   757  * @param int $topic_id Optional. Topic id
       
   758  * @param bool $refresh If set to true, unsets all the previous parameters.
       
   759  *                       Defaults to true
       
   760  * @uses bbp_get_reply_id() To get the reply id
       
   761  * @uses bbp_get_reply_topic_id() To get the reply topic id
       
   762  * @uses bbp_get_reply_forum_id() To get the reply forum id
       
   763  * @uses get_post_ancestors() To get the ancestors of the reply
       
   764  * @uses bbp_is_reply() To check if the ancestor is a reply
       
   765  * @uses bbp_is_topic() To check if the ancestor is a topic
       
   766  * @uses bbp_update_topic_last_reply_id() To update the topic last reply id
       
   767  * @uses bbp_update_topic_last_active_id() To update the topic last active id
       
   768  * @uses bbp_get_topic_last_active_id() To get the topic last active id
       
   769  * @uses get_post_field() To get the post date of the last active id
       
   770  * @uses bbp_update_topic_last_active_time() To update the last active topic meta
       
   771  * @uses bbp_update_topic_voice_count() To update the topic voice count
       
   772  * @uses bbp_update_topic_reply_count() To update the topic reply count
       
   773  * @uses bbp_update_topic_reply_count_hidden() To update the topic hidden reply
       
   774  *                                              count
       
   775  * @uses bbp_is_forum() To check if the ancestor is a forum
       
   776  * @uses bbp_update_forum_last_topic_id() To update the last topic id forum meta
       
   777  * @uses bbp_update_forum_last_reply_id() To update the last reply id forum meta
       
   778  * @uses bbp_update_forum_last_active_id() To update the forum last active id
       
   779  * @uses bbp_get_forum_last_active_id() To get the forum last active id
       
   780  * @uses bbp_update_forum_last_active_time() To update the forum last active time
       
   781  * @uses bbp_update_forum_reply_count() To update the forum reply count
       
   782  */
       
   783 function bbp_update_reply_walker( $reply_id, $last_active_time = '', $forum_id = 0, $topic_id = 0, $refresh = true ) {
       
   784 
       
   785 	// Verify the reply ID
       
   786 	$reply_id = bbp_get_reply_id( $reply_id );
       
   787 
       
   788 	// Reply was passed
       
   789 	if ( !empty( $reply_id ) ) {
       
   790 
       
   791 		// Get the topic ID if none was passed
       
   792 		if ( empty( $topic_id ) ) {
       
   793 			$topic_id = bbp_get_reply_topic_id( $reply_id );
       
   794 		}
       
   795 
       
   796 		// Get the forum ID if none was passed
       
   797 		if ( empty( $forum_id ) ) {
       
   798 			$forum_id = bbp_get_reply_forum_id( $reply_id );
       
   799 		}
       
   800 	}
       
   801 
       
   802 	// Set the active_id based on topic_id/reply_id
       
   803 	$active_id = empty( $reply_id ) ? $topic_id : $reply_id;
       
   804 
       
   805 	// Setup ancestors array to walk up
       
   806 	$ancestors = array_values( array_unique( array_merge( array( $topic_id, $forum_id ), (array) get_post_ancestors( $topic_id ) ) ) );
       
   807 
       
   808 	// If we want a full refresh, unset any of the possibly passed variables
       
   809 	if ( true == $refresh )
       
   810 		$forum_id = $topic_id = $reply_id = $active_id = $last_active_time = 0;
       
   811 
       
   812 	// Walk up ancestors
       
   813 	if ( !empty( $ancestors ) ) {
       
   814 		foreach ( $ancestors as $ancestor ) {
       
   815 
       
   816 			// Reply meta relating to most recent reply
       
   817 			if ( bbp_is_reply( $ancestor ) ) {
       
   818 				// @todo - hierarchical replies
       
   819 
       
   820 			// Topic meta relating to most recent reply
       
   821 			} elseif ( bbp_is_topic( $ancestor ) ) {
       
   822 
       
   823 				// Last reply and active ID's
       
   824 				bbp_update_topic_last_reply_id ( $ancestor, $reply_id  );
       
   825 				bbp_update_topic_last_active_id( $ancestor, $active_id );
       
   826 
       
   827 				// Get the last active time if none was passed
       
   828 				$topic_last_active_time = $last_active_time;
       
   829 				if ( empty( $last_active_time ) ) {
       
   830 					$topic_last_active_time = get_post_field( 'post_date', bbp_get_topic_last_active_id( $ancestor ) );
       
   831 				}
       
   832 
       
   833 				// Only update if reply is published
       
   834 				if ( bbp_is_reply_published( $reply_id ) ) {
       
   835 					bbp_update_topic_last_active_time( $ancestor, $topic_last_active_time );
       
   836 				}
       
   837 
       
   838 				// Counts
       
   839 				bbp_update_topic_voice_count       ( $ancestor );
       
   840 				bbp_update_topic_reply_count       ( $ancestor );
       
   841 				bbp_update_topic_reply_count_hidden( $ancestor );
       
   842 
       
   843 			// Forum meta relating to most recent topic
       
   844 			} elseif ( bbp_is_forum( $ancestor ) ) {
       
   845 
       
   846 				// Last topic and reply ID's
       
   847 				bbp_update_forum_last_topic_id( $ancestor, $topic_id );
       
   848 				bbp_update_forum_last_reply_id( $ancestor, $reply_id );
       
   849 
       
   850 				// Last Active
       
   851 				bbp_update_forum_last_active_id( $ancestor, $active_id );
       
   852 
       
   853 				// Get the last active time if none was passed
       
   854 				$forum_last_active_time = $last_active_time;
       
   855 				if ( empty( $last_active_time ) ) {
       
   856 					$forum_last_active_time = get_post_field( 'post_date', bbp_get_forum_last_active_id( $ancestor ) );
       
   857 				}
       
   858 
       
   859 				// Only update if reply is published
       
   860 				if ( bbp_is_reply_published( $reply_id ) ) {
       
   861 					bbp_update_forum_last_active_time( $ancestor, $forum_last_active_time );
       
   862 				}
       
   863 
       
   864 				// Counts
       
   865 				bbp_update_forum_reply_count( $ancestor );
       
   866 			}
       
   867 		}
       
   868 	}
       
   869 }
       
   870 
       
   871 /** Reply Updaters ************************************************************/
       
   872 
       
   873 /**
       
   874  * Update the reply with its forum id it is in
       
   875  *
       
   876  * @since bbPress (r2855)
       
   877  *
       
   878  * @param int $reply_id Optional. Reply id to update
       
   879  * @param int $forum_id Optional. Forum id
       
   880  * @uses bbp_get_reply_id() To get the reply id
       
   881  * @uses bbp_get_forum_id() To get the forum id
       
   882  * @uses get_post_ancestors() To get the reply's forum
       
   883  * @uses get_post_field() To get the post type of the post
       
   884  * @uses update_post_meta() To update the reply forum id meta
       
   885  * @uses apply_filters() Calls 'bbp_update_reply_forum_id' with the forum id
       
   886  *                        and reply id
       
   887  * @return bool Reply's forum id
       
   888  */
       
   889 function bbp_update_reply_forum_id( $reply_id = 0, $forum_id = 0 ) {
       
   890 
       
   891 	// Validation
       
   892 	$reply_id = bbp_get_reply_id( $reply_id );
       
   893 	$forum_id = bbp_get_forum_id( $forum_id );
       
   894 
       
   895 	// If no forum_id was passed, walk up ancestors and look for forum type
       
   896 	if ( empty( $forum_id ) ) {
       
   897 
       
   898 		// Get ancestors
       
   899 		$ancestors = (array) get_post_ancestors( $reply_id );
       
   900 
       
   901 		// Loop through ancestors
       
   902 		if ( !empty( $ancestors ) ) {
       
   903 			foreach ( $ancestors as $ancestor ) {
       
   904 
       
   905 				// Get first parent that is a forum
       
   906 				if ( get_post_field( 'post_type', $ancestor ) == bbp_get_forum_post_type() ) {
       
   907 					$forum_id = $ancestor;
       
   908 
       
   909 					// Found a forum, so exit the loop and continue
       
   910 					continue;
       
   911 				}
       
   912 			}
       
   913 		}
       
   914 	}
       
   915 
       
   916 	// Update the forum ID
       
   917 	bbp_update_forum_id( $reply_id, $forum_id );
       
   918 
       
   919 	return apply_filters( 'bbp_update_reply_forum_id', (int) $forum_id, $reply_id );
       
   920 }
       
   921 
       
   922 /**
       
   923  * Update the reply with its topic id it is in
       
   924  *
       
   925  * @since bbPress (r2855)
       
   926  *
       
   927  * @param int $reply_id Optional. Reply id to update
       
   928  * @param int $topic_id Optional. Topic id
       
   929  * @uses bbp_get_reply_id() To get the reply id
       
   930  * @uses bbp_get_topic_id() To get the topic id
       
   931  * @uses get_post_ancestors() To get the reply's topic
       
   932  * @uses get_post_field() To get the post type of the post
       
   933  * @uses update_post_meta() To update the reply topic id meta
       
   934  * @uses apply_filters() Calls 'bbp_update_reply_topic_id' with the topic id
       
   935  *                        and reply id
       
   936  * @return bool Reply's topic id
       
   937  */
       
   938 function bbp_update_reply_topic_id( $reply_id = 0, $topic_id = 0 ) {
       
   939 
       
   940 	// Validation
       
   941 	$reply_id = bbp_get_reply_id( $reply_id );
       
   942 	$topic_id = bbp_get_topic_id( $topic_id );
       
   943 
       
   944 	// If no topic_id was passed, walk up ancestors and look for topic type
       
   945 	if ( empty( $topic_id ) ) {
       
   946 
       
   947 		// Get ancestors
       
   948 		$ancestors = (array) get_post_ancestors( $reply_id );
       
   949 
       
   950 		// Loop through ancestors
       
   951 		if ( !empty( $ancestors ) ) {
       
   952 			foreach ( $ancestors as $ancestor ) {
       
   953 
       
   954 				// Get first parent that is a forum
       
   955 				if ( get_post_field( 'post_type', $ancestor ) == bbp_get_topic_post_type() ) {
       
   956 					$topic_id = $ancestor;
       
   957 
       
   958 					// Found a forum, so exit the loop and continue
       
   959 					continue;
       
   960 				}
       
   961 			}
       
   962 		}
       
   963 	}
       
   964 
       
   965 	// Update the topic ID
       
   966 	bbp_update_topic_id( $reply_id, $topic_id );
       
   967 
       
   968 	return apply_filters( 'bbp_update_reply_topic_id', (int) $topic_id, $reply_id );
       
   969 }
       
   970 
       
   971 /**
       
   972  * Update the revision log of the reply
       
   973  *
       
   974  * @since bbPress (r2782)
       
   975  *
       
   976  * @param mixed $args Supports these args:
       
   977  *  - reply_id: reply id
       
   978  *  - author_id: Author id
       
   979  *  - reason: Reason for editing
       
   980  *  - revision_id: Revision id
       
   981  * @uses bbp_get_reply_id() To get the reply id
       
   982  * @uses bbp_get_user_id() To get the user id
       
   983  * @uses bbp_format_revision_reason() To format the reason
       
   984  * @uses bbp_get_reply_raw_revision_log() To get the raw reply revision log
       
   985  * @uses update_post_meta() To update the reply revision log meta
       
   986  * @return mixed False on failure, true on success
       
   987  */
       
   988 function bbp_update_reply_revision_log( $args = '' ) {
       
   989 	$defaults = array (
       
   990 		'reason'      => '',
       
   991 		'reply_id'    => 0,
       
   992 		'author_id'   => 0,
       
   993 		'revision_id' => 0
       
   994 	);
       
   995 
       
   996 	$r = bbp_parse_args( $args, $defaults, 'update_reply_revision_log' );
       
   997 	extract( $r );
       
   998 
       
   999 	// Populate the variables
       
  1000 	$reason      = bbp_format_revision_reason( $reason );
       
  1001 	$reply_id    = bbp_get_reply_id( $reply_id );
       
  1002 	$author_id   = bbp_get_user_id ( $author_id, false, true );
       
  1003 	$revision_id = (int) $revision_id;
       
  1004 
       
  1005 	// Get the logs and append the new one to those
       
  1006 	$revision_log               = bbp_get_reply_raw_revision_log( $reply_id );
       
  1007 	$revision_log[$revision_id] = array( 'author' => $author_id, 'reason' => $reason );
       
  1008 
       
  1009 	// Finally, update
       
  1010 	update_post_meta( $reply_id, '_bbp_revision_log', $revision_log );
       
  1011 
       
  1012 	return apply_filters( 'bbp_update_reply_revision_log', $revision_log, $reply_id );
       
  1013 }
       
  1014 
       
  1015 /** Reply Actions *************************************************************/
       
  1016 
       
  1017 /**
       
  1018  * Handles the front end spamming/unspamming and trashing/untrashing/deleting of
       
  1019  * replies
       
  1020  *
       
  1021  * @since bbPress (r2740)
       
  1022  *
       
  1023  * @uses bbp_get_reply() To get the reply
       
  1024  * @uses current_user_can() To check if the user is capable of editing or
       
  1025  *                           deleting the reply
       
  1026  * @uses check_ajax_referer() To verify the nonce and check the referer
       
  1027  * @uses bbp_get_reply_post_type() To get the reply post type
       
  1028  * @uses bbp_is_reply_spam() To check if the reply is marked as spam
       
  1029  * @uses bbp_spam_reply() To make the reply as spam
       
  1030  * @uses bbp_unspam_reply() To unmark the reply as spam
       
  1031  * @uses wp_trash_post() To trash the reply
       
  1032  * @uses wp_untrash_post() To untrash the reply
       
  1033  * @uses wp_delete_post() To delete the reply
       
  1034  * @uses do_action() Calls 'bbp_toggle_reply_handler' with success, post data
       
  1035  *                    and action
       
  1036  * @uses bbp_get_reply_url() To get the reply url
       
  1037  * @uses add_query_arg() To add custom args to the reply url
       
  1038  * @uses wp_safe_redirect() To redirect to the reply
       
  1039  * @uses bbPress::errors:add() To log the error messages
       
  1040  */
       
  1041 function bbp_toggle_reply_handler() {
       
  1042 
       
  1043 	// Bail if not a GET action
       
  1044 	if ( 'GET' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) )
       
  1045 		return;
       
  1046 
       
  1047 	// Bail if required GET actions aren't passed
       
  1048 	if ( empty( $_GET['reply_id'] ) || empty( $_GET['action'] ) )
       
  1049 		return;
       
  1050 
       
  1051 	// Setup possible get actions
       
  1052 	$possible_actions = array(
       
  1053 		'bbp_toggle_reply_spam',
       
  1054 		'bbp_toggle_reply_trash'
       
  1055 	);
       
  1056 
       
  1057 	// Bail if actions aren't meant for this function
       
  1058 	if ( !in_array( $_GET['action'], $possible_actions ) )
       
  1059 		return;
       
  1060 
       
  1061 	$failure   = '';                         // Empty failure string
       
  1062 	$view_all  = false;                      // Assume not viewing all
       
  1063 	$action    = $_GET['action'];            // What action is taking place?
       
  1064 	$reply_id  = (int) $_GET['reply_id'];    // What's the reply id?
       
  1065 	$success   = false;                      // Flag
       
  1066 	$post_data = array( 'ID' => $reply_id ); // Prelim array
       
  1067 
       
  1068 	// Make sure reply exists
       
  1069 	$reply = bbp_get_reply( $reply_id );
       
  1070 	if ( empty( $reply ) )
       
  1071 		return;
       
  1072 
       
  1073 	// What is the user doing here?
       
  1074 	if ( !current_user_can( 'edit_reply', $reply->ID ) || ( 'bbp_toggle_reply_trash' == $action && !current_user_can( 'delete_reply', $reply->ID ) ) ) {
       
  1075 		bbp_add_error( 'bbp_toggle_reply_permission', __( '<strong>ERROR:</strong> You do not have the permission to do that!', 'bbpress' ) );
       
  1076 		return;
       
  1077 	}
       
  1078 
       
  1079 	// What action are we trying to perform?
       
  1080 	switch ( $action ) {
       
  1081 
       
  1082 		// Toggle spam
       
  1083 		case 'bbp_toggle_reply_spam' :
       
  1084 			check_ajax_referer( 'spam-reply_' . $reply_id );
       
  1085 
       
  1086 			$is_spam  = bbp_is_reply_spam( $reply_id );
       
  1087 			$success  = $is_spam ? bbp_unspam_reply( $reply_id ) : bbp_spam_reply( $reply_id );
       
  1088 			$failure  = $is_spam ? __( '<strong>ERROR</strong>: There was a problem unmarking the reply as spam!', 'bbpress' ) : __( '<strong>ERROR</strong>: There was a problem marking the reply as spam!', 'bbpress' );
       
  1089 			$view_all = !$is_spam;
       
  1090 
       
  1091 			break;
       
  1092 
       
  1093 		// Toggle trash
       
  1094 		case 'bbp_toggle_reply_trash' :
       
  1095 
       
  1096 			$sub_action = in_array( $_GET['sub_action'], array( 'trash', 'untrash', 'delete' ) ) ? $_GET['sub_action'] : false;
       
  1097 
       
  1098 			if ( empty( $sub_action ) )
       
  1099 				break;
       
  1100 
       
  1101 			switch ( $sub_action ) {
       
  1102 				case 'trash':
       
  1103 					check_ajax_referer( 'trash-' . bbp_get_reply_post_type() . '_' . $reply_id );
       
  1104 
       
  1105 					$view_all = true;
       
  1106 					$success  = wp_trash_post( $reply_id );
       
  1107 					$failure  = __( '<strong>ERROR</strong>: There was a problem trashing the reply!', 'bbpress' );
       
  1108 
       
  1109 					break;
       
  1110 
       
  1111 				case 'untrash':
       
  1112 					check_ajax_referer( 'untrash-' . bbp_get_reply_post_type() . '_' . $reply_id );
       
  1113 
       
  1114 					$success = wp_untrash_post( $reply_id );
       
  1115 					$failure = __( '<strong>ERROR</strong>: There was a problem untrashing the reply!', 'bbpress' );
       
  1116 
       
  1117 					break;
       
  1118 
       
  1119 				case 'delete':
       
  1120 					check_ajax_referer( 'delete-' . bbp_get_reply_post_type() . '_' . $reply_id );
       
  1121 
       
  1122 					$success = wp_delete_post( $reply_id );
       
  1123 					$failure = __( '<strong>ERROR</strong>: There was a problem deleting the reply!', 'bbpress' );
       
  1124 
       
  1125 					break;
       
  1126 			}
       
  1127 
       
  1128 			break;
       
  1129 	}
       
  1130 
       
  1131 	// Do additional reply toggle actions
       
  1132 	do_action( 'bbp_toggle_reply_handler', $success, $post_data, $action );
       
  1133 
       
  1134 	// No errors
       
  1135 	if ( ( false != $success ) && !is_wp_error( $success ) ) {
       
  1136 
       
  1137 		/** Redirect **********************************************************/
       
  1138 
       
  1139 		// Redirect to
       
  1140 		$redirect_to = !empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
       
  1141 
       
  1142 		// Get the reply URL
       
  1143 		$reply_url = bbp_get_reply_url( $reply_id, $redirect_to );
       
  1144 
       
  1145 		// Add view all if needed
       
  1146 		if ( !empty( $view_all ) )
       
  1147 			$reply_url = bbp_add_view_all( $reply_url, true );
       
  1148 
       
  1149 		// Redirect back to reply
       
  1150 		wp_safe_redirect( $reply_url );
       
  1151 
       
  1152 		// For good measure
       
  1153 		exit();
       
  1154 
       
  1155 	// Handle errors
       
  1156 	} else {
       
  1157 		bbp_add_error( 'bbp_toggle_reply', $failure );
       
  1158 	}
       
  1159 }
       
  1160 
       
  1161 /** Reply Actions *************************************************************/
       
  1162 
       
  1163 /**
       
  1164  * Marks a reply as spam
       
  1165  *
       
  1166  * @since bbPress (r2740)
       
  1167  *
       
  1168  * @param int $reply_id Reply id
       
  1169  * @uses get_post() To get the reply
       
  1170  * @uses do_action() Calls 'bbp_spam_reply' with the reply ID
       
  1171  * @uses add_post_meta() To add the previous status to a meta
       
  1172  * @uses wp_insert_post() To insert the updated post
       
  1173  * @uses do_action() Calls 'bbp_spammed_reply' with the reply ID
       
  1174  * @return mixed False or {@link WP_Error} on failure, reply id on success
       
  1175  */
       
  1176 function bbp_spam_reply( $reply_id = 0 ) {
       
  1177 
       
  1178 	// Get reply
       
  1179 	$reply = get_post( $reply_id, ARRAY_A );
       
  1180 	if ( empty( $reply ) )
       
  1181 		return $reply;
       
  1182 
       
  1183 	// Bail if already spam
       
  1184 	if ( bbp_get_spam_status_id() == $reply['post_status'] )
       
  1185 		return false;
       
  1186 
       
  1187 	// Execute pre spam code
       
  1188 	do_action( 'bbp_spam_reply', $reply_id );
       
  1189 
       
  1190 	// Add the original post status as post meta for future restoration
       
  1191 	add_post_meta( $reply_id, '_bbp_spam_meta_status', $reply['post_status'] );
       
  1192 
       
  1193 	// Set post status to spam
       
  1194 	$reply['post_status'] = bbp_get_spam_status_id();
       
  1195 
       
  1196 	// No revisions
       
  1197 	remove_action( 'pre_post_update', 'wp_save_post_revision' );
       
  1198 
       
  1199 	// Update the reply
       
  1200 	$reply_id = wp_insert_post( $reply );
       
  1201 
       
  1202 	// Execute post spam code
       
  1203 	do_action( 'bbp_spammed_reply', $reply_id );
       
  1204 
       
  1205 	// Return reply_id
       
  1206 	return $reply_id;
       
  1207 }
       
  1208 
       
  1209 /**
       
  1210  * Unspams a reply
       
  1211  *
       
  1212  * @since bbPress (r2740)
       
  1213  *
       
  1214  * @param int $reply_id Reply id
       
  1215  * @uses get_post() To get the reply
       
  1216  * @uses do_action() Calls 'bbp_unspam_reply' with the reply ID
       
  1217  * @uses get_post_meta() To get the previous status meta
       
  1218  * @uses delete_post_meta() To delete the previous status meta
       
  1219  * @uses wp_insert_post() To insert the updated post
       
  1220  * @uses do_action() Calls 'bbp_unspammed_reply' with the reply ID
       
  1221  * @return mixed False or {@link WP_Error} on failure, reply id on success
       
  1222  */
       
  1223 function bbp_unspam_reply( $reply_id = 0 ) {
       
  1224 
       
  1225 	// Get reply
       
  1226 	$reply = get_post( $reply_id, ARRAY_A );
       
  1227 	if ( empty( $reply ) )
       
  1228 		return $reply;
       
  1229 
       
  1230 	// Bail if already not spam
       
  1231 	if ( bbp_get_spam_status_id() != $reply['post_status'] )
       
  1232 		return false;
       
  1233 
       
  1234 	// Execute pre unspam code
       
  1235 	do_action( 'bbp_unspam_reply', $reply_id );
       
  1236 
       
  1237 	// Get pre spam status
       
  1238 	$reply['post_status'] = get_post_meta( $reply_id, '_bbp_spam_meta_status', true );
       
  1239 
       
  1240 	// Delete pre spam meta
       
  1241 	delete_post_meta( $reply_id, '_bbp_spam_meta_status' );
       
  1242 
       
  1243 	// No revisions
       
  1244 	remove_action( 'pre_post_update', 'wp_save_post_revision' );
       
  1245 
       
  1246 	// Update the reply
       
  1247 	$reply_id = wp_insert_post( $reply );
       
  1248 
       
  1249 	// Execute post unspam code
       
  1250 	do_action( 'bbp_unspammed_reply', $reply_id );
       
  1251 
       
  1252 	// Return reply_id
       
  1253 	return $reply_id;
       
  1254 }
       
  1255 
       
  1256 /** Before Delete/Trash/Untrash ***********************************************/
       
  1257 
       
  1258 /**
       
  1259  * Called before deleting a reply
       
  1260  *
       
  1261  * @uses bbp_get_reply_id() To get the reply id
       
  1262  * @uses bbp_is_reply() To check if the passed id is a reply
       
  1263  * @uses do_action() Calls 'bbp_delete_reply' with the reply id
       
  1264  */
       
  1265 function bbp_delete_reply( $reply_id = 0 ) {
       
  1266 	$reply_id = bbp_get_reply_id( $reply_id );
       
  1267 
       
  1268 	if ( empty( $reply_id ) || !bbp_is_reply( $reply_id ) )
       
  1269 		return false;
       
  1270 
       
  1271 	do_action( 'bbp_delete_reply', $reply_id );
       
  1272 }
       
  1273 
       
  1274 /**
       
  1275  * Called before trashing a reply
       
  1276  *
       
  1277  * @uses bbp_get_reply_id() To get the reply id
       
  1278  * @uses bbp_is_reply() To check if the passed id is a reply
       
  1279  * @uses do_action() Calls 'bbp_trash_reply' with the reply id
       
  1280  */
       
  1281 function bbp_trash_reply( $reply_id = 0 ) {
       
  1282 	$reply_id = bbp_get_reply_id( $reply_id );
       
  1283 
       
  1284 	if ( empty( $reply_id ) || !bbp_is_reply( $reply_id ) )
       
  1285 		return false;
       
  1286 
       
  1287 	do_action( 'bbp_trash_reply', $reply_id );
       
  1288 }
       
  1289 
       
  1290 /**
       
  1291  * Called before untrashing (restoring) a reply
       
  1292  *
       
  1293  * @uses bbp_get_reply_id() To get the reply id
       
  1294  * @uses bbp_is_reply() To check if the passed id is a reply
       
  1295  * @uses do_action() Calls 'bbp_unstrash_reply' with the reply id
       
  1296  */
       
  1297 function bbp_untrash_reply( $reply_id = 0 ) {
       
  1298 	$reply_id = bbp_get_reply_id( $reply_id );
       
  1299 
       
  1300 	if ( empty( $reply_id ) || !bbp_is_reply( $reply_id ) )
       
  1301 		return false;
       
  1302 
       
  1303 	do_action( 'bbp_untrash_reply', $reply_id );
       
  1304 }
       
  1305 
       
  1306 /** After Delete/Trash/Untrash ************************************************/
       
  1307 
       
  1308 /**
       
  1309  * Called after deleting a reply
       
  1310  *
       
  1311  * @uses bbp_get_reply_id() To get the reply id
       
  1312  * @uses bbp_is_reply() To check if the passed id is a reply
       
  1313  * @uses do_action() Calls 'bbp_deleted_reply' with the reply id
       
  1314  */
       
  1315 function bbp_deleted_reply( $reply_id = 0 ) {
       
  1316 	$reply_id = bbp_get_reply_id( $reply_id );
       
  1317 
       
  1318 	if ( empty( $reply_id ) || !bbp_is_reply( $reply_id ) )
       
  1319 		return false;
       
  1320 
       
  1321 	do_action( 'bbp_deleted_reply', $reply_id );
       
  1322 }
       
  1323 
       
  1324 /**
       
  1325  * Called after trashing a reply
       
  1326  *
       
  1327  * @uses bbp_get_reply_id() To get the reply id
       
  1328  * @uses bbp_is_reply() To check if the passed id is a reply
       
  1329  * @uses do_action() Calls 'bbp_trashed_reply' with the reply id
       
  1330  */
       
  1331 function bbp_trashed_reply( $reply_id = 0 ) {
       
  1332 	$reply_id = bbp_get_reply_id( $reply_id );
       
  1333 
       
  1334 	if ( empty( $reply_id ) || !bbp_is_reply( $reply_id ) )
       
  1335 		return false;
       
  1336 
       
  1337 	do_action( 'bbp_trashed_reply', $reply_id );
       
  1338 }
       
  1339 
       
  1340 /**
       
  1341  * Called after untrashing (restoring) a reply
       
  1342  *
       
  1343  * @uses bbp_get_reply_id() To get the reply id
       
  1344  * @uses bbp_is_reply() To check if the passed id is a reply
       
  1345  * @uses do_action() Calls 'bbp_untrashed_reply' with the reply id
       
  1346  */
       
  1347 function bbp_untrashed_reply( $reply_id = 0 ) {
       
  1348 	$reply_id = bbp_get_reply_id( $reply_id );
       
  1349 
       
  1350 	if ( empty( $reply_id ) || !bbp_is_reply( $reply_id ) )
       
  1351 		return false;
       
  1352 
       
  1353 	do_action( 'bbp_untrashed_reply', $reply_id );
       
  1354 }
       
  1355 
       
  1356 /** Settings ******************************************************************/
       
  1357 
       
  1358 /**
       
  1359  * Return the replies per page setting
       
  1360  *
       
  1361  * @since bbPress (r3540)
       
  1362  *
       
  1363  * @param int $default Default replies per page (15)
       
  1364  * @uses get_option() To get the setting
       
  1365  * @uses apply_filters() To allow the return value to be manipulated
       
  1366  * @return int
       
  1367  */
       
  1368 function bbp_get_replies_per_page( $default = 15 ) {
       
  1369 
       
  1370 	// Get database option and cast as integer
       
  1371 	$retval = get_option( '_bbp_replies_per_page', $default );
       
  1372 
       
  1373 	// If return val is empty, set it to default
       
  1374 	if ( empty( $retval ) )
       
  1375 		$retval = $default;
       
  1376 
       
  1377 	// Filter and return
       
  1378 	return (int) apply_filters( 'bbp_get_replies_per_page', $retval, $default );
       
  1379 }
       
  1380 
       
  1381 /**
       
  1382  * Return the replies per RSS page setting
       
  1383  *
       
  1384  * @since bbPress (r3540)
       
  1385  *
       
  1386  * @param int $default Default replies per page (25)
       
  1387  * @uses get_option() To get the setting
       
  1388  * @uses apply_filters() To allow the return value to be manipulated
       
  1389  * @return int
       
  1390  */
       
  1391 function bbp_get_replies_per_rss_page( $default = 25 ) {
       
  1392 
       
  1393 	// Get database option and cast as integer
       
  1394 	$retval = get_option( '_bbp_replies_per_rss_page', $default );
       
  1395 
       
  1396 	// If return val is empty, set it to default
       
  1397 	if ( empty( $retval ) )
       
  1398 		$retval = $default;
       
  1399 
       
  1400 	// Filter and return
       
  1401 	return (int) apply_filters( 'bbp_get_replies_per_rss_page', $retval, $default );
       
  1402 }
       
  1403 
       
  1404 /** Autoembed *****************************************************************/
       
  1405 
       
  1406 /**
       
  1407  * Check if autoembeds are enabled and hook them in if so
       
  1408  *
       
  1409  * @since bbPress (r3752)
       
  1410  * @global WP_Embed $wp_embed
       
  1411  */
       
  1412 function bbp_reply_content_autoembed() {
       
  1413 	global $wp_embed;
       
  1414 
       
  1415 	if ( bbp_use_autoembed() && is_a( $wp_embed, 'WP_Embed' ) ) {
       
  1416 		add_filter( 'bbp_get_reply_content', array( $wp_embed, 'autoembed' ), 8 );
       
  1417 	}
       
  1418 }
       
  1419 
       
  1420 /** Filters *******************************************************************/
       
  1421 
       
  1422 /**
       
  1423  * Used by bbp_has_replies() to add the topic to the posts
       
  1424  *
       
  1425  * This function filters the 'post_where' of the WP_Query, and changes the query
       
  1426  * to include both the topic AND its children in the same loop.
       
  1427  *
       
  1428  * @since bbPress (r4058)
       
  1429  *
       
  1430  * @param string $where
       
  1431  * @return string
       
  1432  */
       
  1433 function _bbp_has_replies_where( $where, $query ) {
       
  1434 
       
  1435 	// Bail if no post_parent to replace
       
  1436 	if ( ! is_numeric( $query->get( 'post_parent' ) ) )
       
  1437 		return $where;
       
  1438 
       
  1439 	// Bail if not a topic and reply query
       
  1440 	if ( array( bbp_get_topic_post_type(), bbp_get_reply_post_type() ) != $query->get( 'post_type' ) )
       
  1441 		return $where;
       
  1442 
       
  1443 	// Bail if meta query
       
  1444 	if ( $query->get( 'meta_key' ) || $query->get( 'meta_query' ) )
       
  1445 		return $where;
       
  1446 
       
  1447 	global $wpdb;
       
  1448 
       
  1449 	// Table name for posts
       
  1450 	$table_name = $wpdb->prefix . 'posts';
       
  1451 
       
  1452 	// Get the topic ID
       
  1453 	$topic_id   = bbp_get_topic_id();
       
  1454 
       
  1455 	// The text we're searching for
       
  1456 	$search     = "WHERE 1=1  AND {$table_name}.post_parent = {$topic_id}";
       
  1457 
       
  1458 	// The text to replace it with
       
  1459 	$replace    = "FORCE INDEX (PRIMARY, post_parent) WHERE 1=1 AND ({$table_name}.ID = {$topic_id} OR {$table_name}.post_parent = {$topic_id})";
       
  1460 
       
  1461 	// Try to replace the search text with the replacement
       
  1462 	if ( $new_where = str_replace( $search, $replace, $where ) )
       
  1463 		$where = $new_where;
       
  1464 
       
  1465 	return $where;
       
  1466 }
       
  1467 
       
  1468 /** Feeds *********************************************************************/
       
  1469 
       
  1470 /**
       
  1471  * Output an RSS2 feed of replies, based on the query passed.
       
  1472  *
       
  1473  * @since bbPress (r3171)
       
  1474  *
       
  1475  * @uses bbp_version()
       
  1476  * @uses bbp_is_single_topic()
       
  1477  * @uses bbp_user_can_view_forum()
       
  1478  * @uses bbp_get_topic_forum_id()
       
  1479  * @uses bbp_show_load_topic()
       
  1480  * @uses bbp_topic_permalink()
       
  1481  * @uses bbp_topic_title()
       
  1482  * @uses bbp_get_topic_reply_count()
       
  1483  * @uses bbp_topic_content()
       
  1484  * @uses bbp_has_replies()
       
  1485  * @uses bbp_replies()
       
  1486  * @uses bbp_the_reply()
       
  1487  * @uses bbp_reply_url()
       
  1488  * @uses bbp_reply_title()
       
  1489  * @uses bbp_reply_content()
       
  1490  * @uses get_wp_title_rss()
       
  1491  * @uses get_option()
       
  1492  * @uses bloginfo_rss
       
  1493  * @uses self_link()
       
  1494  * @uses the_author()
       
  1495  * @uses get_post_time()
       
  1496  * @uses rss_enclosure()
       
  1497  * @uses do_action()
       
  1498  * @uses apply_filters()
       
  1499  *
       
  1500  * @param array $replies_query
       
  1501  */
       
  1502 function bbp_display_replies_feed_rss2( $replies_query = array() ) {
       
  1503 
       
  1504 	// User cannot access forum this topic is in
       
  1505 	if ( bbp_is_single_topic() && !bbp_user_can_view_forum( array( 'forum_id' => bbp_get_topic_forum_id() ) ) )
       
  1506 		return;
       
  1507 
       
  1508 	// Adjust the title based on context
       
  1509 	if ( bbp_is_single_topic() && bbp_user_can_view_forum( array( 'forum_id' => bbp_get_topic_forum_id() ) ) )
       
  1510 		$title = apply_filters( 'wp_title_rss', get_wp_title_rss( ' &#187; ' ) );
       
  1511 	elseif ( !bbp_show_lead_topic() )
       
  1512 		$title = ' &#187; ' .  __( 'All Posts',   'bbpress' );
       
  1513 	else
       
  1514 		$title = ' &#187; ' .  __( 'All Replies', 'bbpress' );
       
  1515 
       
  1516 	// Display the feed
       
  1517 	header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), true );
       
  1518 	header( 'Status: 200 OK' );
       
  1519 	echo '<?xml version="1.0" encoding="' . get_option( 'blog_charset' ) . '"?' . '>'; ?>
       
  1520 
       
  1521 	<rss version="2.0"
       
  1522 		xmlns:content="http://purl.org/rss/1.0/modules/content/"
       
  1523 		xmlns:wfw="http://wellformedweb.org/CommentAPI/"
       
  1524 		xmlns:dc="http://purl.org/dc/elements/1.1/"
       
  1525 		xmlns:atom="http://www.w3.org/2005/Atom"
       
  1526 
       
  1527 		<?php do_action( 'bbp_feed' ); ?>
       
  1528 	>
       
  1529 
       
  1530 	<channel>
       
  1531 		<title><?php bloginfo_rss('name'); echo $title; ?></title>
       
  1532 		<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
       
  1533 		<link><?php self_link(); ?></link>
       
  1534 		<description><?php //?></description>
       
  1535 		<pubDate><?php echo mysql2date( 'D, d M Y H:i:s O', current_time( 'mysql' ), false ); ?></pubDate>
       
  1536 		<generator>http://bbpress.org/?v=<?php bbp_version(); ?></generator>
       
  1537 		<language><?php echo get_option( 'rss_language' ); ?></language>
       
  1538 
       
  1539 		<?php do_action( 'bbp_feed_head' ); ?>
       
  1540 
       
  1541 		<?php if ( bbp_is_single_topic() ) : ?>
       
  1542 			<?php if ( bbp_user_can_view_forum( array( 'forum_id' => bbp_get_topic_forum_id() ) ) ) : ?>
       
  1543 				<?php if ( bbp_show_lead_topic() ) : ?>
       
  1544 
       
  1545 					<item>
       
  1546 						<guid><?php bbp_topic_permalink(); ?></guid>
       
  1547 						<title><![CDATA[<?php bbp_topic_title(); ?>]]></title>
       
  1548 						<link><?php bbp_topic_permalink(); ?></link>
       
  1549 						<pubDate><?php echo mysql2date( 'D, d M Y H:i:s +0000', get_post_time( 'Y-m-d H:i:s', true ), false ); ?></pubDate>
       
  1550 						<dc:creator><?php the_author(); ?></dc:creator>
       
  1551 
       
  1552 						<description>
       
  1553 							<![CDATA[
       
  1554 							<p><?php printf( __( 'Replies: %s', 'bbpress' ), bbp_get_topic_reply_count() ); ?></p>
       
  1555 							<?php bbp_topic_content(); ?>
       
  1556 							]]>
       
  1557 						</description>
       
  1558 
       
  1559 						<?php rss_enclosure(); ?>
       
  1560 
       
  1561 						<?php do_action( 'bbp_feed_item' ); ?>
       
  1562 
       
  1563 					</item>
       
  1564 
       
  1565 				<?php endif; ?>
       
  1566 			<?php endif; ?>
       
  1567 		<?php endif; ?>
       
  1568 
       
  1569 		<?php if ( bbp_has_replies( $replies_query ) ) : ?>
       
  1570 			<?php while ( bbp_replies() ) : bbp_the_reply(); ?>
       
  1571 
       
  1572 				<item>
       
  1573 					<guid><?php bbp_reply_url(); ?></guid>
       
  1574 					<title><![CDATA[<?php bbp_reply_title(); ?>]]></title>
       
  1575 					<link><?php bbp_reply_url(); ?></link>
       
  1576 					<pubDate><?php echo mysql2date( 'D, d M Y H:i:s +0000', get_post_time( 'Y-m-d H:i:s', true ), false ); ?></pubDate>
       
  1577 					<dc:creator><?php the_author() ?></dc:creator>
       
  1578 
       
  1579 					<description>
       
  1580 						<![CDATA[
       
  1581 						<?php bbp_reply_content(); ?>
       
  1582 						]]>
       
  1583 					</description>
       
  1584 
       
  1585 					<?php rss_enclosure(); ?>
       
  1586 
       
  1587 					<?php do_action( 'bbp_feed_item' ); ?>
       
  1588 
       
  1589 				</item>
       
  1590 
       
  1591 			<?php endwhile; ?>
       
  1592 		<?php endif; ?>
       
  1593 
       
  1594 		<?php do_action( 'bbp_feed_footer' ); ?>
       
  1595 
       
  1596 	</channel>
       
  1597 	</rss>
       
  1598 
       
  1599 <?php
       
  1600 
       
  1601 	// We're done here
       
  1602 	exit();
       
  1603 }
       
  1604 
       
  1605 /** Permissions ***************************************************************/
       
  1606 
       
  1607 /**
       
  1608  * Redirect if unathorized user is attempting to edit a reply
       
  1609  *
       
  1610  * @since bbPress (r3605)
       
  1611  *
       
  1612  * @uses bbp_is_reply_edit()
       
  1613  * @uses current_user_can()
       
  1614  * @uses bbp_get_topic_id()
       
  1615  * @uses wp_safe_redirect()
       
  1616  * @uses bbp_get_topic_permalink()
       
  1617  */
       
  1618 function bbp_check_reply_edit() {
       
  1619 
       
  1620 	// Bail if not editing a topic
       
  1621 	if ( !bbp_is_reply_edit() )
       
  1622 		return;
       
  1623 
       
  1624 	// User cannot edit topic, so redirect back to reply
       
  1625 	if ( !current_user_can( 'edit_reply', bbp_get_reply_id() ) ) {
       
  1626 		wp_safe_redirect( bbp_get_reply_url() );
       
  1627 		exit();
       
  1628 	}
       
  1629 }
       
  1630 
       
  1631 /** Reply Position ************************************************************/
       
  1632 
       
  1633 /**
       
  1634  * Update the position of the reply.
       
  1635  *
       
  1636  * The reply position is stored in the menu_order column of the posts table.
       
  1637  * This is done to prevent using a meta_query to retrieve posts in the proper
       
  1638  * freshness order. By updating the menu_order accordingly, we're able to
       
  1639  * leverage core WordPress query ordering much more effectively.
       
  1640  *
       
  1641  * @since bbPress (r3933)
       
  1642  *
       
  1643  * @global type $wpdb
       
  1644  * @param type $reply_id
       
  1645  * @param type $reply_position
       
  1646  * @return mixed
       
  1647  */
       
  1648 function bbp_update_reply_position( $reply_id = 0, $reply_position = 0 ) {
       
  1649 
       
  1650 	// Bail if reply_id is empty
       
  1651 	$reply_id = bbp_get_reply_id( $reply_id );
       
  1652 	if ( empty( $reply_id ) )
       
  1653 		return false;
       
  1654 
       
  1655 	// If no position was passed, get it from the db and update the menu_order
       
  1656 	if ( empty( $reply_position ) ) {
       
  1657 		$reply_position = bbp_get_reply_position_raw( $reply_id, bbp_get_reply_topic_id( $reply_id ) );
       
  1658 	}
       
  1659 
       
  1660 	// Update the replies' 'menp_order' with the reply position
       
  1661 	global $wpdb;
       
  1662 	$wpdb->update( $wpdb->posts, array( 'menu_order' => $reply_position ), array( 'ID' => $reply_id ) );
       
  1663 
       
  1664 	return (int) $reply_position;
       
  1665 }
       
  1666 
       
  1667 /**
       
  1668  * Get the position of a reply by querying the DB directly for the replies
       
  1669  * of a given topic.
       
  1670  *
       
  1671  * @since bbPress (r3933)
       
  1672  *
       
  1673  * @param int $reply_id
       
  1674  * @param int $topic_id
       
  1675  */
       
  1676 function bbp_get_reply_position_raw( $reply_id = 0, $topic_id = 0 ) {
       
  1677 
       
  1678 	// Get required data
       
  1679 	$reply_id       = bbp_get_reply_id( $reply_id );
       
  1680 	$topic_id       = !empty( $topic_id ) ? bbp_get_topic_id( $topic_id ) : bbp_get_reply_topic_id( $reply_id );
       
  1681 	$reply_position = 0;
       
  1682 
       
  1683 	// If reply is actually the first post in a topic, return 0
       
  1684 	if ( $reply_id != $topic_id ) {
       
  1685 
       
  1686 		// Make sure the topic has replies before running another query
       
  1687 		$reply_count = bbp_get_topic_reply_count( $topic_id, false );
       
  1688 		if ( !empty( $reply_count ) ) {
       
  1689 
       
  1690 			// Get reply id's
       
  1691 			$topic_replies = bbp_get_all_child_ids( $topic_id, bbp_get_reply_post_type() );
       
  1692 			if ( !empty( $topic_replies ) ) {
       
  1693 
       
  1694 				// Reverse replies array and search for current reply position
       
  1695 				$topic_replies  = array_reverse( $topic_replies );
       
  1696 				$reply_position = array_search( (string) $reply_id, $topic_replies );
       
  1697 
       
  1698 				// Bump the position to compensate for the lead topic post
       
  1699 				$reply_position++;
       
  1700 			}
       
  1701 		}
       
  1702 	}
       
  1703 
       
  1704 	return (int) $reply_position;
       
  1705 }