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

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

484 lines 16.0 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 ->orderBy('created_at', 'asc')
32 ->with([
33 'xprofile' => function ($q) {
34 $q->select(ProfileHelper::getXProfilePublicFields());
35 }
36 ])
37 ->get();
38
39 $userId = $this->getUserId();
40
41 if ($userId) {
42 $likedIds = FeedsHelper::getLikedIdsByUserFeedId($feed->id, get_current_user_id());
43
44 if ($likedIds) {
45 $comments->each(function ($comment) use ($likedIds) {
46 if (in_array($comment->id, $likedIds)) {
47 $comment->liked = 1;
48 }
49 });
50 }
51 }
52
53 return [
54 'comments' => $comments
55 ];
56 }
57
58 public function store(Request $request, $feedId)
59 {
60 $user = $this->getUser(true);
61 do_action('fluent_community/check_rate_limit/create_comment', $user);
62
63 $text = $this->validateCommentText($request->all());
64 $feed = Feed::withoutGlobalScopes()->findOrFail($feedId);
65
66 $this->verifyCreateCommentPermission($feed);
67
68 $requestData = $request->all();
69
70 // Check for duplicate
71 $exist = Comment::where('user_id', get_current_user_id())
72 ->where('message', $text)
73 ->where('post_id', $feed->id)
74 ->first();
75
76 if ($exist) {
77 return $this->sendError([
78 'message' => __('No duplicate comment please!', 'fluent-community')
79 ]);
80 }
81
82 $mentions = FeedsHelper::getMentions($text, $feed->space_id);
83 $commentHtml = $this->generateCommentHtml($text, $mentions);
84 $commentData = $this->prepareCommentData($feed->id, $text, $commentHtml);
85
86 if ($parentId = $request->get('parent_id')) {
87 $parentId = (int) $parentId;
88 $parentComment = Comment::where('id', $parentId)
89 ->where('post_id', $feed->id)
90 ->first();
91
92 if (!$parentComment) {
93 return $this->sendError([
94 'message' => __('Invalid parent comment', 'fluent-community')
95 ]);
96 }
97
98 $commentData['parent_id'] = $parentId;
99 }
100
101 [$commentData, $media] = $this->prepareCommentMedia($commentData, $requestData);
102
103 do_action('fluent_community/before_comment_create', $commentData, $feed);
104
105 $commentData = apply_filters('fluent_community/comment/comment_data', $commentData, $feed, $requestData);
106
107 $comment = Comment::create($commentData);
108
109 $feed->comments_count = $feed->comments_count + 1;
110 $feed->save();
111
112 if ($media) {
113 $media->fill([
114 'is_active' => 1,
115 'feed_id' => $feed->id,
116 'object_source' => 'comment',
117 'sub_object_id' => $comment->id
118 ]);
119 $media->save();
120 }
121
122 $this->loadCommentRelations($comment);
123
124 $mentionedUsers = $mentions ? $mentions['users'] : null;
125 do_action('fluent_community/comment_added_' . $feed->type, $comment, $feed, $mentionedUsers);
126 do_action('fluent_community/comment_added', $comment, $feed, $mentionedUsers);
127
128 return [
129 'comment' => $comment,
130 'message' => __('Comment has been added', 'fluent-community'),
131 ];
132 }
133
134 public function update(Request $request, $feedId, $commentId)
135 {
136 $text = $this->validateCommentText($request->all());
137 $feed = Feed::withoutGlobalScopes()->findOrFail($feedId);
138 $this->verifySpacePermission($feed);
139
140 $requestData = $request->all();
141 $comment = Comment::findOrFail($commentId);
142 $user = User::find(get_current_user_id());
143
144 if (!$user->can('edit_any_comment') && $comment->user_id != get_current_user_id()) {
145 return $this->sendError([
146 'message' => __('You are not allowed to edit this comment', 'fluent-community')
147 ]);
148 }
149
150 $mentions = FeedsHelper::getMentions($text, $feed->space_id);
151 $commentHtml = $this->generateCommentHtml($text, $mentions);
152
153 $commentData = $this->prepareCommentData($feed->id, $text, $commentHtml);
154
155 [$commentData, $media] = $this->prepareCommentMedia($commentData, $requestData, $comment);
156
157 $commentData = apply_filters('fluent_community/comment/update_comment_data', $commentData, $feed, $requestData);
158
159 $comment->fill($commentData);
160
161 $dirty = $comment->getDirty();
162
163 if ($dirty) {
164 $comment->save();
165 }
166
167 if ($media) {
168 $media->fill([
169 'is_active' => 1,
170 'feed_id' => $feed->id,
171 'object_source' => 'comment',
172 'sub_object_id' => $comment->id
173 ]);
174 $media->save();
175
176 // remove other media
177 $otherMedias = Media::where('object_source', 'comment')
178 ->where('sub_object_id', $comment->id)
179 ->where('id', '!=', $media->id)
180 ->get();
181
182 if (!$otherMedias->isEmpty()) {
183 // do_action('fluent_community/comment/media_deleted', $otherMedias);
184 }
185 } else {
186 // remove other media
187 $otherMedias = Media::where('object_source', 'comment')
188 ->where('sub_object_id', $comment->id)
189 ->get();
190
191 if (!$otherMedias->isEmpty()) {
192 // do_action('fluent_community/comment/media_deleted', $otherMedias);
193 }
194 }
195
196 $this->loadCommentRelations($comment);
197
198 if ($dirty) {
199 do_action('fluent_community/comment_updated', $comment, $feed);
200 do_action('fluent_community/comment_updated_' . $feed->type, $comment, $feed);
201 }
202
203 return [
204 'comment' => $comment,
205 'message' => __('Comment has been updated', 'fluent-community'),
206 ];
207 }
208
209 private function prepareCommentMedia($commentData, $requestData, $exisitngComment = null)
210 {
211 $mediaImages = Arr::get($requestData, 'media_images', []);
212
213 if ($mediaImages) {
214 $uploadedImages = Helper::getMediaByProvider($mediaImages);
215 if ($uploadedImages) {
216 $mediaItems = Helper::getMediaItemsFromUrl($uploadedImages);
217 if ($mediaItems) {
218 $firstMedia = $mediaItems[0];
219 $commentData['meta']['media_preview'] = [
220 'image' => $firstMedia->public_url,
221 'type' => 'image',
222 'provider' => 'upload',
223 'height' => $firstMedia->settings ? Arr::get($firstMedia->settings, 'height', 0) : 0,
224 'width' => $firstMedia->settings ? Arr::get($firstMedia->settings, 'width', 0) : 0,
225 ];
226 return [$commentData, $firstMedia];
227 }
228 }
229 }
230
231 if (empty($requestData['meta']['media_preview']['image'])) {
232 return [$commentData, null];
233 }
234
235 if ($exisitngComment) {
236 $image = sanitize_url(Arr::get($requestData, 'meta.media_preview.image', ''));
237 $existingMedia = Media::where('media_url', $image)
238 ->where('object_source', 'comment')
239 ->where('sub_object_id', $exisitngComment->id)
240 ->first();
241
242 if ($existingMedia) {
243 $commentData['meta'] = $exisitngComment->meta;
244 return [$commentData, $existingMedia];
245 }
246 }
247
248 $commentData['meta']['media_preview'] = array_filter([
249 'image' => sanitize_url(Arr::get($requestData, 'meta.media_preview.image', '')),
250 'type' => Arr::get($requestData, 'meta.media_preview.type', 'image'),
251 'provider' => Arr::get($requestData, 'meta.media_preview.provider', ''),
252 'height' => Arr::get($requestData, 'meta.media_preview.height', 0),
253 'width' => Arr::get($requestData, 'meta.media_preview.width', 0),
254 ]);
255
256 return [$commentData, null];
257 }
258
259 private function validateCommentText($data)
260 {
261 $text = trim(Arr::get($data, 'comment'));
262 $text = CustomSanitizer::unslashMarkdown($text);
263
264 $hasMedia = Arr::get($data, 'media_images', []) || Arr::get($data, 'meta.media_preview.image', false);
265
266 if (!$text && !$hasMedia) {
267 throw new \Exception(esc_html__('Please provide your reply text', 'fluent-community'), 422);
268 }
269
270 $maxCommentLength = apply_filters('fluent_community/max_comment_char_length', 10000);
271 if ($text && strlen($text) > $maxCommentLength) {
272 throw new \Exception(esc_html__('Comment text is too long', 'fluent-community'), 422);
273 }
274
275 return $text;
276 }
277
278 private function verifyCreateCommentPermission($feed)
279 {
280 if (Arr::get($feed->meta, 'comments_disabled') === 'yes') {
281 throw new \Exception(esc_html__('Comments are disabled for this post', 'fluent-community'));
282 }
283
284 $this->verifySpacePermission($feed);
285 }
286
287 private function verifySpacePermission($feed)
288 {
289 if ($feed->space_id && $feed->space) {
290 $user = $this->getUser(true);
291 $user->verifySpacePermission('registered', $feed->space);
292 }
293 }
294
295 private function generateCommentHtml($text, $mentions)
296 {
297 $htmlText = $mentions ? $mentions['text'] : $text;
298 return wp_kses_post(FeedsHelper::mdToHtml($htmlText));
299 }
300
301 private function prepareCommentData($feedId, $text, $commentHtml)
302 {
303 return [
304 'post_id' => $feedId,
305 'message' => $text,
306 'message_rendered' => $commentHtml,
307 'type' => 'comment',
308 'meta' => [],
309 ];
310 }
311
312 private function loadCommentRelations($comment)
313 {
314 $comment->load('media');
315 $comment->load([
316 'xprofile' => function ($q) {
317 $q->select(ProfileHelper::getXProfilePublicFields());
318 }
319 ]);
320 }
321
322 public function addOrRemovePostReact(Request $request, $feed_id)
323 {
324 $feed = Feed::withoutGlobalScopes()->findOrFail($feed_id);
325 $type = $request->get('react_type', 'like');
326 $willRemove = $request->get('remove');
327
328 $react = Reaction::where('user_id', get_current_user_id())
329 ->where('object_id', $feed->id)
330 ->where('type', $type)
331 ->objectType('feed')
332 ->first();
333
334 if ($willRemove) {
335 if ($react) {
336 $react->delete();
337 if ($type == 'like') {
338 $feed->reactions_count = $feed->reactions_count - 1;
339 $feed->save();
340 }
341 }
342
343 return [
344 'message' => 'Reaction has been removed',
345 'new_count' => $feed->reactions_count
346 ];
347 }
348
349 if ($react) {
350 return [
351 'message' => 'You have already reacted to this post',
352 'new_count' => $feed->reactions_count
353 ];
354 }
355
356 $react = Reaction::create([
357 'user_id' => get_current_user_id(),
358 'object_id' => $feed->id,
359 'type' => $type,
360 'object_type' => 'feed'
361 ]);
362
363 if ($type == 'like') {
364 $feed->reactions_count = $feed->reactions_count + 1;
365 $feed->save();
366
367 $react->load('xprofile');
368 do_action('fluent_community/feed/react_added', $react, $feed);
369 }
370
371 return [
372 'message' => 'Reaction has been added',
373 'new_count' => $feed->reactions_count
374 ];
375 }
376
377 public function deleteComment(Request $request, $feedId, $commentId)
378 {
379 $feed = Feed::withoutGlobalScopes()->findOrFail($feedId);
380 $comment = Comment::findOrFail($commentId);
381
382 if ($comment->post_id != $feed->id) {
383 return $this->sendError([
384 'message' => 'Invalid comment'
385 ]);
386 }
387
388 $user = User::find(get_current_user_id());
389 if (!$user->can('delete_any_comment') && $comment->user_id != get_current_user_id()) {
390 return $this->sendError([
391 'message' => 'You are not allowed to delete this comment'
392 ]);
393 }
394
395 do_action('fluent_community/before_comment_delete', $comment);
396
397 if ($comment->media) {
398 do_action('fluent_community/comment/media_deleted', $comment->media);
399 }
400
401 $comment->delete();
402
403 $feed->comments_count = Comment::where('post_id', $feed->id)->count();
404 $feed->save();
405
406 do_action('fluent_community/comment_deleted_' . $feed->type, $commentId, $feed);
407 do_action('fluent_community/comment_deleted', $commentId, $feed);
408
409 return [
410 'message' => __('Selected comment has been deleted', 'fluent-community')
411 ];
412 }
413
414 public function toggoleReaction(Request $request, $feedId, $commentId)
415 {
416 $feed = Feed::withoutGlobalScopes()->findOrFail($feedId);
417 $comment = Comment::findOrFail($commentId);
418
419 if ($comment->post_id != $feed->id) {
420 return $this->sendError([
421 'message' => 'Invalid comment'
422 ]);
423 }
424
425 $user = User::findOrFail(get_current_user_id());
426
427 if ($feed->space_id) {
428 $user->verifySpacePermission('registered', $feed->space);
429 }
430
431 $reactionState = !!$request->get('state', false);
432
433 if ($reactionState) {
434 // add or update the reaction
435 $reaction = Reaction::firstOrCreate([
436 'user_id' => get_current_user_id(),
437 'object_id' => $comment->id,
438 'object_type' => 'comment',
439 'parent_id' => $feed->id
440 ]);
441
442 if ($reaction->wasRecentlyCreated) {
443 $comment->reactions_count = $comment->reactions_count + 1;
444 $comment->save();
445 }
446 } else {
447 // remove the reaction
448 $deleted = Reaction::where('user_id', get_current_user_id())
449 ->where('object_id', $comment->id)
450 ->where('object_type', 'comment')
451 ->delete();
452
453 if ($deleted) {
454 $comment->reactions_count = $comment->reactions_count - 1;
455 $comment->save();
456 }
457 }
458
459 return [
460 'message' => 'Reaction has been toggled',
461 'reactions_count' => $comment->reactions_count,
462 'liked' => $reactionState
463 ];
464 }
465
466 public function show(Request $request, $id)
467 {
468 $comment = Comment::with([
469 'xprofile' => function ($q) {
470 return $q->select(ProfileHelper::getXProfilePublicFields());
471 }
472 ])->findOrFail($id);
473
474 // Just to verify the permission
475 $feed = Feed::withoutGlobalScopes()
476 ->byUserAccess($this->getUserId())
477 ->findOrFail($comment->post_id);
478
479 return [
480 'comment' => $comment
481 ];
482 }
483 }
484