PluginProbe
bbPress / 2.6.19
bbPress v2.6.19
2.6.19 2.6.18 2.6.17 trunk 2.0 2.0-beta-1 2.0-beta-2b 2.0-beta-3 2.0-beta-3b 2.0-rc-2 2.0-rc-3 2.0-rc-4 2.0-rc-5 2.0.1 2.0.2 2.0.3 2.1 2.1-beta-1 2.1-rc1 2.1-rc2 2.1-rc3 2.1-rc4 2.1.1 2.1.2 2.1.3 All 74 releases
← All changes | includes/admin/replies.php +123 -28 2.6.18 → 2.6.19 View file →
@@ -15,9 +15,9 @@
15 15 * Loads bbPress replies admin area
16 16 *
17 17 * @package bbPress
18 18 * @subpackage Administration
19 - * @since 2.0.0 bbPress (r2464)
19 + * @since 2.0.0 bbPress (r3095)
20 20 */
21 21 class BBP_Replies_Admin {
22 22
23 23 /** Variables *************************************************************/
@@ -26,14 +26,16 @@
26 26 * @var The post type of this admin component
27 27 */
28 28 private $post_type = '';
29 29
30 + private $accepted_topic_moves = array();
31 +
30 32 /** Functions *************************************************************/
31 33
32 34 /**
33 35 * The main bbPress admin loader
34 36 *
35 - * @since 2.0.0 bbPress (r2515)
37 + * @since 2.0.0 bbPress (r3095)
36 38 */
37 39 public function __construct() {
38 40 $this->setup_globals();
39 41 $this->setup_actions();
@@ -41,9 +43,9 @@
41 43
42 44 /**
43 45 * Setup the admin hooks, actions and filters
44 46 *
45 - * @since 2.0.0 bbPress (r2646)
47 + * @since 2.0.0 bbPress (r3376)
46 48 * @since 2.6.0 bbPress (r6101) Added bulk actions
47 49 *
48 50 * @access private
49 51 */
@@ -70,8 +72,9 @@
70 72 add_action( 'add_meta_boxes', array( $this, 'attributes_metabox' ) );
71 73 add_action( 'add_meta_boxes', array( $this, 'author_metabox' ) );
72 74 add_action( 'add_meta_boxes', array( $this, 'comments_metabox' ) );
73 75 add_action( 'save_post', array( $this, 'save_meta_boxes' ) );
76 + add_filter( 'wp_insert_post_data', array( $this, 'filter_post_data' ), 20, 2 );
74 77
75 78 // Check if there are any bbp_toggle_reply_* requests on admin_init, also have a message displayed
76 79 add_action( 'load-edit.php', array( $this, 'toggle_reply' ) );
77 80 add_action( 'load-edit.php', array( $this, 'toggle_reply_notice' ) );
@@ -91,9 +94,9 @@
91 94
92 95 /**
93 96 * Admin globals
94 97 *
95 - * @since 2.0.0 bbPress (r2646)
98 + * @since 2.0.0 bbPress (r3376)
96 99 *
97 100 * @access private
98 101 */
99 102 private function setup_globals() {
@@ -104,9 +107,9 @@
104 107
105 108 /**
106 109 * Contextual help for bbPress reply edit page
107 110 *
108 - * @since 2.0.0 bbPress (r3119)
111 + * @since 2.1.0 bbPress (r3686)
109 112 */
110 113 public function edit_help() {
111 114
112 115 // Overview
@@ -174,9 +177,9 @@
174 177
175 178 /**
176 179 * Contextual help for bbPress reply edit page
177 180 *
178 - * @since 2.0.0 bbPress (r3119)
181 + * @since 2.1.0 bbPress (r3686)
179 182 */
180 183 public function new_help() {
181 184
182 185 $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>';
@@ -351,9 +354,9 @@
351 354
352 355 /**
353 356 * Add the reply attributes meta-box
354 357 *
355 - * @since 2.0.0 bbPress (r2746)
358 + * @since 2.4.0 bbPress (r4991)
356 359 */
357 360 public function attributes_metabox() {
358 361 add_meta_box(
359 362 'bbp_reply_attributes',
@@ -369,9 +372,9 @@
369 372 * Add the author info meta-box
370 373 *
371 374 * Allows editing of information about an author
372 375 *
373 - * @since 2.0.0 bbPress (r2828)
376 + * @since 2.0.0 bbPress (r3120)
374 377 */
375 378 public function author_metabox() {
376 379
377 380 // Bail if post_type is not a reply
@@ -404,15 +407,24 @@
404 407
405 408 /**
406 409 * Pass the reply attributes for processing
407 410 *
408 - * @since 2.0.0 bbPress (r2746)
411 + * @since 2.6.0 bbPress (r6056)
409 412 *
410 413 * @param int $reply_id Reply id
411 414 * @return int Parent id
412 415 */
413 416 public function save_meta_boxes( $reply_id ) {
417 + $accepted_move = isset( $this->accepted_topic_moves[ $reply_id ] )
418 + ? $this->accepted_topic_moves[ $reply_id ]
419 + : array();
420 + unset( $this->accepted_topic_moves[ $reply_id ] );
414 421
422 + // Revisions can also fire save_post with the metabox nonce.
423 + if ( ! bbp_is_reply( $reply_id ) ) {
424 + return $reply_id;
425 + }
426 +
415 427 // Bail if doing an autosave
416 428 if ( bbp_doing_autosave() ) {
417 429 return $reply_id;
418 430 }
@@ -432,16 +444,21 @@
432 444 return $reply_id;
433 445 }
434 446
435 447 // Bail if current user cannot edit this reply
436 - if ( ! current_user_can( 'edit_reply', $reply_id ) ) {
448 + if ( ! current_user_can( 'edit_reply', $reply_id ) && empty( $accepted_move ) ) {
437 449 return $reply_id;
438 450 }
439 451
440 - // Get the reply meta post values
441 - $topic_id = ! empty( $_POST['parent_id'] ) ? (int) $_POST['parent_id'] : 0;
442 - $forum_id = ! empty( $_POST['bbp_forum_id'] ) ? (int) $_POST['bbp_forum_id'] : bbp_get_topic_forum_id( $topic_id );
443 - $reply_to = ! empty( $_POST['bbp_reply_to'] ) ? (int) $_POST['bbp_reply_to'] : 0;
452 + // Use the accepted topic and its forum, rather than independent form values.
453 + $topic_id = ! empty( $accepted_move )
454 + ? $accepted_move['new']
455 + : bbp_get_reply_topic_id( $reply_id );
456 + $forum_id = bbp_get_topic_forum_id( $topic_id );
457 + $reply_to = ! empty( $_POST['bbp_reply_to'] ) ? bbp_validate_reply_to( (int) $_POST['bbp_reply_to'], $reply_id ) : 0;
458 + if ( ! empty( $reply_to ) && ( bbp_get_reply_topic_id( $reply_to ) !== $topic_id || ! current_user_can( 'read_reply', $reply_to ) ) ) {
459 + $reply_to = 0;
460 + }
444 461
445 462 // Get reply author data
446 463 $anonymous_data = bbp_filter_anonymous_post_data();
447 464 $author_id = bbp_get_reply_author_id( $reply_id );
@@ -448,8 +465,12 @@
448 465 $is_edit = ( isset( $_POST['hidden_post_status'] ) && ( 'draft' !== $_POST['hidden_post_status'] ) );
449 466
450 467 // Formally update the reply
451 468 bbp_update_reply( $reply_id, $topic_id, $forum_id, $anonymous_data, $author_id, $is_edit, $reply_to );
469 + if ( ! empty( $accepted_move['old'] ) ) {
470 + bbp_update_reply_position( $reply_id );
471 + bbp_move_reply_count( $reply_id, $accepted_move['old'], $accepted_move['new'] );
472 + }
452 473
453 474 // Allow other fun things to happen
454 475 do_action( 'bbp_reply_attributes_metabox_save', $reply_id, $topic_id, $forum_id, $reply_to );
455 476 do_action( 'bbp_author_metabox_save', $reply_id, $anonymous_data );
@@ -457,13 +478,82 @@
457 478 return $reply_id;
458 479 }
459 480
460 481 /**
482 + * Keep admin reply moves within topics the current user may moderate.
483 + *
484 + * @since 2.6.19 bbPress (r7688)
485 + *
486 + * @param array $data Sanitized post data.
487 + * @param array $postarr Unprocessed post data.
488 + * @return array Filtered post data.
489 + */
490 + public function filter_post_data( $data, $postarr ) {
491 +
492 + // Only filter administration saves of existing replies.
493 + if ( ! is_admin() || empty( $postarr['ID'] ) || ( bbp_get_reply_post_type() !== $data['post_type'] ) ) {
494 + return $data;
495 + }
496 +
497 + $reply = bbp_get_reply( $postarr['ID'] );
498 + if ( empty( $reply ) || (int) $reply->post_parent === (int) $data['post_parent'] ) {
499 + return $data;
500 + }
501 +
502 + $old_topic_id = (int) $reply->post_parent;
503 + $new_topic_id = (int) $data['post_parent'];
504 + $new_topic = bbp_get_topic( $new_topic_id );
505 + $new_forum_id = bbp_get_topic_forum_id( $new_topic_id );
506 + $is_new = ( 'auto-draft' === $reply->post_status );
507 + $is_editor = ! empty( $_POST['action'] ) && ( 'editpost' === $_POST['action'] );
508 +
509 + // Other admin save paths cannot complete a bbPress reply move.
510 + if ( ! $is_editor && ! $is_new ) {
511 + $data['post_parent'] = $reply->post_parent;
512 + return $data;
513 + }
514 +
515 + // Match the reply move checks before WordPress changes post_parent.
516 + if (
517 + ! $is_editor
518 + || empty( $_POST['bbp_reply_metabox'] )
519 + || ! is_string( $_POST['bbp_reply_metabox'] )
520 + || ! wp_verify_nonce( $_POST['bbp_reply_metabox'], 'bbp_reply_metabox_save' )
521 + || ! current_user_can( 'edit_reply', $reply->ID )
522 + || ( $is_new && ! current_user_can( 'publish_replies' ) )
523 + || ( ! $is_new && ! empty( $old_topic_id ) && ( ! current_user_can( 'moderate', $old_topic_id ) || ! current_user_can( 'edit_topic', $old_topic_id ) ) )
524 + || empty( $new_topic )
525 + || ( $is_new && ( ! current_user_can( 'read_topic', $new_topic_id ) || ( bbp_is_topic_closed( $new_topic_id ) && ! current_user_can( 'edit_topic', $new_topic_id ) ) ) )
526 + || ( $is_new && ( ! current_user_can( 'read_forum', $new_forum_id ) || ( bbp_is_forum_closed( $new_forum_id ) && ! current_user_can( 'edit_forum', $new_forum_id ) ) ) )
527 + || ( ! $is_new && ( ! current_user_can( 'moderate', $new_topic_id ) || ! current_user_can( 'edit_topic', $new_topic_id ) ) )
528 + ) {
529 + if ( $is_new ) {
530 + wp_die(
531 + esc_html__( 'The selected topic is not available for this reply.', 'bbpress' ),
532 + '',
533 + array(
534 + 'response' => 403,
535 + 'back_link' => true,
536 + )
537 + );
538 + }
539 + $data['post_parent'] = $reply->post_parent;
540 + } else {
541 + $this->accepted_topic_moves[ $reply->ID ] = array(
542 + 'old' => $old_topic_id,
543 + 'new' => $new_topic_id,
544 + );
545 + }
546 +
547 + return $data;
548 + }
549 +
550 + /**
461 551 * Toggle reply
462 552 *
463 553 * Handles the admin-side spamming/unspamming of replies
464 554 *
465 - * @since 2.0.0 bbPress (r2740)
555 + * @since 2.0.0 bbPress (r3095)
466 556 */
467 557 public function toggle_reply() {
468 558
469 559 // Bail if not a topic toggle action
@@ -548,9 +638,9 @@
548 638 *
549 639 * Display the success/error notices from
550 640 * {@link BBP_Admin::toggle_reply()}
551 641 *
552 - * @since 2.0.0 bbPress (r2740)
642 + * @since 2.0.0 bbPress (r3095)
553 643 */
554 644 public function toggle_reply_notice() {
555 645
556 646 // Bail if missing reply toggle action
@@ -626,9 +716,9 @@
626 716
627 717 /**
628 718 * Returns an array of keys used to sort row actions
629 719 *
630 - * @since 2.6.0 bbPress (r6771)
720 + * @since 2.6.0 bbPress (r6772)
631 721 *
632 722 * @return array
633 723 */
634 724 private function get_row_action_sort_order() {
@@ -635,9 +725,9 @@
635 725
636 726 /**
637 727 * Filters the row action sort order for replies.
638 728 *
639 - * @since 2.6.0 bbPress (r6771)
729 + * @since 2.6.0 bbPress (r6772)
640 730 *
641 731 * @param array $order The default sort order.
642 732 */
643 733 return (array) apply_filters(
@@ -658,9 +748,9 @@
658 748
659 749 /**
660 750 * Returns an array of notice toggles
661 751 *
662 - * @since 2.6.0 bbPress (r6396)
752 + * @since 2.6.0 bbPress (r6397)
663 753 *
664 754 * @return array
665 755 */
666 756 private function get_allowed_notice_toggles() {
@@ -679,9 +769,9 @@
679 769
680 770 /**
681 771 * Returns an array of notice toggles
682 772 *
683 - * @since 2.6.0 bbPress (r6396)
773 + * @since 2.6.0 bbPress (r6397)
684 774 *
685 775 * @return array
686 776 */
687 777 private function get_allowed_action_toggles() {
@@ -698,9 +788,9 @@
698 788
699 789 /**
700 790 * Manage the column headers for the replies page
701 791 *
702 - * @since 2.0.0 bbPress (r2577)
792 + * @since 2.4.0 bbPress (r4991)
703 793 *
704 794 * @param array $columns The columns
705 795 *
706 796 * @return array $columns bbPress reply columns
@@ -721,9 +811,9 @@
721 811
722 812 /**
723 813 * Print extra columns for the replies page
724 814 *
725 - * @since 2.0.0 bbPress (r2577)
815 + * @since 2.4.0 bbPress (r4991)
726 816 *
727 817 * @param string $column Column
728 818 * @param int $reply_id reply id
729 819 */
@@ -818,9 +908,9 @@
818 908 *
819 909 * Remove the quick-edit action link under the reply title and add the
820 910 * content and spam link
821 911 *
822 - * @since 2.0.0 bbPress (r2577)
912 + * @since 2.4.0 bbPress (r4991)
823 913 *
824 914 * @param array $actions Actions
825 915 * @param object $reply Reply object
826 916 *
@@ -910,9 +1000,9 @@
910 1000
911 1001 /**
912 1002 * Sort row actions by key
913 1003 *
914 - * @since 2.6.0
1004 + * @since 2.6.0 bbPress (r6772)
915 1005 *
916 1006 * @param array $actions
917 1007 *
918 1008 * @return array
@@ -939,9 +1029,9 @@
939 1029
940 1030 /**
941 1031 * Add forum dropdown to topic and reply list table filters
942 1032 *
943 - * @since 2.0.0 bbPress (r2991)
1033 + * @since 2.0.0 bbPress (r3095)
944 1034 *
945 1035 * @return bool False. If post type is not topic or reply
946 1036 */
947 1037 public function filter_dropdown() {
@@ -990,9 +1080,9 @@
990 1080
991 1081 /**
992 1082 * Adjust the request query and include the forum id
993 1083 *
994 - * @since 2.0.0 bbPress (r2991)
1084 + * @since 2.0.0 bbPress (r3095)
995 1085 *
996 1086 * @param array $query_vars Query variables from {@link WP_Query}
997 1087 * @return array Processed Query Vars
998 1088 */
@@ -1011,9 +1101,9 @@
1011 1101
1012 1102 /**
1013 1103 * Custom user feedback messages for reply post type
1014 1104 *
1015 - * @since 2.0.0 bbPress (r3080)
1105 + * @since 2.0.0 bbPress (r3097)
1016 1106 *
1017 1107 * @global int $post_ID
1018 1108 *
1019 1109 * @param array $messages
@@ -1107,13 +1197,18 @@
1107 1197 *
1108 1198 * This is currently here to make hooking and unhooking of the admin UI easy.
1109 1199 * It could use dependency injection in the future, but for now this is easier.
1110 1200 *
1111 - * @since 2.0.0 bbPress (r2596)
1201 + * @since 2.0.0 bbPress (r3343)
1112 1202 *
1113 1203 * @param WP_Screen $current_screen Current screen object
1114 1204 */
1115 1205 function bbp_admin_replies( $current_screen ) {
1206 +
1207 + // Bail if not in site admin
1208 + if ( ! is_blog_admin() ) {
1209 + return;
1210 + }
1116 1211
1117 1212 // Bail if not a forum screen
1118 1213 if ( empty( $current_screen->post_type ) || ( bbp_get_reply_post_type() !== $current_screen->post_type ) ) {
1119 1214 return;