PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.1.7.3
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.1.7.3
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 / quiz / class-lp-quiz.php

class-lp-quiz.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.1.7.3, at inc/quiz/class-lp-quiz.php

1,087 lines 24.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class LP_Quiz.
4 *
5 * @author ThimPress
6 * @package LearnPress/Classes
7 * @version 3.0.0
8 */
9
10 defined( 'ABSPATH' ) || exit();
11
12 if ( ! class_exists( 'LP_Quiz' ) ) {
13
14 /**
15 * Class LP_Quiz
16 */
17 class LP_Quiz extends LP_Course_Item implements ArrayAccess {
18
19
20 /**
21 * @var array
22 *
23 * @deprecated
24 */
25 protected static $_meta = array();
26
27 /**
28 * @var string
29 */
30 protected $_item_type = LP_QUIZ_CPT;
31
32 /**
33 * @var array
34 */
35 protected $_questions = array();
36
37 /**
38 * @var array
39 */
40 protected $_data = array(
41 // 'show_result' => 'no',
42 'passing_grade_type' => '',
43 'passing_grade' => 0,
44 // 'show_check_answer' => 'no',
45 // 'count_check_answer' => 0,
46 // 'show_hint' => 'no',
47 // 'count_hint' => 0,
48 // 'archive_history' => 'no',
49 // 'show_hide_question' => 'yes',
50 // 'preview' => 'no',
51 // 'minus_points' => 0,
52 'minus_skip_questions' => 'no',
53
54 'negative_marking' => 'no',
55 'instant_check' => 'no',
56 'retake_count' => 0,
57 'show_correct_review' => 'yes',
58 );
59
60 /**
61 * @var int
62 */
63 protected static $_loaded = 0;
64
65 /**
66 * Constructor gets the post object and sets the ID for the loaded course.
67 *
68 * @param mixed $the_quiz
69 * @param mixed $args
70 */
71 public function __construct( $the_quiz, $args = array() ) {
72 $this->_curd = new LP_Quiz_CURD();
73
74 if ( is_numeric( $the_quiz ) && $the_quiz > 0 ) {
75 $this->set_id( $the_quiz );
76 } elseif ( $the_quiz instanceof self ) {
77 $this->set_id( absint( $the_quiz->get_id() ) );
78 } elseif ( ! empty( $the_quiz->ID ) ) {
79 $this->set_id( absint( $the_quiz->ID ) );
80 }
81 if ( $this->get_id() > 0 ) {
82 $this->load();
83 }
84
85 self::$_loaded ++;
86 if ( self::$_loaded == 1 ) {
87 add_filter( 'debug_data', array( __CLASS__, 'log' ) );
88 }
89 }
90
91 /**
92 * Log debug data.
93 *
94 * @since 3.0.0
95 *
96 * @param $data
97 *
98 * @return array
99 */
100 public static function log( $data ) {
101 $data[] = __CLASS__ . '( ' . self::$_loaded . ' )';
102
103 return $data;
104 }
105
106 /**
107 * @param string $context
108 *
109 * @return string
110 */
111 public function get_heading_title( $context = '' ) {
112 return $this->get_title( $context );
113 }
114
115 /**
116 * Load quiz data
117 */
118 public function load() {
119 $this->_curd->load( $this );
120 }
121
122 /**
123 * Get default quiz meta.
124 *
125 * @since 3.0.0
126 *
127 * @return mixed
128 */
129 public static function get_default_meta() {
130 $meta = array(
131 'review' => 'no',
132 'duration' => '10 minute',
133 'passing_grade' => 80,
134 'negative_marking' => 'no',
135 'instant_check' => 'no',
136 'retake_count' => '0',
137 'pagination' => 1,
138 'show_correct_review' => 'yes',
139 );
140
141 return apply_filters( 'learn-press/quiz/default-meta', $meta );
142 }
143
144 /**
145 * Save quiz data.
146 *
147 * @return mixed
148 *
149 * @throws Exception
150 */
151 public function save() {
152 if ( $this->get_id() ) {
153 $return = $this->_curd->update( $this );
154 } else {
155 $return = $this->_curd->create( $this );
156 }
157
158 return $return;
159 }
160
161 public function get_negative_marking() {
162 return $this->get_data( 'negative_marking' ) === 'yes';
163 }
164
165 public function set_negative_marking( $set ) {
166 $this->_set_data( 'negative_marking', ! learn_press_is_negative_value( $set ) ? 'yes' : 'no' );
167 }
168
169 public function get_show_correct_review() {
170 return $this->get_data( 'show_correct_review' ) === 'yes';
171 }
172
173 public function set_show_correct_review( $set ) {
174 $this->_set_data( 'show_correct_review', $set );
175 }
176
177 public function get_instant_check() {
178 return $this->get_data( 'instant_check' ) === 'yes';
179 }
180
181 public function set_instant_check( $set ) {
182 $this->_set_data( 'instant_check', ! learn_press_is_negative_value( $set ) ? 'yes' : 'no' );
183 }
184
185 public function set_retake_count( $count ) {
186 $this->_set_data( 'retake_count', $count );
187 }
188
189 public function get_retake_count() {
190 return $this->get_data( 'retake_count' );
191 }
192
193 public function get_pagination() {
194 return ( $n = $this->get_data( 'pagination' ) ) > 1 ? $n : 0;
195 }
196
197 public function set_pagination( $set ) {
198 $this->_set_data( 'pagination', absint( $set ) );
199 }
200
201 /**
202 * @deprecated
203 *
204 * @param $show_result
205 */
206 public function set_show_result( $show_result ) {
207 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
208
209 $this->_set_data( 'show_result', $show_result );
210 }
211
212 /**
213 * @deprecated
214 *
215 * @return array|mixed
216 */
217 public function get_show_result() {
218
219 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
220
221 return $this->get_data( 'show_result' ) === 'yes';
222 }
223
224 /**
225 *
226 * @param $review_questions
227 */
228 public function set_review_questions( $review_questions ) {
229
230 $this->_set_data( 'review_questions', $review_questions );
231 }
232
233 /**
234 * Enable review quiz
235 *
236 * @return bool
237 */
238 public function get_review_questions(): bool {
239 return 'yes' === $this->get_data( 'review_questions', 'yes' );
240 }
241
242 /**
243 * @param $type
244 */
245 public function set_passing_grade_type( $type ) {
246 $this->_set_data( 'passing_grade_type', $type );
247 }
248
249 /**
250 * @return array|mixed
251 */
252 public function get_passing_grade_type() {
253 return $this->get_data( 'passing_grade_type', 'percentage' );
254 }
255
256 /**
257 * @param $value
258 */
259 public function set_passing_grade( $value ) {
260 $this->_set_data( 'passing_grade', $value );
261 }
262
263 /**
264 * @return array|mixed
265 */
266 public function get_passing_grade() {
267 $type = $this->get_passing_grade_type();
268 $value = $this->get_data( 'passing_grade', 0 );
269
270 switch ( $type ) {
271 case 'point':
272 break;
273 case 'percentage':
274 default:
275 $value = "{$value}%";
276 break;
277 }
278
279 return $value;
280 }
281
282 /**
283 * @deprecated
284 *
285 * @param $value
286 */
287 public function set_show_check_answer( $value ) {
288 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
289
290 $this->_set_data( 'show_check_answer', $value );
291 }
292
293 /**
294 * @deprecated
295 *
296 * @return int|bool
297 */
298 public function get_show_check_answer() {
299 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
300
301 return intval( $this->get_data( 'show_check_answer' ) );
302 }
303
304 /**
305 * @deprecated
306 *
307 * @param $count
308 */
309 public function set_count_check_answer( $count ) {
310 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
311
312 $this->_set_data( 'count_check_answer', $count );
313 }
314
315 /**
316 * @deprecated
317 *
318 * @return int
319 */
320 public function get_check_answer_count() {
321 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
322
323 return intval( $this->get_data( 'check_answer_count' ) );
324 }
325
326 /**
327 * @deprecated
328 *
329 * @param $value
330 */
331 public function set_show_hint( $value ) {
332 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
333
334 $this->_set_data( 'show_hint', $value );
335 }
336
337 /**
338 * @deprecated
339 *
340 * @return int
341 */
342 public function get_show_hint() {
343 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
344
345 return intval( $this->get_data( 'show_hint' ) );
346 }
347
348 /**
349 * @deprecated
350 *
351 * @param $count
352 */
353 public function set_count_hint( $count ) {
354 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
355
356 $this->_set_data( 'count_hint', $count );
357 }
358
359 /**
360 * Return true if hint answer is enabled.
361 *
362 * @deprecated
363 *
364 * @return bool
365 */
366 public function enable_show_hint() {
367 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
368
369 return apply_filters( 'learn-press/quiz/enable-show-hint', $this->get_data( 'show_hint' ) == 'yes', $this->get_id() );
370 }
371
372 /**
373 * @deprecated
374 *
375 * @param $value
376 */
377 public function set_archive_history( $value ) {
378 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
379
380 $this->_set_data( 'archive_history', $value );
381 }
382
383 /**
384 * Return true if archive history is enabled.
385 *
386 * @deprecated
387 *
388 * @return bool
389 */
390 public function enable_archive_history() {
391 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
392
393 return apply_filters( 'learn-press/quiz/enable-archive-history', $this->get_data( 'archive_history' ) == 'yes', $this->get_id() );
394 }
395
396 /**
397 * Return total mark of quiz by calculating total mark of all questions.
398 *
399 * @return int
400 */
401 public function get_mark() {
402 $mark = $this->get_data( 'mark' );
403
404 if ( false === $mark || '' === $mark ) {
405 $questions = $this->get_questions();
406 $mark = 0;
407
408 foreach ( $questions as $question_id ) {
409 $question = LP_Question::get_question( $question_id );
410
411 if ( $question ) {
412 $mark += $question->get_mark();
413 }
414 }
415
416 $this->_set_data( 'mark', $mark );
417 }
418
419 return apply_filters( 'learn-press/quiz-mark', $mark, $this->get_id() );
420 }
421
422 /**
423 * Get duration of quiz
424 *
425 * @return LP_Duration
426 */
427 public function get_duration() {
428 $duration = parent::get_duration();
429
430 return apply_filters( 'learn-press/quiz-duration', $duration, $this->get_id() );
431 }
432
433 /**
434 * Get quiz questions.
435 *
436 * @param string $context
437 *
438 * @return mixed
439 * @editor tungnx
440 * @throws Exception
441 * @since 3.x.x
442 * @version 1.0.1
443 */
444 public function get_questions( $context = 'display' ) {
445 $questions = array();
446 $ids = $this->_curd->read_question_ids( $this->get_id(), $context );
447
448 if ( $ids ) {
449 foreach ( $ids as $id ) {
450 $questions[ $id ] = $id;
451 }
452 }
453
454 return apply_filters( 'learn-press/quiz/questions', $questions, $this->get_id(), $this->get_course_id(), $context );
455 }
456
457 /**
458 * Quiz editor get questions.
459 *
460 * @return mixed
461 */
462 public function quiz_editor_get_questions() {
463 // list questions
464 $questions = $this->get_question_ids( 'edit' );
465 // order questions in quiz
466 $question_order = learn_press_quiz_get_questions_order( $questions );
467
468 $result = array();
469
470 foreach ( $questions as $id ) {
471 $question = LP_Question::get_question( $id );
472
473 $answers = array();
474 // handle question answer
475 if ( is_array( $question->get_data( 'answer_options' ) ) ) {
476 foreach ( $question->get_data( 'answer_options' ) as $answer ) {
477 $answers[] = $answer;
478 }
479 }
480
481 $post = get_post( $id );
482 $result[] = apply_filters(
483 'learn-press/quiz-editor/question-data',
484 array(
485 'id' => $id,
486 'open' => false,
487 'title' => $post->post_title,
488 'type' => array(
489 'key' => $question->get_type(),
490 'label' => $question->get_type_label(),
491 ),
492 'answers' => apply_filters( 'learn-press/quiz-editor/question-answers-data', $answers, $id, $this->get_id() ),
493 'settings' => array(
494 'content' => $post->post_content,
495 'mark' => get_post_meta( $id, '_lp_mark', true ),
496 'explanation' => get_post_meta( $id, '_lp_explanation', true ),
497 'hint' => get_post_meta( $id, '_lp_hint', true ),
498 ),
499 'order' => $question_order[ $id ],
500 ),
501 $id,
502 $this->get_id()
503 );
504 }
505
506 return apply_filters( 'learn-press/quiz/quiz_editor_questions', $result, $this->get_id() );
507 }
508
509 /**
510 * Get quiz duration html.
511 *
512 * @return mixed
513 */
514 public function get_duration_html() {
515 $duration = $this->get_duration();
516 if ( $duration ) {
517 $duration = learn_press_seconds_to_time( $duration->get_seconds() );
518 } else {
519 $duration = __( 'Unlimited', 'learnpress' );
520 }
521
522 return apply_filters( 'learn_press_quiz_duration_html', $duration, $this );
523 }
524
525 /**
526 * Get number questions in quiz.
527 *
528 * @return int
529 */
530 public function count_questions() {
531 $size = 0;
532 $questions = $this->get_question_ids();
533
534 if ( $questions ) {
535 $size = sizeof( $questions );
536 }
537
538 return apply_filters( 'learn-press/quiz/count-questions', $size, $this->get_id() );
539 }
540
541 /**
542 * Get all question's ids of the quiz.
543 *
544 * @param string $context
545 *
546 * @return int[]
547 * @editor tungnx
548 * @version 1.0.1
549 * @since 3.2.0
550 */
551 public function get_question_ids( string $context = 'display' ): array {
552 $ids = $this->_curd->read_question_ids( $this->get_id(), $context );
553
554 return apply_filters( 'learn-press/quiz/get-question-ids', $ids, $this->get_id(), $this->get_course_id(), $context );
555 }
556
557 /**
558 * This quiz has any question?
559 *
560 * @return bool
561 */
562 public function has_questions() {
563 return $this->count_questions() > 0;
564 }
565
566 /**
567 * Get js localize script in frontend. [NOT USED]
568 *
569 * @return mixed
570 */
571 public function get_localize() {
572 $localize = array(
573 'confirm_finish_quiz' => array(
574 'title' => __( 'Finish quiz', 'learnpress' ),
575 'message' => __( 'Are you sure you want to finish this quiz?', 'learnpress' ),
576 ),
577 'confirm_retake_quiz' => array(
578 'title' => __( 'Retake quiz', 'learnpress' ),
579 'message' => __( 'Are you sure you want to retake this quiz?', 'learnpress' ),
580 ),
581 'quiz_time_is_over' => array(
582 'title' => __( 'Time\'s up!', 'learnpress' ),
583 'message' => __( 'The time is up! Your quiz will automatically come to an end', 'learnpress' ),
584 ),
585 'finished_quiz' => __( 'Congrats! You have finished this quiz', 'learnpress' ),
586 'retaken_quiz' => __( 'Congrats! You have re-taken this quiz. Please wait a moment and the page will reload', 'learnpress' ),
587 );
588
589 return apply_filters( 'learn_press_single_quiz_localize', $localize, $this );
590 }
591
592 /**
593 * __isset function.
594 *
595 * @param mixed $key
596 *
597 * @return bool
598 */
599 public function __isset( $key ) {
600 return metadata_exists( 'post', $this->get_id(), '_' . $key );
601 }
602
603 /**
604 * __get function.
605 *
606 * @param string $key
607 *
608 * @return mixed
609 */
610 public function __get( $key ) {
611 echo '@deprecated[' . $key . ']';
612 learn_press_debug( debug_backtrace() );
613
614 return false;
615 }
616
617 /**
618 * @param $feature
619 *
620 * @return mixed
621 * @throws Exception
622 */
623 public function has( $feature ) {
624 _deprecated_function( __FUNCTION__, '3.0.8' );
625
626 $args = func_get_args();
627 unset( $args[0] );
628 $method = 'has_' . preg_replace( '!-!', '_', $feature );
629 $callback = array( $this, $method );
630 if ( is_callable( $callback ) ) {
631 return call_user_func_array( $callback, $args );
632 } else {
633 throw new Exception( sprintf( __( 'The function %s doesn\'t exist', 'learnpress' ), $feature ) );
634 }
635 }
636
637 /**
638 * Return TRUE if quiz contain a question.
639 *
640 * @param int $question_id
641 *
642 * @return bool
643 */
644 public function has_question( $question_id ) {
645 $questions = $this->get_question_ids();
646
647 return apply_filters( 'learn-press/quiz/has-question', in_array( $question_id, $questions ), $question_id, $this->get_id() );
648 }
649
650 /**
651 * Get question permalink from it's ID.
652 * If permalink option is turn on, add name of question
653 * into quiz permalink. Otherwise, add it's ID into
654 * query var.
655 *
656 * @param int $question_id
657 *
658 * @return string
659 */
660 public function get_question_link( $question_id = null ) {
661 $course = learn_press_get_course();
662 if ( ! $course ) {
663 return '';
664 }
665
666 $permalink = $course->get_item_link( $this->get_id() );
667 if ( '' != get_option( 'permalink_structure' ) && get_post_status( $this->get_id() ) != 'draft' ) {
668 if ( get_post_type( $question_id ) === LP_QUESTION_CPT ) {
669 $question_name = get_post_field( 'post_name', $question_id );
670 preg_match( '/\?/i', $permalink, $result );
671 if ( empty( $result ) ) {
672 $permalink = $permalink . $question_name;
673 } else {
674 $permalink = preg_replace( '/\?/i', '/' . $question_name . '/?', $permalink );
675 }
676 }
677 } else {
678 $permalink = esc_url_raw( add_query_arg( array( 'question', $question_id ), $permalink ) );
679 }
680
681 // @deprecated
682 $permalink = apply_filters( 'learn_press_quiz_question_permalink', $permalink, $question_id, $this );
683
684 return apply_filters( 'learn-press/quiz/question-permalink', $permalink, $question_id, $this->get_id() );
685 }
686
687 /**
688 * @param int $at
689 *
690 * @return bool
691 * @deprecated 4.1.6.9
692 */
693 /*public function get_question_at( $at = 0 ) {
694 $questions = $this->get_questions();
695
696 if ( $questions ) {
697 $questions = array_values( $questions );
698
699 return @$questions[ $at ];
700 }
701
702 return false;
703 }*/
704
705 /**
706 * Get prev question from a question.
707 *
708 * @param int $id
709 *
710 * @return bool
711 * @deprecated 4.1.6.9
712 */
713 /*public function get_prev_question( $id ) {
714 $prev = false;
715 $questions = $this->get_questions();
716
717 if ( $questions ) {
718 $questions = array_values( $questions );
719 $at = array_search( $id, $questions );
720
721 if ( 0 < $at ) {
722 $prev = $questions[ $at - 1 ];
723 }
724 }
725
726 return apply_filters( 'learn-press/quiz/prev-question-id', $prev, $this->get_id() );
727 }*/
728
729 /**
730 * Get next question from a question.
731 *
732 * @param int $id
733 *
734 * @return bool
735 * @deprecated 4.1.6.9
736 */
737 /*public function get_next_question( $id ) {
738 $next = false;
739 $questions = $this->get_questions();
740
741 if ( $questions ) {
742 $questions = array_values( $questions );
743 $at = array_search( $id, $questions );
744
745 if ( sizeof( $questions ) - 1 > $at ) {
746 $next = $questions[ $at + 1 ];
747 }
748 }
749
750 return apply_filters( 'learn-press/quiz/next-question-id', $next, $this->get_id() );
751 }*/
752
753 /**
754 * Get index number of a question.
755 *
756 * @param int $id
757 * @param int $start
758 *
759 * @return bool|mixed
760 * @deprecated 4.1.6.9
761 */
762 /*public function get_question_index( $id, $start = 0 ) {
763 $index = 0;
764 $questions = $this->get_questions();
765
766 if ( $questions ) {
767 $questions = array_values( $questions );
768 $index = array_search( $id, $questions );
769 }
770
771 return apply_filters( 'learn-press/quiz/question-index', intval( $start ) + $index, $this->get_id() );
772 }*/
773
774 /**
775 * Check question.
776 *
777 * @param $question_id
778 * @param $user_id
779 *
780 * @return bool
781 */
782 public function check_question( $question_id, $user_id ) {
783 $question = LP_Question::get_question( $question_id );
784
785 if ( ! $question ) {
786 return false;
787 }
788
789 $user = learn_press_get_user( $user_id );
790
791 $history = $user->get_quiz_results( $this->get_id() );
792
793 if ( ! $history ) {
794 return false;
795 }
796
797 $checked = array();
798 $checked = array_filter( $checked );
799
800 if ( ! in_array( $question_id, $checked ) ) {
801 $checked[] = $question_id;
802 }
803
804 return true;
805
806 }
807
808 /**
809 * Get question position in quiz.
810 *
811 * @param $question
812 * @param int $user_id
813 *
814 * @return false|int|string
815 */
816 public function get_question_position( $question, $user_id = 0 ) {
817 if ( ! $user_id ) {
818 $user_id = learn_press_get_current_user_id();
819 }
820
821 $user = learn_press_get_user( $user_id );
822 $results = $user->get_quiz_results( $this->get_id(), '', '' );
823
824 if ( $user && $results ) {
825 $questions = (array) $results->questions;
826
827 } else {
828 $questions = $this->get_question_ids();
829 }
830
831 $position = array_search( $question, $questions );
832
833 return $position;
834 }
835
836 /**
837 * @param int $user_id
838 * @param int $course_id
839 *
840 * @return bool|LP_Question
841 */
842 public function get_current_question( $user_id = 0, $course_id = 0 ) {
843 _deprecated_function( sprintf( '%s::%s', __CLASS__, __FUNCTION__ ), '4.0.0' );
844
845 $user = learn_press_get_user( $user_id );
846 $id = $user->get_current_quiz_question( $this->get_id(), $course_id );
847
848 return LP_Question::get_question( $id );
849 }
850
851 /**
852 * @param string $return
853 *
854 * @return LP_Question|int
855 */
856 public function get_viewing_question( $return = '' ) {
857 global $lp_quiz_question;
858
859 return $return !== 'id' ? $lp_quiz_question : ( $lp_quiz_question ? $lp_quiz_question->get_id() : 0 );
860 }
861
862 /**
863 * @param mixed $the_quiz
864 * @param array $args
865 *
866 * @return LP_Quiz|bool
867 */
868 public static function get_quiz( $the_quiz = false, $args = array() ) {
869
870 if ( is_numeric( $the_quiz ) && isset( LP_Global::$quizzes[ $the_quiz ] ) ) {
871 return LP_Global::$quizzes[ $the_quiz ];
872 }
873
874 $the_quiz = self::get_quiz_object( $the_quiz );
875
876 if ( ! $the_quiz ) {
877 return false;
878 }
879
880 if ( isset( LP_Global::$quizzes[ $the_quiz->ID ] ) ) {
881 return LP_Global::$quizzes[ $the_quiz->ID ];
882 }
883
884 if ( ! empty( $args['force'] ) ) {
885 $force = ! ! $args['force'];
886 unset( $args['force'] );
887 } else {
888 $force = false;
889 }
890 $key_args = wp_parse_args(
891 $args,
892 array(
893 'id' => $the_quiz->ID,
894 'type' => $the_quiz->post_type,
895 )
896 );
897
898 $key = LP_Helper::array_to_md5( $key_args );
899
900 if ( $force ) {
901 LP_Global::$quizzes[ $key ] = false;
902 LP_Global::$quizzes[ $the_quiz->ID ] = false;
903 }
904
905 if ( empty( LP_Global::$quizzes[ $key ] ) ) {
906 $class_name = self::get_quiz_class( $the_quiz, $args );
907 if ( is_string( $class_name ) && class_exists( $class_name ) ) {
908 $quiz = new $class_name( $the_quiz->ID, $args );
909 } elseif ( $class_name instanceof LP_Course_Item ) {
910 $quiz = $class_name;
911 } else {
912 $quiz = new self( $the_quiz->ID, $args );
913 }
914 LP_Global::$quizzes[ $key ] = $quiz;
915 LP_Global::$quizzes[ $the_quiz->ID ] = $quiz;
916 }
917
918 return LP_Global::$quizzes[ $key ];
919 }
920
921 /**
922 * @param string $quiz_type
923 *
924 * @return string|false
925 */
926 private static function get_class_name_from_quiz_type( $quiz_type ) {
927 return LP_QUIZ_CPT === $quiz_type ? __CLASS__ : 'LP_Quiz_' . implode( '_', array_map( 'ucfirst', explode( '-', $quiz_type ) ) );
928 }
929
930 /**
931 * Get the lesson class name
932 *
933 * @param WP_Post $the_quiz
934 * @param array $args (default: array())
935 *
936 * @return string
937 */
938 private static function get_quiz_class( $the_quiz, $args = array() ) {
939 $quiz_id = absint( $the_quiz->ID );
940 $type = $the_quiz->post_type;
941
942 $class_name = self::get_class_name_from_quiz_type( $type );
943
944 // Filter class name so that the class can be overridden if extended.
945 return apply_filters( 'learn-press/quiz/object-class', $class_name, $type, $quiz_id );
946 }
947
948 /**
949 * Get the quiz object
950 *
951 * @param mixed $the_quiz
952 *
953 * @uses WP_Post
954 * @return WP_Post|bool false on failure
955 */
956 private static function get_quiz_object( $the_quiz ) {
957 if ( false === $the_quiz ) {
958 $the_quiz = get_post_type() === LP_QUIZ_CPT ? $GLOBALS['post'] : false;
959 } elseif ( is_numeric( $the_quiz ) ) {
960 $the_quiz = get_post( $the_quiz );
961 } elseif ( $the_quiz instanceof LP_Course_Item ) {
962 $the_quiz = get_post( $the_quiz->get_id() );
963 } elseif ( ! ( $the_quiz instanceof WP_Post ) ) {
964 $the_quiz = false;
965 }
966
967 return apply_filters( 'learn-press/quiz/post-object', $the_quiz );
968 }
969
970 public function set_show_hide_question( $show_or_hide ) {
971 $this->_set_data( 'show_hide_question', $show_or_hide );
972 }
973
974 public function set_preview( $preview ) {
975 $this->_set_data( 'preview', $preview );
976 }
977
978 // public function set_minus_points( $points ) {
979 // $this->_set_data( 'minus_points', $points );
980 // }
981
982 /**
983 * @deprecated
984 *
985 * @param $skip
986 */
987 public function set_minus_skip_questions( $skip ) {
988 $this->_set_data( 'minus_skip_questions', $skip );
989 }
990
991 public function get_preview() {
992 return 'yes' === $this->get_data( 'preview' );
993 }
994
995 /**
996 * @deprecated
997 *
998 * @return bool
999 */
1000 public function get_show_hide_question() {
1001 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
1002
1003 return 'yes' === $this->get_data( 'show_hide_question' );
1004 }
1005
1006 // public function get_minus_points() {
1007 // return $this->get_data( 'minus_points' );
1008 // }
1009
1010 /**
1011 * Get option skip question will be minus points
1012 *
1013 * @return bool
1014 */
1015 public function get_minus_skip_questions(): bool {
1016 return 'yes' === $this->get_data( 'minus_skip_questions', 'no' );
1017 }
1018
1019 /**
1020 * Get css classes of question displays in a list.
1021 *
1022 * @param int $question_id
1023 * @param null $position
1024 *
1025 * @return array
1026 * @deprecated 4.1.6.9
1027 */
1028 /*public function get_question_number_class( $question_id, $position = null ) {
1029 if ( null === $position ) {
1030 $position = $this->get_question_index( $question_id );
1031 }
1032
1033 $class = array( 'question-' . $position );
1034
1035 if ( $this->is_viewing_question( $question_id ) ) {
1036 $class[] = 'current';
1037 }
1038
1039 $user = learn_press_get_current_user();
1040 $quiz_data = $user->get_quiz_data( $this->get_id() );
1041
1042 if ( $quiz_data ) {
1043 if ( $quiz_data->is_skipped( $question_id ) ) {
1044 $class[] = 'skipped';
1045 }
1046 }
1047
1048 return $class;
1049 }*/
1050
1051 /**
1052 * Implement ArrayAccess functions.
1053 *
1054 * @param mixed $offset
1055 * @param mixed $value
1056 */
1057 public function offsetSet( $offset, $value ) {
1058 // Do not allow to set value directly!
1059 }
1060
1061 /**
1062 * @param mixed $offset
1063 */
1064 public function offsetUnset( $offset ) {
1065 // Do not allow to unset value directly!
1066 }
1067
1068 /**
1069 * @param mixed $offset
1070 *
1071 * @return bool|mixed
1072 */
1073 public function offsetGet( $offset ) {
1074 return $this->offsetExists( $offset ) ? $this->_questions[ $offset ] : false;
1075 }
1076
1077 /**
1078 * @param mixed $offset
1079 *
1080 * @return bool
1081 */
1082 public function offsetExists( $offset ) {
1083 return array_key_exists( $offset, $this->_questions );
1084 }
1085 }
1086 }
1087