PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.10.01
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.10.01
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
← All changes | app/Http/Controllers/SpaceController.php +112 -21 2.4.012.10.01 View file →
@@ -53,8 +53,14 @@
53 53 'slug' => 'unique:fcom_spaces,slug',
54 54 'privacy' => 'required|in:public,private,secret'
55 55 ]);
56 56
57 + if (Arr::get($data, 'settings.topic_required') === 'yes' && !array_filter((array)Arr::get($data, 'topic_ids', []))) {
58 + return $this->sendError([
59 + 'message' => __('Please select at least one topic when members are required to select a topic.', 'fluent-community')
60 + ]);
61 + }
62 +
57 63 $spaceGroup = null;
58 64 if (!empty($data['parent_id'])) {
59 65 $spaceGroup = SpaceGroup::findOrFail($data['parent_id']);
60 66 $serial = BaseSpace::query()->withoutGlobalScopes()->where('parent_id', $spaceGroup->id)->max('serial') + 1;
@@ -153,9 +159,10 @@
153 159 $q->where('user_id', get_current_user_id());
154 160 }])
155 161 ->where(function ($q) {
156 162 $q->whereHas('space_pivot', function ($q) {
157 - $q->where('user_id', get_current_user_id());
163 + $q->where('user_id', get_current_user_id())
164 + ->where('status', 'active');
158 165 })
159 166 ->orWhereIn('privacy', ['public', 'private']);
160 167 })
161 168 ->when($type == 'joined', function ($q) {
@@ -179,8 +186,10 @@
179 186
180 187 $memberCounts = $this->getActiveMemberCounts($spaces->pluck('id')->toArray());
181 188
182 189 foreach ($spaces as $space) {
190 + $space->description_rendered = wpautop($space->description);
191 +
183 192 $shouldHideMembersCount = Arr::get($space->settings, 'hide_members_count') == 'yes';
184 193 $canViewMembers = $currentUser && $space->verifyUserPermisson($currentUser, 'can_view_members', false);
185 194
186 195 if ($shouldHideMembersCount && !$canViewMembers) {
@@ -188,9 +197,8 @@
188 197 continue;
189 198 }
190 199
191 200 $space->members_count = (int)Arr::get($memberCounts, $space->id, 0);
192 - $space->description_rendered = wpautop($space->description);
193 201 }
194 202
195 203 $data = [
196 204 'spaces' => $spaces,
@@ -201,11 +209,23 @@
201 209 }
202 210
203 211 public function getAllSpaces(Request $request)
204 212 {
205 - $spaces = Space::paginate();
213 + $currentUser = $this->getUser();
206 214
207 - $currentUser = $this->getUser();
215 + $spacesQuery = Space::query();
216 +
217 + if (!($currentUser && $currentUser->isCommunityModerator())) {
218 + $spacesQuery->where(function ($q) {
219 + $q->whereHas('space_pivot', function ($q) {
220 + $q->where('user_id', get_current_user_id())
221 + ->where('status', 'active');
222 + })
223 + ->orWhereIn('privacy', ['public', 'private']);
224 + });
225 + }
226 + $spaces = $spacesQuery->paginate();
227 +
208 228 $memberCounts = $this->getActiveMemberCounts($spaces->pluck('id')->toArray());
209 229
210 230 foreach ($spaces as $space) {
211 231 $shouldHideMembersCount = Arr::get($space->settings, 'hide_members_count') == 'yes';
@@ -229,17 +249,18 @@
229 249
230 250 public function getBySlug(Request $request, $spaceSlug)
231 251 {
232 252 $user = $this->getUser();
233 - $space = Space::where('slug', $spaceSlug)
234 - ->firstOrFail();
253 + $space = Space::where('slug', $spaceSlug)->first();
235 254
236 255 $userId = $user ? $user->ID : null;
237 - if ($space->privacy == 'secret' && !$space->getMembership($userId) && !$space->isAdmin($userId, true)) {
256 +
257 + // A hidden secret space must be indistinguishable from a non-existent one, so its
258 + // existence cannot be enumerated by slug. Both return an identical 404.
259 + if (!$space || ($space->privacy == 'secret' && !$space->getMembership($userId) && !$space->isAdmin($userId, true))) {
238 260 return $this->sendError([
239 - 'message' => __('You are not allowed to view this space', 'fluent-community'),
240 - 'error_type' => 'restricted'
241 - ]);
261 + 'message' => __('Space not found', 'fluent-community')
262 + ], 404);
242 263 }
243 264
244 265 $space = $space->formatSpaceData($user);
245 266
@@ -264,8 +285,14 @@
264 285 }
265 286
266 287 $data = $request->get('data', []);
267 288
289 + if (Arr::has($data, 'title') && !trim(sanitize_text_field(Arr::get($data, 'title', '')))) {
290 + return $this->sendError([
291 + 'message' => __('Space title is required.', 'fluent-community')
292 + ]);
293 + }
294 +
268 295 if (!empty($data['slug'])) {
269 296 $taken = Space::where('slug', $data['slug'])
270 297 ->where('id', '!=', $space->id)
271 298 ->first();
@@ -276,8 +303,24 @@
276 303 ]);
277 304 }
278 305 }
279 306
307 + $topicRequired = Arr::has($data, 'settings.topic_required')
308 + ? Arr::get($data, 'settings.topic_required')
309 + : Arr::get($space->settings, 'topic_required');
310 +
311 + if ($topicRequired === 'yes') {
312 + $topicIds = Arr::has($data, 'topic_ids')
313 + ? (array)Arr::get($data, 'topic_ids', [])
314 + : array_column(Utility::getTopicsBySpaceId($space->id), 'id');
315 +
316 + if (!array_filter($topicIds)) {
317 + return $this->sendError([
318 + 'message' => __('Please select at least one topic when members are required to select a topic.', 'fluent-community')
319 + ]);
320 + }
321 + }
322 +
280 323 $mediaTypes = ['cover_photo', 'logo'];
281 324 foreach ($mediaTypes as $type) {
282 325 if (!empty($data[$type])) {
283 326 $media = Helper::getMediaFromUrl($data[$type]);
@@ -344,8 +387,9 @@
344 387 }
345 388
346 389 public function getMembers(Request $request, $slug)
347 390 {
391 + /** @var Space $space */
348 392 $space = Space::where('slug', $slug)
349 393 ->firstOrFail();
350 394
351 395 $user = $this->getUser();
@@ -383,20 +427,37 @@
383 427 ], $pendingRequests, $request->all());
384 428 }
385 429 }
386 430
431 + $defaultDirections = [
432 + 'last_activity' => 'DESC',
433 + 'display_name' => 'ASC',
434 + 'created_at' => 'DESC',
435 + ];
436 +
437 + $sortBy = $request->getSafe('sort_by', 'sanitize_text_field', 'created_at');
438 + $sortColumn = in_array($sortBy, array_keys($defaultDirections), true) ? $sortBy : 'created_at';
439 + $sortDir = strtoupper($request->getSafe('sort_dir', 'sanitize_text_field', ''));
440 + $sortDirection = in_array($sortDir, ['ASC', 'DESC'], true) ? $sortDir : ($sortColumn === 'created_at' ? 'ASC' : $defaultDirections[$sortColumn]);
441 +
442 + $profileSort = $sortColumn !== 'created_at';
443 + $orderColumn = $profileSort ? 'fcom_xprofile.' . $sortColumn : 'fcom_space_user.created_at';
444 +
387 445 $spaceMembers = SpaceUserPivot::bySpace($space->id)
388 446 ->whereHas('xprofile', function ($q) use ($search) {
389 - return $q->searchBy($search)
390 - ->where('status', 'active');
447 + $q->searchBy($search)->where('status', 'active');
391 448 })
449 + ->where('fcom_space_user.status', 'active')
392 450 ->with(['xprofile' => function ($q) {
393 451 $q->select(ProfileHelper::getXProfilePublicFields());
394 452 }])
395 - ->where('status', 'active')
396 - ->orderBy('created_at', 'ASC')
453 + ->when($profileSort, function ($q) {
454 + $q->join('fcom_xprofile', 'fcom_xprofile.user_id', '=', 'fcom_space_user.user_id')
455 + ->select('fcom_space_user.*');
456 + })
457 + ->orderBy($orderColumn, $sortDirection)
397 458 ->paginate();
398 -
459 +
399 460 return apply_filters('fluent_community/space_members_api_response', [
400 461 'members' => $spaceMembers,
401 462 'pending_count' => $pendingCount
402 463 ], $spaceMembers, $request->all());
@@ -422,10 +483,11 @@
422 483 ]);
423 484 }
424 485
425 486 $roles = $user->getCommunityRoles();
487 + $isPrivileged = !!array_intersect($roles, ['admin', 'moderator']);
426 488
427 - if (!$roles && $space->privacy == 'secret') {
489 + if (!$isPrivileged && $space->privacy == 'secret') {
428 490 return $this->sendError([
429 491 'message' => __('You are not allowed to join this space', 'fluent-community')
430 492 ]);
431 493 }
@@ -430,9 +492,9 @@
430 492 ]);
431 493 }
432 494
433 495 $status = 'active';
434 - if (!$roles) {
496 + if (!$isPrivileged) {
435 497 if ($space->privacy != 'public') {
436 498 $status = apply_filters('fluent_community/space/join_status_for_private', 'pending', $space, $user);
437 499
438 500 if (!in_array($status, ['pending', 'active'])) {
@@ -691,8 +753,12 @@
691 753 $userIds = $userQuery->get()
692 754 ->pluck('ID')
693 755 ->toArray();
694 756
757 + if ($userIds) {
758 + update_meta_cache('user', $userIds);
759 + }
760 +
695 761 $users = User::select($selects)
696 762 ->whereIn('ID', $userIds)
697 763 ->paginate(100);
698 764
@@ -786,13 +852,28 @@
786 852 'title' => 'required|unique:fcom_spaces,title',
787 853 'slug' => 'required|unique:fcom_spaces,slug'
788 854 ]);
789 855
856 + $title = sanitize_text_field(Arr::get($data, 'title', ''));
857 + $slug = sanitize_title(Arr::get($data, 'slug', ''));
858 + $desc = sanitize_textarea_field(Arr::get($data, 'description', ''));
790 859
860 + if (!$title) {
861 + return $this->sendError([
862 + 'message' => __('Please enter a valid group title.', 'fluent-community')
863 + ]);
864 + }
865 +
866 + if (!$slug) {
867 + return $this->sendError([
868 + 'message' => __('Please enter a valid group slug.', 'fluent-community')
869 + ]);
870 + }
871 +
791 872 $formattedData = [
792 - 'title' => sanitize_text_field($data['title']),
793 - 'slug' => sanitize_title($data['slug']),
794 - 'description' => sanitize_textarea_field($data['description']),
873 + 'title' => $title,
874 + 'slug' => $slug,
875 + 'description' => $desc,
795 876 'status' => 'active',
796 877 'type' => 'space_group',
797 878 'settings' => [
798 879 'always_show_spaces' => Arr::get($data, 'settings.always_show_spaces', 'yes'),
@@ -913,9 +994,19 @@
913 994 }
914 995
915 996 public function getLockScreenSettings(Request $request, $spaceSlug)
916 997 {
917 - $space = Space::where('slug', $spaceSlug)->firstOrFail();
998 + /** @var Space $space */
999 + $space = Space::where('slug', $spaceSlug)->first();
1000 +
1001 + $userId = $this->getUser() ? $this->getUser()->ID : null;
1002 +
1003 + if (!$space || ($space->privacy == 'secret' && !$space->getMembership($userId) && !$space->isAdmin($userId, true))) {
1004 + return $this->sendError([
1005 + 'message' => __('Space not found', 'fluent-community')
1006 + ], 404);
1007 + }
1008 +
918 1009 $lockscreen = $space->getLockscreen();
919 1010
920 1011 $lockscreen = apply_filters('fluent_community/get_lockscreen_settings', $lockscreen, $space);
921 1012