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

functions.php in bbPress 2.2.2, at includes/topics/functions.php

3,339 lines 114.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * bbPress Topic Functions
5 *
6 * @package bbPress
7 * @subpackage Functions
8 */
9
10 // Exit if accessed directly
11 if ( !defined( 'ABSPATH' ) ) exit;
12
13 /** Insert ********************************************************************/
14
15 /**
16 * A wrapper for wp_insert_post() that also includes the necessary meta values
17 * for the topic to function properly.
18 *
19 * @since 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 */
29 function bbp_insert_topic( $topic_data = array(), $topic_meta = array() ) {
30
31 // Forum
32 $default_topic = 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 );
43
44 // Parse args
45 $topic_data = bbp_parse_args( $topic_data, $default_topic, 'insert_topic' );
46
47 // Insert topic
48 $topic_id = wp_insert_post( $topic_data );
49
50 // Bail if no topic was added
51 if ( empty( $topic_id ) )
52 return false;
53
54 // Forum meta
55 $default_meta = array(
56 'author_ip' => bbp_current_author_ip(),
57 'forum_id' => 0,
58 'topic_id' => $topic_id,
59 'voice_count' => 1,
60 'reply_count' => 0,
61 'reply_count_hidden' => 0,
62 'last_reply_id' => 0,
63 'last_active_id' => $topic_id,
64 'last_active_time' => get_post_field( 'post_date', $topic_id, 'db' ),
65 );
66
67 // Parse args
68 $topic_meta = bbp_parse_args( $topic_meta, $default_meta, 'insert_topic_meta' );
69
70 // Insert topic meta
71 foreach ( $topic_meta as $meta_key => $meta_value )
72 update_post_meta( $topic_id, '_bbp_' . $meta_key, $meta_value );
73
74 // Update the forum
75 $forum_id = bbp_get_topic_forum_id( $topic_id );
76 if ( !empty( $forum_id ) )
77 bbp_update_forum( array( 'forum_id' => $forum_id ) );
78
79 // Return new topic ID
80 return $topic_id;
81 }
82
83 /** Post Form Handlers ********************************************************/
84
85 /**
86 * Handles the front end topic submission
87 *
88 * @uses bbPress:errors::add() To log various error messages
89 * @uses bbp_verify_nonce_request() To verify the nonce and check the referer
90 * @uses bbp_is_anonymous() To check if an anonymous post is being made
91 * @uses current_user_can() To check if the current user can publish topic
92 * @uses bbp_get_current_user_id() To get the current user id
93 * @uses bbp_filter_anonymous_post_data() To filter anonymous data
94 * @uses bbp_set_current_anonymous_user_data() To set the anonymous user cookies
95 * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error}
96 * @uses esc_attr() For sanitization
97 * @uses bbp_is_forum_category() To check if the forum is a category
98 * @uses bbp_is_forum_closed() To check if the forum is closed
99 * @uses bbp_is_forum_private() To check if the forum is private
100 * @uses bbp_check_for_flood() To check for flooding
101 * @uses bbp_check_for_duplicate() To check for duplicates
102 * @uses bbp_get_topic_post_type() To get the topic post type
103 * @uses remove_filter() To remove 'wp_filter_kses' filters if needed
104 * @uses apply_filters() Calls 'bbp_new_topic_pre_title' with the content
105 * @uses apply_filters() Calls 'bbp_new_topic_pre_content' with the content
106 * @uses bbPress::errors::get_error_codes() To get the {@link WP_Error} errors
107 * @uses wp_insert_post() To insert the topic
108 * @uses do_action() Calls 'bbp_new_topic' with the topic id, forum id,
109 * anonymous data and reply author
110 * @uses bbp_stick_topic() To stick or super stick the topic
111 * @uses bbp_unstick_topic() To unstick the topic
112 * @uses bbp_get_topic_permalink() To get the topic permalink
113 * @uses wp_safe_redirect() To redirect to the topic link
114 * @uses bbPress::errors::get_error_messages() To get the {@link WP_Error} error
115 * messages
116 */
117 function bbp_new_topic_handler() {
118
119 // Bail if not a POST action
120 if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) )
121 return;
122
123 // Bail if action is not bbp-new-topic
124 if ( empty( $_POST['action'] ) || ( 'bbp-new-topic' !== $_POST['action'] ) )
125 return;
126
127 // Nonce check
128 if ( ! bbp_verify_nonce_request( 'bbp-new-topic' ) ) {
129 bbp_add_error( 'bbp_new_topic_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
130 return;
131 }
132
133 // Define local variable(s)
134 $view_all = false;
135 $forum_id = $topic_author = $anonymous_data = 0;
136 $topic_title = $topic_content = '';
137 $terms = array( bbp_get_topic_tag_tax_id() => array() );
138
139 /** Topic Author **********************************************************/
140
141 // User is anonymous
142 if ( bbp_is_anonymous() ) {
143
144 // Filter anonymous data
145 $anonymous_data = bbp_filter_anonymous_post_data();
146
147 // Anonymous data checks out, so set cookies, etc...
148 if ( !empty( $anonymous_data ) && is_array( $anonymous_data ) ) {
149 bbp_set_current_anonymous_user_data( $anonymous_data );
150 }
151
152 // User is logged in
153 } else {
154
155 // User cannot create topics
156 if ( !current_user_can( 'publish_topics' ) ) {
157 bbp_add_error( 'bbp_topic_permissions', __( '<strong>ERROR</strong>: You do not have permission to create new topics.', 'bbpress' ) );
158 return;
159 }
160
161 // Topic author is current user
162 $topic_author = bbp_get_current_user_id();
163 }
164
165 // Remove wp_filter_kses filters from title and content for capable users and if the nonce is verified
166 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'] ) {
167 remove_filter( 'bbp_new_topic_pre_title', 'wp_filter_kses' );
168 remove_filter( 'bbp_new_topic_pre_content', 'wp_filter_kses' );
169 }
170
171 /** Topic Title ***********************************************************/
172
173 if ( !empty( $_POST['bbp_topic_title'] ) )
174 $topic_title = esc_attr( strip_tags( $_POST['bbp_topic_title'] ) );
175
176 // Filter and sanitize
177 $topic_title = apply_filters( 'bbp_new_topic_pre_title', $topic_title );
178
179 // No topic title
180 if ( empty( $topic_title ) )
181 bbp_add_error( 'bbp_topic_title', __( '<strong>ERROR</strong>: Your topic needs a title.', 'bbpress' ) );
182
183 /** Topic Content *********************************************************/
184
185 if ( !empty( $_POST['bbp_topic_content'] ) )
186 $topic_content = $_POST['bbp_topic_content'];
187
188 // Filter and sanitize
189 $topic_content = apply_filters( 'bbp_new_topic_pre_content', $topic_content );
190
191 // No topic content
192 if ( empty( $topic_content ) )
193 bbp_add_error( 'bbp_topic_content', __( '<strong>ERROR</strong>: Your topic cannot be empty.', 'bbpress' ) );
194
195 /** Topic Forum ***********************************************************/
196
197 // Forum id was not passed
198 if ( empty( $_POST['bbp_forum_id'] ) )
199 bbp_add_error( 'bbp_topic_forum_id', __( '<strong>ERROR</strong>: Forum ID is missing.', 'bbpress' ) );
200
201 // Forum id was passed
202 elseif ( is_numeric( $_POST['bbp_forum_id'] ) )
203 $forum_id = (int) $_POST['bbp_forum_id'];
204
205 // Forum exists
206 if ( !empty( $forum_id ) ) {
207
208 // Forum is a category
209 if ( bbp_is_forum_category( $forum_id ) )
210 bbp_add_error( 'bbp_edit_topic_forum_category', __( '<strong>ERROR</strong>: This forum is a category. No topics can be created in this forum.', 'bbpress' ) );
211
212 // Forum is closed and user cannot access
213 if ( bbp_is_forum_closed( $forum_id ) && !current_user_can( 'edit_forum', $forum_id ) )
214 bbp_add_error( 'bbp_edit_topic_forum_closed', __( '<strong>ERROR</strong>: This forum has been closed to new topics.', 'bbpress' ) );
215
216 // Forum is private and user cannot access
217 if ( bbp_is_forum_private( $forum_id ) && !current_user_can( 'read_private_forums' ) )
218 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' ) );
219
220 // Forum is hidden and user cannot access
221 if ( bbp_is_forum_hidden( $forum_id ) && !current_user_can( 'read_hidden_forums' ) )
222 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' ) );
223 }
224
225 /** Topic Flooding ********************************************************/
226
227 if ( !bbp_check_for_flood( $anonymous_data, $topic_author ) )
228 bbp_add_error( 'bbp_topic_flood', __( '<strong>ERROR</strong>: Slow down; you move too fast.', 'bbpress' ) );
229
230 /** Topic Duplicate *******************************************************/
231
232 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 ) ) )
233 bbp_add_error( 'bbp_topic_duplicate', __( '<strong>ERROR</strong>: Duplicate topic detected; it looks as though you&#8217;ve already said that!', 'bbpress' ) );
234
235 /** Topic Blacklist *******************************************************/
236
237 if ( !bbp_check_for_blacklist( $anonymous_data, $topic_author, $topic_title, $topic_content ) )
238 bbp_add_error( 'bbp_topic_blacklist', __( '<strong>ERROR</strong>: Your topic cannot be created at this time.', 'bbpress' ) );
239
240 /** Topic Status **********************************************************/
241
242 // Maybe put into moderation
243 if ( !bbp_check_for_moderation( $anonymous_data, $topic_author, $topic_title, $topic_content ) ) {
244 $topic_status = bbp_get_pending_status_id();
245
246 // Default to published
247 } else {
248 $topic_status = bbp_get_public_status_id();
249 }
250
251 /** Topic Tags ************************************************************/
252
253 if ( bbp_allow_topic_tags() && !empty( $_POST['bbp_topic_tags'] ) ) {
254
255 // Escape tag input
256 $terms = esc_attr( strip_tags( $_POST['bbp_topic_tags'] ) );
257
258 // Explode by comma
259 if ( strstr( $terms, ',' ) ) {
260 $terms = explode( ',', $terms );
261 }
262
263 // Add topic tag ID as main key
264 $terms = array( bbp_get_topic_tag_tax_id() => $terms );
265 }
266
267 /** Additional Actions (Before Save) **************************************/
268
269 do_action( 'bbp_new_topic_pre_extras', $forum_id );
270
271 // Bail if errors
272 if ( bbp_has_errors() )
273 return;
274
275 /** No Errors *************************************************************/
276
277 // Add the content of the form to $topic_data as an array.
278 // Just in time manipulation of topic data before being created
279 $topic_data = apply_filters( 'bbp_new_topic_pre_insert', array(
280 'post_author' => $topic_author,
281 'post_title' => $topic_title,
282 'post_content' => $topic_content,
283 'post_status' => $topic_status,
284 'post_parent' => $forum_id,
285 'post_type' => bbp_get_topic_post_type(),
286 'tax_input' => $terms,
287 'comment_status' => 'closed'
288 ) );
289
290 // Insert topic
291 $topic_id = wp_insert_post( $topic_data );
292
293 /** No Errors *************************************************************/
294
295 if ( !empty( $topic_id ) && !is_wp_error( $topic_id ) ) {
296
297 /** Stickies **********************************************************/
298
299 if ( !empty( $_POST['bbp_stick_topic'] ) && in_array( $_POST['bbp_stick_topic'], array( 'stick', 'super', 'unstick' ) ) ) {
300
301 // What's the haps?
302 switch ( $_POST['bbp_stick_topic'] ) {
303
304 // Sticky in this forum
305 case 'stick' :
306 bbp_stick_topic( $topic_id );
307 break;
308
309 // Super sticky in all forums
310 case 'super' :
311 bbp_stick_topic( $topic_id, true );
312 break;
313
314 // We can avoid this as it is a new topic
315 case 'unstick' :
316 default :
317 break;
318 }
319 }
320
321 /** Trash Check *******************************************************/
322
323 // If the forum is trash, or the topic_status is switched to
324 // trash, trash it properly
325 if ( ( get_post_field( 'post_status', $forum_id ) == bbp_get_trash_status_id() ) || ( $topic_data['post_status'] == bbp_get_trash_status_id() ) ) {
326
327 // Trash the reply
328 wp_trash_post( $topic_id );
329
330 // Force view=all
331 $view_all = true;
332 }
333
334 /** Spam Check ********************************************************/
335
336 // If reply or topic are spam, officially spam this reply
337 if ( $topic_data['post_status'] == bbp_get_spam_status_id() ) {
338 add_post_meta( $topic_id, '_bbp_spam_meta_status', bbp_get_public_status_id() );
339
340 // Force view=all
341 $view_all = true;
342 }
343
344 /** Update counts, etc... *********************************************/
345
346 do_action( 'bbp_new_topic', $topic_id, $forum_id, $anonymous_data, $topic_author );
347
348 /** Additional Actions (After Save) ***********************************/
349
350 do_action( 'bbp_new_topic_post_extras', $topic_id );
351
352 /** Redirect **********************************************************/
353
354 // Redirect to
355 $redirect_to = !empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
356
357 // Get the topic URL
358 $redirect_url = bbp_get_topic_permalink( $topic_id, $redirect_to );
359
360 // Add view all?
361 if ( bbp_get_view_all() || !empty( $view_all ) ) {
362
363 // User can moderate, so redirect to topic with view all set
364 if ( current_user_can( 'moderate' ) ) {
365 $redirect_url = bbp_add_view_all( $redirect_url );
366
367 // User cannot moderate, so redirect to forum
368 } else {
369 $redirect_url = bbp_get_forum_permalink( $forum_id );
370 }
371 }
372
373 // Allow to be filtered
374 $redirect_url = apply_filters( 'bbp_new_topic_redirect_to', $redirect_url, $redirect_to, $topic_id );
375
376 /** Successful Save ***************************************************/
377
378 // Redirect back to new topic
379 wp_safe_redirect( $redirect_url );
380
381 // For good measure
382 exit();
383
384 // Errors
385 } else {
386 $append_error = ( is_wp_error( $topic_id ) && $topic_id->get_error_message() ) ? $topic_id->get_error_message() . ' ' : '';
387 bbp_add_error( 'bbp_topic_error', __( '<strong>ERROR</strong>: The following problem(s) have been found with your topic:' . $append_error, 'bbpress' ) );
388 }
389 }
390
391 /**
392 * Handles the front end edit topic submission
393 *
394 * @uses bbPress:errors::add() To log various error messages
395 * @uses bbp_get_topic() To get the topic
396 * @uses bbp_verify_nonce_request() To verify the nonce and check the request
397 * @uses bbp_is_topic_anonymous() To check if topic is by an anonymous user
398 * @uses current_user_can() To check if the current user can edit the topic
399 * @uses bbp_filter_anonymous_post_data() To filter anonymous data
400 * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error}
401 * @uses esc_attr() For sanitization
402 * @uses bbp_is_forum_category() To check if the forum is a category
403 * @uses bbp_is_forum_closed() To check if the forum is closed
404 * @uses bbp_is_forum_private() To check if the forum is private
405 * @uses remove_filter() To remove 'wp_filter_kses' filters if needed
406 * @uses apply_filters() Calls 'bbp_edit_topic_pre_title' with the title and
407 * topic id
408 * @uses apply_filters() Calls 'bbp_edit_topic_pre_content' with the content
409 * and topic id
410 * @uses bbPress::errors::get_error_codes() To get the {@link WP_Error} errors
411 * @uses wp_save_post_revision() To save a topic revision
412 * @uses bbp_update_topic_revision_log() To update the topic revision log
413 * @uses bbp_stick_topic() To stick or super stick the topic
414 * @uses bbp_unstick_topic() To unstick the topic
415 * @uses wp_update_post() To update the topic
416 * @uses do_action() Calls 'bbp_edit_topic' with the topic id, forum id,
417 * anonymous data and reply author
418 * @uses bbp_move_topic_handler() To handle movement of a topic from one forum
419 * to another
420 * @uses bbp_get_topic_permalink() To get the topic permalink
421 * @uses wp_safe_redirect() To redirect to the topic link
422 * @uses bbPress::errors::get_error_messages() To get the {@link WP_Error} error
423 * messages
424 */
425 function bbp_edit_topic_handler() {
426
427 // Bail if not a POST action
428 if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) )
429 return;
430
431 // Bail if action is not bbp-edit-topic
432 if ( empty( $_POST['action'] ) || ( 'bbp-edit-topic' !== $_POST['action'] ) )
433 return;
434
435 // Define local variable(s)
436 $revisions_removed = false;
437 $topic = $topic_id = $topic_author = $forum_id = $anonymous_data = 0;
438 $topic_title = $topic_content = $topic_edit_reason = '';
439
440 /** Topic *****************************************************************/
441
442 // Topic id was not passed
443 if ( empty( $_POST['bbp_topic_id'] ) ) {
444 bbp_add_error( 'bbp_edit_topic_id', __( '<strong>ERROR</strong>: Topic ID not found.', 'bbpress' ) );
445 return;
446
447 // Topic id was passed
448 } elseif ( is_numeric( $_POST['bbp_topic_id'] ) ) {
449 $topic_id = (int) $_POST['bbp_topic_id'];
450 $topic = bbp_get_topic( $topic_id );
451 }
452
453 // Topic does not exist
454 if ( empty( $topic ) ) {
455 bbp_add_error( 'bbp_edit_topic_not_found', __( '<strong>ERROR</strong>: The topic you want to edit was not found.', 'bbpress' ) );
456 return;
457
458 // Topic exists
459 } else {
460
461 // Check users ability to create new topic
462 if ( ! bbp_is_topic_anonymous( $topic_id ) ) {
463
464 // User cannot edit this topic
465 if ( !current_user_can( 'edit_topic', $topic_id ) ) {
466 bbp_add_error( 'bbp_edit_topic_permissions', __( '<strong>ERROR</strong>: You do not have permission to edit that topic.', 'bbpress' ) );
467 }
468
469 // Set topic author
470 $topic_author = bbp_get_topic_author_id( $topic_id );
471
472 // It is an anonymous post
473 } else {
474
475 // Filter anonymous data
476 $anonymous_data = bbp_filter_anonymous_post_data( array(), true );
477 }
478 }
479
480 // Nonce check
481 if ( ! bbp_verify_nonce_request( 'bbp-edit-topic_' . $topic_id ) ) {
482 bbp_add_error( 'bbp_edit_topic_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
483 return;
484 }
485
486 // Remove wp_filter_kses filters from title and content for capable users and if the nonce is verified
487 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'] ) ) {
488 remove_filter( 'bbp_edit_topic_pre_title', 'wp_filter_kses' );
489 remove_filter( 'bbp_edit_topic_pre_content', 'wp_filter_kses' );
490 }
491
492 /** Topic Forum ***********************************************************/
493
494 // Forum id was not passed
495 if ( empty( $_POST['bbp_forum_id'] ) ) {
496 bbp_add_error( 'bbp_topic_forum_id', __( '<strong>ERROR</strong>: Forum ID is missing.', 'bbpress' ) );
497
498 // Forum id was passed
499 } elseif ( is_numeric( $_POST['bbp_forum_id'] ) ) {
500 $forum_id = (int) $_POST['bbp_forum_id'];
501 }
502
503 // Current forum this topic is in
504 $current_forum_id = bbp_get_topic_forum_id( $topic_id );
505
506 // Forum exists
507 if ( !empty( $forum_id ) && ( $forum_id !== $current_forum_id ) ) {
508
509 // Forum is a category
510 if ( bbp_is_forum_category( $forum_id ) )
511 bbp_add_error( 'bbp_edit_topic_forum_category', __( '<strong>ERROR</strong>: This forum is a category. No topics can be created in it.', 'bbpress' ) );
512
513 // Forum is closed and user cannot access
514 if ( bbp_is_forum_closed( $forum_id ) && !current_user_can( 'edit_forum', $forum_id ) )
515 bbp_add_error( 'bbp_edit_topic_forum_closed', __( '<strong>ERROR</strong>: This forum has been closed to new topics.', 'bbpress' ) );
516
517 // Forum is private and user cannot access
518 if ( bbp_is_forum_private( $forum_id ) && !current_user_can( 'read_private_forums' ) )
519 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' ) );
520
521 // Forum is hidden and user cannot access
522 if ( bbp_is_forum_hidden( $forum_id ) && !current_user_can( 'read_hidden_forums' ) )
523 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' ) );
524 }
525
526 /** Topic Title ***********************************************************/
527
528 if ( !empty( $_POST['bbp_topic_title'] ) )
529 $topic_title = esc_attr( strip_tags( $_POST['bbp_topic_title'] ) );
530
531 // Filter and sanitize
532 $topic_title = apply_filters( 'bbp_edit_topic_pre_title', $topic_title, $topic_id );
533
534 // No topic title
535 if ( empty( $topic_title ) )
536 bbp_add_error( 'bbp_edit_topic_title', __( '<strong>ERROR</strong>: Your topic needs a title.', 'bbpress' ) );
537
538 /** Topic Content *********************************************************/
539
540 if ( !empty( $_POST['bbp_topic_content'] ) )
541 $topic_content = $_POST['bbp_topic_content'];
542
543 // Filter and sanitize
544 $topic_content = apply_filters( 'bbp_edit_topic_pre_content', $topic_content, $topic_id );
545
546 // No topic content
547 if ( empty( $topic_content ) )
548 bbp_add_error( 'bbp_edit_topic_content', __( '<strong>ERROR</strong>: Your topic cannot be empty.', 'bbpress' ) );
549
550 /** Topic Blacklist *******************************************************/
551
552 if ( !bbp_check_for_blacklist( $anonymous_data, $topic_author, $topic_title, $topic_content ) )
553 bbp_add_error( 'bbp_topic_blacklist', __( '<strong>ERROR</strong>: Your topic cannot be edited at this time.', 'bbpress' ) );
554
555 /** Topic Status **********************************************************/
556
557 // Maybe put into moderation
558 if ( !bbp_check_for_moderation( $anonymous_data, $topic_author, $topic_title, $topic_content ) ) {
559
560 // Set post status to pending if public or closed
561 if ( in_array( $topic->post_status, array( bbp_get_public_status_id(), bbp_get_closed_status_id() ) ) ) {
562 $topic_status = bbp_get_pending_status_id();
563 }
564
565 // Use existing post_status
566 } else {
567 $topic_status = $topic->post_status;
568 }
569
570 /** Topic Tags ************************************************************/
571
572 // Either replace terms
573 if ( bbp_allow_topic_tags() && current_user_can( 'assign_topic_tags' ) && ! empty( $_POST['bbp_topic_tags'] ) ) {
574
575 // Escape tag input
576 $terms = esc_attr( strip_tags( $_POST['bbp_topic_tags'] ) );
577
578 // Explode by comma
579 if ( strstr( $terms, ',' ) )
580 $terms = explode( ',', $terms );
581
582 // Add topic tag ID as main key
583 $terms = array( bbp_get_topic_tag_tax_id() => $terms );
584
585 // ...or remove them.
586 } elseif ( isset( $_POST['bbp_topic_tags'] ) ) {
587 $terms = array( bbp_get_topic_tag_tax_id() => array() );
588
589 // Existing terms
590 } else {
591 $terms = array( bbp_get_topic_tag_tax_id() => explode( ',', bbp_get_topic_tag_names( $topic_id, ',' ) ) );
592 }
593
594 /** Additional Actions (Before Save) **************************************/
595
596 do_action( 'bbp_edit_topic_pre_extras', $topic_id );
597
598 // Bail if errors
599 if ( bbp_has_errors() )
600 return;
601
602 /** No Errors *************************************************************/
603
604 // Add the content of the form to $topic_data as an array
605 // Just in time manipulation of topic data before being edited
606 $topic_data = apply_filters( 'bbp_edit_topic_pre_insert', array(
607 'ID' => $topic_id,
608 'post_title' => $topic_title,
609 'post_content' => $topic_content,
610 'post_status' => $topic_status,
611 'post_parent' => $forum_id,
612 'post_author' => $topic_author,
613 'post_type' => bbp_get_topic_post_type(),
614 'tax_input' => $terms,
615 ) );
616
617 // Toggle revisions to avoid duplicates
618 if ( post_type_supports( bbp_get_topic_post_type(), 'revisions' ) ) {
619 $revisions_removed = true;
620 remove_post_type_support( bbp_get_topic_post_type(), 'revisions' );
621 }
622
623 // Insert topic
624 $topic_id = wp_update_post( $topic_data );
625
626 // Toggle revisions back on
627 if ( true === $revisions_removed ) {
628 $revisions_removed = true;
629 add_post_type_support( bbp_get_topic_post_type(), 'revisions' );
630 }
631
632 /** Stickies **************************************************************/
633
634 if ( !empty( $_POST['bbp_stick_topic'] ) && in_array( $_POST['bbp_stick_topic'], array( 'stick', 'super', 'unstick' ) ) ) {
635
636 // What's the dilly?
637 switch ( $_POST['bbp_stick_topic'] ) {
638
639 // Sticky in forum
640 case 'stick' :
641 bbp_stick_topic( $topic_id );
642 break;
643
644 // Sticky in all forums
645 case 'super' :
646 bbp_stick_topic( $topic_id, true );
647 break;
648
649 // Normal
650 case 'unstick' :
651 default :
652 bbp_unstick_topic( $topic_id );
653 break;
654 }
655 }
656
657 /** Revisions *************************************************************/
658
659 // Revision Reason
660 if ( !empty( $_POST['bbp_topic_edit_reason'] ) )
661 $topic_edit_reason = esc_attr( strip_tags( $_POST['bbp_topic_edit_reason'] ) );
662
663 // Update revision log
664 if ( !empty( $_POST['bbp_log_topic_edit'] ) && ( 1 == $_POST['bbp_log_topic_edit'] ) ) {
665 $revision_id = wp_save_post_revision( $topic_id );
666 if ( ! empty( $revision_id ) ) {
667 bbp_update_topic_revision_log( array(
668 'topic_id' => $topic_id,
669 'revision_id' => $revision_id,
670 'author_id' => bbp_get_current_user_id(),
671 'reason' => $topic_edit_reason
672 ) );
673 }
674 }
675
676 /** No Errors *************************************************************/
677
678 if ( !empty( $topic_id ) && !is_wp_error( $topic_id ) ) {
679
680 // Update counts, etc...
681 do_action( 'bbp_edit_topic', $topic_id, $forum_id, $anonymous_data, $topic_author , true /* Is edit */ );
682
683 // If the new forum id is not equal to the old forum id, run the
684 // bbp_move_topic action and pass the topic's forum id as the
685 // first arg and topic id as the second to update counts.
686 if ( $forum_id != $topic->post_parent )
687 bbp_move_topic_handler( $topic_id, $topic->post_parent, $forum_id );
688
689 /** Additional Actions (After Save) ***********************************/
690
691 do_action( 'bbp_edit_topic_post_extras', $topic_id );
692
693 /** Redirect **********************************************************/
694
695 // Redirect to
696 $redirect_to = !empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
697
698 // View all?
699 $view_all = bbp_get_view_all();
700
701 // Get the topic URL
702 $topic_url = bbp_get_topic_permalink( $topic_id, $redirect_to );
703
704 // Add view all?
705 if ( !empty( $view_all ) )
706 $topic_url = bbp_add_view_all( $topic_url );
707
708 // Allow to be filtered
709 $topic_url = apply_filters( 'bbp_edit_topic_redirect_to', $topic_url, $view_all, $redirect_to );
710
711 /** Successful Edit ***************************************************/
712
713 // Redirect back to new topic
714 wp_safe_redirect( $topic_url );
715
716 // For good measure
717 exit();
718
719 /** Errors ****************************************************************/
720
721 } else {
722 $append_error = ( is_wp_error( $topic_id ) && $topic_id->get_error_message() ) ? $topic_id->get_error_message() . ' ' : '';
723 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' ) );
724 }
725 }
726
727 /**
728 * Handle all the extra meta stuff from posting a new topic
729 *
730 * @param int $topic_id Optional. Topic id
731 * @param int $forum_id Optional. Forum id
732 * @param bool|array $anonymous_data Optional. If it is an array, it is
733 * extracted and anonymous user info is saved
734 * @param int $author_id Author id
735 * @param bool $is_edit Optional. Is the post being edited? Defaults to false.
736 * @uses bbp_get_topic_id() To get the topic id
737 * @uses bbp_get_forum_id() To get the forum id
738 * @uses bbp_get_current_user_id() To get the current user id
739 * @yses bbp_get_topic_forum_id() To get the topic forum id
740 * @uses update_post_meta() To update the topic metas
741 * @uses set_transient() To update the flood check transient for the ip
742 * @uses bbp_update_user_last_posted() To update the users last posted time
743 * @uses bbp_is_subscriptions_active() To check if the subscriptions feature is
744 * activated or not
745 * @uses bbp_is_user_subscribed() To check if the user is subscribed
746 * @uses bbp_remove_user_subscription() To remove the user's subscription
747 * @uses bbp_add_user_subscription() To add the user's subscription
748 * @uses bbp_update_topic_forum_id() To update the topic's forum id
749 * @uses bbp_update_topic_topic_id() To update the topic's topic id
750 * @uses bbp_update_topic_last_reply_id() To update the last reply id topic meta
751 * @uses bbp_update_topic_last_active_id() To update the topic last active id
752 * @uses bbp_update_topic_last_active_time() To update the last active topic meta
753 * @uses bbp_update_topic_reply_count() To update the topic reply count
754 * @uses bbp_update_topic_reply_count_hidden() To udpate the topic hidden reply count
755 * @uses bbp_update_topic_voice_count() To update the topic voice count
756 * @uses bbp_update_topic_walker() To udpate the topic's ancestors
757 */
758 function bbp_update_topic( $topic_id = 0, $forum_id = 0, $anonymous_data = false, $author_id = 0, $is_edit = false ) {
759
760 // Validate the ID's passed from 'bbp_new_topic' action
761 $topic_id = bbp_get_topic_id( $topic_id );
762 $forum_id = bbp_get_forum_id( $forum_id );
763
764 // Bail if there is no topic
765 if ( empty( $topic_id ) )
766 return;
767
768 // Check author_id
769 if ( empty( $author_id ) )
770 $author_id = bbp_get_current_user_id();
771
772 // Check forum_id
773 if ( empty( $forum_id ) )
774 $forum_id = bbp_get_topic_forum_id( $topic_id );
775
776 // If anonymous post, store name, email, website and ip in post_meta.
777 // It expects anonymous_data to be sanitized.
778 // Check bbp_filter_anonymous_post_data() for sanitization.
779 if ( !empty( $anonymous_data ) && is_array( $anonymous_data ) ) {
780
781 // Always set at least these three values to empty
782 $defaults = array(
783 'bbp_anonymous_name' => '',
784 'bbp_anonymous_email' => '',
785 'bbp_anonymous_website' => '',
786 );
787 $r = bbp_parse_args( $anonymous_data, $defaults, 'update_topic' );
788
789 // Update all anonymous metas
790 foreach( $r as $anon_key => $anon_value ) {
791 update_post_meta( $topic_id, '_' . $anon_key, (string) $anon_value, false );
792 }
793
794 // Set transient for throttle check (only on new, not edit)
795 if ( empty( $is_edit ) ) {
796 set_transient( '_bbp_' . bbp_current_author_ip() . '_last_posted', time() );
797 }
798
799 } else {
800 if ( empty( $is_edit ) && !current_user_can( 'throttle' ) ) {
801 bbp_update_user_last_posted( $author_id );
802 }
803 }
804
805 // Handle Subscription Checkbox
806 if ( bbp_is_subscriptions_active() && !empty( $author_id ) ) {
807 $subscribed = bbp_is_user_subscribed( $author_id, $topic_id );
808 $subscheck = ( !empty( $_POST['bbp_topic_subscription'] ) && ( 'bbp_subscribe' == $_POST['bbp_topic_subscription'] ) ) ? true : false;
809
810 // Subscribed and unsubscribing
811 if ( true == $subscribed && false == $subscheck ) {
812 bbp_remove_user_subscription( $author_id, $topic_id );
813
814 // Subscribing
815 } elseif ( false == $subscribed && true == $subscheck ) {
816 bbp_add_user_subscription( $author_id, $topic_id );
817 }
818 }
819
820 // Forum topic meta
821 bbp_update_topic_forum_id( $topic_id, $forum_id );
822 bbp_update_topic_topic_id( $topic_id, $topic_id );
823
824 // Update associated topic values if this is a new topic
825 if ( empty( $is_edit ) ) {
826
827 // Update poster IP if not editing
828 update_post_meta( $topic_id, '_bbp_author_ip', bbp_current_author_ip(), false );
829
830 // Last active time
831 $last_active = current_time( 'mysql' );
832
833 // Reply topic meta
834 bbp_update_topic_last_reply_id ( $topic_id, 0 );
835 bbp_update_topic_last_active_id ( $topic_id, $topic_id );
836 bbp_update_topic_last_active_time ( $topic_id, $last_active );
837 bbp_update_topic_reply_count ( $topic_id, 0 );
838 bbp_update_topic_reply_count_hidden ( $topic_id, 0 );
839 bbp_update_topic_voice_count ( $topic_id );
840
841 // Walk up ancestors and do the dirty work
842 bbp_update_topic_walker( $topic_id, $last_active, $forum_id, 0, false );
843 }
844 }
845
846 /**
847 * Walks up the post_parent tree from the current topic_id, and updates the
848 * counts of forums above it. This calls a few internal functions that all run
849 * manual queries against the database to get their results. As such, this
850 * function can be costly to run but is necessary to keep everything accurate.
851 *
852 * @since bbPress (r2800)
853 * @param int $topic_id Topic id
854 * @param string $last_active_time Optional. Last active time
855 * @param int $forum_id Optional. Forum id
856 * @param int $reply_id Optional. Reply id
857 * @param bool $refresh Reset all the previous parameters? Defaults to true.
858 * @uses bbp_get_topic_id() To get the topic id
859 * @uses bbp_get_topic_forum_id() To get the topic forum id
860 * @uses get_post_ancestors() To get the topic's ancestors
861 * @uses bbp_is_forum() To check if the ancestor is a forum
862 * @uses bbp_update_forum() To update the forum
863 */
864 function bbp_update_topic_walker( $topic_id, $last_active_time = '', $forum_id = 0, $reply_id = 0, $refresh = true ) {
865
866 // Validate topic_id
867 $topic_id = bbp_get_topic_id( $topic_id );
868
869 // Define local variable(s)
870 $active_id = 0;
871
872 // Topic was passed
873 if ( !empty( $topic_id ) ) {
874
875 // Get the forum ID if none was passed
876 if ( empty( $forum_id ) ) {
877 $forum_id = bbp_get_topic_forum_id( $topic_id );
878 }
879
880 // Set the active_id based on topic_id/reply_id
881 $active_id = empty( $reply_id ) ? $topic_id : $reply_id;
882 }
883
884 // Get topic ancestors
885 $ancestors = array_values( array_unique( array_merge( array( $forum_id ), (array) get_post_ancestors( $topic_id ) ) ) );
886
887 // Topic status
888 $topic_status = get_post_status( $topic_id );
889
890 // If we want a full refresh, unset any of the possibly passed variables
891 if ( true == $refresh ) {
892 $forum_id = $topic_id = $reply_id = $active_id = $last_active_time = 0;
893 $topic_status = bbp_get_public_status_id();
894 }
895
896 // Loop through ancestors
897 if ( !empty( $ancestors ) ) {
898 foreach ( $ancestors as $ancestor ) {
899
900 // If ancestor is a forum, update counts
901 if ( bbp_is_forum( $ancestor ) ) {
902
903 // Update the forum
904 bbp_update_forum( array(
905 'forum_id' => $ancestor,
906 'last_topic_id' => $topic_id,
907 'last_reply_id' => $reply_id,
908 'last_active_id' => $active_id,
909 'last_active_time' => 0,
910 'last_active_status' => $topic_status
911 ) );
912 }
913 }
914 }
915 }
916
917 /**
918 * Handle the moving of a topic from one forum to another. This includes walking
919 * up the old and new branches and updating the counts.
920 *
921 * @param int $topic_id Topic id
922 * @param int $old_forum_id Old forum id
923 * @param int $new_forum_id New forum id
924 * @uses bbp_get_topic_id() To get the topic id
925 * @uses bbp_get_forum_id() To get the forum id
926 * @uses bbp_get_stickies() To get the old forums sticky topics
927 * @uses delete_post_meta() To delete the forum sticky meta
928 * @uses update_post_meta() To update the old forum sticky meta
929 * @uses bbp_stick_topic() To stick the topic in the new forum
930 * @uses bbp_get_reply_post_type() To get the reply post type
931 * @uses bbp_get_all_child_ids() To get the public child ids
932 * @uses bbp_update_reply_forum_id() To update the reply forum id
933 * @uses bbp_update_topic_forum_id() To update the topic forum id
934 * @uses get_post_ancestors() To get the topic's ancestors
935 * @uses bbp_is_forum() To check if the ancestor is a forum
936 * @uses bbp_update_forum() To update the forum
937 */
938 function bbp_move_topic_handler( $topic_id, $old_forum_id, $new_forum_id ) {
939
940 // Validate parameters
941 $topic_id = bbp_get_topic_id( $topic_id );
942 $old_forum_id = bbp_get_forum_id( $old_forum_id );
943 $new_forum_id = bbp_get_forum_id( $new_forum_id );
944
945 /** Stickies **************************************************************/
946
947 // Get forum stickies
948 $old_stickies = bbp_get_stickies( $old_forum_id );
949
950 // Only proceed if stickies are found
951 if ( !empty( $old_stickies ) ) {
952
953 // Define local variables
954 $updated_stickies = array();
955
956 // Loop through stickies of forum
957 foreach ( $old_stickies as $sticky_topic_id ) {
958
959 // Add non-matches to the updated array
960 if ( $topic_id != $sticky_topic_id ) {
961 $updated_stickies[] = $sticky_topic_id;
962 }
963 }
964
965 // No more stickies so delete the beta
966 if ( empty( $updated_stickies ) ) {
967 delete_post_meta ( $old_forum_id, '_bbp_sticky_topics' );
968
969 // Still stickies so update the meta
970 } else {
971 update_post_meta( $old_forum_id, '_bbp_sticky_topics', $updated_stickies );
972 }
973
974 // Topic was sticky, so restick in new forum
975 bbp_stick_topic( $topic_id );
976 }
977
978 /** Topic Replies *********************************************************/
979
980 // Get the topics replies
981 $replies = bbp_get_all_child_ids( $topic_id, bbp_get_reply_post_type() );
982
983 // Update the forum_id of all replies in the topic
984 foreach ( $replies as $reply_id )
985 bbp_update_reply_forum_id( $reply_id, $new_forum_id );
986
987 // Forum topic meta
988 bbp_update_topic_forum_id( $topic_id, $new_forum_id );
989
990 /** Old forum_id **********************************************************/
991
992 // Get topic ancestors
993 $ancestors = array_values( array_unique( array_merge( array( $old_forum_id ), (array) get_post_ancestors( $old_forum_id ) ) ) );
994
995 // Loop through ancestors
996 if ( !empty( $ancestors ) ) {
997 foreach ( $ancestors as $ancestor ) {
998
999 // If ancestor is a forum, update counts
1000 if ( bbp_is_forum( $ancestor ) ) {
1001
1002 // Update the forum
1003 bbp_update_forum( array(
1004 'forum_id' => $ancestor,
1005 ) );
1006 }
1007 }
1008 }
1009
1010 /** New forum_id **********************************************************/
1011
1012 // Make sure we're not walking twice
1013 if ( !in_array( $new_forum_id, $ancestors ) ) {
1014
1015 // Get topic ancestors
1016 $ancestors = array_values( array_unique( array_merge( array( $new_forum_id ), (array) get_post_ancestors( $new_forum_id ) ) ) );
1017
1018 // Loop through ancestors
1019 if ( !empty( $ancestors ) ) {
1020 foreach ( $ancestors as $ancestor ) {
1021
1022 // If ancestor is a forum, update counts
1023 if ( bbp_is_forum( $ancestor ) ) {
1024
1025 // Update the forum
1026 bbp_update_forum( array(
1027 'forum_id' => $ancestor,
1028 ) );
1029 }
1030 }
1031 }
1032 }
1033 }
1034
1035 /**
1036 * Merge topic handler
1037 *
1038 * Handles the front end merge topic submission
1039 *
1040 * @since bbPress (r2756)
1041 *
1042 * @uses bbPress:errors::add() To log various error messages
1043 * @uses bbp_get_topic() To get the topics
1044 * @uses bbp_verify_nonce_request() To verify the nonce and check the request
1045 * @uses current_user_can() To check if the current user can edit the topics
1046 * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error}
1047 * @uses do_action() Calls 'bbp_merge_topic' with the destination and source
1048 * topic ids
1049 * @uses bbp_get_topic_subscribers() To get the source topic subscribers
1050 * @uses bbp_add_user_subscription() To add the user subscription
1051 * @uses bbp_remove_user_subscription() To remove the user subscription
1052 * @uses bbp_get_topic_favoriters() To get the source topic favoriters
1053 * @uses bbp_add_user_favorite() To add the user favorite
1054 * @uses bbp_remove_user_favorite() To remove the user favorite
1055 * @uses wp_get_post_terms() To get the source topic tags
1056 * @uses wp_set_post_terms() To set the topic tags
1057 * @uses wp_delete_object_term_relationships() To delete the topic tags
1058 * @uses bbp_open_topic() To open the topic
1059 * @uses bbp_unstick_topic() To unstick the topic
1060 * @uses bbp_get_reply_post_type() To get the reply post type
1061 * @uses get_posts() To get the replies
1062 * @uses wp_update_post() To update the topic
1063 * @uses bbp_update_reply_topic_id() To update the reply topic id
1064 * @uses bbp_get_topic_forum_id() To get the topic forum id
1065 * @uses bbp_update_reply_forum_id() To update the reply forum id
1066 * @uses do_action() Calls 'bbp_merged_topic_reply' with the reply id and
1067 * destination topic id
1068 * @uses do_action() Calls 'bbp_merged_topic' with the destination and source
1069 * topic ids and source topic's forum id
1070 * @uses bbp_get_topic_permalink() To get the topic permalink
1071 * @uses wp_safe_redirect() To redirect to the topic link
1072 */
1073 function bbp_merge_topic_handler() {
1074
1075 // Bail if not a POST action
1076 if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) )
1077 return;
1078
1079 // Bail if action is not bbp-merge-topic
1080 if ( empty( $_POST['action'] ) || ( 'bbp-merge-topic' !== $_POST['action'] ) )
1081 return;
1082
1083 // Define local variable(s)
1084 $source_topic_id = $destination_topic_id = 0;
1085 $source_topic = $destination_topic = 0;
1086 $subscribers = $favoriters = $replies = array();
1087
1088 /** Source Topic **********************************************************/
1089
1090 // Topic id
1091 if ( empty( $_POST['bbp_topic_id'] ) )
1092 bbp_add_error( 'bbp_merge_topic_source_id', __( '<strong>ERROR</strong>: Topic ID not found.', 'bbpress' ) );
1093 else
1094 $source_topic_id = (int) $_POST['bbp_topic_id'];
1095
1096 // Nonce check
1097 if ( ! bbp_verify_nonce_request( 'bbp-merge-topic_' . $source_topic_id ) ) {
1098 bbp_add_error( 'bbp_merge_topic_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
1099 return;
1100
1101 // Source topic not found
1102 } elseif ( !$source_topic = bbp_get_topic( $source_topic_id ) ) {
1103 bbp_add_error( 'bbp_merge_topic_source_not_found', __( '<strong>ERROR</strong>: The topic you want to merge was not found.', 'bbpress' ) );
1104 return;
1105 }
1106
1107 // Cannot edit source topic
1108 if ( !current_user_can( 'edit_topic', $source_topic->ID ) ) {
1109 bbp_add_error( 'bbp_merge_topic_source_permission', __( '<strong>ERROR</strong>: You do not have the permissions to edit the source topic.', 'bbpress' ) );
1110 return;
1111 }
1112
1113 /** Destination Topic *****************************************************/
1114
1115 // Topic id
1116 if ( empty( $_POST['bbp_destination_topic'] ) )
1117 bbp_add_error( 'bbp_merge_topic_destination_id', __( '<strong>ERROR</strong>: Destination topic ID not found.', 'bbpress' ) );
1118 else
1119 $destination_topic_id = (int) $_POST['bbp_destination_topic'];
1120
1121 // Destination topic not found
1122 if ( !$destination_topic = bbp_get_topic( $destination_topic_id ) )
1123 bbp_add_error( 'bbp_merge_topic_destination_not_found', __( '<strong>ERROR</strong>: The topic you want to merge to was not found.', 'bbpress' ) );
1124
1125 // Cannot edit destination topic
1126 if ( !current_user_can( 'edit_topic', $destination_topic->ID ) )
1127 bbp_add_error( 'bbp_merge_topic_destination_permission', __( '<strong>ERROR</strong>: You do not have the permissions to edit the destination topic.', 'bbpress' ) );
1128
1129 // Bail if errors
1130 if ( bbp_has_errors() )
1131 return;
1132
1133 /** No Errors *************************************************************/
1134
1135 // Update counts, etc...
1136 do_action( 'bbp_merge_topic', $destination_topic->ID, $source_topic->ID );
1137
1138 /** Date Check ************************************************************/
1139
1140 // Check if the destination topic is older than the source topic
1141 if ( strtotime( $source_topic->post_date ) < strtotime( $destination_topic->post_date ) ) {
1142
1143 // Set destination topic post_date to 1 second before source topic
1144 $destination_post_date = date( 'Y-m-d H:i:s', strtotime( $source_topic->post_date ) - 1 );
1145
1146 $postarr = array(
1147 'ID' => $destination_topic_id,
1148 'post_date' => $destination_post_date,
1149 'post_date_gmt' => get_gmt_from_date( $destination_post_date )
1150 );
1151
1152 // Update destination topic
1153 wp_update_post( $postarr );
1154 }
1155
1156 /** Subscriptions *********************************************************/
1157
1158 // Get subscribers from source topic
1159 $subscribers = bbp_get_topic_subscribers( $source_topic->ID );
1160
1161 // Remove the topic from everybody's subscriptions
1162 if ( !empty( $subscribers ) ) {
1163
1164 // Loop through each user
1165 foreach ( (array) $subscribers as $subscriber ) {
1166
1167 // Shift the subscriber if told to
1168 if ( !empty( $_POST['bbp_topic_subscribers'] ) && ( 1 == $_POST['bbp_topic_subscribers'] ) && bbp_is_subscriptions_active() )
1169 bbp_add_user_subscription( $subscriber, $destination_topic->ID );
1170
1171 // Remove old subscription
1172 bbp_remove_user_subscription( $subscriber, $source_topic->ID );
1173 }
1174 }
1175
1176 /** Favorites *************************************************************/
1177
1178 // Get favoriters from source topic
1179 $favoriters = bbp_get_topic_favoriters( $source_topic->ID );
1180
1181 // Remove the topic from everybody's favorites
1182 if ( !empty( $favoriters ) ) {
1183
1184 // Loop through each user
1185 foreach ( (array) $favoriters as $favoriter ) {
1186
1187 // Shift the favoriter if told to
1188 if ( !empty( $_POST['bbp_topic_favoriters'] ) && 1 == $_POST['bbp_topic_favoriters'] )
1189 bbp_add_user_favorite( $favoriter, $destination_topic->ID );
1190
1191 // Remove old favorite
1192 bbp_remove_user_favorite( $favoriter, $source_topic->ID );
1193 }
1194 }
1195
1196 /** Tags ******************************************************************/
1197
1198 // Get the source topic tags
1199 $source_topic_tags = wp_get_post_terms( $source_topic->ID, bbp_get_topic_tag_tax_id(), array( 'fields' => 'names' ) );
1200
1201 // Tags to possibly merge
1202 if ( !empty( $source_topic_tags ) && !is_wp_error( $source_topic_tags ) ) {
1203
1204 // Shift the tags if told to
1205 if ( !empty( $_POST['bbp_topic_tags'] ) && ( 1 == $_POST['bbp_topic_tags'] ) )
1206 wp_set_post_terms( $destination_topic->ID, $source_topic_tags, bbp_get_topic_tag_tax_id(), true );
1207
1208 // Delete the tags from the source topic
1209 wp_delete_object_term_relationships( $source_topic->ID, bbp_get_topic_tag_tax_id() );
1210 }
1211
1212 /** Source Topic **********************************************************/
1213
1214 // Status
1215 bbp_open_topic( $source_topic->ID );
1216
1217 // Sticky
1218 bbp_unstick_topic( $source_topic->ID );
1219
1220 // Get the replies of the source topic
1221 $replies = (array) get_posts( array(
1222 'post_parent' => $source_topic->ID,
1223 'post_type' => bbp_get_reply_post_type(),
1224 'posts_per_page' => -1,
1225 'order' => 'ASC'
1226 ) );
1227
1228 // Prepend the source topic to its replies array for processing
1229 array_unshift( $replies, $source_topic );
1230
1231 if ( !empty( $replies ) ) {
1232
1233 /** Merge Replies *****************************************************/
1234
1235 // Change the post_parent of each reply to the destination topic id
1236 foreach ( $replies as $reply ) {
1237 $postarr = array(
1238 'ID' => $reply->ID,
1239 'post_title' => sprintf( __( 'Reply To: %s', 'bbpress' ), $destination_topic->post_title ),
1240 'post_name' => false,
1241 'post_type' => bbp_get_reply_post_type(),
1242 'post_parent' => $destination_topic->ID,
1243 'guid' => ''
1244 );
1245
1246 wp_update_post( $postarr );
1247
1248 // Adjust reply meta values
1249 bbp_update_reply_topic_id( $reply->ID, $destination_topic->ID );
1250 bbp_update_reply_forum_id( $reply->ID, bbp_get_topic_forum_id( $destination_topic->ID ) );
1251
1252 // Do additional actions per merged reply
1253 do_action( 'bbp_merged_topic_reply', $reply->ID, $destination_topic->ID );
1254 }
1255 }
1256
1257 /** Successful Merge ******************************************************/
1258
1259 // Update topic's last meta data
1260 bbp_update_topic_last_reply_id ( $destination_topic->ID );
1261 bbp_update_topic_last_active_id ( $destination_topic->ID );
1262 bbp_update_topic_last_active_time( $destination_topic->ID );
1263
1264 // Send the post parent of the source topic as it has been shifted
1265 // (possibly to a new forum) so we need to update the counts of the
1266 // old forum as well as the new one
1267 do_action( 'bbp_merged_topic', $destination_topic->ID, $source_topic->ID, $source_topic->post_parent );
1268
1269 // Redirect back to new topic
1270 wp_safe_redirect( bbp_get_topic_permalink( $destination_topic->ID ) );
1271
1272 // For good measure
1273 exit();
1274 }
1275
1276 /**
1277 * Fix counts on topic merge
1278 *
1279 * When a topic is merged, update the counts of source and destination topic
1280 * and their forums.
1281 *
1282 * @since bbPress (r2756)
1283 *
1284 * @param int $destination_topic_id Destination topic id
1285 * @param int $source_topic_id Source topic id
1286 * @param int $source_topic_forum Source topic's forum id
1287 * @uses bbp_update_forum_topic_count() To update the forum topic counts
1288 * @uses bbp_update_forum_reply_count() To update the forum reply counts
1289 * @uses bbp_update_topic_reply_count() To update the topic reply counts
1290 * @uses bbp_update_topic_voice_count() To update the topic voice counts
1291 * @uses bbp_update_topic_reply_count_hidden() To update the topic hidden reply
1292 * count
1293 * @uses do_action() Calls 'bbp_merge_topic_count' with the destination topic
1294 * id, source topic id & source topic forum id
1295 */
1296 function bbp_merge_topic_count( $destination_topic_id, $source_topic_id, $source_topic_forum_id ) {
1297
1298 /** Source Topic **********************************************************/
1299
1300 // Forum Topic Counts
1301 bbp_update_forum_topic_count( $source_topic_forum_id );
1302
1303 // Forum Reply Counts
1304 bbp_update_forum_reply_count( $source_topic_forum_id );
1305
1306 /** Destination Topic *****************************************************/
1307
1308 // Topic Reply Counts
1309 bbp_update_topic_reply_count( $destination_topic_id );
1310
1311 // Topic Hidden Reply Counts
1312 bbp_update_topic_reply_count_hidden( $destination_topic_id );
1313
1314 // Topic Voice Counts
1315 bbp_update_topic_voice_count( $destination_topic_id );
1316
1317 do_action( 'bbp_merge_topic_count', $destination_topic_id, $source_topic_id, $source_topic_forum_id );
1318 }
1319
1320 /**
1321 * Split topic handler
1322 *
1323 * Handles the front end split topic submission
1324 *
1325 * @since bbPress (r2756)
1326 *
1327 * @uses bbPress:errors::add() To log various error messages
1328 * @uses bbp_get_reply() To get the reply
1329 * @uses bbp_get_topic() To get the topics
1330 * @uses bbp_verify_nonce_request() To verify the nonce and check the request
1331 * @uses current_user_can() To check if the current user can edit the topics
1332 * @uses bbp_get_topic_post_type() To get the topic post type
1333 * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error}
1334 * @uses do_action() Calls 'bbp_pre_split_topic' with the from reply id, source
1335 * and destination topic ids
1336 * @uses bbp_get_topic_subscribers() To get the source topic subscribers
1337 * @uses bbp_add_user_subscription() To add the user subscription
1338 * @uses bbp_get_topic_favoriters() To get the source topic favoriters
1339 * @uses bbp_add_user_favorite() To add the user favorite
1340 * @uses wp_get_post_terms() To get the source topic tags
1341 * @uses wp_set_post_terms() To set the topic tags
1342 * @uses bbp_get_reply_post_type() To get the reply post type
1343 * @uses wpdb::prepare() To prepare our sql query
1344 * @uses wpdb::get_results() To execute the sql query and get results
1345 * @uses wp_update_post() To update the replies
1346 * @uses bbp_update_reply_topic_id() To update the reply topic id
1347 * @uses bbp_get_topic_forum_id() To get the topic forum id
1348 * @uses bbp_update_reply_forum_id() To update the reply forum id
1349 * @uses do_action() Calls 'bbp_split_topic_reply' with the reply id and
1350 * destination topic id
1351 * @uses bbp_update_topic_last_reply_id() To update the topic last reply id
1352 * @uses bbp_update_topic_last_active_time() To update the topic last active meta
1353 * @uses do_action() Calls 'bbp_post_split_topic' with the destination and
1354 * source topic ids and source topic's forum id
1355 * @uses bbp_get_topic_permalink() To get the topic permalink
1356 * @uses wp_safe_redirect() To redirect to the topic link
1357 */
1358 function bbp_split_topic_handler() {
1359
1360 // Bail if not a POST action
1361 if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) )
1362 return;
1363
1364 // Bail if action is not 'bbp-split-topic'
1365 if ( empty( $_POST['action'] ) || ( 'bbp-split-topic' !== $_POST['action'] ) )
1366 return;
1367
1368 global $wpdb;
1369
1370 // Prevent debug notices
1371 $from_reply_id = $destination_topic_id = 0;
1372 $destination_topic_title = '';
1373 $destination_topic = $from_reply = $source_topic = '';
1374 $split_option = false;
1375
1376 /** Split Reply ***********************************************************/
1377
1378 if ( empty( $_POST['bbp_reply_id'] ) )
1379 bbp_add_error( 'bbp_split_topic_reply_id', __( '<strong>ERROR</strong>: Reply ID to split the topic from not found!', 'bbpress' ) );
1380 else
1381 $from_reply_id = (int) $_POST['bbp_reply_id'];
1382
1383 $from_reply = bbp_get_reply( $from_reply_id );
1384
1385 // Reply exists
1386 if ( empty( $from_reply ) )
1387 bbp_add_error( 'bbp_split_topic_r_not_found', __( '<strong>ERROR</strong>: The reply you want to split from was not found.', 'bbpress' ) );
1388
1389 /** Topic to Split ********************************************************/
1390
1391 // Get the topic being split
1392 $source_topic = bbp_get_topic( $from_reply->post_parent );
1393
1394 // No topic
1395 if ( empty( $source_topic ) )
1396 bbp_add_error( 'bbp_split_topic_source_not_found', __( '<strong>ERROR</strong>: The topic you want to split was not found.', 'bbpress' ) );
1397
1398 // Nonce check failed
1399 if ( ! bbp_verify_nonce_request( 'bbp-split-topic_' . $source_topic->ID ) ) {
1400 bbp_add_error( 'bbp_split_topic_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
1401 return;
1402 }
1403
1404 // Use cannot edit topic
1405 if ( !current_user_can( 'edit_topic', $source_topic->ID ) )
1406 bbp_add_error( 'bbp_split_topic_source_permission', __( '<strong>ERROR</strong>: You do not have the permissions to edit the source topic.', 'bbpress' ) );
1407
1408 // How to Split
1409 if ( !empty( $_POST['bbp_topic_split_option'] ) )
1410 $split_option = (string) trim( $_POST['bbp_topic_split_option'] );
1411
1412 // Invalid split option
1413 if ( empty( $split_option ) || !in_array( $split_option, array( 'existing', 'reply' ) ) ) {
1414 bbp_add_error( 'bbp_split_topic_option', __( '<strong>ERROR</strong>: You need to choose a valid split option.', 'bbpress' ) );
1415
1416 // Valid Split Option
1417 } else {
1418
1419 // What kind of split
1420 switch ( $split_option ) {
1421
1422 // Into an existing topic
1423 case 'existing' :
1424
1425 // Get destination topic id
1426 if ( empty( $_POST['bbp_destination_topic'] ) )
1427 bbp_add_error( 'bbp_split_topic_destination_id', __( '<strong>ERROR</strong>: Destination topic ID not found!', 'bbpress' ) );
1428 else
1429 $destination_topic_id = (int) $_POST['bbp_destination_topic'];
1430
1431 // Get the destination topic
1432 $destination_topic = bbp_get_topic( $destination_topic_id );
1433
1434 // No destination topic
1435 if ( empty( $destination_topic ) )
1436 bbp_add_error( 'bbp_split_topic_destination_not_found', __( '<strong>ERROR</strong>: The topic you want to split to was not found!', 'bbpress' ) );
1437
1438 // User cannot edit the destination topic
1439 if ( !current_user_can( 'edit_topic', $destination_topic->ID ) )
1440 bbp_add_error( 'bbp_split_topic_destination_permission', __( '<strong>ERROR</strong>: You do not have the permissions to edit the destination topic!', 'bbpress' ) );
1441
1442 break;
1443
1444 // Split at reply into a new topic
1445 case 'reply' :
1446 default :
1447
1448 // User needs to be able to publish topics
1449 if ( current_user_can( 'publish_topics' ) ) {
1450
1451 // Use the new title that was passed
1452 if ( !empty( $_POST['bbp_topic_split_destination_title'] ) ) {
1453 $destination_topic_title = esc_attr( strip_tags( $_POST['bbp_topic_split_destination_title'] ) );
1454
1455 // Use the source topic title
1456 } else {
1457 $destination_topic_title = $source_topic->post_title;
1458 }
1459
1460 // Setup the updated topic parameters
1461 $postarr = array(
1462 'ID' => $from_reply->ID,
1463 'post_title' => $destination_topic_title,
1464 'post_name' => false,
1465 'post_type' => bbp_get_topic_post_type(),
1466 'post_parent' => $source_topic->post_parent,
1467 'guid' => ''
1468 );
1469
1470 // Update the topic
1471 $destination_topic_id = wp_update_post( $postarr );
1472 $destination_topic = bbp_get_topic( $destination_topic_id );
1473
1474 // Make sure the new topic knows its a topic
1475 bbp_update_topic_topic_id( $from_reply->ID );
1476
1477 // Shouldn't happen
1478 if ( false == $destination_topic_id || is_wp_error( $destination_topic_id ) || empty( $destination_topic ) ) {
1479 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' ) );
1480 }
1481
1482 // User cannot publish posts
1483 } else {
1484 bbp_add_error( 'bbp_split_topic_destination_permission', __( '<strong>ERROR</strong>: You do not have the permissions to create new topics. The reply could not be converted into a topic.', 'bbpress' ) );
1485 }
1486
1487 break;
1488 }
1489 }
1490
1491 // Bail if there are errors
1492 if ( bbp_has_errors() )
1493 return;
1494
1495 /** No Errors - Do the Spit ***********************************************/
1496
1497 // Update counts, etc...
1498 do_action( 'bbp_pre_split_topic', $from_reply->ID, $source_topic->ID, $destination_topic->ID );
1499
1500 /** Date Check ************************************************************/
1501
1502 // Check if the destination topic is older than the from reply
1503 if ( strtotime( $from_reply->post_date ) < strtotime( $destination_topic->post_date ) ) {
1504
1505 // Set destination topic post_date to 1 second before from reply
1506 $destination_post_date = date( 'Y-m-d H:i:s', strtotime( $from_reply->post_date ) - 1 );
1507
1508 $postarr = array(
1509 'ID' => $destination_topic_id,
1510 'post_date' => $destination_post_date,
1511 'post_date_gmt' => get_gmt_from_date( $destination_post_date )
1512 );
1513
1514 // Update destination topic
1515 wp_update_post( $postarr );
1516 }
1517
1518 /** Subscriptions *********************************************************/
1519
1520 // Copy the subscribers
1521 if ( !empty( $_POST['bbp_topic_subscribers'] ) && 1 == $_POST['bbp_topic_subscribers'] && bbp_is_subscriptions_active() ) {
1522
1523 // Get the subscribers
1524 $subscribers = bbp_get_topic_subscribers( $source_topic->ID );
1525
1526 if ( !empty( $subscribers ) ) {
1527
1528 // Add subscribers to new topic
1529 foreach ( (array) $subscribers as $subscriber ) {
1530 bbp_add_user_subscription( $subscriber, $destination_topic->ID );
1531 }
1532 }
1533 }
1534
1535 /** Favorites *************************************************************/
1536
1537 // Copy the favoriters if told to
1538 if ( !empty( $_POST['bbp_topic_favoriters'] ) && 1 == $_POST['bbp_topic_favoriters'] ) {
1539
1540 // Get the favoriters
1541 $favoriters = bbp_get_topic_favoriters( $source_topic->ID );
1542
1543 if ( !empty( $favoriters ) ) {
1544
1545 // Add the favoriters to new topic
1546 foreach ( (array) $favoriters as $favoriter ) {
1547 bbp_add_user_favorite( $favoriter, $destination_topic->ID );
1548 }
1549 }
1550 }
1551
1552 /** Tags ******************************************************************/
1553
1554 // Copy the tags if told to
1555 if ( !empty( $_POST['bbp_topic_tags'] ) && ( 1 == $_POST['bbp_topic_tags'] ) ) {
1556
1557 // Get the source topic tags
1558 $source_topic_tags = wp_get_post_terms( $source_topic->ID, bbp_get_topic_tag_tax_id(), array( 'fields' => 'names' ) );
1559
1560 if ( !empty( $source_topic_tags ) ) {
1561 wp_set_post_terms( $destination_topic->ID, $source_topic_tags, bbp_get_topic_tag_tax_id(), true );
1562 }
1563 }
1564
1565 /** Split Replies *********************************************************/
1566
1567 // get_posts() is not used because it doesn't allow us to use '>='
1568 // comparision without a filter.
1569 $replies = (array) $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->posts} WHERE {$wpdb->posts}.post_date >= %s AND {$wpdb->posts}.post_parent = %d AND {$wpdb->posts}.post_type = %s ORDER BY {$wpdb->posts}.post_date ASC", $from_reply->post_date, $source_topic->ID, bbp_get_reply_post_type() ) );
1570
1571 // Make sure there are replies to loop through
1572 if ( !empty( $replies ) && !is_wp_error( $replies ) ) {
1573
1574 // Calculate starting point for reply positions
1575 switch ( $split_option ) {
1576
1577 // Get topic reply count for existing topic
1578 case 'existing' :
1579 $reply_position = bbp_get_topic_reply_count( $destination_topic->ID );
1580 break;
1581
1582 // Account for new lead topic
1583 case 'reply' :
1584 $reply_position = 1;
1585 break;
1586 }
1587
1588 // Change the post_parent of each reply to the destination topic id
1589 foreach ( $replies as $reply ) {
1590
1591 // Bump the reply position each iteration through the loop
1592 $reply_position++;
1593
1594 // New reply data
1595 $postarr = array(
1596 'ID' => $reply->ID,
1597 'post_title' => sprintf( __( 'Reply To: %s', 'bbpress' ), $destination_topic->post_title ),
1598 'post_name' => false, // will be automatically generated
1599 'post_parent' => $destination_topic->ID,
1600 'post_position' => $reply_position,
1601 'guid' => ''
1602 );
1603
1604 // Update the reply
1605 wp_update_post( $postarr );
1606
1607 // Adjust reply meta values
1608 bbp_update_reply_topic_id( $reply->ID, $destination_topic->ID );
1609 bbp_update_reply_forum_id( $reply->ID, bbp_get_topic_forum_id( $destination_topic->ID ) );
1610
1611 // Do additional actions per split reply
1612 do_action( 'bbp_split_topic_reply', $reply->ID, $destination_topic->ID );
1613 }
1614
1615 // Set the last reply ID and freshness
1616 $last_reply_id = $reply->ID;
1617 $freshness = $reply->post_date;
1618
1619 // Set the last reply ID and freshness to the from_reply
1620 } else {
1621 $last_reply_id = $from_reply->ID;
1622 $freshness = $from_reply->post_date;
1623 }
1624
1625 // It is a new topic and we need to set some default metas to make
1626 // the topic display in bbp_has_topics() list
1627 if ( 'reply' == $split_option ) {
1628 bbp_update_topic_last_reply_id ( $destination_topic->ID, $last_reply_id );
1629 bbp_update_topic_last_active_id ( $destination_topic->ID, $last_reply_id );
1630 bbp_update_topic_last_active_time( $destination_topic->ID, $freshness );
1631 }
1632
1633 // Update source topic ID last active
1634 bbp_update_topic_last_reply_id ( $source_topic->ID );
1635 bbp_update_topic_last_active_id ( $source_topic->ID );
1636 bbp_update_topic_last_active_time( $source_topic->ID );
1637
1638 /** Successful Split ******************************************************/
1639
1640 // Update counts, etc...
1641 do_action( 'bbp_post_split_topic', $from_reply->ID, $source_topic->ID, $destination_topic->ID );
1642
1643 // Redirect back to the topic
1644 wp_safe_redirect( bbp_get_topic_permalink( $destination_topic->ID ) );
1645
1646 // For good measure
1647 exit();
1648 }
1649
1650 /**
1651 * Fix counts on topic split
1652 *
1653 * When a topic is split, update the counts of source and destination topic
1654 * and their forums.
1655 *
1656 * @since bbPress (r2756)
1657 *
1658 * @param int $from_reply_id From reply id
1659 * @param int $source_topic_id Source topic id
1660 * @param int $destination_topic_id Destination topic id
1661 * @uses bbp_update_forum_topic_count() To update the forum topic counts
1662 * @uses bbp_update_forum_reply_count() To update the forum reply counts
1663 * @uses bbp_update_topic_reply_count() To update the topic reply counts
1664 * @uses bbp_update_topic_voice_count() To update the topic voice counts
1665 * @uses bbp_update_topic_reply_count_hidden() To update the topic hidden reply
1666 * count
1667 * @uses do_action() Calls 'bbp_split_topic_count' with the from reply id,
1668 * source topic id & destination topic id
1669 */
1670 function bbp_split_topic_count( $from_reply_id, $source_topic_id, $destination_topic_id ) {
1671
1672 // Forum Topic Counts
1673 bbp_update_forum_topic_count( $destination_topic_id );
1674
1675 // Forum Reply Counts
1676 bbp_update_forum_reply_count( $destination_topic_id );
1677
1678 // Topic Reply Counts
1679 bbp_update_topic_reply_count( $source_topic_id );
1680 bbp_update_topic_reply_count( $destination_topic_id );
1681
1682 // Topic Hidden Reply Counts
1683 bbp_update_topic_reply_count_hidden( $source_topic_id );
1684 bbp_update_topic_reply_count_hidden( $destination_topic_id );
1685
1686 // Topic Voice Counts
1687 bbp_update_topic_voice_count( $source_topic_id );
1688 bbp_update_topic_voice_count( $destination_topic_id );
1689
1690 do_action( 'bbp_split_topic_count', $from_reply_id, $source_topic_id, $destination_topic_id );
1691 }
1692
1693 /**
1694 * Handles the front end tag management (renaming, merging, destroying)
1695 *
1696 * @since bbPress (r2768)
1697 *
1698 * @uses bbp_verify_nonce_request() To verify the nonce and check the request
1699 * @uses current_user_can() To check if the current user can edit/delete tags
1700 * @uses bbPress::errors::add() To log the error messages
1701 * @uses wp_update_term() To update the topic tag
1702 * @uses get_term_link() To get the topic tag url
1703 * @uses term_exists() To check if the topic tag already exists
1704 * @uses wp_insert_term() To insert a topic tag
1705 * @uses wp_delete_term() To delete the topic tag
1706 * @uses home_url() To get the blog's home page url
1707 * @uses do_action() Calls actions based on the actions with associated args
1708 * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error}
1709 * @uses wp_safe_redirect() To redirect to the url
1710 */
1711 function bbp_edit_topic_tag_handler() {
1712
1713 // Bail if not a POST action
1714 if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) )
1715 return;
1716
1717 // Bail if required POST actions aren't passed
1718 if ( empty( $_POST['tag-id'] ) || empty( $_POST['action'] ) )
1719 return;
1720
1721 // Setup possible get actions
1722 $possible_actions = array(
1723 'bbp-update-topic-tag',
1724 'bbp-merge-topic-tag',
1725 'bbp-delete-topic-tag'
1726 );
1727
1728 // Bail if actions aren't meant for this function
1729 if ( !in_array( $_POST['action'], $possible_actions ) )
1730 return;
1731
1732 // Setup vars
1733 $action = $_POST['action'];
1734 $tag_id = (int) $_POST['tag-id'];
1735 $tag = get_term( $tag_id, bbp_get_topic_tag_tax_id() );
1736
1737 // Tag does not exist
1738 if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
1739 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() ) );
1740 return;
1741 }
1742
1743 // What action are we trying to perform?
1744 switch ( $action ) {
1745
1746 // Update tag
1747 case 'bbp-update-topic-tag' :
1748
1749 // Nonce check
1750 if ( ! bbp_verify_nonce_request( 'update-tag_' . $tag_id ) ) {
1751 bbp_add_error( 'bbp_manage_topic_tag_update_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
1752 return;
1753 }
1754
1755 // Can user edit topic tags?
1756 if ( !current_user_can( 'edit_topic_tags' ) ) {
1757 bbp_add_error( 'bbp_manage_topic_tag_update_permissions', __( '<strong>ERROR</strong>: You do not have the permissions to edit the topic tags.', 'bbpress' ) );
1758 return;
1759 }
1760
1761 // No tag name was provided
1762 if ( empty( $_POST['tag-name'] ) || !$name = $_POST['tag-name'] ) {
1763 bbp_add_error( 'bbp_manage_topic_tag_update_name', __( '<strong>ERROR</strong>: You need to enter a tag name.', 'bbpress' ) );
1764 return;
1765 }
1766
1767 // Attempt to update the tag
1768 $slug = !empty( $_POST['tag-slug'] ) ? $_POST['tag-slug'] : '';
1769 $tag = wp_update_term( $tag_id, bbp_get_topic_tag_tax_id(), array( 'name' => $name, 'slug' => $slug ) );
1770
1771 // Cannot update tag
1772 if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
1773 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() ) );
1774 return;
1775 }
1776
1777 // Redirect
1778 $redirect = get_term_link( $tag_id, bbp_get_topic_tag_tax_id() );
1779
1780 // Update counts, etc...
1781 do_action( 'bbp_update_topic_tag', $tag_id, $tag, $name, $slug );
1782
1783 break;
1784
1785 // Merge two tags
1786 case 'bbp-merge-topic-tag' :
1787
1788 // Nonce check
1789 if ( ! bbp_verify_nonce_request( 'merge-tag_' . $tag_id ) ) {
1790 bbp_add_error( 'bbp_manage_topic_tag_merge_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
1791 return;
1792 }
1793
1794 // Can user edit topic tags?
1795 if ( !current_user_can( 'edit_topic_tags' ) ) {
1796 bbp_add_error( 'bbp_manage_topic_tag_merge_permissions', __( '<strong>ERROR</strong>: You do not have the permissions to edit the topic tags.', 'bbpress' ) );
1797 return;
1798 }
1799
1800 // No tag name was provided
1801 if ( empty( $_POST['tag-existing-name'] ) || !$name = $_POST['tag-existing-name'] ) {
1802 bbp_add_error( 'bbp_manage_topic_tag_merge_name', __( '<strong>ERROR</strong>: You need to enter a tag name.', 'bbpress' ) );
1803 return;
1804 }
1805
1806 // If term does not exist, create it
1807 if ( !$tag = term_exists( $name, bbp_get_topic_tag_tax_id() ) )
1808 $tag = wp_insert_term( $name, bbp_get_topic_tag_tax_id() );
1809
1810 // Problem inserting the new term
1811 if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
1812 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() ) );
1813 return;
1814 }
1815
1816 // Merging in to...
1817 $to_tag = $tag['term_id'];
1818
1819 // Attempting to merge a tag into itself
1820 if ( $tag_id == $to_tag ) {
1821 bbp_add_error( 'bbp_manage_topic_tag_merge_same', __( '<strong>ERROR</strong>: The tags which are being merged can not be the same.', 'bbpress' ) );
1822 return;
1823 }
1824
1825 // Delete the old term
1826 $tag = wp_delete_term( $tag_id, bbp_get_topic_tag_tax_id(), array( 'default' => $to_tag, 'force_default' => true ) );
1827
1828 // Error merging the terms
1829 if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
1830 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() ) );
1831 return;
1832 }
1833
1834 // Redirect
1835 $redirect = get_term_link( (int) $to_tag, bbp_get_topic_tag_tax_id() );
1836
1837 // Update counts, etc...
1838 do_action( 'bbp_merge_topic_tag', $tag_id, $to_tag, $tag );
1839
1840 break;
1841
1842 // Delete tag
1843 case 'bbp-delete-topic-tag' :
1844
1845 // Nonce check
1846 if ( ! bbp_verify_nonce_request( 'delete-tag_' . $tag_id ) ) {
1847 bbp_add_error( 'bbp_manage_topic_tag_delete_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
1848 return;
1849 }
1850
1851 // Can user delete topic tags?
1852 if ( !current_user_can( 'delete_topic_tags' ) ) {
1853 bbp_add_error( 'bbp_manage_topic_tag_delete_permissions', __( '<strong>ERROR</strong>: You do not have the permissions to delete the topic tags.', 'bbpress' ) );
1854 return;
1855 }
1856
1857 // Attempt to delete term
1858 $tag = wp_delete_term( $tag_id, bbp_get_topic_tag_tax_id() );
1859
1860 // Error deleting term
1861 if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
1862 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() ) );
1863 return;
1864 }
1865
1866 // We don't have any other place to go other than home! Or we may die because of the 404 disease
1867 $redirect = home_url();
1868
1869 // Update counts, etc...
1870 do_action( 'bbp_delete_topic_tag', $tag_id, $tag );
1871
1872 break;
1873 }
1874
1875 /** Successful Moderation *************************************************/
1876
1877 // Redirect back
1878 $redirect = ( !empty( $redirect ) && !is_wp_error( $redirect ) ) ? $redirect : home_url();
1879 wp_safe_redirect( $redirect );
1880
1881 // For good measure
1882 exit();
1883 }
1884
1885 /** Stickies ******************************************************************/
1886
1887 /**
1888 * Return sticky topics of a forum
1889 *
1890 * @since bbPress (r2592)
1891 *
1892 * @param int $forum_id Optional. If not passed, super stickies are returned.
1893 * @uses bbp_get_super_stickies() To get the super stickies
1894 * @uses get_post_meta() To get the forum stickies
1895 * @uses apply_filters() Calls 'bbp_get_stickies' with the stickies and forum id
1896 * @return array IDs of sticky topics of a forum or super stickies
1897 */
1898 function bbp_get_stickies( $forum_id = 0 ) {
1899 $stickies = empty( $forum_id ) ? bbp_get_super_stickies() : get_post_meta( $forum_id, '_bbp_sticky_topics', true );
1900 $stickies = ( empty( $stickies ) || !is_array( $stickies ) ) ? array() : $stickies;
1901
1902 return apply_filters( 'bbp_get_stickies', $stickies, (int) $forum_id );
1903 }
1904
1905 /**
1906 * Return topics stuck to front page of the forums
1907 *
1908 * @since bbPress (r2592)
1909 *
1910 * @uses get_option() To get super sticky topics
1911 * @uses apply_filters() Calls 'bbp_get_super_stickies' with the stickies
1912 * @return array IDs of super sticky topics
1913 */
1914 function bbp_get_super_stickies() {
1915 $stickies = get_option( '_bbp_super_sticky_topics', array() );
1916 $stickies = ( empty( $stickies ) || !is_array( $stickies ) ) ? array() : $stickies;
1917
1918 return apply_filters( 'bbp_get_super_stickies', $stickies );
1919 }
1920
1921 /** Topics Actions ************************************************************/
1922
1923 /**
1924 * Handles the front end opening/closing, spamming/unspamming,
1925 * sticking/unsticking and trashing/untrashing/deleting of topics
1926 *
1927 * @since bbPress (r2727)
1928 *
1929 * @uses bbp_get_topic() To get the topic
1930 * @uses current_user_can() To check if the user is capable of editing or
1931 * deleting the topic
1932 * @uses bbp_get_topic_post_type() To get the topic post type
1933 * @uses check_ajax_referer() To verify the nonce and check the referer
1934 * @uses bbp_is_topic_open() To check if the topic is open
1935 * @uses bbp_close_topic() To close the topic
1936 * @uses bbp_open_topic() To open the topic
1937 * @uses bbp_is_topic_sticky() To check if the topic is a sticky
1938 * @uses bbp_unstick_topic() To unstick the topic
1939 * @uses bbp_stick_topic() To stick the topic
1940 * @uses bbp_is_topic_spam() To check if the topic is marked as spam
1941 * @uses bbp_spam_topic() To make the topic as spam
1942 * @uses bbp_unspam_topic() To unmark the topic as spam
1943 * @uses wp_trash_post() To trash the topic
1944 * @uses wp_untrash_post() To untrash the topic
1945 * @uses wp_delete_post() To delete the topic
1946 * @uses do_action() Calls 'bbp_toggle_topic_handler' with success, post data
1947 * and action
1948 * @uses bbp_get_forum_permalink() To get the forum link
1949 * @uses bbp_get_topic_permalink() To get the topic link
1950 * @uses add_query_arg() To add args to the url
1951 * @uses wp_safe_redirect() To redirect to the topic
1952 * @uses bbPress::errors:add() To log the error messages
1953 */
1954 function bbp_toggle_topic_handler() {
1955
1956 // Bail if not a GET action
1957 if ( 'GET' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) )
1958 return;
1959
1960 // Bail if required GET actions aren't passed
1961 if ( empty( $_GET['topic_id'] ) || empty( $_GET['action'] ) )
1962 return;
1963
1964 // Setup possible get actions
1965 $possible_actions = array(
1966 'bbp_toggle_topic_close',
1967 'bbp_toggle_topic_stick',
1968 'bbp_toggle_topic_spam',
1969 'bbp_toggle_topic_trash'
1970 );
1971
1972 // Bail if actions aren't meant for this function
1973 if ( !in_array( $_GET['action'], $possible_actions ) )
1974 return;
1975
1976 $failure = ''; // Empty failure string
1977 $view_all = false; // Assume not viewing all
1978 $action = $_GET['action']; // What action is taking place?
1979 $topic_id = (int) $_GET['topic_id']; // What's the topic id?
1980 $success = false; // Flag
1981 $post_data = array( 'ID' => $topic_id ); // Prelim array
1982 $redirect = ''; // Empty redirect URL
1983
1984 // Make sure topic exists
1985 $topic = bbp_get_topic( $topic_id );
1986 if ( empty( $topic ) )
1987 return;
1988
1989 // What is the user doing here?
1990 if ( !current_user_can( 'edit_topic', $topic->ID ) || ( 'bbp_toggle_topic_trash' == $action && !current_user_can( 'delete_topic', $topic->ID ) ) ) {
1991 bbp_add_error( 'bbp_toggle_topic_permission', __( '<strong>ERROR:</strong> You do not have the permission to do that.', 'bbpress' ) );
1992 return;
1993 }
1994
1995 // What action are we trying to perform?
1996 switch ( $action ) {
1997
1998 // Toggle open/close
1999 case 'bbp_toggle_topic_close' :
2000 check_ajax_referer( 'close-topic_' . $topic_id );
2001
2002 $is_open = bbp_is_topic_open( $topic_id );
2003 $success = $is_open ? bbp_close_topic( $topic_id ) : bbp_open_topic( $topic_id );
2004 $failure = $is_open ? __( '<strong>ERROR</strong>: There was a problem closing the topic.', 'bbpress' ) : __( '<strong>ERROR</strong>: There was a problem opening the topic.', 'bbpress' );
2005
2006 break;
2007
2008 // Toggle sticky/super-sticky/unstick
2009 case 'bbp_toggle_topic_stick' :
2010 check_ajax_referer( 'stick-topic_' . $topic_id );
2011
2012 $is_sticky = bbp_is_topic_sticky( $topic_id );
2013 $is_super = ( empty( $is_sticky ) && !empty( $_GET['super'] ) && 1 == (int) $_GET['super'] ) ? true : false;
2014 $success = $is_sticky ? bbp_unstick_topic( $topic_id ) : bbp_stick_topic( $topic_id, $is_super );
2015 $failure = $is_sticky ? __( '<strong>ERROR</strong>: There was a problem unsticking the topic.', 'bbpress' ) : __( '<strong>ERROR</strong>: There was a problem sticking the topic.', 'bbpress' );
2016
2017 break;
2018
2019 // Toggle spam
2020 case 'bbp_toggle_topic_spam' :
2021 check_ajax_referer( 'spam-topic_' . $topic_id );
2022
2023 $is_spam = bbp_is_topic_spam( $topic_id );
2024 $success = $is_spam ? bbp_unspam_topic( $topic_id ) : bbp_spam_topic( $topic_id );
2025 $failure = $is_spam ? __( '<strong>ERROR</strong>: There was a problem unmarking the topic as spam.', 'bbpress' ) : __( '<strong>ERROR</strong>: There was a problem marking the topic as spam.', 'bbpress' );
2026 $view_all = !$is_spam;
2027
2028 break;
2029
2030 // Toggle trash
2031 case 'bbp_toggle_topic_trash' :
2032
2033 $sub_action = in_array( $_GET['sub_action'], array( 'trash', 'untrash', 'delete' ) ) ? $_GET['sub_action'] : false;
2034
2035 if ( empty( $sub_action ) )
2036 break;
2037
2038 switch ( $sub_action ) {
2039 case 'trash':
2040 check_ajax_referer( 'trash-' . bbp_get_topic_post_type() . '_' . $topic_id );
2041
2042 $view_all = true;
2043 $success = wp_trash_post( $topic_id );
2044 $failure = __( '<strong>ERROR</strong>: There was a problem trashing the topic.', 'bbpress' );
2045
2046 break;
2047
2048 case 'untrash':
2049 check_ajax_referer( 'untrash-' . bbp_get_topic_post_type() . '_' . $topic_id );
2050
2051 $success = wp_untrash_post( $topic_id );
2052 $failure = __( '<strong>ERROR</strong>: There was a problem untrashing the topic.', 'bbpress' );
2053
2054 break;
2055
2056 case 'delete':
2057 check_ajax_referer( 'delete-' . bbp_get_topic_post_type() . '_' . $topic_id );
2058
2059 $success = wp_delete_post( $topic_id );
2060 $failure = __( '<strong>ERROR</strong>: There was a problem deleting the topic.', 'bbpress' );
2061
2062 break;
2063 }
2064
2065 break;
2066 }
2067
2068 // Do additional topic toggle actions
2069 do_action( 'bbp_toggle_topic_handler', $success, $post_data, $action );
2070
2071 // No errors
2072 if ( false != $success && !is_wp_error( $success ) ) {
2073
2074 // Redirect back to the topic's forum
2075 if ( isset( $sub_action ) && ( 'delete' == $sub_action ) ) {
2076 $redirect = bbp_get_forum_permalink( $success->post_parent );
2077
2078 // Redirect back to the topic
2079 } else {
2080
2081 // Get the redirect detination
2082 $permalink = bbp_get_topic_permalink( $topic_id );
2083 $redirect = bbp_add_view_all( $permalink, $view_all );
2084 }
2085
2086 wp_safe_redirect( $redirect );
2087
2088 // For good measure
2089 exit();
2090
2091 // Handle errors
2092 } else {
2093 bbp_add_error( 'bbp_toggle_topic', $failure );
2094 }
2095 }
2096
2097 /** Favorites & Subscriptions *************************************************/
2098
2099 /**
2100 * Remove a deleted topic from all users' favorites
2101 *
2102 * @since bbPress (r2652)
2103 *
2104 * @param int $topic_id Topic ID to remove
2105 * @uses bbp_get_topic_favoriters() To get the topic's favoriters
2106 * @uses bbp_remove_user_favorite() To remove the topic from user's favorites
2107 */
2108 function bbp_remove_topic_from_all_favorites( $topic_id = 0 ) {
2109 $topic_id = bbp_get_topic_id( $topic_id );
2110
2111 // Bail if no topic
2112 if ( empty( $topic_id ) )
2113 return;
2114
2115 // Get users
2116 $users = (array) bbp_get_topic_favoriters( $topic_id );
2117
2118 // Users exist
2119 if ( !empty( $users ) ) {
2120
2121 // Loop through users
2122 foreach ( $users as $user ) {
2123
2124 // Remove each user
2125 bbp_remove_user_favorite( $user, $topic_id );
2126 }
2127 }
2128 }
2129
2130 /**
2131 * Remove a deleted topic from all users' subscriptions
2132 *
2133 * @since bbPress (r2652)
2134 *
2135 * @param int $topic_id Topic ID to remove
2136 * @uses bbp_is_subscriptions_active() To check if the subscriptions are active
2137 * @uses bbp_get_topic_subscribers() To get the topic subscribers
2138 * @uses bbp_remove_user_subscription() To remove the user subscription
2139 */
2140 function bbp_remove_topic_from_all_subscriptions( $topic_id = 0 ) {
2141
2142 // Subscriptions are not active
2143 if ( !bbp_is_subscriptions_active() )
2144 return;
2145
2146 $topic_id = bbp_get_topic_id( $topic_id );
2147
2148 // Bail if no topic
2149 if ( empty( $topic_id ) )
2150 return;
2151
2152 // Get users
2153 $users = (array) bbp_get_topic_subscribers( $topic_id );
2154
2155 // Users exist
2156 if ( !empty( $users ) ) {
2157
2158 // Loop through users
2159 foreach ( $users as $user ) {
2160
2161 // Remove each user
2162 bbp_remove_user_subscription( $user, $topic_id );
2163 }
2164 }
2165 }
2166
2167 /** Count Bumpers *************************************************************/
2168
2169 /**
2170 * Bump the total reply count of a topic
2171 *
2172 * @since bbPress (r3825)
2173 *
2174 * @param int $topic_id Optional. Forum id.
2175 * @param int $difference Optional. Default 1
2176 * @param bool $update_ancestors Optional. Default true
2177 * @uses bbp_get_topic_id() To get the topic id
2178 * @uses update_post_meta() To update the topic's reply count meta
2179 * @uses apply_filters() Calls 'bbp_bump_topic_reply_count' with the reply
2180 * count, topic id, and difference
2181 * @return int Forum reply count
2182 */
2183 function bbp_bump_topic_reply_count( $topic_id = 0, $difference = 1 ) {
2184
2185 // Get counts
2186 $topic_id = bbp_get_topic_id( $topic_id );
2187 $reply_count = bbp_get_topic_reply_count( $topic_id, false );
2188 $new_count = (int) $reply_count + (int) $difference;
2189
2190 // Update this topic id's reply count
2191 update_post_meta( $topic_id, '_bbp_reply_count', (int) $new_count );
2192
2193 return (int) apply_filters( 'bbp_bump_topic_reply_count', (int) $new_count, $topic_id, (int) $difference );
2194 }
2195
2196 /**
2197 * Bump the total hidden reply count of a topic
2198 *
2199 * @since bbPress (r3825)
2200 *
2201 * @param int $topic_id Optional. Forum id.
2202 * @param int $difference Optional. Default 1
2203 * @uses bbp_get_topic_id() To get the topic id
2204 * @uses update_post_meta() To update the topic's reply count meta
2205 * @uses apply_filters() Calls 'bbp_bump_topic_reply_count_hidden' with the
2206 * reply count, topic id, and difference
2207 * @return int Forum hidden reply count
2208 */
2209 function bbp_bump_topic_reply_count_hidden( $topic_id = 0, $difference = 1 ) {
2210
2211 // Get counts
2212 $topic_id = bbp_get_topic_id( $topic_id );
2213 $reply_count = bbp_get_topic_reply_count_hidden( $topic_id, false );
2214 $new_count = (int) $reply_count + (int) $difference;
2215
2216 // Update this topic id's hidder reply count
2217 update_post_meta( $topic_id, '_bbp_reply_count_hidden', (int) $new_count );
2218
2219 return (int) apply_filters( 'bbp_bump_topic_reply_count_hidden', (int) $new_count, $topic_id, (int) $difference );
2220 }
2221
2222 /** Topic Updaters ************************************************************/
2223
2224 /**
2225 * Update the topic's forum id
2226 *
2227 * @since bbPress (r2855)
2228 *
2229 * @param int $topic_id Optional. Topic id to update
2230 * @param int $forum_id Optional. Forum id
2231 * @uses bbp_is_reply() TO check if the passed topic id is a reply
2232 * @uses bbp_get_reply_topic_id() To get the reply topic id
2233 * @uses bbp_get_topic_id() To get the topic id
2234 * @uses get_post_field() To get the post parent of the topic id
2235 * @uses bbp_get_forum_id() To get the forum id
2236 * @uses update_post_meta() To update the topic forum id meta
2237 * @uses apply_filters() Calls 'bbp_update_topic_forum_id' with the forum id
2238 * and topic id
2239 * @return int Forum id
2240 */
2241 function bbp_update_topic_forum_id( $topic_id = 0, $forum_id = 0 ) {
2242
2243 // If it's a reply, then get the parent (topic id)
2244 if ( bbp_is_reply( $topic_id ) )
2245 $topic_id = bbp_get_reply_topic_id( $topic_id );
2246 else
2247 $topic_id = bbp_get_topic_id( $topic_id );
2248
2249 if ( empty( $forum_id ) )
2250 $forum_id = get_post_field( 'post_parent', $topic_id );
2251
2252 update_post_meta( $topic_id, '_bbp_forum_id', (int) $forum_id );
2253
2254 return apply_filters( 'bbp_update_topic_forum_id', (int) $forum_id, $topic_id );
2255 }
2256
2257 /**
2258 * Update the topic's topic id
2259 *
2260 * @since bbPress (r2954)
2261 *
2262 * @param int $topic_id Optional. Topic id to update
2263 * @uses bbp_get_topic_id() To get the topic id
2264 * @uses update_post_meta() To update the topic's topic id meta
2265 * @uses apply_filters() Calls 'bbp_update_topic_topic_id' with the topic id
2266 * @return int Topic id
2267 */
2268 function bbp_update_topic_topic_id( $topic_id = 0 ) {
2269 $topic_id = bbp_get_topic_id( $topic_id );
2270
2271 update_post_meta( $topic_id, '_bbp_topic_id', (int) $topic_id );
2272
2273 return apply_filters( 'bbp_update_topic_topic_id', (int) $topic_id );
2274 }
2275
2276 /**
2277 * Adjust the total reply count of a topic
2278 *
2279 * @since bbPress (r2467)
2280 *
2281 * @param int $topic_id Optional. Topic id to update
2282 * @param int $reply_count Optional. Set the reply count manually.
2283 * @uses bbp_is_reply() To check if the passed topic id is a reply
2284 * @uses bbp_get_reply_topic_id() To get the reply topic id
2285 * @uses bbp_get_topic_id() To get the topic id
2286 * @uses bbp_get_reply_post_type() To get the reply post type
2287 * @uses bbp_get_public_child_count() To get the reply count
2288 * @uses update_post_meta() To update the topic reply count meta
2289 * @uses apply_filters() Calls 'bbp_update_topic_reply_count' with the reply
2290 * count and topic id
2291 * @return int Topic reply count
2292 */
2293 function bbp_update_topic_reply_count( $topic_id = 0, $reply_count = 0 ) {
2294
2295 // If it's a reply, then get the parent (topic id)
2296 if ( bbp_is_reply( $topic_id ) )
2297 $topic_id = bbp_get_reply_topic_id( $topic_id );
2298 else
2299 $topic_id = bbp_get_topic_id( $topic_id );
2300
2301 // Get replies of topic if not passed
2302 if ( empty( $reply_count ) )
2303 $reply_count = bbp_get_public_child_count( $topic_id, bbp_get_reply_post_type() );
2304
2305 update_post_meta( $topic_id, '_bbp_reply_count', (int) $reply_count );
2306
2307 return apply_filters( 'bbp_update_topic_reply_count', (int) $reply_count, $topic_id );
2308 }
2309
2310 /**
2311 * Adjust the total hidden reply count of a topic (hidden includes trashed and spammed replies)
2312 *
2313 * @since bbPress (r2740)
2314 *
2315 * @param int $topic_id Optional. Topic id to update
2316 * @param int $reply_count Optional. Set the reply count manually
2317 * @uses bbp_is_reply() To check if the passed topic id is a reply
2318 * @uses bbp_get_reply_topic_id() To get the reply topic id
2319 * @uses bbp_get_topic_id() To get the topic id
2320 * @uses bbp_get_reply_post_type() To get the reply post type
2321 * @uses wpdb::prepare() To prepare our sql query
2322 * @uses wpdb::get_var() To execute our query and get the var back
2323 * @uses update_post_meta() To update the topic hidden reply count meta
2324 * @uses apply_filters() Calls 'bbp_update_topic_reply_count_hidden' with the
2325 * hidden reply count and topic id
2326 * @return int Topic hidden reply count
2327 */
2328 function bbp_update_topic_reply_count_hidden( $topic_id = 0, $reply_count = 0 ) {
2329 global $wpdb;
2330
2331 // If it's a reply, then get the parent (topic id)
2332 if ( bbp_is_reply( $topic_id ) )
2333 $topic_id = bbp_get_reply_topic_id( $topic_id );
2334 else
2335 $topic_id = bbp_get_topic_id( $topic_id );
2336
2337 // Get replies of topic
2338 if ( empty( $reply_count ) )
2339 $reply_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(ID) FROM {$wpdb->posts} WHERE post_parent = %d AND post_status IN ( '" . join( '\',\'', array( bbp_get_trash_status_id(), bbp_get_spam_status_id() ) ) . "') AND post_type = '%s';", $topic_id, bbp_get_reply_post_type() ) );
2340
2341 update_post_meta( $topic_id, '_bbp_reply_count_hidden', (int) $reply_count );
2342
2343 return apply_filters( 'bbp_update_topic_reply_count_hidden', (int) $reply_count, $topic_id );
2344 }
2345
2346 /**
2347 * Update the topic with the last active post ID
2348 *
2349 * @since bbPress (r2888)
2350 *
2351 * @param int $topic_id Optional. Topic id to update
2352 * @param int $active_id Optional. active id
2353 * @uses bbp_is_reply() To check if the passed topic id is a reply
2354 * @uses bbp_get_reply_topic_id() To get the reply topic id
2355 * @uses bbp_get_topic_id() To get the topic id
2356 * @uses bbp_get_reply_post_type() To get the reply post type
2357 * @uses bbp_get_public_child_last_id() To get the last public reply id
2358 * @uses bbp_get_active_id() To get the active id
2359 * @uses update_post_meta() To update the topic last active id meta
2360 * @uses apply_filters() Calls 'bbp_update_topic_last_active_id' with the active
2361 * id and topic id
2362 * @return int Active id
2363 */
2364 function bbp_update_topic_last_active_id( $topic_id = 0, $active_id = 0 ) {
2365
2366 // If it's a reply, then get the parent (topic id)
2367 if ( bbp_is_reply( $topic_id ) )
2368 $topic_id = bbp_get_reply_topic_id( $topic_id );
2369 else
2370 $topic_id = bbp_get_topic_id( $topic_id );
2371
2372 if ( empty( $active_id ) )
2373 $active_id = bbp_get_public_child_last_id( $topic_id, bbp_get_reply_post_type() );
2374
2375 // Adjust last_id's based on last_reply post_type
2376 if ( empty( $active_id ) || !bbp_is_reply( $active_id ) )
2377 $active_id = $topic_id;
2378
2379 // Update only if published
2380 if ( bbp_get_public_status_id() == get_post_status( $active_id ) )
2381 update_post_meta( $topic_id, '_bbp_last_active_id', (int) $active_id );
2382
2383 return apply_filters( 'bbp_update_topic_last_active_id', (int) $active_id, $topic_id );
2384 }
2385
2386 /**
2387 * Update the topics last active date/time (aka freshness)
2388 *
2389 * @since bbPress (r2680)
2390 *
2391 * @param int $topic_id Optional. Topic id
2392 * @param string $new_time Optional. New time in mysql format
2393 * @uses bbp_get_topic_id() To get the topic id
2394 * @uses bbp_get_reply_topic_id() To get the reply topic id
2395 * @uses current_time() To get the current time
2396 * @uses update_post_meta() To update the topic last active meta
2397 * @return bool True on success, false on failure
2398 */
2399 function bbp_update_topic_last_active_time( $topic_id = 0, $new_time = '' ) {
2400
2401 // If it's a reply, then get the parent (topic id)
2402 if ( bbp_is_reply( $topic_id ) )
2403 $topic_id = bbp_get_reply_topic_id( $topic_id );
2404 else
2405 $topic_id = bbp_get_topic_id( $topic_id );
2406
2407 // Check time and use current if empty
2408 if ( empty( $new_time ) )
2409 $new_time = get_post_field( 'post_date', bbp_get_public_child_last_id( $topic_id, bbp_get_reply_post_type() ) );
2410
2411 // Update only if published
2412 if ( !empty( $new_time ) )
2413 update_post_meta( $topic_id, '_bbp_last_active_time', $new_time );
2414
2415 return apply_filters( 'bbp_update_topic_last_active_time', $new_time, $topic_id );
2416 }
2417
2418 /**
2419 * Update the topic with the most recent reply ID
2420 *
2421 * @since bbPress (r2625)
2422 *
2423 * @param int $topic_id Optional. Topic id to update
2424 * @param int $reply_id Optional. Reply id
2425 * @uses bbp_is_reply() To check if the passed topic id is a reply
2426 * @uses bbp_get_reply_id() To get the reply id
2427 * @uses bbp_get_reply_topic_id() To get the reply topic id
2428 * @uses bbp_get_topic_id() To get the topic id
2429 * @uses bbp_get_reply_post_type() To get the reply post type
2430 * @uses bbp_get_public_child_last_id() To get the last public reply id
2431 * @uses update_post_meta() To update the topic last reply id meta
2432 * @uses apply_filters() Calls 'bbp_update_topic_last_reply_id' with the reply
2433 * id and topic id
2434 * @return int Reply id
2435 */
2436 function bbp_update_topic_last_reply_id( $topic_id = 0, $reply_id = 0 ) {
2437
2438 // If it's a reply, then get the parent (topic id)
2439 if ( empty( $reply_id ) && bbp_is_reply( $topic_id ) ) {
2440 $reply_id = bbp_get_reply_id( $topic_id );
2441 $topic_id = bbp_get_reply_topic_id( $reply_id );
2442 } else {
2443 $reply_id = bbp_get_reply_id( $reply_id );
2444 $topic_id = bbp_get_topic_id( $topic_id );
2445 }
2446
2447 if ( empty( $reply_id ) )
2448 $reply_id = bbp_get_public_child_last_id( $topic_id, bbp_get_reply_post_type() );
2449
2450 // Adjust last_id's based on last_reply post_type
2451 if ( empty( $reply_id ) || !bbp_is_reply( $reply_id ) )
2452 $reply_id = 0;
2453
2454 // Update if reply is published
2455 if ( bbp_is_reply_published( $reply_id ) )
2456 update_post_meta( $topic_id, '_bbp_last_reply_id', (int) $reply_id );
2457
2458 return apply_filters( 'bbp_update_topic_last_reply_id', (int) $reply_id, $topic_id );
2459 }
2460
2461 /**
2462 * Adjust the total voice count of a topic
2463 *
2464 * @since bbPress (r2567)
2465 *
2466 * @param int $topic_id Optional. Topic id to update
2467 * @uses bbp_is_reply() To check if the passed topic id is a reply
2468 * @uses bbp_get_reply_topic_id() To get the reply topic id
2469 * @uses bbp_get_topic_id() To get the topic id
2470 * @uses bbp_get_reply_topic_id() To get the reply topic id
2471 * @uses bbp_get_reply_post_type() To get the reply post type
2472 * @uses bbp_get_topic_post_type() To get the topic post type
2473 * @uses wpdb::prepare() To prepare our sql query
2474 * @uses wpdb::get_col() To execute our query and get the column back
2475 * @uses update_post_meta() To update the topic voice count meta
2476 * @uses apply_filters() Calls 'bbp_update_topic_voice_count' with the voice
2477 * count and topic id
2478 * @return int Voice count
2479 */
2480 function bbp_update_topic_voice_count( $topic_id = 0 ) {
2481 global $wpdb;
2482
2483 // If it's a reply, then get the parent (topic id)
2484 if ( bbp_is_reply( $topic_id ) )
2485 $topic_id = bbp_get_reply_topic_id( $topic_id );
2486 elseif ( bbp_is_topic( $topic_id ) )
2487 $topic_id = bbp_get_topic_id( $topic_id );
2488 else
2489 return;
2490
2491 // Query the DB to get voices in this topic
2492 $voices = $wpdb->get_col( $wpdb->prepare( "SELECT COUNT( DISTINCT post_author ) FROM {$wpdb->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() ) );
2493
2494 // If there's an error, make sure we have at least have 1 voice
2495 $voices = ( empty( $voices ) || is_wp_error( $voices ) ) ? 1 : $voices[0];
2496
2497 // Update the voice count for this topic id
2498 update_post_meta( $topic_id, '_bbp_voice_count', (int) $voices );
2499
2500 return apply_filters( 'bbp_update_topic_voice_count', (int) $voices, $topic_id );
2501 }
2502
2503 /**
2504 * Adjust the total anonymous reply count of a topic
2505 *
2506 * @since bbPress (r2567)
2507 *
2508 * @param int $topic_id Optional. Topic id to update
2509 * @uses bbp_is_reply() To check if the passed topic id is a reply
2510 * @uses bbp_get_reply_topic_id() To get the reply topic id
2511 * @uses bbp_get_topic_id() To get the topic id
2512 * @uses bbp_get_reply_topic_id() To get the reply topic id
2513 * @uses bbp_get_reply_post_type() To get the reply post type
2514 * @uses bbp_get_topic_post_type() To get the topic post type
2515 * @uses wpdb::prepare() To prepare our sql query
2516 * @uses wpdb::get_col() To execute our query and get the column back
2517 * @uses update_post_meta() To update the topic anonymous reply count meta
2518 * @uses apply_filters() Calls 'bbp_update_topic_anonymous_reply_count' with the
2519 * anonymous reply count and topic id
2520 * @return int Anonymous reply count
2521 */
2522 function bbp_update_topic_anonymous_reply_count( $topic_id = 0 ) {
2523 global $wpdb;
2524
2525 // If it's a reply, then get the parent (topic id)
2526 if ( bbp_is_reply( $topic_id ) )
2527 $topic_id = bbp_get_reply_topic_id( $topic_id );
2528 elseif ( bbp_is_topic( $topic_id ) )
2529 $topic_id = bbp_get_topic_id( $topic_id );
2530 else
2531 return;
2532
2533 $anonymous_replies = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT( ID ) FROM {$wpdb->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() ) );
2534
2535 update_post_meta( $topic_id, '_bbp_anonymous_reply_count', (int) $anonymous_replies );
2536
2537 return apply_filters( 'bbp_update_topic_anonymous_reply_count', (int) $anonymous_replies, $topic_id );
2538 }
2539
2540 /**
2541 * Update the revision log of the topic
2542 *
2543 * @since bbPress (r2782)
2544 *
2545 * @param mixed $args Supports these args:
2546 * - topic_id: Topic id
2547 * - author_id: Author id
2548 * - reason: Reason for editing
2549 * - revision_id: Revision id
2550 * @uses bbp_get_topic_id() To get the topic id
2551 * @uses bbp_get_user_id() To get the user id
2552 * @uses bbp_format_revision_reason() To format the reason
2553 * @uses bbp_get_topic_raw_revision_log() To get the raw topic revision log
2554 * @uses update_post_meta() To update the topic revision log meta
2555 * @return mixed False on failure, true on success
2556 */
2557 function bbp_update_topic_revision_log( $args = '' ) {
2558 $defaults = array (
2559 'reason' => '',
2560 'topic_id' => 0,
2561 'author_id' => 0,
2562 'revision_id' => 0
2563 );
2564 $r = bbp_parse_args( $args, $defaults, 'update_topic_revision_log' );
2565 extract( $r );
2566
2567 // Populate the variables
2568 $reason = bbp_format_revision_reason( $reason );
2569 $topic_id = bbp_get_topic_id( $topic_id );
2570 $author_id = bbp_get_user_id ( $author_id, false, true );
2571 $revision_id = (int) $revision_id;
2572
2573 // Get the logs and append the new one to those
2574 $revision_log = bbp_get_topic_raw_revision_log( $topic_id );
2575 $revision_log[$revision_id] = array( 'author' => $author_id, 'reason' => $reason );
2576
2577 // Finally, update
2578 return update_post_meta( $topic_id, '_bbp_revision_log', $revision_log );
2579 }
2580
2581 /** Topic Actions *************************************************************/
2582
2583 /**
2584 * Closes a topic
2585 *
2586 * @since bbPress (r2740)
2587 *
2588 * @param int $topic_id Topic id
2589 * @uses get_post() To get the topic
2590 * @uses do_action() Calls 'bbp_close_topic' with the topic id
2591 * @uses add_post_meta() To add the previous status to a meta
2592 * @uses wp_insert_post() To update the topic with the new status
2593 * @uses do_action() Calls 'bbp_opened_topic' with the topic id
2594 * @return mixed False or {@link WP_Error} on failure, topic id on success
2595 */
2596 function bbp_close_topic( $topic_id = 0 ) {
2597
2598 // Get topic
2599 if ( !$topic = get_post( $topic_id, ARRAY_A ) )
2600 return $topic;
2601
2602 // Bail if already closed
2603 if ( bbp_get_closed_status_id() == $topic['post_status'] )
2604 return false;
2605
2606 // Execute pre close code
2607 do_action( 'bbp_close_topic', $topic_id );
2608
2609 // Add pre close status
2610 add_post_meta( $topic_id, '_bbp_status', $topic['post_status'] );
2611
2612 // Set closed status
2613 $topic['post_status'] = bbp_get_closed_status_id();
2614
2615 // No revisions
2616 remove_action( 'pre_post_update', 'wp_save_post_revision' );
2617
2618 // Update topic
2619 $topic_id = wp_insert_post( $topic );
2620
2621 // Execute post close code
2622 do_action( 'bbp_closed_topic', $topic_id );
2623
2624 // Return topic_id
2625 return $topic_id;
2626 }
2627
2628 /**
2629 * Opens a topic
2630 *
2631 * @since bbPress (r2740)
2632 *
2633 * @param int $topic_id Topic id
2634 * @uses get_post() To get the topic
2635 * @uses do_action() Calls 'bbp_open_topic' with the topic id
2636 * @uses get_post_meta() To get the previous status
2637 * @uses delete_post_meta() To delete the previous status meta
2638 * @uses wp_insert_post() To update the topic with the new status
2639 * @uses do_action() Calls 'bbp_opened_topic' with the topic id
2640 * @return mixed False or {@link WP_Error} on failure, topic id on success
2641 */
2642 function bbp_open_topic( $topic_id = 0 ) {
2643
2644 // Get topic
2645 if ( !$topic = get_post( $topic_id, ARRAY_A ) )
2646 return $topic;
2647
2648 // Bail if already open
2649 if ( bbp_get_closed_status_id() != $topic['post_status'])
2650 return false;
2651
2652 // Execute pre open code
2653 do_action( 'bbp_open_topic', $topic_id );
2654
2655 // Get previous status
2656 $topic_status = get_post_meta( $topic_id, '_bbp_status', true );
2657
2658 // Set previous status
2659 $topic['post_status'] = $topic_status;
2660
2661 // Remove old status meta
2662 delete_post_meta( $topic_id, '_bbp_status' );
2663
2664 // No revisions
2665 remove_action( 'pre_post_update', 'wp_save_post_revision' );
2666
2667 // Update topic
2668 $topic_id = wp_insert_post( $topic );
2669
2670 // Execute post open code
2671 do_action( 'bbp_opened_topic', $topic_id );
2672
2673 // Return topic_id
2674 return $topic_id;
2675 }
2676
2677 /**
2678 * Marks a topic as spam
2679 *
2680 * @since bbPress (r2740)
2681 *
2682 * @param int $topic_id Topic id
2683 * @uses get_post() To get the topic
2684 * @uses do_action() Calls 'bbp_spam_topic' with the topic id
2685 * @uses add_post_meta() To add the previous status to a meta
2686 * @uses wp_insert_post() To update the topic with the new status
2687 * @uses do_action() Calls 'bbp_spammed_topic' with the topic id
2688 * @return mixed False or {@link WP_Error} on failure, topic id on success
2689 */
2690 function bbp_spam_topic( $topic_id = 0 ) {
2691
2692 // Get the topic
2693 if ( !$topic = get_post( $topic_id, ARRAY_A ) )
2694 return $topic;
2695
2696 // Bail if topic is spam
2697 if ( bbp_get_spam_status_id() == $topic['post_status'] )
2698 return false;
2699
2700 // Execute pre spam code
2701 do_action( 'bbp_spam_topic', $topic_id );
2702
2703 // Add the original post status as post meta for future restoration
2704 add_post_meta( $topic_id, '_bbp_spam_meta_status', $topic['post_status'] );
2705
2706 // Get topic tags
2707 $terms = get_the_terms( $topic_id, bbp_get_topic_tag_tax_id() );
2708
2709 // Define local variable(s)
2710 $term_names = array();
2711
2712 // Topic has tags
2713 if ( !empty( $terms ) ) {
2714
2715 // Loop through and collect term names
2716 foreach( $terms as $term ) {
2717 $term_names[] = $term->name;
2718 }
2719
2720 // Topic terms have slugs
2721 if ( !empty( $term_names ) ) {
2722
2723 // Add the original post status as post meta for future restoration
2724 add_post_meta( $topic_id, '_bbp_spam_topic_tags', $term_names );
2725
2726 // Empty the topic of its tags
2727 $topic['tax_input'] = array( bbp_get_topic_tag_tax_id() => '' );
2728 }
2729 }
2730
2731 // Set post status to spam
2732 $topic['post_status'] = bbp_get_spam_status_id();
2733
2734 // No revisions
2735 remove_action( 'pre_post_update', 'wp_save_post_revision' );
2736
2737 // Update the topic
2738 $topic_id = wp_insert_post( $topic );
2739
2740 // Execute post spam code
2741 do_action( 'bbp_spammed_topic', $topic_id );
2742
2743 // Return topic_id
2744 return $topic_id;
2745 }
2746
2747 /**
2748 * Unspams a topic
2749 *
2750 * @since bbPress (r2740)
2751 *
2752 * @param int $topic_id Topic id
2753 * @uses get_post() To get the topic
2754 * @uses do_action() Calls 'bbp_unspam_topic' with the topic id
2755 * @uses get_post_meta() To get the previous status
2756 * @uses delete_post_meta() To delete the previous status meta
2757 * @uses wp_insert_post() To update the topic with the new status
2758 * @uses do_action() Calls 'bbp_unspammed_topic' with the topic id
2759 * @return mixed False or {@link WP_Error} on failure, topic id on success
2760 */
2761 function bbp_unspam_topic( $topic_id = 0 ) {
2762
2763 // Get the topic
2764 if ( !$topic = get_post( $topic_id, ARRAY_A ) )
2765 return $topic;
2766
2767 // Bail if already not spam
2768 if ( bbp_get_spam_status_id() != $topic['post_status'] )
2769 return false;
2770
2771 // Execute pre unspam code
2772 do_action( 'bbp_unspam_topic', $topic_id );
2773
2774 // Get pre spam status
2775 $topic_status = get_post_meta( $topic_id, '_bbp_spam_meta_status', true );
2776
2777 // Set post status to pre spam
2778 $topic['post_status'] = $topic_status;
2779
2780 // Delete pre spam meta
2781 delete_post_meta( $topic_id, '_bbp_spam_meta_status' );
2782
2783 // No revisions
2784 remove_action( 'pre_post_update', 'wp_save_post_revision' );
2785
2786 // Get pre-spam topic tags
2787 $terms = get_post_meta( $topic_id, '_bbp_spam_topic_tags', true );
2788
2789 // Topic had tags before it was spammed
2790 if ( !empty( $terms ) ) {
2791
2792 // Set the tax_input of the topic
2793 $topic['tax_input'] = array( bbp_get_topic_tag_tax_id() => $terms );
2794
2795 // Delete pre-spam topic tag meta
2796 delete_post_meta( $topic_id, '_bbp_spam_topic_tags' );
2797 }
2798
2799 // Update the topic
2800 $topic_id = wp_insert_post( $topic );
2801
2802 // Execute post unspam code
2803 do_action( 'bbp_unspammed_topic', $topic_id );
2804
2805 // Return topic_id
2806 return $topic_id;
2807 }
2808
2809 /**
2810 * Sticks a topic to a forum or front
2811 *
2812 * @since bbPress (r2754)
2813 *
2814 * @param int $topic_id Optional. Topic id
2815 * @param int $super Should we make the topic a super sticky?
2816 * @uses bbp_get_topic_id() To get the topic id
2817 * @uses bbp_unstick_topic() To unstick the topic
2818 * @uses bbp_get_topic_forum_id() To get the topic forum id
2819 * @uses bbp_get_stickies() To get the stickies
2820 * @uses do_action() 'bbp_stick_topic' with topic id and bool super
2821 * @uses update_option() To update the super stickies option
2822 * @uses update_post_meta() To update the forum stickies meta
2823 * @uses do_action() Calls 'bbp_sticked_topic' with the topic id, bool super
2824 * and success
2825 * @return bool True on success, false on failure
2826 */
2827 function bbp_stick_topic( $topic_id = 0, $super = false ) {
2828 $topic_id = bbp_get_topic_id( $topic_id );
2829
2830 // Bail if a topic is not a topic (prevents revisions as stickies)
2831 if ( ! bbp_is_topic( $topic_id ) )
2832 return false;
2833
2834 // We may have a super sticky to which we want to convert into a normal
2835 // sticky and vice versa; unstick the topic first to avoid any possible error.
2836 bbp_unstick_topic( $topic_id );
2837
2838 $forum_id = empty( $super ) ? bbp_get_topic_forum_id( $topic_id ) : 0;
2839 $stickies = bbp_get_stickies( $forum_id );
2840
2841 do_action( 'bbp_stick_topic', $topic_id, $super );
2842
2843 if ( !is_array( $stickies ) ) {
2844 $stickies = array( $topic_id );
2845 } else {
2846 $stickies[] = $topic_id;
2847 }
2848
2849 // Pull out duplicates and empties
2850 $stickies = array_unique( array_filter( $stickies ) );
2851
2852 // Unset incorrectly stuck revisions
2853 foreach ( (array) $stickies as $key => $id ) {
2854 if ( ! bbp_is_topic( $id ) ) {
2855 unset( $stickies[$key] );
2856 }
2857 }
2858
2859 // Reset keys
2860 $stickies = array_values( $stickies );
2861 $success = !empty( $super ) ? update_option( '_bbp_super_sticky_topics', $stickies ) : update_post_meta( $forum_id, '_bbp_sticky_topics', $stickies );
2862
2863 do_action( 'bbp_sticked_topic', $topic_id, $super, $success );
2864
2865 return (bool) $success;
2866 }
2867
2868 /**
2869 * Unsticks a topic both from front and it's forum
2870 *
2871 * @since bbPress (r2754)
2872 *
2873 * @param int $topic_id Optional. Topic id
2874 * @uses bbp_get_topic_id() To get the topic id
2875 * @uses bbp_is_topic_super_sticky() To check if the topic is a super sticky
2876 * @uses bbp_get_topic_forum_id() To get the topic forum id
2877 * @uses bbp_get_stickies() To get the forum stickies
2878 * @uses do_action() Calls 'bbp_unstick_topic' with the topic id
2879 * @uses delete_option() To delete the super stickies option
2880 * @uses update_option() To update the super stickies option
2881 * @uses delete_post_meta() To delete the forum stickies meta
2882 * @uses update_post_meta() To update the forum stickies meta
2883 * @uses do_action() Calls 'bbp_unsticked_topic' with the topic id and success
2884 * @return bool Always true.
2885 */
2886 function bbp_unstick_topic( $topic_id = 0 ) {
2887 $topic_id = bbp_get_topic_id( $topic_id );
2888 $super = bbp_is_topic_super_sticky( $topic_id );
2889 $forum_id = empty( $super ) ? bbp_get_topic_forum_id( $topic_id ) : 0;
2890 $stickies = bbp_get_stickies( $forum_id );
2891 $offset = array_search( $topic_id, $stickies );
2892
2893 do_action( 'bbp_unstick_topic', $topic_id );
2894
2895 if ( empty( $stickies ) ) {
2896 $success = true;
2897 } elseif ( !in_array( $topic_id, $stickies ) ) {
2898 $success = true;
2899 } elseif ( false === $offset ) {
2900 $success = true;
2901 } else {
2902 array_splice( $stickies, $offset, 1 );
2903 if ( empty( $stickies ) ) {
2904 $success = !empty( $super ) ? delete_option( '_bbp_super_sticky_topics' ) : delete_post_meta( $forum_id, '_bbp_sticky_topics' );
2905 } else {
2906 $success = !empty( $super ) ? update_option( '_bbp_super_sticky_topics', $stickies ) : update_post_meta( $forum_id, '_bbp_sticky_topics', $stickies );
2907 }
2908 }
2909
2910 do_action( 'bbp_unsticked_topic', $topic_id, $success );
2911
2912 return (bool) $success;
2913 }
2914
2915 /** Before Delete/Trash/Untrash ***********************************************/
2916
2917 /**
2918 * Called before deleting a topic.
2919 *
2920 * This function is supplemental to the actual topic deletion which is
2921 * handled by WordPress core API functions. It is used to clean up after
2922 * a topic that is being deleted.
2923 *
2924 * @uses bbp_get_topic_id() To get the topic id
2925 * @uses bbp_is_topic() To check if the passed id is a topic
2926 * @uses do_action() Calls 'bbp_delete_topic' with the topic id
2927 * @uses bbp_has_replies() To check if the topic has replies
2928 * @uses bbp_replies() To loop through the replies
2929 * @uses bbp_the_reply() To set a reply as the current reply in the loop
2930 * @uses bbp_get_reply_id() To get the reply id
2931 * @uses wp_delete_post() To delete the reply
2932 */
2933 function bbp_delete_topic( $topic_id = 0 ) {
2934
2935 // Validate topic ID
2936 $topic_id = bbp_get_topic_id( $topic_id );
2937
2938 if ( empty( $topic_id ) || !bbp_is_topic( $topic_id ) )
2939 return false;
2940
2941 do_action( 'bbp_delete_topic', $topic_id );
2942
2943 // Topic is being permanently deleted, so its replies gotta go too
2944 if ( $replies = new WP_Query( array(
2945 'suppress_filters' => true,
2946 'post_type' => bbp_get_reply_post_type(),
2947 'post_status' => 'any',
2948 'post_parent' => $topic_id,
2949 'posts_per_page' => -1,
2950 'nopaging' => true,
2951 'fields' => 'id=>parent'
2952 ) ) ) {
2953 foreach ( $replies->posts as $reply ) {
2954 wp_delete_post( $reply->ID, true );
2955 }
2956
2957 // Reset the $post global
2958 wp_reset_postdata();
2959 }
2960 }
2961
2962 /**
2963 * Called before trashing a topic
2964 *
2965 * This function is supplemental to the actual topic being trashed which is
2966 * handled by WordPress core API functions. It is used to clean up after
2967 * a topic that is being trashed.
2968 *
2969 * @uses bbp_get_topic_id() To get the topic id
2970 * @uses bbp_is_topic() To check if the passed id is a topic
2971 * @uses do_action() Calls 'bbp_trash_topic' with the topic id
2972 * @uses wp_trash_post() To trash the reply
2973 * @uses update_post_meta() To save a list of just trashed replies for future use
2974 */
2975 function bbp_trash_topic( $topic_id = 0 ) {
2976
2977 // Validate topic ID
2978 $topic_id = bbp_get_topic_id( $topic_id );
2979
2980 if ( empty( $topic_id ) || !bbp_is_topic( $topic_id ) )
2981 return false;
2982
2983 do_action( 'bbp_trash_topic', $topic_id );
2984
2985 // Topic is being trashed, so its replies are trashed too
2986 if ( $replies = new WP_Query( array(
2987 'suppress_filters' => true,
2988 'post_type' => bbp_get_reply_post_type(),
2989 'post_status' => bbp_get_public_status_id(),
2990 'post_parent' => $topic_id,
2991 'posts_per_page' => -1,
2992 'nopaging' => true,
2993 'fields' => 'id=>parent'
2994 ) ) ) {
2995
2996 // Prevent debug notices
2997 $pre_trashed_replies = array();
2998
2999 // Loop through replies, trash them, and add them to array
3000 foreach ( $replies->posts as $reply ) {
3001 wp_trash_post( $reply->ID );
3002 $pre_trashed_replies[] = $reply->ID;
3003 }
3004
3005 // Set a post_meta entry of the replies that were trashed by this action.
3006 // This is so we can possibly untrash them, without untrashing replies
3007 // that were purposefully trashed before.
3008 update_post_meta( $topic_id, '_bbp_pre_trashed_replies', $pre_trashed_replies );
3009
3010 // Reset the $post global
3011 wp_reset_postdata();
3012 }
3013 }
3014
3015 /**
3016 * Called before untrashing a topic
3017 *
3018 * @uses bbp_get_topic_id() To get the topic id
3019 * @uses bbp_is_topic() To check if the passed id is a topic
3020 * @uses do_action() Calls 'bbp_untrash_topic' with the topic id
3021 * @uses get_post_meta() To get the list of replies which were trashed with the
3022 * topic
3023 * @uses wp_untrash_post() To untrash the reply
3024 */
3025 function bbp_untrash_topic( $topic_id = 0 ) {
3026 $topic_id = bbp_get_topic_id( $topic_id );
3027
3028 if ( empty( $topic_id ) || !bbp_is_topic( $topic_id ) )
3029 return false;
3030
3031 do_action( 'bbp_untrash_topic', $topic_id );
3032
3033 // Get the replies that were not previously trashed
3034 $pre_trashed_replies = get_post_meta( $topic_id, '_bbp_pre_trashed_replies', true );
3035
3036 // There are replies to untrash
3037 if ( !empty( $pre_trashed_replies ) ) {
3038
3039 // Maybe reverse the trashed replies array
3040 if ( is_array( $pre_trashed_replies ) )
3041 $pre_trashed_replies = array_reverse( $pre_trashed_replies );
3042
3043 // Loop through replies
3044 foreach ( (array) $pre_trashed_replies as $reply ) {
3045 wp_untrash_post( $reply );
3046 }
3047 }
3048 }
3049
3050 /** After Delete/Trash/Untrash ************************************************/
3051
3052 /**
3053 * Called after deleting a topic
3054 *
3055 * @uses bbp_get_topic_id() To get the topic id
3056 * @uses bbp_is_topic() To check if the passed id is a topic
3057 * @uses do_action() Calls 'bbp_deleted_topic' with the topic id
3058 */
3059 function bbp_deleted_topic( $topic_id = 0 ) {
3060 $topic_id = bbp_get_topic_id( $topic_id );
3061
3062 if ( empty( $topic_id ) || !bbp_is_topic( $topic_id ) )
3063 return false;
3064
3065 do_action( 'bbp_deleted_topic', $topic_id );
3066 }
3067
3068 /**
3069 * Called after trashing a topic
3070 *
3071 * @uses bbp_get_topic_id() To get the topic id
3072 * @uses bbp_is_topic() To check if the passed id is a topic
3073 * @uses do_action() Calls 'bbp_trashed_topic' with the topic id
3074 */
3075 function bbp_trashed_topic( $topic_id = 0 ) {
3076 $topic_id = bbp_get_topic_id( $topic_id );
3077
3078 if ( empty( $topic_id ) || !bbp_is_topic( $topic_id ) )
3079 return false;
3080
3081 do_action( 'bbp_trashed_topic', $topic_id );
3082 }
3083
3084 /**
3085 * Called after untrashing a topic
3086 *
3087 * @uses bbp_get_topic_id() To get the topic id
3088 * @uses bbp_is_topic() To check if the passed id is a topic
3089 * @uses do_action() Calls 'bbp_untrashed_topic' with the topic id
3090 */
3091 function bbp_untrashed_topic( $topic_id = 0 ) {
3092 $topic_id = bbp_get_topic_id( $topic_id );
3093
3094 if ( empty( $topic_id ) || !bbp_is_topic( $topic_id ) )
3095 return false;
3096
3097 do_action( 'bbp_untrashed_topic', $topic_id );
3098 }
3099
3100 /** Settings ******************************************************************/
3101
3102 /**
3103 * Return the topics per page setting
3104 *
3105 * @since bbPress (r3540)
3106 *
3107 * @param int $default Default replies per page (15)
3108 * @uses get_option() To get the setting
3109 * @uses apply_filters() To allow the return value to be manipulated
3110 * @return int
3111 */
3112 function bbp_get_topics_per_page( $default = 15 ) {
3113
3114 // Get database option and cast as integer
3115 $retval = get_option( '_bbp_topics_per_page', $default );
3116
3117 // If return val is empty, set it to default
3118 if ( empty( $retval ) )
3119 $retval = $default;
3120
3121 // Filter and return
3122 return (int) apply_filters( 'bbp_get_topics_per_page', $retval, $default );
3123 }
3124
3125 /**
3126 * Return the topics per RSS page setting
3127 *
3128 * @since bbPress (r3540)
3129 *
3130 * @param int $default Default replies per page (25)
3131 * @uses get_option() To get the setting
3132 * @uses apply_filters() To allow the return value to be manipulated
3133 * @return int
3134 */
3135 function bbp_get_topics_per_rss_page( $default = 25 ) {
3136
3137 // Get database option and cast as integer
3138 $retval = get_option( '_bbp_topics_per_rss_page', $default );
3139
3140 // If return val is empty, set it to default
3141 if ( empty( $retval ) )
3142 $retval = $default;
3143
3144 // Filter and return
3145 return (int) apply_filters( 'bbp_get_topics_per_rss_page', $retval, $default );
3146 }
3147
3148 /** Topic Tags ****************************************************************/
3149
3150 /**
3151 * Get topic tags for a specific topic ID
3152 *
3153 * @since bbPress (r4165)
3154 *
3155 * @param int $topic_id
3156 * @param string $sep
3157 * @return string
3158 */
3159 function bbp_get_topic_tag_names( $topic_id = 0, $sep = ', ' ) {
3160 $topic_id = bbp_get_topic_id( $topic_id );
3161 $topic_tags = array_filter( (array) get_the_terms( $topic_id, bbp_get_topic_tag_tax_id() ) );
3162 $terms = array();
3163 foreach( $topic_tags as $term ) {
3164 $terms[] = $term->name;
3165 }
3166 $terms = !empty( $terms ) ? implode( $sep, $terms ) : '';
3167
3168 return apply_filters( 'bbp_get_topic_tags', $terms, $topic_id );
3169 }
3170
3171 /** Autoembed *****************************************************************/
3172
3173 /**
3174 * Check if autoembeds are enabled and hook them in if so
3175 *
3176 * @since bbPress (r3752)
3177 * @global WP_Embed $wp_embed
3178 */
3179 function bbp_topic_content_autoembed() {
3180 global $wp_embed;
3181
3182 if ( bbp_use_autoembed() && is_a( $wp_embed, 'WP_Embed' ) ) {
3183 add_filter( 'bbp_get_topic_content', array( $wp_embed, 'autoembed' ), 8 );
3184 }
3185 }
3186
3187 /** Feeds *********************************************************************/
3188
3189 /**
3190 * Output an RSS2 feed of topics, based on the query passed.
3191 *
3192 * @since bbPress (r3171)
3193 *
3194 * @uses bbp_version()
3195 * @uses bbp_is_single_topic()
3196 * @uses bbp_user_can_view_forum()
3197 * @uses bbp_get_topic_forum_id()
3198 * @uses bbp_show_load_topic()
3199 * @uses bbp_topic_permalink()
3200 * @uses bbp_topic_title()
3201 * @uses bbp_get_topic_reply_count()
3202 * @uses bbp_topic_content()
3203 * @uses bbp_has_topics()
3204 * @uses bbp_topics()
3205 * @uses bbp_the_topic()
3206 * @uses get_wp_title_rss()
3207 * @uses get_option()
3208 * @uses bloginfo_rss
3209 * @uses self_link()
3210 * @uses the_author()
3211 * @uses get_post_time()
3212 * @uses rss_enclosure()
3213 * @uses do_action()
3214 * @uses apply_filters()
3215 *
3216 * @param array $topics_query
3217 */
3218 function bbp_display_topics_feed_rss2( $topics_query = array() ) {
3219
3220 // User cannot access this forum
3221 if ( bbp_is_single_forum() && !bbp_user_can_view_forum( array( 'forum_id' => bbp_get_forum_id() ) ) )
3222 return;
3223
3224 // Display the feed
3225 header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), true );
3226 header( 'Status: 200 OK' );
3227 echo '<?xml version="1.0" encoding="' . get_option( 'blog_charset' ) . '"?' . '>'; ?>
3228
3229 <rss version="2.0"
3230 xmlns:content="http://purl.org/rss/1.0/modules/content/"
3231 xmlns:wfw="http://wellformedweb.org/CommentAPI/"
3232 xmlns:dc="http://purl.org/dc/elements/1.1/"
3233 xmlns:atom="http://www.w3.org/2005/Atom"
3234
3235 <?php do_action( 'bbp_feed' ); ?>
3236 >
3237
3238 <channel>
3239
3240 <title><?php bloginfo_rss( 'name' ); ?> &#187; <?php _e( 'All Topics', 'bbpress' ); ?></title>
3241 <atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
3242 <link><?php self_link(); ?></link>
3243 <description><?php //?></description>
3244 <pubDate><?php echo mysql2date( 'D, d M Y H:i:s O', current_time( 'mysql' ), false ); ?></pubDate>
3245 <generator>http://bbpress.org/?v=<?php bbp_version(); ?></generator>
3246 <language><?php echo get_option( 'rss_language' ); ?></language>
3247
3248 <?php do_action( 'bbp_feed_head' ); ?>
3249
3250 <?php if ( bbp_has_topics( $topics_query ) ) : ?>
3251
3252 <?php while ( bbp_topics() ) : bbp_the_topic(); ?>
3253
3254 <item>
3255 <guid><?php bbp_topic_permalink(); ?></guid>
3256 <title><![CDATA[<?php bbp_topic_title(); ?>]]></title>
3257 <link><?php bbp_topic_permalink(); ?></link>
3258 <pubDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_post_meta( bbp_get_topic_id(), '_bbp_last_active_time', true ) ); ?></pubDate>
3259 <dc:creator><?php the_author() ?></dc:creator>
3260
3261 <?php if ( !post_password_required() ) : ?>
3262
3263 <description>
3264 <![CDATA[
3265 <p><?php printf( __( 'Replies: %s', 'bbpress' ), bbp_get_topic_reply_count() ); ?></p>
3266 <?php bbp_topic_content(); ?>
3267 ]]>
3268 </description>
3269
3270 <?php rss_enclosure(); ?>
3271
3272 <?php endif; ?>
3273
3274 <?php do_action( 'bbp_feed_item' ); ?>
3275
3276 </item>
3277
3278 <?php endwhile; ?>
3279 <?php endif; ?>
3280
3281 <?php do_action( 'bbp_feed_footer' ); ?>
3282
3283 </channel>
3284 </rss>
3285
3286 <?php
3287 exit();
3288 }
3289
3290 /** Permissions ***************************************************************/
3291
3292 /**
3293 * Redirect if unathorized user is attempting to edit a topic
3294 *
3295 * @since bbPress (r3605)
3296 *
3297 * @uses bbp_is_topic_edit()
3298 * @uses current_user_can()
3299 * @uses bbp_get_topic_id()
3300 * @uses wp_safe_redirect()
3301 * @uses bbp_get_topic_permalink()
3302 */
3303 function bbp_check_topic_edit() {
3304
3305 // Bail if not editing a topic
3306 if ( !bbp_is_topic_edit() )
3307 return;
3308
3309 // User cannot edit topic, so redirect back to topic
3310 if ( !current_user_can( 'edit_topic', bbp_get_topic_id() ) ) {
3311 wp_safe_redirect( bbp_get_topic_permalink() );
3312 exit();
3313 }
3314 }
3315
3316 /**
3317 * Redirect if unathorized user is attempting to edit a topic tag
3318 *
3319 * @since bbPress (r3605)
3320 *
3321 * @uses bbp_is_topic_tag_edit()
3322 * @uses current_user_can()
3323 * @uses bbp_get_topic_tag_id()
3324 * @uses wp_safe_redirect()
3325 * @uses bbp_get_topic_tag_link()
3326 */
3327 function bbp_check_topic_tag_edit() {
3328
3329 // Bail if not editing a topic tag
3330 if ( !bbp_is_topic_tag_edit() )
3331 return;
3332
3333 // Bail if current user cannot edit topic tags
3334 if ( !current_user_can( 'edit_topic_tags', bbp_get_topic_tag_id() ) ) {
3335 wp_safe_redirect( bbp_get_topic_tag_link() );
3336 exit();
3337 }
3338 }
3339