PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 1.0.91
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v1.0.91
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 / SpaceController.php

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

797 lines 24.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCommunity\App\Http\Controllers;
4
5 use FluentCommunity\App\Functions\Utility;
6 use FluentCommunity\App\Models\Space;
7 use FluentCommunity\App\Models\Feed;
8 use FluentCommunity\App\Models\BaseSpace;
9 use FluentCommunity\App\Models\SpaceGroup;
10 use FluentCommunity\App\Models\User;
11 use FluentCommunity\App\Services\CustomSanitizer;
12 use FluentCommunity\App\Services\FeedsHelper;
13 use FluentCommunity\App\Services\Helper;
14 use FluentCommunity\App\Services\LockscreenService;
15 use FluentCommunity\App\Services\ProfileHelper;
16 use FluentCommunity\Framework\Http\Request\Request;
17 use FluentCommunity\App\Models\Comment;
18 use FluentCommunity\App\Models\Reaction;
19 use FluentCommunity\App\Models\SpaceUserPivot;
20 use FluentCommunity\Framework\Support\Arr;
21
22 class SpaceController extends Controller
23 {
24 public function get()
25 {
26 $spaces = Space::orderBy('title', 'ASC')
27 ->whereHas('space_pivot', function ($q) {
28 $q->where('user_id', get_current_user_id());
29 })
30 ->get();
31
32 return [
33 'spaces' => $spaces
34 ];
35 }
36
37 public function create(Request $request)
38 {
39 $currentUser = $this->getUser(true);
40 $currentUser->verifyCommunityPermission('community_admin');
41
42 $data = $request->get('space', []);
43
44 if (empty($data['slug'])) {
45 $data['slug'] = sanitize_title($data['title'], '');
46 } else {
47 $data['slug'] = sanitize_title($data['slug'], '');
48 }
49
50 $data['title'] = sanitize_text_field($data['title']);
51 $data['privacy'] = sanitize_text_field($data['privacy']);
52
53 $this->validate($data, [
54 'title' => 'required',
55 'slug' => 'required|unique:fcom_spaces,slug',
56 'privacy' => 'required|in:public,private,secret',
57 'parent_id' => 'required|exists:fcom_spaces,id'
58 ], [
59 'parent_id.required' => __('Please select a menu group', 'fluent-community')
60 ]);
61
62 $spaceGroup = SpaceGroup::findOrFail($data['parent_id']);
63
64 $space = Space::create([
65 'title' => sanitize_text_field($data['title']),
66 'slug' => $data['slug'],
67 'privacy' => $data['privacy'],
68 'description' => sanitize_textarea_field($data['description']),
69 'settings' => [
70 'restricted_post_only' => Arr::get($data, 'settings.restricted_post_only', 'no'),
71 'emoji' => CustomSanitizer::sanitizeEmoji(Arr::get($data, 'settings.emoji', '')),
72 'can_request_join' => Arr::get($data, 'settings.can_request_join', 'no'),
73 'custom_lock_screen' => Arr::get($data, 'settings.custom_lock_screen', 'no'),
74 'layout_style' => Arr::get($data, 'settings.layout_style', 'timeline'),
75 'show_sidebar' => Arr::get($data, 'settings.show_sidebar', 'yes')
76 ],
77 'parent_id' => $spaceGroup->id,
78 'serial' => BaseSpace::where('parent_id', $spaceGroup->id)->max('serial') + 1
79 ]);
80
81 $imageTypes = ['cover_photo', 'logo'];
82 $metaData = [];
83 foreach ($imageTypes as $type) {
84 if (!empty($data[$type])) {
85 $media = Helper::getMediaFromUrl($data[$type]);
86 if (!$media || $media->is_active) {
87 continue;
88 }
89 $metaData[$type] = $media->public_url;
90 $media->update([
91 'is_active' => true,
92 'user_id' => get_current_user_id(),
93 'sub_object_id' => $space->id,
94 'object_source' => 'space_' . $type
95 ]);
96 }
97 }
98
99 if ($metaData) {
100 $space->updateCustomData($metaData, false);
101 }
102
103 $space->members()->attach(get_current_user_id(), [
104 'role' => 'admin'
105 ]);
106
107 $currentUser->cacheAccessSpaces();
108
109 do_action('fluent_community/space/created', $space, $data);
110
111 return [
112 'message' => __('Space has been created successfully', 'fluent-community'),
113 'space' => $space
114 ];
115 }
116
117 public function discover(Request $request)
118 {
119 $spaces = Space::orderBy('title', 'ASC')
120 ->with(['space_pivot' => function ($q) {
121 $q->where('user_id', get_current_user_id());
122 }])
123 ->where(function ($q) {
124 $q->whereHas('space_pivot', function ($q) {
125 $q->where('user_id', get_current_user_id());
126 })
127 ->orWhereIn('privacy', ['public', 'private']);
128 })
129 ->get();
130
131 foreach ($spaces as $space) {
132 $space->members_count = $space->members()->wherePivot('status', 'active')->count();
133 }
134
135 return [
136 'spaces' => $spaces
137 ];
138 }
139
140 public function getBySlug(Request $request, $spaceSlug)
141 {
142 $user = $this->getUser();
143 $space = Space::where('slug', $spaceSlug)
144 ->firstOrFail();
145
146 $space->permissions = $space->getUserPermissions($user);
147 $space->description_rendered = FeedsHelper::mdToHtml($space->description);
148 $space->membership = $space->getMembership(get_current_user_id());
149 $space->topics = Utility::getTopicsBySpaceId($space->id);
150
151 if (!Helper::isSiteAdmin()) {
152 $space->lockscreen_config = LockscreenService::getLockscreenConfig($space, $space->membership);
153 }
154
155 if ($space->privacy == 'secret' && !$space->membership) {
156 return $this->sendError([
157 'message' => __('You are not allowed to view this space', 'fluent-community'),
158 'error_type' => 'restricted'
159 ]);
160 }
161
162 do_action_ref_array('fluent_community/space', [&$space]);
163
164 return [
165 'space' => $space
166 ];
167 }
168
169 public function patchBySlug(Request $request, $slug)
170 {
171 $space = Space::where('slug', $slug)
172 ->first();
173
174 if (!$space) {
175 return $this->sendError([
176 'message' => 'Space not found'
177 ]);
178 }
179
180 $space->verifyUserPermisson($this->getUser(), 'community_admin');
181
182 $data = $request->get('data', []);
183
184 if (!empty($data['title'])) {
185 $taken = Space::where('title', $data['title'])
186 ->where('id', '!=', $space->id)
187 ->first();
188 if ($taken) {
189 return $this->sendError([
190 'message' => 'Space title is already taken. Please use a different title'
191 ]);
192 }
193 }
194
195 $mediaTypes = ['cover_photo', 'logo'];
196 foreach ($mediaTypes as $type) {
197 if (!empty($data[$type])) {
198 $media = Helper::getMediaFromUrl($data[$type]);
199 if (!$media) {
200 unset($data[$type]);
201 continue;
202 }
203
204 if (!$media || $media->is_active) {
205 return $this->sendError([
206 'message' => 'Invalid media image. Please upload a new one.'
207 ]);
208 }
209
210 $data[$type] = $media->public_url;
211
212 $media->update([
213 'is_active' => true,
214 'user_id' => get_current_user_id(),
215 'sub_object_id' => $space->id,
216 'object_source' => 'space_' . $type
217 ]);
218 } else if (isset($data[$type])) {
219 $data[$type] = '';
220 }
221 }
222
223 $space->updateCustomData($data, true);
224
225 if (Arr::has($data, 'topic_ids')) {
226 $topicIds = Arr::get($data, 'topic_ids', []);
227 $space->syncTopics($topicIds);
228 }
229
230 do_action('fluent_community/space/updated', $space, $data);
231
232 return [
233 'message' => __('Space has been updated', 'fluent-community')
234 ];
235 }
236
237 public function getMembers(Request $request, $slug)
238 {
239 $space = Space::where('slug', $slug)
240 ->firstOrFail();
241
242 $user = $this->getUser();
243 $space->verifyUserPermisson($user, 'can_view_members');
244
245 $search = $request->getSafe('search', 'sanitize_text_field');
246
247 $pendingCount = 0;
248 if ($user && $user->can('can_add_member', $space)) {
249 $pendingCount = SpaceUserPivot::bySpace($space->id)
250 ->where('status', 'pending')
251 ->count();
252
253 if ($request->get('status') == 'pending') {
254 $pendingRequests = SpaceUserPivot::bySpace($space->id)
255 ->whereHas('xprofile', function ($q) use ($search) {
256 return $q->searchBy($search)
257 ->where('status', 'active');
258 })
259 ->with(['xprofile' => function ($q) {
260 $q->select(ProfileHelper::getXProfilePublicFields());
261 }])
262 ->where('status', 'pending')
263 ->paginate();
264
265 return [
266 'members' => $pendingRequests,
267 'pending_count' => $pendingCount
268 ];
269 }
270 }
271
272 $spaceMembers = SpaceUserPivot::bySpace($space->id)
273 ->whereHas('xprofile', function ($q) use ($search) {
274 return $q->searchBy($search)
275 ->where('status', 'active');
276 })
277 ->with(['xprofile' => function ($q) {
278 $q->select(ProfileHelper::getXProfilePublicFields());
279 }])
280 ->where('status', 'active')
281 ->paginate();
282
283 return [
284 'members' => $spaceMembers,
285 'pending_count' => $pendingCount
286 ];
287 }
288
289 public function join(Request $request, $slug)
290 {
291 $space = Space::where('slug', $slug)->first();
292
293 if (!$space) {
294 return $this->sendError([
295 'message' => 'Space not found'
296 ]);
297 }
298
299 $user = $this->getUser();
300
301 $membership = $space->getMembership(get_current_user_id());
302
303 if ($membership) {
304 return $this->sendError([
305 'message' => 'You are already a member of this space. Please reload this page'
306 ]);
307 }
308
309 $roles = $user->getCommunityRoles();
310
311 if (!$roles && $space->privacy == 'secret') {
312 return $this->sendError([
313 'message' => 'You are not allowed to join this space'
314 ]);
315 }
316
317 $status = 'active';
318 if (!$roles) {
319 if ($space->privacy != 'public') {
320 $status = apply_filters('fluent_community/space/join_status_for_private', 'pending', $space, $user);
321 }
322 $role = 'member';
323 } else {
324 $role = $user->isCommunityAdmin() ? 'admin' : 'moderator';
325 }
326
327 $space->members()->attach(get_current_user_id(), [
328 'role' => $role,
329 'status' => $status
330 ]);
331
332 $space->membership = $space->getMembership(get_current_user_id());
333
334 if ($status == 'pending') {
335 do_action('fluent_community/space/join_requested', $space, $user->ID, 'self');
336 } else {
337 do_action('fluent_community/space/joined', $space, $user->ID, 'self');
338 }
339
340 $user->cacheAccessSpaces();
341
342 return [
343 'message' => ($status == 'active') ? __('You have joined this Space', 'fluent-community') : __('Your join request has been sent to the Space admin', 'fluent-community'),
344 'membership' => $space->membership
345 ];
346 }
347
348 public function leave(Request $request, $slug)
349 {
350 $user = $this->getUser(true);
351 $space = Space::where('slug', $slug)->first();
352
353 if (!$space) {
354 return $this->sendError([
355 'message' => 'Space not found'
356 ]);
357 }
358
359 $membership = $space->getMembership($user->ID);
360
361 if (!$membership) {
362 return $this->sendError([
363 'message' => 'You are not a member of this community'
364 ]);
365 }
366
367 Helper::removeFromSpace($space, $user->ID, 'self');
368
369 return [
370 'message' => __('You have left this space', 'fluent-community')
371 ];
372 }
373
374 public function delete(Request $request, $slug)
375 {
376 $space = Space::where('slug', $slug)->first();
377
378 if (!$space) {
379 return $this->sendError([
380 'message' => 'Space not found'
381 ]);
382 }
383
384 if (!Helper::isSiteAdmin()) {
385 return $this->sendError([
386 'message' => 'You are not allowed to delete this community'
387 ]);
388 }
389
390 do_action('fluent_community/space/before_delete', $space);
391
392 Comment::whereHas('post', function ($q) use ($space) {
393 $q->where('space_id', $space->id);
394 })->delete();
395
396 Reaction::whereHas('feed', function ($q) use ($space) {
397 $q->where('space_id', $space->id);
398 })->delete();
399
400 Feed::where('space_id', $space->id)->delete();
401
402 SpaceUserPivot::where('space_id', $space->id)->delete();
403
404 $spaceId = $space->id;
405 $space->delete();
406
407 do_action('fluent_community/space/deleted', $spaceId);
408
409 return [
410 'message' => __('Space has been deleted successfully', 'fluent-community')
411 ];
412 }
413
414 public function addMember(Request $request, $slug)
415 {
416 $space = Space::where('slug', $slug)->first();
417
418 if (!$space) {
419 return $this->sendError([
420 'message' => 'Space not found'
421 ]);
422 }
423
424 $this->validate($request->all(), [
425 'user_id' => 'required|exists:users,ID'
426 ]);
427
428 $userId = $request->get('user_id');
429 $targetUser = User::findOrFail($userId);
430 $xprofile = $targetUser->syncXProfile();
431
432 if ($xprofile && $xprofile->status != 'active') {
433 return $this->sendError([
434 'message' => __('Selected user is not active', 'fluent-community')
435 ]);
436 }
437
438 $admin = User::find(get_current_user_id());
439 $admin->verifySpacePermission('can_add_member', $space);
440
441 $pivot = SpaceUserPivot::bySpace($space->id)
442 ->byUser($userId)
443 ->first();
444
445 $role = $request->get('role', 'member');
446
447 if ($pivot) {
448 if ($pivot->status == 'active') {
449 if ($role != $pivot->role) {
450 $pivot->role = $role;
451 $pivot->save();
452
453 do_action('fluent_community/space/member/role_updated', $space, $pivot);
454
455 return [
456 'message' => 'Member role updated'
457 ];
458 }
459
460 return $this->sendError([
461 'message' => 'Selected user is already a member of this community'
462 ]);
463 }
464
465 $pivot->status = 'active';
466 $pivot->save();
467 do_action('fluent_community/space/joined', $space, $userId, 'approved');
468
469 if ($role != 'member') {
470 do_action('fluent_community/space/member/role_updated', $space, $pivot);
471 }
472
473 return [
474 'message' => 'Member approved'
475 ];
476 }
477
478 $space->members()->attach($userId, [
479 'role' => $role,
480 'status' => 'active'
481 ]);
482
483 $targetUser->cacheAccessSpaces();
484
485 do_action('fluent_community/space/joined', $space, $userId, 'by_admin');
486
487 return [
488 'message' => 'User has been added to this community'
489 ];
490 }
491
492 public function removeMember(Request $request, $slug)
493 {
494 $space = Space::where('slug', $slug)->first();
495
496 if (!$space) {
497 return $this->sendError([
498 'message' => 'Space not found'
499 ]);
500 }
501
502 $userId = $request->get('user_id');
503
504 $admin = User::find(get_current_user_id());
505 $admin->verifySpacePermission('can_remove_member', $space);
506
507 $pivot = SpaceUserPivot::bySpace($space->id)
508 ->byUser($userId)
509 ->first();
510
511 if (!$pivot) {
512 return $this->sendError([
513 'message' => 'Selected user is not a member of this community'
514 ]);
515 }
516
517 $pivot->delete();
518
519 $targetUser = User::find($userId);
520
521 if ($targetUser) {
522 $targetUser->cacheAccessSpaces();
523 }
524
525 do_action('fluent_community/space/user_left', $space, $userId, 'by_admin');
526
527 return [
528 'message' => 'User has been removed from this community'
529 ];
530 }
531
532 public function getOtherUsers(Request $request)
533 {
534 $currentUser = $this->getUser(true);
535
536 $this->validate($request->all(), [
537 'space_id' => 'required|exists:fcom_spaces,id'
538 ]);
539
540 $isMod = $currentUser->isCommunityModerator() && current_user_can('list_users');
541
542 $spaceId = $request->get('space_id');
543
544 $selects = ['ID', 'display_name'];
545
546 if ($isMod) {
547 $selects[] = 'user_email';
548 }
549
550 $users = User::whereDoesntHave('spaces', function ($q) use ($spaceId) {
551 return $q->where('space_id', $spaceId);
552 })
553 ->select($selects)
554 ->searchBy($request->get('search'))
555 ->paginate();
556
557 return [
558 'users' => $users
559 ];
560 }
561
562 public function updateLinks(Request $request, $slug)
563 {
564 $space = Space::where('slug', $slug)->first();
565
566 if (!$space) {
567 return $this->sendError([
568 'message' => 'Space not found'
569 ]);
570 }
571
572 $space->verifyUserPermisson($this->getUser(), 'community_admin');
573
574 $links = $request->get('links', []);
575
576 $links = array_map(function ($link) {
577 return CustomSanitizer::santizeLinkItem($link);
578 }, $links);
579
580 $settings = $space->settings;
581 $settings['links'] = $links;
582 $space->settings = $settings;
583 $space->save();
584
585 return [
586 'message' => __('Links has been updated for the space', 'fluent-community'),
587 'links' => $links
588 ];
589 }
590
591 public function getSpaceGroups(Request $request)
592 {
593 $user = $this->getUser(true);
594 if (!$user->isCommunityModerator()) {
595 return $this->sendError([
596 'message' => 'You are not allowed to create space group'
597 ]);
598 }
599
600 $user = $this->getUser();
601
602 $groups = Helper::getAllCommunityGroups($user, false);
603
604 foreach ($groups as $group) {
605 foreach ($group->spaces as $space) {
606 $space->permalink = $space->getPermalink();
607 }
608 }
609
610 return [
611 'groups' => $groups
612 ];
613 }
614
615 public function createSpaceGroup(Request $request)
616 {
617 $user = $this->getUser(true);
618 if (!$user->isCommunityModerator()) {
619 return $this->sendError([
620 'message' => 'You are not allowed to create space group'
621 ]);
622 }
623
624 $data = $request->all();
625
626 $this->validate($data, [
627 'title' => 'required|unique:fcom_spaces,title',
628 'slug' => 'required|unique:fcom_spaces,slug'
629 ]);
630
631
632 $formattedData = [
633 'title' => sanitize_text_field($data['title']),
634 'slug' => sanitize_title($data['slug']),
635 'description' => sanitize_textarea_field($data['description']),
636 'status' => 'active',
637 'type' => 'space_group',
638 'settings' => [
639 'always_show_spaces' => Arr::get($data, 'settings.always_show_spaces', 'yes'),
640 ],
641 'serial' => SpaceGroup::max('serial') + 1
642 ];
643
644 $group = SpaceGroup::create($formattedData);
645
646 return [
647 'message' => __('Space group has been created successfully', 'fluent-community'),
648 'group' => $group
649 ];
650 }
651
652 public function updateSpaceGroup(Request $request, $groupId)
653 {
654 $user = $this->getUser();
655 if (!$user || !$user->isCommunityModerator()) {
656 return $this->sendError([
657 'message' => 'You are not allowed to create space group'
658 ]);
659 }
660
661 $group = SpaceGroup::findOrFail($groupId);
662 $data = $request->all();
663
664 $this->validate($data, [
665 'title' => 'required'
666 ]);
667
668 $taken = BaseSpace::where('title', $data['title'])
669 ->where('id', '!=', $group->id)
670 ->first();
671
672 if ($taken) {
673 return $this->sendError([
674 'message' => 'The title is already taken. Please use a different title'
675 ]);
676 }
677
678 $formattedData = [
679 'title' => sanitize_text_field($data['title']),
680 'description' => sanitize_textarea_field($data['description']),
681 'status' => 'active',
682 'type' => 'space_group',
683 'settings' => [
684 'always_show_spaces' => Arr::get($data, 'settings.always_show_spaces', 'yes'),
685 ]
686 ];
687
688 $group->fill($formattedData)->save();
689
690 return [
691 'message' => __('Space group has been created updated', 'fluent-community'),
692 'group' => $group
693 ];
694 }
695
696 public function deleteSpaceGroup(Request $request, $groupId)
697 {
698
699 $user = $this->getUser();
700 if (!$user || !$user->isCommunityModerator()) {
701 return $this->sendError([
702 'message' => 'You are not allowed to create space group'
703 ]);
704 }
705
706 $group = SpaceGroup::findOrFail($groupId);
707
708 if (!$group->spaces->isEmpty()) {
709 return $this->sendError([
710 'message' => 'You can not delete this group. It has spaces'
711 ]);
712 }
713
714 $group->delete();
715
716 return [
717 'message' => __('Space group has been deleted successfully', 'fluent-community')
718 ];
719 }
720
721 public function updateSpaceGroupIndexes(Request $request)
722 {
723 $indexes = $request->get('indexes', []);
724
725 foreach ($indexes as $groupId => $indexNumber) {
726 $group = SpaceGroup::findOrFail($groupId);
727 $group->update([
728 'serial' => $indexNumber + 1
729 ]);
730 }
731
732 return [
733 'message' => __('Space group indexes has been updated', 'fluent-community')
734 ];
735
736 }
737
738 public function updateSpaceIndexes(Request $request)
739 {
740 $indexes = $request->get('indexes', []);
741
742 foreach ($indexes as $index => $spaceId) {
743 $space = BaseSpace::withoutGlobalScopes()->findOrFail($spaceId);
744 $space->update([
745 'serial' => $index + 1
746 ]);
747 }
748
749 return [
750 'message' => __('Space indexes has been updated', 'fluent-community')
751 ];
752 }
753
754 public function moveSpace(Request $request)
755 {
756 $spaceId = $request->getSafe('space_id', 'intval');
757 $groupId = $request->getSafe('group_id', 'intval');
758
759 $space = BaseSpace::withoutGlobalScopes()->findOrFail($spaceId);
760 $group = SpaceGroup::findOrFail($groupId);
761
762 $space->update([
763 'parent_id' => $groupId
764 ]);
765
766 return [
767 'message' => __('Space has been moved successfully', 'fluent-community')
768 ];
769 }
770
771 public function getLockScreenSettings(Request $request, $spaceSlug)
772 {
773 $space = Space::where('slug', $spaceSlug)->firstOrFail();
774 $lockscreen = $space->getLockscreen();
775
776 return [
777 'lockscreen' => $lockscreen
778 ];
779 }
780
781 public function updateLockscreenSettings(Request $request, $spaceSlug)
782 {
783 $space = Space::where('slug', $spaceSlug)->firstOrFail();
784
785 $settingFields = $request->get('lockscreen', []);
786
787 $formattedFields = LockscreenService::formatLockscreenFields($settingFields);
788
789 $space->setLockscreen($formattedFields);
790
791 return [
792 'message' => 'Lockscreen settings has been updated successfully.',
793 'community' => $space
794 ];
795 }
796 }
797