Skip to:
Content

BuddyPress.org

Ticket #5148: 5148.02.patch

File 5148.02.patch, 89.3 KB (added by boonebgorges, 11 years ago)
  • bp-core/admin/bp-core-components.php

    diff --git bp-core/admin/bp-core-components.php bp-core/admin/bp-core-components.php
    index e15ed3f..da612d7 100644
    function bp_core_admin_components_options() { 
    5858                'xprofile' => array(
    5959                        'title'       => __( 'Extended Profiles', 'buddypress' ),
    6060                        'description' => __( 'Customize your community with fully editable profile fields that allow your users to describe themselves.', 'buddypress' )
    61                 )
     61                ),
     62                'settings' => array(
     63                        'title'       => __( 'Account Settings', 'buddypress' ),
     64                        'description' => __( 'Allow your users to modify their account and notification settings directly from within their profiles.', 'buddypress' )
     65                ),
     66                'notifications' => array(
     67                        'title'       => __( 'Notifications', 'buddypress' ),
     68                        'description' => __( 'Notify members of relevant activity with a toolbar bubble and/or via email, and allow them to customize their notification settings.', 'buddypress' )
     69                ),
    6270        );
    6371
    6472        $optional_components = bp_core_admin_get_components( 'optional' );
    6573        $required_components = bp_core_admin_get_components( 'required' );
    66         $retired_components = bp_core_admin_get_components( 'retired' );
     74        $retired_components  = bp_core_admin_get_components( 'retired' );
    6775
    6876        // Don't show Forums component in optional components if it's disabled
    6977        if ( ! bp_is_active( 'forums' ) ) {
    function bp_core_admin_get_components( $type = 'all' ) { 
    371379                        'title'       => __( 'Activity Streams', 'buddypress' ),
    372380                        'description' => __( 'Global, personal, and group activity streams with threaded commenting, direct posting, favoriting and @mentions, all with full RSS feed and email notification support.', 'buddypress' )
    373381                ),
     382                'notifications' => array(
     383                        'title'       => __( 'Notifications', 'buddypress' ),
     384                        'description' => __( 'Notify members of relevant activity with a toolbar bubble and/or via email, and allow them to customize their notification settings.', 'buddypress' )
     385                ),
    374386                'groups'   => array(
    375387                        'title'       => __( 'User Groups', 'buddypress' ),
    376388                        'description' => __( 'Groups allow your users to organize themselves into specific public, private or hidden sections with separate activity streams and member listings.', 'buddypress' )
  • bp-core/admin/bp-core-schema.php

    diff --git bp-core/admin/bp-core-schema.php bp-core/admin/bp-core-schema.php
    index 3b0e891..6001979 100644
    function bp_core_install( $active_components = false ) { 
    2323        if ( empty( $active_components ) )
    2424                $active_components = apply_filters( 'bp_active_components', bp_get_option( 'bp-active-components' ) );
    2525
    26         // Core DB Tables
    27         bp_core_install_notifications();
     26        // Notifications
     27        if ( !empty( $active_components['notifications'] ) )
     28                bp_core_install_notifications();
    2829
    2930        // Activity Streams
    3031        if ( !empty( $active_components['activity'] ) )
  • bp-core/bp-core-classes.php

    diff --git bp-core/bp-core-classes.php bp-core/bp-core-classes.php
    index 38ba997..dce2a52 100644
    class BP_Core_User { 
    12911291
    12921292
    12931293/**
    1294  * BP_Core_Notification class can be used by any component.
    1295  * It will handle the fetching, saving and deleting of a user notification.
     1294 * BP_Core_Notification is deprecated.
     1295 *
     1296 * Use BP_Notifications_Notification instead.
    12961297 *
    12971298 * @package BuddyPress Core
     1299 * @deprecated since BuddyPress (1.9)
    12981300 */
    1299 
    13001301class BP_Core_Notification {
    13011302
    13021303        /**
  • bp-core/bp-core-loader.php

    diff --git bp-core/bp-core-loader.php bp-core/bp-core-loader.php
    index 0877c0a..2d7f2fe 100644
    class BP_Core extends BP_Component { 
    5454                /** Components ********************************************************/
    5555
    5656                // Set the included and optional components.
    57                 $bp->optional_components = apply_filters( 'bp_optional_components', array( 'activity', 'blogs', 'forums', 'friends', 'groups', 'messages', 'settings', 'xprofile' ) );
     57                $bp->optional_components = apply_filters( 'bp_optional_components', array( 'activity', 'blogs', 'forums', 'friends', 'groups', 'messages', 'notifications', 'settings', 'xprofile' ) );
    5858
    5959                // Set the required components
    6060                $bp->required_components = apply_filters( 'bp_required_components', array( 'members' ) );
    class BP_Core extends BP_Component { 
    177177                $bp->grav_default->group = apply_filters( 'bp_group_gravatar_default', $bp->grav_default->user );
    178178                $bp->grav_default->blog  = apply_filters( 'bp_blog_gravatar_default',  $bp->grav_default->user );
    179179
    180                 // Notifications Table
     180                // Notifications table. Included here for legacy purposes. Use
     181                // bp-notifications instead.
    181182                $bp->core->table_name_notifications = $bp->table_prefix . 'bp_notifications';
    182183
    183184                /**
  • bp-core/bp-core-template.php

    diff --git bp-core/bp-core-template.php bp-core/bp-core-template.php
    index 2370094..c38d049 100644
    function bp_is_forums_component() { 
    14351435}
    14361436
    14371437/**
     1438 * Check whether the current page is part of the Notifications component.
     1439 *
     1440 * @since BuddyPress (1.9.0)
     1441 *
     1442 * @return bool True if the current page is part of the Notifications component.
     1443 */
     1444function bp_is_notifications_component() {
     1445        if ( bp_is_current_component( 'notifications' ) ) {
     1446                return true;
     1447        }
     1448
     1449        return false;
     1450}
     1451
     1452/**
    14381453 * Check whether the current page is part of the Settings component.
    14391454 *
    14401455 * @return bool True if the current page is part of the Settings component.
    function bp_is_user_friend_requests() { 
    17491764}
    17501765
    17511766/**
     1767 * Is this a user's notifications page?
     1768 *
     1769 * Eg http://example.com/members/joe/notifications/ (or a subpage thereof).
     1770 *
     1771 * @since BuddyPress (1.9.0)
     1772 *
     1773 * @return bool True if the current page is a user's Notifications page.
     1774 */
     1775function bp_is_user_notifications() {
     1776        if ( bp_is_user() && bp_is_notifications_component() ) {
     1777                return true;
     1778        }
     1779
     1780        return false;
     1781}
     1782
     1783/**
    17521784 * Is this a user's settings page?
    17531785 *
    17541786 * Eg http://example.com/members/joe/settings/ (or a subpage thereof).
  • bp-core/bp-core-update.php

    diff --git bp-core/bp-core-update.php bp-core/bp-core-update.php
    index e565334..d75564d 100644
    function bp_version_updater() { 
    187187        $raw_db_version = (int) bp_get_db_version_raw();
    188188
    189189        $default_components = apply_filters( 'bp_new_install_default_components', array(
    190                 'activity' => 1,
    191                 'members'  => 1,
    192                 'settings' => 1,
    193                 'xprofile' => 1,
     190                'activity'      => 1,
     191                'members'       => 1,
     192                'settings'      => 1,
     193                'xprofile'      => 1,
     194                'notifications' => 1,
    194195        ) );
    195196
    196197        require_once( BP_PLUGIN_DIR . '/bp-core/admin/bp-core-schema.php' );
  • bp-friends/bp-friends-classes.php

    diff --git bp-friends/bp-friends-classes.php bp-friends/bp-friends-classes.php
    index c895d14..085d0d1 100644
    class BP_Friends_Friendship { 
    363363                // Delete all friendships related to $user_id
    364364                $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->friends->table_name} WHERE friend_user_id = %d OR initiator_user_id = %d", $user_id, $user_id ) );
    365365
    366                 // Delete friend request notifications for members who have a notification from this user.
    367                 $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->core->table_name_notifications} WHERE component_name = 'friends' AND ( component_action = 'friendship_request' OR component_action = 'friendship_accepted' ) AND item_id = %d", $user_id ) );
     366                // Delete friend request notifications for members who have a
     367                // notification from this user.
     368                if ( bp_is_active( 'notifications' ) ) {
     369                        $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->notifications->table_name} WHERE component_name = 'friends' AND ( component_action = 'friendship_request' OR component_action = 'friendship_accepted' ) AND item_id = %d", $user_id ) );
     370                }
    368371
    369372                // Loop through friend_ids and update their counts
    370373                foreach ( (array) $friend_ids as $friend_id ) {
  • bp-members/bp-members-adminbar.php

    diff --git bp-members/bp-members-adminbar.php bp-members/bp-members-adminbar.php
    index 2a29ddc..9c4662c 100644
    add_action( 'admin_bar_menu', 'bp_members_admin_bar_user_admin_menu', 99 ); 
    139139 * @since BuddyPress (1.5)
    140140 */
    141141function bp_members_admin_bar_notifications_menu() {
    142         global $wp_admin_bar;
    143142
    144         if ( !is_user_logged_in() )
     143        // Bail if notifications is not active
     144        if ( ! bp_is_active( 'notifications' ) ) {
    145145                return false;
    146 
    147         $notifications = bp_core_get_notifications_for_user( bp_loggedin_user_id(), 'object' );
    148         $count         = !empty( $notifications ) ? count( $notifications ) : 0;
    149         $alert_class   = (int) $count > 0 ? 'pending-count alert' : 'count no-alert';
    150         $menu_title    = '<span id="ab-pending-notifications" class="' . $alert_class . '">' . $count . '</span>';
    151 
    152         // Add the top-level Notifications button
    153         $wp_admin_bar->add_menu( array(
    154                 'parent'    => 'top-secondary',
    155                 'id'        => 'bp-notifications',
    156                 'title'     => $menu_title,
    157                 'href'      => bp_loggedin_user_domain(),
    158         ) );
    159 
    160         if ( !empty( $notifications ) ) {
    161                 foreach ( (array) $notifications as $notification ) {
    162                         $wp_admin_bar->add_menu( array(
    163                                 'parent' => 'bp-notifications',
    164                                 'id'     => 'notification-' . $notification->id,
    165                                 'title'  => $notification->content,
    166                                 'href'   => $notification->href
    167                         ) );
    168                 }
    169         } else {
    170                 $wp_admin_bar->add_menu( array(
    171                         'parent' => 'bp-notifications',
    172                         'id'     => 'no-notifications',
    173                         'title'  => __( 'No new notifications', 'buddypress' ),
    174                         'href'   => bp_loggedin_user_domain()
    175                 ) );
    176146        }
    177147
    178         return;
     148        bp_notifications_toolbar_menu();
    179149}
    180150add_action( 'admin_bar_menu', 'bp_members_admin_bar_notifications_menu', 90 );
    181151
  • bp-members/bp-members-buddybar.php

    diff --git bp-members/bp-members-buddybar.php bp-members/bp-members-buddybar.php
    index 613d087..f3c08c2 100644
    if ( !defined( 'ABSPATH' ) ) exit; 
    1717 */
    1818function bp_adminbar_notifications_menu() {
    1919
    20         if ( !is_user_logged_in() )
     20        // Bail if notifications is not active
     21        if ( ! bp_is_active( 'notifications' ) ) {
    2122                return false;
    22 
    23         echo '<li id="bp-adminbar-notifications-menu"><a href="' . bp_loggedin_user_domain() . '">';
    24         _e( 'Notifications', 'buddypress' );
    25 
    26         if ( $notifications = bp_core_get_notifications_for_user( bp_loggedin_user_id() ) ) { ?>
    27                 <span><?php echo count( $notifications ) ?></span>
    28         <?php
    29         }
    30 
    31         echo '</a>';
    32         echo '<ul>';
    33 
    34         if ( $notifications ) {
    35                 $counter = 0;
    36                 for ( $i = 0, $count = count( $notifications ); $i < $count; ++$i ) {
    37                         $alt = ( 0 == $counter % 2 ) ? ' class="alt"' : ''; ?>
    38 
    39                         <li<?php echo $alt ?>><?php echo $notifications[$i] ?></li>
    40 
    41                         <?php $counter++;
    42                 }
    43         } else { ?>
    44 
    45                 <li><a href="<?php echo bp_loggedin_user_domain() ?>"><?php _e( 'No new notifications.', 'buddypress' ); ?></a></li>
    46 
    47         <?php
    4823        }
    4924
    50         echo '</ul>';
    51         echo '</li>';
     25        bp_notifications_buddybar_menu();
    5226}
    5327add_action( 'bp_adminbar_menus', 'bp_adminbar_notifications_menu', 8 );
    5428
  • bp-members/bp-members-notifications.php

    diff --git bp-members/bp-members-notifications.php bp-members/bp-members-notifications.php
    index 5e670b7..debb1d5 100644
     
    33/**
    44 * BuddyPress Member Notifications
    55 *
    6  * Functions and filters used for member notification
     6 * Backwards compatibility functions and filters used for member notifications.
     7 * Use bp-notifications instead.
    78 *
    89 * @package BuddyPress
    910 * @subpackage MembersNotifications
    if ( !defined( 'ABSPATH' ) ) exit; 
    2627 */
    2728function bp_core_add_notification( $item_id, $user_id, $component_name, $component_action, $secondary_item_id = 0, $date_notified = false ) {
    2829
    29         if ( empty( $date_notified ) )
    30                 $date_notified = bp_core_current_time();
    31 
    32         $notification                   = new BP_Core_Notification;
    33         $notification->item_id          = $item_id;
    34         $notification->user_id          = $user_id;
    35         $notification->component_name   = $component_name;
    36         $notification->component_action = $component_action;
    37         $notification->date_notified    = $date_notified;
    38         $notification->is_new           = 1;
    39 
    40         if ( !empty( $secondary_item_id ) )
    41                 $notification->secondary_item_id = $secondary_item_id;
    42 
    43         if ( $notification->save() )
    44                 return true;
     30        // Bail if notifications is not active
     31        if ( ! bp_is_active( 'notifications' ) ) {
     32                return false;
     33        }
    4534
    46         return false;
     35        return bp_notifications_add_notification( $item_id, $user_id, $component_name, $component_action, $secondary_item_id = 0, $date_notified = false );
    4736}
    4837
    4938/**
    function bp_core_add_notification( $item_id, $user_id, $component_name, $compone 
    5443 * @return boolean True on success, false on fail
    5544 */
    5645function bp_core_delete_notification( $id ) {
    57         if ( !bp_core_check_notification_access( bp_loggedin_user_id(), $id ) )
     46
     47        // Bail if notifications is not active
     48        if ( ! bp_is_active( 'notifications' ) ) {
    5849                return false;
     50        }
    5951
    60         return BP_Core_Notification::delete( $id );
     52        return bp_notifications_delete_notification( $id );
    6153}
    6254
    6355/**
    function bp_core_delete_notification( $id ) { 
    6860 * @return BP_Core_Notification
    6961 */
    7062function bp_core_get_notification( $id ) {
    71         return new BP_Core_Notification( $id );
     63
     64        // Bail if notifications is not active
     65        if ( ! bp_is_active( 'notifications' ) ) {
     66                return false;
     67        }
     68
     69        return bp_notifications_get_notification( $id );
    7270}
    7371
    7472/**
    function bp_core_get_notification( $id ) { 
    8179 * @return boolean Object or array on success, false on fail
    8280 */
    8381function bp_core_get_notifications_for_user( $user_id, $format = 'simple' ) {
    84         global $bp;
    85 
    86         $notifications         = BP_Core_Notification::get_all_for_user( $user_id );
    87         $grouped_notifications = array(); // Notification groups
    88         $renderable            = array(); // Renderable notifications
    89 
    90         // Group notifications by component and component_action and provide totals
    91         for ( $i = 0, $count = count( $notifications ); $i < $count; ++$i ) {
    92                 $notification = $notifications[$i];
    93                 $grouped_notifications[$notification->component_name][$notification->component_action][] = $notification;
    94         }
    9582
    96         // Bail if no notification groups
    97         if ( empty( $grouped_notifications ) )
     83        // Bail if notifications is not active
     84        if ( ! bp_is_active( 'notifications' ) ) {
    9885                return false;
    99 
    100         // Calculate a renderable output for each notification type
    101         foreach ( $grouped_notifications as $component_name => $action_arrays ) {
    102 
    103                 // Skip if group is empty
    104                 if ( empty( $action_arrays ) )
    105                         continue;
    106 
    107                 // Skip inactive components
    108                 if ( !bp_is_active( $component_name ) )
    109                         continue;
    110 
    111                 // Loop through each actionable item and try to map it to a component
    112                 foreach ( (array) $action_arrays as $component_action_name => $component_action_items ) {
    113 
    114                         // Get the number of actionable items
    115                         $action_item_count = count( $component_action_items );
    116 
    117                         // Skip if the count is less than 1
    118                         if ( $action_item_count < 1 )
    119                                 continue;
    120 
    121                         // Callback function exists
    122                         if ( isset( $bp->{$component_name}->notification_callback ) && is_callable( $bp->{$component_name}->notification_callback ) ) {
    123 
    124                                 // Function should return an object
    125                                 if ( 'object' == $format ) {
    126 
    127                                         // Retrieve the content of the notification using the callback
    128                                         $content = call_user_func(
    129                                                 $bp->{$component_name}->notification_callback,
    130                                                 $component_action_name,
    131                                                 $component_action_items[0]->item_id,
    132                                                 $component_action_items[0]->secondary_item_id,
    133                                                 $action_item_count,
    134                                                 'array'
    135                                         );
    136 
    137                                         // Create the object to be returned
    138                                         $notification_object = new stdClass;
    139 
    140                                         // Minimal backpat with non-compatible notification
    141                                         // callback functions
    142                                         if ( is_string( $content ) ) {
    143                                                 $notification_object->content = $content;
    144                                                 $notification_object->href    = bp_loggedin_user_domain();
    145                                         } else {
    146                                                 $notification_object->content = $content['text'];
    147                                                 $notification_object->href    = $content['link'];
    148                                         }
    149 
    150                                         $notification_object->id = $component_action_items[0]->id;
    151                                         $renderable[]            = $notification_object;
    152 
    153                                 // Return an array of content strings
    154                                 } else {
    155                                         $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 );
    156                                         $renderable[] = $content;
    157                                 }
    158 
    159                         // @deprecated format_notification_function - 1.5
    160                         } elseif ( isset( $bp->{$component_name}->format_notification_function ) && function_exists( $bp->{$component_name}->format_notification_function ) ) {
    161                                 $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 );
    162                         }
    163                 }
    16486        }
    16587
    166         // If renderable is empty array, set to false
    167         if ( empty( $renderable ) )
    168                 $renderable = false;
     88        $renderable = bp_notifications_get_notifications_for_user( $user_id, $format );
    16989
    170         // Filter and return
    17190        return apply_filters( 'bp_core_get_notifications_for_user', $renderable, $user_id, $format );
    17291}
    17392
    function bp_core_get_notifications_for_user( $user_id, $format = 'simple' ) { 
    184103 * @return boolean True on success, false on fail
    185104 */
    186105function bp_core_delete_notifications_by_type( $user_id, $component_name, $component_action ) {
    187         return BP_Core_Notification::delete_for_user_by_type( $user_id, $component_name, $component_action );
     106
     107        // Bail if notifications is not active
     108        if ( ! bp_is_active( 'notifications' ) ) {
     109                return false;
     110        }
     111
     112        return bp_notifications_delete_notifications_by_type( $user_id, $component_name, $component_action );
    188113}
    189114
    190115/**
    function bp_core_delete_notifications_by_type( $user_id, $component_name, $compo 
    200125 * @return boolean True on success, false on fail
    201126 */
    202127function bp_core_delete_notifications_by_item_id( $user_id, $item_id, $component_name, $component_action, $secondary_item_id = false ) {
    203         return BP_Core_Notification::delete_for_user_by_item_id( $user_id, $item_id, $component_name, $component_action, $secondary_item_id );
     128
     129        // Bail if notifications is not active
     130        if ( ! bp_is_active( 'notifications' ) ) {
     131                return false;
     132        }
     133
     134        return bp_notifications_delete_notifications_by_item_id( $user_id, $item_id, $component_name, $component_action, $secondary_item_id );
    204135}
    205136
    206137/**
    function bp_core_delete_notifications_by_item_id( $user_id, $item_id, $component 
    215146 * @return boolean True on success, false on fail
    216147 */
    217148function bp_core_delete_all_notifications_by_type( $item_id, $component_name, $component_action = false, $secondary_item_id = false ) {
    218         return BP_Core_Notification::delete_all_by_type( $item_id, $component_name, $component_action, $secondary_item_id );
     149
     150        // Bail if notifications is not active
     151        if ( ! bp_is_active( 'notifications' ) ) {
     152                return false;
     153        }
     154
     155        bp_notifications_delete_all_notifications_by_type( $item_id, $component_name, $component_action, $secondary_item_id );
    219156}
    220157
    221158/**
    function bp_core_delete_all_notifications_by_type( $item_id, $component_name, $c 
    230167 * @return boolean True on success, false on fail
    231168 */
    232169function bp_core_delete_notifications_from_user( $user_id, $component_name, $component_action ) {
    233         return BP_Core_Notification::delete_from_user_by_type( $user_id, $component_name, $component_action );
     170
     171        // Bail if notifications is not active
     172        if ( ! bp_is_active( 'notifications' ) ) {
     173                return false;
     174        }
     175
     176        return bp_notifications_delete_notifications_from_user( $user_id, $component_name, $component_action );
    234177}
    235178
    236179/**
    function bp_core_delete_notifications_from_user( $user_id, $component_name, $com 
    244187 * @return boolean True on success, false on fail
    245188 */
    246189function bp_core_check_notification_access( $user_id, $notification_id ) {
    247         if ( !BP_Core_Notification::check_access( $user_id, $notification_id ) )
     190
     191        // Bail if notifications is not active
     192        if ( ! bp_is_active( 'notifications' ) ) {
    248193                return false;
     194        }
    249195
    250         return true;
     196        return bp_notifications_check_notification_access( $user_id, $notification_id );
    251197}
  • new file p-notifications/bp-notifications-adminbar.php

    diff --git bp-notifications/bp-notifications-adminbar.php bp-notifications/bp-notifications-adminbar.php
    new file mode 100644
    index 0000000..0700adf
    - +  
     1<?php
     2
     3/**
     4 * BuddyPress Notifications Admin Bar functions.
     5 *
     6 * Admin Bar functions for the Notifications component.
     7 *
     8 * @package BuddyPress
     9 * @subpackage NotificationsToolbar
     10 */
     11
     12// Exit if accessed directly
     13if ( !defined( 'ABSPATH' ) ) exit;
     14
     15/**
     16 * Build the "Notifications" dropdown.
     17 *
     18 * @since BuddyPress (1.9.0)
     19 */
     20function bp_notifications_toolbar_menu() {
     21        global $wp_admin_bar;
     22
     23        if ( ! is_user_logged_in() ) {
     24                return false;
     25        }
     26
     27        $notifications = bp_core_get_notifications_for_user( bp_loggedin_user_id(), 'object' );
     28        $count         = ! empty( $notifications ) ? count( $notifications ) : 0;
     29        $alert_class   = (int) $count > 0 ? 'pending-count alert' : 'count no-alert';
     30        $menu_title    = '<span id="ab-pending-notifications" class="' . $alert_class . '">' . $count . '</span>';
     31
     32        // Add the top-level Notifications button
     33        $wp_admin_bar->add_menu( array(
     34                'parent'    => 'top-secondary',
     35                'id'        => 'bp-notifications',
     36                'title'     => $menu_title,
     37                'href'      => bp_loggedin_user_domain(),
     38        ) );
     39
     40        if ( ! empty( $notifications ) ) {
     41                foreach ( (array) $notifications as $notification ) {
     42                        $wp_admin_bar->add_menu( array(
     43                                'parent' => 'bp-notifications',
     44                                'id'     => 'notification-' . $notification->id,
     45                                'title'  => $notification->content,
     46                                'href'   => $notification->href,
     47                        ) );
     48                }
     49        } else {
     50                $wp_admin_bar->add_menu( array(
     51                        'parent' => 'bp-notifications',
     52                        'id'     => 'no-notifications',
     53                        'title'  => __( 'No new notifications', 'buddypress' ),
     54                        'href'   => bp_loggedin_user_domain(),
     55                ) );
     56        }
     57
     58        return;
     59}
     60add_action( 'admin_bar_menu', 'bp_members_admin_bar_notifications_menu', 90 );
  • new file p-notifications/bp-notifications-buddybar.php

    diff --git bp-notifications/bp-notifications-buddybar.php bp-notifications/bp-notifications-buddybar.php
    new file mode 100644
    index 0000000..3931ecf
    - +  
     1<?php
     2
     3/**
     4 * BuddyPress Notifications Navigational Functions.
     5 *
     6 * Sets up navigation elements, including BuddyBar functionality, for the
     7 * Notifications component.
     8 *
     9 * @package BuddyPress
     10 * @subpackage NotificationsBuddyBar
     11 */
     12
     13// Exit if accessed directly
     14if ( !defined( 'ABSPATH' ) ) exit;
     15
     16/**
     17 * Create the Notifications menu for the BuddyBar.
     18 *
     19 * @since BuddyPress (1.9.0)
     20 */
     21function bp_notifications_buddybar_menu() {
     22
     23        if ( ! is_user_logged_in() ) {
     24                return false;
     25        }
     26
     27        echo '<li id="bp-adminbar-notifications-menu"><a href="' . bp_loggedin_user_domain() . '">';
     28        _e( 'Notifications', 'buddypress' );
     29
     30        if ( $notifications = bp_core_get_notifications_for_user( bp_loggedin_user_id() ) ) : ?>
     31                <span><?php echo count( $notifications ) ?></span>
     32        <?php
     33        endif;
     34
     35        echo '</a>';
     36        echo '<ul>';
     37
     38        if ( $notifications ) {
     39                $counter = 0;
     40                for ( $i = 0, $count = count( $notifications ); $i < $count; ++$i ) {
     41                        $alt = ( 0 == $counter % 2 ) ? ' class="alt"' : ''; ?>
     42
     43                        <li<?php echo $alt ?>><?php echo $notifications[$i] ?></li>
     44
     45                        <?php $counter++;
     46                }
     47        } else { ?>
     48
     49                <li><a href="<?php echo bp_loggedin_user_domain() ?>"><?php _e( 'No new notifications.', 'buddypress' ); ?></a></li>
     50
     51        <?php
     52        }
     53
     54        echo '</ul>';
     55        echo '</li>';
     56}
     57add_action( 'bp_adminbar_menus', 'bp_adminbar_notifications_menu', 8 );
  • new file p-notifications/bp-notifications-classes.php

    diff --git bp-notifications/bp-notifications-classes.php bp-notifications/bp-notifications-classes.php
    new file mode 100644
    index 0000000..4febe78
    - +  
     1<?php
     2
     3/**
     4 * BuddyPress Notifications Classes
     5 *
     6 * Classes used for the Notifications component.
     7 *
     8 * @package BuddyPress
     9 * @subpackage NotificationsClasses
     10 *
     11 * @since BuddyPress (1.9.0)
     12 */
     13
     14// Exit if accessed directly
     15if ( !defined( 'ABSPATH' ) ) exit;
     16
     17/**
     18 * BuddyPress Notification items.
     19 *
     20 * Use this class to create, access, edit, or delete BuddyPress Notifications.
     21 *
     22 * @since BuddyPress (1.9.0)
     23 */
     24class BP_Notifications_Notification {
     25
     26        /**
     27         * The notification ID.
     28         *
     29         * @var int
     30         */
     31        public $id;
     32
     33        /**
     34         * The ID of the item associated with the notification.
     35         *
     36         * @var int
     37         */
     38        public $item_id;
     39
     40        /**
     41         * The ID of the secondary item associated with the notification.
     42         *
     43         * @var int
     44         */
     45        public $secondary_item_id = null;
     46
     47        /**
     48         * The ID of the user the notification is associated with.
     49         *
     50         * @var int
     51         */
     52        public $user_id;
     53
     54        /**
     55         * The name of the component that the notification is for.
     56         *
     57         * @var string
     58         */
     59        public $component_name;
     60
     61        /**
     62         * The component action which the notification is related to.
     63         *
     64         * @var string
     65         */
     66        public $component_action;
     67
     68        /**
     69         * The date the notification was created.
     70         *
     71         * @var string
     72         */
     73        public $date_notified;
     74
     75        /**
     76         * Is the notification new, or has it already been read.
     77         *
     78         * @var bool
     79         */
     80        public $is_new;
     81
     82        /** Public Methods ****************************************************/
     83
     84        /**
     85         * Constructor method.
     86         *
     87         * @since BuddyPress (1.9.0)
     88         *
     89         * @param int $id Optional. Provide an ID to access an existing
     90         *        notification item.
     91         */
     92        public function __construct( $id = 0 ) {
     93                if ( ! empty( $id ) ) {
     94                        $this->id = $id;
     95                        $this->populate();
     96                }
     97        }
     98
     99        /**
     100         * Update or insert notification details into the database.
     101         *
     102         * @since BuddyPress (1.9.0)
     103         *
     104         * @global wpdb $wpdb WordPress database object.
     105         *
     106         * @return bool True on success, false on failure.
     107         */
     108        public function save() {
     109
     110                // Return value
     111                $retval = false;
     112
     113                // Default data and format
     114                $data = array(
     115                        'user_id'           => $this->user_id,
     116                        'item_id'           => $this->item_id,
     117                        'secondary_item_id' => $this->secondary_item_id,
     118                        'component_name'    => $this->component_name,
     119                        'component_action'  => $this->component_action,
     120                        'date_notified'     => $this->date_notified,
     121                        'is_new'            => $this->is_new,
     122                );
     123                $data_format = array( '%d', '%d', '%d', '%s', '%s', '%s', '%d' );
     124
     125                // Update
     126                if ( ! empty( $this->id ) ) {
     127                        $result = self::_update( $data, array( 'ID' => $this->id ), $data_format, array( '%d' ) );
     128
     129                // Insert
     130                } else {
     131                        $result = self::_insert( $data, $data_format );
     132                }
     133
     134                // Set the notification ID if successful
     135                if ( ! empty( $result ) && ! is_wp_error( $result ) ) {
     136                        global $wpdb;
     137
     138                        $this->id = $wpdb->insert_id;
     139                        $retval   = $wpdb->insert_id;
     140                }
     141
     142                // Return the result
     143                return $retval;
     144        }
     145
     146        /**
     147         * Fetch data for an existing notification from the database.
     148         *
     149         * @since BuddyPress (1.9.0)
     150         *
     151         * @global BuddyPress $bp The one true BuddyPress instance.
     152         * @global wpdb $wpdb WordPress database object.
     153         */
     154        public function populate() {
     155                global $wpdb;
     156
     157                $bp = buddypress();
     158
     159                // Look for a notification
     160                $notification = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->notifications->table_name} WHERE id = %d", $this->id ) );
     161
     162                // Setup the notification data
     163                if ( ! empty( $notification ) && ! is_wp_error( $notification ) ) {
     164                        $this->item_id           = $notification->item_id;
     165                        $this->secondary_item_id = $notification->secondary_item_id;
     166                        $this->user_id           = $notification->user_id;
     167                        $this->component_name    = $notification->component_name;
     168                        $this->component_action  = $notification->component_action;
     169                        $this->date_notified     = $notification->date_notified;
     170                        $this->is_new            = $notification->is_new;
     171                }
     172        }
     173
     174        /** Protected Static Methods ******************************************/
     175
     176        /**
     177         * Create a notification entry.
     178         *
     179         * @since BuddyPress (1.9.0)
     180         *
     181         * @param array $data {
     182         *     Array of notification data, passed to {@link wpdb::insert()}.
     183         *     @type int $user_id ID of the associated user.
     184         *     @type int $item_id ID of the associated item.
     185         *     @type int $secondary_item_id ID of the secondary associated item.
     186         *     @type string $component_name Name of the associated component.
     187         *     @type string $component_action Name of the associated component
     188         *           action.
     189         *     @type string $date_notified Timestamp of the notification.
     190         *     @type bool $is_new True if the notification is unread, otherwise
     191         *           false.
     192         * }
     193         * @param array $data_format See {@link wpdb::insert()}.
     194         * @return int|false The number of rows inserted, or false on error.
     195         */
     196        protected static function _insert( $data = array(), $data_format = array() ) {
     197                global $wpdb;
     198                return $wpdb->insert( buddypress()->notifications->table_name, $data, $data_format );
     199        }
     200
     201        /**
     202         * Update notifications.
     203         *
     204         * @since BuddyPress (1.9.0)
     205         *
     206         * @see wpdb::update() for further description of paramater formats.
     207         *
     208         * @param array $data Array of notification data to update, passed to
     209         *        {@link wpdb::update()}. Accepts any property of a
     210         *        BP_Notification_Notification object.
     211         * @param array $where The WHERE params as passed to wpdb::update().
     212         *        Typically consists of array( 'ID' => $id ) to specify the ID
     213         *        of the item being updated. See {@link wpdb::update()}.
     214         * @param array $data_format See {@link wpdb::insert()}.
     215         * @param array $where_format See {@link wpdb::insert()}.
     216         * @return int|false The number of rows updated, or false on error.
     217         */
     218        protected static function _update( $data = array(), $where = array(), $data_format = array(), $where_format = array() ) {
     219                global $wpdb;
     220                return $wpdb->update( buddypress()->notifications->table_name, $data, $where, $data_format, $where_format );
     221        }
     222
     223        /**
     224         * Delete notifications.
     225         *
     226         * @since BuddyPress (1.9.0)
     227         *
     228         * @see wpdb::update() for further description of paramater formats.
     229         *
     230         * @param array $where Array of WHERE clauses to filter by, passed to
     231         *        {@link wpdb::delete()}. Accepts any property of a
     232         *        BP_Notification_Notification object.
     233         * @param array $where_format See {@link wpdb::insert()}.
     234         * @return int|false The number of rows updated, or false on error.
     235         */
     236        protected static function _delete( $where = array(), $where_format = array() ) {
     237                global $wpdb;
     238                return $wpdb->delete( buddypress()->notifications->table_name, $where, $where_format );
     239        }
     240
     241        /**
     242         * Assemble the WHERE clause of a get() SQL statement.
     243         *
     244         * Used by BP_Notifications_Notification::get() to create its WHERE
     245         * clause.
     246         *
     247         * @since BuddyPress (1.9.0)
     248         *
     249         * @param array $args See {@link BP_Notifications_Notification::get()}
     250         *        for more details.
     251         * @return string WHERE clause.
     252         */
     253        protected static function get_where_sql( $args = array() ) {
     254                global $wpdb;
     255
     256                $where_conditions = array();
     257
     258                // id
     259                if ( ! empty( $args['id'] ) ) {
     260                        $id_in = implode( ',', wp_parse_id_list( $args['id'] ) );
     261                        $where_conditions['id'] = "id IN ({$id_in})";
     262                }
     263
     264                // user_id
     265                if ( ! empty( $args['user_id'] ) ) {
     266                        $user_id_in = implode( ',', wp_parse_id_list( $args['user_id'] ) );
     267                        $where_conditions['user_id'] = "user_id IN ({$user_id_in})";
     268                }
     269
     270                // item_id
     271                if ( ! empty( $args['item_id'] ) ) {
     272                        $item_id_in = implode( ',', wp_parse_id_list( $args['item_id'] ) );
     273                        $where_conditions['item_id'] = "item_id IN ({$item_id_in})";
     274                }
     275
     276                // secondary_item_id
     277                if ( ! empty( $args['secondary_item_id'] ) ) {
     278                        $secondary_item_id_in = implode( ',', wp_parse_id_list( $args['secondary_item_id'] ) );
     279                        $where_conditions['secondary_item_id'] = "secondary_item_id IN ({$secondary_item_id_in})";
     280                }
     281
     282                // component_name
     283                if ( ! empty( $args['component_name'] ) ) {
     284                        if ( ! is_array( $args['component_name'] ) ) {
     285                                $component_names = explode( ',', $args['component_name'] );
     286                        } else {
     287                                $component_names = $args['component_name'];
     288                        }
     289
     290                        $cn_clean = array();
     291                        foreach ( $component_names as $cn ) {
     292                                $cn_clean[] = $wpdb->prepare( '%s', $cn );
     293                        }
     294
     295                        $cn_in = implode( ',', $cn_clean );
     296                        $where_conditions['component_name'] = "component_name IN ({$cn_in})";
     297                }
     298
     299                // component_action
     300                if ( ! empty( $args['component_action'] ) ) {
     301                        if ( ! is_array( $args['component_action'] ) ) {
     302                                $component_actions = explode( ',', $args['component_action'] );
     303                        } else {
     304                                $component_actions = $args['component_action'];
     305                        }
     306
     307                        $ca_clean = array();
     308                        foreach ( $component_actions as $ca ) {
     309                                $ca_clean[] = $wpdb->prepare( '%s', $ca );
     310                        }
     311
     312                        $ca_in = implode( ',', $ca_clean );
     313                        $where_conditions['component_action'] = "component_action IN ({$ca_in})";
     314                }
     315
     316                // is_new
     317                if ( ! empty( $args['is_new'] ) ) {
     318                        $where_conditions['is_new'] = "is_new = 1";
     319                }
     320
     321                // search_terms
     322                if ( ! empty( $args['search_terms'] ) ) {
     323                        $search_terms = like_escape( esc_sql( $args['search_terms'] ) );
     324                        $where_conditions['search_terms'] = "( component_name LIKE '%%$search_terms%%' OR component_action LIKE '%%$search_terms%%' )";
     325                }
     326
     327                if ( ! empty( $where_conditions ) ) {
     328                        $where = 'WHERE ' . implode( ' AND ', $where_conditions );
     329                } else {
     330                        $where = '';
     331                }
     332
     333                return $where;
     334        }
     335
     336        /**
     337         * Assemble query clauses, based on arrguments, to pass to $wpdb methods.
     338         *
     339         * The insert(), update(), and delete() methods of {@link wpdb} expect
     340         * arguments of the following forms:
     341         *
     342         * - associative arrays whose key/value pairs are column => value, to
     343         *   be used in WHERE, SET, or VALUES clauses
     344         * - arrays of "formats", which tell $wpdb->prepare() which type of
     345         *   value to expect when sanitizing (eg, array( '%s', '%d' ))
     346         *
     347         * This utility method can be used to assemble both kinds of params,
     348         * out of a single set of associative array arguments, such as:
     349         *
     350         *     $args = array(
     351         *         'user_id' => 4,
     352         *         'component_name' => 'groups',
     353         *     );
     354         *
     355         * This will be converted to:
     356         *
     357         *     array(
     358         *         'data' => array(
     359         *             'user_id' => 4,
     360         *             'component_name' => 'groups',
     361         *         ),
     362         *         'format' => array(
     363         *             '%d',
     364         *             '%s',
     365         *         ),
     366         *     )
     367         *
     368         * which can easily be passed as arguments to the $wpdb methods.
     369         *
     370         * @since BuddyPress (1.9.0)
     371         *
     372         * @param $args Associative array of filter arguments.
     373         *        See {@BP_Notifications_Notification::get()} for a breakdown.
     374         * @return array Associative array of 'data' and 'format' args.
     375         */
     376        protected static function get_query_clauses( $args = array() ) {
     377                $where_clauses = array(
     378                        'data'   => array(),
     379                        'format' => array(),
     380                );
     381
     382                // id
     383                if ( ! empty( $args['id'] ) ) {
     384                        $where_clauses['data']['id'] = absint( $args['id'] );
     385                        $where_clauses['format'][] = '%d';
     386                }
     387
     388                // user_id
     389                if ( ! empty( $args['user_id'] ) ) {
     390                        $where_clauses['data']['user_id'] = absint( $args['user_id'] );
     391                        $where_clauses['format'][] = '%d';
     392                }
     393
     394                // item_id
     395                if ( ! empty( $args['item_id'] ) ) {
     396                        $where_clauses['data']['item_id'] = absint( $args['item_id'] );
     397                        $where_clauses['format'][] = '%d';
     398                }
     399
     400                // secondary_item_id
     401                if ( ! empty( $args['secondary_item_id'] ) ) {
     402                        $where_clauses['data']['secondary_item_id'] = absint( $args['secondary_item_id'] );
     403                        $where_clauses['format'][] = '%d';
     404                }
     405
     406                // component_name
     407                if ( ! empty( $args['component_name'] ) ) {
     408                        $where_clauses['data']['component_name'] = $args['component_name'];
     409                        $where_clauses['format'][] = '%s';
     410                }
     411
     412                // component_action
     413                if ( ! empty( $args['component_action'] ) ) {
     414                        $where_clauses['data']['component_action'] = $args['component_action'];
     415                        $where_clauses['format'][] = '%s';
     416                }
     417
     418                // is_new
     419                if ( isset( $args['is_new'] ) ) {
     420                        $where_clauses['data']['is_new'] = ! empty( $args['is_new'] ) ? 1 : 0;
     421                        $where_clauses['format'][] = '%d';
     422                }
     423
     424                return $where_clauses;
     425        }
     426
     427        /** Public Static Methods *********************************************/
     428
     429        /**
     430         * Check that a specific notification is for a specific user.
     431         *
     432         * @since BuddyPress (1.9.0)
     433         *
     434         * @param int $user_id ID of the user being checked.
     435         * @param int $notification_id ID of the notification being checked.
     436         * @return bool True if the notification belongs to the user, otherwise
     437         *         false.
     438         */
     439        public static function check_access( $user_id, $notification_id ) {
     440                global $wpdb;
     441
     442                $bp = buddypress();
     443
     444                return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(id) FROM {$bp->core->table_name_notifications} WHERE id = %d AND user_id = %d", $notification_id, $user_id ) );
     445        }
     446
     447        /**
     448         * Get notifications, based on provided filter parameters.
     449         *
     450         * @since BuddyPress (1.9.0)
     451         *
     452         * @param array $args {
     453         *     Associative array of arguments. All arguments but $page and
     454         *     $per_page can be treated as filter values for get_where_sql()
     455         *     and get_query_clauses(). All items are optional.
     456         *     @type int|array $id ID of notification being updated. Can be an
     457         *           array of IDs.
     458         *     @type int|array $user_id ID of user being queried. Can be an
     459         *           array of user IDs.
     460         *     @type int|array $item_id ID of associated item. Can be an array
     461         *           of multiple item IDs.
     462         *     @type int|array $secondary_item_id ID of secondary associated
     463         *           item. Can be an array of multiple IDs.
     464         *     @type string|array $component_name Name of the component to
     465         *           filter by. Can be an array of component names.
     466         *     @type string|array $component_action Name of the action to
     467         *           filter by. Can be an array of actions.
     468         *     @type bool $is_new Whether to limit the query to is_new (unread)
     469         *           notifications. Default: true.
     470         *     @type string $search_terms Term to match against component_name
     471         *           or component_action fields.
     472         *     @type int $page Number of the current page of results. Default:
     473         *           false (no pagination - all items).
     474         *     @type int $per_page Number of items to show per page. Default:
     475         *           false (no pagination - all items).
     476         * }
     477         * @return array Located notifications.
     478         */
     479        public static function get( $args = array() ) {
     480                global $wpdb;
     481
     482                $r = wp_parse_args( $args, array(
     483                        'id'                => false,
     484                        'user_id'           => false,
     485                        'item_id'           => false,
     486                        'secondary_item_id' => false,
     487                        'component_name'    => false,
     488                        'component_action'  => false,
     489                        'is_new'            => true,
     490                        'search_terms'      => '',
     491                        'page'              => false,
     492                        'per_page'          => false,
     493                ) );
     494
     495                $bp = buddypress();
     496
     497                $select_sql = "SELECT *";
     498                $from_sql   = "FROM {$bp->notifications->table_name}";
     499
     500                $where_args = array(
     501                        'id'                => $r['id'],
     502                        'user_id'           => $r['user_id'],
     503                        'item_id'           => $r['item_id'],
     504                        'secondary_item_id' => $r['secondary_item_id'],
     505                        'component_name'    => $r['component_name'],
     506                        'component_action'  => $r['component_action'],
     507                        'is_new'            => $r['is_new'],
     508                        'search_terms'      => $r['search_terms'],
     509                );
     510
     511                $where_sql = self::get_where_sql( $where_args );
     512
     513                $pag_sql = '';
     514                if ( ! empty( $r['page'] ) && ! empty( $r['per_page'] ) ) {
     515                        $page     = absint( $r['page'] );
     516                        $per_page = absint( $r['per_page'] );
     517                        $offset   = $per_page * ( $page - 1 );
     518                        $pag_sql = $wpdb->prepare( "LIMIT %d, %d", $offset, $per_page );
     519                }
     520
     521                $sql = "{$select_sql} {$from_sql} {$where_sql} {$pag_sql}";
     522
     523                return $wpdb->get_results( $sql );
     524        }
     525
     526        /**
     527         * Get a count of total notifications matching a set of arguments.
     528         *
     529         * @since BuddyPress (1.9.0)
     530         *
     531         * @see BP_Notifications_Notification::get() for a description of
     532         *      arguments.
     533         *
     534         * @param array $args See {@link BP_Notifications_Notification::get()}.
     535         * @return int Count of located items.
     536         */
     537        public static function get_total_count( $args ) {
     538                global $wpdb;
     539
     540                $bp = buddypress();
     541
     542                $select_sql = "SELECT COUNT(*)";
     543                $from_sql   = "FROM {$bp->notifications->table_name}";
     544                $where_sql  = self::get_where_sql( $args );
     545
     546                $sql = "{$select_sql} {$from_sql} {$where_sql}";
     547
     548                return $wpdb->get_var( $sql );
     549        }
     550
     551        /**
     552         * Update notifications.
     553         *
     554         * @since BuddyPress (1.9.0)
     555         *
     556         * @see BP_Notifications_Notification::get() for a description of
     557         *      accepted update/where arguments.
     558         *
     559         * @param array $update_args Associative array of fields to update,
     560         *        and the values to update them to. Of the format
     561         *            array( 'user_id' => 4, 'component_name' => 'groups', )
     562         * @param array $where_args Associative array of columns/values, to
     563         *        determine which rows should be updated. Of the format
     564         *            array( 'item_id' => 7, 'component_action' => 'members', )
     565         * @return int|bool Number of rows updated on success, false on failure.
     566         */
     567        public static function update( $update_args = array(), $where_args = array() ) {
     568                $update = self::get_query_clauses( $update_args );
     569                $where  = self::get_query_clauses( $where_args );
     570
     571                return self::_update( $update['data'], $where['data'], $update['format'], $where['format'] );
     572        }
     573
     574        /**
     575         * Delete notifications.
     576         *
     577         * @since BuddyPress (1.9.0)
     578         *
     579         * @see BP_Notifications_Notification::get() for a description of
     580         *      accepted update/where arguments.
     581         *
     582         * @param array $args Associative array of columns/values, to determine
     583         *        which rows should be deleted.  Of the format
     584         *            array( 'item_id' => 7, 'component_action' => 'members', )
     585         * @return int|bool Number of rows deleted on success, false on failure.
     586         */
     587        public static function delete( $args = array() ) {
     588                $where = self::get_query_clauses( $args );
     589
     590                return self::_delete( $where['data'], $where['format'] );
     591        }
     592
     593
     594        /** Convenience methods **********************************************/
     595
     596        /**
     597         * Delete a single notification by ID.
     598         *
     599         * @since BuddyPress (1.9.0)
     600         *
     601         * @see BP_Notifications_Notification::delete() for explanation of
     602         *      return value.
     603         *
     604         * @param int $id ID of the notification item to be deleted.
     605         * @return bool True on success, false on failure.
     606         */
     607        public static function delete_by_id( $id ) {
     608                return self::delete( array(
     609                        'id' => $id,
     610                ) );
     611        }
     612
     613        /**
     614         * Fetch all the notifications in the database for a specific user.
     615         *
     616         * @since BuddyPress (1.9.0)
     617         *
     618         * @param int $user_id ID of the user whose notifications are being
     619         *        fetched.
     620         * @param string $status Optional. Status of notifications to fetch.
     621         *        'is_new' to get only unread items, 'all' to get all.
     622         * @return array Associative array of notification items.
     623         */
     624        public static function get_all_for_user( $user_id, $status = 'is_new' ) {
     625                $args = array(
     626                        'user_id' => $user_id,
     627                        'is_new'  => 'is_new' === $status,
     628                );
     629                return self::get( $args );
     630        }
     631
     632        /**
     633         * Fetch all the unread notifications in the database for a specific user.
     634         *
     635         * @since BuddyPress (1.9.0)
     636         *
     637         * @param int $user_id ID of the user whose notifications are being
     638         *        fetched.
     639         * @return array Associative array of unread notification items.
     640         */
     641        public static function get_unread_for_user( $user_id = 0 ) {
     642                $args = array(
     643                        'user_id' => $user_id,
     644                        'is_new'  => true,
     645                );
     646                return self::get( $args );
     647        }
     648
     649        /**
     650         * Fetch all the read notifications in the database for a specific user.
     651         *
     652         * @since BuddyPress (1.9.0)
     653         *
     654         * @param int $user_id ID of the user whose notifications are being
     655         *        fetched.
     656         * @return array Associative array of unread notification items.
     657         */
     658        public static function get_read_for_user( $user_id = 0 ) {
     659                $args = array(
     660                        'user_id' => $user_id,
     661                        'is_new'  => false,
     662                );
     663                return self::get( $args );
     664        }
     665
     666        /**
     667         * Get unread notifications for a user, in a pagination-friendly format.
     668         *
     669         * @since BuddyPress (1.9.0)
     670         *
     671         * @param array $args {
     672         *     Array of arguments.
     673         *     @type int $user_id ID of the user for whom the notifications are
     674         *           being fetched. Default: logged-in user ID.
     675         *     @type bool $is_new Whether to limit the query to unread
     676         *           notifications. Default: true.
     677         *     @type int $page Number of the page to return. Default: 1.
     678         *     @type int $per_page Number of results to display per page.
     679         *           Default: 10.
     680         *     @type string $search_terms Optional. A term to search against in
     681         *           the 'component_name' and 'component_action' columns.
     682         * }
     683         * @return array {
     684         *     @type array $notifications Array of notification results.
     685         *     @type int $total Count of all located notifications matching
     686         *           the query params.
     687         * }
     688         */
     689        public static function get_current_notifications_for_user( $args = array() ) {
     690                $r = wp_parse_args( $args, array(
     691                        'user_id'      => bp_loggedin_user_id(),
     692                        'is_new'       => true,
     693                        'page'         => 1,
     694                        'per_page'     => 10,
     695                        'search_terms' => '',
     696                ) );
     697
     698                $notifications = self::get( $r );
     699
     700                // Bail if no notifications
     701                if ( empty( $notifications ) ) {
     702                        return false;
     703                }
     704
     705                $total_count = self::get_total_count( $r );
     706
     707                return array( 'notifications' => &$notifications, 'total' => $total_count );
     708        }
     709
     710        /** Mark Read *************************************************************/
     711
     712        /**
     713         * Mark all user notifications as read.
     714         *
     715         * @since BuddyPress (1.9.0)
     716         *
     717         * @param int $user_id The ID of the user who the notifications
     718         *        are for.
     719         * @param int $is_new Mark as read (1) or unread (0).
     720         */
     721        public static function mark_all_for_user( $user_id, $is_new = 0, $item_id = 0, $component_name = '', $component_action = '', $secondary_item_id = 0 ) {
     722
     723                // Values to be updated
     724                $update_args = array(
     725                        'is_new' => $is_new,
     726                );
     727
     728                // WHERE clauses
     729                $where_args = array(
     730                        'user_id' => $user_id,
     731                );
     732
     733                if ( $component_name ) {
     734                        $where_args['component_name'] = $component_name;
     735                }
     736
     737                if ( $component_action ) {
     738                        $where_args['component_action'] = $component_action;
     739                }
     740
     741                if ( $secondary_item_id ) {
     742                        $where_args['secondary_item_id'] = $secondary_item_id;
     743                }
     744
     745                return self::update( $update_args, $where_args );
     746        }
     747
     748        /**
     749         * Mark all notifications from a user as read.
     750         *
     751         * @since BuddyPress (1.9.0)
     752         *
     753         * @param int $user_id The ID of the user who the notifications are from.
     754         * @param int $is_new Mark as read (1) or unread (0).
     755         */
     756        public static function mark_all_from_user( $user_id, $is_new = 0, $component_name = '', $component_action = '', $secondary_item_id = 0 ) {
     757
     758                // Values to be updated
     759                $update_args = array(
     760                        'is_new' => $is_new,
     761                );
     762
     763                // WHERE clauses
     764                $where_args = array(
     765                        'item_id' => $user_id,
     766                );
     767
     768                if ( $component_name ) {
     769                        $where_args['component_name'] = $component_name;
     770                }
     771
     772                if ( $component_action ) {
     773                        $where_args['component_action'] = $component_action;
     774                }
     775
     776                if ( $secondary_item_id ) {
     777                        $where_args['secondary_item_id'] = $secondary_item_id;
     778                }
     779
     780                return self::update( $update_args, $where_args );
     781        }
     782
     783        /**
     784         * Mark all notifications for all users as read by item id, and optional
     785         * secondary item id, and component name and action.
     786         *
     787         * @since BuddyPress (1.9.0)
     788         *
     789         * @param int $item_id The ID of the item associated with the
     790         *        notifications.
     791         * @param string $component_name The component that the notifications
     792         *        are associated with.
     793         * @param string $component_action The action that the notifications
     794         *        are associated with.
     795         * @param string $secondary_item_id Optional. ID of the secondary
     796         *        associated item.
     797         */
     798        public static function mark_all_by_type( $item_id, $is_new = 0, $component_name = '', $component_action = '', $secondary_item_id = 0 ) {
     799
     800                // Values to be updated
     801                $update_args = array(
     802                        'is_new' => $is_new,
     803                );
     804
     805                // WHERE clauses
     806                $where_args = array(
     807                        'item_id' => $item_id,
     808                );
     809
     810                if ( $component_name ) {
     811                        $where_args['component_name'] = $component_name;
     812                }
     813
     814                if ( $component_action ) {
     815                        $where_args['component_action'] = $component_action;
     816                }
     817
     818                if ( $secondary_item_id ) {
     819                        $where_args['secondary_item_id'] = $secondary_item_id;
     820                }
     821
     822                return self::update( $update_args, $where_args );
     823        }
     824}
  • new file p-notifications/bp-notifications-functions.php

    diff --git bp-notifications/bp-notifications-functions.php bp-notifications/bp-notifications-functions.php
    new file mode 100644
    index 0000000..526a9c7
    - +  
     1<?php
     2
     3/**
     4 * BuddyPress Member Notifications Functions.
     5 *
     6 * Functions and filters used in the Notifications component.
     7 *
     8 * @package BuddyPress
     9 * @subpackage NotificationsFunctions
     10 */
     11
     12// Exit if accessed directly
     13if ( !defined( 'ABSPATH' ) ) exit;
     14
     15/**
     16 * Add a notification for a specific user, from a specific component.
     17 *
     18 * @since BuddyPress (1.9.0)
     19 *
     20 * @param array $args {
     21 *     Array of arguments describing the notification. All are optional.
     22 *     @type int $user_id ID of the user to associate the notificiton with.
     23 *     @type int $item_id ID of the item to associate the notification with.
     24 *     @type int $secondary_item_id ID of the secondary item to associate the
     25 *           notification with.
     26 *     @type string $component_name Name of the component to associate the
     27 *           notification with.
     28 *     @type string $component_action Name of the action to associate the
     29 *           notification with.
     30 *     @type string $date_notified Timestamp for the notification.
     31 * }
     32 * @return int|bool ID of the newly created notification on success, false
     33 *         on failure.
     34 */
     35function bp_notifications_add_notification( $args = array() ) {
     36
     37        $r = wp_parse_args( $args, array(
     38                'user_id'           => 0,
     39                'item_id'           => 0,
     40                'secondary_item_id' => 0,
     41                'component_name'    => '',
     42                'component_action'  => '',
     43                'date_notified'     => bp_core_current_time(),
     44        ) );
     45
     46        // Setup the new notification
     47        $notification                    = new BP_Notifications_Notification;
     48        $notification->user_id           = $r['user_id'];
     49        $notification->item_id           = $r['item_id'];
     50        $notification->secondary_item_id = $r['secondary_item_id'];
     51        $notification->component_name    = $r['component_name'];
     52        $notification->component_action  = $r['component_action'];
     53        $notification->date_notified     = $r['date_notified'];
     54        $notification->is_new            = 1;
     55
     56        // Save the new notification
     57        return $notification->save();
     58}
     59
     60/**
     61 * Get a specific notification by its ID.
     62 *
     63 * @since BuddyPress (1.9.0)
     64 *
     65 * @param int $id ID of the notification.
     66 * @return BP_Notifications_Notification
     67 */
     68function bp_notifications_get_notification( $id ) {
     69        return new BP_Notifications_Notification( $id );
     70}
     71
     72/**
     73 * Delete a specific notification by its ID.
     74 *
     75 * @since BuddyPress (1.9.0)
     76 *
     77 * @param int $id ID of the notification to delete.
     78 * @return bool True on success, false on failure.
     79 */
     80function bp_notifications_delete_notification( $id ) {
     81        if ( ! bp_notifications_check_notification_access( bp_loggedin_user_id(), $id ) ) {
     82                return false;
     83        }
     84
     85        return BP_Notifications_Notification::delete( $id );
     86}
     87
     88/**
     89 * Get notifications for a specific user.
     90 *
     91 * @since BuddyPress (1.9.0)
     92 *
     93 * @param int $user_id ID of the user whose notification are being fetched.
     94 * @param string $format Format of the returned values. 'simple' returns HTML,
     95 *        while 'object' returns a structured object for parsing.
     96 * @return mixed Object or array on success, false on failure.
     97 */
     98function bp_notifications_get_notifications_for_user( $user_id, $format = 'simple' ) {
     99
     100        // Setup local variables
     101        $bp                    = buddypress();
     102        $notifications         = BP_Notifications_Notification::get( array(
     103                'user_id' => $user_id,
     104        ) );
     105        $grouped_notifications = array(); // Notification groups
     106        $renderable            = array(); // Renderable notifications
     107
     108        // Group notifications by component and component_action and provide totals
     109        for ( $i = 0, $count = count( $notifications ); $i < $count; ++$i ) {
     110                $notification = $notifications[$i];
     111                $grouped_notifications[$notification->component_name][$notification->component_action][] = $notification;
     112        }
     113
     114        // Bail if no notification groups
     115        if ( empty( $grouped_notifications ) ) {
     116                return false;
     117        }
     118
     119        // Calculate a renderable output for each notification type
     120        foreach ( $grouped_notifications as $component_name => $action_arrays ) {
     121
     122                // Skip if group is empty
     123                if ( empty( $action_arrays ) ) {
     124                        continue;
     125                }
     126
     127                // Skip inactive components
     128                if ( ! bp_is_active( $component_name ) ) {
     129                        continue;
     130                }
     131
     132                // Loop through each actionable item and try to map it to a component
     133                foreach ( (array) $action_arrays as $component_action_name => $component_action_items ) {
     134
     135                        // Get the number of actionable items
     136                        $action_item_count = count( $component_action_items );
     137
     138                        // Skip if the count is less than 1
     139                        if ( $action_item_count < 1 ) {
     140                                continue;
     141                        }
     142
     143                        // Callback function exists
     144                        if ( isset( $bp->{$component_name}->notification_callback ) && is_callable( $bp->{$component_name}->notification_callback ) ) {
     145
     146                                // Function should return an object
     147                                if ( 'object' == $format ) {
     148
     149                                        // Retrieve the content of the notification using the callback
     150                                        $content = call_user_func(
     151                                                $bp->{$component_name}->notification_callback,
     152                                                $component_action_name,
     153                                                $component_action_items[0]->item_id,
     154                                                $component_action_items[0]->secondary_item_id,
     155                                                $action_item_count,
     156                                                'array'
     157                                        );
     158
     159                                        // Create the object to be returned
     160                                        $notification_object = new stdClass;
     161
     162                                        // Minimal backpat with non-compatible notification
     163                                        // callback functions
     164                                        if ( is_string( $content ) ) {
     165                                                $notification_object->content = $content;
     166                                                $notification_object->href    = bp_loggedin_user_domain();
     167                                        } else {
     168                                                $notification_object->content = $content['text'];
     169                                                $notification_object->href    = $content['link'];
     170                                        }
     171
     172                                        $notification_object->id = $component_action_items[0]->id;
     173                                        $renderable[]            = $notification_object;
     174
     175                                // Return an array of content strings
     176                                } else {
     177                                        $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 );
     178                                        $renderable[] = $content;
     179                                }
     180
     181                        // @deprecated format_notification_function - 1.5
     182                        } elseif ( isset( $bp->{$component_name}->format_notification_function ) && function_exists( $bp->{$component_name}->format_notification_function ) ) {
     183                                $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 );
     184                        }
     185                }
     186        }
     187
     188        // If renderable is empty array, set to false
     189        if ( empty( $renderable ) ) {
     190                $renderable = false;
     191        }
     192
     193        // Filter and return
     194        return apply_filters( 'bp_core_get_notifications_for_user', $renderable, $user_id, $format );
     195}
     196
     197/**
     198 * Delete notifications for a user by type.
     199 *
     200 * Used when clearing out notifications for a specific component when the user
     201 * has visited that component.
     202 *
     203 * @since BuddyPress (1.9.0)
     204 *
     205 * @param int $user_id ID of the user whose notifications are being deleted.
     206 * @param string $component_name Name of the associated component.
     207 * @param string $component_action Name of the associated action.
     208 * @return bool True on success, false on failure.
     209 */
     210function bp_notifications_delete_notifications_by_type( $user_id, $component_name, $component_action ) {
     211        return BP_Notifications_Notification::delete( array(
     212                'user_id'          => $user_id,
     213                'component_name'   => $component_name,
     214                'component_action' => $component_action,
     215        ) );
     216}
     217
     218/**
     219 * Delete notifications for an item ID.
     220 *
     221 * Used when clearing out notifications for a specific component when the user
     222 * has visited that component.
     223 *
     224 * @since BuddyPress (1.9.0)
     225 *
     226 * @param int $user_id ID of the user whose notifications are being deleted.
     227 * @param int $item_id ID of the associated item.
     228 * @param string $component_name Name of the associated component.
     229 * @param string $component_action Name of the associated action.
     230 * @param int $secondary_item_id ID of the secondary associated item.
     231 * @return bool True on success, false on failure.
     232 */
     233function bp_notifications_delete_notifications_by_item_id( $user_id, $item_id, $component_name, $component_action, $secondary_item_id = false ) {
     234        return BP_Notifications_Notification::delete( array(
     235                'user_id'           => $user_id,
     236                'item_id'           => $item_id,
     237                'secondary_item_id' => $secondary_item_id,
     238                'component_name'    => $component_name,
     239                'component_action'  => $component_action,
     240        ) );
     241}
     242
     243/**
     244 * Delete all notifications by type.
     245 *
     246 * Used when clearing out notifications for an entire component.
     247 *
     248 * @since BuddyPress (1.9.0)
     249 *
     250 * @param int $user_id ID of the user whose notifications are being deleted.
     251 * @param string $component_name Name of the associated component.
     252 * @param string $component_action Optional. Name of the associated action.
     253 * @param int $secondary_item_id Optional. ID of the secondary associated item.
     254 * @return bool True on success, false on failure.
     255 */
     256function bp_notifications_delete_all_notifications_by_type( $item_id, $component_name, $component_action = false, $secondary_item_id = false ) {
     257        return BP_Notifications_Notification::delete( array(
     258                'item_id'           => $item_id,
     259                'secondary_item_id' => $secondary_item_id,
     260                'component_name'    => $component_name,
     261                'component_action'  => $component_action,
     262        ) );
     263}
     264
     265/**
     266 * Delete all notifications from a user.
     267 *
     268 * Used when clearing out all notifications for a user, when deleted or spammed.
     269 *
     270 * @todo This function assumes that items with the user_id in the item_id slot
     271 *       are associated with that user. However, this will only be true with
     272 *       certain components (such as Friends). Use with caution!
     273 *
     274 * @since BuddyPress (1.9.0)
     275 *
     276 * @param int $user_id ID of the user whose associated items are beind deleted.
     277 * @param string $component_name Name of the associated component.
     278 * @param string $component_action Name of the associated action.
     279 * @return bool True on success, false on failure.
     280 */
     281function bp_notifications_delete_notifications_from_user( $user_id, $component_name, $component_action ) {
     282        return BP_Notifications_Notification::delete( array(
     283                'item_id'           => $user_id,
     284                'component_name'    => $component_name,
     285                'component_action'  => $component_action,
     286        ) );
     287}
     288
     289/**
     290 * Check if a user has access to a specific notification.
     291 *
     292 * Used before deleting a notification for a user.
     293 *
     294 * @since BuddyPress (1.9.0)
     295 *
     296 * @param int $user_id ID of the user being checked.
     297 * @param int $notification_id ID of the notification being checked.
     298 * @return bool True if the notification belongs to the user, otherwise false.
     299 */
     300function bp_notifications_check_notification_access( $user_id, $notification_id ) {
     301        return (bool) BP_Notifications_Notification::check_access( $user_id, $notification_id );
     302}
     303
     304/**
     305 * Get a count of unread notification items for a user.
     306 *
     307 * @since BuddyPress (1.9.0)
     308 *
     309 * @param int $user_id ID of the user whose unread notifications are being
     310 *        counted.
     311 * @return int Unread notification count.
     312 */
     313function bp_notifications_get_unread_notification_count( $user_id = 0 ) {
     314
     315        // Default to displayed user if no ID is passed
     316        if ( empty( $user_id ) ) {
     317                $user_id = ( bp_displayed_user_id() ) ? bp_displayed_user_id() : bp_loggedin_user_id();
     318        }
     319
     320        // Get the notifications, and count them
     321        $notifications = BP_Notifications_Notification::get( array(
     322                'user_id' => $user_id,
     323        ) );
     324
     325        $count = ! empty( $notifications ) ? count( $notifications ) : 0;
     326
     327        return apply_filters( 'bp_notifications_get_total_notification_count', $count );
     328}
  • new file p-notifications/bp-notifications-loader.php

    diff --git bp-notifications/bp-notifications-loader.php bp-notifications/bp-notifications-loader.php
    new file mode 100644
    index 0000000..7a4db06
    - +  
     1<?php
     2
     3/**
     4 * BuddyPress Member Notifications Loader.
     5 *
     6 * Initializes the Notifications component.
     7 *
     8 * @package BuddyPress
     9 * @subpackage NotificationsLoader
     10 * @since BuddyPress (1.9.0)
     11 */
     12
     13// Exit if accessed directly
     14if ( !defined( 'ABSPATH' ) ) exit;
     15
     16class BP_Notifications_Component extends BP_Component {
     17
     18        /**
     19         * Start the notifications component creation process.
     20         *
     21         * @since BuddyPress (1.9.0)
     22         */
     23        function __construct() {
     24                parent::start(
     25                        'notifications',
     26                        __( 'Notifications', 'buddypress' ),
     27                        BP_PLUGIN_DIR,
     28                        array(
     29                                'adminbar_myaccount_order' => 100
     30                        )
     31                );
     32        }
     33
     34        /**
     35         * Include notifications component files.
     36         *
     37         * @since BuddyPress (1.9.0)
     38         *
     39         * @see BP_Component::includes() for a description of arguments.
     40         *
     41         * @param array $includes See BP_Component::includes() for a description.
     42         */
     43        public function includes( $includes = array() ) {
     44                $includes = array(
     45                        'classes',
     46                        'screens',
     47                        'adminbar',
     48                        'buddybar',
     49                        'template',
     50                        'functions',
     51                );
     52
     53                parent::includes( $includes );
     54        }
     55
     56        /**
     57         * Setup globals
     58         *
     59         * The BP_FRIENDS_SLUG constant is deprecated, and only used here for
     60         * backwards compatibility.
     61         *
     62         * @since BuddyPress (1.9.0)
     63         *
     64         * @see BP_Component::setup_globals() for a description of arguments.
     65         *
     66         * @param array $args See BP_Component::setup_globals() for a description.
     67         */
     68        public function setup_globals( $args = array() ) {
     69                // Define a slug, if necessary
     70                if ( !defined( 'BP_NOTIFICATIONS_SLUG' ) ) {
     71                        define( 'BP_NOTIFICATIONS_SLUG', $this->id );
     72                }
     73
     74                // Global tables for the notifications component
     75                $global_tables = array(
     76                        'table_name' => bp_core_get_table_prefix() . 'bp_notifications'
     77                );
     78
     79                // All globals for the notifications component.
     80                // Note that global_tables is included in this array.
     81                $args = array(
     82                        'slug'          => BP_NOTIFICATIONS_SLUG,
     83                        'has_directory' => false,
     84                        'search_string' => __( 'Search Notifications...', 'buddypress' ),
     85                        'global_tables' => $global_tables,
     86                );
     87
     88                parent::setup_globals( $args );
     89        }
     90
     91        /**
     92         * Set up component navigation.
     93         *
     94         * @since BuddyPress (1.9.0)
     95         *
     96         * @see BP_Component::setup_nav() for a description of arguments.
     97         *
     98         * @param array $main_nav Optional. See BP_Component::setup_nav() for
     99         *        description.
     100         * @param array $sub_nav Optional. See BP_Component::setup_nav() for
     101         *        description.
     102         */
     103        public function setup_nav( $main_nav = array(), $sub_nav = array() ) {
     104
     105                // Add 'Notifications' to the main navigation
     106                $count    = bp_notifications_get_unread_notification_count( bp_loggedin_user_id() );
     107                $main_nav = array(
     108                        'name'                => sprintf( __( 'Notifications <span>%d</span>', 'buddypress' ), number_format_i18n( $count ) ),
     109                        'slug'                => $this->slug,
     110                        'position'            => 60,
     111                        'screen_function'     => 'bp_notifications_screen_unread',
     112                        'default_subnav_slug' => 'unread',
     113                        'item_css_id'         => $this->id,
     114                );
     115
     116                // Determine user to use
     117                if ( bp_displayed_user_domain() ) {
     118                        $user_domain = bp_displayed_user_domain();
     119                } elseif ( bp_loggedin_user_domain() ) {
     120                        $user_domain = bp_loggedin_user_domain();
     121                } else {
     122                        return;
     123                }
     124
     125                $notifications_link = trailingslashit( $user_domain . bp_get_notifications_slug() );
     126
     127                // Add the subnav items to the notifications nav item
     128                $sub_nav[] = array(
     129                        'name'            => __( 'Unread', 'buddypress' ),
     130                        'slug'            => 'unread',
     131                        'parent_url'      => $notifications_link,
     132                        'parent_slug'     => bp_get_notifications_slug(),
     133                        'screen_function' => 'bp_notifications_screen_unread',
     134                        'position'        => 10,
     135                        'item_css_id'     => 'notifications-my-notifications',
     136                );
     137
     138                $sub_nav[] = array(
     139                        'name'            => __( 'Read',   'buddypress' ),
     140                        'slug'            => 'read',
     141                        'parent_url'      => $notifications_link,
     142                        'parent_slug'     => bp_get_notifications_slug(),
     143                        'screen_function' => 'bp_notifications_screen_read',
     144                        'position'        => 20,
     145                        'user_has_access' => bp_core_can_edit_settings(),
     146                );
     147
     148                parent::setup_nav( $main_nav, $sub_nav );
     149        }
     150
     151        /**
     152         * Set up the component entries in the WordPress Admin Bar.
     153         *
     154         * @since BuddyPress (1.9.0)
     155         *
     156         * @see BP_Component::setup_nav() for a description of the $wp_admin_nav
     157         *      parameter array.
     158         *
     159         * @param array $wp_admin_nav See BP_Component::setup_admin_bar() for a
     160         *        description.
     161         */
     162        public function setup_admin_bar( $wp_admin_nav = array() ) {
     163
     164                // Menus for logged in user
     165                if ( is_user_logged_in() ) {
     166
     167                        // Setup the logged in user variables
     168                        $notifications_link = trailingslashit( bp_loggedin_user_domain() . $this->slug );
     169
     170                        // Pending notification requests
     171                        $count = bp_notifications_get_unread_notification_count( bp_loggedin_user_id() );
     172                        if ( ! empty( $count ) ) {
     173                                $unread = sprintf( __( 'Notifications <span class="count">%s</span>', 'buddypress' ), number_format_i18n( $count ) );
     174                        } else {
     175                                $unread = __( 'Notifications', 'buddypress' );
     176                        }
     177
     178                        // Add the "My Account" sub menus
     179                        $wp_admin_nav[] = array(
     180                                'parent' => buddypress()->my_account_menu_id,
     181                                'id'     => 'my-account-' . $this->id,
     182                                'title'  => $unread,
     183                                'href'   => trailingslashit( $notifications_link ),
     184                        );
     185
     186                        // Unread
     187                        $wp_admin_nav[] = array(
     188                                'parent' => 'my-account-' . $this->id,
     189                                'id'     => 'my-account-' . $this->id . '-unread',
     190                                'title'  => __( 'Unread', 'buddypress' ),
     191                                'href'   => trailingslashit( $notifications_link ),
     192                        );
     193
     194                        // Read
     195                        $wp_admin_nav[] = array(
     196                                'parent' => 'my-account-' . $this->id,
     197                                'id'     => 'my-account-' . $this->id . '-read',
     198                                'title'  => __( 'Read', 'buddypress' ),
     199                                'href'   => trailingslashit( $notifications_link . 'read' ),
     200                        );
     201                }
     202
     203                parent::setup_admin_bar( $wp_admin_nav );
     204        }
     205
     206        /**
     207         * Set up the title for pages and <title>.
     208         *
     209         * @since BuddyPress (1.9.0)
     210         */
     211        function setup_title() {
     212                $bp = buddypress();
     213
     214                // Adjust title
     215                if ( bp_is_notifications_component() ) {
     216                        if ( bp_is_my_profile() ) {
     217                                $bp->bp_options_title = __( 'Notifications', 'buddypress' );
     218                        } else {
     219                                $bp->bp_options_avatar = bp_core_fetch_avatar( array(
     220                                        'item_id' => bp_displayed_user_id(),
     221                                        'type'    => 'thumb',
     222                                        'alt'     => sprintf( __( 'Profile picture of %s', 'buddypress' ), bp_get_displayed_user_fullname() )
     223                                ) );
     224                                $bp->bp_options_title = bp_get_displayed_user_fullname();
     225                        }
     226                }
     227
     228                parent::setup_title();
     229        }
     230}
     231
     232/**
     233 * Bootstrap the Notifications component.
     234 *
     235 * @since BuddyPress (1.9.0)
     236 */
     237function bp_setup_notifications() {
     238        buddypress()->notifications = new BP_Notifications_Component();
     239}
     240add_action( 'bp_setup_components', 'bp_setup_notifications', 6 );
  • new file p-notifications/bp-notifications-screens.php

    diff --git bp-notifications/bp-notifications-screens.php bp-notifications/bp-notifications-screens.php
    new file mode 100644
    index 0000000..cb65c88
    - +  
     1<?php
     2
     3/**
     4 * BuddyPress Notifications Screen Functions.
     5 *
     6 * Screen functions are the controllers of BuddyPress. They will execute when
     7 * their specific URL is caught. They will first save or manipulate data using
     8 * business functions, then pass on the user to a template file.
     9 *
     10 * @package BuddyPress
     11 * @subpackage NotificationsScreens
     12 */
     13
     14// Exit if accessed directly
     15if ( ! defined( 'ABSPATH' ) ) exit;
     16
     17/**
     18 * Catch and route the 'unread' notifications screen.
     19 *
     20 * @since BuddyPress (1.9.0)
     21 */
     22function bp_notifications_screen_unread() {
     23        do_action( 'bp_notifications_screen_unread' );
     24
     25        bp_core_load_template( apply_filters( 'bp_notifications_template_unread', 'members/single/home' ) );
     26}
     27
     28/**
     29 * Catch and route the 'read' notifications screen.
     30 *
     31 * @since BuddyPress (1.9.0)
     32 */
     33function bp_notifications_screen_read() {
     34        do_action( 'bp_notifications_screen_read' );
     35
     36        bp_core_load_template( apply_filters( 'bp_notifications_template_read', 'members/single/home' ) );
     37}
     38
     39/**
     40 * Catch and route the 'settings' notifications screen.
     41 *
     42 * @since BuddyPress (1.9.0)
     43 */
     44function bp_notifications_screen_settings() {
     45
     46}
  • new file p-notifications/bp-notifications-template.php

    diff --git bp-notifications/bp-notifications-template.php bp-notifications/bp-notifications-template.php
    new file mode 100644
    index 0000000..41e688f
    - +  
     1<?php
     2
     3/**
     4 * BuddyPress Notifications Template Functions
     5 *
     6 * @package BuddyPress
     7 * @subpackage TonificationsTemplate
     8 */
     9
     10// Exit if accessed directly
     11if ( !defined( 'ABSPATH' ) ) exit;
     12
     13/**
     14 * Output the notifications component slug.
     15 *
     16 * @since BuddyPress (1.9.0)
     17 */
     18function bp_notifications_slug() {
     19        echo bp_get_notifications_slug();
     20}
     21        /**
     22         * Return the notifications component slug.
     23         *
     24         * @since BuddyPress (1.9.0)
     25         *
     26         * @return string Slug of the Notifications component.
     27         */
     28        function bp_get_notifications_slug() {
     29                return apply_filters( 'bp_get_notifications_slug', buddypress()->notifications->slug );
     30        }
     31
     32/** Main Loop *****************************************************************/
     33
     34/**
     35 * The main notifications template loop class.
     36 *
     37 * Responsible for loading a group of notifications into a loop for display.
     38 *
     39 * @since BuddyPress (1.9.0)
     40 */
     41class BP_Notifications_Template {
     42        /**
     43         * The loop iterator.
     44         *
     45         * @since BuddyPress (1.9.0)
     46         * @access public
     47         * @var int
     48         */
     49        var $current_notification = -1;
     50
     51        /**
     52         * The number of notifications returned by the paged query.
     53         *
     54         * @since BuddyPress (1.9.0)
     55         * @access public
     56         * @var int
     57         */
     58        var $current_notification_count;
     59
     60        /**
     61         * Total number of notifications matching the query.
     62         *
     63         * @since BuddyPress (1.9.0)
     64         * @access public
     65         * @var int
     66         */
     67        var $total_notification_count;
     68
     69        /**
     70         * Array of notifications located by the query.
     71         *
     72         * @since BuddyPress (1.9.0)
     73         * @access public
     74         * @var array
     75         */
     76        var $notifications;
     77
     78        /**
     79         * The notification object currently being iterated on.
     80         *
     81         * @since BuddyPress (1.9.0)
     82         * @access public
     83         * @var object
     84         */
     85        var $notification;
     86
     87        /**
     88         * A flag for whether the loop is currently being iterated.
     89         *
     90         * @since BuddyPress (1.9.0)
     91         * @access public
     92         * @var bool
     93         */
     94        var $in_the_loop;
     95
     96        /**
     97         * The ID of the user to whom the displayed notifications belong.
     98         *
     99         * @since BuddyPress (1.9.0)
     100         * @access public
     101         * @var int
     102         */
     103        var $user_id;
     104
     105        /**
     106         * The page number being requested.
     107         *
     108         * @since BuddyPress (1.9.0)
     109         * @access public
     110         * @var int
     111         */
     112        var $pag_page;
     113
     114        /**
     115         * The number of items to display per page of results.
     116         *
     117         * @since BuddyPress (1.9.0)
     118         * @access public
     119         * @var int
     120         */
     121        var $pag_num;
     122
     123        /**
     124         * An HTML string containing pagination links.
     125         *
     126         * @since BuddyPress (1.9.0)
     127         * @access public
     128         * @var string
     129         */
     130        var $pag_links;
     131
     132        /**
     133         * A string to match against.
     134         *
     135         * @since BuddyPress (1.9.0)
     136         * @access public
     137         * @var string
     138         */
     139        var $search_terms;
     140
     141        /**
     142         * Constructor method.
     143         *
     144         * @since BuddyPress (1.9.0)
     145         *
     146         * @param array $args {
     147         *     @type int $user_id ID of the user to whom the displayed
     148         *           notifications belong.
     149         *     @type bool $is_new Whether to limit the query to unread
     150         *           notifications. Default: true.
     151         *     @type int $page Number of the page of results to return.
     152         *           Will be overridden by URL parameter. Default: 1.
     153         *     @type int $per_page Number of results to return per page.
     154         *           Will be overridden by URL parameter. Default: 25.
     155         *     @type int $max Optional. Max results to display.
     156         *     @type string $search_terms Optional. Term to match against
     157         *           component_name and component_action.
     158         *     @type string $page_arg URL argument to use for pagination.
     159         *           Default: 'npage'.
     160         * }
     161         */
     162        public function __construct( $args = array() ) {
     163
     164                $r = wp_parse_args( $args, array(
     165                        'user_id'      => 0,
     166                        'is_new'       => true,
     167                        'page'         => 1,
     168                        'per_page'     => 25,
     169                        'max'          => null,
     170                        'search_terms' => '',
     171                        'page_arg'     => 'npage',
     172                ) );
     173
     174                // Setup variables
     175                $this->pag_page     = isset( $_GET[ $r['page_arg'] ] ) ? intval( $_GET[ $r['page_arg'] ] ) : $r['page'];
     176                $this->pag_num      = isset( $_GET['num'] ) ? intval( $_GET['num'] ) : $r['per_page'];
     177                $this->user_id      = $r['user_id'];
     178                $this->is_new       = $r['is_new'];
     179                $this->search_terms = $r['search_terms'];
     180                $this->page_arg     = $r['page_arg'];
     181
     182                // Get the notifications
     183                $notifications      = BP_Notifications_Notification::get_current_notifications_for_user( array(
     184                        'user_id'      => $this->user_id,
     185                        'is_new'       => $this->is_new,
     186                        'page'         => $this->pag_page,
     187                        'per_page'     => $this->pag_num,
     188                        'search_terms' => $this->search_terms
     189                ) );
     190
     191                // Setup the notifications to loop through
     192                $this->notifications            = $notifications['notifications'];
     193                $this->total_notification_count = $notifications['total'];
     194
     195                if ( empty( $this->notifications ) ) {
     196                        $this->notification_count       = 0;
     197                        $this->total_notification_count = 0;
     198
     199                } else {
     200                        if ( ! empty( $max ) ) {
     201                                if ( $max >= count( $this->notifications ) ) {
     202                                        $this->notification_count = count( $this->notifications );
     203                                } else {
     204                                        $this->notification_count = (int) $max;
     205                                }
     206                        } else {
     207                                $this->notification_count = count( $this->notifications );
     208                        }
     209                }
     210
     211                if ( (int) $this->total_notification_count && (int) $this->pag_num ) {
     212                        $this->pag_links = paginate_links( array(
     213                                'base'      => add_query_arg( $this->page_arg, '%#%' ),
     214                                'format'    => '',
     215                                'total'     => ceil( (int) $this->total_notification_count / (int) $this->pag_num ),
     216                                'current'   => $this->pag_page,
     217                                'prev_text' => _x( '&larr;', 'Notifications pagination previous text', 'buddypress' ),
     218                                'next_text' => _x( '&rarr;', 'Notifications pagination next text',     'buddypress' ),
     219                                'mid_size'  => 1
     220                        ) );
     221                }
     222        }
     223
     224        /**
     225         * Whether there are notifications available in the loop.
     226         *
     227         * @since BuddyPress (1.9.0)
     228         *
     229         * @see bp_has_notifications()
     230         *
     231         * @return bool True if there are items in the loop, otherwise false.
     232         */
     233        public function has_notifications() {
     234                if ( $this->notification_count ) {
     235                        return true;
     236                }
     237
     238                return false;
     239        }
     240
     241        /**
     242         * Set up the next notification and iterate index.
     243         *
     244         * @since BuddyPress (1.9.0)
     245         *
     246         * @return object The next notification to iterate over.
     247         */
     248        public function next_notification() {
     249
     250                $this->current_notification++;
     251
     252                $this->notification = $this->notifications[ $this->current_notification ];
     253
     254                return $this->notification;
     255        }
     256
     257        /**
     258         * Rewind the blogs and reset blog index.
     259         *
     260         * @since BuddyPress (1.9.0)
     261         */
     262        public function rewind_notifications() {
     263
     264                $this->current_notification = -1;
     265
     266                if ( $this->notification_count > 0 ) {
     267                        $this->notification = $this->notifications[0];
     268                }
     269        }
     270
     271        /**
     272         * Whether there are notifications left in the loop to iterate over.
     273         *
     274         * This method is used by {@link bp_notifications()} as part of the
     275         * while loop that controls iteration inside the notifications loop, eg:
     276         *     while ( bp_notifications() ) { ...
     277         *
     278         * @since BuddyPress (1.9.0)
     279         *
     280         * @see bp_notifications()
     281         *
     282         * @return bool True if there are more notifications to show,
     283         *         otherwise false.
     284         */
     285        public function notifications() {
     286
     287                if ( $this->current_notification + 1 < $this->notification_count ) {
     288                        return true;
     289
     290                } elseif ( $this->current_notification + 1 == $this->notification_count ) {
     291                        do_action( 'notifications_loop_end');
     292
     293                        $this->rewind_notifications();
     294                }
     295
     296                $this->in_the_loop = false;
     297                return false;
     298        }
     299
     300        /**
     301         * Set up the current notification inside the loop.
     302         *
     303         * Used by {@link bp_the_notification()} to set up the current
     304         * notification data while looping, so that template tags used during
     305         * that iteration make reference to the current notification.
     306         *
     307         * @since BuddyPress (1.9.0)
     308         *
     309         * @see bp_the_notification()
     310         */
     311        public function the_notification() {
     312                $this->in_the_loop  = true;
     313                $this->notification = $this->next_notification();
     314
     315                // loop has just started
     316                if ( 0 === $this->current_notification ) {
     317                        do_action( 'notifications_loop_start' );
     318                }
     319        }
     320}
     321
     322/**
     323 * Initialize the notifications loop.
     324 *
     325 * Based on the $args passed, bp_has_notifications() populates
     326 * buddypress()->notifications->query_loop global, enabling the use of BP
     327 * templates and template functions to display a list of notifications.
     328 *
     329 * @since BuddyPress (1.9.0)
     330 *
     331 * @param array $args {
     332 *     Arguments for limiting the contents of the notifications loop. Can be
     333 *     passed as an associative array, or as a URL query string.
     334 *     @type int $user_id ID of the user to whom notifications belong. Default:
     335 *           ID of the logged-in user.
     336 *     @type bool $is_new Whether to limit query to unread notifications.
     337 *           Default: when viewing the 'unread' tab, defaults to true; when
     338 *           viewing the 'read' tab, defaults to false.
     339 *     @type int $page The page of notifications being fetched. Default: 1.
     340 *     @type int $per_page Number of items to display on a page. Default: 25.
     341 *     @type int $max Optional. Max items to display. Default: false.
     342 *     @type string $search_terms Optional. Term to match against
     343 *           component_name and component_action.
     344 *     @type string $page_arg URL argument to use for pagination.
     345 *           Default: 'npage'.
     346 * }
     347 */
     348function bp_has_notifications( $args = '' ) {
     349
     350        // Get the default is_new argument
     351        if ( bp_is_current_action( 'unread' ) ) {
     352                $is_new = 1;
     353        } elseif ( bp_is_current_action( 'read' ) ) {
     354                $is_new = 0;
     355        }
     356
     357        // Parse the args
     358        $r = wp_parse_args( $args, array(
     359                'user_id'      => bp_loggedin_user_id(),
     360                'is_new'       => $is_new,
     361                'page'         => 1,
     362                'per_page'     => 25,
     363                'max'          => false,
     364                'search_terms' => isset( $_REQUEST['s'] ) ? stripslashes( $_REQUEST['s'] ) : '',
     365                'page_arg'     => 'npage'
     366        ) );
     367
     368        // Get the notifications
     369        $query_loop = new BP_Notifications_Template( $r );
     370
     371        // Setup the global query loop
     372        buddypress()->notifications->query_loop = $query_loop;
     373
     374        return apply_filters( 'bp_has_notificationss', $query_loop->has_notifications(), $query_loop );
     375}
     376
     377/**
     378 * Get the notifications returned by the template loop.
     379 *
     380 * @since BuddyPress (1.9.0)
     381 *
     382 * @return array List of notifications.
     383 */
     384function bp_the_notifications() {
     385        return buddypress()->notifications->query_loop->notifications();
     386}
     387
     388/**
     389 * Get the current notification object in the loop.
     390 *
     391 * @since BuddyPress (1.9.0)
     392 *
     393 * @return object The current notification within the loop.
     394 */
     395function bp_the_notification() {
     396        return buddypress()->notifications->query_loop->the_notification();
     397}
     398
     399/**
     400 * Output the ID of the notification currently being iterated on.
     401 *
     402 * @since BuddyPress (1.9.0)
     403 */
     404function bp_the_notification_id() {
     405        echo bp_get_the_notification_id();
     406}
     407        /**
     408         * Return the ID of the notification currently being iterated on.
     409         *
     410         * @since BuddyPress (1.9.0)
     411         *
     412         * @return int ID of the current notification.
     413         */
     414        function bp_get_the_notification_id() {
     415                return apply_filters( 'bp_get_the_notification_id', buddypress()->notifications->query_loop->notification->id );
     416        }
     417
     418/**
     419 * Output the associated item ID of the notification currently being iterated on.
     420 *
     421 * @since BuddyPress (1.9.0)
     422 */
     423function bp_the_notification_item_id() {
     424        echo bp_get_the_notification_item_id();
     425}
     426        /**
     427         * Return the associated item ID of the notification currently being iterated on.
     428         *
     429         * @since BuddyPress (1.9.0)
     430         *
     431         * @return int ID of the item associated with the current notification.
     432         */
     433        function bp_get_the_notification_item_id() {
     434                return apply_filters( 'bp_get_the_notification_item_id', stripslashes_deep( buddypress()->notifications->query_loop->notification->item_id ) );
     435        }
     436
     437/**
     438 * Output the secondary associated item ID of the notification currently being iterated on.
     439 *
     440 * @since BuddyPress (1.9.0)
     441 */
     442function bp_the_notification_secondary_item_id() {
     443        echo bp_get_the_notification_secondary_item_id();
     444}
     445        /**
     446         * Return the secondary associated item ID of the notification currently being iterated on.
     447         *
     448         * @since BuddyPress (1.9.0)
     449         *
     450         * @return int ID of the secondary item associated with the current notification.
     451         */
     452        function bp_get_the_notification_secondary_item_id() {
     453                return apply_filters( 'bp_get_the_notification_secondary_item_id', stripslashes_deep( buddypress()->notifications->query_loop->notification->secondary_item_id ) );
     454        }
     455
     456/**
     457 * Output the name of the component associated with the notification currently being iterated on.
     458 *
     459 * @since BuddyPress (1.9.0)
     460 */
     461function bp_the_notification_component_name() {
     462        echo bp_get_the_notification_component_name();
     463}
     464        /**
     465         * Return the name of the component associated with the notification currently being iterated on.
     466         *
     467         * @since BuddyPress (1.9.0)
     468         *
     469         * @return int Name of the component associated with the current notification.
     470         */
     471        function bp_get_the_notification_component_name() {
     472                return apply_filters( 'bp_get_the_notification_component_name', stripslashes_deep( buddypress()->notifications->query_loop->notification->component_name ) );
     473        }
     474
     475/**
     476 * Output the name of the action associated with the notification currently being iterated on.
     477 *
     478 * @since BuddyPress (1.9.0)
     479 */
     480function bp_the_notification_component_action() {
     481        echo bp_get_the_notification_component_action();
     482}
     483        /**
     484         * Return the name of the action associated with the notification currently being iterated on.
     485         *
     486         * @since BuddyPress (1.9.0)
     487         *
     488         * @return int Name of the action associated with the current notification.
     489         */
     490        function bp_get_the_notification_component_action() {
     491                return apply_filters( 'bp_get_the_notification_component_action', stripslashes_deep( buddypress()->notifications->query_loop->notification->component_action ) );
     492        }
     493
     494/**
     495 * Output the timestamp of the current notification.
     496 *
     497 * @since BuddyPress (1.9.0)
     498 */
     499function bp_the_notification_date_notified() {
     500        echo bp_get_the_notification_date_notified();
     501}
     502        /**
     503         * Return the timestamp of the current notification.
     504         *
     505         * @since BuddyPress (1.9.0)
     506         *
     507         * @return string Timestamp of the current notification.
     508         */
     509        function bp_get_the_notification_date_notified() {
     510                return apply_filters( 'bp_get_the_notification_date_notified', stripslashes_deep( buddypress()->notifications->query_loop->notification->date_notified ) );
     511        }
     512
     513/**
     514 * Output the pagination for the current notification loop.
     515 *
     516 * @since BuddyPress (1.9.0)
     517 */
     518function bp_notifications_pagination_links() {
     519        echo bp_get_notifications_pagination_links();
     520}
     521        /**
     522         * Return the pagination for the current notification loop.
     523         *
     524         * @since BuddyPress (1.9.0)
     525         *
     526         * @return string HTML for the pagination.
     527         */
     528        function bp_get_notifications_pagination_links() {
     529                return apply_filters( 'bp_get_notifications_pagination_links', buddypress()->notifications->query_loop->pag_links );
     530        }
  • bp-templates/bp-legacy/buddypress/members/single/home.php

    diff --git bp-templates/bp-legacy/buddypress/members/single/home.php bp-templates/bp-legacy/buddypress/members/single/home.php
    index 72b6d5a..0022cb3 100644
     
    4545                elseif ( bp_is_user_forums() ) :
    4646                        bp_get_template_part( 'members/single/forums'   );
    4747
     48                elseif ( bp_is_user_notifications() ) :
     49                        bp_get_template_part( 'members/single/notifications' );
     50
    4851                elseif ( bp_is_user_settings() ) :
    4952                        bp_get_template_part( 'members/single/settings' );
    5053
  • new file p-templates/bp-legacy/buddypress/members/single/notifications.php

    diff --git bp-templates/bp-legacy/buddypress/members/single/notifications.php bp-templates/bp-legacy/buddypress/members/single/notifications.php
    new file mode 100644
    index 0000000..082c2ea
    - +  
     1<?php
     2
     3/**
     4 * BuddyPress - Users Notifications
     5 *
     6 * @package BuddyPress
     7 * @subpackage bp-legacy
     8 */
     9
     10?>
     11
     12<div class="item-list-tabs no-ajax" id="subnav" role="navigation">
     13        <ul>
     14                <?php if ( bp_is_my_profile() ) bp_get_options_nav(); ?>
     15
     16                <li id="members-order-select" class="last filter">
     17
     18                        <label for="members-friends"><?php _e( 'Order By:', 'buddypress' ); ?></label>
     19                        <select id="members-friends">
     20                                <option value="newest"><?php _e( 'Newest First', 'buddypress' ); ?></option>
     21                                <option value="oldest"><?php _e( 'Oldest First', 'buddypress' ); ?></option>
     22                        </select>
     23                </li>
     24        </ul>
     25</div>
     26
     27<?php
     28switch ( bp_current_action() ) :
     29
     30        // Unread
     31        case 'unread' :
     32                bp_get_template_part( 'members/single/notifications/unread' );
     33                break;
     34
     35        // Read
     36        case 'read' :
     37                bp_get_template_part( 'members/single/notifications/read' );
     38                break;
     39
     40        // Any other
     41        default :
     42                bp_get_template_part( 'members/single/plugins' );
     43                break;
     44endswitch;
  • new file p-templates/bp-legacy/buddypress/members/single/notifications/notifications-loop.php

    diff --git bp-templates/bp-legacy/buddypress/members/single/notifications/notifications-loop.php bp-templates/bp-legacy/buddypress/members/single/notifications/notifications-loop.php
    new file mode 100644
    index 0000000..16f630c
    - +  
     1<div class="notification-pagination">
     2        <?php bp_notifications_pagination_links() ?>
     3</div>
     4
     5<?php while ( bp_the_notifications() ) : bp_the_notification(); ?>
     6
     7        <tr>
     8                <td></td>
     9                <td><?php bp_the_notification_component_action(); ?></td>
     10                <td><?php echo bp_core_get_userlink( bp_get_the_notification_item_id() ); ?></td>
     11                <td><?php echo bp_core_time_since( bp_get_the_notification_date_notified() ); ?></td>
     12        </tr>
     13
     14<?php endwhile;
  • new file p-templates/bp-legacy/buddypress/members/single/notifications/read.php

    diff --git bp-templates/bp-legacy/buddypress/members/single/notifications/read.php bp-templates/bp-legacy/buddypress/members/single/notifications/read.php
    new file mode 100644
    index 0000000..e55d6db
    - +  
     1<?php if ( bp_has_notifications() ) : ?>
     2
     3        <table class="notification-settings">
     4                <thead>
     5                        <tr>
     6                                <th class="icon"></th>
     7                                <th class="title"><?php _e( 'Notification', 'buddypress' ) ?></th>
     8                                <th class="title"><?php _e( 'Member',       'buddypress' ) ?></th>
     9                                <th class="date"><?php _e( 'Date Received', 'buddypress' ) ?></th>
     10                        </tr>
     11                </thead>
     12
     13                <tbody>
     14                        <?php bp_get_template_part( 'members/single/notifications/notifications-loop' ); ?>
     15                </tbody>
     16        </table>
     17
     18<?php else : ?>
     19
     20        <div id="message" class="info">
     21                <p><?php _e( 'You have no notifications.', 'buddypress' ); ?></p>
     22        </div>
     23
     24<?php endif;
     25 No newline at end of file
  • new file p-templates/bp-legacy/buddypress/members/single/notifications/unread.php

    diff --git bp-templates/bp-legacy/buddypress/members/single/notifications/unread.php bp-templates/bp-legacy/buddypress/members/single/notifications/unread.php
    new file mode 100644
    index 0000000..df83326
    - +  
     1<?php if ( bp_has_notifications() ) : ?>
     2
     3        <table class="notification-settings">
     4                <thead>
     5                        <tr>
     6                                <th class="icon"></th>
     7                                <th class="title"><?php _e( 'Notification', 'buddypress' ) ?></th>
     8                                <th class="title"><?php _e( 'Member',        'buddypress' ) ?></th>
     9                                <th class="date"><?php _e( 'Date Received', 'buddypress' ) ?></th>
     10                        </tr>
     11                </thead>
     12
     13                <tbody>
     14                        <?php bp_get_template_part( 'members/single/notifications/notifications-loop' ); ?>
     15                </tbody>
     16        </table>
     17
     18<?php else : ?>
     19
     20        <div id="message" class="info">
     21                <p><?php _e( 'You have no new notifications.', 'buddypress' ); ?></p>
     22        </div>
     23
     24<?php endif;
     25 No newline at end of file
  • tests/includes/factory.php

    diff --git tests/includes/factory.php tests/includes/factory.php
    index a9938a7..c827821 100644
    class BP_UnitTest_Factory extends WP_UnitTest_Factory { 
    99                $this->group = new BP_UnitTest_Factory_For_Group( $this );
    1010                $this->xprofile_group = new BP_UnitTest_Factory_For_XProfileGroup( $this );
    1111                $this->xprofile_field = new BP_UnitTest_Factory_For_XProfileField( $this );
     12                $this->notification = new BP_UnitTest_Factory_For_Notification( $this );
    1213        }
    1314}
    1415
    class BP_UnitTest_Factory_For_XProfileField extends WP_UnitTest_Factory_For_Thin 
    146147                return new BP_XProfile_Field( $field_id );
    147148        }
    148149}
     150
     151class BP_UnitTest_Factory_For_Notification extends WP_UnitTest_Factory_For_Thing {
     152        public function __construct( $factory = null ) {
     153                parent::__construct( $factory );
     154        }
     155
     156        public function create_object( $args ) {
     157                return bp_notifications_add_notification( $args );
     158        }
     159
     160        public function update_object( $id, $fields ) {}
     161
     162        public function get_object_by_id( $id ) {
     163                return new BP_Notifications_Notification( $id );
     164        }
     165}
  • tests/includes/install.php

    diff --git tests/includes/install.php tests/includes/install.php
    index 39f221d..6f0a7e1 100644
    define( 'BP_ROOT_BLOG', 1 ); 
    2626tests_add_filter( 'show_admin_bar', '__return_true' );
    2727
    2828function wp_test_bp_install( $value ) {
    29         return array( 'activity' => 1, 'blogs' => 1, 'friends' => 1, 'groups' => 1, 'members' => 1, 'messages' => 1, 'settings' => 1, 'xprofile' => 1, );
     29        return array( 'activity' => 1, 'blogs' => 1, 'friends' => 1, 'groups' => 1, 'members' => 1, 'messages' => 1, 'notifications' => 1, 'settings' => 1, 'xprofile' => 1, );
    3030}
    3131tests_add_filter( 'bp_new_install_default_components', 'wp_test_bp_install' );
    3232