PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.5
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.5
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-item / class-lp-user-item.php

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

809 lines 17.5 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_User_Item
5 *
6 * @since 3.0.0
7 */
8 class LP_User_Item extends LP_Abstract_Object_Data {
9 /**
10 * Auto increment
11 *
12 * @var int
13 */
14 public $_user_item_id = 0;
15 /**
16 * User id
17 *
18 * @var string
19 */
20 public $_user_id = 0;
21 /**
22 * Item id (course, lesson, quiz ...)
23 *
24 * @var string
25 */
26 public $_item_id = 0;
27 /**
28 * @var string
29 */
30 public $_start_time = '';
31 /**
32 * @var string
33 */
34 public $_end_time = '';
35 /**
36 * Item type (course, lesson, quiz ...)
37 *
38 * @var string
39 */
40 public $_item_type = '';
41 /**
42 * Status
43 *
44 * @var string
45 */
46 public $_status = '';
47 /**
48 * Graduation
49 *
50 * @var string
51 */
52 public $_graduation = '';
53 /**
54 * Ref id (Order, course ...)
55 *
56 * @var string
57 */
58 public $_ref_id = '';
59 /**
60 * Ref type (Order, course ...)
61 *
62 * @var string
63 */
64 public $_ref_type = '';
65 /**
66 * Parent id
67 *
68 * @var string
69 */
70 public $_parent_id = '';
71 /**
72 * Key get data start time form DB.
73 */
74 const KEY_DATA_START_TIME = 'start_time';
75 /**
76 * Key get data end time form DB.
77 */
78 const KEY_DATA_END_TIME = 'end_time';
79
80 /**
81 * LP_User_Item constructor.
82 *
83 * @param array $item . A record fetched from table _learnpress_user_items
84 */
85 public function __construct( $item ) {
86 if ( is_numeric( $item ) ) {
87 $item = array( 'item_id' => $item );
88 } else {
89 $item = (array) $item;
90 }
91
92 // $this->_data = self::get_empty_item();
93
94 parent::__construct( $item );
95 $this->set_default_data( $item );
96
97 }
98
99 /**
100 * Set data from passed args
101 *
102 * @param array $item
103 */
104 protected function set_default_data( $item ) {
105 $this->_changes = array();
106 $item_id = 0;
107
108 if ( ! empty( $item['user_item_id'] ) ) {
109 $this->set_data( 'user_item_id', absint( $item['user_item_id'] ) );
110 }
111
112 if ( ! empty( $item['item_id'] ) ) {
113 $item['item_id'] = absint( $item['item_id'] );
114
115 $this->set_id( $item['item_id'] );
116 $this->set_data( 'item_id', $item['item_id'] );
117 $this->set_data( 'item_type', learn_press_get_post_type( $item['item_id'] ) );
118 $item_id = $item['item_id'];
119 }
120
121 $this->set_start_time( $item[ self::KEY_DATA_START_TIME ] ?? time() );
122 $this->set_end_time( $item[ self::KEY_DATA_END_TIME ] ?? '' );
123 $this->set_user_id( absint( $item['user_id'] ?? get_current_user_id() ) );
124 $this->set_status( $item['status'] ?? '' );
125
126 if ( ! empty( $item['ref_id'] ) ) {
127 $item['ref_id'] = absint( $item['ref_id'] );
128
129 $this->set_ref_id( $item['ref_id'] );
130 if ( empty( $item['ref_type'] ) ) {
131 $this->set_data( 'ref_type', learn_press_get_post_type( $item['ref_id'] ) );
132 }
133 }
134
135 if ( ! empty( $item['ref_type'] ) ) {
136 $this->set_data( 'ref_type', $item['ref_type'] );
137 }
138
139 if ( ! empty( $item['parent_id'] ) ) {
140 $item['parent_id'] = absint( $item['parent_id'] );
141
142 $this->set_parent_id( $item['parent_id'] );
143 }
144
145 if ( ! empty( $item['access_level'] ) ) {
146 $this->set_data( 'access_level', $item['access_level'] );
147 }
148
149 $this->set_data( 'graduation', $item['graduation'] ?? '' );
150 }
151
152 public function set_user_id( $user_id ) {
153 $this->set_data( 'user_id', $user_id );
154 }
155
156 public function get_user_id() {
157 return $this->get_data( 'user_id' );
158 }
159
160 public function set_ref_id( $ref_id ) {
161 $this->set_data( 'ref_id', $ref_id );
162 $this->set_data( 'ref_type', learn_press_get_post_type( $ref_id ) );
163 }
164
165 public function get_parent_id() {
166 return absint( $this->get_data( 'parent_id' ) );
167 }
168
169 public function set_parent_id( $parent_id ) {
170 $this->set_data( 'parent_id', $parent_id );
171 }
172
173 /**
174 * Get access level to a course.
175 *
176 * @return int
177 * @since 3.x.x
178 */
179 public function get_access_level() {
180 return absint( $this->get_data( 'access_level' ) );
181 }
182
183 /**
184 * Get type of item. Consider is post-type.
185 *
186 * @return array|mixed
187 */
188 public function get_type() {
189 return $this->get_data( 'item_type' );
190 }
191
192 /**
193 * Set start-time.
194 *
195 * @param mixed $time .
196 *
197 * @return $this
198 */
199 public function set_start_time( $time = '' ): LP_User_Item {
200 $this->set_data_date( 'start_time', $time );
201
202 return $this;
203 }
204
205 /**
206 * Get start-time.
207 *
208 * @param string $format
209 * @param bool $local
210 *
211 * @return string|LP_Datetime|false
212 */
213 public function get_start_time( string $format = '', $local = false ) {
214 $date = $this->get_data( self::KEY_DATA_START_TIME );
215
216 return $this->format_time( $date, $format, $local );
217 }
218
219 /**
220 * Set end-time for item.
221 *
222 * @param mixed $time
223 *
224 * @return $this
225 */
226 public function set_end_time( $time = '' ): LP_User_Item {
227 $this->set_data_date( 'end_time', $time );
228
229 return $this;
230 }
231
232 /**
233 * Get end-time.
234 *
235 * @param string $format
236 *
237 * @return string|LP_Datetime
238 */
239 public function get_end_time( string $format = '' ) {
240 $date = $this->get_data( self::KEY_DATA_END_TIME );
241
242 return $this->format_time( $date, $format );
243 }
244
245 /**
246 * @param string|int|LP_Datetime $date
247 * @param string $format
248 * @param bool $local
249 *
250 * @return bool|float|int|LP_Datetime|string
251 */
252 public function format_time( $date, $format = '', $local = false ) {
253 if ( ! $date ) {
254 return false;
255 }
256
257 if ( ! $date instanceof LP_Datetime ) {
258 $date = new LP_Datetime( $date );
259 }
260
261 return $format ? $date->format( $format, $local ) : $date;
262 }
263
264 /**
265 * Get expiration time.
266 *
267 * @return string|LP_Datetime $time
268 * @since 3.3.0
269 * @version 3.3.2
270 */
271 public function get_expiration_time() {
272 $duration = get_post_meta( $this->get_item_id(), '_lp_duration', true );
273 $start_time = $this->get_start_time()->getTimestamp();
274
275 if ( ! absint( $duration ) || ! $start_time ) {
276 $expire = null;
277 } else {
278 // Convert duration from string to seconds.
279 if ( ! is_numeric( $duration ) ) {
280 $duration = strtotime( $duration ) - time();
281 }
282
283 $expire_time = $start_time + $duration;
284 $expire = new LP_Datetime( $expire_time );
285 }
286
287 return apply_filters( 'learn-press/user-item/expiration-time', $expire, $duration, $this );
288 }
289
290 /**
291 * Set item-status.
292 *
293 * @param string $status .
294 *
295 * @return $this
296 */
297 public function set_status( string $status ): LP_User_Item {
298 $this->_set_data( 'status', $status );
299
300 return $this;
301 }
302
303 /**
304 * Get item status.
305 *
306 * @param string $field
307 * @param bool $force_cache Reset first cache
308 *
309 * @version 1.0.1
310 * @return string
311 * @editor tungnx
312 * @modify 4.1.3
313 */
314 public function get_status( string $field = 'status', bool $force_cache = false ): string {
315 $got_status = '';
316
317 try {
318 // User is Guest
319 if ( (int) $this->get_user_id() === 0 ) {
320 return $got_status;
321 }
322
323 if ( LP_COURSE_CPT === $this->get_type() ) {
324 return $this->get_data( $field );
325 }
326
327 /*error_log('status user item id: ' . $this->get_id());
328 error_log('status user item type: ' . $this->get_type());
329 error_log('status user course status: ' . $this->get_data( $field ));*/
330
331 $lp_user_item = LP_User_Items_DB::getInstance();
332 $filter = new LP_User_Items_Filter();
333
334 $filter->user_id = $this->get_user_id();
335 $filter->item_id = $this->get_item_id();
336 $filter->ref_id = $this->get_data( 'ref_id' );
337 $filter->parent_id = $this->get_parent_id();
338
339 $user_item = $lp_user_item->get_user_course_item( $filter, $force_cache );
340
341 if ( ! empty( $user_item ) && isset( $user_item->$field ) ) {
342 $got_status = $user_item->$field;
343 }
344
345 $this->set_data( $field, $got_status );
346 } catch ( Throwable $e ) {
347 LP_Debug::error_log( $e );
348 }
349
350 return $got_status;
351 }
352
353 public function is_exists() {
354 return ! ! $this->get_user_item_id();
355 }
356
357 /**
358 * @param string $return
359 *
360 * @return LP_User|int
361 */
362 public function get_user( $return = '' ) {
363 return $this->get_data( 'user_id', 0 );
364 }
365
366 /**
367 * Get course.
368 *
369 * @param string $return
370 *
371 * @return bool|LP_Course|int|mixed
372 */
373 public function get_course( string $return = '' ) {
374 $course_id = $this->get_data( 'ref_id', 0 );
375 if ( $return == '' ) {
376 return $course_id ? learn_press_get_course( $course_id ) : false;
377 }
378
379 return $course_id;
380 }
381
382 /**
383 * @return int
384 */
385 public function get_user_item_id() {
386 return intval( $this->get_data( 'user_item_id' ) );
387 }
388
389 /**
390 * Change the primary key user_item_id of user-items.
391 * Only use zero value to force creating new item.
392 *
393 * @param int $user_item_id
394 */
395 public function set_user_item_id( $user_item_id ) {
396 $this->_set_data( 'user_item_id', absint( $user_item_id ) );
397 }
398
399 public function get_item_id() {
400 return $this->get_data( 'item_id' );
401 }
402
403 public function get_parent() {
404 $user = learn_press_get_user( $this->get_user_id() );
405 $ref_id = $this->get_data( 'ref_id' );
406
407 if ( get_post_type( $ref_id ) === LP_COURSE_CPT ) {
408 return $user->get_course_data( $ref_id );
409 }
410
411 return false;
412 }
413
414 public function get_result( $prop = 'result' ) {
415 $result = array(
416 'result' => $this->is_completed() ? 100 : 0,
417 'grade' => $this->is_completed() ? 'passed' : 'failed',
418 );
419
420 return $prop && array_key_exists( $prop, $result ) ? $result[ $prop ] : $result;
421 }
422
423 public function read_meta() {
424 global $wpdb;
425 $query = $wpdb->prepare(
426 "
427 SELECT *
428 FROM {$wpdb->learnpress_user_itemmeta}
429 WHERE learnpress_user_item_id = %d
430 ",
431 $this->get_user_item_id()
432 );
433
434 $results = $wpdb->get_results( $query );
435 if ( $results ) {
436 foreach ( $results as $result ) {
437 $result->meta_value = LP_Helper::maybe_unserialize( $result->meta_value );
438 $this->_meta_data[] = $result;
439 }
440 }
441
442 }
443
444 /**
445 * Get structure of an user item.
446 *
447 * @return array
448 * @since 3.1.0
449 */
450 public static function get_empty_item() {
451 return array(
452 'user_item_id' => 0,
453 'user_id' => 0,
454 'item_id' => 0,
455 'start_time' => '',
456 'end_time' => '',
457 'item_type' => '',
458 'status' => '',
459 'graduation' => '',
460 'access_level' => 50,
461 'ref_id' => '',
462 'ref_type' => '',
463 'parent_id' => 0,
464 );
465 }
466
467 /**
468 * Get user-item meta data.
469 * Check if meta data does not exist then return FALSE.
470 *
471 * @updated 3.1.0
472 *
473 * @param string $key
474 * @param bool $single
475 *
476 * @return bool|mixed
477 */
478 public function get_meta( $key, $single = true ) {
479 if ( ! metadata_exists( 'learnpress_user_item', $this->get_user_item_id(), $key ) ) {
480 return false;
481 }
482
483 return learn_press_get_user_item_meta( $this->get_user_item_id(), $key, $single );
484 }
485
486 /**
487 * Update meta data
488 *
489 * @updated 3.1.0
490 *
491 * @param string $key
492 * @param string $value
493 * @param string $prev_value
494 *
495 * @editor tungnx add bk method
496 */
497 public function update_meta_bk( $key = '', $value = '', $prev_value = '' ) {
498 if ( func_num_args() === 0 ) {
499 if ( $this->_meta_data ) {
500 foreach ( $this->_meta_data as $meta_data ) {
501 if ( $meta_data->meta_value ) {
502 learn_press_update_user_item_meta(
503 $this->get_user_item_id(),
504 $meta_data->meta_key,
505 $meta_data->meta_value
506 );
507 } else {
508 learn_press_delete_user_item_meta( $this->get_user_item_id(), $meta_data->meta_key );
509 }
510 }
511 }
512 } else {
513 if ( is_array( $key ) ) {
514 foreach ( $key as $k => $v ) {
515 if ( $v === false ) {
516 learn_press_delete_user_item_meta( $this->get_user_item_id(), $k );
517 } else {
518 learn_press_update_user_item_meta( $this->get_user_item_id(), $k, $v );
519 }
520 }
521 } else {
522 if ( $value === false ) {
523 learn_press_delete_user_item_meta( $this->get_user_item_id(), $key );
524 } else {
525 learn_press_update_user_item_meta( $this->get_user_item_id(), $key, $value, $prev_value );
526 }
527 }
528 }
529 }
530
531 /**
532 * Update meta data
533 *
534 * @param string $key .
535 * @param string $value .
536 * @param string $prev_value .
537 *
538 * @return int|bool
539 * @editor tungnx
540 */
541 public function update_meta( $key = '', $value = '', $prev_value = '' ) {
542 $result = false;
543
544 if ( is_array( $key ) ) {
545 $result = $this->update_meta_multiple_keys( $key );
546 } else {
547 if ( false === $value ) {
548 $result = learn_press_delete_user_item_meta( $this->get_user_item_id(), $key );
549 } else {
550 $result = learn_press_update_user_item_meta( $this->get_user_item_id(), $key, $value, $prev_value );
551 }
552 }
553
554 return $result;
555 }
556
557 /**
558 * Update metadata with array keys values
559 *
560 * @param array $meta_datas .
561 *
562 * @return bool|int
563 */
564 public function update_meta_multiple_keys( $meta_datas = array() ) {
565 $result = false;
566
567 foreach ( $meta_datas as $k => $v ) {
568 if ( false === $v ) {
569 $result = learn_press_delete_user_item_meta( $this->get_user_item_id(), $k );
570 } else {
571 $result = learn_press_update_user_item_meta( $this->get_user_item_id(), $k, $v );
572 }
573 }
574
575 return $result;
576 }
577
578 public function get_mysql_data() {
579 /**
580 * @var LP_Datetime $v
581 */
582 $columns = array();
583
584 foreach ( $this->get_data() as $k => $v ) {
585 $columns[ $k ] = $v;
586 }
587
588 return $columns;
589 }
590
591 /**
592 * @param $data
593 *
594 * @return LP_User_Item|bool
595 */
596 public static function get_item_object( $data ) {
597 $item_id = 0;
598
599 if ( is_array( $data ) && isset( $data['item_id'] ) ) {
600 $item_id = $data['item_id'];
601 } elseif ( is_object( $data ) && isset( $data->item_id ) ) {
602 $item_id = $data->item_id;
603 } elseif ( is_numeric( $data ) ) {
604 $item_id = absint( $data );
605 } elseif ( $data instanceof LP_User_Item ) {
606 $item_id = $data->get_id();
607 }
608
609 $item = false;
610 $item_type = learn_press_get_post_type( $item_id );
611
612 switch ( $item_type ) {
613 case LP_LESSON_CPT:
614 $item = new LP_User_Item( $data );
615 break;
616 case LP_QUIZ_CPT:
617 $item = new LP_User_Item_Quiz( $data );
618 break;
619 default:
620 break;
621 }
622
623 return apply_filters( 'learn-press/user-item-object', $item, $data, $item_type );
624 }
625
626 /**
627 * Set graduation
628 *
629 * @param string $graduation .
630 *
631 * @return $this
632 */
633 public function set_graduation( string $graduation ): LP_User_Item {
634 $this->_set_data( 'graduation', $graduation );
635
636 return $this;
637 }
638
639 /**
640 * Get graduation
641 *
642 * @param string $context
643 *
644 * @return string
645 */
646 public function get_graduation( string $context = '' ): string {
647 $grade = $this->get_data( 'graduation', '' );
648 if ( ! $grade ) {
649 return '';
650 }
651 return $context == 'display' ? learn_press_course_grade_html( $grade, false ) : $grade;
652 }
653
654 /**
655 * Update data from memory to database.
656 *
657 * @updated 3.1.0
658 *
659 * @return bool|mixed
660 */
661 public function update( $force = false, $wp_error = false ) {
662 $data = $this->get_mysql_data();
663 $data = apply_filters( 'learn-press/update-user-item-data', $data, $this->get_user_item_id() );
664 $where = array();
665
666 if ( $this->get_user_item_id() ) {
667 $where = array( 'user_item_id' => $this->get_user_item_id() );
668 }
669
670 $rs = learn_press_update_user_item_field( $data, $where );
671
672 // Clear cache first status
673 $this->get_status( 'status', true );
674
675 if ( $rs ) {
676 foreach ( (array) $rs as $k => $v ) {
677 $this->_set_data( $k, $v );
678 }
679 $this->_changes = array();
680 }
681
682 return $rs;
683 }
684
685 public function get_status_label( $status = '' ) {
686 $statuses = array(
687 LP_COURSE_ENROLLED => esc_html__( 'Enrolled', 'learnpress' ),
688 LP_COURSE_PURCHASED => esc_html__( 'Purchased', 'learnpress' ),
689 LP_ITEM_COMPLETED => esc_html__( 'Completed', 'learnpress' ),
690 LP_ITEM_STARTED => esc_html__( 'Started', 'learnpress' ),
691 LP_COURSE_FINISHED => esc_html__( 'Finished', 'learnpress' ),
692 );
693
694 if ( ! $status ) {
695 $status = $this->get_status();
696 }
697
698 return ! empty( $statuses[ $status ] ) ? $statuses[ $status ] : esc_html__( 'Not Enrolled', 'learnpress' );
699 }
700
701 /**
702 * Get time from user started to ended.
703 *
704 * @param string $context
705 *
706 * @return bool|int
707 */
708 public function get_time_interval( $context = '' ) {
709 $start = $this->get_start_time();
710 $end = $this->get_end_time();
711
712 if ( ! $start instanceof LP_Datetime || ! $end instanceof LP_Datetime ) {
713 return false;
714 }
715
716 if ( $start->is_null() || $end->is_null() ) {
717 return false;
718 }
719
720 return $end->getTimestamp() - $start->getTimestamp();
721 }
722
723 /**
724 * Return true of item is completed/finished
725 *
726 * @param string $status
727 *
728 * @return bool
729 */
730 public function is_completed( $status = 'completed' ) {
731 return $this->get_status() === $status;
732 }
733
734 /**
735 * Complete item
736 *
737 * @editor tungnx
738 * @modify 4.1.4.1 - should review to improve
739 * @version 4.0.1
740 */
741 public function complete( $status = 'completed' ) {
742 try {
743 $this->set_end_time( time() );
744 $this->set_status( $status );
745 $this->update();
746 } catch ( Throwable $e ) {
747 error_log( __FUNCTION__ . ':' . $e->getMessage() );
748 return false;
749 }
750
751 return true;
752 }
753
754 /**
755 * Get post type of item.
756 *
757 * @return string
758 */
759 public function get_post_type() {
760 return learn_press_get_post_type( $this->get_item_id() );
761 }
762
763 /**
764 * @return bool
765 */
766 public function is_passed(): bool {
767 return LP_COURSE_GRADUATION_PASSED === $this->get_graduation();
768 }
769
770 /**
771 * @param int $decimal
772 *
773 * @return mixed|null
774 */
775 public function get_percent_result( $decimal = 1 ) {
776 return apply_filters(
777 'learn-press/user/item-percent-result',
778 sprintf( '%s%', round( $this->get_result( 'result' ), $decimal ) ),
779 $this->get_user_id(),
780 $this->get_item_id()
781 );
782 }
783
784 public function offsetSet( $offset, $value ) {
785 _deprecated_function( __METHOD__, '4.2.3.5' );
786 // TODO: Implement offsetSet() method.
787 }
788
789 public function offsetGet( $offset ) {
790 _deprecated_function( __METHOD__, '4.2.3.5' );
791 if ( is_callable( array( $this, 'get_' . $offset ) ) ) {
792 return call_user_func( array( $this, 'get_' . $offset ) );
793 }
794
795 return false;
796 }
797
798 public function offsetUnset( $offset ) {
799 _deprecated_function( __METHOD__, '4.2.3.5' );
800 // TODO: Implement offsetUnset() method.
801 }
802
803 public function offsetExists( $offset ) {
804 _deprecated_function( __METHOD__, '4.2.3.5' );
805 // TODO: Implement offsetExists() method.
806 }
807 }
808
809