PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.10
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.10
4.4.10 4.4.9.1 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 All 142 releases
← All changes | inc/curds/class-lp-quiz-curd.php +744 -749 4.3.9 → 4.4.10 View file →
@@ -1,749 +1,744 @@
1 -<?php
2 -/**
3 - * Class LP_Quiz_CURD.
4 - *
5 - * @author ThimPress
6 - * @package LearnPress/Classes/CURD
7 - * @since 3.0.0
8 - */
9 -
10 -/**
11 - * Prevent loading this file directly
12 - */
13 -defined( 'ABSPATH' ) || exit();
14 -
15 -if ( ! function_exists( 'LP_Quiz_CURD' ) ) {
16 -
17 - /**
18 - * Class LP_Quiz_CURD
19 - *
20 - * Class to manipulating quiz with database.
21 - */
22 - class LP_Quiz_CURD extends LP_Object_Data_CURD implements LP_Interface_CURD {
23 -
24 - /**
25 - * LP_Quiz_CURD constructor.
26 - */
27 - public function __construct() {
28 - $this->_error_messages = array(
29 - 'QUIZ_NOT_EXISTS' => __( 'The quiz does not exist.', 'learnpress' ),
30 - );
31 - }
32 -
33 - /**
34 - * @param LP_Quiz $quiz
35 - *
36 - * @return LP_Quiz|mixed
37 - * @throws Exception
38 - */
39 - public function load( &$quiz ) {
40 - $id = $quiz->get_id();
41 - if ( ! $id || learn_press_get_post_type( $id ) !== LP_QUIZ_CPT ) {
42 -
43 - throw new Exception( sprintf( __( 'Invalid quiz with ID "%d".', 'learnpress' ), $id ) );
44 - }
45 -
46 - // LP_Helper_CURD::update_meta_cache( $quiz->get_id() );
47 -
48 - $quiz->set_data_via_methods(
49 - array(
50 - // 'show_result' => get_post_meta( $quiz->get_id(), '_lp_show_result', true ),
51 - 'passing_grade_type' => get_post_meta( $quiz->get_id(), '_lp_passing_grade_type', true ),
52 - 'passing_grade' => get_post_meta( $quiz->get_id(), '_lp_passing_grade', true ),
53 - // 'show_check_answer' => get_post_meta( $quiz->get_id(), '_lp_show_check_answer', true ),
54 - // 'count_check_answer' => get_post_meta( $quiz->get_id(), '_lp_check_answer_count', true ),
55 - // 'show_hint' => get_post_meta( $quiz->get_id(), '_lp_show_hint', true ),
56 - // 'archive_history' => get_post_meta( $quiz->get_id(), '_lp_archive_history', true ),
57 - // 'count_hint' => get_post_meta( $quiz->get_id(), '_lp_hint_count', true ),
58 - 'pagination' => get_post_meta( $quiz->get_id(), '_lp_pagination', true ),
59 - 'review_questions' => get_post_meta( $quiz->get_id(), '_lp_review', true ),
60 - 'show_correct_review' => get_post_meta( $quiz->get_id(), '_lp_show_correct_review', true ),
61 - 'preview' => get_post_meta( $quiz->get_id(), '_lp_preview', true ),
62 - // 'minus_points' => get_post_meta( $quiz->get_id(), '_lp_minus_points', true ),
63 - 'minus_skip_questions' => get_post_meta( $quiz->get_id(), '_lp_minus_skip_questions', true ),
64 -
65 - 'instant_check' => get_post_meta( $quiz->get_id(), '_lp_instant_check', true ),
66 - 'negative_marking' => get_post_meta( $quiz->get_id(), '_lp_negative_marking', true ),
67 - 'retake_count' => get_post_meta( $quiz->get_id(), '_lp_retake_count', true ),
68 - )
69 - );
70 -
71 - return $quiz;
72 - }
73 -
74 - /**
75 - * Create quiz, with default meta.
76 - *
77 - * @param $args
78 - *
79 - * @return int|WP_Error
80 - */
81 - public function create( &$args ) {
82 -
83 - $args = wp_parse_args(
84 - $args,
85 - array(
86 - 'id' => '',
87 - 'status' => 'publish',
88 - 'title' => __( 'New Quiz', 'learnpress' ),
89 - 'content' => '',
90 - 'author' => learn_press_get_current_user_id(),
91 - )
92 - );
93 -
94 - $quiz_id = wp_insert_post(
95 - array(
96 - 'ID' => $args['id'],
97 - 'post_type' => LP_QUIZ_CPT,
98 - 'post_status' => $args['status'],
99 - 'post_title' => $args['title'],
100 - 'post_content' => $args['content'],
101 - 'post_author' => $args['author'],
102 - )
103 - );
104 -
105 - if ( $quiz_id ) {
106 - // add default meta for new lesson
107 - $default_meta = LP_Quiz::get_default_meta();
108 -
109 - if ( is_array( $default_meta ) ) {
110 - foreach ( $default_meta as $key => $value ) {
111 - update_post_meta( $quiz_id, '_lp_' . $key, $value );
112 - }
113 - }
114 - }
115 -
116 - return $quiz_id;
117 - }
118 -
119 - public function update( &$quiz ) {
120 - // TODO: Implement update() method.
121 - }
122 -
123 - /**
124 - * Delete quiz.
125 - *
126 - * @since 3.0.0
127 - *
128 - * @param object $quiz_id
129 - */
130 - public function delete( &$quiz_id ) {
131 - // course curd
132 - $curd = new LP_Course_CURD();
133 -
134 - // allow hook
135 - do_action( 'learn-press/before-delete-quiz', $quiz_id );
136 -
137 - // remove quiz from course items
138 - $curd->remove_item( $quiz_id );
139 - // remove questions from quiz
140 - $this->remove_questions( $quiz_id, '', true );
141 - }
142 -
143 - /**
144 - * Duplicate quiz.
145 - *
146 - * @since 3.0.0
147 - *
148 - * @param $quiz_id_origin
149 - * @param array $args
150 - *
151 - * @return mixed|WP_Error
152 - */
153 - public function duplicate( &$quiz_id_origin, $args = array() ) {
154 - $quiz_id_new = 0;
155 -
156 - try {
157 - if ( ! $quiz_id_origin ) {
158 - return new WP_Error( 'lp/clone/quiz/id_null', 'Op! Quiz ID not found' );
159 - }
160 -
161 - if ( learn_press_get_post_type( $quiz_id_origin ) != LP_QUIZ_CPT ) {
162 - return new WP_Error( 'lp/clone/quiz/type_invalid', 'Op! The quiz does not exist' );
163 - }
164 -
165 - // Ensure that user can create quiz
166 - if ( ! current_user_can( 'edit_posts' ) ) {
167 - return new WP_Error( 'lp/clone/quiz/permission', 'Sorry! You have not permission to duplicate this quiz' );
168 - }
169 -
170 - // Duplicate quiz
171 - $quiz_id_new = learn_press_duplicate_post( $quiz_id_origin, $args, true );
172 -
173 - if ( ! $quiz_id_new || is_wp_error( $quiz_id_new ) ) {
174 - return new WP_Error( 'lp/clone/quiz/clone_error', 'Sorry! Failed to duplicate quiz!' );
175 - } else {
176 - // duplicate questions.
177 - $this->duplicate_questions( $quiz_id_origin, $quiz_id_new );
178 -
179 - do_action( 'learn-press/item/after-duplicate', $quiz_id_origin, $quiz_id_new, $args );
180 - }
181 - } catch ( Throwable $e ) {
182 - error_log( $e->getMessage() );
183 - }
184 -
185 - return $quiz_id_new;
186 - }
187 -
188 - /**
189 - * Duplicate questions.
190 - *
191 - * @param int $quiz_id_origin
192 - * @param int $quiz_id_new
193 - *
194 - * @return void
195 - */
196 - public function duplicate_questions( int $quiz_id_origin, int $quiz_id_new ) {
197 - $question_curd = new LP_Question_CURD();
198 -
199 - try {
200 - $quiz_origin = learn_press_get_quiz( $quiz_id_origin );
201 - if ( ! $quiz_origin ) {
202 - return;
203 - }
204 -
205 - $questions_origin = $quiz_origin->get_question_ids();
206 -
207 - foreach ( $questions_origin as $question_id_origin ) {
208 - $can_clone = true;
209 - $args = compact( 'question_id_origin', 'quiz_origin', 'quiz_id_new' );
210 - $can_clone = apply_filters( 'lp/quiz/question/can-clone', $can_clone, $args );
211 -
212 - if ( ! $can_clone ) {
213 - continue;
214 - }
215 -
216 - // duplicate question
217 - $question_id_new = $question_curd->duplicate( $question_id_origin, array( 'post_status' => 'publish' ) );
218 -
219 - if ( ! $question_id_new || is_wp_error( $question_id_new ) ) {
220 - continue;
221 - }
222 -
223 - // add duplicate question to new quiz
224 - $this->add_question( $quiz_id_new, $question_id_new );
225 - }
226 - } catch ( Throwable $e ) {
227 - error_log( $e->getMessage() );
228 - }
229 - }
230 -
231 - /**
232 - * @param LP_Quiz $quiz
233 - *
234 - * @deprecated 4.1.7
235 - */
236 - /*protected function _load_questions( &$quiz ) {
237 - $id = $quiz->get_id();
238 - $questions = LP_Object_Cache::get( 'questions-' . $id, 'learn-press/quizzes' );
239 -
240 - if ( false === $questions || $quiz->get_no_cache() ) {
241 - $this->load_questions( $quiz->get_id() );
242 - }
243 - }*/
244 -
245 - /**
246 - * Read question of a quiz from database
247 - *
248 - * @param int $quiz_id
249 - * @param string $context
250 - *
251 - * @return array|bool
252 - */
253 - /*public function read_questions( $quiz_id, $context = 'display' ) {
254 - $quiz = learn_press_get_quiz( $quiz_id );
255 -
256 - if ( ! $quiz ) {
257 - return false;
258 - }
259 -
260 - return $quiz->get_question_ids( $context );
261 - }*/
262 -
263 - /**
264 - * Read all question ids of a quiz.
265 - *
266 - * @param int $quiz_id
267 - * @param string $context
268 - *
269 - * @return array
270 - */
271 - public function read_question_ids( int $quiz_id = 0, string $context = 'display' ): array {
272 - $lp_question_db = LP_Question_DB::getInstance();
273 - $question_ids = [];
274 -
275 - try {
276 - $quiz = learn_press_get_quiz( $quiz_id );
277 - if ( ! $quiz ) {
278 - return array();
279 - }
280 -
281 - if ( $context === 'display' ) {
282 - $statuses = array( 'publish' );
283 - } else {
284 - $statuses = array( 'publish', 'draft', 'auto-draft' );
285 - }
286 -
287 - $filter = new LP_Question_Filter();
288 - $filter->ID = $quiz_id;
289 - $filter->post_status = $statuses;
290 -
291 - $question_ids = $lp_question_db->get_list_question_ids_of_quiz( $filter );
292 - } catch ( Throwable $e ) {
293 - error_log( $e->getMessage() );
294 - }
295 -
296 - return $question_ids;
297 - }
298 -
299 - /**
300 - * @deprecated 4.1.7
301 - */
302 - /*public function update_question_ids( $quiz_id ) {
303 - wp_cache_delete( 'quiz-' . $quiz_id, 'quiz-questions' );
304 -
305 - $quiz = learn_press_get_quiz( $quiz_id );
306 -
307 - if ( $quiz ) {
308 - $question_ids = $quiz->get_question_ids();
309 - } else {
310 - $question_ids = array();
311 - }
312 -
313 - update_post_meta( $quiz_id, '_questions', $question_ids );
314 - update_post_meta( $quiz_id, '_question_count', sizeof( $question_ids ) );
315 - }*/
316 -
317 - /**
318 - * Get quiz ids that contains a question.
319 - *
320 - * @since 3.1.0
321 - *
322 - * @param int $question_id
323 - *
324 - * @return array
325 - */
326 - public function get_quiz_by_question( $question_id ) {
327 - global $wpdb;
328 - $query = $wpdb->prepare(
329 - "
330 - SELECT ID
331 - FROM {$wpdb->posts} p
332 - INNER JOIN {$wpdb->learnpress_quiz_questions} qq ON qq.quiz_id = p.ID
333 - WHERE qq.question_id = %d
334 - ",
335 - $question_id
336 - );
337 -
338 - return $wpdb->get_col( $query );
339 - }
340 -
341 - public function load_questions( $quiz_id ) {
342 -
343 - global $wpdb;
344 -
345 - if ( is_array( $quiz_id ) ) {
346 - foreach ( $quiz_id as $q_id ) {
347 - $this->load_questions( $q_id );
348 - }
349 -
350 - return;
351 - }
352 -
353 - $query = $wpdb->prepare(
354 - "
355 - SELECT ID, post_title, post_content, post_status, post_type, post_author, post_date, post_name
356 - FROM {$wpdb->posts} p
357 - INNER JOIN {$wpdb->prefix}learnpress_quiz_questions qq ON p.ID = qq.question_id
358 - WHERE qq.quiz_id = %d
359 - AND p.post_status = %s
360 - ORDER BY question_order, quiz_question_id ASC
361 - ",
362 - $quiz_id,
363 - 'publish'
364 - );
365 -
366 - $question_ids = array();
367 - $results = $wpdb->get_results( $query );
368 -
369 - if ( $results ) {
370 - foreach ( $results as $k => $v ) {
371 - settype( $v, 'object' );
372 - wp_cache_set( $v->ID, $v, 'posts' );
373 -
374 - $question_ids[] = $v->ID;
375 - }
376 - }
377 -
378 - LP_Object_Cache::set( 'questions-' . $quiz_id, $question_ids, 'learn-press/quizzes' );
379 -
380 - // LP_Helper_CURD::cache_posts( $question_ids );
381 - $question_factory = new LP_Question_CURD();
382 - $question_factory->load_answer_options( $question_ids );
383 - }
384 -
385 - /**
386 - * Sort questions by order.
387 - * Check in an array of questions if there is a key 'order'.
388 - *
389 - * @param $questions
390 - *
391 - * @return mixed
392 - */
393 - protected function _maybe_sort_questions( &$questions ) {
394 - if ( ! $questions ) {
395 - return $questions;
396 - }
397 -
398 - $first = reset( $questions );
399 -
400 - if ( empty( $first['order'] ) ) {
401 - return $questions;
402 - }
403 -
404 - uasort( $questions, array( $this, '_callback_sort_questions' ) );
405 -
406 - return $questions;
407 - }
408 -
409 - public function _callback_sort_questions( $a, $b ) {
410 - return $a['order'] > $b['order'];
411 - }
412 -
413 - /**
414 - * Reorder question by indexed number.
415 - *
416 - * @param LP_Quiz|WP_Post|int $the_quiz
417 - * @param mixed $questions
418 - *
419 - * @return mixed
420 - */
421 - public function reorder_questions( $the_quiz, $questions = false ) {
422 - global $wpdb;
423 -
424 - $the_quiz = learn_press_get_quiz( $the_quiz );
425 -
426 - if ( ! $the_quiz ) {
427 - return false;
428 - }
429 -
430 - if ( false == $questions ) {
431 - $query = $wpdb->prepare(
432 - "
433 - SELECT quiz_question_id as id
434 - FROM {$wpdb->prefix}learnpress_quiz_questions
435 - WHERE quiz_id = %d
436 - ORDER BY question_order ASC
437 - ",
438 - $the_quiz->get_id()
439 - );
440 -
441 - $rows = $wpdb->get_results( $query );
442 -
443 - if ( $rows ) {
444 - $update = array();
445 - $ids = wp_list_pluck( $rows, 'id' );
446 - $format = array_fill( 0, sizeof( $ids ), '%d' );
447 -
448 - foreach ( $rows as $order => $row ) {
449 - $update[] = $wpdb->prepare( 'WHEN quiz_question_id = %d THEN %d', $row->id, $order + 1 );
450 - }
451 -
452 - $query = $wpdb->prepare(
453 - "
454 - UPDATE {$wpdb->prefix}learnpress_quiz_questions
455 - SET question_order = CASE
456 - " . join( "\n", $update ) . '
457 - ELSE question_order END
458 - WHERE quiz_question_id IN(' . join( ',', $format ) . ')
459 - ',
460 - $ids
461 - );
462 -
463 - return $wpdb->query( $query );
464 - }
465 - } else {
466 - $query = "
467 - UPDATE {$wpdb->learnpress_quiz_questions}
468 - SET question_order = CASE
469 - ";
470 - for ( $order = 0, $n = sizeof( $questions ); $order < $n; $order ++ ) {
471 - $query .= $wpdb->prepare( 'WHEN question_id = %d THEN %d', $questions[ $order ], $order + 1 ) . "\n";
472 - }
473 - $query .= sprintf( 'ELSE question_order END WHERE quiz_id = %d', $the_quiz->get_id() );
474 -
475 - return $wpdb->query( $query );
476 - }
477 -
478 - return false;
479 - }
480 -
481 -
482 - /**
483 - * Get all questions in a quiz
484 - *
485 - * @param LP_Quiz $the_quiz
486 - *
487 - * @return array|mixed
488 - */
489 - public function get_questions( $the_quiz ) {
490 - $the_quiz = learn_press_get_quiz( $the_quiz );
491 -
492 - if ( ! $the_quiz ) {
493 - return $this->get_error( 'QUIZ_NOT_EXISTS' );
494 - }
495 -
496 - return LP_Object_Cache::get( 'questions-' . $the_quiz->get_id(), 'learn-press/quizzes' );
497 - }
498 -
499 - /**
500 - * Add existing question into quiz.
501 - *
502 - * @param LP_Quiz|int $the_quiz
503 - * @param $question_id
504 - * @param array $args
505 - *
506 - * @return mixed false on failed
507 - */
508 - public function add_question( $the_quiz, $question_id, $args = array() ) {
509 - $the_quiz = learn_press_get_quiz( $the_quiz );
510 -
511 - if ( ! $the_quiz ) {
512 - return $this->get_error( 'QUIZ_NOT_EXISTS' );
513 - }
514 -
515 - $question = learn_press_get_question( $question_id );
516 -
517 - if ( ! $question ) {
518 - return false;
519 - }
520 -
521 - if ( $this->is_exists_question( $the_quiz->get_id(), $question_id ) ) {
522 - return false;
523 - }
524 -
525 - // list exist quiz question
526 - //$list_questions = $this->get_questions( $the_quiz );
527 - // add new question and set to cache
528 - //$list_questions[ $question_id ] = strval( $question_id );
529 - //LP_Object_Cache::set( 'questions-' . $the_quiz->get_id(), $list_questions, 'learn-press/quizzes' );
530 -
531 - global $wpdb;
532 -
533 - $id = $the_quiz->get_id();
534 - $args = wp_parse_args( $args, array( 'order' => - 1 ) );
535 -
536 - if ( $args['order'] >= 0 ) {
537 - $query = $wpdb->prepare(
538 - "
539 - UPDATE {$wpdb->prefix}learnpress_quiz_questions
540 - SET question_order = question_order + 1
541 - WHERE quiz_id = %d AND question_order >= %d
542 - ",
543 - $id,
544 - $args['order']
545 - );
546 - $wpdb->get_results( $query );
547 - } else {
548 - $query = $wpdb->prepare(
549 - "
550 - SELECT max(question_order) + 1 as ordering
551 - FROM {$wpdb->prefix}learnpress_quiz_questions
552 - WHERE quiz_id = %d
553 - ",
554 - $id
555 - );
556 -
557 - $order = $wpdb->get_var( $query );
558 -
559 - if ( ! $order ) {
560 - $order = 1;
561 - }
562 -
563 - $args['order'] = $order;
564 - }
565 -
566 - $inserted = $wpdb->insert(
567 - $wpdb->prefix . 'learnpress_quiz_questions',
568 - array(
569 - 'quiz_id' => $id,
570 - 'question_id' => $question_id,
571 - 'question_order' => $args['order'],
572 - ),
573 - array( '%d', '%d', '%d' )
574 - );
575 -
576 - $return = $inserted ? $wpdb->insert_id : $inserted;
577 -
578 - do_action( 'learn-press/quiz-added-question', $inserted, $question_id, $the_quiz->get_id() );
579 -
580 - return $return;
581 - }
582 -
583 - /**
584 - * Check if a question (or batch of questions) is already added to quiz.
585 - *
586 - * @param int $the_id
587 - * @param int|array $ids
588 - *
589 - * @return array|bool|null|object
590 - */
591 - public function is_exists_question( $the_id, $ids ) {
592 - global $wpdb;
593 -
594 - settype( $ids, 'array' );
595 - $format = array_fill( 0, sizeof( $ids ), '%d' );
596 -
597 - $questions_ids = implode( ', ', $ids );
598 -
599 - $query = $wpdb->prepare(
600 - "
601 - SELECT quiz_question_id
602 - FROM {$wpdb->learnpress_quiz_questions}
603 - WHERE question_id IN( " . join( ',', $format ) . ' )
604 - AND quiz_id = %d
605 - ',
606 - $questions_ids,
607 - $the_id
608 - );
609 -
610 - $results = $wpdb->get_results( $query );
611 -
612 - if ( $results ) {
613 - return $results;
614 - }
615 -
616 - return false;
617 - }
618 -
619 - /**
620 - * Update order question in quiz.
621 - *
622 - * @param $order
623 - *
624 - * @return false|int
625 - */
626 - public function sort_questions( $order ) {
627 - global $wpdb;
628 -
629 - foreach ( $order as $index => $question_id ) {
630 - $update = $wpdb->update(
631 - $wpdb->learnpress_quiz_questions,
632 - array( 'question_order' => $index + 1 ),
633 - array( 'question_id' => $question_id ),
634 - array( '%d' ),
635 - array( '%d' )
636 - );
637 -
638 - if ( $update === false ) {
639 - return false;
640 - }
641 - }
642 -
643 - return true;
644 - }
645 -
646 - /**
647 - * Remove question from quiz.
648 - *
649 - * @since 3.0.0
650 - *
651 - * @param $quiz_id
652 - * @param $question_id
653 - * @param bool $force | remove all questions from quiz
654 - *
655 - * @return bool|false|int|WP_Error
656 - */
657 - public function remove_questions( $quiz_id, $question_id, $force = false ) {
658 - $quiz = learn_press_get_quiz( $quiz_id );
659 -
660 - if ( ! $quiz ) {
661 - return $this->get_error( 'QUIZ_NOT_EXISTS' );
662 - }
663 -
664 - global $wpdb;
665 -
666 - if ( $force ) {
667 - // remove all questions from quiz
668 - $delete = $wpdb->delete(
669 - $wpdb->prefix . 'learnpress_quiz_questions',
670 - array( 'quiz_id' => $quiz_id ),
671 - array( '%d' )
672 - );
673 - } else {
674 - do_action( 'learn-press/delete-quiz-question', $question_id, $quiz_id );
675 -
676 - // remove question from quiz
677 - $delete = $wpdb->delete(
678 - $wpdb->prefix . 'learnpress_quiz_questions',
679 - array(
680 - 'quiz_id' => $quiz_id,
681 - 'question_id' => $question_id,
682 - ),
683 - array( '%d', '%d' )
684 - );
685 -
686 - do_action( 'learn-press/deleted-quiz-question', $question_id, $quiz_id, $delete );
687 -
688 - // reorder questions
689 - $this->reorder_questions( $quiz );
690 - }
691 -
692 - // increment quiz questions
693 - learn_press_reset_auto_increment( 'learnpress_quiz_questions' );
694 -
695 - return $delete;
696 - }
697 -
698 - /**
699 - * Update order quiz question answers.
700 - *
701 - * @since 3.0.0
702 - *
703 - * @param $answers
704 - *
705 - * @return array
706 - */
707 - public function sort_question_answers( $answers ) {
708 - global $wpdb;
709 -
710 - $orders = array();
711 -
712 - foreach ( $answers as $index => $answer_id ) {
713 - $order = $index + 1;
714 -
715 - $orders[ $answer_id ] = $order;
716 -
717 - $wpdb->update(
718 - $wpdb->learnpress_question_answers,
719 - array( 'order' => $order ),
720 - array( 'question_answer_id' => $answer_id )
721 - );
722 - }
723 -
724 - return $orders;
725 - }
726 -
727 - public function add_meta( &$object, $meta ) {
728 - // TODO: Implement add_meta() method.
729 - }
730 -
731 - public function delete_meta( &$object, $meta ) {
732 - // TODO: Implement delete_meta() method.
733 - }
734 -
735 - public function read_meta( &$object ) {
736 - // TODO: Implement read_meta() method.
737 - }
738 -
739 - /**
740 - * @param $object
741 - * @param $meta
742 - *
743 - * @return mixed
744 - */
745 - public function update_meta( &$object, $meta ) {
746 - return learn_press_update_user_item_meta( $object->get_user_item_id(), $meta->meta_key, $meta->meta_value );
747 - }
748 - }
749 -}
1 +<?php
2 +/**
3 + * Class LP_Quiz_CURD.
4 + *
5 + * @author ThimPress
6 + * @package LearnPress/Classes/CURD
7 + * @since 3.0.0
8 + */
9 +
10 +/**
11 + * Prevent loading this file directly
12 + */
13 +defined( 'ABSPATH' ) || exit();
14 +
15 +if ( ! function_exists( 'LP_Quiz_CURD' ) ) {
16 +
17 + /**
18 + * Class LP_Quiz_CURD
19 + *
20 + * Class to manipulating quiz with database.
21 + */
22 + class LP_Quiz_CURD extends LP_Object_Data_CURD implements LP_Interface_CURD {
23 +
24 + /**
25 + * LP_Quiz_CURD constructor.
26 + */
27 + public function __construct() {
28 + $this->_error_messages = array(
29 + 'QUIZ_NOT_EXISTS' => __( 'The quiz does not exist.', 'learnpress' ),
30 + );
31 + }
32 +
33 + /**
34 + * @param LP_Quiz $quiz
35 + *
36 + * @return LP_Quiz|mixed
37 + * @throws Exception
38 + */
39 + public function load( &$quiz ) {
40 + $id = $quiz->get_id();
41 + if ( ! $id || learn_press_get_post_type( $id ) !== LP_QUIZ_CPT ) {
42 +
43 + throw new Exception( sprintf( __( 'Invalid quiz with ID "%d".', 'learnpress' ), $id ) );
44 + }
45 +
46 + // LP_Helper_CURD::update_meta_cache( $quiz->get_id() );
47 +
48 + // 'show_result' => get_post_meta( $quiz->get_id(), '_lp_show_result', true ),
49 + // 'show_check_answer' => get_post_meta( $quiz->get_id(), '_lp_show_check_answer', true ),
50 + // 'count_check_answer' => get_post_meta( $quiz->get_id(), '_lp_check_answer_count', true ),
51 + // 'show_hint' => get_post_meta( $quiz->get_id(), '_lp_show_hint', true ),
52 + // 'archive_history' => get_post_meta( $quiz->get_id(), '_lp_archive_history', true ),
53 + // 'count_hint' => get_post_meta( $quiz->get_id(), '_lp_hint_count', true ),
54 + // 'minus_points' => get_post_meta( $quiz->get_id(), '_lp_minus_points', true ),
55 + $quiz->set_passing_grade_type( get_post_meta( $quiz->get_id(), '_lp_passing_grade_type', true ) );
56 + $quiz->set_passing_grade( get_post_meta( $quiz->get_id(), '_lp_passing_grade', true ) );
57 + $quiz->set_pagination( get_post_meta( $quiz->get_id(), '_lp_pagination', true ) );
58 + $quiz->set_review_questions( get_post_meta( $quiz->get_id(), '_lp_review', true ) );
59 + $quiz->set_show_correct_review( get_post_meta( $quiz->get_id(), '_lp_show_correct_review', true ) );
60 + $quiz->set_preview( get_post_meta( $quiz->get_id(), '_lp_preview', true ) );
61 + $quiz->set_minus_skip_questions( get_post_meta( $quiz->get_id(), '_lp_minus_skip_questions', true ) );
62 + $quiz->set_instant_check( get_post_meta( $quiz->get_id(), '_lp_instant_check', true ) );
63 + $quiz->set_negative_marking( get_post_meta( $quiz->get_id(), '_lp_negative_marking', true ) );
64 + $quiz->set_retake_count( get_post_meta( $quiz->get_id(), '_lp_retake_count', true ) );
65 +
66 + return $quiz;
67 + }
68 +
69 + /**
70 + * Create quiz, with default meta.
71 + *
72 + * @param $args
73 + *
74 + * @return int|WP_Error
75 + */
76 + public function create( &$args ) {
77 +
78 + $args = wp_parse_args(
79 + $args,
80 + array(
81 + 'id' => '',
82 + 'status' => 'publish',
83 + 'title' => __( 'New Quiz', 'learnpress' ),
84 + 'content' => '',
85 + 'author' => learn_press_get_current_user_id(),
86 + )
87 + );
88 +
89 + $quiz_id = wp_insert_post(
90 + array(
91 + 'ID' => $args['id'],
92 + 'post_type' => LP_QUIZ_CPT,
93 + 'post_status' => $args['status'],
94 + 'post_title' => $args['title'],
95 + 'post_content' => $args['content'],
96 + 'post_author' => $args['author'],
97 + )
98 + );
99 +
100 + if ( $quiz_id ) {
101 + // add default meta for new lesson
102 + $default_meta = LP_Quiz::get_default_meta();
103 +
104 + if ( is_array( $default_meta ) ) {
105 + foreach ( $default_meta as $key => $value ) {
106 + update_post_meta( $quiz_id, '_lp_' . $key, $value );
107 + }
108 + }
109 + }
110 +
111 + return $quiz_id;
112 + }
113 +
114 + public function update( &$quiz ) {
115 + // TODO: Implement update() method.
116 + }
117 +
118 + /**
119 + * Delete quiz.
120 + *
121 + * @since 3.0.0
122 + *
123 + * @param object $quiz_id
124 + */
125 + public function delete( &$quiz_id ) {
126 + // course curd
127 + $curd = new LP_Course_CURD();
128 +
129 + // allow hook
130 + do_action( 'learn-press/before-delete-quiz', $quiz_id );
131 +
132 + // remove quiz from course items
133 + $curd->remove_item( $quiz_id );
134 + // remove questions from quiz
135 + $this->remove_questions( $quiz_id, '', true );
136 + }
137 +
138 + /**
139 + * Duplicate quiz.
140 + *
141 + * @since 3.0.0
142 + *
143 + * @param $quiz_id_origin
144 + * @param array $args
145 + *
146 + * @return mixed|WP_Error
147 + */
148 + public function duplicate( &$quiz_id_origin, $args = array() ) {
149 + $quiz_id_new = 0;
150 +
151 + try {
152 + if ( ! $quiz_id_origin ) {
153 + return new WP_Error( 'lp/clone/quiz/id_null', 'Op! Quiz ID not found' );
154 + }
155 +
156 + if ( learn_press_get_post_type( $quiz_id_origin ) != LP_QUIZ_CPT ) {
157 + return new WP_Error( 'lp/clone/quiz/type_invalid', 'Op! The quiz does not exist' );
158 + }
159 +
160 + // Ensure that user can create quiz
161 + if ( ! current_user_can( 'edit_posts' ) ) {
162 + return new WP_Error( 'lp/clone/quiz/permission', 'Sorry! You have not permission to duplicate this quiz' );
163 + }
164 +
165 + // Duplicate quiz
166 + $quiz_id_new = learn_press_duplicate_post( $quiz_id_origin, $args, true );
167 +
168 + if ( ! $quiz_id_new || is_wp_error( $quiz_id_new ) ) {
169 + return new WP_Error( 'lp/clone/quiz/clone_error', 'Sorry! Failed to duplicate quiz!' );
170 + } else {
171 + // duplicate questions.
172 + $this->duplicate_questions( $quiz_id_origin, $quiz_id_new );
173 +
174 + do_action( 'learn-press/item/after-duplicate', $quiz_id_origin, $quiz_id_new, $args );
175 + }
176 + } catch ( Throwable $e ) {
177 + error_log( $e->getMessage() );
178 + }
179 +
180 + return $quiz_id_new;
181 + }
182 +
183 + /**
184 + * Duplicate questions.
185 + *
186 + * @param int $quiz_id_origin
187 + * @param int $quiz_id_new
188 + *
189 + * @return void
190 + */
191 + public function duplicate_questions( int $quiz_id_origin, int $quiz_id_new ) {
192 + $question_curd = new LP_Question_CURD();
193 +
194 + try {
195 + $quiz_origin = learn_press_get_quiz( $quiz_id_origin );
196 + if ( ! $quiz_origin ) {
197 + return;
198 + }
199 +
200 + $questions_origin = $quiz_origin->get_question_ids();
201 +
202 + foreach ( $questions_origin as $question_id_origin ) {
203 + $can_clone = true;
204 + $args = compact( 'question_id_origin', 'quiz_origin', 'quiz_id_new' );
205 + $can_clone = apply_filters( 'lp/quiz/question/can-clone', $can_clone, $args );
206 +
207 + if ( ! $can_clone ) {
208 + continue;
209 + }
210 +
211 + // duplicate question
212 + $question_id_new = $question_curd->duplicate( $question_id_origin, array( 'post_status' => 'publish' ) );
213 +
214 + if ( ! $question_id_new || is_wp_error( $question_id_new ) ) {
215 + continue;
216 + }
217 +
218 + // add duplicate question to new quiz
219 + $this->add_question( $quiz_id_new, $question_id_new );
220 + }
221 + } catch ( Throwable $e ) {
222 + error_log( $e->getMessage() );
223 + }
224 + }
225 +
226 + /**
227 + * @param LP_Quiz $quiz
228 + *
229 + * @deprecated 4.1.7
230 + */
231 + /*protected function _load_questions( &$quiz ) {
232 + $id = $quiz->get_id();
233 + $questions = LP_Object_Cache::get( 'questions-' . $id, 'learn-press/quizzes' );
234 +
235 + if ( false === $questions || $quiz->get_no_cache() ) {
236 + $this->load_questions( $quiz->get_id() );
237 + }
238 + }*/
239 +
240 + /**
241 + * Read question of a quiz from database
242 + *
243 + * @param int $quiz_id
244 + * @param string $context
245 + *
246 + * @return array|bool
247 + */
248 + /*public function read_questions( $quiz_id, $context = 'display' ) {
249 + $quiz = learn_press_get_quiz( $quiz_id );
250 +
251 + if ( ! $quiz ) {
252 + return false;
253 + }
254 +
255 + return $quiz->get_question_ids( $context );
256 + }*/
257 +
258 + /**
259 + * Read all question ids of a quiz.
260 + *
261 + * @param int $quiz_id
262 + * @param string $context
263 + *
264 + * @return array
265 + */
266 + public function read_question_ids( int $quiz_id = 0, string $context = 'display' ): array {
267 + $lp_question_db = LP_Question_DB::getInstance();
268 + $question_ids = [];
269 +
270 + try {
271 + $quiz = learn_press_get_quiz( $quiz_id );
272 + if ( ! $quiz ) {
273 + return array();
274 + }
275 +
276 + if ( $context === 'display' ) {
277 + $statuses = array( 'publish' );
278 + } else {
279 + $statuses = array( 'publish', 'draft', 'auto-draft' );
280 + }
281 +
282 + $filter = new LP_Question_Filter();
283 + $filter->ID = $quiz_id;
284 + $filter->post_status = $statuses;
285 +
286 + $question_ids = $lp_question_db->get_list_question_ids_of_quiz( $filter );
287 + } catch ( Throwable $e ) {
288 + error_log( $e->getMessage() );
289 + }
290 +
291 + return $question_ids;
292 + }
293 +
294 + /**
295 + * @deprecated 4.1.7
296 + */
297 + /*public function update_question_ids( $quiz_id ) {
298 + wp_cache_delete( 'quiz-' . $quiz_id, 'quiz-questions' );
299 +
300 + $quiz = learn_press_get_quiz( $quiz_id );
301 +
302 + if ( $quiz ) {
303 + $question_ids = $quiz->get_question_ids();
304 + } else {
305 + $question_ids = array();
306 + }
307 +
308 + update_post_meta( $quiz_id, '_questions', $question_ids );
309 + update_post_meta( $quiz_id, '_question_count', sizeof( $question_ids ) );
310 + }*/
311 +
312 + /**
313 + * Get quiz ids that contains a question.
314 + *
315 + * @since 3.1.0
316 + *
317 + * @param int $question_id
318 + *
319 + * @return array
320 + */
321 + public function get_quiz_by_question( $question_id ) {
322 + global $wpdb;
323 + $query = $wpdb->prepare(
324 + "
325 + SELECT ID
326 + FROM {$wpdb->posts} p
327 + INNER JOIN {$wpdb->learnpress_quiz_questions} qq ON qq.quiz_id = p.ID
328 + WHERE qq.question_id = %d
329 + ",
330 + $question_id
331 + );
332 +
333 + return $wpdb->get_col( $query );
334 + }
335 +
336 + public function load_questions( $quiz_id ) {
337 +
338 + global $wpdb;
339 +
340 + if ( is_array( $quiz_id ) ) {
341 + foreach ( $quiz_id as $q_id ) {
342 + $this->load_questions( $q_id );
343 + }
344 +
345 + return;
346 + }
347 +
348 + $query = $wpdb->prepare(
349 + "
350 + SELECT ID, post_title, post_content, post_status, post_type, post_author, post_date, post_name
351 + FROM {$wpdb->posts} p
352 + INNER JOIN {$wpdb->prefix}learnpress_quiz_questions qq ON p.ID = qq.question_id
353 + WHERE qq.quiz_id = %d
354 + AND p.post_status = %s
355 + ORDER BY question_order, quiz_question_id ASC
356 + ",
357 + $quiz_id,
358 + 'publish'
359 + );
360 +
361 + $question_ids = array();
362 + $results = $wpdb->get_results( $query );
363 +
364 + if ( $results ) {
365 + foreach ( $results as $k => $v ) {
366 + settype( $v, 'object' );
367 + wp_cache_set( $v->ID, $v, 'posts' );
368 +
369 + $question_ids[] = $v->ID;
370 + }
371 + }
372 +
373 + LP_Object_Cache::set( 'questions-' . $quiz_id, $question_ids, 'learn-press/quizzes' );
374 +
375 + // LP_Helper_CURD::cache_posts( $question_ids );
376 + $question_factory = new LP_Question_CURD();
377 + $question_factory->load_answer_options( $question_ids );
378 + }
379 +
380 + /**
381 + * Sort questions by order.
382 + * Check in an array of questions if there is a key 'order'.
383 + *
384 + * @param $questions
385 + *
386 + * @return mixed
387 + */
388 + protected function _maybe_sort_questions( &$questions ) {
389 + if ( ! $questions ) {
390 + return $questions;
391 + }
392 +
393 + $first = reset( $questions );
394 +
395 + if ( empty( $first['order'] ) ) {
396 + return $questions;
397 + }
398 +
399 + uasort( $questions, array( $this, '_callback_sort_questions' ) );
400 +
401 + return $questions;
402 + }
403 +
404 + public function _callback_sort_questions( $a, $b ) {
405 + return $a['order'] > $b['order'];
406 + }
407 +
408 + /**
409 + * Reorder question by indexed number.
410 + *
411 + * @param LP_Quiz|WP_Post|int $the_quiz
412 + * @param mixed $questions
413 + *
414 + * @return mixed
415 + */
416 + public function reorder_questions( $the_quiz, $questions = false ) {
417 + global $wpdb;
418 +
419 + $the_quiz = learn_press_get_quiz( $the_quiz );
420 +
421 + if ( ! $the_quiz ) {
422 + return false;
423 + }
424 +
425 + if ( false == $questions ) {
426 + $query = $wpdb->prepare(
427 + "
428 + SELECT quiz_question_id as id
429 + FROM {$wpdb->prefix}learnpress_quiz_questions
430 + WHERE quiz_id = %d
431 + ORDER BY question_order ASC
432 + ",
433 + $the_quiz->get_id()
434 + );
435 +
436 + $rows = $wpdb->get_results( $query );
437 +
438 + if ( $rows ) {
439 + $update = array();
440 + $ids = wp_list_pluck( $rows, 'id' );
441 + $format = array_fill( 0, sizeof( $ids ), '%d' );
442 +
443 + foreach ( $rows as $order => $row ) {
444 + $update[] = $wpdb->prepare( 'WHEN quiz_question_id = %d THEN %d', $row->id, $order + 1 );
445 + }
446 +
447 + $query = $wpdb->prepare(
448 + "
449 + UPDATE {$wpdb->prefix}learnpress_quiz_questions
450 + SET question_order = CASE
451 + " . join( "\n", $update ) . '
452 + ELSE question_order END
453 + WHERE quiz_question_id IN(' . join( ',', $format ) . ')
454 + ',
455 + $ids
456 + );
457 +
458 + return $wpdb->query( $query );
459 + }
460 + } else {
461 + $query = "
462 + UPDATE {$wpdb->learnpress_quiz_questions}
463 + SET question_order = CASE
464 + ";
465 + for ( $order = 0, $n = sizeof( $questions ); $order < $n; $order ++ ) {
466 + $query .= $wpdb->prepare( 'WHEN question_id = %d THEN %d', $questions[ $order ], $order + 1 ) . "\n";
467 + }
468 + $query .= sprintf( 'ELSE question_order END WHERE quiz_id = %d', $the_quiz->get_id() );
469 +
470 + return $wpdb->query( $query );
471 + }
472 +
473 + return false;
474 + }
475 +
476 +
477 + /**
478 + * Get all questions in a quiz
479 + *
480 + * @param LP_Quiz $the_quiz
481 + *
482 + * @return array|mixed
483 + */
484 + public function get_questions( $the_quiz ) {
485 + $the_quiz = learn_press_get_quiz( $the_quiz );
486 +
487 + if ( ! $the_quiz ) {
488 + return $this->get_error( 'QUIZ_NOT_EXISTS' );
489 + }
490 +
491 + return LP_Object_Cache::get( 'questions-' . $the_quiz->get_id(), 'learn-press/quizzes' );
492 + }
493 +
494 + /**
495 + * Add existing question into quiz.
496 + *
497 + * @param LP_Quiz|int $the_quiz
498 + * @param $question_id
499 + * @param array $args
500 + *
501 + * @return mixed false on failed
502 + */
503 + public function add_question( $the_quiz, $question_id, $args = array() ) {
504 + $the_quiz = learn_press_get_quiz( $the_quiz );
505 +
506 + if ( ! $the_quiz ) {
507 + return $this->get_error( 'QUIZ_NOT_EXISTS' );
508 + }
509 +
510 + $question = learn_press_get_question( $question_id );
511 +
512 + if ( ! $question ) {
513 + return false;
514 + }
515 +
516 + if ( $this->is_exists_question( $the_quiz->get_id(), $question_id ) ) {
517 + return false;
518 + }
519 +
520 + // list exist quiz question
521 + //$list_questions = $this->get_questions( $the_quiz );
522 + // add new question and set to cache
523 + //$list_questions[ $question_id ] = strval( $question_id );
524 + //LP_Object_Cache::set( 'questions-' . $the_quiz->get_id(), $list_questions, 'learn-press/quizzes' );
525 +
526 + global $wpdb;
527 +
528 + $id = $the_quiz->get_id();
529 + $args = wp_parse_args( $args, array( 'order' => - 1 ) );
530 +
531 + if ( $args['order'] >= 0 ) {
532 + $query = $wpdb->prepare(
533 + "
534 + UPDATE {$wpdb->prefix}learnpress_quiz_questions
535 + SET question_order = question_order + 1
536 + WHERE quiz_id = %d AND question_order >= %d
537 + ",
538 + $id,
539 + $args['order']
540 + );
541 + $wpdb->get_results( $query );
542 + } else {
543 + $query = $wpdb->prepare(
544 + "
545 + SELECT max(question_order) + 1 as ordering
546 + FROM {$wpdb->prefix}learnpress_quiz_questions
547 + WHERE quiz_id = %d
548 + ",
549 + $id
550 + );
551 +
552 + $order = $wpdb->get_var( $query );
553 +
554 + if ( ! $order ) {
555 + $order = 1;
556 + }
557 +
558 + $args['order'] = $order;
559 + }
560 +
561 + $inserted = $wpdb->insert(
562 + $wpdb->prefix . 'learnpress_quiz_questions',
563 + array(
564 + 'quiz_id' => $id,
565 + 'question_id' => $question_id,
566 + 'question_order' => $args['order'],
567 + ),
568 + array( '%d', '%d', '%d' )
569 + );
570 +
571 + $return = $inserted ? $wpdb->insert_id : $inserted;
572 +
573 + do_action( 'learn-press/quiz-added-question', $inserted, $question_id, $the_quiz->get_id() );
574 +
575 + return $return;
576 + }
577 +
578 + /**
579 + * Check if a question (or batch of questions) is already added to quiz.
580 + *
581 + * @param int $the_id
582 + * @param int|array $ids
583 + *
584 + * @return array|bool|null|object
585 + */
586 + public function is_exists_question( $the_id, $ids ) {
587 + global $wpdb;
588 +
589 + settype( $ids, 'array' );
590 + $format = array_fill( 0, sizeof( $ids ), '%d' );
591 +
592 + $questions_ids = implode( ', ', $ids );
593 +
594 + $query = $wpdb->prepare(
595 + "
596 + SELECT quiz_question_id
597 + FROM {$wpdb->learnpress_quiz_questions}
598 + WHERE question_id IN( " . join( ',', $format ) . ' )
599 + AND quiz_id = %d
600 + ',
601 + $questions_ids,
602 + $the_id
603 + );
604 +
605 + $results = $wpdb->get_results( $query );
606 +
607 + if ( $results ) {
608 + return $results;
609 + }
610 +
611 + return false;
612 + }
613 +
614 + /**
615 + * Update order question in quiz.
616 + *
617 + * @param $order
618 + *
619 + * @return false|int
620 + */
621 + public function sort_questions( $order ) {
622 + global $wpdb;
623 +
624 + foreach ( $order as $index => $question_id ) {
625 + $update = $wpdb->update(
626 + $wpdb->learnpress_quiz_questions,
627 + array( 'question_order' => $index + 1 ),
628 + array( 'question_id' => $question_id ),
629 + array( '%d' ),
630 + array( '%d' )
631 + );
632 +
633 + if ( $update === false ) {
634 + return false;
635 + }
636 + }
637 +
638 + return true;
639 + }
640 +
641 + /**
642 + * Remove question from quiz.
643 + *
644 + * @since 3.0.0
645 + *
646 + * @param $quiz_id
647 + * @param $question_id
648 + * @param bool $force | remove all questions from quiz
649 + *
650 + * @return bool|false|int|WP_Error
651 + */
652 + public function remove_questions( $quiz_id, $question_id, $force = false ) {
653 + $quiz = learn_press_get_quiz( $quiz_id );
654 +
655 + if ( ! $quiz ) {
656 + return $this->get_error( 'QUIZ_NOT_EXISTS' );
657 + }
658 +
659 + global $wpdb;
660 +
661 + if ( $force ) {
662 + // remove all questions from quiz
663 + $delete = $wpdb->delete(
664 + $wpdb->prefix . 'learnpress_quiz_questions',
665 + array( 'quiz_id' => $quiz_id ),
666 + array( '%d' )
667 + );
668 + } else {
669 + do_action( 'learn-press/delete-quiz-question', $question_id, $quiz_id );
670 +
671 + // remove question from quiz
672 + $delete = $wpdb->delete(
673 + $wpdb->prefix . 'learnpress_quiz_questions',
674 + array(
675 + 'quiz_id' => $quiz_id,
676 + 'question_id' => $question_id,
677 + ),
678 + array( '%d', '%d' )
679 + );
680 +
681 + do_action( 'learn-press/deleted-quiz-question', $question_id, $quiz_id, $delete );
682 +
683 + // reorder questions
684 + $this->reorder_questions( $quiz );
685 + }
686 +
687 + // increment quiz questions
688 + learn_press_reset_auto_increment( 'learnpress_quiz_questions' );
689 +
690 + return $delete;
691 + }
692 +
693 + /**
694 + * Update order quiz question answers.
695 + *
696 + * @since 3.0.0
697 + *
698 + * @param $answers
699 + *
700 + * @return array
701 + */
702 + public function sort_question_answers( $answers ) {
703 + global $wpdb;
704 +
705 + $orders = array();
706 +
707 + foreach ( $answers as $index => $answer_id ) {
708 + $order = $index + 1;
709 +
710 + $orders[ $answer_id ] = $order;
711 +
712 + $wpdb->update(
713 + $wpdb->learnpress_question_answers,
714 + array( 'order' => $order ),
715 + array( 'question_answer_id' => $answer_id )
716 + );
717 + }
718 +
719 + return $orders;
720 + }
721 +
722 + public function add_meta( &$object, $meta ) {
723 + // TODO: Implement add_meta() method.
724 + }
725 +
726 + public function delete_meta( &$object, $meta ) {
727 + // TODO: Implement delete_meta() method.
728 + }
729 +
730 + public function read_meta( &$object ) {
731 + // TODO: Implement read_meta() method.
732 + }
733 +
734 + /**
735 + * @param $object
736 + * @param $meta
737 + *
738 + * @return mixed
739 + */
740 + public function update_meta( &$object, $meta ) {
741 + return learn_press_update_user_item_meta( $object->get_user_item_id(), $meta->meta_key, $meta->meta_value );
742 + }
743 + }
744 +}