PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.4
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.4
4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 4.2.1 All 138 releases
learnpress / inc / user / class-lp-user.php

class-lp-user.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.4, at inc/user/class-lp-user.php

942 lines 27.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use LearnPress\Filters\FilterBase;
4 use LearnPress\Filters\UserItemsFilter;
5 use LearnPress\Models\UserModel;
6
7 /**
8 * Class LP_User
9 *
10 * @author ThimPress
11 * @package LearnPress/Classes
12 * @version 1.0.1
13 */
14 class LP_User extends LP_Abstract_User {
15 /**
16 * Check the user can view content items' course
17 *
18 * @param int $course_id
19 *
20 * @return LP_Model_User_Can_View_Course_Item
21 * @throws Exception
22 */
23 public function can_view_content_course( int $course_id = 0 ): LP_Model_User_Can_View_Course_Item {
24 $view = new LP_Model_User_Can_View_Course_Item();
25 $view->message = esc_html__(
26 'This content is protected. Please enroll in the course to view this content!',
27 'learnpress'
28 );
29
30 $course = learn_press_get_course( $course_id );
31 if ( ! $course ) {
32 return $view;
33 }
34
35 if ( $this->is_admin() || $this->is_author_of( $course_id ) ) {
36 $view->flag = true;
37 $view->message = 'User can view because is Admin or author of course';
38
39 return $view;
40 }
41
42 // Set view->flag is true if course is no required enroll
43 if ( $course->is_no_required_enroll() ) {
44 $view->flag = true;
45
46 return $view;
47 } elseif ( ! is_user_logged_in() ) {
48 $view->message = __(
49 'This content is protected. Please log in or enroll in the course to view this content!',
50 'learnpress'
51 );
52
53 return $view;
54 }
55
56 if ( $course->is_publish() ) {
57 $is_enrolled_or_finished = $this->has_enrolled_or_finished( $course_id );
58
59 if ( $is_enrolled_or_finished ) {
60 $is_finished_course = $this->has_finished_course( $course_id );
61 $enable_block_item_when_finish = $course->enable_block_item_when_finish();
62
63 if ( $is_finished_course && $enable_block_item_when_finish ) {
64 $view->key = LP_BLOCK_COURSE_FINISHED;
65 $view->message = __(
66 'You finished this course. This content is protected. Please enroll in the course to view this content!',
67 'learnpress'
68 );
69 } elseif ( 0 === $course->timestamp_remaining_duration() ) {
70 $view->key = LP_BLOCK_COURSE_DURATION_EXPIRE;
71 $view->message = __(
72 'The content of this item has been blocked because the course has exceeded its duration.',
73 'learnpress'
74 );
75 } elseif ( $this->get_course_status( $course_id ) === LP_COURSE_PURCHASED ) {
76 $view->key = LP_BLOCK_COURSE_PURCHASE;
77 $view->message = __(
78 'This content is protected. Please enroll in the course to view this content!',
79 'learnpress'
80 );
81 } else {
82 $view->key = 'can_view_course';
83 $view->flag = true;
84 $view->message = '';
85 }
86 }
87 }
88
89 // Todo: set cache - tungnx
90
91 return apply_filters( 'learnpress/course/can-view-content', $view, $this->get_id(), $course );
92 }
93
94 /**
95 * Check the user can access to an item inside course.
96 *
97 * @param int $item_id Course's item Id.
98 * @param LP_Model_User_Can_View_Course_Item $view Course Id.
99 *
100 * @author tungnx
101 * @return LP_Model_User_Can_View_Course_Item
102 * @since 4.0.0
103 */
104 public function can_view_item( int $item_id = 0, $view = null ): LP_Model_User_Can_View_Course_Item {
105 $view_new = null;
106
107 if ( ! $view instanceof LP_Model_User_Can_View_Course_Item ) {
108 return new LP_Model_User_Can_View_Course_Item();
109 }
110
111 $item = LP_Course_Item::get_item( $item_id );
112
113 if ( ! $item ) {
114 return $view;
115 }
116
117 if ( $item instanceof LP_Course_Item && $item->is_preview() ) {
118 $view_new = clone $view; // or create new LP_Model_User_Can_View_Course_Item()
119 $view_new->flag = true;
120 $view_new->key = 'lesson_preview';
121 $view_new->message = '';
122 }
123
124 if ( $view_new ) {
125 $view = $view_new;
126 }
127
128 return apply_filters( 'learnpress/course/item/can-view', $view, $item, $this );
129 }
130
131 /**
132 * Check if user can retry course.
133 *
134 * @param int $course_id .
135 *
136 * @return int
137 * @since 4.0.0
138 * @author tungnx
139 */
140 public function can_retry_course( int $course_id = 0 ): int {
141 $flag = 0;
142
143 try {
144 $course = learn_press_get_course( $course_id );
145
146 if ( ! $course ) {
147 throw new Exception( 'Course is not available' );
148 }
149
150 $retake_option = (int) $course->get_data( 'retake_count' );
151
152 if ( $retake_option > 0 ) {
153 /**
154 * Check course is finished
155 * Check duration is blocked
156 */
157 if ( ! $this->has_finished_course( $course->get_id() ) ) {
158 if ( 0 !== $course->timestamp_remaining_duration() ) {
159 throw new Exception();
160 }
161 }
162
163 $user_course_data = $this->get_course_data( $course_id );
164 if ( $user_course_data instanceof LP_User_Item_Course ) {
165 $retaken = $user_course_data->get_retaken_count();
166 $can_retake_times = $retake_option - $retaken;
167
168 if ( $can_retake_times > 0 ) {
169 $flag = $can_retake_times;
170 }
171 }
172 }
173 } catch ( Exception $e ) {
174
175 }
176
177 return apply_filters( 'learn-press/user/course/can-retry', $flag, $this->get_id(), $course_id );
178 }
179
180 /**
181 * Return true if user has already purchased course
182 *
183 * @param int $course_id
184 *
185 * @return bool
186 * @editor tungnx
187 * @modify 4.1.3
188 * @throws Exception
189 */
190 public function has_purchased_course( int $course_id ): bool {
191 $user_course = $this->get_course_data( $course_id );
192
193 return apply_filters( 'learn-press/user-purchased-course', $user_course && $user_course->is_purchased(), $course_id, $this->get_id() );
194 }
195
196 /**
197 * Check course is enrolled
198 *
199 * @param integer $course_id Course ID
200 * @param boolean $return_bool
201 *
202 * @return bool|object
203 * @editor tungnx
204 * @since 4.1.2
205 * @version 1.0.2
206 *
207 * @author Nhamdv
208 */
209 public function has_enrolled_course( int $course_id, bool $return_bool = true ) {
210 $result_check = new stdClass();
211 $result_check->check = true;
212 $result_check->message = '';
213
214 try {
215 /*$order = $this->get_course_order( $course_id );
216
217 if ( ! $order || ! $order->is_completed() ) {
218 throw new Exception( esc_html__( 'Order is not completed', 'learnpress' ) );
219 }*/
220
221 $user_course = $this->get_course_data( $course_id );
222 if ( ! $user_course || ! $user_course->is_enrolled() ) {
223 throw new Exception( esc_html__( 'The course is not enrolled.', 'learnpress' ) );
224 }
225 } catch ( Throwable $th ) {
226 $result_check->check = false;
227 $result_check->message = $th->getMessage();
228 }
229
230 return apply_filters( 'learn-press/user/is-course-enrolled', $return_bool ? $result_check->check : $result_check, $course_id, $return_bool );
231 }
232
233 /**
234 * Return true if user has finished a course
235 *
236 * @param int $course_id .
237 *
238 * @return bool
239 * @throws Exception
240 */
241 public function has_finished_course( int $course_id ): bool {
242 $user_course = $this->get_course_data( $course_id );
243
244 return apply_filters( 'learn-press/user-has-finished-course', $user_course && $user_course->is_finished(), $this->get_id(), $course_id );
245 }
246
247 /**
248 * Check course of user is enrolled or finished
249 *
250 * @param int $course_id
251 *
252 * @return bool
253 */
254 public function has_enrolled_or_finished( int $course_id ): bool {
255 $status = true;
256
257 try {
258 $user_course = $this->get_course_data( $course_id );
259
260 if ( ! $user_course ) {
261 $status = false;
262 } elseif ( ! $user_course->is_enrolled() && ! $user_course->is_finished() ) {
263 $status = false;
264 }
265 } catch ( Throwable $e ) {
266 $status = false;
267 }
268
269 return apply_filters( 'learn-press/user-has-finished-course', $status, $this->get_id(), $course_id );
270 }
271
272 /**
273 * Check user can enroll course
274 *
275 * @param int $course_id
276 * @param bool $return_bool
277 *
278 * @return mixed|object|bool
279 */
280 public function can_enroll_course( int $course_id, bool $return_bool = true ) {
281 $course = learn_press_get_course( $course_id );
282 $output = new stdClass();
283 $output->check = true;
284 $output->message = '';
285
286 try {
287 $is_no_required_enroll = $course->get_data( 'no_required_enroll', 'no' ) === 'yes';
288 if ( ! $course ) {
289 $output->code = 'course_unavailable';
290 throw new Exception( esc_html__( 'No Course or User available', 'learnpress' ) );
291 }
292
293 if ( ! $course->is_publish() ) {
294 $output->code = 'course_not_publish';
295 throw new Exception( esc_html__( 'The course is not public', 'learnpress' ) );
296 }
297
298 if ( $this->has_enrolled_course( $course_id ) ) {
299 $output->code = 'course_is_enrolled';
300 throw new Exception( esc_html__( 'This course is already enrolled.', 'learnpress' ) );
301 }
302
303 if ( ! $course->is_in_stock_enroll() && ! $this->has_purchased_course( $course_id )
304 && ! $this->has_enrolled_or_finished( $course_id ) && ! $is_no_required_enroll ) {
305 $output->code = 'course_out_of_stock';
306 throw new Exception( esc_html__( 'The course is full of students.', 'learnpress' ) );
307 }
308
309 if ( $course->get_external_link()
310 && ! $this->has_purchased_course( $course_id )
311 && ! $course->is_offline() ) {
312 $output->code = 'course_is_external';
313 throw new Exception( esc_html__( 'The course is external', 'learnpress' ) );
314 }
315
316 if ( $this->can_retry_course( $course_id ) ) {
317 $output->code = 'course_can_retry';
318 throw new Exception( esc_html__( 'Course can retake.', 'learnpress' ) );
319 }
320
321 if ( $is_no_required_enroll && ! is_user_logged_in() ) {
322 $output->code = 'course_is_no_required_enroll_not_login';
323 throw new Exception(
324 esc_html__( 'Enrollment in the course is not mandatory. You can access course for learning now.', 'learnpress' )
325 );
326 }
327
328 if ( ! $course->is_free() && ! $is_no_required_enroll && ! $this->has_purchased_course( $course_id ) ) {
329 $output->code = 'course_is_not_purchased';
330 throw new Exception( esc_html__( 'The course is not purchased.', 'learnpress' ) );
331 }
332 } catch ( \Throwable $th ) {
333 $output->check = false;
334 $output->message = $th->getMessage();
335 }
336
337 if ( $return_bool ) {
338 $output = $output->check;
339 }
340
341 return apply_filters( 'learn-press/user/can-enroll-course', $output, $course, $return_bool, $this );
342 }
343
344 /**
345 * Check can show purchase course button
346 *
347 * @param int $course_id
348 *
349 * @return bool|WP_Error
350 * @author nhamdv
351 * @editor tungnx
352 * @since 4.0.8
353 * @version 1.0.6
354 */
355 public function can_purchase_course( int $course_id = 0 ) {
356 $can_purchase = true;
357 $course = learn_press_get_course( $course_id );
358 $code_err = '';
359
360 try {
361 $can_enroll_course = $this->can_enroll_course( $course_id, false );
362 if ( ! $can_enroll_course->check &&
363 ! in_array( $can_enroll_course->code, [ 'course_is_not_purchased', 'course_is_enrolled' ] ) ) {
364 $code_err = $can_enroll_course->code;
365 throw new Exception( $can_enroll_course->message );
366 }
367
368 if ( $course->is_free() ) {
369 $code_err = 'course_is_free';
370 throw new Exception( __( 'Course is free, so you can not purchase', 'learnpress' ) );
371 }
372
373 // Course is not require enrolling.
374 // Not use $course->is_no_required_enroll() because it is not correct, it check with user logged.
375 if ( $course->get_data( 'no_required_enroll', 'no' ) === 'yes' ) {
376 $code_err = 'no_required_enroll';
377 throw new Exception(
378 __(
379 'Enrollment in the course is not mandatory. You can access materials for learning or to take quizzes now.',
380 'learnpress'
381 )
382 );
383 }
384
385 // If the order contains course is processing
386 $order = $this->get_course_order( $course_id );
387 if ( $order && $order->get_status() === LP_ORDER_PROCESSING ) {
388 $code_err = 'order_processing';
389 throw new Exception( __( 'Your order is waiting for processing', 'learnpress' ) );
390 }
391
392 if ( $this->has_purchased_course( $course_id ) ) {
393 $code_err = 'course_purchased';
394 throw new Exception( __( 'Course is purchased', 'learnpress' ) );
395 }
396
397 $is_blocked_course = 0 === $course->timestamp_remaining_duration();
398 $is_enrolled_course = $this->has_enrolled_course( $course_id );
399 if ( $course->allow_repurchase() ) {
400 if ( $is_enrolled_course && ! $is_blocked_course ) {
401 $code_err = 'course_is_enrolled';
402 throw new Exception( 'Course is enrolled' );
403 }
404 } else {
405 if ( $this->has_enrolled_or_finished( $course_id ) ) {
406 $code_err = 'course_is_enrolled_or_finished';
407 throw new Exception( __( 'Course is enrolled or finished', 'learnpress' ) );
408 }
409 }
410 } catch ( Throwable $e ) {
411 $can_purchase = new WP_Error( $code_err, $e->getMessage() );
412 }
413
414 if ( $can_purchase instanceof WP_Error ) {
415 $can_purchase = false;
416 }
417
418 return apply_filters( 'learn-press/user/can-purchase-course', $can_purchase, $this->get_id(), $course_id );
419 }
420
421 /**
422 * Check condition show finish course button
423 *
424 * @param $course
425 *
426 * @return array
427 * @author nhamdv
428 * @editor tungnx
429 * @version 1.0.2
430 */
431 public function can_show_finish_course_btn( $course ): array {
432 $return = array(
433 'status' => 'success',
434 'message' => '',
435 );
436
437 try {
438 if ( ! $course ) {
439 throw new Exception( esc_html__( 'Error: No Course or User available.', 'learnpress' ) );
440 }
441
442 $course_id = $course->get_id();
443
444 if ( $this->has_finished_course( $course_id ) ) {
445 throw new Exception( esc_html__( 'The course has finished.', 'learnpress' ) );
446 }
447
448 if ( ! $this->has_enrolled_course( $course_id ) ) {
449 throw new Exception( esc_html__( 'The course is not enrolled.', 'learnpress' ) );
450 }
451
452 if ( ! $this->is_course_in_progress( $course_id ) ) {
453 throw new Exception( esc_html__( 'Error: The course is not in progress.', 'learnpress' ) );
454 }
455
456 $course_data = $this->get_course_data( $course_id );
457
458 if ( $course_data ) {
459 $course_result = $course_data->get_result();
460
461 if ( ! $course_result['pass'] ) {
462 // Get option Can finish course if completed all item without pass
463 $can_finish = get_post_meta( $course_id, '_lp_has_finish', true ) ?? 'yes';
464
465 if ( $can_finish == 'yes' ) {
466 // Check completed all items
467 $is_all_completed = $this->is_completed_all_items( $course_id );
468 if ( ! $is_all_completed ) {
469 throw new Exception( 'All items not completed and Course not pass' );
470 }
471 } else {
472 throw new Exception( 'Course not pass' );
473 }
474 }
475 }
476
477 if ( ! apply_filters( 'lp_can_finish_course', true ) ) {
478 throw new Exception( esc_html__( 'Error: Filter the disabled finished courses.', 'learnpress' ) );
479 }
480 } catch ( Exception $e ) {
481 $return['status'] = 'false';
482 $return['message'] = $e->getMessage();
483 }
484
485 return $return;
486 }
487
488 /**
489 * Start quiz for the user.
490 *
491 * @param int $quiz_id
492 * @param int $course_id
493 * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false.
494 *
495 * @return LP_User_Item_Quiz|bool|WP_Error
496 * @throws Exception
497 * @deprecated 4.2.9.1
498 */
499 public function start_quiz( int $quiz_id, int $course_id = 0, bool $wp_error = false ) {
500 _deprecated_function( __METHOD__, '4.2.9.1' );
501 return false;
502
503 try {
504 $item_is_preview = learn_press_get_request( 'lp-preview' );
505 if ( $item_is_preview ) {
506 throw new Exception( __( 'You cannot start a quiz in preview mode.', 'learnpress' ) );
507 }
508
509 // Validate course and quiz
510 $course_id = $this->_verify_course_item( $quiz_id, $course_id );
511 if ( ! $course_id ) {
512 throw new Exception(
513 __( 'The course does not exist or does not contain a quiz.', 'learnpress' ),
514 LP_INVALID_QUIZ_OR_COURSE
515 );
516 }
517
518 $course = learn_press_get_course( $course_id );
519 // If user has already finished the course
520 if ( $this->has_finished_course( $course_id ) ) {
521 throw new Exception(
522 __( 'You have already finished the course of this quiz', 'learnpress' ),
523 LP_COURSE_IS_FINISHED
524 );
525 }
526
527 if ( ! $this->has_enrolled_course( $course_id ) || ! $this->is_course_in_progress( $course_id ) ) {
528 if ( ! $course->is_no_required_enroll() ) {
529 throw new Exception(
530 __( 'Please enroll in the course before starting the quiz.', 'learnpress' ),
531 LP_COURSE_IS_FINISHED
532 );
533 }
534 }
535
536 // Check if user has already started or completed quiz
537 if ( $this->has_item_status( array( 'started', 'completed' ), $quiz_id, $course_id ) ) {
538 throw new Exception(
539 __( 'The user has started or completed the quiz.', 'learnpress' ),
540 LP_QUIZ_HAS_STARTED_OR_COMPLETED
541 );
542 }
543
544 $user_current = learn_press_get_current_user();
545 if ( $user_current->is_guest() ) {
546 // if course required enroll => print message "You have to login for starting quiz"
547 if ( ! $course->is_no_required_enroll() ) {
548 throw new Exception( __( 'You have to log in to start the quiz.', 'learnpress' ), LP_REQUIRE_LOGIN );
549 }
550 }
551
552 /**
553 * Hook can start quiz
554 *
555 * @see learn_press_hk_before_start_quiz
556 */
557 $can_start_quiz = apply_filters(
558 'learn-press/can-start-quiz',
559 true,
560 $quiz_id,
561 $course_id,
562 $this->get_id()
563 );
564
565 if ( ! $can_start_quiz ) {
566 return false;
567 }
568
569 $user_quiz = false;
570
571 /**
572 * Hook quiz started
573 *
574 * @since 3.0.0
575 */
576 do_action( 'learn-press/user/quiz-started', $quiz_id, $course_id, $this->get_id() );
577
578 // $return = $user_quiz->get_mysql_data();
579 $return = $user_quiz;
580 } catch ( Throwable $ex ) {
581 $return = $wp_error ? new WP_Error( $ex->getCode(), $ex->getMessage() ) : false;
582 }
583
584 return $return;
585 }
586
587 /**
588 * Finish a quiz for the user and save all data needed
589 *
590 * @param int $quiz_id
591 * @param int $course_id
592 * @param bool $wp_error
593 *
594 * @return LP_User_Item_Quiz|bool|WP_Error
595 */
596 public function finish_quiz( int $quiz_id, int $course_id, bool $wp_error = false ) {
597 $return = false;
598
599 try {
600 // If user has already finished the course
601 if ( $this->has_finished_course( $course_id ) ) {
602 throw new Exception(
603 __( 'The user has already finished the course of this quiz.', 'learnpress' ),
604 LP_COURSE_IS_FINISHED
605 );
606
607 }
608
609 // Check if user has already started or completed quiz
610 if ( $this->has_item_status( array( 'completed' ), $quiz_id, $course_id ) ) {
611 throw new Exception(
612 __( 'The user has completed the quiz', 'learnpress' ),
613 LP_QUIZ_HAS_STARTED_OR_COMPLETED
614 );
615 }
616
617 /**
618 * @var LP_User_Item_Quiz $user_quiz
619 */
620 $user_quiz = $this->get_item_data( $quiz_id, $course_id );
621 $user_quiz->complete();
622
623 do_action( 'learn-press/user/quiz-finished', $quiz_id, $course_id, $this->get_id() );
624 } catch ( Exception $ex ) {
625 $return = $wp_error ? new WP_Error( $ex->getCode(), $ex->getMessage() ) : true;
626 }
627
628 return $return;
629 }
630
631 /**
632 * Retake a quiz for the user
633 *
634 * @param int $quiz_id
635 * @param int $course_id
636 * @param bool $wp_error
637 *
638 * @return bool|WP_Error|LP_User_Item_Quiz
639 *
640 * @throws Exception
641 * @deprecated 4.2.7.2
642 */
643 /*public function retake_quiz( int $quiz_id, int $course_id, bool $wp_error = false ) {
644 $return = false;
645
646 try {
647 $course_id = $this->_verify_course_item( $quiz_id, $course_id );
648
649 if ( false === $course_id ) {
650 throw new Exception(
651 sprintf(
652 __(
653 'The course does not exist or does not contain a quiz.',
654 'learnpress'
655 ),
656 __CLASS__,
657 __FUNCTION__
658 ),
659 LP_INVALID_QUIZ_OR_COURSE
660 );
661 }
662
663 // If user has already finished the course.
664 if ( $this->has_finished_course( $course_id ) ) {
665 throw new Exception(
666 sprintf(
667 __( 'You can not redo a quiz in a finished course.', 'learnpress' ),
668 __CLASS__,
669 __FUNCTION__
670 ),
671 LP_COURSE_IS_FINISHED
672 );
673
674 }
675
676 // Check if user has already started or completed quiz
677 if ( ! $this->has_item_status( array( 'completed' ), $quiz_id, $course_id ) ) {
678 throw new Exception(
679 sprintf(
680 __( '%1$s::%2$s - The user has not completed the quiz.', 'learnpress' ),
681 __CLASS__,
682 __FUNCTION__
683 ),
684 LP_QUIZ_HAS_STARTED_OR_COMPLETED
685 );
686 }
687
688 $allow_attempts = learn_press_get_quiz_max_retrying( $quiz_id, $course_id );
689
690 if ( ! $this->has_retake_quiz( $quiz_id, $course_id ) ) {
691 throw new Exception(
692 sprintf(
693 __( '%1$s::%2$s - Your quiz can\'t be retaken.', 'learnpress' ),
694 __CLASS__,
695 __FUNCTION__
696 ),
697 LP_QUIZ_HAS_STARTED_OR_COMPLETED
698 );
699 }
700
701 $return = learn_press_user_retake_quiz( $quiz_id, false, $course_id, $wp_error );
702
703 do_action( 'learn-press/user/quiz-retried', $quiz_id, $course_id, $this->get_id() );
704 } catch ( Exception $ex ) {
705 $return = $wp_error ? new WP_Error( $ex->getCode(), $ex->getMessage() ) : false;
706 do_action( 'learn-press/user/retake-quiz-failure', $quiz_id, $course_id, $this->get_id() );
707 }
708
709 return $return;
710 }*/
711
712 /**
713 * Get quiz's user learning or completed
714 *
715 * @param LP_User_Items_Filter|UserItemsFilter $filter
716 *
717 * @return LP_Query_List_Table
718 */
719 public function get_user_quizzes( $filter ): LP_Query_List_Table {
720 $quizzes = [
721 'total' => 0,
722 'items' => [],
723 'pages' => 0,
724 ];
725
726 try {
727 $user_quizzes = LP_User_Items_DB::getInstance()->get_user_quizzes( $filter );
728
729 if ( $user_quizzes ) {
730 $count = LP_User_Items_DB::getInstance()->wpdb->get_var( 'SELECT FOUND_ROWS()' );
731
732 $quizzes['total'] = $count;
733 $quizzes['pages'] = ceil( $count / $filter->limit );
734
735 foreach ( $user_quizzes as $item ) {
736 $quizzes['items'][] = new LP_User_Item_Quiz( $item );
737 }
738 }
739
740 $quizzes['single'] = __( 'quiz', 'learnpress' );
741 $quizzes['plural'] = __( 'quizzes', 'learnpress' );
742 } catch ( Throwable $e ) {
743 error_log( __FUNCTION__ . ': ' . $e->getMessage() );
744 }
745
746 return new LP_Query_List_Table( $quizzes );
747 }
748
749 /**
750 * Set item is viewing in single course.
751 *
752 * @param LP_Course_Item $item
753 *
754 * @return int|LP_Course_Item
755 * @since 4.1.6.9 - move from LP_Course
756 * @editor tungnx
757 * @version 1.0.0
758 */
759 public function set_viewing_item( LP_Course_Item $item ) {
760 $flag = false;
761
762 try {
763 $user = learn_press_get_current_user();
764 if ( $user instanceof LP_User_Guest ) {
765 return $flag;
766 }
767
768 $course_id = $item->get_course_id();
769 $item_id = $item->get_id();
770 $course_data = $this->get_course_data( $course_id );
771
772 if ( $course_data && $course_data->is_enrolled() ) {
773 $item = $course_data->get_item( $item_id );
774
775 if ( ! $item ) {
776 $item = LP_User_Item::get_item_object( $item_id );
777
778 if ( ! $item ) {
779 return $flag;
780 }
781
782 if ( $item instanceof LP_User_Item_Quiz ) {
783 return $flag;
784 }
785
786 $item->set_ref_id( $course_id );
787 $item->set_parent_id( $course_data->get_user_item_id() );
788
789 $flag = $item->update();
790 }
791 }
792 } catch ( Throwable $e ) {
793 error_log( $e->getMessage() );
794 }
795
796 return $flag;
797 }
798
799 /**
800 * Get statistic info of student user
801 *
802 * @return array
803 * @since 4.1.6
804 * @version 1.0.0
805 */
806 public function get_student_statistic(): array {
807 $user = $this;
808 $statistic = array(
809 'enrolled_courses' => 0,
810 'in_progress_course' => 0,
811 'finished_courses' => 0,
812 'passed_courses' => 0,
813 'failed_courses' => 0,
814 );
815
816 try {
817 if ( ! $user ) {
818 throw new Exception( 'The user is invalid' );
819 }
820
821 $user_id = $user->get_id();
822 $lp_user_items_db = LP_User_Items_DB::getInstance();
823
824 // Count status
825 $filter = new LP_User_Items_Filter();
826 $filter->user_id = $user_id;
827 $count_status = $lp_user_items_db->count_status_by_items( $filter );
828 $total_courses_enrolled = intval( $count_status->{LP_COURSE_PURCHASED} ?? 0 )
829 + intval( $count_status->{LP_COURSE_ENROLLED} ?? 0 )
830 + intval( $count_status->{LP_COURSE_FINISHED} ?? 0 );
831
832 $statistic['enrolled_courses'] = $total_courses_enrolled;
833 $statistic['in_progress_course'] = $count_status->{LP_COURSE_GRADUATION_IN_PROGRESS} ?? 0;
834 $statistic['finished_courses'] = $count_status->{LP_COURSE_FINISHED} ?? 0;
835 $statistic['passed_courses'] = $count_status->{LP_COURSE_GRADUATION_PASSED} ?? 0;
836 $statistic['failed_courses'] = $count_status->{LP_COURSE_GRADUATION_FAILED} ?? 0;
837 } catch ( Throwable $e ) {
838 error_log( __FUNCTION__ . ': ' . $e->getMessage() );
839 }
840
841 return apply_filters( 'lp/profile/student/statistic', $statistic, $this );
842 }
843
844 /**
845 * Get statistic info of instructor user
846 *
847 * @param array $params
848 *
849 * @return array
850 * @since 4.1.6
851 * @version 1.0.1
852 */
853 public function get_instructor_statistic( array $params = [] ): array {
854 $statistic = array(
855 'total_course' => 0,
856 'published_course' => 0,
857 'pending_course' => 0,
858 'total_student' => 0,
859 'student_completed' => 0,
860 'student_in_progress' => 0,
861 );
862
863 try {
864 $user_id = $this->get_id();
865 $lp_user_items_db = LP_User_Items_DB::getInstance();
866 $lp_course_db = LP_Course_DB::getInstance();
867
868 if ( ! $this->can_create_course() ) {
869 throw new Exception( 'The user is not Instructor' );
870 }
871
872 // Count total user completed course of author
873 $filter_course = new LP_Course_Filter();
874 $filter_course->only_fields = array( 'ID' );
875 $filter_course->post_author = $user_id;
876 $filter_course->post_status = 'publish';
877 $filter_course->return_string_query = true;
878 $query_courses_str = LP_Course_DB::getInstance()->get_courses( $filter_course );
879
880 $filter_count_users = new LP_User_Items_Filter();
881 $filter_count_users->item_type = LP_COURSE_CPT;
882 $filter_count_users->where[] = "AND item_id IN ({$query_courses_str})";
883 $count_student_has_status = $lp_user_items_db->count_status_by_items( $filter_count_users );
884 // Count total user in progress course of author
885
886 // Get total users attend course of author
887 $filter_count_users = $lp_user_items_db->count_user_attend_courses_of_author( $user_id );
888 $count_users_attend_courses_of_author = $lp_user_items_db->get_user_courses( $filter_count_users );
889
890 // Get total courses publish of author
891 $filter_count_courses = $lp_course_db->count_courses_of_author( $user_id, [ 'publish' ] );
892 $total_courses_publish_of_author = $lp_course_db->get_courses( $filter_count_courses );
893
894 // Get total courses of author
895 $filter_count_courses = $lp_course_db->count_courses_of_author( $user_id );
896 $total_courses_of_author = $lp_course_db->get_courses( $filter_count_courses );
897
898 // Get total courses pending of author
899 $filter_count_courses = $lp_course_db->count_courses_of_author( $user_id, [ 'pending' ] );
900 $total_courses_pending_of_author = $lp_course_db->get_courses( $filter_count_courses );
901
902 $statistic['total_course'] = $total_courses_of_author;
903 $statistic['published_course'] = $total_courses_publish_of_author;
904 $statistic['pending_course'] = $total_courses_pending_of_author;
905 $statistic['total_student'] = $count_users_attend_courses_of_author;
906 $statistic['student_completed'] = $count_student_has_status->{LP_COURSE_FINISHED} ?? 0;
907 $statistic['student_in_progress'] = $count_student_has_status->{LP_COURSE_GRADUATION_IN_PROGRESS} ?? 0;
908 } catch ( Throwable $e ) {
909 error_log( __FUNCTION__ . ': ' . $e->getMessage() );
910 }
911
912 return apply_filters( 'lp/profile/instructor/statistic', $statistic, $this );
913 }
914
915 /**
916 * Get url instructor.
917 *
918 * @return string
919 * @version 1.0.1
920 * @since 4.2.3
921 */
922 public function get_url_instructor(): string {
923 $single_instructor_link = '';
924
925 try {
926 $author_id = $this->get_id();
927 $userModel = UserModel::find( $author_id, true );
928 if ( ! $userModel ) {
929 throw new Exception( 'User not found' );
930 }
931
932 $single_instructor_page_id = learn_press_get_page_id( 'single_instructor' );
933 $user_slug = $userModel->get_slug_link();
934 $single_instructor_link = trailingslashit( trailingslashit( get_page_link( $single_instructor_page_id ) ) . $user_slug );
935 } catch ( Throwable $e ) {
936 LP_Debug::error_log( $e );
937 }
938
939 return $single_instructor_link;
940 }
941 }
942