# fluent-community/trunk/app/Http/Controllers/CommentsController.php

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

- Page: https://pluginprobe.com/plugins/fluent-community/trunk/code/app/Http/Controllers/CommentsController.php
- Raw: https://pluginprobe.com/plugins/fluent-community/trunk/raw/app/Http/Controllers/CommentsController.php
- Modified: 2026-09-14T14:31:46+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/trunk/code/app/Http/Controllers/CommentsController.php#L10-L20`.

```php
<?php

namespace FluentCommunity\App\Http\Controllers;

use FluentCommunity\App\Models\Media;
use FluentCommunity\App\Models\User;
use FluentCommunity\App\Services\CustomSanitizer;
use FluentCommunity\App\Services\FeedsHelper;
use FluentCommunity\App\Services\Helper;
use FluentCommunity\App\Services\ProfileHelper;
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\XProfile;
use FluentCommunity\Framework\Support\Arr;

class CommentsController extends Controller
{
    public function getComments(Request $request, $feed_id)
    {
        $feed = Feed::withoutGlobalScopes()
            ->byUserAccess(get_current_user_id())
            ->findOrFail($feed_id);

        if (!in_array($feed->status, FeedsHelper::getViewableByLinkStatuses(), true) && !$feed->hasEditAccess($this->getUserId())) {
            return $this->sendError([
                'message' => __('Sorry, you do not have permission to view this post', 'fluent-community')
            ], 404);
        }

        /*
         * The row's own setting is the default the filter gets handed, rather than a bare
         * true. Before this, meta.enable_comments was read nowhere on this path, so a page
         * with comments switched off still served its thread to anyone who asked for it.
         */
        $canViewComments = apply_filters(
            'fluent_community/can_view_comments_' . $feed->type,
            FeedsHelper::commentsEnabled($feed),
            $feed
        );

        if (!$canViewComments) {
            return [
                'comments' => []
            ];
        }

        $comments = Comment::where('post_id', $feed->id)
            ->byContentModerationAccessStatus($this->getUser())
            ->orderBy('created_at', 'asc')
            ->with([
                'xprofile' => function ($q) {
                    $q->select(ProfileHelper::getXProfilePublicFields());
                }
            ])
            ->whereHas('xprofile', function ($q) {
                $q->where('status', 'active');
            })
            ->get();

        $comments = apply_filters('fluent_community/comments_query_response', $comments, $request->all());

        $userId = $this->getUserId();

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

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

        return apply_filters('fluent_community/comments_api_response', $data, $request->all());
    }

    public function store(Request $request, $feedId)
    {
        $user = $this->getUser(true);
        do_action('fluent_community/check_rate_limit/create_comment', $user);

        $text = $this->validateCommentText($request->all());
        $feed = Feed::withoutGlobalScopes()->findOrFail($feedId);

        if (!in_array($feed->status, FeedsHelper::getViewableByLinkStatuses(), true)) {
            return $this->sendError([
                'message' => __('This post is not published yet', 'fluent-community')
            ]);
        }

        $this->verifyCreateCommentPermission($feed);

        $requestData = $request->all();

        [$markdown, $inlineMedias] = FeedsHelper::replaceImageUrlsWithRealMediaArchive($text);
        $mentions = FeedsHelper::getMentions($markdown, $feed->space_id, true);
        $commentHtml = $this->generateCommentHtml($markdown, $mentions);

        $commentData = $this->prepareCommentData($feed->id, $text, $commentHtml);

        if (!empty($requestData['parent_id'])) {
            $parentId = (int)$requestData['parent_id'];
            $parentComment = Comment::where('id', $parentId)
                ->where('post_id', $feed->id)
                ->first();

            if (!$parentComment) {
                return $this->sendError([
                    'message' => __('Invalid parent comment', 'fluent-community')
                ]);
            }

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

        [$commentData, $mediaItems] = $this->prepareCommentMedia($commentData, $requestData);

        $commentData['is_admin'] = $user->hasSpacePermission('community_moderator', $feed->space);

        if ($mentionUserIds = Arr::get($mentions, 'user_ids', [])) {
            $commentData['meta']['mentioned_user_ids'] = $mentionUserIds;
        }

        do_action('fluent_community/before_comment_create', $commentData, $feed);

        $commentData = apply_filters('fluent_community/comment/comment_data', $commentData, $feed);

        // Only comments with text are duplicate checked
        $shouldCheckDuplicate = $text && !apply_filters('fluent_community/disable_duplicate_comment_check', false, get_current_user_id(), $feed->id);

        // Serialize a member's concurrent submissions by locking their profile row,
        // so parallel matching requests cannot pass the duplicate check and both insert.
        $comment = Helper::dbTransaction(function () use ($commentData, $feed, $text, $shouldCheckDuplicate) {
            XProfile::where('user_id', get_current_user_id())->lockForUpdate()->first();

            if ($shouldCheckDuplicate && Comment::where('user_id', get_current_user_id())->where('message', $text)->where('post_id', $feed->id)->first()) {
                return null;
            }

            $newComment = Comment::create($commentData);
            Feed::withoutGlobalScopes()->where('id', $feed->id)->increment('comments_count');

            return $newComment;
        });

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

        $feed->comments_count = $feed->comments_count + 1;


        // Merge and save all media in one loop
        $mediaItems = $mediaItems ? (is_array($mediaItems) ? $mediaItems : [$mediaItems]) : [];

        if ($inlineMedias) {
            $mediaItems = array_merge($mediaItems, $inlineMedias);
        }

        if ($mediaItems) {
            foreach ($mediaItems as $media) {
                $media->fill([
                    'is_active'     => 1,
                    'feed_id'       => $feed->id,
                    'object_source' => 'comment',
                    'sub_object_id' => $comment->id
                ]);
                $media->save();
            }
        }

        $this->loadCommentRelations($comment);

        if ($comment->status != 'published') {
            do_action('fluent_community/comment/new_comment_' . $comment->status, $comment, $feed);
            /* translators: %$s is replaced by the status of the comment */
            $message = sprintf(__('Your comment has been marked as %s', 'fluent-community'), $comment->status);
            $response = [
                'comment' => $comment,
                'message' => $message
            ];
            return apply_filters('fluent_community/comment/new_comment_response', $response, $comment);
        }

        do_action('fluent_community/comment_added_' . $feed->type, $comment, $feed);
        do_action('fluent_community/comment_added', $comment, $feed, Arr::get($mentions, 'users', []));

        return [
            'comment' => $comment,
            'message' => __('Comment has been added', 'fluent-community'),
        ];
    }

    public function update(Request $request, $feedId, $commentId)
    {
        $text = $this->validateCommentText($request->all());

        $feed = Feed::withoutGlobalScopes()->findOrFail($feedId);
        $this->verifySpacePermission($feed);

        $requestData = $request->all();
        $comment = Comment::findOrFail($commentId);

        if ($comment->post_id != $feed->id) {
            return $this->sendError([
                'message' => __('Invalid comment', 'fluent-community')
            ]);
        }

        $user = $this->getUser(true);

        $requestData['is_admin'] = $user->hasPermissionOrInCurrentSpace('community_moderator', $feed->space);

        if ($comment->user_id != get_current_user_id() && !$user->can('edit_any_comment', $feed->space)) {
            return $this->sendError([
                'message' => __('You are not allowed to edit this comment', 'fluent-community')
            ]);
        }

        [$markdown, $inlineMedias] = FeedsHelper::replaceImageUrlsWithRealMediaArchive($text, $feed);

        $mentions = FeedsHelper::getMentions($markdown, $feed->space_id);

        $commentHtml = $this->generateCommentHtml($markdown, $mentions);

        $commentData = $this->prepareCommentData($feed->id, $text, $commentHtml);

        [$commentData, $mediaItems] = $this->prepareCommentMedia($commentData, $requestData, $comment);

        $commentData = apply_filters('fluent_community/comment/update_comment_data', $commentData, $feed, $requestData, $comment);

        $comment->fill($commentData);

        $dirty = $comment->getDirty();

        if ($dirty) {
            $comment->save();
        }

        // Merge and save all media in one loop
        $mediaItems = $mediaItems ? (is_array($mediaItems) ? $mediaItems : [$mediaItems]) : [];

        if ($inlineMedias) {
            $mediaItems = array_merge($mediaItems, $inlineMedias);
        }

        $allMediaIds = [];

        if ($mediaItems) {
            foreach ($mediaItems as $media) {
                $media->fill([
                    'is_active'     => 1,
                    'feed_id'       => $feed->id,
                    'object_source' => 'comment',
                    'sub_object_id' => $comment->id
                ]);
                $media->save();
                $allMediaIds[] = $media->id;
            }
        }

        // Remove old media not in current list
        $otherMedias = Media::where('object_source', 'comment')
            ->when($allMediaIds, function ($q) use ($allMediaIds) {
                $q->whereNotIn('id', $allMediaIds);
            })
            ->where('sub_object_id', $comment->id)
            ->get();

        if (!$otherMedias->isEmpty()) {
            do_action('fluent_community/comment/media_deleted', $otherMedias);
        }

        $this->loadCommentRelations($comment);

        if ($dirty) {
            do_action('fluent_community/comment_updated', $comment, $feed);
            do_action('fluent_community/comment_updated_' . $feed->type, $comment, $feed);
        }

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

    public function patchComment(Request $request, $feedId, $commentId)
    {
        $feed = Feed::withoutGlobalScopes()->findOrFail($feedId);

        $comment = Comment::findOrFail($commentId);

        if ($comment->post_id != $feed->id) {
            return $this->sendError([
                'message' => __('Invalid comment', 'fluent-community')
            ]);
        }

        $user = $this->getUser(true);

        $isMod = $user && $user->hasPermissionOrInCurrentSpace('community_moderator', $feed->space);
        $isAdmin = $user && $user->hasPermissionOrInCurrentSpace('community_admin', $feed->space);

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

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

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

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

        if (isset($data['is_sticky'])) {
            if ($comment->parent_id) {
                return $this->sendError([
                    'message' => __('You cannot pin a reply comment', 'fluent-community')
                ]);
            }

            $data['is_sticky'] = $data['is_sticky'] ? 1 : 0;
            if ($data['is_sticky']) {
                Comment::where('post_id', $feed->id)->update(['is_sticky' => 0]);
            }
        }

        if ($data) {
            $comment->fill($data);
            $dirty = $comment->getDirty();
            if ($dirty) {
                $comment->save();
                do_action('fluent_community/comment/updated', $comment, $dirty);
            }
        }

        return apply_filters('fluent_community/comment/patch_comment_response', [
            'comment' => $comment,
            'message' => __('Comment updated', 'fluent-community')
        ], $comment, $feed, $request->all());
    }

    private function prepareCommentMedia($commentData, $requestData, $exisitngComment = null)
    {
        $mediaImages = Arr::get($requestData, 'media_images', []);

        if ($mediaImages) {
            if ($exisitngComment) {
                $mediaItems = [];
                $mediaData = [];
                foreach ($mediaImages as $mediaImage) {
                    $id = Arr::get($mediaImage, 'media_id');
                    if ($id) {
                        $media = Media::where('sub_object_id', $exisitngComment->id)
                            ->where('object_source', 'comment')
                            ->find($id);
                    } else {
                        $media = Helper::getMediaFromUrl($mediaImage);
                    }

                    if ($media) {
                        $mediaItems[] = $media;
                        $mediaData[] = [
                            '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')
                        ];
                    }
                }
                $commentData['meta']['media_items'] = $mediaData;
                return [$commentData, $mediaItems];
            }

            $uploadedImages = Helper::getMediaByProvider($mediaImages);
            if ($uploadedImages) {
                $mediaItems = Helper::getMediaItemsFromUrl($uploadedImages);
                if ($mediaItems) {
                    $mediaPreviews = [];
                    foreach ($mediaItems as $mediaItem) {
                        $mediaData = [
                            'media_id' => $mediaItem->id,
                            'url'      => $mediaItem->public_url,
                            'type'     => 'image',
                            'width'    => Arr::get($mediaItem->settings, 'width'),
                            'height'   => Arr::get($mediaItem->settings, 'height'),
                            'provider' => Arr::get($mediaItem->settings, 'provider', 'uploader')
                        ];

                        $mediaPreviews[] = array_filter($mediaData);
                    }
                    $commentData['meta']['media_items'] = $mediaPreviews;
                    return [$commentData, $mediaItems];
                }
            }
        }

        if (empty($requestData['meta']['media_preview']['image'])) {
            return [$commentData, []];
        }

        if ($exisitngComment) {
            $image = sanitize_url(Arr::get($requestData, 'meta.media_preview.image', ''));
            $existingMedia = Media::where('media_url', $image)
                ->where('object_source', 'comment')
                ->where('sub_object_id', $exisitngComment->id)
                ->first();

            if ($existingMedia) {
                $commentData['meta'] = $exisitngComment->meta;
                return [$commentData, [$existingMedia]];
            }
        }

        // type/provider reach :class bindings and width/height a :style binding in
        // _MediaPreview.vue. Neither is an executable sink, but the stored values are
        // request-supplied so they are normalised here rather than trusted.
        $commentData['meta']['media_preview'] = array_filter([
            'image'    => sanitize_url(Arr::get($requestData, 'meta.media_preview.image', '')),
            'type'     => sanitize_text_field(Arr::get($requestData, 'meta.media_preview.type', 'image')),
            'provider' => sanitize_text_field(Arr::get($requestData, 'meta.media_preview.provider', '')),
            'height'   => (int) Arr::get($requestData, 'meta.media_preview.height', 0),
            'width'    => (int) Arr::get($requestData, 'meta.media_preview.width', 0),
        ]);

        return [$commentData, []];
    }

    private function validateCommentText($data)
    {
        $text = trim((string) Arr::get($data, 'comment', ''));
        $text = CustomSanitizer::unslashMarkdown($text);

        // Decode HTML entities (e.g., &#x20; for space) and strip all whitespace for validation
        $textForValidation = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
        $textForValidation = preg_replace('/\s+/u', '', $textForValidation);

        $hasMedia = Arr::get($data, 'media_images', []) || Arr::get($data, 'meta.media_preview.image', false);

        $isReply = !empty($data['parent_id']);
        if (!$textForValidation && !$hasMedia) {
            if ($isReply) {
                throw new \Exception(esc_html__('Reply cannot be empty.', 'fluent-community'), 422);
            } else {
                throw new \Exception(esc_html__('Comment cannot be empty.', 'fluent-community'), 422);
            }
        }

        $maxCommentLength = apply_filters('fluent_community/max_comment_char_length', 10000);
        if ($text && strlen($text) > $maxCommentLength) {
            /* translators: %s is the maximum allowed character count */
            throw new \Exception(esc_html(sprintf(__('The comment is too long. Please keep it under %s characters.', 'fluent-community'), number_format($maxCommentLength))), 422);
        }

        return $text;
    }

    private function verifyCreateCommentPermission($feed)
    {
        if (!FeedsHelper::commentsEnabled($feed)) {
            throw new \Exception(esc_html__('Comments are disabled for this post', 'fluent-community'));
        }

        $this->verifySpacePermission($feed);
    }

    private function verifySpacePermission($feed)
    {
        if ($feed->space_id && $feed->space) {
            $user = $this->getUser(true);
            $user->verifySpacePermission('can_comment', $feed->space);

            if ($feed->space->type == 'course' && Arr::get($feed->space->settings, 'disable_comments') === 'yes') {
                throw new \Exception(esc_html__('Comments are disabled for this course', 'fluent-community'));
            }
        }
    }

    private function generateCommentHtml($text, $mentions)
    {
        $htmlText = $mentions ? $mentions['text'] : $text;
        return wp_kses_post(FeedsHelper::mdToHtml($htmlText));
    }

    private function prepareCommentData($feedId, $text, $commentHtml)
    {
        return [
            'post_id'          => $feedId,
            'message'          => $text,
            'message_rendered' => $commentHtml,
            'type'             => 'comment',
            'meta'             => [],
        ];
    }

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

    public function addOrRemovePostReact(Request $request, $feed_id)
    {
        $userId = get_current_user_id();
        $feed = Feed::withoutGlobalScopes()->byUserAccess($userId)->findOrFail($feed_id);
        $type = $request->get('react_type', 'like');
        $type = in_array($type, ['like', 'bookmark'], true) ? $type : 'like';
        $willRemove = $request->get('remove');

        if (!in_array($feed->status, FeedsHelper::getViewableByLinkStatuses(), true)) {
            return $this->sendError([
                'message' => __('This post is not published yet', 'fluent-community')
            ]);
        }

        if (!$willRemove && (int) $userId === (int) $feed->user_id && apply_filters('fluent_community/disable_self_post_react', false, $feed)) {
            return $this->sendError([
                'message' => __('You cannot react to your own post', 'fluent-community')
            ]);
        }

        $react = Reaction::where('user_id', $userId)
            ->where('object_id', $feed->id)
            ->where('type', $type)
            ->objectType('feed')
            ->first();

        if ($willRemove) {
            if ($react) {
                $react->delete();
                if ($type == 'like') {
                    $feed->reactions_count = $feed->reactions_count - 1;
                    $feed->timestamps = false; // Don't update the updated_at timestamp
                    $feed->save();
                    do_action('fluent_community/feed/react_removed', $feed);
                }
            }

            return [
                'message'   => __('Reaction has been removed', 'fluent-community'),
                'new_count' => $feed->reactions_count
            ];
        }

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

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

        if ($type == 'like') {
            $feed->reactions_count = $feed->reactions_count + 1;
            $feed->timestamps = false; // Don't update the updated_at timestamp
            $feed->save();

            $react->load('xprofile');
            do_action('fluent_community/feed/react_added', $react, $feed);
        }

        return [
            'message'   => __('Reaction has been added', 'fluent-community'),
            'new_count' => $feed->reactions_count
        ];
    }

    public function deleteComment(Request $request, $feedId, $commentId)
    {
        $feed = Feed::withoutGlobalScopes()->findOrFail($feedId);
        $comment = Comment::findOrFail($commentId);

        if ($comment->post_id != $feed->id) {
            return $this->sendError([
                'message' => __('Invalid comment', 'fluent-community')
            ]);
        }

        $user = User::find(get_current_user_id());
        if ($comment->user_id != get_current_user_id() && !$user->can('delete_any_comment', $feed->space)) {
            return $this->sendError([
                'message' => __('You are not allowed to delete this comment', 'fluent-community')
            ]);
        }

        do_action('fluent_community/before_comment_delete', $comment);

        if ($comment->media) {
            do_action('fluent_community/comment/media_deleted', $comment->media);
        }

        $comment->delete();

        $feed->comments_count = Comment::where('post_id', $feed->id)->count();
        $feed->timestamps = false; // Don't update the updated_at timestamp
        $feed->save();

        do_action('fluent_community/comment_deleted_' . $feed->type, $commentId, $feed);
        do_action('fluent_community/comment_deleted', $commentId, $feed);

        return [
            'message' => __('Selected comment has been deleted', 'fluent-community')
        ];
    }

    public function toggleReaction(Request $request, $feedId, $commentId)
    {
        $feed = Feed::withoutGlobalScopes()->byUserAccess(get_current_user_id())->findOrFail($feedId);
        $comment = Comment::findOrFail($commentId);

        if ($comment->post_id != $feed->id) {
            return $this->sendError([
                'message' => __('Invalid comment', 'fluent-community')
            ]);
        }

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

        if ($feed->space_id) {
            $user->verifySpacePermission('registered', $feed->space);
        }

        $userId = get_current_user_id();
        $reactionState = !!$request->get('state', false);

        if ($reactionState && (int) $userId === (int) $comment->user_id && apply_filters('fluent_community/disable_self_comment_react', false, $feed)) {
            return $this->sendError([
                'message' => __('You cannot react to your own comment', 'fluent-community')
            ]);
        }

        if ($reactionState) {
            // Serialize concurrent reactions on this comment by locking its row,
            // so parallel add requests cannot each insert a duplicate reaction.
            $reaction = Helper::dbTransaction(function () use ($comment, $feed) {
                XProfile::where('user_id', get_current_user_id())->lockForUpdate()->first();

                $reaction = Reaction::firstOrCreate([
                    'user_id'     => get_current_user_id(),
                    'object_id'   => $comment->id,
                    'object_type' => 'comment',
                    'parent_id'   => $feed->id
                ]);

                if ($reaction->wasRecentlyCreated) {
                    Comment::where('id', $comment->id)->increment('reactions_count');
                    $comment->reactions_count = $comment->reactions_count + 1;
                }

                return $reaction;
            });

            if ($reaction->wasRecentlyCreated) {
                do_action('fluent_community/comment/react_added', $reaction, $comment, $feed);
            }
        } else {
            // remove the reaction
            $deleted = Reaction::where('user_id', get_current_user_id())
                ->where('object_id', $comment->id)
                ->where('object_type', 'comment')
                ->delete();

            if ($deleted) {
                $comment->reactions_count = $comment->reactions_count - 1;
                $comment->save();
                do_action('fluent_community/comment/react_removed', $comment, $feed);
            }
        }

        return [
            'message'         => __('Reaction has been toggled', 'fluent-community'),
            'reactions_count' => $comment->reactions_count,
            'liked'           => $reactionState
        ];
    }

    public function show(Request $request, $id)
    {

        $testComment = Comment::query()->findOrFail($id);

        $comment = Comment::byContentModerationAccessStatus($this->getUser(), $testComment->space)
            ->with([
                'xprofile' => function ($q) {
                    return $q->select(ProfileHelper::getXProfilePublicFields());
                }
            ])->findOrFail($id);

        // Just to verify the permission
        Feed::withoutGlobalScopes()
            ->byUserAccess($this->getUserId())
            ->findOrFail($comment->post_id);

        if ($request->get('context') == 'edit') {
            $meta = $comment->meta;
            unset($comment->meta);
            $images = Arr::get($meta, 'media_items', []);
            if ($images) {
                $comment->media_images = $images;
            } else {
                $preview = Arr::get($meta, 'media_preview', []);
                if ($preview) {
                    $previewUrl = Arr::get($preview, 'image');
                    $provider = Arr::get($preview, 'provider');
                    if ($previewUrl && $provider == 'uploader') {
                        $media = Media::where('media_url', $previewUrl)
                            ->where('object_source', 'comment')
                            ->where('sub_object_id', $comment->id)
                            ->first();
                        if ($media) {
                            $comment->media_images = [
                                [
                                    'media_id' => $media->id,
                                    'url'      => $media->public_url,
                                    'type'     => $media->media_type,
                                    'width'    => Arr::get($media->settings, 'width'),
                                    'height'   => Arr::get($media->settings, 'height'),
                                    'provider' => Arr::get($media->settings, 'provider', 'uploader')
                                ]
                            ];
                        }
                    } else {
                        $comment->meta = [
                            'media_preview' => $preview
                        ];
                    }
                }
            }
        }

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

        return apply_filters('fluent_community/comment_api_response', $data, $request->all());
    }
}

```
