PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.4.01
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.4.01
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
fluent-community / app / Hooks / Handlers / NotificationEventHandler.php

NotificationEventHandler.php in FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses 2.4.01, at app/Hooks/Handlers/NotificationEventHandler.php

672 lines 25.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCommunity\App\Hooks\Handlers;
4
5 use FluentCommunity\App\Models\Comment;
6 use FluentCommunity\App\Models\Feed;
7 use FluentCommunity\App\Models\Notification;
8 use FluentCommunity\App\Models\NotificationSubscriber;
9 use FluentCommunity\App\Models\SpaceUserPivot;
10 use FluentCommunity\Framework\Support\Arr;
11
12 class NotificationEventHandler
13 {
14 public function register()
15 {
16 add_action('fluent_community/comment_added', [$this, 'handleNewCommentEvent'], 10, 2);
17 add_action('fluent_community/space_feed/created', [$this, 'handleNewSpaceFeed'], 10);
18 add_action('fluent_community/feed/react_added', [$this, 'handleNewFeedReact'], 10, 2);
19
20 add_action('fluent_community/space/member/role_updated', [$this, 'handleSpaceMemberRoleUpdated'], 10, 2);
21
22 /*
23 * Mentions handler
24 */
25 add_action('fluent_community/feed/created', [$this, 'maybeHandleMentionedUserIds'], 10, 1);
26 }
27
28 public function handleNewCommentEvent($comment, $feed)
29 {
30 $this->commentNotificationToAuthorFeed($comment, $feed);
31
32 // now notify all users who commented on this feed
33 $this->commentNotificationToFeedCommenters($comment, $feed);
34 }
35
36 public function handleNewSpaceFeed($feed)
37 {
38 if (!$this->willCreateFeedCreatedNotification($feed)) {
39 return;
40 }
41
42 $user = $feed->user;
43 $space = $feed->space;
44
45 $this->maybeHasEveryoneTag($feed);
46
47 $userIds = SpaceUserPivot::where('space_id', $space->id)
48 ->where('user_id', '!=', $user->ID)
49 ->where('status', 'active')
50 ->pluck('user_id')
51 ->toArray();
52
53 if (!$userIds) {
54 return;
55 }
56
57 $feedTitle = $feed->getHumanExcerpt(60);
58
59 $notificationContent = \sprintf(
60 /* translators: %1$s is the user name, %2$s is the feed title and %3$3s is the space title */
61 __('%1$s posted %2$s in %3$s', 'fluent-community'),
62 '<b class="fcom_nudn">' . esc_html($user->display_name) . '</b>',
63 '<span class="fcom_nft">' . $feedTitle . '</span>',
64 '<b class="fcom_nst">' . esc_html($space->title) . '</b>'
65 );
66
67 $route = $feed->getJsRoute();
68
69 $notification = [
70 'feed_id' => $feed->id,
71 'src_user_id' => $user->ID,
72 'src_object_type' => 'feed',
73 'action' => 'space_feed/created',
74 'content' => $notificationContent,
75 'route' => $route,
76 ];
77
78 $notification = Notification::create($notification);
79
80 $notification->subscribe($userIds);
81 }
82
83 public function handleNewFeedReact($react, $feed)
84 {
85 if ($react->user_id == $feed->user_id) {
86 return;
87 }
88
89 $feedTitle = $feed->getHumanExcerpt(60);
90 $user = $react->user;
91
92 if ($feed->reactions_count > 1) {
93 // check if we have existing notification for this feed and user
94 $existingNotification = Notification::where('feed_id', $feed->id)
95 ->where('action', 'feed/react_added')
96 ->first();
97
98 if ($existingNotification) {
99 $notificationContent = \sprintf(
100 /* translators: %1$s is the user name, %2$s is the like count & %3$s is the feed title */
101 __('%1$s and %2$s other people reacted to %3$s', 'fluent-community'),
102 '<b class="fcom_nudn">' . esc_html($user->display_name) . '</b>',
103 '<b class="fcom_nrc">' . ($feed->reactions_count - 1) . '</b>',
104 '<span class="fcom_nft">' . $feedTitle . '</span>'
105 );
106
107 $existingNotification->content = $notificationContent;
108 $existingNotification->src_user_id = $user->ID;
109 $existingNotification->save();
110 NotificationSubscriber::where('object_id', $existingNotification->id)
111 ->where('user_id', $feed->user_id)
112 ->update([
113 'is_read' => 0,
114 'updated_at' => current_time('mysql')
115 ]);
116 return;
117 }
118 }
119
120 $notificationContent = \sprintf(
121 /* translators: %1$s is the user name, %2$s is the feed title */
122 __('%1$s reacted to %2$s', 'fluent-community'),
123 '<b class="fcom_nudn">' . esc_html($user->display_name) . '</b>',
124 '<span class="fcom_nft">' . $feedTitle . '</span>'
125 );
126
127 $route = $feed->getJsRoute();
128
129 $notification = [
130 'feed_id' => $feed->id,
131 'src_user_id' => $user->ID,
132 'src_object_type' => 'feed',
133 'action' => 'feed/react_added',
134 'content' => $notificationContent,
135 'route' => $route,
136 ];
137
138 $notification = Notification::create($notification);
139
140 $notification->subscribe([$feed->user_id]);
141 }
142
143 public function handleSpaceMemberRoleUpdated($space, $pivot)
144 {
145 $user = $pivot->user;
146
147 $notificationContent = \sprintf(
148 /* translators: %1$s is the role name, %2$s is the space title */
149 __('You have been added as %1$s in %2$s', 'fluent-community'),
150 '<b>' . $pivot->role . '</b>',
151 '<b>' . $space->title . '</b>'
152 );
153
154 $route = [
155 'name' => 'space_feeds',
156 'params' => [
157 'space' => $space->slug
158 ]
159 ];
160
161 $notification = [
162 'object_id' => $space->id,
163 'src_user_id' => $user->ID,
164 'src_object_type' => 'space',
165 'action' => 'space/member/role_updated',
166 'content' => $notificationContent,
167 'route' => $route,
168 ];
169 $notification = Notification::create($notification);
170 $notification->subscribe([$pivot->user_id]);
171 }
172
173 protected function commentNotificationToAuthorFeed(Comment $comment, Feed $feed)
174 {
175 if ($comment->user_id == $feed->user_id) {
176 return;
177 }
178
179 $mentionedUserIds = Arr::get($feed->meta, 'mentioned_user_ids', []);
180 if (in_array($feed->user_id, $mentionedUserIds)) {
181 return;
182 }
183
184 $commenter = '<b class="fcom_nudn">' . esc_html($comment->user->display_name) . '</b>';
185 $feedTitle = $feed->getHumanExcerpt(60);
186
187 $exist = null;
188 if ($feed->comments_count > 1) {
189 // check if we have existing notification for this feed and user
190 $exist = Notification::where('feed_id', $feed->id)
191 ->where('action', 'comment_added')
192 ->first();
193
194 $totalUsers = $feed->comments
195 ->where('user_id', '!=', $feed->user_id)
196 ->pluck('user_id')
197 ->unique()
198 ->count();
199
200 if ($feed->space_id) {
201 if ($totalUsers > 1) {
202 $notificationContent = \sprintf(
203 /* translators: %1$s is the user name, %2$s is the people count, %3$s is the feed title and %4$s space title*/
204 __('%1$s and %2$s other people commented on your post %3$s in %4$s', 'fluent-community'),
205 $commenter,
206 '<b class="fcom_nrc">' . ($totalUsers - 1) . '</b>',
207 '<span class="fcom_nft">' . $feedTitle . '</span>',
208 '<b class="fcom_nst">' . $feed->space->title . '</b>'
209 );
210 } else {
211 $notificationContent = \sprintf(
212 /* translators: %1$s is the user name, %2$s is the feed title and %3$s space title*/
213 __('%1$s commented on your post: %2$s in %3$s', 'fluent-community'),
214 $commenter,
215 '<span class="fcom_nft">' . $feedTitle . '</span>',
216 '<b class="fcom_nst">' . $feed->space->title . '</b>'
217 );
218 }
219 } else {
220
221 if ($totalUsers > 1) {
222 $notificationContent = \sprintf(
223 /* translators: %1$s is the user name, %2$s is the like count & %3$s is the feed title */
224 __('%1$s and %2$s other people commented on your post %3$s', 'fluent-community'),
225 $commenter,
226 '<b class="fcom_nrc">' . ($totalUsers - 1) . '</b>',
227 '<span class="fcom_nft">' . $feedTitle . '</span>'
228 );
229 } else {
230 $notificationContent = \sprintf(
231 /* translators: %1$s is the user name & %2$s is the feed title */
232 __('%1$s commented on your post: %2$s', 'fluent-community'),
233 $commenter,
234 '<span class="fcom_nft">' . $feedTitle . '</span>'
235 );
236 }
237 }
238 } else {
239 if ($feed->space_id) {
240 $notificationContent = \sprintf(
241 /* translators: %1$s is the commenter name, %2$s is the feed title & %3$s is the space title */
242 __('%1$s commented on your post: %2$s in %3$s', 'fluent-community'),
243 $commenter,
244 '<span class="fcom_nft">' . $feedTitle . '</span>',
245 '<b class="fcom_nst">' . $feed->space->title . '</b>'
246 );
247 } else {
248 $notificationContent = \sprintf(
249 /* translators: %1$s is the commenter name & %2$s is the feed title */
250 __('%1$s commented on your post: %2$s', 'fluent-community'),
251 $commenter,
252 '<span class="fcom_nft">' . $feedTitle . '</span>'
253 );
254 }
255 }
256
257 $route = $feed->getJsRoute();
258
259 if ($exist) {
260 $exist->content = $notificationContent;
261 $exist->updated_at = current_time('mysql');
262 $exist->src_user_id = $comment->user->ID;
263 $exist->object_id = $comment->id;
264 $exist->save();
265
266 NotificationSubscriber::where('object_id', $exist->id)
267 ->where('user_id', $feed->user_id)
268 ->update([
269 'is_read' => 0,
270 'updated_at' => current_time('mysql')
271 ]);
272
273 do_action('fluent_community/notification/comment/notifed_to_author', [
274 'user_ids' => [$feed->user_id],
275 'notification' => $exist,
276 'key' => 'notifed_to_author',
277 'comment' => $comment,
278 'feed' => $feed,
279 'created' => false
280 ]);
281
282 return;
283 }
284
285 $notification = [
286 'feed_id' => $feed->id,
287 'object_id' => $comment->id,
288 'src_user_id' => $comment->user_id,
289 'src_object_type' => 'comment',
290 'action' => 'comment_added',
291 'content' => $notificationContent,
292 'route' => $route,
293 ];
294
295 $notification = Notification::create($notification);
296
297 $notification->subscribe([$feed->user_id]);
298
299 do_action('fluent_community/notification/comment/notifed_to_author', [
300 'user_ids' => [$feed->user_id],
301 'notification' => $notification,
302 'comment' => $comment,
303 'key' => 'notifed_to_author',
304 'feed' => $feed,
305 'created' => true
306 ]);
307 }
308
309 protected function commentNotificationToFeedCommenters($comment, $feed)
310 {
311 if ($comment->parent_id) {
312 return $this->notifyForChildCommentReply($comment, $feed);
313 }
314
315 $userIds = Comment::whereNotIn('user_id', [$feed->user_id, $comment->user_id])
316 ->where('post_id', $feed->id)
317 ->whereNull('parent_id')
318 ->distinct()
319 ->pluck('user_id')
320 ->toArray();
321
322 $mentionedUserIds = Arr::get($comment->meta, 'mentioned_user_ids', []);
323
324 if (!$userIds && !$mentionedUserIds) {
325 return;
326 }
327
328 $commenter = '<b class="fcom_nudn">' . esc_html($comment->user->display_name) . '</b>';
329 $feedTitle = '<span class="fcom_nft">' . $feed->getHumanExcerpt(60) . '</span>';
330
331 $route = $feed->getJsRoute();
332 $space = $feed->space;
333
334 if ($feed->comments_count > 1) {
335 $totalUsers = $feed->comments
336 ->where('user_id', '!=', $comment->user_id)
337 ->pluck('user_id')
338 ->unique()
339 ->count();
340
341 if ($feed->space_id) {
342 if ($totalUsers > 1) {
343 $notificationContent = \sprintf(
344 /* translators: %1$s is the user name, %2$s is the people count, %3$s is the feed title and %4$s space title*/
345 __('%1$s and %2$s other people also commented on %3$s in %4$s', 'fluent-community'),
346 $commenter,
347 '<b class="fcom_nrc">' . ($totalUsers - 1) . '</b>',
348 $feedTitle,
349 '<b class="fcom_nst">' . $feed->space->title . '</b>'
350 );
351 } else {
352 $notificationContent = \sprintf(
353 /* translators: %1$s is the user name, %2$s is the feed title and %3$s space title*/
354 __('%1$s also commented on %2$s in %3$s', 'fluent-community'),
355 $commenter,
356 $feedTitle,
357 '<b class="fcom_nst">' . $feed->space->title . '</b>'
358 );
359 }
360 } else {
361 if ($totalUsers > 1) {
362 $notificationContent = \sprintf(
363 /* translators: %1$s is the user name, %2$s is the like count & %3$s is the feed title */
364 __('%1$s and %2$s other people also commented on %3$s', 'fluent-community'),
365 $commenter,
366 '<b class="fcom_nrc">' . ($totalUsers - 1) . '</b>',
367 $feedTitle,
368 );
369 } else {
370 $notificationContent = \sprintf(
371 /* translators: %1$s is the user name & %2$s is the feed title */
372 __('%1$s also commented on %2$s', 'fluent-community'),
373 $commenter,
374 $feedTitle,
375 );
376 }
377 }
378 } else {
379 if ($feed->space_id) {
380 $notificationContent = \sprintf(
381 /* translators: %1$s is the commenter name, %2$s is the feed title & %3$s is the space title */
382 __('%1$s also commented on %2$s in %3$s', 'fluent-community'),
383 $commenter,
384 $feedTitle,
385 '<b class="fcom_nst">' . $space->title . '</b>'
386 );
387 } else {
388 $notificationContent = \sprintf(
389 /* translators: %1$s is the commenter name & %2$s is the feed title */
390 __('%1$s also commented on %2$s', 'fluent-community'),
391 $commenter,
392 $feedTitle,
393 );
394 }
395 }
396
397 if ($mentionedUserIds) {
398 $mentionNotification = Notification::create([
399 'feed_id' => $feed->id,
400 'object_id' => $comment->id,
401 'src_user_id' => $comment->user_id,
402 'src_object_type' => 'comment',
403 'action' => 'mention_added',
404 'content' => \sprintf(
405 /* translators: %1$s is the commenter name & %2$s is the feed title */
406 __('%1$s mentioned you in a comment at %2$s', 'fluent-community'),
407 $commenter,
408 $feedTitle,
409 ),
410 'route' => $route,
411 ]);
412
413 $mentionNotification->subscribe($mentionedUserIds);
414
415 do_action('fluent_community/notification/comment/notifed_to_mentions', [
416 'user_ids' => $mentionedUserIds,
417 'notification' => $mentionNotification,
418 'key' => 'notifed_to_mentions',
419 'comment' => $comment,
420 'feed' => $feed
421 ]);
422 }
423
424 if ($mentionedUserIds) {
425 $userIds = array_values(array_diff($userIds, $mentionedUserIds));
426 }
427
428 if (!$userIds) {
429 return;
430 }
431
432 $existIds = Notification::where('feed_id', $feed->id)
433 ->where('action', 'comment_added')
434 ->whereDoesntHave('subscribers', function ($query) use ($feed, $comment) {
435 $query->whereIn('user_id', [$feed->user_id, $comment->user_id]);
436 })
437 ->pluck('id')
438 ->toArray();
439
440 $existingSubscriberUserIds = [];
441 if (!empty($existIds)) {
442 Notification::whereIn('id', $existIds)->update([
443 'content' => $notificationContent,
444 'updated_at' => current_time('mysql'),
445 'src_user_id' => $comment->user_id,
446 'object_id' => $comment->id
447 ]);
448
449 $existingSubscriberUserIds = NotificationSubscriber::whereIn('object_id', $existIds)
450 ->pluck('user_id')
451 ->unique()
452 ->toArray();
453
454 NotificationSubscriber::whereIn('object_id', $existIds)
455 ->whereIn('user_id', $existingSubscriberUserIds)
456 ->update([
457 'is_read' => 0,
458 'updated_at' => current_time('mysql')
459 ]);
460 }
461
462 if (!empty($existingSubscriberUserIds)) {
463 $userIds = array_values(array_diff($userIds, $existingSubscriberUserIds));
464 }
465
466 $notification = [
467 'feed_id' => $feed->id,
468 'object_id' => $comment->id,
469 'src_user_id' => $comment->user_id,
470 'src_object_type' => 'comment',
471 'action' => 'comment_added',
472 'content' => $notificationContent,
473 'route' => $route,
474 ];
475
476 foreach ($userIds as $userId) {
477 $createdNotification = Notification::create($notification);
478 $createdNotification->subscribe([$userId]);
479 }
480
481 $sendingUserIds = array_merge($userIds, $existingSubscriberUserIds);
482
483 do_action('fluent_community/notification/comment/notifed_to_other_users', [
484 'user_ids' => $sendingUserIds,
485 'key' => 'notifed_to_other_users',
486 'notification' => $notification,
487 'comment' => $comment,
488 'feed' => $feed
489 ]);
490 }
491
492 protected function notifyForChildCommentReply($comment, $feed)
493 {
494 // This is a parent comment, so we need to notify the parent comment author & all child comment authors
495 $childCommentUserIds = Comment::where(function ($q) use ($comment) {
496 $q->where('parent_id', $comment->parent_id)
497 ->orWhere('id', $comment->parent_id);
498 })
499 ->whereNotIn('user_id', [$comment->user_id, $feed->user_id])
500 ->select(['user_id'])
501 ->distinct('user_id')
502 ->get()
503 ->pluck('user_id')
504 ->toArray();
505
506 if (!$childCommentUserIds) {
507 return false;
508 }
509
510 $commenter = '<b class="fcom_nudn">' . esc_html($comment->user->display_name) . '</b>';
511
512 $existingNotification = Notification::where('object_id', $comment->parent_id)
513 ->where('action', 'child_comment_added')
514 ->first();
515
516 if ($existingNotification) {
517 $newContent = \sprintf(
518 /* translators: %1$s is the commenter name, %2$s is the comment user count & %3$s feed excerpt */
519 __('%1$s and %2$s other people replied to your comment at %3$s', 'fluent-community'),
520 $commenter,
521 '<b class="fcom_nrc">' . count($childCommentUserIds) . '</b>',
522 '<b class="fcom_nft">' . $feed->getHumanExcerpt(60) . '</b>'
523 );
524
525 $route = $existingNotification->route;
526 $route['query'] = [
527 'comment_id' => $comment->id
528 ];
529
530 $existingNotification->content = $newContent;
531 $existingNotification->updated_at = current_time('mysql');
532 $existingNotification->src_user_id = $comment->user_id;
533 $existingNotification->route = $route;
534 $existingNotification->save();
535
536 NotificationSubscriber::where('object_id', $existingNotification->id)
537 ->whereIn('user_id', $childCommentUserIds)
538 ->update([
539 'is_read' => 0,
540 'updated_at' => current_time('mysql')
541 ]);
542
543 do_action('fluent_community/notification/comment/notifed_to_thread_commetenter', [
544 'user_ids' => $childCommentUserIds,
545 'notification' => $existingNotification,
546 'key' => 'notifed_to_thread_commetenter',
547 'comment' => $comment,
548 'feed' => $feed
549 ]);
550
551 return $existingNotification;
552 }
553
554 $notificationContent = \sprintf(
555 /* translators: %1$s is the commenter name & %2$s is the feed excerpt */
556 __('%1$s replied to your comment at %2$s', 'fluent-community'),
557 $commenter,
558 '<b class="fcom_nft">' . $feed->getHumanExcerpt(60) . '</b>'
559 );
560
561 $route = $feed->getJsRoute();
562
563 $route['query'] = [
564 'comment_id' => $comment->id
565 ];
566
567 $notification = [
568 'feed_id' => $feed->id,
569 'object_id' => $comment->parent_id,
570 'src_user_id' => $comment->user_id,
571 'src_object_type' => 'comment',
572 'action' => 'child_comment_added',
573 'content' => $notificationContent,
574 'route' => $route,
575 ];
576
577 $notification = Notification::create($notification);
578 $notification->subscribe($childCommentUserIds);
579
580 do_action('fluent_community/notification/comment/notifed_to_thread_commetenter', [
581 'user_ids' => $childCommentUserIds,
582 'notification' => $notification,
583 'key' => 'notifed_to_thread_commetenter',
584 'comment' => $comment,
585 'feed' => $feed
586 ]);
587
588 return $notification;
589 }
590
591 public function maybeHandleMentionedUserIds($feed)
592 {
593 $mentionedUserIds = Arr::get($feed->meta, 'mentioned_user_ids', []);
594 if (!$mentionedUserIds) {
595 return;
596 }
597
598 do_action('fluent_community/feed_mentioned_user_ids', $feed, $mentionedUserIds);
599
600 $feedTitle = $feed->getHumanExcerpt(60);
601 $user = $feed->user;
602
603 $notificationContent = \sprintf(
604 /* translators: %1$s is the user name, %2$s is the feed title */
605 __('%1$s mentioned you in a post: %2$s', 'fluent-community'),
606 '<b class="fcom_nudn">' . esc_html($user->display_name) . '</b>',
607 '<b class="fcom_nft">' . $feedTitle . '</b>'
608 );
609
610 $route = $feed->getJsRoute();
611
612 $notification = [
613 'feed_id' => $feed->id,
614 'src_user_id' => $user->ID,
615 'src_object_type' => 'feed',
616 'action' => 'feed/mentioned',
617 'content' => $notificationContent,
618 'route' => $route,
619 ];
620
621 $notification = Notification::create($notification);
622
623 $notification->subscribe($mentionedUserIds);
624 }
625
626 private function maybeHasEveryoneTag(Feed $feed)
627 {
628 if (!$feed->space_id) {
629 return;
630 }
631
632 if (!$feed->isEnabledForEveryoneTag()) {
633 return;
634 }
635
636 // we have everyone
637 // check if current user is a moderator or admin
638 $user = $feed->user;
639 $spaceRole = $user->getSpaceRole($feed->space);
640 if (!in_array($spaceRole, ['admin', 'moderator'])) {
641 return;
642 }
643
644 do_action('fluent_community/feed/scheduling_everyone_tag', $feed);
645 // Let's schedule an email hook to send email to everyone for this post
646 // We are scheduling this after 5 minutes of the post publish for performance
647 as_schedule_single_action(time() + 300, 'fluent_community/email_notify_users_everyone_tag', [
648 $feed->id,
649 0
650 ], 'fluent-community');
651 }
652
653 private function willCreateFeedCreatedNotification($feed)
654 {
655 // validate if the user is a moderator
656 if (!$feed->user) {
657 return;
658 }
659
660 if ($feed->user->isCommunityModerator()) {
661 return true;
662 }
663
664 if ($feed->space) {
665 $role = $feed->user->getSpaceRole($feed->space);
666 return in_array($role, ['admin', 'moderator']);
667 }
668
669 return false;
670 }
671 }
672