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/EmailNotificationHandler.php +217 -153 1.0.962.11.0 View file →
@@ -12,8 +12,9 @@
12 12 use FluentCommunity\App\Models\XProfile;
13 13 use FluentCommunity\App\Services\Helper;
14 14 use FluentCommunity\App\Services\Libs\DailyDigest;
15 15 use FluentCommunity\App\Services\Libs\Mailer;
16 +use FluentCommunity\App\Services\FeedsHelper;
16 17 use FluentCommunity\App\Services\NotificationPref;
17 18 use FluentCommunity\App\Services\ProfileHelper;
18 19 use FluentCommunity\Framework\Support\Arr;
19 20
@@ -18,14 +19,13 @@
18 19 use FluentCommunity\Framework\Support\Arr;
19 20
20 21 class EmailNotificationHandler
21 22 {
22 -
23 23 private $maxRunTime = 0;
24 24
25 25 public function register()
26 26 {
27 - add_action('fluent_community/space_feed/created', [$this, 'handleSpaceFeedCreated'], 10, 1);
27 + add_action('fluent_community/space_feed/created', [$this, 'handleSpaceFeedCreated'], 20, 1);
28 28 add_action('fluent_community/email_notify_new_posts', [$this, 'notifyOnPostCreatedAsync'], 10, 1);
29 29
30 30 add_action('fluent_community/comment_added', [$this, 'handleNewCommentEvent'], 30, 2);
31 31 add_action('fluent_community/comment_added_async', [$this, 'handleNewCommentNotificationAsync'], 10, 2);
@@ -36,10 +36,21 @@
36 36 add_action('fluent_community/email_notify_users_everyone_tag', [$this, 'emailNotifyUsersForEveryoneTag'], 10, 2);
37 37
38 38 add_action('fluent_community_send_daily_digest', [$this, 'maybeSendDailyDigest'], 10);
39 39 add_action('fluent_community/space/join_requested', [$this, 'handleCommunityJoinRequest'], 10, 2);
40 +
41 + add_action('fluent_community/send_new_user_notification', [$this, 'sendNewUserNotificationAsync'], 10, 1);
40 42 }
41 43
44 + public function sendNewUserNotificationAsync($userId)
45 + {
46 + $userId = (int) $userId;
47 + if (!$userId || !get_userdata($userId)) {
48 + return;
49 + }
50 + wp_new_user_notification($userId, null, 'user');
51 + }
52 +
42 53 public function handleSpaceFeedCreated($feed)
43 54 {
44 55 if (did_action('fluent_community/feed/scheduling_everyone_tag')) {
45 56 return;
@@ -49,23 +60,28 @@
49 60 if (!$space) {
50 61 return false;
51 62 }
52 63
53 - $types = ['np_by_member_mail'];
64 + $events = ['np_by_member'];
54 65 $spaceRole = $feed->user->getSpaceRole($feed->space);
55 - if (!in_array($spaceRole, ['admin', 'moderator'])) {
56 - $types[] = 'np_by_admin_mail';
66 + if (in_array($spaceRole, ['admin', 'moderator'])) {
67 + $events[] = 'np_by_admin';
57 68 }
58 69
59 - $hasSubscribers = User::whereHas('notificationSubscriptions', function ($query) use ($types, $space) {
60 - $query->where(function ($q) use ($types, $space) {
61 - $q->whereIn('notification_type', $types)
70 + $hasSubscribers = User::query()->where(function ($query) use ($events, $space, $feed) {
71 + $query->whereHas('notificationPreferences', function ($query) use ($events, $space) {
72 + $query->where('channel', 'mail')
73 + ->whereIn('event_key', $events)
62 74 ->where('object_id', $space->id)
63 - ->where('is_read', 1);
75 + ->where('value', 1);
64 76 });
77 +
78 + do_action_ref_array('fluent_community/space_feed/email_notify_sub_query', [&$query, $feed, $space, $events]);
79 +
80 + return $query;
65 81 })->exists();
66 82
67 - if ($hasSubscribers) {
83 + if ($hasSubscribers || Arr::get($feed->meta, 'mentioned_user_ids', [])) {
68 84 // We are scheduling this after 2 minutes of the post publish for performance
69 85 as_schedule_single_action(time() + 120, 'fluent_community/email_notify_new_posts', [
70 86 $feed->id
71 87 ], 'fluent-community');
@@ -92,20 +108,32 @@
92 108 if (!$space || !$feed->user) {
93 109 return;
94 110 }
95 111
96 - $types = ['np_by_member_mail'];
112 + $events = ['np_by_member'];
97 113 $spaceRole = $feed->user->getSpaceRole($feed->space);
98 114 if (in_array($spaceRole, ['admin', 'moderator'])) {
99 - $types[] = 'np_by_admin_mail';
115 + $events[] = 'np_by_admin';
100 116 }
101 117
102 118 $lastSendUserId = (int)$feed->getCustomMeta('_last_email_user_id', 0);
119 + $usersQuery = User::query()->where(function ($query) use ($events, $space, $feed) {
120 + $query->whereHas('notificationPreferences', function ($query) use ($events, $space) {
121 + $query->where('channel', 'mail')
122 + ->whereIn('event_key', $events)
123 + ->where('object_id', $space->id)
124 + ->where('value', 1);
125 + });
103 126
104 - $users = User::whereHas('notificationSubscriptions', function ($query) use ($types, $space) {
105 - $query->whereIn('notification_type', $types)
106 - ->where('object_id', $space->id)
107 - ->where('is_read', 1);
127 + $mentionedUserIds = Arr::get($feed->meta, 'mentioned_user_ids', []);
128 +
129 + if ($mentionedUserIds) {
130 + $query->orWhereIn('ID', $mentionedUserIds);
131 + }
132 +
133 + do_action_ref_array('fluent_community/space_feed/email_notify_sub_query', [&$query, $feed, $space, $events]);
134 +
135 + return $query;
108 136 })
109 137 ->whereHas('space_pivot', function ($query) use ($space) {
110 138 $query->where('space_id', $space->id)
111 139 ->where('status', 'active');
@@ -116,23 +144,26 @@
116 144 ->whereHas('xprofile', function ($query) {
117 145 return $query->where('status', 'active');
118 146 })
119 147 ->orderBy('ID', 'ASC')
120 - ->limit(60)
121 - ->get();
148 + ->limit(60);
122 149
150 + $users = $usersQuery->get();
151 +
123 152 if ($users->isEmpty()) {
124 153 return; // It's done
125 154 }
126 155
156 + $undeliverableEmails = Helper::getUndeliverableEmails($users->pluck('user_email')->toArray());
157 +
127 158 $emailSubject = \sprintf(
128 159 /* translators: %1$s is the author name and %2$s is the post excerpt (max 30 chars) */
129 160 __('New Post By %1$s: %2$s', 'fluent-community'),
130 - $feed->user->getDisplayName(),
161 + $feed->user->getPublicDisplayName(),
131 162 $feed->getHumanExcerpt(30)
132 163 );
133 164
134 - $emailBody = $this->getFeedHtml($feed, true);
165 + $emailBody = $feed->getFeedHtml(true);
135 166
136 167 /*
137 168 * must need to replace these two strings
138 169 * ##feed_permalink##
@@ -148,8 +179,12 @@
148 179 if ($user->ID == $feed->user_id) {
149 180 continue;
150 181 }
151 182
183 + if ($undeliverableEmails && in_array(strtolower($user->user_email), $undeliverableEmails)) {
184 + continue;
185 + }
186 +
152 187 $newEmailBody = str_replace([
153 188 '##feed_permalink##',
154 189 '##email_notification_url##'
155 190 ], [
@@ -156,8 +191,26 @@
156 191 ProfileHelper::signUserUrlWithAuthHash($feedLink, $user->ID),
157 192 ProfileHelper::getSignedNotificationPrefUrl($user->ID)
158 193 ], $emailBody);
159 194
195 + $notificationBagde = $this->getNotificationBadges($user->ID);
196 + if ($notificationBagde) {
197 + $newEmailBody = str_replace('<!--before_footer_section-->', $notificationBagde, $newEmailBody);
198 + }
199 +
200 + $hooksSections = apply_filters('fluent_community/new_feed_notification/email_sections', [
201 + 'before_content' => '',
202 + 'after_content' => ''
203 + ], $user, $feed);
204 +
205 + if (!empty($hooksSections['before_content'])) {
206 + $newEmailBody = str_replace('<!--email_content_before-->', $hooksSections['before_content'], $newEmailBody);
207 + }
208 +
209 + if (!empty($hooksSections['after_content'])) {
210 + $newEmailBody = str_replace('<!--email_content_after-->', $hooksSections['after_content'], $newEmailBody);
211 + }
212 +
160 213 $mailer = new Mailer('', $emailSubject, $newEmailBody);
161 214 $mailer->to($user->user_email, $user->display_name);
162 215 $mailer->send();
163 216
@@ -169,9 +222,9 @@
169 222
170 223 if (($index + 1) % $maxSendPerSecond == 0) {
171 224 $timeTaken = microtime(true) - $startTime;
172 225 if ($timeTaken < 1) {
173 - usleep(1000000 - ($timeTaken * 1000000));
226 + usleep((int)(1000000 - ($timeTaken * 1000000)));
174 227 }
175 228 $startTime = microtime(true);
176 229 }
177 230 }
@@ -180,8 +233,14 @@
180 233 }
181 234
182 235 public function handleNewCommentEvent(Comment $comment, $feed)
183 236 {
237 + // Check the comment mentioned users or not
238 + if (Arr::get($comment->meta, 'mentioned_user_ids', [])) {
239 + as_schedule_single_action(time(), 'fluent_community/comment_added_async', [$comment->id, 0], 'fluent-community');
240 + return;
241 + }
242 +
184 243 if ($comment->parent_id) {
185 244 $globalCommentStatus = $this->isEnabled('reply_my_com_mail');
186 245 } else {
187 246 $globalCommentStatus = $this->isEnabled('com_my_post_mail');
@@ -186,10 +245,12 @@
186 245 } else {
187 246 $globalCommentStatus = $this->isEnabled('com_my_post_mail');
188 247 }
189 248
249 + $authorId = FeedsHelper::getNotificationAuthorId($feed);
250 +
190 251 $notificationUserIds = [];
191 - if ($comment->user_id != $feed->user_id && NotificationPref::willGetCommentEmail($feed->user_id, $globalCommentStatus)) {
252 + if ($comment->user_id != $authorId && NotificationPref::willGetNotification($authorId, 'comment', 'mail', $globalCommentStatus)) {
192 253 as_schedule_single_action(time(), 'fluent_community/comment_added_async', [$comment->id, 0], 'fluent-community');
193 254 return true;
194 255 }
195 256
@@ -195,9 +256,9 @@
195 256
196 257 if ($comment->parent_id) {
197 258 $notificationUserIds = $comment->getCommentParentUserIds();
198 259 $notificationUserIds = array_filter($notificationUserIds, function ($userId) use ($globalCommentStatus) {
199 - return NotificationPref::willGetCommentReplyEmail($userId, $globalCommentStatus);
260 + return NotificationPref::willGetNotification($userId, 'reply', 'mail', $globalCommentStatus);
200 261 });
201 262 }
202 263
203 264 if (!$notificationUserIds) {
@@ -230,19 +291,25 @@
230 291 }
231 292
232 293 $notificationUserIds = $comment->getCommentParentUserIds($lastUserId);
233 294 $notificationUserIds = array_filter($notificationUserIds, function ($userId) use ($globalCommentStatus) {
234 - return NotificationPref::willGetCommentReplyEmail($userId, $globalCommentStatus);
295 + return NotificationPref::willGetNotification($userId, 'reply', 'mail', $globalCommentStatus);
235 296 });
236 297
237 298 $notificationUserIds = array_diff($notificationUserIds, [$comment->user_id]);
238 - if ($comment->user_id != $feed->user_id && NotificationPref::willGetCommentEmail($feed->user_id, $globalCommentStatus)) {
299 + $authorId = FeedsHelper::getNotificationAuthorId($feed);
300 + if ($comment->user_id != $authorId && NotificationPref::willGetNotification($authorId, 'comment', 'mail', $globalCommentStatus)) {
239 301 // Add at the first
240 - $notificationUserIds[] = $feed->user_id;
302 + $notificationUserIds[] = $authorId;
241 303 }
242 304
243 - if (!$notificationUserIds) {
244 - return;
305 + // the mentioned user ids
306 + if ($mentionedUserIds = Arr::get($comment->meta, 'mentioned_user_ids', [])) {
307 + foreach ($mentionedUserIds as $mentionedUserId) {
308 + if (NotificationPref::willGetNotification($mentionedUserId, 'mention', 'mail', $this->isEnabled('mention_mail'))) {
309 + $notificationUserIds[] = $mentionedUserId;
310 + }
311 + }
245 312 }
246 313
247 314 if (!$notificationUserIds) {
248 315 return;
@@ -263,9 +330,11 @@
263 330 if ($users->isEmpty()) {
264 331 return; // it's done
265 332 }
266 333
267 - $emailBody = $this->getCommentHtml($comment, true);
334 + $undeliverableEmails = Helper::getUndeliverableEmails($users->pluck('user_email')->toArray());
335 +
336 + $emailBody = $comment->getCommentHtml(true);
268 337 $emailSubject = $comment->getEmailSubject($feed);
269 338
270 339 $feedPermalik = $feed->getPermalink() . '?comment_id=' . $comment->id;
271 340 $usersCount = count($users);
@@ -277,8 +346,12 @@
277 346 if ($user->ID == $comment->user_id) {
278 347 continue;
279 348 }
280 349
350 + if ($undeliverableEmails && in_array(strtolower($user->user_email), $undeliverableEmails)) {
351 + continue;
352 + }
353 +
281 354 $newEmailBody = str_replace([
282 355 '##feed_permalink##',
283 356 '##email_notification_url##'
284 357 ], [
@@ -285,8 +358,26 @@
285 358 ProfileHelper::signUserUrlWithAuthHash($feedPermalik, $user->ID),
286 359 ProfileHelper::getSignedNotificationPrefUrl($user->ID)
287 360 ], $emailBody);
288 361
362 + $notificationBagde = $this->getNotificationBadges($user->ID);
363 + if ($notificationBagde) {
364 + $newEmailBody = str_replace('<!--before_footer_section-->', $notificationBagde, $newEmailBody);
365 + }
366 +
367 + $hooksSections = apply_filters('fluent_community/comment_notification/email_sections', [
368 + 'before_content' => '',
369 + 'after_content' => ''
370 + ], $user, $comment);
371 +
372 + if (!empty($hooksSections['before_content'])) {
373 + $newEmailBody = str_replace('<!--email_content_before-->', $hooksSections['before_content'], $newEmailBody);
374 + }
375 +
376 + if (!empty($hooksSections['after_content'])) {
377 + $newEmailBody = str_replace('<!--email_content_after-->', $hooksSections['after_content'], $newEmailBody);
378 + }
379 +
289 380 $mailer = new Mailer('', $emailSubject, $newEmailBody);
290 381 $mailer->to($user->user_email, $user->display_name);
291 382 $mailer->send();
292 383
@@ -298,9 +389,9 @@
298 389
299 390 if (($index + 1) % $maxSendPerSecond == 0) {
300 391 $timeTaken = microtime(true) - $startTime;
301 392 if ($timeTaken < 1) {
302 - usleep(1000000 - ($timeTaken * 1000000));
393 + usleep((int)(1000000 - ($timeTaken * 1000000)));
303 394 }
304 395 $startTime = microtime(true);
305 396 }
306 397 }
@@ -310,9 +401,8 @@
310 401 }
311 402
312 403 public function emailNotifyUsersForEveryoneTag($feedId, $lastSendUserId = 0)
313 404 {
314 -
315 405 if (!$this->maxRunTime) {
316 406 $this->maxRunTime = Utility::getMaxRunTime();
317 407 }
318 408
@@ -322,13 +412,9 @@
322 412 if (!$feed || !$feed->space) {
323 413 return true;
324 414 }
325 415
326 - $message = $feed->message;
327 - $pattern = '/(?<!\S)@everyone(?!\S)/';
328 -
329 - // match if the message contains @everyone
330 - if (!preg_match($pattern, $message)) {
416 + if (!$feed->isEnabledForEveryoneTag()) {
331 417 return true;
332 418 }
333 419
334 420 $notification = Notification::where('action', 'space_feed/created')
@@ -338,11 +424,12 @@
338 424 if (!$notification) {
339 425 return true;
340 426 }
341 427
342 - $users = User::whereDoesntHave('notificationSubscriptions', function ($query) {
343 - $query->where('notification_type', 'mention_mail')
344 - ->where('is_read', 0);
428 + $users = User::whereDoesntHave('notificationPreferences', function ($query) {
429 + $query->where('channel', 'mail')
430 + ->where('event_key', 'mention')
431 + ->where('value', 0);
345 432 })
346 433 ->whereHas('space_pivot', function ($query) use ($feed) {
347 434 $query->where('space_id', $feed->space_id)
348 435 ->where('status', 'active');
@@ -360,17 +447,21 @@
360 447 if ($users->isEmpty()) {
361 448 return true; // it's done
362 449 }
363 450
451 + $undeliverableEmails = Helper::getUndeliverableEmails($users->pluck('user_email')->toArray());
452 +
364 453 $author = $feed->user;
454 +
365 455 $emailSubject = \sprintf(
366 - /* translators: %1$s is the user name, %2$s is the space title and %3$3s is the time */
367 - __('%1$s mentioned you and others in a post at %2$s [%3$s]', 'fluent-community'),
368 - $author->display_name,
369 - $feed->space->title,
370 - gmdate('H:i', strtotime($feed->created_at))
456 + /* translators: for admin post to send email all space members: %1$s is the feed title, %2$s is the author name and %3$s space name */
457 + __('%1$s - %2$s [%3$s]', 'fluent-community'),
458 + $feed->getHumanExcerpt(30),
459 + $author->getPublicDisplayName(),
460 + $feed->space->title
371 461 );
372 - $emailBody = $this->getFeedHtml($feed, true);
462 +
463 + $emailBody = $feed->getFeedHtml(true);
373 464 $feedPermalink = $feed->getPermalink();
374 465
375 466 $startTime = microtime(true);
376 467 $maxSendPerSecond = 10; // max 10 emails per second
@@ -380,8 +471,12 @@
380 471 if ($user->ID == $author->ID) {
381 472 continue;
382 473 }
383 474
475 + if ($undeliverableEmails && in_array(strtolower($user->user_email), $undeliverableEmails)) {
476 + continue;
477 + }
478 +
384 479 $newEmailBody = str_replace([
385 480 '##feed_permalink##',
386 481 '##email_notification_url##'
387 482 ], [
@@ -388,8 +483,26 @@
388 483 ProfileHelper::signUserUrlWithAuthHash($feedPermalink, $user->ID),
389 484 ProfileHelper::getSignedNotificationPrefUrl($user->ID)
390 485 ], $emailBody);
391 486
487 + $notificationBagde = $this->getNotificationBadges($user->ID);
488 + if ($notificationBagde) {
489 + $newEmailBody = str_replace('<!--before_footer_section-->', $notificationBagde, $newEmailBody);
490 + }
491 +
492 + $hooksSections = apply_filters('fluent_community/new_feed_everybody_notification/email_sections', [
493 + 'before_content' => '',
494 + 'after_content' => ''
495 + ], $user, $feed);
496 +
497 + if (!empty($hooksSections['before_content'])) {
498 + $newEmailBody = str_replace('<!--email_content_before-->', $hooksSections['before_content'], $newEmailBody);
499 + }
500 +
501 + if (!empty($hooksSections['after_content'])) {
502 + $newEmailBody = str_replace('<!--email_content_after-->', $hooksSections['after_content'], $newEmailBody);
503 + }
504 +
392 505 $mailer = new Mailer('', $emailSubject, $newEmailBody);
393 506 $mailer->to($user->user_email, $user->display_name);
394 507 $mailer->send();
395 508
@@ -397,13 +510,13 @@
397 510 // It's been 45 seconds, let's stop and schedule the next one and schedule a new one
398 511 as_schedule_single_action(time(), 'fluent_community/email_notify_users_everyone_tag', [$feedId, $lastSendUserId], 'fluent-community');
399 512 return true;
400 513 }
401 -
514 +
402 515 if (($index + 1) % $maxSendPerSecond == 0) {
403 516 $timeTaken = microtime(true) - $startTime;
404 517 if ($timeTaken < 1) {
405 - usleep(1000000 - ($timeTaken * 1000000));
518 + usleep((int)(1000000 - ($timeTaken * 1000000)));
406 519 }
407 520 $startTime = microtime(true);
408 521 }
409 522 }
@@ -411,79 +524,8 @@
411 524 sleep(1); // sleeping for 1 second
412 525 return $this->emailNotifyUsersForEveryoneTag($feedId, $lastSendUserId);
413 526 }
414 527
415 - public function getCommentHtml($comment, $withPlaceholder = false)
416 - {
417 - $emailComposer = new \FluentCommunity\App\Services\Libs\EmailComposer();
418 - if ($withPlaceholder) {
419 - $postPermalink = '##feed_permalink##';
420 - } else {
421 - $postPermalink = $comment->post->getPermalink() . '?comment_id=' . $comment->id;
422 - }
423 -
424 - if ($comment->post->title) {
425 - $postTitle = $comment->post->title;
426 - } else {
427 - $postTitle = $comment->post->getHumanExcerpt(120);
428 - }
429 -
430 - $renderedMessage = $comment->message_rendered;
431 -
432 - // Remove all the URLs with the text but make it underlined
433 - $renderedMessage = preg_replace('/<a href="([^"]+)">([^<]+)<\/a>/', '<span style="text-decoration: underline !important;">$2</span>', $renderedMessage);
434 -
435 - $renderedMessage .= $this->getMediaHtml($comment->meta, $postPermalink);
436 -
437 - $emailComposer->addBlock('boxed_content', $renderedMessage, [
438 - 'user' => $comment->user,
439 - 'permalink' => $postPermalink,
440 - 'post_content' => $postTitle
441 - ]);
442 -
443 - $emailComposer->addBlock('button', __('View the comment', 'fluent-community'), [
444 - 'link' => $postPermalink
445 - ]);
446 -
447 - // $emailComposer->setLogo(\FluentCommunity\Framework\Support\Arr::get($settting, 'logo'));
448 - $emailComposer->setDefaultFooter($withPlaceholder);
449 -
450 - return $emailComposer->getHtml();
451 - }
452 -
453 - public function getFeedHtml($feed, $withPlaceholder = false)
454 - {
455 - $emailComposer = new \FluentCommunity\App\Services\Libs\EmailComposer();
456 -
457 - if ($withPlaceholder) {
458 - $postPermalink = '##feed_permalink##';
459 - } else {
460 - $postPermalink = $feed->getPermalink();
461 - }
462 -
463 - $feedHtml = $feed->message_rendered;
464 - $feedHtml .= $this->getMediaHtml($feed->meta, $postPermalink);
465 -
466 - $emailComposer->addBlock('post_boxed_content', $feedHtml, [
467 - 'user' => $feed->user,
468 - 'title' => $feed->title,
469 - 'permalink' => $postPermalink,
470 - 'space_name' => $feed->space ? $feed->space->title : __('Community', 'fluent-community'),
471 - 'is_single' => true
472 - ]);
473 -
474 - $emailComposer->addBlock('button', __('Join the conversation', 'fluent-community'), [
475 - 'link' => $postPermalink
476 - ]);
477 -
478 - // $emailComposer->setLogo(\FluentCommunity\Framework\Support\Arr::get($settting, 'logo'));
479 -// $emailComposer->addFooterLine('paragraph', sprintf(__('You are getting this email because you are a member of %s', 'fluent-community'), '<a style="text-decoration: underline !important;" href="' . Helper::baseUrl() . '">' . get_bloginfo('name') . '</a>'));
480 -
481 - $emailComposer->setDefaultFooter();
482 -
483 - return $emailComposer->getHtml();
484 - }
485 -
486 528 public function maybeSendDailyDigest()
487 529 {
488 530 if (!$this->maxRunTime) {
489 531 $this->maxRunTime = Utility::getMaxRunTime();
@@ -504,11 +546,12 @@
504 546 $globalEnabled = Arr::get($settings, 'digest_email_status') === 'yes';
505 547 $lastSentUserId = Utility::getOption('last_digest_sent_user_id');
506 548
507 549 if ($globalEnabled) {
508 - $users = User::whereDoesntHave('notification_records', function ($query) {
509 - $query->where('notification_type', 'digest_mail')
510 - ->where('is_read', 0);
550 + $users = User::whereDoesntHave('notificationPreferences', function ($query) {
551 + $query->where('channel', 'mail')
552 + ->where('event_key', 'digest')
553 + ->where('value', 0);
511 554 })
512 555 ->whereHas('xprofile', function ($query) {
513 556 $query->where('status', 'active');
514 557 })
@@ -518,20 +561,21 @@
518 561 ->limit(100)
519 562 ->orderBy('ID', 'ASC')
520 563 ->get();
521 564 } else {
522 - $users = User::whereHas('notification_records', function ($query) {
523 - $query->where('notification_type', 'digest_mail')
524 - ->where('is_read', 1);
565 + $users = User::whereHas('notificationPreferences', function ($query) {
566 + $query->where('channel', 'mail')
567 + ->where('event_key', 'digest')
568 + ->where('value', 1);
525 569 })
526 - ->orderBy('ID', 'ASC')
527 570 ->whereHas('xprofile', function ($query) {
528 - return $query->where('status', 'active');
571 + $query->where('status', 'active');
529 572 })
530 573 ->when($lastSentUserId, function ($q) use ($lastSentUserId) {
531 574 $q->where('ID', '>', $lastSentUserId);
532 575 })
533 576 ->limit(100)
577 + ->orderBy('ID', 'ASC')
534 578 ->get();
535 579 }
536 580
537 581 if ($users->isEmpty()) {
@@ -540,15 +584,21 @@
540 584 Utility::updateOption('last_digest_sent_user_id', 0);
541 585 return false;
542 586 }
543 587
588 + $undeliverableEmails = Helper::getUndeliverableEmails($users->pluck('user_email')->toArray());
589 +
544 590 $startAt = microtime(true);
545 591 $maxSendPerSecond = 10;
546 -
547 592 $sentCount = 0;
548 593
549 594 foreach ($users as $user) {
550 - Utility::updateOption('last_digest_sent_user_id', $user->user_id);
595 + Utility::updateOption('last_digest_sent_user_id', $user->ID);
596 +
597 + if ($undeliverableEmails && in_array(strtolower($user->user_email), $undeliverableEmails)) {
598 + continue;
599 + }
600 +
551 601 $emailDigest = new DailyDigest($user);
552 602 if ($emailDigest->send()) {
553 603 $sentCount++;
554 604 }
@@ -561,9 +611,9 @@
561 611
562 612 if ($sentCount % $maxSendPerSecond === 0) {
563 613 $timeTaken = microtime(true) - $startAt;
564 614 if ($timeTaken < 1) {
565 - usleep(1000000 - ($timeTaken * 1000000));
615 + usleep((int)(1000000 - ($timeTaken * 1000000)));
566 616 }
567 617 $startAt = microtime(true);
568 618 }
569 619 }
@@ -584,13 +634,12 @@
584 634 if (!$xProfile) {
585 635 return;
586 636 }
587 637
588 - $settting = Helper::generalSettings();
589 -
590 638 $emailComposer = new \FluentCommunity\App\Services\Libs\EmailComposer();
591 639
592 640 $emailComposer->addBlock('paragraph', __('Hi Space Leader,', 'fluent-community'));
641 + /* translators: %1$s is replaced by the name of the user who requested to join the space, %2$s is replaced by the title of the space */
593 642 $emailComposer->addBlock('paragraph', sprintf(__('You have a new join request from %1$s to join %2$s.', 'fluent-community'), '<b>' . $xProfile->display_name . '</b>', '<b>' . $space->title . '</b>'));
594 643 $emailComposer->addBlock('paragraph', __('Please review the request in the portal', 'fluent-community'));
595 644
596 645 $emailComposer->addBlock('button', __('View Pending Join Requests', 'fluent-community'), [
@@ -596,15 +645,17 @@
596 645 $emailComposer->addBlock('button', __('View Pending Join Requests', 'fluent-community'), [
597 646 'link' => Helper::baseUrl('space/' . $space->slug . '/members?view_pending=yes')
598 647 ]);
599 648
600 - $emailComposer->setLogo(\FluentCommunity\Framework\Support\Arr::get($settting, 'logo'));
649 + $emailComposer->setDefaultLogo();
601 650
651 + /* translators: %s is replaced by the title of the space */
602 652 $emailComposer->addFooterLine('paragraph', sprintf(__('You are getting this email because you are an admin/moderator at %s', 'fluent-community'), '<a style="text-decoration: underline !important;" href="' . $space->getPermalink() . '">' . $space->title . '</a>'));
603 653
604 654 $emailBody = $emailComposer->getHtml();
605 655
606 656 $emailSubject = \sprintf(
657 + /* translators: %1$s is replaced by the name of the user who requested to join the space, %2$s is replaced by the title of the space */
607 658 __('%1$s requested to join %2$s', 'fluent-community'),
608 659 $xProfile->display_name,
609 660 $space->title
610 661 );
@@ -623,9 +674,9 @@
623 674 $modUserId = $moderatorsUserIds[0];
624 675
625 676 $moderator = get_user_by('ID', $modUserId);
626 677
627 - if (!$moderator || !$moderator->user_email) {
678 + if (!$moderator || !$moderator->user_email || Helper::isUndeliverableEmail($moderator->user_email)) {
628 679 return;
629 680 }
630 681
631 682 $mailer->to($moderator->user_email, $moderator->display_name);
@@ -639,44 +690,57 @@
639 690
640 691 $mailer = new Mailer('', $emailSubject, $emailBody);
641 692
642 693 $users = User::whereIn('ID', $chunk)->get();
694 + $undeliverableEmails = Helper::getUndeliverableEmails($users->pluck('user_email')->toArray());
695 +
696 + $first = null;
643 697 foreach ($users as $user) {
644 698 if (!$user || !$user->user_email) {
645 699 continue;
646 700 }
701 +
702 + if ($undeliverableEmails && in_array(strtolower($user->user_email), $undeliverableEmails)) {
703 + continue;
704 + }
705 + if (!$first) {
706 + $mailer->to($user->user_email, $user->display_name);
707 + $first = $user;
708 + continue;
709 + }
647 710 $mailer->addBCC($user->display_name . ' <' . $user->user_email . '>');
648 711 }
649 712
650 - $mailer->send();
651 - sleep(1); // sleeping for 1 second
713 + if ($first) {
714 + $mailer->send();
715 + sleep(1); // sleeping for 1 second
716 + }
652 717 }
653 718
654 719 return true;
655 720 }
656 721
657 - private function getMediaHtml($meta, $postPermalink)
722 + private function getNotificationBadges($userId)
658 723 {
659 - $mediaImage = Arr::get($meta, 'media_preview.image');
660 - $mediaCount = 0;
661 - if (!$mediaImage) {
662 - $mediaItems = Arr::get($meta, 'media_items', []);
663 - if ($mediaItems) {
664 - $mediaImage = Arr::get($mediaItems[0], 'url');
665 - $mediaCount = count($mediaItems);
724 + $unreadCount = Notification::byStatus('unread', $userId)->count();
725 + $unreadMessages = apply_filters('fluent_messaging/get_unread_message_count', 0, $userId);
726 +
727 + $html = '';
728 + $linkColor = Utility::getThemeColor();
729 + if ($unreadCount) {
730 + $notificationUrl = ProfileHelper::signUserUrlWithAuthHash(Helper::baseUrl('notifications'), $userId);
731 + /* translators: %d is replaced by the number of unread notifications */
732 + $html = '<a style="text-decoration: none; color: ' . esc_attr($linkColor) . ';" href="' . $notificationUrl . '">' . sprintf(__('🔔 %d Unread Notifications', 'fluent-community'), $unreadCount) . '</a>';
733 + if ($unreadMessages) {
734 + $html .= '<span style="margin: 0 10px;"> | </span>';
666 735 }
667 736 }
668 737
669 - $feedHtml = '';
670 -
671 - if ($mediaImage) {
672 - $feedHtml .= '<div class="fcom_media" style="margin-top: 20px;">';
673 - $feedHtml .= '<a href="' . $postPermalink . '"><img src="' . $mediaImage . '" style="max-width: 100%; height: auto; display: block; margin: 0 auto 0px;" /></a>';
674 - if ($mediaCount > 1) {
675 - $feedHtml .= '<p style="text-align: center; font-size: 14px; color: #666; margin-top: 10px;">' . sprintf(_n('+%d more image', '+%d more images', $mediaCount - 1, 'fluent-community'), $mediaCount - 1) . '</p>';
676 - }
677 - $feedHtml .= '</div>';
738 + if ($unreadMessages) {
739 + $chatUrl = ProfileHelper::signUserUrlWithAuthHash(Helper::baseUrl('chat'), $userId);
740 + /* translators: %d is replaced by the number of unread messages */
741 + $html .= '<a style="text-decoration: none; color: ' . esc_attr($linkColor) . ';" href="' . $chatUrl . '">' . sprintf(__('✉️ %d Unread Messages', 'fluent-community'), $unreadMessages) . '</a>';
678 742 }
679 743
680 - return $feedHtml;
744 + return $html;
681 745 }
682 746 }