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 +368 -234 1.0.912.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,20 +60,14 @@
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 - $route = [
71 - 'name' => 'space_feed',
72 - 'params' => [
73 - 'space' => $space->slug,
74 - 'feed_slug' => $feed->slug
75 - ]
76 - ];
69 + $route = $feed->getJsRoute();
77 70
78 71 $notification = [
79 72 'feed_id' => $feed->id,
80 73 'src_user_id' => $user->ID,
@@ -94,9 +87,9 @@
94 87 if ($react->user_id == $feed->user_id) {
95 88 return;
96 89 }
97 90
98 - $feedTitle = $feed->getHumanExcerpt(60);
91 + $feedTitle = $feed->getHumanExcerpt(40);
99 92 $user = $react->user;
100 93
101 94 if ($feed->reactions_count > 1) {
102 95 // check if we have existing notification for this feed and user
@@ -106,10 +99,10 @@
106 99
107 100 if ($existingNotification) {
108 101 $notificationContent = \sprintf(
109 102 /* translators: %1$s is the user name, %2$s is the like count & %3$s is the feed title */
110 - __('%1$s and %2$s other people loved %3$s', 'fluent-community'),
111 - '<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>',
112 105 '<b class="fcom_nrc">' . ($feed->reactions_count - 1) . '</b>',
113 106 '<span class="fcom_nft">' . $feedTitle . '</span>'
114 107 );
115 108
@@ -127,30 +120,14 @@
127 120 }
128 121
129 122 $notificationContent = \sprintf(
130 123 /* translators: %1$s is the user name, %2$s is the feed title */
131 - __('%1$s loved %2$s', 'fluent-community'),
132 - '<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>',
133 126 '<span class="fcom_nft">' . $feedTitle . '</span>'
134 127 );
135 128
136 - if ($feed->space_id) {
137 - $space = $feed->space;
138 - $route = [
139 - 'name' => 'space_feed',
140 - 'params' => [
141 - 'space' => $space->slug,
142 - 'feed_slug' => $feed->slug
143 - ]
144 - ];
145 - } else {
146 - $route = [
147 - 'name' => 'single_feed',
148 - 'params' => [
149 - 'feed_slug' => $feed->slug
150 - ]
151 - ];
152 - }
129 + $route = $feed->getJsRoute();
153 130
154 131 $notification = [
155 132 'feed_id' => $feed->id,
156 133 'src_user_id' => $user->ID,
@@ -164,8 +141,62 @@
164 141
165 142 $notification->subscribe([$feed->user_id]);
166 143 }
167 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 +
168 199 public function handleSpaceMemberRoleUpdated($space, $pivot)
169 200 {
170 201 $user = $pivot->user;
171 202
@@ -171,10 +202,10 @@
171 202
172 203 $notificationContent = \sprintf(
173 204 /* translators: %1$s is the role name, %2$s is the space title */
174 205 __('You have been added as %1$s in %2$s', 'fluent-community'),
175 - '<b>' . $pivot->role . '</b>',
176 - '<b>' . $space->title . '</b>'
206 + '<b>' . esc_html($pivot->role) . '</b>',
207 + '<b>' . esc_html($space->title) . '</b>'
177 208 );
178 209
179 210 $route = [
180 211 'name' => 'space_feeds',
@@ -194,22 +225,23 @@
194 225 $notification = Notification::create($notification);
195 226 $notification->subscribe([$pivot->user_id]);
196 227 }
197 228
198 - protected function commentNotificationToAuthorFeed(Comment $comment, Feed $feed, $mentionUsers = null)
229 + protected function commentNotificationToAuthorFeed(Comment $comment, Feed $feed)
199 230 {
200 - if ($comment->user_id == $feed->user_id) {
231 + $authorId = FeedsHelper::getNotificationAuthorId($feed);
232 +
233 + if ($comment->user_id == $authorId) {
201 234 return;
202 235 }
203 236
204 - if ($mentionUsers) {
205 - $mentionedUserIds = $mentionUsers->pluck('ID')->toArray();
206 - if (in_array($feed->user_id, $mentionedUserIds)) {
207 - return;
208 - }
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;
209 241 }
210 242
211 - $commenter = '<b class="fcom_nudn">' . $comment->user->display_name . '</b>';
243 + $commenter = '<b class="fcom_nudn">' . esc_html($comment->user->getPublicDisplayName()) . '</b>';
212 244 $feedTitle = $feed->getHumanExcerpt(60);
213 245
214 246 $exist = null;
215 247 if ($feed->comments_count > 1) {
@@ -215,33 +247,55 @@
215 247 if ($feed->comments_count > 1) {
216 248 // check if we have existing notification for this feed and user
217 249 $exist = Notification::where('feed_id', $feed->id)
218 250 ->where('action', 'comment_added')
251 + ->whereHas('subscribers', function ($q) use ($authorId) {
252 + $q->where('user_id', $authorId);
253 + })
219 254 ->first();
220 255
221 - $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');
222 260
223 - if ($totalUsers > 1) {
224 - $commenter .= ' and ' . ($totalUsers - 1) . ' other people';
225 - }
226 -
227 261 if ($feed->space_id) {
228 - $notificationContent = \sprintf(
229 - /* translators: %1$s is the user name, %2$s is the people count, %3$s is the feed title and %4$s space title*/
230 - __('%1$s and %2$s other people commented on your post %3$s in %4$s', 'fluent-community'),
231 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
232 - '<b class="fcom_nrc">' . ($totalUsers - 1) . '</b>',
233 - '<span class="fcom_nft">' . $feedTitle . '</span>',
234 - '<b class="fcom_nst">' . $feed->space->title . '</b>'
235 - );
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 + }
236 280 } else {
237 - $notificationContent = \sprintf(
238 - /* translators: %1$s is the user name, %2$s is the like count & %3$s is the feed title */
239 - __('%1$s and %2$s other people commented on your post %3$s', 'fluent-community'),
240 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
241 - '<b class="fcom_nrc">' . ($totalUsers - 1) . '</b>',
242 - '<span class="fcom_nft">' . $feedTitle . '</span>'
243 - );
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 + }
244 298 }
245 299 } else {
246 300 if ($feed->space_id) {
247 301 $notificationContent = \sprintf(
@@ -246,38 +300,23 @@
246 300 if ($feed->space_id) {
247 301 $notificationContent = \sprintf(
248 302 /* translators: %1$s is the commenter name, %2$s is the feed title & %3$s is the space title */
249 303 __('%1$s commented on your post: %2$s in %3$s', 'fluent-community'),
250 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
304 + $commenter,
251 305 '<span class="fcom_nft">' . $feedTitle . '</span>',
252 - '<b class="fcom_nst">' . $feed->space->title . '</b>'
306 + '<b class="fcom_nst">' . esc_html($feed->space->title) . '</b>'
253 307 );
254 308 } else {
255 309 $notificationContent = \sprintf(
256 310 /* translators: %1$s is the commenter name & %2$s is the feed title */
257 311 __('%1$s commented on your post: %2$s', 'fluent-community'),
258 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
312 + $commenter,
259 313 '<span class="fcom_nft">' . $feedTitle . '</span>'
260 314 );
261 315 }
262 316 }
263 317
264 - if ($feed->space_id) {
265 - $route = [
266 - 'name' => 'space_feed',
267 - 'params' => [
268 - 'space' => $feed->space->slug,
269 - 'feed_slug' => $feed->slug
270 - ]
271 - ];
272 - } else {
273 - $route = [
274 - 'name' => 'single_feed',
275 - 'params' => [
276 - 'feed_slug' => $feed->slug
277 - ]
278 - ];
279 - }
318 + $route = $feed->getJsRoute();
280 319
281 320 if ($exist) {
282 321 $exist->content = $notificationContent;
283 322 $exist->updated_at = current_time('mysql');
@@ -285,13 +324,23 @@
285 324 $exist->object_id = $comment->id;
286 325 $exist->save();
287 326
288 327 NotificationSubscriber::where('object_id', $exist->id)
289 - ->where('user_id', $feed->user_id)
328 + ->where('user_id', $authorId)
290 329 ->update([
291 330 'is_read' => 0,
292 331 'updated_at' => current_time('mysql')
293 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 +
294 343 return;
295 344 }
296 345
297 346 $notification = [
@@ -305,102 +354,152 @@
305 354 ];
306 355
307 356 $notification = Notification::create($notification);
308 357
309 - $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 + ]);
310 368 }
311 369
312 - protected function commentNotificationToFeedCommenters($comment, $feed, $mentionedUsers = null)
370 + protected function commentNotificationToFeedCommenters($comment, $feed)
313 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 +
314 379 if ($comment->parent_id) {
315 - return $this->notifyForChildCommentReply($comment, $feed);
380 + return $this->notifyForChildCommentReply($comment, $feed, $mentionedUserIds);
316 381 }
317 382
318 - $comments = Comment::whereNotIn('user_id', [$feed->user_id, $comment->user_id])
319 - ->select(['user_id'])
383 + $userIds = Comment::whereNotIn('user_id', [$feed->user_id, $comment->user_id])
320 384 ->where('post_id', $feed->id)
321 385 ->whereNull('parent_id')
322 - ->distinct('user_id')
323 - ->get();
386 + ->distinct()
387 + ->pluck('user_id')
388 + ->toArray();
324 389
325 - $userIds = $comments->pluck('user_id')->toArray();
326 -
327 - $mentionedUserIds = [];
328 -
329 - if ($mentionedUsers) {
330 - $mentionedUserIds = $mentionedUsers->pluck('ID')->toArray();
331 - }
332 -
333 390 if (!$userIds && !$mentionedUserIds) {
334 391 return;
335 392 }
336 393
337 - $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>';
338 396
339 - $route = [
340 - 'name' => 'single_feed',
341 - 'params' => [
342 - 'feed_slug' => $feed->slug
343 - ],
344 - 'query' => [
345 - 'comment_id' => $comment->id
346 - ]
347 - ];
397 + $route = $feed->getJsRoute();
398 + $space = $feed->space;
348 399
349 - if ($feed->space_id) {
350 - $space = $feed->space;
351 - $notificationContent = \sprintf(
352 - /* translators: %1$s is the commenter name, %2$s is the feed title & %3$s is the space title */
353 - __('%1$s also commented on %2$s in %3$s', 'fluent-community'),
354 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
355 - '<span class="fcom_nft">' . $feedTitle . '</span>',
356 - '<b class="fcom_nst">' . $space->title . '</b>'
357 - );
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');
358 405
359 - $route = [
360 - 'name' => 'space_feed',
361 - 'params' => [
362 - 'space' => $space->slug,
363 - 'feed_slug' => $feed->slug
364 - ],
365 - 'query' => [
366 - 'comment_id' => $comment->id
367 - ]
368 - ];
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 + }
369 443 } else {
370 - $notificationContent = \sprintf(
371 - /* translators: %1$s is the commenter name & %2$s is the feed title */
372 - __('%1$s also commented on %2$s', 'fluent-community'),
373 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
374 - '<span class="fcom_nft">' . $feedTitle . '</span>'
375 - );
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(
454 + /* translators: %1$s is the commenter name & %2$s is the feed title */
455 + __('%1$s also commented on %2$s', 'fluent-community'),
456 + $commenter,
457 + $feedTitle,
458 + );
459 + }
376 460 }
377 461
378 462 if ($mentionedUserIds) {
379 - $mentionNotification = Notification::create([
380 - 'feed_id' => $feed->id,
381 - 'object_id' => $comment->id,
382 - 'src_user_id' => $comment->user_id,
383 - 'src_object_type' => 'comment',
384 - 'action' => 'mention_added',
385 - 'content' => \sprintf(
386 - // translators: %1$s is the commenter name & %2$s is the feed title
387 - __('%1$s mentioned you in a comment at %2$s', 'fluent-community'),
388 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
389 - '<b class="fcom_nft">' . $feedTitle . '</b>'
390 - ),
391 - 'route' => $route,
392 - ]);
463 + $userIds = array_values(array_diff($userIds, $mentionedUserIds));
464 + }
393 465
394 - $mentionNotification->subscribe($mentionedUserIds);
466 + if (!$userIds) {
467 + return;
395 468 }
396 469
397 - if ($mentionedUserIds) {
398 - $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 + ]);
399 498 }
400 499
401 - if (!$userIds) {
402 - return;
500 + if (!empty($existingSubscriberUserIds)) {
501 + $userIds = array_values(array_diff($userIds, $existingSubscriberUserIds));
403 502 }
404 503
405 504 $notification = [
406 505 'feed_id' => $feed->id,
@@ -410,16 +509,69 @@
410 509 'action' => 'comment_added',
411 510 'content' => $notificationContent,
412 511 'route' => $route,
413 512 ];
414 - $notification = Notification::create($notification);
415 - $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 + ]);
416 528 }
417 529
418 - protected function notifyForChildCommentReply($comment, $feed)
530 + protected function notifyMentionedUsers($comment, $feed, $mentionedUserIds)
419 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 + {
420 569 // This is a parent comment, so we need to notify the parent comment author & all child comment authors
421 - $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 + })
422 574 ->whereNotIn('user_id', [$comment->user_id, $feed->user_id])
423 575 ->select(['user_id'])
424 576 ->distinct('user_id')
425 577 ->get()
@@ -425,21 +577,31 @@
425 577 ->get()
426 578 ->pluck('user_id')
427 579 ->toArray();
428 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 +
429 586 if (!$childCommentUserIds) {
430 587 return false;
431 588 }
432 589
590 + $commenter = '<b class="fcom_nudn">' . esc_html($comment->user->getPublicDisplayName()) . '</b>';
591 +
433 592 $existingNotification = Notification::where('object_id', $comment->parent_id)
434 593 ->where('action', 'child_comment_added')
594 + ->whereHas('subscribers', function ($q) use ($childCommentUserIds) {
595 + $q->whereIn('user_id', $childCommentUserIds);
596 + })
435 597 ->first();
436 598
437 599 if ($existingNotification) {
438 600 $newContent = \sprintf(
439 601 /* translators: %1$s is the commenter name, %2$s is the comment user count & %3$s feed excerpt */
440 - __('%1$s and %2$s other people replied your comment at %3$s', 'fluent-community'),
441 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
602 + __('%1$s and %2$s other people replied to your comment at %3$s', 'fluent-community'),
603 + $commenter,
442 604 '<b class="fcom_nrc">' . count($childCommentUserIds) . '</b>',
443 605 '<b class="fcom_nft">' . $feed->getHumanExcerpt(60) . '</b>'
444 606 );
445 607
@@ -460,43 +622,32 @@
460 622 'is_read' => 0,
461 623 'updated_at' => current_time('mysql')
462 624 ]);
463 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 +
464 634 return $existingNotification;
465 635 }
466 636
467 637 $notificationContent = \sprintf(
468 638 /* translators: %1$s is the commenter name & %2$s is the feed excerpt */
469 - __('%1$s replied your comment at %2$s', 'fluent-community'),
470 - '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
639 + __('%1$s replied to your comment at %2$s', 'fluent-community'),
640 + $commenter,
471 641 '<b class="fcom_nft">' . $feed->getHumanExcerpt(60) . '</b>'
472 642 );
473 643
474 - $route = [
475 - 'name' => 'single_feed',
476 - 'params' => [
477 - 'feed_slug' => $feed->slug
478 - ],
479 - 'query' => [
480 - 'comment_id' => $comment->id
481 - ]
644 + $route = $feed->getJsRoute();
645 +
646 + $route['query'] = [
647 + 'comment_id' => $comment->id
482 648 ];
483 649
484 - if ($feed->space_id) {
485 - $space = $feed->space;
486 -
487 - $route = [
488 - 'name' => 'space_feed',
489 - 'params' => [
490 - 'space' => $space->slug,
491 - 'feed_slug' => $feed->slug
492 - ],
493 - 'query' => [
494 - 'comment_id' => $comment->id
495 - ]
496 - ];
497 - }
498 -
499 650 $notification = [
500 651 'feed_id' => $feed->id,
501 652 'object_id' => $comment->parent_id,
502 653 'src_user_id' => $comment->user_id,
@@ -507,13 +658,29 @@
507 658 ];
508 659
509 660 $notification = Notification::create($notification);
510 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 +
511 671 return $notification;
512 672 }
513 673
514 - public function handleFeedMentions($feed, $mentionedUsers)
674 + public function maybeHandleMentionedUserIds($feed)
515 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 +
516 683 $feedTitle = $feed->getHumanExcerpt(60);
517 684 $user = $feed->user;
518 685
519 686 $notificationContent = \sprintf(
@@ -518,29 +685,13 @@
518 685
519 686 $notificationContent = \sprintf(
520 687 /* translators: %1$s is the user name, %2$s is the feed title */
521 688 __('%1$s mentioned you in a post: %2$s', 'fluent-community'),
522 - '<b class="fcom_nudn">' . sanitize_text_field($user->display_name) . '</b>',
689 + '<b class="fcom_nudn">' . esc_html($user->getPublicDisplayName()) . '</b>',
523 690 '<b class="fcom_nft">' . $feedTitle . '</b>'
524 691 );
525 692
526 - if ($feed->space_id) {
527 - $space = $feed->space;
528 - $route = [
529 - 'name' => 'space_feed',
530 - 'params' => [
531 - 'space' => $space->slug,
532 - 'feed_slug' => $feed->slug
533 - ]
534 - ];
535 - } else {
536 - $route = [
537 - 'name' => 'single_feed',
538 - 'params' => [
539 - 'feed_slug' => $feed->slug
540 - ]
541 - ];
542 - }
693 + $route = $feed->getJsRoute();
543 694
544 695 $notification = [
545 696 'feed_id' => $feed->id,
546 697 'src_user_id' => $user->ID,
@@ -551,11 +702,9 @@
551 702 ];
552 703
553 704 $notification = Notification::create($notification);
554 705
555 - $userIds = $mentionedUsers->pluck('ID')->toArray();
556 -
557 - $notification->subscribe($userIds);
706 + $notification->subscribe($mentionedUserIds);
558 707 }
559 708
560 709 private function maybeHasEveryoneTag(Feed $feed)
561 710 {
@@ -562,14 +711,9 @@
562 711 if (!$feed->space_id) {
563 712 return;
564 713 }
565 714
566 - $message = $feed->message;
567 - $pattern = '/(?<!\S)@everyone(?!\S)/';
568 -
569 - // match if the message contains @everyone
570 -
571 - if (!preg_match($pattern, $message)) {
715 + if (!$feed->isEnabledForEveryoneTag()) {
572 716 return;
573 717 }
574 718
575 719 // we have everyone
@@ -574,30 +718,20 @@
574 718
575 719 // we have everyone
576 720 // check if current user is a moderator or admin
577 721 $user = $feed->user;
578 -
579 722 $spaceRole = $user->getSpaceRole($feed->space);
580 -
581 723 if (!in_array($spaceRole, ['admin', 'moderator'])) {
582 724 return;
583 725 }
584 726
585 - $notificationSettings = Utility::getEmailNotificationSettings();
586 -
587 - if (Arr::get($notificationSettings, 'mention_mail') === 'yes') {
588 -
589 - do_action('fluent_community/feed/scheduling_everyone_tag', $feed);
590 -
591 - // Let's schedule an email hook to send email to everyone for this post
592 - // We are scheduling this after 5 minutes of the post publish for performance
593 - as_schedule_single_action(time() + 300, 'fluent_community/email_notify_users_everyone_tag', [
594 - $feed->id,
595 - 0
596 - ], 'fluent-community');
597 - }
598 -
599 -
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');
600 734 }
601 735
602 736 private function willCreateFeedCreatedNotification($feed)
603 737 {