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

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

731 lines 16.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 LP_User_Item_CURD
5 *
6 * Class to manipulating user item with database.
7 */
8 class LP_User_Item_CURD implements LP_Interface_CURD {
9 /**
10 * Errors codes and message.
11 *
12 * @var array|bool
13 */
14 protected $_error_messages = false;
15
16 /**
17 * LP_User_Item_CURD constructor.
18 */
19 public function __construct() {
20 $this->_error_messages = array(
21 'QUIZ_NOT_EXISTS' => __( 'The quiz does not exist.', 'learnpress' ),
22 );
23 }
24
25 /**
26 * @param LP_Quiz $quiz
27 *
28 * @return LP_Quiz|mixed
29 * @throws Exception
30 */
31 public function load( &$quiz ) {
32 $the_id = $quiz->get_id();
33
34 if ( ! $the_id || LP_QUIZ_CPT !== learn_press_get_post_type( $the_id ) ) {
35 throw new Exception( __( 'Invalid quiz.', 'learnpress' ) );
36 }
37
38 $quiz->set_data_via_methods(
39 array(
40 'retake_count' => get_post_meta( $quiz->get_id(), '_lp_retake_count', true ),
41 'show_result' => get_post_meta( $quiz->get_id(), '_lp_show_result', true ),
42 'passing_grade_type' => get_post_meta( $quiz->get_id(), '_lp_passing_grade_type', true ),
43 'passing_grade' => get_post_meta( $quiz->get_id(), '_lp_passing_grade', true ),
44 'instant_check' => get_post_meta( $quiz->get_id(), '_lp_instant_check', true ),
45 'review_questions' => get_post_meta( $quiz->get_id(), '_lp_review', true ),
46 )
47 );
48
49 $this->_load_questions( $quiz );
50 // $this->_update_meta_cache( $quiz );
51
52 return $quiz;
53 }
54
55 public function create( &$quiz ) {
56 // TODO: Implement create() method.
57 }
58
59 public function update( &$quiz ) {
60 // TODO: Implement update() method.
61 }
62
63 public function delete( &$quiz ) {
64 // TODO: Implement delete() method.
65 }
66
67 public function duplicate( &$quiz, $args = array() ) {
68 // TODO: Implement duplicate() method.
69 }
70
71 /**
72 * @param LP_Quiz $quiz
73 */
74 protected function _load_questions( &$quiz ) {
75 $id = $quiz->get_id();
76 $questions = LP_Object_Cache::get( 'questions-' . $id, 'learn-press/quizzes' );
77 if ( false === $questions ) {
78 global $wpdb;
79 $questions = array();
80 $query = $wpdb->prepare(
81 "
82 SELECT p.*, qq.question_order AS `order`
83 FROM {$wpdb->posts} p
84 INNER JOIN {$wpdb->prefix}learnpress_quiz_questions qq ON p.ID = qq.question_id
85 WHERE qq.quiz_id = %d
86 AND p.post_status = %s
87 ORDER BY question_order ASC
88 ",
89 $id,
90 'publish'
91 );
92
93 $results = $wpdb->get_results( $query, OBJECT_K );
94
95 if ( $results ) {
96 foreach ( $results as $k => $v ) {
97 wp_cache_set( $v->ID, $v, 'posts' );
98 $questions[ $v->ID ] = $v->ID;
99 }
100 }
101 LP_Object_Cache::set( 'questions-' . $id, $questions, 'learn-press/quizzes' );
102
103 $this->_load_question_answers( $quiz );
104 }
105 unset( $questions );
106 }
107
108 /**
109 * @param LP_Quiz $quiz
110 *
111 * @deprecated 4.1.6.4
112 */
113 protected function _update_meta_cache( &$quiz ) {
114 _deprecated_function( __FUNCTION__, '4.1.6.4' );
115 $meta_ids = LP_Object_Cache::get( 'questions-' . $quiz->get_id(), 'learn-press/quizzes' );
116
117 if ( false === $meta_ids ) {
118 $meta_ids = array( $quiz->get_id() );
119 } else {
120 $meta_ids[] = $quiz->get_id();
121 }
122
123 // LP_Helper_CURD::update_meta_cache( $meta_ids );
124 }
125
126 /**
127 * Load answer quiz's questions.
128 */
129 protected function _load_question_answers( &$quiz ) {
130 global $wpdb;
131
132 $questions = $this->get_questions( $quiz );
133
134 if ( ! $questions ) {
135 return;
136 }
137
138 $format = array_fill( 0, sizeof( $questions ), '%d' );
139 $query = $wpdb->prepare(
140 "
141 SELECT *
142 FROM {$wpdb->prefix}learnpress_question_answers
143 WHERE question_id IN(" . join( ',', $format ) . ')
144 ORDER BY question_id, `order` ASC
145 ',
146 $questions
147 );
148
149 $results = $wpdb->get_results( $query, OBJECT_K );
150
151 if ( $results ) {
152 $answer_options = array();
153 $meta_ids = array();
154 $group = 0;
155 foreach ( $results as $k => $v ) {
156 if ( empty( $answer_options[ $v->question_id ] ) ) {
157 $answer_options[ $v->question_id ] = array();
158 }
159 $v = (array) $v;
160
161 $answer_options[ $v['question_id'] ][] = $v;
162 }
163
164 foreach ( $answer_options as $question_id => $options ) {
165 LP_Object_Cache::set( 'answer-options-' . $question_id, $options, 'learn-press/questions' );
166 }
167
168 foreach ( $meta_ids as $meta_id ) {
169 // $this->_load_question_answer_meta( $meta_id );
170 }
171
172 $fetched = array_keys( $answer_options );
173 $un_fetched = array_diff( $questions, $fetched );
174 // $this->_load_question_answer_meta( $answer_options );
175 } else {
176 $un_fetched = $questions;
177 }
178
179 if ( $un_fetched ) {
180 foreach ( $un_fetched as $question_id ) {
181 LP_Object_Cache::set( 'answer-options-' . $question_id, array(), 'learn-press/questions' );
182 }
183 }
184
185 }
186
187 protected function _load_question_answer_meta( $meta_ids ) {
188 global $wpdb;
189
190 $format = array_fill( 0, sizeof( $meta_ids ), '%d' );
191 $query = $wpdb->prepare(
192 "
193 SELECT *
194 FROM {$wpdb->learnpress_question_answermeta}
195 WHERE learnpress_question_answer_id IN(" . join( ',', $format ) . ')
196 ',
197 $meta_ids
198 );
199
200 $metas = $wpdb->get_results( $query );
201
202 if ( $metas ) {
203 foreach ( $metas as $meta ) {
204 $key = $meta->meta_key;
205 $option_key = $meta->learnpress_question_answer_id;
206
207 if ( ! empty( $answer_options[ $option_key ] ) ) {
208 if ( $key == 'checked' ) {
209 $key = 'is_true';
210 }
211
212 $answer_options[ $option_key ][ $key ] = $meta->meta_value;
213 }
214 }
215 }
216 }
217
218 /**
219 * Sort questions by order.
220 * Check in an array of questions if there is a key 'order'.
221 *
222 * @param $questions
223 *
224 * @return mixed
225 */
226 protected function _maybe_sort_questions( &$questions ) {
227 if ( ! $questions ) {
228 return $questions;
229 }
230
231 $first = reset( $questions );
232
233 if ( empty( $first['order'] ) ) {
234 return $questions;
235 }
236
237 uasort( $questions, array( $this, '_callback_sort_questions' ) );
238
239 return $questions;
240 }
241
242 public function _callback_sort_questions( $a, $b ) {
243 return $a['order'] > $b['order'];
244 }
245
246 /**
247 * Reorder question by indexed number.
248 *
249 * @param LP_Quiz|WP_Post|int $the_quiz
250 * @param mixed $questions
251 *
252 * @return mixed
253 */
254 public function reorder_questions( $the_quiz, $questions = false ) {
255 global $wpdb;
256
257 $the_quiz = learn_press_get_quiz( $the_quiz );
258
259 if ( ! $the_quiz ) {
260 return false;
261 }
262
263 if ( false == $questions ) {
264 $query = $wpdb->prepare(
265 "
266 SELECT quiz_question_id as id
267 FROM {$wpdb->prefix}learnpress_quiz_questions
268 WHERE quiz_id = %d
269 ORDER BY question_order ASC
270 ",
271 $the_quiz->get_id()
272 );
273
274 $rows = $wpdb->get_results( $query );
275
276 if ( $rows ) {
277 $update = array();
278 $ids = wp_list_pluck( $rows, 'id' );
279 $format = array_fill( 0, sizeof( $ids ), '%d' );
280
281 foreach ( $rows as $order => $row ) {
282 $update[] = $wpdb->prepare( 'WHEN quiz_question_id = %d THEN %d', $row->id, $order + 1 );
283 }
284
285 $query = $wpdb->prepare(
286 "
287 UPDATE {$wpdb->prefix}learnpress_quiz_questions
288 SET question_order = CASE
289 " . join( "\n", $update ) . '
290 ELSE question_order END
291 WHERE quiz_question_id IN(' . join( ',', $format ) . ')
292 ',
293 $ids
294 );
295
296 return $wpdb->query( $query );
297 }
298 } else {
299 $query = "
300 UPDATE {$wpdb->learnpress_quiz_questions}
301 SET question_order = CASE
302 ";
303
304 for ( $order = 0, $n = sizeof( $questions ); $order < $n; $order ++ ) {
305 $query .= $wpdb->prepare( 'WHEN question_id = %d THEN %d', $questions[ $order ], $order + 1 ) . "\n";
306 }
307
308 $query .= sprintf( 'ELSE question_order END WHERE quiz_id = %d', $the_quiz->get_id() );
309
310 return $wpdb->query( $query );
311 }
312
313 return false;
314 }
315
316 /**
317 * Get all questions in a quiz
318 *
319 * @param LP_Quiz $the_quiz
320 *
321 * @return array|mixed
322 */
323 public function get_questions( $the_quiz ) {
324 $the_quiz = learn_press_get_quiz( $the_quiz );
325
326 if ( ! $the_quiz ) {
327 return $this->get_error( 'QUESTION_NOT_EXISTS' );
328 }
329
330 return LP_Object_Cache::get( 'questions-' . $the_quiz->get_id(), 'learn-press/quizzes' );
331 }
332
333 /**
334 * Add existing question into quiz.
335 *
336 * @param LP_Quiz|int $the_quiz
337 * @param $question_id
338 * @param array $args
339 *
340 * @return mixed false on failed
341 */
342 public function add_question( $the_quiz, $question_id, $args = array() ) {
343 $the_quiz = learn_press_get_quiz( $the_quiz );
344
345 if ( ! $the_quiz ) {
346 return $this->get_error( 'QUESTION_NOT_EXISTS' );
347 }
348
349 $question = learn_press_get_question( $question_id );
350
351 if ( ! $question ) {
352 return false;
353 }
354
355 if ( $this->is_exists_question( $question_id ) ) {
356 return false;
357 }
358
359 global $wpdb;
360
361 $id = $the_quiz->get_id();
362 $args = wp_parse_args( $args, array( 'order' => - 1 ) );
363 $this->reorder_questions( $the_quiz );
364
365 if ( $args['order'] >= 0 ) {
366 $query = $wpdb->prepare(
367 "
368 UPDATE {$wpdb->prefix}learnpress_quiz_questions
369 SET question_order = question_order + 1
370 WHERE quiz_id = %d AND question_order >= %d
371 ",
372 $id,
373 $args['order']
374 );
375 $wpdb->get_results( $query );
376 } else {
377 $query = $wpdb->prepare(
378 "
379 SELECT max(question_order) + 1 as ordering
380 FROM {$wpdb->prefix}learnpress_quiz_questions
381 WHERE quiz_id = %d
382 ",
383 $id
384 );
385
386 $order = $wpdb->get_var( $query );
387
388 if ( ! $order ) {
389 $order = 1;
390 }
391
392 $args['order'] = $order;
393 }
394 $inserted = $wpdb->insert(
395 $wpdb->prefix . 'learnpress_quiz_questions',
396 array(
397 'quiz_id' => $id,
398 'question_id' => $question_id,
399 'question_order' => $args['order'],
400 ),
401 array( '%d', '%d', '%d' )
402 );
403
404 return $inserted ? $wpdb->insert_id : $inserted;
405 }
406
407 /**
408 * Check if a question (or batch of questions) is already added to quiz.
409 *
410 * @param int $the_id
411 * @param int|array $ids
412 *
413 * @return array|bool|null|object
414 */
415 public function is_exists_question( $the_id, $ids = array() ) {
416 global $wpdb;
417
418 settype( $ids, 'array' );
419 $format = array_fill( 0, sizeof( $ids ), '%d' );
420 $args = $ids;
421 $args[] = $the_id;
422 $query = $wpdb->prepare(
423 "
424 SELECT quiz_question_id
425 FROM {$wpdb->learnpress_quiz_questions}
426 WHERE question_id IN( " . join( ',', $format ) . ' )
427 AND quiz_id = %d
428 ',
429 $args
430 );
431
432 $results = $wpdb->get_results( $query );
433
434 if ( $results ) {
435 return $results;
436 }
437
438 return false;
439 }
440
441 public function add_meta( &$object, $meta ) {
442 // TODO: Implement add_meta() method.
443 }
444
445 public function delete_meta( &$object, $meta ) {
446 // TODO: Implement delete_meta() method.
447 }
448
449 public function read_meta( &$object ) {
450 // TODO: Implement read_meta() method.
451 }
452
453 /**
454 * @param $object
455 * @param $meta
456 *
457 * @return mixed
458 */
459 public function update_meta( &$object, $meta ) {
460 return learn_press_update_user_item_meta( $object->get_user_item_id(), $meta->meta_key, $meta->meta_value );
461 }
462
463 /**
464 * Get single user item by values of fields.
465 *
466 * @param string|array $field
467 * @param string $value
468 *
469 * @return mixed
470 * @since 3.1.0
471 * @deprecated 4.2.5
472 */
473 public function get_item_by( $field, $value = '' ) {
474 _deprecated_function( __METHOD__, '4.2.5' );
475 if ( $rows = $this->get_items_by( $field, $value ) ) {
476 return $rows[0];
477 }
478
479 return false;
480 }
481
482 /**
483 * Get multiple rows of user item by values of fields.
484 *
485 * @param string|array $field
486 * @param string $value
487 *
488 * @return array
489 * @since 3.1.0
490 * @deprecated 4.2.5
491 */
492 public function get_items_by( $field, $value = '' ) {
493 _deprecated_function( __METHOD__, '4.2.5' );
494 global $wpdb;
495
496 $where = '';
497 $order = 'ORDER BY user_item_id DESC';
498
499 if ( is_array( $field ) ) {
500 foreach ( $field as $k => $v ) {
501 if ( is_string( $v ) ) {
502 $where .= $wpdb->prepare( " AND {$k} = %s", $v );
503 } else {
504 $where .= $wpdb->prepare( " AND {$k} = %d", $v );
505 }
506 }
507 } else {
508 if ( is_string( $value ) ) {
509 $where .= $wpdb->prepare( " AND {$field} = %s", $value );
510 } else {
511 $where .= $wpdb->prepare( " AND {$field} = %s", $value );
512 }
513 }
514
515 $query = "SELECT * FROM {$wpdb->learnpress_user_items} WHERE 1 {$where} {$order}";
516
517 return $wpdb->get_results( $query );
518 }
519
520 /**
521 * Get WP_Object.
522 *
523 * @param $code
524 *
525 * @return bool|WP_Error
526 */
527 protected function get_error( $code ) {
528 if ( isset( $this->_error_messages[ $code ] ) ) {
529 return new WP_Error( $code, $this->_error_messages[ $code ] );
530 }
531
532 return false;
533 }
534
535 /**
536 * Parse attribute 'preview' for all items in a course
537 *
538 * @param int $course_id
539 * @param int $user_id
540 *
541 * @return array
542 * @since 3.2.0
543 * @editor tungnx
544 * @modify 4.1.3 - comment - not use
545 */
546 /*public function parse_items_preview( $course_id, $user_id = 0 ) {
547 $items = array();
548
549 $course = learn_press_get_course( $course_id );
550
551 if ( ! $course ) {
552 return $items;
553 }
554
555 if ( ! $user_id ) {
556 $user_id = get_current_user_id();
557 }
558
559 $user = learn_press_get_user( $user_id, false );
560 $current_item = LP_Global::course_item();
561 $get_item_ids = $course->get_item_ids();
562 $enrolled = $user ? $user->has_enrolled_course( $course_id ) : false;
563
564 if ( $get_item_ids ) {
565 foreach ( $get_item_ids as $item_id ) {
566 $is_preview = get_post_meta( $item_id, '_lp_preview', true );
567
568 if ( $enrolled ) {
569 $is_preview = 'no';
570 }
571
572 $cached = LP_Object_Cache::get(
573 'item-' . $user_id . '-' . $course_id . '-' . $item_id,
574 'learn-press/preview-items'
575 );
576
577 if ( false === $cached ) {
578 LP_Object_Cache::set(
579 'item-' . $user_id . '-' . $course->get_id() . '-' . $item_id,
580 $is_preview,
581 'learn-press/preview-items'
582 );
583 }
584
585 $items[ $item_id ] = $is_preview;
586 }
587 }
588
589 return $items;
590 }*/
591
592 /**
593 * Parse classes for all items in a course.
594 *
595 * @param int $course_id .
596 * @param int $user_id .
597 * @param array|string $more .
598 *
599 * @return array
600 * @throws Exception
601 * @since 3.2.0
602 * @editor tungnx
603 */
604 public function parse_items_classes( int $course_id = 0, int $user_id = 0, $more = array() ): array {
605 $items = array();
606
607 $course = learn_press_get_course( $course_id );
608
609 if ( ! $course ) {
610 return $items;
611 }
612
613 if ( ! $user_id ) {
614 $user_id = get_current_user_id();
615 }
616
617 $get_item_ids = $course->get_item_ids();
618
619 if ( empty( $get_item_ids ) ) {
620 return $items;
621 }
622
623 $user = learn_press_get_user( $user_id );
624 if ( ! $user ) {
625 return $items;
626 }
627
628 $current_item = LP_Global::course_item();
629 $enrolled = $user->has_enrolled_or_finished( $course_id );
630 $is_free = $course->is_free();
631 $no_required_enroll = $course->is_no_required_enroll();
632 $can_view_content_course = $user->can_view_content_course( $course_id );
633
634 foreach ( $get_item_ids as $item_id ) {
635 $item = $course->get_item( $item_id );
636
637 if ( ! $item instanceof LP_Course_Item ) {
638 continue;
639 }
640
641 $can_view_item = $user->can_view_item( $item_id, $can_view_content_course );
642
643 $defaults = array_merge(
644 array(
645 'course-item',
646 'course-item-' . $item->get_item_type(),
647 'course-item-' . $item_id,
648 ),
649 (array) $more
650 );
651
652 $post_format = $item->get_format();
653 if ( ( 'standard' !== $post_format ) && $post_format ) {
654 $defaults[] = 'course-item-type-' . $post_format;
655 }
656
657 if ( $current_item && $current_item->get_id() == $item->get_id() ) {
658 $defaults[] = 'current';
659 }
660
661 // Edit by tungnx, rewrite class to show icon.
662 if ( $no_required_enroll ) {
663 $defaults[] = 'item-free';
664 } elseif ( ! $enrolled ) {
665 $defaults['item-locked'] = 'item-locked';
666
667 if ( $item->is_preview() ) {
668 $defaults['item-preview'] = 'item-preview';
669 $defaults['has-status'] = 'has-status';
670 unset( $defaults['item-locked'] );
671 }
672 } elseif ( ! $can_view_item->flag ) {
673 $defaults[] = 'item-locked';
674 } else {
675 $item_status = $user->get_item_status( $item_id, $course_id );
676 $item_grade = $user->get_item_grade( $item_id, $course_id );
677
678 if ( $item_status ) {
679 $defaults[] = 'has-status';
680 $defaults[] = 'status-' . $item_status;
681 }
682
683 switch ( $item_status ) {
684 case 'started':
685 break;
686 case 'completed':
687 $defaults[] = $item_grade;
688 break;
689 default:
690 if ( $item->is_preview() ) {
691 $defaults['item-preview'] = 'item-preview';
692 $defaults['has-status'] = 'has-status';
693 }
694
695 $item_class = apply_filters(
696 'learn-press/course-item-status-class',
697 $item_status,
698 $item_grade,
699 $item->get_item_type(),
700 $item_id,
701 $course_id
702 );
703
704 if ( $item_class ) {
705 $defaults[] = $item_class;
706 }
707 }
708 }
709 // End.
710
711 $classes = apply_filters(
712 'learn-press/course-item-class',
713 $defaults,
714 $item->get_item_type(),
715 $item_id,
716 $course_id
717 );
718
719 // Filter unwanted values.
720 $classes = is_array( $classes ) ? $classes : explode( ' ', $classes );
721 $classes = array_filter( $classes );
722 $classes = array_unique( $classes );
723
724 LP_Object_Cache::set( 'item-' . $user_id . '-' . $item_id, $classes, 'learn-press/post-classes' );
725 $items[ $item_id ] = $classes;
726 }
727
728 return $items;
729 }
730 }
731