Skip to:
Content

BuddyPress.org

Ticket #7130: 7130.3.diff

File 7130.3.diff, 15.4 KB (added by boonebgorges, 6 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 981190052..09f140a8a 100644
    function bp_notifications_update_meta_cache( $notification_ids = false ) { 
    4444function bp_notifications_clear_all_for_user_cache( $user_id = 0 ) {
    4545        wp_cache_delete( 'all_for_user_' . $user_id, 'bp_notifications' );
    4646        wp_cache_delete( $user_id, 'bp_notifications_unread_count' );
     47        wp_cache_delete( $user_id, 'bp_notifications_grouped_notifications' );
    4748}
    4849
    4950/**
  • src/bp-notifications/bp-notifications-functions.php

    diff --git src/bp-notifications/bp-notifications-functions.php src/bp-notifications/bp-notifications-functions.php
    index dd20212ad..322967167 100644
    function bp_notifications_get_all_notifications_for_user( $user_id = 0 ) { 
    162162        return apply_filters( 'bp_notifications_get_all_notifications_for_user', $notifications, $user_id );
    163163}
    164164
     165/**
     166 * Get a user's unread notifications, grouped by component and action.
     167 *
     168 * This function returns a list of notifications collapsed by component + action.
     169 * See BP_Notifications_Notification::get_grouped_notifications_for_user() for
     170 * more details.
     171 *
     172 * @since 3.0.0
     173 *
     174 * @param int $user_id ID of the user whose notifications are being fetched.
     175 * @return array $notifications
     176 */
     177function bp_notifications_get_grouped_notifications_for_user( $user_id = 0 ) {
     178        if ( empty( $user_id ) ) {
     179                $user_id = ( bp_displayed_user_id() ) ? bp_displayed_user_id() : bp_loggedin_user_id();
     180        }
     181
     182        $notifications = wp_cache_get( $user_id, 'bp_notifications_grouped_notifications' );
     183        if ( false === $notifications ) {
     184                $notifications = BP_Notifications_Notification::get_grouped_notifications_for_user( $user_id );
     185                wp_cache_set( $user_id, $notifications, 'bp_notifications_grouped_notifications' );
     186        }
     187
     188        return $notifications;
     189}
     190
    165191/**
    166192 * Get notifications for a specific user.
    167193 *
    function bp_notifications_get_all_notifications_for_user( $user_id = 0 ) { 
    173199 * @return mixed Object or array on success, false on failure.
    174200 */
    175201function bp_notifications_get_notifications_for_user( $user_id, $format = 'string' ) {
    176 
    177         // Setup local variables.
    178202        $bp = buddypress();
    179203
    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.
    184 
    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         }
     204        $notifications = bp_notifications_get_grouped_notifications_for_user( $user_id );
    195205
    196206        // Calculate a renderable output for each notification type.
    197         foreach ( $grouped_notifications as $component_name => $action_arrays ) {
     207        foreach ( $notifications as $notification_item ) {
    198208
     209                $component_name = $notification_item->component_name;
    199210                // We prefer that extended profile component-related notifications use
    200211                // the component_name of 'xprofile'. However, the extended profile child
    201212                // object in the $bp object is keyed as 'profile', which is where we need
    202213                // to look for the registered notification callback.
    203                 if ( 'xprofile' == $component_name ) {
     214                if ( 'xprofile' == $notification_item->component_name ) {
    204215                        $component_name = 'profile';
    205216                }
    206217
    207                 // Skip if group is empty.
    208                 if ( empty( $action_arrays ) ) {
    209                         continue;
    210                 }
     218                // Callback function exists.
     219                if ( isset( $bp->{$component_name}->notification_callback ) && is_callable( $bp->{$component_name}->notification_callback ) ) {
    211220
    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 ) {
     221                        // Function should return an object.
     222                        if ( 'object' === $format ) {
    214223
    215                         // Get the number of actionable items.
    216                         $action_item_count = count( $component_action_items );
     224                                // Retrieve the content of the notification using the callback.
     225                                $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 );
    217226
    218                         // Skip if the count is less than 1.
    219                         if ( $action_item_count < 1 ) {
    220                                 continue;
    221                         }
     227                                // Create the object to be returned.
     228                                $notification_object = $notification_item;
    222229
    223                         // Callback function exists.
    224                         if ( isset( $bp->{$component_name}->notification_callback ) && is_callable( $bp->{$component_name}->notification_callback ) ) {
    225 
    226                                 // Function should return an object.
    227                                 if ( 'object' === $format ) {
    228 
    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 
    255                                 // Return an array of content strings.
     230                                // Minimal backpat with non-compatible notification
     231                                // callback functions.
     232                                if ( is_string( $content ) ) {
     233                                        $notification_object->content = $content;
     234                                        $notification_object->href    = bp_loggedin_user_domain();
    256235                                } 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;
     236                                        $notification_object->content = $content['text'];
     237                                        $notification_object->href    = $content['link'];
    259238                                }
    260239
     240                                $renderable[] = $notification_object;
     241
     242                                // Return an array of content strings.
     243                        } else {
     244                                $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 );
     245                                $renderable[] = $content;
     246                        }
     247
    261248                        // @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 );
     249                } elseif ( isset( $bp->{$component_name}->format_notification_function ) && function_exists( $bp->{$component_name}->format_notification_function ) ) {
     250                        $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 );
    264251
    265252                        // Allow non BuddyPress components to hook in.
    266                         } else {
     253                } else {
     254
     255                        // The array to reference with apply_filters_ref_array().
     256                        $ref_array = array(
     257                                $notification_item->component_action,
     258                                $notification_item->item_id,
     259                                $notification_item->secondary_item_id,
     260                                $notification_item->total_count,
     261                                $format,
     262                                $notification_item->component_action, // Duplicated so plugins can check the canonical action name.
     263                                $component_name,
     264                                $notification_item->id,
     265                        );
     266
     267                        // Function should return an object.
     268                        if ( 'object' === $format ) {
     269
     270                                /**
     271                                 * Filters the notification content for notifications created by plugins.
     272                                 * If your plugin extends the {@link BP_Component} class, you should use the
     273                                 * 'notification_callback' parameter in your extended
     274                                 * {@link BP_Component::setup_globals()} method instead.
     275                                 *
     276                                 * @since 1.9.0
     277                                 * @since 2.6.0 Added $component_action_name, $component_name, $id as parameters.
     278                                 *
     279                                 * @param string $content               Component action. Deprecated. Do not do checks against this! Use
     280                                 *                                      the 6th parameter instead - $component_action_name.
     281                                 * @param int    $item_id               Notification item ID.
     282                                 * @param int    $secondary_item_id     Notification secondary item ID.
     283                                 * @param int    $action_item_count     Number of notifications with the same action.
     284                                 * @param string $format                Format of return. Either 'string' or 'object'.
     285                                 * @param string $component_action_name Canonical notification action.
     286                                 * @param string $component_name        Notification component ID.
     287                                 * @param int    $id                    Notification ID.
     288                                 *
     289                                 * @return string|array If $format is 'string', return a string of the notification content.
     290                                 *                      If $format is 'object', return an array formatted like:
     291                                 *                      array( 'text' => 'CONTENT', 'link' => 'LINK' )
     292                                 */
     293                                $content = apply_filters_ref_array( 'bp_notifications_get_notifications_for_user', $ref_array );
     294
     295                                // Create the object to be returned.
     296                                $notification_object = $notification_item;
     297
     298                                // Minimal backpat with non-compatible notification
     299                                // callback functions.
     300                                if ( is_string( $content ) ) {
     301                                        $notification_object->content = $content;
     302                                        $notification_object->href    = bp_loggedin_user_domain();
     303                                } else {
     304                                        $notification_object->content = $content['text'];
     305                                        $notification_object->href    = $content['link'];
     306                                }
    267307
    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                                 );
    279 
    280                                 // Function should return an object.
    281                                 if ( 'object' === $format ) {
    282 
    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 );
    308 
    309                                         // Create the object to be returned.
    310                                         $notification_object = $component_action_items[0];
    311 
    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                                         }
    321 
    322                                         $renderable[] = $notification_object;
     308                                $renderable[] = $notification_object;
    323309
    324310                                // Return an array of content strings.
    325                                 } else {
     311                        } else {
    326312
    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                                 }
     313                                /** This filters is documented in bp-notifications/bp-notifications-functions.php */
     314                                $renderable[] = apply_filters_ref_array( 'bp_notifications_get_notifications_for_user', $ref_array );
    330315                        }
    331316                }
    332317        }
  • 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 a461a5908..45fbe4123 100644
    class BP_Notifications_Notification { 
    11311131
    11321132                return self::update( $update_args, $where_args );
    11331133        }
     1134
     1135        /**
     1136         * Get a user's unread notifications, grouped by component and action.
     1137         *
     1138         * Multiple notifications of the same type (those that share the same component_name
     1139         * and component_action) are collapsed for formatting as "You have 5 pending
     1140         * friendship requests", etc. See bp_notifications_get_notifications_for_user().
     1141         * For a full-fidelity list of user notifications, use
     1142         * bp_notifications_get_all_notifications_for_user().
     1143         *
     1144         * @since 3.0.0
     1145         *
     1146         * @param int $user_id ID of the user whose notifications are being fetched.
     1147         * @return array Notifications items for formatting into a list.
     1148         */
     1149        public static function get_grouped_notifications_for_user( $user_id ) {
     1150                global $wpdb;
     1151
     1152                // Load BuddyPress.
     1153                $bp = buddypress();
     1154
     1155                // SELECT.
     1156                $select_sql = "SELECT id, user_id, item_id, secondary_item_id, component_name, component_action, date_notified, is_new, COUNT(id) as total_count ";
     1157
     1158                // FROM.
     1159                $from_sql = "FROM {$bp->notifications->table_name} n ";
     1160
     1161                // WHERE.
     1162                $where_sql = self::get_where_sql( array(
     1163                        'user_id'        => $user_id,
     1164                        'is_new'         => 1,
     1165                        'component_name' => bp_notifications_get_registered_components(),
     1166                ), $select_sql, $from_sql );
     1167
     1168                // GROUP
     1169                $group_sql = "GROUP BY user_id, component_name, component_action";
     1170
     1171                // SORT
     1172                $order_sql = "ORDER BY date_notified desc";
     1173
     1174                // Concatenate query parts.
     1175                $sql = "{$select_sql} {$from_sql} {$where_sql} {$group_sql} {$order_sql}";
     1176
     1177                // Return the queried results.
     1178                return $wpdb->get_results( $sql );
     1179        }
    11341180}