PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
learnpress / inc / curds / class-lp-question-curd.php

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

992 lines 26.2 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' => __( 'The 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 // add question to quiz
89 if ( ! empty( $args['quiz_id'] ) ) {
90 $quiz_curd = new LP_Quiz_CURD();
91 $quiz_curd->add_question( $args['quiz_id'], $question_id, $args['order'] );
92 }
93
94 if ( $args['create_answers'] ) {
95 $question->create_default_answers();
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( 'lp/question/curd/duplicate/err', 'Oops! ID not found' );
151 }
152
153 if ( learn_press_get_post_type( $question_id ) != LP_QUESTION_CPT ) {
154 return new WP_Error( 'lp/question/curd/duplicate/err', 'Op! The question does not exist' );
155 }
156
157 // ensure that user can create question
158 if ( ! current_user_can( 'edit_posts' ) ) {
159 return new WP_Error( 'lp/question/curd/duplicate/err', 'Sorry! You do not have permission to duplicate this question' );
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( 'lp/question/curd/duplicate/err', 'Sorry! Failed to duplicate the question!' );
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/item/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 $question_id_clone | new question
197 * @version 3.0.1
198 * @since 1.0.1
199 */
200 public function duplicate_answer( $question_id, $question_id_clone ) {
201 $lp_db = LP_Database::getInstance();
202 $lp_question_answers_db = LP_Question_Answers_DB::getInstance();
203
204 try {
205 // Get all answer of question
206 $filter_get_answer_options = new LP_Question_Answers_Filter();
207 $filter_get_answer_options->question_ids = [ $question_id ];
208 $answer_options = $lp_question_answers_db->get_question_answers( $filter_get_answer_options );
209
210 if ( $answer_options ) {
211 foreach ( $answer_options as $answer_option ) {
212 $question_answer_id = $answer_option->question_answer_id;
213
214 // Insert new question_answer
215 $insert_question_answer_rs = $lp_db->wpdb->insert(
216 $lp_db->tb_lp_question_answers,
217 array(
218 'question_id' => $question_id_clone,
219 'title' => ! empty( $answer_option->title ) ? $answer_option->title : '',
220 'value' => ! empty( $answer_option->value ) ? $answer_option->value : '',
221 'is_true' => ! empty( $answer_option->is_true ) ? $answer_option->is_true : '',
222 'order' => $answer_option->order,
223 ),
224 array( '%d', '%s', '%s', '%s', '%s' )
225 );
226
227 if ( ! $insert_question_answer_rs ) {
228 throw new Exception( __( 'Failed to duplicate answer', 'learnpress' ) );
229 }
230
231 // Get question_answer_id have just inserted
232 $filter_question_answer_id = new LP_Question_Answers_Filter();
233 $filter_question_answer_id->only_fields = [ 'MAX(question_answer_id)' ];
234 $filter_question_answer_id->question_ids = [ $question_id_clone ];
235 $filter_question_answer_id->return_string_query = true;
236 $question_answer_id_query = $lp_question_answers_db->get_question_answers( $filter_question_answer_id );
237 $question_answer_id_new = (int) $lp_question_answers_db->wpdb->get_var( $question_answer_id_query );
238
239 if ( ! $question_answer_id_new ) {
240 throw new Exception( __( 'Failed to duplicate answer', 'learnpress' ) );
241 }
242
243 // Duplicate answer meta
244 // Get answer meta by question_answer_id
245 $filter_get = new LP_Question_Answermeta_Filter();
246 $filter_get->collection = $lp_db->tb_lp_question_answermeta;
247 $filter_get->collection_alias = 'qam';
248 $filter_get->field_count = 'meta_id';
249 $filter_get->limit = -1;
250 $filter_get->where[] = $lp_db->wpdb->prepare( 'AND qam.learnpress_question_answer_id = %d', $question_answer_id );
251 $filter_get->fields = $lp_db->get_cols_of_table( $lp_db->tb_lp_question_answermeta );
252 $question_answermeta_rs = $lp_db->execute( $filter_get );
253
254 foreach ( $question_answermeta_rs as $question_answermeta ) {
255 $lp_db->wpdb->insert(
256 $lp_db->tb_lp_question_answermeta,
257 array(
258 'learnpress_question_answer_id' => $question_answer_id_new,
259 'meta_key' => $question_answermeta->meta_key,
260 'meta_value' => $question_answermeta->meta_value,
261 ),
262 array( '%d', '%s', '%s' )
263 );
264 }
265 }
266 }
267 } catch ( Throwable $e ) {
268 error_log( $e->getMessage() );
269 }
270 }
271
272 /**
273 * @param LP_Question $question
274 *
275 * @return bool
276 * @throws Exception
277 */
278 public function load( &$question ) {
279 // question id
280 $id = $question->get_id();
281
282 if ( ! $id || ! in_array( learn_press_get_post_type( $id ), array( 'revision', LP_QUESTION_CPT ) ) ) {
283 throw new Exception( sprintf( __( 'Invalid question with ID "%d".', 'learnpress' ), $id ) );
284 }
285
286 $question->set_explanation( get_post_meta( $id, '_lp_explanation', true ) );
287 $question->set_hint( get_post_meta( $id, '_lp_hint', true ) );
288 // $this->_load_answer_options( $question );
289 $this->_load_meta( $question );
290
291 return true;
292 }
293
294 /**
295 * @param $question | LP_Question
296 */
297 protected function _load_meta( &$question ) {
298 $type = get_post_meta( $question->get_id(), '_lp_type', true );
299 if ( ! learn_press_is_support_question_type( $type ) ) {
300 $type = 'true_or_false';
301 }
302 // $question->set_type( $type );
303
304 $mark = $this->_get_question_mark( $question->get_id() );
305 $question->set_mark( $mark );
306 }
307
308 public function _get_question_mark( $question_id ) {
309
310 // Recheck _lp_mark @tungnx
311 $mark = get_post_meta( $question_id, '_lp_mark', true ) ? get_post_meta( $question_id, '_lp_mark', true ) : 0;
312
313 $mark = abs( $mark );
314 if ( ! $mark ) {
315 $mark = apply_filters( 'learn-press/question/default-mark', 1, $question_id );
316 update_post_meta( $question_id, '_lp_mark', $mark );
317 }
318
319 return $mark;
320 }
321
322 /**
323 * Get the quizzes that a question is assigned to.
324 *
325 * @since 3.0.0
326 *
327 * @param $question_id
328 *
329 * @return null|object WP_Post
330 */
331 public function get_quiz( $question_id ) {
332 global $wpdb;
333
334 $query = $wpdb->prepare(
335 "
336 SELECT post.* FROM {$wpdb->posts} post
337 INNER JOIN {$wpdb->prefix}learnpress_quiz_questions quiz ON post.ID = quiz.quiz_id
338 WHERE quiz.question_id = %d
339 ",
340 $question_id
341 );
342
343 // get single row
344 return $wpdb->get_row( $query );
345 }
346
347 /**
348 * Change question type.
349 *
350 * @param $question LP_Question
351 * @param $new_type
352 *
353 * @return false|void
354 * @since 3.0.0
355 * @version 1.0.1
356 */
357 public function change_question_type( &$question, $new_type ) {
358 if ( learn_press_get_post_type( $question->get_id() ) != LP_QUESTION_CPT ) {
359 return false;
360 }
361
362 $question_id = $question->get_id();
363
364 // If not new Question or not change type return
365 $old_type = get_post_meta( $question_id, '_lp_type', true );
366 if ( ! empty( $old_type ) && $old_type === $new_type ) {
367 return;
368 }
369
370 $answer_options = $question->get_data( 'answer_options' );
371 update_post_meta( $question_id, '_lp_type', $new_type );
372 $question->set_type( $new_type );
373
374 $new_question = LP_Question::get_question( $question_id, array( 'force' => true ) );
375
376 if ( $new_question ) {
377 $user_id = get_current_user_id();
378 update_user_meta( $user_id, '_learn_press_memorize_question_types', $new_type );
379
380 if ( $old_type == 'multi_choice' && $new_type == 'single_choice' ) {
381 $func = '_convert_answers_multi_choice_to_single_choice';
382 } elseif ( ( $old_type == 'multi_choice' || $old_type == 'single_choice' ) && 'true_or_false' == $new_type ) {
383 $func = '_convert_answers_to_true_or_false';
384 } else {
385 // for rest, clear answer data and create default
386 $func = '_convert_default_answers';
387 }
388
389 if ( is_callable( array( $this, $func ) ) ) {
390 $answer_options = call_user_func_array(
391 array( $this, $func ),
392 array(
393 $question,
394 $new_question,
395 $answer_options,
396 )
397 );
398 }
399
400 LP_Object_Cache::set( 'answer-options-' . $question_id, $answer_options, 'learn-press/questions' );
401 $new_question->set_data( 'answer_options', $answer_options );
402
403 $question = $new_question;
404 }
405 }
406
407 /**
408 * Update answer title
409 *
410 * @param $question_id
411 * @param $answer
412 *
413 * @return bool|false|int
414 */
415 public function update_answer_title( $question_id, $answer ) {
416 if ( get_post_type( $question_id ) !== LP_QUESTION_CPT ) {
417 return false;
418 }
419
420 global $wpdb;
421
422 // question data
423 $data = array(
424 'data' => apply_filters(
425 'learn-press/question/update-answer-data',
426 array(
427 'title' => $answer['title'],
428 'value' => $answer['value'] ?? '',
429 'is_true' => $answer['is_true'] ?? '',
430 )
431 ),
432 'where' => array(
433 'question_answer_id' => $answer['question_answer_id'],
434 'question_id' => $question_id,
435 ),
436 );
437
438 $update = $wpdb->update(
439 $wpdb->learnpress_question_answers,
440 $data['data'],
441 $data['where'],
442 array( '%s', '%s', '%s' ),
443 array( '%d', '%d' )
444 );
445
446 // Update for Fill in Blanks.
447 if ( ! empty( $answer['blanks'] ) ) {
448 $blanks = $answer['blanks'];
449
450 /*if ( is_array( $blanks ) ) {
451 $question = LP_Question::get_question( $question_id );
452
453 foreach ( $blanks as $id => $blank ) {
454 $question->_blanks[ $blank['id'] ] = $blank;
455 }
456 }*/
457
458 learn_press_update_question_answer_meta( $answer['question_answer_id'], '_blanks', $blanks );
459 }
460
461 return $update;
462 }
463
464 /**
465 * Update correct answer.
466 *
467 * @param $question LP_Question
468 * @param $correct
469 *
470 * @return bool | LP_Question
471 */
472 public function change_correct_answer( $question, $correct ) {
473 if ( learn_press_get_post_type( $question->get_id() ) != LP_QUESTION_CPT ) {
474 return false;
475 }
476
477 global $wpdb;
478
479 $question_id = $question->get_id();
480 $question_type = $question->get_type();
481 $question_answers = $question->get_data( 'answer_options' );
482
483 $db_args = $answers = array();
484
485 foreach ( $question_answers as $index => $answer ) {
486
487 $answer_data = array(
488 'title' => $answer['title'],
489 'value' => isset( $answer['value'] ) ? stripslashes( $answer['value'] ) : '',
490 'is_true' => isset( $answer['is_true'] ) ? $answer['is_true'] : '',
491 );
492
493 // update correct for select answer
494 if ( $answer['question_answer_id'] == $correct['question_answer_id'] ) {
495 $answer_data['is_true'] = $correct['is_true'];
496 } else {
497 // untrue all rest answer with True or false and Single choice question
498 if ( in_array( $question_type, array( 'true_or_false', 'single_choice' ) ) ) {
499 $answer_data['is_true'] = '';
500 }
501 }
502
503 // question answers data to set cache
504 $answers[ $index ] = array(
505 'question_answer_id' => $answer['question_answer_id'],
506 'question_id' => $question_id,
507 'order' => $answer['order'],
508 'title' => $answer_data['title'],
509 'value' => $answer_data['value'],
510 'is_true' => $answer_data['is_true'],
511 );
512
513 // new answers data
514 $db_args[ $index ] = array(
515 'data' => array(
516 'title' => $answer_data['title'],
517 'value' => $answer_data['value'],
518 'is_true' => $answer_data['is_true'],
519 ),
520 'where' => array(
521 'question_answer_id' => $answer['question_answer_id'],
522 'question_id' => $question_id,
523 'order' => $answer['order'],
524 ),
525 );
526 }
527
528 // update db
529 foreach ( $db_args as $id => $arg ) {
530 $wpdb->update(
531 $wpdb->learnpress_question_answers,
532 $arg['data'],
533 $arg['where'],
534 array( '%s', '%s', '%s' ),
535 array( '%d', '%d', '%d' )
536 );
537 }
538
539 // set question answer data
540 $question->set_data( 'answer_options', $answers );
541
542 return $question;
543 }
544
545 /**
546 * Sort answers.
547 *
548 * @since 3.0.0
549 *
550 * @param $question_id
551 * @param array $order
552 *
553 * @return bool|LP_Question
554 */
555 public function sort_answers( $question_id, $order = array() ) {
556
557 if ( learn_press_get_post_type( $question_id ) !== LP_QUESTION_CPT ) {
558 return false;
559 }
560
561 if ( $order ) {
562 $question = LP_Question::get_question( $question_id );
563 $answers = $question->get_data( 'answer_options' );
564
565 global $wpdb;
566 $new_answers = array();
567 foreach ( $order as $index => $answer_id ) {
568 $wpdb->update(
569 $wpdb->learnpress_question_answers,
570 array( 'order' => $index + 1 ),
571 array( 'question_answer_id' => $answer_id )
572 );
573
574 $new_answers[ $answer_id ] = $answers[ $answer_id ];
575 }
576
577 $question->set_data( 'answer_options', $new_answers );
578
579 return $question;
580
581 }
582
583 return false;
584 }
585
586 /**
587 * Delete question answer.
588 *
589 * @param $question_id
590 * @param $answer_id
591 * @param $force
592 *
593 * @return bool|false|int
594 */
595 public function delete_answer( $question_id, $answer_id, $force = false ) {
596
597 if ( learn_press_get_post_type( $question_id ) !== LP_QUESTION_CPT ) {
598 return false;
599 }
600
601 $question = LP_Question::get_question( $question_id );
602
603 // exist answer options
604 $answers = $question->get_data( 'answer_options' );
605
606 global $wpdb;
607
608 // Delete answer meta
609 $wpdb->delete(
610 $wpdb->learnpress_question_answermeta,
611 array( 'learnpress_question_answer_id' => $answer_id )
612 );
613
614 $delete = $wpdb->delete(
615 $wpdb->learnpress_question_answers,
616 array( 'question_answer_id' => $answer_id )
617 );
618 if ( $delete ) {
619 unset( $answers[ $answer_id ] );
620 $question->set_data( 'answer_options', $answers );
621
622 $this->sort_answers( $question_id, array_keys( $answers ) );
623 }
624
625 return $delete;
626 }
627
628 /**
629 * Add new answer.
630 *
631 * @param $question_id
632 * @param $new_answer
633 *
634 * @return bool|false|int
635 */
636 public function new_answer( $question_id, $new_answer ) {
637 if ( learn_press_get_post_type( $question_id ) !== LP_QUESTION_CPT ) {
638 return false;
639 }
640
641 $question = LP_Question::get_question( $question_id );
642
643 // exist answer options
644 $answers = $question->get_data( 'answer_options' );
645 // number answer options
646 $number = count( $answers );
647
648 if ( $question->get_type() === 'sorting_choice' ) {
649 $new_answer['is_true'] = 'yes';
650 }
651
652 global $wpdb;
653
654 $new_answer = wp_parse_args(
655 $new_answer,
656 array(
657 'question_id' => $question_id,
658 'title' => '',
659 'value' => learn_press_random_value(),
660 'is_true' => '',
661 'order' => $number + 1,
662 )
663 );
664
665 $insert = $wpdb->insert(
666 $wpdb->learnpress_question_answers,
667 $new_answer,
668 learn_press_map_columns_format(
669 $new_answer,
670 array(
671 'question_id' => '%d',
672 'title' => '%s',
673 'value' => '%s',
674 'is_true' => '%s',
675 'order' => '%d',
676 )
677 )
678 );
679
680 if ( $insert ) {
681 $new_answer['question_answer_id'] = $wpdb->insert_id;
682
683 if ( is_array( $answers ) ) {
684 $answers = array_merge( $answers, array( $new_answer ) );
685 } else {
686 $answers = array( $new_answer );
687 }
688 $question->set_data( 'answer_options', $answers );
689 }
690
691 return $wpdb->insert_id;
692 }
693
694
695 /**
696 * Convert answers to true or false question.
697 *
698 * @since 3.0.0
699 *
700 * @param $question
701 * @param $new_question
702 * @param $answers
703 *
704 * @return mixed
705 */
706 protected function _convert_answers_to_true_or_false( $question, $new_question, $answers ) {
707 if ( is_array( $answers ) ) {
708 // array answer ids
709 $answer_ids = array_keys( $answers );
710
711 if ( sizeof( $answers ) > 2 ) {
712 global $wpdb;
713
714 foreach ( $answers as $key => $answer ) {
715 if ( array_search( $key, $answer_ids ) > 1 ) {
716 $wpdb->delete(
717 $wpdb->learnpress_question_answers,
718 array( 'question_answer_id' => $answer['question_answer_id'] )
719 );
720 }
721 }
722 $answers = array_slice( $answers, 0, 2, true );
723 }
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 // for single choice deletes all correct, set first option is correct
734 $answers[ $answer_ids[0] ]['is_true'] = 'yes';
735 } elseif ( $correct == 2 ) {
736 // for multiple choice keeps all correct, remove all correct and keep first option
737 $answers[ $answer_ids[1] ]['is_true'] = 'no';
738 }
739 }
740
741 return $answers;
742 }
743
744 /**
745 *
746 * Convert answers for multi choice to single choice question.
747 *
748 * @since 3.0.0
749 *
750 * @param $question
751 * @param $new_question
752 * @param $answers
753 *
754 * @return array
755 */
756 protected function _convert_answers_multi_choice_to_single_choice( $question, $new_question, $answers ) {
757 if ( is_array( $answers ) ) {
758 // array answer ids
759 $answer_ids = array_keys( $answers );
760
761 $correct = 0;
762 foreach ( $answers as $key => $answer ) {
763 if ( $answer['is_true'] == 'yes' ) {
764 $correct += 1;
765 }
766 }
767
768 if ( ! $correct ) {
769 $answers[ $answer_ids[0] ]['is_true'] = 'yes';
770 } elseif ( $correct > 1 ) {
771 // remove all correct and keep first option
772 $answers[ $answer_ids[0] ]['is_true'] = 'no';
773 }
774 }
775
776 return $answers;
777 }
778
779 /**
780 * Convert default answers.
781 *
782 * @param $question LP_Question
783 * @param $new_question LP_Question
784 * @param $answers
785 *
786 * @return array
787 */
788 protected function _convert_default_answers( $question, $new_question, $answers ) {
789 $question_id = $question->get_id();
790 // clear all exists answer
791 $this->clear( $question_id );
792 // set default answer
793 $answer_options = $new_question->get_default_answers();
794
795 if ( is_array( $answer_options ) ) {
796 foreach ( $answer_options as $index => $answer ) {
797 $insert = array(
798 'question_id' => $question_id,
799 'title' => $answer['title'],
800 'value' => isset( $answer['value'] ) ? stripslashes( $answer['value'] ) : '',
801 'is_true' => ( $answer['is_true'] == 'yes' ) ? $answer['is_true'] : '',
802 'order' => $index + 1,
803 );
804 $new_answers[] = $this->add_answer( $new_question->get_type(), $insert );
805 };
806
807 return $new_answers;
808 }
809
810 return $answers;
811 }
812
813 /**
814 * Add question answer.
815 *
816 * @since 3.0.0
817 *
818 * @param string $question_type
819 * @param array $args
820 *
821 * @return array|bool
822 */
823 public function add_answer( $question_type = '', $args = array() ) {
824 global $wpdb;
825
826 $question = LP_Question::get_question( $args['question_id'], array( 'type' => $question_type ) );
827
828 $wpdb->insert(
829 $wpdb->learnpress_question_answers,
830 array(
831 'question_id' => $args['question_id'],
832 'title' => $args['title'],
833 'value' => $args['value'],
834 'is_true' => $args['is_true'],
835 'order' => $args['order'],
836 ),
837 array( '%d', '%s', '%s', '%s', '%d' )
838 );
839
840 $question_answer_id = $wpdb->insert_id;
841 if ( $question_answer_id ) {
842 // update question answer option data
843 $answer_options = $question->get_data( 'answer_options' ) ? $question->get_data( 'answer_options' ) : array();
844
845 $new_answer_option_data = array(
846 'question_answer_id' => $question_answer_id,
847 'question_id' => $args['question_id'],
848 'order' => $args['order'],
849 'title' => $args['title'],
850 'value' => $args['value'],
851 'is_true' => $args['is_true'],
852 );
853
854 if ( ! $answer_options ) {
855 $question->set_data( 'answer_options', array( $new_answer_option_data ) );
856 } else {
857 $answer_options[] = $new_answer_option_data;
858 $question->set_data( 'answer_options', $answer_options );
859 }
860
861 return $new_answer_option_data;
862 } else {
863 return false;
864 }
865 }
866
867 /**
868 * Delete question answer.
869 *
870 * @since 3.0.0
871 *
872 * @param $question_id
873 * @param $answer_id
874 *
875 * @return bool|false|int
876 */
877 public function delete_question_answer( $question_id, $answer_id ) {
878 if ( learn_press_get_post_type( $question_id ) !== LP_QUESTION_CPT || ! $answer_id ) {
879 return false;
880 }
881
882 global $wpdb;
883
884 $result = $wpdb->delete(
885 $wpdb->learnpress_question_answers,
886 array( 'question_answer_id' => $answer_id )
887 );
888
889 return $result;
890 }
891
892 /**
893 * Delete all question answers.
894 *
895 * @param $question_id
896 *
897 * @return bool|WP_Error
898 */
899 public function clear( $question_id ) {
900
901 if ( ! learn_press_get_question( $question_id ) ) {
902 return $this->get_error( 'QUESTION_NOT_EXISTS' );
903 }
904
905 do_action( 'learn-press/before-clear-question', $question_id );
906
907 global $wpdb;
908 $wpdb->delete( $wpdb->learnpress_question_answers, array( 'question_id' => $question_id ) );
909
910 return true;
911 }
912
913 /**
914 * Load answer options for the question from database.
915 * Load from cache if data is already loaded into cache.
916 * Otherwise, load from database and put to cache.
917 *
918 * @param int $question_id
919 *
920 * @return array
921 */
922 protected function _read_answers( $question_id ) {
923 global $wpdb;
924
925 $query = $wpdb->prepare(
926 "
927 SELECT question_answer_id, title, value, is_true
928 FROM {$wpdb->prefix}learnpress_question_answers
929 WHERE question_id = %d
930 ORDER BY `order` ASC
931 ",
932 $question_id
933 );
934
935 $answer_options = array();
936
937 $results = $wpdb->get_results( $query );
938
939 if ( $results ) {
940 foreach ( $results as $k => $v ) {
941 $answer_option = array(
942 'question_answer_id' => absint( $v->question_answer_id ),
943 'title' => $v->title,
944 'value' => $v->value,
945 'is_true' => $v->is_true,
946 'order' => $k + 1, // Need???
947 );
948
949 $answer_options[ $v->question_answer_id ] = $answer_option;
950 }
951 }
952
953 return $answer_options;
954 }
955
956 /**
957 * Load question answers
958 *
959 * @updated 3.1.0
960 *
961 * @param array|int $question_id
962 *
963 * @return array|bool
964 */
965 public function load_answer_options( $question_id ) {
966 global $wpdb;
967
968 $return_id = 0;
969
970 if ( is_array( $question_id ) ) {
971
972 foreach ( $question_id as $q_id ) {
973 $this->load_answer_options( $q_id );
974 if ( ! $return_id ) {
975 $return_id = $q_id;
976 }
977 }
978 $question_id = $return_id;
979 }
980
981 $answer_options = LP_Object_Cache::get( 'question-' . $question_id, 'question-answers' );
982
983 if ( false === $answer_options ) {
984 $answer_options = $this->_read_answers( $question_id );
985 LP_Object_Cache::set( 'question-' . $question_id, $answer_options, 'question-answers' );
986 }
987
988 return $answer_options;
989 }
990 }
991 }
992