PluginProbe
bbPress / 2.6.15
bbPress v2.6.15
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 2.6.15, at includes/forums/functions.php

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