PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.2
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.2
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-item-curd.php

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

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