/includes/admin/replies.php

  1. <?php 
  2.  
  3. /** 
  4. * bbPress Replies 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_Replies_Admin' ) ) : 
  14. /** 
  15. * Loads bbPress replies admin area 
  16. * 
  17. * @package bbPress 
  18. * @subpackage Administration 
  19. * @since bbPress (r2464) 
  20. */ 
  21. class BBP_Replies_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 admin loader 
  34. * 
  35. * @since bbPress (r2515) 
  36. * 
  37. * @uses BBP_Replies_Admin::setup_globals() Setup the globals needed 
  38. * @uses BBP_Replies_Admin::setup_actions() Setup the hooks and actions 
  39. * @uses BBP_Replies_Admin::setup_actions() 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. // Reply column headers. 
  66. add_filter( 'manage_' . $this->post_type . '_posts_columns', array( $this, 'column_headers' ) ); 
  67.  
  68. // Reply 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. // Reply 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_reply_* requests on admin_init, also have a message displayed 
  77. add_action( 'load-edit.php', array( $this, 'toggle_reply' ) ); 
  78. add_action( 'admin_notices', array( $this, 'toggle_reply_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_reply_post_type(); 
  112.  
  113. /** Contextual Help *******************************************************/ 
  114.  
  115. /** 
  116. * Contextual help for bbPress reply 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 provides access to all of your replies. 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 replies to list per screen using the Screen Options tab.', 'bbpress' ) . '</li>' . 
  141. '<li>' . __( 'You can filter the list of replies by reply status using the text links in the upper left to show All, Published, Draft, or Trashed replies. The default view is to show all replies.', 'bbpress' ) . '</li>' . 
  142. '<li>' . __( 'You can view replies in a simple title list or with an excerpt. Choose the view you prefer by clicking on the icons at the top of the list on the right.', 'bbpress' ) . '</li>' . 
  143. '<li>' . __( 'You can refine the list to show only replies in a specific category or from a specific month by using the dropdown menus above the replies list. Click the Filter button after making your selection. You also can refine the list by clicking on the reply author, category or tag in the replies list.', 'bbpress' ) . '</li>' . 
  144. '</ul>' 
  145. ) ); 
  146.  
  147. // Available Actions 
  148. get_current_screen()->add_help_tab( array( 
  149. 'id' => 'action-links',  
  150. 'title' => __( 'Available Actions', 'bbpress' ),  
  151. 'content' => 
  152. '<p>' . __( 'Hovering over a row in the replies list will display action links that allow you to manage your reply. You can perform the following actions:', 'bbpress' ) . '</p>' . 
  153. '<ul>' . 
  154. '<li>' . __( '<strong>Edit</strong> takes you to the editing screen for that reply. You can also reach that screen by clicking on the reply title.', 'bbpress' ) . '</li>' . 
  155. //'<li>' . __( '<strong>Quick Edit</strong> provides inline access to the metadata of your reply, allowing you to update reply details without leaving this screen.', 'bbpress' ) . '</li>' . 
  156. '<li>' . __( '<strong>Trash</strong> removes your reply from this list and places it in the trash, from which you can permanently delete it.', 'bbpress' ) . '</li>' . 
  157. '<li>' . __( '<strong>Spam</strong> removes your reply from this list and places it in the spam queue, from which you can permanently delete it.', 'bbpress' ) . '</li>' . 
  158. '<li>' . __( '<strong>Preview</strong> will show you what your draft reply will look like if you publish it. View will take you to your live site to view the reply. Which link is available depends on your reply’s status.', 'bbpress' ) . '</li>' . 
  159. '</ul>' 
  160. ) ); 
  161.  
  162. // Bulk Actions 
  163. get_current_screen()->add_help_tab( array( 
  164. 'id' => 'bulk-actions',  
  165. 'title' => __( 'Bulk Actions', 'bbpress' ),  
  166. 'content' => 
  167. '<p>' . __( 'You can also edit or move multiple replies to the trash at once. Select the replies 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>' . 
  168. '<p>' . __( 'When using Bulk Edit, you can change the metadata (categories, author, etc.) for all selected replies at once. To remove a reply from the grouping, just click the x next to its name in the Bulk Edit area that appears.', 'bbpress' ) . '</p>' 
  169. ) ); 
  170.  
  171. // Help Sidebar 
  172. get_current_screen()->set_help_sidebar( 
  173. '<p><strong>' . __( 'For more information:', 'bbpress' ) . '</strong></p>' . 
  174. '<p>' . __( '<a href="http://codex.bbpress.org" target="_blank">bbPress Documentation</a>', 'bbpress' ) . '</p>' . 
  175. '<p>' . __( '<a href="http://bbpress.org/forums/" target="_blank">bbPress Support Forums</a>', 'bbpress' ) . '</p>' 
  176. ); 
  177.  
  178. /** 
  179. * Contextual help for bbPress reply edit page 
  180. * 
  181. * @since bbPress (r3119) 
  182. * @uses get_current_screen() 
  183. */ 
  184. public function new_help() { 
  185.  
  186. if ( $this->bail() ) return; 
  187.  
  188. $customize_display = '<p>' . __( 'The title field and the big reply 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>'; 
  189.  
  190. get_current_screen()->add_help_tab( array( 
  191. 'id' => 'customize-display',  
  192. 'title' => __( 'Customizing This Display', 'bbpress' ),  
  193. 'content' => $customize_display,  
  194. ) ); 
  195.  
  196. get_current_screen()->add_help_tab( array( 
  197. 'id' => 'title-reply-editor',  
  198. 'title' => __( 'Title and Reply Editor', 'bbpress' ),  
  199. 'content' => 
  200. '<p>' . __( '<strong>Title</strong> - Enter a title for your reply. After you enter a title, you’ll see the permalink below, which you can edit.', 'bbpress' ) . '</p>' . 
  201. '<p>' . __( '<strong>Reply Editor</strong> - Enter the text for your reply. 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 reply text. You can insert media files by clicking the icons above the reply 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 reply editor.', 'bbpress' ) . '</p>' 
  202. ) ); 
  203.  
  204. $publish_box = '<p>' . __( '<strong>Publish</strong> - You can set the terms of publishing your reply 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 reply 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 reply to be published in the future or backdate a reply.', 'bbpress' ) . '</p>'; 
  205.  
  206. if ( current_theme_supports( 'reply-thumbnails' ) && post_type_supports( 'reply', 'thumbnail' ) ) { 
  207. $publish_box .= '<p>' . __( '<strong>Featured Image</strong> - This allows you to associate an image with your reply without inserting it. This is usually useful only if your theme makes use of the featured image as a reply thumbnail on the home page, a custom header, etc.', 'bbpress' ) . '</p>'; 
  208.  
  209. get_current_screen()->add_help_tab( array( 
  210. 'id' => 'reply-attributes',  
  211. 'title' => __( 'Reply Attributes', 'bbpress' ),  
  212. 'content' => 
  213. '<p>' . __( 'Select the attributes that your reply should have:', 'bbpress' ) . '</p>' . 
  214. '<ul>' . 
  215. '<li>' . __( '<strong>Forum</strong> dropdown determines the parent forum that the reply belongs to. Select the forum, or leave the default (Use Forum of Topic) to post the reply in forum of the topic.', 'bbpress' ) . '</li>' . 
  216. '<li>' . __( '<strong>Topic</strong> determines the parent topic that the reply belongs to.', 'bbpress' ) . '</li>' . 
  217. '<li>' . __( '<strong>Reply To</strong> determines the threading of the reply.', '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 reply attributes metabox 
  235. * 
  236. * @since bbPress (r2746) 
  237. * 
  238. * @uses bbp_get_reply_post_type() To get the reply post type 
  239. * @uses add_meta_box() To add the metabox 
  240. * @uses do_action() Calls 'bbp_reply_attributes_metabox' 
  241. */ 
  242. public function attributes_metabox() { 
  243.  
  244. if ( $this->bail() ) return; 
  245.  
  246. add_meta_box ( 
  247. 'bbp_reply_attributes',  
  248. __( 'Reply Attributes', 'bbpress' ),  
  249. 'bbp_reply_metabox',  
  250. $this->post_type,  
  251. 'side',  
  252. 'high' 
  253. ); 
  254.  
  255. do_action( 'bbp_reply_attributes_metabox' ); 
  256.  
  257. /** 
  258. * Pass the reply attributes for processing 
  259. * 
  260. * @since bbPress (r2746) 
  261. * 
  262. * @param int $reply_id Reply id 
  263. * @uses current_user_can() To check if the current user is capable of 
  264. * editing the reply 
  265. * @uses do_action() Calls 'bbp_reply_attributes_metabox_save' with the 
  266. * reply id and parent id 
  267. * @return int Parent id 
  268. */ 
  269. public function attributes_metabox_save( $reply_id ) { 
  270.  
  271. if ( $this->bail() ) return $reply_id; 
  272.  
  273. // Bail if doing an autosave 
  274. if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) 
  275. return $reply_id; 
  276.  
  277. // Bail if not a post request 
  278. if ( ! bbp_is_post_request() ) 
  279. return $reply_id; 
  280.  
  281. // Check action exists 
  282. if ( empty( $_POST['action'] ) ) 
  283. return $reply_id; 
  284.  
  285. // Nonce check 
  286. if ( empty( $_POST['bbp_reply_metabox'] ) || !wp_verify_nonce( $_POST['bbp_reply_metabox'], 'bbp_reply_metabox_save' ) ) 
  287. return $reply_id; 
  288.  
  289. // Current user cannot edit this reply 
  290. if ( !current_user_can( 'edit_reply', $reply_id ) ) 
  291. return $reply_id; 
  292.  
  293. // Get the reply meta post values 
  294. $topic_id = !empty( $_POST['parent_id'] ) ? (int) $_POST['parent_id'] : 0; 
  295. $forum_id = !empty( $_POST['bbp_forum_id'] ) ? (int) $_POST['bbp_forum_id'] : bbp_get_topic_forum_id( $topic_id ); 
  296. $reply_to = !empty( $_POST['bbp_reply_to'] ) ? (int) $_POST['bbp_reply_to'] : 0; 
  297.  
  298. // Get reply author data 
  299. $anonymous_data = bbp_filter_anonymous_post_data(); 
  300. $author_id = bbp_get_reply_author_id( $reply_id ); 
  301. $is_edit = (bool) isset( $_POST['save'] ); 
  302.  
  303. // Formally update the reply 
  304. bbp_update_reply( $reply_id, $topic_id, $forum_id, $anonymous_data, $author_id, $is_edit, $reply_to ); 
  305.  
  306. // Allow other fun things to happen 
  307. do_action( 'bbp_reply_attributes_metabox_save', $reply_id, $topic_id, $forum_id, $reply_to ); 
  308. do_action( 'bbp_author_metabox_save', $reply_id, $anonymous_data ); 
  309.  
  310. return $reply_id; 
  311.  
  312. /** 
  313. * Add the author info metabox 
  314. * 
  315. * Allows editing of information about an author 
  316. * 
  317. * @since bbPress (r2828) 
  318. * 
  319. * @uses bbp_get_topic() To get the topic 
  320. * @uses bbp_get_reply() To get the reply 
  321. * @uses bbp_get_topic_post_type() To get the topic post type 
  322. * @uses bbp_get_reply_post_type() To get the reply post type 
  323. * @uses add_meta_box() To add the metabox 
  324. * @uses do_action() Calls 'bbp_author_metabox' with the topic/reply 
  325. * id 
  326. */ 
  327. public function author_metabox() { 
  328.  
  329. if ( $this->bail() ) return; 
  330.  
  331. // Bail if post_type is not a reply 
  332. if ( empty( $_GET['action'] ) || ( 'edit' !== $_GET['action'] ) ) 
  333. return; 
  334.  
  335. // Add the metabox 
  336. add_meta_box( 
  337. 'bbp_author_metabox',  
  338. __( 'Author Information', 'bbpress' ),  
  339. 'bbp_author_metabox',  
  340. $this->post_type,  
  341. 'side',  
  342. 'high' 
  343. ); 
  344.  
  345. do_action( 'bbp_author_metabox', get_the_ID() ); 
  346.  
  347. /** 
  348. * Add some general styling to the admin area 
  349. * 
  350. * @since bbPress (r2464) 
  351. * 
  352. * @uses bbp_get_forum_post_type() To get the forum post type 
  353. * @uses bbp_get_topic_post_type() To get the topic post type 
  354. * @uses bbp_get_reply_post_type() To get the reply post type 
  355. * @uses sanitize_html_class() To sanitize the classes 
  356. * @uses do_action() Calls 'bbp_admin_head' 
  357. */ 
  358. public function admin_head() { 
  359.  
  360. if ( $this->bail() ) return; 
  361.  
  362. ?> 
  363.  
  364. <style type="text/css" media="screen"> 
  365. /*<![CDATA[*/ 
  366.  
  367. strong.label { 
  368. display: inline-block; 
  369. width: 60px; 
  370.  
  371. .column-bbp_forum_topic_count,  
  372. .column-bbp_forum_reply_count,  
  373. .column-bbp_topic_reply_count,  
  374. .column-bbp_topic_voice_count { 
  375. width: 8% !important; 
  376.  
  377. .column-author,  
  378. .column-bbp_reply_author,  
  379. .column-bbp_topic_author { 
  380. width: 10% !important; 
  381.  
  382. .column-bbp_topic_forum,  
  383. .column-bbp_reply_forum,  
  384. .column-bbp_reply_topic { 
  385. width: 10% !important; 
  386.  
  387. .column-bbp_forum_freshness,  
  388. .column-bbp_topic_freshness { 
  389. width: 10% !important; 
  390.  
  391. .column-bbp_forum_created,  
  392. .column-bbp_topic_created,  
  393. .column-bbp_reply_created { 
  394. width: 15% !important; 
  395.  
  396. .status-closed { 
  397. background-color: #eaeaea; 
  398.  
  399. .status-spam { 
  400. background-color: #faeaea; 
  401.  
  402. /*]]>*/ 
  403. </style> 
  404.  
  405. <?php 
  406.  
  407. /** 
  408. * Toggle reply 
  409. * 
  410. * Handles the admin-side spamming/unspamming of replies 
  411. * 
  412. * @since bbPress (r2740) 
  413. * 
  414. * @uses bbp_get_reply() To get the reply 
  415. * @uses current_user_can() To check if the user is capable of editing 
  416. * the reply 
  417. * @uses wp_die() To die if the user isn't capable or the post wasn't 
  418. * found 
  419. * @uses check_admin_referer() To verify the nonce and check referer 
  420. * @uses bbp_is_reply_spam() To check if the reply is marked as spam 
  421. * @uses bbp_unspam_reply() To unmark the reply as spam 
  422. * @uses bbp_spam_reply() To mark the reply as spam 
  423. * @uses do_action() Calls 'bbp_toggle_reply_admin' with success, post 
  424. * data, action and message 
  425. * @uses add_query_arg() To add custom args to the url 
  426. * @uses wp_safe_redirect() Redirect the page to custom url 
  427. */ 
  428. public function toggle_reply() { 
  429.  
  430. if ( $this->bail() ) return; 
  431.  
  432. // Only proceed if GET is a reply toggle action 
  433. if ( bbp_is_get_request() && !empty( $_GET['action'] ) && in_array( $_GET['action'], array( 'bbp_toggle_reply_spam' ) ) && !empty( $_GET['reply_id'] ) ) { 
  434. $action = $_GET['action']; // What action is taking place? 
  435. $reply_id = (int) $_GET['reply_id']; // What's the reply id? 
  436. $success = false; // Flag 
  437. $post_data = array( 'ID' => $reply_id ); // Prelim array 
  438.  
  439. // Get reply and die if empty 
  440. $reply = bbp_get_reply( $reply_id ); 
  441. if ( empty( $reply ) ) // Which reply? 
  442. wp_die( __( 'The reply was not found!', 'bbpress' ) ); 
  443.  
  444. if ( !current_user_can( 'moderate', $reply->ID ) ) // What is the user doing here? 
  445. wp_die( __( 'You do not have the permission to do that!', 'bbpress' ) ); 
  446.  
  447. switch ( $action ) { 
  448. case 'bbp_toggle_reply_spam' : 
  449. check_admin_referer( 'spam-reply_' . $reply_id ); 
  450.  
  451. $is_spam = bbp_is_reply_spam( $reply_id ); 
  452. $message = $is_spam ? 'unspammed' : 'spammed'; 
  453. $success = $is_spam ? bbp_unspam_reply( $reply_id ) : bbp_spam_reply( $reply_id ); 
  454.  
  455. break; 
  456.  
  457. $success = wp_update_post( $post_data ); 
  458. $message = array( 'bbp_reply_toggle_notice' => $message, 'reply_id' => $reply->ID ); 
  459.  
  460. if ( false === $success || is_wp_error( $success ) ) 
  461. $message['failed'] = '1'; 
  462.  
  463. // Do additional reply toggle actions (admin side) 
  464. do_action( 'bbp_toggle_reply_admin', $success, $post_data, $action, $message ); 
  465.  
  466. // Redirect back to the reply 
  467. $redirect = add_query_arg( $message, remove_query_arg( array( 'action', 'reply_id' ) ) ); 
  468. wp_safe_redirect( $redirect ); 
  469.  
  470. // For good measure 
  471. exit(); 
  472.  
  473. /** 
  474. * Toggle reply notices 
  475. * 
  476. * Display the success/error notices from 
  477. * {@link BBP_Admin::toggle_reply()} 
  478. * 
  479. * @since bbPress (r2740) 
  480. * 
  481. * @uses bbp_get_reply() To get the reply 
  482. * @uses bbp_get_reply_title() To get the reply title of the reply 
  483. * @uses esc_html() To sanitize the reply title 
  484. * @uses apply_filters() Calls 'bbp_toggle_reply_notice_admin' with 
  485. * message, reply id, notice and is it a failure 
  486. */ 
  487. public function toggle_reply_notice() { 
  488.  
  489. if ( $this->bail() ) return; 
  490.  
  491. // Only proceed if GET is a reply toggle action 
  492. if ( bbp_is_get_request() && !empty( $_GET['bbp_reply_toggle_notice'] ) && in_array( $_GET['bbp_reply_toggle_notice'], array( 'spammed', 'unspammed' ) ) && !empty( $_GET['reply_id'] ) ) { 
  493. $notice = $_GET['bbp_reply_toggle_notice']; // Which notice? 
  494. $reply_id = (int) $_GET['reply_id']; // What's the reply id? 
  495. $is_failure = !empty( $_GET['failed'] ) ? true : false; // Was that a failure? 
  496.  
  497. // Empty? No reply? 
  498. if ( empty( $notice ) || empty( $reply_id ) ) 
  499. return; 
  500.  
  501. // Get reply and bail if empty 
  502. $reply = bbp_get_reply( $reply_id ); 
  503. if ( empty( $reply ) ) 
  504. return; 
  505.  
  506. $reply_title = bbp_get_reply_title( $reply->ID ); 
  507.  
  508. switch ( $notice ) { 
  509. case 'spammed' : 
  510. $message = $is_failure === true ? sprintf( __( 'There was a problem marking the reply "%1$s" as spam.', 'bbpress' ), $reply_title ) : sprintf( __( 'Reply "%1$s" successfully marked as spam.', 'bbpress' ), $reply_title ); 
  511. break; 
  512.  
  513. case 'unspammed' : 
  514. $message = $is_failure === true ? sprintf( __( 'There was a problem unmarking the reply "%1$s" as spam.', 'bbpress' ), $reply_title ) : sprintf( __( 'Reply "%1$s" successfully unmarked as spam.', 'bbpress' ), $reply_title ); 
  515. break; 
  516.  
  517. // Do additional reply toggle notice filters (admin side) 
  518. $message = apply_filters( 'bbp_toggle_reply_notice_admin', $message, $reply->ID, $notice, $is_failure ); 
  519.  
  520. ?> 
  521.  
  522. <div id="message" class="<?php echo $is_failure === true ? 'error' : 'updated'; ?> fade"> 
  523. <p style="line-height: 150%"><?php echo esc_html( $message ); ?></p> 
  524. </div> 
  525.  
  526. <?php 
  527.  
  528. /** 
  529. * Manage the column headers for the replies page 
  530. * 
  531. * @since bbPress (r2577) 
  532. * 
  533. * @param array $columns The columns 
  534. * @uses apply_filters() Calls 'bbp_admin_replies_column_headers' with 
  535. * the columns 
  536. * @return array $columns bbPress reply columns 
  537. */ 
  538. public function column_headers( $columns ) { 
  539.  
  540. if ( $this->bail() ) return $columns; 
  541.  
  542. $columns = array( 
  543. 'cb' => '<input type="checkbox" />',  
  544. 'title' => __( 'Title', 'bbpress' ),  
  545. 'bbp_reply_forum' => __( 'Forum', 'bbpress' ),  
  546. 'bbp_reply_topic' => __( 'Topic', 'bbpress' ),  
  547. 'bbp_reply_author' => __( 'Author', 'bbpress' ),  
  548. 'bbp_reply_created' => __( 'Created', 'bbpress' ),  
  549. ); 
  550.  
  551. return apply_filters( 'bbp_admin_replies_column_headers', $columns ); 
  552.  
  553. /** 
  554. * Print extra columns for the replies page 
  555. * 
  556. * @since bbPress (r2577) 
  557. * 
  558. * @param string $column Column 
  559. * @param int $reply_id reply id 
  560. * @uses bbp_get_reply_topic_id() To get the topic id of the reply 
  561. * @uses bbp_topic_title() To output the reply's topic title 
  562. * @uses apply_filters() Calls 'reply_topic_row_actions' with an array 
  563. * of reply topic actions 
  564. * @uses bbp_get_topic_permalink() To get the topic permalink 
  565. * @uses bbp_get_topic_forum_id() To get the forum id of the topic of 
  566. * the reply 
  567. * @uses bbp_get_forum_permalink() To get the forum permalink 
  568. * @uses admin_url() To get the admin url of post.php 
  569. * @uses apply_filters() Calls 'reply_topic_forum_row_actions' with an 
  570. * array of reply topic forum actions 
  571. * @uses bbp_reply_author_display_name() To output the reply author name 
  572. * @uses get_the_date() Get the reply creation date 
  573. * @uses get_the_time() Get the reply creation time 
  574. * @uses esc_attr() To sanitize the reply creation time 
  575. * @uses bbp_get_reply_last_active_time() To get the time when the reply was 
  576. * last active 
  577. * @uses do_action() Calls 'bbp_admin_replies_column_data' with the 
  578. * column and reply id 
  579. */ 
  580. public function column_data( $column, $reply_id ) { 
  581.  
  582. if ( $this->bail() ) return; 
  583.  
  584. // Get topic ID 
  585. $topic_id = bbp_get_reply_topic_id( $reply_id ); 
  586.  
  587. // Populate Column Data 
  588. switch ( $column ) { 
  589.  
  590. // Topic 
  591. case 'bbp_reply_topic' : 
  592.  
  593. // Output forum name 
  594. if ( !empty( $topic_id ) ) { 
  595.  
  596. // Topic Title 
  597. $topic_title = bbp_get_topic_title( $topic_id ); 
  598. if ( empty( $topic_title ) ) { 
  599. $topic_title = esc_html__( 'No Topic', 'bbpress' ); 
  600.  
  601. // Output the title 
  602. echo $topic_title; 
  603.  
  604. // Reply has no topic 
  605. } else { 
  606. esc_html_e( 'No Topic', 'bbpress' ); 
  607.  
  608. break; 
  609.  
  610. // Forum 
  611. case 'bbp_reply_forum' : 
  612.  
  613. // Get Forum ID's 
  614. $reply_forum_id = bbp_get_reply_forum_id( $reply_id ); 
  615. $topic_forum_id = bbp_get_topic_forum_id( $topic_id ); 
  616.  
  617. // Output forum name 
  618. if ( !empty( $reply_forum_id ) ) { 
  619.  
  620. // Forum Title 
  621. $forum_title = bbp_get_forum_title( $reply_forum_id ); 
  622. if ( empty( $forum_title ) ) { 
  623. $forum_title = esc_html__( 'No Forum', 'bbpress' ); 
  624.  
  625. // Alert capable users of reply forum mismatch 
  626. if ( $reply_forum_id !== $topic_forum_id ) { 
  627. if ( current_user_can( 'edit_others_replies' ) || current_user_can( 'moderate' ) ) { 
  628. $forum_title .= '<div class="attention">' . esc_html__( '(Mismatch)', 'bbpress' ) . '</div>'; 
  629.  
  630. // Output the title 
  631. echo $forum_title; 
  632.  
  633. // Reply has no forum 
  634. } else { 
  635. _e( 'No Forum', 'bbpress' ); 
  636.  
  637. break; 
  638.  
  639. // Author 
  640. case 'bbp_reply_author' : 
  641. bbp_reply_author_display_name ( $reply_id ); 
  642. break; 
  643.  
  644. // Freshness 
  645. case 'bbp_reply_created': 
  646.  
  647. // Output last activity time and date 
  648. printf( '%1$s <br /> %2$s',  
  649. get_the_date(),  
  650. esc_attr( get_the_time() ) 
  651. ); 
  652.  
  653. break; 
  654.  
  655. // Do action for anything else 
  656. default : 
  657. do_action( 'bbp_admin_replies_column_data', $column, $reply_id ); 
  658. break; 
  659.  
  660. /** 
  661. * Reply Row actions 
  662. * 
  663. * Remove the quick-edit action link under the reply title and add the 
  664. * content and spam link 
  665. * 
  666. * @since bbPress (r2577) 
  667. * 
  668. * @param array $actions Actions 
  669. * @param array $reply Reply object 
  670. * @uses bbp_get_reply_post_type() To get the reply post type 
  671. * @uses bbp_reply_content() To output reply content 
  672. * @uses bbp_get_reply_permalink() To get the reply link 
  673. * @uses bbp_get_reply_title() To get the reply title 
  674. * @uses current_user_can() To check if the current user can edit or 
  675. * delete the reply 
  676. * @uses bbp_is_reply_spam() To check if the reply is marked as spam 
  677. * @uses get_post_type_object() To get the reply post type object 
  678. * @uses add_query_arg() To add custom args to the url 
  679. * @uses remove_query_arg() To remove custom args from the url 
  680. * @uses wp_nonce_url() To nonce the url 
  681. * @uses get_delete_post_link() To get the delete post link of the reply 
  682. * @return array $actions Actions 
  683. */ 
  684. public function row_actions( $actions, $reply ) { 
  685.  
  686. if ( $this->bail() ) return $actions; 
  687.  
  688. unset( $actions['inline hide-if-no-js'] ); 
  689.  
  690. // Reply view links to topic 
  691. $actions['view'] = '<a href="' . esc_url( bbp_get_reply_url( $reply->ID ) ) . '" title="' . esc_attr( sprintf( __( 'View “%s”', 'bbpress' ), bbp_get_reply_title( $reply->ID ) ) ) . '" rel="permalink">' . esc_html__( 'View', 'bbpress' ) . '</a>'; 
  692.  
  693. // User cannot view replies in trash 
  694. if ( ( bbp_get_trash_status_id() === $reply->post_status ) && !current_user_can( 'view_trash' ) ) 
  695. unset( $actions['view'] ); 
  696.  
  697. // Only show the actions if the user is capable of viewing them 
  698. if ( current_user_can( 'moderate', $reply->ID ) ) { 
  699. if ( in_array( $reply->post_status, array( bbp_get_public_status_id(), bbp_get_spam_status_id() ) ) ) { 
  700. $spam_uri = wp_nonce_url( add_query_arg( array( 'reply_id' => $reply->ID, 'action' => 'bbp_toggle_reply_spam' ), remove_query_arg( array( 'bbp_reply_toggle_notice', 'reply_id', 'failed', 'super' ) ) ), 'spam-reply_' . $reply->ID ); 
  701. if ( bbp_is_reply_spam( $reply->ID ) ) { 
  702. $actions['spam'] = '<a href="' . esc_url( $spam_uri ) . '" title="' . esc_attr__( 'Mark the reply as not spam', 'bbpress' ) . '">' . esc_html__( 'Not spam', 'bbpress' ) . '</a>'; 
  703. } else { 
  704. $actions['spam'] = '<a href="' . esc_url( $spam_uri ) . '" title="' . esc_attr__( 'Mark this reply as spam', 'bbpress' ) . '">' . esc_html__( 'Spam', 'bbpress' ) . '</a>'; 
  705.  
  706. // Trash 
  707. if ( current_user_can( 'delete_reply', $reply->ID ) ) { 
  708. if ( bbp_get_trash_status_id() === $reply->post_status ) { 
  709. $post_type_object = get_post_type_object( bbp_get_reply_post_type() ); 
  710. $actions['untrash'] = "<a title='" . esc_attr__( 'Restore this item from the Trash', 'bbpress' ) . "' href='" . esc_url( add_query_arg( array( '_wp_http_referer' => add_query_arg( array( 'post_type' => bbp_get_reply_post_type() ), admin_url( 'edit.php' ) ) ), wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&action=untrash', $reply->ID ) ), 'untrash-' . $reply->post_type . '_' . $reply->ID ) ) ) . "'>" . esc_html__( 'Restore', 'bbpress' ) . "</a>"; 
  711. } elseif ( EMPTY_TRASH_DAYS ) { 
  712. $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_reply_post_type() ), admin_url( 'edit.php' ) ) ), get_delete_post_link( $reply->ID ) ) ) . "'>" . esc_html__( 'Trash', 'bbpress' ) . "</a>"; 
  713.  
  714. if ( bbp_get_trash_status_id() === $reply->post_status || !EMPTY_TRASH_DAYS ) { 
  715. $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_reply_post_type() ), admin_url( 'edit.php' ) ) ), get_delete_post_link( $reply->ID, '', true ) ) ) . "'>" . esc_html__( 'Delete Permanently', 'bbpress' ) . "</a>"; 
  716. } elseif ( bbp_get_spam_status_id() === $reply->post_status ) { 
  717. unset( $actions['trash'] ); 
  718.  
  719. return $actions; 
  720.  
  721. /** 
  722. * Add forum dropdown to topic and reply list table filters 
  723. * 
  724. * @since bbPress (r2991) 
  725. * 
  726. * @uses bbp_get_reply_post_type() To get the reply post type 
  727. * @uses bbp_get_topic_post_type() To get the topic post type 
  728. * @uses bbp_dropdown() To generate a forum dropdown 
  729. * @return bool False. If post type is not topic or reply 
  730. */ 
  731. public function filter_dropdown() { 
  732.  
  733. if ( $this->bail() ) return; 
  734.  
  735. // Add Empty Spam button 
  736. if ( !empty( $_GET['post_status'] ) && ( bbp_get_spam_status_id() === $_GET['post_status'] ) && current_user_can( 'moderate' ) ) { 
  737. wp_nonce_field( 'bulk-destroy', '_destroy_nonce' ); 
  738. $title = esc_attr__( 'Empty Spam', 'bbpress' ); 
  739. submit_button( $title, 'button-secondary apply', 'delete_all', false ); 
  740.  
  741. // Get which forum is selected 
  742. $selected = !empty( $_GET['bbp_forum_id'] ) ? $_GET['bbp_forum_id'] : ''; 
  743.  
  744. // Show the forums dropdown 
  745. bbp_dropdown( array( 
  746. 'selected' => $selected,  
  747. 'show_none' => __( 'In all forums', 'bbpress' ) 
  748. ) ); 
  749.  
  750. /** 
  751. * Adjust the request query and include the forum id 
  752. * 
  753. * @since bbPress (r2991) 
  754. * 
  755. * @param array $query_vars Query variables from {@link WP_Query} 
  756. * @uses is_admin() To check if it's the admin section 
  757. * @uses bbp_get_topic_post_type() To get the topic post type 
  758. * @uses bbp_get_reply_post_type() To get the reply post type 
  759. * @return array Processed Query Vars 
  760. */ 
  761. public function filter_post_rows( $query_vars ) { 
  762.  
  763. if ( $this->bail() ) return $query_vars; 
  764.  
  765. // Add post_parent query_var if one is present 
  766. if ( !empty( $_GET['bbp_forum_id'] ) ) { 
  767. $query_vars['meta_key'] = '_bbp_forum_id'; 
  768. $query_vars['meta_value'] = $_GET['bbp_forum_id']; 
  769.  
  770. // Return manipulated query_vars 
  771. return $query_vars; 
  772.  
  773. /** 
  774. * Custom user feedback messages for reply post type 
  775. * 
  776. * @since bbPress (r3080) 
  777. * 
  778. * @global int $post_ID 
  779. * @uses bbp_get_topic_permalink() 
  780. * @uses wp_post_revision_title() 
  781. * @uses esc_url() 
  782. * @uses add_query_arg() 
  783. * 
  784. * @param array $messages 
  785. * 
  786. * @return array 
  787. */ 
  788. public function updated_messages( $messages ) { 
  789. global $post_ID; 
  790.  
  791. if ( $this->bail() ) return $messages; 
  792.  
  793. // URL for the current topic 
  794. $topic_url = bbp_get_topic_permalink( bbp_get_reply_topic_id( $post_ID ) ); 
  795.  
  796. // Current reply's post_date 
  797. $post_date = bbp_get_global_post_field( 'post_date', 'raw' ); 
  798.  
  799. // Messages array 
  800. $messages[$this->post_type] = array( 
  801. 0 => '', // Left empty on purpose 
  802.  
  803. // Updated 
  804. 1 => sprintf( __( 'Reply updated. <a href="%s">View topic</a>', 'bbpress' ), $topic_url ),  
  805.  
  806. // Custom field updated 
  807. 2 => __( 'Custom field updated.', 'bbpress' ),  
  808.  
  809. // Custom field deleted 
  810. 3 => __( 'Custom field deleted.', 'bbpress' ),  
  811.  
  812. // Reply updated 
  813. 4 => __( 'Reply updated.', 'bbpress' ),  
  814.  
  815. // Restored from revision 
  816. // translators: %s: date and time of the revision 
  817. 5 => isset( $_GET['revision'] ) 
  818. ? sprintf( __( 'Reply restored to revision from %s', 'bbpress' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) 
  819. : false,  
  820.  
  821. // Reply created 
  822. 6 => sprintf( __( 'Reply created. <a href="%s">View topic</a>', 'bbpress' ), $topic_url ),  
  823.  
  824. // Reply saved 
  825. 7 => __( 'Reply saved.', 'bbpress' ),  
  826.  
  827. // Reply submitted 
  828. 8 => sprintf( __( 'Reply submitted. <a target="_blank" href="%s">Preview topic</a>', 'bbpress' ), esc_url( add_query_arg( 'preview', 'true', $topic_url ) ) ),  
  829.  
  830. // Reply scheduled 
  831. 9 => sprintf( __( 'Reply scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview topic</a>', 'bbpress' ),  
  832. // translators: Publish box date format, see http://php.net/date 
  833. date_i18n( __( 'M j, Y @ G:i', 'bbpress' ),  
  834. strtotime( $post_date ) ),  
  835. $topic_url ),  
  836.  
  837. // Reply draft updated 
  838. 10 => sprintf( __( 'Reply draft updated. <a target="_blank" href="%s">Preview topic</a>', 'bbpress' ), esc_url( add_query_arg( 'preview', 'true', $topic_url ) ) ),  
  839. ); 
  840.  
  841. return $messages; 
  842. endif; // class_exists check 
  843.  
  844. /** 
  845. * Setup bbPress Replies Admin 
  846. * 
  847. * This is currently here to make hooking and unhooking of the admin UI easy. 
  848. * It could use dependency injection in the future, but for now this is easier. 
  849. * 
  850. * @since bbPress (r2596) 
  851. * 
  852. * @uses BBP_Replies_Admin 
  853. */ 
  854. function bbp_admin_replies() { 
  855. bbpress()->admin->replies = new BBP_Replies_Admin(); 
.