/wp-content/plugins/bbpress/includes/forums/functions.php

https://bitbucket.org/Thane2376/death-edge.ru · PHP · 2352 lines · 920 code · 444 blank · 988 comment · 189 complexity · 037fa58009bc272c0840f0fbfbfd8634 MD5 · raw file

  1. <?php
  2. /**
  3. * bbPress Forum Functions
  4. *
  5. * @package bbPress
  6. * @subpackage Functions
  7. */
  8. // Exit if accessed directly
  9. if ( !defined( 'ABSPATH' ) ) exit;
  10. /** Insert ********************************************************************/
  11. /**
  12. * A wrapper for wp_insert_post() that also includes the necessary meta values
  13. * for the forum to function properly.
  14. *
  15. * @since bbPress (r3349)
  16. *
  17. * @uses bbp_parse_args()
  18. * @uses bbp_get_forum_post_type()
  19. * @uses wp_insert_post()
  20. * @uses update_post_meta()
  21. *
  22. * @param array $forum_data Forum post data
  23. * @param arrap $forum_meta Forum meta data
  24. */
  25. function bbp_insert_forum( $forum_data = array(), $forum_meta = array() ) {
  26. // Forum
  27. $forum_data = bbp_parse_args( $forum_data, array(
  28. 'post_parent' => 0, // forum ID
  29. 'post_status' => bbp_get_public_status_id(),
  30. 'post_type' => bbp_get_forum_post_type(),
  31. 'post_author' => bbp_get_current_user_id(),
  32. 'post_password' => '',
  33. 'post_content' => '',
  34. 'post_title' => '',
  35. 'menu_order' => 0,
  36. 'comment_status' => 'closed'
  37. ), 'insert_forum' );
  38. // Insert forum
  39. $forum_id = wp_insert_post( $forum_data );
  40. // Bail if no forum was added
  41. if ( empty( $forum_id ) ) {
  42. return false;
  43. }
  44. // Forum meta
  45. $forum_meta = bbp_parse_args( $forum_meta, array(
  46. 'reply_count' => 0,
  47. 'topic_count' => 0,
  48. 'topic_count_hidden' => 0,
  49. 'total_reply_count' => 0,
  50. 'total_topic_count' => 0,
  51. 'last_topic_id' => 0,
  52. 'last_reply_id' => 0,
  53. 'last_active_id' => 0,
  54. 'last_active_time' => 0,
  55. 'forum_subforum_count' => 0,
  56. ), 'insert_forum_meta' );
  57. // Insert forum meta
  58. foreach ( $forum_meta as $meta_key => $meta_value ) {
  59. update_post_meta( $forum_id, '_bbp_' . $meta_key, $meta_value );
  60. }
  61. // Return new forum ID
  62. return $forum_id;
  63. }
  64. /** Post Form Handlers ********************************************************/
  65. /**
  66. * Handles the front end forum submission
  67. *
  68. * @param string $action The requested action to compare this function to
  69. * @uses bbp_add_error() To add an error message
  70. * @uses bbp_verify_nonce_request() To verify the nonce and check the request
  71. * @uses bbp_is_anonymous() To check if an anonymous post is being made
  72. * @uses current_user_can() To check if the current user can publish forum
  73. * @uses bbp_get_current_user_id() To get the current user id
  74. * @uses bbp_filter_anonymous_post_data() To filter anonymous data
  75. * @uses bbp_set_current_anonymous_user_data() To set the anonymous user cookies
  76. * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error}
  77. * @uses esc_attr() For sanitization
  78. * @uses bbp_is_forum_category() To check if the forum is a category
  79. * @uses bbp_is_forum_closed() To check if the forum is closed
  80. * @uses bbp_is_forum_private() To check if the forum is private
  81. * @uses bbp_check_for_flood() To check for flooding
  82. * @uses bbp_check_for_duplicate() To check for duplicates
  83. * @uses bbp_get_forum_post_type() To get the forum post type
  84. * @uses remove_filter() To remove kses filters if needed
  85. * @uses apply_filters() Calls 'bbp_new_forum_pre_title' with the content
  86. * @uses apply_filters() Calls 'bbp_new_forum_pre_content' with the content
  87. * @uses bbPress::errors::get_error_codes() To get the {@link WP_Error} errors
  88. * @uses wp_insert_post() To insert the forum
  89. * @uses do_action() Calls 'bbp_new_forum' with the forum id, forum id,
  90. * anonymous data and reply author
  91. * @uses bbp_stick_forum() To stick or super stick the forum
  92. * @uses bbp_unstick_forum() To unstick the forum
  93. * @uses bbp_get_forum_permalink() To get the forum permalink
  94. * @uses wp_safe_redirect() To redirect to the forum link
  95. * @uses bbPress::errors::get_error_messages() To get the {@link WP_Error} error
  96. * messages
  97. */
  98. function bbp_new_forum_handler( $action = '' ) {
  99. // Bail if action is not bbp-new-forum
  100. if ( 'bbp-new-forum' !== $action )
  101. return;
  102. // Nonce check
  103. if ( ! bbp_verify_nonce_request( 'bbp-new-forum' ) ) {
  104. bbp_add_error( 'bbp_new_forum_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
  105. return;
  106. }
  107. // Define local variable(s)
  108. $view_all = $anonymous_data = false;
  109. $forum_parent_id = $forum_author = 0;
  110. $forum_title = $forum_content = '';
  111. /** Forum Author **********************************************************/
  112. // User cannot create forums
  113. if ( !current_user_can( 'publish_forums' ) ) {
  114. bbp_add_error( 'bbp_forum_permissions', __( '<strong>ERROR</strong>: You do not have permission to create new forums.', 'bbpress' ) );
  115. return;
  116. }
  117. // Forum author is current user
  118. $forum_author = bbp_get_current_user_id();
  119. // Remove kses filters from title and content for capable users and if the nonce is verified
  120. if ( current_user_can( 'unfiltered_html' ) && !empty( $_POST['_bbp_unfiltered_html_forum'] ) && wp_create_nonce( 'bbp-unfiltered-html-forum_new' ) === $_POST['_bbp_unfiltered_html_forum'] ) {
  121. remove_filter( 'bbp_new_forum_pre_title', 'wp_filter_kses' );
  122. remove_filter( 'bbp_new_forum_pre_content', 'bbp_encode_bad', 10 );
  123. remove_filter( 'bbp_new_forum_pre_content', 'bbp_filter_kses', 30 );
  124. }
  125. /** Forum Title ***********************************************************/
  126. if ( !empty( $_POST['bbp_forum_title'] ) )
  127. $forum_title = esc_attr( strip_tags( $_POST['bbp_forum_title'] ) );
  128. // Filter and sanitize
  129. $forum_title = apply_filters( 'bbp_new_forum_pre_title', $forum_title );
  130. // No forum title
  131. if ( empty( $forum_title ) )
  132. bbp_add_error( 'bbp_forum_title', __( '<strong>ERROR</strong>: Your forum needs a title.', 'bbpress' ) );
  133. /** Forum Content *********************************************************/
  134. if ( !empty( $_POST['bbp_forum_content'] ) )
  135. $forum_content = $_POST['bbp_forum_content'];
  136. // Filter and sanitize
  137. $forum_content = apply_filters( 'bbp_new_forum_pre_content', $forum_content );
  138. // No forum content
  139. if ( empty( $forum_content ) )
  140. bbp_add_error( 'bbp_forum_content', __( '<strong>ERROR</strong>: Your forum description cannot be empty.', 'bbpress' ) );
  141. /** Forum Parent **********************************************************/
  142. // Forum parent was passed (the norm)
  143. if ( !empty( $_POST['bbp_forum_parent_id'] ) ) {
  144. $forum_parent_id = bbp_get_forum_id( $_POST['bbp_forum_parent_id'] );
  145. }
  146. // Filter and sanitize
  147. $forum_parent_id = apply_filters( 'bbp_new_forum_pre_parent_id', $forum_parent_id );
  148. // No forum parent was passed (should never happen)
  149. if ( empty( $forum_parent_id ) ) {
  150. bbp_add_error( 'bbp_new_forum_missing_parent', __( '<strong>ERROR</strong>: Your forum must have a parent.', 'bbpress' ) );
  151. // Forum exists
  152. } elseif ( !empty( $forum_parent_id ) ) {
  153. // Forum is a category
  154. if ( bbp_is_forum_category( $forum_parent_id ) ) {
  155. bbp_add_error( 'bbp_new_forum_forum_category', __( '<strong>ERROR</strong>: This forum is a category. No forums can be created in this forum.', 'bbpress' ) );
  156. }
  157. // Forum is closed and user cannot access
  158. if ( bbp_is_forum_closed( $forum_parent_id ) && !current_user_can( 'edit_forum', $forum_parent_id ) ) {
  159. bbp_add_error( 'bbp_new_forum_forum_closed', __( '<strong>ERROR</strong>: This forum has been closed to new forums.', 'bbpress' ) );
  160. }
  161. // Forum is private and user cannot access
  162. if ( bbp_is_forum_private( $forum_parent_id ) && !current_user_can( 'read_private_forums' ) ) {
  163. bbp_add_error( 'bbp_new_forum_forum_private', __( '<strong>ERROR</strong>: This forum is private and you do not have the capability to read or create new forums in it.', 'bbpress' ) );
  164. }
  165. // Forum is hidden and user cannot access
  166. if ( bbp_is_forum_hidden( $forum_parent_id ) && !current_user_can( 'read_hidden_forums' ) ) {
  167. bbp_add_error( 'bbp_new_forum_forum_hidden', __( '<strong>ERROR</strong>: This forum is hidden and you do not have the capability to read or create new forums in it.', 'bbpress' ) );
  168. }
  169. }
  170. /** Forum Flooding ********************************************************/
  171. if ( !bbp_check_for_flood( $anonymous_data, $forum_author ) )
  172. bbp_add_error( 'bbp_forum_flood', __( '<strong>ERROR</strong>: Slow down; you move too fast.', 'bbpress' ) );
  173. /** Forum Duplicate *******************************************************/
  174. if ( !bbp_check_for_duplicate( array( 'post_type' => bbp_get_forum_post_type(), 'post_author' => $forum_author, 'post_content' => $forum_content, 'anonymous_data' => $anonymous_data ) ) )
  175. bbp_add_error( 'bbp_forum_duplicate', __( '<strong>ERROR</strong>: This forum already exists.', 'bbpress' ) );
  176. /** Forum Blacklist *******************************************************/
  177. if ( !bbp_check_for_blacklist( $anonymous_data, $forum_author, $forum_title, $forum_content ) )
  178. bbp_add_error( 'bbp_forum_blacklist', __( '<strong>ERROR</strong>: Your forum cannot be created at this time.', 'bbpress' ) );
  179. /** Forum Moderation ******************************************************/
  180. $post_status = bbp_get_public_status_id();
  181. if ( !bbp_check_for_moderation( $anonymous_data, $forum_author, $forum_title, $forum_content ) )
  182. $post_status = bbp_get_pending_status_id();
  183. /** Additional Actions (Before Save) **************************************/
  184. do_action( 'bbp_new_forum_pre_extras', $forum_parent_id );
  185. // Bail if errors
  186. if ( bbp_has_errors() )
  187. return;
  188. /** No Errors *************************************************************/
  189. // Add the content of the form to $forum_data as an array
  190. // Just in time manipulation of forum data before being created
  191. $forum_data = apply_filters( 'bbp_new_forum_pre_insert', array(
  192. 'post_author' => $forum_author,
  193. 'post_title' => $forum_title,
  194. 'post_content' => $forum_content,
  195. 'post_parent' => $forum_parent_id,
  196. 'post_status' => $post_status,
  197. 'post_type' => bbp_get_forum_post_type(),
  198. 'comment_status' => 'closed'
  199. ) );
  200. // Insert forum
  201. $forum_id = wp_insert_post( $forum_data );
  202. /** No Errors *************************************************************/
  203. if ( !empty( $forum_id ) && !is_wp_error( $forum_id ) ) {
  204. /** Trash Check *******************************************************/
  205. // If the forum is trash, or the forum_status is switched to
  206. // trash, trash it properly
  207. if ( ( get_post_field( 'post_status', $forum_id ) === bbp_get_trash_status_id() ) || ( $forum_data['post_status'] === bbp_get_trash_status_id() ) ) {
  208. // Trash the reply
  209. wp_trash_post( $forum_id );
  210. // Force view=all
  211. $view_all = true;
  212. }
  213. /** Spam Check ********************************************************/
  214. // If reply or forum are spam, officially spam this reply
  215. if ( $forum_data['post_status'] === bbp_get_spam_status_id() ) {
  216. add_post_meta( $forum_id, '_bbp_spam_meta_status', bbp_get_public_status_id() );
  217. // Force view=all
  218. $view_all = true;
  219. }
  220. /** Update counts, etc... *********************************************/
  221. do_action( 'bbp_new_forum', array(
  222. 'forum_id' => $forum_id,
  223. 'post_parent' => $forum_parent_id,
  224. 'forum_author' => $forum_author,
  225. 'last_topic_id' => 0,
  226. 'last_reply_id' => 0,
  227. 'last_active_id' => 0,
  228. 'last_active_time' => 0,
  229. 'last_active_status' => bbp_get_public_status_id()
  230. ) );
  231. /** Additional Actions (After Save) ***********************************/
  232. do_action( 'bbp_new_forum_post_extras', $forum_id );
  233. /** Redirect **********************************************************/
  234. // Redirect to
  235. $redirect_to = bbp_get_redirect_to();
  236. // Get the forum URL
  237. $redirect_url = bbp_get_forum_permalink( $forum_id, $redirect_to );
  238. // Add view all?
  239. if ( bbp_get_view_all() || !empty( $view_all ) ) {
  240. // User can moderate, so redirect to forum with view all set
  241. if ( current_user_can( 'moderate' ) ) {
  242. $redirect_url = bbp_add_view_all( $redirect_url );
  243. // User cannot moderate, so redirect to forum
  244. } else {
  245. $redirect_url = bbp_get_forum_permalink( $forum_id );
  246. }
  247. }
  248. // Allow to be filtered
  249. $redirect_url = apply_filters( 'bbp_new_forum_redirect_to', $redirect_url, $redirect_to );
  250. /** Successful Save ***************************************************/
  251. // Redirect back to new forum
  252. wp_safe_redirect( $redirect_url );
  253. // For good measure
  254. exit();
  255. // Errors
  256. } else {
  257. $append_error = ( is_wp_error( $forum_id ) && $forum_id->get_error_message() ) ? $forum_id->get_error_message() . ' ' : '';
  258. bbp_add_error( 'bbp_forum_error', __( '<strong>ERROR</strong>: The following problem(s) have been found with your forum:' . $append_error, 'bbpress' ) );
  259. }
  260. }
  261. /**
  262. * Handles the front end edit forum submission
  263. *
  264. * @param string $action The requested action to compare this function to
  265. * @uses bbPress:errors::add() To log various error messages
  266. * @uses bbp_get_forum() To get the forum
  267. * @uses bbp_verify_nonce_request() To verify the nonce and check the request
  268. * @uses bbp_is_forum_anonymous() To check if forum is by an anonymous user
  269. * @uses current_user_can() To check if the current user can edit the forum
  270. * @uses bbp_filter_anonymous_post_data() To filter anonymous data
  271. * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error}
  272. * @uses esc_attr() For sanitization
  273. * @uses bbp_is_forum_category() To check if the forum is a category
  274. * @uses bbp_is_forum_closed() To check if the forum is closed
  275. * @uses bbp_is_forum_private() To check if the forum is private
  276. * @uses remove_filter() To remove kses filters if needed
  277. * @uses apply_filters() Calls 'bbp_edit_forum_pre_title' with the title and
  278. * forum id
  279. * @uses apply_filters() Calls 'bbp_edit_forum_pre_content' with the content
  280. * and forum id
  281. * @uses bbPress::errors::get_error_codes() To get the {@link WP_Error} errors
  282. * @uses wp_save_post_revision() To save a forum revision
  283. * @uses bbp_update_forum_revision_log() To update the forum revision log
  284. * @uses wp_update_post() To update the forum
  285. * @uses do_action() Calls 'bbp_edit_forum' with the forum id, forum id,
  286. * anonymous data and reply author
  287. * @uses bbp_move_forum_handler() To handle movement of a forum from one forum
  288. * to another
  289. * @uses bbp_get_forum_permalink() To get the forum permalink
  290. * @uses wp_safe_redirect() To redirect to the forum link
  291. * @uses bbPress::errors::get_error_messages() To get the {@link WP_Error} error
  292. * messages
  293. */
  294. function bbp_edit_forum_handler( $action = '' ) {
  295. // Bail if action is not bbp-edit-forum
  296. if ( 'bbp-edit-forum' !== $action )
  297. return;
  298. // Define local variable(s)
  299. $anonymous_data = array();
  300. $forum = $forum_id = $forum_parent_id = 0;
  301. $forum_title = $forum_content = $forum_edit_reason = '';
  302. /** Forum *****************************************************************/
  303. // Forum id was not passed
  304. if ( empty( $_POST['bbp_forum_id'] ) ) {
  305. bbp_add_error( 'bbp_edit_forum_id', __( '<strong>ERROR</strong>: Forum ID not found.', 'bbpress' ) );
  306. return;
  307. // Forum id was passed
  308. } elseif ( is_numeric( $_POST['bbp_forum_id'] ) ) {
  309. $forum_id = (int) $_POST['bbp_forum_id'];
  310. $forum = bbp_get_forum( $forum_id );
  311. }
  312. // Nonce check
  313. if ( ! bbp_verify_nonce_request( 'bbp-edit-forum_' . $forum_id ) ) {
  314. bbp_add_error( 'bbp_edit_forum_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
  315. return;
  316. // Forum does not exist
  317. } elseif ( empty( $forum ) ) {
  318. bbp_add_error( 'bbp_edit_forum_not_found', __( '<strong>ERROR</strong>: The forum you want to edit was not found.', 'bbpress' ) );
  319. return;
  320. // User cannot edit this forum
  321. } elseif ( !current_user_can( 'edit_forum', $forum_id ) ) {
  322. bbp_add_error( 'bbp_edit_forum_permissions', __( '<strong>ERROR</strong>: You do not have permission to edit that forum.', 'bbpress' ) );
  323. return;
  324. }
  325. // Remove kses filters from title and content for capable users and if the nonce is verified
  326. if ( current_user_can( 'unfiltered_html' ) && !empty( $_POST['_bbp_unfiltered_html_forum'] ) && ( wp_create_nonce( 'bbp-unfiltered-html-forum_' . $forum_id ) === $_POST['_bbp_unfiltered_html_forum'] ) ) {
  327. remove_filter( 'bbp_edit_forum_pre_title', 'wp_filter_kses' );
  328. remove_filter( 'bbp_edit_forum_pre_content', 'bbp_encode_bad', 10 );
  329. remove_filter( 'bbp_edit_forum_pre_content', 'bbp_filter_kses', 30 );
  330. }
  331. /** Forum Parent ***********************************************************/
  332. // Forum parent id was passed
  333. if ( !empty( $_POST['bbp_forum_parent_id'] ) ) {
  334. $forum_parent_id = bbp_get_forum_id( $_POST['bbp_forum_parent_id'] );
  335. }
  336. // Current forum this forum is in
  337. $current_parent_forum_id = bbp_get_forum_parent_id( $forum_id );
  338. // Forum exists
  339. if ( !empty( $forum_parent_id ) && ( $forum_parent_id !== $current_parent_forum_id ) ) {
  340. // Forum is closed and user cannot access
  341. if ( bbp_is_forum_closed( $forum_parent_id ) && !current_user_can( 'edit_forum', $forum_parent_id ) ) {
  342. bbp_add_error( 'bbp_edit_forum_forum_closed', __( '<strong>ERROR</strong>: This forum has been closed to new forums.', 'bbpress' ) );
  343. }
  344. // Forum is private and user cannot access
  345. if ( bbp_is_forum_private( $forum_parent_id ) && !current_user_can( 'read_private_forums' ) ) {
  346. bbp_add_error( 'bbp_edit_forum_forum_private', __( '<strong>ERROR</strong>: This forum is private and you do not have the capability to read or create new forums in it.', 'bbpress' ) );
  347. }
  348. // Forum is hidden and user cannot access
  349. if ( bbp_is_forum_hidden( $forum_parent_id ) && !current_user_can( 'read_hidden_forums' ) ) {
  350. bbp_add_error( 'bbp_edit_forum_forum_hidden', __( '<strong>ERROR</strong>: This forum is hidden and you do not have the capability to read or create new forums in it.', 'bbpress' ) );
  351. }
  352. }
  353. /** Forum Title ***********************************************************/
  354. if ( !empty( $_POST['bbp_forum_title'] ) )
  355. $forum_title = esc_attr( strip_tags( $_POST['bbp_forum_title'] ) );
  356. // Filter and sanitize
  357. $forum_title = apply_filters( 'bbp_edit_forum_pre_title', $forum_title, $forum_id );
  358. // No forum title
  359. if ( empty( $forum_title ) )
  360. bbp_add_error( 'bbp_edit_forum_title', __( '<strong>ERROR</strong>: Your forum needs a title.', 'bbpress' ) );
  361. /** Forum Content *********************************************************/
  362. if ( !empty( $_POST['bbp_forum_content'] ) )
  363. $forum_content = $_POST['bbp_forum_content'];
  364. // Filter and sanitize
  365. $forum_content = apply_filters( 'bbp_edit_forum_pre_content', $forum_content, $forum_id );
  366. // No forum content
  367. if ( empty( $forum_content ) )
  368. bbp_add_error( 'bbp_edit_forum_content', __( '<strong>ERROR</strong>: Your forum description cannot be empty.', 'bbpress' ) );
  369. /** Forum Blacklist *******************************************************/
  370. if ( !bbp_check_for_blacklist( $anonymous_data, bbp_get_forum_author_id( $forum_id ), $forum_title, $forum_content ) )
  371. bbp_add_error( 'bbp_forum_blacklist', __( '<strong>ERROR</strong>: Your forum cannot be edited at this time.', 'bbpress' ) );
  372. /** Forum Moderation ******************************************************/
  373. $post_status = bbp_get_public_status_id();
  374. if ( !bbp_check_for_moderation( $anonymous_data, bbp_get_forum_author_id( $forum_id ), $forum_title, $forum_content ) )
  375. $post_status = bbp_get_pending_status_id();
  376. /** Additional Actions (Before Save) **************************************/
  377. do_action( 'bbp_edit_forum_pre_extras', $forum_id );
  378. // Bail if errors
  379. if ( bbp_has_errors() )
  380. return;
  381. /** No Errors *************************************************************/
  382. // Add the content of the form to $forum_data as an array
  383. // Just in time manipulation of forum data before being edited
  384. $forum_data = apply_filters( 'bbp_edit_forum_pre_insert', array(
  385. 'ID' => $forum_id,
  386. 'post_title' => $forum_title,
  387. 'post_content' => $forum_content,
  388. 'post_status' => $post_status,
  389. 'post_parent' => $forum_parent_id
  390. ) );
  391. // Insert forum
  392. $forum_id = wp_update_post( $forum_data );
  393. /** Revisions *************************************************************/
  394. /**
  395. * @todo omitted for 2.1
  396. // Revision Reason
  397. if ( !empty( $_POST['bbp_forum_edit_reason'] ) )
  398. $forum_edit_reason = esc_attr( strip_tags( $_POST['bbp_forum_edit_reason'] ) );
  399. // Update revision log
  400. if ( !empty( $_POST['bbp_log_forum_edit'] ) && ( "1" === $_POST['bbp_log_forum_edit'] ) && ( $revision_id = wp_save_post_revision( $forum_id ) ) ) {
  401. bbp_update_forum_revision_log( array(
  402. 'forum_id' => $forum_id,
  403. 'revision_id' => $revision_id,
  404. 'author_id' => bbp_get_current_user_id(),
  405. 'reason' => $forum_edit_reason
  406. ) );
  407. }
  408. */
  409. /** No Errors *************************************************************/
  410. if ( !empty( $forum_id ) && !is_wp_error( $forum_id ) ) {
  411. // Update counts, etc...
  412. do_action( 'bbp_edit_forum', array(
  413. 'forum_id' => $forum_id,
  414. 'post_parent' => $forum_parent_id,
  415. 'forum_author' => $forum->post_author,
  416. 'last_topic_id' => 0,
  417. 'last_reply_id' => 0,
  418. 'last_active_id' => 0,
  419. 'last_active_time' => 0,
  420. 'last_active_status' => bbp_get_public_status_id()
  421. ) );
  422. // If the new forum parent id is not equal to the old forum parent
  423. // id, run the bbp_move_forum action and pass the forum's parent id
  424. // as the first arg and new forum parent id as the second.
  425. // @todo implement
  426. //if ( $forum_id !== $forum->post_parent )
  427. // bbp_move_forum_handler( $forum_parent_id, $forum->post_parent, $forum_id );
  428. /** Additional Actions (After Save) ***********************************/
  429. do_action( 'bbp_edit_forum_post_extras', $forum_id );
  430. /** Redirect **********************************************************/
  431. // Redirect to
  432. $redirect_to = bbp_get_redirect_to();
  433. // View all?
  434. $view_all = bbp_get_view_all();
  435. // Get the forum URL
  436. $forum_url = bbp_get_forum_permalink( $forum_id, $redirect_to );
  437. // Add view all?
  438. if ( !empty( $view_all ) )
  439. $forum_url = bbp_add_view_all( $forum_url );
  440. // Allow to be filtered
  441. $forum_url = apply_filters( 'bbp_edit_forum_redirect_to', $forum_url, $view_all, $redirect_to );
  442. /** Successful Edit ***************************************************/
  443. // Redirect back to new forum
  444. wp_safe_redirect( $forum_url );
  445. // For good measure
  446. exit();
  447. /** Errors ****************************************************************/
  448. } else {
  449. $append_error = ( is_wp_error( $forum_id ) && $forum_id->get_error_message() ) ? $forum_id->get_error_message() . ' ' : '';
  450. bbp_add_error( 'bbp_forum_error', __( '<strong>ERROR</strong>: The following problem(s) have been found with your forum:' . $append_error . 'Please try again.', 'bbpress' ) );
  451. }
  452. }
  453. /**
  454. * Handle the saving of core forum metadata (Status, Visibility, and Type)
  455. *
  456. * @since bbPress (r3678)
  457. * @param int $forum_id
  458. * @uses bbp_is_forum_closed() To check if forum is closed
  459. * @uses bbp_close_forum() To close forum
  460. * @uses bbp_open_forum() To open forum
  461. * @uses bbp_is_forum_category() To check if forum is a category
  462. * @uses bbp_categorize_forum() To turn forum into a category
  463. * @uses bbp_normalize_forum() To turn category into forum
  464. * @uses bbp_get_public_status_id() To get the public status ID
  465. * @uses bbp_get_private_status_id() To get the private status ID
  466. * @uses bbp_get_hidden_status_id() To get the hidden status ID
  467. * @uses bbp_get_forum_visibility() To get the forums visibility
  468. * @uses bbp_hide_forum() To hide a forum
  469. * @uses bbp_privatize_forum() To make a forum private
  470. * @uses bbp_publicize_forum() To make a forum public
  471. * @return If forum ID is empty
  472. */
  473. function bbp_save_forum_extras( $forum_id = 0 ) {
  474. // Validate the forum ID
  475. $forum_id = bbp_get_forum_id( $forum_id );
  476. // Bail if forum ID is empty
  477. if ( empty( $forum_id ) || ! bbp_is_forum( $forum_id ) )
  478. return;
  479. /** Forum Status ******************************************************/
  480. if ( !empty( $_POST['bbp_forum_status'] ) && in_array( $_POST['bbp_forum_status'], array( 'open', 'closed' ) ) ) {
  481. if ( 'closed' === $_POST['bbp_forum_status'] && !bbp_is_forum_closed( $forum_id, false ) ) {
  482. bbp_close_forum( $forum_id );
  483. } elseif ( 'open' === $_POST['bbp_forum_status'] && bbp_is_forum_closed( $forum_id, false ) ) {
  484. bbp_open_forum( $forum_id );
  485. }
  486. }
  487. /** Forum Type ********************************************************/
  488. if ( !empty( $_POST['bbp_forum_type'] ) && in_array( $_POST['bbp_forum_type'], array( 'forum', 'category' ) ) ) {
  489. if ( 'category' === $_POST['bbp_forum_type'] && !bbp_is_forum_category( $forum_id ) ) {
  490. bbp_categorize_forum( $forum_id );
  491. } elseif ( 'forum' === $_POST['bbp_forum_type'] && bbp_is_forum_category( $forum_id ) ) {
  492. bbp_normalize_forum( $forum_id );
  493. }
  494. }
  495. /** Forum Visibility **************************************************/
  496. if ( !empty( $_POST['bbp_forum_visibility'] ) && in_array( $_POST['bbp_forum_visibility'], array( bbp_get_public_status_id(), bbp_get_private_status_id(), bbp_get_hidden_status_id() ) ) ) {
  497. // Get forums current visibility
  498. $visibility = bbp_get_forum_visibility( $forum_id );
  499. // What is the new forum visibility setting?
  500. switch ( $_POST['bbp_forum_visibility'] ) {
  501. // Hidden
  502. case bbp_get_hidden_status_id() :
  503. bbp_hide_forum( $forum_id, $visibility );
  504. break;
  505. // Private
  506. case bbp_get_private_status_id() :
  507. bbp_privatize_forum( $forum_id, $visibility );
  508. break;
  509. // Publish (default)
  510. case bbp_get_public_status_id() :
  511. default :
  512. bbp_publicize_forum( $forum_id, $visibility );
  513. break;
  514. }
  515. }
  516. }
  517. /** Forum Actions *************************************************************/
  518. /**
  519. * Closes a forum
  520. *
  521. * @since bbPress (r2746)
  522. *
  523. * @param int $forum_id forum id
  524. * @uses do_action() Calls 'bbp_close_forum' with the forum id
  525. * @uses update_post_meta() To add the previous status to a meta
  526. * @uses do_action() Calls 'bbp_opened_forum' with the forum id
  527. * @return mixed False or {@link WP_Error} on failure, forum id on success
  528. */
  529. function bbp_close_forum( $forum_id = 0 ) {
  530. $forum_id = bbp_get_forum_id( $forum_id );
  531. do_action( 'bbp_close_forum', $forum_id );
  532. update_post_meta( $forum_id, '_bbp_status', 'closed' );
  533. do_action( 'bbp_closed_forum', $forum_id );
  534. return $forum_id;
  535. }
  536. /**
  537. * Opens a forum
  538. *
  539. * @since bbPress (r2746)
  540. *
  541. * @param int $forum_id forum id
  542. * @uses do_action() Calls 'bbp_open_forum' with the forum id
  543. * @uses get_post_meta() To get the previous status
  544. * @uses update_post_meta() To delete the previous status meta
  545. * @uses do_action() Calls 'bbp_opened_forum' with the forum id
  546. * @return mixed False or {@link WP_Error} on failure, forum id on success
  547. */
  548. function bbp_open_forum( $forum_id = 0 ) {
  549. $forum_id = bbp_get_forum_id( $forum_id );
  550. do_action( 'bbp_open_forum', $forum_id );
  551. update_post_meta( $forum_id, '_bbp_status', 'open' );
  552. do_action( 'bbp_opened_forum', $forum_id );
  553. return $forum_id;
  554. }
  555. /**
  556. * Make the forum a category
  557. *
  558. * @since bbPress (r2746)
  559. *
  560. * @param int $forum_id Optional. Forum id
  561. * @uses update_post_meta() To update the forum category meta
  562. * @return bool False on failure, true on success
  563. */
  564. function bbp_categorize_forum( $forum_id = 0 ) {
  565. $forum_id = bbp_get_forum_id( $forum_id );
  566. do_action( 'bbp_categorize_forum', $forum_id );
  567. update_post_meta( $forum_id, '_bbp_forum_type', 'category' );
  568. do_action( 'bbp_categorized_forum', $forum_id );
  569. return $forum_id;
  570. }
  571. /**
  572. * Remove the category status from a forum
  573. *
  574. * @since bbPress (r2746)
  575. *
  576. * @param int $forum_id Optional. Forum id
  577. * @uses delete_post_meta() To delete the forum category meta
  578. * @return bool False on failure, true on success
  579. */
  580. function bbp_normalize_forum( $forum_id = 0 ) {
  581. $forum_id = bbp_get_forum_id( $forum_id );
  582. do_action( 'bbp_normalize_forum', $forum_id );
  583. update_post_meta( $forum_id, '_bbp_forum_type', 'forum' );
  584. do_action( 'bbp_normalized_forum', $forum_id );
  585. return $forum_id;
  586. }
  587. /**
  588. * Mark the forum as public
  589. *
  590. * @since bbPress (r2746)
  591. *
  592. * @param int $forum_id Optional. Forum id
  593. * @uses update_post_meta() To update the forum private meta
  594. * @return bool False on failure, true on success
  595. */
  596. function bbp_publicize_forum( $forum_id = 0, $current_visibility = '' ) {
  597. $forum_id = bbp_get_forum_id( $forum_id );
  598. do_action( 'bbp_publicize_forum', $forum_id );
  599. // Get private forums
  600. $private = bbp_get_private_forum_ids();
  601. // Find this forum in the array
  602. if ( in_array( $forum_id, $private ) ) {
  603. $offset = array_search( $forum_id, $private );
  604. // Splice around it
  605. array_splice( $private, $offset, 1 );
  606. // Update private forums minus this one
  607. update_option( '_bbp_private_forums', array_unique( array_filter( array_values( $private ) ) ) );
  608. }
  609. // Get hidden forums
  610. $hidden = bbp_get_hidden_forum_ids();
  611. // Find this forum in the array
  612. if ( in_array( $forum_id, $hidden ) ) {
  613. $offset = array_search( $forum_id, $hidden );
  614. // Splice around it
  615. array_splice( $hidden, $offset, 1 );
  616. // Update hidden forums minus this one
  617. update_option( '_bbp_hidden_forums', array_unique( array_filter( array_values( $hidden ) ) ) );
  618. }
  619. // Only run queries if visibility is changing
  620. if ( bbp_get_public_status_id() !== $current_visibility ) {
  621. // Update forums visibility setting
  622. global $wpdb;
  623. $wpdb->update( $wpdb->posts, array( 'post_status' => bbp_get_public_status_id() ), array( 'ID' => $forum_id ) );
  624. wp_transition_post_status( bbp_get_public_status_id(), $current_visibility, get_post( $forum_id ) );
  625. bbp_clean_post_cache( $forum_id );
  626. }
  627. do_action( 'bbp_publicized_forum', $forum_id );
  628. return $forum_id;
  629. }
  630. /**
  631. * Mark the forum as private
  632. *
  633. * @since bbPress (r2746)
  634. *
  635. * @param int $forum_id Optional. Forum id
  636. * @uses update_post_meta() To update the forum private meta
  637. * @return bool False on failure, true on success
  638. */
  639. function bbp_privatize_forum( $forum_id = 0, $current_visibility = '' ) {
  640. $forum_id = bbp_get_forum_id( $forum_id );
  641. do_action( 'bbp_privatize_forum', $forum_id );
  642. // Only run queries if visibility is changing
  643. if ( bbp_get_private_status_id() !== $current_visibility ) {
  644. // Get hidden forums
  645. $hidden = bbp_get_hidden_forum_ids();
  646. // Find this forum in the array
  647. if ( in_array( $forum_id, $hidden ) ) {
  648. $offset = array_search( $forum_id, $hidden );
  649. // Splice around it
  650. array_splice( $hidden, $offset, 1 );
  651. // Update hidden forums minus this one
  652. update_option( '_bbp_hidden_forums', array_unique( array_filter( array_values( $hidden ) ) ) );
  653. }
  654. // Add to '_bbp_private_forums' site option
  655. $private = bbp_get_private_forum_ids();
  656. $private[] = $forum_id;
  657. update_option( '_bbp_private_forums', array_unique( array_filter( array_values( $private ) ) ) );
  658. // Update forums visibility setting
  659. global $wpdb;
  660. $wpdb->update( $wpdb->posts, array( 'post_status' => bbp_get_private_status_id() ), array( 'ID' => $forum_id ) );
  661. wp_transition_post_status( bbp_get_private_status_id(), $current_visibility, get_post( $forum_id ) );
  662. bbp_clean_post_cache( $forum_id );
  663. }
  664. do_action( 'bbp_privatized_forum', $forum_id );
  665. return $forum_id;
  666. }
  667. /**
  668. * Mark the forum as hidden
  669. *
  670. * @since bbPress (r2996)
  671. *
  672. * @param int $forum_id Optional. Forum id
  673. * @uses update_post_meta() To update the forum private meta
  674. * @return bool False on failure, true on success
  675. */
  676. function bbp_hide_forum( $forum_id = 0, $current_visibility = '' ) {
  677. $forum_id = bbp_get_forum_id( $forum_id );
  678. do_action( 'bbp_hide_forum', $forum_id );
  679. // Only run queries if visibility is changing
  680. if ( bbp_get_hidden_status_id() !== $current_visibility ) {
  681. // Get private forums
  682. $private = bbp_get_private_forum_ids();
  683. // Find this forum in the array
  684. if ( in_array( $forum_id, $private ) ) {
  685. $offset = array_search( $forum_id, $private );
  686. // Splice around it
  687. array_splice( $private, $offset, 1 );
  688. // Update private forums minus this one
  689. update_option( '_bbp_private_forums', array_unique( array_filter( array_values( $private ) ) ) );
  690. }
  691. // Add to '_bbp_hidden_forums' site option
  692. $hidden = bbp_get_hidden_forum_ids();
  693. $hidden[] = $forum_id;
  694. update_option( '_bbp_hidden_forums', array_unique( array_filter( array_values( $hidden ) ) ) );
  695. // Update forums visibility setting
  696. global $wpdb;
  697. $wpdb->update( $wpdb->posts, array( 'post_status' => bbp_get_hidden_status_id() ), array( 'ID' => $forum_id ) );
  698. wp_transition_post_status( bbp_get_hidden_status_id(), $current_visibility, get_post( $forum_id ) );
  699. bbp_clean_post_cache( $forum_id );
  700. }
  701. do_action( 'bbp_hid_forum', $forum_id );
  702. return $forum_id;
  703. }
  704. /**
  705. * Recaches the private and hidden forums
  706. *
  707. * @since bbPress (r5017)
  708. *
  709. * @uses delete_option() to delete private and hidden forum pointers
  710. * @uses WP_Query() To query post IDs
  711. * @uses is_wp_error() To return if error occurred
  712. * @uses update_option() To update the private and hidden post ID pointers
  713. * @return array An array of the status code and the message
  714. */
  715. function bbp_repair_forum_visibility() {
  716. // First, delete everything.
  717. delete_option( '_bbp_private_forums' );
  718. delete_option( '_bbp_hidden_forums' );
  719. // Next, get all the private and hidden forums
  720. $private_forums = new WP_Query( array(
  721. 'suppress_filters' => true,
  722. 'nopaging' => true,
  723. 'post_type' => bbp_get_forum_post_type(),
  724. 'post_status' => bbp_get_private_status_id(),
  725. 'fields' => 'ids'
  726. ) );
  727. $hidden_forums = new WP_Query( array(
  728. 'suppress_filters' => true,
  729. 'nopaging' => true,
  730. 'post_type' => bbp_get_forum_post_type(),
  731. 'post_status' => bbp_get_hidden_status_id(),
  732. 'fields' => 'ids'
  733. ) );
  734. // Reset the $post global
  735. wp_reset_postdata();
  736. // Bail if queries returned errors
  737. if ( is_wp_error( $private_forums ) || is_wp_error( $hidden_forums ) )
  738. return false;
  739. // Update the private/hidden options
  740. update_option( '_bbp_private_forums', $private_forums->posts ); // Private forums
  741. update_option( '_bbp_hidden_forums', $hidden_forums->posts ); // Hidden forums
  742. // Complete results
  743. return true;
  744. }
  745. /** Subscriptions *************************************************************/
  746. /**
  747. * Remove a deleted forum from all users' subscriptions
  748. *
  749. * @since bbPress (r5156)
  750. *
  751. * @param int $forum_id Get the forum ID to remove
  752. * @uses bbp_is_subscriptions_active() To check if the subscriptions are active
  753. * @uses bbp_get_forum_id To get the forum id
  754. * @uses bbp_get_forum_subscribers() To get the forum subscribers
  755. * @uses bbp_remove_user_subscription() To remove the user subscription
  756. */
  757. function bbp_remove_forum_from_all_subscriptions( $forum_id = 0 ) {
  758. // Subscriptions are not active
  759. if ( ! bbp_is_subscriptions_active() ) {
  760. return;
  761. }
  762. $forum_id = bbp_get_forum_id( $forum_id );
  763. // Bail if no forum
  764. if ( empty( $forum_id ) ) {
  765. return;
  766. }
  767. // Get users
  768. $users = (array) bbp_get_forum_subscribers( $forum_id );
  769. // Users exist
  770. if ( !empty( $users ) ) {
  771. // Loop through users
  772. foreach ( $users as $user ) {
  773. // Remove each user
  774. bbp_remove_user_subscription( $user, $forum_id );
  775. }
  776. }
  777. }
  778. /** Count Bumpers *************************************************************/
  779. /**
  780. * Bump the total topic count of a forum
  781. *
  782. * @since bbPress (r3825)
  783. *
  784. * @param int $forum_id Optional. Forum id.
  785. * @param int $difference Optional. Default 1
  786. * @param bool $update_ancestors Optional. Default true
  787. * @uses bbp_get_forum_id() To get the forum id
  788. * @uses update_post_meta() To update the forum's topic count meta
  789. * @uses apply_filters() Calls 'bbp_bump_forum_topic_count' with the topic
  790. * count, forum id, and difference
  791. * @return int Forum topic count
  792. */
  793. function bbp_bump_forum_topic_count( $forum_id = 0, $difference = 1, $update_ancestors = true ) {
  794. // Get some counts
  795. $forum_id = bbp_get_forum_id( $forum_id );
  796. $topic_count = bbp_get_forum_topic_count( $forum_id, false, true );
  797. $total_topic_count = bbp_get_forum_topic_count( $forum_id, true, true );
  798. // Update this forum id
  799. update_post_meta( $forum_id, '_bbp_topic_count', (int) $topic_count + (int) $difference );
  800. update_post_meta( $forum_id, '_bbp_total_topic_count', (int) $total_topic_count + (int) $difference );
  801. // Check for ancestors
  802. if ( true === $update_ancestors ) {
  803. // Get post ancestors
  804. $forum = get_post( $forum_id );
  805. $ancestors = get_post_ancestors( $forum );
  806. // If has ancestors, loop through them...
  807. if ( !empty( $ancestors ) ) {
  808. foreach ( (array) $ancestors as $parent_forum_id ) {
  809. // Get forum counts
  810. $parent_topic_count = bbp_get_forum_topic_count( $parent_forum_id, false, true );
  811. $parent_total_topic_count = bbp_get_forum_topic_count( $parent_forum_id, true, true );
  812. // Update counts
  813. update_post_meta( $parent_forum_id, '_bbp_topic_count', (int) $parent_topic_count + (int) $difference );
  814. update_post_meta( $parent_forum_id, '_bbp_total_topic_count', (int) $parent_total_topic_count + (int) $difference );
  815. }
  816. }
  817. }
  818. return (int) apply_filters( 'bbp_bump_forum_topic_count', (int) $total_topic_count + (int) $difference, $forum_id, (int) $difference, (bool) $update_ancestors );
  819. }
  820. /**
  821. * Bump the total hidden topic count of a forum
  822. *
  823. * @since bbPress (r3825)
  824. *
  825. * @param int $forum_id Optional. Forum id.
  826. * @param int $difference Optional. Default 1
  827. * @uses bbp_get_forum_id() To get the forum id
  828. * @uses update_post_meta() To update the forum's topic count meta
  829. * @uses apply_filters() Calls 'bbp_bump_forum_topic_count_hidden' with the
  830. * topic count, forum id, and difference
  831. * @return int Forum hidden topic count
  832. */
  833. function bbp_bump_forum_topic_count_hidden( $forum_id = 0, $difference = 1 ) {
  834. // Get some counts
  835. $forum_id = bbp_get_forum_id( $forum_id );
  836. $topic_count = bbp_get_forum_topic_count_hidden( $forum_id, true );
  837. $new_count = (int) $topic_count + (int) $difference;
  838. // Update this forum id
  839. update_post_meta( $forum_id, '_bbp_topic_count_hidden', (int) $new_count );
  840. return (int) apply_filters( 'bbp_bump_forum_topic_count_hidden', (int) $new_count, $forum_id, (int) $difference );
  841. }
  842. /**
  843. * Bump the total topic count of a forum
  844. *
  845. * @since bbPress (r3825)
  846. *
  847. * @param int $forum_id Optional. Forum id.
  848. * @param int $difference Optional. Default 1
  849. * @param bool $update_ancestors Optional. Default true
  850. * @uses bbp_get_forum_id() To get the forum id
  851. * @uses update_post_meta() To update the forum's topic count meta
  852. * @uses apply_filters() Calls 'bbp_bump_forum_reply_count' with the topic
  853. * count, forum id, and difference
  854. * @return int Forum topic count
  855. */
  856. function bbp_bump_forum_reply_count( $forum_id = 0, $difference = 1, $update_ancestors = true ) {
  857. // Get some counts
  858. $forum_id = bbp_get_forum_id( $forum_id );
  859. $topic_count = bbp_get_forum_reply_count( $forum_id, false, true );
  860. $total_reply_count = bbp_get_forum_reply_count( $forum_id, true, true );
  861. // Update this forum id
  862. update_post_meta( $forum_id, '_bbp_reply_count', (int) $topic_count + (int) $difference );
  863. update_post_meta( $forum_id, '_bbp_total_reply_count', (int) $total_reply_count + (int) $difference );
  864. // Check for ancestors
  865. if ( true === $update_ancestors ) {
  866. // Get post ancestors
  867. $forum = get_post( $forum_id );
  868. $ancestors = get_post_ancestors( $forum );
  869. // If has ancestors, loop through them...
  870. if ( !empty( $ancestors ) ) {
  871. foreach ( (array) $ancestors as $parent_forum_id ) {
  872. // Get forum counts
  873. $parent_topic_count = bbp_get_forum_reply_count( $parent_forum_id, false, true );
  874. $parent_total_reply_count = bbp_get_forum_reply_count( $parent_forum_id, true, true );
  875. // Update counts
  876. update_post_meta( $parent_forum_id, '_bbp_reply_count', (int) $parent_topic_count + (int) $difference );
  877. update_post_meta( $parent_forum_id, '_bbp_total_reply_count', (int) $parent_total_reply_count + (int) $difference );
  878. }
  879. }
  880. }
  881. return (int) apply_filters( 'bbp_bump_forum_reply_count', (int) $total_reply_count + (int) $difference, $forum_id, (int) $difference, (bool) $update_ancestors );
  882. }
  883. /** Forum Updaters ************************************************************/
  884. /**
  885. * Update the forum last topic id
  886. *
  887. * @since bbPress (r2625)
  888. *
  889. * @param int $forum_id Optional. Forum id
  890. * @param int $topic_id Optional. Topic id
  891. * @uses bbp_get_forum_id() To get the forum id
  892. * @uses bbp_forum_query_subforum_ids() To get the subforum ids
  893. * @uses bbp_update_forum_last_topic_id() To update the last topic id of child
  894. * forums
  895. * @uses get_posts() To get the most recent topic in the forum
  896. * @uses update_post_meta() To update the forum's last active id meta
  897. * @uses apply_filters() Calls 'bbp_update_forum_last_topic_id' with the last
  898. * reply id and forum id
  899. * @return bool True on success, false on failure
  900. */
  901. function bbp_update_forum_last_topic_id( $forum_id = 0, $topic_id = 0 ) {
  902. $forum_id = bbp_get_forum_id( $forum_id );
  903. // Define local variable(s)
  904. $children_last_topic = 0;
  905. // Do some calculation if not manually set
  906. if ( empty( $topic_id ) ) {
  907. // Loop through children and add together forum reply counts
  908. $children = bbp_forum_query_subforum_ids( $forum_id );
  909. if ( !empty( $children ) ) {
  910. foreach ( (array) $children as $child ) {
  911. $children_last_topic = bbp_update_forum_last_topic_id( $child ); // Recursive
  912. }
  913. }
  914. // Setup recent topic query vars
  915. $post_vars = array(
  916. 'post_parent' => $forum_id,
  917. 'post_type' => bbp_get_topic_post_type(),
  918. 'meta_key' => '_bbp_last_active_time',
  919. 'orderby' => 'meta_value',
  920. 'numberposts' => 1
  921. );
  922. // Get the most recent topic in this forum_id
  923. $recent_topic = get_posts( $post_vars );
  924. if ( !empty( $recent_topic ) ) {
  925. $topic_id = $recent_topic[0]->ID;
  926. }
  927. }
  928. // Cast as integer in case of empty or string
  929. $topic_id = (int) $topic_id;
  930. $children_last_topic = (int) $children_last_topic;
  931. // If child forums have higher id, use that instead
  932. if ( !empty( $children ) && ( $children_last_topic > $topic_id ) )
  933. $topic_id = $children_last_topic;
  934. // Update the last public topic ID
  935. if ( bbp_is_topic_published( $topic_id ) )
  936. update_post_meta( $forum_id, '_bbp_last_topic_id', $topic_id );
  937. return (int) apply_filters( 'bbp_update_forum_last_topic_id', $topic_id, $forum_id );
  938. }
  939. /**
  940. * Update the forum last reply id
  941. *
  942. * @since bbPress (r2625)
  943. *
  944. * @param int $forum_id Optional. Forum id
  945. * @param int $reply_id Optional. Reply id
  946. * @uses bbp_get_forum_id() To get the forum id
  947. * @uses bbp_forum_query_subforum_ids() To get the subforum ids
  948. * @uses bbp_update_forum_last_reply_id() To update the last reply id of child
  949. * forums
  950. * @uses bbp_forum_query_topic_ids() To get the topic ids in the forum
  951. * @uses bbp_forum_query_last_reply_id() To get the forum's last reply id
  952. * @uses bbp_is_reply_published() To make sure the reply is published
  953. * @uses update_post_meta() To update the forum's last active id meta
  954. * @uses apply_filters() Calls 'bbp_update_forum_last_reply_id' with the last
  955. * reply id and forum id
  956. * @return bool True on success, false on failure
  957. */
  958. function bbp_update_forum_last_reply_id( $forum_id = 0, $reply_id = 0 ) {
  959. $forum_id = bbp_get_forum_id( $forum_id );
  960. // Define local variable(s)
  961. $children_last_reply = 0;
  962. // Do some calculation if not manually set
  963. if ( empty( $reply_id ) ) {
  964. // Loop through children and get the most recent reply id
  965. $children = bbp_forum_query_subforum_ids( $forum_id );
  966. if ( !empty( $children ) ) {
  967. foreach ( (array) $children as $child ) {
  968. $children_last_reply = bbp_update_forum_last_reply_id( $child ); // Recursive
  969. }
  970. }
  971. // If this forum has topics...
  972. $topic_ids = bbp_forum_query_topic_ids( $forum_id );
  973. if ( !empty( $topic_ids ) ) {
  974. // ...get the most recent reply from those topics...
  975. $reply_id = bbp_forum_query_last_reply_id( $forum_id, $topic_ids );
  976. // ...and compare it to the most recent topic id...
  977. $reply_id = ( $reply_id > max( $topic_ids ) ) ? $reply_id : max( $topic_ids );
  978. }
  979. }
  980. // Cast as integer in case of empty or string
  981. $reply_id = (int) $reply_id;
  982. $children_last_reply = (int) $children_last_reply;
  983. // If child forums have higher ID, check for newer reply id
  984. if ( !empty( $children ) && ( $children_last_reply > $reply_id ) )
  985. $reply_id = $children_last_reply;
  986. // Update the last public reply ID
  987. if ( bbp_is_reply_published( $reply_id ) )
  988. update_post_meta( $forum_id, '_bbp_last_reply_id', $reply_id );
  989. return (int) apply_filters( 'bbp_update_forum_last_reply_id', $reply_id, $forum_id );
  990. }
  991. /**
  992. * Update the forum last active post id
  993. *
  994. * @since bbPress (r2860)
  995. *
  996. * @param int $forum_id Optional. Forum id
  997. * @param int $active_id Optional. Active post id
  998. * @uses bbp_get_forum_id() To get the forum id
  999. * @uses bbp_forum_query_subforum_ids() To get the subforum ids
  1000. * @uses bbp_update_forum_last_active_id() To update the last active id of
  1001. * child forums
  1002. * @uses bbp_forum_query_topic_ids() To get the topic ids in the forum
  1003. * @uses bbp_forum_query_last_reply_id() To get the forum's last reply id
  1004. * @uses get_post_status() To make sure the reply is published
  1005. * @uses update_post_meta() To update the forum's last active id meta
  1006. * @uses apply_filters() Calls 'bbp_update_forum_last_active_id' with the last
  1007. * active post id and forum id
  1008. * @return bool True on success, false on failure
  1009. */
  1010. function bbp_update_forum_last_active_id( $forum_id = 0, $active_id = 0 ) {
  1011. $forum_id = bbp_get_forum_id( $forum_id );
  1012. // Define local variable(s)
  1013. $children_last_active = 0;
  1014. // Do some calculation if not manually set
  1015. if ( empty( $active_id ) ) {
  1016. // Loop through children and add together forum reply counts
  1017. $children = bbp_forum_query_subforum_ids( $forum_id );
  1018. if ( !empty( $children ) ) {
  1019. foreach ( (array) $children as $child ) {
  1020. $children_last_active = bbp_update_forum_last_active_id( $child, $active_id );
  1021. }
  1022. }
  1023. // Don't count replies if the forum is a category
  1024. $topic_ids = bbp_forum_query_topic_ids( $forum_id );
  1025. if ( !empty( $topic_ids ) ) {
  1026. $active_id = bbp_forum_query_last_reply_id( $forum_id, $topic_ids );
  1027. $active_id = $active_id > max( $topic_ids ) ? $active_id : max( $topic_ids );
  1028. // Forum has no topics
  1029. } else {
  1030. $active_id = 0;
  1031. }
  1032. }
  1033. // Cast as integer in case of empty or string
  1034. $active_id = (int) $active_id;
  1035. $children_last_active = (int) $children_last_active;
  1036. // If child forums have higher id, use that instead
  1037. if ( !empty( $children ) && ( $children_last_active > $active_id ) )
  1038. $active_id = $children_last_active;
  1039. // Update only if published
  1040. if ( bbp_get_public_status_id() === get_post_status( $active_id ) )
  1041. update_post_meta( $forum_id, '_bbp_last_active_id', (int) $active_id );
  1042. return (int) apply_filters( 'bbp_update_forum_last_active_id', (int) $active_id, $forum_id );
  1043. }
  1044. /**
  1045. * Update the forums last active date/time (aka freshness)
  1046. *
  1047. * @since bbPress (r2680)
  1048. *
  1049. * @param int $forum_id Optional. Topic id
  1050. * @param string $new_time Optional. New time in mysql format
  1051. * @uses bbp_get_forum_id() To get the forum id
  1052. * @uses bbp_get_forum_last_active_id() To get the forum's last post id
  1053. * @uses get_post_field() To get the post date of the forum's last post
  1054. * @uses update_post_meta() To update the forum last active time
  1055. * @uses apply_filters() Calls 'bbp_update_forum_last_active' with the new time
  1056. * and forum id
  1057. * @return bool True on success, false on failure
  1058. */
  1059. function bbp_update_forum_last_active_time( $forum_id = 0, $new_time = '' ) {
  1060. $forum_id = bbp_get_forum_id( $forum_id );
  1061. // Check time and use current if empty
  1062. if ( empty( $new_time ) )
  1063. $new_time = get_post_field( 'post_date', bbp_get_forum_last_active_id( $forum_id ) );
  1064. // Update only if there is a time
  1065. if ( !empty( $new_time ) )
  1066. update_post_meta( $forum_id, '_bbp_last_active_time', $new_time );
  1067. return (int) apply_filters( 'bbp_update_forum_last_active', $new_time, $forum_id );
  1068. }
  1069. /**
  1070. * Update the forum sub-forum count
  1071. *
  1072. * @since bbPress (r2625)
  1073. *
  1074. * @param int $forum_id Optional. Forum id
  1075. * @uses bbp_get_forum_id() To get the forum id
  1076. * @return bool True on success, false on failure
  1077. */
  1078. function bbp_update_forum_subforum_count( $forum_id = 0, $subforums = 0 ) {
  1079. $forum_id = bbp_get_forum_id( $forum_id );
  1080. if ( empty( $subforums ) )
  1081. $subforums = count( bbp_forum_query_subforum_ids( $forum_id ) );
  1082. update_post_meta( $forum_id, '_bbp_forum_subforum_count', (int) $subforums );
  1083. return (int) apply_filters( 'bbp_update_forum_subforum_count', (int) $subforums, $forum_id );
  1084. }
  1085. /**
  1086. * Adjust the total topic count of a forum
  1087. *
  1088. * @since bbPress (r2464)
  1089. *
  1090. * @param int $forum_id Optional. Forum id or topic id. It is checked whether it
  1091. * is a topic or a forum. If it's a topic, its parent,
  1092. * i.e. the forum is automatically retrieved.
  1093. * @param bool $total_count Optional. To return the total count or normal
  1094. * count?
  1095. * @uses bbp_get_forum_id() To get the forum id
  1096. * @uses bbp_forum_query_subforum_ids() To get the subforum ids
  1097. * @uses bbp_update_forum_topic_count() To update the forum topic count
  1098. * @uses bbp_forum_query_topic_ids() To get the forum topic ids
  1099. * @uses update_post_meta() To update the forum's topic count meta
  1100. * @uses apply_filters() Calls 'bbp_update_forum_topic_count' with the topic
  1101. * count and forum id
  1102. * @return int Forum topic count
  1103. */
  1104. function bbp_update_forum_topic_count( $forum_id = 0 ) {
  1105. $forum_id = bbp_get_forum_id( $forum_id );
  1106. $children_topic_count = 0;
  1107. // Loop through subforums and add together forum topic counts
  1108. $children = bbp_forum_query_subforum_ids( $forum_id );
  1109. if ( !empty( $children ) ) {
  1110. foreach ( (array) $children as $child ) {
  1111. $children_topic_count += bbp_update_forum_topic_count( $child ); // Recursive
  1112. }
  1113. }
  1114. // Get total topics for this forum
  1115. $topics = (int) count( bbp_forum_query_topic_ids( $forum_id ) );
  1116. // Calculate total topics in this forum
  1117. $total_topics = $topics + $children_topic_count;
  1118. // Update the count
  1119. update_post_meta( $forum_id, '_bbp_topic_count', (int) $topics );
  1120. update_post_meta( $forum_id, '_bbp_total_topic_count', (int) $total_topics );
  1121. return (int) apply_filters( 'bbp_update_forum_topic_count', (int) $total_topics, $forum_id );
  1122. }
  1123. /**
  1124. * Adjust the total hidden topic count of a forum (hidden includes trashed and spammed topics)
  1125. *
  1126. * @since bbPress (r2888)
  1127. *
  1128. * @param int $forum_id Optional. Topic id to update
  1129. * @param int $topic_count Optional. Set the topic count manually
  1130. * @uses bbp_is_topic() To check if the supplied id is a topic
  1131. * @uses bbp_get_topic_id() To get the topic id
  1132. * @uses bbp_get_topic_forum_id() To get the topic forum id
  1133. * @uses bbp_get_forum_id() To get the forum id
  1134. * @uses wpdb::prepare() To prepare our sql query
  1135. * @uses wpdb::get_col() To execute our query and get the column back
  1136. * @uses update_post_meta() To update the forum hidden topic count meta
  1137. * @uses apply_filters() Calls 'bbp_update_forum_topic_count_hidden' with the
  1138. * hidden topic count and forum id
  1139. * @return int Topic hidden topic count
  1140. */
  1141. function bbp_update_forum_topic_count_hidden( $forum_id = 0, $topic_count = 0 ) {
  1142. global $wpdb;
  1143. // If topic_id was passed as $forum_id, then get its forum
  1144. if ( bbp_is_topic( $forum_id ) ) {
  1145. $topic_id = bbp_get_topic_id( $forum_id );
  1146. $forum_id = bbp_get_topic_forum_id( $topic_id );
  1147. // $forum_id is not a topic_id, so validate and proceed
  1148. } else {
  1149. $forum_id = bbp_get_forum_id( $forum_id );
  1150. }
  1151. // Can't update what isn't there
  1152. if ( !empty( $forum_id ) ) {
  1153. // Get topics of forum
  1154. if ( empty( $topic_count ) ) {
  1155. $post_status = "'" . implode( "','", array( bbp_get_trash_status_id(), bbp_get_spam_status_id() ) ) . "'";
  1156. $topic_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';", $forum_id, bbp_get_topic_post_type() ) );
  1157. }
  1158. // Update the count
  1159. update_post_meta( $forum_id, '_bbp_topic_count_hidden', (int) $topic_count );
  1160. }
  1161. return (int) apply_filters( 'bbp_update_forum_topic_count_hidden', (int) $topic_count, $forum_id );
  1162. }
  1163. /**
  1164. * Adjust the total reply count of a forum
  1165. *
  1166. * @since bbPress (r2464)
  1167. *
  1168. * @param int $forum_id Optional. Forum id or topic id. It is checked whether it
  1169. * is a topic or a forum. If it's a topic, its parent,
  1170. * i.e. the forum is automatically retrieved.
  1171. * @param bool $total_count Optional. To return the total count or normal
  1172. * count?
  1173. * @uses bbp_get_forum_id() To get the forum id
  1174. * @uses bbp_forum_query_subforum_ids() To get the subforum ids
  1175. * @uses bbp_update_forum_reply_count() To update the forum reply count
  1176. * @uses bbp_forum_query_topic_ids() To get the forum topic ids
  1177. * @uses wpdb::prepare() To prepare the sql statement
  1178. * @uses wpdb::get_var() To execute the query and get the var back
  1179. * @uses update_post_meta() To update the forum's reply count meta
  1180. * @uses apply_filters() Calls 'bbp_update_forum_topic_count' with the reply
  1181. * count and forum id
  1182. * @return int Forum reply count
  1183. */
  1184. function bbp_update_forum_reply_count( $forum_id = 0 ) {
  1185. global $wpdb;
  1186. $forum_id = bbp_get_forum_id( $forum_id );
  1187. $children_reply_count = 0;
  1188. // Loop through children and add together forum reply counts
  1189. $children = bbp_forum_query_subforum_ids( $forum_id );
  1190. if ( !empty( $children ) ) {
  1191. foreach ( (array) $children as $child ) {
  1192. $children_reply_count += bbp_update_forum_reply_count( $child );
  1193. }
  1194. }
  1195. // Don't count replies if the forum is a category
  1196. $topic_ids = bbp_forum_query_topic_ids( $forum_id );
  1197. if ( !empty( $topic_ids ) ) {
  1198. $topic_ids = implode( ',', wp_parse_id_list( $topic_ids ) );
  1199. $reply_count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(ID) FROM {$wpdb->posts} WHERE post_parent IN ( {$topic_ids} ) AND post_status = '%s' AND post_type = '%s';", bbp_get_public_status_id(), bbp_get_reply_post_type() ) );
  1200. } else {
  1201. $reply_count = 0;
  1202. }
  1203. // Calculate total replies in this forum
  1204. $total_replies = (int) $reply_count + $children_reply_count;
  1205. // Update the count
  1206. update_post_meta( $forum_id, '_bbp_reply_count', (int) $reply_count );
  1207. update_post_meta( $forum_id, '_bbp_total_reply_count', (int) $total_replies );
  1208. return (int) apply_filters( 'bbp_update_forum_reply_count', (int) $total_replies, $forum_id );
  1209. }
  1210. /**
  1211. * Updates the counts of a forum.
  1212. *
  1213. * This calls a few internal functions that all run manual queries against the
  1214. * database to get their results. As such, this function can be costly to run
  1215. * but is necessary to keep everything accurate.
  1216. *
  1217. * @since bbPress (r2908)
  1218. *
  1219. * @param mixed $args Supports these arguments:
  1220. * - forum_id: Forum id
  1221. * - last_topic_id: Last topic id
  1222. * - last_reply_id: Last reply id
  1223. * - last_active_id: Last active post id
  1224. * - last_active_time: last active time
  1225. * @uses bbp_update_forum_last_topic_id() To update the forum last topic id
  1226. * @uses bbp_update_forum_last_reply_id() To update the forum last reply id
  1227. * @uses bbp_update_forum_last_active_id() To update the last active post id
  1228. * @uses get_post_field() To get the post date of the last active id
  1229. * @uses bbp_update_forum_last_active_time() To update the last active time
  1230. * @uses bbp_update_forum_subforum_count() To update the subforum count
  1231. * @uses bbp_update_forum_topic_count() To update the forum topic count
  1232. * @uses bbp_update_forum_reply_count() To update the forum reply count
  1233. * @uses bbp_update_forum_topic_count_hidden() To update the hidden topic count
  1234. */
  1235. function bbp_update_forum( $args = '' ) {
  1236. // Parse arguments against default values
  1237. $r = bbp_parse_args( $args, array(
  1238. 'forum_id' => 0,
  1239. 'post_parent' => 0,
  1240. 'last_topic_id' => 0,
  1241. 'last_reply_id' => 0,
  1242. 'last_active_id' => 0,
  1243. 'last_active_time' => 0,
  1244. 'last_active_status' => bbp_get_public_status_id()
  1245. ), 'update_forum' );
  1246. // Last topic and reply ID's
  1247. bbp_update_forum_last_topic_id( $r['forum_id'], $r['last_topic_id'] );
  1248. bbp_update_forum_last_reply_id( $r['forum_id'], $r['last_reply_id'] );
  1249. // Active dance
  1250. $r['last_active_id'] = bbp_update_forum_last_active_id( $r['forum_id'], $r['last_active_id'] );
  1251. // If no active time was passed, get it from the last_active_id
  1252. if ( empty( $r['last_active_time'] ) ) {
  1253. $r['last_active_time'] = get_post_field( 'post_date', $r['last_active_id'] );
  1254. }
  1255. if ( bbp_get_public_status_id() === $r['last_active_status'] ) {
  1256. bbp_update_forum_last_active_time( $r['forum_id'], $r['last_active_time'] );
  1257. }
  1258. // Counts
  1259. bbp_update_forum_subforum_count ( $r['forum_id'] );
  1260. bbp_update_forum_reply_count ( $r['forum_id'] );
  1261. bbp_update_forum_topic_count ( $r['forum_id'] );
  1262. bbp_update_forum_topic_count_hidden( $r['forum_id'] );
  1263. // Update the parent forum if one was passed
  1264. if ( !empty( $r['post_parent'] ) && is_numeric( $r['post_parent'] ) ) {
  1265. bbp_update_forum( array(
  1266. 'forum_id' => $r['post_parent'],
  1267. 'post_parent' => get_post_field( 'post_parent', $r['post_parent'] )
  1268. ) );
  1269. }
  1270. }
  1271. /** Helpers *******************************************************************/
  1272. /**
  1273. * Return an associative array of available topic statuses
  1274. *
  1275. * @since bbPress (r5059)
  1276. *
  1277. * @return array
  1278. */
  1279. function bbp_get_forum_statuses() {
  1280. return apply_filters( 'bbp_get_forum_statuses', array(
  1281. 'open' => _x( 'Open', 'Open the forum', 'bbpress' ),
  1282. 'closed' => _x( 'Closed', 'Close the forum', 'bbpress' )
  1283. ) );
  1284. }
  1285. /**
  1286. * Return an associative array of forum types
  1287. *
  1288. * @since bbPress (r5059)
  1289. *
  1290. * @return array
  1291. */
  1292. function bbp_get_forum_types() {
  1293. return apply_filters( 'bbp_get_forum_types', array(
  1294. 'forum' => _x( 'Forum', 'Forum accepts new topics', 'bbpress' ),
  1295. 'category' => _x( 'Category', 'Forum is a category', 'bbpress' )
  1296. ) );
  1297. }
  1298. /**
  1299. * Return an associative array of forum visibility
  1300. *
  1301. * @since bbPress (r5059)
  1302. *
  1303. * @return array
  1304. */
  1305. function bbp_get_forum_visibilities() {
  1306. return apply_filters( 'bbp_get_forum_visibilities', array(
  1307. bbp_get_public_status_id() => _x( 'Public', 'Make forum public', 'bbpress' ),
  1308. bbp_get_private_status_id() => _x( 'Private', 'Make forum private', 'bbpress' ),
  1309. bbp_get_hidden_status_id() => _x( 'Hidden', 'Make forum hidden', 'bbpress' )
  1310. ) );
  1311. }
  1312. /** Queries *******************************************************************/
  1313. /**
  1314. * Returns the hidden forum ids
  1315. *
  1316. * Only hidden forum ids are returned. Public and private ids are not.
  1317. *
  1318. * @since bbPress (r3007)
  1319. *
  1320. * @uses get_option() Returns the unserialized array of hidden forum ids
  1321. * @uses apply_filters() Calls 'bbp_forum_query_topic_ids' with the topic ids
  1322. * and forum id
  1323. */
  1324. function bbp_get_hidden_forum_ids() {
  1325. $forum_ids = get_option( '_bbp_hidden_forums', array() );
  1326. return apply_filters( 'bbp_get_hidden_forum_ids', (array) $forum_ids );
  1327. }
  1328. /**
  1329. * Returns the private forum ids
  1330. *
  1331. * Only private forum ids are returned. Public and hidden ids are not.
  1332. *
  1333. * @since bbPress (r3007)
  1334. *
  1335. * @uses get_option() Returns the unserialized array of private forum ids
  1336. * @uses apply_filters() Calls 'bbp_forum_query_topic_ids' with the topic ids
  1337. * and forum id
  1338. */
  1339. function bbp_get_private_forum_ids() {
  1340. $forum_ids = get_option( '_bbp_private_forums', array() );
  1341. return apply_filters( 'bbp_get_private_forum_ids', (array) $forum_ids );
  1342. }
  1343. /**
  1344. * Returns a meta_query that either includes or excludes hidden forum IDs
  1345. * from a query.
  1346. *
  1347. * @since bbPress (r3291)
  1348. *
  1349. * @param string Optional. The type of value to return. (string|array|meta_query)
  1350. *
  1351. * @uses bbp_is_user_keymaster()
  1352. * @uses bbp_get_hidden_forum_ids()
  1353. * @uses bbp_get_private_forum_ids()
  1354. * @uses apply_filters()
  1355. */
  1356. function bbp_exclude_forum_ids( $type = 'string' ) {
  1357. // Setup arrays
  1358. $private = $hidden = $meta_query = $forum_ids = array();
  1359. // Default return value
  1360. switch ( $type ) {
  1361. case 'string' :
  1362. $retval = '';
  1363. break;
  1364. case 'array' :
  1365. $retval = array();
  1366. break;
  1367. case 'meta_query' :
  1368. $retval = array( array() ) ;
  1369. break;
  1370. }
  1371. // Exclude for everyone but keymasters
  1372. if ( ! bbp_is_user_keymaster() ) {
  1373. // Private forums
  1374. if ( !current_user_can( 'read_private_forums' ) )
  1375. $private = bbp_get_private_forum_ids();
  1376. // Hidden forums
  1377. if ( !current_user_can( 'read_hidden_forums' ) )
  1378. $hidden = bbp_get_hidden_forum_ids();
  1379. // Merge private and hidden forums together
  1380. $forum_ids = (array) array_filter( wp_parse_id_list( array_merge( $private, $hidden ) ) );
  1381. // There are forums that need to be excluded
  1382. if ( !empty( $forum_ids ) ) {
  1383. switch ( $type ) {
  1384. // Separate forum ID's into a comma separated string
  1385. case 'string' :
  1386. $retval = implode( ',', $forum_ids );
  1387. break;
  1388. // Use forum_ids array
  1389. case 'array' :
  1390. $retval = $forum_ids;
  1391. break;
  1392. // Build a meta_query
  1393. case 'meta_query' :
  1394. $retval = array(
  1395. 'key' => '_bbp_forum_id',
  1396. 'value' => implode( ',', $forum_ids ),
  1397. 'type' => 'numeric',
  1398. 'compare' => ( 1 < count( $forum_ids ) ) ? 'NOT IN' : '!='
  1399. );
  1400. break;
  1401. }
  1402. }
  1403. }
  1404. // Filter and return the results
  1405. return apply_filters( 'bbp_exclude_forum_ids', $retval, $forum_ids, $type );
  1406. }
  1407. /**
  1408. * Adjusts forum, topic, and reply queries to exclude items that might be
  1409. * contained inside hidden or private forums that the user does not have the
  1410. * capability to view.
  1411. *
  1412. * Doing it with an action allows us to trap all WP_Query's rather than needing
  1413. * to hardcode this logic into each query. It also protects forum content for
  1414. * plugins that might be doing their own queries.
  1415. *
  1416. * @since bbPress (r3291)
  1417. *
  1418. * @param WP_Query $posts_query
  1419. *
  1420. * @uses apply_filters()
  1421. * @uses bbp_exclude_forum_ids()
  1422. * @uses bbp_get_topic_post_type()
  1423. * @uses bbp_get_reply_post_type()
  1424. * @return WP_Query
  1425. */
  1426. function bbp_pre_get_posts_normalize_forum_visibility( $posts_query = null ) {
  1427. // Bail if all forums are explicitly allowed
  1428. if ( true === apply_filters( 'bbp_include_all_forums', false, $posts_query ) ) {
  1429. return;
  1430. }
  1431. // Bail if $posts_query is not an object or of incorrect class
  1432. if ( !is_object( $posts_query ) || !is_a( $posts_query, 'WP_Query' ) ) {
  1433. return;
  1434. }
  1435. // Get query post types array .
  1436. $post_types = (array) $posts_query->get( 'post_type' );
  1437. // Forums
  1438. if ( bbp_get_forum_post_type() === implode( '', $post_types ) ) {
  1439. // Prevent accidental wp-admin post_row override
  1440. if ( is_admin() && isset( $_REQUEST['post_status'] ) ) {
  1441. return;
  1442. }
  1443. /** Default ***********************************************************/
  1444. // Get any existing post status
  1445. $post_stati = $posts_query->get( 'post_status' );
  1446. // Default to public status
  1447. if ( empty( $post_stati ) ) {
  1448. $post_stati[] = bbp_get_public_status_id();
  1449. // Split the status string
  1450. } elseif ( is_string( $post_stati ) ) {
  1451. $post_stati = explode( ',', $post_stati );
  1452. }
  1453. /** Private ***********************************************************/
  1454. // Remove bbp_get_private_status_id() if user is not capable
  1455. if ( ! current_user_can( 'read_private_forums' ) ) {
  1456. $key = array_search( bbp_get_private_status_id(), $post_stati );
  1457. if ( !empty( $key ) ) {
  1458. unset( $post_stati[$key] );
  1459. }
  1460. // ...or add it if they are
  1461. } else {
  1462. $post_stati[] = bbp_get_private_status_id();
  1463. }
  1464. /** Hidden ************************************************************/
  1465. // Remove bbp_get_hidden_status_id() if user is not capable
  1466. if ( ! current_user_can( 'read_hidden_forums' ) ) {
  1467. $key = array_search( bbp_get_hidden_status_id(), $post_stati );
  1468. if ( !empty( $key ) ) {
  1469. unset( $post_stati[$key] );
  1470. }
  1471. // ...or add it if they are
  1472. } else {
  1473. $post_stati[] = bbp_get_hidden_status_id();
  1474. }
  1475. // Add the statuses
  1476. $posts_query->set( 'post_status', array_unique( array_filter( $post_stati ) ) );
  1477. }
  1478. // Topics Or Replies
  1479. if ( array_intersect( array( bbp_get_topic_post_type(), bbp_get_reply_post_type() ), $post_types ) ) {
  1480. // Get forums to exclude
  1481. $forum_ids = bbp_exclude_forum_ids( 'meta_query' );
  1482. // Bail if no forums to exclude
  1483. if ( ! array_filter( $forum_ids ) ) {
  1484. return;
  1485. }
  1486. // Get any existing meta queries
  1487. $meta_query = $posts_query->get( 'meta_query' );
  1488. // Add our meta query to existing
  1489. $meta_query[] = $forum_ids;
  1490. // Set the meta_query var
  1491. $posts_query->set( 'meta_query', $meta_query );
  1492. }
  1493. }
  1494. /**
  1495. * Returns the forum's topic ids
  1496. *
  1497. * Only topics with published and closed statuses are returned
  1498. *
  1499. * @since bbPress (r2908)
  1500. *
  1501. * @param int $forum_id Forum id
  1502. * @uses bbp_get_topic_post_type() To get the topic post type
  1503. * @uses bbp_get_public_child_ids() To get the topic ids
  1504. * @uses apply_filters() Calls 'bbp_forum_query_topic_ids' with the topic ids
  1505. * and forum id
  1506. */
  1507. function bbp_forum_query_topic_ids( $forum_id ) {
  1508. $topic_ids = bbp_get_public_child_ids( $forum_id, bbp_get_topic_post_type() );
  1509. return apply_filters( 'bbp_forum_query_topic_ids', $topic_ids, $forum_id );
  1510. }
  1511. /**
  1512. * Returns the forum's subforum ids
  1513. *
  1514. * Only forums with published status are returned
  1515. *
  1516. * @since bbPress (r2908)
  1517. *
  1518. * @param int $forum_id Forum id
  1519. * @uses bbp_get_forum_post_type() To get the forum post type
  1520. * @uses bbp_get_public_child_ids() To get the forum ids
  1521. * @uses apply_filters() Calls 'bbp_forum_query_subforum_ids' with the subforum
  1522. * ids and forum id
  1523. */
  1524. function bbp_forum_query_subforum_ids( $forum_id ) {
  1525. $subforum_ids = bbp_get_all_child_ids( $forum_id, bbp_get_forum_post_type() );
  1526. //usort( $subforum_ids, '_bbp_forum_query_usort_subforum_ids' );
  1527. return apply_filters( 'bbp_get_forum_subforum_ids', $subforum_ids, $forum_id );
  1528. }
  1529. /**
  1530. * Callback to sort forum ID's based on last active time
  1531. *
  1532. * @since bbPress (r3789)
  1533. * @param int $a First forum ID to compare
  1534. * @param int $b Second forum ID to compare
  1535. * @return Position change based on sort
  1536. */
  1537. function _bbp_forum_query_usort_subforum_ids( $a = 0, $b = 0 ) {
  1538. $ta = get_post_meta( $a, '_bbp_last_active_time', true );
  1539. $tb = get_post_meta( $b, '_bbp_last_active_time', true );
  1540. return ( $ta < $tb ) ? -1 : 1;
  1541. }
  1542. /**
  1543. * Returns the forum's last reply id
  1544. *
  1545. * @since bbPress (r2908)
  1546. *
  1547. * @param int $forum_id Forum id
  1548. * @param int $topic_ids Optional. Topic ids
  1549. * @uses wp_cache_get() To check for cache and retrieve it
  1550. * @uses bbp_forum_query_topic_ids() To get the forum's topic ids
  1551. * @uses wpdb::prepare() To prepare the query
  1552. * @uses wpdb::get_var() To execute the query and get the var back
  1553. * @uses bbp_get_reply_post_type() To get the reply post type
  1554. * @uses wp_cache_set() To set the cache for future use
  1555. * @uses apply_filters() Calls 'bbp_forum_query_last_reply_id' with the reply id
  1556. * and forum id
  1557. */
  1558. function bbp_forum_query_last_reply_id( $forum_id, $topic_ids = 0 ) {
  1559. global $wpdb;
  1560. $cache_id = 'bbp_get_forum_' . $forum_id . '_reply_id';
  1561. $reply_id = (int) wp_cache_get( $cache_id, 'bbpress_posts' );
  1562. if ( false === $reply_id ) {
  1563. if ( empty( $topic_ids ) ) {
  1564. $topic_ids = bbp_forum_query_topic_ids( $forum_id );
  1565. }
  1566. if ( !empty( $topic_ids ) ) {
  1567. $topic_ids = implode( ',', wp_parse_id_list( $topic_ids ) );
  1568. $reply_id = (int) $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_parent IN ( {$topic_ids} ) AND post_status = '%s' AND post_type = '%s' ORDER BY ID DESC LIMIT 1;", bbp_get_public_status_id(), bbp_get_reply_post_type() ) );
  1569. wp_cache_set( $cache_id, $reply_id, 'bbpress_posts' ); // May be (int) 0
  1570. } else {
  1571. wp_cache_set( $cache_id, '0', 'bbpress_posts' );
  1572. }
  1573. }
  1574. return (int) apply_filters( 'bbp_get_forum_last_reply_id', (int) $reply_id, $forum_id );
  1575. }
  1576. /** Listeners *****************************************************************/
  1577. /**
  1578. * Check if it's a hidden forum or a topic or reply of a hidden forum and if
  1579. * the user can't view it, then sets a 404
  1580. *
  1581. * @since bbPress (r2996)
  1582. *
  1583. * @uses current_user_can() To check if the current user can read private forums
  1584. * @uses is_singular() To check if it's a singular page
  1585. * @uses bbp_is_user_keymaster() To check if user is a keymaster
  1586. * @uses bbp_get_forum_post_type() To get the forum post type
  1587. * @uses bbp_get_topic_post_type() To get the topic post type
  1588. * @uses bbp_get_reply_post_type() TO get the reply post type
  1589. * @uses bbp_get_topic_forum_id() To get the topic forum id
  1590. * @uses bbp_get_reply_forum_id() To get the reply forum id
  1591. * @uses bbp_is_forum_hidden() To check if the forum is hidden or not
  1592. * @uses bbp_set_404() To set a 404 status
  1593. */
  1594. function bbp_forum_enforce_hidden() {
  1595. // Bail if not viewing a single item or if user has caps
  1596. if ( !is_singular() || bbp_is_user_keymaster() || current_user_can( 'read_hidden_forums' ) )
  1597. return;
  1598. global $wp_query;
  1599. // Define local variable
  1600. $forum_id = 0;
  1601. // Check post type
  1602. switch ( $wp_query->get( 'post_type' ) ) {
  1603. // Forum
  1604. case bbp_get_forum_post_type() :
  1605. $forum_id = bbp_get_forum_id( $wp_query->post->ID );
  1606. break;
  1607. // Topic
  1608. case bbp_get_topic_post_type() :
  1609. $forum_id = bbp_get_topic_forum_id( $wp_query->post->ID );
  1610. break;
  1611. // Reply
  1612. case bbp_get_reply_post_type() :
  1613. $forum_id = bbp_get_reply_forum_id( $wp_query->post->ID );
  1614. break;
  1615. }
  1616. // If forum is explicitly hidden and user not capable, set 404
  1617. if ( !empty( $forum_id ) && bbp_is_forum_hidden( $forum_id ) && !current_user_can( 'read_hidden_forums' ) )
  1618. bbp_set_404();
  1619. }
  1620. /**
  1621. * Check if it's a private forum or a topic or reply of a private forum and if
  1622. * the user can't view it, then sets a 404
  1623. *
  1624. * @since bbPress (r2996)
  1625. *
  1626. * @uses current_user_can() To check if the current user can read private forums
  1627. * @uses is_singular() To check if it's a singular page
  1628. * @uses bbp_is_user_keymaster() To check if user is a keymaster
  1629. * @uses bbp_get_forum_post_type() To get the forum post type
  1630. * @uses bbp_get_topic_post_type() To get the topic post type
  1631. * @uses bbp_get_reply_post_type() TO get the reply post type
  1632. * @uses bbp_get_topic_forum_id() To get the topic forum id
  1633. * @uses bbp_get_reply_forum_id() To get the reply forum id
  1634. * @uses bbp_is_forum_private() To check if the forum is private or not
  1635. * @uses bbp_set_404() To set a 404 status
  1636. */
  1637. function bbp_forum_enforce_private() {
  1638. // Bail if not viewing a single item or if user has caps
  1639. if ( !is_singular() || bbp_is_user_keymaster() || current_user_can( 'read_private_forums' ) )
  1640. return;
  1641. global $wp_query;
  1642. // Define local variable
  1643. $forum_id = 0;
  1644. // Check post type
  1645. switch ( $wp_query->get( 'post_type' ) ) {
  1646. // Forum
  1647. case bbp_get_forum_post_type() :
  1648. $forum_id = bbp_get_forum_id( $wp_query->post->ID );
  1649. break;
  1650. // Topic
  1651. case bbp_get_topic_post_type() :
  1652. $forum_id = bbp_get_topic_forum_id( $wp_query->post->ID );
  1653. break;
  1654. // Reply
  1655. case bbp_get_reply_post_type() :
  1656. $forum_id = bbp_get_reply_forum_id( $wp_query->post->ID );
  1657. break;
  1658. }
  1659. // If forum is explicitly hidden and user not capable, set 404
  1660. if ( !empty( $forum_id ) && bbp_is_forum_private( $forum_id ) && !current_user_can( 'read_private_forums' ) )
  1661. bbp_set_404();
  1662. }
  1663. /** Permissions ***************************************************************/
  1664. /**
  1665. * Redirect if unathorized user is attempting to edit a forum
  1666. *
  1667. * @since bbPress (r3607)
  1668. *
  1669. * @uses bbp_is_forum_edit()
  1670. * @uses current_user_can()
  1671. * @uses bbp_get_forum_id()
  1672. * @uses wp_safe_redirect()
  1673. * @uses bbp_get_forum_permalink()
  1674. */
  1675. function bbp_check_forum_edit() {
  1676. // Bail if not editing a topic
  1677. if ( !bbp_is_forum_edit() )
  1678. return;
  1679. // User cannot edit topic, so redirect back to reply
  1680. if ( !current_user_can( 'edit_forum', bbp_get_forum_id() ) ) {
  1681. wp_safe_redirect( bbp_get_forum_permalink() );
  1682. exit();
  1683. }
  1684. }
  1685. /**
  1686. * Delete all topics (and their replies) for a specific forum ID
  1687. *
  1688. * @since bbPress (r3668)
  1689. *
  1690. * @param int $forum_id
  1691. * @uses bbp_get_forum_id() To validate the forum ID
  1692. * @uses bbp_is_forum() To make sure it's a forum
  1693. * @uses bbp_get_topic_post_type() To get the topic post type
  1694. * @uses bbp_topics() To make sure there are topics to loop through
  1695. * @uses wp_trash_post() To trash the post
  1696. * @uses update_post_meta() To update the forum meta of trashed topics
  1697. * @return If forum is not valid
  1698. */
  1699. function bbp_delete_forum_topics( $forum_id = 0 ) {
  1700. // Validate forum ID
  1701. $forum_id = bbp_get_forum_id( $forum_id );
  1702. if ( empty( $forum_id ) )
  1703. return;
  1704. // Forum is being permanently deleted, so its content has go too
  1705. // Note that we get all post statuses here
  1706. $topics = new WP_Query( array(
  1707. 'suppress_filters' => true,
  1708. 'post_type' => bbp_get_topic_post_type(),
  1709. 'post_parent' => $forum_id,
  1710. 'post_status' => array_keys( get_post_stati() ),
  1711. 'posts_per_page' => -1,
  1712. 'nopaging' => true,
  1713. 'fields' => 'id=>parent'
  1714. ) );
  1715. // Loop through and delete child topics. Topic replies will get deleted by
  1716. // the bbp_delete_topic() action.
  1717. if ( !empty( $topics->posts ) ) {
  1718. foreach ( $topics->posts as $topic ) {
  1719. wp_delete_post( $topic->ID, true );
  1720. }
  1721. // Reset the $post global
  1722. wp_reset_postdata();
  1723. }
  1724. // Cleanup
  1725. unset( $topics );
  1726. }
  1727. /**
  1728. * Trash all topics inside a forum
  1729. *
  1730. * @since bbPress (r3668)
  1731. *
  1732. * @param int $forum_id
  1733. * @uses bbp_get_forum_id() To validate the forum ID
  1734. * @uses bbp_is_forum() To make sure it's a forum
  1735. * @uses bbp_get_public_status_id() To return public post status
  1736. * @uses bbp_get_closed_status_id() To return closed post status
  1737. * @uses bbp_get_pending_status_id() To return pending post status
  1738. * @uses bbp_get_topic_post_type() To get the topic post type
  1739. * @uses wp_trash_post() To trash the post
  1740. * @uses update_post_meta() To update the forum meta of trashed topics
  1741. * @return If forum is not valid
  1742. */
  1743. function bbp_trash_forum_topics( $forum_id = 0 ) {
  1744. // Validate forum ID
  1745. $forum_id = bbp_get_forum_id( $forum_id );
  1746. if ( empty( $forum_id ) )
  1747. return;
  1748. // Allowed post statuses to pre-trash
  1749. $post_stati = implode( ',', array(
  1750. bbp_get_public_status_id(),
  1751. bbp_get_closed_status_id(),
  1752. bbp_get_pending_status_id()
  1753. ) );
  1754. // Forum is being trashed, so its topics and replies are trashed too
  1755. $topics = new WP_Query( array(
  1756. 'suppress_filters' => true,
  1757. 'post_type' => bbp_get_topic_post_type(),
  1758. 'post_parent' => $forum_id,
  1759. 'post_status' => $post_stati,
  1760. 'posts_per_page' => -1,
  1761. 'nopaging' => true,
  1762. 'fields' => 'id=>parent'
  1763. ) );
  1764. // Loop through and trash child topics. Topic replies will get trashed by
  1765. // the bbp_trash_topic() action.
  1766. if ( !empty( $topics->posts ) ) {
  1767. // Prevent debug notices
  1768. $pre_trashed_topics = array();
  1769. // Loop through topics, trash them, and add them to array
  1770. foreach ( $topics->posts as $topic ) {
  1771. wp_trash_post( $topic->ID, true );
  1772. $pre_trashed_topics[] = $topic->ID;
  1773. }
  1774. // Set a post_meta entry of the topics that were trashed by this action.
  1775. // This is so we can possibly untrash them, without untrashing topics
  1776. // that were purposefully trashed before.
  1777. update_post_meta( $forum_id, '_bbp_pre_trashed_topics', $pre_trashed_topics );
  1778. // Reset the $post global
  1779. wp_reset_postdata();
  1780. }
  1781. // Cleanup
  1782. unset( $topics );
  1783. }
  1784. /**
  1785. * Trash all topics inside a forum
  1786. *
  1787. * @since bbPress (r3668)
  1788. *
  1789. * @param int $forum_id
  1790. * @uses bbp_get_forum_id() To validate the forum ID
  1791. * @uses bbp_is_forum() To make sure it's a forum
  1792. * @uses get_post_meta() To update the forum meta of trashed topics
  1793. * @uses wp_untrash_post() To trash the post
  1794. * @return If forum is not valid
  1795. */
  1796. function bbp_untrash_forum_topics( $forum_id = 0 ) {
  1797. // Validate forum ID
  1798. $forum_id = bbp_get_forum_id( $forum_id );
  1799. if ( empty( $forum_id ) )
  1800. return;
  1801. // Get the topics that were not previously trashed
  1802. $pre_trashed_topics = get_post_meta( $forum_id, '_bbp_pre_trashed_topics', true );
  1803. // There are topics to untrash
  1804. if ( !empty( $pre_trashed_topics ) ) {
  1805. // Maybe reverse the trashed topics array
  1806. if ( is_array( $pre_trashed_topics ) )
  1807. $pre_trashed_topics = array_reverse( $pre_trashed_topics );
  1808. // Loop through topics
  1809. foreach ( (array) $pre_trashed_topics as $topic ) {
  1810. wp_untrash_post( $topic );
  1811. }
  1812. }
  1813. }
  1814. /** Before Delete/Trash/Untrash ***********************************************/
  1815. /**
  1816. * Called before deleting a forum.
  1817. *
  1818. * This function is supplemental to the actual forum deletion which is
  1819. * handled by WordPress core API functions. It is used to clean up after
  1820. * a forum that is being deleted.
  1821. *
  1822. * @since bbPress (r3668)
  1823. * @uses bbp_get_forum_id() To get the forum id
  1824. * @uses bbp_is_forum() To check if the passed id is a forum
  1825. * @uses do_action() Calls 'bbp_delete_forum' with the forum id
  1826. */
  1827. function bbp_delete_forum( $forum_id = 0 ) {
  1828. $forum_id = bbp_get_forum_id( $forum_id );
  1829. if ( empty( $forum_id ) || !bbp_is_forum( $forum_id ) )
  1830. return false;
  1831. do_action( 'bbp_delete_forum', $forum_id );
  1832. }
  1833. /**
  1834. * Called before trashing a forum
  1835. *
  1836. * This function is supplemental to the actual forum being trashed which is
  1837. * handled by WordPress core API functions. It is used to clean up after
  1838. * a forum that is being trashed.
  1839. *
  1840. * @since bbPress (r3668)
  1841. * @uses bbp_get_forum_id() To get the forum id
  1842. * @uses bbp_is_forum() To check if the passed id is a forum
  1843. * @uses do_action() Calls 'bbp_trash_forum' with the forum id
  1844. */
  1845. function bbp_trash_forum( $forum_id = 0 ) {
  1846. $forum_id = bbp_get_forum_id( $forum_id );
  1847. if ( empty( $forum_id ) || !bbp_is_forum( $forum_id ) )
  1848. return false;
  1849. do_action( 'bbp_trash_forum', $forum_id );
  1850. }
  1851. /**
  1852. * Called before untrashing a forum
  1853. *
  1854. * @since bbPress (r3668)
  1855. * @uses bbp_get_forum_id() To get the forum id
  1856. * @uses bbp_is_forum() To check if the passed id is a forum
  1857. * @uses do_action() Calls 'bbp_untrash_forum' with the forum id
  1858. */
  1859. function bbp_untrash_forum( $forum_id = 0 ) {
  1860. $forum_id = bbp_get_forum_id( $forum_id );
  1861. if ( empty( $forum_id ) || !bbp_is_forum( $forum_id ) )
  1862. return false;
  1863. do_action( 'bbp_untrash_forum', $forum_id );
  1864. }
  1865. /** After Delete/Trash/Untrash ************************************************/
  1866. /**
  1867. * Called after deleting a forum
  1868. *
  1869. * @since bbPress (r3668)
  1870. * @uses bbp_get_forum_id() To get the forum id
  1871. * @uses bbp_is_forum() To check if the passed id is a forum
  1872. * @uses do_action() Calls 'bbp_deleted_forum' with the forum id
  1873. */
  1874. function bbp_deleted_forum( $forum_id = 0 ) {
  1875. $forum_id = bbp_get_forum_id( $forum_id );
  1876. if ( empty( $forum_id ) || !bbp_is_forum( $forum_id ) )
  1877. return false;
  1878. do_action( 'bbp_deleted_forum', $forum_id );
  1879. }
  1880. /**
  1881. * Called after trashing a forum
  1882. *
  1883. * @since bbPress (r3668)
  1884. * @uses bbp_get_forum_id() To get the forum id
  1885. * @uses bbp_is_forum() To check if the passed id is a forum
  1886. * @uses do_action() Calls 'bbp_trashed_forum' with the forum id
  1887. */
  1888. function bbp_trashed_forum( $forum_id = 0 ) {
  1889. $forum_id = bbp_get_forum_id( $forum_id );
  1890. if ( empty( $forum_id ) || !bbp_is_forum( $forum_id ) )
  1891. return false;
  1892. do_action( 'bbp_trashed_forum', $forum_id );
  1893. }
  1894. /**
  1895. * Called after untrashing a forum
  1896. *
  1897. * @since bbPress (r3668)
  1898. * @uses bbp_get_forum_id() To get the forum id
  1899. * @uses bbp_is_forum() To check if the passed id is a forum
  1900. * @uses do_action() Calls 'bbp_untrashed_forum' with the forum id
  1901. */
  1902. function bbp_untrashed_forum( $forum_id = 0 ) {
  1903. $forum_id = bbp_get_forum_id( $forum_id );
  1904. if ( empty( $forum_id ) || !bbp_is_forum( $forum_id ) )
  1905. return false;
  1906. do_action( 'bbp_untrashed_forum', $forum_id );
  1907. }