[ Index ] |
PHP Cross Reference of BBPress |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * bbPress Replies Admin Class 5 * 6 * @package bbPress 7 * @subpackage Administration 8 */ 9 10 // Exit if accessed directly 11 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 2.0.0 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 2.0.0 bbPress (r2515) 36 */ 37 public function __construct() { 38 $this->setup_globals(); 39 $this->setup_actions(); 40 } 41 42 /** 43 * Setup the admin hooks, actions and filters 44 * 45 * @since 2.0.0 bbPress (r2646) 46 * @since 2.6.0 bbPress (r6101) Added bulk actions 47 * 48 * @access private 49 */ 50 private function setup_actions() { 51 52 // Messages 53 add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) ); 54 55 // Reply bulk actions, added in WordPress 4.7, see #WP16031 56 if ( bbp_get_major_wp_version() >= 4.7 ) { 57 add_filter( 'bulk_actions-edit-reply', array( $this, 'bulk_actions' ) ); 58 add_filter( 'handle_bulk_actions-edit-reply', array( $this, 'handle_bulk_actions' ), 10, 3 ); 59 add_filter( 'bulk_post_updated_messages', array( $this, 'bulk_post_updated_messages' ), 10, 2 ); 60 } 61 62 // Reply column headers. 63 add_filter( 'manage_' . $this->post_type . '_posts_columns', array( $this, 'column_headers' ) ); 64 65 // Reply columns (in post row) 66 add_action( 'manage_' . $this->post_type . '_posts_custom_column', array( $this, 'column_data' ), 10, 2 ); 67 add_filter( 'post_row_actions', array( $this, 'row_actions' ), 10, 2 ); 68 69 // Reply meta-box actions 70 add_action( 'add_meta_boxes', array( $this, 'attributes_metabox' ) ); 71 add_action( 'add_meta_boxes', array( $this, 'author_metabox' ) ); 72 add_action( 'add_meta_boxes', array( $this, 'comments_metabox' ) ); 73 add_action( 'save_post', array( $this, 'save_meta_boxes' ) ); 74 75 // Check if there are any bbp_toggle_reply_* requests on admin_init, also have a message displayed 76 add_action( 'load-edit.php', array( $this, 'toggle_reply' ) ); 77 add_action( 'load-edit.php', array( $this, 'toggle_reply_notice' ) ); 78 79 // Add ability to filter topics and replies per forum 80 add_filter( 'restrict_manage_posts', array( $this, 'filter_dropdown' ) ); 81 add_filter( 'bbp_request', array( $this, 'filter_post_rows' ) ); 82 83 // Empty spam 84 add_filter( 'manage_posts_extra_tablenav', array( $this, 'filter_empty_spam' ) ); 85 86 // Contextual Help 87 add_action( 'load-edit.php', array( $this, 'edit_help' ) ); 88 add_action( 'load-post.php', array( $this, 'new_help' ) ); 89 add_action( 'load-post-new.php', array( $this, 'new_help' ) ); 90 } 91 92 /** 93 * Admin globals 94 * 95 * @since 2.0.0 bbPress (r2646) 96 * 97 * @access private 98 */ 99 private function setup_globals() { 100 $this->post_type = bbp_get_reply_post_type(); 101 } 102 103 /** Contextual Help *******************************************************/ 104 105 /** 106 * Contextual help for bbPress reply edit page 107 * 108 * @since 2.0.0 bbPress (r3119) 109 */ 110 public function edit_help() { 111 112 // Overview 113 get_current_screen()->add_help_tab( array( 114 'id' => 'overview', 115 'title' => __( 'Overview', 'bbpress' ), 116 'content' => 117 '<p>' . __( 'This screen provides access to all of your replies. You can customize the display of this screen to suit your workflow.', 'bbpress' ) . '</p>' 118 ) ); 119 120 // Screen Content 121 get_current_screen()->add_help_tab( array( 122 'id' => 'screen-content', 123 'title' => __( 'Screen Content', 'bbpress' ), 124 'content' => 125 '<p>' . __( 'You can customize the display of this screen’s contents in a number of ways:', 'bbpress' ) . '</p>' . 126 '<ul>' . 127 '<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>' . 128 '<li>' . __( 'You can filter the list of replies by reply status using the text links in the upper left to show All, Published, Draft, Pending, Trashed, or Spam replies. The default view is to show all replies.', 'bbpress' ) . '</li>' . 129 '<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>' . 130 '<li>' . __( 'You can refine the list to show only replies in a specific forum or from a specific month by using the dropdown menus above the replies list. Click the Filter button after making your selection.', 'bbpress' ) . '</li>' . 131 '</ul>' 132 ) ); 133 134 // Available Actions 135 get_current_screen()->add_help_tab( array( 136 'id' => 'action-links', 137 'title' => __( 'Available Actions', 'bbpress' ), 138 'content' => 139 '<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>' . 140 '<ul>' . 141 '<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>' . 142 //'<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>' . 143 '<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>' . 144 '<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>' . 145 '<li>' . __( '<strong>View</strong> will take you to your live site to view the reply.', 'bbpress' ) . '</li>' . 146 '<li>' . __( '<strong>Approve</strong> will change the status from pending to publish.', 'bbpress' ) . '</li>' . 147 '</ul>' 148 ) ); 149 150 // Bulk Actions 151 get_current_screen()->add_help_tab( array( 152 'id' => 'bulk-actions', 153 'title' => __( 'Bulk Actions', 'bbpress' ), 154 'content' => 155 '<p>' . __( 'You can also edit, spam, 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>' . 156 '<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>' 157 ) ); 158 159 // Help Sidebar 160 get_current_screen()->set_help_sidebar( 161 '<p><strong>' . __( 'For more information:', 'bbpress' ) . '</strong></p>' . 162 '<p>' . __( '<a href="https://codex.bbpress.org" target="_blank">bbPress Documentation</a>', 'bbpress' ) . '</p>' . 163 '<p>' . __( '<a href="https://bbpress.org/forums/" target="_blank">bbPress Support Forums</a>', 'bbpress' ) . '</p>' 164 ); 165 } 166 167 /** 168 * Contextual help for bbPress reply edit page 169 * 170 * @since 2.0.0 bbPress (r3119) 171 */ 172 public function new_help() { 173 174 $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>'; 175 176 get_current_screen()->add_help_tab( array( 177 'id' => 'customize-display', 178 'title' => __( 'Customizing This Display', 'bbpress' ), 179 'content' => $customize_display, 180 ) ); 181 182 get_current_screen()->add_help_tab( array( 183 'id' => 'title-reply-editor', 184 'title' => __( 'Title and Reply Editor', 'bbpress' ), 185 'content' => 186 '<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>' . 187 '<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>' 188 ) ); 189 190 $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>'; 191 192 if ( current_theme_supports( 'reply-thumbnails' ) && post_type_supports( bbp_get_reply_post_type(), 'thumbnail' ) ) { 193 $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>'; 194 } 195 196 get_current_screen()->add_help_tab( array( 197 'id' => 'reply-attributes', 198 'title' => __( 'Reply Attributes', 'bbpress' ), 199 'content' => 200 '<p>' . __( 'Select the attributes that your reply should have:', 'bbpress' ) . '</p>' . 201 '<ul>' . 202 '<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>' . 203 '<li>' . __( '<strong>Topic</strong> determines the parent topic that the reply belongs to.', 'bbpress' ) . '</li>' . 204 '<li>' . __( '<strong>Reply To</strong> determines the threading of the reply.', 'bbpress' ) . '</li>' . 205 '</ul>' 206 ) ); 207 208 get_current_screen()->add_help_tab( array( 209 'id' => 'publish-box', 210 'title' => __( 'Publish Box', 'bbpress' ), 211 'content' => $publish_box, 212 ) ); 213 214 get_current_screen()->set_help_sidebar( 215 '<p><strong>' . __( 'For more information:', 'bbpress' ) . '</strong></p>' . 216 '<p>' . __( '<a href="https://codex.bbpress.org" target="_blank">bbPress Documentation</a>', 'bbpress' ) . '</p>' . 217 '<p>' . __( '<a href="https://bbpress.org/forums/" target="_blank">bbPress Support Forums</a>', 'bbpress' ) . '</p>' 218 ); 219 } 220 221 /** 222 * Add spam/unspam bulk actions to the bulk action dropdown. 223 * 224 * @since 2.6.0 bbPress (r6101) 225 * 226 * @param array $actions The list of bulk actions. 227 * @return array The filtered list of bulk actions. 228 */ 229 public function bulk_actions( $actions ) { 230 231 if ( current_user_can( 'moderate' ) ) { 232 if ( bbp_get_spam_status_id() === get_query_var( 'post_status' ) ) { 233 $actions['unspam'] = esc_html__( 'Unspam', 'bbpress' ); 234 } else { 235 $actions['spam'] = esc_html__( 'Spam', 'bbpress' ); 236 } 237 } 238 239 return $actions; 240 } 241 242 /** 243 * Add custom bulk action updated messages for replies. 244 * 245 * @since 2.6.0 bbPress (r6101) 246 * 247 * @param array $bulk_messages Arrays of messages, each keyed by the corresponding post type. 248 * @param array $bulk_counts Array of item counts for each message, used to build internationalized strings. 249 */ 250 public function bulk_post_updated_messages( $bulk_messages, $bulk_counts ) { 251 $bulk_messages['reply']['updated'] = _n( '%s reply updated.', '%s replies updated.', $bulk_counts['updated'], 'bbpress'); 252 $bulk_messages['reply']['locked'] = ( 1 === $bulk_counts['locked'] ) 253 ? __( '1 reply not updated, somebody is editing it.', 'bbpress' ) 254 : _n( '%s reply not updated, somebody is editing it.', '%s replies not updated, somebody is editing them.', $bulk_counts['locked'], 'bbpress' ); 255 256 return $bulk_messages; 257 } 258 259 /** 260 * Handle spam/unspam bulk actions. 261 * 262 * @since 2.6.0 bbPress (r6101) 263 * 264 * @param string $sendback The sendback URL. 265 * @param string $doaction The action to be taken. 266 * @param array $post_ids The post IDS to take the action on. 267 * @return string The sendback URL. 268 */ 269 public function handle_bulk_actions( $sendback, $doaction, $post_ids ) { 270 271 $sendback = remove_query_arg( array( 'spam', 'unspam' ), $sendback ); 272 $updated = $locked = 0; 273 274 if ( 'spam' === $doaction ) { 275 276 foreach ( (array) $post_ids as $post_id ) { 277 if ( ! current_user_can( 'moderate', $post_id ) ) { 278 wp_die( esc_html__( 'Sorry, you are not allowed to spam this item.', 'bbpress' ) ); 279 } 280 281 if ( wp_check_post_lock( $post_id ) ) { 282 $locked++; 283 continue; 284 } 285 286 if ( ! bbp_spam_reply( $post_id ) ) { 287 wp_die( esc_html__( 'Error in spamming reply.', 'bbpress' ) ); 288 } 289 290 $updated++; 291 } 292 293 $sendback = add_query_arg( array( 294 'updated' => $updated, 295 'ids' => implode( ',', $post_ids ), 296 'locked' => $locked 297 ), $sendback ); 298 299 } elseif ( 'unspam' === $doaction ) { 300 301 foreach ( (array) $post_ids as $post_id ) { 302 if ( ! current_user_can( 'moderate', $post_id ) ) { 303 wp_die( esc_html__( 'Sorry, you are not allowed to unspam this reply.', 'bbpress' ) ); 304 } 305 306 if ( wp_check_post_lock( $post_id ) ) { 307 $locked++; 308 continue; 309 } 310 311 if ( ! bbp_unspam_reply( $post_id ) ) { 312 wp_die( esc_html__( 'Error in unspamming reply.', 'bbpress' ) ); 313 } 314 315 $updated++; 316 } 317 318 $sendback = add_query_arg( array( 319 'updated' => $updated, 320 'ids' => implode( ',', $post_ids ), 321 'locked' => $locked 322 ), $sendback ); 323 } 324 325 return $sendback; 326 } 327 328 /** 329 * Add the reply attributes meta-box 330 * 331 * @since 2.0.0 bbPress (r2746) 332 */ 333 public function attributes_metabox() { 334 add_meta_box( 335 'bbp_reply_attributes', 336 esc_html__( 'Reply Attributes', 'bbpress' ), 337 'bbp_reply_metabox', 338 $this->post_type, 339 'side', 340 'high' 341 ); 342 } 343 344 /** 345 * Add the author info meta-box 346 * 347 * Allows editing of information about an author 348 * 349 * @since 2.0.0 bbPress (r2828) 350 */ 351 public function author_metabox() { 352 353 // Bail if post_type is not a reply 354 if ( empty( $_GET['action'] ) || ( 'edit' !== $_GET['action'] ) ) { 355 return; 356 } 357 358 // Add the meta-box 359 add_meta_box( 360 'bbp_author_metabox', 361 esc_html__( 'Author Information', 'bbpress' ), 362 'bbp_author_metabox', 363 $this->post_type, 364 'side', 365 'high' 366 ); 367 } 368 369 /** 370 * Remove comments & discussion meta-boxes if comments are not supported 371 * 372 * @since 2.6.0 bbPress (r6186) 373 */ 374 public function comments_metabox() { 375 if ( ! post_type_supports( $this->post_type, 'comments' ) ) { 376 remove_meta_box( 'commentstatusdiv', $this->post_type, 'normal' ); 377 remove_meta_box( 'commentsdiv', $this->post_type, 'normal' ); 378 } 379 } 380 381 /** 382 * Pass the reply attributes for processing 383 * 384 * @since 2.0.0 bbPress (r2746) 385 * 386 * @param int $reply_id Reply id 387 * @return int Parent id 388 */ 389 public function save_meta_boxes( $reply_id ) { 390 391 // Bail if doing an autosave 392 if ( bbp_doing_autosave() ) { 393 return $reply_id; 394 } 395 396 // Bail if not a post request 397 if ( ! bbp_is_post_request() ) { 398 return $reply_id; 399 } 400 401 // Check action exists 402 if ( empty( $_POST['action'] ) ) { 403 return $reply_id; 404 } 405 406 // Nonce check 407 if ( empty( $_POST['bbp_reply_metabox'] ) || ! wp_verify_nonce( $_POST['bbp_reply_metabox'], 'bbp_reply_metabox_save' ) ) { 408 return $reply_id; 409 } 410 411 // Bail if current user cannot edit this reply 412 if ( ! current_user_can( 'edit_reply', $reply_id ) ) { 413 return $reply_id; 414 } 415 416 // Get the reply meta post values 417 $topic_id = ! empty( $_POST['parent_id'] ) ? (int) $_POST['parent_id'] : 0; 418 $forum_id = ! empty( $_POST['bbp_forum_id'] ) ? (int) $_POST['bbp_forum_id'] : bbp_get_topic_forum_id( $topic_id ); 419 $reply_to = ! empty( $_POST['bbp_reply_to'] ) ? (int) $_POST['bbp_reply_to'] : 0; 420 421 // Get reply author data 422 $anonymous_data = bbp_filter_anonymous_post_data(); 423 $author_id = bbp_get_reply_author_id( $reply_id ); 424 $is_edit = ( isset( $_POST['hidden_post_status'] ) && ( $_POST['hidden_post_status'] !== 'draft' ) ); 425 426 // Formally update the reply 427 bbp_update_reply( $reply_id, $topic_id, $forum_id, $anonymous_data, $author_id, $is_edit, $reply_to ); 428 429 // Allow other fun things to happen 430 do_action( 'bbp_reply_attributes_metabox_save', $reply_id, $topic_id, $forum_id, $reply_to ); 431 do_action( 'bbp_author_metabox_save', $reply_id, $anonymous_data ); 432 433 return $reply_id; 434 } 435 436 /** 437 * Toggle reply 438 * 439 * Handles the admin-side spamming/unspamming of replies 440 * 441 * @since 2.0.0 bbPress (r2740) 442 */ 443 public function toggle_reply() { 444 445 // Bail if not a topic toggle action 446 if ( ! bbp_is_get_request() || empty( $_GET['action'] ) || empty( $_GET['reply_id'] ) ) { 447 return; 448 } 449 450 // Bail if not an allowed action 451 $action = sanitize_key( $_GET['action'] ); 452 if ( empty( $action ) || ! in_array( $action, $this->get_allowed_action_toggles(), true ) ) { 453 return; 454 } 455 456 // Get reply and die if empty 457 $reply_id = bbp_get_reply_id( $_GET['reply_id'] ); 458 if ( ! bbp_get_reply( $reply_id ) ) { 459 wp_die( esc_html__( 'The reply was not found.', 'bbpress' ) ); 460 } 461 462 // What is the user doing here? 463 if ( ! current_user_can( 'moderate', $reply_id ) ) { 464 wp_die( esc_html__( 'You do not have permission to do that.', 'bbpress' ) ); 465 } 466 467 // Defaults 468 $post_data = array( 'ID' => $reply_id ); 469 $message = ''; 470 $success = false; 471 472 switch ( $action ) { 473 case 'bbp_toggle_reply_approve' : 474 check_admin_referer( 'approve-reply_' . $reply_id ); 475 476 $is_approve = bbp_is_reply_public( $reply_id ); 477 $message = ( true === $is_approve ) 478 ? 'unpproved' 479 : 'approved'; 480 $success = ( true === $is_approve ) 481 ? bbp_unapprove_reply( $reply_id ) 482 : bbp_approve_reply( $reply_id ); 483 484 break; 485 486 case 'bbp_toggle_reply_spam' : 487 check_admin_referer( 'spam-reply_' . $reply_id ); 488 489 $is_spam = bbp_is_reply_spam( $reply_id ); 490 $message = ( true === $is_spam ) 491 ? 'unspammed' 492 : 'spammed'; 493 $success = ( true === $is_spam ) 494 ? bbp_unspam_reply( $reply_id ) 495 : bbp_spam_reply( $reply_id ); 496 497 break; 498 } 499 500 // Setup the message 501 $retval = array( 502 'bbp_reply_toggle_notice' => $message, 503 'reply_id' => $reply_id 504 ); 505 506 // Prepare for failure 507 if ( ( false === $success ) || is_wp_error( $success ) ) { 508 $retval['failed'] = '1'; 509 } 510 511 // Filter all message args 512 $retval = apply_filters( 'bbp_toggle_reply_action_admin', $retval, $reply_id, $action ); 513 514 // Do additional reply toggle actions (admin side) 515 do_action( 'bbp_toggle_reply_admin', $success, $post_data, $action, $retval ); 516 517 // Redirect back to the reply 518 $redirect = add_query_arg( $retval, remove_query_arg( array( 'action', 'reply_id' ) ) ); 519 bbp_redirect( $redirect ); 520 } 521 522 /** 523 * Toggle reply notices 524 * 525 * Display the success/error notices from 526 * {@link BBP_Admin::toggle_reply()} 527 * 528 * @since 2.0.0 bbPress (r2740) 529 */ 530 public function toggle_reply_notice() { 531 532 // Bail if missing reply toggle action 533 if ( ! bbp_is_get_request() || empty( $_GET['reply_id'] ) || empty( $_GET['bbp_reply_toggle_notice'] ) ) { 534 return; 535 } 536 537 // Bail if not an allowed notice 538 $notice = sanitize_key( $_GET['bbp_reply_toggle_notice'] ); 539 if ( empty( $notice ) || ! in_array( $notice, $this->get_allowed_notice_toggles(), true ) ) { 540 return; 541 } 542 543 // Bail if no reply_id or notice 544 $reply_id = bbp_get_reply_id( $_GET['reply_id'] ); 545 if ( empty( $reply_id ) ) { 546 return; 547 } 548 549 // Bail if reply is missing 550 if ( ! bbp_get_reply( $reply_id ) ) { 551 return; 552 } 553 554 // Use the title in the responses 555 $reply_title = bbp_get_reply_title( $reply_id ); 556 $is_failure = ! empty( $_GET['failed'] ); 557 $message = ''; 558 559 switch ( $notice ) { 560 case 'spammed' : 561 $message = ( $is_failure === true ) 562 ? sprintf( esc_html__( 'There was a problem marking the reply "%1$s" as spam.', 'bbpress' ), $reply_title ) 563 : sprintf( esc_html__( 'Reply "%1$s" successfully marked as spam.', 'bbpress' ), $reply_title ); 564 break; 565 566 case 'unspammed' : 567 $message = ( $is_failure === true ) 568 ? sprintf( esc_html__( 'There was a problem unmarking the reply "%1$s" as spam.', 'bbpress' ), $reply_title ) 569 : sprintf( esc_html__( 'Reply "%1$s" successfully unmarked as spam.', 'bbpress' ), $reply_title ); 570 break; 571 572 case 'approved' : 573 $message = ( $is_failure === true ) 574 ? sprintf( esc_html__( 'There was a problem approving the reply "%1$s".', 'bbpress' ), $reply_title ) 575 : sprintf( esc_html__( 'Reply "%1$s" successfully approved.', 'bbpress' ), $reply_title ); 576 break; 577 578 case 'unapproved' : 579 $message = ( $is_failure === true ) 580 ? sprintf( esc_html__( 'There was a problem unapproving the reply "%1$s".', 'bbpress' ), $reply_title ) 581 : sprintf( esc_html__( 'Reply "%1$s" successfully unapproved.', 'bbpress' ), $reply_title ); 582 break; 583 } 584 585 // Do additional reply toggle notice filters (admin side) 586 $message = apply_filters( 'bbp_toggle_reply_notice_admin', $message, $reply_id, $notice, $is_failure ); 587 $class = ( $is_failure === true ) 588 ? 'error' 589 : 'updated'; 590 591 // Add the notice 592 bbp_admin()->add_notice( $message, $class, true ); 593 } 594 595 /** 596 * Returns an array of keys used to sort row actions 597 * 598 * @since 2.6.0 bbPress (r6771) 599 * 600 * @return array 601 */ 602 private function get_row_action_sort_order() { 603 604 // Filter & return 605 return (array) apply_filters( 'bbp_admin_reply_row_action_sort_order', array( 606 'edit', 607 'approved', 608 'unapproved', 609 'spam', 610 'unspam', 611 'trash', 612 'untrash', 613 'delete', 614 'view' 615 ) ); 616 } 617 618 /** 619 * Returns an array of notice toggles 620 * 621 * @since 2.6.0 bbPress (r6396) 622 * 623 * @return array 624 */ 625 private function get_allowed_notice_toggles() { 626 627 // Filter & return 628 return apply_filters( 'bbp_admin_replies_allowed_notice_toggles', array( 629 'spammed', 630 'unspammed', 631 'approved', 632 'unapproved' 633 ) ); 634 } 635 636 /** 637 * Returns an array of notice toggles 638 * 639 * @since 2.6.0 bbPress (r6396) 640 * 641 * @return array 642 */ 643 private function get_allowed_action_toggles() { 644 645 // Filter & return 646 return apply_filters( 'bbp_admin_replies_allowed_action_toggles', array( 647 'bbp_toggle_reply_spam', 648 'bbp_toggle_reply_approve' 649 ) ); 650 } 651 652 /** 653 * Manage the column headers for the replies page 654 * 655 * @since 2.0.0 bbPress (r2577) 656 * 657 * @param array $columns The columns 658 * 659 * @return array $columns bbPress reply columns 660 */ 661 public function column_headers( $columns ) { 662 $columns = array( 663 'cb' => '<input type="checkbox" />', 664 'title' => esc_html__( 'Title', 'bbpress' ), 665 'bbp_reply_forum' => esc_html__( 'Forum', 'bbpress' ), 666 'bbp_reply_topic' => esc_html__( 'Topic', 'bbpress' ), 667 'bbp_reply_author' => esc_html__( 'Author', 'bbpress' ), 668 'bbp_reply_created' => esc_html__( 'Created', 'bbpress' ), 669 ); 670 671 // Filter & return 672 return apply_filters( 'bbp_admin_replies_column_headers', $columns ); 673 } 674 675 /** 676 * Print extra columns for the replies page 677 * 678 * @since 2.0.0 bbPress (r2577) 679 * 680 * @param string $column Column 681 * @param int $reply_id reply id 682 */ 683 public function column_data( $column, $reply_id ) { 684 685 // Get topic ID 686 $topic_id = bbp_get_reply_topic_id( $reply_id ); 687 688 // Populate Column Data 689 switch ( $column ) { 690 691 // Topic 692 case 'bbp_reply_topic' : 693 694 // Get title 695 $topic_title = ! empty( $topic_id ) 696 ? bbp_get_topic_title( $topic_id ) 697 : ''; 698 699 // Output topic name 700 if ( ! empty( $topic_title ) ) { 701 echo $topic_title; 702 703 // Output dash 704 } else { 705 ?> 706 <span aria-hidden="true">—</span> 707 <span class="screen-reader-text"><?php esc_html_e( 'No topic', 'bbpress' ); ?></span> 708 <?php 709 } 710 711 break; 712 713 // Forum 714 case 'bbp_reply_forum' : 715 716 // Get Forum ID's 717 $reply_forum_id = bbp_get_reply_forum_id( $reply_id ); 718 $topic_forum_id = bbp_get_topic_forum_id( $topic_id ); 719 720 // Forum Title 721 $forum_title = ! empty( $reply_forum_id ) 722 ? bbp_get_forum_title( $reply_forum_id ) 723 : ''; 724 725 // Alert capable users of reply forum mismatch 726 if ( $reply_forum_id !== $topic_forum_id ) { 727 if ( current_user_can( 'edit_others_replies' ) || current_user_can( 'moderate', $reply_id ) ) { 728 $forum_title .= '<div class="attention">' . esc_html__( '(Mismatch)', 'bbpress' ) . '</div>'; 729 } 730 } 731 732 // Output forum name 733 if ( ! empty( $forum_title ) ) { 734 echo $forum_title; 735 736 // Reply has no forum 737 } else { 738 ?> 739 <span aria-hidden="true">—</span> 740 <span class="screen-reader-text"><?php esc_html_e( 'No forum', 'bbpress' ); ?></span> 741 <?php 742 } 743 744 break; 745 746 // Author 747 case 'bbp_reply_author' : 748 bbp_reply_author_display_name( $reply_id ); 749 break; 750 751 // Freshness 752 case 'bbp_reply_created': 753 754 // Output last activity time and date 755 printf( '%1$s <br /> %2$s', 756 get_the_date(), 757 esc_attr( get_the_time() ) 758 ); 759 760 break; 761 762 // Do action for anything else 763 default : 764 do_action( 'bbp_admin_replies_column_data', $column, $reply_id ); 765 break; 766 } 767 } 768 769 /** 770 * Reply Row actions 771 * 772 * Remove the quick-edit action link under the reply title and add the 773 * content and spam link 774 * 775 * @since 2.0.0 bbPress (r2577) 776 * 777 * @param array $actions Actions 778 * @param object $reply Reply object 779 * 780 * @return array $actions Actions 781 */ 782 public function row_actions( $actions = array(), $reply = false ) { 783 784 // Disable quick edit (too much to do here) 785 unset( $actions['inline hide-if-no-js'] ); 786 787 // View link 788 $view_link = bbp_get_reply_url( $reply->ID ); 789 790 // Maybe add view=all 791 if ( ! in_array( $reply->post_status, array( bbp_get_closed_status_id(), bbp_get_public_status_id() ), true ) ) { 792 $view_link = bbp_add_view_all( $view_link, true ); 793 } 794 795 // Reply view links to topic 796 $actions['view'] = '<a href="' . esc_url( $view_link ) . '" title="' . esc_attr( sprintf( __( 'View “%s”', 'bbpress' ), bbp_get_reply_title( $reply->ID ) ) ) . '" rel="permalink">' . esc_html__( 'View', 'bbpress' ) . '</a>'; 797 798 // User cannot view replies in trash 799 if ( ( bbp_get_trash_status_id() === $reply->post_status ) && ! current_user_can( 'view_trash' ) ) { 800 unset( $actions['view'] ); 801 } 802 803 // Only show the actions if the user is capable of viewing them 804 if ( current_user_can( 'moderate', $reply->ID ) ) { 805 806 // Show the 'approve' link on non-published posts only and 'unapprove' on published posts only 807 $approve_uri = wp_nonce_url( add_query_arg( array( 'reply_id' => $reply->ID, 'action' => 'bbp_toggle_reply_approve' ), remove_query_arg( array( 'bbp_reply_toggle_notice', 'reply_id', 'failed', 'super' ) ) ), 'approve-reply_' . $reply->ID ); 808 if ( bbp_is_reply_public( $reply->ID ) ) { 809 $actions['unapproved'] = '<a href="' . esc_url( $approve_uri ) . '" title="' . esc_attr__( 'Unapprove this reply', 'bbpress' ) . '">' . _x( 'Unapprove', 'Unapprove reply', 'bbpress' ) . '</a>'; 810 } else { 811 $actions['approved'] = '<a href="' . esc_url( $approve_uri ) . '" title="' . esc_attr__( 'Approve this reply', 'bbpress' ) . '">' . _x( 'Approve', 'Approve reply', 'bbpress' ) . '</a>'; 812 } 813 814 // Show the 'spam' link on published and pending replies and 'not spam' on spammed replies 815 if ( in_array( $reply->post_status, array( bbp_get_public_status_id(), bbp_get_trash_status_id(), bbp_get_pending_status_id(), bbp_get_spam_status_id() ), true ) ) { 816 $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 ); 817 if ( ! bbp_is_reply_spam( $reply->ID ) ) { 818 $actions['spam'] = '<a href="' . esc_url( $spam_uri ) . '" title="' . esc_attr__( 'Mark this reply as spam', 'bbpress' ) . '">' . esc_html__( 'Spam', 'bbpress' ) . '</a>'; 819 } else { 820 $actions['unspam'] = '<a href="' . esc_url( $spam_uri ) . '" title="' . esc_attr__( 'Mark the reply as not spam', 'bbpress' ) . '">' . esc_html__( 'Not Spam', 'bbpress' ) . '</a>'; 821 } 822 } 823 } 824 825 // Trash 826 if ( current_user_can( 'delete_reply', $reply->ID ) ) { 827 $trash_days = bbp_get_trash_days( bbp_get_reply_post_type() ); 828 829 if ( bbp_get_trash_status_id() === $reply->post_status ) { 830 $post_type_object = get_post_type_object( bbp_get_reply_post_type() ); 831 $actions['untrash'] = "<a title='" . esc_attr__( 'Restore this item from the Trash', 'bbpress' ) . "' href='" . esc_url( wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&action=untrash', $reply->ID ) ), 'untrash-post_' . $reply->ID ) ) . "'>" . esc_html__( 'Restore', 'bbpress' ) . '</a>'; 832 } elseif ( ! empty( $trash_days ) ) { 833 $actions['trash'] = "<a class='submitdelete' title='" . esc_attr__( 'Move this item to the Trash', 'bbpress' ) . "' href='" . esc_url( get_delete_post_link( $reply->ID ) ) . "'>" . esc_html__( 'Trash', 'bbpress' ) . '</a>'; 834 } 835 836 if ( ( bbp_get_trash_status_id() === $reply->post_status ) || empty( $trash_days ) ) { 837 $actions['delete'] = "<a class='submitdelete' title='" . esc_attr__( 'Delete this item permanently', 'bbpress' ) . "' href='" . esc_url( get_delete_post_link( $reply->ID, '', true ) ) . "'>" . esc_html__( 'Delete Permanently', 'bbpress' ) . '</a>'; 838 } 839 } 840 841 // Sort & return 842 return $this->sort_row_actions( $actions ); 843 } 844 845 /** 846 * Sort row actions by key 847 * 848 * @since 2.6.0 849 * 850 * @param array $actions 851 * 852 * @return array 853 */ 854 private function sort_row_actions( $actions = array() ) { 855 856 // Return value 857 $retval = array(); 858 859 // Known row actions, in sort order 860 $known_actions = $this->get_row_action_sort_order(); 861 862 // Sort known actions, and keep any unknown ones 863 foreach ( $known_actions as $key ) { 864 if ( isset( $actions[ $key ] ) ) { 865 $retval[ $key ] = $actions[ $key ]; 866 unset( $actions[ $key ] ); 867 } 868 } 869 870 // Combine & return 871 return $retval + $actions; 872 } 873 874 /** 875 * Add forum dropdown to topic and reply list table filters 876 * 877 * @since 2.0.0 bbPress (r2991) 878 * 879 * @return bool False. If post type is not topic or reply 880 */ 881 public function filter_dropdown() { 882 883 // Get which forum is selected 884 $selected = ! empty( $_GET['bbp_forum_id'] ) 885 ? (int) $_GET['bbp_forum_id'] 886 : 0; 887 888 // Show the forums dropdown 889 bbp_dropdown( array( 890 'selected' => $selected, 891 'show_none' => esc_html__( 'In all forums', 'bbpress' ) 892 ) ); 893 } 894 895 /** 896 * Add "Empty Spam" button for moderators 897 * 898 * @since 2.6.0 bbPress (r6791) 899 */ 900 public function filter_empty_spam() { 901 902 // Bail if not viewing spam 903 if ( empty( $_GET['post_status'] ) || ( bbp_get_spam_status_id() !== $_GET['post_status'] ) && current_user_can( 'moderate' ) ) { 904 return; 905 } 906 907 ?> 908 909 <div class="alignleft actions"><?php 910 911 // Output the nonce & button 912 wp_nonce_field( 'bulk-destroy', '_destroy_nonce' ); 913 submit_button( 914 esc_attr__( 'Empty Spam', 'bbpress' ), 915 'button-secondary apply', 916 'delete_all', 917 false 918 ); 919 920 ?></div><?php 921 } 922 923 /** 924 * Adjust the request query and include the forum id 925 * 926 * @since 2.0.0 bbPress (r2991) 927 * 928 * @param array $query_vars Query variables from {@link WP_Query} 929 * @return array Processed Query Vars 930 */ 931 public function filter_post_rows( $query_vars ) { 932 933 // Add post_parent query_var if one is present 934 if ( ! empty( $_GET['bbp_forum_id'] ) ) { 935 $query_vars['meta_key'] = '_bbp_forum_id'; 936 $query_vars['meta_type'] = 'NUMERIC'; 937 $query_vars['meta_value'] = $_GET['bbp_forum_id']; 938 } 939 940 // Return manipulated query_vars 941 return $query_vars; 942 } 943 944 /** 945 * Custom user feedback messages for reply post type 946 * 947 * @since 2.0.0 bbPress (r3080) 948 * 949 * @global int $post_ID 950 * 951 * @param array $messages 952 * 953 * @return array 954 */ 955 public function updated_messages( $messages ) { 956 global $post_ID; 957 958 // URL for the current topic 959 $topic_url = bbp_get_topic_permalink( bbp_get_reply_topic_id( $post_ID ) ); 960 961 // Current reply's post_date 962 $post_date = bbp_get_global_post_field( 'post_date', 'raw' ); 963 964 // Messages array 965 $messages[ $this->post_type ] = array( 966 0 => '', // Left empty on purpose 967 968 // Updated 969 1 => sprintf( 970 '%1$s <a href="%2$s">%3$s</a>', 971 esc_html__( 'Reply updated.', 'bbpress' ), 972 $topic_url, 973 esc_html__( 'View topic', 'bbpress' ) 974 ), 975 976 // Custom field updated 977 2 => esc_html__( 'Custom field updated.', 'bbpress' ), 978 979 // Custom field deleted 980 3 => esc_html__( 'Custom field deleted.', 'bbpress' ), 981 982 // Reply updated 983 4 => esc_html__( 'Reply updated.', 'bbpress' ), 984 985 // Restored from revision 986 // translators: %s: date and time of the revision 987 5 => isset( $_GET['revision'] ) 988 ? sprintf( esc_html__( 'Reply restored to revision from %s', 'bbpress' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) 989 : false, 990 991 // Reply created 992 6 => sprintf( 993 '%1$s <a href="%2$s">%3$s</a>', 994 esc_html__( 'Reply created.', 'bbpress' ), 995 $topic_url, 996 esc_html__( 'View topic', 'bbpress' ) 997 ), 998 999 // Reply saved 1000 7 => esc_html__( 'Reply saved.', 'bbpress' ), 1001 1002 // Reply submitted 1003 8 => sprintf( 1004 '%1$s <a href="%2$s" target="_blank">%3$s</a>', 1005 esc_html__( 'Reply submitted.', 'bbpress' ), 1006 esc_url( add_query_arg( 'preview', 'true', $topic_url ) ), 1007 esc_html__( 'Preview topic', 'bbpress' ) 1008 ), 1009 1010 // Reply scheduled 1011 9 => sprintf( 1012 '%1$s <a target="_blank" href="%2$s">%3$s</a>', 1013 sprintf( 1014 esc_html__( 'Reply scheduled for: %s.', 'bbpress' ), 1015 // translators: Publish box date format, see http://php.net/date 1016 '<strong>' . date_i18n( __( 'M j, Y @ G:i', 'bbpress' ), strtotime( $post_date ) ) . '</strong>' 1017 ), 1018 $topic_url, 1019 esc_html__( 'Preview topic', 'bbpress' ) 1020 ), 1021 1022 // Reply draft updated 1023 10 => sprintf( 1024 '%1$s <a href="%2$s" target="_blank">%3$s</a>', 1025 esc_html__( 'Reply draft updated.', 'bbpress' ), 1026 esc_url( add_query_arg( 'preview', 'true', $topic_url ) ), 1027 esc_html__( 'Preview topic', 'bbpress' ) 1028 ), 1029 ); 1030 1031 return $messages; 1032 } 1033 } 1034 endif; // class_exists check 1035 1036 /** 1037 * Setup bbPress Replies Admin 1038 * 1039 * This is currently here to make hooking and unhooking of the admin UI easy. 1040 * It could use dependency injection in the future, but for now this is easier. 1041 * 1042 * @since 2.0.0 bbPress (r2596) 1043 * 1044 * @param WP_Screen $current_screen Current screen object 1045 */ 1046 function bbp_admin_replies( $current_screen ) { 1047 1048 // Bail if not a forum screen 1049 if ( empty( $current_screen->post_type ) || ( bbp_get_reply_post_type() !== $current_screen->post_type ) ) { 1050 return; 1051 } 1052 1053 // Init the replies admin 1054 bbp_admin()->replies = new BBP_Replies_Admin(); 1055 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 11 01:00:49 2024 | Cross-referenced by PHPXref 0.7.1 |