PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
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 / curds / class-lp-user-curd.php

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

739 lines 16.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_CURD
5 *
6 * @since 3.0
7 */
8 class LP_User_CURD extends LP_Object_Data_CURD implements LP_Interface_CURD {
9
10 /**
11 * @var string
12 */
13 protected $_meta_type = 'user';
14
15 /**
16 * @var int
17 */
18 protected $_user_id = 0;
19
20 /**
21 * @var int
22 */
23 protected $_course_id = 0;
24
25 /**
26 * LP_User_CURD constructor.
27 *
28 * @param int $the_user
29 * @param int $the_course
30 */
31 public function __construct( $the_user = 0, $the_course = 0 ) {
32 $this->_user_id = $the_user;
33 $this->_course_id = $the_course;
34 }
35
36 /**
37 * Get courses of an user.
38 *
39 * @param array $args
40 *
41 * @return array
42 * @since 3.3.0
43 * @deprecated 4.2.4
44 */
45 public function get_courses( $args = array() ) {
46 _deprecated_function( __METHOD__, '4.2.4' );
47
48 global $wpdb;
49
50 $no_join_users = isset( $args['no_join_users'] ) && $args['no_join_users'];
51 $args = wp_parse_args(
52 $args,
53 array(
54 'offset' => 0,
55 'limit' => 10,
56 'expired' => false,
57 'status' => '',
58 'user_id' => 0,
59 'paginate' => false,
60 )
61 );
62
63 // Join
64 $join = "
65 INNER JOIN {$wpdb->posts} p ON p.ID = X.item_id
66 ";
67
68 if ( ! $no_join_users ) {
69 $join .= "
70 INNER JOIN {$wpdb->users} u ON u.ID = X.user_id
71 ";
72 }
73
74 $join .= $wpdb->prepare(
75 "LEFT JOIN {$wpdb->learnpress_user_itemmeta} uim ON uim.learnpress_user_item_id = X.user_item_id AND uim.meta_key = %s",
76 'grade'
77 );
78
79 // Where
80 $where = $wpdb->prepare(
81 'WHERE 1
82 AND X.item_type = %s
83 ',
84 LP_COURSE_CPT
85 );
86
87 if ( $args['user_id'] ) {
88
89 if ( ! is_array( $args['user_id'] ) ) {
90 $user__in = preg_split( '!\s*,\s*!', $args['user_id'] );
91 } else {
92 $user__in = $args['user_id'];
93 }
94
95 $where .= 'AND u.ID IN(' . join( ',', $user__in ) . ')';
96 }
97
98 // Limitation
99 $limit = $args['limit'] > 0 ? '
100 LIMIT ' . $args['offset'] . ', ' . $args['limit'] : '';
101
102 if ( $args['status'] ) {
103
104 if ( ! is_array( $args['status'] ) ) {
105 $status__in = preg_split( '!\s*,\s*!', $args['status'] );
106 } else {
107 $status__in = $args['status'];
108 }
109
110 $where .= " AND ( X.status IN('" . join( "','", $status__in ) . "')";
111
112 $status__in_1 = array();
113 $status__in_2 = array();
114
115 if ( in_array( 'failed', $status__in ) ) {
116 $status__in_1[] = 'finished';
117 $status__in_2[] = 'failed';
118 }
119
120 if ( in_array( 'passed', $status__in ) ) {
121 $status__in_1[] = 'finished';
122 $status__in_2[] = 'passed';
123 }
124
125 if ( in_array( 'in-progress', $status__in ) ) {
126 $status__in_1[] = 'enrolled';
127 $status__in_2[] = 'in-progress';
128 }
129
130 if ( in_array( 'finished', $status__in ) ) {
131 $status__in_1[] = 'passed';
132 $status__in_1[] = 'failed';
133 $status__in_2[] = 'passed';
134 $status__in_2[] = 'failed';
135 }
136
137 if ( $status__in_1 || $status__in_2 ) {
138
139 $where .= " OR (
140 X.status IN('" . join( "','", $status__in_1 ) . "')";
141
142 if ( ! in_array( 'in-progress', $status__in ) ) {
143 $where .= "AND ( uim.meta_value IN('" . join( "','", $status__in_2 ) . "')
144 " . ( in_array( 'in-progress', $status__in ) ? ' OR uim.meta_value IS NULL' : '' ) . ')';
145 }
146 $where .= ')';
147 }
148
149 $where .= ' )';
150
151 }
152
153 if ( $args['expired'] ) {
154 $where .= ' AND expiration_time <= UTC_TIMESTAMP()';
155 }
156
157 if ( $args['paginate'] && ! empty( $limit ) ) {
158 $found_rows = 'SQL_CALC_FOUND_ROWS';
159 } else {
160 $found_rows = '';
161 }
162
163 $query = $wpdb->prepare(
164 "
165 SELECT {$found_rows} p.ID course_id, X.*, IF(X.status = %s AND uim.meta_value IS NOT NULL, uim.meta_value, X.status) status
166 FROM(
167 SELECT ui.*
168 FROM {$wpdb->learnpress_user_items} ui
169 LEFT JOIN {$wpdb->learnpress_user_items} uix
170 ON ui.item_id = uix.item_id
171 AND ui.user_id = uix.user_id
172 AND ui.user_item_id < uix.user_item_id
173 WHERE uix.user_item_id IS NULL
174 ) X
175 $join
176 $where
177 $limit
178 ",
179 'finished'
180 );
181
182 $rows = $wpdb->get_results( $query );
183
184 // echo nl2br( $query );
185
186 if ( $args['paginate'] && $args['limit'] ) {
187 $found_courses = sizeof( $rows ) ? $wpdb->get_var( 'SELECT FOUND_ROWS()' ) : 0;
188
189 $return = array(
190 'courses' => $rows,
191 'found_courses' => $found_courses,
192 'max_num_pages' => $found_courses ? ceil( $found_courses / $args['limit'] ) : 0,
193 );
194 } else {
195 $return = $rows;
196 }
197
198 // $query = $wpdb->prepare( "
199 // SELECT X.*
200 // FROM(
201 // SELECT ui.*
202 // FROM {$wpdb->learnpress_user_items} ui
203 // LEFT JOIN {$wpdb->learnpress_user_items} uix
204 // ON ui.item_id = uix.item_id
205 // AND ui.user_id = uix.user_id
206 // AND ui.user_item_id < uix.user_item_id
207 // WHERE uix.user_item_id IS NULL
208 // ) X
209 //
210 // WHERE
211 // AND X.status = %s
212 // AND expiration_time_gmt <= UTC_TIMESTAMP()
213 // LIMIT 0, 10
214 // ", LP_COURSE_CPT, 'enrolled' );
215
216 // echo nl2br( $query );
217 // learn_press_debug( $return );
218
219 return $return;
220 }
221
222 /**
223 * @param LP_User $user
224 */
225 public function create( &$user ) {
226
227 }
228
229 /**
230 * @param LP_User $user
231 */
232 public function update( &$user ) {
233 // TODO: Implement update() method.
234 }
235
236 /**
237 * @param LP_User $user
238 */
239 public function delete( &$user ) {
240 // TODO: Implement delete() method.
241 }
242
243 /**
244 * Load user data
245 *
246 * @param LP_User|LP_Abstract_User $user
247 *
248 * @return mixed;
249 */
250 public function load( &$user ) {
251 $user_id = $user->get_id();
252 $user_object = get_user_by( 'id', $user_id );
253
254 if ( false !== $user_object ) {
255 $user->set_data(
256 array(
257 'email' => $user_object->user_email,
258 'user_login' => $user_object->user_login,
259 'description' => $user_object->description,
260 'first_name' => $user_object->first_name ?? '',
261 'last_name' => $user_object->last_name ?? '',
262 'nickname' => $user_object->nickname ?? '',
263 'display_name' => $user_object->display_name,
264 'date_created' => $user_object->user_registered,
265 'date_modified' => get_user_meta( $user_id, 'last_update', true ),
266 'role' => $user_object->roles[0] ?? '',
267 'roles' => $user_object->roles,
268 'profile_picture' => get_user_meta( $user_id, '_lp_profile_picture', true ),
269 'profile_privacy' => get_user_meta( $user_id, '_lp_profile_privacy', true ),
270 )
271 );
272 }
273
274 return true;
275 }
276
277 /**
278 * Get all orders of an user grouped by id of course.
279 *
280 * A course can have multi orders, each element is an array of order ids
281 * with the key is id of the course. The orders is sorted from highest
282 * to lowest. With the highest value is the latest order user placed (current order).
283 *
284 * Format:
285 * array(
286 * course_id_1 => array( order_id_1, order_id_2, ...),
287 * course_id_2 => array( order_id_3, order_id_4, ...),
288 * ...
289 * )
290 *
291 * @param int $user_id
292 * @param array $args
293 *
294 * @return array|mixed
295 */
296 public function get_orders( $user_id, $args = array() ) {
297 $user = learn_press_get_user( $user_id );
298
299 if ( ! $user_id || ! $user ) {
300 return false;
301 }
302
303 $cache_key = false;
304 if ( $args ) {
305 $args = wp_parse_args(
306 $args,
307 array(
308 'group_by_order' => false,
309 'status' => '',
310 )
311 );
312
313 ksort( $args );
314 $cache_key = md5( serialize( $args ) );
315
316 /**
317 * Get orders from cache by args
318 */
319 $orders = LP_Object_Cache::get( "user-{$user_id}-" . $cache_key, 'lp-user-orders' );
320
321 if ( false !== $orders ) {
322 return $orders;
323 }
324 }
325
326 // Get orders for the user from cache
327 $orders = LP_Object_Cache::get( 'user-' . $user_id, 'lp-user-orders' );
328
329 if ( false === $orders ) {
330 global $wpdb;
331
332 $orders = array();
333 $post_status_in = array_keys( LP_Order::get_order_statuses() );
334 $post_status_in_format = array_fill( 0, sizeof( $post_status_in ), '%s' );
335 $user_id_str = $wpdb->prepare( '%"%d"%', $user_id );
336
337 // Get order by user
338 $sql_orders = $wpdb->prepare(
339 "
340 SELECT p.*
341 FROM {$wpdb->posts} p
342 INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id AND meta_key = %s AND (meta_value = %d OR meta_value like '%s')
343 ",
344 '_user_id',
345 $user_id,
346 $user_id_str
347 );
348
349 /**
350 * Get order checked out by Guest but with the email of the user are getting
351 * Error when checkout with guest then register error Start Quiz - nhamdv.
352 */
353 // $sql_guest_orders = $wpdb->prepare(
354 // "
355 // SELECT p.*
356 // FROM {$wpdb->posts} p
357 // INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id AND meta_key = %s AND meta_value = %s
358 // LEFT JOIN {$wpdb->postmeta} pmu ON p.ID = pmu.post_id AND pmu.meta_key = %s AND pmu.meta_value IS NULL
359 // ",
360 // '_checkout_email',
361 // $user->get_email(),
362 // '_user_id'
363 // );
364
365 /**
366 * The rest
367 */
368 $sql_rest = $wpdb->prepare(
369 '
370 HAVING p.post_type = %s
371 AND p.post_status IN(' . join( ',', $post_status_in_format ) . ')
372 ORDER BY ID DESC
373 ',
374 array_merge(
375 array(
376 LP_ORDER_CPT,
377 ),
378 $post_status_in
379 )
380 );
381
382 $sql = $sql_orders /* . ' UNION ' . $sql_guest_orders */ . $sql_rest;
383
384 $order_posts = $wpdb->get_results( $sql );
385
386 if ( $order_posts ) {
387 $order_ids = array();
388
389 foreach ( $order_posts as $order_post ) {
390 $_post = sanitize_post( $order_post, 'raw' );
391 wp_cache_add( $_post->ID, $_post, 'posts' );
392
393 $order_ids[] = $_post->ID;
394 }
395
396 $order_ids_format = array_fill( 0, sizeof( $order_ids ), '%d' );
397 $query = $wpdb->prepare(
398 "
399 SELECT meta_value as course_id, order_id
400 FROM {$wpdb->learnpress_order_items} oi
401 INNER JOIN {$wpdb->learnpress_order_itemmeta} oim ON oi.order_item_id = oim.learnpress_order_item_id AND oim.meta_key = %s
402 WHERE oi.order_id IN (" . join( ',', $order_ids_format ) . ')
403 ORDER BY FIELD(order_id, ' . join( ',', $order_ids_format ) . ')
404 ',
405 array_merge( array( '_course_id' ), $order_ids, $order_ids )
406 );
407
408 $results = $wpdb->get_results( $query );
409
410 if ( $results ) {
411 foreach ( $results as $result ) {
412 if ( empty( $orders[ $result->course_id ] ) ) {
413 $orders[ $result->course_id ] = array();
414 }
415 $orders[ $result->course_id ][] = $result->order_id;
416 }
417 }
418 }
419
420 LP_Object_Cache::set( 'user-' . $user_id, $orders, 'lp-user-orders' );
421 }
422
423 if ( $orders ) {
424 if ( array_key_exists( 'status', $args ) && $args['status'] ) {
425 LP_Helper::sanitize_order_status( $args['status'] );
426
427 $statuses = (array) $args['status'];
428 foreach ( $orders as $course_id => $order_ids ) {
429 $orders[ $course_id ] = array();
430 foreach ( $order_ids as $order_id ) {
431 if ( in_array( get_post_status( $order_id ), $statuses ) ) {
432 $orders[ $course_id ][] = $order_id;
433 }
434 }
435 }
436 }
437
438 if ( array_key_exists( 'group_by_order', $args ) && $args['group_by_order'] ) {
439 $this->_group_orders( $orders );
440 }
441 }
442
443 if ( $cache_key ) {
444 LP_Object_Cache::set( "user-{$user_id}-" . $cache_key, $orders, 'lp-user-orders' );
445 }
446
447 return $orders;
448 }
449
450 protected function _group_orders( &$orders ) {
451 $groups = array();
452 foreach ( $orders as $course_id => $order_ids ) {
453 foreach ( $order_ids as $order_id ) {
454 if ( empty( $groups[ $order_id ] ) ) {
455 $groups[ $order_id ] = array();
456 }
457 $groups[ $order_id ][] = $course_id;
458 }
459 }
460 $orders = $groups;
461 krsort( $orders );
462
463 return $orders;
464 }
465
466 /**
467 * Read meta data of an user item.
468 *
469 * @param $item
470 *
471 * @deprecated 4.2.4
472 */
473 protected function _read_item_meta( &$item ) {
474 _deprecated_function( __METHOD__, '4.2.4' );
475 global $wpdb;
476 $query = $wpdb->prepare(
477 "
478 SELECT *
479 FROM {$wpdb->learnpress_user_itemmeta}
480 WHERE learnpress_user_item_id = %d
481 ",
482 $item['user_item_id']
483 );
484
485 update_meta_cache( 'learnpress_user_item', $item['user_item_id'] );
486
487 if ( $meta = $wpdb->get_results( $query, ARRAY_A ) ) {
488 $item['meta'] = array();
489 foreach ( $meta as $k => $v ) {
490 $v['meta_value'] = LP_Helper::maybe_unserialize( $v['meta_value'] );
491 $item['meta'][ $v['meta_id'] ] = $v;
492 }
493 }
494 }
495
496 /**
497 * @param int $user_item_id
498 * @param string $type
499 *
500 * @return array
501 */
502 public function get_user_item_by_id( $user_item_id, $type = '' ) {
503 global $wpdb;
504
505 $query = $wpdb->prepare(
506 "
507 SELECT *
508 FROM {$wpdb->learnpress_user_items}
509 WHERE user_item_id = %d
510 " . ( $type ? $wpdb->prepare( 'AND item_type = %s', $type ) : '' ) . '
511 ',
512 $user_item_id
513 );
514 $item = $wpdb->get_row( $query, ARRAY_A );
515
516 return $item;
517 }
518
519 /**
520 * Update status of an user item by id.
521 *
522 * @param int $user_item_id
523 * @param string $new_status
524 *
525 * @return mixed
526 */
527 public function update_user_item_status( $user_item_id, $new_status ) {
528 global $wpdb;
529 $item = $this->get_user_item_by_id( $user_item_id );
530 if ( ! $item ) {
531 return false;
532 }
533
534 // No need to update if it is not change
535 if ( $item['status'] === $new_status ) {
536 return false;
537 }
538
539 $updated = $wpdb->update(
540 $wpdb->learnpress_user_items,
541 array( 'status' => $new_status ),
542 array( 'user_item_id' => $user_item_id ),
543 array( '%s' ),
544 array( '%d' )
545 );
546 // if ( $updated ) {
547 // $this->update_user_item_meta( $user_item_id, '_last_status', $item['status'] );
548 // $this->update_user_item_meta( $user_item_id, '_current_status', $new_status );
549 // }
550
551 return $updated;
552 }
553
554 /**
555 * Delete user item by fields.
556 *
557 * @param string $args
558 *
559 * @return bool
560 */
561 public function delete_user_item( $args = '' ) {
562 global $wpdb;
563 $args = wp_parse_args(
564 $args,
565 array(
566 'user_id' => 0,
567 'item_id' => 0,
568 'ref_id' => 0,
569 'parent_id' => 0,
570 )
571 );
572 $where = array();
573 foreach ( $args as $k => $v ) {
574 if ( $v ) {
575 $where[ $k ] = $v;
576 }
577 }
578
579 if ( ! $where ) {
580 return false;
581 }
582 $query_where = array();
583 foreach ( $where as $k => $v ) {
584 $query_where[] = "{$k} = %d";
585 }
586
587 $query = $wpdb->prepare(
588 "SELECT user_item_id FROM {$wpdb->learnpress_user_items} WHERE " . join(
589 ' AND ',
590 $query_where
591 ),
592 array_values( $where )
593 );
594 $user_item_ids = $wpdb->get_col( $query );
595
596 $wpdb->delete(
597 $wpdb->learnpress_user_items,
598 $where,
599 array_fill( 0, sizeof( $where ), '%d' )
600 );
601
602 foreach ( $user_item_ids as $user_item_id ) {
603 $wpdb->query(
604 $wpdb->prepare(
605 "DELETE FROM {$wpdb->learnpress_user_itemmeta} WHERE learnpress_user_item_id = %d",
606 $user_item_id
607 )
608 );
609 do_action( 'learn-press/deleted-user-item', $user_item_id );
610 }
611
612 return true;
613 }
614
615 /**
616 * Get courses user has purchased via orders are completed
617 * but it is not already added to user-items table.
618 *
619 * @param int $user_id
620 *
621 * @return array|bool|mixed
622 * @deprecated 4.2.4
623 */
624 public function query_courses_by_order( $user_id ) {
625 _deprecated_function( __METHOD__, '4.2.4' );
626
627 return false;
628 global $wpdb;
629
630 $query = $wpdb->prepare(
631 "
632 SELECT item_id
633 FROM {$wpdb->learnpress_user_items}
634 WHERE user_id = %d
635 AND item_type = %s
636 ",
637 $user_id,
638 LP_COURSE_CPT
639 );
640 $user_item_ids = $wpdb->get_col( $query );
641
642 $orders = $this->get_orders(
643 $user_id,
644 array(
645 'status' => 'completed',
646 'group_by_order' => true,
647 )
648 );
649
650 if ( ! $orders ) {
651 return false;
652 }
653
654 $course_ids = array_shift( $orders );
655
656 foreach ( $orders as $ids ) {
657 if ( ! $ids ) {
658 continue;
659 }
660 $course_ids = array_merge( $course_ids, $ids );
661 }
662
663 if ( $user_item_ids ) {
664 $course_ids = array_diff( $course_ids, $user_item_ids );
665 }
666
667 return $course_ids;
668 }
669
670 /**
671 * @deprecated 4.2.4
672 */
673 public function read_course_info( $course ) {
674 _deprecated_function( __METHOD__, '4.2.4' );
675
676 return [];
677 $data = $course;
678 global $wpdb;
679 $query = $wpdb->prepare(
680 "
681 SELECT *
682 FROM {$wpdb->learnpress_user_itemmeta}
683 WHERE learnpress_user_item_id = %d
684 ",
685 $course['user_item_id']
686 );
687
688 $itemmeta = $wpdb->get_results( $query, ARRAY_A );
689
690 if ( $itemmeta ) {
691 foreach ( $itemmeta as $item ) {
692 $data[ $item['meta_key'] ] = $item['meta_value'];
693 }
694 }
695
696 return $data;
697 }
698
699 public function update_item( $item ) {
700 global $wpdb;
701 if ( empty( $item['user_item_id'] ) ) {
702 $wpdb->insert(
703 $wpdb->learnpress_user_items,
704 $item
705 );
706 }
707 }
708
709 /**
710 * @deprecated 4.2.4
711 */
712 public function get_current_user_order( $user_id, $course_id ) {
713 _deprecated_function( __METHOD__, '4.2.4' );
714
715 return 0;
716 global $wpdb;
717 $sql = $wpdb->prepare(
718 "
719 SELECT MAX(ID) AS order_id
720 FROM {$wpdb->posts} p
721 INNER JOIN {$wpdb->postmeta} pm_u ON pm_u.post_id = p.ID AND pm_u.meta_key = %s AND pm_u.meta_value = %d
722 INNER JOIN {$wpdb->learnpress_order_items} oi ON oi.order_id = p.id
723 INNER JOIN {$wpdb->learnpress_order_itemmeta} oim ON oim.meta_key = %s and oim.meta_value = %d
724 ",
725 '_user_id',
726 $user_id,
727 '_course_id',
728 $course_id
729 );
730 $order_id = $wpdb->get_var( $sql );
731
732 return $order_id;
733 }
734
735 public function duplicate( &$user, $args = array() ) {
736 // TODO: Implement duplicate() method.
737 }
738 }
739