PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.11.0
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.11.0
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
← All changes | Modules/Course/Http/Controllers/CourseAdminController.php +223 -113 2.7.02.11.0 View file →
@@ -36,9 +36,9 @@
36 36 $query = Course::searchBy($request->getSafe('search'))
37 37 ->byAdminAccess($user->ID)
38 38 ->byPostTopic($topicSlug);
39 39
40 - if ($status && in_array($status, ['published', 'draft'])) {
40 + if ($status && in_array($status, [ 'published', 'draft' ])) {
41 41 $query->where('status', $status);
42 42 }
43 43
44 44 if ($sortBy === 'alphabetical') {
@@ -46,9 +46,9 @@
46 46 } else {
47 47 $query->orderBy('created_at', 'DESC');
48 48 }
49 49
50 - $courses = $query->with(['owner'])->paginate();
50 + $courses = $query->with([ 'owner' ])->paginate();
51 51
52 52 foreach ($courses as $course) {
53 53 $course->students_count = $course->students()->count();
54 54 if (!$course->cover_photo) {
@@ -59,9 +59,9 @@
59 59 }
60 60
61 61 $data = [
62 62 'courses' => $courses,
63 - 'course_categories' => $request->get('with_categories') ? CourseHelper::getCourseCategories() : []
63 + 'course_categories' => $request->get('with_categories') ? CourseHelper::getCourseCategories() : [],
64 64 ];
65 65
66 66 return apply_filters('fluent_community/admin_courses_api_response', $data, $request->all());
67 67 }
@@ -71,9 +71,9 @@
71 71 $this->validate($request->all(), [
72 72 'title' => 'required',
73 73 'description' => 'required',
74 74 'privacy' => 'required|in:public,private,secret',
75 - 'course_type' => 'required|in:self_paced,structured,scheduled'
75 + 'course_type' => 'required|in:self_paced,structured,scheduled',
76 76 ]);
77 77
78 78 $parentId = $request->get('parent_id');
79 79 if ($parentId) {
@@ -82,12 +82,12 @@
82 82 $serial = BaseSpace::max('serial') + 1;
83 83 }
84 84
85 85 $courseData = [
86 - 'parent_id' => $request->get('parent_id') ?: NULL,
86 + 'parent_id' => $request->get('parent_id') ?: null, // phpcs:ignore Universal.Operators.DisallowShortTernary.Found
87 87 'title' => $request->getSafe('title', 'sanitize_text_field'),
88 88 'privacy' => $request->get('privacy'),
89 - 'description' => wp_kses_post($request->get('description')),
89 + 'description' => wp_kses_post((string) $request->get('description', '')),
90 90 'status' => $request->get('status', 'draft'),
91 91 'settings' => [
92 92 'course_type' => $request->get('course_type'),
93 93 'emoji' => CustomSanitizer::sanitizeEmoji($request->get('settings.emoji', '')),
@@ -94,18 +94,18 @@
94 94 'shape_svg' => CustomSanitizer::sanitizeSvg($request->get('settings.shape_svg', '')),
95 95 'disable_comments' => $request->get('settings.disable_comments') === 'yes' ? 'yes' : 'no',
96 96 'hide_members_count' => $request->get('settings.hide_members_count') === 'yes' ? 'yes' : 'no',
97 97 'course_layout' => $request->get('settings.course_layout') === 'modern' ? 'modern' : 'classic',
98 - 'course_details' => CustomSanitizer::unslashMarkdown(trim($request->get('settings.course_details'))),
98 + 'course_details' => CustomSanitizer::unslashMarkdown(trim((string) $request->get('settings.course_details', ''))),
99 99 'hide_instructor_view' => $request->get('settings.hide_instructor_view') === 'yes' ? 'yes' : 'no',
100 100 'show_instructor_students_count' => $request->get('settings.show_instructor_students_count') === 'yes' ? 'yes' : 'no',
101 101 'sequential_lesson_order' => $request->get('settings.sequential_lesson_order') === 'yes' ? 'yes' : 'no',
102 102 ],
103 - 'serial' => $serial
103 + 'serial' => $serial,
104 104 ];
105 105
106 106 $lockScreenType = $request->get('settings.custom_lock_screen');
107 - if (!in_array($lockScreenType, ['yes', 'no', 'redirect']) || $request->get('privacy') != 'private') {
107 + if (!in_array($lockScreenType, [ 'yes', 'no', 'redirect' ]) || $request->get('privacy') != 'private') {
108 108 $lockScreenType = 'no';
109 109 }
110 110
111 111 $courseData['settings']['custom_lock_screen'] = $lockScreenType;
@@ -113,9 +113,9 @@
113 113 if ($lockScreenType === 'redirect') {
114 114 $redirectUrl = $request->get('settings.onboard_redirect_url');
115 115 if (!$redirectUrl || !filter_var($redirectUrl, FILTER_VALIDATE_URL)) {
116 116 return $this->sendError([
117 - 'message' => __('Course Redirect URL is not valid', 'fluent-community')
117 + 'message' => __('Course Redirect URL is not valid', 'fluent-community'),
118 118 ]);
119 119 }
120 120 $courseData['settings']['onboard_redirect_url'] = sanitize_url($redirectUrl);
121 121 }
@@ -125,9 +125,9 @@
125 125 }
126 126
127 127 $slug = $request->get('slug');
128 128
129 - $slug = $slug ?: $courseData['title'];
129 + $slug = $slug ? $slug : $courseData['title'];
130 130
131 131 $slug = preg_replace('/[^a-zA-Z0-9-_]/', '', $slug);
132 132
133 133 $slug = sanitize_title($slug, '');
@@ -147,9 +147,9 @@
147 147 do_action('fluent_community/course/before_create', $courseData);
148 148
149 149 $course = Course::create($courseData);
150 150
151 - $imageTypes = ['cover_photo', 'logo'];
151 + $imageTypes = [ 'cover_photo', 'logo' ];
152 152
153 153 $metaData = [];
154 154 foreach ($imageTypes as $type) {
155 155 if (!empty($request->get($type))) {
@@ -161,9 +161,9 @@
161 161 $media->update([
162 162 'is_active' => true,
163 163 'user_id' => get_current_user_id(),
164 164 'sub_object_id' => $course->id,
165 - 'object_source' => 'space_' . $type
165 + 'object_source' => 'space_' . $type,
166 166 ]);
167 167 }
168 168 }
169 169
@@ -182,16 +182,17 @@
182 182 do_action('fluent_community/course/created', $course);
183 183
184 184 return [
185 185 'message' => __('Course has been created successfully', 'fluent-community'),
186 - 'course' => $course
186 + 'course' => $course,
187 187 ];
188 188 }
189 189
190 190 public function findCourse(Request $request, $courseId)
191 191 {
192 + /** @var Course $course */
192 193 $course = Course::where('id', $courseId)
193 - ->with(['owner'])
194 + ->with([ 'owner' ])
194 195 ->firstOrFail();
195 196
196 197 $course->students_count = $course->students()->count();
197 198 $course->course_type = $course->settings['course_type'];
@@ -208,9 +209,9 @@
208 209
209 210 $course = apply_filters('fluent_community/course_info', $course, $request->all());
210 211
211 212 return [
212 - 'course' => $course
213 + 'course' => $course,
213 214 ];
214 215 }
215 216
216 217 public function updateCourse(Request $request, $courseId)
@@ -220,9 +221,9 @@
220 221 'description' => 'required',
221 222 'privacy' => 'required|in:public,private,secret',
222 223 'status' => 'required|in:draft,published,archived',
223 224 'course_type' => 'required|in:self_paced,structured,scheduled',
224 - 'created_by' => 'exists:users,ID'
225 + 'created_by' => 'exists:users,ID',
225 226 ]);
226 227
227 228 $course = Course::findOrFail($courseId);
228 229
@@ -228,12 +229,12 @@
228 229
229 230 $courseData = [
230 231 'title' => $request->getSafe('title', 'sanitize_text_field'),
231 232 'privacy' => $request->get('privacy'),
232 - 'description' => wp_kses_post($request->get('description')),
233 + 'description' => wp_kses_post((string) $request->get('description', '')),
233 234 'status' => $request->get('status'),
234 235 'cover_photo' => $request->getSafe('cover_photo', 'sanitize_url'),
235 - 'parent_id' => $request->get('parent_id') ?: NULL,
236 + 'parent_id' => $request->get('parent_id') ?: null, // phpcs:ignore Universal.Operators.DisallowShortTernary.Found
236 237 ];
237 238
238 239 $slug = $request->get('slug');
239 240 if ($slug && $course->slug != $slug) {
@@ -244,9 +245,9 @@
244 245 ->exists();
245 246
246 247 if ($exist || !$slug) {
247 248 return $this->sendError([
248 - 'message' => __('Slug is already taken. Please use a different slug', 'fluent-community')
249 + 'message' => __('Slug is already taken. Please use a different slug', 'fluent-community'),
249 250 ]);
250 251 }
251 252
252 253 $courseData['slug'] = $slug;
@@ -255,9 +256,9 @@
255 256 if ($request->get('created_by') && Helper::isSiteAdmin()) {
256 257 $courseData['created_by'] = (int)$request->get('created_by');
257 258 }
258 259
259 - $imageTypes = ['cover_photo', 'logo'];
260 + $imageTypes = [ 'cover_photo', 'logo' ];
260 261
261 262 foreach ($imageTypes as $type) {
262 263 if (!empty($request->get($type))) {
263 264 $media = Helper::getMediaFromUrl($request->get($type));
@@ -268,9 +269,9 @@
268 269 $media->update([
269 270 'is_active' => true,
270 271 'user_id' => get_current_user_id(),
271 272 'sub_object_id' => $course->id,
272 - 'object_source' => 'space_' . $type
273 + 'object_source' => 'space_' . $type,
273 274 ]);
274 275 } else {
275 276 $courseData[$type] = null;
276 277 }
@@ -279,9 +280,9 @@
279 280 $existingSettings = $course->settings;
280 281 $existingSettings['course_type'] = $request->get('course_type');
281 282
282 283 $lockScreenType = $request->get('settings.custom_lock_screen');
283 - if (!in_array($lockScreenType, ['yes', 'no', 'redirect']) || $request->get('privacy') != 'private') {
284 + if (!in_array($lockScreenType, [ 'yes', 'no', 'redirect' ]) || $request->get('privacy') != 'private') {
284 285 $lockScreenType = 'no';
285 286 }
286 287 if ($lockScreenType == 'redirect') {
287 288 $redirectUrl = $request->get('settings.onboard_redirect_url');
@@ -286,9 +287,9 @@
286 287 if ($lockScreenType == 'redirect') {
287 288 $redirectUrl = $request->get('settings.onboard_redirect_url');
288 289 if (!$redirectUrl || !filter_var($redirectUrl, FILTER_VALIDATE_URL)) {
289 290 return $this->sendError([
290 - 'message' => __('Course Redirect URL is not valid', 'fluent-community')
291 + 'message' => __('Course Redirect URL is not valid', 'fluent-community'),
291 292 ]);
292 293 }
293 294 $existingSettings['onboard_redirect_url'] = sanitize_url($redirectUrl);
294 295 }
@@ -302,9 +303,9 @@
302 303 $existingSettings['show_instructor_students_count'] = $request->get('settings.show_instructor_students_count') === 'yes' ? 'yes' : 'no';
303 304 $existingSettings['show_paywalls'] = $request->get('settings.show_paywalls') === 'yes' ? 'yes' : 'no';
304 305 $existingSettings['show_welcome_banner'] = $request->get('settings.show_welcome_banner') === 'yes' ? 'yes' : 'no';
305 306 $existingSettings['course_layout'] = $request->get('settings.course_layout') === 'modern' ? 'modern' : 'classic';
306 - $existingSettings['course_details'] = CustomSanitizer::unslashMarkdown(trim($request->get('settings.course_details')));
307 + $existingSettings['course_details'] = CustomSanitizer::unslashMarkdown(trim((string) $request->get('settings.course_details', '')));
307 308 $existingSettings['sequential_lesson_order'] = $request->get('settings.sequential_lesson_order') === 'yes' ? 'yes' : 'no';
308 309
309 310 if ($request->get('privacy') == 'public' && $existingSettings['course_type'] == 'self_paced') {
310 311 $existingSettings['public_lesson_view'] = $request->get('settings.public_lesson_view') == 'yes' ? 'yes' : 'no';
@@ -344,9 +345,9 @@
344 345 }
345 346
346 347 return [
347 348 'message' => __('Course has been updated successfully.', 'fluent-community'),
348 - 'course' => $course
349 + 'course' => $course,
349 350 ];
350 351 }
351 352
352 353 public function duplicateCourse(Request $request, $courseId)
@@ -360,8 +361,9 @@
360 361 $courseData['created_by'] = get_current_user_id();
361 362
362 363 do_action('fluent_community/course/before_create', $courseData);
363 364
365 + /** @var Course $newCourse */
364 366 $newCourse = $original->replicate();
365 367 $newCourse->title = $courseData['title'];
366 368 $newCourse->slug = $courseData['slug'];
367 369 $newCourse->status = $courseData['status'];
@@ -376,18 +378,24 @@
376 378 ->where('space_id', $original->id)
377 379 ->get();
378 380
379 381 foreach ($topics as $topic) {
382 + /** @var CourseTopic $topic */
380 383 $newTopic = $topic->replicate();
381 384 $newTopic->space_id = $newCourse->id;
382 385 $newTopic->save();
383 386
387 + do_action('fluent_community/section/created', $newTopic, $newCourse);
388 +
384 389 foreach ($topic->lessons as $lesson) {
390 + /** @var CourseLesson $lesson */
385 391 $newLesson = $lesson->replicate();
386 392 $newLesson->space_id = $newCourse->id;
387 393 $newLesson->parent_id = $newTopic->id;
388 394 $newLesson->save();
389 395 CourseHelper::copyLessonDocuments($lesson, $newLesson);
396 +
397 + do_action('fluent_community/lesson/created', $newLesson, $newTopic);
390 398 }
391 399 }
392 400
393 401 do_action('fluent_community/course/created', $newCourse);
@@ -393,9 +401,9 @@
393 401 do_action('fluent_community/course/created', $newCourse);
394 402
395 403 return [
396 404 'message' => __('Course duplicated successfully.', 'fluent-community'),
397 - 'course' => $newCourse
405 + 'course' => $newCourse,
398 406 ];
399 407 }
400 408
401 409 public function deleteCourse(Request $request, $courseId)
@@ -437,33 +445,34 @@
437 445
438 446 do_action('fluent_community/course/deleted', $courseId);
439 447
440 448 return [
441 - 'message' => __('Course has been deleted successfully along with all the associated data', 'fluent-community')
449 + 'message' => __('Course has been deleted successfully along with all the associated data', 'fluent-community'),
442 450 ];
443 451 }
444 452
445 453 public function getCourseComments(Request $request, $courseId)
446 454 {
447 - Course::findOrFail($courseId);
455 + $course = Course::findOrFail($courseId);
448 456
449 - $comments = Comment::whereHas('post', function ($q) use ($courseId) {
450 - return $q->where('space_id', $courseId);
451 - })
457 + $comments = Comment::byContentModerationAccessStatus($this->getUser(), $course)
458 + ->whereHas('post', function ($q) use ($courseId) {
459 + return $q->where('space_id', $courseId);
460 + })
452 461 ->orderBy('id', 'DESC')
453 462 ->with([
454 463 'post' => function ($q) {
455 - return $q->select(['id', 'title', 'slug']);
464 + return $q->select([ 'id', 'title', 'slug' ]);
456 465 },
457 466 'xprofile' => function ($q) {
458 467 $q->select(ProfileHelper::getXProfilePublicFields());
459 - }
468 + },
460 469 ])
461 470 ->paginate();
462 471
463 472 foreach ($comments as $comment) {
464 473 if ($comment->user) {
465 - $comment->user->makeHidden(['user_email']);
474 + $comment->user->makeHidden([ 'user_email' ]);
466 475 }
467 476 $likedIds = FeedsHelper::getLikedIdsByUserFeedId($comment->post_id, get_current_user_id());
468 477 if ($likedIds && in_array($comment->id, $likedIds)) {
469 478 $comment->liked = 1;
@@ -470,9 +479,9 @@
470 479 }
471 480 }
472 481
473 482 $data = [
474 - 'comments' => $comments
483 + 'comments' => $comments,
475 484 ];
476 485
477 486 return apply_filters('fluent_community/admin_course_comments_api_response', $data, $request->all());
478 487 }
@@ -482,13 +491,27 @@
482 491 Course::findOrFail($courseId);
483 492
484 493 $search = $request->getSafe('search');
485 494
486 - $students = XProfile::whereHas('space_pivot', function ($q) use ($courseId) {
487 - return $q->where('space_id', $courseId)
488 - ->where('role', 'student');
489 - })
490 - ->searchBy($search)
495 + $defaultDirections = [
496 + 'display_name' => 'ASC',
497 + 'created_at' => 'DESC',
498 + 'last_activity' => 'DESC',
499 + ];
500 +
501 + $sortBy = $request->getSafe('sort_by', 'sanitize_text_field', 'created_at');
502 + $sortColumn = in_array($sortBy, array_keys($defaultDirections), true) ? $sortBy : 'created_at';
503 + $sortDir = strtoupper($request->getSafe('sort_dir', 'sanitize_text_field', ''));
504 + $sortDirection = in_array($sortDir, ['ASC', 'DESC'], true) ? $sortDir : $defaultDirections[$sortColumn];
505 + $orderColumn = $sortColumn === 'created_at'
506 + ? 'fcom_space_user.created_at'
507 + : 'fcom_xprofile.' . $sortColumn;
508 +
509 + $publicFields = array_map(function ($field) {
510 + return 'fcom_xprofile.' . $field;
511 + }, ProfileHelper::getXProfilePublicFields());
512 +
513 + $students = XProfile::searchBy($search)
491 514 ->whereHas('user')
492 515 ->with([
493 516 'space_pivot' => function ($q) use ($courseId) {
494 517 return $q->where('space_id', $courseId);
@@ -493,9 +516,15 @@
493 516 'space_pivot' => function ($q) use ($courseId) {
494 517 return $q->where('space_id', $courseId);
495 518 },
496 519 ])
497 - ->select(ProfileHelper::getXProfilePublicFields())
520 + ->join('fcom_space_user', function ($join) use ($courseId) {
521 + $join->on('fcom_space_user.user_id', '=', 'fcom_xprofile.user_id')
522 + ->where('fcom_space_user.space_id', $courseId)
523 + ->where('fcom_space_user.role', 'student');
524 + })
525 + ->select($publicFields)
526 + ->orderBy($orderColumn, $sortDirection)
498 527 ->paginate();
499 528
500 529 $studentUserIds = $students->pluck('user_id')->toArray();
501 530
@@ -505,9 +534,9 @@
505 534 $student->progress = $progressMap[$student->user_id] ?? 0;
506 535 }
507 536
508 537 $data = [
509 - 'students' => $students
538 + 'students' => $students,
510 539 ];
511 540
512 541 return apply_filters('fluent_community/admin_course_students_api_response', $data, $request->all());
513 542 }
@@ -516,9 +545,9 @@
516 545 {
517 546 $course = Course::findOrFail($courseId);
518 547
519 548 $this->validate($request->all(), [
520 - 'user_id' => 'required|exists:users,ID'
549 + 'user_id' => 'required|exists:users,ID',
521 550 ]);
522 551
523 552 $userId = (int)$request->get('user_id');
524 553 $targetUser = User::findOrFail($userId);
@@ -525,9 +554,9 @@
525 554 $xprofile = $targetUser->syncXProfile();
526 555
527 556 if ($xprofile && $xprofile->status != 'active') {
528 557 return $this->sendError([
529 - 'message' => __('Selected user is not active', 'fluent-community')
558 + 'message' => __('Selected user is not active', 'fluent-community'),
530 559 ]);
531 560 }
532 561
533 562 $enrolled = CourseHelper::enrollCourse($course, $userId, 'by_admin');
@@ -533,14 +562,14 @@
533 562 $enrolled = CourseHelper::enrollCourse($course, $userId, 'by_admin');
534 563
535 564 if (!$enrolled) {
536 565 return $this->sendError([
537 - 'message' => __('User is already added to this course.', 'fluent-community')
566 + 'message' => __('User is already added to this course.', 'fluent-community'),
538 567 ]);
539 568 }
540 569
541 570 return [
542 - 'message' => __('User has been added to this course', 'fluent-community')
571 + 'message' => __('User has been added to this course', 'fluent-community'),
543 572 ];
544 573 }
545 574
546 575 public function removeStudent(Request $request, $courseId, $studentId)
@@ -552,9 +581,9 @@
552 581 ->first();
553 582
554 583 if (!$student) {
555 584 return $this->sendError([
556 - 'message' => __('Selected user is not a student of this course', 'fluent-community')
585 + 'message' => __('Selected user is not a student of this course', 'fluent-community'),
557 586 ]);
558 587 }
559 588
560 589 Helper::removeFromSpace($course, $studentId, 'by_admin');
@@ -559,9 +588,9 @@
559 588
560 589 Helper::removeFromSpace($course, $studentId, 'by_admin');
561 590
562 591 return [
563 - 'message' => __('Student has been removed from this course', 'fluent-community')
592 + 'message' => __('Student has been removed from this course', 'fluent-community'),
564 593 ];
565 594 }
566 595
567 596 public function resetStudentProgress(Request $request, $courseId, $studentId)
@@ -574,16 +603,20 @@
574 603 ->first();
575 604
576 605 if (!$pivot) {
577 606 return $this->sendError([
578 - 'message' => __('This student is not enrolled in this course.', 'fluent-community')
607 + 'message' => __('This student is not enrolled in this course.', 'fluent-community'),
579 608 ]);
580 609 }
581 610
582 - CourseHelper::resetCourseProgress($courseId, (int) $studentId);
611 + if (!CourseHelper::resetCourseProgress($courseId, (int) $studentId)) {
612 + return $this->sendError([
613 + 'message' => __("Student's progress could not be reset. Please try again.", 'fluent-community'),
614 + ]);
615 + }
583 616
584 617 return [
585 - 'message' => __("Student's progress has been reset.", 'fluent-community')
618 + 'message' => __("Student's progress has been reset.", 'fluent-community'),
586 619 ];
587 620 }
588 621
589 622 public function getSections(Request $request, $courseId)
@@ -588,8 +621,9 @@
588 621
589 622 public function getSections(Request $request, $courseId)
590 623 {
591 624 $course = Course::findOrFail($courseId);
625 + /** @var Course $course */
592 626
593 627 $sectionsQuery = CourseTopic::where('space_id', $courseId)
594 628 ->orderBy('priority', 'ASC')
595 629 ->orderBy('id', 'ASC');
@@ -595,21 +629,23 @@
595 629 ->orderBy('id', 'ASC');
596 630
597 631 if (in_array('only_published', $request->get('conditions', []))) {
598 632 $sectionsQuery->where('status', 'published')
599 - ->with(['lessons' => function ($q) {
633 + ->with([
634 + 'lessons' => function ($q) {
600 635 $q->where('status', 'published');
601 - }]);
636 + },
637 + ]);
602 638 }
603 639
604 640 if (empty($request->get('conditions', []))) {
605 - $sectionsQuery->with(['lessons']);
641 + $sectionsQuery->with([ 'lessons' ]);
606 642 }
607 643
608 644 $sections = $sectionsQuery->get();
609 645
610 646 $data = [
611 - 'sections' => $sections
647 + 'sections' => $sections,
612 648 ];
613 649
614 650 if ($request->get('with_lock_screen')) {
615 651 $data['lockscreen'] = LockscreenService::getLockscreenSettings($course);
@@ -624,13 +660,13 @@
624 660 ->whereHas('course', function ($query) use ($courseId) {
625 661 $query->where('id', $courseId);
626 662 })
627 663 ->where('id', $topicId)
628 - ->with(['lessons'])
664 + ->with([ 'lessons' ])
629 665 ->firstOrFail();
630 666
631 667 $data = [
632 - 'topic' => $topic
668 + 'topic' => $topic,
633 669 ];
634 670
635 671 return apply_filters('fluent_community/admin_course_section_api_response', $data, $request->all());
636 672 }
@@ -643,9 +679,10 @@
643 679 ->whereIn('id', array_keys($indexes))
644 680 ->get();
645 681
646 682 foreach ($sections as $section) {
647 - if (!isset($indexes[$section->id])) continue;
683 + if (!isset($indexes[$section->id])) { continue;
684 + }
648 685 $section->priority = $indexes[$section->id];
649 686 $section->save();
650 687 }
651 688
@@ -650,9 +687,9 @@
650 687 }
651 688
652 689 return [
653 690 'sections' => $sections,
654 - 'message' => __('Section indexes have been updated successfully.', 'fluent-community')
691 + 'message' => __('Section indexes have been updated successfully.', 'fluent-community'),
655 692 ];
656 693 }
657 694
658 695 public function resetLessonIndexes(Request $request, $courseId, $sectionId)
@@ -664,9 +701,10 @@
664 701 ->whereIn('id', array_keys($indexes))
665 702 ->get();
666 703
667 704 foreach ($lessons as $lesson) {
668 - if (!isset($indexes[$lesson->id])) continue;
705 + if (!isset($indexes[$lesson->id])) { continue;
706 + }
669 707 $lesson->priority = $indexes[$lesson->id];
670 708 $lesson->save();
671 709 }
672 710
@@ -671,9 +709,9 @@
671 709 }
672 710
673 711 return [
674 712 'lessons' => $lessons,
675 - 'message' => __('Lesson indexes have been updated successfully.', 'fluent-community')
713 + 'message' => __('Lesson indexes have been updated successfully.', 'fluent-community'),
676 714 ];
677 715 }
678 716
679 717 public function moveLesson(Request $request, $courseId)
@@ -681,18 +719,17 @@
681 719 $lessonId = $request->getSafe('lesson_id', 'intval');
682 720 $sectionId = $request->getSafe('section_id', 'intval');
683 721
684 722 Course::findOrFail($courseId);
685 - CourseTopic::findOrFail($sectionId);
723 + $section = CourseTopic::where('space_id', $courseId)->findOrFail($sectionId);
724 + $lesson = CourseLesson::where('space_id', $courseId)->findOrFail($lessonId);
686 725
687 - $lesson = CourseLesson::findOrFail($lessonId);
688 -
689 726 $lesson->update([
690 - 'parent_id' => $sectionId
727 + 'parent_id' => $section->id,
691 728 ]);
692 729
693 730 return [
694 - 'message' => __('Lesson has been moved successfully', 'fluent-community')
731 + 'message' => __('Lesson has been moved successfully', 'fluent-community'),
695 732 ];
696 733 }
697 734
698 735 public function createSection(Request $request, $courseId)
@@ -697,18 +734,18 @@
697 734
698 735 public function createSection(Request $request, $courseId)
699 736 {
700 737 $this->validate($request->all(), [
701 - 'title' => 'required'
738 + 'title' => 'required',
702 739 ]);
703 740
704 741 $sectionData = [
705 742 'title' => $request->getSafe('title'),
706 743 'space_id' => $courseId,
707 - 'status' => 'published'
744 + 'status' => 'published',
708 745 ];
709 746
710 - Course::findOrFail($courseId);
747 + $course = Course::findOrFail($courseId);
711 748
712 749 $latestPriority = CourseTopic::where('type', 'course_section')->where('space_id', $courseId)->max('priority');
713 750
714 751 $sectionData['priority'] = (int) $latestPriority + 1;
@@ -716,11 +753,13 @@
716 753 $section = CourseTopic::create($sectionData);
717 754
718 755 $section->load('lessons');
719 756
757 + do_action('fluent_community/section/created', $section, $course);
758 +
720 759 return [
721 760 'message' => __('Section has been created successfully.', 'fluent-community'),
722 - 'section' => $section
761 + 'section' => $section,
723 762 ];
724 763 }
725 764
726 765 public function updateSection(Request $request, $courseId, $tipicId)
@@ -726,9 +765,9 @@
726 765 public function updateSection(Request $request, $courseId, $tipicId)
727 766 {
728 767 $this->validate($request->all(), [
729 768 'title' => 'required',
730 - 'status' => 'required|in:draft,published,archived'
769 + 'status' => 'required|in:draft,published,archived',
731 770 ]);
732 771
733 772 Course::findOrFail($courseId);
734 773
@@ -738,9 +777,9 @@
738 777
739 778
740 779 $topicData = [
741 780 'title' => $request->getSafe('title'),
742 - 'status' => $request->get('status')
781 + 'status' => $request->get('status'),
743 782 ];
744 783
745 784 $topic->update($topicData);
746 785
@@ -745,9 +784,9 @@
745 784 $topic->update($topicData);
746 785
747 786 return [
748 787 'message' => __('Topic has been updated successfully.', 'fluent-community'),
749 - 'topic' => $topic
788 + 'topic' => $topic,
750 789 ];
751 790 }
752 791
753 792 public function patchSection(Request $request, $courseId, $tipicId)
@@ -757,21 +796,32 @@
757 796 $topic = CourseTopic::where('space_id', $courseId)
758 797 ->where('id', $tipicId)
759 798 ->firstOrFail();
760 799
761 - $acceptedFields = ['title', 'status'];
800 + $acceptedFields = [ 'title', 'status' ];
762 801
763 802 if ($course->getCourseType() == 'scheduled') {
764 803 $acceptedFields[] = 'scheduled_at';
765 - } else if ($course->getCourseType() == 'structured') {
804 + } elseif ($course->getCourseType() == 'structured') {
766 805 $acceptedFields[] = 'reactions_count';
767 806 }
768 807
808 + // Request::only() does not sanitize. Section titles currently render as escaped
809 + // text, so this is hygiene rather than a live sink, but keep the stored value
810 + // clean so a future v-html render cannot turn it into one.
769 811 $topicData = $request->only($acceptedFields);
770 812
813 + if (isset($topicData['title'])) {
814 + $topicData['title'] = sanitize_text_field($topicData['title']);
815 + }
816 +
817 + if (isset($topicData['status'])) {
818 + $topicData['status'] = sanitize_text_field($topicData['status']);
819 + }
820 +
771 821 if (!empty($topicData['scheduled_at'])) {
772 822 $topic->reactions_count = 0;
773 - } else if (isset($topicData['reactions_count'])) {
823 + } elseif (isset($topicData['reactions_count'])) {
774 824 $topic->scheduled_at = null;
775 825 $topic->reactions_count = $topicData['reactions_count'];
776 826 }
777 827
@@ -796,9 +846,9 @@
796 846 }
797 847
798 848 return [
799 849 'message' => __('Topic has been updated successfully.', 'fluent-community'),
800 - 'topic' => $topic
850 + 'topic' => $topic,
801 851 ];
802 852 }
803 853
804 854 public function copySection(Request $request, $toCourseId)
@@ -809,12 +859,13 @@
809 859 $fromCourse = Course::findOrFail($fromCourseId);
810 860
811 861 if (!$fromCourse->isCourseAdmin()) {
812 862 return $this->sendError([
813 - 'message' => __('You do not have permission to access this course', 'fluent-community')
863 + 'message' => __('You do not have permission to access this course', 'fluent-community'),
814 864 ]);
815 865 }
816 866
867 + /** @var CourseTopic $originalSection */
817 868 $originalSection = CourseTopic::where('id', $sectionId)
818 869 ->where('space_id', $fromCourseId)
819 870 ->firstOrFail();
820 871
@@ -821,20 +872,26 @@
821 872 $toCourse = Course::findOrFail($toCourseId);
822 873
823 874 $latestPriority = CourseTopic::where('type', 'course_section')->where('space_id', $toCourse->id)->max('priority');
824 875
876 + /** @var CourseTopic $newSection */
825 877 $newSection = $originalSection->replicate();
826 878 $newSection->space_id = $toCourse->id;
827 879 $newSection->priority = (int) $latestPriority + 1;
828 880 $newSection->save();
829 881
882 + do_action('fluent_community/section/created', $newSection, $toCourse);
883 +
830 884 $originalLessons = CourseLesson::where('parent_id', $originalSection->id)->get();
831 885 foreach ($originalLessons as $lesson) {
886 + /** @var CourseLesson $lesson */
832 887 $newLesson = $lesson->replicate();
833 888 $newLesson->space_id = $toCourse->id;
834 889 $newLesson->parent_id = $newSection->id;
835 890 $newLesson->save();
836 891 CourseHelper::copyLessonDocuments($lesson, $newLesson);
892 +
893 + do_action('fluent_community/lesson/created', $newLesson, $newSection);
837 894 }
838 895
839 896 $newSection->load('lessons');
840 897
@@ -839,9 +896,9 @@
839 896 $newSection->load('lessons');
840 897
841 898 return [
842 899 'message' => __('Section has been copied to the selected course', 'fluent-community'),
843 - 'section' => $newSection
900 + 'section' => $newSection,
844 901 ];
845 902 }
846 903
847 904 public function deleteSection(Request $request, $courseId, $sectionId)
@@ -847,9 +904,9 @@
847 904 public function deleteSection(Request $request, $courseId, $sectionId)
848 905 {
849 906 $topic = CourseTopic::where([
850 907 'id' => $sectionId,
851 - 'space_id' => $courseId
908 + 'space_id' => $courseId,
852 909 ])->firstOrFail();
853 910
854 911 do_action('fluent_community/section/before_deleted', $topic);
855 912
@@ -856,9 +913,9 @@
856 913 $topic->delete();
857 914
858 915 $lessons = CourseLesson::where([
859 916 'parent_id' => $sectionId,
860 - 'space_id' => $courseId
917 + 'space_id' => $courseId,
861 918 ])->get();
862 919
863 920 foreach ($lessons as $lesson) {
864 921 do_action('fluent_community/lesson/before_deleted', $lesson);
@@ -865,9 +922,9 @@
865 922 $lesson->delete();
866 923 }
867 924
868 925 return [
869 - 'message' => __('Section has been deleted successfully.', 'fluent-community')
926 + 'message' => __('Section has been deleted successfully.', 'fluent-community'),
870 927 ];
871 928 }
872 929
873 930 public function getLessons(Request $request, $courseId)
@@ -886,9 +943,9 @@
886 943
887 944 $lessons = $lessons->get();
888 945
889 946 $data = [
890 - 'lessons' => $lessons
947 + 'lessons' => $lessons,
891 948 ];
892 949
893 950 return apply_filters('fluent_community/admin_course_lessons_api_response', $data, $request->all());
894 951 }
@@ -898,23 +955,26 @@
898 955 $lesson = CourseLesson::whereHas('course', function ($query) use ($courseId) {
899 956 $query->where('id', $courseId);
900 957 })
901 958 ->where('id', $lessonId)
902 - ->with(['topic', 'course'])
959 + ->with([ 'topic', 'course' ])
903 960 ->firstOrFail();
904 961
905 962 $data = [
906 - 'lesson' => $lesson
963 + 'lesson' => $lesson,
907 964 ];
908 965
909 966 return apply_filters('fluent_community/admin_course_lesson_api_response', $data, $request->all());
910 967 }
911 968
969 + /**
970 + * Expects `title` and `section_id` at the top level of the request.
971 + */
912 972 public function createLesson(Request $request, $courseId)
913 973 {
914 974 $this->validate($request->all(), [
915 975 'title' => 'required',
916 - 'section_id' => 'required'
976 + 'section_id' => 'required',
917 977 ]);
918 978
919 979 $sectionId = (int)$request->get('section_id');
920 980
@@ -927,9 +987,9 @@
927 987 $lessonData = [
928 988 'title' => $request->getSafe('title'),
929 989 'parent_id' => $topic->id,
930 990 'space_id' => $courseId,
931 - 'status' => 'draft'
991 + 'status' => 'draft',
932 992 ];
933 993
934 994 $latestPriority = CourseLesson::where('type', 'course_lesson')
935 995 ->where('parent_id', $sectionId)
@@ -943,24 +1003,29 @@
943 1003 $lesson = CourseLesson::create($lessonData);
944 1004
945 1005 $lesson = CourseLesson::findOrFail($lesson->id);
946 1006
1007 + do_action('fluent_community/lesson/created', $lesson, $topic);
1008 +
947 1009 return [
948 1010 'message' => __('Lesson has been created successfully.', 'fluent-community'),
949 - 'lesson' => $lesson
1011 + 'lesson' => $lesson,
950 1012 ];
951 1013 }
952 1014
1015 + /**
1016 + * Expects the fields nested under `lesson`, referencing the section as `parent_id`.
1017 + */
953 1018 public function updateLesson(Request $request, $courseId, $lessionId)
954 1019 {
955 1020 Course::findOrFail($courseId);
956 1021
957 - $lessonData = $request->get('lesson');
1022 + $lessonData = (array)$request->get('lesson');
958 1023
959 1024 $this->validate($lessonData, [
960 1025 'title' => 'required',
961 1026 'parent_id' => 'required',
962 - 'status' => 'required|in:draft,published,archived'
1027 + 'status' => 'required|in:draft,published,archived',
963 1028 ]);
964 1029
965 1030 CourseTopic::whereHas('course', function ($query) use ($courseId) {
966 1031 $query->where('id', $courseId);
@@ -967,8 +1032,9 @@
967 1032 })
968 1033 ->where('id', $lessonData['parent_id'])
969 1034 ->firstOrFail();
970 1035
1036 + /** @var CourseLesson $lesson */
971 1037 $lesson = CourseLesson::where('id', $lessionId)
972 1038 ->where('space_id', $courseId)
973 1039 ->firstOrFail();
974 1040
@@ -976,12 +1042,12 @@
976 1042
977 1043 $updatedMeta = CourseHelper::sanitizeLessonMeta(Arr::get($lessonData, 'meta', []), $lesson);
978 1044 $updatedMeta['document_ids'] = Arr::get($lesson->meta, 'document_ids', []);
979 1045
980 - if ($mediaId = Arr::get($updatedMeta, 'featured_image_id')) {
1046 + if ($mediaId = Arr::get($updatedMeta, 'featured_image_id')) { // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
981 1047 if (!$lesson->isQuizType()) {
982 1048 $media = wp_get_attachment_image_url($mediaId);
983 - $lesson->featured_image = $media ?: null;
1049 + $lesson->featured_image = $media ? $media : null;
984 1050 } else {
985 1051 $media = Helper::getMediaFromUrl(sanitize_url($mediaId));
986 1052 if ($media && !$media->is_active) {
987 1053 Helper::removeMediaByUrl($lesson->featured_image, $lesson->id);
@@ -989,9 +1055,9 @@
989 1055 $media->update([
990 1056 'is_active' => true,
991 1057 'user_id' => get_current_user_id(),
992 1058 'sub_object_id' => $lesson->id,
993 - 'object_source' => 'quiz_thumbnail_' . $lesson->id
1059 + 'object_source' => 'quiz_thumbnail_' . $lesson->id,
994 1060 ]);
995 1061 }
996 1062 }
997 1063 } else {
@@ -1001,9 +1067,9 @@
1001 1067
1002 1068 $updateData = array_filter([
1003 1069 'title' => sanitize_text_field(Arr::get($lessonData, 'title')),
1004 1070 'status' => Arr::get($lessonData, 'status'),
1005 - 'meta' => wp_parse_args($updatedMeta, $lesson->meta)
1071 + 'meta' => wp_parse_args($updatedMeta, $lesson->meta),
1006 1072 ]);
1007 1073
1008 1074 // message bypasses array_filter so an emptied lesson body still saves
1009 1075 if (array_key_exists('message', $lessonData)) {
@@ -1018,8 +1084,12 @@
1018 1084 if ($dirtyFields) {
1019 1085 $lesson->save();
1020 1086 $isNewlyPublished = $lesson->status === 'published' && $previousStatus !== 'published';
1021 1087 do_action('fluent_community/lesson/updated', $lesson, $dirtyFields, $isNewlyPublished);
1088 +
1089 + if ($isNewlyPublished) {
1090 + do_action('fluent_community/lesson/published', $lesson);
1091 + }
1022 1092 }
1023 1093
1024 1094 do_action('fluent_community/lesson/additional_media_updated', $request->all(), $lesson, $updateData);
1025 1095
@@ -1024,9 +1094,9 @@
1024 1094 do_action('fluent_community/lesson/additional_media_updated', $request->all(), $lesson, $updateData);
1025 1095
1026 1096 return [
1027 1097 'message' => __('Lesson has been updated successfully.', 'fluent-community'),
1028 - 'lesson' => $lesson
1098 + 'lesson' => $lesson,
1029 1099 ];
1030 1100 }
1031 1101
1032 1102 public function patchLesson(Request $request, $courseId, $lessionId)
@@ -1036,15 +1106,39 @@
1036 1106 })
1037 1107 ->where('id', $lessionId)
1038 1108 ->firstOrFail();
1039 1109
1040 - $acceptedFields = ['title', 'status', 'slug'];
1110 + $previousStatus = $lesson->status;
1041 1111
1112 + $acceptedFields = [ 'title', 'status', 'slug' ];
1113 +
1042 1114 // empty title/slug/status must not overwrite, but a literal "0" is a valid value
1115 + // Request::only() is a plain array pick with no sanitization, so each field is
1116 + // sanitized here the same way createLesson/updateLesson do it. The title is
1117 + // rendered with v-html in the course views, so it must not carry markup.
1043 1118 $lessonData = array_filter($request->only($acceptedFields), function ($value) {
1044 1119 return $value !== null && $value !== '';
1045 1120 });
1046 1121
1122 + if (isset($lessonData['title'])) {
1123 + $lessonData['title'] = sanitize_text_field($lessonData['title']);
1124 + }
1125 +
1126 + if (isset($lessonData['slug'])) {
1127 + // sanitize_title() alone let an author set a slug already taken by a
1128 + // sibling lesson, which getLessonBySlug() then resolves arbitrarily.
1129 + $lessonData['slug'] = CourseLesson::uniqueSlug(
1130 + $lessonData['slug'],
1131 + $lesson->space_id,
1132 + $lesson->id,
1133 + Arr::get($lessonData, 'title', $lesson->title)
1134 + );
1135 + }
1136 +
1137 + if (isset($lessonData['status']) && !in_array($lessonData['status'], ['draft', 'published', 'archived'], true)) {
1138 + unset($lessonData['status']);
1139 + }
1140 +
1047 1141 if (Arr::get($lessonData, 'status') === 'published' && $lesson->status !== 'published') {
1048 1142 if (empty($lesson->scheduled_at)) {
1049 1143 $lessonData['scheduled_at'] = current_time('mysql');
1050 1144 }
@@ -1049,18 +1143,32 @@
1049 1143 $lessonData['scheduled_at'] = current_time('mysql');
1050 1144 }
1051 1145 }
1052 1146
1147 + // message bypasses the empty-value filter above so an emptied lesson body still saves
1148 + if ($request->exists('message')) {
1149 + $lessonData['message'] = CourseHelper::santizeLessonBody((string) $request->get('message'));
1150 + }
1151 +
1053 1152 if (!empty($lessonData)) {
1054 1153 $lesson->fill($lessonData);
1055 - if ($lesson->isDirty()) {
1154 + $dirtyFields = $lesson->getDirty();
1155 +
1156 + if ($dirtyFields) {
1056 1157 $lesson->save();
1158 +
1159 + $isNewlyPublished = $lesson->status === 'published' && $previousStatus !== 'published';
1160 + do_action('fluent_community/lesson/updated', $lesson, $dirtyFields, $isNewlyPublished);
1161 +
1162 + if ($isNewlyPublished) {
1163 + do_action('fluent_community/lesson/published', $lesson);
1164 + }
1057 1165 }
1058 1166 }
1059 1167
1060 1168 return [
1061 1169 'message' => __('Lesson has been updated successfully.', 'fluent-community'),
1062 - 'lesson' => $lesson
1170 + 'lesson' => $lesson,
1063 1171 ];
1064 1172 }
1065 1173
1066 1174 public function deleteLesson(Request $request, $courseId, $lessionId)
@@ -1075,9 +1183,9 @@
1075 1183
1076 1184 $lesson->delete();
1077 1185
1078 1186 return [
1079 - 'message' => __('Lesson has been deleted successfully.', 'fluent-community')
1187 + 'message' => __('Lesson has been deleted successfully.', 'fluent-community'),
1080 1188 ];
1081 1189 }
1082 1190
1083 1191 public function duplicateLesson(Request $request, $courseId, $lessonId)
@@ -1106,13 +1214,14 @@
1106 1214 $duplicateTitle = $lesson->title . ' (Copy)';
1107 1215 if (in_array($duplicateTitle, $existingTitles, true)) {
1108 1216 $counter = 2;
1109 1217 while (in_array($lesson->title . ' (Copy ' . $counter . ')', $existingTitles, true)) {
1110 - $counter++;
1218 + ++$counter;
1111 1219 }
1112 1220 $duplicateTitle = $lesson->title . ' (Copy ' . $counter . ')';
1113 1221 }
1114 1222
1223 + /** @var CourseLesson $newLesson */
1115 1224 $newLesson = $lesson->replicate();
1116 1225 $newLesson->title = $duplicateTitle;
1117 1226 $newLesson->slug = null;
1118 1227 $newLesson->priority = $sourceIndex + 1;
@@ -1118,12 +1227,12 @@
1118 1227 $newLesson->priority = $sourceIndex + 1;
1119 1228 $newLesson->save();
1120 1229
1121 1230 $orderedIds = $siblings->pluck('id')->toArray();
1122 - array_splice($orderedIds, $sourceIndex + 1, 0, [$newLesson->id]);
1231 + array_splice($orderedIds, $sourceIndex + 1, 0, [ $newLesson->id ]);
1123 1232
1124 1233 foreach ($orderedIds as $index => $siblingId) {
1125 - CourseLesson::where('id', $siblingId)->update(['priority' => $index]);
1234 + CourseLesson::where('id', $siblingId)->update([ 'priority' => $index ]);
1126 1235 }
1127 1236
1128 1237 $newLesson = CourseLesson::findOrFail($newLesson->id);
1129 1238
@@ -1128,13 +1237,14 @@
1128 1237 $newLesson = CourseLesson::findOrFail($newLesson->id);
1129 1238
1130 1239 CourseHelper::copyLessonDocuments($lesson, $newLesson);
1131 1240
1241 + do_action('fluent_community/lesson/created', $newLesson, $newLesson->topic);
1132 1242 do_action('fluent_community/lesson/duplicated', $newLesson, $lesson);
1133 1243
1134 1244 return [
1135 1245 'message' => __('Lesson has been duplicated successfully.', 'fluent-community'),
1136 - 'lesson' => $newLesson
1246 + 'lesson' => $newLesson,
1137 1247 ];
1138 1248 }
1139 1249
1140 1250 public function getOtherUsers(Request $request, $courseId)
@@ -1140,9 +1250,9 @@
1140 1250 public function getOtherUsers(Request $request, $courseId)
1141 1251 {
1142 1252 $selects = [
1143 1253 'ID',
1144 - 'display_name'
1254 + 'display_name',
1145 1255 ];
1146 1256
1147 1257 if (current_user_can('list_users')) {
1148 1258 $selects[] = 'user_email';
@@ -1147,9 +1257,9 @@
1147 1257 if (current_user_can('list_users')) {
1148 1258 $selects[] = 'user_email';
1149 1259 }
1150 1260
1151 - $userQuery = User::select(['ID'])
1261 + $userQuery = User::select([ 'ID' ])
1152 1262 ->whereDoesntHave('space_pivot', function ($q) use ($courseId) {
1153 1263 $q->where('space_id', $courseId);
1154 1264 })
1155 1265 ->limit(100)
@@ -1158,9 +1268,9 @@
1158 1268 if (is_multisite()) {
1159 1269 global $wpdb;
1160 1270 $blogId = get_current_blog_id();
1161 1271 $blogPrefix = $wpdb->get_blog_prefix($blogId);
1162 - $userQuery->whereHas('usermeta', function($q) use ($blogPrefix) {
1272 + $userQuery->whereHas('usermeta', function ($q) use ($blogPrefix) {
1163 1273 $q->where('meta_key', $blogPrefix . 'capabilities');
1164 1274 });
1165 1275 }
1166 1276
@@ -1172,9 +1282,9 @@
1172 1282 ->whereIn('ID', $userIds)
1173 1283 ->paginate(100);
1174 1284
1175 1285 $data = [
1176 - 'users' => $users
1286 + 'users' => $users,
1177 1287 ];
1178 1288
1179 1289 return apply_filters('fluent_community/admin_course_non_members_api_response', $data, $request->all());
1180 1290 }
@@ -1194,9 +1304,9 @@
1194 1304 $course->save();
1195 1305
1196 1306 return [
1197 1307 'message' => __('Links have been updated for the course', 'fluent-community'),
1198 - 'links' => $links
1308 + 'links' => $links,
1199 1309 ];
1200 1310 }
1201 1311
1202 1312 public function getMetaSettings(Request $request, $id)
@@ -1205,14 +1315,14 @@
1205 1315 $metaSettings = apply_filters('fluent_community/course/meta_fields', [], $course, $request->all());
1206 1316
1207 1317 if (!$metaSettings) {
1208 1318 return [
1209 - 'meta_settings' => null
1319 + 'meta_settings' => null,
1210 1320 ];
1211 1321 }
1212 1322
1213 1323 return [
1214 - 'meta_settings' => $metaSettings
1324 + 'meta_settings' => $metaSettings,
1215 1325 ];
1216 1326 }
1217 1327
1218 1328 public function getOtherInstructors(Request $request, $courseId)
@@ -1222,9 +1332,9 @@
1222 1332 Course::findOrFail($courseId);
1223 1333
1224 1334 $selects = [
1225 1335 'ID',
1226 - 'display_name'
1336 + 'display_name',
1227 1337 ];
1228 1338
1229 1339 if (current_user_can('list_users')) {
1230 1340 $selects[] = 'user_email';
@@ -1235,9 +1345,9 @@
1235 1345 ->searchBy($search)
1236 1346 ->get();
1237 1347
1238 1348 $data = [
1239 - 'instructors' => $instructors
1349 + 'instructors' => $instructors,
1240 1350 ];
1241 1351
1242 1352 return apply_filters('fluent_community/admin_course_other_instructors_api_response', $data, $request->all());
1243 1353 }