<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[BuddyPress][10715] trunk: Introduce screen notifications for activity comments and activity comment replies</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://buddypress.trac.wordpress.org/changeset/10715">10715</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://buddypress.trac.wordpress.org/changeset/10715","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>imath</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2016-04-21 07:44:45 +0000 (Thu, 21 Apr 2016)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>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 <a href="http://buddypress.trac.wordpress.org/ticket/6057">#6057</a></pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcbpactivitybpactivitynotificationsphp">trunk/src/bp-activity/bp-activity-notifications.php</a></li>
<li><a href="#trunksrcbpnotificationsbpnotificationstemplatephp">trunk/src/bp-notifications/bp-notifications-template.php</a></li>
<li><a href="#trunktestsphpunittestcasesactivitynotificationsphp">trunk/tests/phpunit/testcases/activity/notifications.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcbpactivitybpactivitynotificationsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/bp-activity/bp-activity-notifications.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/bp-activity/bp-activity-notifications.php       2016-04-20 19:16:16 UTC (rev 10714)
+++ trunk/src/bp-activity/bp-activity-notifications.php 2016-04-21 07:44:45 UTC (rev 10715)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -148,19 +148,35 @@
</span><span class="cx" style="display: block; padding: 0 10px">        add_filter( 'bp_get_activity_content_body', 'wpautop' );
</span><span class="cx" style="display: block; padding: 0 10px">        add_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( $original_activity->user_id != $commenter_id && 'no' != bp_get_user_meta( $original_activity->user_id, 'notification_activity_new_reply', true ) ) {
-               $args = array(
-                       'tokens' => array(
-                               'comment.id'                => $comment_id,
-                               'commenter.id'              => $commenter_id,
-                               'usermessage'               => wp_strip_all_tags( $content ),
-                               'original_activity.user_id' => $original_activity->user_id,
-                               'poster.name'               => $poster_name,
-                               'thread.url'                => esc_url( $thread_link ),
-                       ),
-               );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $original_activity->user_id != $commenter_id ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                bp_send_email( 'activity-comment', $original_activity->user_id, $args );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // Send an email if the user hasn't opted-out.
+               if ( 'no' != bp_get_user_meta( $original_activity->user_id, 'notification_activity_new_reply', true ) ) {
+                       $args = array(
+                               'tokens' => array(
+                                       'comment.id'                => $comment_id,
+                                       'commenter.id'              => $commenter_id,
+                                       'usermessage'               => wp_strip_all_tags( $content ),
+                                       'original_activity.user_id' => $original_activity->user_id,
+                                       'poster.name'               => $poster_name,
+                                       'thread.url'                => esc_url( $thread_link ),
+                               ),
+                       );
+
+                       bp_send_email( 'activity-comment', $original_activity->user_id, $args );
+               }
+
+               /**
+                * Fires at the point that notifications should be sent for activity comments.
+                *
+                * @since 2.6.0
+                *
+                * @param BP_Activity_Activity $original_activity The original activity.
+                * @param int                  $comment_id        ID for the newly received comment.
+                * @param int                  $commenter_id      ID of the user who made the comment.
+                * @param array                $params            Arguments used with the original activity comment.
+                */
+               do_action( 'bp_activity_sent_reply_to_update_notification', $original_activity, $comment_id, $commenter_id, $params );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -174,19 +190,35 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        $parent_comment = new BP_Activity_Activity( $params['parent_id'] );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        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 ) ) {
-               $args = array(
-                       'tokens' => array(
-                               'comment.id'             => $comment_id,
-                               'commenter.id'           => $commenter_id,
-                               'usermessage'            => wp_strip_all_tags( $content ),
-                               'parent-comment-user.id' => $parent_comment->user_id,
-                               'poster.name'            => $poster_name,
-                               'thread.url'             => esc_url( $thread_link ),
-                       ),
-               );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $parent_comment->user_id != $commenter_id && $original_activity->user_id != $parent_comment->user_id ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                bp_send_email( 'activity-comment-author', $parent_comment->user_id, $args );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // Send an email if the user hasn't opted-out.
+               if ( 'no' != bp_get_user_meta( $parent_comment->user_id, 'notification_activity_new_reply', true ) ) {
+                       $args = array(
+                               'tokens' => array(
+                                       'comment.id'             => $comment_id,
+                                       'commenter.id'           => $commenter_id,
+                                       'usermessage'            => wp_strip_all_tags( $content ),
+                                       'parent-comment-user.id' => $parent_comment->user_id,
+                                       'poster.name'            => $poster_name,
+                                       'thread.url'             => esc_url( $thread_link ),
+                               ),
+                       );
+
+                       bp_send_email( 'activity-comment-author', $parent_comment->user_id, $args );
+               }
+
+               /**
+                * Fires at the point that notifications should be sent for comments on activity replies.
+                *
+                * @since 2.6.0
+                *
+                * @param BP_Activity_Activity $parent_comment The parent activity.
+                * @param int                  $comment_id     ID for the newly received comment.
+                * @param int                  $commenter_id   ID of the user who made the comment.
+                * @param array                $params         Arguments used with the original activity comment.
+                */
+               do_action( 'bp_activity_sent_reply_to_reply_notification', $parent_comment, $comment_id, $commenter_id, $params );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -225,64 +257,99 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * @return string $return Formatted @mention notification.
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><span class="cx" style="display: block; padding: 0 10px"> function bp_activity_format_notifications( $action, $item_id, $secondary_item_id, $total_items, $format = 'string' ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        $action_filter = $action;
+       $return        = false;
+       $activity_id   = $item_id;
+       $user_id       = $secondary_item_id;
+       $user_fullname = bp_core_get_user_displayname( $user_id );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        switch ( $action ) {
</span><span class="cx" style="display: block; padding: 0 10px">                case 'new_at_mention':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $activity_id      = $item_id;
-                       $poster_user_id   = $secondary_item_id;
-                       $at_mention_link  = bp_loggedin_user_domain() . bp_get_activity_slug() . '/mentions/';
-                       $at_mention_title = sprintf( __( '@%s Mentions', 'buddypress' ), bp_get_loggedin_user_username() );
-                       $amount = 'single';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $action_filter = 'at_mentions';
+                       $link          = bp_loggedin_user_domain() . bp_get_activity_slug() . '/mentions/';
+                       $title         = sprintf( __( '@%s Mentions', 'buddypress' ), bp_get_loggedin_user_username() );
+                       $amount        = 'single';
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( (int) $total_items > 1 ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $text = sprintf( __( 'You have %1$d new mentions', 'buddypress' ), (int) $total_items );
</span><span class="cx" style="display: block; padding: 0 10px">                                $amount = 'multiple';
</span><span class="cx" style="display: block; padding: 0 10px">                        } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $user_fullname = bp_core_get_user_displayname( $poster_user_id );
</del><span class="cx" style="display: block; padding: 0 10px">                                 $text =  sprintf( __( '%1$s mentioned you', 'buddypress' ), $user_fullname );
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                break;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+               case 'update_reply':
+                       $link   = bp_get_notifications_permalink();
+                       $title  = __( 'New Activity reply', 'buddypress' );
+                       $amount = 'single';
+
+                       if ( (int) $total_items > 1 ) {
+                               $link   = add_query_arg( 'type', $action, $link );
+                               $text   = sprintf( __( 'You have %1$d new replies', 'buddypress' ), (int) $total_items );
+                               $amount = 'multiple';
+                       } else {
+                               $link   = bp_activity_get_permalink( $activity_id );
+                               $text   =  sprintf( __( '%1$s commented on one of your updates', 'buddypress' ), $user_fullname );
+                       }
+               break;
+
+               case 'comment_reply':
+                       $link   = bp_get_notifications_permalink();
+                       $title  = __( 'New Activity comment reply', 'buddypress' );
+                       $amount = 'single';
+
+                       if ( (int) $total_items > 1 ) {
+                               $link   = add_query_arg( 'type', $action, $link );
+                               $text   = sprintf( __( 'You have %1$d new comment replies', 'buddypress' ), (int) $total_items );
+                               $amount = 'multiple';
+                       } else {
+                               $link   = bp_activity_get_permalink( $activity_id );
+                               $text   =  sprintf( __( '%1$s replied to one your activity comments', 'buddypress' ), $user_fullname );
+                       }
+               break;
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        if ( 'string' == $format ) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * Filters the @mention notification for the string format.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          * Filters the activity notification for the string format.
</ins><span class="cx" style="display: block; padding: 0 10px">                  *
</span><span class="cx" style="display: block; padding: 0 10px">                 * This is a variable filter that is dependent on how many items
</span><span class="cx" style="display: block; padding: 0 10px">                 * need notified about. The two possible hooks are bp_activity_single_at_mentions_notification
</span><span class="cx" style="display: block; padding: 0 10px">                 * or bp_activity_multiple_at_mentions_notification.
</span><span class="cx" style="display: block; padding: 0 10px">                 *
</span><span class="cx" style="display: block; padding: 0 10px">                 * @since 1.5.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 * @since 2.6.0 use the $action_filter as a new dynamic portion of the filter name.
</ins><span class="cx" style="display: block; padding: 0 10px">                  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * @param string $string          HTML anchor tag for the mention.
-                * @param string $at_mention_link The permalink for the mention.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          * @param string $string          HTML anchor tag for the interaction.
+                * @param string $link            The permalink for the interaction.
</ins><span class="cx" style="display: block; padding: 0 10px">                  * @param int    $total_items     How many items being notified about.
</span><span class="cx" style="display: block; padding: 0 10px">                 * @param int    $activity_id     ID of the activity item being formatted.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * @param int    $poster_user_id  ID of the user posting the mention.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          * @param int    $user_id         ID of the user who inited the interaction.
</ins><span class="cx" style="display: block; padding: 0 10px">                  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $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 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $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 );
</ins><span class="cx" style="display: block; padding: 0 10px">         } else {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * Filters the @mention notification for any non-string format.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          * Filters the activity notification for any non-string format.
</ins><span class="cx" style="display: block; padding: 0 10px">                  *
</span><span class="cx" style="display: block; padding: 0 10px">                 * This is a variable filter that is dependent on how many items need notified about.
</span><span class="cx" style="display: block; padding: 0 10px">                 * The two possible hooks are bp_activity_single_at_mentions_notification
</span><span class="cx" style="display: block; padding: 0 10px">                 * or bp_activity_multiple_at_mentions_notification.
</span><span class="cx" style="display: block; padding: 0 10px">                 *
</span><span class="cx" style="display: block; padding: 0 10px">                 * @since 1.5.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 * @since 2.6.0 use the $action_filter as a new dynamic portion of the filter name.
</ins><span class="cx" style="display: block; padding: 0 10px">                  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * @param array  $array           Array holding the content and permalink for the mention notification.
-                * @param string $at_mention_link The permalink for the mention.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          * @param array  $array           Array holding the content and permalink for the interaction notification.
+                * @param string $link            The permalink for the interaction.
</ins><span class="cx" style="display: block; padding: 0 10px">                  * @param int    $total_items     How many items being notified about.
</span><span class="cx" style="display: block; padding: 0 10px">                 * @param int    $activity_id     ID of the activity item being formatted.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * @param int    $poster_user_id  ID of the user posting the mention.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          * @param int    $user_id         ID of the user who inited the interaction.
</ins><span class="cx" style="display: block; padding: 0 10px">                  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $return = apply_filters( 'bp_activity_' . $amount . '_at_mentions_notification', array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $return = apply_filters( 'bp_activity_' . $amount . '_' . $action_filter . '_notification', array(
</ins><span class="cx" style="display: block; padding: 0 10px">                         'text' => $text,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        'link' => $at_mention_link
-               ), $at_mention_link, (int) $total_items, $activity_id, $poster_user_id );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 'link' => $link
+               ), $link, (int) $total_items, $activity_id, $user_id );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -292,7 +359,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @param string $action            The type of activity item.
</span><span class="cx" style="display: block; padding: 0 10px">         * @param int    $item_id           The activity ID.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * @param int    $secondary_item_id @mention mentioner ID.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * @param int    $secondary_item_id The user ID who inited the interaction.
</ins><span class="cx" style="display: block; padding: 0 10px">          * @param int    $total_items       Total amount of items to format.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        do_action( 'activity_format_notifications', $action, $item_id, $secondary_item_id, $total_items );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -332,6 +399,54 @@
</span><span class="cx" style="display: block; padding: 0 10px"> add_action( 'bp_activity_sent_mention_email', 'bp_activity_at_mention_add_notification', 10, 5 );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Notify a member one of their activity received a reply.
+ *
+ * @since 2.6.0
+ *
+ * @param BP_Activity_Activity $activity     The original activity.
+ * @param int                  $comment_id   ID for the newly received comment.
+ * @param int                  $commenter_id ID of the user who made the comment.
+ */
+function bp_activity_update_reply_add_notification( $activity, $comment_id, $commenter_id ) {
+       if ( bp_is_active( 'notifications' ) ) {
+               bp_notifications_add_notification( array(
+                       'user_id'           => $activity->user_id,
+                       'item_id'           => $activity->id,
+                       'secondary_item_id' => $commenter_id,
+                       'component_name'    => buddypress()->activity->id,
+                       'component_action'  => 'update_reply',
+                       'date_notified'     => bp_core_current_time(),
+                       'is_new'            => 1,
+               ) );
+       }
+}
+add_action( 'bp_activity_sent_reply_to_update_notification', 'bp_activity_update_reply_add_notification', 10, 3 );
+
+/**
+ * Notify a member one of their activity comment received a reply.
+ *
+ * @since 2.6.0
+ *
+ * @param BP_Activity_Activity $activity_comment The parent activity.
+ * @param int                  $comment_id       ID for the newly received comment.
+ * @param int                  $commenter_id     ID of the user who made the comment.
+ */
+function bp_activity_comment_reply_add_notification( $activity_comment, $comment_id, $commenter_id ) {
+       if ( bp_is_active( 'notifications' ) ) {
+               bp_notifications_add_notification( array(
+                       'user_id'           => $activity_comment->user_id,
+                       'item_id'           => $activity_comment->item_id,
+                       'secondary_item_id' => $commenter_id,
+                       'component_name'    => buddypress()->activity->id,
+                       'component_action'  => 'comment_reply',
+                       'date_notified'     => bp_core_current_time(),
+                       'is_new'            => 1,
+               ) );
+       }
+}
+add_action( 'bp_activity_sent_reply_to_reply_notification', 'bp_activity_comment_reply_add_notification', 10, 3 );
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px">  * Mark at-mention notifications as read when users visit their Mentions page.
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @since 1.5.0
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -358,6 +473,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * Mark at-mention notification as read when user visits the activity with the mention.
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @since 2.0.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 2.6.0 Mark notifications for 'update_reply' and 'comment_reply' actions
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @param BP_Activity_Activity $activity Activity object.
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -370,8 +486,27 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // Mark as read any notifications for the current user related to this activity item.
-       bp_notifications_mark_notifications_by_item_id( bp_loggedin_user_id(), $activity->id, buddypress()->activity->id, 'new_at_mention' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Filter here to add the notification actions to mark as read
+        * when the single activity is displayed.
+        *
+        * @since 2.6.0
+        *
+        * @param array $value List of notification actions to mark as read.
+        */
+       $notification_actions = apply_filters( 'bp_activity_notification_actions_single_activity', array(
+               'new_at_mention',
+               'update_reply',
+               'comment_reply',
+       ) );
+
+       $user_id   = bp_loggedin_user_id();
+       $component = buddypress()->activity->id;
+
+       foreach ( $notification_actions as $action ) {
+               // Mark as read any notifications for the current user related to this activity item.
+               bp_notifications_mark_notifications_by_item_id( $user_id, $activity->id, $component, $action );
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> add_action( 'bp_activity_screen_single_activity_permalink', 'bp_activity_remove_screen_notifications_single_activity_permalink' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre></div>
<a id="trunksrcbpnotificationsbpnotificationstemplatephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/bp-notifications/bp-notifications-template.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/bp-notifications/bp-notifications-template.php  2016-04-20 19:16:16 UTC (rev 10714)
+++ trunk/src/bp-notifications/bp-notifications-template.php    2016-04-21 07:44:45 UTC (rev 10715)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -169,15 +169,29 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $user_id = bp_loggedin_user_id();
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        // Set the component action (by default false to get all actions)
+       $component_action = false;
+
+       if ( isset( $_REQUEST['type'] ) ) {
+               $component_action = sanitize_key( $_REQUEST['type'] );
+       }
+
+       // Set the search terms (by default an empty string to get all notifications)
+       $search_terms = '';
+
+       if ( isset( $_REQUEST['s'] ) ) {
+               $search_terms = stripslashes( $_REQUEST['s'] );
+       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">         // Parse the args.
</span><span class="cx" style="display: block; padding: 0 10px">        $r = bp_parse_args( $args, array(
</span><span class="cx" style="display: block; padding: 0 10px">                'id'                => false,
</span><span class="cx" style="display: block; padding: 0 10px">                'user_id'           => $user_id,
</span><span class="cx" style="display: block; padding: 0 10px">                'secondary_item_id' => false,
</span><span class="cx" style="display: block; padding: 0 10px">                'component_name'    => bp_notifications_get_registered_components(),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                'component_action'  => false,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         'component_action'  => $component_action,
</ins><span class="cx" style="display: block; padding: 0 10px">                 'is_new'            => $is_new,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                'search_terms'      => isset( $_REQUEST['s'] ) ? stripslashes( $_REQUEST['s'] ) : '',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         'search_terms'      => $search_terms,
</ins><span class="cx" style="display: block; padding: 0 10px">                 'order_by'          => 'date_notified',
</span><span class="cx" style="display: block; padding: 0 10px">                'sort_order'        => 'DESC',
</span><span class="cx" style="display: block; padding: 0 10px">                'meta_query'        => false,
</span></span></pre></div>
<a id="trunktestsphpunittestcasesactivitynotificationsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/testcases/activity/notifications.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/testcases/activity/notifications.php  2016-04-20 19:16:16 UTC (rev 10714)
+++ trunk/tests/phpunit/testcases/activity/notifications.php    2016-04-21 07:44:45 UTC (rev 10715)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -287,4 +287,91 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        'content' => sprintf( 'Hello! @%s', $u2_mentionname ),
</span><span class="cx" style="display: block; padding: 0 10px">                ) );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       /**
+        * @group bp_activity_format_notifications
+        */
+       public function test_bp_activity_format_notifications_new_at_mention() {
+               $this->test_format_filter = array();
+
+               // Current user is $this->u1, so $this->u2 posted the mention
+               $a = $this->factory->activity->create( array(
+                       'user_id' => $this->u2,
+                       'component' => buddypress()->activity->id,
+                       'type' => 'activity_update',
+                       'content' => 'fake new_at_mention activity',
+               ) );
+
+               add_filter( 'bp_activity_single_at_mentions_notification', array( $this, 'format_notification_filter' ), 10, 1 );
+               add_filter( 'bp_activity_multiple_at_mentions_notification', array( $this, 'format_notification_filter' ), 10, 1 );
+
+               $format_tests = array(
+                       'array_single'    => bp_activity_format_notifications( 'new_at_mention', $a, $this->u2, 1, 'array' ),
+                       'string_single'   => bp_activity_format_notifications( 'new_at_mention', $a, $this->u2, 1 ),
+                       'array_multiple'  => bp_activity_format_notifications( 'new_at_mention', $a, $this->u2, 2, 'array' ),
+                       'string_multiple' => bp_activity_format_notifications( 'new_at_mention', $a, $this->u2, 2 ),
+               );
+
+               remove_filter( 'bp_activity_single_at_mentions_notification', array( $this, 'format_notification_filter' ), 10, 1 );
+               remove_filter( 'bp_activity_multiple_at_mentions_notification', array( $this, 'format_notification_filter' ), 10, 1 );
+
+               $single = sprintf( __( '%1$s mentioned you', 'buddypress' ), bp_core_get_user_displayname( $this->u2 ) );
+               $multiple = 'You have 2 new mentions';
+
+               $this->assertContains( $single, $format_tests['string_single'] );
+               $this->assertContains( $single, $format_tests['array_single']['text'] );
+               $this->assertContains( $multiple, $format_tests['string_multiple'] );
+               $this->assertContains( $multiple, $format_tests['array_multiple']['text'] );
+
+               // Check filters
+               $this->assertTrue( 4 === count( $this->test_format_filter ) );
+       }
+
+       public function format_notification_filter( $return ) {
+               $this->test_format_filter[] = current_filter();
+               return $return;
+       }
+
+       /**
+        * @group bp_activity_update_reply_add_notification
+        * @group bp_activity_comment_reply_add_notification
+        */
+       public function test_bp_activity_comment_add_notification() {
+               $a = $this->factory->activity->create( array(
+                       'user_id' => $this->u1,
+                       'component' => buddypress()->activity->id,
+                       'type' => 'activity_update',
+                       'content' => 'Please comment this activity.',
+               ) );
+
+               $c = bp_activity_new_comment( array(
+                       'content'     => 'this is the comment',
+                       'user_id'     => $this->u2,
+                       'activity_id' => $a, // ID of the root activity item.
+                       'parent_id'   => false  // ID of a parent comment (optional).
+               ) );
+
+               $u3 = $this->factory->user->create();
+
+               $r3 = bp_activity_new_comment( array(
+                       'content'     => 'this is a reply to a comment',
+                       'user_id'     => $u3,
+                       'activity_id' => $a, // ID of the root activity item.
+                       'parent_id'   => $c  // ID of a parent comment (optional).
+               ) );
+
+               $u1_notifications = BP_Notifications_Notification::get( array(
+                       'user_id' => $this->u1,
+               ) );
+
+               $expected_commenters = array( $this->u2, $u3 );
+               $this->assertEquals( $expected_commenters, wp_list_pluck( $u1_notifications, 'secondary_item_id' ) );
+
+               $u2_notifications = BP_Notifications_Notification::get( array(
+                       'user_id' => $this->u2,
+               ) );
+
+               $expected_commenter = array( $u3 );
+               $this->assertEquals( $expected_commenter, wp_list_pluck( $u2_notifications, 'secondary_item_id' ) );
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre>
</div>
</div>

</body>
</html>