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 +49 -8 2.8.12.10.0 View file →
@@ -85,9 +85,9 @@
85 85 $courseData = [
86 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,9 +94,9 @@
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 ],
@@ -229,9 +229,9 @@
229 229
230 230 $courseData = [
231 231 'title' => $request->getSafe('title', 'sanitize_text_field'),
232 232 'privacy' => $request->get('privacy'),
233 - 'description' => wp_kses_post($request->get('description')),
233 + 'description' => wp_kses_post((string) $request->get('description', '')),
234 234 'status' => $request->get('status'),
235 235 'cover_photo' => $request->getSafe('cover_photo', 'sanitize_url'),
236 236 'parent_id' => $request->get('parent_id') ?: null, // phpcs:ignore Universal.Operators.DisallowShortTernary.Found
237 237 ];
@@ -303,9 +303,9 @@
303 303 $existingSettings['show_instructor_students_count'] = $request->get('settings.show_instructor_students_count') === 'yes' ? 'yes' : 'no';
304 304 $existingSettings['show_paywalls'] = $request->get('settings.show_paywalls') === 'yes' ? 'yes' : 'no';
305 305 $existingSettings['show_welcome_banner'] = $request->get('settings.show_welcome_banner') === 'yes' ? 'yes' : 'no';
306 306 $existingSettings['course_layout'] = $request->get('settings.course_layout') === 'modern' ? 'modern' : 'classic';
307 - $existingSettings['course_details'] = CustomSanitizer::unslashMarkdown(trim($request->get('settings.course_details')));
307 + $existingSettings['course_details'] = CustomSanitizer::unslashMarkdown(trim((string) $request->get('settings.course_details', '')));
308 308 $existingSettings['sequential_lesson_order'] = $request->get('settings.sequential_lesson_order') === 'yes' ? 'yes' : 'no';
309 309
310 310 if ($request->get('privacy') == 'public' && $existingSettings['course_type'] == 'self_paced') {
311 311 $existingSettings['public_lesson_view'] = $request->get('settings.public_lesson_view') == 'yes' ? 'yes' : 'no';
@@ -383,8 +383,10 @@
383 383 $newTopic = $topic->replicate();
384 384 $newTopic->space_id = $newCourse->id;
385 385 $newTopic->save();
386 386
387 + do_action('fluent_community/section/created', $newTopic, $newCourse);
388 +
387 389 foreach ($topic->lessons as $lesson) {
388 390 /** @var CourseLesson $lesson */
389 391 $newLesson = $lesson->replicate();
390 392 $newLesson->space_id = $newCourse->id;
@@ -390,8 +392,10 @@
390 392 $newLesson->space_id = $newCourse->id;
391 393 $newLesson->parent_id = $newTopic->id;
392 394 $newLesson->save();
393 395 CourseHelper::copyLessonDocuments($lesson, $newLesson);
396 +
397 + do_action('fluent_community/lesson/created', $newLesson, $newTopic);
394 398 }
395 399 }
396 400
397 401 do_action('fluent_community/course/created', $newCourse);
@@ -735,9 +739,9 @@
735 739 'space_id' => $courseId,
736 740 'status' => 'published',
737 741 ];
738 742
739 - Course::findOrFail($courseId);
743 + $course = Course::findOrFail($courseId);
740 744
741 745 $latestPriority = CourseTopic::where('type', 'course_section')->where('space_id', $courseId)->max('priority');
742 746
743 747 $sectionData['priority'] = (int) $latestPriority + 1;
@@ -745,8 +749,10 @@
745 749 $section = CourseTopic::create($sectionData);
746 750
747 751 $section->load('lessons');
748 752
753 + do_action('fluent_community/section/created', $section, $course);
754 +
749 755 return [
750 756 'message' => __('Section has been created successfully.', 'fluent-community'),
751 757 'section' => $section,
752 758 ];
@@ -868,8 +874,10 @@
868 874 $newSection->space_id = $toCourse->id;
869 875 $newSection->priority = (int) $latestPriority + 1;
870 876 $newSection->save();
871 877
878 + do_action('fluent_community/section/created', $newSection, $toCourse);
879 +
872 880 $originalLessons = CourseLesson::where('parent_id', $originalSection->id)->get();
873 881 foreach ($originalLessons as $lesson) {
874 882 /** @var CourseLesson $lesson */
875 883 $newLesson = $lesson->replicate();
@@ -876,8 +884,10 @@
876 884 $newLesson->space_id = $toCourse->id;
877 885 $newLesson->parent_id = $newSection->id;
878 886 $newLesson->save();
879 887 CourseHelper::copyLessonDocuments($lesson, $newLesson);
888 +
889 + do_action('fluent_community/lesson/created', $newLesson, $newSection);
880 890 }
881 891
882 892 $newSection->load('lessons');
883 893
@@ -951,8 +961,11 @@
951 961
952 962 return apply_filters('fluent_community/admin_course_lesson_api_response', $data, $request->all());
953 963 }
954 964
965 + /**
966 + * Expects `title` and `section_id` at the top level of the request.
967 + */
955 968 public function createLesson(Request $request, $courseId)
956 969 {
957 970 $this->validate($request->all(), [
958 971 'title' => 'required',
@@ -986,8 +999,10 @@
986 999 $lesson = CourseLesson::create($lessonData);
987 1000
988 1001 $lesson = CourseLesson::findOrFail($lesson->id);
989 1002
1003 + do_action('fluent_community/lesson/created', $lesson, $topic);
1004 +
990 1005 return [
991 1006 'message' => __('Lesson has been created successfully.', 'fluent-community'),
992 1007 'lesson' => $lesson,
993 1008 ];
@@ -992,13 +1007,16 @@
992 1007 'lesson' => $lesson,
993 1008 ];
994 1009 }
995 1010
1011 + /**
1012 + * Expects the fields nested under `lesson`, referencing the section as `parent_id`.
1013 + */
996 1014 public function updateLesson(Request $request, $courseId, $lessionId)
997 1015 {
998 1016 Course::findOrFail($courseId);
999 1017
1000 - $lessonData = $request->get('lesson');
1018 + $lessonData = (array)$request->get('lesson');
1001 1019
1002 1020 $this->validate($lessonData, [
1003 1021 'title' => 'required',
1004 1022 'parent_id' => 'required',
@@ -1062,8 +1080,12 @@
1062 1080 if ($dirtyFields) {
1063 1081 $lesson->save();
1064 1082 $isNewlyPublished = $lesson->status === 'published' && $previousStatus !== 'published';
1065 1083 do_action('fluent_community/lesson/updated', $lesson, $dirtyFields, $isNewlyPublished);
1084 +
1085 + if ($isNewlyPublished) {
1086 + do_action('fluent_community/lesson/published', $lesson);
1087 + }
1066 1088 }
1067 1089
1068 1090 do_action('fluent_community/lesson/additional_media_updated', $request->all(), $lesson, $updateData);
1069 1091
@@ -1080,8 +1102,10 @@
1080 1102 })
1081 1103 ->where('id', $lessionId)
1082 1104 ->firstOrFail();
1083 1105
1106 + $previousStatus = $lesson->status;
1107 +
1084 1108 $acceptedFields = [ 'title', 'status', 'slug' ];
1085 1109
1086 1110 // empty title/slug/status must not overwrite, but a literal "0" is a valid value
1087 1111 // Request::only() is a plain array pick with no sanitization, so each field is
@@ -1095,9 +1119,16 @@
1095 1119 $lessonData['title'] = sanitize_text_field($lessonData['title']);
1096 1120 }
1097 1121
1098 1122 if (isset($lessonData['slug'])) {
1099 - $lessonData['slug'] = sanitize_title($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 + );
1100 1131 }
1101 1132
1102 1133 if (isset($lessonData['status']) && !in_array($lessonData['status'], ['draft', 'published', 'archived'], true)) {
1103 1134 unset($lessonData['status']);
@@ -1115,10 +1146,19 @@
1115 1146 }
1116 1147
1117 1148 if (!empty($lessonData)) {
1118 1149 $lesson->fill($lessonData);
1119 - if ($lesson->isDirty()) {
1150 + $dirtyFields = $lesson->getDirty();
1151 +
1152 + if ($dirtyFields) {
1120 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 + }
1121 1161 }
1122 1162 }
1123 1163
1124 1164 return [
@@ -1193,8 +1233,9 @@
1193 1233 $newLesson = CourseLesson::findOrFail($newLesson->id);
1194 1234
1195 1235 CourseHelper::copyLessonDocuments($lesson, $newLesson);
1196 1236
1237 + do_action('fluent_community/lesson/created', $newLesson, $newLesson->topic);
1197 1238 do_action('fluent_community/lesson/duplicated', $newLesson, $lesson);
1198 1239
1199 1240 return [
1200 1241 'message' => __('Lesson has been duplicated successfully.', 'fluent-community'),