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

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

961 lines 30.6 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\Space;
6 use FluentCommunity\App\Models\Feed;
7 use FluentCommunity\App\Models\BaseSpace;
8 use FluentCommunity\App\Models\SpaceGroup;
9 use FluentCommunity\App\Models\User;
10 use FluentCommunity\App\Services\CustomSanitizer;
11 use FluentCommunity\App\Services\Helper;
12 use FluentCommunity\App\Functions\Utility;
13 use FluentCommunity\App\Services\ProfileHelper;
14 use FluentCommunity\Framework\Http\Request\Request;
15 use FluentCommunity\App\Models\Comment;
16 use FluentCommunity\App\Models\Reaction;
17 use FluentCommunity\App\Models\SpaceUserPivot;
18 use FluentCommunity\Framework\Support\Arr;
19
20 class SpaceController extends Controller
21 {
22 public function get()
23 {
24 $spaces = Space::orderBy('title', 'ASC')
25 ->whereHas('space_pivot', function ($q) {
26 $q->where('user_id', get_current_user_id());
27 })
28 ->get();
29
30 $data = [
31 'spaces' => $spaces
32 ];
33
34 return apply_filters('fluent_community/spaces_api_response', $data, $this->request->all());
35 }
36
37 public function create(Request $request)
38 {
39 $currentUser = $this->getUser(true);
40
41 $data = $request->get('space', []);
42
43 $slug = Arr::get($data, 'slug') ?: Arr::get($data, 'title');
44
45 $slug = preg_replace('/[^a-zA-Z0-9-_]/', '', $slug);
46
47 $data['slug'] = sanitize_title($slug, '');
48 $data['title'] = sanitize_text_field(Arr::get($data, 'title'));
49 $data['privacy'] = sanitize_text_field(Arr::get($data, 'privacy'));
50
51 $this->validate($data, [
52 'title' => 'required',
53 'slug' => 'unique:fcom_spaces,slug',
54 'privacy' => 'required|in:public,private,secret'
55 ]);
56
57 $spaceGroup = null;
58 if (!empty($data['parent_id'])) {
59 $spaceGroup = SpaceGroup::findOrFail($data['parent_id']);
60 $serial = BaseSpace::query()->withoutGlobalScopes()->where('parent_id', $spaceGroup->id)->max('serial') + 1;
61 } else {
62 $serial = BaseSpace::query()->withoutGlobalScopes()->max('serial') + 1;
63 }
64
65 $settings = CustomSanitizer::santizeSpaceSettings(Arr::get($data, 'settings', []), $data['privacy']);
66
67 if (is_wp_error($settings)) {
68 return $this->sendError([
69 'message' => $settings->get_error_message()
70 ]);
71 }
72
73 $spaceData = apply_filters('fluent_community/space/create_data', [
74 'title' => sanitize_text_field($data['title']),
75 'slug' => $data['slug'],
76 'privacy' => $data['privacy'],
77 'description' => sanitize_textarea_field(Arr::get($data, 'description', '')),
78 'settings' => $settings,
79 'parent_id' => $spaceGroup ? $spaceGroup->id : null,
80 'serial' => $serial ?: 1
81 ]);
82
83 $ogImage = Arr::get($data, 'settings.og_image', '');
84 $ogMedia = null;
85 if ($ogImage) {
86 $ogMedia = Helper::getMediaFromUrl($ogImage);
87 if ($ogMedia && !$ogMedia->is_active) {
88 $spaceData['settings']['og_image'] = $ogMedia->public_url;
89 }
90 }
91
92 $space = Space::create($spaceData);
93 if ($ogMedia && !$ogMedia->is_active) {
94 $ogMedia->update([
95 'is_active' => true,
96 'user_id' => get_current_user_id(),
97 'sub_object_id' => $space->id,
98 'object_source' => 'space_og_image'
99 ]);
100 }
101
102 $imageTypes = ['cover_photo', 'logo'];
103 $metaData = [];
104 foreach ($imageTypes as $type) {
105 if (!empty($data[$type])) {
106 $media = Helper::getMediaFromUrl($data[$type]);
107 if (!$media || $media->is_active) {
108 continue;
109 }
110 $metaData[$type] = $media->public_url;
111 $media->update([
112 'is_active' => true,
113 'user_id' => get_current_user_id(),
114 'sub_object_id' => $space->id,
115 'object_source' => 'space_' . $type
116 ]);
117 }
118 }
119
120 if ($metaData) {
121 $space->updateCustomData($metaData, false);
122 }
123
124 $space->members()->attach(get_current_user_id(), [
125 'role' => 'admin'
126 ]);
127
128 if (Arr::has($data, 'topic_ids')) {
129 $topicsConfig = Helper::getTopicsConfig();
130 $topicIds = (array)Arr::get($data, 'topic_ids', []);
131 $topicIds = array_slice($topicIds, 0, $topicsConfig['max_topics_per_space']);
132 $space->syncTopics($topicIds);
133 }
134
135 $currentUser->cacheAccessSpaces();
136 do_action('fluent_community/space/created', $space, $data);
137
138 return [
139 'message' => __('Space has been created successfully', 'fluent-community'),
140 'space' => $space
141 ];
142 }
143
144 public function discover(Request $request)
145 {
146 $start = microtime(true);
147 $currentUser = $this->getUser();
148 $type = $request->getSafe('type');
149 $search = $request->getSafe('search');
150 $sortBy = $request->getSafe('sort_by', 'sanitize_text_field', 'alphabetical');
151
152 $spaces = Space::with(['space_pivot' => function ($q) {
153 $q->where('user_id', get_current_user_id());
154 }])
155 ->where(function ($q) {
156 $q->whereHas('space_pivot', function ($q) {
157 $q->where('user_id', get_current_user_id());
158 })
159 ->orWhereIn('privacy', ['public', 'private']);
160 })
161 ->when($type == 'joined', function ($q) {
162 $q->whereHas('space_pivot', function ($q) {
163 $q->where('user_id', get_current_user_id());
164 });
165 })
166 ->when($search, function ($q) use ($search) {
167 $q->where('title', 'like', '%' . $search . '%');
168 })
169 ->when($sortBy == 'alphabetical', function ($q) {
170 $q->orderBy('title', 'ASC');
171 })
172 ->when($sortBy == 'oldest', function ($q) {
173 $q->orderBy('created_at', 'ASC');
174 })
175 ->when($sortBy == 'latest', function ($q) {
176 $q->orderBy('created_at', 'DESC');
177 })
178 ->paginate();
179
180 $memberCounts = $this->getActiveMemberCounts($spaces->pluck('id')->toArray());
181
182 foreach ($spaces as $space) {
183 $shouldHideMembersCount = Arr::get($space->settings, 'hide_members_count') == 'yes';
184 $canViewMembers = $currentUser && $space->verifyUserPermisson($currentUser, 'can_view_members', false);
185
186 if ($shouldHideMembersCount && !$canViewMembers) {
187 $space->members_count = 0;
188 continue;
189 }
190
191 $space->members_count = (int)Arr::get($memberCounts, $space->id, 0);
192 $space->description_rendered = wpautop($space->description);
193 }
194
195 $data = [
196 'spaces' => $spaces,
197 'execution_time' => microtime(true) - $start
198 ];
199
200 return apply_filters('fluent_community/spaces_api_response', $data, $request->all());
201 }
202
203 public function getAllSpaces(Request $request)
204 {
205 $spaces = Space::paginate();
206
207 $currentUser = $this->getUser();
208 $memberCounts = $this->getActiveMemberCounts($spaces->pluck('id')->toArray());
209
210 foreach ($spaces as $space) {
211 $shouldHideMembersCount = Arr::get($space->settings, 'hide_members_count') == 'yes';
212 $canViewMembers = $currentUser && $space->verifyUserPermisson($currentUser, 'can_view_members', false);
213
214 if ($shouldHideMembersCount && !$canViewMembers) {
215 $space->members_count = 0;
216 continue;
217 }
218
219 $space->members_count = (int)Arr::get($memberCounts, $space->id, 0);
220
221 $space->formatSpaceData($currentUser);
222 do_action_ref_array('fluent_community/space', [&$space]);
223 }
224
225 return apply_filters('fluent_community/all_spaces_api_response', [
226 'spaces' => $spaces
227 ], $request->all());
228 }
229
230 public function getBySlug(Request $request, $spaceSlug)
231 {
232 $user = $this->getUser();
233 $space = Space::where('slug', $spaceSlug)
234 ->firstOrFail();
235
236 $userId = $user ? $user->ID : null;
237 if ($space->privacy == 'secret' && !$space->getMembership($userId) && !$space->isAdmin($userId, true)) {
238 return $this->sendError([
239 'message' => __('You are not allowed to view this space', 'fluent-community'),
240 'error_type' => 'restricted'
241 ]);
242 }
243
244 $space = $space->formatSpaceData($user);
245
246 do_action_ref_array('fluent_community/space', [&$space]);
247
248 $data = [
249 'space' => $space
250 ];
251
252 return apply_filters('fluent_community/space_api_response', $data, $request->all());
253 }
254
255 public function patchBySlug(Request $request, $slug)
256 {
257 $space = Space::where('slug', $slug)
258 ->first();
259
260 if (!$space) {
261 return $this->sendError([
262 'message' => __('Space not found', 'fluent-community')
263 ]);
264 }
265
266 $data = $request->get('data', []);
267
268 if (!empty($data['slug'])) {
269 $taken = Space::where('slug', $data['slug'])
270 ->where('id', '!=', $space->id)
271 ->first();
272
273 if ($taken) {
274 return $this->sendError([
275 'message' => __('Slug is already taken. Please use a different slug', 'fluent-community')
276 ]);
277 }
278 }
279
280 $mediaTypes = ['cover_photo', 'logo'];
281 foreach ($mediaTypes as $type) {
282 if (!empty($data[$type])) {
283 $media = Helper::getMediaFromUrl($data[$type]);
284 if (!$media || $media->is_active) {
285 unset($data[$type]);
286 continue;
287 }
288
289 $data[$type] = $media->public_url;
290
291 $media->update([
292 'is_active' => true,
293 'user_id' => get_current_user_id(),
294 'sub_object_id' => $space->id,
295 'object_source' => 'space_' . $type
296 ]);
297 } else if (isset($data[$type])) {
298 $data[$type] = '';
299 }
300 }
301
302 $data = apply_filters('fluent_community/space/update_data', $data, $space);
303
304 if (isset($data['parent_id']) && !$data['parent_id']) {
305 $data['parent_id'] = '';
306 }
307
308 $space = $space->updateCustomData($data, true);
309
310 if (is_wp_error($space)) {
311 return $this->sendError([
312 'message' => $space->get_error_message()
313 ]);
314 }
315
316 if (Arr::has($data, 'topic_ids')) {
317 $topicsConfig = Helper::getTopicsConfig();
318 $topicIds = (array)Arr::get($data, 'topic_ids', []);
319 $topicIds = array_slice($topicIds, 0, $topicsConfig['max_topics_per_space']);
320 $space->syncTopics($topicIds);
321 }
322
323 do_action('fluent_community/space/updated', $space, $data);
324 $slugUpdated = $slug != $space->slug;
325
326 $metaSettings = $request->get('meta_settings', []);
327 if($metaSettings) {
328 foreach ($metaSettings as $metaProvider => $metaData) {
329 do_action('fluent_community/space/update_meta_settings_'.$metaProvider, $metaData, $space);
330 }
331 }
332
333 return [
334 'message' => __('Settings have been updated', 'fluent-community'),
335 'redirect_url' => $slugUpdated ? $space->getPermalink() : ''
336 ];
337 }
338
339 public function patchById(Request $request, $id)
340 {
341 $space = Space::findOrFail($id);
342
343 return $this->patchBySlug($request, $space->slug);
344 }
345
346 public function getMembers(Request $request, $slug)
347 {
348 $space = Space::where('slug', $slug)
349 ->firstOrFail();
350
351 $user = $this->getUser();
352
353 if (!$space->verifyUserPermisson($user, 'can_view_members', false)) {
354 return $this->sendError([
355 'message' => __('You are not allowed to view members of this space', 'fluent-community'),
356 'permission_failed' => true
357 ]);
358 }
359
360 $search = $request->getSafe('search', 'sanitize_text_field');
361
362 $pendingCount = 0;
363 if ($user && $user->can('can_add_member', $space)) {
364 $pendingCount = SpaceUserPivot::bySpace($space->id)
365 ->where('status', 'pending')
366 ->count();
367
368 if ($request->get('status') == 'pending') {
369 $pendingRequests = SpaceUserPivot::bySpace($space->id)
370 ->whereHas('xprofile', function ($q) use ($search) {
371 return $q->searchBy($search)
372 ->where('status', 'active');
373 })
374 ->with(['xprofile' => function ($q) {
375 $q->select(ProfileHelper::getXProfilePublicFields());
376 }])
377 ->where('status', 'pending')
378 ->paginate();
379
380 return apply_filters('fluent_community/space_members_api_response', [
381 'members' => $pendingRequests,
382 'pending_count' => $pendingCount
383 ], $pendingRequests, $request->all());
384 }
385 }
386
387 $spaceMembers = SpaceUserPivot::bySpace($space->id)
388 ->whereHas('xprofile', function ($q) use ($search) {
389 return $q->searchBy($search)
390 ->where('status', 'active');
391 })
392 ->with(['xprofile' => function ($q) {
393 $q->select(ProfileHelper::getXProfilePublicFields());
394 }])
395 ->where('status', 'active')
396 ->orderBy('created_at', 'ASC')
397 ->paginate();
398
399 return apply_filters('fluent_community/space_members_api_response', [
400 'members' => $spaceMembers,
401 'pending_count' => $pendingCount
402 ], $spaceMembers, $request->all());
403 }
404
405 public function join(Request $request, $slug)
406 {
407 $space = Space::where('slug', $slug)->first();
408
409 if (!$space) {
410 return $this->sendError([
411 'message' => __('Space not found', 'fluent-community')
412 ]);
413 }
414
415 $user = $this->getUser();
416
417 $membership = $space->getMembership(get_current_user_id());
418
419 if ($membership) {
420 return $this->sendError([
421 'message' => __('You are already a member of this space. Please reload this page', 'fluent-community')
422 ]);
423 }
424
425 $roles = $user->getCommunityRoles();
426
427 if (!$roles && $space->privacy == 'secret') {
428 return $this->sendError([
429 'message' => __('You are not allowed to join this space', 'fluent-community')
430 ]);
431 }
432
433 $status = 'active';
434 if (!$roles) {
435 if ($space->privacy != 'public') {
436 $status = apply_filters('fluent_community/space/join_status_for_private', 'pending', $space, $user);
437
438 if (!in_array($status, ['pending', 'active'])) {
439 $status = 'pending';
440 }
441 }
442 $role = 'member';
443 } else {
444 $role = $user->isCommunityAdmin() ? 'admin' : 'moderator';
445 }
446
447
448 $space->members()->attach(get_current_user_id(), [
449 'role' => $role,
450 'status' => $status
451 ]);
452
453 $space->membership = $space->getMembership(get_current_user_id());
454
455 if ($status == 'pending') {
456 do_action('fluent_community/space/join_requested', $space, $user->ID, 'self');
457 } else {
458 do_action('fluent_community/space/joined', $space, $user->ID, 'self');
459 }
460
461 $user->cacheAccessSpaces();
462
463 return [
464 'message' => ($status == 'active') ? __('You have joined this Space', 'fluent-community') : __('Your join request has been sent to the Space admin.', 'fluent-community'),
465 'membership' => $space->membership
466 ];
467 }
468
469 public function leave(Request $request, $slug)
470 {
471 $user = $this->getUser(true);
472 $space = Space::where('slug', $slug)->first();
473
474 if (!$space) {
475 return $this->sendError([
476 'message' => __('Space not found', 'fluent-community')
477 ]);
478 }
479
480 $membership = $space->getMembership($user->ID);
481
482 if (!$membership) {
483 return $this->sendError([
484 'message' => __('You are not a member of this community', 'fluent-community')
485 ]);
486 }
487
488 Helper::removeFromSpace($space, $user->ID, 'self');
489
490 return [
491 'message' => __('You have left this space', 'fluent-community')
492 ];
493 }
494
495 public function deleteBySlug(Request $request, $slug)
496 {
497 $space = Space::where('slug', $slug)->first();
498
499 if (!$space) {
500 return $this->sendError([
501 'message' => __('Space not found', 'fluent-community')
502 ]);
503 }
504
505 do_action('fluent_community/space/before_delete', $space);
506
507 Comment::whereHas('post', function ($q) use ($space) {
508 $q->where('space_id', $space->id);
509 })->delete();
510
511 Reaction::whereHas('feed', function ($q) use ($space) {
512 $q->where('space_id', $space->id);
513 })->delete();
514
515 Feed::where('space_id', $space->id)->delete();
516
517 SpaceUserPivot::where('space_id', $space->id)->delete();
518
519 $spaceId = $space->id;
520 $space->delete();
521
522 do_action('fluent_community/space/deleted', $spaceId);
523
524 return [
525 'message' => __('Space has been deleted successfully', 'fluent-community')
526 ];
527 }
528
529 public function deleteById(Request $request, $id)
530 {
531 $space = Space::findOrFail($id);
532
533 return $this->deleteBySlug($request, $space->slug);
534 }
535
536 public function addMember(Request $request, $slug)
537 {
538 $space = Space::where('slug', $slug)->first();
539
540 if (!$space) {
541 return $this->sendError([
542 'message' => __('Space not found', 'fluent-community')
543 ]);
544 }
545
546 $this->validate($request->all(), [
547 'user_id' => 'required|exists:users,ID'
548 ]);
549
550 $userId = $request->get('user_id');
551 $targetUser = User::findOrFail($userId);
552 $targetUser->syncXProfile();
553 $xprofile = $targetUser->xprofile;
554
555 if ($xprofile && $xprofile->status != 'active') {
556 return $this->sendError([
557 'message' => __('Selected user is not active', 'fluent-community')
558 ]);
559 }
560
561 $pivot = SpaceUserPivot::bySpace($space->id)
562 ->byUser($userId)
563 ->first();
564
565 $allowedRoles = ['member', 'moderator', 'admin'];
566 $requestedRole = $request->get('role', 'member');
567 $role = in_array($requestedRole, $allowedRoles, true) ? $requestedRole : 'member';
568
569 if ($pivot) {
570 if ($pivot->status == 'active') {
571 if ($role != $pivot->role) {
572 $pivot->role = $role;
573 $pivot->save();
574
575 do_action('fluent_community/space/member/role_updated', $space, $pivot);
576
577 return [
578 'message' => __('Member role updated', 'fluent-community')
579 ];
580 }
581
582 return $this->sendError([
583 'message' => __('Selected user is already a member of this community', 'fluent-community')
584 ]);
585 }
586
587 $pivot->status = 'active';
588 $pivot->save();
589 do_action('fluent_community/space/joined', $space, $userId, 'by_admin');
590
591 if ($role != 'member') {
592 do_action('fluent_community/space/member/role_updated', $space, $pivot);
593 }
594
595 return [
596 'message' => __('Member approved', 'fluent-community')
597 ];
598 }
599
600 $space->members()->attach($userId, [
601 'role' => $role,
602 'status' => 'active'
603 ]);
604
605 $targetUser->cacheAccessSpaces();
606
607 do_action('fluent_community/space/joined', $space, $userId, 'by_admin');
608
609 return [
610 'message' => __('User has been added to this Space', 'fluent-community')
611 ];
612 }
613
614 public function removeMember(Request $request, $slug)
615 {
616 $space = Space::where('slug', $slug)->first();
617
618 if (!$space) {
619 return $this->sendError([
620 'message' => __('Space not found', 'fluent-community')
621 ]);
622 }
623
624 $userId = $request->get('user_id');
625
626 $pivot = SpaceUserPivot::bySpace($space->id)
627 ->byUser($userId)
628 ->first();
629
630 if (!$pivot) {
631 return $this->sendError([
632 'message' => __('Selected user is not a member of this community', 'fluent-community')
633 ]);
634 }
635
636 $pivot->delete();
637
638 $targetUser = User::find($userId);
639
640 if ($targetUser) {
641 $targetUser->cacheAccessSpaces();
642 }
643
644 do_action('fluent_community/space/user_left', $space, $userId, 'by_admin');
645
646 return [
647 'message' => __('User has been removed from this community', 'fluent-community')
648 ];
649 }
650
651 public function getOtherUsers(Request $request)
652 {
653 $currentUser = $this->getUser(true);
654
655 $this->validate($request->all(), [
656 'space_id' => 'required|exists:fcom_spaces,id'
657 ]);
658
659 $isMod = $currentUser->isCommunityModerator() && current_user_can('list_users');
660
661 $spaceId = $request->get('space_id');
662 $space = Space::findOrFail($spaceId);
663
664 if (!$space->verifyUserPermisson($currentUser, 'can_add_member', false)) {
665 return $this->sendError([
666 'message' => __('You are not allowed to add members to this space', 'fluent-community')
667 ]);
668 }
669
670 $selects = ['ID', 'display_name'];
671 if ($isMod) {
672 $selects[] = 'user_email';
673 }
674
675 $userQuery = User::select(['ID'])
676 ->whereDoesntHave('space_pivot', function ($q) use ($space) {
677 $q->where('space_id', $space->id);
678 })
679 ->limit(100)
680 ->searchBy($request->getSafe('search'));
681
682 if (is_multisite()) {
683 global $wpdb;
684 $blogId = get_current_blog_id();
685 $blogPrefix = $wpdb->get_blog_prefix($blogId);
686 $userQuery->whereHas('usermeta', function ($q) use ($blogPrefix) {
687 $q->where('meta_key', $blogPrefix . 'capabilities');
688 });
689 }
690
691 $userIds = $userQuery->get()
692 ->pluck('ID')
693 ->toArray();
694
695 $users = User::select($selects)
696 ->whereIn('ID', $userIds)
697 ->paginate(100);
698
699 $data = [
700 'users' => $users
701 ];
702 return apply_filters('fluent_community/space_non_members_api_response', $data, $request->all());
703 }
704
705 public function updateLinks(Request $request, $slug)
706 {
707 $space = Space::where('slug', $slug)->first();
708
709 if (!$space) {
710 return $this->sendError([
711 'message' => __('Space not found', 'fluent-community')
712 ]);
713 }
714
715 $links = $request->get('links', []);
716
717 $links = array_map(function ($link) {
718 return CustomSanitizer::santizeLinkItem($link);
719 }, $links);
720
721 $settings = $space->settings;
722 $settings['links'] = $links;
723 $space->settings = $settings;
724 $space->save();
725
726 return [
727 'message' => __('Links have been updated for the space', 'fluent-community'),
728 'links' => $links
729 ];
730 }
731
732 public function getSpaceGroups(Request $request)
733 {
734 if ($request->get('options_only')) {
735 $groups = SpaceGroup::orderBy('serial', 'ASC')
736 ->select(['id', 'title'])
737 ->get();
738
739 return [
740 'groups' => $groups
741 ];
742 }
743
744 $user = $this->getUser();
745
746 $groups = Helper::getAllCommunityGroups($user, false);
747
748 foreach ($groups as $group) {
749 foreach ($group->spaces as $space) {
750 $space->permalink = $space->getPermalink();
751 if ($space->type === 'community') {
752 $space = $space->formatSpaceData($user);
753 } else {
754 $space->topics = Utility::getTopicsBySpaceId($space->id);
755 }
756 }
757 }
758
759 $orphanedSpaces = BaseSpace::withoutGlobalScopes()
760 ->whereNull('parent_id')
761 ->whereIn('type', ['community', 'course'])
762 ->orderBy('title', 'ASC')
763 ->get();
764
765 foreach ($orphanedSpaces as $space) {
766 $space->permalink = $space->getPermalink();
767 if ($space->type === 'community') {
768 $space = $space->formatSpaceData($user);
769 } else {
770 $space->topics = Utility::getTopicsBySpaceId($space->id);
771 }
772 }
773
774 $data = [
775 'groups' => $groups,
776 'orphaned_spaces' => $orphanedSpaces
777 ];
778 return apply_filters('fluent_community/space_groups_api_response', $data, $request->all());
779 }
780
781 public function createSpaceGroup(Request $request)
782 {
783 $data = $request->all();
784
785 $this->validate($data, [
786 'title' => 'required|unique:fcom_spaces,title',
787 'slug' => 'required|unique:fcom_spaces,slug'
788 ]);
789
790
791 $formattedData = [
792 'title' => sanitize_text_field($data['title']),
793 'slug' => sanitize_title($data['slug']),
794 'description' => sanitize_textarea_field($data['description']),
795 'status' => 'active',
796 'type' => 'space_group',
797 'settings' => [
798 'always_show_spaces' => Arr::get($data, 'settings.always_show_spaces', 'yes'),
799 ],
800 'serial' => SpaceGroup::max('serial') + 1
801 ];
802
803 $group = SpaceGroup::create($formattedData);
804
805 return [
806 'message' => __('Space group has been created successfully', 'fluent-community'),
807 'group' => $group
808 ];
809 }
810
811 public function updateSpaceGroup(Request $request, $groupId)
812 {
813 $group = SpaceGroup::findOrFail($groupId);
814 $data = $request->all();
815
816 $this->validate($data, [
817 'title' => 'required'
818 ]);
819
820 $taken = BaseSpace::where('title', $data['title'])
821 ->where('id', '!=', $group->id)
822 ->first();
823
824 if ($taken) {
825 return $this->sendError([
826 'message' => __('The title is already taken. Please use a different title', 'fluent-community')
827 ]);
828 }
829
830 $formattedData = [
831 'title' => sanitize_text_field($data['title']),
832 'description' => sanitize_textarea_field($data['description']),
833 'status' => 'active',
834 'type' => 'space_group',
835 'settings' => [
836 'always_show_spaces' => Arr::get($data, 'settings.always_show_spaces', 'yes'),
837 ]
838 ];
839
840 $group->fill($formattedData)->save();
841
842 return [
843 'message' => __('Space group has been updated', 'fluent-community'),
844 'group' => $group
845 ];
846 }
847
848 public function deleteSpaceGroup(Request $request, $groupId)
849 {
850 $group = SpaceGroup::findOrFail($groupId);
851
852 if (!$group->spaces->isEmpty()) {
853 return $this->sendError([
854 'message' => __('You cannot delete this group. It has spaces', 'fluent-community')
855 ]);
856 }
857
858 $group->delete();
859
860 return [
861 'message' => __('Space group has been deleted successfully', 'fluent-community')
862 ];
863 }
864
865 public function updateSpaceGroupIndexes(Request $request)
866 {
867 $indexes = $request->get('indexes', []);
868
869 foreach ($indexes as $groupId => $indexNumber) {
870 $group = SpaceGroup::findOrFail($groupId);
871 $group->update([
872 'serial' => $indexNumber + 1
873 ]);
874 }
875
876 return [
877 'message' => __('Space group indexes have been updated.', 'fluent-community')
878 ];
879
880 }
881
882 public function updateSpaceIndexes(Request $request)
883 {
884 $indexes = $request->get('indexes', []);
885
886 foreach ($indexes as $index => $spaceId) {
887 $space = BaseSpace::withoutGlobalScopes()->findOrFail($spaceId);
888 $space->update([
889 'serial' => $index + 1
890 ]);
891 }
892
893 return [
894 'message' => __('Space indexes have been updated.', 'fluent-community')
895 ];
896 }
897
898 public function moveSpace(Request $request)
899 {
900 $spaceId = $request->getSafe('space_id', 'intval');
901 $groupId = $request->getSafe('group_id', 'intval');
902
903 $space = BaseSpace::withoutGlobalScopes()->findOrFail($spaceId);
904 $group = SpaceGroup::findOrFail($groupId);
905
906 $space->update([
907 'parent_id' => $group->id
908 ]);
909
910 return [
911 'message' => __('Space has been moved successfully', 'fluent-community')
912 ];
913 }
914
915 public function getLockScreenSettings(Request $request, $spaceSlug)
916 {
917 $space = Space::where('slug', $spaceSlug)->firstOrFail();
918 $lockscreen = $space->getLockscreen();
919
920 $lockscreen = apply_filters('fluent_community/get_lockscreen_settings', $lockscreen, $space);
921
922 return [
923 'lockscreen' => $lockscreen
924 ];
925 }
926
927 public function getMetaSettings(Request $request, $spaceSlug)
928 {
929 $space = Space::where('slug', $spaceSlug)->firstOrFail();
930 $metaSettings = apply_filters('fluent_community/space/meta_fields', [], $space);
931
932 if (!$metaSettings) {
933 return [
934 'meta_settings' => null
935 ];
936 }
937
938 return [
939 'meta_settings' => $metaSettings
940 ];
941 }
942
943 private function getActiveMemberCounts($spaceIds)
944 {
945 if (!$spaceIds) {
946 return [];
947 }
948
949 return SpaceUserPivot::whereIn('space_id', $spaceIds)
950 ->where('status', 'active')
951 ->whereHas('xprofile', function ($q) {
952 $q->where('status', 'active');
953 })
954 ->whereHas('user')
955 ->selectRaw('space_id, COUNT(*) as total')
956 ->groupBy('space_id')
957 ->pluck('total', 'space_id')
958 ->toArray();
959 }
960 }
961