Skip to:
Content

BuddyPress.org

Ticket #8637: 8637.2.patch

File 8637.2.patch, 19.7 KB (added by imath, 3 years ago)
  • src/bp-notifications/bp-notifications-cache.php

    diff --git src/bp-notifications/bp-notifications-cache.php src/bp-notifications/bp-notifications-cache.php
    index f948daef3..38abcfdc3 100644
    function bp_notifications_clear_all_for_user_cache_before_update( $update_args, 
    101101        } elseif ( ! empty( $where_args['id'] ) ) {
    102102                $n = bp_notifications_get_notification( $where_args['id'] );
    103103                bp_notifications_clear_all_for_user_cache( $n->user_id );
     104
     105                // Get the list of user IDs from notification IDs.
     106        } elseif ( isset( $where_args['ids'] ) && $where_args['ids'] ) {
     107                $ids = (array) $where_args['ids'];
     108
     109                $ns = BP_Notifications_Notification::get(
     110                        array(
     111                                'id' => $ids,
     112                        )
     113                );
     114
     115                $user_ids = wp_list_pluck( $ns, 'user_id' );
     116                $user_ids = array_unique( $user_ids );
     117
     118                foreach ( $user_ids as $user_id ) {
     119                        bp_notifications_clear_all_for_user_cache( $user_id );
     120                }
    104121        }
    105122}
    106123add_action( 'bp_notification_before_update', 'bp_notifications_clear_all_for_user_cache_before_update', 10, 2 );
  • 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 9d5c1ebae..cb8998e2c 100644
    class BP_Notifications_Notification { 
    933933                $_items       = implode( ',', wp_parse_id_list( $items ) );
    934934                $conditions[] = "{$field} IN ({$_items})";
    935935
    936                 foreach ( $update_args['data'] as $field => $value ) {
    937                         $index  = array_search( $field, array_keys( $update_args['data'] ) );
     936                foreach ( $update_args['data'] as $update_field => $value ) {
     937                        $index  = array_search( $update_field, array_keys( $update_args['data'] ) );
    938938                        $format = $update_args['format'][ $index ];
    939939
    940                         $fields[] = "{$field} = {$format}";
     940                        $fields[] = "{$update_field} = {$format}";
    941941                        $values[] = $value;
    942942                }
    943943
    944                 foreach ( $where_args['data'] as $field => $value ) {
    945                         $index  = array_search( $field, array_keys( $where_args['data'] ) );
     944                foreach ( $where_args['data'] as $where_field => $value ) {
     945                        $index  = array_search( $where_field, array_keys( $where_args['data'] ) );
    946946                        $format = $where_args['format'][ $index ];
    947947
    948                         $conditions[] = "{$field} = {$format}";
     948                        $conditions[] = "{$where_field} = {$format}";
    949949                        $values[]     = $value;
    950950                }
    951951
    952952                $fields     = implode( ', ', $fields );
    953953                $conditions = implode( ' AND ', $conditions );
    954954
     955                if ( 'item_id' === $field ) {
     956                        $where_args['item_ids'] = $items;
     957                        $where_args['user_id']  = $where_args['data']['user_id'];
     958                } else {
     959                        $where_args['ids'] = $items;
     960                }
     961
    955962                /** This action is documented in bp-notifications/classes/class-bp-notifications-notification.php */
    956963                do_action( 'bp_notification_before_update', $update_args, $where_args );
    957964
    class BP_Notifications_Notification { 
    10211028                $_items       = implode( ',', wp_parse_id_list( $items ) );
    10221029                $conditions[] = "{$field} IN ({$_items})";
    10231030
    1024                 foreach ( $where['data'] as $field => $value ) {
    1025                         $index  = array_search( $field, array_keys( $where['data'] ) );
     1031                foreach ( $where['data'] as $where_field => $value ) {
     1032                        $index  = array_search( $where_field, array_keys( $where['data'] ) );
    10261033                        $format = $where['format'][ $index ];
    10271034
    1028                         $conditions[] = "{$field} = {$format}";
     1035                        $conditions[] = "{$where_field} = {$format}";
    10291036                        $values[]     = $value;
    10301037                }
    10311038
    10321039                $conditions = implode( ' AND ', $conditions );
    10331040
     1041                if ( 'id' === $field ) {
     1042                        $args['id'] = $items;
     1043                }
     1044
    10341045                /** This action is documented in bp-notifications/classes/class-bp-notifications-notification.php */
    10351046                do_action( 'bp_notification_before_delete', $args );
    10361047
  • new file tests/phpunit/testcases/notifications/cache.php

    diff --git tests/phpunit/testcases/notifications/cache.php tests/phpunit/testcases/notifications/cache.php
    new file mode 100644
    index 000000000..4c99dff0a
    - +  
     1<?php
     2
     3/**
     4 * @group notifications
     5 * @group cache
     6 */
     7class BP_Tests_Notifications_Cache extends BP_UnitTestCase {
     8
     9        /**
     10         * @group cache
     11         */
     12        public function test_cache_invalidation_all_for_user_on_save() {
     13                $u = self::factory()->user->create();
     14
     15                self::factory()->notification->create( array(
     16                        'component_name' => 'groups',
     17                        'user_id'        => $u
     18                ) );
     19                self::factory()->notification->create( array(
     20                        'component_name' => 'messages',
     21                        'user_id'        => $u,
     22                        'item_id'        => 1
     23                ) );
     24
     25                // prime cache
     26                $count = bp_notifications_get_unread_notification_count( $u );
     27
     28                // just to be sure...
     29                $this->assertEquals( 2, $count, 'Cache count should be 2 before invalidation.' );
     30
     31                // Trigger invalidation via save
     32                self::factory()->notification->create( array(
     33                        'component_name' => 'messages',
     34                        'user_id'        => $u,
     35                        'item_id'        => 2
     36                ) );
     37
     38                $this->assertFalse( wp_cache_get( 'all_for_user_' . $u, 'bp_notifications' ) );
     39                $this->assertFalse( wp_cache_get( $u, 'bp_notifications_unread_count' ) );
     40        }
     41
     42        /**
     43         * @group cache
     44         */
     45        public function test_cache_invalidation_all_for_user_on_delete() {
     46                $u  = self::factory()->user->create();
     47                $n1 = self::factory()->notification->create( array(
     48                        'component_name' => 'groups',
     49                        'user_id'        => $u
     50                ) );
     51                self::factory()->notification->create( array(
     52                        'component_name' => 'messages',
     53                        'user_id'        => $u
     54                ) );
     55
     56                // prime cache
     57                $count = bp_notifications_get_unread_notification_count( $u );
     58
     59                // just to be sure...
     60                $this->assertEquals( 2, $count, 'Cache count should be 2 before invalidation.' );
     61
     62                // delete
     63                BP_Notifications_Notification::delete( array( 'id' => $n1, ) );
     64
     65                $this->assertFalse( wp_cache_get( 'all_for_user_' . $u, 'bp_notifications' ) );
     66                $this->assertFalse( wp_cache_get( $u, 'bp_notifications_unread_count' ) );
     67        }
     68
     69        /**
     70         * @group cache
     71         */
     72        public function test_cache_invalidation_all_for_user_on_update_user_id() {
     73                $u = self::factory()->user->create();
     74
     75                self::factory()->notification->create( array(
     76                        'component_name' => 'groups',
     77                        'user_id'        => $u
     78                ) );
     79                self::factory()->notification->create( array(
     80                        'component_name' => 'messages',
     81                        'user_id'        => $u
     82                ) );
     83
     84                // prime cache
     85                $count = bp_notifications_get_unread_notification_count( $u );
     86
     87                // just to be sure...
     88                $this->assertEquals( 2, $count, 'Cache count should be 2 before invalidation.' );
     89
     90                // mark all notifications by user as read
     91                BP_Notifications_Notification::update(
     92                        array( 'is_new'  => false ),
     93                        array( 'user_id' => $u    )
     94                );
     95
     96                $this->assertFalse( wp_cache_get( 'all_for_user_' . $u, 'bp_notifications' ) );
     97                $this->assertFalse( wp_cache_get( $u, 'bp_notifications_unread_count' ) );
     98        }
     99
     100        /**
     101         * @group cache
     102         */
     103        public function test_cache_invalidation_all_for_user_on_update_id() {
     104                $u  = self::factory()->user->create();
     105                $n1 = self::factory()->notification->create( array(
     106                        'component_name' => 'groups',
     107                        'user_id'        => $u
     108                ) );
     109
     110                self::factory()->notification->create( array(
     111                        'component_name' => 'messages',
     112                        'user_id'        => $u
     113                ) );
     114
     115                // prime cache
     116                $count = bp_notifications_get_unread_notification_count( $u );
     117
     118                // just to be sure...
     119                $this->assertEquals( 2, $count, 'Cache count should be 2 before invalidation.' );
     120
     121                // mark one notification as read
     122                BP_Notifications_Notification::update(
     123                        array( 'is_new' => false ),
     124                        array( 'id'     => $n1   )
     125                );
     126
     127                $this->assertFalse( wp_cache_get( 'all_for_user_' . $u, 'bp_notifications' ) );
     128                $this->assertFalse( wp_cache_get( $u, 'bp_notifications_unread_count' ) );
     129        }
     130
     131        /**
     132         * @group bp_notifications_update_meta_cache
     133         */
     134        public function test_bp_notifications_update_meta_cache() {
     135                $u = self::factory()->user->create();
     136
     137                $n1 = self::factory()->notification->create( array(
     138                        'component_name' => 'messages',
     139                        'user_id'        => $u
     140                ) );
     141
     142                $n2 = self::factory()->notification->create( array(
     143                        'component_name' => 'groups',
     144                        'user_id'        => $u
     145                ) );
     146
     147                // Add cache for each notification.
     148                bp_notifications_update_meta( $n1, 'meta', 'data' );
     149                bp_notifications_update_meta( $n1, 'data', 'meta' );
     150                bp_notifications_update_meta( $n2, 'meta', 'human' );
     151
     152                // Prime cache.
     153                bp_notifications_get_meta( $n1, 'meta' );
     154
     155                // Ensure an empty cache for second notification.
     156                wp_cache_delete( $n2, 'notification_meta' );
     157
     158                // Update notification meta cache.
     159                bp_notifications_update_meta_cache( array( $n1, $n2 ) );
     160
     161                $expected = array(
     162                        $n1 => array(
     163                                'meta' => array(
     164                                        'data',
     165                                ),
     166                                'data' => array(
     167                                        'meta',
     168                                ),
     169                        ),
     170                        $n2 => array(
     171                                'meta' => array(
     172                                        'human',
     173                                ),
     174                        ),
     175                );
     176
     177                $found = array(
     178                        $n1 => wp_cache_get( $n1, 'notification_meta' ),
     179                        $n2 => wp_cache_get( $n2, 'notification_meta' ),
     180                );
     181
     182                $this->assertEquals( $expected, $found );
     183        }
     184
     185        /**
     186         * @group cache
     187         * @ticket BP8637
     188         */
     189        public function test_bp_notifications_clear_all_for_user_cache_before_update() {
     190                $u = self::factory()->user->create();
     191                $a = self::factory()->activity->create();
     192
     193                $notification_ids = self::factory()->notification->create_many(
     194                        4,
     195                        array(
     196                                'component_name'    => 'activity',
     197                                'component_action'  => 'at_mentions',
     198                                'user_id'           => $u,
     199                                'item_id'           => $a,
     200                                'allow_duplicate'   => true,
     201                        )
     202                );
     203
     204                $all_for_user_notifications = bp_notifications_get_all_notifications_for_user( $u );
     205                $this->assertEquals( $notification_ids, wp_list_pluck( $all_for_user_notifications, 'id' ) );
     206
     207                // Mark as read.
     208                $amount = bp_notifications_mark_notifications_by_ids( $notification_ids );
     209                $this->assertTrue( $amount === count( $notification_ids ) );
     210
     211                // Add a new one.
     212                $notification_id = self::factory()->notification->create(
     213                        array(
     214                                'component_name'    => 'activity',
     215                                'component_action'  => 'at_mentions',
     216                                'user_id'           => $u,
     217                                'item_id'           => $a,
     218                                'allow_duplicate'   => true,
     219                        )
     220                );
     221
     222                $all_for_user_notifications = bp_notifications_get_all_notifications_for_user( $u );
     223                $all_ids = wp_list_pluck( $all_for_user_notifications, 'id' );
     224
     225                $this->assertEmpty( array_intersect( $notification_ids, $all_ids ) );
     226                $this->assertContains( $notification_id, $all_ids );
     227        }
     228
     229        /**
     230         * @group cache
     231         * @ticket BP8637
     232         */
     233        public function test_bp_notifications_clear_all_for_user_cache_before_delete() {
     234                $u = self::factory()->user->create();
     235                $a = self::factory()->activity->create();
     236
     237                $notification_ids = self::factory()->notification->create_many(
     238                        4,
     239                        array(
     240                                'component_name'    => 'activity',
     241                                'component_action'  => 'at_mentions',
     242                                'user_id'           => $u,
     243                                'item_id'           => $a,
     244                                'allow_duplicate'   => true,
     245                        )
     246                );
     247
     248                $all_for_user_notifications = bp_notifications_get_all_notifications_for_user( $u );
     249                $this->assertEquals( $notification_ids, wp_list_pluck( $all_for_user_notifications, 'id' ) );
     250
     251                $u2 = self::factory()->user->create();
     252                $a2 = self::factory()->activity->create();
     253
     254                // Check this one is not deleted.
     255                $notification_id = self::factory()->notification->create(
     256                        array(
     257                                'component_name'    => 'activity',
     258                                'component_action'  => 'at_mentions',
     259                                'user_id'           => $u2,
     260                                'item_id'           => $a2,
     261                                'allow_duplicate'   => true,
     262                        )
     263                );
     264
     265                // Delete.
     266                $amount = bp_notifications_delete_notifications_by_ids( $notification_ids );
     267                $this->assertTrue( $amount === count( $notification_ids ) );
     268
     269                $all_for_user_notifications = bp_notifications_get_all_notifications_for_user( $u );
     270                $all_ids = wp_list_pluck( $all_for_user_notifications, 'id' );
     271
     272                $this->assertEmpty( array_intersect( $notification_ids, $all_ids ) );
     273
     274                $all_for_user_notifications = bp_notifications_get_all_notifications_for_user( $u2 );
     275                $this->assertSame( $all_for_user_notifications[0]->id, $notification_id );
     276        }
     277
     278        /**
     279         * @group cache
     280         * @ticket BP8637
     281         */
     282        public function test_bp_notifications_clear_all_for_user_cache_before_update_when_item_ids() {
     283                $s = self::factory()->user->create();
     284                $r = self::factory()->user->create();
     285
     286                $message_ids = self::factory()->message->create_many(
     287                        4,
     288                        array(
     289                                'sender_id'  => $s,
     290                                'recipients' => array( $r ),
     291                                'content'    => 'testing notification all for user cache',
     292                        )
     293                );
     294
     295                $all_for_user_notifications = bp_notifications_get_all_notifications_for_user( $r );
     296                $this->assertEquals( $message_ids, wp_list_pluck( $all_for_user_notifications, 'item_id' ) );
     297
     298                // Mark read.
     299                $amount = bp_notifications_mark_notifications_by_item_ids( $r, $message_ids, 'messages', 'new_message', false );
     300                $this->assertTrue( $amount === count( $message_ids ) );
     301
     302                $message_id = self::factory()->message->create(
     303                        array(
     304                                'sender_id'  => $s,
     305                                'recipients' => array( $r ),
     306                                'content'    => 'testing notification all for user cache',
     307                        )
     308                );
     309
     310                $all_for_user_notifications = bp_notifications_get_all_notifications_for_user( $r );
     311                $all_ids = wp_list_pluck( $all_for_user_notifications, 'item_id' );
     312
     313                $this->assertEmpty( array_intersect( $message_ids, $all_ids ) );
     314                $this->assertContains( $message_id, $all_ids );
     315        }
     316
     317        /**
     318         * @group cache
     319         * @ticket BP8637
     320         */
     321        public function test_bp_notifications_clear_all_for_user_cache_before_delete_when_item_ids() {
     322                $s = self::factory()->user->create();
     323                $r = self::factory()->user->create();
     324
     325                $message_ids = self::factory()->message->create_many(
     326                        4,
     327                        array(
     328                                'sender_id'  => $s,
     329                                'recipients' => array( $r ),
     330                                'content'    => 'testing notification all for user cache',
     331                        )
     332                );
     333
     334                $all_for_user_notifications = bp_notifications_get_all_notifications_for_user( $r );
     335                $this->assertEquals( $message_ids, wp_list_pluck( $all_for_user_notifications, 'item_id' ) );
     336
     337                $message_id = self::factory()->message->create(
     338                        array(
     339                                'sender_id'  => $r,
     340                                'recipients' => array( $s ),
     341                                'content'    => 'testing notification all for user cache',
     342                        )
     343                );
     344
     345                // Delete.
     346                $amount = bp_notifications_delete_notifications_by_item_ids( $r, $message_ids, 'messages', 'new_message' );
     347                $this->assertTrue( $amount === count( $message_ids ) );
     348
     349                $all_for_user_notifications = bp_notifications_get_all_notifications_for_user( $r );
     350                $all_ids = wp_list_pluck( $all_for_user_notifications, 'item_id' );
     351
     352                $this->assertEmpty( array_intersect( $message_ids, $all_ids ) );
     353
     354                $all_for_user_notifications = bp_notifications_get_all_notifications_for_user( $s );
     355                $this->assertSame( $all_for_user_notifications[0]->item_id, $message_id );
     356        }
     357}
  • tests/phpunit/testcases/notifications/functions.php

    diff --git tests/phpunit/testcases/notifications/functions.php tests/phpunit/testcases/notifications/functions.php
    index 864a71d99..90c73d869 100644
     
    55 */
    66class BP_Tests_Notifications_Functions extends BP_UnitTestCase {
    77
    8         /**
    9          * @group cache
    10          */
    11         public function test_cache_invalidation_all_for_user_on_save() {
    12                 $u = self::factory()->user->create();
    13 
    14                 self::factory()->notification->create( array(
    15                         'component_name' => 'groups',
    16                         'user_id'        => $u
    17                 ) );
    18                 self::factory()->notification->create( array(
    19                         'component_name' => 'messages',
    20                         'user_id'        => $u,
    21                         'item_id'        => 1
    22                 ) );
    23 
    24                 // prime cache
    25                 $count = bp_notifications_get_unread_notification_count( $u );
    26 
    27                 // just to be sure...
    28                 $this->assertEquals( 2, $count, 'Cache count should be 2 before invalidation.' );
    29 
    30                 // Trigger invalidation via save
    31                 self::factory()->notification->create( array(
    32                         'component_name' => 'messages',
    33                         'user_id'        => $u,
    34                         'item_id'        => 2
    35                 ) );
    36 
    37                 $this->assertFalse( wp_cache_get( 'all_for_user_' . $u, 'bp_notifications' ) );
    38                 $this->assertFalse( wp_cache_get( $u, 'bp_notifications_unread_count' ) );
    39         }
    40 
    41         /**
    42          * @group cache
    43          */
    44         public function test_cache_invalidation_all_for_user_on_delete() {
    45                 $u  = self::factory()->user->create();
    46                 $n1 = self::factory()->notification->create( array(
    47                         'component_name' => 'groups',
    48                         'user_id'        => $u
    49                 ) );
    50                 self::factory()->notification->create( array(
    51                         'component_name' => 'messages',
    52                         'user_id'        => $u
    53                 ) );
    54 
    55                 // prime cache
    56                 $count = bp_notifications_get_unread_notification_count( $u );
    57 
    58                 // just to be sure...
    59                 $this->assertEquals( 2, $count, 'Cache count should be 2 before invalidation.' );
    60 
    61                 // delete
    62                 BP_Notifications_Notification::delete( array( 'id' => $n1, ) );
    63 
    64                 $this->assertFalse( wp_cache_get( 'all_for_user_' . $u, 'bp_notifications' ) );
    65                 $this->assertFalse( wp_cache_get( $u, 'bp_notifications_unread_count' ) );
    66         }
    67 
    68         /**
    69          * @group cache
    70          */
    71         public function test_cache_invalidation_all_for_user_on_update_user_id() {
    72                 $u = self::factory()->user->create();
    73 
    74                 self::factory()->notification->create( array(
    75                         'component_name' => 'groups',
    76                         'user_id'        => $u
    77                 ) );
    78                 self::factory()->notification->create( array(
    79                         'component_name' => 'messages',
    80                         'user_id'        => $u
    81                 ) );
    82 
    83                 // prime cache
    84                 $count = bp_notifications_get_unread_notification_count( $u );
    85 
    86                 // just to be sure...
    87                 $this->assertEquals( 2, $count, 'Cache count should be 2 before invalidation.' );
    88 
    89                 // mark all notifications by user as read
    90                 BP_Notifications_Notification::update(
    91                         array( 'is_new'  => false ),
    92                         array( 'user_id' => $u    )
    93                 );
    94 
    95                 $this->assertFalse( wp_cache_get( 'all_for_user_' . $u, 'bp_notifications' ) );
    96                 $this->assertFalse( wp_cache_get( $u, 'bp_notifications_unread_count' ) );
    97         }
    98 
    99         /**
    100          * @group cache
    101          */
    102         public function test_cache_invalidation_all_for_user_on_update_id() {
    103                 $u  = self::factory()->user->create();
    104                 $n1 = self::factory()->notification->create( array(
    105                         'component_name' => 'groups',
    106                         'user_id'        => $u
    107                 ) );
    108 
    109                 self::factory()->notification->create( array(
    110                         'component_name' => 'messages',
    111                         'user_id'        => $u
    112                 ) );
    113 
    114                 // prime cache
    115                 $count = bp_notifications_get_unread_notification_count( $u );
    116 
    117                 // just to be sure...
    118                 $this->assertEquals( 2, $count, 'Cache count should be 2 before invalidation.' );
    119 
    120                 // mark one notification as read
    121                 BP_Notifications_Notification::update(
    122                         array( 'is_new' => false ),
    123                         array( 'id'     => $n1   )
    124                 );
    125 
    126                 $this->assertFalse( wp_cache_get( 'all_for_user_' . $u, 'bp_notifications' ) );
    127                 $this->assertFalse( wp_cache_get( $u, 'bp_notifications_unread_count' ) );
    128         }
    129 
    130         /**
    131          * @group bp_notifications_update_meta_cache
    132          */
    133         public function test_bp_notifications_update_meta_cache() {
    134                 $u = self::factory()->user->create();
    135 
    136                 $n1 = self::factory()->notification->create( array(
    137                         'component_name' => 'messages',
    138                         'user_id'        => $u
    139                 ) );
    140 
    141                 $n2 = self::factory()->notification->create( array(
    142                         'component_name' => 'groups',
    143                         'user_id'        => $u
    144                 ) );
    145 
    146                 // Add cache for each notification.
    147                 bp_notifications_update_meta( $n1, 'meta', 'data' );
    148                 bp_notifications_update_meta( $n1, 'data', 'meta' );
    149                 bp_notifications_update_meta( $n2, 'meta', 'human' );
    150 
    151                 // Prime cache.
    152                 bp_notifications_get_meta( $n1, 'meta' );
    153 
    154                 // Ensure an empty cache for second notification.
    155                 wp_cache_delete( $n2, 'notification_meta' );
    156 
    157                 // Update notification meta cache.
    158                 bp_notifications_update_meta_cache( array( $n1, $n2 ) );
    159 
    160                 $expected = array(
    161                         $n1 => array(
    162                                 'meta' => array(
    163                                         'data',
    164                                 ),
    165                                 'data' => array(
    166                                         'meta',
    167                                 ),
    168                         ),
    169                         $n2 => array(
    170                                 'meta' => array(
    171                                         'human',
    172                                 ),
    173                         ),
    174                 );
    175 
    176                 $found = array(
    177                         $n1 => wp_cache_get( $n1, 'notification_meta' ),
    178                         $n2 => wp_cache_get( $n2, 'notification_meta' ),
    179                 );
    180 
    181                 $this->assertEquals( $expected, $found );
    182         }
    183 
    1848        /**
    1859         * @group bp_notifications_add_notification
    18610         */