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

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

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