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

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

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