PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.1.6.9
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.1.6.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 4.2.0 All 139 releases
learnpress / inc / curds / class-lp-question-curd.php

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

1,048 lines 26.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_Question_CURD
5 *
6 * @author ThimPress
7 * @package LearnPress/Classes/CURD
8 * @since 3.0.0
9 */
10
11 /**
12 * Prevent loading this file directly
13 */
14 defined( 'ABSPATH' ) || exit();
15
16 if ( ! class_exists( 'LP_Question_CURD' ) ) {
17
18 /**
19 * Class LP_Question_CURD
20 */
21 class LP_Question_CURD extends LP_Object_Data_CURD implements LP_Interface_CURD {
22
23 /**
24 * LP_Question_CURD constructor.
25 */
26 public function __construct() {
27 $this->_error_messages = array(
28 'QUESTION_NOT_EXISTS' => __( 'Question does not exist.', 'learnpress' ),
29 );
30 }
31
32 /**
33 * Create question and can add to quiz.
34 *
35 * @param $args
36 *
37 * @return bool|int|LP_Question|WP_Error
38 */
39 public function create( &$args ) {
40 $args = wp_parse_args(
41 $args,
42 array(
43 'quiz_id' => 0,
44 'order' => - 1,
45 'id' => '',
46 'status' => 'publish',
47 'type' => 'true_or_false',
48 'title' => __( 'New Question', 'learnpress' ),
49 'content' => '',
50 'create_answers' => true,
51 )
52 );
53
54 // set question author for author of quiz
55 if ( ! empty( $args['quiz_id'] ) ) {
56 $user_id = get_post_field( 'post_author', $args['quiz_id'] );
57 } else {
58 $user_id = learn_press_get_current_user_id();
59 }
60
61 $question_id = wp_insert_post(
62 array(
63 'ID' => $args['id'],
64 'post_author' => $user_id,
65 'post_type' => LP_QUESTION_CPT,
66 'post_status' => $args['status'],
67 'post_title' => $args['title'],
68 'post_content' => $args['content'],
69 )
70 );
71
72 if ( $question_id ) {
73 // add default meta for new lesson
74 $default_meta = LP_Question::get_default_meta();
75
76 if ( is_array( $default_meta ) ) {
77 foreach ( $default_meta as $key => $value ) {
78 update_post_meta( $question_id, '_lp_' . $key, $value );
79 }
80 }
81 update_post_meta( $question_id, '_lp_type', $args['type'] );
82 // update user memory question types
83 get_user_meta( $user_id, '_learn_press_memorize_question_types', $args['type'] );
84
85 $question = LP_Question::get_question( $question_id, array( 'type' => $args['type'] ) );
86 $question->set_type( $args['type'] );
87
88 if ( $args['create_answers'] ) {
89 $question->create_default_answers();
90
91 // add question to quiz
92 if ( ! empty( $args['quiz_id'] ) ) {
93 $quiz_curd = new LP_Quiz_CURD();
94 $quiz_curd->add_question( $args['quiz_id'], $question_id, $args['order'] );
95 }
96 }
97
98 do_action( 'learn-press/after-create-question', $question );
99
100 return $question;
101 }
102
103 return $question_id;
104 }
105
106
107 public function update( &$question ) {
108 return $question;
109 // TODO: Implement update() method.
110 }
111
112 /**
113 * Delete all question's related data before run wp_delete_post(), hook to before delete question hook.
114 *
115 * @since 3.0.0
116 *
117 * @param object $question_id
118 */
119 public function delete( &$question_id ) {
120 // remove all answer of question from {$wpdb->prefix}learnpress_question_answers table
121 $this->clear( $question_id );
122
123 // quiz curd
124 $curd = new LP_Quiz_CURD();
125
126 // allow hook
127 do_action( 'learn-press/before-delete-question', $question_id );
128
129 // get the quizzes that a question is assigned to, return WP Post
130 $quiz = $this->get_quiz( $question_id );
131
132 // remove question from quiz
133 if ( $quiz ) {
134 $curd->remove_questions( $quiz->ID, $question_id );
135 }
136 }
137
138 /**
139 * Duplicate question.
140 *
141 * @since 3.0.0
142 *
143 * @param $question_id
144 * @param array $args
145 *
146 * @return mixed|WP_Error
147 */
148 public function duplicate( &$question_id, $args = array() ) {
149 if ( ! $question_id ) {
150 return new WP_Error( __( '<p>Op! ID not found</p>', 'learnpress' ) );
151 }
152
153 if ( learn_press_get_post_type( $question_id ) != LP_QUESTION_CPT ) {
154 return new WP_Error( __( '<p>Op! The question does not exist</p>', 'learnpress' ) );
155 }
156
157 // ensure that user can create question
158 if ( ! current_user_can( 'edit_posts' ) ) {
159 return new WP_Error( __( '<p>Sorry! You don\'t have permission to duplicate this question</p>', 'learnpress' ) );
160 }
161
162 // origin question
163 $question = LP_Question::get_question( $question_id );
164
165 // duplicate question
166 $new_question_id = learn_press_duplicate_post( $question_id, array( 'post_status' => 'publish' ) );
167
168 if ( ! $new_question_id || is_wp_error( $new_question_id ) ) {
169 return new WP_Error( __( '<p>Sorry! Failed to duplicate question!</p>', 'learnpress' ) );
170 } else {
171
172 // init new question
173 $new_question = LP_Question::get_question( $new_question_id );
174
175 // set data
176 $new_question->set_type( $question->get_type() );
177 $new_question->set_data( 'answer_options', $question->get_data( 'answer_options' ) );
178
179 // trigger change user memorize question types
180 $user_id = get_current_user_id();
181 update_user_meta( $user_id, '_learn_press_memorize_question_types', $new_question->get_type() );
182
183 // duplicate answer
184 $this->duplicate_answer( $question_id, $new_question_id );
185
186 do_action( 'learn-press/after-duplicate', $question_id, $new_question_id, $args );
187
188 return $new_question_id;
189 }
190 }
191
192 /**
193 * Duplicate answer question.
194 *
195 * @param $question_id | origin question
196 * @param $new_question_id | new question
197 * @TODO tungnx: check duplicate question typ fill_in_blank - must clone row in learnpress_question_answermeta
198 */
199 public function duplicate_answer( $question_id, $new_question_id ) {
200 global $wpdb;
201
202 $query = $wpdb->prepare( " SELECT * FROM $wpdb->learnpress_question_answers WHERE question_id = %d", $question_id );
203 $answer_options = $wpdb->get_results( $query );
204
205 if ( $answer_options ) {
206 foreach ( $answer_options as $option ) {
207 $wpdb->insert(
208 $wpdb->learnpress_question_answers,
209 array(
210 'question_id' => $new_question_id,
211 'title' => ! empty( $option->title ) ? $option->title : '',
212 'value' => ! empty( $option->value ) ? $option->value : '',
213 'is_true' => ! empty( $option->is_true ) ? $option->is_true : '',
214 'order' => $option->order,
215 ),
216 array( '%d', '%s', '%s', '%s', '%s' )
217 );
218 }
219 }
220 }
221
222 /**
223 * @param LP_Question $question
224 *
225 * @return bool
226 * @throws Exception
227 */
228 public function load( &$question ) {
229 // question id
230 $id = $question->get_id();
231
232 if ( ! $id || ! in_array( learn_press_get_post_type( $id ), array( 'revision', LP_QUESTION_CPT ) ) ) {
233 throw new Exception( sprintf( __( 'Invalid question with ID "%d".', 'learnpress' ), $id ) );
234 }
235
236 $question->set_data_via_methods(
237 array(
238 'explanation' => get_post_meta( $id, '_lp_explanation', true ),
239 'hint' => get_post_meta( $id, '_lp_hint', true ),
240 )
241 );
242 // $this->_load_answer_options( $question );
243 $this->_load_meta( $question );
244
245 return true;
246 }
247
248 /**
249 * @param $question | LP_Question
250 */
251 protected function _load_meta( &$question ) {
252 $type = get_post_meta( $question->get_id(), '_lp_type', true );
253 if ( ! learn_press_is_support_question_type( $type ) ) {
254 $type = 'true_or_false';
255 }
256 // $question->set_type( $type );
257
258 $mark = $this->_get_question_mark( $question->get_id() );
259 $question->set_data_via_methods(
260 array(
261 'mark' => $mark,
262 )
263 );
264 }
265
266 public function _get_question_mark( $question_id ) {
267
268 // Recheck _lp_mark @tungnx
269 $mark = get_post_meta( $question_id, '_lp_mark', true ) ? get_post_meta( $question_id, '_lp_mark', true ) : 0;
270
271 $mark = abs( $mark );
272 if ( ! $mark ) {
273 $mark = apply_filters( 'learn-press/question/default-mark', 1, $question_id );
274 update_post_meta( $question_id, '_lp_mark', $mark );
275 }
276
277 return $mark;
278 }
279
280 /**
281 * Get the quizzes that a question is assigned to.
282 *
283 * @since 3.0.0
284 *
285 * @param $question_id
286 *
287 * @return null|object WP_Post
288 */
289 public function get_quiz( $question_id ) {
290 global $wpdb;
291
292 $query = $wpdb->prepare(
293 "
294 SELECT post.* FROM {$wpdb->posts} post
295 INNER JOIN {$wpdb->prefix}learnpress_quiz_questions quiz ON post.ID = quiz.quiz_id
296 WHERE quiz.question_id = %d
297 ",
298 $question_id
299 );
300
301 // get single row
302 return $wpdb->get_row( $query );
303 }
304
305 /**
306 * Change question type.
307 *
308 * @param $question LP_Question
309 * @param $new_type
310 *
311 * @return bool|int|LP_Question
312 */
313 public function change_question_type( $question, $new_type ) {
314 if ( learn_press_get_post_type( $question->get_id() ) != LP_QUESTION_CPT ) {
315 return false;
316 }
317
318 $question_id = $question->get_id();
319 $old_type = $question->get_type();
320
321 /*if ( $old_type == $new_type ) {
322 return false;
323 }*/
324
325 $answer_options = $question->get_data( 'answer_options' );
326
327 update_post_meta( $question_id, '_lp_type', $new_type );
328 $question->set_type( $new_type );
329
330 $new_question = LP_Question::get_question( $question_id, array( 'force' => true ) );
331
332 if ( $new_question ) {
333 $user_id = get_current_user_id();
334 update_user_meta( $user_id, '_learn_press_memorize_question_types', $new_type );
335
336 if ( $old_type == 'multi_choice' && $new_type == 'single_choice' ) {
337 $func = '_convert_answers_multi_choice_to_single_choice';
338 } elseif ( ( $old_type == 'multi_choice' || $old_type == 'single_choice' ) && 'true_or_false' == $new_type ) {
339 $func = '_convert_answers_to_true_or_false';
340 } else {
341 // for rest, clear answer data and create default
342 $func = '_convert_default_answers';
343 }
344
345 if ( is_callable( array( $this, $func ) ) ) {
346 $answer_options = call_user_func_array(
347 array( $this, $func ),
348 array(
349 $question,
350 $new_question,
351 $answer_options,
352 )
353 );
354 }
355
356 LP_Object_Cache::set( 'answer-options-' . $question_id, $answer_options, 'learn-press/questions' );
357 $new_question->set_data( 'answer_options', $answer_options );
358
359 return $new_question;
360 }
361
362 return false;
363 }
364
365 /**
366 * Update answer title
367 *
368 * @param $question_id
369 * @param $answer
370 *
371 * @return bool|false|int
372 */
373 public function update_answer_title( $question_id, $answer ) {
374 if ( get_post_type( $question_id ) !== LP_QUESTION_CPT ) {
375 return false;
376 }
377
378 global $wpdb;
379
380 // question data
381 $data = array(
382 'data' => apply_filters(
383 'learn-press/question/update-answer-data',
384 array(
385 'title' => $answer['title'],
386 'value' => isset( $answer['value'] ) ? $answer['value'] : '',
387 'is_true' => isset( $answer['is_true'] ) ? $answer['is_true'] : '',
388 )
389 ),
390 'where' => array(
391 'question_answer_id' => $answer['question_answer_id'],
392 'question_id' => $question_id,
393 ),
394 );
395
396 $update = $wpdb->update(
397 $wpdb->learnpress_question_answers,
398 $data['data'],
399 $data['where'],
400 array( '%s', '%s', '%s' ),
401 array( '%d', '%d' )
402 );
403
404 // Update for Fill in Blanks.
405 if ( ! empty( $answer['blanks'] ) ) {
406 $blanks = $answer['blanks'];
407
408 if ( is_array( $blanks ) ) {
409 $question = LP_Question::get_question( $question_id );
410
411 foreach ( $blanks as $id => $blank ) {
412 $question->_blanks[ $blank['id'] ] = $blank;
413 }
414 }
415
416 learn_press_update_question_answer_meta( $answer['question_answer_id'], '_blanks', $blanks );
417 }
418
419 return $update;
420 }
421
422 /**
423 * Update correct answer.
424 *
425 * @param $question LP_Question
426 * @param $correct
427 *
428 * @return bool | LP_Question
429 */
430 public function change_correct_answer( $question, $correct ) {
431 if ( learn_press_get_post_type( $question->get_id() ) != LP_QUESTION_CPT ) {
432 return false;
433 }
434
435 global $wpdb;
436
437 $question_id = $question->get_id();
438 $question_type = $question->get_type();
439 $question_answers = $question->get_data( 'answer_options' );
440
441 $db_args = $answers = array();
442
443 foreach ( $question_answers as $index => $answer ) {
444
445 $answer_data = array(
446 'title' => $answer['title'],
447 'value' => isset( $answer['value'] ) ? stripslashes( $answer['value'] ) : '',
448 'is_true' => isset( $answer['is_true'] ) ? $answer['is_true'] : '',
449 );
450
451 // update correct for select answer
452 if ( $answer['question_answer_id'] == $correct['question_answer_id'] ) {
453 $answer_data['is_true'] = $correct['is_true'];
454 } else {
455 // untrue all rest answer with True or false and Single choice question
456 if ( in_array( $question_type, array( 'true_or_false', 'single_choice' ) ) ) {
457 $answer_data['is_true'] = '';
458 }
459 }
460
461 // question answers data to set cache
462 $answers[ $index ] = array(
463 'question_answer_id' => $answer['question_answer_id'],
464 'question_id' => $question_id,
465 'order' => $answer['order'],
466 'title' => $answer_data['title'],
467 'value' => $answer_data['value'],
468 'is_true' => $answer_data['is_true'],
469 );
470
471 // new answers data
472 $db_args[ $index ] = array(
473 'data' => array(
474 'title' => $answer_data['title'],
475 'value' => $answer_data['value'],
476 'is_true' => $answer_data['is_true'],
477 ),
478 'where' => array(
479 'question_answer_id' => $answer['question_answer_id'],
480 'question_id' => $question_id,
481 'order' => $answer['order'],
482 ),
483 );
484 }
485
486 // update db
487 foreach ( $db_args as $id => $arg ) {
488 $wpdb->update(
489 $wpdb->learnpress_question_answers,
490 $arg['data'],
491 $arg['where'],
492 array( '%s', '%s', '%s' ),
493 array( '%d', '%d', '%d' )
494 );
495 }
496
497 // set question answer data
498 $question->set_data( 'answer_options', $answers );
499
500 return $question;
501 }
502
503 /**
504 * Sort answers.
505 *
506 * @since 3.0.0
507 *
508 * @param $question_id
509 * @param array $order
510 *
511 * @return bool|LP_Question
512 */
513 public function sort_answers( $question_id, $order = array() ) {
514
515 if ( learn_press_get_post_type( $question_id ) !== LP_QUESTION_CPT ) {
516 return false;
517 }
518
519 if ( $order ) {
520 $question = LP_Question::get_question( $question_id );
521 $answers = $question->get_data( 'answer_options' );
522
523 global $wpdb;
524 $new_answers = array();
525 foreach ( $order as $index => $answer_id ) {
526 $wpdb->update(
527 $wpdb->learnpress_question_answers,
528 array( 'order' => $index + 1 ),
529 array( 'question_answer_id' => $answer_id )
530 );
531
532 $new_answers[ $answer_id ] = $answers[ $answer_id ];
533 }
534
535 $question->set_data( 'answer_options', $new_answers );
536
537 return $question;
538
539 }
540
541 return false;
542 }
543
544 /**
545 * Delete question answer.
546 *
547 * @param $question_id
548 * @param $answer_id
549 * @param $force
550 *
551 * @return bool|false|int
552 */
553 public function delete_answer( $question_id, $answer_id, $force = false ) {
554
555 if ( learn_press_get_post_type( $question_id ) !== LP_QUESTION_CPT ) {
556 return false;
557 }
558
559 $question = LP_Question::get_question( $question_id );
560
561 // exist answer options
562 $answers = $question->get_data( 'answer_options' );
563
564 global $wpdb;
565
566 // delete all answer in question
567 if ( $force ) {
568 $delete = $wpdb->delete(
569 $wpdb->learnpress_question_answers,
570 array( 'question_id' => $question_id )
571 );
572
573 if ( $delete ) {
574 $question->set_data( 'answer_options', '' );
575 }
576 } else {
577 $delete = $wpdb->delete(
578 $wpdb->learnpress_question_answers,
579 array( 'question_answer_id' => $answer_id )
580 );
581 if ( $delete ) {
582 unset( $answers[ $answer_id ] );
583 $question->set_data( 'answer_options', $answers );
584
585 $this->sort_answers( $question_id, array_keys( $answers ) );
586 }
587 }
588
589 return $delete;
590 }
591
592 /**
593 * Add new answer.
594 *
595 * @param $question_id
596 * @param $new_answer
597 *
598 * @return bool|false|int
599 */
600 public function new_answer( $question_id, $new_answer ) {
601 if ( learn_press_get_post_type( $question_id ) !== LP_QUESTION_CPT ) {
602 return false;
603 }
604
605 $question = LP_Question::get_question( $question_id );
606
607 // exist answer options
608 $answers = $question->get_data( 'answer_options' );
609 // number answer options
610 $number = count( $answers );
611
612 if ( $question->get_type() === 'sorting_choice' ) {
613 $new_answer['is_true'] = 'yes';
614 }
615
616 global $wpdb;
617
618 $new_answer = wp_parse_args(
619 $new_answer,
620 array(
621 'question_id' => $question_id,
622 'title' => '',
623 'value' => learn_press_random_value(),
624 'is_true' => '',
625 'order' => $number + 1,
626 )
627 );
628
629 $insert = $wpdb->insert(
630 $wpdb->learnpress_question_answers,
631 $new_answer,
632 learn_press_map_columns_format(
633 $new_answer,
634 array(
635 'question_id' => '%d',
636 'title' => '%s',
637 'value' => '%s',
638 'is_true' => '%s',
639 'order' => '%d',
640 )
641 )
642 );
643
644 if ( $insert ) {
645 $new_answer['question_answer_id'] = $wpdb->insert_id;
646
647 if ( is_array( $answers ) ) {
648 $answers = array_merge( $answers, array( $new_answer ) );
649 } else {
650 $answers = array( $new_answer );
651 }
652 $question->set_data( 'answer_options', $answers );
653 }
654
655 return $wpdb->insert_id;
656 }
657
658
659 /**
660 * Convert answers to true or false question.
661 *
662 * @since 3.0.0
663 *
664 * @param $question
665 * @param $new_question
666 * @param $answers
667 *
668 * @return mixed
669 */
670 protected function _convert_answers_to_true_or_false( $question, $new_question, $answers ) {
671 if ( is_array( $answers ) ) {
672 // array answer ids
673 $answer_ids = array_keys( $answers );
674
675 if ( sizeof( $answers ) > 2 ) {
676 global $wpdb;
677
678 foreach ( $answers as $key => $answer ) {
679 if ( array_search( $key, $answer_ids ) > 1 ) {
680 $wpdb->delete(
681 $wpdb->learnpress_question_answers,
682 array( 'question_answer_id' => $answer['question_answer_id'] )
683 );
684 }
685 }
686 $answers = array_slice( $answers, 0, 2, true );
687 }
688
689 $correct = 0;
690 foreach ( $answers as $key => $answer ) {
691 if ( $answer['is_true'] == 'yes' ) {
692 $correct += 1;
693 }
694 }
695
696 if ( ! $correct ) {
697 // for single choice deletes all correct, set first option is correct
698 $answers[ $answer_ids[0] ]['is_true'] = 'yes';
699 } elseif ( $correct == 2 ) {
700 // for multiple choice keeps all correct, remove all correct and keep first option
701 $answers[ $answer_ids[1] ]['is_true'] = 'no';
702 }
703 }
704
705 return $answers;
706 }
707
708 /**
709 *
710 * Convert answers for multi choice to single choice question.
711 *
712 * @since 3.0.0
713 *
714 * @param $question
715 * @param $new_question
716 * @param $answers
717 *
718 * @return array
719 */
720 protected function _convert_answers_multi_choice_to_single_choice( $question, $new_question, $answers ) {
721 if ( is_array( $answers ) ) {
722 // array answer ids
723 $answer_ids = array_keys( $answers );
724
725 $correct = 0;
726 foreach ( $answers as $key => $answer ) {
727 if ( $answer['is_true'] == 'yes' ) {
728 $correct += 1;
729 }
730 }
731
732 if ( ! $correct ) {
733 $answers[ $answer_ids[0] ]['is_true'] = 'yes';
734 } elseif ( $correct > 1 ) {
735 // remove all correct and keep first option
736 $answers[ $answer_ids[0] ]['is_true'] = 'no';
737 }
738 }
739
740 return $answers;
741 }
742
743 /**
744 * Convert default answers.
745 *
746 * @param $question LP_Question
747 * @param $new_question LP_Question
748 * @param $answers
749 *
750 * @return array
751 */
752 protected function _convert_default_answers( $question, $new_question, $answers ) {
753 $question_id = $question->get_id();
754 // clear all exists answer
755 $this->clear( $question_id );
756 // set default answer
757 $answer_options = $new_question->get_default_answers();
758
759 if ( is_array( $answer_options ) ) {
760 foreach ( $answer_options as $index => $answer ) {
761 $insert = array(
762 'question_id' => $question_id,
763 'title' => $answer['title'],
764 'value' => isset( $answer['value'] ) ? stripslashes( $answer['value'] ) : '',
765 'is_true' => ( $answer['is_true'] == 'yes' ) ? $answer['is_true'] : '',
766 'order' => $index + 1,
767 );
768 $new_answers[] = $this->add_answer( $new_question->get_type(), $insert );
769 };
770
771 return $new_answers;
772 }
773
774 return $answers;
775 }
776
777 /**
778 * Add question answer.
779 *
780 * @since 3.0.0
781 *
782 * @param string $question_type
783 * @param array $args
784 *
785 * @return array|bool
786 */
787 public function add_answer( $question_type = '', $args = array() ) {
788 global $wpdb;
789
790 $question = LP_Question::get_question( $args['question_id'], array( 'type' => $question_type ) );
791
792 $wpdb->insert(
793 $wpdb->learnpress_question_answers,
794 array(
795 'question_id' => $args['question_id'],
796 'title' => $args['title'],
797 'value' => $args['value'],
798 'is_true' => $args['is_true'],
799 'order' => $args['order'],
800 ),
801 array( '%d', '%s', '%s', '%s', '%d' )
802 );
803
804 $question_answer_id = $wpdb->insert_id;
805 if ( $question_answer_id ) {
806 // update question answer option data
807 $answer_options = $question->get_data( 'answer_options' ) ? $question->get_data( 'answer_options' ) : array();
808
809 $new_answer_option_data = array(
810 'question_answer_id' => $question_answer_id,
811 'question_id' => $args['question_id'],
812 'order' => $args['order'],
813 'title' => $args['title'],
814 'value' => $args['value'],
815 'is_true' => $args['is_true'],
816 );
817
818 if ( ! $answer_options ) {
819 $question->set_data( 'answer_options', array( $new_answer_option_data ) );
820 } else {
821 $answer_options[] = $new_answer_option_data;
822 $question->set_data( 'answer_options', $answer_options );
823 }
824
825 return $new_answer_option_data;
826 } else {
827 return false;
828 }
829 }
830
831 /**
832 * Delete question answer.
833 *
834 * @since 3.0.0
835 *
836 * @param $question_id
837 * @param $answer_id
838 *
839 * @return bool|false|int
840 */
841 public function delete_question_answer( $question_id, $answer_id ) {
842 if ( learn_press_get_post_type( $question_id ) !== LP_QUESTION_CPT || ! $answer_id ) {
843 return false;
844 }
845
846 global $wpdb;
847
848 $result = $wpdb->delete(
849 $wpdb->learnpress_question_answers,
850 array( 'question_answer_id' => $answer_id )
851 );
852
853 return $result;
854 }
855
856 /**
857 * Delete all question answers.
858 *
859 * @param $question_id
860 *
861 * @return bool|WP_Error
862 */
863 public function clear( $question_id ) {
864
865 if ( ! learn_press_get_question( $question_id ) ) {
866 return $this->get_error( 'QUESTION_NOT_EXISTS' );
867 }
868
869 do_action( 'learn-press/before-clear-question', $question_id );
870
871 global $wpdb;
872 $wpdb->delete( $wpdb->learnpress_question_answers, array( 'question_id' => $question_id ) );
873
874 return true;
875 }
876
877 /**
878 * Load answer options for the question from database.
879 * Load from cache if data is already loaded into cache.
880 * Otherwise, load from database and put to cache.
881 *
882 * @param int $question_id
883 *
884 * @return array
885 */
886 protected function _read_answers( $question_id ) {
887 global $wpdb;
888
889 $query = $wpdb->prepare(
890 "
891 SELECT question_answer_id, title, value, is_true
892 FROM {$wpdb->prefix}learnpress_question_answers
893 WHERE question_id = %d
894 ORDER BY `order` ASC
895 ",
896 $question_id
897 );
898
899 $answer_options = array();
900
901 $results = $wpdb->get_results( $query );
902
903 if ( $results ) {
904 foreach ( $results as $k => $v ) {
905 $answer_option = array(
906 'question_answer_id' => absint( $v->question_answer_id ),
907 'title' => $v->title,
908 'value' => $v->value,
909 'is_true' => $v->is_true,
910 'order' => $k + 1, // Need???
911 );
912
913 $answer_options[ $v->question_answer_id ] = $answer_option;
914 }
915 }
916
917 return $answer_options;
918 }
919
920 /**
921 * Load answer options for the question from database.
922 * Load from cache if data is already loaded into cache.
923 * Otherwise, load from database and put to cache.
924 *
925 * @param $question LP_Question
926 */
927 protected function _load_answer_options( &$question ) {
928 $id = $question->get_id();
929 $answer_options = LP_Object_Cache::get( 'answer-options-' . $id, 'lp-questions' );
930
931 if ( false === $answer_options ) {
932 global $wpdb;
933 $query = $wpdb->prepare(
934 "
935 SELECT *
936 FROM {$wpdb->prefix}learnpress_question_answers
937 WHERE question_id = %d
938 ORDER BY `order` ASC
939 ",
940 $id
941 );
942
943 $answer_options = $this->load_answer_options( $question->get_id() );
944 }
945 $answer_options = apply_filters( 'learn-press/question/load-answer-options', $answer_options, $id );
946
947 if ( ! empty( $answer_options['question_answer_id'] ) && $answer_options['question_answer_id'] > 0 ) {
948 $this->_load_answer_option_meta( $answer_options );
949 }
950 LP_Object_Cache::set( 'answer-options-' . $id, $answer_options, 'lp-questions' );
951
952 $question->set_data( 'answer_options', $answer_options );
953 }
954
955 /**
956 * Load question answers
957 *
958 * @updated 3.1.0
959 *
960 * @param array|int $question_id
961 *
962 * @return array|bool
963 */
964 public function load_answer_options( $question_id ) {
965 global $wpdb;
966
967 $return_id = 0;
968
969 if ( is_array( $question_id ) ) {
970
971 foreach ( $question_id as $q_id ) {
972 $this->load_answer_options( $q_id );
973 if ( ! $return_id ) {
974 $return_id = $q_id;
975 }
976 }
977 $question_id = $return_id;
978 }
979
980 $answer_options = LP_Object_Cache::get( 'question-' . $question_id, 'question-answers' );
981
982 if ( false === $answer_options ) {
983 $answer_options = $this->_read_answers( $question_id );
984 LP_Object_Cache::set( 'question-' . $question_id, $answer_options, 'question-answers' );
985 }
986
987 return $answer_options;
988 }
989
990 /**
991 * Load meta data for answer options.
992 *
993 * @param array $answer_options
994 *
995 * @return mixed;
996 */
997 protected function _load_answer_option_meta( &$answer_options ) {
998 if ( ! $answer_options ) {
999 return false;
1000 }
1001
1002 $answer_option_ids = wp_list_pluck( $answer_options, 'question_answer_id' );
1003 $format = array_fill( 0, sizeof( $answer_option_ids ), '%d' );
1004 $query = $wpdb->prepare(
1005 "
1006 SELECT *
1007 FROM {$wpdb->prefix}learnpress_question_answermeta
1008 WHERE learnpress_question_answer_id IN(" . join( ', ', $format ) . ')
1009 ',
1010 $answer_option_ids
1011 );
1012
1013 $metas = $wpdb->get_results( $query );
1014
1015 if ( $metas ) {
1016 foreach ( $metas as $meta ) {
1017 $key = $meta->meta_key;
1018 $option_key = $meta->learnpress_question_answer_id;
1019 if ( ! empty( $answer_options[ $option_key ] ) ) {
1020 if ( $key == 'checked' ) {
1021 $key = 'is_true';
1022 }
1023 $answer_options[ $option_key ][ $key ] = $meta->meta_value;
1024 }
1025 }
1026 }
1027
1028 return true;
1029 }
1030
1031 public function add_meta( &$object, $meta ) {
1032 // TODO: Implement add_meta() method.
1033 }
1034
1035 public function delete_meta( &$object, $meta ) {
1036 // TODO: Implement delete_meta() method.
1037 }
1038
1039 public function read_meta( &$object ) {
1040 // TODO: Implement read_meta() method.
1041 }
1042
1043 public function update_meta( &$object, $meta ) {
1044 // TODO: Implement update_meta() method.
1045 }
1046 }
1047 }
1048