PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.5.0
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.5.0
2.11.0 2.10.0 2.10.01 2.9.1 2.9.0 2.8.1 2.8.0 2.7.7 2.7.5 2.7.0 2.6.01 2.6.0 2.5.0 2.4.01 trunk 1.0.90 1.0.91 1.0.92 1.0.93 1.0.94 1.0.95 1.0.96 1.0.97 1.0.98 1.0.99 All 78 releases
fluent-community / app / Http / Controllers / CommentsController.php

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

710 lines 25.8 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\Models\Media;
6 use FluentCommunity\App\Models\User;
7 use FluentCommunity\App\Services\CustomSanitizer;
8 use FluentCommunity\App\Services\FeedsHelper;
9 use FluentCommunity\App\Services\Helper;
10 use FluentCommunity\App\Services\ProfileHelper;
11 use FluentCommunity\Framework\Http\Request\Request;
12 use FluentCommunity\App\Models\Comment;
13 use FluentCommunity\App\Models\Feed;
14 use FluentCommunity\App\Models\Reaction;
15 use FluentCommunity\Framework\Support\Arr;
16
17 class CommentsController extends Controller
18 {
19 public function getComments(Request $request, $feed_id)
20 {
21 $feed = Feed::withoutGlobalScopes()->findOrFail($feed_id);
22 $canViewComments = apply_filters('fluent_community/can_view_comments_' . $feed->type, true, $feed);
23
24 if (!$canViewComments) {
25 return [
26 'comments' => []
27 ];
28 }
29
30 $comments = Comment::where('post_id', $feed->id)
31 ->byContentModerationAccessStatus($this->getUser())
32 ->orderBy('created_at', 'asc')
33 ->with([
34 'xprofile' => function ($q) {
35 $q->select(ProfileHelper::getXProfilePublicFields());
36 }
37 ])
38 ->whereHas('xprofile', function ($q) {
39 $q->where('status', 'active');
40 })
41 ->get();
42
43 $comments = apply_filters('fluent_community/comments_query_response', $comments, $request->all());
44
45 $userId = $this->getUserId();
46
47 if ($userId) {
48 $likedIds = FeedsHelper::getLikedIdsByUserFeedId($feed->id, get_current_user_id());
49 if ($likedIds) {
50 $comments->each(function ($comment) use ($likedIds) {
51 if (in_array($comment->id, $likedIds)) {
52 $comment->liked = 1;
53 }
54 });
55 }
56 }
57
58 $data = [
59 'comments' => $comments
60 ];
61
62 return apply_filters('fluent_community/comments_api_response', $data, $request->all());
63 }
64
65 public function store(Request $request, $feedId)
66 {
67 $user = $this->getUser(true);
68 do_action('fluent_community/check_rate_limit/create_comment', $user);
69
70 $text = $this->validateCommentText($request->all());
71 $feed = Feed::withoutGlobalScopes()->findOrFail($feedId);
72
73 if ($feed->status != 'published') {
74 return $this->sendError([
75 'message' => __('This post is not published yet', 'fluent-community')
76 ]);
77 }
78
79 $this->verifyCreateCommentPermission($feed);
80
81 $requestData = $request->all();
82
83 // Check for duplicate (only for comments with text)
84 if ($text) {
85 $skipDuplicateCheck = apply_filters('fluent_community/disable_duplicate_comment_check', false, get_current_user_id(), $feed->id);
86 if (!$skipDuplicateCheck) {
87 $exist = Comment::where('user_id', get_current_user_id())
88 ->where('message', $text)
89 ->where('post_id', $feed->id)
90 ->first();
91
92 if ($exist) {
93 return $this->sendError([
94 'message' => __('No duplicate comment please!', 'fluent-community')
95 ]);
96 }
97 }
98 }
99
100 [$markdown, $inlineMedias] = FeedsHelper::replaceImageUrlsWithRealMediaArchive($text);
101 $mentions = FeedsHelper::getMentions($markdown, $feed->space_id, true);
102 $commentHtml = $this->generateCommentHtml($markdown, $mentions);
103
104 $commentData = $this->prepareCommentData($feed->id, $text, $commentHtml);
105
106 if (!empty($requestData['parent_id'])) {
107 $parentId = (int)$requestData['parent_id'];
108 $parentComment = Comment::where('id', $parentId)
109 ->where('post_id', $feed->id)
110 ->first();
111
112 if (!$parentComment) {
113 return $this->sendError([
114 'message' => __('Invalid parent comment', 'fluent-community')
115 ]);
116 }
117
118 $commentData['parent_id'] = $parentId;
119 }
120
121 [$commentData, $mediaItems] = $this->prepareCommentMedia($commentData, $requestData);
122
123 $commentData['is_admin'] = $user->hasSpacePermission('community_moderator', $feed->space);
124
125 if ($mentionUserIds = Arr::get($mentions, 'user_ids', [])) {
126 $commentData['meta']['mentioned_user_ids'] = $mentionUserIds;
127 }
128
129 do_action('fluent_community/before_comment_create', $commentData, $feed);
130
131 $commentData = apply_filters('fluent_community/comment/comment_data', $commentData, $feed);
132
133 $comment = Comment::create($commentData);
134
135 $feed->comments_count = $feed->comments_count + 1;
136 $feed->save();
137
138
139 // Merge and save all media in one loop
140 $mediaItems = $mediaItems ? (is_array($mediaItems) ? $mediaItems : [$mediaItems]) : [];
141
142 if ($inlineMedias) {
143 $mediaItems = array_merge($mediaItems, $inlineMedias);
144 }
145
146 if ($mediaItems) {
147 foreach ($mediaItems as $media) {
148 $media->fill([
149 'is_active' => 1,
150 'feed_id' => $feed->id,
151 'object_source' => 'comment',
152 'sub_object_id' => $comment->id
153 ]);
154 $media->save();
155 }
156 }
157
158 $this->loadCommentRelations($comment);
159
160 if ($comment->status != 'published') {
161 do_action('fluent_community/comment/new_comment_' . $comment->status, $comment, $feed);
162 /* translators: %$s is replaced by the status of the comment */
163 $message = sprintf(__('Your comment has been marked as %s', 'fluent-community'), $comment->status);
164 return [
165 'comment' => $comment,
166 'message' => $message
167 ];
168 }
169
170 do_action('fluent_community/comment_added_' . $feed->type, $comment, $feed);
171 do_action('fluent_community/comment_added', $comment, $feed, Arr::get($mentions, 'users', []));
172
173 return [
174 'comment' => $comment,
175 'message' => __('Comment has been added', 'fluent-community'),
176 ];
177 }
178
179 public function update(Request $request, $feedId, $commentId)
180 {
181 $text = $this->validateCommentText($request->all());
182
183 $feed = Feed::withoutGlobalScopes()->findOrFail($feedId);
184 $this->verifySpacePermission($feed);
185
186 $requestData = $request->all();
187 $comment = Comment::findOrFail($commentId);
188 $user = $this->getUser(true);
189
190 $requestData['is_admin'] = $user->hasPermissionOrInCurrentSpace('community_moderator', $feed->space);
191
192 if ($comment->user_id != get_current_user_id() && !$user->can('edit_any_comment', $feed->space)) {
193 return $this->sendError([
194 'message' => __('You are not allowed to edit this comment', 'fluent-community')
195 ]);
196 }
197
198 [$markdown, $inlineMedias] = FeedsHelper::replaceImageUrlsWithRealMediaArchive($text, $feed);
199
200 $mentions = FeedsHelper::getMentions($markdown, $feed->space_id);
201
202 $commentHtml = $this->generateCommentHtml($markdown, $mentions);
203
204 $commentData = $this->prepareCommentData($feed->id, $text, $commentHtml);
205
206 [$commentData, $mediaItems] = $this->prepareCommentMedia($commentData, $requestData, $comment);
207
208 $commentData = apply_filters('fluent_community/comment/update_comment_data', $commentData, $feed, $requestData, $comment);
209
210 $comment->fill($commentData);
211
212 $dirty = $comment->getDirty();
213
214 if ($dirty) {
215 $comment->save();
216 }
217
218 // Merge and save all media in one loop
219 $mediaItems = $mediaItems ? (is_array($mediaItems) ? $mediaItems : [$mediaItems]) : [];
220
221 if ($inlineMedias) {
222 $mediaItems = array_merge($mediaItems, $inlineMedias);
223 }
224
225 $allMediaIds = [];
226
227 if ($mediaItems) {
228 foreach ($mediaItems as $media) {
229 $media->fill([
230 'is_active' => 1,
231 'feed_id' => $feed->id,
232 'object_source' => 'comment',
233 'sub_object_id' => $comment->id
234 ]);
235 $media->save();
236 $allMediaIds[] = $media->id;
237 }
238 }
239
240 // Remove old media not in current list
241 $otherMedias = Media::where('object_source', 'comment')
242 ->when($allMediaIds, function ($q) use ($allMediaIds) {
243 $q->whereNotIn('id', $allMediaIds);
244 })
245 ->where('sub_object_id', $comment->id)
246 ->get();
247
248 if (!$otherMedias->isEmpty()) {
249 do_action('fluent_community/comment/media_deleted', $otherMedias);
250 }
251
252 $this->loadCommentRelations($comment);
253
254 if ($dirty) {
255 do_action('fluent_community/comment_updated', $comment, $feed);
256 do_action('fluent_community/comment_updated_' . $feed->type, $comment, $feed);
257 }
258
259 return [
260 'comment' => $comment,
261 'message' => __('Comment has been updated', 'fluent-community'),
262 ];
263 }
264
265 public function patchComment(Request $request, $feedId, $commentId)
266 {
267 $feed = Feed::withoutGlobalScopes()->findOrFail($feedId);
268
269 $comment = Comment::findOrFail($commentId);
270
271 $user = $this->getUser(true);
272
273 $isMod = $user && $user->hasPermissionOrInCurrentSpace('community_moderator', $feed->space);
274 $isAdmin = $user && $user->hasPermissionOrInCurrentSpace('community_admin', $feed->space);
275
276 if (!$isMod && !$isAdmin) {
277 return $this->sendError([
278 'message' => __('You do not have permission to perform this action', 'fluent-community')
279 ]);
280 }
281
282 $allData = $request->all();
283 $validKeys = ['is_sticky'];
284
285 $data = Arr::only($allData, $validKeys);
286
287 $data = array_map('intval', $data);
288
289 if (isset($data['is_sticky'])) {
290 if ($comment->parent_id) {
291 return $this->sendError([
292 'message' => __('You cannot pin a reply comment', 'fluent-community')
293 ]);
294 }
295
296 $data['is_sticky'] = $data['is_sticky'] ? 1 : 0;
297 if ($data['is_sticky']) {
298 Comment::where('post_id', $feed->id)->update(['is_sticky' => 0]);
299 }
300 }
301
302 if ($data) {
303 $comment->fill($data);
304 $dirty = $comment->getDirty();
305 if ($dirty) {
306 $comment->save();
307 do_action('fluent_community/comment/updated', $comment, $dirty);
308 }
309 }
310
311 return apply_filters('fluent_community/comment/patch_comment_response', [
312 'comment' => $comment,
313 'message' => __('Comment updated', 'fluent-community')
314 ], $comment, $feed, $request->all());
315 }
316
317 private function prepareCommentMedia($commentData, $requestData, $exisitngComment = null)
318 {
319 $mediaImages = Arr::get($requestData, 'media_images', []);
320
321 if ($mediaImages) {
322 if ($exisitngComment) {
323 $mediaItems = [];
324 $mediaData = [];
325 foreach ($mediaImages as $mediaImage) {
326 $id = Arr::get($mediaImage, 'media_id');
327 if ($id) {
328 $media = Media::where('sub_object_id', $exisitngComment->id)
329 ->where('object_source', 'comment')
330 ->find($id);
331 } else {
332 $media = Helper::getMediaFromUrl($mediaImage);
333 }
334
335 if ($media) {
336 $mediaItems[] = $media;
337 $mediaData[] = [
338 'media_id' => $media->id,
339 'url' => $media->public_url,
340 'type' => 'image',
341 'width' => Arr::get($media->settings, 'width'),
342 'height' => Arr::get($media->settings, 'height'),
343 'provider' => Arr::get($media->settings, 'provider', 'uploader')
344 ];
345 }
346 }
347 $commentData['meta']['media_items'] = $mediaData;
348 return [$commentData, $mediaItems];
349 }
350
351 $uploadedImages = Helper::getMediaByProvider($mediaImages);
352 if ($uploadedImages) {
353 $mediaItems = Helper::getMediaItemsFromUrl($uploadedImages);
354 if ($mediaItems) {
355 $mediaPreviews = [];
356 foreach ($mediaItems as $mediaItem) {
357 $mediaData = [
358 'media_id' => $mediaItem->id,
359 'url' => $mediaItem->public_url,
360 'type' => 'image',
361 'width' => Arr::get($mediaItem->settings, 'width'),
362 'height' => Arr::get($mediaItem->settings, 'height'),
363 'provider' => Arr::get($mediaItem->settings, 'provider', 'uploader')
364 ];
365
366 $mediaPreviews[] = array_filter($mediaData);
367 }
368 $commentData['meta']['media_items'] = $mediaPreviews;
369 return [$commentData, $mediaItems];
370 }
371 }
372 }
373
374 if (empty($requestData['meta']['media_preview']['image'])) {
375 return [$commentData, []];
376 }
377
378 if ($exisitngComment) {
379 $image = sanitize_url(Arr::get($requestData, 'meta.media_preview.image', ''));
380 $existingMedia = Media::where('media_url', $image)
381 ->where('object_source', 'comment')
382 ->where('sub_object_id', $exisitngComment->id)
383 ->first();
384
385 if ($existingMedia) {
386 $commentData['meta'] = $exisitngComment->meta;
387 return [$commentData, [$existingMedia]];
388 }
389 }
390
391 $commentData['meta']['media_preview'] = array_filter([
392 'image' => sanitize_url(Arr::get($requestData, 'meta.media_preview.image', '')),
393 'type' => Arr::get($requestData, 'meta.media_preview.type', 'image'),
394 'provider' => Arr::get($requestData, 'meta.media_preview.provider', ''),
395 'height' => Arr::get($requestData, 'meta.media_preview.height', 0),
396 'width' => Arr::get($requestData, 'meta.media_preview.width', 0),
397 ]);
398
399 return [$commentData, []];
400 }
401
402 private function validateCommentText($data)
403 {
404 $text = trim(Arr::get($data, 'comment'));
405 $text = CustomSanitizer::unslashMarkdown($text);
406
407 // Decode HTML entities (e.g., &#x20; for space) and strip all whitespace for validation
408 $textForValidation = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
409 $textForValidation = preg_replace('/\s+/u', '', $textForValidation);
410
411 $hasMedia = Arr::get($data, 'media_images', []) || Arr::get($data, 'meta.media_preview.image', false);
412
413 $isReply = !empty($data['parent_id']);
414 if (!$textForValidation && !$hasMedia) {
415 if ($isReply) {
416 throw new \Exception(esc_html__('Reply cannot be empty.', 'fluent-community'), 422);
417 } else {
418 throw new \Exception(esc_html__('Comment cannot be empty.', 'fluent-community'), 422);
419 }
420 }
421
422 $maxCommentLength = apply_filters('fluent_community/max_comment_char_length', 10000);
423 if ($text && strlen($text) > $maxCommentLength) {
424 /* translators: %s is the maximum allowed character count */
425 throw new \Exception(esc_html(sprintf(__('The comment is too long. Please keep it under %s characters.', 'fluent-community'), number_format($maxCommentLength))), 422);
426 }
427
428 return $text;
429 }
430
431 private function verifyCreateCommentPermission($feed)
432 {
433 if (Arr::get($feed->meta, 'comments_disabled') === 'yes') {
434 throw new \Exception(esc_html__('Comments are disabled for this post', 'fluent-community'));
435 }
436
437 $this->verifySpacePermission($feed);
438 }
439
440 private function verifySpacePermission($feed)
441 {
442 if ($feed->space_id && $feed->space) {
443 $user = $this->getUser(true);
444 $user->verifySpacePermission('can_comment', $feed->space);
445
446 if ($feed->space->type == 'course' && Arr::get($feed->space->settings, 'disable_comments') === 'yes') {
447 throw new \Exception(esc_html__('Comments are disabled for this course', 'fluent-community'));
448 }
449 }
450 }
451
452 private function generateCommentHtml($text, $mentions)
453 {
454 $htmlText = $mentions ? $mentions['text'] : $text;
455 return wp_kses_post(FeedsHelper::mdToHtml($htmlText));
456 }
457
458 private function prepareCommentData($feedId, $text, $commentHtml)
459 {
460 return [
461 'post_id' => $feedId,
462 'message' => $text,
463 'message_rendered' => $commentHtml,
464 'type' => 'comment',
465 'meta' => [],
466 ];
467 }
468
469 private function loadCommentRelations($comment)
470 {
471 $comment->load('media');
472 $comment->load([
473 'xprofile' => function ($q) {
474 $q->select(ProfileHelper::getXProfilePublicFields());
475 }
476 ]);
477 }
478
479 public function addOrRemovePostReact(Request $request, $feed_id)
480 {
481 $userId = get_current_user_id();
482 $feed = Feed::withoutGlobalScopes()->byUserAccess($userId)->findOrFail($feed_id);
483 $type = $request->get('react_type', 'like');
484 $willRemove = $request->get('remove');
485
486 if ($feed->status != 'published') {
487 return $this->sendError([
488 'message' => __('This post is not published yet', 'fluent-community')
489 ]);
490 }
491
492 if ($userId === $feed->user_id && apply_filters('fluent_community/disable_self_post_react', false, $feed)) {
493 return $this->sendError([
494 'message' => __('You cannot react to your own post', 'fluent-community')
495 ]);
496 }
497
498 $react = Reaction::where('user_id', $userId)
499 ->where('object_id', $feed->id)
500 ->where('type', $type)
501 ->objectType('feed')
502 ->first();
503
504 if ($willRemove) {
505 if ($react) {
506 $react->delete();
507 if ($type == 'like') {
508 $feed->reactions_count = $feed->reactions_count - 1;
509 $feed->timestamps = false; // Don't update the updated_at timestamp
510 $feed->save();
511 do_action('fluent_community/feed/react_removed', $feed);
512 }
513 }
514
515 return [
516 'message' => __('Reaction has been removed', 'fluent-community'),
517 'new_count' => $feed->reactions_count
518 ];
519 }
520
521 if ($react) {
522 return [
523 'message' => __('You have already reacted to this post', 'fluent-community'),
524 'new_count' => $feed->reactions_count
525 ];
526 }
527
528 $react = Reaction::create([
529 'user_id' => get_current_user_id(),
530 'object_id' => $feed->id,
531 'type' => $type,
532 'object_type' => 'feed'
533 ]);
534
535 if ($type == 'like') {
536 $feed->reactions_count = $feed->reactions_count + 1;
537 $feed->timestamps = false; // Don't update the updated_at timestamp
538 $feed->save();
539
540 $react->load('xprofile');
541 do_action('fluent_community/feed/react_added', $react, $feed);
542 }
543
544 return [
545 'message' => __('Reaction has been added', 'fluent-community'),
546 'new_count' => $feed->reactions_count
547 ];
548 }
549
550 public function deleteComment(Request $request, $feedId, $commentId)
551 {
552 $feed = Feed::withoutGlobalScopes()->findOrFail($feedId);
553 $comment = Comment::findOrFail($commentId);
554
555 if ($comment->post_id != $feed->id) {
556 return $this->sendError([
557 'message' => __('Invalid comment', 'fluent-community')
558 ]);
559 }
560
561 $user = User::find(get_current_user_id());
562 if ($comment->user_id != get_current_user_id() && !$user->can('delete_any_comment', $feed->space)) {
563 return $this->sendError([
564 'message' => __('You are not allowed to delete this comment', 'fluent-community')
565 ]);
566 }
567
568 do_action('fluent_community/before_comment_delete', $comment);
569
570 if ($comment->media) {
571 do_action('fluent_community/comment/media_deleted', $comment->media);
572 }
573
574 $comment->delete();
575
576 $feed->comments_count = Comment::where('post_id', $feed->id)->count();
577 $feed->timestamps = false; // Don't update the updated_at timestamp
578 $feed->save();
579
580 do_action('fluent_community/comment_deleted_' . $feed->type, $commentId, $feed);
581 do_action('fluent_community/comment_deleted', $commentId, $feed);
582
583 return [
584 'message' => __('Selected comment has been deleted', 'fluent-community')
585 ];
586 }
587
588 public function toggleReaction(Request $request, $feedId, $commentId)
589 {
590 $feed = Feed::withoutGlobalScopes()->findOrFail($feedId);
591 $comment = Comment::findOrFail($commentId);
592
593 if ($comment->post_id != $feed->id) {
594 return $this->sendError([
595 'message' => __('Invalid comment', 'fluent-community')
596 ]);
597 }
598
599 $user = User::findOrFail(get_current_user_id());
600
601 if ($feed->space_id) {
602 $user->verifySpacePermission('registered', $feed->space);
603 }
604
605 $userId = get_current_user_id();
606 if ($userId === $comment->user_id && apply_filters('fluent_community/disable_self_comment_react', false, $feed)) {
607 return $this->sendError([
608 'message' => __('You cannot react to your own comment', 'fluent-community')
609 ]);
610 }
611
612 $reactionState = !!$request->get('state', false);
613
614 if ($reactionState) {
615 // add or update the reaction
616 $reaction = Reaction::firstOrCreate([
617 'user_id' => get_current_user_id(),
618 'object_id' => $comment->id,
619 'object_type' => 'comment',
620 'parent_id' => $feed->id
621 ]);
622
623 if ($reaction->wasRecentlyCreated) {
624 $comment->reactions_count = $comment->reactions_count + 1;
625 $comment->save();
626 do_action('fluent_community/comment/react_added', $reaction, $comment, $feed);
627 }
628 } else {
629 // remove the reaction
630 $deleted = Reaction::where('user_id', get_current_user_id())
631 ->where('object_id', $comment->id)
632 ->where('object_type', 'comment')
633 ->delete();
634
635 if ($deleted) {
636 $comment->reactions_count = $comment->reactions_count - 1;
637 $comment->save();
638 do_action('fluent_community/comment/react_removed', $comment, $feed);
639 }
640 }
641
642 return [
643 'message' => __('Reaction has been toggled', 'fluent-community'),
644 'reactions_count' => $comment->reactions_count,
645 'liked' => $reactionState
646 ];
647 }
648
649 public function show(Request $request, $id)
650 {
651
652 $testComment = Comment::query()->findOrFail($id);
653
654 $comment = Comment::byContentModerationAccessStatus($this->getUser(), $testComment->space)
655 ->with([
656 'xprofile' => function ($q) {
657 return $q->select(ProfileHelper::getXProfilePublicFields());
658 }
659 ])->findOrFail($id);
660
661 // Just to verify the permission
662 Feed::withoutGlobalScopes()
663 ->byUserAccess($this->getUserId())
664 ->findOrFail($comment->post_id);
665
666 if ($request->get('context') == 'edit') {
667 $meta = $comment->meta;
668 unset($comment->meta);
669 $images = Arr::get($meta, 'media_items', []);
670 if ($images) {
671 $comment->media_images = $images;
672 } else {
673 $preview = Arr::get($meta, 'media_preview', []);
674 if ($preview) {
675 $previewUrl = Arr::get($preview, 'image');
676 $provider = Arr::get($preview, 'provider');
677 if ($previewUrl && $provider == 'uploader') {
678 $media = Media::where('media_url', $previewUrl)
679 ->where('object_source', 'comment')
680 ->where('sub_object_id', $comment->id)
681 ->first();
682 if ($media) {
683 $comment->media_images = [
684 [
685 'media_id' => $media->id,
686 'url' => $media->public_url,
687 'type' => $media->media_type,
688 'width' => Arr::get($media->settings, 'width'),
689 'height' => Arr::get($media->settings, 'height'),
690 'provider' => Arr::get($media->settings, 'provider', 'uploader')
691 ]
692 ];
693 }
694 } else {
695 $comment->meta = [
696 'media_preview' => $preview
697 ];
698 }
699 }
700 }
701 }
702
703 $data = [
704 'comment' => $comment
705 ];
706
707 return apply_filters('fluent_community/comment_api_response', $data, $request->all());
708 }
709 }
710