Skip to:
Content

BuddyPress.org

Changeset 10715


Ignore:
Timestamp:
04/21/2016 07:44:45 AM (8 years ago)
Author:
imath
Message:

Introduce screen notifications for activity comments and activity comment replies

Users will be notified about comments made on their activities and about replies made on their activity comments.

If there is only one notification of the above types, the WP Admin Bar bubble will link to the single activity. Clicking on this link will mark the notification as read.
If there are more than one, we use the notifications screen and an extra parameter to filter the notifications according to the type so that only these notifications are displayed. Clicking on the listed links will mark the notification as read.

Props dcavins, boonebgorges, DJPaul

Fixes #6057

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-activity/bp-activity-notifications.php

    r10500 r10715  
    149149    add_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
    150150
    151     if ( $original_activity->user_id != $commenter_id && 'no' != bp_get_user_meta( $original_activity->user_id, 'notification_activity_new_reply', true ) ) {
    152         $args = array(
    153             'tokens' => array(
    154                 'comment.id'                => $comment_id,
    155                 'commenter.id'              => $commenter_id,
    156                 'usermessage'               => wp_strip_all_tags( $content ),
    157                 'original_activity.user_id' => $original_activity->user_id,
    158                 'poster.name'               => $poster_name,
    159                 'thread.url'                => esc_url( $thread_link ),
    160             ),
    161         );
    162 
    163         bp_send_email( 'activity-comment', $original_activity->user_id, $args );
     151    if ( $original_activity->user_id != $commenter_id ) {
     152
     153        // Send an email if the user hasn't opted-out.
     154        if ( 'no' != bp_get_user_meta( $original_activity->user_id, 'notification_activity_new_reply', true ) ) {
     155            $args = array(
     156                'tokens' => array(
     157                    'comment.id'                => $comment_id,
     158                    'commenter.id'              => $commenter_id,
     159                    'usermessage'               => wp_strip_all_tags( $content ),
     160                    'original_activity.user_id' => $original_activity->user_id,
     161                    'poster.name'               => $poster_name,
     162                    'thread.url'                => esc_url( $thread_link ),
     163                ),
     164            );
     165
     166            bp_send_email( 'activity-comment', $original_activity->user_id, $args );
     167        }
     168
     169        /**
     170         * Fires at the point that notifications should be sent for activity comments.
     171         *
     172         * @since 2.6.0
     173         *
     174         * @param BP_Activity_Activity $original_activity The original activity.
     175         * @param int                  $comment_id        ID for the newly received comment.
     176         * @param int                  $commenter_id      ID of the user who made the comment.
     177         * @param array                $params            Arguments used with the original activity comment.
     178         */
     179        do_action( 'bp_activity_sent_reply_to_update_notification', $original_activity, $comment_id, $commenter_id, $params );
    164180    }
    165181
     
    175191    $parent_comment = new BP_Activity_Activity( $params['parent_id'] );
    176192
    177     if ( $parent_comment->user_id != $commenter_id && $original_activity->user_id != $parent_comment->user_id && 'no' != bp_get_user_meta( $parent_comment->user_id, 'notification_activity_new_reply', true ) ) {
    178         $args = array(
    179             'tokens' => array(
    180                 'comment.id'             => $comment_id,
    181                 'commenter.id'           => $commenter_id,
    182                 'usermessage'            => wp_strip_all_tags( $content ),
    183                 'parent-comment-user.id' => $parent_comment->user_id,
    184                 'poster.name'            => $poster_name,
    185                 'thread.url'             => esc_url( $thread_link ),
    186             ),
    187         );
    188 
    189         bp_send_email( 'activity-comment-author', $parent_comment->user_id, $args );
     193    if ( $parent_comment->user_id != $commenter_id && $original_activity->user_id != $parent_comment->user_id ) {
     194
     195        // Send an email if the user hasn't opted-out.
     196        if ( 'no' != bp_get_user_meta( $parent_comment->user_id, 'notification_activity_new_reply', true ) ) {
     197            $args = array(
     198                'tokens' => array(
     199                    'comment.id'             => $comment_id,
     200                    'commenter.id'           => $commenter_id,
     201                    'usermessage'            => wp_strip_all_tags( $content ),
     202                    'parent-comment-user.id' => $parent_comment->user_id,
     203                    'poster.name'            => $poster_name,
     204                    'thread.url'             => esc_url( $thread_link ),
     205                ),
     206            );
     207
     208            bp_send_email( 'activity-comment-author', $parent_comment->user_id, $args );
     209        }
     210
     211        /**
     212         * Fires at the point that notifications should be sent for comments on activity replies.
     213         *
     214         * @since 2.6.0
     215         *
     216         * @param BP_Activity_Activity $parent_comment The parent activity.
     217         * @param int                  $comment_id     ID for the newly received comment.
     218         * @param int                  $commenter_id   ID of the user who made the comment.
     219         * @param array                $params         Arguments used with the original activity comment.
     220         */
     221        do_action( 'bp_activity_sent_reply_to_reply_notification', $parent_comment, $comment_id, $commenter_id, $params );
    190222    }
    191223}
     
    226258 */
    227259function bp_activity_format_notifications( $action, $item_id, $secondary_item_id, $total_items, $format = 'string' ) {
     260    $action_filter = $action;
     261    $return        = false;
     262    $activity_id   = $item_id;
     263    $user_id       = $secondary_item_id;
     264    $user_fullname = bp_core_get_user_displayname( $user_id );
    228265
    229266    switch ( $action ) {
    230267        case 'new_at_mention':
    231             $activity_id      = $item_id;
    232             $poster_user_id   = $secondary_item_id;
    233             $at_mention_link  = bp_loggedin_user_domain() . bp_get_activity_slug() . '/mentions/';
    234             $at_mention_title = sprintf( __( '@%s Mentions', 'buddypress' ), bp_get_loggedin_user_username() );
    235             $amount = 'single';
     268            $action_filter = 'at_mentions';
     269            $link          = bp_loggedin_user_domain() . bp_get_activity_slug() . '/mentions/';
     270            $title         = sprintf( __( '@%s Mentions', 'buddypress' ), bp_get_loggedin_user_username() );
     271            $amount        = 'single';
    236272
    237273            if ( (int) $total_items > 1 ) {
     
    239275                $amount = 'multiple';
    240276            } else {
    241                 $user_fullname = bp_core_get_user_displayname( $poster_user_id );
    242277                $text =  sprintf( __( '%1$s mentioned you', 'buddypress' ), $user_fullname );
    243278            }
    244279        break;
     280
     281        case 'update_reply':
     282            $link   = bp_get_notifications_permalink();
     283            $title  = __( 'New Activity reply', 'buddypress' );
     284            $amount = 'single';
     285
     286            if ( (int) $total_items > 1 ) {
     287                $link   = add_query_arg( 'type', $action, $link );
     288                $text   = sprintf( __( 'You have %1$d new replies', 'buddypress' ), (int) $total_items );
     289                $amount = 'multiple';
     290            } else {
     291                $link   = bp_activity_get_permalink( $activity_id );
     292                $text   =  sprintf( __( '%1$s commented on one of your updates', 'buddypress' ), $user_fullname );
     293            }
     294        break;
     295
     296        case 'comment_reply':
     297            $link   = bp_get_notifications_permalink();
     298            $title  = __( 'New Activity comment reply', 'buddypress' );
     299            $amount = 'single';
     300
     301            if ( (int) $total_items > 1 ) {
     302                $link   = add_query_arg( 'type', $action, $link );
     303                $text   = sprintf( __( 'You have %1$d new comment replies', 'buddypress' ), (int) $total_items );
     304                $amount = 'multiple';
     305            } else {
     306                $link   = bp_activity_get_permalink( $activity_id );
     307                $text   =  sprintf( __( '%1$s replied to one your activity comments', 'buddypress' ), $user_fullname );
     308            }
     309        break;
    245310    }
    246311
     
    248313
    249314        /**
    250          * Filters the @mention notification for the string format.
     315         * Filters the activity notification for the string format.
    251316         *
    252317         * This is a variable filter that is dependent on how many items
     
    255320         *
    256321         * @since 1.5.0
    257          *
    258          * @param string $string          HTML anchor tag for the mention.
    259          * @param string $at_mention_link The permalink for the mention.
     322         * @since 2.6.0 use the $action_filter as a new dynamic portion of the filter name.
     323         *
     324         * @param string $string          HTML anchor tag for the interaction.
     325         * @param string $link            The permalink for the interaction.
    260326         * @param int    $total_items     How many items being notified about.
    261327         * @param int    $activity_id     ID of the activity item being formatted.
    262          * @param int    $poster_user_id  ID of the user posting the mention.
     328         * @param int    $user_id         ID of the user who inited the interaction.
    263329         */
    264         $return = apply_filters( 'bp_activity_' . $amount . '_at_mentions_notification', '<a href="' . esc_url( $at_mention_link ) . '" title="' . esc_attr( $at_mention_title ) . '">' . esc_html( $text ) . '</a>', $at_mention_link, (int) $total_items, $activity_id, $poster_user_id );
     330        $return = apply_filters( 'bp_activity_' . $amount . '_' . $action_filter . '_notification', '<a href="' . esc_url( $link ) . '" title="' . esc_attr( $title ) . '">' . esc_html( $text ) . '</a>', $link, (int) $total_items, $activity_id, $user_id );
    265331    } else {
    266332
    267333        /**
    268          * Filters the @mention notification for any non-string format.
     334         * Filters the activity notification for any non-string format.
    269335         *
    270336         * This is a variable filter that is dependent on how many items need notified about.
     
    273339         *
    274340         * @since 1.5.0
    275          *
    276          * @param array  $array           Array holding the content and permalink for the mention notification.
    277          * @param string $at_mention_link The permalink for the mention.
     341         * @since 2.6.0 use the $action_filter as a new dynamic portion of the filter name.
     342         *
     343         * @param array  $array           Array holding the content and permalink for the interaction notification.
     344         * @param string $link            The permalink for the interaction.
    278345         * @param int    $total_items     How many items being notified about.
    279346         * @param int    $activity_id     ID of the activity item being formatted.
    280          * @param int    $poster_user_id  ID of the user posting the mention.
     347         * @param int    $user_id         ID of the user who inited the interaction.
    281348         */
    282         $return = apply_filters( 'bp_activity_' . $amount . '_at_mentions_notification', array(
     349        $return = apply_filters( 'bp_activity_' . $amount . '_' . $action_filter . '_notification', array(
    283350            'text' => $text,
    284             'link' => $at_mention_link
    285         ), $at_mention_link, (int) $total_items, $activity_id, $poster_user_id );
     351            'link' => $link
     352        ), $link, (int) $total_items, $activity_id, $user_id );
    286353    }
    287354
     
    293360     * @param string $action            The type of activity item.
    294361     * @param int    $item_id           The activity ID.
    295      * @param int    $secondary_item_id @mention mentioner ID.
     362     * @param int    $secondary_item_id The user ID who inited the interaction.
    296363     * @param int    $total_items       Total amount of items to format.
    297364     */
     
    333400
    334401/**
     402 * Notify a member one of their activity received a reply.
     403 *
     404 * @since 2.6.0
     405 *
     406 * @param BP_Activity_Activity $activity     The original activity.
     407 * @param int                  $comment_id   ID for the newly received comment.
     408 * @param int                  $commenter_id ID of the user who made the comment.
     409 */
     410function bp_activity_update_reply_add_notification( $activity, $comment_id, $commenter_id ) {
     411    if ( bp_is_active( 'notifications' ) ) {
     412        bp_notifications_add_notification( array(
     413            'user_id'           => $activity->user_id,
     414            'item_id'           => $activity->id,
     415            'secondary_item_id' => $commenter_id,
     416            'component_name'    => buddypress()->activity->id,
     417            'component_action'  => 'update_reply',
     418            'date_notified'     => bp_core_current_time(),
     419            'is_new'            => 1,
     420        ) );
     421    }
     422}
     423add_action( 'bp_activity_sent_reply_to_update_notification', 'bp_activity_update_reply_add_notification', 10, 3 );
     424
     425/**
     426 * Notify a member one of their activity comment received a reply.
     427 *
     428 * @since 2.6.0
     429 *
     430 * @param BP_Activity_Activity $activity_comment The parent activity.
     431 * @param int                  $comment_id       ID for the newly received comment.
     432 * @param int                  $commenter_id     ID of the user who made the comment.
     433 */
     434function bp_activity_comment_reply_add_notification( $activity_comment, $comment_id, $commenter_id ) {
     435    if ( bp_is_active( 'notifications' ) ) {
     436        bp_notifications_add_notification( array(
     437            'user_id'           => $activity_comment->user_id,
     438            'item_id'           => $activity_comment->item_id,
     439            'secondary_item_id' => $commenter_id,
     440            'component_name'    => buddypress()->activity->id,
     441            'component_action'  => 'comment_reply',
     442            'date_notified'     => bp_core_current_time(),
     443            'is_new'            => 1,
     444        ) );
     445    }
     446}
     447add_action( 'bp_activity_sent_reply_to_reply_notification', 'bp_activity_comment_reply_add_notification', 10, 3 );
     448
     449/**
    335450 * Mark at-mention notifications as read when users visit their Mentions page.
    336451 *
     
    359474 *
    360475 * @since 2.0.0
     476 * @since 2.6.0 Mark notifications for 'update_reply' and 'comment_reply' actions
    361477 *
    362478 * @param BP_Activity_Activity $activity Activity object.
     
    371487    }
    372488
    373     // Mark as read any notifications for the current user related to this activity item.
    374     bp_notifications_mark_notifications_by_item_id( bp_loggedin_user_id(), $activity->id, buddypress()->activity->id, 'new_at_mention' );
     489    /**
     490     * Filter here to add the notification actions to mark as read
     491     * when the single activity is displayed.
     492     *
     493     * @since 2.6.0
     494     *
     495     * @param array $value List of notification actions to mark as read.
     496     */
     497    $notification_actions = apply_filters( 'bp_activity_notification_actions_single_activity', array(
     498        'new_at_mention',
     499        'update_reply',
     500        'comment_reply',
     501    ) );
     502
     503    $user_id   = bp_loggedin_user_id();
     504    $component = buddypress()->activity->id;
     505
     506    foreach ( $notification_actions as $action ) {
     507        // Mark as read any notifications for the current user related to this activity item.
     508        bp_notifications_mark_notifications_by_item_id( $user_id, $activity->id, $component, $action );
     509    }
    375510}
    376511add_action( 'bp_activity_screen_single_activity_permalink', 'bp_activity_remove_screen_notifications_single_activity_permalink' );
  • trunk/src/bp-notifications/bp-notifications-template.php

    r10652 r10715  
    168168    } else {
    169169        $user_id = bp_loggedin_user_id();
     170    }
     171
     172    // Set the component action (by default false to get all actions)
     173    $component_action = false;
     174
     175    if ( isset( $_REQUEST['type'] ) ) {
     176        $component_action = sanitize_key( $_REQUEST['type'] );
     177    }
     178
     179    // Set the search terms (by default an empty string to get all notifications)
     180    $search_terms = '';
     181
     182    if ( isset( $_REQUEST['s'] ) ) {
     183        $search_terms = stripslashes( $_REQUEST['s'] );
    170184    }
    171185
     
    176190        'secondary_item_id' => false,
    177191        'component_name'    => bp_notifications_get_registered_components(),
    178         'component_action'  => false,
     192        'component_action'  => $component_action,
    179193        'is_new'            => $is_new,
    180         'search_terms'      => isset( $_REQUEST['s'] ) ? stripslashes( $_REQUEST['s'] ) : '',
     194        'search_terms'      => $search_terms,
    181195        'order_by'          => 'date_notified',
    182196        'sort_order'        => 'DESC',
  • trunk/tests/phpunit/testcases/activity/notifications.php

    r10457 r10715  
    288288        ) );
    289289    }
     290
     291    /**
     292     * @group bp_activity_format_notifications
     293     */
     294    public function test_bp_activity_format_notifications_new_at_mention() {
     295        $this->test_format_filter = array();
     296
     297        // Current user is $this->u1, so $this->u2 posted the mention
     298        $a = $this->factory->activity->create( array(
     299            'user_id' => $this->u2,
     300            'component' => buddypress()->activity->id,
     301            'type' => 'activity_update',
     302            'content' => 'fake new_at_mention activity',
     303        ) );
     304
     305        add_filter( 'bp_activity_single_at_mentions_notification', array( $this, 'format_notification_filter' ), 10, 1 );
     306        add_filter( 'bp_activity_multiple_at_mentions_notification', array( $this, 'format_notification_filter' ), 10, 1 );
     307
     308        $format_tests = array(
     309            'array_single'    => bp_activity_format_notifications( 'new_at_mention', $a, $this->u2, 1, 'array' ),
     310            'string_single'   => bp_activity_format_notifications( 'new_at_mention', $a, $this->u2, 1 ),
     311            'array_multiple'  => bp_activity_format_notifications( 'new_at_mention', $a, $this->u2, 2, 'array' ),
     312            'string_multiple' => bp_activity_format_notifications( 'new_at_mention', $a, $this->u2, 2 ),
     313        );
     314
     315        remove_filter( 'bp_activity_single_at_mentions_notification', array( $this, 'format_notification_filter' ), 10, 1 );
     316        remove_filter( 'bp_activity_multiple_at_mentions_notification', array( $this, 'format_notification_filter' ), 10, 1 );
     317
     318        $single = sprintf( __( '%1$s mentioned you', 'buddypress' ), bp_core_get_user_displayname( $this->u2 ) );
     319        $multiple = 'You have 2 new mentions';
     320
     321        $this->assertContains( $single, $format_tests['string_single'] );
     322        $this->assertContains( $single, $format_tests['array_single']['text'] );
     323        $this->assertContains( $multiple, $format_tests['string_multiple'] );
     324        $this->assertContains( $multiple, $format_tests['array_multiple']['text'] );
     325
     326        // Check filters
     327        $this->assertTrue( 4 === count( $this->test_format_filter ) );
     328    }
     329
     330    public function format_notification_filter( $return ) {
     331        $this->test_format_filter[] = current_filter();
     332        return $return;
     333    }
     334
     335    /**
     336     * @group bp_activity_update_reply_add_notification
     337     * @group bp_activity_comment_reply_add_notification
     338     */
     339    public function test_bp_activity_comment_add_notification() {
     340        $a = $this->factory->activity->create( array(
     341            'user_id' => $this->u1,
     342            'component' => buddypress()->activity->id,
     343            'type' => 'activity_update',
     344            'content' => 'Please comment this activity.',
     345        ) );
     346
     347        $c = bp_activity_new_comment( array(
     348            'content'     => 'this is the comment',
     349            'user_id'     => $this->u2,
     350            'activity_id' => $a, // ID of the root activity item.
     351            'parent_id'   => false  // ID of a parent comment (optional).
     352        ) );
     353
     354        $u3 = $this->factory->user->create();
     355
     356        $r3 = bp_activity_new_comment( array(
     357            'content'     => 'this is a reply to a comment',
     358            'user_id'     => $u3,
     359            'activity_id' => $a, // ID of the root activity item.
     360            'parent_id'   => $c  // ID of a parent comment (optional).
     361        ) );
     362
     363        $u1_notifications = BP_Notifications_Notification::get( array(
     364            'user_id' => $this->u1,
     365        ) );
     366
     367        $expected_commenters = array( $this->u2, $u3 );
     368        $this->assertEquals( $expected_commenters, wp_list_pluck( $u1_notifications, 'secondary_item_id' ) );
     369
     370        $u2_notifications = BP_Notifications_Notification::get( array(
     371            'user_id' => $this->u2,
     372        ) );
     373
     374        $expected_commenter = array( $u3 );
     375        $this->assertEquals( $expected_commenter, wp_list_pluck( $u2_notifications, 'secondary_item_id' ) );
     376    }
    290377}
Note: See TracChangeset for help on using the changeset viewer.