PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.3.9.1
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.3.9.1
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.3.9.1, at inc/curds/class-lp-question-curd.php

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