PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.1.7.2
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.1.7.2
4.4.8 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 All 139 releases
learnpress / inc / user / abstract-lp-user.php

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

1,432 lines 32.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Class LP_Abstract_User
5 *
6 * @author ThimPress
7 * @package LearnPress/Classes
8 * @version 3.0.0
9 */
10
11 /**
12 * Prevent loading this file directly
13 */
14 defined( 'ABSPATH' ) || exit();
15
16 if ( ! class_exists( 'LP_Abstract_User' ) ) {
17
18 /**
19 * Class LP_Abstract_User
20 */
21 class LP_Abstract_User extends LP_Abstract_Object_Data {
22
23 /**
24 * @var WP_User object
25 */
26 public $user = false;
27
28 /**
29 * @var null
30 */
31 public $profile_picture_src = null;
32
33 /**
34 * @var null
35 */
36 public $profile_picture_type = null;
37
38 /**
39 * @var array
40 */
41 protected $_data = array(
42 'email' => '',
43 'user_login' => '',
44 'description' => '',
45 'first_name' => '',
46 'last_name' => '',
47 'nickname' => '',
48 'display_name' => '',
49 'date_created' => '',
50 'date_modified' => '',
51 'role' => '',
52 'roles' => array(),
53 );
54
55 /**
56 * @var LP_User_CURD
57 */
58 protected $_curd = null;
59
60 /**
61 * LP_Abstract_User constructor.
62 *
63 * @param int $the_user
64 * @param array $args
65 */
66 public function __construct( $the_user = 0, $args = array() ) {
67
68 parent::__construct( $the_user, $args );
69
70 $this->_curd = new LP_User_CURD();
71
72 if ( is_numeric( $the_user ) && $the_user > 0 ) {
73 $this->set_id( $the_user );
74 } elseif ( $the_user instanceof self ) {
75 $this->set_id( absint( $the_user->get_id() ) );
76 } elseif ( ! empty( $the_user->ID ) ) {
77 $this->set_id( absint( $the_user->ID ) );
78 }
79
80 if ( $this->get_id() > 0 ) {
81 $this->load();
82 }
83
84 }
85
86 /**
87 * Load user data from curd
88 */
89 public function load() {
90 $this->_curd->load( $this );
91 }
92
93 /**
94 * Get data for a course user has enrolled.
95 *
96 * @param int $course_id .
97 *
98 * @return LP_User_Item_Course|bool
99 * @version 3.1.3
100 * @editor tungnx
101 * @modify 4.1.3
102 */
103 public function get_course_data( int $course_id = 0 ) {
104 $lp_user_items_db = LP_User_Items_DB::getInstance();
105
106 try {
107 if ( ! $course_id ) {
108 $course_id = get_the_ID();
109 }
110
111 /*if ( $this instanceof LP_User_Guest ) {
112 throw new Exception( 'User is Guest' );
113 }*/
114
115 $filter = new LP_User_Items_Filter();
116 $filter->item_id = $course_id;
117 $filter->user_id = $this->get_id();
118 $last_user_course = $lp_user_items_db->get_last_user_course( $filter );
119
120 if ( $last_user_course ) {
121 $object_course_data = new LP_User_Item_Course( $last_user_course );
122 } else {
123 $object_course_data = false;
124 /**
125 * Todo: some themes still not check false, so still use below code.\
126 * @editor tungnx 4.1.6.9
127 */
128 $object_course_data = new LP_User_Item_Course( $course_id );
129 }
130 } catch ( Throwable $e ) {
131 $object_course_data = false;
132 }
133
134 return $object_course_data;
135 }
136
137 /**
138 * Get user course item.
139 *
140 * @param int $item_id
141 * @param int $course_id
142 * @param string $field - Optional. Value of field to return.
143 *
144 * @return LP_User_Item_Quiz|LP_User_Item|bool
145 */
146 public function get_item_data( $item_id, $course_id, $field = '' ) {
147 $user_item = $this->get_user_item( $item_id, $course_id );
148
149 switch ( $field ) {
150 case 'end_time':
151 return $user_item->get_end_time();
152 }
153
154 return $user_item;
155 }
156
157 /**
158 * Get data for a item user started in table user-items
159 *
160 * @param int $item_id
161 * @param int $course_id
162 *
163 * @return LP_User_Item_Quiz|LP_User_Item|bool
164 */
165 public function get_user_item( $item_id, $course_id ) {
166 $data = false;
167
168 $course_data = $this->get_course_data( $course_id );
169
170 if ( $course_data ) {
171 $data = $course_data->get_item( $item_id );
172 }
173
174 return $data;
175 }
176
177 /**
178 * Return TRUE if user has used function for checking the question.
179 *
180 * @param int $question_id
181 * @param int $quiz_id
182 * @param int $course_id
183 *
184 * @return mixed
185 * @since 3.0.0
186 */
187 public function has_checked_question( $question_id, $quiz_id, $course_id = 0 ) {
188 $checked = false;
189
190 if ( $this->get_quiz_data( $quiz_id, $course_id ) ) {
191 $data = $this->get_quiz_data( $quiz_id, $course_id );
192 $checked = $data->has_checked_question( $question_id );
193 }
194
195 return apply_filters(
196 'learn-press/user/checked-question',
197 $checked,
198 $question_id,
199 $quiz_id,
200 $course_id,
201 $this->get_id()
202 );
203 }
204
205 /**
206 * Magic function to get user data
207 *
208 * @param $key
209 *
210 * @return bool
211 */
212 public function __get( $key ) {
213 $return = false;
214
215 if ( strtolower( $key ) !== 'id' ) {
216 _deprecated_argument( __CLASS__ . '::' . $key, '3.0.0' );
217 }
218
219 if ( ! empty( $this->user->data->{$key} ) ) {
220 $return = $this->user->data->{$key};
221 } else {
222 if ( isset( $this->{$key} ) ) {
223 $return = $this->{$key};
224 } elseif ( strpos( $key, '_lp_' ) === false ) {
225 $key = '_lp_' . $key;
226 $return = get_user_meta( $this->get_id(), $key, true );
227 if ( ! empty( $value ) ) {
228 $this->$key = $return;
229 }
230 }
231 }
232
233 return $return;
234 }
235
236 /**
237 * Check if a course is exists then return it's ID.
238 * Try to get it from global.
239 *
240 * @param int $course_id
241 * @param string $return
242 *
243 * @return bool|false|int|LP_Course
244 */
245 protected function _get_course( $course_id, $return = 'id' ) {
246
247 // if $course_id is not passed then try to get it from global
248 if ( ! $course_id && learn_press_is_course() ) {
249 $course_id = get_the_ID();
250 }
251
252 // Validate course
253 $course = learn_press_get_course( $course_id );
254
255 if ( $course ) {
256 switch ( $return ) {
257 case 'id':
258 return $course_id;
259 case 'object':
260 return $course;
261 }
262 }
263
264 return false;
265 }
266
267 /**
268 *
269 * @param int $item_id
270 * @param int $course_id
271 *
272 * @return bool
273 *
274 * @since 3.0.0
275 */
276 protected function _verify_course_item( $item_id, $course_id = 0 ) {
277 $course = $this->_get_course( $course_id, 'object' );
278
279 if ( false !== $course ) {
280 return $course->has_item( $item_id ) ? $course_id : false;
281 }
282
283 return false;
284 }
285
286 /**
287 * Return TRUE if an item has a status.
288 *
289 * @param array $statuses
290 * @param int $item_id
291 * @param int $course_id
292 *
293 * @return mixed
294 *
295 * @since 3.0.0
296 */
297 public function has_item_status( $statuses, $item_id, $course_id ) {
298 settype( $statuses, 'array' );
299 $status = $this->get_item_status( $item_id, $course_id );
300
301 //Todo: tungnx
302 //$status = $this->getItemStatus( $item_id, $course_id );
303
304 return apply_filters(
305 'learn-press/user-has-item-status',
306 in_array( $status, $statuses ),
307 $statuses,
308 $item_id,
309 $course_id,
310 $this->get_id()
311 );
312 }
313
314 /**
315 * Get all records of an item.
316 *
317 * @param int $item_id
318 * @param int $course_id
319 * @param bool $return_last
320 *
321 * @return bool|mixed
322 */
323 public function get_item_archive( $item_id, $course_id = 0, $return_last = false ) {
324 $records = LP_Object_Cache::get(
325 'course-item-' . $this->get_id() . '-' . $course_id . '-' . $item_id,
326 'lp-user-course-items'
327 );
328
329 if ( $records ) {
330 // $records = array_filter( $records );
331 }
332
333 if ( $return_last && is_array( $records ) ) {
334 $records = reset( $records );
335 }
336
337 return $records;
338 }
339
340 /**
341 * Check quiz can retake?
342 *
343 * @param [type] $quiz_id
344 * @param [type] $course_id
345 *
346 * @return boolean
347 */
348 public function has_retake_quiz( $quiz_id, $course_id ): bool {
349 $user_quiz = $this->get_item_data( $quiz_id, $course_id );
350 $flag = false;
351
352 if ( $user_quiz ) {
353 $retaken = $user_quiz->get_retaken_count();
354 $retake_config = get_post_meta( $quiz_id, '_lp_retake_count', true );
355
356 if ( $retake_config == '-1' ) { // For no limit
357 $flag = true;
358 } elseif ( absint( $retaken ) < absint( $retake_config ) ) {
359 $flag = true;
360 }
361 }
362
363 return apply_filters( 'lp/quiz/can-retake', $flag );
364 }
365
366 /**
367 * Get quiz status for the user
368 *
369 * @param int $quiz_id
370 * @param int $course_id
371 *
372 * @return mixed
373 */
374 public function get_quiz_status( $quiz_id, $course_id = 0 ) {
375 return $this->get_item_status( $quiz_id, $course_id );
376 }
377
378 /**
379 * Get quiz status for the user
380 *
381 * @param int $lesson_id
382 * @param int $course_id
383 *
384 * @return mixed
385 */
386 public function get_lesson_status( $lesson_id, $course_id = 0 ) {
387 return $this->get_item_status( $lesson_id, $course_id );
388 }
389
390 /**
391 * @param int $item_id
392 * @param int $course_id
393 * @param bool $last
394 *
395 * @return mixed
396 * @since 3.0.0
397 */
398 public function get_item( $item_id, $course_id = 0, $last = false ) {
399 if ( ! $course_id ) {
400 $course_id = get_the_ID();
401 }
402
403 if ( ! $course_id ) {
404 return false;
405 }
406
407 $course_data = $this->get_course_data( $course_id );
408 if ( $course_data ) {
409 return $course_data->get_item( $item_id );
410 }
411
412 return false;
413 }
414
415 /**
416 * @param int $item_id
417 * @param int $course_id
418 *
419 * @return mixed
420 * @since 3.0.0
421 * @version 1.0.1
422 * @editor tungnx
423 * @modify 4.1.4.1
424 */
425 public function get_item_grade( $item_id, $course_id = 0 ) {
426 if ( ! $course_id ) {
427 $course_id = get_the_ID();
428 }
429
430 $grade = false;
431
432 $course_data = $this->get_course_data( $course_id );
433
434 if ( $course_data ) {
435 $grade = $course_data->get_item_result( $item_id, 'grade' );
436 }
437
438 return apply_filters( 'learn-press/user-item-grade', $grade, $item_id, $this->get_id(), $course_id );
439 }
440
441 /**
442 * Get current status of an item for user.
443 *
444 * @param int $item_id
445 * @param int $course_id
446 *
447 * @return bool|mixed
448 */
449 public function get_item_status( $item_id, $course_id = 0 ) {
450 $status = '';
451
452 if ( ! $course_id ) {
453 $course_id = get_the_ID();
454 }
455
456 if ( ! $course_id ) {
457 return $status;
458 }
459
460 $item = $this->get_item( $item_id, $course_id, true );
461
462 if ( false !== $item ) {
463 $status = $item['status'];
464 }
465
466 return apply_filters( 'learn-press/user-item-status', $status, $item_id, $this->get_id(), $course_id );
467 }
468
469 /**
470 * Checks if has status of a quiz for user
471 *
472 * @param string|array $statuses
473 * @param int $quiz_id
474 * @param int $course_id
475 * @param boolean $force
476 *
477 * @return bool
478 */
479 public function has_quiz_status( $statuses, $quiz_id, $course_id = 0, $force = false ) {
480 $status = $this->get_quiz_status( $quiz_id, $course_id );
481
482 settype( $statuses, 'array' );
483
484 return apply_filters(
485 'learn_press_user_has_quiz_status',
486 in_array( $status, $statuses ),
487 $statuses,
488 $status,
489 $quiz_id,
490 $course_id,
491 $this->get_id()
492 );
493 }
494
495 /**
496 * Get current results of a quiz
497 *
498 * @param int $quiz_id
499 * @param int $course_id
500 * @param string $prop
501 *
502 * @return mixed
503 */
504 public function get_quiz_results( $quiz_id, $course_id = 0, $prop = 'result' ) {
505 $user_quiz = $this->get_item_data( $quiz_id, $course_id );
506
507 return $user_quiz ? $user_quiz->get_results( $prop ) : false;
508 }
509
510 /**
511 * Get current progress of user's quiz.
512 *
513 * @param int $quiz_id
514 * @param int $course_id
515 *
516 * @return LP_User_Item_Quiz|false
517 */
518 public function get_quiz_data( $quiz_id, $course_id = 0 ) {
519 $result = false;
520 $course_result = $this->get_course_data( $course_id );
521 if ( $course_result ) {
522 $result = $course_result->get_item( $quiz_id );
523 }
524
525 return $result;
526 }
527
528 /**
529 * Mark question that user has checked.
530 *
531 * @param int $question_id
532 * @param int $quiz_id
533 * @param int $course_id
534 *
535 * @return WP_Error|mixed
536 * @since 3.0.0
537 */
538 public function hint( $question_id, $quiz_id, $course_id ) {
539 $course = learn_press_get_course( $course_id );
540 if ( ! $course ) {
541 return false;
542 }
543
544 if ( ! $course->has_item( $quiz_id ) ) {
545 return false;
546 }
547
548 /**
549 * @var $quiz LP_Quiz
550 */
551 $quiz = $course->get_item( $quiz_id );
552 if ( ! $quiz instanceof LP_Course_Item_Quiz ) {
553 return false;
554 }
555
556 if ( ! $quiz->has_question( $question_id ) ) {
557 return false;
558 }
559
560 $quiz_data = $this->get_item_data( $quiz_id, $course_id );
561 $remain = $quiz_data->hint( $question_id );
562 if ( false === $remain ) {
563 return new WP_Error( 1001, __( 'You can not hint question.', 'learnpress' ) );
564 }
565
566 return $remain;
567 }
568
569 public function get_quiz_last_results( $quiz_id ) {
570 $results = $this->get_course_info( $quiz_id );
571 if ( $results ) {
572 $results = reset( $results );
573 }
574
575 return apply_filters( 'learn_press_user_quiz_last_results', $results, $quiz_id, $this );
576 }
577
578 /**
579 * Check if user has at least one role.
580 *
581 * @param array|string $roles
582 *
583 * @return array
584 */
585 public function has_role( $roles ) {
586 settype( $roles, 'array' );
587
588 return array_intersect( $roles, $this->get_roles() );
589 }
590
591 /**
592 * Detect the type of user
593 *
594 * @param string|int $type
595 *
596 * @return bool
597 */
598 public function is( $type ) {
599 $is = false;
600 if ( $type === 'current' ) {
601 $is = $this->is( get_current_user_id() );
602 } elseif ( is_string( $type ) ) {
603 $name = preg_replace( '!LP_User(_?)!', '', get_class( $this ) );
604 $is = strtolower( $name ) == strtolower( $type );
605 } elseif ( is_numeric( $type ) ) {
606 $is = $this->get_id() && ( $this->get_id() == $type );
607 }
608
609 return $is;
610 }
611
612 /**
613 *
614 * Check what the user can do
615 *
616 * @param $role
617 *
618 * @return mixed
619 * @throws Exception
620 */
621 public function can( $role ) {
622 _deprecated_function( __FUNCTION__, '3.0.8' );
623 $args = func_get_args();
624 unset( $args[0] );
625 $method = 'can_' . preg_replace( '!-!', '_', $role );
626 $callback = array( $this, $method );
627 if ( is_callable( $callback ) ) {
628 return call_user_func_array( $callback, $args );
629 } else {
630 throw new Exception( sprintf( __( 'The role %s for user doesn\'t exist', 'learnpress' ), $role ) );
631 }
632 }
633
634 public function can_edit_item( $item_id, $course_id = 0 ) {
635 $return = $this->is_admin();
636
637 if ( ! $return ) {
638 $course_id = $this->_get_course( $course_id );
639
640 $course_author = learn_press_get_course_user( $course_id );
641 if ( $course_author && $course_author->get_id() == $this->get_id() ) {
642 $return = true;
643 }
644 }
645
646 return apply_filters( 'learn_press_user_can_edit_item', $return, $item_id, $course_id, $this->get_id() );
647 }
648
649 /**
650 * Check if user can finish course by getting current progress
651 * and compares with course passing condition.
652 *
653 * @param int $course_id
654 *
655 * @return bool
656 * @editor tungnx
657 * @modify 4.1.3
658 */
659 public function can_finish_course( int $course_id ) {
660 _deprecated_function( __FUNCTION__, '4.1.3', 'is_course_finished' );
661
662 return true;
663 }
664
665 /**
666 * Check if course has any passed status for an user.
667 * Statuses: depending on value of column `status` in user_items.
668 * - purchased: bought and order is completed, `start_date` and `end_date` is null
669 * - enrolled: value of column `status` in user_items is enrolled
670 * - started: value of column `status` in user_items is started
671 * - enrolled: value of column `status` in user_items is enrolled
672 *
673 * @param int $course_id
674 * @param string|array $statuses
675 *
676 * @return bool
677 * @since 2.0
678 */
679 public function has_course_status( $course_id, $statuses ) {
680 $status = $this->get_course_status( $course_id );
681
682 if ( is_array( $statuses ) ) {
683 return in_array( $status, $statuses );
684 } elseif ( is_string( $statuses ) ) {
685 return $statuses == $status;
686 }
687
688 return false;
689 }
690
691 /**
692 * Finish course
693 *
694 * @param int $course_id
695 *
696 * @return int|bool
697 */
698 public function finish_course( int $course_id ) {
699 $return = false;
700 $course = learn_press_get_course( $course_id );
701
702 if ( $course ) {
703 $user_course = $this->get_course_data( $course_id );
704
705 $result = $user_course->calculate_course_results();
706
707 // Save result for course
708 LP_User_Items_Result_DB::instance()->update( $user_course->get_user_item_id(), wp_json_encode( $result ) );
709
710 if ( $result['pass'] ) {
711 $graduation = LP_COURSE_GRADUATION_PASSED;
712 } else {
713 $graduation = LP_COURSE_GRADUATION_FAILED;
714 }
715
716 $user_course->set_graduation( $graduation );
717 $user_course->save();
718
719 $return = $user_course->complete( 'finished' );
720
721 if ( $return ) {
722 do_action( 'learn-press/user-course-finished', $course_id, $this->get_id(), $return );
723 }
724 }
725
726 return apply_filters( 'learn-press/user-course-finished-data', $return, $course_id, $this->get_id() );
727 }
728
729 /**
730 * Check user instructor.
731 *
732 * @return bool
733 */
734 public function is_instructor(): bool {
735
736 $roles = $this->get_data( 'roles' ) ? $this->get_data( 'roles' ) : array();
737
738 return in_array( LP_TEACHER_ROLE, $roles );
739 }
740
741 /**
742 * Check user admin.
743 *
744 * @return bool
745 */
746 public function is_admin() {
747 $roles = $this->get_data( 'roles' ) ? $this->get_data( 'roles' ) : array();
748
749 return in_array( 'administrator', $roles );
750 }
751
752
753 public function can_create_course() {
754 return $this->is_instructor() || $this->is_admin();
755 }
756
757 /**
758 * Wrap function to check this user is author of a post.
759 *
760 * @param int $post_id
761 *
762 * @return bool
763 * @since 3.1.0
764 */
765 public function is_author_of( $post_id ) {
766 return absint( get_post_field( 'post_author', $post_id ) ) === $this->get_id();
767 }
768
769 public function has( $role ) {
770 _deprecated_function( __FUNCTION__, '3.0.8' );
771
772 $args = func_get_args();
773 unset( $args[0] );
774 $method = 'has_' . preg_replace( '!-!', '_', $role );
775 $callback = array( $this, $method );
776 if ( is_callable( $callback ) ) {
777 return call_user_func_array( $callback, $args );
778 } else {
779 throw new Exception( sprintf( __( 'The role %s for user doesn\'t exist', 'learnpress' ), $role ) );
780 }
781 }
782
783 public function get( $role ) {
784 $args = func_get_args();
785 unset( $args[0] );
786 $method = 'get_' . preg_replace( '!-!', '_', $role );
787 $callback = array( $this, $method );
788 if ( is_callable( $callback ) ) {
789 return call_user_func_array( $callback, $args );
790 } else {
791 throw new Exception( sprintf( __( 'The role %s for user doesn\'t exist', 'learnpress' ), $role ) );
792 }
793 }
794
795 /**
796 * Check user has passed course.
797 *
798 * @param $course_id
799 *
800 * @return mixed
801 */
802 public function has_passed_course( $course_id ) {
803 $user_course = $this->get_course_data( $course_id );
804
805 return $user_course && $user_course->is_passed();
806 }
807
808 /**
809 * Checks if user has started a quiz
810 * - FALSE if user has not started quiz
811 * - String if user has started quiz (status of quiz)
812 *
813 * @param int $quiz_id
814 * @param int $course_id
815 *
816 * @return mixed
817 */
818 public function has_started_quiz( $quiz_id, $course_id = 0 ) {
819 $course_id = $this->_get_course( $course_id );
820 $started = false;
821 $started = $this->has_quiz_status( array( 'started', 'completed' ), $quiz_id, $course_id );
822
823 return apply_filters( 'learn_press_user_started_quiz', $started, $quiz_id, $course_id, $this->get_id() );
824 }
825
826 /**
827 * Return true if user has completed a quiz
828 *
829 * @param int $quiz_id
830 * @param int $course_id
831 *
832 * @return bool
833 * @depecated 4.1.6.9
834 */
835 /*public function has_completed_quiz( $quiz_id, $course_id = 0 ): bool {
836 return $this->get_item_status( $quiz_id, $course_id ) == 'completed';
837 }*/
838
839 /**
840 * Mark a lesson is completed for user
841 *
842 * @param int $lesson_id
843 * @param int $course_id
844 *
845 * @return bool|WP_Error
846 */
847 public function complete_lesson( $lesson_id = 0, $course_id = 0 ) {
848 $result = true;
849
850 try {
851 $course = learn_press_get_course( $course_id );
852 if ( ! $course ) {
853 throw new Exception( __( 'Invalid course', 'learnpress' ) );
854 }
855
856 $course_data = $this->get_course_data( $course_id );
857 if ( ! $course_data ) {
858 throw new Exception( __( 'You must enroll course!', 'learnpress' ) );
859 }
860
861 /**
862 * If user has stared a lesson, get user lesson information
863 */
864 $item = $course_data->get_item( $lesson_id );
865 if ( ! $item ) {
866 throw new Exception( __( 'Invalid lesson', 'learnpress' ) );
867 }
868
869 if ( $item->is_completed() ) {
870 throw new Exception( __( 'You have already completed this lesson.', 'learnpress' ) );
871 }
872
873 $item->set_end_time( time() );
874 $item->set_status( 'completed' );
875 $item->set_graduation( 'passed' );
876
877 $updated = $item->update();
878
879 do_action( 'learn-press/user-completed-lesson', $lesson_id, $course_id, $this->get_id() );
880 } catch ( Throwable $e ) {
881 $result = new WP_Error( 'error_lesson_complete', $e->getMessage() );
882 }
883
884 return $result;
885 }
886
887 /**
888 * Returns TRUE if user has already completed a lesson
889 *
890 * @param int $lesson_id Lesson id.
891 * @param null $course_id Course id.
892 *
893 * @return bool
894 * @depecated 4.1.6.9
895 */
896 public function has_completed_lesson( $lesson_id = 0, $course_id = null ): bool {
897 return 'completed' === $this->get_item_status( $lesson_id, $course_id );
898 }
899
900 /**
901 * Return current status of course for user
902 *
903 * @param int $course_id
904 * @param string $field
905 * @param bool $force
906 *
907 * @return mixed
908 */
909 public function get_course_info( int $course_id, $field = null, $force = false ) {
910 $user_data = $this->get_course_data( $course_id );
911 if ( $user_data ) {
912 return $user_data->get_results( $field );
913 }
914
915 return false;
916 }
917
918 /**
919 * @param $course_id
920 *
921 * @return int
922 * @depecated 4.1.6.9
923 */
924 public function get_course_history_id( $course_id ) {
925 $history = $this->get_course_info( $course_id );
926
927 return ! empty( $history['history_id'] ) ? $history['history_id'] : 0;
928 }
929
930 /**
931 * Get current status of a course for user.
932 *
933 * @param int $course_id
934 *
935 * @return mixed
936 * @editor tungnx
937 * @modify 4.1.3
938 * @version 1.0.1
939 */
940 public function get_course_status( int $course_id ): string {
941 $status = '';
942
943 try {
944 $user_data = $this->get_course_data( $course_id );
945
946 if ( $user_data ) {
947 $status = $user_data->get_status();
948 }
949 } catch ( Throwable $e ) {
950 if ( LP_Debug::is_debug() ) {
951 error_log( $e->getMessage() );
952 }
953 }
954
955 return apply_filters( 'learn-press/user-course-status', $status, $course_id, $this->get_id() );
956 }
957
958 /**
959 * Get order status of a course.
960 *
961 * @param int $course_id
962 *
963 * @return mixed
964 */
965 public function get_order_status( $course_id ) {
966 try {
967 $order = $this->get_course_order( $course_id );
968
969 if ( ! $order ) {
970 throw new Exception( 'Order not exists' );
971 }
972
973 $order_status = apply_filters(
974 'learn-press/course-order-status',
975 get_post_status( $order->get_id() ),
976 $course_id,
977 $this->get_id()
978 );
979 } catch ( Throwable $e ) {
980 $order_status = false;
981 }
982
983 return $order_status;
984 }
985
986 /**
987 * Check item completed.
988 *
989 * @param $item
990 * @param int $course_id
991 * @param bool $force
992 *
993 * @return mixed|void
994 * @version 3.0.1
995 * @since 3.0.0
996 */
997 public function has_completed_item( $item, $course_id = 0, $force = false ) {
998 $course_id = $this->_get_course( $course_id );
999
1000 $return = false;
1001 $item_id = 0;
1002 if ( is_numeric( $item ) ) {
1003 $item_id = absint( $item );
1004 } else {
1005 settype( $item, 'array' );
1006 if ( ! empty( $item['ID'] ) ) {
1007 $item_id = absint( $item['ID'] );
1008 }
1009 }
1010
1011 if ( $item_id ) {
1012 $return = 'completed' === $this->get_item_status( $item_id, $course_id );
1013 }
1014
1015 return apply_filters( 'learn_press_user_has_completed_item', $return, $item );
1016 }
1017
1018 /**
1019 * Get the remaining time of a course for the user.
1020 *
1021 * @param int $course_id
1022 *
1023 * @return bool|int|string
1024 */
1025 public function get_course_remaining_time( $course_id ) {
1026 $course = learn_press_get_course( $course_id );
1027 $remain = false;
1028
1029 if ( $course && $course->get_id() ) {
1030 $course_data = $this->get_course_data( $course_id, true );
1031 if ( $course_data ) {
1032 $remain = $course_data->is_exceeded();
1033 }
1034 }
1035
1036 return $remain > 0 ? learn_press_seconds_to_weeks( $remain ) : false;
1037 }
1038
1039 /**
1040 * Get the order that contains the course.
1041 *
1042 * @param int $course_id
1043 *
1044 * @return bool|LP_Order
1045 * @editor tungnx
1046 * @throws Exception
1047 * @version 1.0.2
1048 * @since 4.1.1
1049 */
1050 public function get_course_order( int $course_id ) {
1051 $lp_order = false;
1052 $lp_order_db = LP_Order_DB::getInstance();
1053 $lp_order_id = $lp_order_db->get_last_lp_order_id_of_user_course( $this->get_id(), $course_id );
1054
1055 if ( $lp_order_id ) {
1056 $lp_order = new LP_Order( $lp_order_id );
1057 }
1058
1059 return $lp_order;
1060 }
1061
1062 /**
1063 * @param $question_id
1064 *
1065 * @return null|string
1066 */
1067 public function get_quiz_by_question( $question_id ) {
1068 global $wpdb;
1069 $query = $wpdb->prepare(
1070 "
1071 SELECT quiz_id
1072 FROM {$wpdb->prefix}learnpress_user_items uq
1073 INNER JOIN {$wpdb->prefix}learnpress_user_itemmeta uqm ON uqm.learnpress_user_item_id = uq.user_item_id AND uqm.meta_key = %s AND uqm.meta_value LIKE %s
1074 ",
1075 'questions',
1076 '%i:' . $wpdb->esc_like( $question_id . '' ) . ';%'
1077 );
1078
1079 return $wpdb->get_var( $query );
1080 }
1081
1082 /**
1083 * @param $question_id
1084 * @param null $quiz_id
1085 *
1086 * @return bool
1087 */
1088 public function get_answer_results( $question_id, $quiz_id = null ) {
1089
1090 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '3.0.0' );
1091
1092 $data = false;
1093 if ( ! $quiz_id ) {
1094 $quiz_id = $this->get_quiz_by_question( $question_id );
1095 }
1096 if ( $quiz_id ) {
1097 $question = LP_Question::get_question( $question_id );
1098
1099 if ( $question ) {
1100 $quiz_results = $this->get_quiz_results( $quiz_id );
1101 if ( ! empty( $quiz_results->question_answers ) ) {
1102 $question_answer = array_key_exists(
1103 $question_id,
1104 $quiz_results->question_answers
1105 ) ? $quiz_results->question_answers[ $question_id ] : null;
1106 $data = $question->check( $question_answer );
1107 }
1108 }
1109 }
1110
1111 return $data;
1112 }
1113
1114 /**
1115 * @param $question_id
1116 * @param null $quiz_id
1117 *
1118 * @return bool
1119 */
1120 public function is_answered_question( $question_id, $quiz_id = null ) {
1121 if ( empty( $this->answered_questions ) ) {
1122 $this->answered_questions = array();
1123 }
1124 if ( ! $quiz_id ) {
1125 $quiz_id = $this->get_quiz_by_question( $question_id );
1126 }
1127
1128 $results = $this->get_quiz_results( $quiz_id );
1129 $answered = ! empty( $results->question_answers ) ? $results->question_answers : array();
1130
1131 return $answered ? array_key_exists( $question_id, $answered ) : false;
1132 }
1133
1134 /**
1135 * @return array
1136 */
1137 public function get_roles() {
1138 return (array) $this->get_data( 'roles' );
1139 }
1140
1141 /**
1142 * @param $question_id
1143 * @param $quiz_id
1144 * @param int $course_id
1145 *
1146 * @return bool
1147 */
1148 public function has_checked_answer( $question_id, $quiz_id, $course_id = 0 ) {
1149 if ( ! $course_id ) {
1150 $course_id = get_the_ID();
1151 }
1152
1153 $quiz_data = $this->get_item_data( $quiz_id, $course_id );
1154
1155 return $quiz_data ? $quiz_data->has_checked_question( $question_id ) : false;
1156 }
1157
1158 /**
1159 * @param $question_id
1160 * @param $quiz_id
1161 * @param int $course_id
1162 *
1163 * @return bool
1164 */
1165 public function has_hinted_answer( $question_id, $quiz_id, $course_id = 0 ) {
1166 if ( ! $course_id ) {
1167 $course_id = get_the_ID();
1168 }
1169
1170 $quiz_data = $this->get_item_data( $quiz_id, $course_id );
1171
1172 return $quiz_data ? $quiz_data->has_hinted_question( $question_id ) : false;
1173 }
1174
1175 /**
1176 * Return TRUE if user is already exists.
1177 *
1178 * @return bool
1179 */
1180 public function is_exists() {
1181 return ! ! get_user_by( 'id', $this->get_id() );
1182 }
1183
1184 /**
1185 * Check if the user is logged in.
1186 *
1187 * @return bool
1188 */
1189 public function is_logged_in() {
1190 return $this->get_id() == get_current_user_id();
1191 }
1192
1193 /**
1194 * Get upload profile src
1195 * Option: null: get origin picture, "thumbnail": get thumbnail picture
1196 *
1197 * @param mixed $size
1198 *
1199 * @return string
1200 */
1201 public function get_upload_profile_src( $size = '' ) {
1202 return LP_Profile::instance( $this->get_id() )->get_upload_profile_src( $size );
1203 }
1204
1205 /**
1206 * @param string $type
1207 * @param int $size
1208 * @param bool $src_only
1209 *
1210 * @return false|string
1211 */
1212 public function get_profile_picture( $type = '', $size = 96, $src_only = false ) {
1213 return LP_Profile::instance( $this->get_id() )->get_profile_picture( $type, $size );
1214 }
1215
1216 /**
1217 * Get links socials of use on Profile page
1218 *
1219 * @param int $user_id
1220 * @return array
1221 */
1222 public function get_profile_socials( int $user_id = 0 ): array {
1223 $socials = array();
1224 $extra_info = learn_press_get_user_extra_profile_info( $user_id );
1225
1226 if ( $extra_info ) {
1227 foreach ( $extra_info as $k => $v ) {
1228 if ( empty( $v ) ) {
1229 continue;
1230 }
1231
1232 switch ( $k ) {
1233 case 'facebook':
1234 $i = '<i class="fab fa-facebook-f"></i>';
1235 break;
1236 case 'twitter':
1237 $i = '<i class="fab fa-twitter"></i>';
1238 break;
1239 case 'googleplus':
1240 $i = '<i class="fab fa-google-plus-g"></i>';
1241 break;
1242 case 'youtube':
1243 $i = '<i class="fab fa-youtube"></i>';
1244 break;
1245 default:
1246 $i = sprintf( '<i class="fab fa-%s"></i>', $k );
1247 }
1248
1249 $icon = apply_filters(
1250 'learn-press/user-profile-social-icon',
1251 $i,
1252 $k,
1253 $this->get_id(),
1254 $this
1255 );
1256 $socials[ $k ] = sprintf( '<a href="%s">%s</a>', esc_url_raw( $v ), $icon );
1257 }
1258 }
1259
1260 return apply_filters( 'learn-press/user-profile-socials', $socials, $this->get_id(), $this );
1261 }
1262
1263 /**
1264 * Check course of user has graduation is in-progress
1265 *
1266 * @param $course_id
1267 * @return bool
1268 * @throws Exception
1269 */
1270 public function is_course_in_progress( $course_id ): bool {
1271 $user = learn_press_get_user( $this->get_id() );
1272 $user_course = $user->get_course_data( $course_id );
1273
1274 return $user_course && LP_COURSE_GRADUATION_IN_PROGRESS === $user_course->get_graduation();
1275 }
1276
1277 /**
1278 * Return TRUE if user can do a quiz
1279 *
1280 * @param $quiz_id
1281 * @param int $course_id
1282 *
1283 * @return bool
1284 * @throws Exception
1285 */
1286 public function can_do_quiz( $quiz_id, $course_id = 0 ) {
1287 $course = learn_press_get_course( $course_id );
1288
1289 if ( ! $course->is_no_required_enroll() ) {
1290 $can = $this->has_course_status( $course_id, array( 'enrolled' ) ) && ! $this->has_started_quiz( $quiz_id, $course_id );
1291 } else {
1292 $can = ! $this->has_started_quiz( $quiz_id, $course_id );
1293 }
1294
1295 return apply_filters( 'learn_press_user_can_do_quiz', $can, $quiz_id, $this->get_id(), $course_id );
1296 }
1297
1298 /**
1299 * Check if all items in course completed.
1300 *
1301 * @return boolean
1302 * @author Nhamdv <email@email.com>
1303 */
1304 public function is_completed_all_items( $course_id ) {
1305 $course = learn_press_get_course( $course_id );
1306
1307 $course_data = $this->get_course_data( $course_id );
1308
1309 $course_results = $course_data->get_result();
1310
1311 if ( ! isset( $course_results['completed_items'] ) ) {
1312 return false;
1313 }
1314
1315 return $course_results['completed_items'] >= $course->count_items();
1316 }
1317
1318 public function get_role() {
1319 return $this->is_admin() ? 'admin' : ( $this->is_instructor() ? 'instructor' : 'user' );
1320 }
1321
1322 /**
1323 * Get user course's grade.
1324 * Possible values:
1325 * + passed User has finished and passed course.
1326 * + failed User has finished but failed.
1327 * + in-progress User still is learning course.
1328 *
1329 * @param $course_id
1330 *
1331 * @return string|bool
1332 */
1333 public function get_course_grade( $course_id ) {
1334 $grade = false;
1335 $course_data = $this->get_course_data( $course_id );
1336
1337 if ( $course_data ) {
1338 $grade = $course_data->get_status( 'graduation' );
1339 }
1340
1341 return apply_filters( 'learn-press/user-course-grade', $grade, $this->get_id(), $course_id );
1342 }
1343
1344 /**
1345 * Check if user is a GUEST by checking the meta _lp_temp_user is exists.
1346 *
1347 * @return bool
1348 */
1349 public function is_guest(): bool {
1350 return ! $this->get_id() || ! get_user_by( 'id', $this->get_id() );
1351 }
1352
1353 /**
1354 * Check if user can edit a post.
1355 *
1356 * @param int $post_id
1357 *
1358 * @return bool
1359 */
1360 public function can_edit( int $post_id ): bool {
1361 if ( $this->get_id() !== get_current_user_id() ) {
1362 return false;
1363 }
1364
1365 return current_user_can( 'edit_post', $post_id );
1366 }
1367
1368 /**
1369 * Get email of user
1370 *
1371 * @return string
1372 */
1373 public function get_email(): string {
1374 return $this->get_data( 'email', '' );
1375 }
1376
1377 /**
1378 * Return user_login of the user.
1379 *
1380 * @return string
1381 */
1382 public function get_username(): string {
1383 return $this->get_data( 'user_login', '' );
1384 }
1385
1386 /**
1387 * Return user bio information.
1388 *
1389 * @return string
1390 */
1391 public function get_description(): string {
1392 return $this->get_data( 'description', '' );
1393 }
1394
1395 /**
1396 * Return user first name.
1397 *
1398 * @return string
1399 */
1400 public function get_first_name(): string {
1401 return $this->get_data( 'first_name', '' );
1402 }
1403
1404 /**
1405 * Return user last name.
1406 *
1407 * @return string
1408 */
1409 public function get_last_name(): string {
1410 return $this->get_data( 'last_name', '' );
1411 }
1412
1413 /**
1414 * Return user nickname.
1415 *
1416 * @return string
1417 */
1418 public function get_nickname(): string {
1419 return $this->get_data( 'nickname', '' );
1420 }
1421
1422 /**
1423 * Return user display name.
1424 *
1425 * @return string
1426 */
1427 public function get_display_name(): string {
1428 return $this->get_data( 'display_name', '' );
1429 }
1430 }
1431 }
1432