PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.1.7
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.1.7
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 / abstract-lp-user.php

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

2,109 lines 50.4 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 * Count number of rows for an item in user-items
342 *
343 * @param int $item_id
344 * @param int $course_id
345 *
346 * @return int
347 * @editor tungnx
348 * @modify 4.1.3 - comment - not user
349 */
350 /*public function count_item_archive( $item_id, $course_id = 0 ) {
351 $count = 0;
352
353 if ( $items = $this->get_item_archive( $item_id, $course_id ) ) {
354 $count = sizeof( $items );
355 }
356
357 return $count;
358 }*/
359
360 /**
361 * Check quiz can retake?
362 *
363 * @param [type] $quiz_id
364 * @param [type] $course_id
365 *
366 * @return boolean
367 */
368 public function has_retake_quiz( $quiz_id, $course_id ): bool {
369 $user_quiz = $this->get_item_data( $quiz_id, $course_id );
370 $flag = false;
371
372 if ( $user_quiz ) {
373 $retaken = $user_quiz->get_retaken_count();
374 $retake_config = get_post_meta( $quiz_id, '_lp_retake_count', true );
375
376 if ( $retake_config == '-1' ) { // For no limit
377 $flag = true;
378 } elseif ( absint( $retaken ) < absint( $retake_config ) ) {
379 $flag = true;
380 }
381 }
382
383 return apply_filters( 'lp/quiz/can-retake', $flag );
384 }
385
386 /**
387 * Get quiz status for the user
388 *
389 * @param int $quiz_id
390 * @param int $course_id
391 *
392 * @return mixed
393 */
394 public function get_quiz_status( $quiz_id, $course_id = 0 ) {
395 return $this->get_item_status( $quiz_id, $course_id );
396 }
397
398 /**
399 * Get quiz status for the user
400 *
401 * @param int $lesson_id
402 * @param int $course_id
403 *
404 * @return mixed
405 */
406 public function get_lesson_status( $lesson_id, $course_id = 0 ) {
407 return $this->get_item_status( $lesson_id, $course_id );
408 }
409
410 /**
411 * @param int $item_id
412 * @param int $course_id
413 * @param bool $last
414 *
415 * @return mixed
416 * @since 3.0.0
417 */
418 public function get_item( $item_id, $course_id = 0, $last = false ) {
419 if ( ! $course_id ) {
420 $course_id = get_the_ID();
421 }
422
423 if ( ! $course_id ) {
424 return false;
425 }
426
427 $course_data = $this->get_course_data( $course_id );
428 if ( $course_data ) {
429 return $course_data->get_item( $item_id );
430 }
431
432 return false;
433 }
434
435 /**
436 * @param int $item_id
437 * @param int $course_id
438 *
439 * @return mixed
440 * @since 3.0.0
441 * @version 1.0.1
442 * @editor tungnx
443 * @modify 4.1.4.1
444 */
445 public function get_item_grade( $item_id, $course_id = 0 ) {
446 if ( ! $course_id ) {
447 $course_id = get_the_ID();
448 }
449
450 $grade = false;
451
452 $course_data = $this->get_course_data( $course_id );
453
454 if ( $course_data ) {
455 $grade = $course_data->get_item_result( $item_id, 'grade' );
456 }
457
458 return apply_filters( 'learn-press/user-item-grade', $grade, $item_id, $this->get_id(), $course_id );
459 }
460
461 /**
462 * Get current status of an item for user.
463 *
464 * @param int $item_id
465 * @param int $course_id
466 *
467 * @return bool|mixed
468 */
469 public function get_item_status( $item_id, $course_id = 0 ) {
470 $status = '';
471
472 if ( ! $course_id ) {
473 $course_id = get_the_ID();
474 }
475
476 if ( ! $course_id ) {
477 return $status;
478 }
479
480 $item = $this->get_item( $item_id, $course_id, true );
481
482 if ( false !== $item ) {
483 $status = $item['status'];
484 }
485
486 return apply_filters( 'learn-press/user-item-status', $status, $item_id, $this->get_id(), $course_id );
487 }
488
489 /**
490 * To rewrite get_item_status on abstract-lp-user.
491 *
492 * @throws Exception
493 * @author tungnx
494 */
495 /*public function getItemStatus( $item_id, $course_id ) {
496 $status = LP_User_Items_DB::getInstance()->get_item_status( $item_id, $course_id );
497
498 return $status;
499 }*/
500
501 /**
502 * Update viewing item data into database.
503 *
504 * @param int $item_id
505 * @param int $course_id
506 *
507 * @return bool
508 * @since 3.0.0
509 * @version 4.0.1
510 * @depecated 4.1.6.9
511 */
512 /*public function maybe_update_item( $item_id, $course_id ) {
513 $return = false;
514
515 try {
516 $course_data = $this->get_course_data( $course_id );
517
518 if ( $course_data ) {
519 $item = $course_data->get_item( $item_id );
520
521 if ( ! $item ) {
522 $item = LP_User_Item::get_item_object( $item_id );
523
524 if ( ! $item ) {
525 return $return;
526 }
527
528 if ( $item instanceof LP_User_Item_Quiz ) {
529 return $return;
530 }
531
532 $item->set_ref_id( $course_id );
533 $item->set_parent_id( $course_data->get_user_item_id() );
534
535 $return = $item->update();
536 }
537 }
538 } catch ( Throwable $e ) {
539 error_log( $e->getMessage() );
540 }
541
542 return $return;
543 }*/
544
545 /**
546 * Get item user has accessed in last time.
547 *
548 * @param int $course_id
549 * @param bool $permalink - Optional. TRUE will return permalink instead of ID.
550 *
551 * @return mixed
552 * @depecated 4.1.6.9
553 */
554 public function get_current_item( $course_id, $permalink = false ) {
555 _deprecated_function( __FUNCTION__, '4.1.6.9' );
556 return 0;
557 /*$course_data = $this->get_course_data( $course_id );
558 if ( ! $course_data ) {
559 return false;
560 }
561
562 $course = learn_press_get_course( $course_id );
563 $id = learn_press_get_user_item_meta( $course_data->get_user_item_id(), '_current_item' );
564 if ( ! $id || $this->has_completed_item( $id, $course_id ) ) {
565 $items = $course->get_items( '', false );
566 if ( $items ) {
567 foreach ( $items as $item_id ) {
568 if ( ! $this->has_completed_item( $item_id, $course_id ) ) {
569 $id = $item_id;
570 break;
571 }
572 }
573
574 if ( ! $id ) {
575 $id = reset( $items );
576 }
577 }
578
579 if ( $id ) {
580 learn_press_update_user_item_meta( $course_data->get_user_item_id(), '_current_item', $id );
581 }
582 }
583
584 if ( $permalink && $id ) {
585 return apply_filters(
586 'learn-press/current-course-item-permalink',
587 $course->get_item_link( $id ),
588 $course_id,
589 $this->get_id()
590 );
591 } else {
592 return apply_filters( 'learn-press/current-course-item', $id, $course_id, $this->get_id() );
593 }*/
594 }
595
596 /**
597 * Get current question's ID/Permalink inside quiz.
598 *
599 * @param int $quiz_id
600 * @param int $course_id
601 * @param bool $permalink
602 *
603 * @return bool|int|string
604 * @depecated 4.1.6.9
605 */
606 /*public function get_current_question( $quiz_id, $course_id, $permalink = false ) {
607 _deprecated_function( sprintf( '%s::%s', __CLASS__, __FUNCTION__ ), '4.0.0' );
608 }*/
609
610 /**
611 * Get previous Question
612 *
613 * @param null $quiz_id
614 * @param int $course_id
615 * @param false $permalink
616 * @depecated 4.1.6.9
617 */
618 /*public function get_prev_question( $quiz_id = null, $course_id = 0, $permalink = false ) {
619 _deprecated_function( sprintf( '%s::%s', __CLASS__, __FUNCTION__ ), '4.0.0' );
620 }*/
621
622 /**
623 * Get next Question
624 *
625 * @param null $quiz_id
626 * @param int $course_id
627 * @param false $permalink
628 * @depecated 4.1.6.9
629 */
630 /*public function get_next_question( $quiz_id = null, $course_id = 0, $permalink = false ) {
631 _deprecated_function( sprintf( '%s::%s', __CLASS__, __FUNCTION__ ), '4.0.0' );
632 }*/
633
634 /**
635 * Checks if has status of a quiz for user
636 *
637 * @param string|array $statuses
638 * @param int $quiz_id
639 * @param int $course_id
640 * @param boolean $force
641 *
642 * @return bool
643 */
644 public function has_quiz_status( $statuses, $quiz_id, $course_id = 0, $force = false ) {
645 $status = $this->get_quiz_status( $quiz_id, $course_id );
646
647 settype( $statuses, 'array' );
648
649 return apply_filters(
650 'learn_press_user_has_quiz_status',
651 in_array( $status, $statuses ),
652 $statuses,
653 $status,
654 $quiz_id,
655 $course_id,
656 $this->get_id()
657 );
658 }
659
660 /**
661 * Get current results of a quiz
662 *
663 * @param int $quiz_id
664 * @param int $course_id
665 * @param string $prop
666 *
667 * @return mixed
668 */
669 public function get_quiz_results( $quiz_id, $course_id = 0, $prop = 'result' ) {
670 $user_quiz = $this->get_item_data( $quiz_id, $course_id );
671
672 return $user_quiz ? $user_quiz->get_results( $prop ) : false;
673 }
674
675 /**
676 * Get current progress of user's quiz.
677 *
678 * @param int $quiz_id
679 * @param int $course_id
680 *
681 * @return LP_User_Item_Quiz|false
682 */
683 public function get_quiz_data( $quiz_id, $course_id = 0 ) {
684 $result = false;
685 $course_result = $this->get_course_data( $course_id );
686 if ( $course_result ) {
687 $result = $course_result->get_item( $quiz_id );
688 }
689
690 return $result;
691 }
692
693 /**
694 * Mark question that user has checked.
695 *
696 * @param int $question_id
697 * @param int $quiz_id
698 * @param int $course_id
699 *
700 * @return WP_Error|mixed
701 * @since 3.0.0
702 * @editor tungnx
703 * @modify 4.1.4.1 - comment - not use
704 */
705 /*public function check_question( $question_id, $quiz_id, $course_id ) {
706 if ( ! $course = learn_press_get_course( $course_id ) ) {
707 return false;
708 }
709
710 if ( ! $course->has_item( $quiz_id ) ) {
711 return false;
712 }
713
714 $quiz = $course->get_item( $quiz_id );
715
716 if ( ! $quiz->has_question( $question_id ) ) {
717 return false;
718 }
719
720 $quiz_data = $this->get_item_data( $quiz_id, $course_id );
721
722 return $quiz_data->check_question( $question_id );
723 }*/
724
725 /**
726 * Mark question that user has checked.
727 *
728 * @param int $question_id
729 * @param int $quiz_id
730 * @param int $course_id
731 *
732 * @return WP_Error|mixed
733 * @since 3.0.0
734 */
735 public function hint( $question_id, $quiz_id, $course_id ) {
736 $course = learn_press_get_course( $course_id );
737 if ( ! $course ) {
738 return false;
739 }
740
741 if ( ! $course->has_item( $quiz_id ) ) {
742 return false;
743 }
744
745 /**
746 * @var $quiz LP_Quiz
747 */
748 $quiz = $course->get_item( $quiz_id );
749 if ( ! $quiz instanceof LP_Course_Item_Quiz ) {
750 return false;
751 }
752
753 if ( ! $quiz->has_question( $question_id ) ) {
754 return false;
755 }
756
757 $quiz_data = $this->get_item_data( $quiz_id, $course_id );
758 $remain = $quiz_data->hint( $question_id );
759 if ( false === $remain ) {
760 return new WP_Error( 1001, __( 'You can not hint question.', 'learnpress' ) );
761 }
762
763 return $remain;
764 }
765
766 /**
767 * Return true if check answer is enabled.
768 *
769 * @param int $quiz_id
770 * @param int $course_id
771 *
772 * @return bool
773 * @deprecated 4.1.4.1
774 */
775 /*public function can_check_answer( $quiz_id, $course_id = 0 ) {
776 _deprecated_function( __FUNCTION__, '4.1.4.1' );
777 if ( ! $course_id ) {
778 $course_id = get_the_ID();
779 }
780
781 if ( $quiz_data = $this->get_item_data( $quiz_id, $course_id ) ) {
782 return $quiz_data->can_check_answer();
783 }
784
785 return false;
786 }*/
787
788 /**
789 * Return true if check answer is enabled.
790 *
791 * @param int $quiz_id
792 * @param int $course_id
793 *
794 * @return bool
795 * @depecated 4.1.6.9
796 */
797 /*public function can_hint_answer( $quiz_id, $course_id = 0 ) {
798
799 if ( ! $course_id ) {
800 $course_id = get_the_ID();
801 }
802
803 if ( $quiz_data = $this->get_item_data( $quiz_id, $course_id ) ) {
804 return $quiz_data->can_hint_answer();
805 }
806
807 return false;
808 }*/
809
810
811 public function get_quiz_last_results( $quiz_id ) {
812 $results = $this->get_course_info( $quiz_id );
813 if ( $results ) {
814 $results = reset( $results );
815 }
816
817 return apply_filters( 'learn_press_user_quiz_last_results', $results, $quiz_id, $this );
818 }
819
820 /**
821 * Check if user has at least one role.
822 *
823 * @param array|string $roles
824 *
825 * @return array
826 */
827 public function has_role( $roles ) {
828 settype( $roles, 'array' );
829
830 return array_intersect( $roles, $this->get_roles() );
831 }
832
833 /**
834 * Detect the type of user
835 *
836 * @param string|int $type
837 *
838 * @return bool
839 */
840 public function is( $type ) {
841 $is = false;
842 if ( $type === 'current' ) {
843 $is = $this->is( get_current_user_id() );
844 } elseif ( is_string( $type ) ) {
845 $name = preg_replace( '!LP_User(_?)!', '', get_class( $this ) );
846 $is = strtolower( $name ) == strtolower( $type );
847 } elseif ( is_numeric( $type ) ) {
848 $is = $this->get_id() && ( $this->get_id() == $type );
849 }
850
851 return $is;
852 }
853
854 /**
855 *
856 * Check what the user can do
857 *
858 * @param $role
859 *
860 * @return mixed
861 * @throws Exception
862 */
863 public function can( $role ) {
864 _deprecated_function( __FUNCTION__, '3.0.8' );
865 $args = func_get_args();
866 unset( $args[0] );
867 $method = 'can_' . preg_replace( '!-!', '_', $role );
868 $callback = array( $this, $method );
869 if ( is_callable( $callback ) ) {
870 return call_user_func_array( $callback, $args );
871 } else {
872 throw new Exception( sprintf( __( 'The role %s for user doesn\'t exist', 'learnpress' ), $role ) );
873 }
874 }
875
876 public function can_edit_item( $item_id, $course_id = 0 ) {
877 $return = $this->is_admin();
878
879 if ( ! $return ) {
880 $course_id = $this->_get_course( $course_id );
881
882 $course_author = learn_press_get_course_user( $course_id );
883 if ( $course_author && $course_author->get_id() == $this->get_id() ) {
884 $return = true;
885 }
886 }
887
888 return apply_filters( 'learn_press_user_can_edit_item', $return, $item_id, $course_id, $this->get_id() );
889 }
890
891 /**
892 * Check if user can finish course by getting current progress
893 * and compares with course passing condition.
894 *
895 * @param int $course_id
896 *
897 * @return bool
898 * @editor tungnx
899 * @modify 4.1.3
900 */
901 public function can_finish_course( int $course_id ) {
902 _deprecated_function( __FUNCTION__, '4.1.3', 'is_course_finished' );
903
904 return true;
905 }
906
907 /**
908 * Check if course has any passed status for an user.
909 * Statuses: depending on value of column `status` in user_items.
910 * - purchased: bought and order is completed, `start_date` and `end_date` is null
911 * - enrolled: value of column `status` in user_items is enrolled
912 * - started: value of column `status` in user_items is started
913 * - enrolled: value of column `status` in user_items is enrolled
914 *
915 * @param int $course_id
916 * @param string|array $statuses
917 *
918 * @return bool
919 * @since 2.0
920 */
921 public function has_course_status( $course_id, $statuses ) {
922 $status = $this->get_course_status( $course_id );
923
924 if ( is_array( $statuses ) ) {
925 return in_array( $status, $statuses );
926 } elseif ( is_string( $statuses ) ) {
927 return $statuses == $status;
928 }
929
930 return false;
931 }
932
933 /**
934 * @depecated 4.1.6.9.1
935 */
936 /*public function get_completed_items( $course_id ) {
937 $this->_curd->get_user_items( $this->get_id(), $course_id );
938
939 return $this->_curd->get_user_completed_items( $this->get_id(), $course_id );
940 }*/
941
942 /**
943 * Finish course
944 *
945 * @param int $course_id
946 *
947 * @return int|bool
948 */
949 public function finish_course( int $course_id ) {
950 $return = false;
951 $course = learn_press_get_course( $course_id );
952
953 if ( $course ) {
954 $user_course = $this->get_course_data( $course_id );
955
956 $result = $user_course->calculate_course_results();
957
958 // Save result for course
959 LP_User_Items_Result_DB::instance()->update( $user_course->get_user_item_id(), wp_json_encode( $result ) );
960
961 if ( $result['pass'] ) {
962 $graduation = LP_COURSE_GRADUATION_PASSED;
963 } else {
964 $graduation = LP_COURSE_GRADUATION_FAILED;
965 }
966
967 $user_course->set_graduation( $graduation );
968 $user_course->save();
969
970 $return = $user_course->complete( 'finished' );
971
972 if ( $return ) {
973 do_action( 'learn-press/user-course-finished', $course_id, $this->get_id(), $return );
974 }
975 }
976
977 return apply_filters( 'learn-press/user-course-finished-data', $return, $course_id, $this->get_id() );
978 }
979
980 /**
981 * Check user instructor.
982 *
983 * @return bool
984 */
985 public function is_instructor(): bool {
986
987 $roles = $this->get_data( 'roles' ) ? $this->get_data( 'roles' ) : array();
988
989 return in_array( LP_TEACHER_ROLE, $roles );
990 }
991
992 /**
993 * Check user admin.
994 *
995 * @return bool
996 */
997 public function is_admin() {
998 $roles = $this->get_data( 'roles' ) ? $this->get_data( 'roles' ) : array();
999
1000 return in_array( 'administrator', $roles );
1001 }
1002
1003
1004 public function can_create_course() {
1005 return $this->is_instructor() || $this->is_admin();
1006 }
1007
1008 /**
1009 * Wrap function to check this user is author of a post.
1010 *
1011 * @param int $post_id
1012 *
1013 * @return bool
1014 * @since 3.1.0
1015 */
1016 public function is_author_of( $post_id ) {
1017 return absint( get_post_field( 'post_author', $post_id ) ) === $this->get_id();
1018 }
1019
1020 public function has( $role ) {
1021 _deprecated_function( __FUNCTION__, '3.0.8' );
1022
1023 $args = func_get_args();
1024 unset( $args[0] );
1025 $method = 'has_' . preg_replace( '!-!', '_', $role );
1026 $callback = array( $this, $method );
1027 if ( is_callable( $callback ) ) {
1028 return call_user_func_array( $callback, $args );
1029 } else {
1030 throw new Exception( sprintf( __( 'The role %s for user doesn\'t exist', 'learnpress' ), $role ) );
1031 }
1032 }
1033
1034 public function get( $role ) {
1035 $args = func_get_args();
1036 unset( $args[0] );
1037 $method = 'get_' . preg_replace( '!-!', '_', $role );
1038 $callback = array( $this, $method );
1039 if ( is_callable( $callback ) ) {
1040 return call_user_func_array( $callback, $args );
1041 } else {
1042 throw new Exception( sprintf( __( 'The role %s for user doesn\'t exist', 'learnpress' ), $role ) );
1043 }
1044 }
1045
1046 /**
1047 * Check user has passed course.
1048 *
1049 * @param $course_id
1050 *
1051 * @return mixed
1052 */
1053 public function has_passed_course( $course_id ) {
1054 $user_course = $this->get_course_data( $course_id );
1055
1056 return $user_course && $user_course->is_passed();
1057 }
1058
1059 /**
1060 * Checks if user has started a quiz
1061 * - FALSE if user has not started quiz
1062 * - String if user has started quiz (status of quiz)
1063 *
1064 * @param int $quiz_id
1065 * @param int $course_id
1066 *
1067 * @return mixed
1068 */
1069 public function has_started_quiz( $quiz_id, $course_id = 0 ) {
1070 $course_id = $this->_get_course( $course_id );
1071 $started = false;
1072 $started = $this->has_quiz_status( array( 'started', 'completed' ), $quiz_id, $course_id );
1073
1074 return apply_filters( 'learn_press_user_started_quiz', $started, $quiz_id, $course_id, $this->get_id() );
1075 }
1076
1077 /**
1078 * Return true if user has completed a quiz
1079 *
1080 * @param int $quiz_id
1081 * @param int $course_id
1082 *
1083 * @return bool
1084 * @depecated 4.1.6.9
1085 */
1086 /*public function has_completed_quiz( $quiz_id, $course_id = 0 ): bool {
1087 return $this->get_item_status( $quiz_id, $course_id ) == 'completed';
1088 }*/
1089
1090 /**
1091 * Mark a lesson is completed for user
1092 *
1093 * @param int $lesson_id
1094 * @param int $course_id
1095 * @param bool $return_wp_error
1096 *
1097 * @return bool|WP_Error
1098 */
1099 public function complete_lesson( $lesson_id, $course_id = 0, $return_wp_error = true ) {
1100 try {
1101 $course_id = $this->_get_course( $course_id );
1102
1103 $course_data = $this->get_course_data( $course_id );
1104
1105 $result = false;
1106
1107 /**
1108 * If user has stared a lesson, get user lesson information
1109 */
1110 $item = $course_data->get_item( $lesson_id );
1111 if ( $item ) {
1112 if ( $item->is_completed() ) {
1113 throw new Exception(
1114 __( 'You have already completed this lesson.', 'learnpress' ),
1115 LP_COMPLETE_ITEM_FAIL
1116 );
1117 }
1118
1119 $item->set_end_time( current_time( 'mysql', 1 ) );
1120 $item->set_status( 'completed' );
1121 $item->set_graduation( 'passed' );
1122
1123 $updated = $item->update();
1124
1125 if ( is_wp_error( $updated ) ) {
1126 return $return_wp_error ? $updated : false;
1127 } else {
1128 $result = true;
1129 }
1130 }
1131
1132 do_action( 'learn-press/user-completed-lesson', $lesson_id, $course_id, $this->get_id() );
1133 } catch ( Exception $ex ) {
1134 $result = $return_wp_error ? new WP_Error( $ex->getCode(), $ex->getMessage() ) : false;
1135 }
1136
1137 return $result;
1138 }
1139
1140 /**
1141 * Returns TRUE if user has already completed a lesson
1142 *
1143 * @param int $lesson_id Lesson id.
1144 * @param null $course_id Course id.
1145 *
1146 * @return bool
1147 * @depecated 4.1.6.9
1148 */
1149 public function has_completed_lesson( $lesson_id = 0, $course_id = null ): bool {
1150 return 'completed' === $this->get_item_status( $lesson_id, $course_id );
1151 }
1152
1153 /**
1154 * Return current status of course for user
1155 *
1156 * @param int $course_id
1157 * @param string $field
1158 * @param bool $force
1159 *
1160 * @return mixed
1161 */
1162 public function get_course_info( int $course_id, $field = null, $force = false ) {
1163 $user_data = $this->get_course_data( $course_id );
1164 if ( $user_data ) {
1165 return $user_data->get_results( $field );
1166 }
1167
1168 return false;
1169 }
1170
1171 /**
1172 * @param $course_id
1173 *
1174 * @return int
1175 * @depecated 4.1.6.9
1176 */
1177 public function get_course_history_id( $course_id ) {
1178 $history = $this->get_course_info( $course_id );
1179
1180 return ! empty( $history['history_id'] ) ? $history['history_id'] : 0;
1181 }
1182
1183 /**
1184 * Get current status of a course for user.
1185 *
1186 * @param int $course_id
1187 *
1188 * @return mixed
1189 * @editor tungnx
1190 * @modify 4.1.3
1191 * @version 1.0.1
1192 */
1193 public function get_course_status( int $course_id ): string {
1194 $status = '';
1195
1196 try {
1197 $user_data = $this->get_course_data( $course_id );
1198
1199 if ( $user_data ) {
1200 $status = $user_data->get_status();
1201 }
1202 } catch ( Throwable $e ) {
1203 if ( LP_Debug::is_debug() ) {
1204 error_log( $e->getMessage() );
1205 }
1206 }
1207
1208 return apply_filters( 'learn-press/user-course-status', $status, $course_id, $this->get_id() );
1209 }
1210
1211 /**
1212 * Controls what this user can do with a course.
1213 *
1214 * 0 => No accessible
1215 * 10 => Normal users (like not logged in)
1216 * 20 => Author of course
1217 * 30 => Admin site
1218 * 35 => No require enrollment
1219 * 40 => Ordered but not completed
1220 * 50 => Order is completed but not enrolled
1221 * 60 => User has already enrolled course
1222 * 70 => User has already finished course
1223 *
1224 * @param int $course_id
1225 *
1226 * @return int
1227 * @since 3.1.0
1228 * @editor tungnx
1229 * @modify 4.1.3 - comment - not use
1230 */
1231 /*public function get_course_access_level( $course_id ) {
1232 $access_level = LP_Object_Cache::get(
1233 'course-' . $course_id . '-' . $this->get_id(),
1234 'learn-press/course-access-levels'
1235 );
1236
1237 if ( false === $access_level ) {
1238 $course = learn_press_get_course( $course_id );
1239
1240 if ( ! $course ) {
1241 $access_level = LP_COURSE_ACCESS_LEVEL_0;
1242 } elseif ( $this->is_admin() ) {
1243 $access_level = LP_COURSE_ACCESS_LEVEL_30;
1244 } elseif ( $this->is_author_of( $course_id ) ) {
1245 $access_level = LP_COURSE_ACCESS_LEVEL_20;
1246 } else {
1247 $access_level = LP_COURSE_ACCESS_LEVEL_10;
1248 }
1249
1250 // Default level
1251 $access_level = apply_filters(
1252 'learn-press/course-access-level-default',
1253 $access_level,
1254 $course_id,
1255 $this->get_id()
1256 );
1257 $course_data = $this->get_course_data( $course_id );
1258
1259 if ( $course_data && $course_data->get_user_item_id() ) {
1260 // if ( $course_data->get_access_level() >= 50 ) {
1261 switch ( $course_data->get_status() ) {
1262 case 'completed':
1263 case 'failed':
1264 $access_level = LP_COURSE_ACCESS_LEVEL_60;
1265 break;
1266 case 'in-progress':
1267 case 'enrolled':
1268 $access_level = LP_COURSE_ACCESS_LEVEL_70;
1269 break;
1270 }
1271 // }
1272 } else {
1273 $order = $this->get_course_order( $course_id );
1274
1275 if ( $order ) {
1276 switch ( $order->get_status() ) {
1277 case 'completed':
1278 $access_level = LP_COURSE_ACCESS_LEVEL_50;
1279 break;
1280 default:
1281 $access_level = LP_COURSE_ACCESS_LEVEL_40;
1282 }
1283 }
1284 }
1285
1286 LP_Object_Cache::set(
1287 'course-' . $course_id . '-' . $this->get_id(),
1288 $access_level,
1289 'learn-press/course-access-levels'
1290 );
1291 }
1292
1293 return apply_filters( 'learn-press/course-access-level', $access_level, $course_id, $this->get_id() );
1294 }*/
1295
1296 /**
1297 * @editor tungnx
1298 * @reason comment - not use
1299 * @modify 4.1.2
1300 */
1301 /*public function get_item_access_level( $item_id, $course_id ) {
1302 $access_level = 0;
1303
1304 if ( $course = learn_press_get_course( $course_id ) ) {
1305 if ( $course->has_item( $item_id ) ) {
1306 if ( 10 < $this->get_course_access_level( $course_id ) ) {
1307 $access_level = 10;
1308 } else {
1309 $item = $course->get_item( $item_id );
1310 if ( $item->is_preview() ) {
1311 $access_level = 10;
1312 }
1313 }
1314 }
1315 }
1316
1317 return apply_filters(
1318 'learn-press/course-item-access-level',
1319 $access_level,
1320 $item_id,
1321 $course_id,
1322 $this->get_id()
1323 );
1324 }*/
1325
1326 /**
1327 * Set new access-level of an user with a course.
1328 *
1329 * @param int $access_level
1330 * @param int $course_id
1331 *
1332 * @return mixed
1333 * @since 3.1.0
1334 * @editor tungnx
1335 * @reason comment - not use
1336 * @modify 4.1.2
1337 */
1338 /*public function set_course_access_level( $access_level, $course_id ) {
1339 if ( $access_level !== $this->get_course_access_level( $course_id ) ) {
1340 LP_Object_Cache::set(
1341 'course-' . $course_id . '-' . $this->get_id(),
1342 $access_level,
1343 'learn-press/course-access-levels'
1344 );
1345 }
1346
1347 return $access_level;
1348 }*/
1349
1350 /**
1351 * Check if user have an access-level.
1352 * Consider the passed access-level is max level user have.
1353 *
1354 * @param int[] $access_level
1355 * @param int $course_id
1356 * @param string $compare
1357 *
1358 * @return bool
1359 * @since 3.1.0
1360 * @editor tungnx
1361 * @modify 4.1.3 - not - use
1362 */
1363 /*public function has_course_access_level( $access_level, $course_id, $compare = '<=' ) {
1364 $user_access_level = $this->get_course_access_level( $course_id );
1365
1366 switch ( $compare ) {
1367 case 'any':
1368 settype( $access_level, 'array' );
1369 $has = in_array( $user_access_level, $access_level );
1370 break;
1371 default:
1372 $has = version_compare( $user_access_level, $access_level );
1373 }
1374
1375 return $has;
1376 }*/
1377
1378 /**
1379 * Check if user has an access-level with a course.
1380 *
1381 * @param int $access_level
1382 * @param int $course_id
1383 *
1384 * @return bool
1385 * @since 3.1.0
1386 * @editor tungnx
1387 * @modify 4.1.2
1388 * @reason comment - not use
1389 */
1390 /*public function is_access_level( $access_level, $course_id ) {
1391 $user_access_level = $this->get_course_access_level( $course_id );
1392
1393 return $user_access_level === $access_level;
1394 }*/
1395
1396 /**
1397 * Check if user is already ordered a course.
1398 *
1399 * @param int $course_id
1400 *
1401 * @return mixed|LP_Order
1402 * @editor tungnx
1403 * @modify 4.1.3 - comment - not use
1404 */
1405 /*public function has_ordered_course( $course_id ) {
1406 $return = apply_filters(
1407 'learn-press/user-has-ordered-course',
1408 $this->get_course_order( $course_id ),
1409 $course_id,
1410 $this->get_id()
1411 );
1412
1413 // Deprecated since 3.0.0
1414 $return = apply_filters( 'learn_press_user_has_ordered_course', $return, $course_id, $this->get_id() );
1415
1416 return $return;
1417 }*/
1418
1419 /**
1420 * Get order status of a course.
1421 *
1422 * @param int $course_id
1423 *
1424 * @return mixed
1425 */
1426 public function get_order_status( $course_id ) {
1427 try {
1428 $order = $this->get_course_order( $course_id );
1429
1430 if ( ! $order ) {
1431 throw new Exception( 'Order not exists' );
1432 }
1433
1434 $order_status = apply_filters(
1435 'learn-press/course-order-status',
1436 get_post_status( $order->get_id() ),
1437 $course_id,
1438 $this->get_id()
1439 );
1440 } catch ( Throwable $e ) {
1441 $order_status = false;
1442 }
1443
1444 return $order_status;
1445 }
1446
1447 /**
1448 * Check item completed.
1449 *
1450 * @param $item
1451 * @param int $course_id
1452 * @param bool $force
1453 *
1454 * @return mixed|void
1455 * @version 3.0.1
1456 * @since 3.0.0
1457 */
1458 public function has_completed_item( $item, $course_id = 0, $force = false ) {
1459 $course_id = $this->_get_course( $course_id );
1460
1461 $return = false;
1462 $item_id = 0;
1463 if ( is_numeric( $item ) ) {
1464 $item_id = absint( $item );
1465 } else {
1466 settype( $item, 'array' );
1467 if ( ! empty( $item['ID'] ) ) {
1468 $item_id = absint( $item['ID'] );
1469 }
1470 }
1471
1472 if ( $item_id ) {
1473 $return = 'completed' === $this->get_item_status( $item_id, $course_id );
1474 }
1475
1476 return apply_filters( 'learn_press_user_has_completed_item', $return, $item );
1477 }
1478
1479 /**
1480 * Get the remaining time of a course for the user.
1481 *
1482 * @param int $course_id
1483 *
1484 * @return bool|int|string
1485 */
1486 public function get_course_remaining_time( $course_id ) {
1487 $course = learn_press_get_course( $course_id );
1488 $remain = false;
1489
1490 if ( $course && $course->get_id() ) {
1491 $course_data = $this->get_course_data( $course_id, true );
1492 if ( $course_data ) {
1493 $remain = $course_data->is_exceeded();
1494 }
1495 }
1496
1497 return $remain > 0 ? learn_press_seconds_to_weeks( $remain ) : false;
1498 }
1499
1500 /**
1501 * Get the order that contains the course.
1502 *
1503 * @param int $course_id
1504 *
1505 * @return bool|LP_Order
1506 * @editor tungnx
1507 * @throws Exception
1508 * @version 1.0.2
1509 * @since 4.1.1
1510 */
1511 public function get_course_order( int $course_id ) {
1512 $lp_order = false;
1513 $lp_order_db = LP_Order_DB::getInstance();
1514 $lp_order_id = $lp_order_db->get_last_lp_order_id_of_user_course( $this->get_id(), $course_id );
1515
1516 if ( $lp_order_id ) {
1517 $lp_order = new LP_Order( $lp_order_id );
1518 }
1519
1520 return $lp_order;
1521 }
1522
1523 /**
1524 * Enroll this user to a course.
1525 *
1526 * @param int $course_id
1527 * @param int $order_id - Optional. An user can be enrolled to a course
1528 *
1529 * @return bool|WP_Error
1530 * @throws Exception
1531 * @since 3.3.0
1532 * @editor tungnx
1533 * @version 3.3.1
1534 * @modify 4.1.3 - comment - not use
1535 */
1536 // public function enroll_course( int $course_id = 0, int $order_id = 0 ) {
1537 // $lp_user_items_db = LP_User_Items_DB::getInstance();
1538 //
1539 // try {
1540 // /*$user_item_api = new LP_User_Item_CURD();
1541 // $find_query = array(
1542 // 'item_id' => $course_id,
1543 // 'user_id' => $this->get_id(),
1544 // );
1545 //
1546 // if ( $order_id ) {
1547 // $find_query['ref_id'] = $order_id;
1548 // }*/
1549 //
1550 // $filter = new LP_User_Items_Filter();
1551 // $filter->user_id = get_current_user_id();
1552 // $filter->item_id = $course_id;
1553 // $course_item = $lp_user_items_db->get_last_user_course( $filter );
1554 //
1555 // if ( ! $course_item ) {
1556 // $course_item = LP_User_Item::get_empty_item();
1557 // } else {
1558 // $course_item = (array) $course_item;
1559 // }
1560 //
1561 // $user_id = $this->get_id();
1562 //
1563 // $course_item['user_id'] = $user_id;
1564 // $course_item['item_id'] = $course_id;
1565 // $course_item['item_type'] = learn_press_get_post_type( $course_id );
1566 // $course_item['ref_id'] = $order_id;
1567 // $course_item['ref_type'] = ( $order_id != 0 ) ? learn_press_get_post_type( $order_id ) : '';
1568 // $course_item['start_time'] = current_time( 'mysql', true );
1569 // $course_item['access_level'] = 50;
1570 //
1571 // /**
1572 // * @editor tungnx
1573 // * @fixed: case no auto enroll
1574 // */
1575 // if ( 'yes' == LP_Settings::get_option( 'auto_enroll' ) ) {
1576 // $course_item['graduation'] = 'in-progress';
1577 // }
1578 //
1579 // $user_course = new LP_User_Item_Course( $course_item );
1580 // $user_course->set_status( LP_COURSE_PURCHASED );
1581 //
1582 // if ( ! $user_course->update( true ) ) {
1583 // throw new Exception( __( 'Update user item error.', 'learnpress' ) );
1584 // }
1585 //
1586 // /*$user_id = is_user_logged_in() ? $this->get_id() : 0;
1587 //
1588 // global $wpdb;
1589 // $query = $wpdb->prepare(
1590 // "
1591 // UPDATE {$wpdb->learnpress_user_items}
1592 // SET access_level = %d
1593 // WHERE user_id = %d
1594 // AND item_id = %d
1595 // AND user_item_id NOT IN(%d)
1596 // ",
1597 // 0,
1598 // $user_id,
1599 // $course_id,
1600 // $user_course->get_user_item_id()
1601 // );
1602 // $wpdb->query( $query );*/
1603 //
1604 // $return = $user_course->get_user_item_id();
1605 // } catch ( Exception $ex ) {
1606 // error_log( $ex->getMessage() );
1607 // return false;
1608 // }
1609 //
1610 // return $return;
1611 // }
1612
1613 /**
1614 * Enroll this user to a course.
1615 *
1616 * @param int $course_id
1617 * @param int $order_id
1618 * @param bool $force - Optional. Force create db record for preview quiz case
1619 * @param bool $wp_error - Optional. TRUE will return WP_Error object if there is an error.
1620 * @editor tungnx - comment - not use
1621 * @return bool|mixed|WP_Error
1622 */
1623 /*public function enroll( $course_id, $order_id, $force = false, $wp_error = false ) {
1624 global $wpdb;
1625
1626 _deprecated_function( __FUNCTION__, '4.1.0' );
1627
1628 try {
1629 $course = learn_press_get_course( $course_id );
1630 $user_id = $this->get_id();
1631
1632 if ( $course->is_required_enroll() && ! $force ) {
1633 $order = learn_press_get_order( $order_id );
1634
1635 if ( ! $order ) {
1636 throw new Exception( __( 'Failed to enroll course.', 'learnpress' ), 10000 );
1637 }
1638
1639 if ( ! $this->can_enroll_course( $course_id ) ) {
1640 throw new Exception( __( 'Failed to enroll course.', 'learnpress' ), 10001 );
1641 }
1642
1643 if ( ! $this->get_id() ) {
1644 throw new Exception( __( 'Please login to enroll course.', 'learnpress' ), 10002 );
1645 }
1646 }
1647
1648 $return = $this->enroll_course( $course_id, $order_id, false, $wp_error );
1649
1650 return $return;
1651
1652 } catch ( Exception $ex ) {
1653 return new WP_Error( $ex->getCode(), $ex->getMessage() );
1654 }
1655 }*/
1656
1657 /**
1658 * @param $question_id
1659 *
1660 * @return null|string
1661 */
1662 public function get_quiz_by_question( $question_id ) {
1663 global $wpdb;
1664 $query = $wpdb->prepare(
1665 "
1666 SELECT quiz_id
1667 FROM {$wpdb->prefix}learnpress_user_items uq
1668 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
1669 ",
1670 'questions',
1671 '%i:' . $wpdb->esc_like( $question_id . '' ) . ';%'
1672 );
1673
1674 return $wpdb->get_var( $query );
1675 }
1676
1677 /**
1678 * @param $question_id
1679 * @param null $quiz_id
1680 *
1681 * @return bool
1682 */
1683 public function get_answer_results( $question_id, $quiz_id = null ) {
1684
1685 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '3.0.0' );
1686
1687 $data = false;
1688 if ( ! $quiz_id ) {
1689 $quiz_id = $this->get_quiz_by_question( $question_id );
1690 }
1691 if ( $quiz_id ) {
1692 $question = LP_Question::get_question( $question_id );
1693
1694 if ( $question ) {
1695 $quiz_results = $this->get_quiz_results( $quiz_id );
1696 if ( ! empty( $quiz_results->question_answers ) ) {
1697 $question_answer = array_key_exists(
1698 $question_id,
1699 $quiz_results->question_answers
1700 ) ? $quiz_results->question_answers[ $question_id ] : null;
1701 $data = $question->check( $question_answer );
1702 }
1703 }
1704 }
1705
1706 return $data;
1707 }
1708
1709 /**
1710 * @param $question_id
1711 * @param null $quiz_id
1712 *
1713 * @return bool
1714 */
1715 public function is_answered_question( $question_id, $quiz_id = null ) {
1716 if ( empty( $this->answered_questions ) ) {
1717 $this->answered_questions = array();
1718 }
1719 if ( ! $quiz_id ) {
1720 $quiz_id = $this->get_quiz_by_question( $question_id );
1721 }
1722
1723 $results = $this->get_quiz_results( $quiz_id );
1724 $answered = ! empty( $results->question_answers ) ? $results->question_answers : array();
1725
1726 return $answered ? array_key_exists( $question_id, $answered ) : false;
1727 }
1728
1729 /**
1730 * @param array $args
1731 *
1732 * @return LP_Query_List_Table
1733 * @editor tungnx
1734 * @deprecated 4.1.6
1735 */
1736 /*public function get_purchased_courses( array $args = array() ): LP_Query_List_Table {
1737 $filter = new LP_User_Items_Filter();
1738 $filter->fields = array( 'item_id' );
1739 $filter->user_id = $this->get_id();
1740 $filter->status = $args['status'] ?? '';
1741 $filter->page = $args['paged'] ?? 1;
1742 $filter->limit = $args['limit'] ?? $filter->limit;
1743 $total_rows = 0;
1744 $result_courses = LP_User_Item_Course::get_user_courses( $filter, $total_rows );
1745
1746 $course_ids = LP_Course::get_course_ids( $result_courses, 'item_id' );
1747
1748 $courses = array(
1749 'total' => $total_rows,
1750 'paged' => $filter->page,
1751 'limit' => $filter->limit,
1752 'items' => $course_ids,
1753 );
1754
1755 return new LP_Query_List_Table( $courses );
1756 }*/
1757
1758 /**
1759 * @return array
1760 */
1761 public function get_roles() {
1762 return (array) $this->get_data( 'roles' );
1763 }
1764
1765 /**
1766 * @param $question_id
1767 * @param $quiz_id
1768 * @param int $course_id
1769 *
1770 * @return bool
1771 */
1772 public function has_checked_answer( $question_id, $quiz_id, $course_id = 0 ) {
1773 if ( ! $course_id ) {
1774 $course_id = get_the_ID();
1775 }
1776
1777 $quiz_data = $this->get_item_data( $quiz_id, $course_id );
1778
1779 return $quiz_data ? $quiz_data->has_checked_question( $question_id ) : false;
1780 }
1781
1782 /**
1783 * @param $question_id
1784 * @param $quiz_id
1785 * @param int $course_id
1786 *
1787 * @return bool
1788 */
1789 public function has_hinted_answer( $question_id, $quiz_id, $course_id = 0 ) {
1790 if ( ! $course_id ) {
1791 $course_id = get_the_ID();
1792 }
1793
1794 $quiz_data = $this->get_item_data( $quiz_id, $course_id );
1795
1796 return $quiz_data ? $quiz_data->has_hinted_question( $question_id ) : false;
1797 }
1798
1799 /**
1800 * Return TRUE if user is already exists.
1801 *
1802 * @return bool
1803 */
1804 public function is_exists() {
1805 return ! ! get_user_by( 'id', $this->get_id() );
1806 }
1807
1808 /**
1809 * Check if the user is logged in.
1810 *
1811 * @return bool
1812 */
1813 public function is_logged_in() {
1814 return $this->get_id() == get_current_user_id();
1815 }
1816
1817 /**
1818 * Get upload profile src
1819 * Option: null: get origin picture, "thumbnail": get thumbnail picture
1820 *
1821 * @param mixed $size
1822 *
1823 * @return string
1824 */
1825 public function get_upload_profile_src( $size = '' ) {
1826 return LP_Profile::instance( $this->get_id() )->get_upload_profile_src( $size );
1827 }
1828
1829 /**
1830 * @param string $type
1831 * @param int $size
1832 * @param bool $src_only
1833 *
1834 * @return false|string
1835 */
1836 public function get_profile_picture( $type = '', $size = 96, $src_only = false ) {
1837 return LP_Profile::instance( $this->get_id() )->get_profile_picture( $type, $size );
1838 }
1839
1840 /**
1841 * Get links socials of use on Profile page
1842 *
1843 * @param int $user_id
1844 * @return array
1845 */
1846 public function get_profile_socials( int $user_id = 0 ): array {
1847 $socials = array();
1848 $extra_info = learn_press_get_user_extra_profile_info( $user_id );
1849
1850 if ( $extra_info ) {
1851 foreach ( $extra_info as $k => $v ) {
1852 if ( empty( $v ) ) {
1853 continue;
1854 }
1855
1856 switch ( $k ) {
1857 case 'facebook':
1858 $i = '<i class="fab fa-facebook-f"></i>';
1859 break;
1860 case 'twitter':
1861 $i = '<i class="fab fa-twitter"></i>';
1862 break;
1863 case 'googleplus':
1864 $i = '<i class="fab fa-google-plus-g"></i>';
1865 break;
1866 case 'youtube':
1867 $i = '<i class="fab fa-youtube"></i>';
1868 break;
1869 default:
1870 $i = sprintf( '<i class="fab fa-%s"></i>', $k );
1871 }
1872
1873 $icon = apply_filters(
1874 'learn-press/user-profile-social-icon',
1875 $i,
1876 $k,
1877 $this->get_id(),
1878 $this
1879 );
1880 $socials[ $k ] = sprintf( '<a href="%s">%s</a>', esc_url_raw( $v ), $icon );
1881 }
1882 }
1883
1884 return apply_filters( 'learn-press/user-profile-socials', $socials, $this->get_id(), $this );
1885 }
1886
1887 /**
1888 * Check if user can access to a course.
1889 *
1890 * @param int $course_id
1891 *
1892 * @return mixed
1893 * @editor tungnx
1894 * @modify 4.1.3 - comment - not use
1895 */
1896 /*public function can_access_course( $course_id ) {
1897
1898 $accessible = $this->has_course_access_level(
1899 array(
1900 LP_COURSE_ACCESS_LEVEL_60,
1901 LP_COURSE_ACCESS_LEVEL_70,
1902 ),
1903 $course_id,
1904 'any'
1905 );
1906
1907 $accessible = apply_filters(
1908 'learn-press/user-can-access-course',
1909 $accessible,
1910 $course_id,
1911 $this->get_id()
1912 );
1913
1914 return $accessible;
1915 }*/
1916
1917 /**
1918 * Check course of user has graduation is in-progress
1919 *
1920 * @param $course_id
1921 * @return bool
1922 * @throws Exception
1923 */
1924 public function is_course_in_progress( $course_id ): bool {
1925 $user = learn_press_get_user( $this->get_id() );
1926 $user_course = $user->get_course_data( $course_id );
1927
1928 return $user_course && LP_COURSE_GRADUATION_IN_PROGRESS === $user_course->get_graduation();
1929 }
1930
1931 /**
1932 * Return TRUE if user can do a quiz
1933 *
1934 * @param $quiz_id
1935 * @param int $course_id
1936 *
1937 * @return bool
1938 * @throws Exception
1939 */
1940 public function can_do_quiz( $quiz_id, $course_id = 0 ) {
1941 $course = learn_press_get_course( $course_id );
1942
1943 if ( $course->is_required_enroll() ) {
1944 $can = $this->has_course_status(
1945 $course_id,
1946 array( 'enrolled' )
1947 ) && ! $this->has_started_quiz( $quiz_id, $course_id );
1948 } else {
1949 $can = ! $this->has_started_quiz( $quiz_id, $course_id );
1950 }
1951
1952 return apply_filters( 'learn_press_user_can_do_quiz', $can, $quiz_id, $this->get_id(), $course_id );
1953 }
1954
1955 /**
1956 * @depecated 4.1.6.9.2
1957 */
1958 /*public function evaluate_course_results( $course_id ) {
1959 $user_course = $this->get_course_data( $course_id );
1960
1961 return isset( $user_course ) ? $user_course->get_results( 'result' ) : 0;
1962 }*/
1963
1964 /**
1965 * @editor tungnx
1966 * @modify 4.1.4.1 - comment - not use
1967 */
1968 /*public function has_reached_passing_condition( $course_id ) {
1969 $course = learn_press_get_course( $course_id );
1970 $result = $this->evaluate_course_results( $course_id );
1971
1972 return $return = $result >= $course->get_passing_condition();
1973 }*/
1974
1975 /**
1976 * Check if all items in course completed.
1977 *
1978 * @return boolean
1979 * @author Nhamdv <email@email.com>
1980 */
1981 public function is_completed_all_items( $course_id ) {
1982 $course = learn_press_get_course( $course_id );
1983
1984 $course_data = $this->get_course_data( $course_id );
1985
1986 $course_results = $course_data->get_result();
1987
1988 if ( ! isset( $course_results['completed_items'] ) ) {
1989 return false;
1990 }
1991
1992 return $course_results['completed_items'] >= $course->count_items();
1993 }
1994
1995 public function get_role() {
1996 return $this->is_admin() ? 'admin' : ( $this->is_instructor() ? 'instructor' : 'user' );
1997 }
1998
1999 /**
2000 * Get user course's grade.
2001 * Possible values:
2002 * + passed User has finished and passed course.
2003 * + failed User has finished but failed.
2004 * + in-progress User still is learning course.
2005 *
2006 * @param $course_id
2007 *
2008 * @return string|bool
2009 */
2010 public function get_course_grade( $course_id ) {
2011 $grade = false;
2012 $course_data = $this->get_course_data( $course_id );
2013
2014 if ( $course_data ) {
2015 $grade = $course_data->get_status( 'graduation' );
2016 }
2017
2018 return apply_filters( 'learn-press/user-course-grade', $grade, $this->get_id(), $course_id );
2019 }
2020
2021 /**
2022 * Check if user is a GUEST by checking the meta _lp_temp_user is exists.
2023 *
2024 * @return bool
2025 */
2026 public function is_guest(): bool {
2027 return ! $this->get_id() || ! get_user_by( 'id', $this->get_id() );
2028 }
2029
2030 /**
2031 * Check if user can edit a post.
2032 *
2033 * @param int $post_id
2034 *
2035 * @return bool
2036 */
2037 public function can_edit( int $post_id ): bool {
2038 if ( $this->get_id() !== get_current_user_id() ) {
2039 return false;
2040 }
2041
2042 return current_user_can( 'edit_post', $post_id );
2043 }
2044
2045 /**
2046 * Get email of user
2047 *
2048 * @return string
2049 */
2050 public function get_email(): string {
2051 return $this->get_data( 'email', '' );
2052 }
2053
2054 /**
2055 * Return user_login of the user.
2056 *
2057 * @return string
2058 */
2059 public function get_username(): string {
2060 return $this->get_data( 'user_login', '' );
2061 }
2062
2063 /**
2064 * Return user bio information.
2065 *
2066 * @return string
2067 */
2068 public function get_description(): string {
2069 return $this->get_data( 'description', '' );
2070 }
2071
2072 /**
2073 * Return user first name.
2074 *
2075 * @return string
2076 */
2077 public function get_first_name(): string {
2078 return $this->get_data( 'first_name', '' );
2079 }
2080
2081 /**
2082 * Return user last name.
2083 *
2084 * @return string
2085 */
2086 public function get_last_name(): string {
2087 return $this->get_data( 'last_name', '' );
2088 }
2089
2090 /**
2091 * Return user nickname.
2092 *
2093 * @return string
2094 */
2095 public function get_nickname(): string {
2096 return $this->get_data( 'nickname', '' );
2097 }
2098
2099 /**
2100 * Return user display name.
2101 *
2102 * @return string
2103 */
2104 public function get_display_name(): string {
2105 return $this->get_data( 'display_name', '' );
2106 }
2107 }
2108 }
2109