PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.11.0
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.11.0
2.11.0 2.10.0 2.10.01 2.9.1 2.9.0 2.8.1 2.8.0 2.7.7 2.7.5 2.7.0 2.6.01 2.6.0 2.5.0 2.4.01 trunk 1.0.90 1.0.91 1.0.92 1.0.93 1.0.94 1.0.95 1.0.96 1.0.97 1.0.98 1.0.99 All 78 releases
← All changes | app/Hooks/Handlers/NotificationEventHandler.php +361 -137 1.0.982.11.0 View file →
@@ -1,15 +1,14 @@
1 1 <?php
2 2
3 3 namespace FluentCommunity\App\Hooks\Handlers;
4 4
5 -use FluentCommunity\App\Functions\Utility;
6 5 use FluentCommunity\App\Models\Comment;
7 6 use FluentCommunity\App\Models\Feed;
8 7 use FluentCommunity\App\Models\Notification;
9 8 use FluentCommunity\App\Models\NotificationSubscriber;
10 9 use FluentCommunity\App\Models\SpaceUserPivot;
11 -use FluentCommunity\App\Services\Helper;
10 +use FluentCommunity\App\Services\FeedsHelper;
12 11 use FluentCommunity\Framework\Support\Arr;
13 12
14 13 class NotificationEventHandler
15 14 {
@@ -14,11 +13,12 @@
14 13 class NotificationEventHandler
15 14 {
16 15 public function register()
17 16 {
18 - add_action('fluent_community/comment_added', [$this, 'handleNewCommentEvent'], 10, 3);
17 + add_action('fluent_community/comment_added', [$this, 'handleNewCommentEvent'], 10, 2);
19 18 add_action('fluent_community/space_feed/created', [$this, 'handleNewSpaceFeed'], 10);
20 19 add_action('fluent_community/feed/react_added', [$this, 'handleNewFeedReact'], 10, 2);
20 + add_action('fluent_community/comment/react_added', [$this, 'handleNewCommentReact'], 10, 3);
21 21
22 22 add_action('fluent_community/space/member/role_updated', [$this, 'handleSpaceMemberRoleUpdated'], 10, 2);
23 23
24 24 /*
@@ -23,18 +23,17 @@
23 23
24 24 /*
25 25 * Mentions handler
26 26 */
27 - add_action('fluent_community/feed_mentioned', [$this, 'handleFeedMentions'], 10, 2);
28 -
27 + add_action('fluent_community/feed/created', [$this, 'maybeHandleMentionedUserIds'], 10, 1);
29 28 }
30 29
31 - public function handleNewCommentEvent($comment, $feed, $mentionedUsers = null)
30 + public function handleNewCommentEvent($comment, $feed)
32 31 {
33 - $this->commentNotificationToAuthorFeed($comment, $feed, $mentionedUsers);
32 + $this->commentNotificationToAuthorFeed($comment, $feed);
34 33
35 34 // now notify all users who commented on this feed
36 - $this->commentNotificationToFeedCommenters($comment, $feed, $mentionedUsers);
35 + $this->commentNotificationToFeedCommenters($comment, $feed);
37 36 }
38 37
39 38 public function handleNewSpaceFeed($feed)
40 39 {
@@ -61,11 +60,11 @@
61 60
62 61 $notificationContent = \sprintf(
63 62 /* translators: %1$s is the user name, %2$s is the feed title and %3$3s is the space title */
64 63 __('%1$s posted %2$s in %3$s', 'fluent-community'),
65 - '<b class="fcom_nudn">' . $user->display_name . '</b>',
64 + '<b class="fcom_nudn">' . esc_html($user->getPublicDisplayName()) . '</b>',
66 65 '<span class="fcom_nft">' . $feedTitle . '</span>',
67 - '<b class="fcom_nst">' . $space->title . '</b>'
66 + '<b class="fcom_nst">' . esc_html($space->title) . '</b>'
68 67 );
69 68
70 69 $route = $feed->getJsRoute();
71 70
@@ -88,9 +87,9 @@
88 87 if ($react->user_id == $feed->user_id) {
89 88 return;
90 89 }
91 90
92 - $feedTitle = $feed->getHumanExcerpt(60);
91 + $feedTitle = $feed->getHumanExcerpt(40);
93 92 $user = $react->user;
94 93
95 94 if ($feed->reactions_count > 1) {
96 95 // check if we have existing notification for this feed and user
@@ -100,10 +99,10 @@
100 99
101 100 if ($existingNotification) {
102 101 $notificationContent = \sprintf(
103 102 /* translators: %1$s is the user name, %2$s is the like count & %3$s is the feed title */
104 - __('%1$s and %2$s other people loved %3$s', 'fluent-community'),
105 - '<b class="fcom_nudn">' . $user->display_name . '</b>',
103 + __('%1$s and %2$s other people reacted to your post %3$s', 'fluent-community'),
104 + '<b class="fcom_nudn">' . esc_html($user->getPublicDisplayName()) . '</b>',
106 105 '<b class="fcom_nrc">' . ($feed->reactions_count - 1) . '</b>',
107 106 '<span class="fcom_nft">' . $feedTitle . '</span>'
108 107 );
109 108
@@ -121,10 +120,10 @@
121 120 }
122 121
123 122 $notificationContent = \sprintf(
124 123 /* translators: %1$s is the user name, %2$s is the feed title */
125 - __('%1$s loved %2$s', 'fluent-community'),
126 - '<b class="fcom_nudn">' . $user->display_name . '</b>',
124 + __('%1$s reacted to your post %2$s', 'fluent-community'),
125 + '<b class="fcom_nudn">' . esc_html($user->getPublicDisplayName()) . '</b>',
127 126 '<span class="fcom_nft">' . $feedTitle . '</span>'
128 127 );
129 128
130 129 $route = $feed->getJsRoute();
@@ -142,8 +141,62 @@
142 141
143 142 $notification->subscribe([$feed->user_id]);
144 143 }
145 144
145 + public function handleNewCommentReact($react, $comment, $feed)
146 + {
147 + if ($react->user_id == $comment->user_id) {
148 + return;
149 + }
150 +
151 + $commentExcerpt = $comment->getHumanExcerpt(40);
152 + $user = $react->user;
153 +
154 + if ($comment->reactions_count > 1) {
155 + $notificationContent = \sprintf(
156 + /* translators: %1$s is the user name, %2$s is the like count & %3$s is the comment excerpt */
157 + __('%1$s and %2$s other people reacted to your comment %3$s', 'fluent-community'),
158 + '<b class="fcom_nudn">' . esc_html($user->getPublicDisplayName()) . '</b>',
159 + '<b class="fcom_nrc">' . ($comment->reactions_count - 1) . '</b>',
160 + '<span class="fcom_nft">' . $commentExcerpt . '</span>'
161 + );
162 + } else {
163 + $notificationContent = \sprintf(
164 + /* translators: %1$s is the user name, %2$s is the comment excerpt */
165 + __('%1$s reacted to your comment %2$s', 'fluent-community'),
166 + '<b class="fcom_nudn">' . esc_html($user->getPublicDisplayName()) . '</b>',
167 + '<span class="fcom_nft">' . $commentExcerpt . '</span>'
168 + );
169 + }
170 +
171 + $existingNotification = Notification::where('feed_id', $feed->id)
172 + ->where('object_id', $comment->id)
173 + ->where('action', 'comment/react_added')
174 + ->first();
175 +
176 + if ($existingNotification) {
177 + $existingNotification->content = $notificationContent;
178 + $existingNotification->src_user_id = $user->ID;
179 + $existingNotification->save();
180 + NotificationSubscriber::where('object_id', $existingNotification->id)
181 + ->where('user_id', $comment->user_id)
182 + ->update(['is_read' => 0, 'updated_at' => current_time('mysql')]);
183 + return;
184 + }
185 +
186 + $notification = Notification::create([
187 + 'feed_id' => $feed->id,
188 + 'object_id' => $comment->id,
189 + 'src_user_id' => $user->ID,
190 + 'src_object_type' => 'comment',
191 + 'action' => 'comment/react_added',
192 + 'content' => $notificationContent,
193 + 'route' => $feed->getJsRoute(),
194 + ]);
195 +
196 + $notification->subscribe([$comment->user_id]);
197 + }
198 +
146 199 public function handleSpaceMemberRoleUpdated($space, $pivot)
147 200 {
148 201 $user = $pivot->user;
149 202
@@ -149,10 +202,10 @@
149 202
150 203 $notificationContent = \sprintf(
151 204 /* translators: %1$s is the role name, %2$s is the space title */
152 205 __('You have been added as %1$s in %2$s', 'fluent-community'),
153 - '<b>' . $pivot->role . '</b>',
154 - '<b>' . $space->title . '</b>'
206 + '<b>' . esc_html($pivot->role) . '</b>',
207 + '<b>' . esc_html($space->title) . '</b>'
155 208 );
156 209
157 210 $route = [
158 211 'name' => 'space_feeds',
@@ -172,22 +225,23 @@
172 225 $notification = Notification::create($notification);
173 226 $notification->subscribe([$pivot->user_id]);
174 227 }
175 228
176 - protected function commentNotificationToAuthorFeed(Comment $comment, Feed $feed, $mentionUsers = null)
229 + protected function commentNotificationToAuthorFeed(Comment $comment, Feed $feed)
177 230 {
178 - if ($comment->user_id == $feed->user_id) {
231 + $authorId = FeedsHelper::getNotificationAuthorId($feed);
232 +
233 + if ($comment->user_id == $authorId) {
179 234 return;
180 235 }
181 236
182 - if ($mentionUsers) {
183 - $mentionedUserIds = $mentionUsers->pluck('ID')->toArray();
184 - if (in_array($feed->user_id, $mentionedUserIds)) {
185 - return;
186 - }
237 + // Skip a mentioned author here; notifyMentionedUsers() notifies them instead.
238 + $mentionedUserIds = Arr::get($comment->meta, 'mentioned_user_ids', []);
239 + if (in_array($authorId, $mentionedUserIds)) {
240 + return;
187 241 }
188 242
189 - $commenter = '<b class="fcom_nudn">' . $comment->user->display_name . '</b>';
243 + $commenter = '<b class="fcom_nudn">' . esc_html($comment->user->getPublicDisplayName()) . '</b>';
190 244 $feedTitle = $feed->getHumanExcerpt(60);
191 245
192 246 $exist = null;
193 247 if ($feed->comments_count > 1) {
@@ -193,33 +247,55 @@
193 247 if ($feed->comments_count > 1) {
194 248 // check if we have existing notification for this feed and user
195 249 $exist = Notification::where('feed_id', $feed->id)
196 250 ->where('action', 'comment_added')
251 + ->whereHas('subscribers', function ($q) use ($authorId) {
252 + $q->where('user_id', $authorId);
253 + })
197 254 ->first();
198 255
199 - $totalUsers = $feed->comments->pluck('user_id')->unique()->count();
256 + $totalUsers = Comment::where('post_id', $feed->id)
257 + ->where('user_id', '!=', $authorId)
258 + ->distinct()
259 + ->count('user_id');
200 260
201 - if ($totalUsers > 1) {
202 - $commenter .= ' and ' . ($totalUsers - 1) . ' other people';
203 - }
204 -
205 261 if ($feed->space_id) {
206 - $notificationContent = \sprintf(
207 - /* translators: %1$s is the user name, %2$s is the people count, %3$s is the feed title and %4$s space title*/
208 - __('%1$s and %2$s other people commented on your post %3$s in %4$s', 'fluent-community'),
209 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
210 - '<b class="fcom_nrc">' . ($totalUsers - 1) . '</b>',
211 - '<span class="fcom_nft">' . $feedTitle . '</span>',
212 - '<b class="fcom_nst">' . $feed->space->title . '</b>'
213 - );
262 + if ($totalUsers > 1) {
263 + $notificationContent = \sprintf(
264 + /* translators: %1$s is the user name, %2$s is the people count, %3$s is the feed title and %4$s space title*/
265 + __('%1$s and %2$s other people commented on your post %3$s in %4$s', 'fluent-community'),
266 + $commenter,
267 + '<b class="fcom_nrc">' . ($totalUsers - 1) . '</b>',
268 + '<span class="fcom_nft">' . $feedTitle . '</span>',
269 + '<b class="fcom_nst">' . esc_html($feed->space->title) . '</b>'
270 + );
271 + } else {
272 + $notificationContent = \sprintf(
273 + /* translators: %1$s is the user name, %2$s is the feed title and %3$s space title*/
274 + __('%1$s commented on your post: %2$s in %3$s', 'fluent-community'),
275 + $commenter,
276 + '<span class="fcom_nft">' . $feedTitle . '</span>',
277 + '<b class="fcom_nst">' . esc_html($feed->space->title) . '</b>'
278 + );
279 + }
214 280 } else {
215 - $notificationContent = \sprintf(
216 - /* translators: %1$s is the user name, %2$s is the like count & %3$s is the feed title */
217 - __('%1$s and %2$s other people commented on your post %3$s', 'fluent-community'),
218 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
219 - '<b class="fcom_nrc">' . ($totalUsers - 1) . '</b>',
220 - '<span class="fcom_nft">' . $feedTitle . '</span>'
221 - );
281 +
282 + if ($totalUsers > 1) {
283 + $notificationContent = \sprintf(
284 + /* translators: %1$s is the user name, %2$s is the like count & %3$s is the feed title */
285 + __('%1$s and %2$s other people commented on your post %3$s', 'fluent-community'),
286 + $commenter,
287 + '<b class="fcom_nrc">' . ($totalUsers - 1) . '</b>',
288 + '<span class="fcom_nft">' . $feedTitle . '</span>'
289 + );
290 + } else {
291 + $notificationContent = \sprintf(
292 + /* translators: %1$s is the user name & %2$s is the feed title */
293 + __('%1$s commented on your post: %2$s', 'fluent-community'),
294 + $commenter,
295 + '<span class="fcom_nft">' . $feedTitle . '</span>'
296 + );
297 + }
222 298 }
223 299 } else {
224 300 if ($feed->space_id) {
225 301 $notificationContent = \sprintf(
@@ -224,23 +300,22 @@
224 300 if ($feed->space_id) {
225 301 $notificationContent = \sprintf(
226 302 /* translators: %1$s is the commenter name, %2$s is the feed title & %3$s is the space title */
227 303 __('%1$s commented on your post: %2$s in %3$s', 'fluent-community'),
228 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
304 + $commenter,
229 305 '<span class="fcom_nft">' . $feedTitle . '</span>',
230 - '<b class="fcom_nst">' . $feed->space->title . '</b>'
306 + '<b class="fcom_nst">' . esc_html($feed->space->title) . '</b>'
231 307 );
232 308 } else {
233 309 $notificationContent = \sprintf(
234 310 /* translators: %1$s is the commenter name & %2$s is the feed title */
235 311 __('%1$s commented on your post: %2$s', 'fluent-community'),
236 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
312 + $commenter,
237 313 '<span class="fcom_nft">' . $feedTitle . '</span>'
238 314 );
239 315 }
240 316 }
241 317
242 -
243 318 $route = $feed->getJsRoute();
244 319
245 320 if ($exist) {
246 321 $exist->content = $notificationContent;
@@ -249,13 +324,23 @@
249 324 $exist->object_id = $comment->id;
250 325 $exist->save();
251 326
252 327 NotificationSubscriber::where('object_id', $exist->id)
253 - ->where('user_id', $feed->user_id)
328 + ->where('user_id', $authorId)
254 329 ->update([
255 330 'is_read' => 0,
256 331 'updated_at' => current_time('mysql')
257 332 ]);
333 +
334 + do_action('fluent_community/notification/comment/notifed_to_author', [
335 + 'user_ids' => [$authorId],
336 + 'notification' => $exist,
337 + 'key' => 'notifed_to_author',
338 + 'comment' => $comment,
339 + 'feed' => $feed,
340 + 'created' => false
341 + ]);
342 +
258 343 return;
259 344 }
260 345
261 346 $notification = [
@@ -269,83 +354,152 @@
269 354 ];
270 355
271 356 $notification = Notification::create($notification);
272 357
273 - $notification->subscribe([$feed->user_id]);
358 + $notification->subscribe([$authorId]);
359 +
360 + do_action('fluent_community/notification/comment/notifed_to_author', [
361 + 'user_ids' => [$authorId],
362 + 'notification' => $notification,
363 + 'comment' => $comment,
364 + 'key' => 'notifed_to_author',
365 + 'feed' => $feed,
366 + 'created' => true
367 + ]);
274 368 }
275 369
276 - protected function commentNotificationToFeedCommenters($comment, $feed, $mentionedUsers = null)
370 + protected function commentNotificationToFeedCommenters($comment, $feed)
277 371 {
372 + $mentionedUserIds = Arr::get($comment->meta, 'mentioned_user_ids', []);
373 +
374 + // Notify mentioned users for both top-level comments and replies.
375 + if ($mentionedUserIds) {
376 + $this->notifyMentionedUsers($comment, $feed, $mentionedUserIds);
377 + }
378 +
278 379 if ($comment->parent_id) {
279 - return $this->notifyForChildCommentReply($comment, $feed);
380 + return $this->notifyForChildCommentReply($comment, $feed, $mentionedUserIds);
280 381 }
281 382
282 - $comments = Comment::whereNotIn('user_id', [$feed->user_id, $comment->user_id])
283 - ->select(['user_id'])
383 + $userIds = Comment::whereNotIn('user_id', [$feed->user_id, $comment->user_id])
284 384 ->where('post_id', $feed->id)
285 385 ->whereNull('parent_id')
286 - ->distinct('user_id')
287 - ->get();
386 + ->distinct()
387 + ->pluck('user_id')
388 + ->toArray();
288 389
289 - $userIds = $comments->pluck('user_id')->toArray();
290 -
291 - $mentionedUserIds = [];
292 -
293 - if ($mentionedUsers) {
294 - $mentionedUserIds = $mentionedUsers->pluck('ID')->toArray();
295 - }
296 -
297 390 if (!$userIds && !$mentionedUserIds) {
298 391 return;
299 392 }
300 393
301 - $feedTitle = $feed->getHumanExcerpt(60);
394 + $commenter = '<b class="fcom_nudn">' . esc_html($comment->user->getPublicDisplayName()) . '</b>';
395 + $feedTitle = '<span class="fcom_nft">' . $feed->getHumanExcerpt(60) . '</span>';
302 396
303 397 $route = $feed->getJsRoute();
398 + $space = $feed->space;
304 399
305 - if ($feed->space_id) {
306 - $space = $feed->space;
307 - $notificationContent = \sprintf(
308 - /* translators: %1$s is the commenter name, %2$s is the feed title & %3$s is the space title */
309 - __('%1$s also commented on %2$s in %3$s', 'fluent-community'),
310 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
311 - '<span class="fcom_nft">' . $feedTitle . '</span>',
312 - '<b class="fcom_nst">' . $space->title . '</b>'
313 - );
400 + if ($feed->comments_count > 1) {
401 + $totalUsers = Comment::where('post_id', $feed->id)
402 + ->where('user_id', '!=', $comment->user_id)
403 + ->distinct()
404 + ->count('user_id');
405 +
406 + if ($feed->space_id) {
407 + if ($totalUsers > 1) {
408 + $notificationContent = \sprintf(
409 + /* translators: %1$s is the user name, %2$s is the people count, %3$s is the feed title and %4$s space title*/
410 + __('%1$s and %2$s other people also commented on %3$s in %4$s', 'fluent-community'),
411 + $commenter,
412 + '<b class="fcom_nrc">' . ($totalUsers - 1) . '</b>',
413 + $feedTitle,
414 + '<b class="fcom_nst">' . esc_html($feed->space->title) . '</b>'
415 + );
416 + } else {
417 + $notificationContent = \sprintf(
418 + /* translators: %1$s is the user name, %2$s is the feed title and %3$s space title*/
419 + __('%1$s also commented on %2$s in %3$s', 'fluent-community'),
420 + $commenter,
421 + $feedTitle,
422 + '<b class="fcom_nst">' . esc_html($feed->space->title) . '</b>'
423 + );
424 + }
425 + } else {
426 + if ($totalUsers > 1) {
427 + $notificationContent = \sprintf(
428 + /* translators: %1$s is the user name, %2$s is the like count & %3$s is the feed title */
429 + __('%1$s and %2$s other people also commented on %3$s', 'fluent-community'),
430 + $commenter,
431 + '<b class="fcom_nrc">' . ($totalUsers - 1) . '</b>',
432 + $feedTitle,
433 + );
434 + } else {
435 + $notificationContent = \sprintf(
436 + /* translators: %1$s is the user name & %2$s is the feed title */
437 + __('%1$s also commented on %2$s', 'fluent-community'),
438 + $commenter,
439 + $feedTitle,
440 + );
441 + }
442 + }
314 443 } else {
315 - $notificationContent = \sprintf(
444 + if ($feed->space_id) {
445 + $notificationContent = \sprintf(
446 + /* translators: %1$s is the commenter name, %2$s is the feed title & %3$s is the space title */
447 + __('%1$s also commented on %2$s in %3$s', 'fluent-community'),
448 + $commenter,
449 + $feedTitle,
450 + '<b class="fcom_nst">' . esc_html($space->title) . '</b>'
451 + );
452 + } else {
453 + $notificationContent = \sprintf(
316 454 /* translators: %1$s is the commenter name & %2$s is the feed title */
317 - __('%1$s also commented on %2$s', 'fluent-community'),
318 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
319 - '<span class="fcom_nft">' . $feedTitle . '</span>'
320 - );
455 + __('%1$s also commented on %2$s', 'fluent-community'),
456 + $commenter,
457 + $feedTitle,
458 + );
459 + }
321 460 }
322 461
323 462 if ($mentionedUserIds) {
324 - $mentionNotification = Notification::create([
325 - 'feed_id' => $feed->id,
326 - 'object_id' => $comment->id,
327 - 'src_user_id' => $comment->user_id,
328 - 'src_object_type' => 'comment',
329 - 'action' => 'mention_added',
330 - 'content' => \sprintf(
331 - // translators: %1$s is the commenter name & %2$s is the feed title
332 - __('%1$s mentioned you in a comment at %2$s', 'fluent-community'),
333 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
334 - '<b class="fcom_nft">' . $feedTitle . '</b>'
335 - ),
336 - 'route' => $route,
337 - ]);
463 + $userIds = array_values(array_diff($userIds, $mentionedUserIds));
464 + }
338 465
339 - $mentionNotification->subscribe($mentionedUserIds);
466 + if (!$userIds) {
467 + return;
340 468 }
341 469
342 - if ($mentionedUserIds) {
343 - $userIds = array_values(array_diff($userIds, $mentionedUserIds));
470 + $existIds = Notification::where('feed_id', $feed->id)
471 + ->where('action', 'comment_added')
472 + ->whereDoesntHave('subscribers', function ($query) use ($feed, $comment) {
473 + $query->whereIn('user_id', [$feed->user_id, $comment->user_id]);
474 + })
475 + ->pluck('id')
476 + ->toArray();
477 +
478 + $existingSubscriberUserIds = [];
479 + if (!empty($existIds)) {
480 + Notification::whereIn('id', $existIds)->update([
481 + 'content' => $notificationContent,
482 + 'updated_at' => current_time('mysql'),
483 + 'src_user_id' => $comment->user_id,
484 + 'object_id' => $comment->id
485 + ]);
486 +
487 + $existingSubscriberUserIds = NotificationSubscriber::whereIn('object_id', $existIds)
488 + ->pluck('user_id')
489 + ->unique()
490 + ->toArray();
491 +
492 + NotificationSubscriber::whereIn('object_id', $existIds)
493 + ->whereIn('user_id', $existingSubscriberUserIds)
494 + ->update([
495 + 'is_read' => 0,
496 + 'updated_at' => current_time('mysql')
497 + ]);
344 498 }
345 499
346 - if (!$userIds) {
347 - return;
500 + if (!empty($existingSubscriberUserIds)) {
501 + $userIds = array_values(array_diff($userIds, $existingSubscriberUserIds));
348 502 }
349 503
350 504 $notification = [
351 505 'feed_id' => $feed->id,
@@ -355,16 +509,69 @@
355 509 'action' => 'comment_added',
356 510 'content' => $notificationContent,
357 511 'route' => $route,
358 512 ];
359 - $notification = Notification::create($notification);
360 - $notification->subscribe($userIds);
513 +
514 + foreach ($userIds as $userId) {
515 + $createdNotification = Notification::create($notification);
516 + $createdNotification->subscribe([$userId]);
517 + }
518 +
519 + $sendingUserIds = array_merge($userIds, $existingSubscriberUserIds);
520 +
521 + do_action('fluent_community/notification/comment/notifed_to_other_users', [
522 + 'user_ids' => $sendingUserIds,
523 + 'key' => 'notifed_to_other_users',
524 + 'notification' => $notification,
525 + 'comment' => $comment,
526 + 'feed' => $feed
527 + ]);
361 528 }
362 529
363 - protected function notifyForChildCommentReply($comment, $feed)
530 + protected function notifyMentionedUsers($comment, $feed, $mentionedUserIds)
364 531 {
532 + if (!$mentionedUserIds) {
533 + return;
534 + }
535 +
536 + $commenter = '<b class="fcom_nudn">' . esc_html($comment->user->getPublicDisplayName()) . '</b>';
537 + $feedTitle = '<span class="fcom_nft">' . $feed->getHumanExcerpt(60) . '</span>';
538 +
539 + $mentionNotification = Notification::create([
540 + 'feed_id' => $feed->id,
541 + 'object_id' => $comment->id,
542 + 'src_user_id' => $comment->user_id,
543 + 'src_object_type' => 'comment',
544 + 'action' => 'mention_added',
545 + 'content' => \sprintf(
546 + /* translators: %1$s is the commenter name & %2$s is the feed title */
547 + __('%1$s mentioned you in a comment at %2$s', 'fluent-community'),
548 + $commenter,
549 + $feedTitle,
550 + ),
551 + 'route' => $feed->getJsRoute(),
552 + ]);
553 +
554 + $mentionNotification->subscribe($mentionedUserIds);
555 +
556 + do_action('fluent_community/notification/comment/notifed_to_mentions', [
557 + 'user_ids' => $mentionedUserIds,
558 + 'notification' => $mentionNotification,
559 + 'key' => 'notifed_to_mentions',
560 + 'comment' => $comment,
561 + 'feed' => $feed
562 + ]);
563 +
564 + return $mentionNotification;
565 + }
566 +
567 + protected function notifyForChildCommentReply($comment, $feed, $mentionedUserIds = [])
568 + {
365 569 // This is a parent comment, so we need to notify the parent comment author & all child comment authors
366 - $childCommentUserIds = Comment::where('parent_id', $comment->parent_id)
570 + $childCommentUserIds = Comment::where(function ($q) use ($comment) {
571 + $q->where('parent_id', $comment->parent_id)
572 + ->orWhere('id', $comment->parent_id);
573 + })
367 574 ->whereNotIn('user_id', [$comment->user_id, $feed->user_id])
368 575 ->select(['user_id'])
369 576 ->distinct('user_id')
370 577 ->get()
@@ -370,14 +577,24 @@
370 577 ->get()
371 578 ->pluck('user_id')
372 579 ->toArray();
373 580
581 + // Mentioned users get a mention notification instead, so skip them here.
582 + if ($mentionedUserIds) {
583 + $childCommentUserIds = array_values(array_diff($childCommentUserIds, $mentionedUserIds));
584 + }
585 +
374 586 if (!$childCommentUserIds) {
375 587 return false;
376 588 }
377 589
590 + $commenter = '<b class="fcom_nudn">' . esc_html($comment->user->getPublicDisplayName()) . '</b>';
591 +
378 592 $existingNotification = Notification::where('object_id', $comment->parent_id)
379 593 ->where('action', 'child_comment_added')
594 + ->whereHas('subscribers', function ($q) use ($childCommentUserIds) {
595 + $q->whereIn('user_id', $childCommentUserIds);
596 + })
380 597 ->first();
381 598
382 599 if ($existingNotification) {
383 600 $newContent = \sprintf(
@@ -382,9 +599,9 @@
382 599 if ($existingNotification) {
383 600 $newContent = \sprintf(
384 601 /* translators: %1$s is the commenter name, %2$s is the comment user count & %3$s feed excerpt */
385 602 __('%1$s and %2$s other people replied to your comment at %3$s', 'fluent-community'),
386 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
603 + $commenter,
387 604 '<b class="fcom_nrc">' . count($childCommentUserIds) . '</b>',
388 605 '<b class="fcom_nft">' . $feed->getHumanExcerpt(60) . '</b>'
389 606 );
390 607
@@ -405,23 +622,31 @@
405 622 'is_read' => 0,
406 623 'updated_at' => current_time('mysql')
407 624 ]);
408 625
626 + do_action('fluent_community/notification/comment/notifed_to_thread_commetenter', [
627 + 'user_ids' => $childCommentUserIds,
628 + 'notification' => $existingNotification,
629 + 'key' => 'notifed_to_thread_commetenter',
630 + 'comment' => $comment,
631 + 'feed' => $feed
632 + ]);
633 +
409 634 return $existingNotification;
410 635 }
411 636
412 637 $notificationContent = \sprintf(
413 638 /* translators: %1$s is the commenter name & %2$s is the feed excerpt */
414 - __('%1$s replied your comment at %2$s', 'fluent-community'),
415 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
639 + __('%1$s replied to your comment at %2$s', 'fluent-community'),
640 + $commenter,
416 641 '<b class="fcom_nft">' . $feed->getHumanExcerpt(60) . '</b>'
417 642 );
418 643
419 644 $route = $feed->getJsRoute();
420 645
421 - if ($feed->space_id) {
422 - $space = $feed->space;
423 - }
646 + $route['query'] = [
647 + 'comment_id' => $comment->id
648 + ];
424 649
425 650 $notification = [
426 651 'feed_id' => $feed->id,
427 652 'object_id' => $comment->parent_id,
@@ -433,13 +658,29 @@
433 658 ];
434 659
435 660 $notification = Notification::create($notification);
436 661 $notification->subscribe($childCommentUserIds);
662 +
663 + do_action('fluent_community/notification/comment/notifed_to_thread_commetenter', [
664 + 'user_ids' => $childCommentUserIds,
665 + 'notification' => $notification,
666 + 'key' => 'notifed_to_thread_commetenter',
667 + 'comment' => $comment,
668 + 'feed' => $feed
669 + ]);
670 +
437 671 return $notification;
438 672 }
439 673
440 - public function handleFeedMentions($feed, $mentionedUsers)
674 + public function maybeHandleMentionedUserIds($feed)
441 675 {
676 + $mentionedUserIds = Arr::get($feed->meta, 'mentioned_user_ids', []);
677 + if (!$mentionedUserIds) {
678 + return;
679 + }
680 +
681 + do_action('fluent_community/feed_mentioned_user_ids', $feed, $mentionedUserIds);
682 +
442 683 $feedTitle = $feed->getHumanExcerpt(60);
443 684 $user = $feed->user;
444 685
445 686 $notificationContent = \sprintf(
@@ -444,9 +685,9 @@
444 685
445 686 $notificationContent = \sprintf(
446 687 /* translators: %1$s is the user name, %2$s is the feed title */
447 688 __('%1$s mentioned you in a post: %2$s', 'fluent-community'),
448 - '<b class="fcom_nudn">' . sanitize_text_field($user->display_name) . '</b>',
689 + '<b class="fcom_nudn">' . esc_html($user->getPublicDisplayName()) . '</b>',
449 690 '<b class="fcom_nft">' . $feedTitle . '</b>'
450 691 );
451 692
452 693 $route = $feed->getJsRoute();
@@ -461,11 +702,9 @@
461 702 ];
462 703
463 704 $notification = Notification::create($notification);
464 705
465 - $userIds = $mentionedUsers->pluck('ID')->toArray();
466 -
467 - $notification->subscribe($userIds);
706 + $notification->subscribe($mentionedUserIds);
468 707 }
469 708
470 709 private function maybeHasEveryoneTag(Feed $feed)
471 710 {
@@ -472,14 +711,9 @@
472 711 if (!$feed->space_id) {
473 712 return;
474 713 }
475 714
476 - $message = $feed->message;
477 - $pattern = '/(?<!\S)@everyone(?!\S)/';
478 -
479 - // match if the message contains @everyone
480 -
481 - if (!preg_match($pattern, $message)) {
715 + if (!$feed->isEnabledForEveryoneTag()) {
482 716 return;
483 717 }
484 718
485 719 // we have everyone
@@ -484,30 +718,20 @@
484 718
485 719 // we have everyone
486 720 // check if current user is a moderator or admin
487 721 $user = $feed->user;
488 -
489 722 $spaceRole = $user->getSpaceRole($feed->space);
490 -
491 723 if (!in_array($spaceRole, ['admin', 'moderator'])) {
492 724 return;
493 725 }
494 726
495 - $notificationSettings = Utility::getEmailNotificationSettings();
496 -
497 - if (Arr::get($notificationSettings, 'mention_mail') === 'yes') {
498 -
499 - do_action('fluent_community/feed/scheduling_everyone_tag', $feed);
500 -
501 - // Let's schedule an email hook to send email to everyone for this post
502 - // We are scheduling this after 5 minutes of the post publish for performance
503 - as_schedule_single_action(time() + 300, 'fluent_community/email_notify_users_everyone_tag', [
504 - $feed->id,
505 - 0
506 - ], 'fluent-community');
507 - }
508 -
509 -
727 + do_action('fluent_community/feed/scheduling_everyone_tag', $feed);
728 + // Let's schedule an email hook to send email to everyone for this post
729 + // We are scheduling this after 5 minutes of the post publish for performance
730 + as_schedule_single_action(time() + 300, 'fluent_community/email_notify_users_everyone_tag', [
731 + $feed->id,
732 + 0
733 + ], 'fluent-community');
510 734 }
511 735
512 736 private function willCreateFeedCreatedNotification($feed)
513 737 {