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 | Modules/Course/Http/Controllers/CourseController.php +393 -82 1.0.902.10.01 View file →
@@ -3,15 +3,18 @@
3 3 namespace FluentCommunity\Modules\Course\Http\Controllers;
4 4
5 5 use FluentCommunity\App\Http\Controllers\Controller;
6 6 use FluentCommunity\App\Models\SpaceUserPivot;
7 -use FluentCommunity\App\Models\User;
7 +use FluentCommunity\App\Services\Helper;
8 8 use FluentCommunity\App\Services\LockscreenService;
9 9 use FluentCommunity\Framework\Http\Request\Request;
10 +use FluentCommunity\Framework\Support\Arr;
10 11 use FluentCommunity\Modules\Course\Model\Course;
11 12 use FluentCommunity\Modules\Course\Model\CourseLesson;
12 13 use FluentCommunity\Modules\Course\Model\CourseTopic;
14 +use FluentCommunity\App\Services\FeedsHelper;
13 15 use FluentCommunity\Modules\Course\Services\CourseHelper;
16 +use FluentCommunity\Modules\Course\Services\LessonVideoGateService;
14 17
15 18 class CourseController extends Controller
16 19 {
17 20 public function getCourses(Request $request)
@@ -16,34 +19,44 @@
16 19 {
17 20 public function getCourses(Request $request)
18 21 {
19 22 $user = $this->getUser();
20 - $isModerator = $user && $user->isCommunityModerator();
23 + $isCourseCreator = $user && $user->hasCourseCreatorAccess();
24 + $enrolledIds = CourseHelper::getEnrolledCourseIds();
21 25
22 - if ($request->get('type') == 'enrolled') {
23 - $courses = Course::searchBy($request->get('search'))
24 - ->where('status', 'published')
25 - ->orderBy('title', 'ASC')
26 - ->byPostTopic($request->get('topic_slug'))
27 - ->whereIn('id', CourseHelper::getEnrolledCourseIds())
28 - ->paginate();
29 - } else {
30 - $courses = Course::searchBy($request->get('search'))
31 - ->when(!$isModerator, function ($q) {
26 + $search = $request->getSafe('search');
27 + $topicSlug = $request->getSafe('topic_slug');
28 + $isEnrolled = $request->getSafe('type') == 'enrolled';
29 + $sortBy = $request->getSafe('sort_by', 'sanitize_text_field', 'alphabetical');
30 +
31 + $courses = Course::searchBy($search)
32 + ->where(function ($q) use ($isCourseCreator, $isEnrolled, $user) {
33 + if ($isCourseCreator && !$isEnrolled) {
34 + $q->where('status', 'published')
35 + ->orWhere('created_by', $user->ID);
36 + } else {
32 37 $q->where('status', 'published');
33 - })
34 - ->byPostTopic($request->get('topic_slug'))
35 - ->orderBy('title', 'ASC')
36 - ->where(function ($q) {
37 - $q->whereIn('privacy', ['public', 'private']);
38 - if ($enrolledIds = CourseHelper::getEnrolledCourseIds()) {
39 - $q->orWhereIn('id', $enrolledIds);
40 - }
41 - })
42 - ->paginate();
43 - }
38 + }
39 + })
40 + ->byPostTopic($topicSlug)
41 + ->where(function ($q) use ($enrolledIds) {
42 + $q->whereIn('privacy', ['public', 'private']);
43 + $q->orWhereIn('id', $enrolledIds);
44 + })
45 + ->when($isEnrolled, function ($q) use ($enrolledIds) {
46 + $q->whereIn('id', $enrolledIds);
47 + })
48 + ->when($sortBy == 'alphabetical', function ($q) {
49 + $q->orderBy('title', 'ASC');
50 + })
51 + ->when($sortBy == 'oldest', function ($q) {
52 + $q->orderBy('created_at', 'ASC');
53 + })
54 + ->when($sortBy == 'latest', function ($q) {
55 + $q->orderBy('created_at', 'DESC');
56 + })
57 + ->paginate();
44 58
45 -
46 59 foreach ($courses as $course) {
47 60 $course->isEnrolled = CourseHelper::isEnrolled($course->id);
48 61 if ($course->isEnrolled) {
49 62 $course->progress = CourseHelper::getCourseProgress($course->id);
@@ -54,59 +67,168 @@
54 67 }
55 68
56 69 $course->sectionsCount = CourseTopic::where('space_id', $course->id)->count();
57 70 $course->lessonsCount = CourseLesson::where('space_id', $course->id)->count();
58 - $course->studentsCount = SpaceUserPivot::where('space_id', $course->id)->count();
71 + if (Arr::get($course->settings, 'hide_members_count') != 'yes') {
72 + $course->studentsCount = SpaceUserPivot::where('space_id', $course->id)->count();
73 + } else {
74 + $course->studentsCount = 0;
75 + }
76 +
77 + do_action_ref_array('fluent_community/course', [&$course]);
59 78 }
60 79
61 - return [
80 + $data = [
62 81 'courses' => $courses,
63 - 'course_categories' => $request->get('with_categories') ? CourseHelper::getCourseCategories() : []
82 + 'course_categories' => $request->get('with_categories') ? CourseHelper::getCourseCategories() : []
64 83 ];
84 +
85 + return apply_filters('fluent_community/courses_api_response', $data, $request->all());
65 86 }
66 87
67 88 public function getCourse(Request $request, $courseId)
68 89 {
69 90 $user = $this->getUser();
70 - $isModerator = $user && $user->isCommunityModerator();
71 91
72 - $course = Course::when(!$isModerator, function ($q) {
73 - $q->where('status', 'published');
74 - })->find($courseId);
92 + $course = Course::findOrFail($courseId);
93 + /** @var Course $course */
75 94
76 - if (!$course) {
95 + $isCourseCreator = $course->isCourseAdmin($user);
96 +
97 + if ($course->status !== 'published' && !$isCourseCreator) {
77 98 return $this->sendError([
78 - 'message' => 'Course not found. maybe the course is not published yet!'
99 + 'message' => __('Course not found. maybe the course is not published yet!', 'fluent-community')
79 100 ]);
80 101 }
81 102
82 - return $this->processCourse($course, $isModerator);
103 + $intendtedLessonSlug = $request->get('intended_lesson_slug');
104 +
105 + $data = $this->processCourse($course, $isCourseCreator, $intendtedLessonSlug);
106 +
107 + return apply_filters('fluent_community/get_course_api_response', $data, $request->all());
83 108 }
84 109
85 110 public function getCourseBySlug(Request $request, $slug)
86 111 {
87 112 $user = $this->getUser();
88 - $isModerator = $user && $user->isCommunityModerator();
89 113
90 - $course = Course::when(!$isModerator, function ($q) {
91 - $q->where('status', 'published');
92 - })->where('slug', $slug)->firstOrFail();
114 + $course = Course::where('slug', $slug)->firstOrFail();
115 + /** @var Course $course */
93 116
94 - if (!$course) {
117 + $isCourseCreator = $course->isCourseAdmin($user);
118 +
119 + if ($course->status !== 'published' && !$isCourseCreator) {
95 120 return $this->sendError([
96 - 'message' => 'Course not found. maybe the course is not published yet!'
121 + 'message' => __('Course not found. maybe the course is not published yet!', 'fluent-community')
97 122 ]);
98 123 }
99 124
100 - return $this->processCourse($course, $isModerator);
125 + $hideInstructorView = Arr::get($course->settings, 'hide_instructor_view') == 'yes';
126 + $showStudentCount = Arr::get($course->settings, 'show_instructor_students_count') == 'yes';
127 + if (!$hideInstructorView) {
128 + $course->load(['creator']);
129 + if ($course->creator) {
130 + $creatorCourseIds = Course::where('created_by', $course->creator->user_id)->pluck('id');
131 + $course->creator->total_courses = count($creatorCourseIds);
132 + if ($showStudentCount) {
133 + $course->creator->total_students = SpaceUserPivot::whereIn('space_id', $creatorCourseIds)->distinct('user_id')->count('user_id');
134 + }
135 + if ($course->creator->short_description) {
136 + $course->creator->short_description_rendered = wp_kses_post(FeedsHelper::mdToHtml($course->creator->short_description));
137 + }
138 + }
139 + }
140 +
141 + $intendtedLessonSlug = $request->get('intended_lesson_slug');
142 +
143 + $data = $this->processCourse($course, $isCourseCreator, $intendtedLessonSlug);
144 +
145 + return apply_filters('fluent_community/course_api_response', $data, $request->all());
101 146 }
102 147
103 - private function processCourse($course, $isModerator)
148 + public function getLessonBySlug(Request $request, $courseSlug, $lessonSlug)
104 149 {
150 + $user = $this->getUser();
151 +
152 + /** @var Course $course */
153 + $course = Course::where('slug', $courseSlug)->firstOrFail();
154 +
155 + $isCourseCreator = $course->isCourseAdmin($user);
156 +
157 + if ($course->status !== 'published' && !$isCourseCreator) {
158 + return $this->sendError([
159 + 'message' => __('Course not found. maybe the course is not published yet!', 'fluent-community')
160 + ]);
161 + }
162 +
163 + $lesson = CourseLesson::where('space_id', $course->id)
164 + ->where('slug', $lessonSlug)
165 + ->when(!$isCourseCreator, function ($q) {
166 + $q->where('status', 'published');
167 + })
168 + ->with(['topic'])
169 + ->firstOrFail();
170 +
171 + if (!$lesson || !$lesson->topic) {
172 + return $this->sendError([
173 + 'message' => __('Lesson not found. maybe the lesson is not published yet!', 'fluent-community')
174 + ]);
175 + }
176 +
177 + $enrollment = CourseHelper::getCourseEnrollment($course->id);
178 +
179 + if ($course->privacy == 'secret' && !$enrollment && !$isCourseCreator) {
180 + return $this->sendError([
181 + 'message' => __('You must need to be invited to view this course', 'fluent-community')
182 + ]);
183 + }
184 +
185 + $section = $lesson->topic;
186 + $hasAcessSectionAcess = !!$enrollment;
187 + $unlockDate = '';
188 + $courseType = $course->getCourseType();
189 + $hasPublicViewAccess = $course->privacy == 'public' && Arr::get($course->settings, 'public_lesson_view') == 'yes' && $courseType == 'self_paced';
190 + if ($hasAcessSectionAcess) {
191 + $unlockDate = CourseHelper::getSectionAccessDate($section, $courseType, $enrollment);
192 + if ($unlockDate && strtotime($unlockDate) > current_time('timestamp')) {
193 + $hasAcessSectionAcess = false;
194 + } else {
195 + $unlockDate = null;
196 + }
197 + }
198 +
199 + $initialCanView = $hasAcessSectionAcess || $isCourseCreator || $hasPublicViewAccess;
200 + $accessInfo = CourseHelper::resolveLessonAccess($initialCanView, $lesson, $course, $this->getUser(), [
201 + 'enrollment' => $enrollment,
202 + 'is_admin' => $isCourseCreator,
203 + 'has_section_access' => $hasAcessSectionAcess,
204 + 'has_public_access' => $hasPublicViewAccess,
205 + ]);
206 + $canViewLesson = $accessInfo['can_view'];
207 + $lockType = $accessInfo['lock_type'];
208 +
209 + $formattedLesson = CourseHelper::formatLessonData($course, $lesson, $user, [
210 + 'can_view' => $canViewLesson,
211 + 'parse_content' => $canViewLesson,
212 + 'is_locked' => !$canViewLesson && !$isCourseCreator,
213 + 'unlock_date' => $unlockDate,
214 + 'lock_type' => $lockType
215 + ]);
216 +
217 + $data = [
218 + 'lesson' => $formattedLesson
219 + ];
220 +
221 + return apply_filters('fluent_community/course_lesson_api_response', $data, $request->all());
222 + }
223 +
224 + private function processCourse(Course $course, $isCourseCreator, $intendtedLessonSlug = '')
225 + {
105 226 $sections = CourseTopic::where('space_id', $course->id)
106 227 ->orderBy('priority', 'ASC')
107 - ->with(['lessons' => function ($query) use ($isModerator) {
108 - if (!$isModerator) {
228 + ->orderBy('id', 'ASC')
229 + ->with(['lessons' => function ($query) use ($isCourseCreator) {
230 + if (!$isCourseCreator) {
109 231 $query->where('status', 'published');
110 232 }
111 233 }])
112 234 ->get();
@@ -111,22 +233,40 @@
111 233 }])
112 234 ->get();
113 235
114 236 $enrollment = CourseHelper::getCourseEnrollment($course->id);
115 - $formattedSections = [];
116 237
238 + $currentUser = Helper::getCurrentUser();
239 +
117 240 if ($course->privacy == 'private' && !$enrollment) {
118 - $course->lockscreen_config = LockscreenService::getLockscreenConfig($course);
241 + $course->lockscreen_config = LockscreenService::getLockscreenConfig($course, null, true);
119 242 }
120 243
121 - if ($course->privacy == 'secret' && !$enrollment && !$isModerator) {
244 + if ($course->privacy == 'secret' && !$enrollment && !$isCourseCreator) {
122 245 return $this->sendError([
123 - 'message' => 'You must need to be invited to view this course'
246 + 'message' => __('You must need to be invited to view this course', 'fluent-community')
124 247 ]);
125 248 }
126 249
250 + $course->is_course_admin = $isCourseCreator;
251 + $course->can_self_enroll = $isCourseCreator || ($course->status === 'published' && $course->privacy === 'public');
252 +
253 + $course = apply_filters('fluent_community/course/processed', $course, [
254 + 'is_enrolled' => !!$enrollment,
255 + ]);
256 +
257 + $courseSettings = $course->settings;
258 + if (Arr::get($courseSettings, 'course_details')) {
259 + $courseSettings['course_details_rendered'] = wp_kses_post(FeedsHelper::mdToHtml($courseSettings['course_details']));
260 + $course->settings = $courseSettings;
261 + }
262 +
127 263 $courseType = $course->getCourseType();
128 264
265 + $hasPublicViewAccess = $course->privacy == 'public' && Arr::get($course->settings, 'public_lesson_view') == 'yes' && $courseType == 'self_paced';
266 +
267 + $formattedSections = [];
268 +
129 269 foreach ($sections as $section) {
130 270 if ($section->lessons->isEmpty()) {
131 271 continue;
132 272 }
@@ -135,9 +275,9 @@
135 275 $unlockDate = '';
136 276
137 277 if ($hasAcessSectionAcess) {
138 278 $unlockDate = CourseHelper::getSectionAccessDate($section, $courseType, $enrollment);
139 - if (!$unlockDate || strtotime($unlockDate) > current_time('timestamp')) {
279 + if ($unlockDate && strtotime($unlockDate) > current_time('timestamp')) {
140 280 $hasAcessSectionAcess = false;
141 281 } else {
142 282 $unlockDate = null;
143 283 }
@@ -142,34 +282,40 @@
142 282 $unlockDate = null;
143 283 }
144 284 }
145 285
286 + $sectionCtx = [
287 + 'enrollment' => $enrollment,
288 + 'is_admin' => $isCourseCreator,
289 + 'has_section_access' => $hasAcessSectionAcess,
290 + 'has_public_access' => $hasPublicViewAccess,
291 + ];
292 +
146 293 $formattedLessons = [];
294 + foreach ($section->lessons as $lesson) {
295 + $initialCanView = $hasAcessSectionAcess || $isCourseCreator || $hasPublicViewAccess;
296 + $accessInfo = CourseHelper::resolveLessonAccess($initialCanView, $lesson, $course, $this->getUser(), $sectionCtx);
297 + $canViewLesson = $accessInfo['can_view'];
298 + $lockType = $accessInfo['lock_type'];
147 299
148 - foreach ($section->lessons as $lesson) {
300 + $parseContent = $intendtedLessonSlug === $lesson->slug && $canViewLesson;
149 301
150 - if ($hasAcessSectionAcess || $isModerator) {
151 - $content = $lesson->message_rendered;
152 - if (!$content && $lesson->message) {
153 - $content = do_blocks($lesson->message);
154 - }
155 - } else {
156 - $content = '';
302 + $formattedLesson = CourseHelper::formatLessonData($course, $lesson, $currentUser, [
303 + 'can_view' => $canViewLesson,
304 + 'parse_content' => $parseContent,
305 + 'is_locked' => !$canViewLesson && !$isCourseCreator,
306 + 'unlock_date' => $unlockDate,
307 + 'lock_type' => $lockType
308 + ]);
309 +
310 + $isLazyLoad = !$parseContent;
311 + if(!$canViewLesson && $lockType !== 'sequential') {
312 + $isLazyLoad = false;
157 313 }
158 314
159 - $formattedLessons[] = [
160 - 'id' => $lesson->id,
161 - 'title' => $lesson->title,
162 - 'content' => $content,
163 - 'slug' => $lesson->slug,
164 - 'course_id' => $lesson->space_id,
165 - 'section_id' => $lesson->parent_id,
166 - 'created_at' => $lesson->created_at,
167 - 'meta' => $lesson->meta,
168 - 'comments_count' => $lesson->comments_count,
169 - 'is_locked' => !$hasAcessSectionAcess && !$isModerator,
170 - 'unclock_date' => $unlockDate
171 - ];
315 + $formattedLesson['lazy_load'] = $isLazyLoad;
316 +
317 + $formattedLessons[] = $formattedLesson;
172 318 }
173 319
174 320 $formattedSections[] = [
175 321 'id' => $section->id,
@@ -177,9 +323,9 @@
177 323 'lessons' => $formattedLessons,
178 324 'created_at' => $section->created_at,
179 325 'slug' => $section->slug,
180 326 'type' => 'section',
181 - 'is_locked' => !$hasAcessSectionAcess && !$isModerator,
327 + 'is_locked' => !$hasAcessSectionAcess && !$isCourseCreator,
182 328 'unlock_date' => $unlockDate
183 329 ];
184 330 }
185 331
@@ -199,16 +345,21 @@
199 345 'message' => __('You need to login to enroll in this course.', 'fluent-community')
200 346 ]);
201 347 }
202 348
203 - $isModerator = $user->isCommunityModerator();
204 - $course = Course::when(!$isModerator, function ($q) {
205 - $q->where('status', 'published');
206 - })->findOrFail($courseId);
349 + $course = Course::findOrFail($courseId);
350 + /** @var Course $course */
207 351
352 + $isCourseCreator = $course->isCourseAdmin($user);
208 353
209 - if (!$isModerator && $course->privacy != 'public') {
354 + if ($course->status !== 'published' && !$isCourseCreator) {
210 355 return $this->sendError([
356 + 'message' => __('Course not found. maybe the course is not published yet!', 'fluent-community')
357 + ]);
358 + }
359 +
360 + if (!$isCourseCreator && $course->privacy != 'public') {
361 + return $this->sendError([
211 362 'message' => __('You are not allowed to enroll in this course.', 'fluent-community')
212 363 ]);
213 364 }
214 365
@@ -232,9 +383,9 @@
232 383 $course = Course::findOrFail($courseId);
233 384
234 385 if ($course->status != 'published') {
235 386 return $this->sendError([
236 - 'message' => __('Course is not on published state.', 'fluent-community')
387 + 'message' => __('Course is not in published state.', 'fluent-community')
237 388 ]);
238 389 }
239 390
240 391
@@ -239,9 +390,9 @@
239 390
240 391
241 392 if (!CourseHelper::isEnrolled($courseId)) {
242 393 return $this->sendError([
243 - 'message' => 'You are not enrolled in this action.'
394 + 'message' => __('Please enroll this course first', 'fluent-community')
244 395 ]);
245 396 }
246 397
247 398 $lesson = CourseLesson::where('space_id', $courseId)
@@ -250,9 +401,9 @@
250 401 ->first();
251 402
252 403 if (!$lesson) {
253 404 return $this->sendError([
254 - 'message' => 'Lesson is not on published state.'
405 + 'message' => __('Lesson is not on published state.', 'fluent-community')
255 406 ]);
256 407 }
257 408
258 409 $state = $request->get('state');
@@ -258,23 +409,183 @@
258 409 $state = $request->get('state');
259 410
260 411 if (!in_array($state, ['completed', 'incomplete'])) {
261 412 return $this->sendError([
262 - 'message' => 'Invalid state.'
413 + 'message' => __('Invalid state.', 'fluent-community')
263 414 ]);
264 415 }
265 416
417 + $isAllowed = apply_filters('fluent_community/is_allowed_to_complete_lesson', true, $lesson, $state);
418 +
419 + if (!$isAllowed) {
420 + $errorData = [
421 + 'message' => __('You are not allowed to complete this lesson.', 'fluent-community')
422 + ];
423 +
424 + if (LessonVideoGateService::isCompletionBlockedFor($lesson, Helper::getCurrentUser())) {
425 + $errorData['code'] = 'video_watch_required';
426 + $errorData['threshold'] = LessonVideoGateService::getThreshold($lesson);
427 + }
428 +
429 + return $this->sendError($errorData);
430 + }
431 +
266 432 CourseHelper::updateLessonCompletion($lesson, get_current_user_id(), $state);
267 433 $track = CourseHelper::getCourseProgressTrack($courseId);
268 434 $isCompleted = $track['progress'] == 100;
269 435
270 436 if ($isCompleted) {
271 - CourseHelper::completeCourse($course, get_current_user_id());
437 + CourseHelper::completeCourse($course, $lesson, get_current_user_id());
272 438 }
273 439
274 440 return [
275 - 'message' => 'Lesson completion state updated.',
441 + 'message' => __('Lesson completion state updated.', 'fluent-community'),
276 442 'track' => $track,
277 443 'is_completed' => $isCompleted
278 444 ];
445 + }
446 +
447 + public function markLessonVideoWatched(Request $request, $courseId, $lessonId)
448 + {
449 + $course = Course::findOrFail($courseId);
450 +
451 + if ($course->status != 'published') {
452 + return $this->sendError([
453 + 'message' => __('Course is not in published state.', 'fluent-community')
454 + ]);
455 + }
456 +
457 + if (!CourseHelper::isEnrolled($courseId)) {
458 + return $this->sendError([
459 + 'message' => __('Please enroll this course first', 'fluent-community')
460 + ]);
461 + }
462 +
463 + $lesson = CourseLesson::where('space_id', $courseId)
464 + ->where('status', 'published')
465 + ->where('id', $lessonId)
466 + ->first();
467 +
468 + if (!$lesson) {
469 + return $this->sendError([
470 + 'message' => __('Lesson is not on published state.', 'fluent-community')
471 + ]);
472 + }
473 +
474 + if (!LessonVideoGateService::isGatedLesson($lesson)) {
475 + return [
476 + 'message' => __('This lesson does not require video completion.', 'fluent-community'),
477 + 'is_gated' => false,
478 + 'watched' => false
479 + ];
480 + }
481 +
482 + $watchedPercent = min(100, absint($request->get('watched_percent')));
483 + $threshold = LessonVideoGateService::getThreshold($lesson);
484 +
485 + if ($watchedPercent < $threshold) {
486 + return $this->sendError([
487 + /* translators: %d is the watched percentage required to complete the lesson */
488 + 'message' => sprintf(__('Please watch at least %d%% of the video.', 'fluent-community'), $threshold)
489 + ]);
490 + }
491 +
492 + LessonVideoGateService::markWatched($lesson, get_current_user_id());
493 +
494 + return [
495 + 'message' => __('Video watch progress has been recorded.', 'fluent-community'),
496 + 'is_gated' => true,
497 + 'watched' => true
498 + ];
499 + }
500 +
501 + public function resetMyProgress(Request $request, $courseId)
502 + {
503 + $course = Course::findOrFail($courseId);
504 +
505 + if ($course->status !== 'published') {
506 + return $this->sendError([
507 + 'message' => __('Course is not in published state.', 'fluent-community')
508 + ]);
509 + }
510 +
511 + if (!CourseHelper::isEnrolled($courseId)) {
512 + return $this->sendError([
513 + 'message' => __('Please enroll this course first', 'fluent-community')
514 + ]);
515 + }
516 +
517 + CourseHelper::resetCourseProgress($courseId, get_current_user_id());
518 +
519 + return [
520 + 'message' => __('Your course progress has been reset.', 'fluent-community'),
521 + 'track' => [
522 + 'completed_lessons' => [],
523 + 'isEnrolled' => true,
524 + 'progress' => 0
525 + ]
526 + ];
527 + }
528 +
529 + public function getAllCourses(Request $request)
530 + {
531 + $user = $this->getUser();
532 + $isCourseCreator = $user && $user->hasCourseCreatorAccess();
533 +
534 + $coursesQuery = Course::where(function ($q) use ($isCourseCreator, $user) {
535 + if ($isCourseCreator) {
536 + $q->where('status', 'published')
537 + ->orWhere('created_by', $user->ID);
538 + } else {
539 + $q->where('status', 'published');
540 + }
541 + });
542 +
543 + if (!($user && $user->isCommunityModerator())) {
544 + $userId = get_current_user_id();
545 + $coursesQuery->where(function ($q) use ($userId) {
546 + $q->whereIn('privacy', ['public', 'private'])
547 + ->orWhereHas('space_pivot', function ($sub) use ($userId) {
548 + $sub->where('user_id', $userId)
549 + ->where('role', 'student');
550 + })
551 + ->orWhere('created_by', $userId);
552 + });
553 + }
554 +
555 + $courses = $coursesQuery->with(['creator'])->paginate();
556 +
557 + $formattedCourses = [];
558 + foreach ($courses as $course) {
559 + $course->sectionsCount = CourseTopic::where('space_id', $course->id)->count();
560 + $course->lessonsCount = CourseLesson::where('space_id', $course->id)->count();
561 +
562 + if (Arr::get($course->settings, 'hide_members_count') != 'yes') {
563 + $course->studentsCount = SpaceUserPivot::where('space_id', $course->id)->count();
564 + } else {
565 + $course->studentsCount = 0;
566 + }
567 +
568 + $showInstructorView = Arr::get($course->settings, 'hide_instructor_view') != 'yes';
569 + $showStudentCount = Arr::get($course->settings, 'show_instructor_students_count') == 'yes';
570 + if ($showInstructorView) {
571 + if ($course->creator) {
572 + $creatorCourseIds = Course::where('created_by', $course->creator->user_id)->pluck('id');
573 + $course->creator->total_courses = count($creatorCourseIds);
574 + if ($showStudentCount) {
575 + $course->creator->total_students = SpaceUserPivot::whereIn('space_id', $creatorCourseIds)->distinct('user_id')->count('user_id');
576 + }
577 + if ($course->creator->short_description) {
578 + $course->creator->short_description_rendered = wp_kses_post(FeedsHelper::mdToHtml($course->creator->short_description));
579 + }
580 + }
581 + }
582 +
583 + $formattedCourses[] = $this->processCourse($course, $course->isCourseAdmin($user));
584 + }
585 +
586 + return apply_filters('fluent_community/all_courses_api_response', [
587 + 'courses' => $formattedCourses,
588 + 'total' => $courses->total()
589 + ], $request->all());
279 590 }
280 591 }