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

1,157 lines 24.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Class LP_User_Item
5 *
6 * @since 3.0.0
7 */
8 class LP_User_Item extends LP_Abstract_Object_Data implements ArrayAccess {
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
73 /**
74 * @var string
75 */
76 protected $_data_key = '';
77
78 /**
79 * LP_User_Item constructor.
80 *
81 * @param array $item . A record fetched from table _learnpress_user_items
82 */
83 public function __construct( $item ) {
84 if ( is_numeric( $item ) ) {
85 $item = array( 'item_id' => $item );
86 } else {
87 $item = (array) $item;
88 }
89
90 // $this->_data = self::get_empty_item();
91
92 parent::__construct( $item );
93 $this->set_default_data( $item );
94
95 }
96
97 /**
98 * Set data from passed args
99 *
100 * @param array $item
101 */
102 protected function set_default_data( $item ) {
103 $this->_changes = array();
104 $item_id = 0;
105
106 if ( ! empty( $item['user_item_id'] ) ) {
107 $this->set_data( 'user_item_id', absint( $item['user_item_id'] ) );
108 }
109
110 if ( ! empty( $item['item_id'] ) ) {
111 $item['item_id'] = absint( $item['item_id'] );
112
113 $this->set_id( $item['item_id'] );
114 $this->set_data( 'item_id', $item['item_id'] );
115 $this->set_data( 'item_type', learn_press_get_post_type( $item['item_id'] ) );
116 $item_id = $item['item_id'];
117 }
118
119 if ( ! empty( $item['start_time'] ) ) {
120 $this->set_start_time( $item['start_time'] );
121 } else {
122 $this->set_start_time( current_time( 'mysql', 1 ) );
123 }
124
125 if ( ! empty( $item['end_time'] ) ) {
126 $this->set_end_time( $item['end_time'] );
127 } else {
128 $this->set_end_time( null );
129 }
130
131 if ( ! empty( $item['user_id'] ) ) {
132 $item['user_id'] = absint( $item['user_id'] );
133
134 $this->set_user_id( $item['user_id'] );
135 } else {
136 $this->set_user_id( get_current_user_id() );
137 }
138
139 if ( ! empty( $item['status'] ) ) {
140 $this->set_status( $item['status'] );
141 } else {
142 $this->set_status( '' );
143 }
144
145 if ( ! empty( $item['ref_id'] ) ) {
146 $item['ref_id'] = absint( $item['ref_id'] );
147
148 $this->set_ref_id( $item['ref_id'] );
149 if ( empty( $item['ref_type'] ) ) {
150 $this->set_data( 'ref_type', learn_press_get_post_type( $item['ref_id'] ) );
151 }
152 }
153
154 if ( ! empty( $item['ref_type'] ) ) {
155 $this->set_data( 'ref_type', $item['ref_type'] );
156 }
157
158 if ( ! empty( $item['parent_id'] ) ) {
159 $item['parent_id'] = absint( $item['parent_id'] );
160
161 $this->set_parent_id( $item['parent_id'] );
162 }
163
164 if ( ! empty( $item['access_level'] ) ) {
165 $this->set_data( 'access_level', $item['access_level'] );
166 }
167
168 if ( ! empty( $item['graduation'] ) ) {
169 $this->set_data( 'graduation', $item['graduation'] );
170 }
171
172 $new_data = $this->get_mysql_data();
173 ksort( $new_data );
174 $this->_data_key = md5( serialize( $new_data ) );
175 }
176
177 public function set_user_id( $user_id ) {
178 $this->set_data( 'user_id', $user_id );
179 }
180
181 public function get_user_id() {
182 return $this->get_data( 'user_id' );
183 }
184
185 public function set_ref_id( $ref_id ) {
186 $this->set_data( 'ref_id', $ref_id );
187 $this->set_data( 'ref_type', learn_press_get_post_type( $ref_id ) );
188 }
189
190 public function get_parent_id() {
191 return absint( $this->get_data( 'parent_id' ) );
192 }
193
194 public function set_parent_id( $parent_id ) {
195 $this->set_data( 'parent_id', $parent_id );
196 }
197
198 /**
199 * Get access level to a course.
200 *
201 * @return int
202 * @since 3.x.x
203 */
204 public function get_access_level() {
205 return absint( $this->get_data( 'access_level' ) );
206 }
207
208 /**
209 * Get type of item. Consider is post-type.
210 *
211 * @return array|mixed
212 */
213 public function get_type() {
214 return $this->get_data( 'item_type' );
215 }
216
217 /**
218 * Set start-time.
219 *
220 * @param mixed $time .
221 *
222 * @return $this
223 */
224 public function set_start_time( $time ) {
225 $this->_set_data_date( 'start_time', $time );
226
227 return $this;
228 }
229
230 public function get_time( $field, $format = '', $human_diff_time = false ) {
231 if ( ! $format ) {
232 $format = get_option( 'date_format' );
233 }
234
235 $m_time = call_user_func( array( $this, 'get_' . $field ) );
236 $time = mysql2date( 'G', call_user_func( array( $this, 'get_' . $field . '_gmt' ) ) );
237 $time_diff = time() - $time;
238
239 if ( $human_diff_time && $time_diff > 0 && $time_diff < DAY_IN_SECONDS ) {
240 $h_time = sprintf( __( '%s ago', 'learnpress' ), human_time_diff( $time ) );
241 } else {
242 $h_time = mysql2date( $format, $m_time );
243 }
244
245 return $h_time;
246 }
247
248 /**
249 * Get start-time.
250 *
251 * @param string $format
252 * @param bool $local
253 *
254 * @return string|LP_Datetime
255 */
256 public function get_start_time( $format = '', $local = false ) {
257 $date = $this->get_data( 'start_time' );
258
259 return $this->format_time( $date, $format, $local );
260 }
261
262 /**
263 * @param $time
264 *
265 * @deprecated 4.0.0
266 */
267 public function set_start_time_gmt( $time ) {
268 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
269 }
270
271 /**
272 * @param string $format
273 *
274 * @return array|bool|LP_Datetime|mixed|string
275 * @deprecated
276 */
277 public function get_start_time_gmt( $format = '' ) {
278 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
279
280 // $date = $this->get_data_date( 'start_time_gmt' );
281 // if ( $format ) {
282 // return $date->is_null() ? false : ( $format = 'i18n' ? learn_press_date_i18n( $date->getTimestamp() ) : $date->format( $format ) );
283 // }
284 //
285 // return $date;
286 }
287
288 /**
289 * Set end-time for item.
290 *
291 * @param mixed $time
292 *
293 * @return $this
294 */
295 public function set_end_time( $time ) {
296 if ( $time && '0000-00-00 00:00:00' !== $time ) {
297 $this->_set_data_date( 'end_time', $time );
298 } else {
299 $this->_set_data( 'end_time', '' );
300 }
301
302 return $this;
303 }
304
305 /**
306 * Get end-time.
307 *
308 * @param string $format
309 *
310 * @return string|LP_Datetime
311 */
312 public function get_end_time( $format = '' ) {
313 $date = $this->get_data( 'end_time' );
314
315 return $this->format_time( $date, $format );
316 }
317
318 public function get_start_time_local() {
319
320 }
321
322 /**
323 * @param string|int|LP_Datetime $date
324 * @param string $format
325 * @param bool $local
326 *
327 * @return bool|float|int|LP_Datetime|string
328 */
329 public function format_time( $date, $format = '', $local = false ) {
330 if ( ! $date ) {
331 return false;
332 }
333
334 if ( ! $date instanceof LP_Datetime ) {
335 $date = new LP_Datetime( $date );
336 }
337
338 return $format ? $date->format( $format, $local ) : $date;
339 }
340
341 /**
342 * Get end-time.
343 *
344 * @param mixed $time
345 *
346 * @deprecated 4.0.0
347 */
348 public function set_end_time_gmt( $time ) {
349 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
350 }
351
352 /**
353 * Get end-time.
354 *
355 * @param string $format
356 *
357 * @return string|LP_Datetime
358 * @deprecated
359 */
360 public function get_end_time_gmt( $format = '' ) {
361 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
362 }
363
364 /**
365 * Get expiration time.
366 *
367 * @param string $format
368 *
369 * @return string|LP_Datetime $time
370 * @since 3.3.0
371 * @version 3.3.1
372 */
373 public function get_expiration_time( string $format = '' ) {
374 $duration = get_post_meta( $this->get_item_id(), '_lp_duration', true );
375 $start_time = $this->get_start_time( '', false );
376
377 if ( ! absint( $duration ) || ! $start_time ) {
378 $expire = null;
379 } else {
380 $date = new LP_Datetime( $start_time->getPeriod( $duration, true ) );
381 $expire = $this->format_time( $date, $format );
382 }
383
384 return apply_filters( 'learn-press/user-item/expiration-time', $expire, $format, $this );
385 }
386
387 /**
388 * Set item-status.
389 *
390 * @param string $status .
391 *
392 * @return $this
393 */
394 public function set_status( string $status ): LP_User_Item {
395 $this->_set_data( 'status', $status );
396
397 return $this;
398 }
399
400 /**
401 * Get item status.
402 *
403 * @param string $field
404 * @param bool $force_cache Reset first cache
405 *
406 * @version 1.0.1
407 * @return string
408 * @editor tungnx
409 * @modify 4.1.3
410 */
411 public function get_status( string $field = 'status', bool $force_cache = false ): string {
412 $got_status = '';
413
414 try {
415 // User is Guest
416 if ( (int) $this->get_user_id() === 0 ) {
417 return $got_status;
418 }
419
420 $lp_user_item = LP_User_Items_DB::getInstance();
421 $filter = new LP_User_Items_Filter();
422
423 $filter->user_id = $this->get_user_id();
424 $filter->item_id = $this->get_item_id();
425 $filter->ref_id = $this->get_data( 'ref_id' );
426 $filter->parent_id = $this->get_parent_id();
427
428 $user_item = $lp_user_item->get_user_course_item( $filter, $force_cache );
429
430 if ( ! empty( $user_item ) && isset( $user_item->$field ) ) {
431 $got_status = $user_item->$field;
432 }
433
434 $this->set_data( $field, $got_status );
435 } catch ( Throwable $e ) {
436 LP_Debug::error_log( __FUNCTION__ . ':' . $e->getMessage() );
437 }
438
439 return $got_status;
440 }
441
442 public function is_exists() {
443 return ! ! $this->get_user_item_id();
444 }
445
446 /**
447 * @param string $return
448 *
449 * @return LP_User|int
450 */
451 public function get_user( $return = '' ) {
452 return $this->get_data( 'user_id', 0 );
453 }
454
455 /**
456 * Get course.
457 *
458 * @param string $return
459 *
460 * @return bool|LP_Course|int|mixed
461 */
462 public function get_course( string $return = '' ) {
463 $course_id = $this->get_data( 'ref_id', 0 );
464 if ( $return == '' ) {
465 return $course_id ? learn_press_get_course( $course_id ) : false;
466 }
467
468 return $course_id;
469 }
470
471 /**
472 * @return int
473 */
474 public function get_user_item_id() {
475 return intval( $this->get_data( 'user_item_id' ) );
476 }
477
478 /**
479 * Change the primary key user_item_id of user-items.
480 * Only use zero value to force creating new item.
481 *
482 * @param int $user_item_id
483 */
484 public function set_user_item_id( $user_item_id ) {
485 $this->_set_data( 'user_item_id', absint( $user_item_id ) );
486 }
487
488 public function get_item_id() {
489 return $this->get_data( 'item_id' );
490 }
491
492 public function get_parent() {
493 $user = learn_press_get_user( $this->get_user_id() );
494 $ref_id = $this->get_data( 'ref_id' );
495
496 if ( get_post_type( $ref_id ) === LP_COURSE_CPT ) {
497 return $user->get_course_data( $ref_id );
498 }
499
500 return false;
501 }
502
503 public function get_result( $prop = 'result' ) {
504 $result = array(
505 'result' => $this->is_completed() ? 100 : 0,
506 'grade' => $this->is_completed() ? 'passed' : 'failed',
507 );
508
509 return $prop && array_key_exists( $prop, $result ) ? $result[ $prop ] : $result;
510 }
511
512 public function read_meta() {
513 global $wpdb;
514 $query = $wpdb->prepare(
515 "
516 SELECT *
517 FROM {$wpdb->learnpress_user_itemmeta}
518 WHERE learnpress_user_item_id = %d
519 ",
520 $this->get_user_item_id()
521 );
522
523 $results = $wpdb->get_results( $query );
524 if ( $results ) {
525 foreach ( $results as $result ) {
526 $result->meta_value = LP_Helper::maybe_unserialize( $result->meta_value );
527 $this->_meta_data[] = $result;
528 }
529 }
530
531 }
532
533 /**
534 * Get structure of an user item.
535 *
536 * @return array
537 * @since 3.1.0
538 */
539 public static function get_empty_item() {
540 return array(
541 'user_item_id' => 0,
542 'user_id' => 0,
543 'item_id' => 0,
544 'start_time' => '',
545 'end_time' => '',
546 'item_type' => '',
547 'status' => '',
548 'graduation' => '',
549 'access_level' => 50,
550 'ref_id' => '',
551 'ref_type' => '',
552 'parent_id' => 0,
553 );
554 }
555
556 /**
557 * Get user-item meta data.
558 * Check if meta data does not exist then return FALSE.
559 *
560 * @updated 3.1.0
561 *
562 * @param string $key
563 * @param bool $single
564 *
565 * @return bool|mixed
566 */
567 public function get_meta( $key, $single = true ) {
568 if ( ! metadata_exists( 'learnpress_user_item', $this->get_user_item_id(), $key ) ) {
569 return false;
570 }
571
572 return learn_press_get_user_item_meta( $this->get_user_item_id(), $key, $single );
573 }
574
575 /**
576 * Update meta data
577 *
578 * @updated 3.1.0
579 *
580 * @param string $key
581 * @param string $value
582 * @param string $prev_value
583 *
584 * @editor tungnx add bk method
585 */
586 public function update_meta_bk( $key = '', $value = '', $prev_value = '' ) {
587 if ( func_num_args() === 0 ) {
588 if ( $this->_meta_data ) {
589 foreach ( $this->_meta_data as $meta_data ) {
590 if ( $meta_data->meta_value ) {
591 learn_press_update_user_item_meta(
592 $this->get_user_item_id(),
593 $meta_data->meta_key,
594 $meta_data->meta_value
595 );
596 } else {
597 learn_press_delete_user_item_meta( $this->get_user_item_id(), $meta_data->meta_key );
598 }
599 }
600 }
601 } else {
602 if ( is_array( $key ) ) {
603 foreach ( $key as $k => $v ) {
604 if ( $v === false ) {
605 learn_press_delete_user_item_meta( $this->get_user_item_id(), $k );
606 } else {
607 learn_press_update_user_item_meta( $this->get_user_item_id(), $k, $v );
608 }
609 }
610 } else {
611 if ( $value === false ) {
612 learn_press_delete_user_item_meta( $this->get_user_item_id(), $key );
613 } else {
614 learn_press_update_user_item_meta( $this->get_user_item_id(), $key, $value, $prev_value );
615 }
616 }
617 }
618 }
619
620 /**
621 * Update meta data
622 *
623 * @param string $key .
624 * @param string $value .
625 * @param string $prev_value .
626 *
627 * @return int|bool
628 * @editor tungnx
629 */
630 public function update_meta( $key = '', $value = '', $prev_value = '' ) {
631 $result = false;
632
633 if ( is_array( $key ) ) {
634 $result = $this->update_meta_multiple_keys( $key );
635 } else {
636 if ( false === $value ) {
637 $result = learn_press_delete_user_item_meta( $this->get_user_item_id(), $key );
638 } else {
639 $result = learn_press_update_user_item_meta( $this->get_user_item_id(), $key, $value, $prev_value );
640 }
641 }
642
643 return $result;
644 }
645
646 /**
647 * Update metadata with array keys values
648 *
649 * @param array $meta_datas .
650 *
651 * @return bool|int
652 */
653 public function update_meta_multiple_keys( $meta_datas = array() ) {
654 $result = false;
655
656 foreach ( $meta_datas as $k => $v ) {
657 if ( false === $v ) {
658 $result = learn_press_delete_user_item_meta( $this->get_user_item_id(), $k );
659 } else {
660 $result = learn_press_update_user_item_meta( $this->get_user_item_id(), $k, $v );
661 }
662 }
663
664 return $result;
665 }
666
667 public function get_mysql_data() {
668 /**
669 * @var LP_Datetime $v
670 */
671 $columns = array();
672
673 foreach ( $this->get_data() as $k => $v ) {
674 switch ( $k ) {
675 case 'start_time':
676 case 'end_time':
677 $v = is_a( $v, 'LP_Datetime' ) ? $v->toSql( false ) : $v;
678 break;
679 }
680 $columns[ $k ] = $v;
681 }
682
683 return $columns;
684 }
685
686 /**
687 * @param $data
688 *
689 * @return LP_User_Item|bool
690 */
691 public static function get_item_object( $data ) {
692 $item_id = 0;
693
694 if ( is_array( $data ) && isset( $data['item_id'] ) ) {
695 $item_id = $data['item_id'];
696 } elseif ( is_object( $data ) && isset( $data->item_id ) ) {
697 $item_id = $data->item_id;
698 } elseif ( is_numeric( $data ) ) {
699 $item_id = absint( $data );
700 } elseif ( $data instanceof LP_User_Item ) {
701 $item_id = $data->get_id();
702 }
703
704 $item = false;
705 $item_type = learn_press_get_post_type( $item_id );
706
707 switch ( $item_type ) {
708 case LP_LESSON_CPT:
709 $item = new LP_User_Item( $data );
710 break;
711 case LP_QUIZ_CPT:
712 $item = new LP_User_Item_Quiz( $data );
713 break;
714 default:
715 break;
716 }
717
718 return apply_filters( 'learn-press/user-item-object', $item, $data, $item_type );
719 }
720
721 /**
722 * Set graduation
723 *
724 * @param string $graduation .
725 *
726 * @return $this
727 */
728 public function set_graduation( string $graduation ): LP_User_Item {
729 $this->_set_data( 'graduation', $graduation );
730
731 return $this;
732 }
733
734 /**
735 * Get graduation
736 *
737 * @param string $context
738 *
739 * @return string
740 */
741 public function get_graduation( string $context = '' ): string {
742 $grade = $this->get_data( 'graduation', '' );
743 if ( ! $grade ) {
744 return '';
745 }
746 return $context == 'display' ? learn_press_course_grade_html( $grade, false ) : $grade;
747 }
748
749 /**
750 * Update data from memory to database.
751 *
752 * @updated 3.1.0
753 *
754 * @return bool|mixed
755 * @throws Exception
756 */
757 public function update( $force = false, $wp_error = false ) {
758
759 $data = $this->get_mysql_data();
760
761 /**
762 * @since 3.3.0
763 * Allow filter to modify data
764 */
765 $data = apply_filters( 'learn-press/update-user-item-data', $data, $this->get_user_item_id() );
766 $where = array();
767
768 if ( $this->get_user_item_id() ) {
769 $where = array( 'user_item_id' => $this->get_user_item_id() );
770 }
771
772 $return = learn_press_update_user_item_field( $data, $where );
773
774 // Clear cache first status
775 $this->get_status( 'status', true );
776
777 if ( $return ) {
778 foreach ( (array) $return as $k => $v ) {
779 $this->_set_data( $k, $v );
780 }
781 $this->_changes = array();
782 }
783
784 /*$data_course = $this->get_parent();
785 if ( $data_course ) {
786 $data_course->calculate_course_results();
787 }*/
788
789 return $return;
790 }
791
792 /**
793 * @editor tungnx
794 * @reason commnet - not use
795 * @modify 4.1.2
796 */
797 /*
798 public function is_course_item() {
799 return learn_press_is_support_course_item_type( $this->get_data( 'item_type' ) );
800 }*/
801
802 public function get_status_label( $status = '' ) {
803 $statuses = array(
804 LP_COURSE_ENROLLED => esc_html__( 'Enrolled', 'learnpress' ),
805 LP_COURSE_PURCHASED => esc_html__( 'Purchased', 'learnpress' ),
806 LP_ITEM_COMPLETED => esc_html__( 'Completed', 'learnpress' ),
807 LP_ITEM_STARTED => esc_html__( 'Started', 'learnpress' ),
808 LP_COURSE_FINISHED => esc_html__( 'Finished', 'learnpress' ),
809 );
810
811 if ( ! $status ) {
812 $status = $this->get_status();
813 }
814
815 return ! empty( $statuses[ $status ] ) ? $statuses[ $status ] : esc_html__( 'Not Enrolled', 'learnpress' );
816 }
817
818 /**
819 * Get time from user started to ended.
820 *
821 * @param string $context
822 *
823 * @return bool|float|int
824 */
825 public function get_time_interval( $context = '' ) {
826 $start = $this->get_start_time();
827 $end = $this->get_end_time();
828
829 if ( ! $start instanceof LP_Datetime || ! $end instanceof LP_Datetime ) {
830 return false;
831 }
832
833 if ( $start->is_null() || $end->is_null() ) {
834 return false;
835 }
836 $interval = $end->getTimestamp() - $start->getTimestamp();
837
838 return $interval;
839 }
840
841 /*public function get_history() {
842 return LP_Object_Cache::get(
843 sprintf(
844 'course-item-%s-%s-%s',
845 $this->get_user_id(),
846 $this->get_course( 'id' ),
847 $this->get_id()
848 ),
849 'learn-press/user-course-items'
850 );
851 }*/
852
853 /**
854 * @editor tungnx
855 * @modify 4.1.2
856 * @reason comment - not use
857 */
858 /*
859 public function count_history() {
860 if ( $items = $this->get_history() ) {
861 return sizeof( $items );
862 }
863
864 return 0;
865 }*/
866
867 /**
868 * @editor tungnx
869 * @modify 4.1.2
870 * @reason comment - not use
871 */
872 /*
873 public function remove_user_items_history( $keep = 10 ) {
874 learn_press_remove_user_items_history(
875 $this->get_item_id(),
876 $this->get_course( 'id' ),
877 $this->get_user_id(),
878 $keep
879 );
880 }*/
881
882 /**
883 * Return number of seconds has exceeded from the expiration time to now.
884 * If less than or equals to 0 that means the time is exceeded.
885 * Otherwise, the time is not exceeded.
886 *
887 * @return float|int
888 * @since 3.3.0
889 */
890 public function get_exceeded() {
891 $time = new LP_Datetime();
892 $current = $time->getTimestamp( false );
893 $exceeded = $this->get_expiration_time();
894
895 return false !== $exceeded ? $exceeded->getTimestamp() - $current : false;
896 }
897
898 /**
899 * Check if user was finished before the expiration time is exceeded.
900 * If the expiration-time is NULL that mean the course is not set duration.
901 *
902 * @return bool|float|int
903 * @since 3.3.0
904 * Todo: check remove function
905 */
906 public function is_exceeded() {
907 $expiration = $this->get_expiration_time();
908 $end = $this->get_end_time();
909
910 if ( ! $expiration ) {
911 return false;
912 }
913
914 // If course is not finished then consider end time is current time
915 if ( ! $end || 0 >= $end->getTimestamp() ) {
916 $end = new LP_Datetime();
917 $end = $end->getTimestamp( false );
918 } else {
919 $end = $end->getTimestamp();
920 }
921
922 return $expiration->getTimestamp() - $end;
923 }
924
925 /**
926 * Get time remaining for user item.
927 *
928 * @param string $return - Optional. What kind of data to return.
929 *
930 * @return LP_Duration
931 * @since 3.3.0
932 */
933 public function get_time_remaining( $return = 'object' ) {
934 $is_exceeded = $this->is_exceeded();
935 $time = false;
936
937 if ( false !== $is_exceeded ) {
938 $time = 0 < $is_exceeded ? absint( $is_exceeded ) : 0;
939 }
940
941 // return apply_filters( 'learn-press/quiz/time-remaining', $remaining, $this->get_item_id(), $this->get_course_id() );
942 return apply_filters(
943 'learn-press/user-item-time-remaining',
944 $return === 'object' ? new LP_Duration( $time ) : $time,
945 $this->get_item_id(),
946 $this->get_parent_id(),
947 $this->get_user_id()
948 );
949 }
950
951 /**
952 * Return true of item is completed/finished
953 *
954 * @param string $status
955 *
956 * @return bool
957 */
958 public function is_completed( $status = 'completed' ) {
959 return $this->get_status() === $status;
960 }
961
962 /**
963 * Complete item
964 *
965 * @editor tungnx
966 * @modify 4.1.4.1 - should review to improve
967 * @version 4.0.1
968 */
969 public function complete( $status = 'completed' ) {
970 global $wpdb;
971
972 // $end_time = new LP_Datetime();
973 // $null_time = null;
974
975 try {
976 // if ( ! $this->get_end_time() ) {
977 $this->set_end_time( current_time( 'mysql', 1 ) );
978 // }
979
980 $this->set_status( $status );
981 $this->update();
982
983 /*
984 $query = $wpdb->prepare(
985 "SELECT user_item_id
986 FROM {$wpdb->prefix}learnpress_user_items
987 WHERE user_id = %d
988 AND item_id = %d
989 AND status = %s
990 GROUP BY user_item_id DESC
991 LIMIT 1
992 ",
993 $this->get_user_id(),
994 $this->get_item_id(),
995 $status
996 );
997
998 return $wpdb->get_var( $query );*/
999 } catch ( Throwable $e ) {
1000 error_log( __FUNCTION__ . ':' . $e->getMessage() );
1001 return false;
1002 }
1003
1004 return true;
1005 }
1006
1007 /**
1008 * @editor tungnx
1009 * @modify 4.1.2
1010 * @reason comment - not use
1011 */
1012 /*
1013 public function delete_meta_data( $include = '', $exclude = '' ) {
1014 global $wpdb;
1015
1016 $where = '';
1017 if ( $include ) {
1018 settype( $include, 'array' );
1019 $format = array_fill( 0, sizeof( $include ), '%s' );
1020 $where .= $wpdb->prepare( ' AND meta_key IN(' . join( ',', $format ) . ')', $include );
1021 }
1022
1023 if ( $exclude ) {
1024 settype( $exclude, 'array' );
1025 $format = array_fill( 0, sizeof( $exclude ), '%s' );
1026 $where .= $wpdb->prepare( ' AND meta_key IN(' . join( ',', $format ) . ')', $exclude );
1027 }
1028
1029 $query = $wpdb->prepare(
1030 "
1031 DELETE FROM {$wpdb->learnpress_user_itemmeta}
1032 WHERE learnpress_user_item_id = %d
1033 {$where}
1034 ",
1035 $this->get_user_item_id()
1036 );
1037
1038 $wpdb->query( $query );
1039
1040 $this->_meta_data = array();
1041 update_meta_cache( 'learnpress_user_item', $this->get_user_item_id() );
1042 }*/
1043
1044 /**
1045 * Get post type of item.
1046 *
1047 * @return string
1048 */
1049 public function get_post_type() {
1050 return learn_press_get_post_type( $this->get_item_id() );
1051 }
1052
1053 /**
1054 * @return bool
1055 */
1056 public function is_passed() {
1057 return 'passed' === $this->get_graduation();
1058 }
1059
1060 public function get_percent_result( $decimal = 1 ) {
1061 return apply_filters(
1062 'learn-press/user/item-percent-result',
1063 sprintf(
1064 '%s%%',
1065 round( $this->get_result( 'result' ), $decimal ),
1066 $this->get_user_id(),
1067 $this->get_item_id()
1068 )
1069 );
1070 }
1071
1072 /**
1073 * Calculate expiration time from the start time and duration.
1074 *
1075 * @param int|string|LP_Datetime $duration
1076 *
1077 * @return LP_Datetime
1078 * @since 3.3.0
1079 * @depecated 4.1.7
1080 */
1081 /*public function set_duration( $duration ) {
1082 if ( $duration instanceof LP_Datetime ) {
1083 $period = $duration->toSql();
1084 } else {
1085 $period = $duration;
1086 }
1087
1088 return $this->get_expiration_time();
1089 }*/
1090
1091 /**
1092 * @depecated 4.1.7
1093 */
1094 /*public function is_change() {
1095
1096 $new_data = $this->get_mysql_data();
1097 ksort( $new_data );
1098
1099 return $this->_data_key !== md5( serialize( $new_data ) );
1100 }*/
1101
1102 protected function _set_data_date( $key, $value, $extra = false ) {
1103 if ( $value instanceof LP_Datetime ) {
1104 $value = $value->getTimestamp();
1105 } else {
1106 $value = is_numeric( $value ) ? $value : strtotime( $value );
1107 }
1108 $offset = (int) ( get_option( 'gmt_offset', 0 ) * HOUR_IN_SECONDS );
1109
1110 parent::_set_data_date( $key, $value + $offset, $extra );
1111 }
1112
1113 /**
1114 * @param $name
1115 * @param $arguments
1116 *
1117 * @return mixed
1118 * @depecated 4.1.7
1119 */
1120 /*public function __call( $name, $arguments ) {
1121 if ( ! method_exists( $this, $name ) ) {
1122 $course = $this->get_course();
1123
1124 if ( $course ) {
1125 $item = $course->get_item( $this->get_item_id() );
1126
1127 if ( is_callable( array( $item, $name ) ) ) {
1128 return call_user_func_array( array( $item, $name ), $arguments );
1129 }
1130 }
1131 }
1132
1133 return false;
1134 }*/
1135
1136 public function offsetSet( $offset, $value ) {
1137 // TODO: Implement offsetSet() method.
1138 }
1139
1140 public function offsetGet( $offset ) {
1141 if ( is_callable( array( $this, 'get_' . $offset ) ) ) {
1142 return call_user_func( array( $this, 'get_' . $offset ) );
1143 }
1144
1145 return false;
1146 }
1147
1148 public function offsetUnset( $offset ) {
1149 // TODO: Implement offsetUnset() method.
1150 }
1151
1152 public function offsetExists( $offset ) {
1153 // TODO: Implement offsetExists() method.
1154 }
1155 }
1156
1157