PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.7
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.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 / Models / UserItems / UserItemModel.php

UserItemModel.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.7, at inc/Models/UserItems/UserItemModel.php

658 lines 15.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Class UserItemModel
5 * To replace class LP_User_Item
6 *
7 * @package LearnPress/Classes
8 * @version 1.0.3
9 * @since 4.2.5
10 */
11
12 namespace LearnPress\Models\UserItems;
13
14 use Exception;
15 use LearnPress\Filters\UserItemsFilter;
16 use LearnPress\Models\CoursePostModel;
17 use LearnPress\Models\PostModel;
18 use LearnPress\Models\UserItemMeta\UserItemMetaModel;
19 use LearnPress\Models\UserModel;
20 use LP_Datetime;
21 use LP_User_Item_Meta_DB;
22 use LP_User_Item_Meta_Filter;
23 use LP_User_Items_Cache;
24 use LP_User_Items_DB;
25 use LP_User_Items_Filter;
26 use stdClass;
27 use Throwable;
28
29 class UserItemModel {
30 /**
31 * Auto increment, Primary key
32 *
33 * @var int
34 */
35 private $user_item_id = 0;
36 /**
37 * @var string User ID, foreign key
38 */
39 public $user_id = 0;
40 /**
41 * Item id (course, lesson, quiz ...)
42 *
43 * @var string foreign key
44 */
45 public $item_id = 0;
46 /**
47 * @var string Time start item
48 */
49 public $start_time = null;
50 /**
51 * @var string Time finish item
52 */
53 public $end_time = null;
54 /**
55 * Item type (course, lesson, quiz ...)
56 *
57 * @var string Item type
58 */
59 public $item_type = '';
60 /**
61 * Item status (completed, enrolled, finished ...)
62 *
63 * @var string
64 */
65 public $status = '';
66 /**
67 * Item graduation
68 *
69 * @var string (passed, failed, in-progress...)
70 */
71 public $graduation = null;
72 /**
73 * Ref id (Order, course ...)
74 *
75 * @var int Reference id
76 */
77 public $ref_id = 0;
78 /**
79 * Ref type (Order, course ...)
80 *
81 * @var string
82 */
83 public $ref_type = '';
84 /**
85 * Parent id
86 *
87 * @var int
88 */
89 public $parent_id = 0;
90 /**
91 * @var null|PostModel|CoursePostModel
92 */
93 public $item;
94 /**
95 * List UserItemMetaModel
96 * object {meta_key: {meta_id, learnpress_user_item_id, meta_key, meta_value, extra_value}}
97 *
98 * @var {meta_key: UserItemMetaModel}
99 */
100 public $meta_data;
101
102 // Constants
103 const STATUS_COMPLETED = 'completed';
104 const STATUS_FINISHED = 'finished';
105 const STATUS_ENROLLED = 'enrolled';
106 const STATUS_PURCHASED = 'purchased';
107 const STATUS_CANCEL = 'cancel';
108 const GRADUATION_IN_PROGRESS = 'in-progress';
109 const GRADUATION_PASSED = 'passed';
110 const GRADUATION_FAILED = 'failed';
111
112 /**
113 * If data get from database, map to object.
114 * Else create new object to save data to database.
115 *
116 * @param array|object|mixed $data
117 */
118 public function __construct( $data = null ) {
119 if ( $data ) {
120 $this->map_to_object( $data );
121 $this->get_user_model();
122 }
123
124 if ( ! $this->meta_data instanceof stdClass ) {
125 $this->meta_data = new stdClass();
126 }
127 }
128
129 /**
130 * Get start time
131 *
132 * @return string
133 */
134 public function get_start_time(): string {
135 return is_null( $this->start_time ) ? '' : $this->start_time;
136 }
137
138 /**
139 * Get end time
140 *
141 * @return string
142 */
143 public function get_end_time(): string {
144 return is_null( $this->end_time ) ? '' : $this->end_time;
145 }
146
147 /**
148 * Get status
149 *
150 * @return string
151 */
152 public function get_status(): string {
153 return $this->status;
154 }
155
156 /**
157 * Get graduation
158 *
159 * @return string
160 */
161 public function get_graduation(): string {
162 return is_null( $this->graduation ) ? '' : $this->graduation;
163 }
164
165
166 /**
167 * Get user item id
168 *
169 * @return int
170 */
171 public function get_user_item_id(): int {
172 return $this->user_item_id;
173 }
174
175 /**
176 * Set user item id
177 *
178 * @param int $user_item_id
179 */
180 private function set_user_item_id( int $user_item_id ) {
181 $this->user_item_id = $user_item_id;
182 }
183
184 /**
185 * Get user model
186 *
187 * @return false|UserModel
188 * @since 4.2.6
189 * @version 1.0.1
190 */
191 public function get_user_model() {
192 return UserModel::find( $this->user_id, true );
193 }
194
195 /**
196 * Map array, object data to UserItemModel.
197 * Use for data get from database.
198 *
199 * @param array|object|mixed $data
200 *
201 * @return UserItemModel
202 */
203 public function map_to_object( $data ): UserItemModel {
204 foreach ( $data as $key => $value ) {
205 if ( property_exists( $this, $key ) ) {
206 $this->{$key} = $value;
207 }
208 }
209
210 return $this;
211 }
212
213 /**
214 * Get user item from database by user_id, item_id, item_type.
215 * If not exists, return false.
216 * If exists, return UserItemModel.
217 *
218 * @param LP_User_Items_Filter|UserItemsFilter $filter
219 *
220 * @return UserItemModel|false|static
221 * @since 4.2.5
222 * @version 1.0.2
223 */
224 public static function get_user_item_model_from_db( $filter ) {
225 $lp_user_item_db = LP_User_Items_DB::getInstance();
226 $user_item_model = false;
227
228 try {
229 // Set order by user_item_id DESC to get the latest user item.
230 $filter->order = $filter::ORDER_DESC;
231 $filter->order_by = $filter::COL_USER_ITEM_ID;
232 if ( empty( $filter->item_type ) ) {
233 $filter->item_type = ( new static() )->item_type;
234 }
235
236 $lp_user_item_db->get_query_single_row( $filter );
237 $query_single_row = $lp_user_item_db->get_user_items( $filter );
238 $user_item_rs = $lp_user_item_db->wpdb->get_row( $query_single_row );
239 if ( $user_item_rs instanceof stdClass ) {
240 $user_item_model = new static( $user_item_rs );
241 }
242 } catch ( Throwable $e ) {
243 error_log( __METHOD__ . ': ' . $e->getMessage() );
244 }
245
246 return $user_item_model;
247 }
248
249 /**
250 * Find User Item by user_id, item_id, item_type.
251 *
252 * @param int $user_id
253 * @param int $item_id
254 * @param string $item_type
255 * @param int $ref_id
256 * @param string $ref_type
257 * @param bool $check_cache
258 *
259 * @return false|UserItemModel|static
260 * @since 4.2.7.3
261 * @version 1.0.2
262 */
263 public static function find_user_item(
264 int $user_id,
265 int $item_id,
266 string $item_type,
267 int $ref_id = 0,
268 string $ref_type = '',
269 bool $check_cache = false
270 ) {
271 $key_cache = "userItemModel/find/{$user_id}/{$item_id}/{$item_type}";
272 $filter = new LP_User_Items_Filter();
273 $filter->user_id = $user_id;
274 $filter->item_id = $item_id;
275 $filter->item_type = $item_type;
276 if ( ! empty( $ref_id ) ) {
277 $filter->ref_id = $ref_id;
278 $key_cache .= "/{$ref_id}";
279 }
280 if ( ! empty( $ref_type ) ) {
281 $filter->ref_type = $ref_type;
282 $key_cache .= "/{$ref_type}";
283 }
284 $lpUserItemCache = new LP_User_Items_Cache();
285
286 // Check cache
287 if ( $check_cache ) {
288 $userItemModel = $lpUserItemCache->get_cache( $key_cache );
289 if ( $userItemModel instanceof UserItemModel ) {
290 return new static( $userItemModel );
291 }
292 }
293
294 $userItemModel = static::get_user_item_model_from_db( $filter );
295 // Set cache
296 if ( $userItemModel instanceof UserItemModel ) {
297 if ( ! $userItemModel->meta_data instanceof stdClass ) {
298 $userItemModel->meta_data = new stdClass();
299 }
300
301 $lpUserItemCache->set_cache( $key_cache, $userItemModel );
302 }
303
304 return $userItemModel;
305 }
306
307 /**
308 * Get user item metadata from object meta_data or database by user_item_id, meta_key.
309 *
310 * @param string $key
311 *
312 * @return false|UserItemMetaModel
313 * @since 4.2.5
314 * @version 1.0.1
315 */
316 public function get_meta_model_from_key( string $key ) {
317 $filter = new LP_User_Item_Meta_Filter();
318 $filter->meta_key = $key;
319 $filter->learnpress_user_item_id = $this->get_user_item_id();
320
321 return UserItemMetaModel::get_user_item_meta_model_from_db( $filter );
322 }
323
324 /**
325 * Get metadata from key
326 *
327 * @param string $key
328 * @param mixed $default_value
329 * @param bool $get_extra
330 *
331 * @return false|string
332 * @since 4.2.5
333 * @version 1.0.3
334 */
335 public function get_meta_value_from_key( string $key, $default_value = false, bool $get_extra = false ) {
336 if ( $this->meta_data instanceof stdClass && isset( $this->meta_data->{$key} ) ) {
337 return maybe_unserialize( $this->meta_data->{$key} );
338 }
339
340 $user_item_metadata = $this->get_meta_model_from_key( $key );
341 if ( $user_item_metadata instanceof UserItemMetaModel ) {
342 if ( ! $this->meta_data instanceof stdClass ) {
343 $this->meta_data = new stdClass();
344 }
345
346 if ( $get_extra ) {
347 $data = $user_item_metadata->extra_value;
348 } else {
349 $data = $user_item_metadata->meta_value;
350 }
351
352 $this->meta_data->{$key} = maybe_unserialize( $data );
353 } else {
354 $data = $default_value;
355 }
356
357 return $data;
358 }
359
360 /**
361 * Update meta value for key.
362 *
363 * @param string $key
364 * @param mixed $value
365 * @param bool $is_extra
366 *
367 * @return void
368 * @since 4.2.7.4
369 * @version 1.0.0
370 */
371 public function set_meta_value_for_key( string $key, $value, bool $is_extra = false ) {
372 if ( ! $this->meta_data instanceof stdClass ) {
373 $this->meta_data = new stdClass();
374 }
375
376 $this->meta_data->{$key} = $value;
377 $lp_db = LP_User_Items_DB::getInstance();
378 if ( $is_extra ) {
379 if ( is_object( $value ) || is_array( $value ) ) {
380 $value = json_encode( $value );
381 }
382 $lp_db->update_extra_value( $this->get_user_item_id(), $key, $value );
383 } else {
384 learn_press_update_user_item_meta( $this->get_user_item_id(), $key, $value );
385 }
386
387 //$this->clean_caches();
388 }
389
390 /**
391 * Delete meta from key.
392 *
393 * @param string $key
394 *
395 * @return void
396 * @since 4.2.7.4
397 * @version 1.0.0
398 */
399 public function delete_meta( string $key ) {
400 $user_item_metadata = $this->get_meta_model_from_key( $key );
401 if ( $user_item_metadata instanceof UserItemMetaModel ) {
402 $user_item_metadata->delete();
403 $this->meta_data->{$key} = null;
404 $this->clean_caches();
405 }
406 }
407
408 /**
409 * Update data to database.
410 *
411 * If user_item_id is empty, insert new data, else update data.
412 *
413 * @return UserItemModel
414 * @throws Exception
415 * @since 4.2.5
416 * @version 1.0.3
417 */
418 public function save(): UserItemModel {
419 $lp_user_item_db = LP_User_Items_DB::getInstance();
420 $user_item_id_new = 0;
421 $data = get_object_vars( $this );
422
423 if ( ! isset( $data['start_time'] ) ) {
424 $data['start_time'] = gmdate( 'Y-m-d H:i:s', time() );
425 $this->start_time = $data['start_time'];
426 }
427
428 // Check if exists user_item_id.
429 if ( empty( $this->get_user_item_id() ) ) { // Insert data.
430 if ( empty( $data['item_id'] ) ) {
431 throw new Exception( 'Item ID is require.' );
432 }
433 if ( empty( $data['item_type'] ) ) {
434 throw new Exception( 'Item Type is require.' );
435 }
436
437 // Guest can buy course if enable guest checkout.
438 if ( empty( $data['user_id'] ) && LP_COURSE_CPT !== $data['item_type'] ) {
439 throw new Exception( 'User ID is require.' );
440 }
441
442 $user_item_id_new = $lp_user_item_db->insert_data( $data );
443 if ( empty( $user_item_id_new ) ) {
444 throw new Exception( 'Cannot insert data to database.' );
445 }
446 } else { // Update data.
447 $lp_user_item_db->update_data( $data );
448 }
449
450 if ( $user_item_id_new ) {
451 $this->set_user_item_id( $user_item_id_new );
452 }
453
454 // Clear caches before firing the created hook. Webhook and third-party listeners may reload
455 // this user item from the model/cache layer, so firing earlier can expose stale data.
456 $this->clean_caches();
457
458 if ( $user_item_id_new ) {
459 do_action( 'learn-press/user-item/created', $this );
460 }
461
462 return $this;
463 }
464
465 /**
466 * Get total timestamp complete, done item.
467 *
468 * @return int
469 */
470 public function get_total_timestamp_completed(): int {
471 $time_interval = 0;
472
473 if ( empty( $this->get_start_time() ) || empty( $this->get_end_time() ) ) {
474 return $time_interval;
475 }
476
477 $start = new LP_Datetime( $this->get_start_time() );
478 $end = new LP_Datetime( $this->get_end_time() );
479
480 return $end->getTimestamp() - $start->getTimestamp();
481 }
482
483 /**
484 * Get expiration time.
485 *
486 * @return null|LP_Datetime $time
487 * @since 3.3.0
488 * @version 3.3.3
489 */
490 public function get_expiration_time() {
491 $duration = get_post_meta( $this->item_id, '_lp_duration', true );
492
493 if ( ! absint( $duration ) || empty( $this->start_time ) ) {
494 $expire = null;
495 } else {
496 $start = new LP_Datetime( $this->start_time );
497 $start_time = $start->getTimestamp();
498 // Convert duration from string to seconds.
499 if ( ! is_numeric( $duration ) ) {
500 $duration = strtotime( $duration ) - time();
501 }
502
503 $expire_time = $start_time + $duration;
504 $expire = new LP_Datetime( $expire_time );
505 }
506
507 return apply_filters( 'learnPress/user-item/expiration-time', $expire, $duration, $this );
508 }
509
510 /**
511 * Get translate value.
512 *
513 * @param string $value
514 *
515 * @return string
516 * @since 4.2.7.8
517 * @version 1.0.0
518 */
519 public function get_string_i18n( string $value ): string {
520 switch ( $value ) {
521 case self::STATUS_COMPLETED:
522 $value = __( 'Completed', 'learnpress' );
523 break;
524 case self::STATUS_FINISHED:
525 $value = __( 'Finished', 'learnpress' );
526 break;
527 case self::STATUS_ENROLLED:
528 $value = __( 'Enrolled', 'learnpress' );
529 break;
530 case self::STATUS_CANCEL:
531 $value = __( 'Cancel', 'learnpress' );
532 break;
533 case self::GRADUATION_IN_PROGRESS:
534 $value = __( 'In Progress', 'learnpress' );
535 break;
536 case self::GRADUATION_PASSED:
537 $value = __( 'Passed', 'learnpress' );
538 break;
539 case self::GRADUATION_FAILED:
540 $value = __( 'Failed', 'learnpress' );
541 break;
542 }
543
544 return $value;
545 }
546
547 /**
548 * Get status label.
549 *
550 * @return string
551 * @since 4.4.2
552 * @version 1.0.0
553 */
554 public function get_status_label(): string {
555 switch ( $this->get_status() ) {
556 case self::STATUS_COMPLETED:
557 $value = __( 'Completed', 'learnpress' );
558 break;
559 case self::STATUS_FINISHED:
560 $value = __( 'Finished', 'learnpress' );
561 break;
562 case self::STATUS_ENROLLED:
563 $value = __( 'Enrolled', 'learnpress' );
564 break;
565 case self::STATUS_CANCEL:
566 $value = __( 'Cancel', 'learnpress' );
567 break;
568 default:
569 $value = $this->get_status();
570 break;
571 }
572
573 return (string) $value;
574 }
575
576 /**
577 * Get graduation label.
578 *
579 * @return string
580 * @since 4.4.2
581 * @version 1.0.0
582 */
583 public function get_graduation_label(): string {
584 switch ( $this->get_graduation() ) {
585 case self::GRADUATION_IN_PROGRESS:
586 $value = __( 'In Progress', 'learnpress' );
587 break;
588 case self::GRADUATION_PASSED:
589 $value = __( 'Passed', 'learnpress' );
590 break;
591 case self::GRADUATION_FAILED:
592 $value = __( 'Failed', 'learnpress' );
593 break;
594 default:
595 $value = $this->get_graduation();
596 break;
597 }
598
599 return (string) $value;
600 }
601
602 /**
603 * Delete user item.
604 *
605 * @throws Exception
606 * @since 4.2.7.3
607 * @version 1.0.2
608 */
609 public function delete() {
610 // Delete meta data of user item.
611 $lp_user_item_meta_db = LP_User_Item_Meta_DB::getInstance();
612 $filter = new LP_User_Item_Meta_Filter();
613 $filter->where[] = $lp_user_item_meta_db->wpdb->prepare( 'AND learnpress_user_item_id = %d', $this->get_user_item_id() );
614 $filter->collection = $lp_user_item_meta_db->tb_lp_user_itemmeta;
615 $lp_user_item_meta_db->delete_execute( $filter );
616 $this->meta_data = null;
617
618 // Delete user item relationships.
619 $lp_user_item_db = LP_User_Items_DB::getInstance();
620 $filter = new LP_User_Items_Filter();
621 $filter->where[] = $lp_user_item_db->wpdb->prepare( 'AND parent_id = %d', $this->get_user_item_id() );
622 $filter->collection = $lp_user_item_db->tb_lp_user_items;
623 $lp_user_item_db->delete_execute( $filter );
624
625 // Delete user item.
626 $lp_user_item_db = LP_User_Items_DB::getInstance();
627 $filter = new LP_User_Items_Filter();
628 $filter->where[] = $lp_user_item_db->wpdb->prepare( 'AND user_item_id = %d', $this->get_user_item_id() );
629 $filter->collection = $lp_user_item_db->tb_lp_user_items;
630 $lp_user_item_db->delete_execute( $filter );
631
632 $this->clean_caches();
633 }
634
635 /**
636 * Clean caches.
637 *
638 * @return void
639 */
640 public function clean_caches() {
641 // Clear cache user item.
642 $lp_user_items_cache = new LP_User_Items_Cache();
643 $lp_user_items_cache->clean_user_item(
644 [
645 $this->user_id,
646 $this->item_id,
647 $this->item_type,
648 ]
649 );
650
651 $key_cache_user_item = "userItemModel/find/{$this->user_id}/{$this->item_id}/{$this->item_type}";
652 $lp_user_items_cache->clear( $key_cache_user_item );
653
654 $key_cache_user_item_ref = "userItemModel/find/{$this->user_id}/{$this->item_id}/{$this->item_type}/{$this->ref_id}/{$this->ref_type}";
655 $lp_user_items_cache->clear( $key_cache_user_item_ref );
656 }
657 }
658