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

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

531 lines 19.0 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\Functions\Utility;
6 use FluentCommunity\App\Models\Comment;
7 use FluentCommunity\App\Models\Feed;
8 use FluentCommunity\App\Models\Notification;
9 use FluentCommunity\App\Models\NotificationSubscriber;
10 use FluentCommunity\App\Models\SpaceUserPivot;
11 use FluentCommunity\App\Services\Helper;
12 use FluentCommunity\Framework\Support\Arr;
13
14 class NotificationEventHandler
15 {
16 public function register()
17 {
18 add_action('fluent_community/comment_added', [$this, 'handleNewCommentEvent'], 10, 3);
19 add_action('fluent_community/space_feed/created', [$this, 'handleNewSpaceFeed'], 10);
20 add_action('fluent_community/feed/react_added', [$this, 'handleNewFeedReact'], 10, 2);
21
22 add_action('fluent_community/space/member/role_updated', [$this, 'handleSpaceMemberRoleUpdated'], 10, 2);
23
24 /*
25 * Mentions handler
26 */
27 add_action('fluent_community/feed_mentioned', [$this, 'handleFeedMentions'], 10, 2);
28
29 }
30
31 public function handleNewCommentEvent($comment, $feed, $mentionedUsers = null)
32 {
33 $this->commentNotificationToAuthorFeed($comment, $feed, $mentionedUsers);
34
35 // now notify all users who commented on this feed
36 $this->commentNotificationToFeedCommenters($comment, $feed, $mentionedUsers);
37 }
38
39 public function handleNewSpaceFeed($feed)
40 {
41 if (!$this->willCreateFeedCreatedNotification($feed)) {
42 return;
43 }
44
45 $user = $feed->user;
46 $space = $feed->space;
47
48 $this->maybeHasEveryoneTag($feed);
49
50 $userIds = SpaceUserPivot::where('space_id', $space->id)
51 ->where('user_id', '!=', $user->ID)
52 ->where('status', 'active')
53 ->pluck('user_id')
54 ->toArray();
55
56 if (!$userIds) {
57 return;
58 }
59
60 $feedTitle = $feed->getHumanExcerpt(60);
61
62 $notificationContent = \sprintf(
63 /* translators: %1$s is the user name, %2$s is the feed title and %3$3s is the space title */
64 __('%1$s posted %2$s in %3$s', 'fluent-community'),
65 '<b class="fcom_nudn">' . $user->display_name . '</b>',
66 '<span class="fcom_nft">' . $feedTitle . '</span>',
67 '<b class="fcom_nst">' . $space->title . '</b>'
68 );
69
70 $route = $feed->getJsRoute();
71
72 $notification = [
73 'feed_id' => $feed->id,
74 'src_user_id' => $user->ID,
75 'src_object_type' => 'feed',
76 'action' => 'space_feed/created',
77 'content' => $notificationContent,
78 'route' => $route,
79 ];
80
81 $notification = Notification::create($notification);
82
83 $notification->subscribe($userIds);
84 }
85
86 public function handleNewFeedReact($react, $feed)
87 {
88 if ($react->user_id == $feed->user_id) {
89 return;
90 }
91
92 $feedTitle = $feed->getHumanExcerpt(60);
93 $user = $react->user;
94
95 if ($feed->reactions_count > 1) {
96 // check if we have existing notification for this feed and user
97 $existingNotification = Notification::where('feed_id', $feed->id)
98 ->where('action', 'feed/react_added')
99 ->first();
100
101 if ($existingNotification) {
102 $notificationContent = \sprintf(
103 /* 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>',
106 '<b class="fcom_nrc">' . ($feed->reactions_count - 1) . '</b>',
107 '<span class="fcom_nft">' . $feedTitle . '</span>'
108 );
109
110 $existingNotification->content = $notificationContent;
111 $existingNotification->src_user_id = $user->ID;
112 $existingNotification->save();
113 NotificationSubscriber::where('object_id', $existingNotification->id)
114 ->where('user_id', $feed->user_id)
115 ->update([
116 'is_read' => 0,
117 'updated_at' => current_time('mysql')
118 ]);
119 return;
120 }
121 }
122
123 $notificationContent = \sprintf(
124 /* 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>',
127 '<span class="fcom_nft">' . $feedTitle . '</span>'
128 );
129
130 $route = $feed->getJsRoute();
131
132 $notification = [
133 'feed_id' => $feed->id,
134 'src_user_id' => $user->ID,
135 'src_object_type' => 'feed',
136 'action' => 'feed/react_added',
137 'content' => $notificationContent,
138 'route' => $route,
139 ];
140
141 $notification = Notification::create($notification);
142
143 $notification->subscribe([$feed->user_id]);
144 }
145
146 public function handleSpaceMemberRoleUpdated($space, $pivot)
147 {
148 $user = $pivot->user;
149
150 $notificationContent = \sprintf(
151 /* translators: %1$s is the role name, %2$s is the space title */
152 __('You have been added as %1$s in %2$s', 'fluent-community'),
153 '<b>' . $pivot->role . '</b>',
154 '<b>' . $space->title . '</b>'
155 );
156
157 $route = [
158 'name' => 'space_feeds',
159 'params' => [
160 'space' => $space->slug
161 ]
162 ];
163
164 $notification = [
165 'object_id' => $space->id,
166 'src_user_id' => $user->ID,
167 'src_object_type' => 'space',
168 'action' => 'space/member/role_updated',
169 'content' => $notificationContent,
170 'route' => $route,
171 ];
172 $notification = Notification::create($notification);
173 $notification->subscribe([$pivot->user_id]);
174 }
175
176 protected function commentNotificationToAuthorFeed(Comment $comment, Feed $feed, $mentionUsers = null)
177 {
178 if ($comment->user_id == $feed->user_id) {
179 return;
180 }
181
182 if ($mentionUsers) {
183 $mentionedUserIds = $mentionUsers->pluck('ID')->toArray();
184 if (in_array($feed->user_id, $mentionedUserIds)) {
185 return;
186 }
187 }
188
189 $commenter = '<b class="fcom_nudn">' . $comment->user->display_name . '</b>';
190 $feedTitle = $feed->getHumanExcerpt(60);
191
192 $exist = null;
193 if ($feed->comments_count > 1) {
194 // check if we have existing notification for this feed and user
195 $exist = Notification::where('feed_id', $feed->id)
196 ->where('action', 'comment_added')
197 ->first();
198
199 $totalUsers = $feed->comments->pluck('user_id')->unique()->count();
200
201 if ($totalUsers > 1) {
202 $commenter .= ' and ' . ($totalUsers - 1) . ' other people';
203 }
204
205 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 );
214 } 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 );
222 }
223 } else {
224 if ($feed->space_id) {
225 $notificationContent = \sprintf(
226 /* translators: %1$s is the commenter name, %2$s is the feed title & %3$s is the space title */
227 __('%1$s commented on your post: %2$s in %3$s', 'fluent-community'),
228 '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
229 '<span class="fcom_nft">' . $feedTitle . '</span>',
230 '<b class="fcom_nst">' . $feed->space->title . '</b>'
231 );
232 } else {
233 $notificationContent = \sprintf(
234 /* translators: %1$s is the commenter name & %2$s is the feed title */
235 __('%1$s commented on your post: %2$s', 'fluent-community'),
236 '<b class="fcom_nudn">' . $comment->user->display_name . '</b>',
237 '<span class="fcom_nft">' . $feedTitle . '</span>'
238 );
239 }
240 }
241
242
243 $route = $feed->getJsRoute();
244
245 if ($exist) {
246 $exist->content = $notificationContent;
247 $exist->updated_at = current_time('mysql');
248 $exist->src_user_id = $comment->user->ID;
249 $exist->object_id = $comment->id;
250 $exist->save();
251
252 NotificationSubscriber::where('object_id', $exist->id)
253 ->where('user_id', $feed->user_id)
254 ->update([
255 'is_read' => 0,
256 'updated_at' => current_time('mysql')
257 ]);
258 return;
259 }
260
261 $notification = [
262 'feed_id' => $feed->id,
263 'object_id' => $comment->id,
264 'src_user_id' => $comment->user_id,
265 'src_object_type' => 'comment',
266 'action' => 'comment_added',
267 'content' => $notificationContent,
268 'route' => $route,
269 ];
270
271 $notification = Notification::create($notification);
272
273 $notification->subscribe([$feed->user_id]);
274 }
275
276 protected function commentNotificationToFeedCommenters($comment, $feed, $mentionedUsers = null)
277 {
278 if ($comment->parent_id) {
279 return $this->notifyForChildCommentReply($comment, $feed);
280 }
281
282 $comments = Comment::whereNotIn('user_id', [$feed->user_id, $comment->user_id])
283 ->select(['user_id'])
284 ->where('post_id', $feed->id)
285 ->whereNull('parent_id')
286 ->distinct('user_id')
287 ->get();
288
289 $userIds = $comments->pluck('user_id')->toArray();
290
291 $mentionedUserIds = [];
292
293 if ($mentionedUsers) {
294 $mentionedUserIds = $mentionedUsers->pluck('ID')->toArray();
295 }
296
297 if (!$userIds && !$mentionedUserIds) {
298 return;
299 }
300
301 $feedTitle = $feed->getHumanExcerpt(60);
302
303 $route = $feed->getJsRoute();
304
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 );
314 } else {
315 $notificationContent = \sprintf(
316 /* 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 );
321 }
322
323 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 ]);
338
339 $mentionNotification->subscribe($mentionedUserIds);
340 }
341
342 if ($mentionedUserIds) {
343 $userIds = array_values(array_diff($userIds, $mentionedUserIds));
344 }
345
346 if (!$userIds) {
347 return;
348 }
349
350 $notification = [
351 'feed_id' => $feed->id,
352 'object_id' => $comment->id,
353 'src_user_id' => $comment->user_id,
354 'src_object_type' => 'comment',
355 'action' => 'comment_added',
356 'content' => $notificationContent,
357 'route' => $route,
358 ];
359 $notification = Notification::create($notification);
360 $notification->subscribe($userIds);
361 }
362
363 protected function notifyForChildCommentReply($comment, $feed)
364 {
365 // 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)
367 ->whereNotIn('user_id', [$comment->user_id, $feed->user_id])
368 ->select(['user_id'])
369 ->distinct('user_id')
370 ->get()
371 ->pluck('user_id')
372 ->toArray();
373
374 if (!$childCommentUserIds) {
375 return false;
376 }
377
378 $existingNotification = Notification::where('object_id', $comment->parent_id)
379 ->where('action', 'child_comment_added')
380 ->first();
381
382 if ($existingNotification) {
383 $newContent = \sprintf(
384 /* translators: %1$s is the commenter name, %2$s is the comment user count & %3$s feed excerpt */
385 __('%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>',
387 '<b class="fcom_nrc">' . count($childCommentUserIds) . '</b>',
388 '<b class="fcom_nft">' . $feed->getHumanExcerpt(60) . '</b>'
389 );
390
391 $route = $existingNotification->route;
392 $route['query'] = [
393 'comment_id' => $comment->id
394 ];
395
396 $existingNotification->content = $newContent;
397 $existingNotification->updated_at = current_time('mysql');
398 $existingNotification->src_user_id = $comment->user_id;
399 $existingNotification->route = $route;
400 $existingNotification->save();
401
402 NotificationSubscriber::where('object_id', $existingNotification->id)
403 ->whereIn('user_id', $childCommentUserIds)
404 ->update([
405 'is_read' => 0,
406 'updated_at' => current_time('mysql')
407 ]);
408
409 return $existingNotification;
410 }
411
412 $notificationContent = \sprintf(
413 /* 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>',
416 '<b class="fcom_nft">' . $feed->getHumanExcerpt(60) . '</b>'
417 );
418
419 $route = $feed->getJsRoute();
420
421 if ($feed->space_id) {
422 $space = $feed->space;
423 }
424
425 $notification = [
426 'feed_id' => $feed->id,
427 'object_id' => $comment->parent_id,
428 'src_user_id' => $comment->user_id,
429 'src_object_type' => 'comment',
430 'action' => 'child_comment_added',
431 'content' => $notificationContent,
432 'route' => $route,
433 ];
434
435 $notification = Notification::create($notification);
436 $notification->subscribe($childCommentUserIds);
437 return $notification;
438 }
439
440 public function handleFeedMentions($feed, $mentionedUsers)
441 {
442 $feedTitle = $feed->getHumanExcerpt(60);
443 $user = $feed->user;
444
445 $notificationContent = \sprintf(
446 /* translators: %1$s is the user name, %2$s is the feed title */
447 __('%1$s mentioned you in a post: %2$s', 'fluent-community'),
448 '<b class="fcom_nudn">' . sanitize_text_field($user->display_name) . '</b>',
449 '<b class="fcom_nft">' . $feedTitle . '</b>'
450 );
451
452 $route = $feed->getJsRoute();
453
454 $notification = [
455 'feed_id' => $feed->id,
456 'src_user_id' => $user->ID,
457 'src_object_type' => 'feed',
458 'action' => 'feed/mentioned',
459 'content' => $notificationContent,
460 'route' => $route,
461 ];
462
463 $notification = Notification::create($notification);
464
465 $userIds = $mentionedUsers->pluck('ID')->toArray();
466
467 $notification->subscribe($userIds);
468 }
469
470 private function maybeHasEveryoneTag(Feed $feed)
471 {
472 if (!$feed->space_id) {
473 return;
474 }
475
476 $message = $feed->message;
477 $pattern = '/(?<!\S)@everyone(?!\S)/';
478
479 // match if the message contains @everyone
480
481 if (!preg_match($pattern, $message)) {
482 return;
483 }
484
485 // we have everyone
486 // check if current user is a moderator or admin
487 $user = $feed->user;
488
489 $spaceRole = $user->getSpaceRole($feed->space);
490
491 if (!in_array($spaceRole, ['admin', 'moderator'])) {
492 return;
493 }
494
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
510 }
511
512 private function willCreateFeedCreatedNotification($feed)
513 {
514 // validate if the user is a moderator
515 if (!$feed->user) {
516 return;
517 }
518
519 if ($feed->user->isCommunityModerator()) {
520 return true;
521 }
522
523 if ($feed->space) {
524 $role = $feed->user->getSpaceRole($feed->space);
525 return in_array($role, ['admin', 'moderator']);
526 }
527
528 return false;
529 }
530 }
531