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 / quiz / class-lp-quiz.php

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

1,092 lines 25.0 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(), $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_questions( 'edit' );
465 // order questions in quiz
466 $question_order = learn_press_quiz_get_questions_order( $questions );
467
468 $result = array();
469 if ( is_array( $questions ) ) {
470 foreach ( $questions as $index => $id ) {
471
472 $question = LP_Question::get_question( $id );
473
474 $answers = array();
475 // handle question answer
476 if ( is_array( $question->get_data( 'answer_options' ) ) ) {
477 foreach ( $question->get_data( 'answer_options' ) as $answer ) {
478 $answers[] = $answer;
479 }
480 }
481
482 $post = get_post( $id );
483 $result[] = apply_filters(
484 'learn-press/quiz-editor/question-data',
485 array(
486 'id' => $id,
487 'open' => false,
488 'title' => $post->post_title,
489 'type' => array(
490 'key' => $question->get_type(),
491 'label' => $question->get_type_label(),
492 ),
493 'answers' => apply_filters( 'learn-press/quiz-editor/question-answers-data', $answers, $id, $this->get_id() ),
494 'settings' => array(
495 'content' => $post->post_content,
496 'mark' => get_post_meta( $id, '_lp_mark', true ),
497 'explanation' => get_post_meta( $id, '_lp_explanation', true ),
498 'hint' => get_post_meta( $id, '_lp_hint', true ),
499 ),
500 'order' => $question_order[ $index ],
501 ),
502 $id,
503 $this->get_id()
504 );
505 }
506 }
507
508 return apply_filters( 'learn-press/quiz/quiz_editor_questions', $result, $this->get_id() );
509 }
510
511 /**
512 * Get quiz duration html.
513 *
514 * @return mixed
515 */
516 public function get_duration_html() {
517 $duration = $this->get_duration();
518 if ( $duration ) {
519 $duration = learn_press_seconds_to_time( $duration->get_seconds() );
520 } else {
521 $duration = __( 'Unlimited', 'learnpress' );
522 }
523
524 return apply_filters( 'learn_press_quiz_duration_html', $duration, $this );
525 }
526
527 /**
528 * Get number questions in quiz.
529 *
530 * @return int
531 */
532 public function count_questions() {
533 $size = 0;
534 $questions = $this->get_questions();
535
536 if ( $questions ) {
537 $size = sizeof( $questions );
538 }
539
540 return apply_filters( 'learn-press/quiz/count-questions', $size, $this->get_id() );
541 }
542
543 /**
544 * Get all question's ids of the quiz.
545 *
546 * @param string $context
547 *
548 * @return int[]
549 * @editor tungnx
550 * @throws Exception
551 * @version 1.0.1
552 * @since 3.2.0
553 *
554 */
555 public function get_question_ids( string $context = 'display' ): array {
556 $ids = $this->_curd->read_question_ids( $this->get_id(), $context );
557
558 return apply_filters( 'learn-press/quiz/get-question-ids', $ids, $this->get_id(), $this->get_course_id(), $context );
559 }
560
561 /**
562 * This quiz has any question?
563 *
564 * @return bool
565 */
566 public function has_questions() {
567 return $this->count_questions() > 0;
568 }
569
570 /**
571 * Get js localize script in frontend. [NOT USED]
572 *
573 * @return mixed
574 */
575 public function get_localize() {
576 $localize = array(
577 'confirm_finish_quiz' => array(
578 'title' => __( 'Finish quiz', 'learnpress' ),
579 'message' => __( 'Are you sure you want to finish this quiz?', 'learnpress' ),
580 ),
581 'confirm_retake_quiz' => array(
582 'title' => __( 'Retake quiz', 'learnpress' ),
583 'message' => __( 'Are you sure you want to retake this quiz?', 'learnpress' ),
584 ),
585 'quiz_time_is_over' => array(
586 'title' => __( 'Time\'s up!', 'learnpress' ),
587 'message' => __( 'The time is up! Your quiz will automate come to finish', 'learnpress' ),
588 ),
589 'finished_quiz' => __( 'Congrats! You have finished this quiz', 'learnpress' ),
590 'retaken_quiz' => __( 'Congrats! You have re-taken this quiz. Please wait a moment and the page will reload', 'learnpress' ),
591 );
592
593 return apply_filters( 'learn_press_single_quiz_localize', $localize, $this );
594 }
595
596 /**
597 * __isset function.
598 *
599 * @param mixed $key
600 *
601 * @return bool
602 */
603 public function __isset( $key ) {
604 return metadata_exists( 'post', $this->get_id(), '_' . $key );
605 }
606
607 /**
608 * __get function.
609 *
610 * @param string $key
611 *
612 * @return mixed
613 */
614 public function __get( $key ) {
615 echo '@deprecated[' . $key . ']';
616 learn_press_debug( debug_backtrace() );
617
618 return false;
619 }
620
621 /**
622 * @param $feature
623 *
624 * @return mixed
625 * @throws Exception
626 */
627 public function has( $feature ) {
628 _deprecated_function( __FUNCTION__, '3.0.8' );
629
630 $args = func_get_args();
631 unset( $args[0] );
632 $method = 'has_' . preg_replace( '!-!', '_', $feature );
633 $callback = array( $this, $method );
634 if ( is_callable( $callback ) ) {
635 return call_user_func_array( $callback, $args );
636 } else {
637 throw new Exception( sprintf( __( 'The function %s doesn\'t exist', 'learnpress' ), $feature ) );
638 }
639 }
640
641 /**
642 * Return TRUE if quiz contain a question.
643 *
644 * @param int $question_id
645 *
646 * @return bool
647 */
648 public function has_question( $question_id ) {
649 $questions = $this->get_questions();
650
651 return apply_filters( 'learn-press/quiz/has-question', is_array( $questions ) && ( false !== array_search( $question_id, $questions ) ), $question_id, $this->get_id() );
652 }
653
654 /**
655 * Get question permalink from it's ID.
656 * If permalink option is turn on, add name of question
657 * into quiz permalink. Otherwise, add it's ID into
658 * query var.
659 *
660 * @param int $question_id
661 *
662 * @return string
663 */
664 public function get_question_link( $question_id = null ) {
665 $course = learn_press_get_course();
666 if ( ! $course ) {
667 return '';
668 }
669
670 $permalink = $course->get_item_link( $this->get_id() );
671 if ( '' != get_option( 'permalink_structure' ) && get_post_status( $this->get_id() ) != 'draft' ) {
672 if ( get_post_type( $question_id ) === LP_QUESTION_CPT ) {
673 $question_name = get_post_field( 'post_name', $question_id );
674 preg_match( '/\?/i', $permalink, $result );
675 if ( empty( $result ) ) {
676 $permalink = $permalink . $question_name;
677 } else {
678 $permalink = preg_replace( '/\?/i', '/' . $question_name . '/?', $permalink );
679 }
680 }
681 } else {
682 $permalink = esc_url_raw( add_query_arg( array( 'question', $question_id ), $permalink ) );
683 }
684
685 // @deprecated
686 $permalink = apply_filters( 'learn_press_quiz_question_permalink', $permalink, $question_id, $this );
687
688 return apply_filters( 'learn-press/quiz/question-permalink', $permalink, $question_id, $this->get_id() );
689 }
690
691 /**
692 * @param int $at
693 *
694 * @return bool
695 * @depecated 4.1.6.9
696 */
697 /*public function get_question_at( $at = 0 ) {
698 $questions = $this->get_questions();
699
700 if ( $questions ) {
701 $questions = array_values( $questions );
702
703 return @$questions[ $at ];
704 }
705
706 return false;
707 }*/
708
709 /**
710 * Get prev question from a question.
711 *
712 * @param int $id
713 *
714 * @return bool
715 * @depecated 4.1.6.9
716 */
717 /*public function get_prev_question( $id ) {
718 $prev = false;
719 $questions = $this->get_questions();
720
721 if ( $questions ) {
722 $questions = array_values( $questions );
723 $at = array_search( $id, $questions );
724
725 if ( 0 < $at ) {
726 $prev = $questions[ $at - 1 ];
727 }
728 }
729
730 return apply_filters( 'learn-press/quiz/prev-question-id', $prev, $this->get_id() );
731 }*/
732
733 /**
734 * Get next question from a question.
735 *
736 * @param int $id
737 *
738 * @return bool
739 * @depecated 4.1.6.9
740 */
741 /*public function get_next_question( $id ) {
742 $next = false;
743 $questions = $this->get_questions();
744
745 if ( $questions ) {
746 $questions = array_values( $questions );
747 $at = array_search( $id, $questions );
748
749 if ( sizeof( $questions ) - 1 > $at ) {
750 $next = $questions[ $at + 1 ];
751 }
752 }
753
754 return apply_filters( 'learn-press/quiz/next-question-id', $next, $this->get_id() );
755 }*/
756
757 /**
758 * Get index number of a question.
759 *
760 * @param int $id
761 * @param int $start
762 *
763 * @return bool|mixed
764 * @depecated 4.1.6.9
765 */
766 /*public function get_question_index( $id, $start = 0 ) {
767 $index = 0;
768 $questions = $this->get_questions();
769
770 if ( $questions ) {
771 $questions = array_values( $questions );
772 $index = array_search( $id, $questions );
773 }
774
775 return apply_filters( 'learn-press/quiz/question-index', intval( $start ) + $index, $this->get_id() );
776 }*/
777
778 /**
779 * Check question.
780 *
781 * @param $question_id
782 * @param $user_id
783 *
784 * @return bool
785 */
786 public function check_question( $question_id, $user_id ) {
787 $question = LP_Question::get_question( $question_id );
788
789 if ( ! $question ) {
790 return false;
791 }
792
793 $user = learn_press_get_user( $user_id );
794
795 $history = $user->get_quiz_results( $this->get_id() );
796
797 if ( ! $history ) {
798 return false;
799 }
800
801 $checked = array();
802 $checked = array_filter( $checked );
803
804 if ( ! in_array( $question_id, $checked ) ) {
805 $checked[] = $question_id;
806 }
807
808 return true;
809
810 }
811
812 /**
813 * Get question position in quiz.
814 *
815 * @param $question
816 * @param int $user_id
817 *
818 * @return false|int|string
819 */
820 public function get_question_position( $question, $user_id = 0 ) {
821 if ( ! $user_id ) {
822 $user_id = learn_press_get_current_user_id();
823 }
824
825 $user = learn_press_get_user( $user_id );
826 $results = $user->get_quiz_results( $this->get_id(), '', '' );
827
828 if ( $user && $results ) {
829 $questions = (array) $results->questions;
830
831 } else {
832 $questions = (array) $this->get_questions();
833 $questions = array_keys( $questions );
834 }
835
836 $position = array_search( $question, $questions );
837
838 return $position;
839 }
840
841 /**
842 * @param int $user_id
843 * @param int $course_id
844 *
845 * @return bool|LP_Question
846 */
847 public function get_current_question( $user_id = 0, $course_id = 0 ) {
848 _deprecated_function( sprintf( '%s::%s', __CLASS__, __FUNCTION__ ), '4.0.0' );
849
850 $user = learn_press_get_user( $user_id );
851 $id = $user->get_current_quiz_question( $this->get_id(), $course_id );
852
853 return LP_Question::get_question( $id );
854 }
855
856 /**
857 * @param string $return
858 *
859 * @return LP_Question|int
860 */
861 public function get_viewing_question( $return = '' ) {
862 global $lp_quiz_question;
863
864 return $return !== 'id' ? $lp_quiz_question : ( $lp_quiz_question ? $lp_quiz_question->get_id() : 0 );
865 }
866
867 /**
868 * @param mixed $the_quiz
869 * @param array $args
870 *
871 * @return LP_Quiz|bool
872 */
873 public static function get_quiz( $the_quiz = false, $args = array() ) {
874
875 if ( is_numeric( $the_quiz ) && isset( LP_Global::$quizzes[ $the_quiz ] ) ) {
876 return LP_Global::$quizzes[ $the_quiz ];
877 }
878
879 $the_quiz = self::get_quiz_object( $the_quiz );
880
881 if ( ! $the_quiz ) {
882 return false;
883 }
884
885 if ( isset( LP_Global::$quizzes[ $the_quiz->ID ] ) ) {
886 return LP_Global::$quizzes[ $the_quiz->ID ];
887 }
888
889 if ( ! empty( $args['force'] ) ) {
890 $force = ! ! $args['force'];
891 unset( $args['force'] );
892 } else {
893 $force = false;
894 }
895 $key_args = wp_parse_args(
896 $args,
897 array(
898 'id' => $the_quiz->ID,
899 'type' => $the_quiz->post_type,
900 )
901 );
902
903 $key = LP_Helper::array_to_md5( $key_args );
904
905 if ( $force ) {
906 LP_Global::$quizzes[ $key ] = false;
907 LP_Global::$quizzes[ $the_quiz->ID ] = false;
908 }
909
910 if ( empty( LP_Global::$quizzes[ $key ] ) ) {
911 $class_name = self::get_quiz_class( $the_quiz, $args );
912 if ( is_string( $class_name ) && class_exists( $class_name ) ) {
913 $quiz = new $class_name( $the_quiz->ID, $args );
914 } elseif ( $class_name instanceof LP_Course_Item ) {
915 $quiz = $class_name;
916 } else {
917 $quiz = new self( $the_quiz->ID, $args );
918 }
919 LP_Global::$quizzes[ $key ] = $quiz;
920 LP_Global::$quizzes[ $the_quiz->ID ] = $quiz;
921 }
922
923 return LP_Global::$quizzes[ $key ];
924 }
925
926 /**
927 * @param string $quiz_type
928 *
929 * @return string|false
930 */
931 private static function get_class_name_from_quiz_type( $quiz_type ) {
932 return LP_QUIZ_CPT === $quiz_type ? __CLASS__ : 'LP_Quiz_' . implode( '_', array_map( 'ucfirst', explode( '-', $quiz_type ) ) );
933 }
934
935 /**
936 * Get the lesson class name
937 *
938 * @param WP_Post $the_quiz
939 * @param array $args (default: array())
940 *
941 * @return string
942 */
943 private static function get_quiz_class( $the_quiz, $args = array() ) {
944 $quiz_id = absint( $the_quiz->ID );
945 $type = $the_quiz->post_type;
946
947 $class_name = self::get_class_name_from_quiz_type( $type );
948
949 // Filter class name so that the class can be overridden if extended.
950 return apply_filters( 'learn-press/quiz/object-class', $class_name, $type, $quiz_id );
951 }
952
953 /**
954 * Get the quiz object
955 *
956 * @param mixed $the_quiz
957 *
958 * @uses WP_Post
959 * @return WP_Post|bool false on failure
960 */
961 private static function get_quiz_object( $the_quiz ) {
962 if ( false === $the_quiz ) {
963 $the_quiz = get_post_type() === LP_QUIZ_CPT ? $GLOBALS['post'] : false;
964 } elseif ( is_numeric( $the_quiz ) ) {
965 $the_quiz = get_post( $the_quiz );
966 } elseif ( $the_quiz instanceof LP_Course_Item ) {
967 $the_quiz = get_post( $the_quiz->get_id() );
968 } elseif ( ! ( $the_quiz instanceof WP_Post ) ) {
969 $the_quiz = false;
970 }
971
972 return apply_filters( 'learn-press/quiz/post-object', $the_quiz );
973 }
974
975 public function set_show_hide_question( $show_or_hide ) {
976 $this->_set_data( 'show_hide_question', $show_or_hide );
977 }
978
979 public function set_preview( $preview ) {
980 $this->_set_data( 'preview', $preview );
981 }
982
983 // public function set_minus_points( $points ) {
984 // $this->_set_data( 'minus_points', $points );
985 // }
986
987 /**
988 * @deprecated
989 *
990 * @param $skip
991 */
992 public function set_minus_skip_questions( $skip ) {
993 $this->_set_data( 'minus_skip_questions', $skip );
994 }
995
996 public function get_preview() {
997 return 'yes' === $this->get_data( 'preview' );
998 }
999
1000 /**
1001 * @deprecated
1002 *
1003 * @return bool
1004 */
1005 public function get_show_hide_question() {
1006 _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0.0' );
1007
1008 return 'yes' === $this->get_data( 'show_hide_question' );
1009 }
1010
1011 // public function get_minus_points() {
1012 // return $this->get_data( 'minus_points' );
1013 // }
1014
1015 /**
1016 * Get option skip question will be minus points
1017 *
1018 * @return bool
1019 */
1020 public function get_minus_skip_questions(): bool {
1021 return 'yes' === $this->get_data( 'minus_skip_questions', 'no' );
1022 }
1023
1024 /**
1025 * Get css classes of question displays in a list.
1026 *
1027 * @param int $question_id
1028 * @param null $position
1029 *
1030 * @return array
1031 * @depecated 4.1.6.9
1032 */
1033 /*public function get_question_number_class( $question_id, $position = null ) {
1034 if ( null === $position ) {
1035 $position = $this->get_question_index( $question_id );
1036 }
1037
1038 $class = array( 'question-' . $position );
1039
1040 if ( $this->is_viewing_question( $question_id ) ) {
1041 $class[] = 'current';
1042 }
1043
1044 $user = learn_press_get_current_user();
1045 $quiz_data = $user->get_quiz_data( $this->get_id() );
1046
1047 if ( $quiz_data ) {
1048 if ( $quiz_data->is_skipped( $question_id ) ) {
1049 $class[] = 'skipped';
1050 }
1051 }
1052
1053 return $class;
1054 }*/
1055
1056 /**
1057 * Implement ArrayAccess functions.
1058 *
1059 * @param mixed $offset
1060 * @param mixed $value
1061 */
1062 public function offsetSet( $offset, $value ) {
1063 // Do not allow to set value directly!
1064 }
1065
1066 /**
1067 * @param mixed $offset
1068 */
1069 public function offsetUnset( $offset ) {
1070 // Do not allow to unset value directly!
1071 }
1072
1073 /**
1074 * @param mixed $offset
1075 *
1076 * @return bool|mixed
1077 */
1078 public function offsetGet( $offset ) {
1079 return $this->offsetExists( $offset ) ? $this->_questions[ $offset ] : false;
1080 }
1081
1082 /**
1083 * @param mixed $offset
1084 *
1085 * @return bool
1086 */
1087 public function offsetExists( $offset ) {
1088 return array_key_exists( $offset, $this->_questions );
1089 }
1090 }
1091 }
1092