commentNotificationToAuthorFeed($comment, $feed); // now notify all users who commented on this feed $this->commentNotificationToFeedCommenters($comment, $feed); } public function handleNewSpaceFeed($feed) { if (!$this->willCreateFeedCreatedNotification($feed)) { return; } $user = $feed->user; $space = $feed->space; $this->maybeHasEveryoneTag($feed); $userIds = SpaceUserPivot::where('space_id', $space->id) ->where('user_id', '!=', $user->ID) ->where('status', 'active') ->pluck('user_id') ->toArray(); if (!$userIds) { return; } $feedTitle = $feed->getHumanExcerpt(60); $notificationContent = \sprintf( /* translators: %1$s is the user name, %2$s is the feed title and %3$3s is the space title */ __('%1$s posted %2$s in %3$s', 'fluent-community'), '' . esc_html($user->display_name) . '', '' . $feedTitle . '', '' . esc_html($space->title) . '' ); $route = $feed->getJsRoute(); $notification = [ 'feed_id' => $feed->id, 'src_user_id' => $user->ID, 'src_object_type' => 'feed', 'action' => 'space_feed/created', 'content' => $notificationContent, 'route' => $route, ]; $notification = Notification::create($notification); $notification->subscribe($userIds); } public function handleNewFeedReact($react, $feed) { if ($react->user_id == $feed->user_id) { return; } $feedTitle = $feed->getHumanExcerpt(60); $user = $react->user; if ($feed->reactions_count > 1) { // check if we have existing notification for this feed and user $existingNotification = Notification::where('feed_id', $feed->id) ->where('action', 'feed/react_added') ->first(); if ($existingNotification) { $notificationContent = \sprintf( /* translators: %1$s is the user name, %2$s is the like count & %3$s is the feed title */ __('%1$s and %2$s other people reacted to %3$s', 'fluent-community'), '' . esc_html($user->display_name) . '', '' . ($feed->reactions_count - 1) . '', '' . $feedTitle . '' ); $existingNotification->content = $notificationContent; $existingNotification->src_user_id = $user->ID; $existingNotification->save(); NotificationSubscriber::where('object_id', $existingNotification->id) ->where('user_id', $feed->user_id) ->update([ 'is_read' => 0, 'updated_at' => current_time('mysql') ]); return; } } $notificationContent = \sprintf( /* translators: %1$s is the user name, %2$s is the feed title */ __('%1$s reacted to %2$s', 'fluent-community'), '' . esc_html($user->display_name) . '', '' . $feedTitle . '' ); $route = $feed->getJsRoute(); $notification = [ 'feed_id' => $feed->id, 'src_user_id' => $user->ID, 'src_object_type' => 'feed', 'action' => 'feed/react_added', 'content' => $notificationContent, 'route' => $route, ]; $notification = Notification::create($notification); $notification->subscribe([$feed->user_id]); } public function handleSpaceMemberRoleUpdated($space, $pivot) { $user = $pivot->user; $notificationContent = \sprintf( /* translators: %1$s is the role name, %2$s is the space title */ __('You have been added as %1$s in %2$s', 'fluent-community'), '' . $pivot->role . '', '' . $space->title . '' ); $route = [ 'name' => 'space_feeds', 'params' => [ 'space' => $space->slug ] ]; $notification = [ 'object_id' => $space->id, 'src_user_id' => $user->ID, 'src_object_type' => 'space', 'action' => 'space/member/role_updated', 'content' => $notificationContent, 'route' => $route, ]; $notification = Notification::create($notification); $notification->subscribe([$pivot->user_id]); } protected function commentNotificationToAuthorFeed(Comment $comment, Feed $feed) { if ($comment->user_id == $feed->user_id) { return; } $mentionedUserIds = Arr::get($feed->meta, 'mentioned_user_ids', []); if (in_array($feed->user_id, $mentionedUserIds)) { return; } $commenter = '' . esc_html($comment->user->display_name) . ''; $feedTitle = $feed->getHumanExcerpt(60); $exist = null; if ($feed->comments_count > 1) { // check if we have existing notification for this feed and user $exist = Notification::where('feed_id', $feed->id) ->where('action', 'comment_added') ->first(); $totalUsers = $feed->comments ->where('user_id', '!=', $feed->user_id) ->pluck('user_id') ->unique() ->count(); if ($feed->space_id) { if ($totalUsers > 1) { $notificationContent = \sprintf( /* translators: %1$s is the user name, %2$s is the people count, %3$s is the feed title and %4$s space title*/ __('%1$s and %2$s other people commented on your post %3$s in %4$s', 'fluent-community'), $commenter, '' . ($totalUsers - 1) . '', '' . $feedTitle . '', '' . $feed->space->title . '' ); } else { $notificationContent = \sprintf( /* translators: %1$s is the user name, %2$s is the feed title and %3$s space title*/ __('%1$s commented on your post: %2$s in %3$s', 'fluent-community'), $commenter, '' . $feedTitle . '', '' . $feed->space->title . '' ); } } else { if ($totalUsers > 1) { $notificationContent = \sprintf( /* translators: %1$s is the user name, %2$s is the like count & %3$s is the feed title */ __('%1$s and %2$s other people commented on your post %3$s', 'fluent-community'), $commenter, '' . ($totalUsers - 1) . '', '' . $feedTitle . '' ); } else { $notificationContent = \sprintf( /* translators: %1$s is the user name & %2$s is the feed title */ __('%1$s commented on your post: %2$s', 'fluent-community'), $commenter, '' . $feedTitle . '' ); } } } else { if ($feed->space_id) { $notificationContent = \sprintf( /* translators: %1$s is the commenter name, %2$s is the feed title & %3$s is the space title */ __('%1$s commented on your post: %2$s in %3$s', 'fluent-community'), $commenter, '' . $feedTitle . '', '' . $feed->space->title . '' ); } else { $notificationContent = \sprintf( /* translators: %1$s is the commenter name & %2$s is the feed title */ __('%1$s commented on your post: %2$s', 'fluent-community'), $commenter, '' . $feedTitle . '' ); } } $route = $feed->getJsRoute(); if ($exist) { $exist->content = $notificationContent; $exist->updated_at = current_time('mysql'); $exist->src_user_id = $comment->user->ID; $exist->object_id = $comment->id; $exist->save(); NotificationSubscriber::where('object_id', $exist->id) ->where('user_id', $feed->user_id) ->update([ 'is_read' => 0, 'updated_at' => current_time('mysql') ]); do_action('fluent_community/notification/comment/notifed_to_author', [ 'user_ids' => [$feed->user_id], 'notification' => $exist, 'key' => 'notifed_to_author', 'comment' => $comment, 'feed' => $feed, 'created' => false ]); return; } $notification = [ 'feed_id' => $feed->id, 'object_id' => $comment->id, 'src_user_id' => $comment->user_id, 'src_object_type' => 'comment', 'action' => 'comment_added', 'content' => $notificationContent, 'route' => $route, ]; $notification = Notification::create($notification); $notification->subscribe([$feed->user_id]); do_action('fluent_community/notification/comment/notifed_to_author', [ 'user_ids' => [$feed->user_id], 'notification' => $notification, 'comment' => $comment, 'key' => 'notifed_to_author', 'feed' => $feed, 'created' => true ]); } protected function commentNotificationToFeedCommenters($comment, $feed) { if ($comment->parent_id) { return $this->notifyForChildCommentReply($comment, $feed); } $userIds = Comment::whereNotIn('user_id', [$feed->user_id, $comment->user_id]) ->where('post_id', $feed->id) ->whereNull('parent_id') ->distinct() ->pluck('user_id') ->toArray(); $mentionedUserIds = Arr::get($comment->meta, 'mentioned_user_ids', []); if (!$userIds && !$mentionedUserIds) { return; } $commenter = '' . esc_html($comment->user->display_name) . ''; $feedTitle = '' . $feed->getHumanExcerpt(60) . ''; $route = $feed->getJsRoute(); $space = $feed->space; if ($feed->comments_count > 1) { $totalUsers = $feed->comments ->where('user_id', '!=', $comment->user_id) ->pluck('user_id') ->unique() ->count(); if ($feed->space_id) { if ($totalUsers > 1) { $notificationContent = \sprintf( /* translators: %1$s is the user name, %2$s is the people count, %3$s is the feed title and %4$s space title*/ __('%1$s and %2$s other people also commented on %3$s in %4$s', 'fluent-community'), $commenter, '' . ($totalUsers - 1) . '', $feedTitle, '' . $feed->space->title . '' ); } else { $notificationContent = \sprintf( /* translators: %1$s is the user name, %2$s is the feed title and %3$s space title*/ __('%1$s also commented on %2$s in %3$s', 'fluent-community'), $commenter, $feedTitle, '' . $feed->space->title . '' ); } } else { if ($totalUsers > 1) { $notificationContent = \sprintf( /* translators: %1$s is the user name, %2$s is the like count & %3$s is the feed title */ __('%1$s and %2$s other people also commented on %3$s', 'fluent-community'), $commenter, '' . ($totalUsers - 1) . '', $feedTitle, ); } else { $notificationContent = \sprintf( /* translators: %1$s is the user name & %2$s is the feed title */ __('%1$s also commented on %2$s', 'fluent-community'), $commenter, $feedTitle, ); } } } else { if ($feed->space_id) { $notificationContent = \sprintf( /* translators: %1$s is the commenter name, %2$s is the feed title & %3$s is the space title */ __('%1$s also commented on %2$s in %3$s', 'fluent-community'), $commenter, $feedTitle, '' . $space->title . '' ); } else { $notificationContent = \sprintf( /* translators: %1$s is the commenter name & %2$s is the feed title */ __('%1$s also commented on %2$s', 'fluent-community'), $commenter, $feedTitle, ); } } if ($mentionedUserIds) { $mentionNotification = Notification::create([ 'feed_id' => $feed->id, 'object_id' => $comment->id, 'src_user_id' => $comment->user_id, 'src_object_type' => 'comment', 'action' => 'mention_added', 'content' => \sprintf( /* translators: %1$s is the commenter name & %2$s is the feed title */ __('%1$s mentioned you in a comment at %2$s', 'fluent-community'), $commenter, $feedTitle, ), 'route' => $route, ]); $mentionNotification->subscribe($mentionedUserIds); do_action('fluent_community/notification/comment/notifed_to_mentions', [ 'user_ids' => $mentionedUserIds, 'notification' => $mentionNotification, 'key' => 'notifed_to_mentions', 'comment' => $comment, 'feed' => $feed ]); } if ($mentionedUserIds) { $userIds = array_values(array_diff($userIds, $mentionedUserIds)); } if (!$userIds) { return; } $existIds = Notification::where('feed_id', $feed->id) ->where('action', 'comment_added') ->whereDoesntHave('subscribers', function ($query) use ($feed, $comment) { $query->whereIn('user_id', [$feed->user_id, $comment->user_id]); }) ->pluck('id') ->toArray(); $existingSubscriberUserIds = []; if (!empty($existIds)) { Notification::whereIn('id', $existIds)->update([ 'content' => $notificationContent, 'updated_at' => current_time('mysql'), 'src_user_id' => $comment->user_id, 'object_id' => $comment->id ]); $existingSubscriberUserIds = NotificationSubscriber::whereIn('object_id', $existIds) ->pluck('user_id') ->unique() ->toArray(); NotificationSubscriber::whereIn('object_id', $existIds) ->whereIn('user_id', $existingSubscriberUserIds) ->update([ 'is_read' => 0, 'updated_at' => current_time('mysql') ]); } if (!empty($existingSubscriberUserIds)) { $userIds = array_values(array_diff($userIds, $existingSubscriberUserIds)); } $notification = [ 'feed_id' => $feed->id, 'object_id' => $comment->id, 'src_user_id' => $comment->user_id, 'src_object_type' => 'comment', 'action' => 'comment_added', 'content' => $notificationContent, 'route' => $route, ]; foreach ($userIds as $userId) { $createdNotification = Notification::create($notification); $createdNotification->subscribe([$userId]); } $sendingUserIds = array_merge($userIds, $existingSubscriberUserIds); do_action('fluent_community/notification/comment/notifed_to_other_users', [ 'user_ids' => $sendingUserIds, 'key' => 'notifed_to_other_users', 'notification' => $notification, 'comment' => $comment, 'feed' => $feed ]); } protected function notifyForChildCommentReply($comment, $feed) { // This is a parent comment, so we need to notify the parent comment author & all child comment authors $childCommentUserIds = Comment::where(function ($q) use ($comment) { $q->where('parent_id', $comment->parent_id) ->orWhere('id', $comment->parent_id); }) ->whereNotIn('user_id', [$comment->user_id, $feed->user_id]) ->select(['user_id']) ->distinct('user_id') ->get() ->pluck('user_id') ->toArray(); if (!$childCommentUserIds) { return false; } $commenter = '' . esc_html($comment->user->display_name) . ''; $existingNotification = Notification::where('object_id', $comment->parent_id) ->where('action', 'child_comment_added') ->first(); if ($existingNotification) { $newContent = \sprintf( /* translators: %1$s is the commenter name, %2$s is the comment user count & %3$s feed excerpt */ __('%1$s and %2$s other people replied to your comment at %3$s', 'fluent-community'), $commenter, '' . count($childCommentUserIds) . '', '' . $feed->getHumanExcerpt(60) . '' ); $route = $existingNotification->route; $route['query'] = [ 'comment_id' => $comment->id ]; $existingNotification->content = $newContent; $existingNotification->updated_at = current_time('mysql'); $existingNotification->src_user_id = $comment->user_id; $existingNotification->route = $route; $existingNotification->save(); NotificationSubscriber::where('object_id', $existingNotification->id) ->whereIn('user_id', $childCommentUserIds) ->update([ 'is_read' => 0, 'updated_at' => current_time('mysql') ]); do_action('fluent_community/notification/comment/notifed_to_thread_commetenter', [ 'user_ids' => $childCommentUserIds, 'notification' => $existingNotification, 'key' => 'notifed_to_thread_commetenter', 'comment' => $comment, 'feed' => $feed ]); return $existingNotification; } $notificationContent = \sprintf( /* translators: %1$s is the commenter name & %2$s is the feed excerpt */ __('%1$s replied to your comment at %2$s', 'fluent-community'), $commenter, '' . $feed->getHumanExcerpt(60) . '' ); $route = $feed->getJsRoute(); $route['query'] = [ 'comment_id' => $comment->id ]; $notification = [ 'feed_id' => $feed->id, 'object_id' => $comment->parent_id, 'src_user_id' => $comment->user_id, 'src_object_type' => 'comment', 'action' => 'child_comment_added', 'content' => $notificationContent, 'route' => $route, ]; $notification = Notification::create($notification); $notification->subscribe($childCommentUserIds); do_action('fluent_community/notification/comment/notifed_to_thread_commetenter', [ 'user_ids' => $childCommentUserIds, 'notification' => $notification, 'key' => 'notifed_to_thread_commetenter', 'comment' => $comment, 'feed' => $feed ]); return $notification; } public function maybeHandleMentionedUserIds($feed) { $mentionedUserIds = Arr::get($feed->meta, 'mentioned_user_ids', []); if (!$mentionedUserIds) { return; } do_action('fluent_community/feed_mentioned_user_ids', $feed, $mentionedUserIds); $feedTitle = $feed->getHumanExcerpt(60); $user = $feed->user; $notificationContent = \sprintf( /* translators: %1$s is the user name, %2$s is the feed title */ __('%1$s mentioned you in a post: %2$s', 'fluent-community'), '' . esc_html($user->display_name) . '', '' . $feedTitle . '' ); $route = $feed->getJsRoute(); $notification = [ 'feed_id' => $feed->id, 'src_user_id' => $user->ID, 'src_object_type' => 'feed', 'action' => 'feed/mentioned', 'content' => $notificationContent, 'route' => $route, ]; $notification = Notification::create($notification); $notification->subscribe($mentionedUserIds); } private function maybeHasEveryoneTag(Feed $feed) { if (!$feed->space_id) { return; } if (!$feed->isEnabledForEveryoneTag()) { return; } // we have everyone // check if current user is a moderator or admin $user = $feed->user; $spaceRole = $user->getSpaceRole($feed->space); if (!in_array($spaceRole, ['admin', 'moderator'])) { return; } do_action('fluent_community/feed/scheduling_everyone_tag', $feed); // Let's schedule an email hook to send email to everyone for this post // We are scheduling this after 5 minutes of the post publish for performance as_schedule_single_action(time() + 300, 'fluent_community/email_notify_users_everyone_tag', [ $feed->id, 0 ], 'fluent-community'); } private function willCreateFeedCreatedNotification($feed) { // validate if the user is a moderator if (!$feed->user) { return; } if ($feed->user->isCommunityModerator()) { return true; } if ($feed->space) { $role = $feed->user->getSpaceRole($feed->space); return in_array($role, ['admin', 'moderator']); } return false; } }