PluginProbe
bbPress / trunk
bbPress vtrunk
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 / forums / functions.php

functions.php in bbPress trunk, at includes/forums/functions.php

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