/includes/admin/topics.php

  1. <?php 
  2.  
  3. /** 
  4. * bbPress Topics Admin Class 
  5. * 
  6. * @package bbPress 
  7. * @subpackage Administration 
  8. */ 
  9.  
  10. // Exit if accessed directly 
  11. if ( !defined( 'ABSPATH' ) ) exit; 
  12.  
  13. if ( !class_exists( 'BBP_Topics_Admin' ) ) : 
  14. /** 
  15. * Loads bbPress topics admin area 
  16. * 
  17. * @package bbPress 
  18. * @subpackage Administration 
  19. * @since bbPress (r2464) 
  20. */ 
  21. class BBP_Topics_Admin { 
  22.  
  23. /** Variables *************************************************************/ 
  24.  
  25. /** 
  26. * @var The post type of this admin component 
  27. */ 
  28. private $post_type = ''; 
  29.  
  30. /** Functions *************************************************************/ 
  31.  
  32. /** 
  33. * The main bbPress topics admin loader 
  34. * 
  35. * @since bbPress (r2515) 
  36. * 
  37. * @uses BBP_Topics_Admin::setup_globals() Setup the globals needed 
  38. * @uses BBP_Topics_Admin::setup_actions() Setup the hooks and actions 
  39. * @uses BBP_Topics_Admin::setup_help() Setup the help text 
  40. */ 
  41. public function __construct() { 
  42. $this->setup_globals(); 
  43. $this->setup_actions(); 
  44.  
  45. /** 
  46. * Setup the admin hooks, actions and filters 
  47. * 
  48. * @since bbPress (r2646) 
  49. * @access private 
  50. * 
  51. * @uses add_action() To add various actions 
  52. * @uses add_filter() To add various filters 
  53. * @uses bbp_get_forum_post_type() To get the forum post type 
  54. * @uses bbp_get_topic_post_type() To get the topic post type 
  55. * @uses bbp_get_reply_post_type() To get the reply post type 
  56. */ 
  57. private function setup_actions() { 
  58.  
  59. // Add some general styling to the admin area 
  60. add_action( 'bbp_admin_head', array( $this, 'admin_head' ) ); 
  61.  
  62. // Messages 
  63. add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) ); 
  64.  
  65. // Topic column headers. 
  66. add_filter( 'manage_' . $this->post_type . '_posts_columns', array( $this, 'column_headers' ) ); 
  67.  
  68. // Topic columns (in post row) 
  69. add_action( 'manage_' . $this->post_type . '_posts_custom_column', array( $this, 'column_data' ), 10, 2 ); 
  70. add_filter( 'post_row_actions', array( $this, 'row_actions' ), 10, 2 ); 
  71.  
  72. // Topic metabox actions 
  73. add_action( 'add_meta_boxes', array( $this, 'attributes_metabox' ) ); 
  74. add_action( 'save_post', array( $this, 'attributes_metabox_save' ) ); 
  75.  
  76. // Check if there are any bbp_toggle_topic_* requests on admin_init, also have a message displayed 
  77. add_action( 'load-edit.php', array( $this, 'toggle_topic' ) ); 
  78. add_action( 'admin_notices', array( $this, 'toggle_topic_notice' ) ); 
  79.  
  80. // Anonymous metabox actions 
  81. add_action( 'add_meta_boxes', array( $this, 'author_metabox' ) ); 
  82.  
  83. // Add ability to filter topics and replies per forum 
  84. add_filter( 'restrict_manage_posts', array( $this, 'filter_dropdown' ) ); 
  85. add_filter( 'bbp_request', array( $this, 'filter_post_rows' ) ); 
  86.  
  87. // Contextual Help 
  88. add_action( 'load-edit.php', array( $this, 'edit_help' ) ); 
  89. add_action( 'load-post.php', array( $this, 'new_help' ) ); 
  90. add_action( 'load-post-new.php', array( $this, 'new_help' ) ); 
  91.  
  92. /** 
  93. * Should we bail out of this method? 
  94. * 
  95. * @since bbPress (r4067) 
  96. * @return boolean 
  97. */ 
  98. private function bail() { 
  99. if ( !isset( get_current_screen()->post_type ) || ( $this->post_type !== get_current_screen()->post_type ) ) 
  100. return true; 
  101.  
  102. return false; 
  103.  
  104. /** 
  105. * Admin globals 
  106. * 
  107. * @since bbPress (r2646) 
  108. * @access private 
  109. */ 
  110. private function setup_globals() { 
  111. $this->post_type = bbp_get_topic_post_type(); 
  112.  
  113. /** Contextual Help *******************************************************/ 
  114.  
  115. /** 
  116. * Contextual help for bbPress topic edit page 
  117. * 
  118. * @since bbPress (r3119) 
  119. * @uses get_current_screen() 
  120. */ 
  121. public function edit_help() { 
  122.  
  123. if ( $this->bail() ) return; 
  124.  
  125. // Overview 
  126. get_current_screen()->add_help_tab( array( 
  127. 'id' => 'overview',  
  128. 'title' => __( 'Overview', 'bbpress' ),  
  129. 'content' => 
  130. '<p>' . __( 'This screen displays the individual topics on your site. You can customize the display of this screen to suit your workflow.', 'bbpress' ) . '</p>' 
  131. ) ); 
  132.  
  133. // Screen Content 
  134. get_current_screen()->add_help_tab( array( 
  135. 'id' => 'screen-content',  
  136. 'title' => __( 'Screen Content', 'bbpress' ),  
  137. 'content' => 
  138. '<p>' . __( 'You can customize the display of this screen’s contents in a number of ways:', 'bbpress' ) . '</p>' . 
  139. '<ul>' . 
  140. '<li>' . __( 'You can hide/display columns based on your needs and decide how many topics to list per screen using the Screen Options tab.', 'bbpress' ) . '</li>' . 
  141. '<li>' . __( 'You can filter the list of topics by topic status using the text links in the upper left to show All, Published, or Trashed topics. The default view is to show all topics.', 'bbpress' ) . '</li>' . 
  142. '<li>' . __( 'You can refine the list to show only topics from a specific month by using the dropdown menus above the topics list. Click the Filter button after making your selection. You also can refine the list by clicking on the topic creator in the topics list.', 'bbpress' ) . '</li>' . 
  143. '</ul>' 
  144. ) ); 
  145.  
  146. // Available Actions 
  147. get_current_screen()->add_help_tab( array( 
  148. 'id' => 'action-links',  
  149. 'title' => __( 'Available Actions', 'bbpress' ),  
  150. 'content' => 
  151. '<p>' . __( 'Hovering over a row in the topics list will display action links that allow you to manage your topic. You can perform the following actions:', 'bbpress' ) . '</p>' . 
  152. '<ul>' . 
  153. '<li>' . __( '<strong>Edit</strong> takes you to the editing screen for that topic. You can also reach that screen by clicking on the topic title.', 'bbpress' ) . '</li>' . 
  154. '<li>' . __( '<strong>Trash</strong> removes your topic from this list and places it in the trash, from which you can permanently delete it.', 'bbpress' ) . '</li>' . 
  155. '<li>' . __( '<strong>Spam</strong> removes your topic from this list and places it in the spam queue, from which you can permanently delete it.', 'bbpress' ) . '</li>' . 
  156. '<li>' . __( '<strong>Preview</strong> will show you what your draft topic will look like if you publish it. View will take you to your live site to view the topic. Which link is available depends on your topic’s status.', 'bbpress' ) . '</li>' . 
  157. '<li>' . __( '<strong>Close</strong> will mark the selected topic as ’closed’ and disable the option to post new replies to the topic.', 'bbpress' ) . '</li>' . 
  158. '<li>' . __( '<strong>Stick</strong> will keep the selected topic ’pinned’ to the top the parent forum topic list.', 'bbpress' ) . '</li>' . 
  159. '<li>' . __( '<strong>Stick <em>(to front)</em></strong> will keep the selected topic ’pinned’ to the top of ALL forums and be visable in any forums topics list.', 'bbpress' ) . '</li>' . 
  160. '</ul>' 
  161. ) ); 
  162.  
  163. // Bulk Actions 
  164. get_current_screen()->add_help_tab( array( 
  165. 'id' => 'bulk-actions',  
  166. 'title' => __( 'Bulk Actions', 'bbpress' ),  
  167. 'content' => 
  168. '<p>' . __( 'You can also edit or move multiple topics to the trash at once. Select the topics you want to act on using the checkboxes, then select the action you want to take from the Bulk Actions menu and click Apply.', 'bbpress' ) . '</p>' . 
  169. '<p>' . __( 'When using Bulk Edit, you can change the metadata (categories, author, etc.) for all selected topics at once. To remove a topic from the grouping, just click the x next to its name in the Bulk Edit area that appears.', 'bbpress' ) . '</p>' 
  170. ) ); 
  171.  
  172. // Help Sidebar 
  173. get_current_screen()->set_help_sidebar( 
  174. '<p><strong>' . __( 'For more information:', 'bbpress' ) . '</strong></p>' . 
  175. '<p>' . __( '<a href="http://codex.bbpress.org" target="_blank">bbPress Documentation</a>', 'bbpress' ) . '</p>' . 
  176. '<p>' . __( '<a href="http://bbpress.org/forums/" target="_blank">bbPress Support Forums</a>', 'bbpress' ) . '</p>' 
  177. ); 
  178.  
  179. /** 
  180. * Contextual help for bbPress topic edit page 
  181. * 
  182. * @since bbPress (r3119) 
  183. * @uses get_current_screen() 
  184. */ 
  185. public function new_help() { 
  186.  
  187. if ( $this->bail() ) return; 
  188.  
  189. $customize_display = '<p>' . __( 'The title field and the big topic editing Area are fixed in place, but you can reposition all the other boxes using drag and drop, and can minimize or expand them by clicking the title bar of each box. Use the Screen Options tab to unhide more boxes (Excerpt, Send Trackbacks, Custom Fields, Discussion, Slug, Author) or to choose a 1- or 2-column layout for this screen.', 'bbpress' ) . '</p>'; 
  190.  
  191. get_current_screen()->add_help_tab( array( 
  192. 'id' => 'customize-display',  
  193. 'title' => __( 'Customizing This Display', 'bbpress' ),  
  194. 'content' => $customize_display,  
  195. ) ); 
  196.  
  197. get_current_screen()->add_help_tab( array( 
  198. 'id' => 'title-topic-editor',  
  199. 'title' => __( 'Title and Topic Editor', 'bbpress' ),  
  200. 'content' => 
  201. '<p>' . __( '<strong>Title</strong> - Enter a title for your topic. After you enter a title, you’ll see the permalink below, which you can edit.', 'bbpress' ) . '</p>' . 
  202. '<p>' . __( '<strong>Topic Editor</strong> - Enter the text for your topic. There are two modes of editing: Visual and HTML. Choose the mode by clicking on the appropriate tab. Visual mode gives you a WYSIWYG editor. Click the last icon in the row to get a second row of controls. The HTML mode allows you to enter raw HTML along with your topic text. You can insert media files by clicking the icons above the topic editor and following the directions. You can go to the distraction-free writing screen via the Fullscreen icon in Visual mode (second to last in the top row) or the Fullscreen button in HTML mode (last in the row). Once there, you can make buttons visible by hovering over the top area. Exit Fullscreen back to the regular topic editor.', 'bbpress' ) . '</p>' 
  203. ) ); 
  204.  
  205. $publish_box = '<p>' . __( '<strong>Publish</strong> - You can set the terms of publishing your topic in the Publish box. For Status, Visibility, and Publish (immediately), click on the Edit link to reveal more options. Visibility includes options for password-protecting a topic or making it stay at the top of your blog indefinitely (sticky). Publish (immediately) allows you to set a future or past date and time, so you can schedule a topic to be published in the future or backdate a topic.', 'bbpress' ) . '</p>'; 
  206.  
  207. if ( current_theme_supports( 'topic-thumbnails' ) && post_type_supports( 'topic', 'thumbnail' ) ) { 
  208. $publish_box .= '<p>' . __( '<strong>Featured Image</strong> - This allows you to associate an image with your topic without inserting it. This is usually useful only if your theme makes use of the featured image as a topic thumbnail on the home page, a custom header, etc.', 'bbpress' ) . '</p>'; 
  209.  
  210. get_current_screen()->add_help_tab( array( 
  211. 'id' => 'topic-attributes',  
  212. 'title' => __( 'Topic Attributes', 'bbpress' ),  
  213. 'content' => 
  214. '<p>' . __( 'Select the attributes that your topic should have:', 'bbpress' ) . '</p>' . 
  215. '<ul>' . 
  216. '<li>' . __( '<strong>Forum</strong> dropdown determines the parent forum that the topic belongs to. Select the forum or category from the dropdown, or leave the default (No Forum) to post the topic without an assigned forum.', 'bbpress' ) . '</li>' . 
  217. '<li>' . __( '<strong>Topic Type</strong> dropdown indicates the sticky status of the topic. Selecting the super sticky option would stick the topic to the front of your forums, i.e. the topic index, sticky option would stick the topic to its respective forum. Selecting normal would not stick the topic anywhere.', 'bbpress' ) . '</li>' . 
  218. '</ul>' 
  219. ) ); 
  220.  
  221. get_current_screen()->add_help_tab( array( 
  222. 'id' => 'publish-box',  
  223. 'title' => __( 'Publish Box', 'bbpress' ),  
  224. 'content' => $publish_box,  
  225. ) ); 
  226.  
  227. get_current_screen()->set_help_sidebar( 
  228. '<p><strong>' . __( 'For more information:', 'bbpress' ) . '</strong></p>' . 
  229. '<p>' . __( '<a href="http://codex.bbpress.org" target="_blank">bbPress Documentation</a>', 'bbpress' ) . '</p>' . 
  230. '<p>' . __( '<a href="http://bbpress.org/forums/" target="_blank">bbPress Support Forums</a>', 'bbpress' ) . '</p>' 
  231. ); 
  232.  
  233. /** 
  234. * Add the topic attributes metabox 
  235. * 
  236. * @since bbPress (r2744) 
  237. * 
  238. * @uses bbp_get_topic_post_type() To get the topic post type 
  239. * @uses add_meta_box() To add the metabox 
  240. * @uses do_action() Calls 'bbp_topic_attributes_metabox' 
  241. */ 
  242. public function attributes_metabox() { 
  243.  
  244. if ( $this->bail() ) return; 
  245.  
  246. add_meta_box ( 
  247. 'bbp_topic_attributes',  
  248. __( 'Topic Attributes', 'bbpress' ),  
  249. 'bbp_topic_metabox',  
  250. $this->post_type,  
  251. 'side',  
  252. 'high' 
  253. ); 
  254.  
  255. do_action( 'bbp_topic_attributes_metabox' ); 
  256.  
  257. /** 
  258. * Pass the topic attributes for processing 
  259. * 
  260. * @since bbPress (r2746) 
  261. * 
  262. * @param int $topic_id Topic id 
  263. * @uses current_user_can() To check if the current user is capable of 
  264. * editing the topic 
  265. * @uses do_action() Calls 'bbp_topic_attributes_metabox_save' with the 
  266. * topic id and parent id 
  267. * @return int Parent id 
  268. */ 
  269. public function attributes_metabox_save( $topic_id ) { 
  270.  
  271. if ( $this->bail() ) return $topic_id; 
  272.  
  273. // Bail if doing an autosave 
  274. if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) 
  275. return $topic_id; 
  276.  
  277. // Bail if not a post request 
  278. if ( ! bbp_is_post_request() ) 
  279. return $topic_id; 
  280.  
  281. // Nonce check 
  282. if ( empty( $_POST['bbp_topic_metabox'] ) || !wp_verify_nonce( $_POST['bbp_topic_metabox'], 'bbp_topic_metabox_save' ) ) 
  283. return $topic_id; 
  284.  
  285. // Bail if current user cannot edit this topic 
  286. if ( !current_user_can( 'edit_topic', $topic_id ) ) 
  287. return $topic_id; 
  288.  
  289. // Get the forum ID 
  290. $forum_id = !empty( $_POST['parent_id'] ) ? (int) $_POST['parent_id'] : 0; 
  291.  
  292. // Get topic author data 
  293. $anonymous_data = bbp_filter_anonymous_post_data(); 
  294. $author_id = bbp_get_topic_author_id( $topic_id ); 
  295. $is_edit = (bool) isset( $_POST['save'] ); 
  296.  
  297. // Formally update the topic 
  298. bbp_update_topic( $topic_id, $forum_id, $anonymous_data, $author_id, $is_edit ); 
  299.  
  300. // Stickies 
  301. if ( !empty( $_POST['bbp_stick_topic'] ) && in_array( $_POST['bbp_stick_topic'], array( 'stick', 'super', 'unstick' ) ) ) { 
  302.  
  303. // What's the haps? 
  304. switch ( $_POST['bbp_stick_topic'] ) { 
  305.  
  306. // Sticky in this forum 
  307. case 'stick' : 
  308. bbp_stick_topic( $topic_id ); 
  309. break; 
  310.  
  311. // Super sticky in all forums 
  312. case 'super' : 
  313. bbp_stick_topic( $topic_id, true ); 
  314. break; 
  315.  
  316. // Normal 
  317. case 'unstick' : 
  318. default : 
  319. bbp_unstick_topic( $topic_id ); 
  320. break; 
  321.  
  322. // Allow other fun things to happen 
  323. do_action( 'bbp_topic_attributes_metabox_save', $topic_id, $forum_id ); 
  324. do_action( 'bbp_author_metabox_save', $topic_id, $anonymous_data ); 
  325.  
  326. return $topic_id; 
  327.  
  328. /** 
  329. * Add the author info metabox 
  330. * 
  331. * @since bbPress (r2828) 
  332. * 
  333. * @uses bbp_get_topic() To get the topic 
  334. * @uses bbp_get_reply() To get the reply 
  335. * @uses bbp_get_topic_post_type() To get the topic post type 
  336. * @uses bbp_get_reply_post_type() To get the reply post type 
  337. * @uses add_meta_box() To add the metabox 
  338. * @uses do_action() Calls 'bbp_author_metabox' with the topic/reply 
  339. * id 
  340. */ 
  341. public function author_metabox() { 
  342.  
  343. if ( $this->bail() ) return; 
  344.  
  345. // Bail if post_type is not a topic 
  346. if ( empty( $_GET['action'] ) || ( 'edit' !== $_GET['action'] ) ) 
  347. return; 
  348.  
  349. // Add the metabox 
  350. add_meta_box( 
  351. 'bbp_author_metabox',  
  352. __( 'Author Information', 'bbpress' ),  
  353. 'bbp_author_metabox',  
  354. $this->post_type,  
  355. 'side',  
  356. 'high' 
  357. ); 
  358.  
  359. do_action( 'bbp_author_metabox', get_the_ID() ); 
  360.  
  361. /** 
  362. * Add some general styling to the admin area 
  363. * 
  364. * @since bbPress (r2464) 
  365. * 
  366. * @uses bbp_get_forum_post_type() To get the forum post type 
  367. * @uses bbp_get_topic_post_type() To get the topic post type 
  368. * @uses bbp_get_reply_post_type() To get the reply post type 
  369. * @uses sanitize_html_class() To sanitize the classes 
  370. * @uses do_action() Calls 'bbp_admin_head' 
  371. */ 
  372. public function admin_head() { 
  373.  
  374. if ( $this->bail() ) return; 
  375.  
  376. ?> 
  377.  
  378. <style type="text/css" media="screen"> 
  379. /*<![CDATA[*/ 
  380.  
  381. strong.label { 
  382. display: inline-block; 
  383. width: 60px; 
  384.  
  385. .column-bbp_forum_topic_count,  
  386. .column-bbp_forum_reply_count,  
  387. .column-bbp_topic_reply_count,  
  388. .column-bbp_topic_voice_count { 
  389. width: 8% !important; 
  390.  
  391. .column-author,  
  392. .column-bbp_reply_author,  
  393. .column-bbp_topic_author { 
  394. width: 10% !important; 
  395.  
  396. .column-bbp_topic_forum,  
  397. .column-bbp_reply_forum,  
  398. .column-bbp_reply_topic { 
  399. width: 10% !important; 
  400.  
  401. .column-bbp_forum_freshness,  
  402. .column-bbp_topic_freshness { 
  403. width: 10% !important; 
  404.  
  405. .column-bbp_forum_created,  
  406. .column-bbp_topic_created,  
  407. .column-bbp_reply_created { 
  408. width: 15% !important; 
  409.  
  410. .status-closed { 
  411. background-color: #eaeaea; 
  412.  
  413. .status-spam { 
  414. background-color: #faeaea; 
  415.  
  416. /*]]>*/ 
  417. </style> 
  418.  
  419. <?php 
  420.  
  421. /** 
  422. * Toggle topic 
  423. * 
  424. * Handles the admin-side opening/closing, sticking/unsticking and 
  425. * spamming/unspamming of topics 
  426. * 
  427. * @since bbPress (r2727) 
  428. * 
  429. * @uses bbp_get_topic() To get the topic 
  430. * @uses current_user_can() To check if the user is capable of editing 
  431. * the topic 
  432. * @uses wp_die() To die if the user isn't capable or the post wasn't 
  433. * found 
  434. * @uses check_admin_referer() To verify the nonce and check referer 
  435. * @uses bbp_is_topic_open() To check if the topic is open 
  436. * @uses bbp_close_topic() To close the topic 
  437. * @uses bbp_open_topic() To open the topic 
  438. * @uses bbp_is_topic_sticky() To check if the topic is a sticky or 
  439. * super sticky 
  440. * @uses bbp_unstick_topic() To unstick the topic 
  441. * @uses bbp_stick_topic() To stick the topic 
  442. * @uses bbp_is_topic_spam() To check if the topic is marked as spam 
  443. * @uses bbp_unspam_topic() To unmark the topic as spam 
  444. * @uses bbp_spam_topic() To mark the topic as spam 
  445. * @uses do_action() Calls 'bbp_toggle_topic_admin' with success, post 
  446. * data, action and message 
  447. * @uses add_query_arg() To add custom args to the url 
  448. * @uses wp_safe_redirect() Redirect the page to custom url 
  449. */ 
  450. public function toggle_topic() { 
  451.  
  452. if ( $this->bail() ) return; 
  453.  
  454. // Only proceed if GET is a topic toggle action 
  455. if ( bbp_is_get_request() && !empty( $_GET['action'] ) && in_array( $_GET['action'], array( 'bbp_toggle_topic_close', 'bbp_toggle_topic_stick', 'bbp_toggle_topic_spam' ) ) && !empty( $_GET['topic_id'] ) ) { 
  456. $action = $_GET['action']; // What action is taking place? 
  457. $topic_id = (int) $_GET['topic_id']; // What's the topic id? 
  458. $success = false; // Flag 
  459. $post_data = array( 'ID' => $topic_id ); // Prelim array 
  460. $topic = bbp_get_topic( $topic_id ); 
  461.  
  462. // Bail if topic is missing 
  463. if ( empty( $topic ) ) 
  464. wp_die( __( 'The topic was not found!', 'bbpress' ) ); 
  465.  
  466. if ( !current_user_can( 'moderate', $topic->ID ) ) // What is the user doing here? 
  467. wp_die( __( 'You do not have the permission to do that!', 'bbpress' ) ); 
  468.  
  469. switch ( $action ) { 
  470. case 'bbp_toggle_topic_close' : 
  471. check_admin_referer( 'close-topic_' . $topic_id ); 
  472.  
  473. $is_open = bbp_is_topic_open( $topic_id ); 
  474. $message = true === $is_open ? 'closed' : 'opened'; 
  475. $success = true === $is_open ? bbp_close_topic( $topic_id ) : bbp_open_topic( $topic_id ); 
  476.  
  477. break; 
  478.  
  479. case 'bbp_toggle_topic_stick' : 
  480. check_admin_referer( 'stick-topic_' . $topic_id ); 
  481.  
  482. $is_sticky = bbp_is_topic_sticky( $topic_id ); 
  483. $is_super = false === $is_sticky && !empty( $_GET['super'] ) && ( "1" === $_GET['super'] ) ? true : false; 
  484. $message = true === $is_sticky ? 'unsticked' : 'sticked'; 
  485. $message = true === $is_super ? 'super_sticked' : $message; 
  486. $success = true === $is_sticky ? bbp_unstick_topic( $topic_id ) : bbp_stick_topic( $topic_id, $is_super ); 
  487.  
  488. break; 
  489.  
  490. case 'bbp_toggle_topic_spam' : 
  491. check_admin_referer( 'spam-topic_' . $topic_id ); 
  492.  
  493. $is_spam = bbp_is_topic_spam( $topic_id ); 
  494. $message = true === $is_spam ? 'unspammed' : 'spammed'; 
  495. $success = true === $is_spam ? bbp_unspam_topic( $topic_id ) : bbp_spam_topic( $topic_id ); 
  496.  
  497. break; 
  498.  
  499. $message = array( 'bbp_topic_toggle_notice' => $message, 'topic_id' => $topic->ID ); 
  500.  
  501. if ( false === $success || is_wp_error( $success ) ) 
  502. $message['failed'] = '1'; 
  503.  
  504. // Do additional topic toggle actions (admin side) 
  505. do_action( 'bbp_toggle_topic_admin', $success, $post_data, $action, $message ); 
  506.  
  507. // Redirect back to the topic 
  508. $redirect = add_query_arg( $message, remove_query_arg( array( 'action', 'topic_id' ) ) ); 
  509. wp_safe_redirect( $redirect ); 
  510.  
  511. // For good measure 
  512. exit(); 
  513.  
  514. /** 
  515. * Toggle topic notices 
  516. * 
  517. * Display the success/error notices from 
  518. * {@link BBP_Admin::toggle_topic()} 
  519. * 
  520. * @since bbPress (r2727) 
  521. * 
  522. * @uses bbp_get_topic() To get the topic 
  523. * @uses bbp_get_topic_title() To get the topic title of the topic 
  524. * @uses esc_html() To sanitize the topic title 
  525. * @uses apply_filters() Calls 'bbp_toggle_topic_notice_admin' with 
  526. * message, topic id, notice and is it a failure 
  527. */ 
  528. public function toggle_topic_notice() { 
  529.  
  530. if ( $this->bail() ) return; 
  531.  
  532. // Only proceed if GET is a topic toggle action 
  533. if ( bbp_is_get_request() && !empty( $_GET['bbp_topic_toggle_notice'] ) && in_array( $_GET['bbp_topic_toggle_notice'], array( 'opened', 'closed', 'super_sticked', 'sticked', 'unsticked', 'spammed', 'unspammed' ) ) && !empty( $_GET['topic_id'] ) ) { 
  534. $notice = $_GET['bbp_topic_toggle_notice']; // Which notice? 
  535. $topic_id = (int) $_GET['topic_id']; // What's the topic id? 
  536. $is_failure = !empty( $_GET['failed'] ) ? true : false; // Was that a failure? 
  537.  
  538. // Bais if no topic_id or notice 
  539. if ( empty( $notice ) || empty( $topic_id ) ) 
  540. return; 
  541.  
  542. // Bail if topic is missing 
  543. $topic = bbp_get_topic( $topic_id ); 
  544. if ( empty( $topic ) ) 
  545. return; 
  546.  
  547. $topic_title = bbp_get_topic_title( $topic->ID ); 
  548.  
  549. switch ( $notice ) { 
  550. case 'opened' : 
  551. $message = $is_failure === true ? sprintf( __( 'There was a problem opening the topic "%1$s".', 'bbpress' ), $topic_title ) : sprintf( __( 'Topic "%1$s" successfully opened.', 'bbpress' ), $topic_title ); 
  552. break; 
  553.  
  554. case 'closed' : 
  555. $message = $is_failure === true ? sprintf( __( 'There was a problem closing the topic "%1$s".', 'bbpress' ), $topic_title ) : sprintf( __( 'Topic "%1$s" successfully closed.', 'bbpress' ), $topic_title ); 
  556. break; 
  557.  
  558. case 'super_sticked' : 
  559. $message = $is_failure === true ? sprintf( __( 'There was a problem sticking the topic "%1$s" to front.', 'bbpress' ), $topic_title ) : sprintf( __( 'Topic "%1$s" successfully sticked to front.', 'bbpress' ), $topic_title ); 
  560. break; 
  561.  
  562. case 'sticked' : 
  563. $message = $is_failure === true ? sprintf( __( 'There was a problem sticking the topic "%1$s".', 'bbpress' ), $topic_title ) : sprintf( __( 'Topic "%1$s" successfully sticked.', 'bbpress' ), $topic_title ); 
  564. break; 
  565.  
  566. case 'unsticked' : 
  567. $message = $is_failure === true ? sprintf( __( 'There was a problem unsticking the topic "%1$s".', 'bbpress' ), $topic_title ) : sprintf( __( 'Topic "%1$s" successfully unsticked.', 'bbpress' ), $topic_title ); 
  568. break; 
  569.  
  570. case 'spammed' : 
  571. $message = $is_failure === true ? sprintf( __( 'There was a problem marking the topic "%1$s" as spam.', 'bbpress' ), $topic_title ) : sprintf( __( 'Topic "%1$s" successfully marked as spam.', 'bbpress' ), $topic_title ); 
  572. break; 
  573.  
  574. case 'unspammed' : 
  575. $message = $is_failure === true ? sprintf( __( 'There was a problem unmarking the topic "%1$s" as spam.', 'bbpress' ), $topic_title ) : sprintf( __( 'Topic "%1$s" successfully unmarked as spam.', 'bbpress' ), $topic_title ); 
  576. break; 
  577.  
  578. // Do additional topic toggle notice filters (admin side) 
  579. $message = apply_filters( 'bbp_toggle_topic_notice_admin', $message, $topic->ID, $notice, $is_failure ); 
  580.  
  581. ?> 
  582.  
  583. <div id="message" class="<?php echo $is_failure === true ? 'error' : 'updated'; ?> fade"> 
  584. <p style="line-height: 150%"><?php echo esc_html( $message ); ?></p> 
  585. </div> 
  586.  
  587. <?php 
  588.  
  589. /** 
  590. * Manage the column headers for the topics page 
  591. * 
  592. * @since bbPress (r2485) 
  593. * 
  594. * @param array $columns The columns 
  595. * @uses apply_filters() Calls 'bbp_admin_topics_column_headers' with 
  596. * the columns 
  597. * @return array $columns bbPress topic columns 
  598. */ 
  599. public function column_headers( $columns ) { 
  600.  
  601. if ( $this->bail() ) return $columns; 
  602.  
  603. $columns = array( 
  604. 'cb' => '<input type="checkbox" />',  
  605. 'title' => __( 'Topics', 'bbpress' ),  
  606. 'bbp_topic_forum' => __( 'Forum', 'bbpress' ),  
  607. 'bbp_topic_reply_count' => __( 'Replies', 'bbpress' ),  
  608. 'bbp_topic_voice_count' => __( 'Voices', 'bbpress' ),  
  609. 'bbp_topic_author' => __( 'Author', 'bbpress' ),  
  610. 'bbp_topic_created' => __( 'Created', 'bbpress' ),  
  611. 'bbp_topic_freshness' => __( 'Freshness', 'bbpress' ) 
  612. ); 
  613.  
  614. return apply_filters( 'bbp_admin_topics_column_headers', $columns ); 
  615.  
  616. /** 
  617. * Print extra columns for the topics page 
  618. * 
  619. * @since bbPress (r2485) 
  620. * 
  621. * @param string $column Column 
  622. * @param int $topic_id Topic id 
  623. * @uses bbp_get_topic_forum_id() To get the forum id of the topic 
  624. * @uses bbp_forum_title() To output the topic's forum title 
  625. * @uses apply_filters() Calls 'topic_forum_row_actions' with an array 
  626. * of topic forum actions 
  627. * @uses bbp_get_forum_permalink() To get the forum permalink 
  628. * @uses admin_url() To get the admin url of post.php 
  629. * @uses bbp_topic_reply_count() To output the topic reply count 
  630. * @uses bbp_topic_voice_count() To output the topic voice count 
  631. * @uses bbp_topic_author_display_name() To output the topic author name 
  632. * @uses get_the_date() Get the topic creation date 
  633. * @uses get_the_time() Get the topic creation time 
  634. * @uses esc_attr() To sanitize the topic creation time 
  635. * @uses bbp_get_topic_last_active_time() To get the time when the topic was 
  636. * last active 
  637. * @uses do_action() Calls 'bbp_admin_topics_column_data' with the 
  638. * column and topic id 
  639. */ 
  640. public function column_data( $column, $topic_id ) { 
  641.  
  642. if ( $this->bail() ) return; 
  643.  
  644. // Get topic forum ID 
  645. $forum_id = bbp_get_topic_forum_id( $topic_id ); 
  646.  
  647. // Populate column data 
  648. switch ( $column ) { 
  649.  
  650. // Forum 
  651. case 'bbp_topic_forum' : 
  652.  
  653. // Output forum name 
  654. if ( !empty( $forum_id ) ) { 
  655.  
  656. // Forum Title 
  657. $forum_title = bbp_get_forum_title( $forum_id ); 
  658. if ( empty( $forum_title ) ) { 
  659. $forum_title = esc_html__( 'No Forum', 'bbpress' ); 
  660.  
  661. // Output the title 
  662. echo $forum_title; 
  663.  
  664. } else { 
  665. esc_html_e( '(No Forum)', 'bbpress' ); 
  666.  
  667. break; 
  668.  
  669. // Reply Count 
  670. case 'bbp_topic_reply_count' : 
  671. bbp_topic_reply_count( $topic_id ); 
  672. break; 
  673.  
  674. // Reply Count 
  675. case 'bbp_topic_voice_count' : 
  676. bbp_topic_voice_count( $topic_id ); 
  677. break; 
  678.  
  679. // Author 
  680. case 'bbp_topic_author' : 
  681. bbp_topic_author_display_name( $topic_id ); 
  682. break; 
  683.  
  684. // Freshness 
  685. case 'bbp_topic_created': 
  686. printf( '%1$s <br /> %2$s',  
  687. get_the_date(),  
  688. esc_attr( get_the_time() ) 
  689. ); 
  690.  
  691. break; 
  692.  
  693. // Freshness 
  694. case 'bbp_topic_freshness' : 
  695. $last_active = bbp_get_topic_last_active_time( $topic_id, false ); 
  696. if ( !empty( $last_active ) ) { 
  697. echo esc_html( $last_active ); 
  698. } else { 
  699. esc_html_e( 'No Replies', 'bbpress' ); // This should never happen 
  700.  
  701. break; 
  702.  
  703. // Do an action for anything else 
  704. default : 
  705. do_action( 'bbp_admin_topics_column_data', $column, $topic_id ); 
  706. break; 
  707.  
  708. /** 
  709. * Topic Row actions 
  710. * 
  711. * Remove the quick-edit action link under the topic title and add the 
  712. * content and close/stick/spam links 
  713. * 
  714. * @since bbPress (r2485) 
  715. * 
  716. * @param array $actions Actions 
  717. * @param array $topic Topic object 
  718. * @uses bbp_get_topic_post_type() To get the topic post type 
  719. * @uses bbp_topic_content() To output topic content 
  720. * @uses bbp_get_topic_permalink() To get the topic link 
  721. * @uses bbp_get_topic_title() To get the topic title 
  722. * @uses current_user_can() To check if the current user can edit or 
  723. * delete the topic 
  724. * @uses bbp_is_topic_open() To check if the topic is open 
  725. * @uses bbp_is_topic_spam() To check if the topic is marked as spam 
  726. * @uses bbp_is_topic_sticky() To check if the topic is a sticky or a 
  727. * super sticky 
  728. * @uses get_post_type_object() To get the topic post type object 
  729. * @uses add_query_arg() To add custom args to the url 
  730. * @uses remove_query_arg() To remove custom args from the url 
  731. * @uses wp_nonce_url() To nonce the url 
  732. * @uses get_delete_post_link() To get the delete post link of the topic 
  733. * @return array $actions Actions 
  734. */ 
  735. public function row_actions( $actions, $topic ) { 
  736.  
  737. if ( $this->bail() ) return $actions; 
  738.  
  739. unset( $actions['inline hide-if-no-js'] ); 
  740.  
  741. // Show view link if it's not set, the topic is trashed and the user can view trashed topics 
  742. if ( empty( $actions['view'] ) && ( bbp_get_trash_status_id() === $topic->post_status ) && current_user_can( 'view_trash' ) ) 
  743. $actions['view'] = '<a href="' . esc_url( bbp_get_topic_permalink( $topic->ID ) ) . '" title="' . esc_attr( sprintf( __( 'View “%s”', 'bbpress' ), bbp_get_topic_title( $topic->ID ) ) ) . '" rel="permalink">' . esc_html__( 'View', 'bbpress' ) . '</a>'; 
  744.  
  745. // Only show the actions if the user is capable of viewing them :) 
  746. if ( current_user_can( 'moderate', $topic->ID ) ) { 
  747.  
  748. // Close 
  749. // Show the 'close' and 'open' link on published and closed posts only 
  750. if ( in_array( $topic->post_status, array( bbp_get_public_status_id(), bbp_get_closed_status_id() ) ) ) { 
  751. $close_uri = wp_nonce_url( add_query_arg( array( 'topic_id' => $topic->ID, 'action' => 'bbp_toggle_topic_close' ), remove_query_arg( array( 'bbp_topic_toggle_notice', 'topic_id', 'failed', 'super' ) ) ), 'close-topic_' . $topic->ID ); 
  752. if ( bbp_is_topic_open( $topic->ID ) ) 
  753. $actions['closed'] = '<a href="' . esc_url( $close_uri ) . '" title="' . esc_attr__( 'Close this topic', 'bbpress' ) . '">' . _x( 'Close', 'Close a Topic', 'bbpress' ) . '</a>'; 
  754. else 
  755. $actions['closed'] = '<a href="' . esc_url( $close_uri ) . '" title="' . esc_attr__( 'Open this topic', 'bbpress' ) . '">' . _x( 'Open', 'Open a Topic', 'bbpress' ) . '</a>'; 
  756.  
  757. // Dont show sticky if topic links is spam or trash 
  758. if ( !bbp_is_topic_spam( $topic->ID ) && !bbp_is_topic_trash( $topic->ID ) ) { 
  759.  
  760. // Sticky 
  761. $stick_uri = wp_nonce_url( add_query_arg( array( 'topic_id' => $topic->ID, 'action' => 'bbp_toggle_topic_stick' ), remove_query_arg( array( 'bbp_topic_toggle_notice', 'topic_id', 'failed', 'super' ) ) ), 'stick-topic_' . $topic->ID ); 
  762. if ( bbp_is_topic_sticky( $topic->ID ) ) { 
  763. $actions['stick'] = '<a href="' . esc_url( $stick_uri ) . '" title="' . esc_attr__( 'Unstick this topic', 'bbpress' ) . '">' . esc_html__( 'Unstick', 'bbpress' ) . '</a>'; 
  764. } else { 
  765. $super_uri = wp_nonce_url( add_query_arg( array( 'topic_id' => $topic->ID, 'action' => 'bbp_toggle_topic_stick', 'super' => '1' ), remove_query_arg( array( 'bbp_topic_toggle_notice', 'topic_id', 'failed', 'super' ) ) ), 'stick-topic_' . $topic->ID ); 
  766. $actions['stick'] = '<a href="' . esc_url( $stick_uri ) . '" title="' . esc_attr__( 'Stick this topic to its forum', 'bbpress' ) . '">' . esc_html__( 'Stick', 'bbpress' ) . '</a> <a href="' . esc_url( $super_uri ) . '" title="' . esc_attr__( 'Stick this topic to front', 'bbpress' ) . '">' . esc_html__( '(to front)', 'bbpress' ) . '</a>'; 
  767.  
  768. // Spam 
  769. $spam_uri = wp_nonce_url( add_query_arg( array( 'topic_id' => $topic->ID, 'action' => 'bbp_toggle_topic_spam' ), remove_query_arg( array( 'bbp_topic_toggle_notice', 'topic_id', 'failed', 'super' ) ) ), 'spam-topic_' . $topic->ID ); 
  770. if ( bbp_is_topic_spam( $topic->ID ) ) 
  771. $actions['spam'] = '<a href="' . esc_url( $spam_uri ) . '" title="' . esc_attr__( 'Mark the topic as not spam', 'bbpress' ) . '">' . esc_html__( 'Not spam', 'bbpress' ) . '</a>'; 
  772. else 
  773. $actions['spam'] = '<a href="' . esc_url( $spam_uri ) . '" title="' . esc_attr__( 'Mark this topic as spam', 'bbpress' ) . '">' . esc_html__( 'Spam', 'bbpress' ) . '</a>'; 
  774.  
  775.  
  776. // Do not show trash links for spam topics, or spam links for trashed topics 
  777. if ( current_user_can( 'delete_topic', $topic->ID ) ) { 
  778. if ( bbp_get_trash_status_id() === $topic->post_status ) { 
  779. $post_type_object = get_post_type_object( bbp_get_topic_post_type() ); 
  780. $actions['untrash'] = "<a title='" . esc_attr__( 'Restore this item from the Trash', 'bbpress' ) . "' href='" . esc_url( wp_nonce_url( add_query_arg( array( '_wp_http_referer' => add_query_arg( array( 'post_type' => bbp_get_topic_post_type() ), admin_url( 'edit.php' ) ) ), admin_url( sprintf( $post_type_object->_edit_link . '&action=untrash', $topic->ID ) ) ), 'untrash-' . $topic->post_type . '_' . $topic->ID ) ) . "'>" . esc_html__( 'Restore', 'bbpress' ) . "</a>"; 
  781. } elseif ( EMPTY_TRASH_DAYS ) { 
  782. $actions['trash'] = "<a class='submitdelete' title='" . esc_attr__( 'Move this item to the Trash', 'bbpress' ) . "' href='" . esc_url( add_query_arg( array( '_wp_http_referer' => add_query_arg( array( 'post_type' => bbp_get_topic_post_type() ), admin_url( 'edit.php' ) ) ), get_delete_post_link( $topic->ID ) ) ) . "'>" . esc_html__( 'Trash', 'bbpress' ) . "</a>"; 
  783.  
  784. if ( bbp_get_trash_status_id() === $topic->post_status || !EMPTY_TRASH_DAYS ) { 
  785. $actions['delete'] = "<a class='submitdelete' title='" . esc_attr__( 'Delete this item permanently', 'bbpress' ) . "' href='" . esc_url( add_query_arg( array( '_wp_http_referer' => add_query_arg( array( 'post_type' => bbp_get_topic_post_type() ), admin_url( 'edit.php' ) ) ), get_delete_post_link( $topic->ID, '', true ) ) ) . "'>" . esc_html__( 'Delete Permanently', 'bbpress' ) . "</a>"; 
  786. } elseif ( bbp_get_spam_status_id() === $topic->post_status ) { 
  787. unset( $actions['trash'] ); 
  788.  
  789. return $actions; 
  790.  
  791. /** 
  792. * Add forum dropdown to topic and reply list table filters 
  793. * 
  794. * @since bbPress (r2991) 
  795. * 
  796. * @uses bbp_get_reply_post_type() To get the reply post type 
  797. * @uses bbp_get_topic_post_type() To get the topic post type 
  798. * @uses bbp_dropdown() To generate a forum dropdown 
  799. * @return bool False. If post type is not topic or reply 
  800. */ 
  801. public function filter_dropdown() { 
  802.  
  803. if ( $this->bail() ) return; 
  804.  
  805. // Add Empty Spam button 
  806. if ( !empty( $_GET['post_status'] ) && ( bbp_get_spam_status_id() === $_GET['post_status'] ) && current_user_can( 'moderate' ) ) { 
  807. wp_nonce_field( 'bulk-destroy', '_destroy_nonce' ); 
  808. $title = esc_attr__( 'Empty Spam', 'bbpress' ); 
  809. submit_button( $title, 'button-secondary apply', 'delete_all', false ); 
  810.  
  811. // Get which forum is selected 
  812. $selected = !empty( $_GET['bbp_forum_id'] ) ? $_GET['bbp_forum_id'] : ''; 
  813.  
  814. // Show the forums dropdown 
  815. bbp_dropdown( array( 
  816. 'selected' => $selected,  
  817. 'show_none' => __( 'In all forums', 'bbpress' ) 
  818. ) ); 
  819.  
  820. /** 
  821. * Adjust the request query and include the forum id 
  822. * 
  823. * @since bbPress (r2991) 
  824. * 
  825. * @param array $query_vars Query variables from {@link WP_Query} 
  826. * @uses is_admin() To check if it's the admin section 
  827. * @uses bbp_get_topic_post_type() To get the topic post type 
  828. * @uses bbp_get_reply_post_type() To get the reply post type 
  829. * @return array Processed Query Vars 
  830. */ 
  831. function filter_post_rows( $query_vars ) { 
  832.  
  833. if ( $this->bail() ) return $query_vars; 
  834.  
  835. // Add post_parent query_var if one is present 
  836. if ( !empty( $_GET['bbp_forum_id'] ) ) { 
  837. $query_vars['meta_key'] = '_bbp_forum_id'; 
  838. $query_vars['meta_value'] = $_GET['bbp_forum_id']; 
  839.  
  840. // Return manipulated query_vars 
  841. return $query_vars; 
  842.  
  843. /** 
  844. * Custom user feedback messages for topic post type 
  845. * 
  846. * @since bbPress (r3080) 
  847. * 
  848. * @global int $post_ID 
  849. * @uses bbp_get_topic_permalink() 
  850. * @uses wp_post_revision_title() 
  851. * @uses esc_url() 
  852. * @uses add_query_arg() 
  853. * 
  854. * @param array $messages 
  855. * 
  856. * @return array 
  857. */ 
  858. public function updated_messages( $messages ) { 
  859. global $post_ID; 
  860.  
  861. if ( $this->bail() ) return $messages; 
  862.  
  863. // URL for the current topic 
  864. $topic_url = bbp_get_topic_permalink( $post_ID ); 
  865.  
  866. // Current topic's post_date 
  867. $post_date = bbp_get_global_post_field( 'post_date', 'raw' ); 
  868.  
  869. // Messages array 
  870. $messages[$this->post_type] = array( 
  871. 0 => '', // Left empty on purpose 
  872.  
  873. // Updated 
  874. 1 => sprintf( __( 'Topic updated. <a href="%s">View topic</a>', 'bbpress' ), $topic_url ),  
  875.  
  876. // Custom field updated 
  877. 2 => __( 'Custom field updated.', 'bbpress' ),  
  878.  
  879. // Custom field deleted 
  880. 3 => __( 'Custom field deleted.', 'bbpress' ),  
  881.  
  882. // Topic updated 
  883. 4 => __( 'Topic updated.', 'bbpress' ),  
  884.  
  885. // Restored from revision 
  886. // translators: %s: date and time of the revision 
  887. 5 => isset( $_GET['revision'] ) 
  888. ? sprintf( __( 'Topic restored to revision from %s', 'bbpress' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) 
  889. : false,  
  890.  
  891. // Topic created 
  892. 6 => sprintf( __( 'Topic created. <a href="%s">View topic</a>', 'bbpress' ), $topic_url ),  
  893.  
  894. // Topic saved 
  895. 7 => __( 'Topic saved.', 'bbpress' ),  
  896.  
  897. // Topic submitted 
  898. 8 => sprintf( __( 'Topic submitted. <a target="_blank" href="%s">Preview topic</a>', 'bbpress' ), esc_url( add_query_arg( 'preview', 'true', $topic_url ) ) ),  
  899.  
  900. // Topic scheduled 
  901. 9 => sprintf( __( 'Topic scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview topic</a>', 'bbpress' ),  
  902. // translators: Publish box date format, see http://php.net/date 
  903. date_i18n( __( 'M j, Y @ G:i', 'bbpress' ),  
  904. strtotime( $post_date ) ),  
  905. $topic_url ),  
  906.  
  907. // Topic draft updated 
  908. 10 => sprintf( __( 'Topic draft updated. <a target="_blank" href="%s">Preview topic</a>', 'bbpress' ), esc_url( add_query_arg( 'preview', 'true', $topic_url ) ) ),  
  909. ); 
  910.  
  911. return $messages; 
  912. endif; // class_exists check 
  913.  
  914. /** 
  915. * Setup bbPress Topics Admin 
  916. * 
  917. * This is currently here to make hooking and unhooking of the admin UI easy. 
  918. * It could use dependency injection in the future, but for now this is easier. 
  919. * 
  920. * @since bbPress (r2596) 
  921. * 
  922. * @uses BBP_Forums_Admin 
  923. */ 
  924. function bbp_admin_topics() { 
  925. bbpress()->admin->topics = new BBP_Topics_Admin(); 
.