PluginProbe
bbPress / 2.2
bbPress v2.2
trunk 2.0 2.0-beta-1 2.0-beta-2b 2.0-beta-3 2.0-beta-3b 2.0-rc-2 2.0-rc-3 2.0-rc-4 2.0-rc-5 2.0.1 2.0.2 2.0.3 2.1 2.1-beta-1 2.1-rc1 2.1-rc2 2.1-rc3 2.1-rc4 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.2.2 All 71 releases
bbpress / includes / replies / functions.php

functions.php in bbPress 2.2, at includes/replies/functions.php

1,706 lines 56.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 }
1706