Skip to:
Content

BuddyPress.org

Ticket #7130: 7130.diff

File 7130.diff, 17.0 KB (added by m_uysl, 2 years ago)
  • src/bp-notifications/bp-notifications-cache.php

     
    3838 * Clear all notifications cache for a given user ID.
    3939 *
    4040 * @since 2.3.0
     41 * @since 2.9.0  cleans unread_notification cache and grouped_notifications
    4142 *
    4243 * @param int $user_id The user ID's cache to clear.
    4344 */
    4445function bp_notifications_clear_all_for_user_cache( $user_id = 0 ) {
    4546        wp_cache_delete( 'all_for_user_' . $user_id, 'bp_notifications' );
     47        wp_cache_delete( 'grouped_notifications_for_user_' . $user_id, 'bp_notifications' );
     48        wp_cache_delete( 'unread_notification_count_for_user_' . $user_id, 'bp_notifications' );
    4649}
    4750
    4851/**
  • src/bp-notifications/bp-notifications-functions.php

     
    163163}
    164164
    165165/**
     166 * Get latest notifications based on component_action
     167 *
     168 * @since 2.9.0
     169 *
     170 * @param int $user_id
     171 *
     172 * @return array $notifications
     173 */
     174function bp_notifications_get_grouped_notifications_for_user( $user_id = 0 ) {
     175
     176        if ( empty( $user_id ) ) {
     177                $user_id = ( bp_displayed_user_id() ) ? bp_displayed_user_id() : bp_loggedin_user_id();
     178        }
     179
     180        $notifications = wp_cache_get( 'grouped_notifications_for_user_' . $user_id, 'bp_notifications' );
     181        if ( false === $notifications ) {
     182                $notifications = BP_Notifications_Notification::get_grouped_notifications_for_user( $user_id );
     183                wp_cache_set( 'grouped_notifications_for_user_' . $user_id, $notifications, 'bp_notifications' );
     184        }
     185
     186        return $notifications;
     187}
     188
     189/**
    166190 * Get notifications for a specific user.
    167191 *
    168192 * @since 1.9.0
     
    173197 * @return mixed Object or array on success, false on failure.
    174198 */
    175199function bp_notifications_get_notifications_for_user( $user_id, $format = 'string' ) {
    176 
    177         // Setup local variables.
    178200        $bp = buddypress();
    179201
    180         // Get notifications (out of the cache, or query if necessary).
    181         $notifications         = bp_notifications_get_all_notifications_for_user( $user_id );
    182         $grouped_notifications = array(); // Notification groups.
    183         $renderable            = array(); // Renderable notifications.
     202        $notifications = bp_notifications_get_grouped_notifications_for_user( $user_id );
    184203
    185         // Group notifications by component and component_action and provide totals.
    186         for ( $i = 0, $count = count( $notifications ); $i < $count; ++$i ) {
    187                 $notification = $notifications[$i];
    188                 $grouped_notifications[$notification->component_name][$notification->component_action][] = $notification;
    189         }
    190 
    191         // Bail if no notification groups.
    192         if ( empty( $grouped_notifications ) ) {
    193                 return false;
    194         }
    195 
    196204        // Calculate a renderable output for each notification type.
    197         foreach ( $grouped_notifications as $component_name => $action_arrays ) {
     205        foreach ( $notifications as $notification_item ) {
    198206
     207                $component_name = $notification_item->component_name;
    199208                // We prefer that extended profile component-related notifications use
    200209                // the component_name of 'xprofile'. However, the extended profile child
    201210                // object in the $bp object is keyed as 'profile', which is where we need
    202211                // to look for the registered notification callback.
    203                 if ( 'xprofile' == $component_name ) {
     212                if ( 'xprofile' == $notification_item->component_name ) {
    204213                        $component_name = 'profile';
    205214                }
    206215
    207                 // Skip if group is empty.
    208                 if ( empty( $action_arrays ) ) {
    209                         continue;
    210                 }
     216                // Callback function exists.
     217                if ( isset( $bp->{$component_name}->notification_callback ) && is_callable( $bp->{$component_name}->notification_callback ) ) {
    211218
    212                 // Loop through each actionable item and try to map it to a component.
    213                 foreach ( (array) $action_arrays as $component_action_name => $component_action_items ) {
     219                        // Function should return an object.
     220                        if ( 'object' === $format ) {
    214221
    215                         // Get the number of actionable items.
    216                         $action_item_count = count( $component_action_items );
     222                                // Retrieve the content of the notification using the callback.
     223                                $content = call_user_func( $bp->{$component_name}->notification_callback, $notification_item->component_action, $notification_item->item_id, $notification_item->secondary_item_id, $notification_item->total_count, 'array', $notification_item->id );
    217224
    218                         // Skip if the count is less than 1.
    219                         if ( $action_item_count < 1 ) {
    220                                 continue;
    221                         }
     225                                // Create the object to be returned.
     226                                $notification_object = $notification_item;
    222227
    223                         // Callback function exists.
    224                         if ( isset( $bp->{$component_name}->notification_callback ) && is_callable( $bp->{$component_name}->notification_callback ) ) {
     228                                // Minimal backpat with non-compatible notification
     229                                // callback functions.
     230                                if ( is_string( $content ) ) {
     231                                        $notification_object->content = $content;
     232                                        $notification_object->href    = bp_loggedin_user_domain();
     233                                } else {
     234                                        $notification_object->content = $content['text'];
     235                                        $notification_object->href    = $content['link'];
     236                                }
    225237
    226                                 // Function should return an object.
    227                                 if ( 'object' === $format ) {
     238                                $renderable[] = $notification_object;
    228239
    229                                         // Retrieve the content of the notification using the callback.
    230                                         $content = call_user_func(
    231                                                 $bp->{$component_name}->notification_callback,
    232                                                 $component_action_name,
    233                                                 $component_action_items[0]->item_id,
    234                                                 $component_action_items[0]->secondary_item_id,
    235                                                 $action_item_count,
    236                                                 'array',
    237                                                 $component_action_items[0]->id
    238                                         );
    239 
    240                                         // Create the object to be returned.
    241                                         $notification_object = $component_action_items[0];
    242 
    243                                         // Minimal backpat with non-compatible notification
    244                                         // callback functions.
    245                                         if ( is_string( $content ) ) {
    246                                                 $notification_object->content = $content;
    247                                                 $notification_object->href    = bp_loggedin_user_domain();
    248                                         } else {
    249                                                 $notification_object->content = $content['text'];
    250                                                 $notification_object->href    = $content['link'];
    251                                         }
    252 
    253                                         $renderable[] = $notification_object;
    254 
    255240                                // Return an array of content strings.
    256                                 } else {
    257                                         $content      = call_user_func( $bp->{$component_name}->notification_callback, $component_action_name, $component_action_items[0]->item_id, $component_action_items[0]->secondary_item_id, $action_item_count, 'string', $component_action_items[0]->id );
    258                                         $renderable[] = $content;
    259                                 }
     241                        } else {
     242                                $content      = call_user_func( $bp->{$component_name}->notification_callback, $notification_item->component_action, $notification_item->item_id, $notification_item->secondary_item_id, $notification_item->total_count, 'string', $notification_item->id );
     243                                $renderable[] = $content;
     244                        }
    260245
    261246                        // @deprecated format_notification_function - 1.5
    262                         } elseif ( isset( $bp->{$component_name}->format_notification_function ) && function_exists( $bp->{$component_name}->format_notification_function ) ) {
    263                                 $renderable[] = call_user_func( $bp->{$component_name}->format_notification_function, $component_action_name, $component_action_items[0]->item_id, $component_action_items[0]->secondary_item_id, $action_item_count );
     247                } elseif ( isset( $bp->{$component_name}->format_notification_function ) && function_exists( $bp->{$component_name}->format_notification_function ) ) {
     248                        $renderable[] = call_user_func( $bp->{$component_name}->notification_callback, $notification_item->component_action, $notification_item->item_id, $notification_item->secondary_item_id, $notification_item->total_count );
    264249
    265250                        // Allow non BuddyPress components to hook in.
    266                         } else {
     251                } else {
    267252
    268                                 // The array to reference with apply_filters_ref_array().
    269                                 $ref_array = array(
    270                                         $component_action_name,
    271                                         $component_action_items[0]->item_id,
    272                                         $component_action_items[0]->secondary_item_id,
    273                                         $action_item_count,
    274                                         $format,
    275                                         $component_action_name, // Duplicated so plugins can check the canonical action name.
    276                                         $component_name,
    277                                         $component_action_items[0]->id
    278                                 );
     253                        // The array to reference with apply_filters_ref_array().
     254                        $ref_array = array(
     255                                $notification_item->component_action,
     256                                $notification_item->item_id,
     257                                $notification_item->secondary_item_id,
     258                                $notification_item->total_count,
     259                                $format,
     260                                $notification_item->component_action, // Duplicated so plugins can check the canonical action name.
     261                                $component_name,
     262                                $notification_item->id,
     263                        );
    279264
    280                                 // Function should return an object.
    281                                 if ( 'object' === $format ) {
     265                        // Function should return an object.
     266                        if ( 'object' === $format ) {
    282267
    283                                         /**
    284                                          * Filters the notification content for notifications created by plugins.
    285                                          *
    286                                          * If your plugin extends the {@link BP_Component} class, you should use the
    287                                          * 'notification_callback' parameter in your extended
    288                                          * {@link BP_Component::setup_globals()} method instead.
    289                                          *
    290                                          * @since 1.9.0
    291                                          * @since 2.6.0 Added $component_action_name, $component_name, $id as parameters.
    292                                          *
    293                                          * @param string $content               Component action. Deprecated. Do not do checks against this! Use
    294                                          *                                      the 6th parameter instead - $component_action_name.
    295                                          * @param int    $item_id               Notification item ID.
    296                                          * @param int    $secondary_item_id     Notification secondary item ID.
    297                                          * @param int    $action_item_count     Number of notifications with the same action.
    298                                          * @param string $format                Format of return. Either 'string' or 'object'.
    299                                          * @param string $component_action_name Canonical notification action.
    300                                          * @param string $component_name        Notification component ID.
    301                                          * @param int    $id                    Notification ID.
    302                                          *
    303                                          * @return string|array If $format is 'string', return a string of the notification content.
    304                                          *                      If $format is 'object', return an array formatted like:
    305                                          *                      array( 'text' => 'CONTENT', 'link' => 'LINK' )
    306                                          */
    307                                         $content = apply_filters_ref_array( 'bp_notifications_get_notifications_for_user', $ref_array );
     268                                /**
     269                                 * Filters the notification content for notifications created by plugins.
     270                                 * If your plugin extends the {@link BP_Component} class, you should use the
     271                                 * 'notification_callback' parameter in your extended
     272                                 * {@link BP_Component::setup_globals()} method instead.
     273                                 *
     274                                 * @since 1.9.0
     275                                 * @since 2.6.0 Added $component_action_name, $component_name, $id as parameters.
     276                                 *
     277                                 * @param string $content               Component action. Deprecated. Do not do checks against this! Use
     278                                 *                                      the 6th parameter instead - $component_action_name.
     279                                 * @param int    $item_id               Notification item ID.
     280                                 * @param int    $secondary_item_id     Notification secondary item ID.
     281                                 * @param int    $action_item_count     Number of notifications with the same action.
     282                                 * @param string $format                Format of return. Either 'string' or 'object'.
     283                                 * @param string $component_action_name Canonical notification action.
     284                                 * @param string $component_name        Notification component ID.
     285                                 * @param int    $id                    Notification ID.
     286                                 *
     287                                 * @return string|array If $format is 'string', return a string of the notification content.
     288                                 *                      If $format is 'object', return an array formatted like:
     289                                 *                      array( 'text' => 'CONTENT', 'link' => 'LINK' )
     290                                 */
     291                                $content = apply_filters_ref_array( 'bp_notifications_get_notifications_for_user', $ref_array );
    308292
    309                                         // Create the object to be returned.
    310                                         $notification_object = $component_action_items[0];
     293                                // Create the object to be returned.
     294                                $notification_object = $notification_item;
    311295
    312                                         // Minimal backpat with non-compatible notification
    313                                         // callback functions.
    314                                         if ( is_string( $content ) ) {
    315                                                 $notification_object->content = $content;
    316                                                 $notification_object->href    = bp_loggedin_user_domain();
    317                                         } else {
    318                                                 $notification_object->content = $content['text'];
    319                                                 $notification_object->href    = $content['link'];
    320                                         }
     296                                // Minimal backpat with non-compatible notification
     297                                // callback functions.
     298                                if ( is_string( $content ) ) {
     299                                        $notification_object->content = $content;
     300                                        $notification_object->href    = bp_loggedin_user_domain();
     301                                } else {
     302                                        $notification_object->content = $content['text'];
     303                                        $notification_object->href    = $content['link'];
     304                                }
    321305
    322                                         $renderable[] = $notification_object;
     306                                $renderable[] = $notification_object;
    323307
    324308                                // Return an array of content strings.
    325                                 } else {
     309                        } else {
    326310
    327                                         /** This filters is documented in bp-notifications/bp-notifications-functions.php */
    328                                         $renderable[] = apply_filters_ref_array( 'bp_notifications_get_notifications_for_user', $ref_array );
    329                                 }
     311                                /** This filters is documented in bp-notifications/bp-notifications-functions.php */
     312                                $renderable[] = apply_filters_ref_array( 'bp_notifications_get_notifications_for_user', $ref_array );
    330313                        }
    331314                }
    332315        }
     
    607590 * @return int Unread notification count.
    608591 */
    609592function bp_notifications_get_unread_notification_count( $user_id = 0 ) {
    610         $notifications = bp_notifications_get_all_notifications_for_user( $user_id );
    611         $count         = ! empty( $notifications ) ? count( $notifications ) : 0;
     593        if ( empty( $user_id ) ) {
     594                $user_id = ( bp_displayed_user_id() ) ? bp_displayed_user_id() : bp_loggedin_user_id();
     595        }
    612596
     597        $count = wp_cache_get( 'unread_notification_count_for_user_' . $user_id, 'bp_notifications' );
     598
     599        if ( false === $count ) {
     600                $count = BP_Notifications_Notification::get_total_count( array(
     601                        'user_id' => $user_id,
     602                        'is_new'  => 1,
     603                ) );
     604                wp_cache_set( 'unread_notification_count_for_user_' . $user_id, 'bp_notifications' );
     605        }
     606
    613607        /**
    614608         * Filters the count of unread notification items for a user.
    615609         *
  • src/bp-notifications/classes/class-bp-notifications-notification.php

     
    11311131
    11321132                return self::update( $update_args, $where_args );
    11331133        }
     1134
     1135        /**
     1136         * Get latest unread notifications and total count based on component_action
     1137         *
     1138         * @since 2.9.0
     1139         *
     1140         * @return array list of latest unread notifications
     1141         */
     1142        public static function get_grouped_notifications_for_user( $user_id ) {
     1143                global $wpdb;
     1144
     1145                // Load BuddyPress.
     1146                $bp = buddypress();
     1147
     1148                // SELECT.
     1149                $select_sql = "SELECT id,user_id,item_id, secondary_item_id,component_name,component_action,date_notified,is_new,COUNT(id) as total_count ";
     1150
     1151                // FROM.
     1152                $from_sql = "FROM {$bp->notifications->table_name} n ";
     1153
     1154                // WHERE.
     1155                $where_sql = self::get_where_sql( array(
     1156                        'user_id'        => $user_id,
     1157                        'is_new'         => 1,
     1158                        'component_name' => bp_notifications_get_registered_components(),
     1159                ), $select_sql, $from_sql );
     1160
     1161                // GROUP
     1162                $group_sql = "GROUP BY user_id,component_name,component_action";
     1163
     1164                // SORT
     1165                $order_sql = "ORDER BY date_notified desc";
     1166
     1167                // Concatenate query parts.
     1168                $sql = "{$select_sql} {$from_sql} {$where_sql} {$group_sql} {$order_sql}";
     1169
     1170                // Return the queried results.
     1171                return $wpdb->get_results( $sql );
     1172        }
     1173
    11341174}
  • tests/phpunit/testcases/notifications/functions.php

     
    3535                ) );
    3636
    3737                $this->assertFalse( wp_cache_get( 'all_for_user_' . $u, 'bp_notifications' ) );
     38                $this->assertFalse( wp_cache_get( 'grouped_notifications_for_user_' . $u, 'bp_notifications' ) );
     39                $this->assertFalse( wp_cache_get( 'unread_notification_count_for_user_' . $u, 'bp_notifications' ) );
    3840        }
    3941
    4042        /**
     
    6163                BP_Notifications_Notification::delete( array( 'id' => $n1, ) );
    6264
    6365                $this->assertFalse( wp_cache_get( 'all_for_user_' . $u, 'bp_notifications' ) );
     66                $this->assertFalse( wp_cache_get( 'grouped_notifications_for_user_' . $u, 'bp_notifications' ) );
     67                $this->assertFalse( wp_cache_get( 'unread_notification_count_for_user_' . $u, 'bp_notifications' ) );
    6468        }
    6569
    6670        /**
     
    9195                );
    9296
    9397                $this->assertFalse( wp_cache_get( 'all_for_user_' . $u, 'bp_notifications' ) );
     98                $this->assertFalse( wp_cache_get( 'grouped_notifications_for_user_' . $u, 'bp_notifications' ) );
     99                $this->assertFalse( wp_cache_get( 'unread_notification_count_for_user_' . $u, 'bp_notifications' ) );
    94100        }
    95101
    96102        /**
     
    121127                );
    122128
    123129                $this->assertFalse( wp_cache_get( 'all_for_user_' . $u, 'bp_notifications' ) );
     130                $this->assertFalse( wp_cache_get( 'grouped_notifications_for_user_' . $u, 'bp_notifications' ) );
     131                $this->assertFalse( wp_cache_get( 'unread_notification_count_for_user_' . $u, 'bp_notifications' ) );
    124132        }
    125133
    126134        /**