PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 1.0.94
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v1.0.94
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.94, at app/Http/Controllers/SpaceController.php

798 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
233 return [
234 'message' => __('Space has been updated', 'fluent-community')
235 ];
236 }
237
238 public function getMembers(Request $request, $slug)
239 {
240 $space = Space::where('slug', $slug)
241 ->firstOrFail();
242
243 $user = $this->getUser();
244 $space->verifyUserPermisson($user, 'can_view_members');
245
246 $search = $request->getSafe('search', 'sanitize_text_field');
247
248 $pendingCount = 0;
249 if ($user && $user->can('can_add_member', $space)) {
250 $pendingCount = SpaceUserPivot::bySpace($space->id)
251 ->where('status', 'pending')
252 ->count();
253
254 if ($request->get('status') == 'pending') {
255 $pendingRequests = SpaceUserPivot::bySpace($space->id)
256 ->whereHas('xprofile', function ($q) use ($search) {
257 return $q->searchBy($search)
258 ->where('status', 'active');
259 })
260 ->with(['xprofile' => function ($q) {
261 $q->select(ProfileHelper::getXProfilePublicFields());
262 }])
263 ->where('status', 'pending')
264 ->paginate();
265
266 return [
267 'members' => $pendingRequests,
268 'pending_count' => $pendingCount
269 ];
270 }
271 }
272
273 $spaceMembers = SpaceUserPivot::bySpace($space->id)
274 ->whereHas('xprofile', function ($q) use ($search) {
275 return $q->searchBy($search)
276 ->where('status', 'active');
277 })
278 ->with(['xprofile' => function ($q) {
279 $q->select(ProfileHelper::getXProfilePublicFields());
280 }])
281 ->where('status', 'active')
282 ->paginate();
283
284 return [
285 'members' => $spaceMembers,
286 'pending_count' => $pendingCount
287 ];
288 }
289
290 public function join(Request $request, $slug)
291 {
292 $space = Space::where('slug', $slug)->first();
293
294 if (!$space) {
295 return $this->sendError([
296 'message' => 'Space not found'
297 ]);
298 }
299
300 $user = $this->getUser();
301
302 $membership = $space->getMembership(get_current_user_id());
303
304 if ($membership) {
305 return $this->sendError([
306 'message' => 'You are already a member of this space. Please reload this page'
307 ]);
308 }
309
310 $roles = $user->getCommunityRoles();
311
312 if (!$roles && $space->privacy == 'secret') {
313 return $this->sendError([
314 'message' => 'You are not allowed to join this space'
315 ]);
316 }
317
318 $status = 'active';
319 if (!$roles) {
320 if ($space->privacy != 'public') {
321 $status = apply_filters('fluent_community/space/join_status_for_private', 'pending', $space, $user);
322 }
323 $role = 'member';
324 } else {
325 $role = $user->isCommunityAdmin() ? 'admin' : 'moderator';
326 }
327
328 $space->members()->attach(get_current_user_id(), [
329 'role' => $role,
330 'status' => $status
331 ]);
332
333 $space->membership = $space->getMembership(get_current_user_id());
334
335 if ($status == 'pending') {
336 do_action('fluent_community/space/join_requested', $space, $user->ID, 'self');
337 } else {
338 do_action('fluent_community/space/joined', $space, $user->ID, 'self');
339 }
340
341 $user->cacheAccessSpaces();
342
343 return [
344 'message' => ($status == 'active') ? __('You have joined this Space', 'fluent-community') : __('Your join request has been sent to the Space admin', 'fluent-community'),
345 'membership' => $space->membership
346 ];
347 }
348
349 public function leave(Request $request, $slug)
350 {
351 $user = $this->getUser(true);
352 $space = Space::where('slug', $slug)->first();
353
354 if (!$space) {
355 return $this->sendError([
356 'message' => 'Space not found'
357 ]);
358 }
359
360 $membership = $space->getMembership($user->ID);
361
362 if (!$membership) {
363 return $this->sendError([
364 'message' => 'You are not a member of this community'
365 ]);
366 }
367
368 Helper::removeFromSpace($space, $user->ID, 'self');
369
370 return [
371 'message' => __('You have left this space', 'fluent-community')
372 ];
373 }
374
375 public function delete(Request $request, $slug)
376 {
377 $space = Space::where('slug', $slug)->first();
378
379 if (!$space) {
380 return $this->sendError([
381 'message' => 'Space not found'
382 ]);
383 }
384
385 if (!Helper::isSiteAdmin()) {
386 return $this->sendError([
387 'message' => 'You are not allowed to delete this community'
388 ]);
389 }
390
391 do_action('fluent_community/space/before_delete', $space);
392
393 Comment::whereHas('post', function ($q) use ($space) {
394 $q->where('space_id', $space->id);
395 })->delete();
396
397 Reaction::whereHas('feed', function ($q) use ($space) {
398 $q->where('space_id', $space->id);
399 })->delete();
400
401 Feed::where('space_id', $space->id)->delete();
402
403 SpaceUserPivot::where('space_id', $space->id)->delete();
404
405 $spaceId = $space->id;
406 $space->delete();
407
408 do_action('fluent_community/space/deleted', $spaceId);
409
410 return [
411 'message' => __('Space has been deleted successfully', 'fluent-community')
412 ];
413 }
414
415 public function addMember(Request $request, $slug)
416 {
417 $space = Space::where('slug', $slug)->first();
418
419 if (!$space) {
420 return $this->sendError([
421 'message' => 'Space not found'
422 ]);
423 }
424
425 $this->validate($request->all(), [
426 'user_id' => 'required|exists:users,ID'
427 ]);
428
429 $userId = $request->get('user_id');
430 $targetUser = User::findOrFail($userId);
431 $xprofile = $targetUser->syncXProfile();
432
433 if ($xprofile && $xprofile->status != 'active') {
434 return $this->sendError([
435 'message' => __('Selected user is not active', 'fluent-community')
436 ]);
437 }
438
439 $admin = User::find(get_current_user_id());
440 $admin->verifySpacePermission('can_add_member', $space);
441
442 $pivot = SpaceUserPivot::bySpace($space->id)
443 ->byUser($userId)
444 ->first();
445
446 $role = $request->get('role', 'member');
447
448 if ($pivot) {
449 if ($pivot->status == 'active') {
450 if ($role != $pivot->role) {
451 $pivot->role = $role;
452 $pivot->save();
453
454 do_action('fluent_community/space/member/role_updated', $space, $pivot);
455
456 return [
457 'message' => 'Member role updated'
458 ];
459 }
460
461 return $this->sendError([
462 'message' => 'Selected user is already a member of this community'
463 ]);
464 }
465
466 $pivot->status = 'active';
467 $pivot->save();
468 do_action('fluent_community/space/joined', $space, $userId, 'approved');
469
470 if ($role != 'member') {
471 do_action('fluent_community/space/member/role_updated', $space, $pivot);
472 }
473
474 return [
475 'message' => 'Member approved'
476 ];
477 }
478
479 $space->members()->attach($userId, [
480 'role' => $role,
481 'status' => 'active'
482 ]);
483
484 $targetUser->cacheAccessSpaces();
485
486 do_action('fluent_community/space/joined', $space, $userId, 'by_admin');
487
488 return [
489 'message' => 'User has been added to this community'
490 ];
491 }
492
493 public function removeMember(Request $request, $slug)
494 {
495 $space = Space::where('slug', $slug)->first();
496
497 if (!$space) {
498 return $this->sendError([
499 'message' => 'Space not found'
500 ]);
501 }
502
503 $userId = $request->get('user_id');
504
505 $admin = User::find(get_current_user_id());
506 $admin->verifySpacePermission('can_remove_member', $space);
507
508 $pivot = SpaceUserPivot::bySpace($space->id)
509 ->byUser($userId)
510 ->first();
511
512 if (!$pivot) {
513 return $this->sendError([
514 'message' => 'Selected user is not a member of this community'
515 ]);
516 }
517
518 $pivot->delete();
519
520 $targetUser = User::find($userId);
521
522 if ($targetUser) {
523 $targetUser->cacheAccessSpaces();
524 }
525
526 do_action('fluent_community/space/user_left', $space, $userId, 'by_admin');
527
528 return [
529 'message' => 'User has been removed from this community'
530 ];
531 }
532
533 public function getOtherUsers(Request $request)
534 {
535 $currentUser = $this->getUser(true);
536
537 $this->validate($request->all(), [
538 'space_id' => 'required|exists:fcom_spaces,id'
539 ]);
540
541 $isMod = $currentUser->isCommunityModerator() && current_user_can('list_users');
542
543 $spaceId = $request->get('space_id');
544
545 $selects = ['ID', 'display_name'];
546
547 if ($isMod) {
548 $selects[] = 'user_email';
549 }
550
551 $users = User::whereDoesntHave('spaces', function ($q) use ($spaceId) {
552 return $q->where('space_id', $spaceId);
553 })
554 ->select($selects)
555 ->searchBy($request->get('search'))
556 ->paginate();
557
558 return [
559 'users' => $users
560 ];
561 }
562
563 public function updateLinks(Request $request, $slug)
564 {
565 $space = Space::where('slug', $slug)->first();
566
567 if (!$space) {
568 return $this->sendError([
569 'message' => 'Space not found'
570 ]);
571 }
572
573 $space->verifyUserPermisson($this->getUser(), 'community_admin');
574
575 $links = $request->get('links', []);
576
577 $links = array_map(function ($link) {
578 return CustomSanitizer::santizeLinkItem($link);
579 }, $links);
580
581 $settings = $space->settings;
582 $settings['links'] = $links;
583 $space->settings = $settings;
584 $space->save();
585
586 return [
587 'message' => __('Links has been updated for the space', 'fluent-community'),
588 'links' => $links
589 ];
590 }
591
592 public function getSpaceGroups(Request $request)
593 {
594 $user = $this->getUser(true);
595 if (!$user->isCommunityModerator()) {
596 return $this->sendError([
597 'message' => 'You are not allowed to create space group'
598 ]);
599 }
600
601 $user = $this->getUser();
602
603 $groups = Helper::getAllCommunityGroups($user, false);
604
605 foreach ($groups as $group) {
606 foreach ($group->spaces as $space) {
607 $space->permalink = $space->getPermalink();
608 }
609 }
610
611 return [
612 'groups' => $groups
613 ];
614 }
615
616 public function createSpaceGroup(Request $request)
617 {
618 $user = $this->getUser(true);
619 if (!$user->isCommunityModerator()) {
620 return $this->sendError([
621 'message' => 'You are not allowed to create space group'
622 ]);
623 }
624
625 $data = $request->all();
626
627 $this->validate($data, [
628 'title' => 'required|unique:fcom_spaces,title',
629 'slug' => 'required|unique:fcom_spaces,slug'
630 ]);
631
632
633 $formattedData = [
634 'title' => sanitize_text_field($data['title']),
635 'slug' => sanitize_title($data['slug']),
636 'description' => sanitize_textarea_field($data['description']),
637 'status' => 'active',
638 'type' => 'space_group',
639 'settings' => [
640 'always_show_spaces' => Arr::get($data, 'settings.always_show_spaces', 'yes'),
641 ],
642 'serial' => SpaceGroup::max('serial') + 1
643 ];
644
645 $group = SpaceGroup::create($formattedData);
646
647 return [
648 'message' => __('Space group has been created successfully', 'fluent-community'),
649 'group' => $group
650 ];
651 }
652
653 public function updateSpaceGroup(Request $request, $groupId)
654 {
655 $user = $this->getUser();
656 if (!$user || !$user->isCommunityModerator()) {
657 return $this->sendError([
658 'message' => 'You are not allowed to create space group'
659 ]);
660 }
661
662 $group = SpaceGroup::findOrFail($groupId);
663 $data = $request->all();
664
665 $this->validate($data, [
666 'title' => 'required'
667 ]);
668
669 $taken = BaseSpace::where('title', $data['title'])
670 ->where('id', '!=', $group->id)
671 ->first();
672
673 if ($taken) {
674 return $this->sendError([
675 'message' => 'The title is already taken. Please use a different title'
676 ]);
677 }
678
679 $formattedData = [
680 'title' => sanitize_text_field($data['title']),
681 'description' => sanitize_textarea_field($data['description']),
682 'status' => 'active',
683 'type' => 'space_group',
684 'settings' => [
685 'always_show_spaces' => Arr::get($data, 'settings.always_show_spaces', 'yes'),
686 ]
687 ];
688
689 $group->fill($formattedData)->save();
690
691 return [
692 'message' => __('Space group has been created updated', 'fluent-community'),
693 'group' => $group
694 ];
695 }
696
697 public function deleteSpaceGroup(Request $request, $groupId)
698 {
699
700 $user = $this->getUser();
701 if (!$user || !$user->isCommunityModerator()) {
702 return $this->sendError([
703 'message' => 'You are not allowed to create space group'
704 ]);
705 }
706
707 $group = SpaceGroup::findOrFail($groupId);
708
709 if (!$group->spaces->isEmpty()) {
710 return $this->sendError([
711 'message' => 'You can not delete this group. It has spaces'
712 ]);
713 }
714
715 $group->delete();
716
717 return [
718 'message' => __('Space group has been deleted successfully', 'fluent-community')
719 ];
720 }
721
722 public function updateSpaceGroupIndexes(Request $request)
723 {
724 $indexes = $request->get('indexes', []);
725
726 foreach ($indexes as $groupId => $indexNumber) {
727 $group = SpaceGroup::findOrFail($groupId);
728 $group->update([
729 'serial' => $indexNumber + 1
730 ]);
731 }
732
733 return [
734 'message' => __('Space group indexes has been updated', 'fluent-community')
735 ];
736
737 }
738
739 public function updateSpaceIndexes(Request $request)
740 {
741 $indexes = $request->get('indexes', []);
742
743 foreach ($indexes as $index => $spaceId) {
744 $space = BaseSpace::withoutGlobalScopes()->findOrFail($spaceId);
745 $space->update([
746 'serial' => $index + 1
747 ]);
748 }
749
750 return [
751 'message' => __('Space indexes has been updated', 'fluent-community')
752 ];
753 }
754
755 public function moveSpace(Request $request)
756 {
757 $spaceId = $request->getSafe('space_id', 'intval');
758 $groupId = $request->getSafe('group_id', 'intval');
759
760 $space = BaseSpace::withoutGlobalScopes()->findOrFail($spaceId);
761 $group = SpaceGroup::findOrFail($groupId);
762
763 $space->update([
764 'parent_id' => $groupId
765 ]);
766
767 return [
768 'message' => __('Space has been moved successfully', 'fluent-community')
769 ];
770 }
771
772 public function getLockScreenSettings(Request $request, $spaceSlug)
773 {
774 $space = Space::where('slug', $spaceSlug)->firstOrFail();
775 $lockscreen = $space->getLockscreen();
776
777 return [
778 'lockscreen' => $lockscreen
779 ];
780 }
781
782 public function updateLockscreenSettings(Request $request, $spaceSlug)
783 {
784 $space = Space::where('slug', $spaceSlug)->firstOrFail();
785
786 $settingFields = $request->get('lockscreen', []);
787
788 $formattedFields = LockscreenService::formatLockscreenFields($settingFields);
789
790 $space->setLockscreen($formattedFields);
791
792 return [
793 'message' => 'Lockscreen settings has been updated successfully.',
794 'community' => $space
795 ];
796 }
797 }
798