PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.10.0
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.10.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 1.1.0 All 77 releases
← All changes | Modules/Course/Http/Controllers/CourseAdminController.php +218 -112 2.7.02.10.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,9 +603,9 @@
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 611 CourseHelper::resetCourseProgress($courseId, (int) $studentId);
@@ -581,9 +610,9 @@
581 610
582 611 CourseHelper::resetCourseProgress($courseId, (int) $studentId);
583 612
584 613 return [
585 - 'message' => __("Student's progress has been reset.", 'fluent-community')
614 + 'message' => __("Student's progress has been reset.", 'fluent-community'),
586 615 ];
587 616 }
588 617
589 618 public function getSections(Request $request, $courseId)
@@ -588,8 +617,9 @@
588 617
589 618 public function getSections(Request $request, $courseId)
590 619 {
591 620 $course = Course::findOrFail($courseId);
621 + /** @var Course $course */
592 622
593 623 $sectionsQuery = CourseTopic::where('space_id', $courseId)
594 624 ->orderBy('priority', 'ASC')
595 625 ->orderBy('id', 'ASC');
@@ -595,21 +625,23 @@
595 625 ->orderBy('id', 'ASC');
596 626
597 627 if (in_array('only_published', $request->get('conditions', []))) {
598 628 $sectionsQuery->where('status', 'published')
599 - ->with(['lessons' => function ($q) {
629 + ->with([
630 + 'lessons' => function ($q) {
600 631 $q->where('status', 'published');
601 - }]);
632 + },
633 + ]);
602 634 }
603 635
604 636 if (empty($request->get('conditions', []))) {
605 - $sectionsQuery->with(['lessons']);
637 + $sectionsQuery->with([ 'lessons' ]);
606 638 }
607 639
608 640 $sections = $sectionsQuery->get();
609 641
610 642 $data = [
611 - 'sections' => $sections
643 + 'sections' => $sections,
612 644 ];
613 645
614 646 if ($request->get('with_lock_screen')) {
615 647 $data['lockscreen'] = LockscreenService::getLockscreenSettings($course);
@@ -624,13 +656,13 @@
624 656 ->whereHas('course', function ($query) use ($courseId) {
625 657 $query->where('id', $courseId);
626 658 })
627 659 ->where('id', $topicId)
628 - ->with(['lessons'])
660 + ->with([ 'lessons' ])
629 661 ->firstOrFail();
630 662
631 663 $data = [
632 - 'topic' => $topic
664 + 'topic' => $topic,
633 665 ];
634 666
635 667 return apply_filters('fluent_community/admin_course_section_api_response', $data, $request->all());
636 668 }
@@ -643,9 +675,10 @@
643 675 ->whereIn('id', array_keys($indexes))
644 676 ->get();
645 677
646 678 foreach ($sections as $section) {
647 - if (!isset($indexes[$section->id])) continue;
679 + if (!isset($indexes[$section->id])) { continue;
680 + }
648 681 $section->priority = $indexes[$section->id];
649 682 $section->save();
650 683 }
651 684
@@ -650,9 +683,9 @@
650 683 }
651 684
652 685 return [
653 686 'sections' => $sections,
654 - 'message' => __('Section indexes have been updated successfully.', 'fluent-community')
687 + 'message' => __('Section indexes have been updated successfully.', 'fluent-community'),
655 688 ];
656 689 }
657 690
658 691 public function resetLessonIndexes(Request $request, $courseId, $sectionId)
@@ -664,9 +697,10 @@
664 697 ->whereIn('id', array_keys($indexes))
665 698 ->get();
666 699
667 700 foreach ($lessons as $lesson) {
668 - if (!isset($indexes[$lesson->id])) continue;
701 + if (!isset($indexes[$lesson->id])) { continue;
702 + }
669 703 $lesson->priority = $indexes[$lesson->id];
670 704 $lesson->save();
671 705 }
672 706
@@ -671,9 +705,9 @@
671 705 }
672 706
673 707 return [
674 708 'lessons' => $lessons,
675 - 'message' => __('Lesson indexes have been updated successfully.', 'fluent-community')
709 + 'message' => __('Lesson indexes have been updated successfully.', 'fluent-community'),
676 710 ];
677 711 }
678 712
679 713 public function moveLesson(Request $request, $courseId)
@@ -681,18 +715,17 @@
681 715 $lessonId = $request->getSafe('lesson_id', 'intval');
682 716 $sectionId = $request->getSafe('section_id', 'intval');
683 717
684 718 Course::findOrFail($courseId);
685 - CourseTopic::findOrFail($sectionId);
719 + $section = CourseTopic::where('space_id', $courseId)->findOrFail($sectionId);
720 + $lesson = CourseLesson::where('space_id', $courseId)->findOrFail($lessonId);
686 721
687 - $lesson = CourseLesson::findOrFail($lessonId);
688 -
689 722 $lesson->update([
690 - 'parent_id' => $sectionId
723 + 'parent_id' => $section->id,
691 724 ]);
692 725
693 726 return [
694 - 'message' => __('Lesson has been moved successfully', 'fluent-community')
727 + 'message' => __('Lesson has been moved successfully', 'fluent-community'),
695 728 ];
696 729 }
697 730
698 731 public function createSection(Request $request, $courseId)
@@ -697,18 +730,18 @@
697 730
698 731 public function createSection(Request $request, $courseId)
699 732 {
700 733 $this->validate($request->all(), [
701 - 'title' => 'required'
734 + 'title' => 'required',
702 735 ]);
703 736
704 737 $sectionData = [
705 738 'title' => $request->getSafe('title'),
706 739 'space_id' => $courseId,
707 - 'status' => 'published'
740 + 'status' => 'published',
708 741 ];
709 742
710 - Course::findOrFail($courseId);
743 + $course = Course::findOrFail($courseId);
711 744
712 745 $latestPriority = CourseTopic::where('type', 'course_section')->where('space_id', $courseId)->max('priority');
713 746
714 747 $sectionData['priority'] = (int) $latestPriority + 1;
@@ -716,11 +749,13 @@
716 749 $section = CourseTopic::create($sectionData);
717 750
718 751 $section->load('lessons');
719 752
753 + do_action('fluent_community/section/created', $section, $course);
754 +
720 755 return [
721 756 'message' => __('Section has been created successfully.', 'fluent-community'),
722 - 'section' => $section
757 + 'section' => $section,
723 758 ];
724 759 }
725 760
726 761 public function updateSection(Request $request, $courseId, $tipicId)
@@ -726,9 +761,9 @@
726 761 public function updateSection(Request $request, $courseId, $tipicId)
727 762 {
728 763 $this->validate($request->all(), [
729 764 'title' => 'required',
730 - 'status' => 'required|in:draft,published,archived'
765 + 'status' => 'required|in:draft,published,archived',
731 766 ]);
732 767
733 768 Course::findOrFail($courseId);
734 769
@@ -738,9 +773,9 @@
738 773
739 774
740 775 $topicData = [
741 776 'title' => $request->getSafe('title'),
742 - 'status' => $request->get('status')
777 + 'status' => $request->get('status'),
743 778 ];
744 779
745 780 $topic->update($topicData);
746 781
@@ -745,9 +780,9 @@
745 780 $topic->update($topicData);
746 781
747 782 return [
748 783 'message' => __('Topic has been updated successfully.', 'fluent-community'),
749 - 'topic' => $topic
784 + 'topic' => $topic,
750 785 ];
751 786 }
752 787
753 788 public function patchSection(Request $request, $courseId, $tipicId)
@@ -757,21 +792,32 @@
757 792 $topic = CourseTopic::where('space_id', $courseId)
758 793 ->where('id', $tipicId)
759 794 ->firstOrFail();
760 795
761 - $acceptedFields = ['title', 'status'];
796 + $acceptedFields = [ 'title', 'status' ];
762 797
763 798 if ($course->getCourseType() == 'scheduled') {
764 799 $acceptedFields[] = 'scheduled_at';
765 - } else if ($course->getCourseType() == 'structured') {
800 + } elseif ($course->getCourseType() == 'structured') {
766 801 $acceptedFields[] = 'reactions_count';
767 802 }
768 803
804 + // Request::only() does not sanitize. Section titles currently render as escaped
805 + // text, so this is hygiene rather than a live sink, but keep the stored value
806 + // clean so a future v-html render cannot turn it into one.
769 807 $topicData = $request->only($acceptedFields);
770 808
809 + if (isset($topicData['title'])) {
810 + $topicData['title'] = sanitize_text_field($topicData['title']);
811 + }
812 +
813 + if (isset($topicData['status'])) {
814 + $topicData['status'] = sanitize_text_field($topicData['status']);
815 + }
816 +
771 817 if (!empty($topicData['scheduled_at'])) {
772 818 $topic->reactions_count = 0;
773 - } else if (isset($topicData['reactions_count'])) {
819 + } elseif (isset($topicData['reactions_count'])) {
774 820 $topic->scheduled_at = null;
775 821 $topic->reactions_count = $topicData['reactions_count'];
776 822 }
777 823
@@ -796,9 +842,9 @@
796 842 }
797 843
798 844 return [
799 845 'message' => __('Topic has been updated successfully.', 'fluent-community'),
800 - 'topic' => $topic
846 + 'topic' => $topic,
801 847 ];
802 848 }
803 849
804 850 public function copySection(Request $request, $toCourseId)
@@ -809,12 +855,13 @@
809 855 $fromCourse = Course::findOrFail($fromCourseId);
810 856
811 857 if (!$fromCourse->isCourseAdmin()) {
812 858 return $this->sendError([
813 - 'message' => __('You do not have permission to access this course', 'fluent-community')
859 + 'message' => __('You do not have permission to access this course', 'fluent-community'),
814 860 ]);
815 861 }
816 862
863 + /** @var CourseTopic $originalSection */
817 864 $originalSection = CourseTopic::where('id', $sectionId)
818 865 ->where('space_id', $fromCourseId)
819 866 ->firstOrFail();
820 867
@@ -821,20 +868,26 @@
821 868 $toCourse = Course::findOrFail($toCourseId);
822 869
823 870 $latestPriority = CourseTopic::where('type', 'course_section')->where('space_id', $toCourse->id)->max('priority');
824 871
872 + /** @var CourseTopic $newSection */
825 873 $newSection = $originalSection->replicate();
826 874 $newSection->space_id = $toCourse->id;
827 875 $newSection->priority = (int) $latestPriority + 1;
828 876 $newSection->save();
829 877
878 + do_action('fluent_community/section/created', $newSection, $toCourse);
879 +
830 880 $originalLessons = CourseLesson::where('parent_id', $originalSection->id)->get();
831 881 foreach ($originalLessons as $lesson) {
882 + /** @var CourseLesson $lesson */
832 883 $newLesson = $lesson->replicate();
833 884 $newLesson->space_id = $toCourse->id;
834 885 $newLesson->parent_id = $newSection->id;
835 886 $newLesson->save();
836 887 CourseHelper::copyLessonDocuments($lesson, $newLesson);
888 +
889 + do_action('fluent_community/lesson/created', $newLesson, $newSection);
837 890 }
838 891
839 892 $newSection->load('lessons');
840 893
@@ -839,9 +892,9 @@
839 892 $newSection->load('lessons');
840 893
841 894 return [
842 895 'message' => __('Section has been copied to the selected course', 'fluent-community'),
843 - 'section' => $newSection
896 + 'section' => $newSection,
844 897 ];
845 898 }
846 899
847 900 public function deleteSection(Request $request, $courseId, $sectionId)
@@ -847,9 +900,9 @@
847 900 public function deleteSection(Request $request, $courseId, $sectionId)
848 901 {
849 902 $topic = CourseTopic::where([
850 903 'id' => $sectionId,
851 - 'space_id' => $courseId
904 + 'space_id' => $courseId,
852 905 ])->firstOrFail();
853 906
854 907 do_action('fluent_community/section/before_deleted', $topic);
855 908
@@ -856,9 +909,9 @@
856 909 $topic->delete();
857 910
858 911 $lessons = CourseLesson::where([
859 912 'parent_id' => $sectionId,
860 - 'space_id' => $courseId
913 + 'space_id' => $courseId,
861 914 ])->get();
862 915
863 916 foreach ($lessons as $lesson) {
864 917 do_action('fluent_community/lesson/before_deleted', $lesson);
@@ -865,9 +918,9 @@
865 918 $lesson->delete();
866 919 }
867 920
868 921 return [
869 - 'message' => __('Section has been deleted successfully.', 'fluent-community')
922 + 'message' => __('Section has been deleted successfully.', 'fluent-community'),
870 923 ];
871 924 }
872 925
873 926 public function getLessons(Request $request, $courseId)
@@ -886,9 +939,9 @@
886 939
887 940 $lessons = $lessons->get();
888 941
889 942 $data = [
890 - 'lessons' => $lessons
943 + 'lessons' => $lessons,
891 944 ];
892 945
893 946 return apply_filters('fluent_community/admin_course_lessons_api_response', $data, $request->all());
894 947 }
@@ -898,23 +951,26 @@
898 951 $lesson = CourseLesson::whereHas('course', function ($query) use ($courseId) {
899 952 $query->where('id', $courseId);
900 953 })
901 954 ->where('id', $lessonId)
902 - ->with(['topic', 'course'])
955 + ->with([ 'topic', 'course' ])
903 956 ->firstOrFail();
904 957
905 958 $data = [
906 - 'lesson' => $lesson
959 + 'lesson' => $lesson,
907 960 ];
908 961
909 962 return apply_filters('fluent_community/admin_course_lesson_api_response', $data, $request->all());
910 963 }
911 964
965 + /**
966 + * Expects `title` and `section_id` at the top level of the request.
967 + */
912 968 public function createLesson(Request $request, $courseId)
913 969 {
914 970 $this->validate($request->all(), [
915 971 'title' => 'required',
916 - 'section_id' => 'required'
972 + 'section_id' => 'required',
917 973 ]);
918 974
919 975 $sectionId = (int)$request->get('section_id');
920 976
@@ -927,9 +983,9 @@
927 983 $lessonData = [
928 984 'title' => $request->getSafe('title'),
929 985 'parent_id' => $topic->id,
930 986 'space_id' => $courseId,
931 - 'status' => 'draft'
987 + 'status' => 'draft',
932 988 ];
933 989
934 990 $latestPriority = CourseLesson::where('type', 'course_lesson')
935 991 ->where('parent_id', $sectionId)
@@ -943,24 +999,29 @@
943 999 $lesson = CourseLesson::create($lessonData);
944 1000
945 1001 $lesson = CourseLesson::findOrFail($lesson->id);
946 1002
1003 + do_action('fluent_community/lesson/created', $lesson, $topic);
1004 +
947 1005 return [
948 1006 'message' => __('Lesson has been created successfully.', 'fluent-community'),
949 - 'lesson' => $lesson
1007 + 'lesson' => $lesson,
950 1008 ];
951 1009 }
952 1010
1011 + /**
1012 + * Expects the fields nested under `lesson`, referencing the section as `parent_id`.
1013 + */
953 1014 public function updateLesson(Request $request, $courseId, $lessionId)
954 1015 {
955 1016 Course::findOrFail($courseId);
956 1017
957 - $lessonData = $request->get('lesson');
1018 + $lessonData = (array)$request->get('lesson');
958 1019
959 1020 $this->validate($lessonData, [
960 1021 'title' => 'required',
961 1022 'parent_id' => 'required',
962 - 'status' => 'required|in:draft,published,archived'
1023 + 'status' => 'required|in:draft,published,archived',
963 1024 ]);
964 1025
965 1026 CourseTopic::whereHas('course', function ($query) use ($courseId) {
966 1027 $query->where('id', $courseId);
@@ -967,8 +1028,9 @@
967 1028 })
968 1029 ->where('id', $lessonData['parent_id'])
969 1030 ->firstOrFail();
970 1031
1032 + /** @var CourseLesson $lesson */
971 1033 $lesson = CourseLesson::where('id', $lessionId)
972 1034 ->where('space_id', $courseId)
973 1035 ->firstOrFail();
974 1036
@@ -976,12 +1038,12 @@
976 1038
977 1039 $updatedMeta = CourseHelper::sanitizeLessonMeta(Arr::get($lessonData, 'meta', []), $lesson);
978 1040 $updatedMeta['document_ids'] = Arr::get($lesson->meta, 'document_ids', []);
979 1041
980 - if ($mediaId = Arr::get($updatedMeta, 'featured_image_id')) {
1042 + if ($mediaId = Arr::get($updatedMeta, 'featured_image_id')) { // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
981 1043 if (!$lesson->isQuizType()) {
982 1044 $media = wp_get_attachment_image_url($mediaId);
983 - $lesson->featured_image = $media ?: null;
1045 + $lesson->featured_image = $media ? $media : null;
984 1046 } else {
985 1047 $media = Helper::getMediaFromUrl(sanitize_url($mediaId));
986 1048 if ($media && !$media->is_active) {
987 1049 Helper::removeMediaByUrl($lesson->featured_image, $lesson->id);
@@ -989,9 +1051,9 @@
989 1051 $media->update([
990 1052 'is_active' => true,
991 1053 'user_id' => get_current_user_id(),
992 1054 'sub_object_id' => $lesson->id,
993 - 'object_source' => 'quiz_thumbnail_' . $lesson->id
1055 + 'object_source' => 'quiz_thumbnail_' . $lesson->id,
994 1056 ]);
995 1057 }
996 1058 }
997 1059 } else {
@@ -1001,9 +1063,9 @@
1001 1063
1002 1064 $updateData = array_filter([
1003 1065 'title' => sanitize_text_field(Arr::get($lessonData, 'title')),
1004 1066 'status' => Arr::get($lessonData, 'status'),
1005 - 'meta' => wp_parse_args($updatedMeta, $lesson->meta)
1067 + 'meta' => wp_parse_args($updatedMeta, $lesson->meta),
1006 1068 ]);
1007 1069
1008 1070 // message bypasses array_filter so an emptied lesson body still saves
1009 1071 if (array_key_exists('message', $lessonData)) {
@@ -1018,8 +1080,12 @@
1018 1080 if ($dirtyFields) {
1019 1081 $lesson->save();
1020 1082 $isNewlyPublished = $lesson->status === 'published' && $previousStatus !== 'published';
1021 1083 do_action('fluent_community/lesson/updated', $lesson, $dirtyFields, $isNewlyPublished);
1084 +
1085 + if ($isNewlyPublished) {
1086 + do_action('fluent_community/lesson/published', $lesson);
1087 + }
1022 1088 }
1023 1089
1024 1090 do_action('fluent_community/lesson/additional_media_updated', $request->all(), $lesson, $updateData);
1025 1091
@@ -1024,9 +1090,9 @@
1024 1090 do_action('fluent_community/lesson/additional_media_updated', $request->all(), $lesson, $updateData);
1025 1091
1026 1092 return [
1027 1093 'message' => __('Lesson has been updated successfully.', 'fluent-community'),
1028 - 'lesson' => $lesson
1094 + 'lesson' => $lesson,
1029 1095 ];
1030 1096 }
1031 1097
1032 1098 public function patchLesson(Request $request, $courseId, $lessionId)
@@ -1036,15 +1102,39 @@
1036 1102 })
1037 1103 ->where('id', $lessionId)
1038 1104 ->firstOrFail();
1039 1105
1040 - $acceptedFields = ['title', 'status', 'slug'];
1106 + $previousStatus = $lesson->status;
1041 1107
1108 + $acceptedFields = [ 'title', 'status', 'slug' ];
1109 +
1042 1110 // empty title/slug/status must not overwrite, but a literal "0" is a valid value
1111 + // Request::only() is a plain array pick with no sanitization, so each field is
1112 + // sanitized here the same way createLesson/updateLesson do it. The title is
1113 + // rendered with v-html in the course views, so it must not carry markup.
1043 1114 $lessonData = array_filter($request->only($acceptedFields), function ($value) {
1044 1115 return $value !== null && $value !== '';
1045 1116 });
1046 1117
1118 + if (isset($lessonData['title'])) {
1119 + $lessonData['title'] = sanitize_text_field($lessonData['title']);
1120 + }
1121 +
1122 + if (isset($lessonData['slug'])) {
1123 + // sanitize_title() alone let an author set a slug already taken by a
1124 + // sibling lesson, which getLessonBySlug() then resolves arbitrarily.
1125 + $lessonData['slug'] = CourseLesson::uniqueSlug(
1126 + $lessonData['slug'],
1127 + $lesson->space_id,
1128 + $lesson->id,
1129 + Arr::get($lessonData, 'title', $lesson->title)
1130 + );
1131 + }
1132 +
1133 + if (isset($lessonData['status']) && !in_array($lessonData['status'], ['draft', 'published', 'archived'], true)) {
1134 + unset($lessonData['status']);
1135 + }
1136 +
1047 1137 if (Arr::get($lessonData, 'status') === 'published' && $lesson->status !== 'published') {
1048 1138 if (empty($lesson->scheduled_at)) {
1049 1139 $lessonData['scheduled_at'] = current_time('mysql');
1050 1140 }
@@ -1049,18 +1139,32 @@
1049 1139 $lessonData['scheduled_at'] = current_time('mysql');
1050 1140 }
1051 1141 }
1052 1142
1143 + // message bypasses the empty-value filter above so an emptied lesson body still saves
1144 + if ($request->exists('message')) {
1145 + $lessonData['message'] = CourseHelper::santizeLessonBody((string) $request->get('message'));
1146 + }
1147 +
1053 1148 if (!empty($lessonData)) {
1054 1149 $lesson->fill($lessonData);
1055 - if ($lesson->isDirty()) {
1150 + $dirtyFields = $lesson->getDirty();
1151 +
1152 + if ($dirtyFields) {
1056 1153 $lesson->save();
1154 +
1155 + $isNewlyPublished = $lesson->status === 'published' && $previousStatus !== 'published';
1156 + do_action('fluent_community/lesson/updated', $lesson, $dirtyFields, $isNewlyPublished);
1157 +
1158 + if ($isNewlyPublished) {
1159 + do_action('fluent_community/lesson/published', $lesson);
1160 + }
1057 1161 }
1058 1162 }
1059 1163
1060 1164 return [
1061 1165 'message' => __('Lesson has been updated successfully.', 'fluent-community'),
1062 - 'lesson' => $lesson
1166 + 'lesson' => $lesson,
1063 1167 ];
1064 1168 }
1065 1169
1066 1170 public function deleteLesson(Request $request, $courseId, $lessionId)
@@ -1075,9 +1179,9 @@
1075 1179
1076 1180 $lesson->delete();
1077 1181
1078 1182 return [
1079 - 'message' => __('Lesson has been deleted successfully.', 'fluent-community')
1183 + 'message' => __('Lesson has been deleted successfully.', 'fluent-community'),
1080 1184 ];
1081 1185 }
1082 1186
1083 1187 public function duplicateLesson(Request $request, $courseId, $lessonId)
@@ -1106,13 +1210,14 @@
1106 1210 $duplicateTitle = $lesson->title . ' (Copy)';
1107 1211 if (in_array($duplicateTitle, $existingTitles, true)) {
1108 1212 $counter = 2;
1109 1213 while (in_array($lesson->title . ' (Copy ' . $counter . ')', $existingTitles, true)) {
1110 - $counter++;
1214 + ++$counter;
1111 1215 }
1112 1216 $duplicateTitle = $lesson->title . ' (Copy ' . $counter . ')';
1113 1217 }
1114 1218
1219 + /** @var CourseLesson $newLesson */
1115 1220 $newLesson = $lesson->replicate();
1116 1221 $newLesson->title = $duplicateTitle;
1117 1222 $newLesson->slug = null;
1118 1223 $newLesson->priority = $sourceIndex + 1;
@@ -1118,12 +1223,12 @@
1118 1223 $newLesson->priority = $sourceIndex + 1;
1119 1224 $newLesson->save();
1120 1225
1121 1226 $orderedIds = $siblings->pluck('id')->toArray();
1122 - array_splice($orderedIds, $sourceIndex + 1, 0, [$newLesson->id]);
1227 + array_splice($orderedIds, $sourceIndex + 1, 0, [ $newLesson->id ]);
1123 1228
1124 1229 foreach ($orderedIds as $index => $siblingId) {
1125 - CourseLesson::where('id', $siblingId)->update(['priority' => $index]);
1230 + CourseLesson::where('id', $siblingId)->update([ 'priority' => $index ]);
1126 1231 }
1127 1232
1128 1233 $newLesson = CourseLesson::findOrFail($newLesson->id);
1129 1234
@@ -1128,13 +1233,14 @@
1128 1233 $newLesson = CourseLesson::findOrFail($newLesson->id);
1129 1234
1130 1235 CourseHelper::copyLessonDocuments($lesson, $newLesson);
1131 1236
1237 + do_action('fluent_community/lesson/created', $newLesson, $newLesson->topic);
1132 1238 do_action('fluent_community/lesson/duplicated', $newLesson, $lesson);
1133 1239
1134 1240 return [
1135 1241 'message' => __('Lesson has been duplicated successfully.', 'fluent-community'),
1136 - 'lesson' => $newLesson
1242 + 'lesson' => $newLesson,
1137 1243 ];
1138 1244 }
1139 1245
1140 1246 public function getOtherUsers(Request $request, $courseId)
@@ -1140,9 +1246,9 @@
1140 1246 public function getOtherUsers(Request $request, $courseId)
1141 1247 {
1142 1248 $selects = [
1143 1249 'ID',
1144 - 'display_name'
1250 + 'display_name',
1145 1251 ];
1146 1252
1147 1253 if (current_user_can('list_users')) {
1148 1254 $selects[] = 'user_email';
@@ -1147,9 +1253,9 @@
1147 1253 if (current_user_can('list_users')) {
1148 1254 $selects[] = 'user_email';
1149 1255 }
1150 1256
1151 - $userQuery = User::select(['ID'])
1257 + $userQuery = User::select([ 'ID' ])
1152 1258 ->whereDoesntHave('space_pivot', function ($q) use ($courseId) {
1153 1259 $q->where('space_id', $courseId);
1154 1260 })
1155 1261 ->limit(100)
@@ -1158,9 +1264,9 @@
1158 1264 if (is_multisite()) {
1159 1265 global $wpdb;
1160 1266 $blogId = get_current_blog_id();
1161 1267 $blogPrefix = $wpdb->get_blog_prefix($blogId);
1162 - $userQuery->whereHas('usermeta', function($q) use ($blogPrefix) {
1268 + $userQuery->whereHas('usermeta', function ($q) use ($blogPrefix) {
1163 1269 $q->where('meta_key', $blogPrefix . 'capabilities');
1164 1270 });
1165 1271 }
1166 1272
@@ -1172,9 +1278,9 @@
1172 1278 ->whereIn('ID', $userIds)
1173 1279 ->paginate(100);
1174 1280
1175 1281 $data = [
1176 - 'users' => $users
1282 + 'users' => $users,
1177 1283 ];
1178 1284
1179 1285 return apply_filters('fluent_community/admin_course_non_members_api_response', $data, $request->all());
1180 1286 }
@@ -1194,9 +1300,9 @@
1194 1300 $course->save();
1195 1301
1196 1302 return [
1197 1303 'message' => __('Links have been updated for the course', 'fluent-community'),
1198 - 'links' => $links
1304 + 'links' => $links,
1199 1305 ];
1200 1306 }
1201 1307
1202 1308 public function getMetaSettings(Request $request, $id)
@@ -1205,14 +1311,14 @@
1205 1311 $metaSettings = apply_filters('fluent_community/course/meta_fields', [], $course, $request->all());
1206 1312
1207 1313 if (!$metaSettings) {
1208 1314 return [
1209 - 'meta_settings' => null
1315 + 'meta_settings' => null,
1210 1316 ];
1211 1317 }
1212 1318
1213 1319 return [
1214 - 'meta_settings' => $metaSettings
1320 + 'meta_settings' => $metaSettings,
1215 1321 ];
1216 1322 }
1217 1323
1218 1324 public function getOtherInstructors(Request $request, $courseId)
@@ -1222,9 +1328,9 @@
1222 1328 Course::findOrFail($courseId);
1223 1329
1224 1330 $selects = [
1225 1331 'ID',
1226 - 'display_name'
1332 + 'display_name',
1227 1333 ];
1228 1334
1229 1335 if (current_user_can('list_users')) {
1230 1336 $selects[] = 'user_email';
@@ -1235,9 +1341,9 @@
1235 1341 ->searchBy($search)
1236 1342 ->get();
1237 1343
1238 1344 $data = [
1239 - 'instructors' => $instructors
1345 + 'instructors' => $instructors,
1240 1346 ];
1241 1347
1242 1348 return apply_filters('fluent_community/admin_course_other_instructors_api_response', $data, $request->all());
1243 1349 }