Skip to:
Content

bbPress.org

source: trunk/src/includes/topics/functions.php @ 6304

Last change on this file since 6304 was 6304, checked in by johnjamesjacoby, 5 years ago

Feeds: Allow feed titles to be filtered (using the WordPress filter name.)

Also removes redundant conditional in replies feed.

Props SergeyBiryukov. Fixes #3064.

File size: 139.6 KB
Line 
1<?php
2
3/**
4 * bbPress Topic Functions
5 *
6 * @package bbPress
7 * @subpackage Functions
8 */
9
10// Exit if accessed directly
11defined( 'ABSPATH' ) || exit;
12
13/** Insert ********************************************************************/
14
15/**
16 * A wrapper for wp_insert_post() that also includes the necessary meta values
17 * for the topic to function properly.
18 *
19 * @since 2.0.0 bbPress (r3349)
20 *
21 * @uses bbp_parse_args()
22 * @uses bbp_get_topic_post_type()
23 * @uses wp_insert_post()
24 * @uses update_post_meta()
25 *
26 * @param array $topic_data Forum post data
27 * @param arrap $topic_meta Forum meta data
28 */
29function bbp_insert_topic( $topic_data = array(), $topic_meta = array() ) {
30
31        // Parse arguments against default values
32        $topic_data = bbp_parse_args( $topic_data, array(
33                'post_parent'    => 0, // forum ID
34                'post_status'    => bbp_get_public_status_id(),
35                'post_type'      => bbp_get_topic_post_type(),
36                'post_author'    => bbp_get_current_user_id(),
37                'post_password'  => '',
38                'post_content'   => '',
39                'post_title'     => '',
40                'comment_status' => 'closed',
41                'menu_order'     => 0,
42        ), 'insert_topic' );
43
44        // Insert topic
45        $topic_id = wp_insert_post( $topic_data );
46
47        // Bail if no topic was added
48        if ( empty( $topic_id ) ) {
49                return false;
50        }
51
52        // Parse arguments against default values
53        $topic_meta = bbp_parse_args( $topic_meta, array(
54                'author_ip'          => bbp_current_author_ip(),
55                'forum_id'           => 0,
56                'topic_id'           => $topic_id,
57                'voice_count'        => 1,
58                'reply_count'        => 0,
59                'reply_count_hidden' => 0,
60                'last_reply_id'      => 0,
61                'last_active_id'     => $topic_id,
62                'last_active_time'   => get_post_field( 'post_date', $topic_id, 'db' ),
63        ), 'insert_topic_meta' );
64
65        // Insert topic meta
66        foreach ( $topic_meta as $meta_key => $meta_value ) {
67                update_post_meta( $topic_id, '_bbp_' . $meta_key, $meta_value );
68        }
69
70        // Update the topic and hierarchy
71        bbp_update_topic( $topic_id, $topic_meta['forum_id'], array(), $topic_data['post_author'], false );
72
73        /**
74         * Fires after topic has been inserted via `bbp_insert_topic`.
75         *
76         * @since 2.6.0 bbPress (r6036)
77         *
78         * @param int $topic_id               The topic id.
79         * @param int $topic_meta['forum_id'] The topic forum meta.
80         */
81        do_action( 'bbp_insert_topic', (int) $topic_id, (int) $topic_meta['forum_id'] );
82
83        // Return new topic ID
84        return $topic_id;
85}
86
87/** Post Form Handlers ********************************************************/
88
89/**
90 * Handles the front end topic submission
91 *
92 * @param string $action The requested action to compare this function to
93 * @uses bbp_add_error() To add an error message
94 * @uses bbp_verify_nonce_request() To verify the nonce and check the referer
95 * @uses bbp_is_anonymous() To check if an anonymous post is being made
96 * @uses current_user_can() To check if the current user can publish topic
97 * @uses bbp_get_current_user_id() To get the current user id
98 * @uses bbp_filter_anonymous_post_data() To filter anonymous data
99 * @uses bbp_set_current_anonymous_user_data() To set the anonymous user cookies
100 * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error}
101 * @uses bbp_is_forum_category() To check if the forum is a category
102 * @uses bbp_is_forum_closed() To check if the forum is closed
103 * @uses bbp_is_forum_private() To check if the forum is private
104 * @uses bbp_check_for_flood() To check for flooding
105 * @uses bbp_check_for_duplicate() To check for duplicates
106 * @uses bbp_get_topic_post_type() To get the topic post type
107 * @uses remove_filter() To remove kses filters if needed
108 * @uses apply_filters() Calls 'bbp_new_topic_pre_title' with the content
109 * @uses apply_filters() Calls 'bbp_new_topic_pre_content' with the content
110 * @uses bbPress::errors::get_error_codes() To get the {@link WP_Error} errors
111 * @uses wp_insert_post() To insert the topic
112 * @uses get_post_field() To get the post status
113 * @uses bbp_get_closed_status_id() To get the closed status id
114 * @uses bbp_close_topic() To close topics
115 * @uses bbp_get_trash_status_id() To get the trash status id
116 * @uses wp_trash_post() To trash topics
117 * @uses bbp_get_spam_status_id() To get the spam status id
118 * @uses add_post_meta() To add spam status meta to spam topics
119 * @uses do_action() Calls 'bbp_new_topic' with the topic id, forum id,
120 *                    anonymous data and reply author
121 * @uses bbp_stick_topic() To stick or super stick the topic
122 * @uses bbp_unstick_topic() To unstick the topic
123 * @uses bbp_get_topic_permalink() To get the topic permalink
124 * @uses bbp_redirect() To redirect to the topic link
125 * @uses bbPress::errors::get_error_messages() To get the {@link WP_Error} error
126 *                                              messages
127 */
128function bbp_new_topic_handler( $action = '' ) {
129
130        // Bail if action is not bbp-new-topic
131        if ( 'bbp-new-topic' !== $action ) {
132                return;
133        }
134
135        // Nonce check
136        if ( ! bbp_verify_nonce_request( 'bbp-new-topic' ) ) {
137                bbp_add_error( 'bbp_new_topic_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
138                return;
139        }
140
141        // Define local variable(s)
142        $view_all = false;
143        $forum_id = $topic_author = $anonymous_data = 0;
144        $topic_title = $topic_content = '';
145        $terms = array( bbp_get_topic_tag_tax_id() => array() );
146
147        /** Topic Author **********************************************************/
148
149        // User is anonymous
150        if ( bbp_is_anonymous() ) {
151
152                // Filter anonymous data
153                $anonymous_data = bbp_filter_anonymous_post_data();
154
155                // Anonymous data checks out, so set cookies, etc...
156                if ( ! empty( $anonymous_data ) && is_array( $anonymous_data ) ) {
157                        bbp_set_current_anonymous_user_data( $anonymous_data );
158                }
159
160        // User is logged in
161        } else {
162
163                // User cannot create topics
164                if ( ! current_user_can( 'publish_topics' ) ) {
165                        bbp_add_error( 'bbp_topic_permission', __( '<strong>ERROR</strong>: You do not have permission to create new topics.', 'bbpress' ) );
166                        return;
167                }
168
169                // Topic author is current user
170                $topic_author = bbp_get_current_user_id();
171        }
172
173        // Remove kses filters from title and content for capable users and if the nonce is verified
174        if ( current_user_can( 'unfiltered_html' ) && ! empty( $_POST['_bbp_unfiltered_html_topic'] ) && wp_create_nonce( 'bbp-unfiltered-html-topic_new' ) === $_POST['_bbp_unfiltered_html_topic'] ) {
175                remove_filter( 'bbp_new_topic_pre_title',   'wp_filter_kses'      );
176                remove_filter( 'bbp_new_topic_pre_content', 'bbp_encode_bad',  10 );
177                remove_filter( 'bbp_new_topic_pre_content', 'bbp_filter_kses', 30 );
178        }
179
180        /** Topic Title ***********************************************************/
181
182        if ( ! empty( $_POST['bbp_topic_title'] ) ) {
183                $topic_title = sanitize_text_field( $_POST['bbp_topic_title'] );
184        }
185
186        // Filter and sanitize
187        $topic_title = apply_filters( 'bbp_new_topic_pre_title', $topic_title );
188
189        // No topic title
190        if ( empty( $topic_title ) ) {
191                bbp_add_error( 'bbp_topic_title', __( '<strong>ERROR</strong>: Your topic needs a title.', 'bbpress' ) );
192        }
193
194        /** Topic Content *********************************************************/
195
196        if ( ! empty( $_POST['bbp_topic_content'] ) ) {
197                $topic_content = $_POST['bbp_topic_content'];
198        }
199
200        // Filter and sanitize
201        $topic_content = apply_filters( 'bbp_new_topic_pre_content', $topic_content );
202
203        // No topic content
204        if ( empty( $topic_content ) ) {
205                bbp_add_error( 'bbp_topic_content', __( '<strong>ERROR</strong>: Your topic cannot be empty.', 'bbpress' ) );
206        }
207
208        /** Topic Forum ***********************************************************/
209
210        // Error check the POST'ed topic id
211        if ( isset( $_POST['bbp_forum_id'] ) ) {
212
213                // Empty Forum id was passed
214                if ( empty( $_POST['bbp_forum_id'] ) ) {
215                        bbp_add_error( 'bbp_topic_forum_id', __( '<strong>ERROR</strong>: Forum ID is missing.', 'bbpress' ) );
216
217                // Forum id is not a number
218                } elseif ( ! is_numeric( $_POST['bbp_forum_id'] ) ) {
219                        bbp_add_error( 'bbp_topic_forum_id', __( '<strong>ERROR</strong>: Forum ID must be a number.', 'bbpress' ) );
220
221                // Forum id might be valid
222                } else {
223
224                        // Get the forum id
225                        $posted_forum_id = intval( $_POST['bbp_forum_id'] );
226
227                        // Forum id is empty
228                        if ( 0 === $posted_forum_id ) {
229                                bbp_add_error( 'bbp_topic_forum_id', __( '<strong>ERROR</strong>: Forum ID is missing.', 'bbpress' ) );
230
231                        // Forum id is a negative number
232                        } elseif ( 0 > $posted_forum_id ) {
233                                bbp_add_error( 'bbp_topic_forum_id', __( '<strong>ERROR</strong>: Forum ID cannot be a negative number.', 'bbpress' ) );
234
235                        // Forum does not exist
236                        } elseif ( ! bbp_get_forum( $posted_forum_id ) ) {
237                                bbp_add_error( 'bbp_topic_forum_id', __( '<strong>ERROR</strong>: Forum does not exist.', 'bbpress' ) );
238
239                        // Use the POST'ed forum id
240                        } else {
241                                $forum_id = $posted_forum_id;
242                        }
243                }
244        }
245
246        // Forum exists
247        if ( ! empty( $forum_id ) ) {
248
249                // Forum is a category
250                if ( bbp_is_forum_category( $forum_id ) ) {
251                        bbp_add_error( 'bbp_new_topic_forum_category', __( '<strong>ERROR</strong>: This forum is a category. No topics can be created in this forum.', 'bbpress' ) );
252
253                // Forum is not a category
254                } else {
255
256                        // Forum is closed and user cannot access
257                        if ( bbp_is_forum_closed( $forum_id ) && ! current_user_can( 'edit_forum', $forum_id ) ) {
258                                bbp_add_error( 'bbp_new_topic_forum_closed', __( '<strong>ERROR</strong>: This forum has been closed to new topics.', 'bbpress' ) );
259                        }
260
261                        // Forum is private and user cannot access
262                        if ( bbp_is_forum_private( $forum_id ) ) {
263                                if ( ! current_user_can( 'read_private_forums' ) ) {
264                                        bbp_add_error( 'bbp_new_topic_forum_private', __( '<strong>ERROR</strong>: This forum is private and you do not have the capability to read or create new topics in it.', 'bbpress' ) );
265                                }
266
267                        // Forum is hidden and user cannot access
268                        } elseif ( bbp_is_forum_hidden( $forum_id ) ) {
269                                if ( ! current_user_can( 'read_hidden_forums' ) ) {
270                                        bbp_add_error( 'bbp_new_topic_forum_hidden', __( '<strong>ERROR</strong>: This forum is hidden and you do not have the capability to read or create new topics in it.', 'bbpress' ) );
271                                }
272                        }
273                }
274        }
275
276        /** Topic Flooding ********************************************************/
277
278        if ( ! bbp_check_for_flood( $anonymous_data, $topic_author ) ) {
279                bbp_add_error( 'bbp_topic_flood', __( '<strong>ERROR</strong>: Slow down; you move too fast.', 'bbpress' ) );
280        }
281
282        /** Topic Duplicate *******************************************************/
283
284        if ( ! bbp_check_for_duplicate( array( 'post_type' => bbp_get_topic_post_type(), 'post_author' => $topic_author, 'post_content' => $topic_content, 'anonymous_data' => $anonymous_data ) ) ) {
285                bbp_add_error( 'bbp_topic_duplicate', __( '<strong>ERROR</strong>: Duplicate topic detected; it looks as though you&#8217;ve already said that.', 'bbpress' ) );
286        }
287
288        /** Topic Blacklist *******************************************************/
289
290        if ( ! bbp_check_for_blacklist( $anonymous_data, $topic_author, $topic_title, $topic_content ) ) {
291                bbp_add_error( 'bbp_topic_blacklist', __( '<strong>ERROR</strong>: Your topic cannot be created at this time.', 'bbpress' ) );
292        }
293
294        /** Topic Status **********************************************************/
295
296        // Get available topic statuses
297        $topic_statuses = bbp_get_topic_statuses();
298
299        // Maybe put into moderation
300        if ( ! bbp_check_for_moderation( $anonymous_data, $topic_author, $topic_title, $topic_content ) ) {
301                $topic_status = bbp_get_pending_status_id();
302
303        // Check a whitelist of possible topic status ID's
304        } elseif ( ! empty( $_POST['bbp_topic_status'] ) && in_array( $_POST['bbp_topic_status'], array_keys( $topic_statuses ) ) ) {
305                $topic_status = sanitize_key( $_POST['bbp_topic_status'] );
306
307        // Default to published if nothing else
308        } else {
309                $topic_status = bbp_get_public_status_id();
310        }
311
312        /** Topic Tags ************************************************************/
313
314        if ( bbp_allow_topic_tags() && ! empty( $_POST['bbp_topic_tags'] ) ) {
315
316                // Escape tag input
317                $terms = sanitize_text_field( $_POST['bbp_topic_tags'] );
318
319                // Explode by comma
320                if ( strstr( $terms, ',' ) ) {
321                        $terms = explode( ',', $terms );
322                }
323
324                // Add topic tag ID as main key
325                $terms = array( bbp_get_topic_tag_tax_id() => $terms );
326        }
327
328        /** Additional Actions (Before Save) **************************************/
329
330        do_action( 'bbp_new_topic_pre_extras', $forum_id );
331
332        // Bail if errors
333        if ( bbp_has_errors() ) {
334                return;
335        }
336
337        /** No Errors *************************************************************/
338
339        // Add the content of the form to $topic_data as an array.
340        // Just in time manipulation of topic data before being created
341        $topic_data = apply_filters( 'bbp_new_topic_pre_insert', array(
342                'post_author'    => $topic_author,
343                'post_title'     => $topic_title,
344                'post_content'   => $topic_content,
345                'post_status'    => $topic_status,
346                'post_parent'    => $forum_id,
347                'post_type'      => bbp_get_topic_post_type(),
348                'tax_input'      => $terms,
349                'comment_status' => 'closed'
350        ) );
351
352        // Insert topic
353        $topic_id = wp_insert_post( $topic_data );
354
355        /** No Errors *************************************************************/
356
357        if ( ! empty( $topic_id ) && ! is_wp_error( $topic_id ) ) {
358
359                /** Close Check *******************************************************/
360
361                // If the topic is closed, close it properly
362                if ( ( get_post_field( 'post_status', $topic_id ) === bbp_get_closed_status_id() ) || ( $topic_data['post_status'] === bbp_get_closed_status_id() ) ) {
363
364                        // Close the topic
365                        bbp_close_topic( $topic_id );
366                }
367
368                /** Trash Check *******************************************************/
369
370                // If the forum is trash, or the topic_status is switched to
371                // trash, trash the topic properly
372                if ( ( get_post_field( 'post_status', $forum_id ) === bbp_get_trash_status_id() ) || ( $topic_data['post_status'] === bbp_get_trash_status_id() ) ) {
373
374                        // Trash the topic
375                        wp_trash_post( $topic_id );
376
377                        // Force view=all
378                        $view_all = true;
379                }
380
381                /** Spam Check ********************************************************/
382
383                // If the topic is spam, officially spam this topic
384                if ( $topic_data['post_status'] === bbp_get_spam_status_id() ) {
385                        add_post_meta( $topic_id, '_bbp_spam_meta_status', bbp_get_public_status_id() );
386
387                        // Force view=all
388                        $view_all = true;
389                }
390
391                /** Update counts, etc... *********************************************/
392
393                do_action( 'bbp_new_topic', $topic_id, $forum_id, $anonymous_data, $topic_author );
394
395                /** Additional Actions (After Save) ***********************************/
396
397                do_action( 'bbp_new_topic_post_extras', $topic_id );
398
399                /** Redirect **********************************************************/
400
401                // Redirect to
402                $redirect_to = bbp_get_redirect_to();
403
404                // Get the topic URL
405                $redirect_url = bbp_get_topic_permalink( $topic_id, $redirect_to );
406
407                // Add view all?
408                if ( bbp_get_view_all() || ! empty( $view_all ) ) {
409
410                        // User can moderate, so redirect to topic with view all set
411                        if ( current_user_can( 'moderate', $topic_id ) ) {
412                                $redirect_url = bbp_add_view_all( $redirect_url );
413
414                        // User cannot moderate, so redirect to forum
415                        } else {
416                                $redirect_url = bbp_get_forum_permalink( $forum_id );
417                        }
418                }
419
420                // Allow to be filtered
421                $redirect_url = apply_filters( 'bbp_new_topic_redirect_to', $redirect_url, $redirect_to, $topic_id );
422
423                /** Successful Save ***************************************************/
424
425                // Redirect back to new topic
426                bbp_redirect( $redirect_url );
427
428        // Errors
429        } else {
430                $append_error = ( is_wp_error( $topic_id ) && $topic_id->get_error_message() ) ? $topic_id->get_error_message() . ' ' : '';
431                bbp_add_error( 'bbp_topic_error', __( '<strong>ERROR</strong>: The following problem(s) have been found with your topic:' . $append_error, 'bbpress' ) );
432        }
433}
434
435/**
436 * Handles the front end edit topic submission
437 *
438 * @param string $action The requested action to compare this function to
439 * @uses bbp_add_error() To add an error message
440 * @uses bbp_get_topic() To get the topic
441 * @uses bbp_verify_nonce_request() To verify the nonce and check the request
442 * @uses bbp_is_topic_anonymous() To check if topic is by an anonymous user
443 * @uses current_user_can() To check if the current user can edit the topic
444 * @uses bbp_filter_anonymous_post_data() To filter anonymous data
445 * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error}
446 * @uses bbp_is_forum_category() To check if the forum is a category
447 * @uses bbp_is_forum_closed() To check if the forum is closed
448 * @uses bbp_is_forum_private() To check if the forum is private
449 * @uses remove_filter() To remove kses filters if needed
450 * @uses apply_filters() Calls 'bbp_edit_topic_pre_title' with the title and
451 *                        topic id
452 * @uses apply_filters() Calls 'bbp_edit_topic_pre_content' with the content
453 *                        and topic id
454 * @uses bbPress::errors::get_error_codes() To get the {@link WP_Error} errors
455 * @uses wp_save_post_revision() To save a topic revision
456 * @uses bbp_update_topic_revision_log() To update the topic revision log
457 * @uses bbp_stick_topic() To stick or super stick the topic
458 * @uses bbp_unstick_topic() To unstick the topic
459 * @uses wp_update_post() To update the topic
460 * @uses do_action() Calls 'bbp_edit_topic' with the topic id, forum id,
461 *                    anonymous data and reply author
462 * @uses bbp_move_topic_handler() To handle movement of a topic from one forum
463 *                                 to another
464 * @uses bbp_get_topic_permalink() To get the topic permalink
465 * @uses bbp_redirect() To redirect to the topic link
466 * @uses bbPress::errors::get_error_messages() To get the {@link WP_Error} error
467 *                                              messages
468 */
469function bbp_edit_topic_handler( $action = '' ) {
470
471        // Bail if action is not bbp-edit-topic
472        if ( 'bbp-edit-topic' !== $action ) {
473                return;
474        }
475
476        // Define local variable(s)
477        $revisions_removed = false;
478        $topic = $topic_id = $topic_author = $forum_id = $anonymous_data = 0;
479        $topic_title = $topic_content = $topic_edit_reason = '';
480
481        /** Topic *****************************************************************/
482
483        // Topic id was not passed
484        if ( empty( $_POST['bbp_topic_id'] ) ) {
485                bbp_add_error( 'bbp_edit_topic_id', __( '<strong>ERROR</strong>: Topic ID not found.', 'bbpress' ) );
486                return;
487
488        // Topic id was passed
489        } elseif ( is_numeric( $_POST['bbp_topic_id'] ) ) {
490                $topic_id = (int) $_POST['bbp_topic_id'];
491                $topic    = bbp_get_topic( $topic_id );
492        }
493
494        // Topic does not exist
495        if ( empty( $topic ) ) {
496                bbp_add_error( 'bbp_edit_topic_not_found', __( '<strong>ERROR</strong>: The topic you want to edit was not found.', 'bbpress' ) );
497                return;
498
499        // Topic exists
500        } else {
501
502                // Check users ability to create new topic
503                if ( ! bbp_is_topic_anonymous( $topic_id ) ) {
504
505                        // User cannot edit this topic
506                        if ( ! current_user_can( 'edit_topic', $topic_id ) ) {
507                                bbp_add_error( 'bbp_edit_topic_permission', __( '<strong>ERROR</strong>: You do not have permission to edit that topic.', 'bbpress' ) );
508                        }
509
510                        // Set topic author
511                        $topic_author = bbp_get_topic_author_id( $topic_id );
512
513                // It is an anonymous post
514                } else {
515
516                        // Filter anonymous data
517                        $anonymous_data = bbp_filter_anonymous_post_data( array(), true );
518                }
519        }
520
521        // Nonce check
522        if ( ! bbp_verify_nonce_request( 'bbp-edit-topic_' . $topic_id ) ) {
523                bbp_add_error( 'bbp_edit_topic_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
524                return;
525        }
526
527        // Remove kses filters from title and content for capable users and if the nonce is verified
528        if ( current_user_can( 'unfiltered_html' ) && ! empty( $_POST['_bbp_unfiltered_html_topic'] ) && ( wp_create_nonce( 'bbp-unfiltered-html-topic_' . $topic_id ) === $_POST['_bbp_unfiltered_html_topic'] ) ) {
529                remove_filter( 'bbp_edit_topic_pre_title',   'wp_filter_kses'      );
530                remove_filter( 'bbp_edit_topic_pre_content', 'bbp_encode_bad',  10 );
531                remove_filter( 'bbp_edit_topic_pre_content', 'bbp_filter_kses', 30 );
532        }
533
534        /** Topic Forum ***********************************************************/
535
536        // Forum id was not passed
537        if ( empty( $_POST['bbp_forum_id'] ) ) {
538                bbp_add_error( 'bbp_topic_forum_id', __( '<strong>ERROR</strong>: Forum ID is missing.', 'bbpress' ) );
539
540        // Forum id was passed
541        } elseif ( is_numeric( $_POST['bbp_forum_id'] ) ) {
542                $forum_id = (int) $_POST['bbp_forum_id'];
543        }
544
545        // Current forum this topic is in
546        $current_forum_id = bbp_get_topic_forum_id( $topic_id );
547
548        // Forum exists
549        if ( ! empty( $forum_id ) && ( $forum_id !== $current_forum_id ) ) {
550
551                // Forum is a category
552                if ( bbp_is_forum_category( $forum_id ) ) {
553                        bbp_add_error( 'bbp_edit_topic_forum_category', __( '<strong>ERROR</strong>: This forum is a category. No topics can be created in it.', 'bbpress' ) );
554
555                // Forum is not a category
556                } else {
557
558                        // Forum is closed and user cannot access
559                        if ( bbp_is_forum_closed( $forum_id ) && ! current_user_can( 'edit_forum', $forum_id ) ) {
560                                bbp_add_error( 'bbp_edit_topic_forum_closed', __( '<strong>ERROR</strong>: This forum has been closed to new topics.', 'bbpress' ) );
561                        }
562
563                        // Forum is private and user cannot access
564                        if ( bbp_is_forum_private( $forum_id ) ) {
565                                if ( ! current_user_can( 'read_private_forums' ) ) {
566                                        bbp_add_error( 'bbp_edit_topic_forum_private', __( '<strong>ERROR</strong>: This forum is private and you do not have the capability to read or create new topics in it.', 'bbpress' ) );
567                                }
568
569                        // Forum is hidden and user cannot access
570                        } elseif ( bbp_is_forum_hidden( $forum_id ) ) {
571                                if ( ! current_user_can( 'read_hidden_forums' ) ) {
572                                        bbp_add_error( 'bbp_edit_topic_forum_hidden', __( '<strong>ERROR</strong>: This forum is hidden and you do not have the capability to read or create new topics in it.', 'bbpress' ) );
573                                }
574                        }
575                }
576        }
577
578        /** Topic Title ***********************************************************/
579
580        if ( ! empty( $_POST['bbp_topic_title'] ) ) {
581                $topic_title = sanitize_text_field( $_POST['bbp_topic_title'] );
582        }
583
584        // Filter and sanitize
585        $topic_title = apply_filters( 'bbp_edit_topic_pre_title', $topic_title, $topic_id );
586
587        // No topic title
588        if ( empty( $topic_title ) ) {
589                bbp_add_error( 'bbp_edit_topic_title', __( '<strong>ERROR</strong>: Your topic needs a title.', 'bbpress' ) );
590        }
591
592        /** Topic Content *********************************************************/
593
594        if ( ! empty( $_POST['bbp_topic_content'] ) ) {
595                $topic_content = $_POST['bbp_topic_content'];
596        }
597
598        // Filter and sanitize
599        $topic_content = apply_filters( 'bbp_edit_topic_pre_content', $topic_content, $topic_id );
600
601        // No topic content
602        if ( empty( $topic_content ) ) {
603                bbp_add_error( 'bbp_edit_topic_content', __( '<strong>ERROR</strong>: Your topic cannot be empty.', 'bbpress' ) );
604        }
605
606        /** Topic Blacklist *******************************************************/
607
608        if ( ! bbp_check_for_blacklist( $anonymous_data, $topic_author, $topic_title, $topic_content ) ) {
609                bbp_add_error( 'bbp_topic_blacklist', __( '<strong>ERROR</strong>: Your topic cannot be edited at this time.', 'bbpress' ) );
610        }
611
612        /** Topic Status **********************************************************/
613
614        // Get available topic statuses
615        $topic_statuses = bbp_get_topic_statuses( $topic_id );
616
617        // Maybe put into moderation
618        if ( ! bbp_check_for_moderation( $anonymous_data, $topic_author, $topic_title, $topic_content ) ) {
619
620                // Set post status to pending if public or closed
621                if ( in_array( $topic->post_status, array( bbp_get_public_status_id(), bbp_get_closed_status_id() ) ) ) {
622                        $topic_status = bbp_get_pending_status_id();
623                }
624
625        // Check a whitelist of possible topic status ID's
626        } elseif ( ! empty( $_POST['bbp_topic_status'] ) && in_array( $_POST['bbp_topic_status'], array_keys( $topic_statuses ) ) ) {
627                $topic_status = sanitize_key( $_POST['bbp_topic_status'] );
628
629        // Use existing post_status
630        } else {
631                $topic_status = $topic->post_status;
632        }
633
634        /** Topic Tags ************************************************************/
635
636        // Either replace terms
637        if ( bbp_allow_topic_tags() && current_user_can( 'assign_topic_tags' ) && ! empty( $_POST['bbp_topic_tags'] ) ) {
638
639                // Escape tag input
640                $terms = sanitize_text_field( $_POST['bbp_topic_tags'] );
641
642                // Explode by comma
643                if ( strstr( $terms, ',' ) ) {
644                        $terms = explode( ',', $terms );
645                }
646
647                // Add topic tag ID as main key
648                $terms = array( bbp_get_topic_tag_tax_id() => $terms );
649
650        // ...or remove them.
651        } elseif ( isset( $_POST['bbp_topic_tags'] ) ) {
652                $terms = array( bbp_get_topic_tag_tax_id() => array() );
653
654        // Existing terms
655        } else {
656                $terms = array( bbp_get_topic_tag_tax_id() => explode( ',', bbp_get_topic_tag_names( $topic_id, ',' ) ) );
657        }
658
659        /** Additional Actions (Before Save) **************************************/
660
661        do_action( 'bbp_edit_topic_pre_extras', $topic_id );
662
663        // Bail if errors
664        if ( bbp_has_errors() ) {
665                return;
666        }
667
668        /** No Errors *************************************************************/
669
670        // Add the content of the form to $topic_data as an array
671        // Just in time manipulation of topic data before being edited
672        $topic_data = apply_filters( 'bbp_edit_topic_pre_insert', array(
673                'ID'           => $topic_id,
674                'post_title'   => $topic_title,
675                'post_content' => $topic_content,
676                'post_status'  => $topic_status,
677                'post_parent'  => $forum_id,
678                'post_author'  => $topic_author,
679                'post_type'    => bbp_get_topic_post_type(),
680                'tax_input'    => $terms,
681        ) );
682
683        // Toggle revisions to avoid duplicates
684        if ( post_type_supports( bbp_get_topic_post_type(), 'revisions' ) ) {
685                $revisions_removed = true;
686                remove_post_type_support( bbp_get_topic_post_type(), 'revisions' );
687        }
688
689        // Insert topic
690        $topic_id = wp_update_post( $topic_data );
691
692        // Toggle revisions back on
693        if ( true === $revisions_removed ) {
694                $revisions_removed = false;
695                add_post_type_support( bbp_get_topic_post_type(), 'revisions' );
696        }
697
698        /** No Errors *************************************************************/
699
700        if ( ! empty( $topic_id ) && ! is_wp_error( $topic_id ) ) {
701
702                // Update counts, etc...
703                do_action( 'bbp_edit_topic', $topic_id, $forum_id, $anonymous_data, $topic_author , true /* Is edit */ );
704
705                /** Revisions *********************************************************/
706
707                // Revision Reason
708                if ( ! empty( $_POST['bbp_topic_edit_reason'] ) ) {
709                        $topic_edit_reason = sanitize_text_field( $_POST['bbp_topic_edit_reason'] );
710                }
711
712                // Update revision log
713                if ( ! empty( $_POST['bbp_log_topic_edit'] ) && ( "1" === $_POST['bbp_log_topic_edit'] ) )  {
714                        $revision_id = wp_save_post_revision( $topic_id );
715                        if ( ! empty( $revision_id ) ) {
716                                bbp_update_topic_revision_log( array(
717                                        'topic_id'    => $topic_id,
718                                        'revision_id' => $revision_id,
719                                        'author_id'   => bbp_get_current_user_id(),
720                                        'reason'      => $topic_edit_reason
721                                ) );
722                        }
723                }
724
725                /** Move Topic ********************************************************/
726
727                // If the new forum id is not equal to the old forum id, run the
728                // bbp_move_topic action and pass the topic's forum id as the
729                // first arg and topic id as the second to update counts.
730                if ( $forum_id !== $topic->post_parent ) {
731                        bbp_move_topic_handler( $topic_id, $topic->post_parent, $forum_id );
732                }
733
734                /** Additional Actions (After Save) ***********************************/
735
736                do_action( 'bbp_edit_topic_post_extras', $topic_id );
737
738                /** Redirect **********************************************************/
739
740                // Redirect to
741                $redirect_to = bbp_get_redirect_to();
742
743                // View all?
744                $view_all = bbp_get_view_all();
745
746                // Get the topic URL
747                $topic_url = bbp_get_topic_permalink( $topic_id, $redirect_to );
748
749                // Add view all?
750                if ( ! empty( $view_all ) ) {
751                        $topic_url = bbp_add_view_all( $topic_url );
752                }
753
754                // Allow to be filtered
755                $topic_url = apply_filters( 'bbp_edit_topic_redirect_to', $topic_url, $view_all, $redirect_to );
756
757                /** Successful Edit ***************************************************/
758
759                // Redirect back to new topic
760                bbp_redirect( $topic_url );
761
762        /** Errors ****************************************************************/
763
764        } else {
765                $append_error = ( is_wp_error( $topic_id ) && $topic_id->get_error_message() ) ? $topic_id->get_error_message() . ' ' : '';
766                bbp_add_error( 'bbp_topic_error', __( '<strong>ERROR</strong>: The following problem(s) have been found with your topic:' . $append_error . 'Please try again.', 'bbpress' ) );
767        }
768}
769
770/**
771 * Handle all the extra meta stuff from posting a new topic
772 *
773 * @param int $topic_id Optional. Topic id
774 * @param int $forum_id Optional. Forum id
775 * @param bool|array $anonymous_data Optional logged-out user data.
776 * @param int $author_id Author id
777 * @param bool $is_edit Optional. Is the post being edited? Defaults to false.
778 * @uses bbp_get_topic_id() To get the topic id
779 * @uses bbp_get_forum_id() To get the forum id
780 * @uses bbp_get_current_user_id() To get the current user id
781 * @uses bbp_get_topic_forum_id() To get the topic forum id
782 * @uses update_post_meta() To update the topic metas
783 * @uses set_transient() To update the flood check transient for the ip
784 * @uses bbp_update_user_last_posted() To update the users last posted time
785 * @uses bbp_is_subscriptions_active() To check if the subscriptions feature is
786 *                                      activated or not
787 * @uses bbp_is_user_subscribed() To check if the user is subscribed
788 * @uses bbp_remove_user_subscription() To remove the user's subscription
789 * @uses bbp_add_user_subscription() To add the user's subscription
790 * @uses bbp_update_topic_forum_id() To update the topic's forum id
791 * @uses bbp_update_topic_topic_id() To update the topic's topic id
792 * @uses bbp_update_topic_last_reply_id() To update the last reply id topic meta
793 * @uses bbp_update_topic_last_active_id() To update the topic last active id
794 * @uses bbp_update_topic_last_active_time() To update the last active topic meta
795 * @uses bbp_update_topic_reply_count() To update the topic reply count
796 * @uses bbp_update_topic_reply_count_hidden() To udpate the topic hidden reply count
797 * @uses bbp_update_topic_voice_count() To update the topic voice count
798 * @uses bbp_update_topic_walker() To udpate the topic's ancestors
799 */
800function bbp_update_topic( $topic_id = 0, $forum_id = 0, $anonymous_data = false, $author_id = 0, $is_edit = false ) {
801
802        // Validate the ID's passed from 'bbp_new_topic' action
803        $topic_id = bbp_get_topic_id( $topic_id );
804        $forum_id = bbp_get_forum_id( $forum_id );
805
806        // Bail if there is no topic
807        if ( empty( $topic_id ) ) {
808                return;
809        }
810
811        // Check author_id
812        if ( empty( $author_id ) ) {
813                $author_id = bbp_get_current_user_id();
814        }
815
816        // Check forum_id
817        if ( empty( $forum_id ) ) {
818                $forum_id = bbp_get_topic_forum_id( $topic_id );
819        }
820
821        // Get the topic types
822        $topic_types = bbp_get_topic_types( $topic_id );
823
824        // Sticky check after 'bbp_new_topic' action so forum ID meta is set
825        if ( ! empty( $_POST['bbp_stick_topic'] ) && in_array( $_POST['bbp_stick_topic'], array_keys( $topic_types ) ) ) {
826
827                // What's the caps?
828                if ( current_user_can( 'moderate', $topic_id ) ) {
829
830                        // What's the haps?
831                        switch ( $_POST['bbp_stick_topic'] ) {
832
833                                // Sticky in this forum
834                                case 'stick'   :
835                                        bbp_stick_topic( $topic_id );
836                                        break;
837
838                                // Super sticky in all forums
839                                case 'super'   :
840                                        bbp_stick_topic( $topic_id, true );
841                                        break;
842
843                                // We can avoid this as it is a new topic
844                                case 'unstick' :
845                                default        :
846                                        break;
847                        }
848                }
849        }
850
851        // If anonymous post, store name, email, website and ip in post_meta.
852        // It expects anonymous_data to be sanitized.
853        // Check bbp_filter_anonymous_post_data() for sanitization.
854        if ( ! empty( $anonymous_data ) && is_array( $anonymous_data ) ) {
855
856                // Parse arguments against default values
857                $r = bbp_parse_args( $anonymous_data, array(
858                        'bbp_anonymous_name'    => '',
859                        'bbp_anonymous_email'   => '',
860                        'bbp_anonymous_website' => '',
861                ), 'update_topic' );
862
863                // Update all anonymous metas
864                foreach ( $r as $anon_key => $anon_value ) {
865                        update_post_meta( $topic_id, '_' . $anon_key, (string) $anon_value, false );
866                }
867
868                // Set transient for throttle check (only on new, not edit)
869                if ( empty( $is_edit ) ) {
870                        set_transient( '_bbp_' . bbp_current_author_ip() . '_last_posted', time() );
871                }
872
873        } else {
874                if ( empty( $is_edit ) && ! current_user_can( 'throttle' ) ) {
875                        bbp_update_user_last_posted( $author_id );
876                }
877        }
878
879        // Handle Subscription Checkbox
880        if ( bbp_is_subscriptions_active() && ! empty( $author_id ) ) {
881                $subscribed = bbp_is_user_subscribed( $author_id, $topic_id );
882                $subscheck  = ( ! empty( $_POST['bbp_topic_subscription'] ) && ( 'bbp_subscribe' === $_POST['bbp_topic_subscription'] ) ) ? true : false;
883
884                // Subscribed and unsubscribing
885                if ( true === $subscribed && false === $subscheck ) {
886                        bbp_remove_user_subscription( $author_id, $topic_id );
887
888                // Subscribing
889                } elseif ( false === $subscribed && true === $subscheck ) {
890                        bbp_add_user_subscription( $author_id, $topic_id );
891                }
892        }
893
894        // Forum topic meta
895        bbp_update_topic_forum_id( $topic_id, $forum_id );
896        bbp_update_topic_topic_id( $topic_id, $topic_id );
897
898        // Update associated topic values if this is a new topic
899        if ( empty( $is_edit ) ) {
900
901                // Update poster IP if not editing
902                update_post_meta( $topic_id, '_bbp_author_ip', bbp_current_author_ip(), false );
903
904                // Last active time
905                $last_active = get_post_field( 'post_date', $topic_id );
906
907                // Reply topic meta
908                bbp_update_topic_last_reply_id      ( $topic_id, 0            );
909                bbp_update_topic_last_active_id     ( $topic_id, $topic_id    );
910                bbp_update_topic_last_active_time   ( $topic_id, $last_active );
911                bbp_update_topic_reply_count        ( $topic_id, 0            );
912                bbp_update_topic_reply_count_hidden ( $topic_id, 0            );
913                bbp_update_topic_voice_count        ( $topic_id               );
914
915                // Walk up ancestors and do the dirty work
916                bbp_update_topic_walker( $topic_id, $last_active, $forum_id, 0, false );
917        }
918}
919
920/**
921 * Walks up the post_parent tree from the current topic_id, and updates the
922 * counts of forums above it. This calls a few internal functions that all run
923 * manual queries against the database to get their results. As such, this
924 * function can be costly to run but is necessary to keep everything accurate.
925 *
926 * @since 2.0.0 bbPress (r2800)
927 *
928 * @param int $topic_id Topic id
929 * @param string $last_active_time Optional. Last active time
930 * @param int $forum_id Optional. Forum id
931 * @param int $reply_id Optional. Reply id
932 * @param bool $refresh Reset all the previous parameters? Defaults to true.
933 * @uses bbp_get_topic_id() To get the topic id
934 * @uses bbp_get_topic_forum_id() To get the topic forum id
935 * @uses get_post_ancestors() To get the topic's ancestors
936 * @uses bbp_is_forum() To check if the ancestor is a forum
937 * @uses bbp_update_forum() To update the forum
938 */
939function bbp_update_topic_walker( $topic_id, $last_active_time = '', $forum_id = 0, $reply_id = 0, $refresh = true ) {
940
941        // Validate topic_id
942        $topic_id  = bbp_get_topic_id( $topic_id );
943
944        // Define local variable(s)
945        $active_id = 0;
946
947        // Topic was passed
948        if ( ! empty( $topic_id ) ) {
949
950                // Get the forum ID if none was passed
951                if ( empty( $forum_id )  ) {
952                        $forum_id = bbp_get_topic_forum_id( $topic_id );
953
954                        // Make every effort to get forum id
955                        // https://bbpress.trac.wordpress.org/ticket/2529
956                        if ( empty( $forum_id ) && ( current_filter() === 'bbp_deleted_topic' ) ) {
957                                $forum_id = get_post_field( 'post_parent', $topic_id );
958                        }
959                }
960
961                // Set the active_id based on topic_id/reply_id
962                $active_id = empty( $reply_id ) ? $topic_id : $reply_id;
963        }
964
965        // Get topic ancestors
966        $ancestors = array_values( array_unique( array_merge( array( $forum_id ), (array) get_post_ancestors( $topic_id ) ) ) );
967
968        // Topic status
969        $topic_status = get_post_status( $topic_id );
970
971        // If we want a full refresh, unset any of the possibly passed variables
972        if ( true === $refresh ) {
973                $forum_id = $topic_id = $reply_id = $active_id = $last_active_time = 0;
974                $topic_status = bbp_get_public_status_id();
975        }
976
977        // Loop through ancestors
978        if ( ! empty( $ancestors ) ) {
979                foreach ( $ancestors as $ancestor ) {
980
981                        // If ancestor is a forum, update counts
982                        if ( bbp_is_forum( $ancestor ) ) {
983
984                                // Update the forum
985                                bbp_update_forum( array(
986                                        'forum_id'           => $ancestor,
987                                        'last_topic_id'      => $topic_id,
988                                        'last_reply_id'      => $reply_id,
989                                        'last_active_id'     => $active_id,
990                                        'last_active_time'   => $last_active_time,
991                                        'last_active_status' => $topic_status
992                                ) );
993                        }
994                }
995        }
996}
997
998/**
999 * Handle the moving of a topic from one forum to another. This includes walking
1000 * up the old and new branches and updating the counts.
1001 *
1002 * @since 2.0.0 bbPress (r2907)
1003 *
1004 * @param int $topic_id     The topic id.
1005 * @param int $old_forum_id Old forum id.
1006 * @param int $new_forum_id New forum id.
1007 * @uses bbp_get_topic_id() To get the topic id
1008 * @uses bbp_get_forum_id() To get the forum id
1009 * @uses bbp_clean_post_cache() To clean the old and new forum post caches
1010 * @uses bbp_update_topic_forum_id() To update the topic forum id
1011 * @uses wp_update_post() To update the topic post parent`
1012 * @uses bbp_get_stickies() To get the old forums sticky topics
1013 * @uses delete_post_meta() To delete the forum sticky meta
1014 * @uses update_post_meta() To update the old forum sticky meta
1015 * @uses bbp_stick_topic() To stick the topic in the new forum
1016 * @uses bbp_get_reply_post_type() To get the reply post type
1017 * @uses bbp_get_all_child_ids() To get all the child ids
1018 * @uses bbp_update_reply_forum_id() To update the reply forum id
1019 * @uses get_post_ancestors() To get the topic's ancestors
1020 * @uses bbp_get_public_child_ids() To get all the public child ids
1021 * @uses get_post_field() To get the topic's post status
1022 * @uses bbp_get_public_status_id() To get the public status id
1023 * @uses bbp_decrease_forum_topic_count() To bump the forum topic count by -1
1024 * @uses bbp_bump_forum_reply_count() To bump the forum reply count
1025 * @uses bbp_increase_forum_topic_count() To bump the forum topic count by 1
1026 * @uses bbp_decrease_forum_topic_count_hidden() To bump the forum topic hidden count by -1
1027 * @uses bbp_increase_forum_topic_count_hidden() To bump the forum topic hidden count by 1
1028 * @uses bbp_is_forum() To check if the ancestor is a forum
1029 * @uses bbp_update_forum() To update the forum
1030 */
1031function bbp_move_topic_handler( $topic_id, $old_forum_id, $new_forum_id ) {
1032
1033        // Validate parameters
1034        $topic_id     = bbp_get_topic_id( $topic_id     );
1035        $old_forum_id = bbp_get_forum_id( $old_forum_id );
1036        $new_forum_id = bbp_get_forum_id( $new_forum_id );
1037
1038        // Clean old and new forum caches before proceeding, to ensure subsequent
1039        // calls to forum objects are using updated data.
1040        bbp_clean_post_cache( $old_forum_id );
1041        bbp_clean_post_cache( $new_forum_id );
1042
1043        // Update topic forum's ID
1044        bbp_update_topic_forum_id( $topic_id, $new_forum_id );
1045
1046        // Update topic post parent with the new forum ID
1047        wp_update_post( array(
1048                'ID'          => $topic_id,
1049                'post_parent' => $new_forum_id,
1050        ) );
1051
1052        /** Stickies **************************************************************/
1053
1054        // Get forum stickies
1055        $old_stickies = bbp_get_stickies( $old_forum_id );
1056
1057        // Only proceed if stickies are found
1058        if ( ! empty( $old_stickies ) ) {
1059
1060                // Define local variables
1061                $updated_stickies = array();
1062
1063                // Loop through stickies of forum and add misses to the updated array
1064                foreach ( (array) $old_stickies as $sticky_topic_id ) {
1065                        if ( $topic_id !== $sticky_topic_id ) {
1066                                $updated_stickies[] = $sticky_topic_id;
1067                        }
1068                }
1069
1070                // If stickies are different, update or delete them
1071                if ( $updated_stickies !== $old_stickies ) {
1072
1073                        // No more stickies so delete the meta
1074                        if ( empty( $updated_stickies ) ) {
1075                                delete_post_meta( $old_forum_id, '_bbp_sticky_topics' );
1076
1077                        // Still stickies so update the meta
1078                        } else {
1079                                update_post_meta( $old_forum_id, '_bbp_sticky_topics', $updated_stickies );
1080                        }
1081
1082                        // Topic was sticky, so restick in new forum
1083                        bbp_stick_topic( $topic_id );
1084                }
1085        }
1086
1087        /** Topic Replies *********************************************************/
1088
1089        // Get the topics replies
1090        $replies = bbp_get_all_child_ids( $topic_id, bbp_get_reply_post_type() );
1091
1092        // Update the forum_id of all replies in the topic
1093        foreach ( $replies as $reply_id ) {
1094                bbp_update_reply_forum_id( $reply_id, $new_forum_id );
1095        }
1096
1097        /** Old forum_id **********************************************************/
1098
1099        // Get topic ancestors
1100        $old_forum_ancestors = array_values( array_unique( array_merge( array( $old_forum_id ), (array) get_post_ancestors( $old_forum_id ) ) ) );
1101
1102        // Get reply count.
1103        $public_reply_count = count( bbp_get_public_child_ids( $topic_id, bbp_get_reply_post_type() ) );
1104
1105        // Topic status.
1106        $topic_status = get_post_field( 'post_status', $topic_id );
1107
1108        // Update old/new forum counts.
1109        if ( $topic_status === bbp_get_public_status_id() ) {
1110
1111                // Update old forum counts.
1112                bbp_decrease_forum_topic_count( $old_forum_id );
1113                bbp_bump_forum_reply_count( $old_forum_id, -$public_reply_count );
1114
1115                // Update new forum counts.
1116                bbp_increase_forum_topic_count( $new_forum_id );
1117                bbp_bump_forum_reply_count( $new_forum_id, $public_reply_count );
1118        } else {
1119
1120                // Update old forum counts.
1121                bbp_decrease_forum_topic_count_hidden( $old_forum_id );
1122
1123                // Update new forum counts.
1124                bbp_increase_forum_topic_count_hidden( $new_forum_id );
1125        }
1126
1127        // Loop through ancestors and update them
1128        if ( ! empty( $old_forum_ancestors ) ) {
1129                foreach ( $old_forum_ancestors as $ancestor ) {
1130                        if ( bbp_is_forum( $ancestor ) ) {
1131                                bbp_update_forum( array(
1132                                        'forum_id' => $ancestor,
1133                                ) );
1134                        }
1135                }
1136        }
1137
1138        /** New forum_id **********************************************************/
1139
1140        // Make sure we're not walking twice
1141        if ( ! in_array( $new_forum_id, $old_forum_ancestors ) ) {
1142
1143                // Get topic ancestors
1144                $new_forum_ancestors = array_values( array_unique( array_merge( array( $new_forum_id ), (array) get_post_ancestors( $new_forum_id ) ) ) );
1145
1146                // Make sure we're not walking twice
1147                $new_forum_ancestors = array_diff( $new_forum_ancestors, $old_forum_ancestors );
1148
1149                // Loop through ancestors and update them
1150                if ( ! empty( $new_forum_ancestors ) ) {
1151                        foreach ( $new_forum_ancestors as $ancestor ) {
1152                                if ( bbp_is_forum( $ancestor ) ) {
1153                                        bbp_update_forum( array(
1154                                                'forum_id' => $ancestor,
1155                                        ) );
1156                                }
1157                        }
1158                }
1159        }
1160}
1161
1162/**
1163 * Merge topic handler
1164 *
1165 * Handles the front end merge topic submission
1166 *
1167 * @since 2.0.0 bbPress (r2756)
1168 *
1169 * @param string $action The requested action to compare this function to
1170 * @uses bbp_add_error() To add an error message
1171 * @uses bbp_get_topic() To get the topics
1172 * @uses bbp_verify_nonce_request() To verify the nonce and check the request
1173 * @uses current_user_can() To check if the current user can edit the topics
1174 * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error}
1175 * @uses do_action() Calls 'bbp_merge_topic' with the destination and source
1176 *                    topic ids
1177 * @uses bbp_get_topic_subscribers() To get the source topic subscribers
1178 * @uses bbp_add_user_subscription() To add the user subscription
1179 * @uses bbp_remove_user_subscription() To remove the user subscription
1180 * @uses bbp_get_topic_favoriters() To get the source topic favoriters
1181 * @uses bbp_add_user_favorite() To add the user favorite
1182 * @uses bbp_remove_user_favorite() To remove the user favorite
1183 * @uses wp_get_post_terms() To get the source topic tags
1184 * @uses wp_set_post_terms() To set the topic tags
1185 * @uses wp_delete_object_term_relationships() To delete the topic tags
1186 * @uses bbp_open_topic() To open the topic
1187 * @uses bbp_unstick_topic() To unstick the topic
1188 * @uses bbp_get_reply_post_type() To get the reply post type
1189 * @uses get_posts() To get the replies
1190 * @uses wp_update_post() To update the topic
1191 * @uses bbp_update_reply_topic_id() To update the reply topic id
1192 * @uses bbp_get_topic_forum_id() To get the topic forum id
1193 * @uses bbp_update_reply_forum_id() To update the reply forum id
1194 * @uses do_action() Calls 'bbp_merged_topic_reply' with the reply id and
1195 *                    destination topic id
1196 * @uses do_action() Calls 'bbp_merged_topic' with the destination and source
1197 *                    topic ids and source topic's forum id
1198 * @uses bbp_get_topic_permalink() To get the topic permalink
1199 * @uses bbp_redirect() To redirect to the topic link
1200 */
1201function bbp_merge_topic_handler( $action = '' ) {
1202
1203        // Bail if action is not bbp-merge-topic
1204        if ( 'bbp-merge-topic' !== $action ) {
1205                return;
1206        }
1207
1208        // Define local variable(s)
1209        $source_topic_id = $destination_topic_id = 0;
1210        $source_topic = $destination_topic = 0;
1211        $subscribers = $favoriters = $replies = array();
1212
1213        /** Source Topic **********************************************************/
1214
1215        // Topic id
1216        if ( empty( $_POST['bbp_topic_id'] ) ) {
1217                bbp_add_error( 'bbp_merge_topic_source_id', __( '<strong>ERROR</strong>: Topic ID not found.', 'bbpress' ) );
1218        } else {
1219                $source_topic_id = (int) $_POST['bbp_topic_id'];
1220        }
1221
1222        // Nonce check
1223        if ( ! bbp_verify_nonce_request( 'bbp-merge-topic_' . $source_topic_id ) ) {
1224                bbp_add_error( 'bbp_merge_topic_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
1225                return;
1226
1227        // Source topic not found
1228        } elseif ( ! $source_topic = bbp_get_topic( $source_topic_id ) ) {
1229                bbp_add_error( 'bbp_merge_topic_source_not_found', __( '<strong>ERROR</strong>: The topic you want to merge was not found.', 'bbpress' ) );
1230                return;
1231        }
1232
1233        // Cannot edit source topic
1234        if ( ! current_user_can( 'edit_topic', $source_topic->ID ) ) {
1235                bbp_add_error( 'bbp_merge_topic_source_permission', __( '<strong>ERROR</strong>: You do not have permission to edit the source topic.', 'bbpress' ) );
1236                return;
1237        }
1238
1239        /** Destination Topic *****************************************************/
1240
1241        // Topic id
1242        if ( empty( $_POST['bbp_destination_topic'] ) ) {
1243                bbp_add_error( 'bbp_merge_topic_destination_id', __( '<strong>ERROR</strong>: Destination topic ID not found.', 'bbpress' ) );
1244        } else {
1245                $destination_topic_id = (int) $_POST['bbp_destination_topic'];
1246        }
1247
1248        // Destination topic not found
1249        if ( ! $destination_topic = bbp_get_topic( $destination_topic_id ) ) {
1250                bbp_add_error( 'bbp_merge_topic_destination_not_found', __( '<strong>ERROR</strong>: The topic you want to merge to was not found.', 'bbpress' ) );
1251        }
1252
1253        // Cannot edit destination topic
1254        if ( ! current_user_can( 'edit_topic', $destination_topic->ID ) ) {
1255                bbp_add_error( 'bbp_merge_topic_destination_permission', __( '<strong>ERROR</strong>: You do not have permission to edit the destination topic.', 'bbpress' ) );
1256        }
1257
1258        // Bail if errors
1259        if ( bbp_has_errors() ) {
1260                return;
1261        }
1262
1263        /** No Errors *************************************************************/
1264
1265        // Update counts, etc...
1266        do_action( 'bbp_merge_topic', $destination_topic->ID, $source_topic->ID );
1267
1268        /** Date Check ************************************************************/
1269
1270        // Check if the destination topic is older than the source topic
1271        if ( strtotime( $source_topic->post_date ) < strtotime( $destination_topic->post_date ) ) {
1272
1273                // Set destination topic post_date to 1 second before source topic
1274                $destination_post_date = date( 'Y-m-d H:i:s', strtotime( $source_topic->post_date ) - 1 );
1275
1276                // Update destination topic
1277                wp_update_post( array(
1278                        'ID'            => $destination_topic_id,
1279                        'post_date'     => $destination_post_date,
1280                        'post_date_gmt' => get_gmt_from_date( $destination_post_date )
1281                ) );
1282        }
1283
1284        /** Subscriptions *********************************************************/
1285
1286        // Get subscribers from source topic
1287        $subscribers = bbp_get_topic_subscribers( $source_topic->ID );
1288
1289        // Remove the topic from everybody's subscriptions
1290        if ( ! empty( $subscribers ) ) {
1291
1292                // Loop through each user
1293                foreach ( (array) $subscribers as $subscriber ) {
1294
1295                        // Shift the subscriber if told to
1296                        if ( ! empty( $_POST['bbp_topic_subscribers'] ) && ( "1" === $_POST['bbp_topic_subscribers'] ) && bbp_is_subscriptions_active() ) {
1297                                bbp_add_user_subscription( $subscriber, $destination_topic->ID );
1298                        }
1299
1300                        // Remove old subscription
1301                        bbp_remove_user_subscription( $subscriber, $source_topic->ID );
1302                }
1303        }
1304
1305        /** Favorites *************************************************************/
1306
1307        // Get favoriters from source topic
1308        $favoriters = bbp_get_topic_favoriters( $source_topic->ID );
1309
1310        // Remove the topic from everybody's favorites
1311        if ( ! empty( $favoriters ) ) {
1312
1313                // Loop through each user
1314                foreach ( (array) $favoriters as $favoriter ) {
1315
1316                        // Shift the favoriter if told to
1317                        if ( ! empty( $_POST['bbp_topic_favoriters'] ) && "1" === $_POST['bbp_topic_favoriters'] ) {
1318                                bbp_add_user_favorite( $favoriter, $destination_topic->ID );
1319                        }
1320
1321                        // Remove old favorite
1322                        bbp_remove_user_favorite( $favoriter, $source_topic->ID );
1323                }
1324        }
1325
1326        /** Tags ******************************************************************/
1327
1328        // Get the source topic tags
1329        $source_topic_tags = wp_get_post_terms( $source_topic->ID, bbp_get_topic_tag_tax_id(), array( 'fields' => 'names' ) );
1330
1331        // Tags to possibly merge
1332        if ( ! empty( $source_topic_tags ) && ! is_wp_error( $source_topic_tags ) ) {
1333
1334                // Shift the tags if told to
1335                if ( ! empty( $_POST['bbp_topic_tags'] ) && ( "1" === $_POST['bbp_topic_tags'] ) ) {
1336                        wp_set_post_terms( $destination_topic->ID, $source_topic_tags, bbp_get_topic_tag_tax_id(), true );
1337                }
1338
1339                // Delete the tags from the source topic
1340                wp_delete_object_term_relationships( $source_topic->ID, bbp_get_topic_tag_tax_id() );
1341        }
1342
1343        /** Source Topic **********************************************************/
1344
1345        // Status
1346        bbp_open_topic( $source_topic->ID );
1347
1348        // Sticky
1349        bbp_unstick_topic( $source_topic->ID );
1350
1351        // Delete source topic's last & count meta data
1352        delete_post_meta( $source_topic->ID, '_bbp_last_reply_id'      );
1353        delete_post_meta( $source_topic->ID, '_bbp_last_active_id'     );
1354        delete_post_meta( $source_topic->ID, '_bbp_last_active_time'   );
1355        delete_post_meta( $source_topic->ID, '_bbp_voice_count'        );
1356        delete_post_meta( $source_topic->ID, '_bbp_reply_count'        );
1357        delete_post_meta( $source_topic->ID, '_bbp_reply_count_hidden' );
1358
1359        // Get the replies of the source topic
1360        $replies = (array) get_posts( array(
1361                'post_parent'    => $source_topic->ID,
1362                'post_type'      => bbp_get_reply_post_type(),
1363                'posts_per_page' => -1,
1364                'order'          => 'ASC'
1365        ) );
1366
1367        // Prepend the source topic to its replies array for processing
1368        array_unshift( $replies, $source_topic );
1369
1370        if ( ! empty( $replies ) ) {
1371
1372                /** Merge Replies *****************************************************/
1373
1374                // Change the post_parent of each reply to the destination topic id
1375                foreach ( $replies as $reply ) {
1376
1377                        // Update the reply
1378                        wp_update_post( array(
1379                                'ID'          => $reply->ID,
1380                                'post_title'  => '',
1381                                'post_name'   => false,
1382                                'post_type'   => bbp_get_reply_post_type(),
1383                                'post_parent' => $destination_topic->ID,
1384                                'guid'        => ''
1385                        ) );
1386
1387                        // Adjust reply meta values
1388                        bbp_update_reply_topic_id( $reply->ID, $destination_topic->ID                           );
1389                        bbp_update_reply_forum_id( $reply->ID, bbp_get_topic_forum_id( $destination_topic->ID ) );
1390
1391                        // Update the reply position
1392                        bbp_update_reply_position( $reply->ID );
1393
1394                        // Do additional actions per merged reply
1395                        do_action( 'bbp_merged_topic_reply', $reply->ID, $destination_topic->ID );
1396                }
1397        }
1398
1399        /** Successful Merge ******************************************************/
1400
1401        // Update topic's last meta data
1402        bbp_update_topic_last_reply_id   ( $destination_topic->ID );
1403        bbp_update_topic_last_active_id  ( $destination_topic->ID );
1404        bbp_update_topic_last_active_time( $destination_topic->ID );
1405
1406        // Send the post parent of the source topic as it has been shifted
1407        // (possibly to a new forum) so we need to update the counts of the
1408        // old forum as well as the new one
1409        do_action( 'bbp_merged_topic', $destination_topic->ID, $source_topic->ID, $source_topic->post_parent );
1410
1411        // Redirect back to new topic
1412        bbp_redirect( bbp_get_topic_permalink( $destination_topic->ID ) );
1413}
1414
1415/**
1416 * Fix counts on topic merge
1417 *
1418 * When a topic is merged, update the counts of source and destination topic
1419 * and their forums.
1420 *
1421 * @since 2.0.0 bbPress (r2756)
1422 *
1423 * @param int $destination_topic_id Destination topic id
1424 * @param int $source_topic_id Source topic id
1425 * @param int $source_topic_forum_id Source topic's forum id
1426 * @uses bbp_update_forum_topic_count() To update the forum topic counts
1427 * @uses bbp_update_forum_reply_count() To update the forum reply counts
1428 * @uses bbp_update_topic_reply_count() To update the topic reply counts
1429 * @uses bbp_update_topic_voice_count() To update the topic voice counts
1430 * @uses bbp_update_topic_reply_count_hidden() To update the topic hidden reply
1431 *                                              count
1432 * @uses do_action() Calls 'bbp_merge_topic_count' with the destination topic
1433 *                    id, source topic id & source topic forum id
1434 */
1435function bbp_merge_topic_count( $destination_topic_id, $source_topic_id, $source_topic_forum_id ) {
1436
1437        /** Source Topic **********************************************************/
1438
1439        // Forum Topic Counts
1440        bbp_update_forum_topic_count( $source_topic_forum_id );
1441
1442        // Forum Reply Counts
1443        bbp_update_forum_reply_count( $source_topic_forum_id );
1444
1445        /** Destination Topic *****************************************************/
1446
1447        // Topic Reply Counts
1448        bbp_update_topic_reply_count( $destination_topic_id );
1449
1450        // Topic Hidden Reply Counts
1451        bbp_update_topic_reply_count_hidden( $destination_topic_id );
1452
1453        // Topic Voice Counts
1454        bbp_update_topic_voice_count( $destination_topic_id );
1455
1456        do_action( 'bbp_merge_topic_count', $destination_topic_id, $source_topic_id, $source_topic_forum_id );
1457}
1458
1459/**
1460 * Split topic handler
1461 *
1462 * Handles the front end split topic submission
1463 *
1464 * @since 2.0.0 bbPress (r2756)
1465 *
1466 * @param string $action The requested action to compare this function to
1467 * @uses bbp_add_error() To add an error message
1468 * @uses bbp_get_reply() To get the reply
1469 * @uses bbp_get_topic() To get the topics
1470 * @uses bbp_verify_nonce_request() To verify the nonce and check the request
1471 * @uses current_user_can() To check if the current user can edit the topics
1472 * @uses bbp_get_topic_post_type() To get the topic post type
1473 * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error}
1474 * @uses do_action() Calls 'bbp_pre_split_topic' with the from reply id, source
1475 *                    and destination topic ids
1476 * @uses bbp_get_topic_subscribers() To get the source topic subscribers
1477 * @uses bbp_add_user_subscription() To add the user subscription
1478 * @uses bbp_get_topic_favoriters() To get the source topic favoriters
1479 * @uses bbp_add_user_favorite() To add the user favorite
1480 * @uses wp_get_post_terms() To get the source topic tags
1481 * @uses wp_set_post_terms() To set the topic tags
1482 * @uses bbp_get_reply_post_type() To get the reply post type
1483 * @uses wpdb::prepare() To prepare our sql query
1484 * @uses wpdb::get_results() To execute the sql query and get results
1485 * @uses wp_update_post() To update the replies
1486 * @uses bbp_update_reply_topic_id() To update the reply topic id
1487 * @uses bbp_get_topic_forum_id() To get the topic forum id
1488 * @uses bbp_update_reply_forum_id() To update the reply forum id
1489 * @uses do_action() Calls 'bbp_split_topic_reply' with the reply id and
1490 *                    destination topic id
1491 * @uses bbp_update_topic_last_reply_id() To update the topic last reply id
1492 * @uses bbp_update_topic_last_active_time() To update the topic last active meta
1493 * @uses do_action() Calls 'bbp_post_split_topic' with the destination and
1494 *                    source topic ids and source topic's forum id
1495 * @uses bbp_get_topic_permalink() To get the topic permalink
1496 * @uses bbp_redirect() To redirect to the topic link
1497 */
1498function bbp_split_topic_handler( $action = '' ) {
1499
1500        // Bail if action is not 'bbp-split-topic'
1501        if ( 'bbp-split-topic' !== $action ) {
1502                return;
1503        }
1504
1505        // Prevent debug notices
1506        $from_reply_id = $destination_topic_id = 0;
1507        $destination_topic_title = '';
1508        $destination_topic = $from_reply = $source_topic = '';
1509        $split_option = false;
1510
1511        /** Split Reply ***********************************************************/
1512
1513        if ( empty( $_POST['bbp_reply_id'] ) ) {
1514                bbp_add_error( 'bbp_split_topic_reply_id', __( '<strong>ERROR</strong>: A reply ID is required.', 'bbpress' ) );
1515        } else {
1516                $from_reply_id = (int) $_POST['bbp_reply_id'];
1517        }
1518
1519        $from_reply = bbp_get_reply( $from_reply_id );
1520
1521        // Reply exists
1522        if ( empty( $from_reply ) ) {
1523                bbp_add_error( 'bbp_split_topic_r_not_found', __( '<strong>ERROR</strong>: The reply you want to split from was not found.', 'bbpress' ) );
1524        }
1525
1526        /** Topic to Split ********************************************************/
1527
1528        // Get the topic being split
1529        $source_topic = bbp_get_topic( $from_reply->post_parent );
1530
1531        // No topic
1532        if ( empty( $source_topic ) ) {
1533                bbp_add_error( 'bbp_split_topic_source_not_found', __( '<strong>ERROR</strong>: The topic you want to split was not found.', 'bbpress' ) );
1534        }
1535
1536        // Nonce check failed
1537        if ( ! bbp_verify_nonce_request( 'bbp-split-topic_' . $source_topic->ID ) ) {
1538                bbp_add_error( 'bbp_split_topic_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
1539                return;
1540        }
1541
1542        // Use cannot edit topic
1543        if ( ! current_user_can( 'edit_topic', $source_topic->ID ) ) {
1544                bbp_add_error( 'bbp_split_topic_source_permission', __( '<strong>ERROR</strong>: You do not have permission to edit the source topic.', 'bbpress' ) );
1545        }
1546
1547        // How to Split
1548        if ( ! empty( $_POST['bbp_topic_split_option'] ) ) {
1549                $split_option = sanitize_key( $_POST['bbp_topic_split_option'] );
1550        }
1551
1552        // Invalid split option
1553        if ( empty( $split_option ) || ! in_array( $split_option, array( 'existing', 'reply' ) ) ) {
1554                bbp_add_error( 'bbp_split_topic_option', __( '<strong>ERROR</strong>: You need to choose a valid split option.', 'bbpress' ) );
1555
1556        // Valid Split Option
1557        } else {
1558
1559                // What kind of split
1560                switch ( $split_option ) {
1561
1562                        // Into an existing topic
1563                        case 'existing' :
1564
1565                                // Get destination topic id
1566                                if ( empty( $_POST['bbp_destination_topic'] ) ) {
1567                                        bbp_add_error( 'bbp_split_topic_destination_id', __( '<strong>ERROR</strong>: A topic ID is required.', 'bbpress' ) );
1568                                } else {
1569                                        $destination_topic_id = (int) $_POST['bbp_destination_topic'];
1570                                }
1571
1572                                // Get the destination topic
1573                                $destination_topic = bbp_get_topic( $destination_topic_id );
1574
1575                                // No destination topic
1576                                if ( empty( $destination_topic ) ) {
1577                                        bbp_add_error( 'bbp_split_topic_destination_not_found', __( '<strong>ERROR</strong>: The topic you want to split to was not found.', 'bbpress' ) );
1578                                }
1579
1580                                // User cannot edit the destination topic
1581                                if ( ! current_user_can( 'edit_topic', $destination_topic->ID ) ) {
1582                                        bbp_add_error( 'bbp_split_topic_destination_permission', __( '<strong>ERROR</strong>: You do not have permission to edit the destination topic.', 'bbpress' ) );
1583                                }
1584
1585                                break;
1586
1587                        // Split at reply into a new topic
1588                        case 'reply' :
1589                        default :
1590
1591                                // User needs to be able to publish topics
1592                                if ( current_user_can( 'publish_topics' ) ) {
1593
1594                                        // Use the new title that was passed
1595                                        if ( ! empty( $_POST['bbp_topic_split_destination_title'] ) ) {
1596                                                $destination_topic_title = sanitize_text_field( $_POST['bbp_topic_split_destination_title'] );
1597
1598                                        // Use the source topic title
1599                                        } else {
1600                                                $destination_topic_title = $source_topic->post_title;
1601                                        }
1602
1603                                        // Update the topic
1604                                        $destination_topic_id = wp_update_post( array(
1605                                                'ID'          => $from_reply->ID,
1606                                                'post_title'  => $destination_topic_title,
1607                                                'post_name'   => false,
1608                                                'post_type'   => bbp_get_topic_post_type(),
1609                                                'post_parent' => $source_topic->post_parent,
1610                                                'menu_order'  => 0,
1611                                                'guid'        => ''
1612                                        ) );
1613                                        $destination_topic = bbp_get_topic( $destination_topic_id );
1614
1615                                        // Make sure the new topic knows its a topic
1616                                        bbp_update_topic_topic_id( $from_reply->ID );
1617
1618                                        // Shouldn't happen
1619                                        if ( false === $destination_topic_id || is_wp_error( $destination_topic_id ) || empty( $destination_topic ) ) {
1620                                                bbp_add_error( 'bbp_split_topic_destination_reply', __( '<strong>ERROR</strong>: There was a problem converting the reply into the topic. Please try again.', 'bbpress' ) );
1621                                        }
1622
1623                                // User cannot publish posts
1624                                } else {
1625                                        bbp_add_error( 'bbp_split_topic_destination_permission', __( '<strong>ERROR</strong>: You do not have permission to create new topics. The reply could not be converted into a topic.', 'bbpress' ) );
1626                                }
1627
1628                                break;
1629                }
1630        }
1631
1632        // Bail if there are errors
1633        if ( bbp_has_errors() ) {
1634                return;
1635        }
1636
1637        /** No Errors - Do the Spit ***********************************************/
1638
1639        // Update counts, etc...
1640        do_action( 'bbp_pre_split_topic', $from_reply->ID, $source_topic->ID, $destination_topic->ID );
1641
1642        /** Date Check ************************************************************/
1643
1644        // Check if the destination topic is older than the from reply
1645        if ( strtotime( $from_reply->post_date ) < strtotime( $destination_topic->post_date ) ) {
1646
1647                // Set destination topic post_date to 1 second before from reply
1648                $destination_post_date = date( 'Y-m-d H:i:s', strtotime( $from_reply->post_date ) - 1 );
1649
1650                // Update destination topic
1651                wp_update_post( array(
1652                        'ID'            => $destination_topic_id,
1653                        'post_date'     => $destination_post_date,
1654                        'post_date_gmt' => get_gmt_from_date( $destination_post_date )
1655                ) );
1656        }
1657
1658        /** Subscriptions *********************************************************/
1659
1660        // Copy the subscribers
1661        if ( ! empty( $_POST['bbp_topic_subscribers'] ) && "1" === $_POST['bbp_topic_subscribers'] && bbp_is_subscriptions_active() ) {
1662
1663                // Get the subscribers
1664                $subscribers = bbp_get_topic_subscribers( $source_topic->ID );
1665
1666                if ( ! empty( $subscribers ) ) {
1667
1668                        // Add subscribers to new topic
1669                        foreach ( (array) $subscribers as $subscriber ) {
1670                                bbp_add_user_subscription( $subscriber, $destination_topic->ID );
1671                        }
1672                }
1673        }
1674
1675        /** Favorites *************************************************************/
1676
1677        // Copy the favoriters if told to
1678        if ( ! empty( $_POST['bbp_topic_favoriters'] ) && ( "1" === $_POST['bbp_topic_favoriters'] ) ) {
1679
1680                // Get the favoriters
1681                $favoriters = bbp_get_topic_favoriters( $source_topic->ID );
1682
1683                if ( ! empty( $favoriters ) ) {
1684
1685                        // Add the favoriters to new topic
1686                        foreach ( (array) $favoriters as $favoriter ) {
1687                                bbp_add_user_favorite( $favoriter, $destination_topic->ID );
1688                        }
1689                }
1690        }
1691
1692        /** Tags ******************************************************************/
1693
1694        // Copy the tags if told to
1695        if ( ! empty( $_POST['bbp_topic_tags'] ) && ( "1" === $_POST['bbp_topic_tags'] ) ) {
1696
1697                // Get the source topic tags
1698                $source_topic_tags = wp_get_post_terms( $source_topic->ID, bbp_get_topic_tag_tax_id(), array( 'fields' => 'names' ) );
1699
1700                if ( ! empty( $source_topic_tags ) ) {
1701                        wp_set_post_terms( $destination_topic->ID, $source_topic_tags, bbp_get_topic_tag_tax_id(), true );
1702                }
1703        }
1704
1705        /** Split Replies *********************************************************/
1706
1707        // get_posts() is not used because it doesn't allow us to use '>='
1708        // comparision without a filter.
1709        $bbp_db  = bbp_db();
1710        $query   = $bbp_db->prepare( "SELECT * FROM {$bbp_db->posts} WHERE {$bbp_db->posts}.post_date >= %s AND {$bbp_db->posts}.post_parent = %d AND {$bbp_db->posts}.post_type = %s ORDER BY {$bbp_db->posts}.post_date ASC", $from_reply->post_date, $source_topic->ID, bbp_get_reply_post_type() );
1711        $replies = (array) $bbp_db->get_results( $query );
1712
1713        // Make sure there are replies to loop through
1714        if ( ! empty( $replies ) && ! is_wp_error( $replies ) ) {
1715
1716                // Save reply ids
1717                $reply_ids = array();
1718
1719                // Change the post_parent of each reply to the destination topic id
1720                foreach ( $replies as $reply ) {
1721
1722                        // Update the reply
1723                        wp_update_post( array(
1724                                'ID'          => $reply->ID,
1725                                'post_title'  => '',
1726                                'post_name'   => false, // will be automatically generated
1727                                'post_parent' => $destination_topic->ID,
1728                                'guid'        => ''
1729                        ) );
1730
1731                        // Gather reply ids
1732                        $reply_ids[] = $reply->ID;
1733
1734                        // Adjust reply meta values
1735                        bbp_update_reply_topic_id( $reply->ID, $destination_topic->ID                           );
1736                        bbp_update_reply_forum_id( $reply->ID, bbp_get_topic_forum_id( $destination_topic->ID ) );
1737
1738                        // Adjust reply position
1739                        bbp_update_reply_position( $reply->ID );
1740
1741                        // Adjust reply to values
1742                        $reply_to = bbp_get_reply_to( $reply->ID );
1743
1744                        // Not a reply to a reply that moved over
1745                        if ( ! in_array( $reply_to, $reply_ids ) ) {
1746                                bbp_update_reply_to( $reply->ID, 0 );
1747                        }
1748
1749                        // New topic from reply can't be a reply to
1750                        if ( ( $from_reply->ID === $destination_topic->ID ) && ( $from_reply->ID === $reply_to ) ) {
1751                                bbp_update_reply_to( $reply->ID, 0 );
1752                        }
1753
1754                        // Do additional actions per split reply
1755                        do_action( 'bbp_split_topic_reply', $reply->ID, $destination_topic->ID );
1756                }
1757
1758                // Remove reply to from new topic
1759                if ( $from_reply->ID === $destination_topic->ID ) {
1760                        delete_post_meta( $from_reply->ID, '_bbp_reply_to' );
1761                }
1762
1763                // Set the last reply ID and freshness
1764                $last_reply_id = $reply->ID;
1765                $freshness     = $reply->post_date;
1766
1767        // Set the last reply ID and freshness to the from_reply
1768        } else {
1769                $last_reply_id = $from_reply->ID;
1770                $freshness     = $from_reply->post_date;
1771        }
1772
1773        // It is a new topic and we need to set some default metas to make
1774        // the topic display in bbp_has_topics() list
1775        if ( 'reply' === $split_option ) {
1776                bbp_update_topic_last_reply_id   ( $destination_topic->ID, $last_reply_id );
1777                bbp_update_topic_last_active_id  ( $destination_topic->ID, $last_reply_id );
1778                bbp_update_topic_last_active_time( $destination_topic->ID, $freshness     );
1779        }
1780
1781        // Update source topic ID last active
1782        bbp_update_topic_last_reply_id   ( $source_topic->ID );
1783        bbp_update_topic_last_active_id  ( $source_topic->ID );
1784        bbp_update_topic_last_active_time( $source_topic->ID );
1785
1786        /** Successful Split ******************************************************/
1787
1788        // Update counts, etc...
1789        do_action( 'bbp_post_split_topic', $from_reply->ID, $source_topic->ID, $destination_topic->ID );
1790
1791        // Redirect back to the topic
1792        bbp_redirect( bbp_get_topic_permalink( $destination_topic->ID ) );
1793}
1794
1795/**
1796 * Fix counts on topic split
1797 *
1798 * When a topic is split, update the counts of source and destination topic
1799 * and their forums.
1800 *
1801 * @since 2.0.0 bbPress (r2756)
1802 *
1803 * @param int $from_reply_id From reply id
1804 * @param int $source_topic_id Source topic id
1805 * @param int $destination_topic_id Destination topic id
1806 * @uses bbp_update_forum_topic_count() To update the forum topic counts
1807 * @uses bbp_update_forum_reply_count() To update the forum reply counts
1808 * @uses bbp_update_topic_reply_count() To update the topic reply counts
1809 * @uses bbp_update_topic_voice_count() To update the topic voice counts
1810 * @uses bbp_update_topic_reply_count_hidden() To update the topic hidden reply
1811 *                                              count
1812 * @uses do_action() Calls 'bbp_split_topic_count' with the from reply id,
1813 *                    source topic id & destination topic id
1814 */
1815function bbp_split_topic_count( $from_reply_id, $source_topic_id, $destination_topic_id ) {
1816
1817        // Forum Topic Counts
1818        bbp_update_forum_topic_count( bbp_get_topic_forum_id( $destination_topic_id ) );
1819
1820        // Forum Reply Counts
1821        bbp_update_forum_reply_count( bbp_get_topic_forum_id( $destination_topic_id ) );
1822
1823        // Topic Reply Counts
1824        bbp_update_topic_reply_count( $source_topic_id      );
1825        bbp_update_topic_reply_count( $destination_topic_id );
1826
1827        // Topic Hidden Reply Counts
1828        bbp_update_topic_reply_count_hidden( $source_topic_id      );
1829        bbp_update_topic_reply_count_hidden( $destination_topic_id );
1830
1831        // Topic Voice Counts
1832        bbp_update_topic_voice_count( $source_topic_id      );
1833        bbp_update_topic_voice_count( $destination_topic_id );
1834
1835        do_action( 'bbp_split_topic_count', $from_reply_id, $source_topic_id, $destination_topic_id );
1836}
1837
1838/**
1839 * Handles the front end tag management (renaming, merging, destroying)
1840 *
1841 * @since 2.0.0 bbPress (r2768)
1842 *
1843 * @param string $action The requested action to compare this function to
1844 * @uses bbp_verify_nonce_request() To verify the nonce and check the request
1845 * @uses current_user_can() To check if the current user can edit/delete tags
1846 * @uses bbp_add_error() To add an error message
1847 * @uses wp_update_term() To update the topic tag
1848 * @uses get_term_link() To get the topic tag url
1849 * @uses term_exists() To check if the topic tag already exists
1850 * @uses wp_insert_term() To insert a topic tag
1851 * @uses wp_delete_term() To delete the topic tag
1852 * @uses home_url() To get the blog's home page url
1853 * @uses do_action() Calls actions based on the actions with associated args
1854 * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error}
1855 * @uses bbp_redirect() To redirect to the url
1856 */
1857function bbp_edit_topic_tag_handler( $action = '' ) {
1858
1859        // Bail if required POST actions aren't passed
1860        if ( empty( $_POST['tag-id'] ) ) {
1861                return;
1862        }
1863
1864        // Setup possible get actions
1865        $possible_actions = array(
1866                'bbp-update-topic-tag',
1867                'bbp-merge-topic-tag',
1868                'bbp-delete-topic-tag'
1869        );
1870
1871        // Bail if actions aren't meant for this function
1872        if ( ! in_array( $action, $possible_actions ) ) {
1873                return;
1874        }
1875
1876        // Setup vars
1877        $tag_id = (int) $_POST['tag-id'];
1878        $tag    = get_term( $tag_id, bbp_get_topic_tag_tax_id() );
1879
1880        // Tag does not exist
1881        if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
1882                bbp_add_error( 'bbp_manage_topic_invalid_tag', sprintf( __( '<strong>ERROR</strong>: The following problem(s) have been found while getting the tag: %s', 'bbpress' ), $tag->get_error_message() ) );
1883                return;
1884        }
1885
1886        // What action are we trying to perform?
1887        switch ( $action ) {
1888
1889                // Update tag
1890                case 'bbp-update-topic-tag' :
1891
1892                        // Nonce check
1893                        if ( ! bbp_verify_nonce_request( 'update-tag_' . $tag_id ) ) {
1894                                bbp_add_error( 'bbp_manage_topic_tag_update_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
1895                                return;
1896                        }
1897
1898                        // Can user edit topic tags?
1899                        if ( ! current_user_can( 'edit_topic_tags' ) ) {
1900                                bbp_add_error( 'bbp_manage_topic_tag_update_permission', __( '<strong>ERROR</strong>: You do not have permission to edit the topic tags.', 'bbpress' ) );
1901                                return;
1902                        }
1903
1904                        // No tag name was provided
1905                        if ( empty( $_POST['tag-name'] ) || ! $name = $_POST['tag-name'] ) {
1906                                bbp_add_error( 'bbp_manage_topic_tag_update_name', __( '<strong>ERROR</strong>: You need to enter a tag name.', 'bbpress' ) );
1907                                return;
1908                        }
1909
1910                        // Attempt to update the tag
1911                        $slug        = ! empty( $_POST['tag-slug']        ) ? $_POST['tag-slug']        : '';
1912                        $description = ! empty( $_POST['tag-description'] ) ? $_POST['tag-description'] : '';
1913                        $tag         = wp_update_term( $tag_id, bbp_get_topic_tag_tax_id(), array( 'name' => $name, 'slug' => $slug, 'description' => $description ) );
1914
1915                        // Cannot update tag
1916                        if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
1917                                bbp_add_error( 'bbp_manage_topic_tag_update_error', sprintf( __( '<strong>ERROR</strong>: The following problem(s) have been found while updating the tag: %s', 'bbpress' ), $tag->get_error_message() ) );
1918                                return;
1919                        }
1920
1921                        // Redirect
1922                        $redirect = get_term_link( $tag_id, bbp_get_topic_tag_tax_id() );
1923
1924                        // Update counts, etc...
1925                        do_action( 'bbp_update_topic_tag', $tag_id, $tag, $name, $slug, $description );
1926
1927                        break;
1928
1929                // Merge two tags
1930                case 'bbp-merge-topic-tag'  :
1931
1932                        // Nonce check
1933                        if ( ! bbp_verify_nonce_request( 'merge-tag_' . $tag_id ) ) {
1934                                bbp_add_error( 'bbp_manage_topic_tag_merge_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
1935                                return;
1936                        }
1937
1938                        // Can user edit topic tags?
1939                        if ( ! current_user_can( 'edit_topic_tags' ) ) {
1940                                bbp_add_error( 'bbp_manage_topic_tag_merge_permission', __( '<strong>ERROR</strong>: You do not have permission to edit the topic tags.', 'bbpress' ) );
1941                                return;
1942                        }
1943
1944                        // No tag name was provided
1945                        if ( empty( $_POST['tag-existing-name'] ) || ! $name = $_POST['tag-existing-name'] ) {
1946                                bbp_add_error( 'bbp_manage_topic_tag_merge_name', __( '<strong>ERROR</strong>: You need to enter a tag name.', 'bbpress' ) );
1947                                return;
1948                        }
1949
1950                        // If term does not exist, create it
1951                        if ( ! $tag = term_exists( $name, bbp_get_topic_tag_tax_id() ) ) {
1952                                $tag = wp_insert_term( $name, bbp_get_topic_tag_tax_id() );
1953                        }
1954
1955                        // Problem inserting the new term
1956                        if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
1957                                bbp_add_error( 'bbp_manage_topic_tag_merge_error', sprintf( __( '<strong>ERROR</strong>: The following problem(s) have been found while merging the tags: %s', 'bbpress' ), $tag->get_error_message() ) );
1958                                return;
1959                        }
1960
1961                        // Merging in to...
1962                        $to_tag = $tag['term_id'];
1963
1964                        // Attempting to merge a tag into itself
1965                        if ( $tag_id === $to_tag ) {
1966                                bbp_add_error( 'bbp_manage_topic_tag_merge_same', __( '<strong>ERROR</strong>: The tags which are being merged can not be the same.', 'bbpress' ) );
1967                                return;
1968                        }
1969
1970                        // Delete the old term
1971                        $tag = wp_delete_term( $tag_id, bbp_get_topic_tag_tax_id(), array( 'default' => $to_tag, 'force_default' => true ) );
1972
1973                        // Error merging the terms
1974                        if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
1975                                bbp_add_error( 'bbp_manage_topic_tag_merge_error', sprintf( __( '<strong>ERROR</strong>: The following problem(s) have been found while merging the tags: %s', 'bbpress' ), $tag->get_error_message() ) );
1976                                return;
1977                        }
1978
1979                        // Redirect
1980                        $redirect = get_term_link( (int) $to_tag, bbp_get_topic_tag_tax_id() );
1981
1982                        // Update counts, etc...
1983                        do_action( 'bbp_merge_topic_tag', $tag_id, $to_tag, $tag );
1984
1985                        break;
1986
1987                // Delete tag
1988                case 'bbp-delete-topic-tag' :
1989
1990                        // Nonce check
1991                        if ( ! bbp_verify_nonce_request( 'delete-tag_' . $tag_id ) ) {
1992                                bbp_add_error( 'bbp_manage_topic_tag_delete_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
1993                                return;
1994                        }
1995
1996                        // Can user delete topic tags?
1997                        if ( ! current_user_can( 'delete_topic_tags' ) ) {
1998                                bbp_add_error( 'bbp_manage_topic_tag_delete_permission', __( '<strong>ERROR</strong>: You do not have permission to delete the topic tags.', 'bbpress' ) );
1999                                return;
2000                        }
2001
2002                        // Attempt to delete term
2003                        $tag = wp_delete_term( $tag_id, bbp_get_topic_tag_tax_id() );
2004
2005                        // Error deleting term
2006                        if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
2007                                bbp_add_error( 'bbp_manage_topic_tag_delete_error', sprintf( __( '<strong>ERROR</strong>: The following problem(s) have been found while deleting the tag: %s', 'bbpress' ), $tag->get_error_message() ) );
2008                                return;
2009                        }
2010
2011                        // We don't have any other place to go other than home! Or we may die because of the 404 disease
2012                        $redirect = home_url();
2013
2014                        // Update counts, etc...
2015                        do_action( 'bbp_delete_topic_tag', $tag_id, $tag );
2016
2017                        break;
2018        }
2019
2020        /** Successful Moderation *************************************************/
2021
2022        // Redirect back
2023        $redirect = ( ! empty( $redirect ) && ! is_wp_error( $redirect ) ) ? $redirect : home_url();
2024        bbp_redirect( $redirect );
2025}
2026
2027/** Helpers *******************************************************************/
2028
2029/**
2030 * Return an associative array of available topic statuses
2031 *
2032 * @since 2.4.0 bbPress (r5059)
2033 *
2034 * @param int $topic_id   Optional. Topic id.
2035 *
2036 * @return array
2037 */
2038function bbp_get_topic_statuses( $topic_id = 0 ) {
2039        return apply_filters( 'bbp_get_topic_statuses', array(
2040                bbp_get_public_status_id()  => _x( 'Open',    'Open the topic',        'bbpress' ),
2041                bbp_get_closed_status_id()  => _x( 'Closed',  'Close the topic',       'bbpress' ),
2042                bbp_get_spam_status_id()    => _x( 'Spam',    'Spam the topic',        'bbpress' ),
2043                bbp_get_trash_status_id()   => _x( 'Trash',   'Trash the topic',       'bbpress' ),
2044                bbp_get_pending_status_id() => _x( 'Pending', 'Mark topic as pending', 'bbpress' ),
2045        ), $topic_id );
2046}
2047
2048/**
2049 * Return an associative array of topic sticky types
2050 *
2051 * @since 2.4.0 bbPress (r5059)
2052 *
2053 * @param int $topic_id   Optional. Topic id.
2054 *
2055 * @return array
2056 */
2057function bbp_get_topic_types( $topic_id = 0 ) {
2058        return apply_filters( 'bbp_get_topic_types', array(
2059                'unstick' => _x( 'Normal',       'Unstick a topic',         'bbpress' ),
2060                'stick'   => _x( 'Sticky',       'Make topic sticky',       'bbpress' ),
2061                'super'   => _x( 'Super Sticky', 'Make topic super sticky', 'bbpress' )
2062        ), $topic_id );
2063}
2064
2065/**
2066 * Return array of available topic toggle actions
2067 *
2068 * @since 2.6.0 bbPress (r6133)
2069 *
2070 * @param int $topic_id   Optional. Topic id.
2071 *
2072 * @return array
2073 */
2074function bbp_get_topic_toggles( $topic_id = 0 ) {
2075        return apply_filters( 'bbp_get_toggle_topic_actions', array(
2076                'bbp_toggle_topic_close',
2077                'bbp_toggle_topic_stick',
2078                'bbp_toggle_topic_spam',
2079                'bbp_toggle_topic_trash',
2080                'bbp_toggle_topic_approve'
2081        ), $topic_id );
2082}
2083
2084/** Stickies ******************************************************************/
2085
2086/**
2087 * Return sticky topics of a forum
2088 *
2089 * @since 2.0.0 bbPress (r2592)
2090 *
2091 * @param int $forum_id Optional. If not passed, super stickies are returned.
2092 * @uses bbp_get_super_stickies() To get the super stickies
2093 * @uses get_post_meta() To get the forum stickies
2094 * @uses apply_filters() Calls 'bbp_get_stickies' with the stickies and forum id
2095 * @return array IDs of sticky topics of a forum or super stickies
2096 */
2097function bbp_get_stickies( $forum_id = 0 ) {
2098        $stickies = empty( $forum_id ) ? bbp_get_super_stickies() : get_post_meta( $forum_id, '_bbp_sticky_topics', true );
2099        $stickies = ( empty( $stickies ) || ! is_array( $stickies ) ) ? array() : $stickies;
2100
2101        return apply_filters( 'bbp_get_stickies', $stickies, $forum_id );
2102}
2103
2104/**
2105 * Return topics stuck to front page of the forums
2106 *
2107 * @since 2.0.0 bbPress (r2592)
2108 *
2109 * @uses get_option() To get super sticky topics
2110 * @uses apply_filters() Calls 'bbp_get_super_stickies' with the stickies
2111 * @return array IDs of super sticky topics
2112 */
2113function bbp_get_super_stickies() {
2114        $stickies = get_option( '_bbp_super_sticky_topics', array() );
2115        $stickies = ( empty( $stickies ) || ! is_array( $stickies ) ) ? array() : $stickies;
2116
2117        return apply_filters( 'bbp_get_super_stickies', $stickies );
2118}
2119
2120/** Topics Actions ************************************************************/
2121
2122/**
2123 * Handles the front end opening/closing, spamming/unspamming,
2124 * sticking/unsticking and trashing/untrashing/deleting of topics
2125 *
2126 * @since 2.0.0 bbPress (r2727)
2127 *
2128 * @param string $action The requested action to compare this function to
2129 * @uses bbp_get_topic() To get the topic
2130 * @uses current_user_can() To check if the user is capable of editing or
2131 *                           deleting the topic
2132 * @uses bbp_get_topic_post_type() To get the topic post type
2133 * @uses check_ajax_referer() To verify the nonce and check the referer
2134 * @uses bbp_is_topic_open() To check if the topic is open
2135 * @uses bbp_close_topic() To close the topic
2136 * @uses bbp_open_topic() To open the topic
2137 * @uses bbp_is_topic_sticky() To check if the topic is a sticky
2138 * @uses bbp_unstick_topic() To unstick the topic
2139 * @uses bbp_stick_topic() To stick the topic
2140 * @uses bbp_is_topic_spam() To check if the topic is marked as spam
2141 * @uses bbp_spam_topic() To make the topic as spam
2142 * @uses bbp_unspam_topic() To unmark the topic as spam
2143 * @uses wp_trash_post() To trash the topic
2144 * @uses wp_untrash_post() To untrash the topic
2145 * @uses wp_delete_post() To delete the topic
2146 * @uses do_action() Calls 'bbp_toggle_topic_handler' with success, post data
2147 *                    and action
2148 * @uses bbp_get_forum_permalink() To get the forum link
2149 * @uses bbp_get_topic_permalink() To get the topic link
2150 * @uses bbp_redirect() To redirect to the topic
2151 * @uses bbPress::errors:add() To log the error messages
2152 */
2153function bbp_toggle_topic_handler( $action = '' ) {
2154
2155        // Bail if required GET actions aren't passed
2156        if ( empty( $_GET['topic_id'] ) ) {
2157                return;
2158        }
2159
2160        // What's the topic id?
2161        $topic_id = bbp_get_topic_id( (int) $_GET['topic_id'] );
2162
2163        // Get possible topic-handler toggles
2164        $toggles = bbp_get_topic_toggles( $topic_id );
2165
2166        // Bail if actions aren't meant for this function
2167        if ( ! in_array( $action, $toggles, true ) ) {
2168                return;
2169        }
2170
2171        // Make sure topic exists
2172        $topic = bbp_get_topic( $topic_id );
2173        if ( empty( $topic ) ) {
2174                bbp_add_error( 'bbp_toggle_topic_missing', __( '<strong>ERROR:</strong> This topic could not be found or no longer exists.', 'bbpress' ) );
2175                return;
2176        }
2177
2178        // What is the user doing here?
2179        if ( ! current_user_can( 'edit_topic', $topic_id ) || ( 'bbp_toggle_topic_trash' === $action && ! current_user_can( 'delete_topic', $topic_id ) ) ) {
2180                bbp_add_error( 'bbp_toggle_topic_permission', __( '<strong>ERROR:</strong> You do not have permission to do that.', 'bbpress' ) );
2181                return;
2182        }
2183
2184        // Sub-action?
2185        $sub_action = ! empty( $_GET['sub_action'] )
2186                ? sanitize_key( $_GET['sub_action'] )
2187                : false;
2188
2189        // Preliminary array
2190        $post_data = array( 'ID' => $topic_id );
2191
2192        // Do the topic toggling
2193        $retval = bbp_toggle_topic( array(
2194                'id'         => $topic_id,
2195                'action'     => $action,
2196                'sub_action' => $sub_action,
2197                'data'       => $post_data
2198        ) );
2199
2200        // Do additional topic toggle actions
2201        do_action( 'bbp_toggle_topic_handler', $retval['status'], $post_data, $action );
2202
2203        // No errors
2204        if ( ( false !== $retval['status'] ) && ! is_wp_error( $retval['status'] ) ) {
2205                bbp_redirect( $retval['redirect_to'] );
2206
2207        // Handle errors
2208        } else {
2209                bbp_add_error( 'bbp_toggle_topic', $retval['message'] );
2210        }
2211}
2212
2213/**
2214 * Do the actual topic toggling
2215 *
2216 * This function is used by `bbp_toggle_topic_handler()` to do the actual heavy
2217 * lifting when it comes to toggling topic. It only really makes sense to call
2218 * within that context, so if you need to call this function directly, make sure
2219 * you're also doing what the handler does too.
2220 *
2221 * @since 2.6.0  bbPress (r6133)
2222 * @access private
2223 *
2224 * @param array $args
2225 */
2226function bbp_toggle_topic( $args = array() ) {
2227
2228        // Parse the arguments
2229        $r = bbp_parse_args( $args, array(
2230                'id'         => 0,
2231                'action'     => '',
2232                'sub_action' => '',
2233                'data'       => array()
2234        ) );
2235
2236        // Build the nonce suffix
2237        $nonce_suffix = bbp_get_topic_post_type() . '_' . (int) $r['id'];
2238
2239        // Default return values
2240        $retval = array(
2241                'status'      => 0,
2242                'message'     => '',
2243                'redirect_to' => bbp_get_topic_permalink( $r['id'], bbp_get_redirect_to() ),
2244                'view_all'    => false
2245        );
2246
2247        // What action are we trying to perform?
2248        switch ( $r['action'] ) {
2249
2250                // Toggle approve/unapprove
2251                case 'bbp_toggle_topic_approve' :
2252                        check_ajax_referer( "approve-{$nonce_suffix}" );
2253
2254                        $is_pending         = bbp_is_topic_pending( $r['id'] );
2255                        $retval['view_all'] = ! $is_pending;
2256
2257                        // Toggle
2258                        $retval['status'] = ( true === $is_pending )
2259                                ? bbp_approve_topic( $r['id'] )
2260                                : bbp_unapprove_topic( $r['id'] );
2261
2262                        // Feedback
2263                        $retval['message'] = ( true === $is_pending )
2264                                ? __( '<strong>ERROR</strong>: There was a problem approving the topic.',   'bbpress' )
2265                                : __( '<strong>ERROR</strong>: There was a problem unapproving the topic.', 'bbpress' );
2266
2267                        break;
2268
2269                // Toggle open/close
2270                case 'bbp_toggle_topic_close' :
2271                        check_ajax_referer( "close-{$nonce_suffix}" );
2272
2273                        $is_open = bbp_is_topic_open( $r['id'] );
2274
2275                        // Toggle
2276                        $retval['status'] = ( true === $is_open )
2277                                ? bbp_close_topic( $r['id'] )
2278                                : bbp_open_topic( $r['id'] );
2279
2280                        // Feedback
2281                        $retval['message'] = ( true === $is_open )
2282                                ? __( '<strong>ERROR</strong>: There was a problem closing the topic.', 'bbpress' )
2283                                : __( '<strong>ERROR</strong>: There was a problem opening the topic.', 'bbpress' );
2284
2285                        break;
2286
2287                // Toggle sticky/super-sticky/unstick
2288                case 'bbp_toggle_topic_stick' :
2289                        check_ajax_referer( "stick-{$nonce_suffix}" );
2290
2291                        $is_sticky = bbp_is_topic_sticky( $r['id'] );
2292                        $is_super  = false === $is_sticky && ! empty( $_GET['super'] ) && ( "1" === $_GET['super'] ) ? true : false;
2293
2294                        // Toggle
2295                        $retval['status'] = ( true === $is_sticky )
2296                                ? bbp_unstick_topic( $r['id'] )
2297                                : bbp_stick_topic( $r['id'], $is_super );
2298
2299                        // Feedback
2300                        $retval['message'] = ( true === $is_sticky )
2301                                ? __( '<strong>ERROR</strong>: There was a problem unsticking the topic.', 'bbpress' )
2302                                : __( '<strong>ERROR</strong>: There was a problem sticking the topic.',   'bbpress' );
2303
2304                        break;
2305
2306                // Toggle spam
2307                case 'bbp_toggle_topic_spam' :
2308                        check_ajax_referer( "spam-{$nonce_suffix}" );
2309
2310                        $is_spam            = bbp_is_topic_spam( $r['id'] );
2311                        $retval['view_all'] = ! $is_spam;
2312
2313                        // Toggle
2314                        $retval['status'] = ( true === $is_spam )
2315                                ? bbp_unspam_topic( $r['id'] )
2316                                : bbp_spam_topic( $r['id'] );
2317
2318                        // Feedback
2319                        $retval['message'] = ( true === $is_spam )
2320                                ? __( '<strong>ERROR</strong>: There was a problem unmarking the topic as spam.', 'bbpress' )
2321                                : __( '<strong>ERROR</strong>: There was a problem marking the topic as spam.',   'bbpress' );
2322
2323                        break;
2324
2325                // Toggle trash
2326                case 'bbp_toggle_topic_trash' :
2327
2328                        switch ( $r['sub_action'] ) {
2329                                case 'trash':
2330                                        check_ajax_referer( "trash-{$nonce_suffix}" );
2331
2332                                        $retval['view_all']    = true;
2333                                        $retval['status']      = wp_trash_post( $r['id'] );
2334                                        $retval['message']     = __( '<strong>ERROR</strong>: There was a problem trashing the topic.', 'bbpress' );
2335                                        $retval['redirect_to'] = bbp_get_topic_permalink( $r['id'] );
2336
2337                                        break;
2338
2339                                case 'untrash':
2340                                        check_ajax_referer( "untrash-{$nonce_suffix}" );
2341
2342                                        $retval['status']      = wp_untrash_post( $r['id'] );
2343                                        $retval['message']     = __( '<strong>ERROR</strong>: There was a problem untrashing the topic.', 'bbpress' );
2344                                        $retval['redirect_to'] = bbp_get_topic_permalink( $r['id'] );
2345
2346                                        break;
2347
2348                                case 'delete':
2349                                        check_ajax_referer( "delete-{$nonce_suffix}" );
2350
2351                                        $retval['status']      = wp_delete_post( $r['id'] );
2352                                        $retval['message']     = __( '<strong>ERROR</strong>: There was a problem deleting the topic.', 'bbpress' );
2353                                        $retval['redirect_to'] = bbp_get_forum_permalink( $retval['status']->post_parent );
2354
2355                                        break;
2356                        }
2357
2358                        break;
2359        }
2360
2361        // Add view all if needed
2362        if ( ! empty( $retval['view_all'] ) ) {
2363                $retval['redirect_to'] = bbp_add_view_all( $retval['redirect_to'], true );
2364        }
2365
2366        // Filter & return
2367        return apply_filters( 'bbp_toggle_topic', $retval, $r, $args );
2368}
2369
2370/** Favorites & Subscriptions *************************************************/
2371
2372/**
2373 * Remove a deleted topic from all users' favorites
2374 *
2375 * @since 2.0.0 bbPress (r2652)
2376 *
2377 * @param int $topic_id Get the topic id to remove
2378 * @uses bbp_get_topic_id To get the topic id
2379 * @uses bbp_get_topic_favoriters() To get the topic's favoriters
2380 * @uses bbp_remove_user_favorite() To remove the topic from user's favorites
2381 */
2382function bbp_remove_topic_from_all_favorites( $topic_id = 0 ) {
2383        $topic_id = bbp_get_topic_id( $topic_id );
2384
2385        // Bail if no topic
2386        if ( empty( $topic_id ) ) {
2387                return;
2388        }
2389
2390        // Get users
2391        $users = (array) bbp_get_topic_favoriters( $topic_id );
2392
2393        // Users exist
2394        if ( ! empty( $users ) ) {
2395
2396                // Loop through users
2397                foreach ( $users as $user ) {
2398
2399                        // Remove each user
2400                        bbp_remove_user_favorite( $user, $topic_id );
2401                }
2402        }
2403}
2404
2405/**
2406 * Remove a deleted topic from all users' subscriptions
2407 *
2408 * @since 2.0.0 bbPress (r2652)
2409 *
2410 * @param int $topic_id Get the topic id to remove
2411 * @uses bbp_is_subscriptions_active() To check if the subscriptions are active
2412 * @uses bbp_get_topic_id To get the topic id
2413 * @uses bbp_get_topic_subscribers() To get the topic subscribers
2414 * @uses bbp_remove_user_subscription() To remove the user subscription
2415 */
2416function bbp_remove_topic_from_all_subscriptions( $topic_id = 0 ) {
2417
2418        // Subscriptions are not active
2419        if ( ! bbp_is_subscriptions_active() ) {
2420                return;
2421        }
2422
2423        $topic_id = bbp_get_topic_id( $topic_id );
2424
2425        // Bail if no topic
2426        if ( empty( $topic_id ) ) {
2427                return;
2428        }
2429
2430        // Get users
2431        $users = (array) bbp_get_topic_subscribers( $topic_id );
2432
2433        // Users exist
2434        if ( ! empty( $users ) ) {
2435
2436                // Loop through users
2437                foreach ( $users as $user ) {
2438
2439                        // Remove each user
2440                        bbp_remove_user_subscription( $user, $topic_id );
2441                }
2442        }
2443}
2444
2445/** Count Bumpers *************************************************************/
2446
2447/**
2448 * Bump the total reply count of a topic
2449 *
2450 * @since 2.1.0 bbPress (r3825)
2451 *
2452 * @param int $topic_id   Optional. Topic id.
2453 * @param int $difference Optional. Default 1
2454 * @uses bbp_get_topic_id() To get the topic id
2455 * @uses bbp_get_topic_reply_count() To get the topic reply count
2456 * @uses update_post_meta() To update the topic's reply count meta
2457 * @uses apply_filters() Calls 'bbp_bump_topic_reply_count' with the reply
2458 *                        count, topic id, and difference
2459 * @return int Topic reply count
2460 */
2461function bbp_bump_topic_reply_count( $topic_id = 0, $difference = 1 ) {
2462
2463        // Bail if no bump
2464        if ( empty( $difference ) ) {
2465                return false;
2466        }
2467
2468        // Get counts
2469        $topic_id    = bbp_get_topic_id( $topic_id );
2470        $reply_count = bbp_get_topic_reply_count( $topic_id, true );
2471        $difference  = (int) $difference;
2472        $new_count   = (int) ( $reply_count + $difference );
2473
2474        // Update this topic id's reply count
2475        update_post_meta( $topic_id, '_bbp_reply_count', $new_count );
2476
2477        return (int) apply_filters( 'bbp_bump_topic_reply_count', $new_count, $topic_id, $difference );
2478}
2479
2480/**
2481 * Increase the total reply count of a topic by one.
2482 *
2483 * @since 2.6.0 bbPress (r6036)
2484 *
2485 * @param int $topic_id The topic id.
2486 *
2487 * @uses bbp_is_reply() To check if the passed topic id is a reply
2488 * @uses bbp_get_reply_topic_id() To get the replies topic id
2489 * @uses bbp_is_reply_published() To check if the reply is published
2490 * @uses bbp_increase_topic_reply_count_hidden() To increase the topics reply
2491 *                                                hidden count by 1
2492 * @uses bbp_bump_topic_reply_count() To bump the topic reply count
2493 *
2494 * @return void
2495 */
2496function bbp_increase_topic_reply_count( $topic_id = 0 ) {
2497
2498        // Bail early if no id is passed.
2499        if ( empty( $topic_id ) ) {
2500                return;
2501        }
2502
2503        // If it's a reply, get the topic id.
2504        if ( bbp_is_reply( $topic_id ) ) {
2505                $reply_id = $topic_id;
2506                $topic_id = bbp_get_reply_topic_id( $reply_id );
2507
2508                // If this is a new, unpublished, reply, update hidden count and bail.
2509                if ( 'bbp_new_reply' === current_filter() && ! bbp_is_reply_published( $reply_id ) ) {
2510                        bbp_increase_topic_reply_count_hidden( $topic_id );
2511                        return;
2512                }
2513        }
2514
2515        bbp_bump_topic_reply_count( $topic_id );
2516}
2517
2518/**
2519 * Decrease the total reply count of a topic by one.
2520 *
2521 * @since 2.6.0 bbPress (r6036)
2522 *
2523 * @param int $topic_id The topic id.
2524 *
2525 * @uses bbp_is_reply() To check if the passed topic id is a reply
2526 * @uses bbp_get_reply_topic_id() To get the replies topic id
2527 * @uses bbp_bump_topic_reply_count() To bump the topic reply count
2528 *
2529 * @return void
2530 */
2531function bbp_decrease_topic_reply_count( $topic_id = 0 ) {
2532
2533        // Bail early if no id is passed.
2534        if ( empty( $topic_id ) ) {
2535                return;
2536        }
2537
2538        // If it's a reply, get the topic id.
2539        if ( bbp_is_reply( $topic_id ) ) {
2540                $topic_id = bbp_get_reply_topic_id( $topic_id );
2541        }
2542
2543        bbp_bump_topic_reply_count( $topic_id, -1 );
2544}
2545
2546/**
2547 * Bump the total hidden reply count of a topic
2548 *
2549 * @since 2.1.0 bbPress (r3825)
2550 *
2551 * @param int $topic_id   Optional. Topic id.
2552 * @param int $difference Optional. Default 1
2553 * @uses bbp_get_topic_id() To get the topic id
2554 * @uses bbp_get_topic_reply_count_hidden To get the topic's hidden reply count
2555 * @uses update_post_meta() To update the topic's reply count meta
2556 * @uses apply_filters() Calls 'bbp_bump_topic_reply_count_hidden' with the
2557 *                        reply count, topic id, and difference
2558 * @return int Topic hidden reply count
2559 */
2560function bbp_bump_topic_reply_count_hidden( $topic_id = 0, $difference = 1 ) {
2561
2562        // Bail if no bump
2563        if ( empty( $difference ) ) {
2564                return false;
2565        }
2566
2567        // Get counts
2568        $topic_id    = bbp_get_topic_id( $topic_id );
2569        $reply_count = bbp_get_topic_reply_count_hidden( $topic_id, true );
2570        $difference  = (int) $difference;
2571        $new_count   = (int) ( $reply_count + $difference );
2572
2573        // Update this topic id's hidden reply count
2574        update_post_meta( $topic_id, '_bbp_reply_count_hidden', $new_count );
2575
2576        return (int) apply_filters( 'bbp_bump_topic_reply_count_hidden', $new_count, $topic_id, $difference );
2577}
2578
2579/**
2580 * Increase the total hidden reply count of a topic by one.
2581 *
2582 * @since 2.6.0 bbPress (r6036)
2583 *
2584 * @param int $topic_id The topic id.
2585 *
2586 * @uses bbp_is_reply() To check if the passed topic id is a reply
2587 * @uses bbp_get_reply_topic_id() To get the topic id
2588 * @uses bbp_bump_topic_reply_count_hidden() To bump topic hidden reply count
2589 *
2590 * @return void
2591 */
2592function bbp_increase_topic_reply_count_hidden( $topic_id = 0 ) {
2593
2594        // Bail early if no id is passed.
2595        if ( empty( $topic_id ) ) {
2596                return;
2597        }
2598
2599        // If it's a reply, get the topic id.
2600        if ( bbp_is_reply( $topic_id ) ) {
2601                $topic_id = bbp_get_reply_topic_id( $topic_id );
2602        }
2603
2604        bbp_bump_topic_reply_count_hidden( $topic_id );
2605}
2606
2607/**
2608 * Decrease the total hidden reply count of a topic by one.
2609 *
2610 * @since 2.6.0 bbPress (r6036)
2611 *
2612 * @param int $topic_id The topic id.
2613 *
2614 * @uses bbp_is_reply() To check if the passed topic id is a reply
2615 * @uses bbp_get_reply_topic_id() To get the topic id
2616 * @uses bbp_bump_topic_reply_count_hidden() To bump topic hidden reply count
2617 *
2618 * @return void
2619 */
2620function bbp_decrease_topic_reply_count_hidden( $topic_id = 0 ) {
2621
2622        // Bail early if no id is passed.
2623        if ( empty( $topic_id ) ) {
2624                return;
2625        }
2626
2627        // If it's a reply, get the topic id.
2628        if ( bbp_is_reply( $topic_id ) ) {
2629                $topic_id = bbp_get_reply_topic_id( $topic_id );
2630        }
2631
2632        bbp_bump_topic_reply_count_hidden( $topic_id, -1 );
2633}
2634
2635/**
2636 * Update counts after a topic is inserted via `bbp_insert_topic`.
2637 *
2638 * @since 2.6.0 bbPress (r6036)
2639 *
2640 * @param int $topic_id The topic id.
2641 * @param int $forum_id The forum id.
2642 *
2643 * @uses bbp_get_topic_status() To get the post status
2644 * @uses bbp_get_public_status_id() To get the public status id
2645 * @uses bbp_increase_forum_topic_count() To bump the topic's forum topic count by 1
2646 * @uses bbp_increase_forum_topic_count_hidden() To bump the topic's forum topic
2647 *                                               hidden count by 1
2648 *
2649 * @return void
2650 */
2651function bbp_insert_topic_update_counts( $topic_id = 0, $forum_id = 0 ) {
2652
2653        // If the topic is public, update the forum topic counts.
2654        if ( bbp_get_topic_status( $topic_id ) === bbp_get_public_status_id() ) {
2655                bbp_increase_forum_topic_count( $forum_id );
2656
2657        // If the topic isn't public only update the forum topic hidden count.
2658        } else {
2659                bbp_increase_forum_topic_count_hidden( $forum_id );
2660        }
2661}
2662
2663/** Topic Updaters ************************************************************/
2664
2665/**
2666 * Update the topic's forum id
2667 *
2668 * @since 2.0.0 bbPress (r2855)
2669 *
2670 * @param int $topic_id Optional. Topic id to update
2671 * @param int $forum_id Optional. Forum id
2672 * @uses bbp_is_reply() TO check if the passed topic id is a reply
2673 * @uses bbp_get_reply_topic_id() To get the reply topic id
2674 * @uses bbp_get_topic_id() To get the topic id
2675 * @uses get_post_field() To get the post parent of the topic id
2676 * @uses bbp_get_forum_id() To get the forum id
2677 * @uses update_post_meta() To update the topic forum id meta
2678 * @uses apply_filters() Calls 'bbp_update_topic_forum_id' with the forum id
2679 *                        and topic id
2680 * @return int Forum id
2681 */
2682function bbp_update_topic_forum_id( $topic_id = 0, $forum_id = 0 ) {
2683
2684        // If it's a reply, then get the parent (topic id)
2685        if ( bbp_is_reply( $topic_id ) ) {
2686                $topic_id = bbp_get_reply_topic_id( $topic_id );
2687        } else {
2688                $topic_id = bbp_get_topic_id( $topic_id );
2689        }
2690
2691        if ( empty( $forum_id ) ) {
2692                $forum_id = get_post_field( 'post_parent', $topic_id );
2693        }
2694
2695        $forum_id = (int) $forum_id;
2696
2697        update_post_meta( $topic_id, '_bbp_forum_id', $forum_id );
2698
2699        return (int) apply_filters( 'bbp_update_topic_forum_id', $forum_id, $topic_id );
2700}
2701
2702/**
2703 * Update the topic's topic id
2704 *
2705 * @since 2.0.0 bbPress (r2954)
2706 *
2707 * @param int $topic_id Optional. Topic id to update
2708 * @uses bbp_get_topic_id() To get the topic id
2709 * @uses update_post_meta() To update the topic's topic id meta
2710 * @uses apply_filters() Calls 'bbp_update_topic_topic_id' with the topic id
2711 * @return int Topic id
2712 */
2713function bbp_update_topic_topic_id( $topic_id = 0 ) {
2714        $topic_id = bbp_get_topic_id( $topic_id );
2715
2716        update_post_meta( $topic_id, '_bbp_topic_id', $topic_id );
2717
2718        return apply_filters( 'bbp_update_topic_topic_id', $topic_id );
2719}
2720
2721/**
2722 * Adjust the total reply count of a topic
2723 *
2724 * @since 2.0.0 bbPress (r2467)
2725 *
2726 * @param int $topic_id Optional. Topic id to update
2727 * @param int $reply_count Optional. Set the reply count manually.
2728 * @uses bbp_is_reply() To check if the passed topic id is a reply
2729 * @uses bbp_get_reply_topic_id() To get the reply topic id
2730 * @uses bbp_get_topic_id() To get the topic id
2731 * @uses bbp_get_reply_post_type() To get the reply post type
2732 * @uses bbp_get_public_child_count() To get the reply count
2733 * @uses update_post_meta() To update the topic reply count meta
2734 * @uses apply_filters() Calls 'bbp_update_topic_reply_count' with the reply
2735 *                        count and topic id
2736 * @return int Topic reply count
2737 */
2738function bbp_update_topic_reply_count( $topic_id = 0, $reply_count = 0 ) {
2739
2740        // If it's a reply, then get the parent (topic id)
2741        if ( bbp_is_reply( $topic_id ) ) {
2742                $topic_id = bbp_get_reply_topic_id( $topic_id );
2743        } else {
2744                $topic_id = bbp_get_topic_id( $topic_id );
2745        }
2746
2747        // Get replies of topic if not passed
2748        if ( empty( $reply_count ) ) {
2749                $reply_count = bbp_get_public_child_count( $topic_id, bbp_get_reply_post_type() );
2750        }
2751
2752        $reply_count = (int) $reply_count;
2753
2754        update_post_meta( $topic_id, '_bbp_reply_count', $reply_count );
2755
2756        return (int) apply_filters( 'bbp_update_topic_reply_count', $reply_count, $topic_id );
2757}
2758
2759/**
2760 * Adjust the total hidden reply count of a topic (hidden includes trashed,
2761 * spammed and pending replies)
2762 *
2763 * @since 2.0.0 bbPress (r2740)
2764 *
2765 * @param int $topic_id Optional. Topic id to update
2766 * @param int $reply_count Optional. Set the reply count manually
2767 * @uses bbp_is_reply() To check if the passed topic id is a reply
2768 * @uses bbp_get_reply_topic_id() To get the reply topic id
2769 * @uses bbp_get_topic_id() To get the topic id
2770 * @uses bbp_get_trash_status_id() To get the trash status id
2771 * @uses bbp_get_spam_status_id() To get the spam status id
2772 * @uses bbp_get_pending_status_id() To get the pending status id
2773 * @uses bbp_get_reply_post_type() To get the reply post type
2774 * @uses wpdb::prepare() To prepare our sql query
2775 * @uses wpdb::get_var() To execute our query and get the var back
2776 * @uses update_post_meta() To update the topic hidden reply count meta
2777 * @uses apply_filters() Calls 'bbp_update_topic_reply_count_hidden' with the
2778 *                        hidden reply count and topic id
2779 * @return int Topic hidden reply count
2780 */
2781function bbp_update_topic_reply_count_hidden( $topic_id = 0, $reply_count = 0 ) {
2782
2783        // If it's a reply, then get the parent (topic id)
2784        if ( bbp_is_reply( $topic_id ) ) {
2785                $topic_id = bbp_get_reply_topic_id( $topic_id );
2786        } else {
2787                $topic_id = bbp_get_topic_id( $topic_id );
2788        }
2789
2790        // Get replies of topic
2791        if ( empty( $reply_count ) ) {
2792                $statuses    = array( bbp_get_trash_status_id(), bbp_get_spam_status_id(), bbp_get_pending_status_id() );
2793                $post_status = "'" . implode( "','", $statuses ) . "'";
2794                $bbp_db      = bbp_db();
2795                $query       = $bbp_db->prepare( "SELECT COUNT(ID) FROM {$bbp_db->posts} WHERE post_parent = %d AND post_status IN ( {$post_status} ) AND post_type = %s", $topic_id, bbp_get_reply_post_type() );
2796                $reply_count = $bbp_db->get_var( $query );
2797        }
2798
2799        $reply_count = (int) $reply_count;
2800
2801        update_post_meta( $topic_id, '_bbp_reply_count_hidden', $reply_count );
2802
2803        return (int) apply_filters( 'bbp_update_topic_reply_count_hidden', $reply_count, $topic_id );
2804}
2805
2806/**
2807 * Update the topic with the last active post ID
2808 *
2809 * @since 2.0.0 bbPress (r2888)
2810 *
2811 * @param int $topic_id Optional. Topic id to update
2812 * @param int $active_id Optional. active id
2813 * @uses bbp_is_reply() To check if the passed topic id is a reply
2814 * @uses bbp_get_reply_topic_id() To get the reply topic id
2815 * @uses bbp_get_topic_id() To get the topic id
2816 * @uses bbp_get_reply_post_type() To get the reply post type
2817 * @uses bbp_get_public_child_last_id() To get the last public reply id
2818 * @uses bbp_get_active_id() To get the active id
2819 * @uses update_post_meta() To update the topic last active id meta
2820 * @uses apply_filters() Calls 'bbp_update_topic_last_active_id' with the active
2821 *                        id and topic id
2822 * @return int Active id
2823 */
2824function bbp_update_topic_last_active_id( $topic_id = 0, $active_id = 0 ) {
2825
2826        // If it's a reply, then get the parent (topic id)
2827        if ( bbp_is_reply( $topic_id ) ) {
2828                $topic_id = bbp_get_reply_topic_id( $topic_id );
2829        } else {
2830                $topic_id = bbp_get_topic_id( $topic_id );
2831        }
2832
2833        if ( empty( $active_id ) ) {
2834                $active_id = bbp_get_public_child_last_id( $topic_id, bbp_get_reply_post_type() );
2835        }
2836
2837        // Adjust last_id's based on last_reply post_type
2838        if ( empty( $active_id ) || ! bbp_is_reply( $active_id ) ) {
2839                $active_id = $topic_id;
2840        }
2841
2842        $active_id = (int) $active_id;
2843
2844        // Update only if published
2845        if ( bbp_get_public_status_id() === get_post_status( $active_id ) ) {
2846                update_post_meta( $topic_id, '_bbp_last_active_id', $active_id );
2847        }
2848
2849        return (int) apply_filters( 'bbp_update_topic_last_active_id', $active_id, $topic_id );
2850}
2851
2852/**
2853 * Update the topics last active date/time (aka freshness)
2854 *
2855 * @since 2.0.0 bbPress (r2680)
2856 *
2857 * @param int    $topic_id Optional. Topic id.
2858 * @param string $new_time Optional. New time in mysql format.
2859 * @uses bbp_is_reply() To check if the passed topic id is a reply
2860 * @uses bbp_get_topic_id() To get the topic id
2861 * @uses bbp_get_reply_topic_id() To get the reply topic id
2862 * @uses get_post_field() To get the timestamp of the newest topic reply
2863 * @uses bbp_get_public_child_last_id() To get the newest topic reply id
2864 * @uses bbp_get_reply_post_type() To get the reply post type
2865 * @uses update_post_meta() To update the topic last active time meta
2866 * @return string MySQL timestamp of last active reply
2867 */
2868function bbp_update_topic_last_active_time( $topic_id = 0, $new_time = '' ) {
2869
2870        // If it's a reply, then get the parent (topic id)
2871        if ( bbp_is_reply( $topic_id ) ) {
2872                $topic_id = bbp_get_reply_topic_id( $topic_id );
2873        } else {
2874                $topic_id = bbp_get_topic_id( $topic_id );
2875        }
2876
2877        // Check time and use current if empty
2878        if ( empty( $new_time ) ) {
2879                $new_time = get_post_field( 'post_date', bbp_get_public_child_last_id( $topic_id, bbp_get_reply_post_type() ) );
2880        }
2881
2882        // Update only if published
2883        if ( ! empty( $new_time ) ) {
2884                update_post_meta( $topic_id, '_bbp_last_active_time', $new_time );
2885        }
2886
2887        return apply_filters( 'bbp_update_topic_last_active_time', $new_time, $topic_id );
2888}
2889
2890/**
2891 * Update the topic with the most recent reply ID
2892 *
2893 * @since 2.0.0 bbPress (r2625)
2894 *
2895 * @param int $topic_id Optional. Topic id to update
2896 * @param int $reply_id Optional. Reply id
2897 * @uses bbp_is_reply() To check if the passed topic id is a reply
2898 * @uses bbp_get_reply_id() To get the reply id
2899 * @uses bbp_get_reply_topic_id() To get the reply topic id
2900 * @uses bbp_get_topic_id() To get the topic id
2901 * @uses bbp_get_reply_post_type() To get the reply post type
2902 * @uses bbp_get_public_child_last_id() To get the last public reply id
2903 * @uses update_post_meta() To update the topic last reply id meta
2904 * @uses apply_filters() Calls 'bbp_update_topic_last_reply_id' with the reply
2905 *                        id and topic id
2906 * @return int Reply id
2907 */
2908function bbp_update_topic_last_reply_id( $topic_id = 0, $reply_id = 0 ) {
2909
2910        // If it's a reply, then get the parent (topic id)
2911        if ( empty( $reply_id ) && bbp_is_reply( $topic_id ) ) {
2912                $reply_id = bbp_get_reply_id( $topic_id );
2913                $topic_id = bbp_get_reply_topic_id( $reply_id );
2914        } else {
2915                $reply_id = bbp_get_reply_id( $reply_id );
2916                $topic_id = bbp_get_topic_id( $topic_id );
2917        }
2918
2919        if ( empty( $reply_id ) ) {
2920                $reply_id = bbp_get_public_child_last_id( $topic_id, bbp_get_reply_post_type() );
2921        }
2922
2923        // Adjust last_id's based on last_reply post_type
2924        if ( empty( $reply_id ) || ! bbp_is_reply( $reply_id ) ) {
2925                $reply_id = 0;
2926        }
2927
2928        $reply_id = (int) $reply_id;
2929
2930        // Update if reply is published
2931        if ( bbp_is_reply_published( $reply_id ) ) {
2932                update_post_meta( $topic_id, '_bbp_last_reply_id', $reply_id );
2933        }
2934
2935        return (int) apply_filters( 'bbp_update_topic_last_reply_id', $reply_id, $topic_id );
2936}
2937
2938/**
2939 * Adjust the total voice count of a topic
2940 *
2941 * @since 2.0.0 bbPress (r2567)
2942 *
2943 * @param int $topic_id Optional. Topic id to update
2944 * @uses bbp_is_reply() To check if the passed topic id is a reply
2945 * @uses bbp_get_reply_topic_id() To get the reply topic id
2946 * @uses bbp_get_topic_id() To get the topic id
2947 * @uses bbp_get_reply_topic_id() To get the reply topic id
2948 * @uses bbp_get_reply_post_type() To get the reply post type
2949 * @uses bbp_get_topic_post_type() To get the topic post type
2950 * @uses wpdb::prepare() To prepare our sql query
2951 * @uses wpdb::get_var() To execute our query and get the column back
2952 * @uses update_post_meta() To update the topic voice count meta
2953 * @uses apply_filters() Calls 'bbp_update_topic_voice_count' with the voice
2954 *                        count and topic id
2955 * @return int Voice count
2956 */
2957function bbp_update_topic_voice_count( $topic_id = 0 ) {
2958
2959        // If it's a reply, then get the parent (topic id)
2960        if ( bbp_is_reply( $topic_id ) ) {
2961                $topic_id = bbp_get_reply_topic_id( $topic_id );
2962        } elseif ( bbp_is_topic( $topic_id ) ) {
2963                $topic_id = bbp_get_topic_id( $topic_id );
2964        } else {
2965                return;
2966        }
2967
2968        // Query the DB to get voices in this topic
2969        $bbp_db = bbp_db();
2970        $query  = $bbp_db->prepare( "SELECT COUNT( DISTINCT post_author ) FROM {$bbp_db->posts} WHERE ( post_parent = %d AND post_status = %s AND post_type = %s ) OR ( ID = %d AND post_type = %s )", $topic_id, bbp_get_public_status_id(), bbp_get_reply_post_type(), $topic_id, bbp_get_topic_post_type() );
2971        $voices = (int) $bbp_db->get_var( $query );
2972
2973        // Update the voice count for this topic id
2974        update_post_meta( $topic_id, '_bbp_voice_count', $voices );
2975
2976        return (int) apply_filters( 'bbp_update_topic_voice_count', $voices, $topic_id );
2977}
2978
2979/**
2980 * Adjust the total anonymous reply count of a topic
2981 *
2982 * @since 2.0.0 bbPress (r2567)
2983 *
2984 * @param int $topic_id Optional. Topic id to update
2985 * @uses bbp_is_reply() To check if the passed topic id is a reply
2986 * @uses bbp_get_reply_topic_id() To get the reply topic id
2987 * @uses bbp_get_topic_id() To get the topic id
2988 * @uses bbp_get_reply_topic_id() To get the reply topic id
2989 * @uses bbp_get_reply_post_type() To get the reply post type
2990 * @uses bbp_get_topic_post_type() To get the topic post type
2991 * @uses wpdb::prepare() To prepare our sql query
2992 * @uses wpdb::get_var() To execute our query and get the column back
2993 * @uses update_post_meta() To update the topic anonymous reply count meta
2994 * @uses apply_filters() Calls 'bbp_update_topic_anonymous_reply_count' with the
2995 *                        anonymous reply count and topic id
2996 * @return int Anonymous reply count
2997 */
2998function bbp_update_topic_anonymous_reply_count( $topic_id = 0 ) {
2999
3000        // If it's a reply, then get the parent (topic id)
3001        if ( bbp_is_reply( $topic_id ) ) {
3002                $topic_id = bbp_get_reply_topic_id( $topic_id );
3003        } elseif ( bbp_is_topic( $topic_id ) ) {
3004                $topic_id = bbp_get_topic_id( $topic_id );
3005        } else {
3006                return;
3007        }
3008
3009        // Query the DB to get anonymous replies in this topic
3010        $bbp_db  = bbp_db();
3011        $query   = $bbp_db->prepare( "SELECT COUNT( ID ) FROM {$bbp_db->posts} WHERE ( post_parent = %d AND post_status = %s AND post_type = %s AND post_author = 0 ) OR ( ID = %d AND post_type = %s AND post_author = 0 )", $topic_id, bbp_get_public_status_id(), bbp_get_reply_post_type(), $topic_id, bbp_get_topic_post_type() );
3012        $replies = (int) $bbp_db->get_var( $query );
3013
3014        update_post_meta( $topic_id, '_bbp_anonymous_reply_count', $replies );
3015
3016        return (int) apply_filters( 'bbp_update_topic_anonymous_reply_count', $replies, $topic_id );
3017}
3018
3019/**
3020 * Update the revision log of the topic
3021 *
3022 * @since 2.0.0 bbPress (r2782)
3023 *
3024 * @param array $args Supports these args:
3025 *  - topic_id: Topic id
3026 *  - author_id: Author id
3027 *  - reason: Reason for editing
3028 *  - revision_id: Revision id
3029 * @uses bbp_get_topic_id() To get the topic id
3030 * @uses bbp_format_revision_reason() To format the reason
3031 * @uses bbp_get_topic_raw_revision_log() To get the raw topic revision log
3032 * @uses update_post_meta() To update the topic revision log meta
3033 * @return mixed False on failure, true on success
3034 */
3035function bbp_update_topic_revision_log( $args = array() ) {
3036
3037        // Parse arguments against default values
3038        $r = bbp_parse_args( $args, array(
3039                'reason'      => '',
3040                'topic_id'    => 0,
3041                'author_id'   => 0,
3042                'revision_id' => 0
3043        ), 'update_topic_revision_log' );
3044
3045        // Populate the variables
3046        $r['reason']      = bbp_format_revision_reason( $r['reason'] );
3047        $r['topic_id']    = bbp_get_topic_id( $r['topic_id'] );
3048        $r['author_id']   = bbp_get_user_id ( $r['author_id'], false, true );
3049        $r['revision_id'] = (int) $r['revision_id'];
3050
3051        // Get the logs and append the new one to those
3052        $revision_log                      = bbp_get_topic_raw_revision_log( $r['topic_id'] );
3053        $revision_log[ $r['revision_id'] ] = array( 'author' => $r['author_id'], 'reason' => $r['reason'] );
3054
3055        // Finally, update
3056        return update_post_meta( $r['topic_id'], '_bbp_revision_log', $revision_log );
3057}
3058
3059/** Topic Actions *************************************************************/
3060
3061/**
3062 * Closes a topic
3063 *
3064 * @since 2.0.0 bbPress (r2740)
3065 *
3066 * @param int $topic_id Topic id
3067 * @uses bbp_get_topic() To get the topic
3068 * @uses get_post_meta() To get the topic status meta
3069 * @uses bbp_get_closed_status_id() to get the closed status
3070 * @uses bbp_get_public_status_id() to get the public status
3071 * @uses do_action() Calls 'bbp_close_topic' with the topic id
3072 * @uses add_post_meta() To add the previous status to a meta
3073 * @uses post_type_supports() To check if revisions are enabled
3074 * @uses bbp_get_topic_post_type() To get the topic post type
3075 * @uses remove_post_type_support() To temporarily remove topic revisions
3076 * @uses wp_update_post() To update the topic with the new status
3077 * @uses add_post_type_support() To restore topic revisions
3078 * @uses do_action() Calls 'bbp_closed_topic' with the topic id
3079 * @return mixed False or {@link WP_Error} on failure, topic id on success
3080 */
3081function bbp_close_topic( $topic_id = 0 ) {
3082
3083        // Get topic
3084        $topic = bbp_get_topic( $topic_id );
3085        if ( empty( $topic ) ) {
3086                return $topic;
3087        }
3088
3089        // Get previous topic status meta
3090        $topic_status = get_post_meta( $topic_id, '_bbp_status', true );
3091
3092        // Bail if already closed and topic status meta exists
3093        if ( bbp_get_closed_status_id() === $topic->post_status && ! empty( $topic_status ) ) {
3094                return false;
3095        }
3096
3097        // Set status meta public
3098        $topic_status = bbp_get_public_status_id();
3099
3100        // Execute pre close code
3101        do_action( 'bbp_close_topic', $topic_id );
3102
3103        // Add pre close status
3104        add_post_meta( $topic_id, '_bbp_status', $topic_status );
3105
3106        // Set closed status
3107        $topic->post_status = bbp_get_closed_status_id();
3108
3109        // Toggle revisions off as we are not altering content
3110        if ( post_type_supports( bbp_get_topic_post_type(), 'revisions' ) ) {
3111                $revisions_removed = true;
3112                remove_post_type_support( bbp_get_topic_post_type(), 'revisions' );
3113        }
3114
3115        // Update topic
3116        $topic_id = wp_update_post( $topic );
3117
3118        // Toggle revisions back on
3119        if ( true === $revisions_removed ) {
3120                $revisions_removed = false;
3121                add_post_type_support( bbp_get_topic_post_type(), 'revisions' );
3122        }
3123
3124        // Execute post close code
3125        do_action( 'bbp_closed_topic', $topic_id );
3126
3127        // Return topic_id
3128        return $topic_id;
3129}
3130
3131/**
3132 * Opens a topic
3133 *
3134 * @since 2.0.0 bbPress (r2740)
3135 *
3136 * @param int $topic_id Topic id
3137 * @uses bbp_get_topic() To get the topic
3138 * @uses do_action() Calls 'bbp_open_topic' with the topic id
3139 * @uses get_post_meta() To get the previous status
3140 * @uses delete_post_meta() To delete the previous status meta
3141 * @uses post_type_supports() To check if revisions are enabled
3142 * @uses bbp_get_topic_post_type() To get the topic post type
3143 * @uses remove_post_type_support() To temporarily remove topic revisions
3144 * @uses wp_update_post() To update the topic with the new status
3145 * @uses add_post_type_support() To restore topic revisions
3146 * @uses do_action() Calls 'bbp_opened_topic' with the topic id
3147 * @return mixed False or {@link WP_Error} on failure, topic id on success
3148 */
3149function bbp_open_topic( $topic_id = 0 ) {
3150
3151        // Get topic
3152        $topic = bbp_get_topic( $topic_id );
3153        if ( empty( $topic ) ) {
3154                return $topic;
3155        }
3156
3157        // Bail if not closed
3158        if ( bbp_get_closed_status_id() !== $topic->post_status ) {
3159                return false;
3160        }
3161
3162        // Execute pre open code
3163        do_action( 'bbp_open_topic', $topic_id );
3164
3165        // Get previous status
3166        $topic_status = get_post_meta( $topic_id, '_bbp_status', true );
3167
3168        // If no previous status, default to publish
3169        if ( empty( $topic_status ) ) {
3170                $topic_status = bbp_get_public_status_id();
3171        }
3172
3173        // Set previous status
3174        $topic->post_status = $topic_status;
3175
3176        // Remove old status meta
3177        delete_post_meta( $topic_id, '_bbp_status' );
3178
3179        // Toggle revisions off as we are not altering content
3180        if ( post_type_supports( bbp_get_topic_post_type(), 'revisions' ) ) {
3181                $revisions_removed = true;
3182                remove_post_type_support( bbp_get_topic_post_type(), 'revisions' );
3183        }
3184
3185        // Update topic
3186        $topic_id = wp_update_post( $topic );
3187
3188        // Toggle revisions back on
3189        if ( true === $revisions_removed ) {
3190                $revisions_removed = false;
3191                add_post_type_support( bbp_get_topic_post_type(), 'revisions' );
3192        }
3193
3194        // Execute post open code
3195        do_action( 'bbp_opened_topic', $topic_id );
3196
3197        // Return topic_id
3198        return $topic_id;
3199}
3200
3201/**
3202 * Marks a topic as spam
3203 *
3204 * @since 2.0.0 bbPress (r2740)
3205 *
3206 * @param int $topic_id Topic id
3207 * @uses bbp_get_topic() To get the topic
3208 * @uses do_action() Calls 'bbp_spam_topic' with the topic id
3209 * @uses add_post_meta() To add the previous status to a meta
3210 * @uses wp_update_post() To update the topic with the new status
3211 * @uses do_action() Calls 'bbp_spammed_topic' with the topic id
3212 * @return mixed False or {@link WP_Error} on failure, topic id on success
3213 */
3214function bbp_spam_topic( $topic_id = 0 ) {
3215
3216        // Get the topic
3217        $topic = bbp_get_topic( $topic_id );
3218        if ( empty( $topic ) ) {
3219                return $topic;
3220        }
3221
3222        // Bail if topic is spam
3223        if ( bbp_get_spam_status_id() === $topic->post_status ) {
3224                return false;
3225        }
3226
3227        // Add the original post status as post meta for future restoration
3228        add_post_meta( $topic_id, '_bbp_spam_meta_status', $topic->post_status );
3229
3230        // Execute pre spam code
3231        do_action( 'bbp_spam_topic', $topic_id );
3232
3233        // Set post status to spam
3234        $topic->post_status = bbp_get_spam_status_id();
3235
3236        // Empty the topic of its tags
3237        $topic->tax_input = bbp_spam_topic_tags( $topic_id );
3238
3239        // No revisions
3240        remove_action( 'pre_post_update', 'wp_save_post_revision' );
3241
3242        // Update the topic
3243        $topic_id = wp_update_post( $topic );
3244
3245        // Execute post spam code
3246        do_action( 'bbp_spammed_topic', $topic_id );
3247
3248        // Return topic_id
3249        return $topic_id;
3250}
3251
3252/**
3253 * Trash replies to a topic when it's marked as spam
3254 *
3255 * Usually you'll want to do this before the topic itself is marked as spam.
3256 *
3257 * @since 2.6.0 bbPress (r5405)
3258 *
3259 * @param int $topic_id
3260 */
3261function bbp_spam_topic_replies( $topic_id = 0 ) {
3262
3263        // Validation
3264        $topic_id = bbp_get_topic_id( $topic_id );
3265
3266        // Topic is being spammed, so its replies are trashed
3267        $replies = new WP_Query( array(
3268                'suppress_filters' => true,
3269                'post_type'        => bbp_get_reply_post_type(),
3270                'post_status'      => bbp_get_public_status_id(),
3271                'post_parent'      => $topic_id,
3272                'posts_per_page'   => -1,
3273                'nopaging'         => true,
3274                'no_found_rows'    => true,
3275                'fields'           => 'id=>parent'
3276        ) );
3277
3278        if ( ! empty( $replies->posts ) ) {
3279
3280                // Prevent debug notices
3281                $pre_spammed_replies = array();
3282
3283                // Loop through replies, trash them, and add them to array
3284                foreach ( $replies->posts as $reply ) {
3285                        wp_trash_post( $reply->ID );
3286                        $pre_spammed_replies[] = $reply->ID;
3287                }
3288
3289                // Set a post_meta entry of the replies that were trashed by this action.
3290                // This is so we can possibly untrash them, without untrashing replies
3291                // that were purposefully trashed before.
3292                update_post_meta( $topic_id, '_bbp_pre_spammed_replies', $pre_spammed_replies );
3293
3294                // Reset the global post data after looping through the above WP_Query
3295                wp_reset_postdata();
3296        }
3297}
3298
3299/**
3300 * Store the tags to a topic in post meta before it's marked as spam so they
3301 * can be retreived and unspammed later.
3302 *
3303 * Usually you'll want to do this before the topic itself is marked as spam.
3304 *
3305 * @since 2.6.0 bbPress (r5405)
3306 *
3307 * @param int $topic_id
3308 */
3309function bbp_spam_topic_tags( $topic_id = 0 ) {
3310
3311        // Validation
3312        $topic_id = bbp_get_topic_id( $topic_id );
3313
3314        // Get topic tags
3315        $terms = get_the_terms( $topic_id, bbp_get_topic_tag_tax_id() );
3316
3317        // Define local variable(s)
3318        $term_names = array();
3319
3320        // Topic has tags
3321        if ( ! empty( $terms ) ) {
3322
3323                // Loop through and collect term names
3324                foreach ( $terms as $term ) {
3325                        $term_names[] = $term->name;
3326                }
3327
3328                // Topic terms have slugs
3329                if ( ! empty( $term_names ) ) {
3330
3331                        // Add the original post status as post meta for future restoration
3332                        add_post_meta( $topic_id, '_bbp_spam_topic_tags', $term_names );
3333                }
3334        }
3335
3336        return array( bbp_get_topic_tag_tax_id() => '' );
3337}
3338
3339/**
3340 * Unspams a topic
3341 *
3342 * @since 2.0.0 bbPress (r2740)
3343 *
3344 * @param int $topic_id Topic id
3345 * @uses bbp_get_topic() To get the topic
3346 * @uses do_action() Calls 'bbp_unspam_topic' with the topic id
3347 * @uses get_post_meta() To get the previous status
3348 * @uses delete_post_meta() To delete the previous status meta
3349 * @uses wp_update_post() To update the topic with the new status
3350 * @uses do_action() Calls 'bbp_unspammed_topic' with the topic id
3351 * @return mixed False or {@link WP_Error} on failure, topic id on success
3352 */
3353function bbp_unspam_topic( $topic_id = 0 ) {
3354
3355        // Get the topic
3356        $topic = bbp_get_topic( $topic_id );
3357        if ( empty( $topic ) ) {
3358                return $topic;
3359        }
3360
3361        // Bail if already not spam
3362        if ( bbp_get_spam_status_id() !== $topic->post_status ) {
3363                return false;
3364        }
3365
3366        // Execute pre unspam code
3367        do_action( 'bbp_unspam_topic', $topic_id );
3368
3369        // Get pre spam status
3370        $topic_status = get_post_meta( $topic_id, '_bbp_spam_meta_status', true );
3371
3372        // If no previous status, default to publish
3373        if ( empty( $topic_status ) ) {
3374                $topic_status = bbp_get_public_status_id();
3375        }
3376
3377        // Set post status to pre spam
3378        $topic->post_status = $topic_status;
3379        $topic->tax_input   = bbp_unspam_topic_tags( $topic_id );
3380
3381        // Delete pre spam meta
3382        delete_post_meta( $topic_id, '_bbp_spam_meta_status' );
3383
3384        // No revisions
3385        remove_action( 'pre_post_update', 'wp_save_post_revision' );
3386
3387        // Update the topic
3388        $topic_id = wp_update_post( $topic );
3389
3390        // Execute post unspam code
3391        do_action( 'bbp_unspammed_topic', $topic_id );
3392
3393        // Return topic_id
3394        return $topic_id;
3395}
3396
3397/**
3398 * Untrash replies to a topic previously marked as spam.
3399 *
3400 * Usually you'll want to do this after the topic is unspammed.
3401 *
3402 * @since 2.6.0 bbPress (r5405)
3403 *
3404 * @param int $topic_id
3405 */
3406function bbp_unspam_topic_replies( $topic_id = 0 ) {
3407
3408        // Validation
3409        $topic_id = bbp_get_topic_id( $topic_id );
3410
3411        // Get the replies that were not previously trashed
3412        $pre_spammed_replies = get_post_meta( $topic_id, '_bbp_pre_spammed_replies', true );
3413
3414        // There are replies to untrash
3415        if ( ! empty( $pre_spammed_replies ) ) {
3416
3417                // Maybe reverse the trashed replies array
3418                if ( is_array( $pre_spammed_replies ) ) {
3419                        $pre_spammed_replies = array_reverse( $pre_spammed_replies );
3420                }
3421
3422                // Loop through replies
3423                foreach ( (array) $pre_spammed_replies as $reply ) {
3424                        wp_untrash_post( $reply );
3425                }
3426        }
3427
3428        // Clear the trasheed reply meta for the topic
3429        delete_post_meta( $topic_id, '_bbp_pre_spammed_replies' );
3430}
3431
3432/**
3433 * Retreive tags to a topic from post meta before it's unmarked as spam so they.
3434 *
3435 * Usually you'll want to do this before the topic itself is unmarked as spam.
3436 *
3437 * @since 2.6.0 bbPress (r5405)
3438 *
3439 * @param int $topic_id
3440 */
3441function bbp_unspam_topic_tags( $topic_id = 0 ) {
3442
3443        // Validation
3444        $topic_id = bbp_get_topic_id( $topic_id );
3445
3446        // Get pre-spam topic tags
3447        $terms = get_post_meta( $topic_id, '_bbp_spam_topic_tags', true );
3448
3449        // Delete pre-spam topic tag meta
3450        if ( ! empty( $terms ) ) {
3451                delete_post_meta( $topic_id, '_bbp_spam_topic_tags' );
3452        }
3453
3454        return array( bbp_get_topic_tag_tax_id() => $terms );
3455}
3456
3457/**
3458 * Sticks a topic to a forum or front
3459 *
3460 * @since 2.0.0 bbPress (r2754)
3461 *
3462 * @param int $topic_id Optional. Topic id
3463 * @param int $super Should we make the topic a super sticky?
3464 * @uses bbp_get_topic_id() To get the topic id
3465 * @uses bbp_unstick_topic() To unstick the topic
3466 * @uses bbp_get_topic_forum_id() To get the topic forum id
3467 * @uses bbp_get_stickies() To get the stickies
3468 * @uses do_action() 'bbp_stick_topic' with topic id and bool super
3469 * @uses update_option() To update the super stickies option
3470 * @uses update_post_meta() To update the forum stickies meta
3471 * @uses do_action() Calls 'bbp_stuck_topic' with the topic id, bool super
3472 *                    and success
3473 * @return bool True on success, false on failure
3474 */
3475function bbp_stick_topic( $topic_id = 0, $super = false ) {
3476
3477        // Validation
3478        $topic_id = bbp_get_topic_id( $topic_id );
3479
3480        // Bail if a topic is not a topic (prevents revisions as stickies)
3481        if ( ! bbp_is_topic( $topic_id ) ) {
3482                return false;
3483        }
3484
3485        // We may have a super sticky to which we want to convert into a normal
3486        // sticky and vice versa; unstick the topic first to avoid any possible error.
3487        bbp_unstick_topic( $topic_id );
3488
3489        $forum_id = empty( $super ) ? bbp_get_topic_forum_id( $topic_id ) : 0;
3490        $stickies = bbp_get_stickies( $forum_id );
3491
3492        do_action( 'bbp_stick_topic', $topic_id, $super );
3493
3494        if ( ! is_array( $stickies ) ) {
3495                $stickies   = array( $topic_id );
3496        } else {
3497                $stickies[] = $topic_id;
3498        }
3499
3500        // Pull out duplicates and empties
3501        $stickies = array_unique( array_filter( $stickies ) );
3502
3503        // Unset incorrectly stuck revisions
3504        foreach ( (array) $stickies as $key => $id ) {
3505                if ( ! bbp_is_topic( $id ) ) {
3506                        unset( $stickies[ $key ] );
3507                }
3508        }
3509
3510        // Reset keys
3511        $stickies = array_values( $stickies );
3512        $success  = ! empty( $super ) ? update_option( '_bbp_super_sticky_topics', $stickies ) : update_post_meta( $forum_id, '_bbp_sticky_topics', $stickies );
3513
3514        do_action( 'bbp_stuck_topic', $topic_id, $super, $success );
3515
3516        return (bool) $success;
3517}
3518
3519/**
3520 * Approves a pending topic
3521 *
3522 * @since 2.6.0 bbPress (r5503)
3523 *
3524 * @param int $topic_id Topic id
3525 * @uses bbp_get_topic() To get the topic
3526 * @uses bbp_get_pending_status_id() To get the pending status id
3527 * @uses do_action() Calls 'bbp_approve_topic' with the topic id
3528 * @uses bbp_get_public_status_id() To get the public status id
3529 * @uses remove_action() To remove the auto save post revision action
3530 * @uses wp_update_post() To update the topic with the new status
3531 * @uses do_action() Calls 'bbp_approved_topic' with the topic id
3532 * @return mixed False or {@link WP_Error} on failure, topic id on success
3533 */
3534function bbp_approve_topic( $topic_id = 0 ) {
3535
3536        // Get topic
3537        $topic = bbp_get_topic( $topic_id );
3538        if ( empty( $topic ) ) {
3539                return $topic;
3540        }
3541
3542        // Bail if already approved
3543        if ( bbp_get_pending_status_id() !== $topic->post_status ) {
3544                return false;
3545        }
3546
3547        // Execute pre pending code
3548        do_action( 'bbp_approve_topic', $topic_id );
3549
3550        // Set publish status
3551        $topic->post_status = bbp_get_public_status_id();
3552
3553        // No revisions
3554        remove_action( 'pre_post_update', 'wp_save_post_revision' );
3555
3556        // Update topic
3557        $topic_id = wp_update_post( $topic );
3558
3559        // Execute post pending code
3560        do_action( 'bbp_approved_topic', $topic_id );
3561
3562        // Return topic_id
3563        return $topic_id;
3564}
3565
3566/**
3567 * Unapproves a topic
3568 *
3569 * @since 2.6.0 bbPress (r5503)
3570 *
3571 * @param int $topic_id Topic id
3572 * @uses bbp_get_topic() To get the topic
3573 * @uses bbp_get_pending_status_id() To get the pending status id
3574 * @uses do_action() Calls 'bbp_unapprove_topic' with the topic id
3575 * @uses remove_action() To remove the auto save post revision action
3576 * @uses wp_update_post() To update the topic with the new status
3577 * @uses do_action() Calls 'bbp_unapproved_topic' with the topic id
3578 * @return mixed False or {@link WP_Error} on failure, topic id on success
3579 */
3580function bbp_unapprove_topic( $topic_id = 0 ) {
3581
3582        // Get topic
3583        $topic = bbp_get_topic( $topic_id );
3584        if ( empty( $topic ) ) {
3585                return $topic;
3586        }
3587
3588        // Bail if already pending
3589        if ( bbp_get_pending_status_id() === $topic->post_status ) {
3590                return false;
3591        }
3592
3593        // Execute pre open code
3594        do_action( 'bbp_unapprove_topic', $topic_id );
3595
3596        // Set pending status
3597        $topic->post_status = bbp_get_pending_status_id();
3598
3599        // No revisions
3600        remove_action( 'pre_post_update', 'wp_save_post_revision' );
3601
3602        // Update topic
3603        $topic_id = wp_update_post( $topic );
3604
3605        // Execute post open code
3606        do_action( 'bbp_unapproved_topic', $topic_id );
3607
3608        // Return topic_id
3609        return $topic_id;
3610}
3611
3612/**
3613 * Unsticks a topic both from front and it's forum
3614 *
3615 * @since 2.0.0 bbPress (r2754)
3616 *
3617 * @param int $topic_id Optional. Topic id
3618 * @uses bbp_get_topic_id() To get the topic id
3619 * @uses bbp_is_topic_super_sticky() To check if the topic is a super sticky
3620 * @uses bbp_get_topic_forum_id() To get the topic forum id
3621 * @uses bbp_get_stickies() To get the forum stickies
3622 * @uses do_action() Calls 'bbp_unstick_topic' with the topic id
3623 * @uses delete_option() To delete the super stickies option
3624 * @uses update_option() To update the super stickies option
3625 * @uses delete_post_meta() To delete the forum stickies meta
3626 * @uses update_post_meta() To update the forum stickies meta
3627 * @uses do_action() Calls 'bbp_unstuck_topic' with the topic id and success
3628 * @return bool Always true.
3629 */
3630function bbp_unstick_topic( $topic_id = 0 ) {
3631        $topic_id = bbp_get_topic_id( $topic_id );
3632        $super    = bbp_is_topic_super_sticky( $topic_id );
3633        $forum_id = empty( $super ) ? bbp_get_topic_forum_id( $topic_id ) : 0;
3634        $stickies = bbp_get_stickies( $forum_id );
3635        $offset   = array_search( $topic_id, $stickies );
3636
3637        do_action( 'bbp_unstick_topic', $topic_id );
3638
3639        if ( empty( $stickies ) ) {
3640                $success = true;
3641        } elseif ( ! in_array( $topic_id, $stickies ) ) {
3642                $success = true;
3643        } elseif ( false === $offset ) {
3644                $success = true;
3645        } else {
3646                array_splice( $stickies, $offset, 1 );
3647                if ( empty( $stickies ) ) {
3648                        $success = ! empty( $super ) ? delete_option( '_bbp_super_sticky_topics'            ) : delete_post_meta( $forum_id, '_bbp_sticky_topics'            );
3649                } else {
3650                        $success = ! empty( $super ) ? update_option( '_bbp_super_sticky_topics', $stickies ) : update_post_meta( $forum_id, '_bbp_sticky_topics', $stickies );
3651                }
3652        }
3653
3654        do_action( 'bbp_unstuck_topic', $topic_id, $success );
3655
3656        return (bool) $success;
3657}
3658
3659/** Before Delete/Trash/Untrash ***********************************************/
3660
3661/**
3662 * Called before deleting a topic.
3663 *
3664 * This function is supplemental to the actual topic deletion which is
3665 * handled by WordPress core API functions. It is used to clean up after
3666 * a topic that is being deleted.
3667 *
3668 * @uses bbp_get_topic_id() To get the topic id
3669 * @uses bbp_is_topic() To check if the passed id is a topic
3670 * @uses do_action() Calls 'bbp_delete_topic' with the topic id
3671 * @uses bbp_has_replies() To check if the topic has replies
3672 * @uses bbp_replies() To loop through the replies
3673 * @uses bbp_the_reply() To set a reply as the current reply in the loop
3674 * @uses bbp_get_reply_id() To get the reply id
3675 * @uses wp_delete_post() To delete the reply
3676 */
3677function bbp_delete_topic( $topic_id = 0 ) {
3678
3679        // Validate topic ID
3680        $topic_id = bbp_get_topic_id( $topic_id );
3681
3682        if ( empty( $topic_id ) || ! bbp_is_topic( $topic_id ) ) {
3683                return false;
3684        }
3685
3686        do_action( 'bbp_delete_topic', $topic_id );
3687}
3688
3689/**
3690 * Delete replies to a topic when it's deleted
3691 *
3692 * Usually you'll want to do this before the topic itself is deleted.
3693 *
3694 * @since 2.6.0 bbPress (r5405)
3695 *
3696 * @param int $topic_id
3697 */
3698function bbp_delete_topic_replies( $topic_id = 0 ) {
3699
3700        // Validate topic ID
3701        $topic_id = bbp_get_topic_id( $topic_id );
3702
3703        // Topic is being permanently deleted, so its replies gotta go too
3704        // Note that we get all post statuses here
3705        $replies = new WP_Query( array(
3706                'suppress_filters' => true,
3707                'post_type'        => bbp_get_reply_post_type(),
3708                'post_status'      => array_keys( get_post_stati() ),
3709                'post_parent'      => $topic_id,
3710                'posts_per_page'   => -1,
3711                'nopaging'         => true,
3712                'no_found_rows'    => true,
3713                'fields'           => 'id=>parent'
3714        ) );
3715
3716        // Loop through and delete child replies
3717        if ( ! empty( $replies->posts ) ) {
3718                foreach ( $replies->posts as $reply ) {
3719                        wp_delete_post( $reply->ID, true );
3720                }
3721
3722                // Reset the $post global
3723                wp_reset_postdata();
3724        }
3725}
3726
3727/**
3728 * Called before trashing a topic
3729 *
3730 * This function is supplemental to the actual topic being trashed which is
3731 * handled by WordPress core API functions. It is used to clean up after
3732 * a topic that is being trashed.
3733 *
3734 * @uses bbp_get_topic_id() To get the topic id
3735 * @uses bbp_is_topic() To check if the passed id is a topic
3736 * @uses do_action() Calls 'bbp_trash_topic' with the topic id
3737 * @uses wp_trash_post() To trash the reply
3738 * @uses update_post_meta() To save a list of just trashed replies for future use
3739 */
3740function bbp_trash_topic( $topic_id = 0 ) {
3741
3742        // Validate topic ID
3743        $topic_id = bbp_get_topic_id( $topic_id );
3744
3745        if ( empty( $topic_id ) || ! bbp_is_topic( $topic_id ) ) {
3746                return false;
3747        }
3748
3749        do_action( 'bbp_trash_topic', $topic_id );
3750}
3751
3752/**
3753 * Trash replies to a topic when it's trashed.
3754 *
3755 * Usually you'll want to do this before the topic itself is marked as spam.
3756 *
3757 * @since 2.6.0 bbPress (r5405)
3758 *
3759 * @param int $topic_id
3760 */
3761function bbp_trash_topic_replies( $topic_id = 0 ) {
3762
3763        // Validate topic ID
3764        $topic_id = bbp_get_topic_id( $topic_id );
3765
3766        // Topic is being trashed, so its replies are trashed too
3767        $replies = new WP_Query( array(
3768                'suppress_filters' => true,
3769                'post_type'        => bbp_get_reply_post_type(),
3770                'post_status'      => bbp_get_public_status_id(),
3771                'post_parent'      => $topic_id,
3772                'posts_per_page'   => -1,
3773                'nopaging'         => true,
3774                'no_found_rows'    => true,
3775                'fields'           => 'id=>parent'
3776        ) );
3777
3778        if ( ! empty( $replies->posts ) ) {
3779
3780                // Prevent debug notices
3781                $pre_trashed_replies = array();
3782
3783                // Loop through replies, trash them, and add them to array
3784                foreach ( $replies->posts as $reply ) {
3785                        wp_trash_post( $reply->ID );
3786                        $pre_trashed_replies[] = $reply->ID;
3787                }
3788
3789                // Set a post_meta entry of the replies that were trashed by this action.
3790                // This is so we can possibly untrash them, without untrashing replies
3791                // that were purposefully trashed before.
3792                update_post_meta( $topic_id, '_bbp_pre_trashed_replies', $pre_trashed_replies );
3793
3794                // Reset the $post global
3795                wp_reset_postdata();
3796        }
3797}
3798
3799/**
3800 * Called before untrashing a topic
3801 *
3802 * @uses bbp_get_topic_id() To get the topic id
3803 * @uses bbp_is_topic() To check if the passed id is a topic
3804 * @uses do_action() Calls 'bbp_untrash_topic' with the topic id
3805 * @uses get_post_meta() To get the list of replies which were trashed with the
3806 *                        topic
3807 * @uses wp_untrash_post() To untrash the reply
3808 */
3809function bbp_untrash_topic( $topic_id = 0 ) {
3810        $topic_id = bbp_get_topic_id( $topic_id );
3811
3812        if ( empty( $topic_id ) || ! bbp_is_topic( $topic_id ) ) {
3813                return false;
3814        }
3815
3816        do_action( 'bbp_untrash_topic', $topic_id );
3817}
3818
3819/**
3820 * Untrash replies to a topic previously trashed.
3821 *
3822 * Usually you'll want to do this after the topic is unspammed.
3823 *
3824 * @since 2.6.0 bbPress (r5405)
3825 *
3826 * @param int $topic_id
3827 */
3828function bbp_untrash_topic_replies( $topic_id = 0 ) {
3829
3830        // Validation
3831        $topic_id = bbp_get_topic_id( $topic_id );
3832
3833        // Get the replies that were not previously trashed
3834        $pre_trashed_replies = get_post_meta( $topic_id, '_bbp_pre_trashed_replies', true );
3835
3836        // There are replies to untrash
3837        if ( ! empty( $pre_trashed_replies ) ) {
3838
3839                // Maybe reverse the trashed replies array
3840                if ( is_array( $pre_trashed_replies ) ) {
3841                        $pre_trashed_replies = array_reverse( $pre_trashed_replies );
3842                }
3843
3844                // Loop through replies
3845                foreach ( (array) $pre_trashed_replies as $reply ) {
3846                        wp_untrash_post( $reply );
3847                }
3848        }
3849
3850        // Clear the trashed reply meta for the topic
3851        delete_post_meta( $topic_id, '_bbp_pre_trashed_replies' );
3852}
3853
3854/** After Delete/Trash/Untrash ************************************************/
3855
3856/**
3857 * Called after deleting a topic
3858 *
3859 * @uses bbp_get_topic_id() To get the topic id
3860 * @uses bbp_is_topic() To check if the passed id is a topic
3861 * @uses do_action() Calls 'bbp_deleted_topic' with the topic id
3862 */
3863function bbp_deleted_topic( $topic_id = 0 ) {
3864        $topic_id = bbp_get_topic_id( $topic_id );
3865
3866        if ( empty( $topic_id ) || ! bbp_is_topic( $topic_id ) ) {
3867                return false;
3868        }
3869
3870        do_action( 'bbp_deleted_topic', $topic_id );
3871}
3872
3873/**
3874 * Called after trashing a topic
3875 *
3876 * @uses bbp_get_topic_id() To get the topic id
3877 * @uses bbp_is_topic() To check if the passed id is a topic
3878 * @uses do_action() Calls 'bbp_trashed_topic' with the topic id
3879 */
3880function bbp_trashed_topic( $topic_id = 0 ) {
3881        $topic_id = bbp_get_topic_id( $topic_id );
3882
3883        if ( empty( $topic_id ) || ! bbp_is_topic( $topic_id ) ) {
3884                return false;
3885        }
3886
3887        do_action( 'bbp_trashed_topic', $topic_id );
3888}
3889
3890/**
3891 * Called after untrashing a topic
3892 *
3893 * @uses bbp_get_topic_id() To get the topic id
3894 * @uses bbp_is_topic() To check if the passed id is a topic
3895 * @uses do_action() Calls 'bbp_untrashed_topic' with the topic id
3896 */
3897function bbp_untrashed_topic( $topic_id = 0 ) {
3898        $topic_id = bbp_get_topic_id( $topic_id );
3899
3900        if ( empty( $topic_id ) || ! bbp_is_topic( $topic_id ) ) {
3901                return false;
3902        }
3903
3904        do_action( 'bbp_untrashed_topic', $topic_id );
3905}
3906
3907/** Settings ******************************************************************/
3908
3909/**
3910 * Return the topics per page setting
3911 *
3912 * @since 2.0.0 bbPress (r3540)
3913 *
3914 * @param int $default Default replies per page (15)
3915 * @uses get_option() To get the setting
3916 * @uses apply_filters() To allow the return value to be manipulated
3917 * @return int
3918 */
3919function bbp_get_topics_per_page( $default = 15 ) {
3920
3921        // Get database option and cast as integer
3922        $retval = get_option( '_bbp_topics_per_page', $default );
3923
3924        // If return val is empty, set it to default
3925        if ( empty( $retval ) ) {
3926                $retval = $default;
3927        }
3928
3929        // Filter and return
3930        return (int) apply_filters( 'bbp_get_topics_per_page', $retval, $default );
3931}
3932
3933/**
3934 * Return the topics per RSS page setting
3935 *
3936 * @since 2.0.0 bbPress (r3540)
3937 *
3938 * @param int $default Default replies per page (25)
3939 * @uses get_option() To get the setting
3940 * @uses apply_filters() To allow the return value to be manipulated
3941 * @return int
3942 */
3943function bbp_get_topics_per_rss_page( $default = 25 ) {
3944
3945        // Get database option and cast as integer
3946        $retval = get_option( '_bbp_topics_per_rss_page', $default );
3947
3948        // If return val is empty, set it to default
3949        if ( empty( $retval ) ) {
3950                $retval = $default;
3951        }
3952
3953        // Filter and return
3954        return (int) apply_filters( 'bbp_get_topics_per_rss_page', $retval, $default );
3955}
3956
3957/** Topic Tags ****************************************************************/
3958
3959/**
3960 * Get topic tags for a specific topic ID
3961 *
3962 * @since 2.6.0 bbPress (r5836)
3963 *
3964 * @param int $topic_id
3965 *
3966 * @return string
3967 */
3968function bbp_get_topic_tags( $topic_id = 0 ) {
3969        $topic_id   = bbp_get_topic_id( $topic_id );
3970        $terms      = (array) get_the_terms( $topic_id, bbp_get_topic_tag_tax_id() );
3971        $topic_tags = array_filter( $terms );
3972
3973        return apply_filters( 'bbp_get_topic_tags', $topic_tags, $topic_id );
3974}
3975
3976/**
3977 * Get topic tags for a specific topic ID
3978 *
3979 * @since 2.2.0 bbPress (r4165)
3980 *
3981 * @param int    $topic_id
3982 * @param string $sep
3983 *
3984 * @return string
3985 */
3986function bbp_get_topic_tag_names( $topic_id = 0, $sep = ', ' ) {
3987        $topic_tags = bbp_get_topic_tags( $topic_id );
3988        $pluck      = wp_list_pluck( $topic_tags, 'name' );
3989        $terms      = ! empty( $pluck ) ? implode( $sep, $pluck ) : '';
3990
3991        return apply_filters( 'bbp_get_topic_tag_names', $terms, $topic_id, $sep );
3992}
3993
3994/**
3995 * Will update topic-tag count based on object type.
3996 *
3997 * Function for the default callback for topic-tag taxonomies.
3998 *
3999 * @see https://bbpress.trac.wordpress.org/ticket/3043
4000 * @access private
4001 *
4002 * @since 2.6.0 bbPress (r6253)
4003 *
4004 * @param array  $terms    List of Term taxonomy IDs.
4005 * @param object $taxonomy Current taxonomy object of terms.
4006 */
4007function bbp_update_topic_tag_count( $terms, $taxonomy ) {
4008
4009        // Bail if no object types are available
4010        if ( empty( $terms ) || empty( $taxonomy->object_type ) ) {
4011                return;
4012        }
4013
4014        // Get object types
4015        $object_types = (array) $taxonomy->object_type;
4016
4017        foreach ( $object_types as &$object_type ) {
4018                list( $object_type ) = explode( ':', $object_type );
4019        }
4020
4021        $object_types = array_unique( $object_types );
4022
4023        if ( ! empty( $object_types ) ) {
4024                $object_types = esc_sql( array_filter( $object_types, 'post_type_exists' ) );
4025        }
4026
4027        // Statuses to count
4028        $object_statuses = array(
4029                bbp_get_public_status_id(),
4030                bbp_get_closed_status_id()
4031        );
4032
4033        // Get database
4034        $bbp_db = bbp_db();
4035
4036        // Loop through terms, maybe update counts
4037        foreach ( (array) $terms as $term ) {
4038                $count = 0;
4039
4040                // Get count, and bump it
4041                if ( ! empty( $object_types ) ) {
4042                        $query    = "SELECT COUNT(*) FROM {$bbp_db->term_relationships}, {$bbp_db->posts} WHERE {$bbp_db->posts}.ID = {$bbp_db->term_relationships}.object_id AND post_status IN ('" . implode("', '", $object_statuses ) . "') AND post_type IN ('" . implode("', '", $object_types ) . "') AND term_taxonomy_id = %d";
4043                        $prepare  = $bbp_db->prepare( $query, $term );
4044                        $count   += (int) $bbp_db->get_var( $prepare );
4045                }
4046
4047                /** This action is documented in wp-includes/taxonomy.php */
4048                do_action( 'edit_term_taxonomy', $term, $taxonomy->name );
4049                $bbp_db->update( $bbp_db->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) );
4050
4051                /** This action is documented in wp-includes/taxonomy.php */
4052                do_action( 'edited_term_taxonomy', $term, $taxonomy->name );
4053        }
4054}
4055
4056/** Autoembed *****************************************************************/
4057
4058/**
4059 * Check if autoembeds are enabled and hook them in if so
4060 *
4061 * @since 2.1.0 bbPress (r3752)
4062 *
4063 * @global WP_Embed $wp_embed
4064 */
4065function bbp_topic_content_autoembed() {
4066        global $wp_embed;
4067
4068        if ( bbp_use_autoembed() && is_a( $wp_embed, 'WP_Embed' ) ) {
4069                add_filter( 'bbp_get_topic_content', array( $wp_embed, 'autoembed' ), 2 );
4070        }
4071}
4072
4073/** Feeds *********************************************************************/
4074
4075/**
4076 * Output an RSS2 feed of topics, based on the query passed.
4077 *
4078 * @since 2.0.0 bbPress (r3171)
4079 *
4080 * @uses bbp_version()
4081 * @uses bbp_is_single_topic()
4082 * @uses bbp_user_can_view_forum()
4083 * @uses bbp_get_topic_forum_id()
4084 * @uses bbp_show_lead_topic()
4085 * @uses bbp_topic_permalink()
4086 * @uses bbp_topic_title()
4087 * @uses bbp_get_topic_reply_count()
4088 * @uses bbp_topic_content()
4089 * @uses bbp_has_topics()
4090 * @uses bbp_topics()
4091 * @uses bbp_the_topic()
4092 * @uses get_bloginfo_rss()
4093 * @uses get_option()
4094 * @uses self_link()
4095 * @uses the_author()
4096 * @uses get_post_time()
4097 * @uses rss_enclosure()
4098 * @uses do_action()
4099 * @uses apply_filters()
4100 *
4101 * @param array $topics_query
4102 */
4103function bbp_display_topics_feed_rss2( $topics_query = array() ) {
4104
4105        // User cannot access this forum
4106        if ( bbp_is_single_forum() && ! bbp_user_can_view_forum( array( 'forum_id' => bbp_get_forum_id() ) ) ) {
4107                return;
4108        }
4109
4110        // Feed title
4111        $title = get_bloginfo_rss( 'name' ) . ' &#187; ' . __( 'All Topics', 'bbpress' );
4112        $title = apply_filters( 'wp_title_rss', $title );
4113
4114        // Display the feed
4115        header( 'Content-Type: ' . feed_content_type( 'rss2' ) . '; charset=' . get_option( 'blog_charset' ), true );
4116        header( 'Status: 200 OK' );
4117        echo '<?xml version="1.0" encoding="' . get_option( 'blog_charset' ) . '"?' . '>'; ?>
4118
4119        <rss version="2.0"
4120                xmlns:content="http://purl.org/rss/1.0/modules/content/"
4121                xmlns:wfw="http://wellformedweb.org/CommentAPI/"
4122                xmlns:dc="http://purl.org/dc/elements/1.1/"
4123                xmlns:atom="http://www.w3.org/2005/Atom"
4124
4125                <?php do_action( 'bbp_feed' ); ?>
4126        >
4127
4128        <channel>
4129
4130                <title><?php echo $title; ?></title>
4131                <atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
4132                <link><?php self_link(); ?></link>
4133                <description><?php //?></description>
4134                <pubDate><?php echo mysql2date( 'D, d M Y H:i:s O', current_time( 'mysql' ), false ); ?></pubDate>
4135                <generator>https://bbpress.org/?v=<?php bbp_version(); ?></generator>
4136                <language><?php bloginfo_rss( 'language' ); ?></language>
4137
4138                <?php do_action( 'bbp_feed_head' ); ?>
4139
4140                <?php if ( bbp_has_topics( $topics_query ) ) : ?>
4141
4142                        <?php while ( bbp_topics() ) : bbp_the_topic(); ?>
4143
4144                                <item>
4145                                        <guid><?php bbp_topic_permalink(); ?></guid>
4146                                        <title><![CDATA[<?php bbp_topic_title(); ?>]]></title>
4147                                        <link><?php bbp_topic_permalink(); ?></link>
4148                                        <pubDate><?php echo mysql2date( 'D, d M Y H:i:s +0000', get_post_meta( bbp_get_topic_id(), '_bbp_last_active_time', true ), false ); ?></pubDate>
4149                                        <dc:creator><?php the_author() ?></dc:creator>
4150
4151                                        <?php if ( !post_password_required() ) : ?>
4152
4153                                        <description>
4154                                                <![CDATA[
4155                                                <p><?php printf( esc_html__( 'Replies: %s', 'bbpress' ), bbp_get_topic_reply_count() ); ?></p>
4156                                                <?php bbp_topic_content(); ?>
4157                                                ]]>
4158                                        </description>
4159
4160                                        <?php rss_enclosure(); ?>
4161
4162                                        <?php endif; ?>
4163
4164                                        <?php do_action( 'bbp_feed_item' ); ?>
4165
4166                                </item>
4167
4168                                <?php endwhile; ?>
4169                        <?php endif; ?>
4170
4171                <?php do_action( 'bbp_feed_footer' ); ?>
4172
4173        </channel>
4174        </rss>
4175
4176<?php
4177        exit();
4178}
4179
4180/** Permissions ***************************************************************/
4181
4182/**
4183 * Redirect if unathorized user is attempting to edit a topic
4184 *
4185 * @since 2.1.0 bbPress (r3605)
4186 *
4187 * @uses bbp_is_topic_edit()
4188 * @uses current_user_can()
4189 * @uses bbp_get_topic_id()
4190 * @uses bbp_redirect()
4191 * @uses bbp_get_topic_permalink()
4192 */
4193function bbp_check_topic_edit() {
4194
4195        // Bail if not editing a topic
4196        if ( ! bbp_is_topic_edit() ) {
4197                return;
4198        }
4199
4200        // User cannot edit topic, so redirect back to topic
4201        if ( ! current_user_can( 'edit_topic', bbp_get_topic_id() ) ) {
4202                bbp_redirect( bbp_get_topic_permalink() );
4203        }
4204}
4205
4206/**
4207 * Redirect if unathorized user is attempting to edit a topic tag
4208 *
4209 * @since 2.1.0 bbPress (r3605)
4210 *
4211 * @uses bbp_is_topic_tag_edit()
4212 * @uses current_user_can()
4213 * @uses bbp_get_topic_tag_id()
4214 * @uses bbp_redirect()
4215 * @uses bbp_get_topic_tag_link()
4216 */
4217function bbp_check_topic_tag_edit() {
4218
4219        // Bail if not editing a topic tag
4220        if ( ! bbp_is_topic_tag_edit() ) {
4221                return;
4222        }
4223
4224        // Bail if current user cannot edit topic tags
4225        if ( ! current_user_can( 'edit_topic_tags', bbp_get_topic_tag_id() ) ) {
4226                bbp_redirect( bbp_get_topic_tag_link() );
4227        }
4228}
Note: See TracBrowser for help on using the repository browser.