PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 1.0.95
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v1.0.95
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 / EmailNotificationHandler.php

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

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