PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 1.0.98
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v1.0.98
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 / Http / Controllers / FeedsController.php

FeedsController.php in FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses 1.0.98, at app/Http/Controllers/FeedsController.php

803 lines 26.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\Http\Controllers;
4
5 use FluentCommunity\App\Functions\Utility;
6 use FluentCommunity\App\Models\Media;
7 use FluentCommunity\App\Models\NotificationSubscriber;
8 use FluentCommunity\App\Models\Space;
9 use FluentCommunity\App\Models\User;
10 use FluentCommunity\App\Services\CustomSanitizer;
11 use FluentCommunity\App\Services\FeedsHelper;
12 use FluentCommunity\App\Services\Helper;
13 use FluentCommunity\App\Services\Libs\FileSystem;
14 use FluentCommunity\App\Services\ProfileHelper;
15 use FluentCommunity\App\Services\RemoteUrlParser;
16 use FluentCommunity\Framework\Http\Request\Request;
17 use FluentCommunity\App\Models\Comment;
18 use FluentCommunity\App\Models\Feed;
19 use FluentCommunity\App\Models\Reaction;
20 use FluentCommunity\App\Models\BaseSpace;
21 use FluentCommunity\Framework\Support\Arr;
22
23 class FeedsController extends Controller
24 {
25 public function get(Request $request)
26 {
27 $bySpace = $request->get('space');
28 $userId = $request->getSafe('user_id', 'intval', '');
29 $selectedTopic = $request->getSafe('topic_slug', 'sanitize_text_field', '');
30 $search = $request->get('search');
31 if ($bySpace) {
32 // just for validation
33 $space = BaseSpace::where('slug', $bySpace)->first();
34 if (!$space) {
35 return $this->sendError('Invalid space slug');
36 }
37 }
38
39 $feedsQuery = Feed::where('status', 'published')
40 ->select(Feed::$publicColumns)
41 ->with([
42 'xprofile' => function ($q) {
43 $q->select(ProfileHelper::getXProfilePublicFields());
44 },
45 'comments.xprofile' => function ($q) {
46 $q->select(ProfileHelper::getXProfilePublicFields());
47 },
48 'space',
49 'reactions' => function ($q) {
50 $q->with([
51 'xprofile' => function ($query) {
52 $query->select(['user_id', 'avatar']);
53 }
54 ])
55 ->where('type', 'like')
56 ->limit(3);
57 },
58 'terms' => function ($q) {
59 $q->select(['title', 'slug'])
60 ->where('taxonomy_name', 'post_topic');
61 }
62 ]
63 )
64 ->searchBy($search)
65 ->byTopicSlug($selectedTopic)
66 ->customOrderBy($request->get('type', ''));
67
68 $stickyFeed = null;
69
70 $disableSticky = $request->get('disable_sticky', '') == 'yes' || !!$search || !!$selectedTopic;
71
72 if ($bySpace && !$disableSticky) {
73 $feedsQuery = $feedsQuery->filterBySpaceSlug($bySpace)
74 ->where('is_sticky', 0);
75 if ($request->page == 1) {
76 $stickyFeed = Feed::where('space_id', $space->id)
77 ->where('is_sticky', 1)
78 ->with([
79 'xprofile' => function ($q) {
80 $q->select(ProfileHelper::getXProfilePublicFields());
81 },
82 'comments.xprofile' => function ($q) {
83 $q->select(ProfileHelper::getXProfilePublicFields());
84 },
85 'space'
86 ]
87 )
88 ->first();
89 }
90 }
91
92 if ($userId) {
93 $feedsQuery = $feedsQuery->where('user_id', $userId);
94 if ($userId != get_current_user_id()) {
95 $feedsQuery = $feedsQuery->byUserAccess(get_current_user_id());
96 }
97 } else {
98 $feedsQuery->byUserAccess(get_current_user_id());
99 }
100
101 do_action_ref_array('fluent_community/feeds_query', [&$feedsQuery, $request->all()]);
102
103 $feeds = $feedsQuery->paginate();
104
105 // add $stickyFeed to the first page
106 if ($stickyFeed) {
107 $stickyFeed = $this->transformFeed($stickyFeed);
108 }
109
110 $feeds->getCollection()->each(function ($feed) {
111 $this->transformFeed($feed);
112 });
113
114 $data = [
115 'feeds' => $feeds,
116 'sticky' => $stickyFeed
117 ];
118
119 $isMainFeed = $request->get('page') == 1 && !$search && !$userId;
120 if ($isMainFeed && get_current_user_id()) {
121 $data['last_fetched_timestamp'] = current_time('timestamp');
122 }
123
124 return $data;
125 }
126
127 public function getFeedBySlug(Request $request, $feed_slug)
128 {
129 if ($request->get('context') == 'edit') {
130 $feed = Feed::where('slug', $feed_slug)->first();
131
132 if (!$feed || !$feed->hasEditAccess(get_current_user_id())) {
133 return $this->sendError([
134 'message' => 'You do not have permission to edit this feed'
135 ]);
136 }
137
138 return [
139 'feed' => FeedsHelper::transformForEdit($feed)
140 ];
141 }
142
143 $feed = Feed::where('slug', $feed_slug)
144 ->select(Feed::$publicColumns)
145 ->with([
146 'xprofile' => function ($q) {
147 $q->select(ProfileHelper::getXProfilePublicFields());
148 },
149 'space',
150 'comments.xprofile' => function ($q) {
151 $q->select(ProfileHelper::getXProfilePublicFields());
152 },
153 'reactions' => function ($q) {
154 $q->with([
155 'xprofile' => function ($query) {
156 $query->select(['user_id', 'avatar']);
157 }
158 ])
159 ->where('type', 'like')
160 ->limit(3);
161 },
162 'terms' => function ($q) {
163 $q->select(['title', 'slug'])
164 ->where('taxonomy_name', 'post_topic');
165 }
166 ])
167 ->byUserAccess($this->getUserId())
168 ->first();
169
170 if (!$feed) {
171 return $this->sendError([
172 'message' => __('The feed could not be found', 'fluent-commuity')
173 ], 404);
174 }
175
176 $this->transformFeed($feed);
177
178 return [
179 'feed' => $feed
180 ];
181 }
182
183 public function getBookmarks(Request $request)
184 {
185 $userId = get_current_user_id();
186
187 $feedsQuery = Feed::where('status', 'published')
188 ->select(Feed::$publicColumns)
189 ->with([
190 'xprofile' => function ($q) {
191 $q->select(ProfileHelper::getXProfilePublicFields());
192 },
193 'comments.xprofile' => function ($q) {
194 $q->select(ProfileHelper::getXProfilePublicFields());
195 },
196 'space'
197 ]
198 )
199 ->byBookMarked($userId)
200 ->byUserAccess($userId)
201 ->searchBy($request->get('search'));
202
203
204 if ($type = $request->get('type')) {
205 $feedsQuery = $feedsQuery->where('type', $type);
206 }
207
208 $feeds = $feedsQuery->orderBy('id', 'DESC')
209 ->paginate();
210
211 $feeds->getCollection()->each(function ($feed) {
212 $this->transformFeed($feed);
213 });
214
215 $data = [
216 'feeds' => $feeds
217 ];
218
219 if ($request->get('page') == 1) {
220 $lastItem = FeedsHelper::getLastFeedId();
221 if ($lastItem) {
222 $data['last_id'] = $lastItem;
223 }
224 }
225
226 return $data;
227 }
228
229 public function store(Request $request)
230 {
231 $user = $this->getUser(true);
232 do_action('fluent_community/check_rate_limit/create_post', $user);
233 $requestData = $request->all();
234
235 $data = $this->sanitizeAndValidateData($requestData);
236
237 if ($isDulicate = $this->checkForDuplicatePost($user->ID, $data['message'])) {
238 return $isDulicate;
239 }
240
241 $feed = new Feed();
242 $feed->user_id = $user->ID;
243
244 if ($spaceSlug = $request->get('space')) {
245 $data['space_id'] = $this->validateAndSetSpace($spaceSlug, $user);
246 } else if (!Helper::hasGlobalPost()) {
247 return $this->sendError([
248 'message' => __('Please select a valid space to post in.', 'fluent-community')
249 ]);
250 }
251
252 $message = $data['message'];
253 $mentions = FeedsHelper::getMentions($data['message'], Arr::get($data, 'space_id'));
254 if ($mentions) {
255 $data['message'] = $message;
256 $message = $mentions['text'];
257 }
258
259 // replace new line with br
260 $data['message_rendered'] = wp_kses_post(FeedsHelper::mdToHtml($message));
261
262 [$data, $mediaItems] = FeedsHelper::processFeedMetaData($data, $requestData);
263
264 $data = apply_filters('fluent_community/feed/new_feed_data', $data, $requestData);
265
266 $feed->fill($data);
267
268 $feed->save();
269
270 if ($mediaItems) {
271 $this->saveMediaItems($feed, $mediaItems);
272 }
273
274 $this->handleMentions($feed, $mentions ?? []);
275
276 $feed->load(['xprofile', 'comments.xprofile']);
277 if ($feed->space_id) {
278 $feed->load(['space']);
279 $topicIds = (array)$request->get('topic_ids', []);
280 // take only max topics per post
281 if ($topicIds) {
282 $topicsConfig = Helper::getTopicsConfig();
283 $topicIds = array_slice($topicIds, 0, $topicsConfig['max_topics_per_post']);
284 $feed->attachTopics($topicIds, false);
285 }
286 }
287
288 do_action('fluent_community/feed/created', $feed);
289 if ($feed->space_id) {
290 do_action('fluent_community/space_feed/created', $feed);
291 }
292
293 return [
294 'feed' => $this->transformFeed($feed),
295 'message' => __('Your post has been published', 'fluent-community'),
296 'last_fetched_timestamp' => current_time('timestamp')
297 ];
298 }
299
300 public function update(Request $request, $feedId)
301 {
302 $requestData = $request->all();
303 $data = $this->sanitizeAndValidateData($requestData);
304 $user = $this->getUser(true);
305 $existingFeed = Feed::findOrFail($feedId);
306 $user->canEditFeed($existingFeed, true);
307
308 $message = $data['message'];
309 $mentions = FeedsHelper::getMentions($data['message'], Arr::get($data, 'space_id'));
310 if ($mentions) {
311 $data['message'] = $message;
312 $message = $mentions['text'];
313 }
314
315 // replace new line with br
316 $data['message_rendered'] = wp_kses_post(FeedsHelper::mdToHtml($message));
317
318 [$data, $mediaItems] = FeedsHelper::processFeedMetaData($data, $requestData, $existingFeed);
319
320 $data = apply_filters('fluent_community/feed/update_feed_data', $data, $requestData);
321
322 if ($message != $existingFeed->message) {
323 $data['meta']['last_edited'] = [
324 'user_id' => $user->ID,
325 'time' => current_time('mysql')
326 ];
327 }
328
329 $data = apply_filters('fluent_community/feed/update_data', $data, $existingFeed);
330 $existingFeed->fill($data);
331 $dirty = $existingFeed->getDirty();
332
333 $existingFeed->fill($data);
334 $existingFeed->save();
335
336 if ($message != $existingFeed->message) {
337 $editHistory = $existingFeed->getCustomMeta('_edit_history', []);
338 if (!$editHistory) {
339 $editHistory = [];
340 }
341
342 $editHistory[] = array_filter([
343 'user_id' => $user->ID,
344 'time' => current_time('mysql'),
345 'prev_message' => $existingFeed->message,
346 'prev_title' => $existingFeed->title
347 ]);
348
349 // get last 5 edit history
350 $editHistory = array_slice($editHistory, -5);
351 $existingFeed->updateCustomMeta('_edit_history', $editHistory);
352 }
353
354 if ($mediaItems) {
355 $this->saveMediaItems($existingFeed, $mediaItems);
356 }
357
358 $existingFeed->load(['xprofile', 'comments.xprofile']);
359
360 if ($existingFeed->space_id) {
361 $existingFeed->load(['space']);
362 $topicIds = (array)Arr::get($requestData, 'topic_ids', []);
363 // take only max topics per post
364 if ($topicIds) {
365 $topicsConfig = Helper::getTopicsConfig();
366 $topicIds = array_slice($topicIds, 0, $topicsConfig['max_topics_per_post']);
367 $existingFeed->attachTopics($topicIds, true);
368 }
369 }
370
371 if ($dirty) {
372 do_action('fluent_community/feed/updated', $existingFeed, $dirty);
373 if ($existingFeed->space_id) {
374 do_action('fluent_community/space_feed/updated', $existingFeed);
375 }
376 }
377
378 return [
379 'feed' => $this->transformFeed($existingFeed),
380 'message' => __('Your post has been updated', 'fluent-community')
381 ];
382 }
383
384 public function patchFeed(Request $request, $feedId)
385 {
386 $feed = Feed::findOrFail($feedId);
387 $user = $this->getUser(true);
388
389 $isMod = $user->isCommunityModerator();
390 $isAuthor = $feed->user_id == $user->ID;
391
392 if (!$isMod && !$isAuthor) {
393 return $this->sendError([
394 'message' => __('You do not have permission to perform this action', 'fluent-community')
395 ]);
396 }
397
398 $allData = $request->all();
399 $validKeys = ['is_sticky', 'priority', 'comments_disabled'];
400
401 if (!$isMod) {
402 $validKeys = ['comments_disabled'];
403 }
404
405 $data = Arr::only($allData, $validKeys);
406
407 $data = array_map('intval', $data);
408
409 if (isset($data['is_sticky'])) {
410 $data['is_sticky'] = $data['is_sticky'] ? 1 : 0;
411 if ($data['is_sticky'] && $feed->space_id) {
412 // remove all the sticky posts from the space
413 Feed::where('space_id', $feed->space_id)->update(['is_sticky' => 0]);
414 }
415 }
416
417 if (isset($data['comments_disabled'])) {
418 $meta = $feed->meta;
419 $meta['comments_disabled'] = $data['comments_disabled'] ? 'yes' : 'no';
420 $data['meta'] = $meta;
421 }
422
423
424 if ($data) {
425 $feed->fill($data);
426 $dirty = $feed->getDirty();
427 if ($dirty) {
428 $feed->save();
429 do_action('fluent_community/feed/updated', $feed, $dirty);
430 }
431 }
432
433 return [
434 'feed' => $feed,
435 'message' => __('Feed updated', 'fluent-community')
436 ];
437 }
438
439 public function getLinks(Request $request)
440 {
441 return [
442 'links' => Helper::getFeedLinks()
443 ];
444 }
445
446 public function updateLinks(Request $request)
447 {
448 $links = $request->get('links', []);
449
450 $links = array_map(function ($link) {
451 return CustomSanitizer::santizeLinkItem($link);
452 }, $links);
453
454 Helper::updateFeedLinks($links);
455
456 return [
457 'message' => __('Links have been updated.', 'fluent-community'),
458 'links' => $links
459 ];
460 }
461
462 private function saveMediaItems($feed, $mediaItems)
463 {
464 foreach ($mediaItems as $media) {
465 $media->feed_id = $feed->id;
466 $media->is_active = 1;
467 $media->object_source = 'feed';
468 $media->save();
469 }
470 }
471
472 private function handleMentions($feed, $mentions)
473 {
474 if ($mentions) {
475 do_action('fluent_community/feed_mentioned', $feed, $mentions['users']);
476 }
477 }
478
479 private function sanitizeAndValidateData($data)
480 {
481 $data['type'] = 'text';
482
483 $this->validate($data, [
484 'message' => 'required'
485 ], [
486 'message.required' => __('Message is required', 'fluent-community'),
487 ]);
488
489 return FeedsHelper::sanitizeAndValidateData($data);
490 }
491
492 private function checkForDuplicatePost($userId, $message)
493 {
494 $message = trim($message);
495
496 $exist = Feed::where('user_id', $userId)
497 ->where('message', $message)
498 ->where('created_at', '>', gmdate('Y-m-d H:i:s', current_time('timestamp') - 7 * 24 * 60 * 60))
499 ->first();
500
501 if ($exist) {
502 return $this->sendError(['message' => 'No duplicate post please!']);
503 }
504
505 return false;
506 }
507
508 private function validateAndSetSpace($spaceSlug, $user)
509 {
510 if ($spaceSlug == '__self__post__') {
511 if (!Helper::hasGlobalPost()) {
512 throw new \Exception(__('Please select a valid space to post in', 'fluent-community'));
513 }
514
515 return null;
516 }
517
518 $space = Space::where('slug', $spaceSlug)->first();
519
520 if (!$space) {
521 throw new \Exception(__('Please select a valid space to post in', 'fluent-community'));
522 }
523
524 $user->verifySpacePermission('can_create_post', $space);
525
526 return $space->id;
527 }
528
529 public function deleteFeed(Request $request, $feed_id)
530 {
531 $feed = Feed::findOrFail($feed_id);
532
533 $user = User::find(get_current_user_id());
534 $user->canDeleteFeed($feed, true);
535 do_action('fluent_community/feed/before_deleted', $feed);
536 $feed->delete();
537
538 do_action('fluent_community/feed/deleted', $feed_id);
539
540 return [
541 'message' => 'Feed has been deleted successfully'
542 ];
543 }
544
545 public function deleteMediaPreview(Request $request, $feed_id)
546 {
547 $feed = Feed::findOrFail($feed_id);
548 $user = User::find(get_current_user_id());
549 $user->canDeleteFeed($feed, true);
550
551 do_action('fluent_community/feed/media_deleted', $feed->media);
552
553 $meta = $feed->meta;
554 $meta['media_preview'] = null;
555
556 $feed->meta = $meta;
557 $feed->save();
558
559 return [
560 'message' => __('Media preview image has been removed successfully.', 'fluent-community')
561 ];
562 }
563
564 public function handleMediaUpload(Request $request)
565 {
566 $allowedTypes = implode(
567 ',',
568 apply_filters('fluent_community/support_attachment_types', [
569 'image/jpeg',
570 'image/pjpeg',
571 'image/jpeg',
572 'image/pjpeg',
573 'image/png',
574 'image/gif',
575 'image/webp'
576 ])
577 );
578
579 $files = $this->validate($this->request->files(), [
580 'file' => 'mimetypes:' . $allowedTypes,
581 ], [
582 'file.mimetypes' => __('The file must be an image type.', 'fluent-community')
583 ]);
584
585 $uploadedFiles = FileSystem::put($files);
586
587 $file = $uploadedFiles[0];
588
589 $willWebPConvert = apply_filters('fluent_community/convert_image_to_webp', true, $file);
590
591 if ($request->get('resize') && $maxWidth = $request->get('max_width')) {
592 $upload_dir = wp_upload_dir();
593 $fileUrl = str_replace($upload_dir['baseurl'], $upload_dir['basedir'], $file['url']);
594
595 $editor = wp_get_image_editor($fileUrl);
596
597 if (!is_wp_error($editor) && $editor->get_size()['width'] > $maxWidth) {
598 // Current file extension
599 $ext = pathinfo($file['url'], PATHINFO_EXTENSION);
600 $imageExtensions = ['jpg', 'jpeg', 'png', 'gif'];
601
602 $willConvert = in_array($ext, $imageExtensions) && $willWebPConvert;
603
604 if ($willConvert) {
605 $imageExtensions = array_map(function ($ext) {
606 return '.' . $ext;
607 }, $imageExtensions);
608 $fileUrl = str_replace($imageExtensions, '.webp', $fileUrl);
609 $file['file'] = str_replace($imageExtensions, '.webp', $file['file']);
610 $file['url'] = str_replace($imageExtensions, '.webp', $file['url']);
611 $file['type'] = 'image/webp';
612 }
613
614 // resize the image
615 $editor->resize($maxWidth, null, false);
616 $editor->set_quality(90);
617 if ($willConvert) {
618 $editor->save($fileUrl, 'image/webp');
619 // remove original file now
620 wp_delete_file(str_replace('.webp', '.' . $ext, $fileUrl));
621 $file['is_converted'] = true;
622 } else {
623 $editor->save($fileUrl);
624 }
625
626 $file['meta'] = [
627 'width' => $editor->get_size()['width'],
628 'height' => $editor->get_size()['height']
629 ];
630 }
631 $file['path'] = $upload_dir['basedir'] . '/fluent-community/' . $file['file'];
632 } else {
633 $upload_dir = wp_upload_dir();
634 $file['path'] = $upload_dir['basedir'] . '/fluent-community/' . $file['file'];
635 }
636
637 if ($willWebPConvert && empty($file['is_converted']) && !$request->get('skip_convert')) {
638 $path = $file['path'];
639 $extension = pathinfo($path, PATHINFO_EXTENSION);
640
641 $convertFromExtensions = ['png', 'jpg', 'jpeg', 'gif'];
642 if ($extension != 'webp' && in_array($extension, $convertFromExtensions)) {
643 // Let's convert to webp
644 $editor = wp_get_image_editor($file['path']);
645 if (!is_wp_error($editor)) {
646 $orginalPath = $file['path'];
647 $file['path'] = str_replace('.' . $extension, '.webp', $file['path']);
648 $file['url'] = str_replace('.' . $extension, '.webp', $file['url']);
649 $file['type'] = 'image/webp';
650 $editor->save($file['path'], 'image/webp');
651 wp_delete_file($orginalPath);
652
653 $file['meta'] = [
654 'width' => $editor->get_size()['width'],
655 'height' => $editor->get_size()['height']
656 ];
657 }
658 }
659 }
660
661 $mediaData = [
662 'media_type' => $file['type'],
663 'driver' => 'local',
664 'media_path' => $file['path'],
665 'media_url' => $file['url'],
666 'settings' => Arr::get($file, 'meta', [])
667 ];
668
669 $mediaData = apply_filters('fluent_community/media_upload_data', $mediaData, $file);
670
671 if (is_wp_error($mediaData)) {
672 return $this->sendError([
673 'message' => $mediaData->get_error_message(),
674 'errors' => $mediaData->get_error_data()
675 ]);
676 }
677
678 if (!$mediaData) {
679 return $this->sendError([
680 'message' => 'Error while uploading the media'
681 ]);
682 }
683
684 // Let's create the media now
685 $media = Media::create($mediaData);
686
687 $mediaUrl = $media->public_url;
688
689 $mediaUrl = add_query_arg([
690 'media_key' => $media->media_key,
691 ], $mediaUrl);
692
693 return [
694 'media' => [
695 'url' => $mediaUrl,
696 'media_key' => $media->media_key,
697 'type' => $media->media_type,
698 'width' => Arr::get($media->settings, 'width'),
699 'height' => Arr::get($media->settings, 'height')
700 ]
701 ];
702 }
703
704 public function getTicker(Request $request)
705 {
706 do_action('fluent_communit/track_activity');
707 $lastLoadedTimeStamp = $request->get('last_fetched_timestamp');
708
709 //check if $lastLoadedTimeStamp is valid date
710 if (!$lastLoadedTimeStamp || (current_time('timestamp') - $lastLoadedTimeStamp) > HOUR_IN_SECONDS) {
711 return [
712 'last_fetched_timestamp' => current_time('timestamp'),
713 'error' => 'Invalid timestamp',
714 'given' => $lastLoadedTimeStamp
715 ];
716 }
717
718 $userId = get_current_user_id();
719 if (!$userId) {
720 return [
721 'last_fetched_timestamp' => current_time('timestamp'),
722 'error' => 'Invalid user'
723 ];
724 }
725
726 $newItemsCount = Feed::where('created_at', '>', date('Y-m-d H:i:s', $lastLoadedTimeStamp))
727 ->where('status', 'published')
728 ->byUserAccess(get_current_user_id())
729 ->count();
730
731 $notificationCount = NotificationSubscriber::unread()->where('user_id', $userId)->count();
732
733 return apply_filters('fluent_community/feed_ticker', [
734 'last_fetched_timestamp' => current_time('timestamp'),
735 'new_items_count' => $newItemsCount > 10 ? 10 : $newItemsCount,
736 'unread_notification_count' => $notificationCount
737 ]);
738 }
739
740 public function getOembed(Request $request)
741 {
742 $url = $request->get('url');
743 // check if the url is valid
744 $metaData = RemoteUrlParser::parse($url);
745
746 if ($metaData && !is_wp_error($metaData)) {
747 return [
748 'oembed' => $metaData
749 ];
750 }
751
752 return $this->send([
753 'message' => 'No oembed data found',
754 'url' => $url
755 ]);
756 }
757
758 public function markdownToHtml(Request $request)
759 {
760 $message = trim(sanitize_textarea_field($request->get('text', '')));
761
762 $html = FeedsHelper::mdToHtml($message);
763
764 return [
765 'html' => $html
766 ];
767 }
768
769 private function transformFeed(Feed $feed)
770 {
771 $userId = $this->getUserId();
772 if ($userId) {
773 $feed->has_user_react = $feed->hasUserReact($userId, 'like');
774 $feed->bookmarked = $feed->hasUserReact($userId, 'bookmark');
775
776 $likedIds = FeedsHelper::getLikedIdsByUserFeedId($feed->id, get_current_user_id());
777 $feed->comments->each(function ($comment) use ($likedIds) {
778 if ($likedIds && in_array($comment->id, $likedIds)) {
779 $comment->liked = 1;
780 }
781 });
782
783 if ($feed->content_type == 'survey') {
784 $votedOptions = $feed->getSurveyCastsByUserId($userId);
785
786 if ($votedOptions) {
787 $surveyConfig = Arr::get($feed->meta, 'survey_config', []);
788 foreach ($surveyConfig['options'] as $index => $option) {
789 if (in_array($option['slug'], $votedOptions)) {
790 $surveyConfig['options'][$index]['voted'] = true;
791 }
792 }
793 $meta = $feed->meta;
794 $meta['survey_config'] = $surveyConfig;
795 $feed->meta = $meta;
796 }
797 }
798 }
799
800 return $feed;
801 }
802 }
803