/includes/topics/functions.php

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