Ticket #8426: 8426.10.patch
File 8426.10.patch, 22.5 KB (added by , 3 years ago) |
---|
-
src/bp-messages/bp-messages-notifications.php
diff --git src/bp-messages/bp-messages-notifications.php src/bp-messages/bp-messages-notifications.php index 176a950d6..758413bbf 100644
function bp_messages_screen_conversation_mark_notifications() { 247 247 $message_ids = array_intersect( $unread_message_ids, wp_list_pluck( $thread_template->thread->messages, 'id' ) ); 248 248 249 249 // Mark each notification for each PM message as read. 250 foreach ( $message_ids as $message_id ) { 251 bp_notifications_mark_notifications_by_item_id( bp_loggedin_user_id(), (int) $message_id, buddypress()->messages->id, 'new_message' ); 252 } 250 bp_notifications_mark_notifications_by_item_ids( bp_loggedin_user_id(), $message_ids, 'messages', 'new_message', false ); 253 251 } 254 252 add_action( 'thread_loop_start', 'bp_messages_screen_conversation_mark_notifications', 10 ); 255 253 … … add_action( 'thread_loop_start', 'bp_messages_screen_conversation_mark_notificat 261 259 * @since 3.0.0 262 260 * 263 261 * @param int $thread_id ID of the thread being marked as read. 262 * @param int $user_id ID of the user thread will be marked as unread. 263 * @param int $num_rows The number of affected rows by the "mark read" update query. 264 264 */ 265 function bp_messages_mark_notification_on_mark_thread( $thread_id ) { 265 function bp_messages_mark_notification_on_mark_thread( $thread_id, $user_id = 0, $num_rows = 0 ) { 266 if ( ! $num_rows ) { 267 return; 268 } 269 266 270 $thread_messages = BP_Messages_Thread::get_messages( $thread_id ); 271 $message_ids = wp_list_pluck( $thread_messages, 'id' ); 267 272 268 foreach ( $thread_messages as $thread_message ) { 269 bp_notifications_mark_notifications_by_item_id( bp_loggedin_user_id(), $thread_message->id, buddypress()->messages->id, 'new_message' ); 270 } 273 bp_notifications_mark_notifications_by_item_ids( $user_id, $message_ids, 'messages', 'new_message', false ); 271 274 } 272 add_action( 'messages_thread_mark_as_read', 'bp_messages_mark_notification_on_mark_thread' );275 add_action( 'messages_thread_mark_as_read', 'bp_messages_mark_notification_on_mark_thread', 10, 3 ); 273 276 274 277 /** 275 278 * When a message is deleted, delete corresponding notifications. … … function bp_messages_message_delete_notifications( $thread_id, $message_ids ) { 283 286 // For each recipient, delete notifications corresponding to each message. 284 287 $thread = new BP_Messages_Thread( $thread_id ); 285 288 foreach ( $thread->get_recipients() as $recipient ) { 286 foreach ( $message_ids as $message_id ) { 287 if ( ! empty( $recipient->user_id ) ) { 288 bp_notifications_delete_notifications_by_item_id( 289 $recipient->user_id, 290 (int) $message_id, 291 buddypress()->messages->id, 292 'new_message' 293 ); 294 } 289 if ( ! isset( $recipient->user_id ) || ! $recipient->user_id ) { 290 continue; 295 291 } 292 293 bp_notifications_delete_notifications_by_item_ids( $recipient->user_id, $message_ids, buddypress()->messages->id, 'new_message' ); 296 294 } 297 295 } 298 296 add_action( 'bp_messages_thread_after_delete', 'bp_messages_message_delete_notifications', 10, 2 ); -
src/bp-messages/classes/class-bp-messages-thread.php
diff --git src/bp-messages/classes/class-bp-messages-thread.php src/bp-messages/classes/class-bp-messages-thread.php index ebdf8bd1e..e1a7f1891 100644
class BP_Messages_Thread { 766 766 bp_loggedin_user_id(); 767 767 } 768 768 769 $bp = buddypress();770 $ retval= $wpdb->query( $wpdb->prepare( "UPDATE {$bp->messages->table_name_recipients} SET unread_count = 0 WHERE user_id = %d AND thread_id = %d", $user_id, $thread_id ) );769 $bp = buddypress(); 770 $num_rows = $wpdb->query( $wpdb->prepare( "UPDATE {$bp->messages->table_name_recipients} SET unread_count = 0 WHERE user_id = %d AND thread_id = %d", $user_id, $thread_id ) ); 771 771 772 772 wp_cache_delete( 'thread_recipients_' . $thread_id, 'bp_messages' ); 773 773 wp_cache_delete( $user_id, 'bp_messages_unread_count' ); … … class BP_Messages_Thread { 777 777 * 778 778 * @since 2.8.0 779 779 * @since 9.0.0 Added the `user_id` parameter. 780 * @since 10.0.0 Added the `$num_rows` parameter. 780 781 * 781 782 * @param int $thread_id The message thread ID. 782 783 * @param int $user_id The user the thread will be marked as read. 784 * @param bool|int $num_rows Number of threads marked as unread or false on error. 783 785 */ 784 do_action( 'messages_thread_mark_as_read', $thread_id, $user_id );786 do_action( 'messages_thread_mark_as_read', $thread_id, $user_id, $num_rows ); 785 787 786 return $ retval;788 return $num_rows; 787 789 } 788 790 789 791 /** … … class BP_Messages_Thread { 810 812 bp_loggedin_user_id(); 811 813 } 812 814 813 $bp = buddypress();814 $ retval= $wpdb->query( $wpdb->prepare( "UPDATE {$bp->messages->table_name_recipients} SET unread_count = 1 WHERE user_id = %d AND thread_id = %d", $user_id, $thread_id ) );815 $bp = buddypress(); 816 $num_rows = $wpdb->query( $wpdb->prepare( "UPDATE {$bp->messages->table_name_recipients} SET unread_count = 1 WHERE user_id = %d AND thread_id = %d", $user_id, $thread_id ) ); 815 817 816 818 wp_cache_delete( 'thread_recipients_' . $thread_id, 'bp_messages' ); 817 819 wp_cache_delete( $user_id, 'bp_messages_unread_count' ); … … class BP_Messages_Thread { 821 823 * 822 824 * @since 2.8.0 823 825 * @since 9.0.0 Added the `$user_id` parameter. 824 * @since 10.0.0 Added the `$ retval` parameter.826 * @since 10.0.0 Added the `$num_rows` parameter. 825 827 * 826 828 * @param int $thread_id The message thread ID. 827 829 * @param int $user_id The user the thread will be marked as unread. 828 * @param bool|int $ retval =Number of threads marked as unread or false on error.830 * @param bool|int $num_rows Number of threads marked as unread or false on error. 829 831 */ 830 do_action( 'messages_thread_mark_as_unread', $thread_id, $user_id, $ retval);832 do_action( 'messages_thread_mark_as_unread', $thread_id, $user_id, $num_rows ); 831 833 832 return $ retval;834 return $num_rows; 833 835 } 834 836 835 837 /** -
src/bp-notifications/actions/bulk-manage.php
diff --git src/bp-notifications/actions/bulk-manage.php src/bp-notifications/actions/bulk-manage.php index 95d8255e5..52e9cb92c 100644
function bp_notifications_action_bulk_manage() { 42 42 // Delete, mark as read or unread depending on the user 'action'. 43 43 switch ( $action ) { 44 44 case 'delete': 45 foreach ( $notifications as $notification ) { 46 bp_notifications_delete_notification( $notification ); 47 } 45 bp_notifications_delete_notifications_by_ids( $notifications ); 48 46 bp_core_add_message( __( 'Notifications deleted.', 'buddypress' ) ); 49 47 break; 50 48 51 49 case 'read': 52 foreach ( $notifications as $notification ) { 53 bp_notifications_mark_notification( $notification, false ); 54 } 50 bp_notifications_mark_notifications_by_ids( $notifications, false ); 55 51 bp_core_add_message( __( 'Notifications marked as read', 'buddypress' ) ); 56 52 break; 57 53 58 54 case 'unread': 59 foreach ( $notifications as $notification ) { 60 bp_notifications_mark_notification( $notification, true ); 61 } 55 bp_notifications_mark_notifications_by_ids( $notifications, true ); 62 56 bp_core_add_message( __( 'Notifications marked as unread.', 'buddypress' ) ); 63 57 break; 64 58 } -
src/bp-notifications/bp-notifications-functions.php
diff --git src/bp-notifications/bp-notifications-functions.php src/bp-notifications/bp-notifications-functions.php index b818ab01b..a7b316af5 100644
function bp_notifications_delete_notifications_by_item_id( $user_id, $item_id, $ 384 384 ) ); 385 385 } 386 386 387 /** 388 * Delete notifications by notification ids. 389 * 390 * @since 10.0.0 391 * 392 * @param array $ids IDs of the associated notifications. 393 * @param string $component_name Name of the associated component. 394 * @param string $component_action Name of the associated action. 395 * @return int|false The number of rows updated. False on error. 396 */ 397 function bp_notifications_delete_notifications_by_ids( $ids ) { 398 return BP_Notifications_Notification::delete_by_id_list( 'id', $ids ); 399 } 400 401 /** 402 * Delete notifications by item ids and user. 403 * 404 * @since 10.0.0 405 * 406 * @param int $user_id ID of the user whose notifications are being deleted. 407 * @param array $item_ids ID of the associated item. 408 * @param string $component_name Name of the associated component. 409 * @param string $component_action Name of the associated action. 410 * @return int|false The number of rows updated. False on error. 411 */ 412 function bp_notifications_delete_notifications_by_item_ids( $user_id, $item_ids, $component_name, $component_action ) { 413 return BP_Notifications_Notification::delete_by_id_list( 414 'item_id', 415 $item_ids, 416 array( 417 'user_id' => $user_id, 418 'component_name' => $component_name, 419 'component_action' => $component_action 420 ) 421 ); 422 } 423 387 424 /** 388 425 * Delete all notifications by type. 389 426 * … … function bp_notifications_mark_notifications_from_user( $user_id, $component_nam 584 621 ); 585 622 } 586 623 624 /** 625 * Mark notifications read/unread by item ids and user. 626 * 627 * @since 10.0.0 628 * 629 * @param int $user_id ID of the user whose notifications are being deleted. 630 * @param array $item_ids ID of the associated item. 631 * @param string $component_name Name of the associated component. 632 * @param string $component_action Name of the associated action. 633 * @param int|false $is_new 0 for read, 1 for unread. 634 * @return int|false The number of rows updated. False on error. 635 */ 636 function bp_notifications_mark_notifications_by_item_ids( $user_id, $item_ids, $component_name, $component_action, $is_new = false ) { 637 return BP_Notifications_Notification::update_id_list( 638 'item_id', 639 $item_ids, 640 array( 641 'is_new' => $is_new, 642 ), 643 array( 644 'user_id' => $user_id, 645 'component_name' => $component_name, 646 'component_action' => $component_action 647 ) 648 ); 649 } 650 651 /** 652 * Mark notifications read/unread by notification ids. 653 * 654 * @since 10.0.0 655 * 656 * @param array $ids IDs of the associated notification items. 657 * @param int|false $is_new 0 for read, 1 for unread. 658 * @return int|false The number of rows updated. False on error. 659 */ 660 function bp_notifications_mark_notifications_by_ids( $ids, $is_new = false ) { 661 return BP_Notifications_Notification::update_id_list( 662 'id', 663 $ids, 664 array( 665 'is_new' => $is_new, 666 ) 667 ); 668 } 669 587 670 /** Helpers *******************************************************************/ 588 671 589 672 /** -
src/bp-notifications/classes/class-bp-notifications-notification.php
diff --git src/bp-notifications/classes/class-bp-notifications-notification.php src/bp-notifications/classes/class-bp-notifications-notification.php index bc3b49821..4d888137e 100644
class BP_Notifications_Notification { 910 910 ); 911 911 } 912 912 913 /** 914 * Update notifications using a list of ids/items_ids. 915 * 916 * @since 10.0.0 917 * 918 * @param string $field The name of the db field of the items to update. 919 * Possible values are `id` or `item_id`. 920 * @param int[] $items The list of items to update. 921 * @param array $data Array of notification data to update, passed to 922 * {@link wpdb::update()}. Accepts any property of a 923 * BP_Notification_Notification object. 924 * @param array $where The WHERE params as passed to wpdb::update(). 925 * Typically consists of array( 'ID' => $id ) to specify the ID 926 * of the item being updated. See {@link wpdb::update()}. 927 * @return int|false The number of rows updated. False on error. 928 */ 929 public static function update_id_list( $field, $items = array(), $data = array(), $where = array() ) { 930 global $wpdb; 931 $bp = buddypress(); 932 933 $supported_fields = array( 'id', 'item_id' ); 934 935 if ( false === in_array( $field, $supported_fields, true ) ) { 936 return false; 937 } 938 939 if ( ! is_array( $items ) || ! is_array( $data ) || ! is_array( $where ) ) { 940 return false; 941 } 942 943 $update_args = self::get_query_clauses( $data ); 944 $where_args = self::get_query_clauses( $where ); 945 946 $fields = array(); 947 $conditions = array(); 948 $values = array(); 949 950 $_items = implode( ',', wp_parse_id_list( $items ) ); 951 $conditions[] = "{$field} IN ({$_items})"; 952 953 foreach ( $update_args['data'] as $field => $value ) { 954 $index = array_search( $field, array_keys( $update_args['data'] ) ); 955 $format = $update_args['format'][ $index ]; 956 957 $fields[] = "{$field} = {$format}"; 958 $values[] = $value; 959 } 960 961 foreach ( $where_args['data'] as $field => $value ) { 962 $index = array_search( $field, array_keys( $where_args['data'] ) ); 963 $format = $where_args['format'][ $index ]; 964 965 $conditions[] = "{$field} = {$format}"; 966 $values[] = $value; 967 } 968 969 $fields = implode( ', ', $fields ); 970 $conditions = implode( ' AND ', $conditions ); 971 972 /** This action is documented in bp-notifications/classes/class-bp-notifications-notification.php */ 973 do_action( 'bp_notification_before_update', $update_args, $where_args ); 974 975 return $wpdb->query( $wpdb->prepare( "UPDATE {$bp->notifications->table_name} SET {$fields} WHERE {$conditions}", $values ) ); 976 } 977 913 978 /** 914 979 * Delete notifications. 915 980 * … … class BP_Notifications_Notification { 940 1005 return self::_delete( $where['data'], $where['format'] ); 941 1006 } 942 1007 1008 /** 1009 * Delete notifications using a list of ids/items_ids. 1010 * 1011 * @since 10.0.0 1012 * 1013 * @param string $field The name of the db field of the items to delete. 1014 * Possible values are `id` or `item_id`. 1015 * @param int[] $items The list of items to delete. 1016 * @param array $args The WHERE params as passed to wpdb::delete(). 1017 * Typically consists of array( 'ID' => $id ) to specify the ID 1018 * of the item being deleted. See {@link wpdb::delete()}. 1019 * @return int|false The number of rows deleted. False on error. 1020 */ 1021 public static function delete_by_id_list( $field, $items = array(), $args = array() ) { 1022 global $wpdb; 1023 $bp = buddypress(); 1024 1025 $supported_fields = array( 'id', 'item_id' ); 1026 1027 if ( false === in_array( $field, $supported_fields, true ) ) { 1028 return false; 1029 } 1030 1031 if ( ! is_array( $items ) || ! is_array( $args ) ) { 1032 return false; 1033 } 1034 1035 $where = self::get_query_clauses( $args ); 1036 1037 $conditions = array(); 1038 $values = array(); 1039 1040 $_items = implode( ',', wp_parse_id_list( $items ) ); 1041 $conditions[] = "{$field} IN ({$_items})"; 1042 1043 foreach ( $where['data'] as $field => $value ) { 1044 $index = array_search( $field, array_keys( $where['data'] ) ); 1045 $format = $where['format'][ $index ]; 1046 1047 $conditions[] = "{$field} = {$format}"; 1048 $values[] = $value; 1049 } 1050 1051 $conditions = implode( ' AND ', $conditions ); 1052 1053 /** This action is documented in bp-notifications/classes/class-bp-notifications-notification.php */ 1054 do_action( 'bp_notification_before_delete', $args ); 1055 1056 if ( ! $values ) { 1057 return $wpdb->query( "DELETE FROM {$bp->notifications->table_name} WHERE {$conditions}" ); 1058 } 1059 1060 return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->notifications->table_name} WHERE {$conditions}", $values ) ); 1061 } 1062 943 1063 /** Convenience methods ***************************************************/ 944 1064 945 1065 /** -
tests/phpunit/testcases/messages/notifications.php
diff --git tests/phpunit/testcases/messages/notifications.php tests/phpunit/testcases/messages/notifications.php index 8e348a830..4438d5ad1 100644
class BP_Tests_Messages_Notifications extends BP_UnitTestCase { 11 11 public function setUp() { 12 12 parent::setUp(); 13 13 14 $this->reset_user_id = get_current_user_id(); 15 14 16 $this->filter_fired = ''; 15 17 } 16 18 19 public function tearDown() { 20 parent::tearDown(); 21 22 $this->set_current_user( $this->reset_user_id ); 23 } 24 17 25 /** 18 26 * @group messages_format_notifications 19 27 */ … … class BP_Tests_Messages_Notifications extends BP_UnitTestCase { 40 48 41 49 /** 42 50 * @group messages_format_notifications 43 * @group imath44 51 */ 45 52 public function test_friends_format_notifications_bp_messages_single_new_message_notification_nonstring_filter() { 46 53 // Dummy thread ID … … class BP_Tests_Messages_Notifications extends BP_UnitTestCase { 145 152 $this->assertSame( array(), $n2 ); 146 153 } 147 154 155 /** 156 * @ticket BP8426 157 */ 158 public function test_bp_messages_mark_notification_on_mark_thread() { 159 $u1 = self::factory()->user->create(); 160 $u2 = self::factory()->user->create(); 161 $m1 = self::factory()->message->create_and_get( array( 162 'sender_id' => $u1, 163 'recipients' => array( $u2 ), 164 'subject' => 'Foo', 165 ) ); 166 167 self::factory()->message->create_many( 168 9, 169 array( 170 'thread_id' => $m1->thread_id, 171 'sender_id' => $u2, 172 'recipients' => array( $u1 ), 173 'subject' => 'Bar', 174 ) 175 ); 176 177 $unreadn = wp_list_pluck( 178 BP_Notifications_Notification::get( 179 array( 180 'user_id' => $u1, 181 'component_name' => buddypress()->messages->id, 182 'component_action' => 'new_message', 183 'is_new' => 1, 184 ) 185 ), 186 'user_id', 187 'id' 188 ); 189 190 $this->set_current_user( $u1 ); 191 192 // Mark a thread read. 193 bp_messages_mark_notification_on_mark_thread( $m1->thread_id, $u1, count( $unreadn ) ); 194 195 $readn = wp_list_pluck( 196 BP_Notifications_Notification::get( 197 array( 198 'user_id' => $u1, 199 'component_name' => buddypress()->messages->id, 200 'component_action' => 'new_message', 201 'is_new' => 0, 202 ) 203 ), 204 'user_id', 205 'id' 206 ); 207 208 $this->assertSame( $unreadn, $readn ); 209 } 210 211 /** 212 * @ticket BP8426 213 * @group message_delete_notifications 214 */ 215 public function test_bp_messages_message_delete_notifications() { 216 $u1 = self::factory()->user->create(); 217 $u2 = self::factory()->user->create(); 218 $m1 = self::factory()->message->create_and_get( array( 219 'sender_id' => $u1, 220 'recipients' => array( $u2 ), 221 'subject' => 'Foo', 222 ) ); 223 224 $message_ids = self::factory()->message->create_many( 225 9, 226 array( 227 'thread_id' => $m1->thread_id, 228 'sender_id' => $u2, 229 'recipients' => array( $u1 ), 230 'subject' => 'Bar', 231 ) 232 ); 233 234 $message_ids = wp_list_pluck( 235 BP_Notifications_Notification::get( 236 array( 237 'user_id' => $u1, 238 'component_name' => buddypress()->messages->id, 239 'component_action' => 'new_message', 240 'is_new' => 1, 241 ) 242 ), 243 'item_id' 244 ); 245 246 $test = bp_messages_message_delete_notifications( $m1->thread_id, $message_ids ); 247 248 $deleted = BP_Notifications_Notification::get( 249 array( 250 'user_id' => $u1, 251 'component_name' => buddypress()->messages->id, 252 'component_action' => 'new_message', 253 'is_new' => 1, 254 ) 255 ); 256 257 $this->assertEmpty( $deleted ); 258 } 259 148 260 public function notification_filter_callback( $value ) { 149 261 $this->filter_fired = current_filter(); 150 262 return $value; -
tests/phpunit/testcases/notifications/functions.php
diff --git tests/phpunit/testcases/notifications/functions.php tests/phpunit/testcases/notifications/functions.php index f47556048..864a71d99 100644
class BP_Tests_Notifications_Functions extends BP_UnitTestCase { 541 541 $found = bp_notifications_get_notifications_for_user( $u, 'object' ); 542 542 $this->assertEqualSets( [ $n1 ], wp_list_pluck( $found, 'id' ) ); 543 543 } 544 545 /** 546 * @ticket BP8426 547 */ 548 public function test_bp_notifications_mark_notifications_by_ids() { 549 $u = self::factory()->user->create(); 550 551 $n = self::factory()->notification->create( 552 array( 553 'component_name' => 'barfoo', 554 'component_action' => 'new_bar', 555 'item_id' => 98, 556 'user_id' => $u, 557 ) 558 ); 559 560 for ( $i = 101; $i < 111; ++$i ) { 561 self::factory()->notification->create( 562 array( 563 'component_name' => 'foobar', 564 'component_action' => 'new_foo', 565 'item_id' => $i, 566 'user_id' => $u, 567 ) 568 ); 569 } 570 571 $unread = wp_list_pluck( 572 BP_Notifications_Notification::get( 573 array( 574 'user_id' => $u, 575 'component_name' => 'foobar', 576 'component_action' => 'new_foo', 577 'is_new' => 1, 578 ) 579 ), 580 'id' 581 ); 582 583 bp_notifications_mark_notifications_by_ids( $unread ); 584 585 $read = wp_list_pluck( 586 BP_Notifications_Notification::get( 587 array( 588 'user_id' => $u, 589 'component_name' => 'foobar', 590 'component_action' => 'new_foo', 591 'is_new' => 0, 592 ) 593 ), 594 'id' 595 ); 596 597 $n_get = BP_Notifications_Notification::get( 598 array( 599 'id' => $n, 600 'component_name' => 'barfoo', 601 'component_action' => 'new_bar', 602 ) 603 ); 604 605 $n_obj = reset( $n_get ); 606 607 $this->assertEquals( $unread, $read ); 608 $this->assertEquals( $n, $n_obj->id ); 609 $this->assertTrue( 1 === (int) $n_obj->is_new ); 610 } 611 612 /** 613 * @ticket BP8426 614 * @group delete_notifications_by_ids 615 */ 616 public function test_bp_notifications_delete_notifications_by_ids() { 617 $u = self::factory()->user->create(); 618 619 $n = self::factory()->notification->create( 620 array( 621 'component_name' => 'barfoo', 622 'component_action' => 'new_bar', 623 'item_id' => 98, 624 'user_id' => $u, 625 ) 626 ); 627 628 for ( $i = 101; $i < 111; ++$i ) { 629 self::factory()->notification->create( 630 array( 631 'component_name' => 'foobar', 632 'component_action' => 'new_foo', 633 'item_id' => $i, 634 'user_id' => $u, 635 ) 636 ); 637 } 638 639 $unread = wp_list_pluck( 640 BP_Notifications_Notification::get( 641 array( 642 'user_id' => $u, 643 'component_name' => 'foobar', 644 'component_action' => 'new_foo', 645 'is_new' => 1, 646 ) 647 ), 648 'id' 649 ); 650 651 bp_notifications_delete_notifications_by_ids( $unread ); 652 653 $deleted = wp_list_pluck( 654 BP_Notifications_Notification::get( 655 array( 656 'user_id' => $u, 657 'component_name' => 'foobar', 658 'component_action' => 'new_foo', 659 'is_new' => 1, 660 ) 661 ), 662 'id' 663 ); 664 665 $n_get = BP_Notifications_Notification::get( 666 array( 667 'id' => $n, 668 'component_name' => 'barfoo', 669 'component_action' => 'new_bar', 670 ) 671 ); 672 673 $n_obj = reset( $n_get ); 674 675 $this->assertEmpty( $deleted ); 676 $this->assertEquals( $n, $n_obj->id ); 677 $this->assertTrue( 1 === (int) $n_obj->is_new ); 678 } 544 679 }