# fluent-community/1.0.93/app/Http/Controllers/FeedsController.php

FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS &amp; Online Courses, version 1.0.93. 1,200 lines.

- Page: https://pluginprobe.com/plugins/fluent-community/1.0.93/code/app/Http/Controllers/FeedsController.php
- Raw: https://pluginprobe.com/plugins/fluent-community/1.0.93/raw/app/Http/Controllers/FeedsController.php
- Modified: 2024-11-07T12:38:44+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/fluent-community/1.0.93/code/app/Http/Controllers/FeedsController.php#L10-L20`.

```php
<?php

namespace FluentCommunity\App\Http\Controllers;

use FluentCommunity\App\Functions\Utility;
use FluentCommunity\App\Models\Media;
use FluentCommunity\App\Models\NotificationSubscriber;
use FluentCommunity\App\Models\Space;
use FluentCommunity\App\Models\User;
use FluentCommunity\App\Services\CustomSanitizer;
use FluentCommunity\App\Services\FeedsHelper;
use FluentCommunity\App\Services\Helper;
use FluentCommunity\App\Services\Libs\FileSystem;
use FluentCommunity\App\Services\ProfileHelper;
use FluentCommunity\App\Services\RemoteUrlParser;
use FluentCommunity\Framework\Http\Request\Request;
use FluentCommunity\App\Models\Comment;
use FluentCommunity\App\Models\Feed;
use FluentCommunity\App\Models\Reaction;
use FluentCommunity\App\Models\BaseSpace;
use FluentCommunity\Framework\Support\Arr;

class FeedsController extends Controller
{
    public function get(Request $request)
    {
        $bySpace = $request->get('space');
        $userId = $request->getSafe('user_id', 'intval', '');
        $selectedTopic = $request->getSafe('topic_slug', 'sanitize_text_field', '');

        $search = $request->get('search');

        if ($bySpace) {
            // just for validation
            $space = BaseSpace::where('slug', $bySpace)->first();
            if (!$space) {
                return $this->sendError('Invalid space slug');
            }
        }

        $feedsQuery = Feed::where('status', 'published')
            ->select(Feed::$publicColumns)
            ->with([
                    'xprofile'          => function ($q) {
                        $q->select(ProfileHelper::getXProfilePublicFields());
                    },
                    'comments.xprofile' => function ($q) {
                        $q->select(ProfileHelper::getXProfilePublicFields());
                    },
                    'space',
                    'reactions'         => function ($q) {
                        $q->with([
                            'xprofile' => function ($query) {
                                $query->select(['user_id', 'avatar']);
                            }
                        ])
                            ->where('type', 'like')
                            ->limit(3);
                    }
                ]
            )
            ->searchBy($search)
            ->byTopicSlug($selectedTopic)
            ->customOrderBy($request->get('type', ''));

        $stickyFeed = null;

        $disableSticky = $request->get('disable_sticky', '') == 'yes' || !!$search || !!$selectedTopic;

        if ($bySpace && !$disableSticky) {
            $feedsQuery = $feedsQuery->filterBySpaceSlug($bySpace)
                ->where('is_sticky', 0);

            if ($request->page == 1) {
                $stickyFeed = Feed::where('space_id', $space->id)
                    ->where('is_sticky', 1)
                    ->with([
                            'xprofile'          => function ($q) {
                                $q->select(ProfileHelper::getXProfilePublicFields());
                            },
                            'comments.xprofile' => function ($q) {
                                $q->select(ProfileHelper::getXProfilePublicFields());
                            },
                            'space'
                        ]
                    )
                    ->first();
            }
        }

        if ($userId) {
            $feedsQuery = $feedsQuery->where('user_id', $userId);
            if ($userId != get_current_user_id()) {
                $feedsQuery = $feedsQuery->byUserAccess(get_current_user_id());
            }
        } else {
            $feedsQuery->byUserAccess(get_current_user_id());
        }

        do_action_ref_array('fluent_community/feeds_query', [&$feedsQuery, $request->all()]);

        $feeds = $feedsQuery->paginate();

        // add $stickyFeed to the first page
        if ($stickyFeed) {
            $stickyFeed = $this->transformFeed($stickyFeed);
        }

        $feeds->getCollection()->each(function ($feed) {
            $this->transformFeed($feed);
        });

        $data = [
            'feeds'  => $feeds,
            'sticky' => $stickyFeed
        ];

        if ($request->get('page') == 1) {
            $lastItem = FeedsHelper::getLastFeedId();
            if ($lastItem) {
                $data['last_id'] = $lastItem;
            }
        }

        return $data;
    }

    public function getFeedBySlug(Request $request, $feed_slug)
    {
        if ($request->get('context') == 'edit') {
            $feed = Feed::where('slug', $feed_slug)->with(['space'])->first();

            if (!$feed || !$feed->hasEditAccess(get_current_user_id())) {
                return $this->sendError([
                    'message' => 'You do not have permission to edit this feed'
                ]);
            }

            return [
                'feed' => $feed
            ];
        }

        $feed = Feed::where('slug', $feed_slug)
            ->select(Feed::$publicColumns)
            ->with([
                'xprofile'          => function ($q) {
                    $q->select(ProfileHelper::getXProfilePublicFields());
                },
                'space',
                'comments.xprofile' => function ($q) {
                    $q->select(ProfileHelper::getXProfilePublicFields());
                },
                'reactions'         => function ($q) {
                    $q->with([
                        'xprofile' => function ($query) {
                            $query->select(['user_id', 'avatar']);
                        }
                    ])
                        ->where('type', 'like')
                        ->limit(3);
                }
            ])
            ->byUserAccess($this->getUserId())
            ->first();

        if (!$feed) {
            return $this->sendError([
                'message' => __('The feed could not be found', 'fluent-commuity')
            ], 404);
        }

        $this->transformFeed($feed);

        return [
            'feed' => $feed
        ];
    }

    public function getBookmarks(Request $request)
    {
        $userId = get_current_user_id();

        $feedsQuery = Feed::where('status', 'published')
            ->select(Feed::$publicColumns)
            ->with([
                    'xprofile'          => function ($q) {
                        $q->select(ProfileHelper::getXProfilePublicFields());
                    },
                    'comments.xprofile' => function ($q) {
                        $q->select(ProfileHelper::getXProfilePublicFields());
                    },
                    'space'
                ]
            )
            ->byBookMarked($userId)
            ->byUserAccess($userId)
            ->searchBy($request->get('search'));


        if ($type = $request->get('type')) {
            $feedsQuery = $feedsQuery->where('type', $type);
        }

        $feeds = $feedsQuery->orderBy('id', 'DESC')
            ->paginate();

        $feeds->getCollection()->each(function ($feed) {
            $this->transformFeed($feed);
        });

        $data = [
            'feeds' => $feeds
        ];

        if ($request->get('page') == 1) {
            $lastItem = FeedsHelper::getLastFeedId();
            if ($lastItem) {
                $data['last_id'] = $lastItem;
            }
        }

        return $data;
    }

    public function store(Request $request)
    {
        $userId = get_current_user_id();
        $user = $this->getUser(true);

        do_action('fluent_community/check_rate_limit/create_post', $user);

        $requestData = $request->all();

        $data = $this->sanitizeAndValidateData($requestData);

        if ($isDulicate = $this->checkForDuplicatePost($userId, $data['message'])) {
            return $isDulicate;
        }

        $feed = new Feed();
        $feed->user_id = $userId;

        if ($spaceSlug = $request->get('space')) {
            $data['space_id'] = $this->validateAndSetSpace($spaceSlug, $user);
        } else {
            // Check if the user has global post permission
            if (!Helper::hasGlobalPost()) {
                return $this->sendError([
                    'message' => __('Please select a valid space to post in', 'fluent-community')
                ]);
            }
        }

        $message = $data['message'];

        $mentions = FeedsHelper::getMentions($data['message'], Arr::get($data, 'space_id'));

        if ($mentions) {
            $data['message'] = $message;
            $message = $mentions['text'];
        }

        // replace new line with br
        $data['message_rendered'] = wp_kses_post(FeedsHelper::mdToHtml($message));

        $mediaItems = null;

        if (!empty($data['survey'])) {
            $this->handleSurveyConfig($data);
        } elseif (Arr::get($requestData, 'meta.media_preview.provider') == 'giphy') {
            $this->setGiphyMediaPreview($data, $requestData);
        } else {
            $mediaItems = $this->processNewMedia($requestData, $data);
        }

        $data = apply_filters('fluent_community/feed_data/new', $data);

        $feed->fill($data);

        $feed->save();

        if ($mediaItems) {
            $this->saveMediaItems($feed, $mediaItems);
        }

        $this->handleMentions($feed, $mentions ?? []);
        $this->syncHashTags($feed, $data['message']);

        $feed->load(['xprofile', 'comments.xprofile']);

        if ($feed->space_id) {
            $feed->load(['space']);
            $topicIds = $request->get('topic_ids', []);
            // take only first 5 topics
            if ($topicIds) {
                $topicIds = array_slice($topicIds, 0, apply_filters('fluent_community/max_topic_per_post', 5));
                $feed->attachTopics($topicIds, false);
            }
        }

        do_action('fluent_community/feed/created', $feed);

        if ($feed->space_id) {
            do_action('fluent_community/space_feed/created', $feed);
        }

        return [
            'feed'    => $feed,
            'message' => __('Feed added', 'fluent-community')
        ];
    }

    public function update(Request $request, $feedId)
    {
        $requestData = $request->all();
        $data = $this->sanitizeAndValidateData($requestData);

        $userId = get_current_user_id();
        $user = User::findOrFail($userId);

        $feed = Feed::find($feedId);

        if (!$feed) {
            return $this->sendError(['message' => __('Feed not found', 'fluent-community')]);
        }

        $user->canEditFeed($feed, false);

        if (!$feed->hasEditAccess($userId)) {
            return $this->send('You do not have permission to edit this feed', 403);
        }

        if ($spaceSlug = $request->get('space')) {
            $data['space_id'] = $this->validateAndSetSpace($spaceSlug, $user);
        }

        $message = $data['message'];

        $mentions = FeedsHelper::getMentions($data['message'], Arr::get($data, 'space_id'));

        if ($mentions) {
            $data['message'] = $message;
            $message = $mentions['text'];
        }

        // replace new line with br
        $data['message_rendered'] = wp_kses_post(FeedsHelper::mdToHtml($message));
        $mediaItems = null;

        if (!empty($data['survey'])) {
            $this->handleSurveyConfig($data);
        } elseif (Arr::get($requestData, 'meta.media_preview.provider') == 'giphy') {
            $this->setGiphyMediaPreview($data, $requestData);
        } else {
            $mediaItems = $this->processExistingMedia($feed, $requestData, $data);
        }

        if ($message != $feed->message) {
            $meta = $feed->meta;
            $meta['last_edited'] = [
                'user_id' => $userId,
                'time'    => current_time('mysql')
            ];

            $editHistory = $feed->getCustomMeta('_edit_history', []);

            if (!$editHistory) {
                $editHistory = [];
            }

            $editHistory[] = array_filter([
                'user_id'      => $userId,
                'time'         => current_time('mysql'),
                'prev_message' => $feed->message,
                'prev_title'   => $feed->title
            ]);

            // get last 5 edit history
            $editHistory = array_slice($editHistory, -5);
            $feed->updateCustomMeta('_edit_history', $editHistory);
            $data['meta'] = $meta;
        }

        $data = apply_filters('fluent_community/feed_data/update', $data, $feed);
        $feed->fill($data);
        $feed->save();

        if ($mediaItems) {
            $this->saveMediaItems($feed, $mediaItems);
        }

        $this->syncHashTags($feed, $data['message']);

        $feed->load(['xprofile', 'comments.xprofile']);

        if ($feed->space_id) {
            $feed->load(['space']);
        }

        return [
            'feed'    => $feed,
            'message' => __('Feed updated', 'fluent-community')
        ];
    }

    public function patchFeed(Request $request, $feedId)
    {
        $feed = Feed::findOrFail($feedId);
        $user = $this->getUser(true);

        $isMod = $user->isCommunityModerator();
        $isAuthor = $feed->user_id == $user->ID;

        if (!$isMod && !$isAuthor) {
            return $this->sendError([
                'message' => __('You do not have permission to perform this action', 'fluent-community')
            ]);
        }

        $allData = $request->all();
        $validKeys = ['is_sticky', 'priority', 'comments_disabled'];

        if (!$isMod) {
            $validKeys = ['comments_disabled'];
        }

        $data = Arr::only($allData, $validKeys);

        $data = array_map('intval', $data);

        if (isset($data['is_sticky'])) {
            $data['is_sticky'] = $data['is_sticky'] ? 1 : 0;
            if ($data['is_sticky'] && $feed->space_id) {
                // remove all the sticky posts from the space
                Feed::where('space_id', $feed->space_id)->update(['is_sticky' => 0]);
            }
        }

        if (isset($data['comments_disabled'])) {
            $meta = $feed->meta;
            $meta['comments_disabled'] = $data['comments_disabled'] ? 'yes' : 'no';
            $data['meta'] = $meta;
        }

        if ($data) {
            $feed->fill($data);
            $feed->save();
        }

        return [
            'feed'    => $feed,
            'message' => __('Feed updated', 'fluent-community')
        ];
    }

    public function getLinks(Request $request)
    {
        return [
            'links' => Helper::getFeedLinks()
        ];
    }

    public function updateLinks(Request $request)
    {
        $links = $request->get('links', []);

        $links = array_map(function ($link) {
            return CustomSanitizer::santizeLinkItem($link);
        }, $links);

        Helper::updateFeedLinks($links);

        return [
            'message' => __('Links has been updated', 'fluent-community'),
            'links'   => $links
        ];
    }

    private function setGiphyMediaPreview(&$data, $requestData)
    {
        if (empty(Arr::get($requestData, 'meta.media_preview.image'))) {
            return;
        }

        $data['meta']['media_preview'] = array_filter([
            'image'    => sanitize_url($requestData['meta']['media_preview']['image']),
            'type'     => Arr::get($requestData, 'meta.media_preview.type', 'image'),
            'provider' => Arr::get($requestData, 'meta.media_preview.provider', ''),
            'height'   => Arr::get($requestData, 'meta.media_preview.height', 0),
            'width'    => Arr::get($requestData, 'meta.media_preview.width', 0),
        ]);
    }

    private function handleSurveyConfig(&$data)
    {
        if (empty($data['meta'])) {
            $data['meta'] = [];
        }

        $data['meta']['survey_config'] = $data['survey'];
        $data['content_type'] = 'survey';
    }

    private function processNewMedia($requestData, &$data)
    {
        if ($mediaImages = Arr::get($requestData, 'media_images')) {
            $uploadedImages = Helper::getMediaByProvider($mediaImages);
            $uploadedMediaItems = Helper::getMediaItemsFromUrl($uploadedImages);
            $mediaPreviews = $this->generateMediaPreviews($uploadedMediaItems);
            $this->formatMediaMeta($mediaPreviews, $data, $mediaImages);
            return $uploadedMediaItems;
        }

        if ($media = Arr::get($requestData, 'media')) {
            $type = Arr::get($media, 'type', 'oembed');
            if ($type == 'oembed') {
                $url = Arr::get($media, 'url');
                $metaData = RemoteUrlParser::parse($url);
                if ($metaData && !is_wp_error($metaData) && (!empty($metaData['image']) || !empty($metaData['html']))) {
                    $data['meta']['media_preview'] = $metaData;
                    return [];
                }
            }
        }

        $urlMeta = $this->parseFirstUrl($data['message_rendered']);

        if ($urlMeta) {
            $data['meta'] = $urlMeta;
            return [];
        }

        // Let's give option to the user to check if there is any fallback
        do_action_ref_array('fluent_community/feed/meta_fallback', [&$data]);

        return [];
    }

    private function processExistingMedia($feed, $requestData, &$data)
    {
        $images = (array)Arr::get($requestData, 'media_images', []);
        $mediaImages = Helper::getMediaByProvider($images);
        $metaMediaMetaItems = Helper::getMediaByProvider((array)Arr::get($requestData, 'meta.media_items', []));
        $metaMediaPreview = array_filter((array)Arr::get($requestData, 'meta.media_preview', []));
        $requestMediaIds = array_column($metaMediaMetaItems, 'media_id');

        if (count($mediaImages) == 0 && count($metaMediaMetaItems) == 0) {
            if (count($metaMediaPreview) === 0) {
                do_action('fluent_community/feed/media_deleted', $feed->media);
                $data['meta']['media_preview'] = null;
            }

            $previewMeta = $this->parseFirstUrl($data['message_rendered']);
            if (count($metaMediaPreview) > 0) {
                $data['meta']['media_preview'] = $metaMediaPreview;
            } elseif (count($previewMeta) > 0) {
                $data['meta'] = $previewMeta;
            }

            return [];
        }

        if (count($mediaImages) == 1 && (count($metaMediaMetaItems) == 0 || count($metaMediaPreview) > 0)) {
            if (Arr::get($metaMediaPreview, 'is_uploaded')) {
                $mediaImages[] = $metaMediaPreview['image'] . '?media_key=' . $feed->media[0]->media_key;
                unset($data['meta']['media_preview']);
            } elseif (count($metaMediaPreview) > 0) {
                do_action('fluent_community/feed/media_deleted', $feed->media);
            }

            $mediaItems = Helper::getMediaItemsFromUrl($mediaImages);
            $mediaPreviews = $this->generateMediaPreviews($mediaItems);

            $this->formatMediaMeta($mediaPreviews, $data, $images);

            return $mediaItems;
        }

        $message = $data['message'];

        if ($mentions = FeedsHelper::getMentions($message, Arr::get($data, 'space_id'))) {
            $message = $mentions['text'];
        }

        $data['message_rendered'] = FeedsHelper::mdToHtml($message);

        if (count($mediaImages) > 1) {
            $mediaItems = $this->processNewMedia($requestData, $data);
        }

        $deletedMediaItems = $feed->media()->whereNotIn('id', $requestMediaIds)->get();
        do_action('fluent_community/feed/media_deleted', $deletedMediaItems);


        if (!isset($data['meta']['media_items'])) {
            $data['meta']['media_items'] = [];
        }

        if (!isset($data['meta']['media_preview'])) {
            $data['meta']['media_preview'] = null;
        }

        if ($metaMediaMetaItems) {
            $filteredData = array_filter($metaMediaMetaItems, function ($item) use ($requestMediaIds) {
                return in_array($item['media_id'], $requestMediaIds);
            });

            if (count($mediaImages) == 1 && count($filteredData) > 0) {
                $mediaItems = Helper::getMediaItemsFromUrl($mediaImages);
                $newMediaItems = $this->generateMediaPreviews($mediaItems);
                $filteredData = array_merge($filteredData, $newMediaItems);
            }

            $data['meta']['media_items'] = array_merge($filteredData, $data['meta']['media_items']);
        }

        if (isset($feed->meta['media_preview'])) {
            if (count($mediaImages) > 1) {
                $data['meta']['media_preview'] = null;
            }
        }

        return $mediaItems ?? [];
    }

    private function generateMediaPreviews($mediaItems)
    {
        $mediaPreviews = [];
        foreach ($mediaItems as $media) {
            if (!$media || !$media->is_active) {
                $this->sendError(['message' => 'Invalid media image. Please upload a new one.']);
            }

            $data = [
                'media_id' => $media->id,
                'url'      => $media->public_url,
                'type'     => 'image',
                'width'    => Arr::get($media->settings, 'width'),
                'height'   => Arr::get($media->settings, 'height'),
                'provider' => Arr::get($media->settings, 'provider', 'uploader')
            ];

            $mediaPreviews[] = array_filter($data);
        }

        return $mediaPreviews;
    }

    private function formatMediaMeta($mediaPreviews, &$data, $mediaImages)
    {
        $giphyImages = Helper::getMediaByProvider($mediaImages, 'giphy');
        $metaMediaItems = Helper::getMediaByProvider($this->request->get('meta.media_items', []), 'giphy');

        if (count($mediaPreviews) === 1 && empty($giphyImages) && empty($metaMediaItems)) {
            $mediaPreview = array_filter([
                'is_uploaded' => true,
                'image'       => $mediaPreviews[0]['url'],
                'type'        => 'meta_data',
                'width'       => Arr::get($mediaPreviews[0], 'width'),
                'height'      => Arr::get($mediaPreviews[0], 'height')
            ]);

            $data['meta']['media_preview'] = $mediaPreview;
        } elseif ($mediaPreviews) {
            $data['meta']['media_items'] = $mediaPreviews;
        }
    }

    private function processGiphyImages($requestData, &$data)
    {
        if (!isset($data['meta']['media_items'])) {
            $data['meta']['media_items'] = null;
        }

        if ($metaMediaItems = Arr::get($requestData, 'meta.media_items', [])) {
            $giphyMediaItems = Helper::getMediaByProvider($metaMediaItems, 'giphy');

            if ($giphyMediaItems) {
                $data['meta']['media_items'] = array_merge($giphyMediaItems, (array)$data['meta']['media_items']);
            }
        }

        if ($giphyImages = Helper::getMediaByProvider(Arr::get($requestData, 'media_images', []), 'giphy')) {

            foreach ($giphyImages as $giphy) {
                $data['meta']['media_items'][] = [
                    'url'      => $giphy['url'],
                    'type'     => 'image',
                    'provider' => 'giphy'
                ];
            }
        }
    }

    private function parseFirstUrl($messageRendered)
    {
        $firstUrl = FeedsHelper::findFirstUrl($messageRendered);

        if ($firstUrl) {
            $metaData = RemoteUrlParser::parse($firstUrl);
            if ($metaData && !is_wp_error($metaData) && (!empty($metaData['image']) || !empty($metaData['html']))) {
                return [
                    'media_preview' => $metaData
                ];
            }
        }

        return [];
    }

    private function saveMediaItems($feed, $mediaItems)
    {
        foreach ($mediaItems as $media) {
            $media->feed_id = $feed->id;
            $media->is_active = 1;
            $media->object_source = 'feed';
            $media->save();
        }
    }

    private function handleMentions($feed, $mentions)
    {
        if ($mentions) {
            do_action('fluent_community/feed_mentioned', $feed, $mentions['users']);
        }
    }

    private function syncHashTags($feed, $message)
    {
        if ($feed->id) {
            do_action('fluent_community/feed/hashtags_deleted', $feed->terms);
        }

        $hashTags = FeedsHelper::extractHashTags($message);
        if ($hashTags) {
            $feed->terms()->sync($hashTags);
        }
    }

    private function sanitizeAndValidateData($data)
    {
        $message = CustomSanitizer::unslashMarkdown(trim(Arr::get($data, 'message')));
        $type = sanitize_text_field(Arr::get($data, 'type', 'text'));

        $processedData = [
            'message' => $message,
            'type'    => $type
        ];

        $survey = Arr::get($data, 'survey', []);

        if ($survey) {
            $options = Arr::get($survey, 'options', []);
            $formattedOptions = [];
            foreach ($options as $index => $option) {
                if (empty($option['label'])) {
                    continue;
                }

                $formattedOptions[] = [
                    'label' => sanitize_text_field($option['label']),
                    'slug'  => 'opt_' . ($index + 1)
                ];
            }

            if ($formattedOptions) {
                $processedData['survey'] = [
                    'type'    => Arr::get($survey, 'type') == 'single_choice' ? 'single_choice' : 'multi_choice',
                    'options' => $formattedOptions
                ];
            }
        }

        $this->validate($processedData, [
            'message' => 'required|min:10',
            'type'    => 'required'
        ]);

        $maxlen = apply_filters('fluent_community/max_post_length', 15000);
        if (\strlen($message) > $maxlen) {
            throw new \Exception(esc_html__('Post message is too long', 'fluent-community'));
        }

        $titlePref = Utility::postTitlePref();

        if ($titlePref) {
            $processedData['title'] = sanitize_text_field(Arr::get($data, 'title'));
            if ($titlePref == 'required' && empty($processedData['title'])) {
                throw new \Exception(esc_html__('Title is required. Please provide a title', 'fluent-community'));
            }
            // trim the title if it's too long to 150 char
            if (\strlen($processedData['title']) > 192) {
                $processedData['title'] = substr($processedData['title'], 0, 192);
            }
        }

        return $processedData;
    }

    private function checkForDuplicatePost($userId, $message)
    {
        $message = trim($message);

        $exist = Feed::where('user_id', $userId)
            ->where('message', $message)
            ->where('created_at', '>', gmdate('Y-m-d H:i:s', current_time('timestamp') - 7 * 24 * 60 * 60))
            ->first();

        if ($exist) {
            return $this->sendError(['message' => 'No duplicate post please!']);
        }

        return false;
    }

    private function validateAndSetSpace($spaceSlug, $user)
    {
        if ($spaceSlug == '__self__post__') {
            if (!Helper::hasGlobalPost()) {
                throw new \Exception(__('Please select a valid space to post in', 'fluent-community'));
            }

            return null;
        }

        $space = Space::where('slug', $spaceSlug)->first();

        if (!$space) {
            throw new \Exception(__('Please select a valid space to post in', 'fluent-community'));
        }

        $user->verifySpacePermission('can_create_post', $space);

        return $space->id;
    }

    public function deleteFeed(Request $request, $feed_id)
    {
        $feed = Feed::findOrFail($feed_id);

        $user = User::find(get_current_user_id());
        $user->canDeleteFeed($feed, true);
        do_action('fluent_community/feed/before_deleted', $feed);
        $feed->delete();

        do_action('fluent_community/feed/deleted', $feed_id);

        return [
            'message' => 'Feed has been deleted successfully'
        ];
    }

    public function deleteMediaPreview(Request $request, $feed_id)
    {
        $feed = Feed::findOrFail($feed_id);

        $user = User::find(get_current_user_id());
        $user->canDeleteFeed($feed, true);

        do_action('fluent_community/feed/media_deleted', $feed->media);

        $meta = $feed->meta;

        $meta['media_preview'] = null;

        $feed->meta = $meta;
        $feed->save();

        return [
            'message' => 'Media preview has been removed successfully'
        ];
    }

    public function addComment(Request $request, $feed_id)
    {
        $feed = Feed::findOrFail($feed_id);
        $text = trim($request->getSafe('comment', 'sanitize_textarea_field', ''));

        if (!$text) {
            return $this->sendError([
                'message' => 'Please provide your reply text'
            ]);
        }

        // check for duplicate
        $exist = Comment::where('user_id', get_current_user_id())
            ->where('message', $text)
            ->where('post_id', $feed->id)
            ->first();

        if ($exist) {
            return $this->sendError([
                'message' => 'No duplicate comment please!'
            ]);
        }

        if ($feed->space_id) {
            $user = User::find(get_current_user_id());
            $user->verifySpacePermission('registered', $feed->space);
        }

        $commentData = [
            'post_id'          => $feed->id,
            'message'          => $text,
            'message_rendered' => wp_kses_post(FeedsHelper::mdToHtml($text)),
            'type'             => 'comment'
        ];

        if ($request->get('parent_id')) {
            $parentId = (int)$request->get('parent_id');

            // verify the parent id
            $parentComment = Comment::where('id', $parentId)
                ->where('post_id', $feed->id)
                ->first();

            if (!$parentComment || $parentComment->post_id != $feed->id) {
                return $this->sendError([
                    'message' => 'Invalid parent comment'
                ]);
            }

            $commentData['parent_id'] = $parentId;
        }

        $comment = Comment::create($commentData);

        $feed->comments_count = $feed->comments_count + 1;
        $feed->save();

        $comment->load([
            'xprofile' => function ($q) {
                $q->select(ProfileHelper::getXProfilePublicFields());
            }
        ]);

        return [
            'comment' => $comment,
            'message' => 'Comment has been added'
        ];
    }

    public function addOrRemovePostReact(Request $request, $feed_id)
    {

        $feed = Feed::byUserAccess(get_current_user_id())->findOrFail($feed_id);

        $type = $request->get('react_type', 'like');
        $willRemove = $request->get('remove');
        $react = Reaction::where('user_id', get_current_user_id())
            ->where('object_id', $feed->id)
            ->where('type', $type)
            ->objectType('feed')
            ->first();

        if ($willRemove) {
            if ($react) {
                $react->delete();
                $feed->reactions_count = $feed->reactions_count - 1;
                $feed->save();
            }

            return [
                'message'   => 'Reaction has been removed',
                'new_count' => $feed->reactions_count
            ];
        }

        if ($react) {
            return [
                'message'   => 'You have already reacted to this post',
                'new_count' => $feed->reactions_count
            ];
        }

        $react = Reaction::create([
            'user_id'     => get_current_user_id(),
            'object_id'   => $feed->id,
            'type'        => $type,
            'object_type' => 'feed'
        ]);

        $feed->reactions_count = $feed->reactions_count + 1;
        $feed->save();

        return [
            'message'   => 'Reaction has been added',
            'new_count' => $feed->reactions_count
        ];
    }

    public function handleMediaUpload(Request $request)
    {
        $allowedTypes = implode(
            ',',
            apply_filters('fluent_community/support_attachment_types', [
                'image/jpeg',
                'image/pjpeg',
                'image/jpeg',
                'image/pjpeg',
                'image/png',
                'image/gif',
                'image/webp'
            ])
        );

        $files = $this->validate($this->request->files(), [
            'file' => 'mimetypes:' . $allowedTypes,
            // 'source' => 'required|in:feed,avatar,comment,cover,space'
        ], [
            'file.mimetypes' => __('The file must be a image type.', 'fluent-community')
        ]);

        $uploadedFiles = FileSystem::put($files);

        $file = $uploadedFiles[0];

        $willWebPConvert = apply_filters('fluent_community/convert_image_to_webp', true, $file);

        if ($request->get('resize') && $maxWidth = $request->get('max_width')) {
            $upload_dir = wp_upload_dir();
            $fileUrl = str_replace($upload_dir['baseurl'], $upload_dir['basedir'], $file['url']);
            $editor = wp_get_image_editor($fileUrl);
            if (!is_wp_error($editor) && $editor->get_size()['width'] > $maxWidth) {
                // Current file extension
                $ext = pathinfo($file['url'], PATHINFO_EXTENSION);
                $imageExtensions = ['jpg', 'jpeg', 'png', 'gif'];

                $willConvert = in_array($ext, $imageExtensions) && $willWebPConvert;

                if ($willConvert) {
                    $imageExtensions = array_map(function ($ext) {
                        return '.' . $ext;
                    }, $imageExtensions);
                    $fileUrl = str_replace($imageExtensions, '.webp', $fileUrl);
                    $file['file'] = str_replace($imageExtensions, '.webp', $file['file']);
                    $file['url'] = str_replace($imageExtensions, '.webp', $file['url']);
                    $file['type'] = 'image/webp';
                }

                // resize the image
                $editor->resize($maxWidth, null, false);
                $editor->set_quality(90);
                if ($willConvert) {
                    $editor->save($fileUrl, 'image/webp');
                    // remove original file now
                    wp_delete_file(str_replace('.webp', '.' . $ext, $fileUrl));
                    $file['is_converted'] = true;
                } else {
                    $editor->save($fileUrl);
                }

                $file['meta'] = [
                    'width'  => $editor->get_size()['width'],
                    'height' => $editor->get_size()['height']
                ];
            }
            $file['path'] = $upload_dir['basedir'] . '/fluent-community/' . $file['file'];
        } else {
            $upload_dir = wp_upload_dir();
            $file['path'] = $upload_dir['basedir'] . '/fluent-community/' . $file['file'];
        }

        if ($willWebPConvert && empty($file['is_converted']) && !$request->get('skip_convert')) {
            $path = $file['path'];
            $extension = pathinfo($path, PATHINFO_EXTENSION);

            $convertFromExtensions = ['png', 'jpg', 'jpeg', 'gif'];
            if ($extension != 'webp' && in_array($extension, $convertFromExtensions)) {
                // Let's convert to webp
                $editor = wp_get_image_editor($file['path']);
                if (!is_wp_error($editor)) {
                    $orginalPath = $file['path'];
                    $file['path'] = str_replace('.' . $extension, '.webp', $file['path']);
                    $file['url'] = str_replace('.' . $extension, '.webp', $file['url']);
                    $file['type'] = 'image/webp';
                    $editor->save($file['path'], 'image/webp');
                    wp_delete_file($orginalPath);

                    $file['meta'] = [
                        'width'  => $editor->get_size()['width'],
                        'height' => $editor->get_size()['height']
                    ];
                }
            }
        }

        $mediaData = apply_filters('fluent_community/media_upload_data', [
            'media_type' => $file['type'],
            'driver'     => 'local',
            'media_path' => $file['path'],
            'media_url'  => $file['url'],
            'settings'   => Arr::get($file, 'meta', [])
        ], $file);

        // Let's create the media now
        $media = Media::create($mediaData);

        $mediaUrl = $media->public_url;

        $mediaUrl = add_query_arg([
            'media_key' => $media->media_key,
        ], $mediaUrl);

        return [
            'media' => [
                'url'       => $mediaUrl,
                'media_key' => $media->media_key,
                'type'      => $media->media_type,
                'width'     => Arr::get($media->settings, 'width'),
                'height'    => Arr::get($media->settings, 'height')
            ]
        ];
    }

    public function getTicker(Request $request)
    {
        do_action('fluent_communit/track_activity');

        $lastId = $request->get('last_feed_id');

        $newItemsCount = Feed::where('id', '>', $lastId)
            ->where('status', 'published')
            ->byUserAccess(get_current_user_id())
            ->count();

        $notificationCount = NotificationSubscriber::unread()->where('user_id', get_current_user_id())->count();

        return [
            'new_items_count'           => $newItemsCount,
            'last_checked'              => current_time('mysql'),
            'unread_notification_count' => $notificationCount
        ];
    }

    public function getOembed(Request $request)
    {
        $url = $request->get('url');
        // check if the url is valid
        $metaData = RemoteUrlParser::parse($url);

        if ($metaData && !is_wp_error($metaData)) {
            return [
                'oembed' => $metaData
            ];
        }

        return $this->send([
            'message' => 'No oembed data found',
            'url'     => $url
        ]);
    }

    public function markdownToHtml(Request $request)
    {
        $message = trim(sanitize_textarea_field($request->get('text', '')));

        $html = FeedsHelper::mdToHtml($message);

        return [
            'html' => $html
        ];
    }

    private function transformFeed(Feed $feed)
    {
        $userId = $this->getUserId();
        if ($userId) {
            $feed->has_user_react = $feed->hasUserReact($userId, 'like');
            $feed->bookmarked = $feed->hasUserReact($userId, 'bookmark');

            $likedIds = FeedsHelper::getLikedIdsByUserFeedId($feed->id, get_current_user_id());
            $feed->comments->each(function ($comment) use ($likedIds) {
                if ($likedIds && in_array($comment->id, $likedIds)) {
                    $comment->liked = 1;
                }
            });

            if ($feed->content_type == 'survey') {
                $votedOptions = $feed->getSurveyCastsByUserId($userId);

                if ($votedOptions) {
                    $surveyConfig = Arr::get($feed->meta, 'survey_config', []);
                    foreach ($surveyConfig['options'] as $index => $option) {
                        if (in_array($option['slug'], $votedOptions)) {
                            $surveyConfig['options'][$index]['voted'] = true;
                        }
                    }
                    $meta = $feed->meta;
                    $meta['survey_config'] = $surveyConfig;
                    $feed->meta = $meta;
                }
            }
        }

        return $feed;
    }
}

```
