PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 1.0.97
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v1.0.97
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
fluent-community / Modules / Course / Services / CourseHelper.php

CourseHelper.php in FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses 1.0.97, at Modules/Course/Services/CourseHelper.php

416 lines 11.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCommunity\Modules\Course\Services;
4
5 use FluentCommunity\App\Models\Activity;
6 use FluentCommunity\App\Models\Meta;
7 use FluentCommunity\App\Models\Reaction;
8 use FluentCommunity\App\Models\SpaceUserPivot;
9 use FluentCommunity\App\Models\Term;
10 use FluentCommunity\App\Services\CustomSanitizer;
11 use FluentCommunity\App\Services\Helper;
12 use FluentCommunity\Framework\Support\Arr;
13 use FluentCommunity\Modules\Course\Model\Course;
14 use FluentCommunity\Modules\Course\Model\CourseLesson;
15
16 class CourseHelper
17 {
18 public static function getCourseProgressTrack($courseId, $userId = null)
19 {
20 $isEnrolled = self::isEnrolled($courseId, $userId);
21
22 return [
23 'completed_lessons' => $isEnrolled ? self::getCompletedLessonIds($courseId, $userId) : [],
24 'isEnrolled' => $isEnrolled,
25 'progress' => $isEnrolled ? self::getCourseProgress($courseId, $userId) : 0,
26 ];
27 }
28
29 public static function isEnrolled($courseId, $userId = null)
30 {
31 if (!$userId) {
32 $userId = get_current_user_id();
33 }
34
35 if (!$userId) {
36 return false;
37 }
38
39 return SpaceUserPivot::where('space_id', $courseId)
40 ->where('user_id', $userId)
41 ->exists();
42 }
43
44 public static function getCourseEnrollment($courseId, $userId = null)
45 {
46 if (!$userId) {
47 $userId = get_current_user_id();
48 }
49
50 if (!$userId) {
51 return null;
52 }
53
54 return SpaceUserPivot::where('space_id', $courseId)
55 ->where('user_id', $userId)
56 ->first();
57
58 }
59
60 public static function getCoursePublishedLessonIds($courseId)
61 {
62 static $counts = [];
63
64 if (isset($counts[$courseId])) {
65 return $counts[$courseId];
66 }
67
68 $counts[$courseId] = CourseLesson::where('space_id', $courseId)
69 ->where('status', 'published')
70 ->pluck('id')
71 ->toArray();
72
73 return $counts[$courseId];
74 }
75
76 public static function getCourseProgress($courseId, $userId = null)
77 {
78 if (!$userId) {
79 $userId = get_current_user_id();
80 }
81
82 if (!$userId) {
83 return 0;
84 }
85
86 $lessonIds = self::getCoursePublishedLessonIds($courseId);
87
88 if (!$lessonIds) {
89 return 0;
90 }
91
92 $completedLessons = Reaction::where('user_id', $userId)
93 ->whereIn('object_id', $lessonIds)
94 ->where('object_type', 'lesson_completed')
95 ->where('type', 'completed')
96 ->count();
97
98 if (!$completedLessons) {
99 return 0;
100 }
101
102 $result = floor(($completedLessons / count($lessonIds)) * 100);
103
104 if (!$result) {
105 return 0;
106 }
107
108 if ($result > 100) {
109 return 100;
110 }
111
112 return $result;
113
114 }
115
116 public static function getCompletedLessonIds($courseId, $userId = null)
117 {
118 if (!$userId) {
119 $userId = get_current_user_id();
120 }
121
122 if (!$userId) {
123 return [];
124 }
125
126 return Reaction::where('user_id', $userId)
127 ->where('parent_id', $courseId)
128 ->where('object_type', 'lesson_completed')
129 ->where('type', 'completed')
130 ->pluck('object_id')
131 ->toArray();
132 }
133
134 public static function overallCourseProgressAverage($course)
135 {
136 $lessonsCount = CourseLesson::where('space_id', $course->id)
137 ->where('status', 'published')
138 ->count();
139
140 if (!$lessonsCount) {
141 return 0;
142 }
143
144 $allCompletedCount = Reaction::where('object_type', 'lesson_completed')
145 ->where('type', 'completed')
146 ->where('parent_id', $course->id)
147 ->count();
148
149 $studentsCount = $course->students_count ? $course->students_count : $course->students()->count();
150
151 if (!$studentsCount) {
152 return 0;
153 }
154
155 // calculate the average of all students
156 return ceil(($allCompletedCount / ($studentsCount * $lessonsCount)) * 100);
157 }
158
159 public static function updateLessonCompletion($lesson, $userId, $state = 'completed')
160 {
161 $reaction = Reaction::where('user_id', $userId)
162 ->where('object_id', $lesson->id)
163 ->where('object_type', 'lesson_completed')
164 ->first();
165
166 if ($reaction) {
167 if ($state != 'completed') {
168 $reaction->type = 'incomplete';
169 $reaction->save();
170 } else {
171 $reaction->type = 'completed';
172 $reaction->save();
173 }
174 return true;
175 }
176
177 Reaction::create([
178 'user_id' => $userId,
179 'object_id' => $lesson->id,
180 'object_type' => 'lesson_completed',
181 'parent_id' => $lesson->space_id,
182 'type' => 'completed'
183 ]);
184
185 do_action('fluent_community/course/lesson_completed', $lesson, $userId);
186
187 return true;
188 }
189
190 public static function getCourseMeta($key, $default = false, $withModel = false)
191 {
192 $meta = Meta::where('meta_key', $key)
193 ->where('object_type', 'course')
194 ->first();
195
196 if ($withModel) {
197 return $meta;
198 }
199
200 return $meta ? $meta->value : $default;
201 }
202
203 public static function updateCourseMeta($key, $value)
204 {
205 $meta = Meta::where('meta_key', $key)
206 ->where('object_type', 'course')
207 ->first();
208
209 if ($meta) {
210 $meta->update([
211 'value' => $value
212 ]);
213 return $meta;
214 }
215
216 return Meta::create([
217 'meta_key' => $key,
218 'value' => $value,
219 'object_type' => 'course'
220 ]);
221 }
222
223 public static function completeCourse($course, $userId)
224 {
225 $exists = Activity::where('feed_id', $course->id) // we are using feed_id as it's indexed in the DB
226 ->where('user_id', $userId)
227 ->where('action_name', 'course_completed')
228 ->exists();
229
230 if ($exists) {
231 return false;
232 }
233
234 Activity::create([
235 'feed_id' => $course->id,
236 'user_id' => $userId,
237 'action_name' => 'course_completed'
238 ]);
239
240 do_action('fluent_community/course/completed', $course, $userId);
241
242 return true;
243 }
244
245 public static function enrollCourse($course, $userId = null, $by = 'self')
246 {
247 return Helper::addToSpace($course, $userId, 'student', $by);
248 }
249
250 public static function enrollCourses($courseIds, $userId = null, $by = 'self')
251 {
252 if (!$userId) {
253 $userId = get_current_user_id();
254 }
255
256 $enrolledCourseIds = [];
257
258 foreach ($courseIds as $courseId) {
259 $course = Course::find($courseId);
260 if ($course) {
261 if (self::enrollCourse($course, $userId, $by)) {
262 $enrolledCourseIds[] = $courseId;
263 }
264 }
265 }
266
267 return $enrolledCourseIds;
268 }
269
270 public static function leaveCourse($course, $userId = null, $by = 'self')
271 {
272 if (!$userId) {
273 $userId = get_current_user_id();
274 }
275
276 if (!$userId) {
277 return false;
278 }
279
280 return Helper::removeFromSpace($course, $userId, $by);
281 }
282
283 public static function leaveCourses($courseIds, $userId = null, $by = 'self')
284 {
285 if (!$userId) {
286 $userId = get_current_user_id();
287 }
288
289 $processedCourseIds = [];
290
291 foreach ($courseIds as $courseId) {
292 $course = Course::find($courseId);
293 if ($course) {
294 if (self::leaveCourse($course, $userId, $by)) {
295 $processedCourseIds[] = $courseId;
296 }
297 }
298
299 }
300
301 return $processedCourseIds;
302 }
303
304 public static function getEnrolledCourseIds($userId = null)
305 {
306 if (!$userId) {
307 $userId = get_current_user_id();
308 }
309
310 if (!$userId) {
311 return [];
312 }
313
314 return SpaceUserPivot::where('user_id', $userId)
315 ->where('role', 'student')
316 ->pluck('space_id')
317 ->toArray();
318
319 }
320
321 public static function getSectionAccessDate($section, $courseType, $enrollment = null)
322 {
323 if ($courseType == 'slef_paced') {
324 return null;
325 }
326
327 if ($courseType == 'scheduled') {
328 return $section->scheduled_at;
329 }
330
331 // This is for structured course
332 if (!$enrollment) {
333 return null;
334 }
335
336 $accessAfterEnrollment = $section->reactions_count;
337
338 return gmdate('Y-m-d H:i:s', strtotime($enrollment->created_at) + $accessAfterEnrollment * 86400);
339 }
340
341 public static function sanitizeLessonMeta($meta)
342 {
343 $validFields = [
344 'enable_comments',
345 'enable_media',
346 'media',
347 'video_length',
348 ];
349
350 $meta = Arr::only($meta, $validFields);
351
352 $yesNoFields = ['enable_comments', 'enable_media'];
353
354 foreach ($yesNoFields as $field) {
355 $meta[$field] = Arr::get($meta, $field, 'no') == 'yes' ? 'yes' : 'no';
356 }
357
358 if (Arr::get($meta, 'enable_media') == 'yes') {
359 if ($media = Arr::get($meta, 'media', [])) {
360 $media = array_filter([
361 'type' => sanitize_text_field(Arr::get($media, 'type', '')),
362 'url' => sanitize_url(Arr::get($media, 'url', '')),
363 'content_type' => sanitize_text_field(Arr::get($media, 'content_type', '')),
364 'provider' => sanitize_url(Arr::get($media, 'provider', '')),
365 'title' => sanitize_text_field(Arr::get($media, 'title', '')),
366 'author_name' => sanitize_text_field(Arr::get($media, 'author_name', '')),
367 'html' => CustomSanitizer::sanitizeRichText(Arr::get($media, 'html', '')),
368 ]);
369 $meta['media'] = $media;
370 }
371 } else {
372 $meta['media'] = [
373 'provider' => ''
374 ];
375 }
376
377 $numericFields = ['video_length'];
378
379 foreach ($numericFields as $field) {
380 $meta[$field] = absint(Arr::get($meta, $field, 0));
381 }
382
383 return $meta;
384 }
385
386 public static function getCourseCategories()
387 {
388 $terms = Term::whereHas('base_spaces', function ($q) {
389 $q->where('type', 'course');
390 })->get();
391
392 $formattedTerms = [];
393
394 foreach ($terms as $term) {
395 $formattedTerms[] = [
396 'id' => $term->id,
397 'title' => $term->title,
398 'slug' => $term->slug
399 ];
400 }
401
402 return $formattedTerms;
403 }
404
405 public function getUserCourses($userId = null)
406 {
407 if (!$userId) {
408 $userId = get_current_user_id();
409 }
410
411 return Course::whereHas('students', function ($q) use ($userId) {
412 $q->where('user_id', $userId);
413 })->get();
414 }
415 }
416