1: <?php
2: if ( ! defined( 'ABSPATH' ) ) exit;
3:
4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14: class Sensei_Question {
15: public $token;
16: public $meta_fields;
17:
18: 19: 20: 21:
22: public function __construct () {
23: $this->token = 'question';
24: $this->question_types = $this->question_types();
25: $this->meta_fields = array( 'question_right_answer', 'question_wrong_answers' );
26: if ( is_admin() ) {
27:
28: add_filter( 'manage_edit-question_columns', array( $this, 'add_column_headings' ), 10, 1 );
29: add_action( 'manage_posts_custom_column', array( $this, 'add_column_data' ), 10, 2 );
30: add_action( 'add_meta_boxes', array( $this, 'question_edit_panel_metabox' ), 10, 2 );
31:
32:
33: add_action( 'restrict_manage_posts', array( $this, 'filter_options' ) );
34: add_filter( 'request', array( $this, 'filter_actions' ) );
35:
36: add_action( 'save_post', array( $this, 'save_question' ), 10, 1 );
37: }
38: }
39:
40: public function question_types() {
41: $types = array(
42: 'multiple-choice' => __( 'Multiple Choice', 'woothemes-sensei' ),
43: 'boolean' => __( 'True/False', 'woothemes-sensei' ),
44: 'gap-fill' => __( 'Gap Fill', 'woothemes-sensei' ),
45: 'single-line' => __( 'Single Line', 'woothemes-sensei' ),
46: 'multi-line' => __( 'Multi Line', 'woothemes-sensei' ),
47: 'file-upload' => __( 'File Upload', 'woothemes-sensei' ),
48: );
49:
50: return apply_filters( 'sensei_question_types', $types );
51: }
52:
53: 54: 55: 56: 57: 58: 59:
60: public function add_column_headings ( $defaults ) {
61: $new_columns['cb'] = '<input type="checkbox" />';
62: $new_columns['title'] = _x( 'Question', 'column name', 'woothemes-sensei' );
63: $new_columns['question-type'] = _x( 'Type', 'column name', 'woothemes-sensei' );
64: $new_columns['question-category'] = _x( 'Categories', 'column name', 'woothemes-sensei' );
65: if ( isset( $defaults['date'] ) ) {
66: $new_columns['date'] = $defaults['date'];
67: }
68:
69: return $new_columns;
70: }
71:
72: 73: 74: 75: 76: 77: 78: 79:
80: public function add_column_data ( $column_name, $id ) {
81: global $wpdb, $post;
82:
83: switch ( $column_name ) {
84:
85: case 'id':
86: echo $id;
87: break;
88:
89: case 'question-type':
90: $question_type = strip_tags( get_the_term_list( $id, 'question-type', '', ', ', '' ) );
91: $output = '—';
92: if( isset( $this->question_types[ $question_type ] ) ) {
93: $output = $this->question_types[ $question_type ];
94: }
95: echo $output;
96: break;
97:
98: case 'question-category':
99: $output = strip_tags( get_the_term_list( $id, 'question-category', '', ', ', '' ) );
100: if( ! $output ) {
101: $output = '—';
102: }
103: echo $output;
104: break;
105:
106: default:
107: break;
108:
109: }
110:
111: }
112:
113: public function question_edit_panel_metabox( $post_type, $post ) {
114: if( in_array( $post_type, array( 'question', 'multiple_question' ) ) ) {
115:
116: $metabox_title = __( 'Question', 'woothemes-sensei' );
117:
118: if( isset( $post->ID ) ) {
119:
120: $question_type = Sensei()->question->get_question_type( $post->ID );
121:
122: if( $question_type ) {
123: $type = $this->question_types[ $question_type ];
124: if( $type ) {
125: $metabox_title = $type;
126: }
127: }
128: }
129: add_meta_box( 'question-edit-panel', $metabox_title, array( $this, 'question_edit_panel' ), 'question', 'normal', 'high' );
130: add_meta_box( 'question-lessons-panel', __( 'Quizzes', 'woothemes-sensei' ), array( $this, 'question_lessons_panel' ), 'question', 'side', 'default' );
131: add_meta_box( 'multiple-question-lessons-panel', __( 'Quizzes', 'woothemes-sensei' ), array( $this, 'question_lessons_panel' ), 'multiple_question', 'side', 'default' );
132: }
133: }
134:
135: public function question_edit_panel() {
136: global $post, $pagenow;
137:
138: add_action( 'admin_enqueue_scripts', array( Sensei()->lesson, 'enqueue_scripts' ) );
139: add_action( 'admin_enqueue_scripts', array( Sensei()->lesson, 'enqueue_styles' ) );
140:
141: $html = '<div id="lesson-quiz" class="single-question"><div id="add-question-main">';
142:
143: if( 'post-new.php' == $pagenow ) {
144:
145: $html .= '<div id="add-question-actions">';
146: $html .= Sensei()->lesson->quiz_panel_add( 'question' );
147: $html .= '</div>';
148:
149: } else {
150: $question_id = $post->ID;
151:
152: $question_type = Sensei()->question->get_question_type( $post->ID );
153:
154: $html .= '<div id="add-question-metadata"><table class="widefat">';
155: $html .= Sensei()->lesson->quiz_panel_question( $question_type, 0, $question_id, 'question' );
156: $html .= '</table></div>';
157: }
158:
159: $html .= '</div></div>';
160:
161: echo $html;
162: }
163:
164: public function question_lessons_panel() {
165: global $post;
166:
167: $no_lessons = sprintf( __( '%1$sThis question does not appear in any quizzes yet.%2$s', 'woothemes-sensei' ), '<em>', '</em>' );
168:
169: if( ! isset( $post->ID ) ) {
170: echo $no_lessons;
171: return;
172: }
173:
174:
175: $quizzes = get_post_meta( $post->ID, '_quiz_id', false );
176:
177:
178: $categories_of_question = wp_get_post_terms( $post->ID, 'question-category', array( 'fields' => 'ids' ) );
179: if ( ! empty( $categories_of_question ) ) {
180: foreach ( $categories_of_question as $term_id ) {
181: $qargs = array(
182: 'fields' => 'ids',
183: 'post_type' => 'multiple_question',
184: 'posts_per_page' => -1,
185: 'meta_query' => array(
186: array(
187: 'key' => 'category',
188: 'value' => $term_id,
189: ),
190: ),
191: 'post_status' => 'any',
192: 'suppress_filters' => 0,
193: );
194: $cat_question_ids = get_posts( $qargs );
195: foreach( $cat_question_ids as $cat_question_id ) {
196: $cat_quizzes = get_post_meta( $cat_question_id, '_quiz_id', false );
197: $quizzes = array_merge( $quizzes, $cat_quizzes );
198: }
199: }
200: $quizzes = array_unique( array_filter( $quizzes ) );
201: }
202:
203: if( 0 == count( $quizzes ) ) {
204: echo $no_lessons;
205: return;
206: }
207:
208: $lessons = false;
209:
210: foreach( $quizzes as $quiz ) {
211:
212: $lesson_id = get_post_meta( $quiz, '_quiz_lesson', true );
213:
214: if( ! $lesson_id ) continue;
215:
216: $lessons[ $lesson_id ]['title'] = get_the_title( $lesson_id );
217: $lessons[ $lesson_id ]['link'] = admin_url( 'post.php?post=' . $lesson_id . '&action=edit' );
218: }
219:
220: if( ! $lessons ) {
221: echo $no_lessons;
222: return;
223: }
224:
225: $html = '<ul>';
226:
227: foreach( $lessons as $id => $lesson ) {
228: $html .= '<li><a href="' . esc_url( $lesson['link'] ) . '">' . esc_html( $lesson['title'] ) . '</a></li>';
229: }
230:
231: $html .= '</ul>';
232:
233: echo $html;
234:
235: }
236:
237: public function save_question( $post_id = 0 ) {
238:
239: if( ! isset( $_POST['post_type']
240: ) || 'question' != $_POST['post_type'] ) {
241: return;
242: }
243:
244:
245:
246:
247: $data = $_POST ;
248: $data['quiz_id'] = 0;
249: $data['question_id'] = $post_id;
250:
251: if ( ! wp_is_post_revision( $post_id ) ){
252:
253:
254: remove_action( 'save_post', array( $this, 'save_question' ) );
255:
256:
257: $question_id = Sensei()->lesson->lesson_save_question( $data, 'question' );
258:
259:
260: add_action( 'save_post', array( $this, 'save_question' ) );
261: }
262:
263: return;
264: }
265:
266: 267: 268: 269:
270: public function filter_options() {
271: global $typenow;
272:
273: if( is_admin() && 'question' == $typenow ) {
274:
275: $output = '';
276:
277:
278: $selected = isset( $_GET['question_type'] ) ? $_GET['question_type'] : '';
279: $type_options = '<option value="">' . __( 'All types', 'woothemes-sensei' ) . '</option>';
280: foreach( $this->question_types as $label => $type ) {
281: $type_options .= '<option value="' . esc_attr( $label ) . '" ' . selected( $selected, $label, false ) . '>' . esc_html( $type ) . '</option>';
282: }
283:
284: $output .= '<select name="question_type" id="dropdown_question_type">';
285: $output .= $type_options;
286: $output .= '</select>';
287:
288:
289: $cats = get_terms( 'question-category', array( 'hide_empty' => false ) );
290: if ( ! empty( $cats ) && ! is_wp_error( $cats ) ) {
291: $selected = isset( $_GET['question_cat'] ) ? $_GET['question_cat'] : '';
292: $cat_options = '<option value="">' . __( 'All categories', 'woothemes-sensei' ) . '</option>';
293: foreach( $cats as $cat ) {
294: $cat_options .= '<option value="' . esc_attr( $cat->slug ) . '" ' . selected( $selected, $cat->slug, false ) . '>' . esc_html( $cat->name ) . '</option>';
295: }
296:
297: $output .= '<select name="question_cat" id="dropdown_question_cat">';
298: $output .= $cat_options;
299: $output .= '</select>';
300: }
301:
302: echo $output;
303: }
304: }
305:
306: 307: 308: 309: 310:
311: public function filter_actions( $request ) {
312: global $typenow;
313:
314: if( is_admin() && 'question' == $typenow ) {
315:
316:
317: $question_type = isset( $_GET['question_type'] ) ? $_GET['question_type'] : '';
318: if( $question_type ) {
319: $type_query = array(
320: 'taxonomy' => 'question-type',
321: 'terms' => $question_type,
322: 'field' => 'slug',
323: );
324: $request['tax_query'][] = $type_query;
325: }
326:
327:
328: $question_cat = isset( $_GET['question_cat'] ) ? $_GET['question_cat'] : '';
329: if( $question_cat ) {
330: $cat_query = array(
331: 'taxonomy' => 'question-category',
332: 'terms' => $question_cat,
333: 'field' => 'slug',
334: );
335: $request['tax_query'][] = $cat_query;
336: }
337: }
338:
339: return $request;
340: }
341:
342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353:
354: public function get_question_type( $question_id ){
355:
356: if( empty( $question_id ) || ! intval( $question_id ) > 0
357: || 'question' != get_post_type( $question_id ) ){
358: return false;
359: }
360:
361: $question_type = 'multiple-choice';
362: $question_types = wp_get_post_terms( $question_id, 'question-type' );
363: foreach( $question_types as $type ) {
364: $question_type = $type->slug;
365: }
366:
367: return $question_type;
368:
369: }
370:
371: 372: 373: 374: 375: 376: 377: 378: 379:
380: public function get_question_grade( $question_id ) {
381:
382: if ( empty( $question_id ) || ! intval( $question_id ) > 0
383: || 'question' != get_post_type( $question_id ) ) {
384: return false;
385: }
386:
387: $question_grade_raw = get_post_meta( $question_id, '_question_grade', true );
388:
389: if ( false === $question_grade_raw || $question_grade_raw == '' ) {
390: $question_grade = 1;
391: }
392:
393: else {
394: $question_grade = intval( $question_grade_raw );
395: }
396:
397: 398: 399: 400: 401:
402: return apply_filters( 'sensei_get_question_grade', $question_grade, $question_id );
403:
404: }
405:
406:
407: 408: 409: 410: 411: 412:
413: public static function load_question_template( $question_type ){
414:
415: Sensei_Templates::get_template ( 'single-quiz/question_type-' . $question_type . '.php' );
416: }
417:
418: 419: 420: 421: 422: 423: 424: 425:
426: public static function the_question_title( $question_id ){
427:
428: echo self::get_the_question_title( $question_id );
429:
430: }
431:
432: 433: 434: 435: 436: 437: 438: 439:
440: public static function get_the_question_title( $question_id ){
441:
442: 443: 444: 445: 446: 447:
448: $title = apply_filters( 'sensei_question_title', get_the_title( $question_id ) );
449:
450: 451: 452:
453: $title = apply_filters( 'sensei_single_title', $title, 'question');
454:
455: $title_html = '<span class="question question-title">';
456: $title_html .= $title;
457: $title_html .= '<span class="grade">' . Sensei()->question->get_question_grade( $question_id ) . '</span>';
458: $title_html .='</span>';
459:
460: return $title_html;
461: }
462:
463: 464: 465: 466: 467: 468:
469: public static function get_the_question_description( $question_id ){
470:
471: $question = get_post( $question_id );
472:
473: 474: 475:
476: return apply_filters( 'the_content', $question->post_content );
477:
478: }
479:
480: 481: 482: 483: 484: 485:
486: public static function the_question_description( $question_id ){
487:
488: echo self::get_the_question_description( $question_id );
489:
490: }
491:
492: 493: 494: 495: 496: 497: 498:
499: public static function get_the_question_media( $question_id ){
500:
501: $question_media = get_post_meta( $question_id, '_question_media', true );
502: $question_media_link = '';
503: if( 0 < intval( $question_media ) ) {
504: $mimetype = get_post_mime_type( $question_media );
505: if( $mimetype ) {
506: $mimetype_array = explode( '/', $mimetype);
507: if( isset( $mimetype_array[0] ) && $mimetype_array[0] ) {
508: $question_media_type = $mimetype_array[0];
509: $question_media_url = wp_get_attachment_url( $question_media );
510: $attachment = get_post( $question_media );
511: $question_media_title = $attachment->post_title;
512: $question_media_description = $attachment->post_content;
513: switch( $question_media_type ) {
514: case 'image':
515: $image_size = apply_filters( 'sensei_question_image_size', 'medium', $question_id );
516: $attachment_src = wp_get_attachment_image_src( $question_media, $image_size );
517: $question_media_link = '<a class="' . esc_attr( $question_media_type ) . '" title="' . esc_attr( $question_media_title ) . '" href="' . esc_url( $question_media_url ) . '" target="_blank"><img src="' . $attachment_src[0] . '" width="' . $attachment_src[1] . '" height="' . $attachment_src[2] . '" /></a>';
518: break;
519:
520: case 'audio':
521: $question_media_link = wp_audio_shortcode( array( 'src' => $question_media_url ) );
522: break;
523:
524: case 'video':
525: $question_media_link = wp_video_shortcode( array( 'src' => $question_media_url ) );
526: break;
527:
528: default:
529: $question_media_filename = basename( $question_media_url );
530: $question_media_link = '<a class="' . esc_attr( $question_media_type ) . '" title="' . esc_attr( $question_media_title ) . '" href="' . esc_url( $question_media_url ) . '" target="_blank">' . $question_media_filename . '</a>';
531: break;
532: }
533: }
534: }
535: }
536:
537: $output = '';
538: if( $question_media_link ) {
539:
540: $output .= '<div class="question_media_display">';
541: $output .= $question_media_link;
542: $output .= '<dl>';
543:
544: if( $question_media_title ) {
545:
546: $output .= '<dt>'. $question_media_title. '</dt>';
547:
548: }
549:
550: if( $question_media_description ) {
551:
552: $output .= '<dd>' . $question_media_description . '</dd>';
553:
554: }
555:
556: $output .= '</dl>';
557: $output .= '</div>';
558:
559:
560: }
561:
562: return $output;
563:
564: }
565:
566:
567: 568: 569: 570: 571: 572:
573: public static function the_question_media( $question_id ){
574:
575: echo self::get_the_question_media( $question_id );
576:
577: }
578:
579: 580: 581: 582: 583: 584: 585:
586: public static function the_question_hidden_fields( $question_id ){
587: ?>
588:
589: <input type="hidden" name="question_id_<?php $question_id;?>" value="<?php $question_id;?>" />
590: <input type="hidden" name="questions_asked[]" value="<?php esc_attr_e( $question_id ); ?>" />
591:
592: <?php
593: }
594:
595: 596: 597: 598: 599: 600:
601: public static function answer_feedback_notes( $question_id ){
602:
603:
604: $quiz_id = get_the_ID();
605: $lesson_id = Sensei()->quiz->get_lesson_id( $quiz_id );
606:
607:
608: $user_answers = Sensei()->quiz->get_user_answers( $lesson_id, get_current_user_id() );
609: if ( empty( $user_answers ) ) {
610: return;
611: }
612:
613:
614:
615: $user_lesson_status = Sensei_Utils::user_lesson_status( $lesson_id, get_current_user_id() );
616: $user_quiz_grade = Sensei_Quiz::get_user_quiz_grade( $lesson_id, get_current_user_id() );
617: $reset_quiz_allowed = Sensei_Quiz::is_reset_allowed( $lesson_id );
618: $quiz_grade_type = get_post_meta( $quiz_id , '_quiz_grade_type', true );
619: $quiz_graded = isset( $user_lesson_status->comment_approved ) && in_array( $user_lesson_status->comment_approved, array( 'graded', 'passed' ) );
620:
621: $quiz_required_pass_grade = intval( get_post_meta($quiz_id, '_quiz_passmark', true) );
622: $failed_and_reset_not_allowed = $user_quiz_grade < $quiz_required_pass_grade && ! $reset_quiz_allowed && $quiz_graded;
623:
624: if ( $quiz_graded || $failed_and_reset_not_allowed ) {
625:
626: $answer_notes = Sensei()->quiz->get_user_question_feedback( $lesson_id, $question_id, get_current_user_id() );
627:
628: if( $answer_notes ) { ?>
629:
630: <div class="sensei-message info info-special answer-feedback">
631:
632: <?php
633:
634: 635: 636: 637: 638: 639: 640: 641:
642: echo apply_filters( 'sensei_question_answer_notes', $answer_notes, $question_id, $lesson_id );
643:
644: ?>
645:
646: </div>
647:
648: <?php }
649:
650: }
651:
652: }
653:
654: 655: 656: 657: 658: 659: 660: 661: 662: 663:
664: public static function the_answer_result_indication(){
665:
666: global $post, $current_user, $sensei_question_loop;
667:
668: $answer_message = '';
669: $answer_message_class = '';
670: $quiz_id = $sensei_question_loop['quiz_id'];
671: $question_item = $sensei_question_loop['current_question'];
672: $lesson_id = Sensei()->quiz->get_lesson_id( $quiz_id );
673: $user_lesson_status = Sensei_Utils::user_lesson_status( $lesson_id, get_current_user_id() );
674: $quiz_graded = isset( $user_lesson_status->comment_approved ) && in_array( $user_lesson_status->comment_approved, array( 'graded', 'passed' ) );
675:
676: if ( ! Sensei_Utils::user_started_course( Sensei()->lesson->get_course_id( $lesson_id ), get_current_user_id() ) ) {
677: return;
678: }
679:
680: if ( ! $quiz_graded ) {
681: return;
682: }
683:
684: if ( ! Sensei_Quiz::is_pass_required( $lesson_id ) ) {
685: self::output_result_indication( $lesson_id, $question_item->ID);
686: return;
687: }
688:
689: $user_quiz_grade = Sensei_Quiz::get_user_quiz_grade( $lesson_id, get_current_user_id() );
690: $quiz_required_pass_grade = intval( get_post_meta($quiz_id, '_quiz_passmark', true) );
691: $user_passed = $user_quiz_grade >= $quiz_required_pass_grade;
692:
693: if ( $user_passed ) {
694: self::output_result_indication( $lesson_id, $question_item->ID);
695: return;
696: }
697:
698: if ( ! Sensei_Quiz::is_reset_allowed( $lesson_id ) ) {
699: self::output_result_indication( $lesson_id, $question_item->ID);
700: return;
701: }
702: }
703:
704: 705: 706: 707: 708: 709:
710: public static function output_result_indication( $lesson_id, $question_id ) {
711:
712: $question_grade = Sensei()->question->get_question_grade( $question_id );
713: $user_question_grade = Sensei()->quiz->get_user_question_grade( $lesson_id, $question_id, get_current_user_id() );
714:
715:
716: $user_correct = false;
717: $answer_message_class = 'user_wrong';
718: $answer_message = __( 'Incorrect - Right Answer:','woothemes-sensei') . ' ' . self::get_correct_answer( $question_id );
719:
720:
721: if ( 0 == $question_grade ) {
722: $user_correct = true;
723: $answer_message_class = '';
724: $answer_message = '';
725: } elseif( $user_question_grade > 0 ) {
726: $user_correct = true;
727: $answer_message_class = 'user_right';
728: $answer_message = sprintf( __( 'Grade: %d', 'woothemes-sensei' ), $user_question_grade );
729: }
730:
731:
732: $answer_notes = Sensei()->quiz->get_user_question_feedback( $lesson_id, $question_id, get_current_user_id() );
733: if( $answer_notes ) {
734: $answer_message_class .= ' has_notes';
735: }
736:
737: ?>
738: <div class="answer_message <?php esc_attr_e( $answer_message_class ); ?>">
739:
740: <span><?php echo $answer_message; ?></span>
741:
742: </div>
743: <?php
744: }
745:
746: 747: 748: 749: 750: 751: 752: 753: 754:
755: public static function get_template_data( $question_id, $quiz_id ){
756:
757: $lesson_id = Sensei()->quiz->get_lesson_id( $quiz_id );
758:
759: $reset_allowed = get_post_meta( $quiz_id, '_enable_quiz_reset', true );
760:
761: if( 'on' == $reset_allowed ) {
762: $reset_allowed = 1;
763: }
764:
765:
766: $user_lesson_end = Sensei_Utils::user_completed_lesson( Sensei()->quiz->get_lesson_id( $quiz_id), get_current_user_id() );
767: $user_lesson_complete = false;
768: if ( $user_lesson_end ) {
769: $user_lesson_complete = true;
770: }
771:
772:
773: $data[ 'ID' ] = $question_id;
774: $data[ 'title' ] = get_the_title( $question_id );
775: $data[ 'content' ] = get_post( $question_id )->post_content;
776: $data[ 'quiz_id' ] = $quiz_id;
777: $data[ 'lesson_id' ] = Sensei()->quiz->get_lesson_id( $quiz_id );
778: $data[ 'type' ] = Sensei()->question->get_question_type( $question_id );
779: $data[ 'question_grade' ] = Sensei()->question->get_question_grade( $question_id );
780: $data[ 'user_question_grade' ] = Sensei()->quiz->get_user_question_grade( $lesson_id, $question_id , get_current_user_id());
781: $data[ 'question_right_answer' ] = get_post_meta( $question_id , '_question_right_answer', true );
782: $data[ 'question_wrong_answers' ] = get_post_meta( $question_id , '_question_wrong_answers', true );
783: $data[ 'user_answer_entry' ] = Sensei()->quiz->get_user_question_answer( $lesson_id, $question_id , get_current_user_id() );
784: $data[ 'lesson_completed' ] = Sensei_Utils::user_completed_course( $lesson_id, get_current_user_id( ) );
785: $data[ 'quiz_grade_type' ] = get_post_meta( $quiz_id , '_quiz_grade_type', true );
786: $data[ 'reset_quiz_allowed' ] = $reset_allowed;
787: $data[ 'lesson_complete' ] = $user_lesson_complete;
788:
789: 790: 791: 792: 793: 794: 795: 796: 797: 798: 799: 800:
801: return apply_filters( 'sensei_get_question_template_data', $data, $question_id, $quiz_id );
802:
803: }
804:
805: 806: 807: 808: 809: 810: 811: 812: 813: 814: 815: 816:
817: public static function file_upload_load_question_data ( $question_data, $question_id, $quiz_id ){
818:
819:
820: if( 'file-upload' == Sensei()->question->get_question_type( $question_id ) ) {
821:
822:
823: $attachment_id = $question_data[ 'user_answer_entry' ];
824: $answer_media_url = $answer_media_filename = '';
825:
826:
827: $question_helptext = '';
828: if( isset( $question_data['question_wrong_answers'][0] ) ) {
829:
830: $question_helptext = $question_data['question_wrong_answers'][0];
831:
832: }
833:
834:
835: if( 0 < intval( $attachment_id ) ) {
836:
837: $answer_media_url = wp_get_attachment_url( $attachment_id );
838: $answer_media_filename = basename( $answer_media_url );
839:
840: }
841:
842:
843:
844:
845: $upload_size_unit = $max_upload_size = wp_max_upload_size();
846: $sizes = array( 'KB', 'MB', 'GB' );
847: for ( $u = -1; $upload_size_unit > 1024 && $u < count( $sizes ) - 1; $u++ ) {
848: $upload_size_unit /= 1024;
849: }
850: if ( $u < 0 ) {
851:
852: $upload_size_unit = 0;
853: $u = 0;
854:
855: } else {
856:
857: $upload_size_unit = (int) $upload_size_unit;
858:
859: }
860: $max_upload_size = sprintf( __( 'Maximum upload file size: %d%s' ), esc_html( $upload_size_unit ), esc_html( $sizes[ $u ] ) );
861:
862:
863: $question_data[ 'answer_media_url' ] = $answer_media_url;
864: $question_data[ 'answer_media_filename' ] = $answer_media_filename;
865: $question_data[ 'max_upload_size' ] = $max_upload_size;
866:
867: $question_data[ 'question_helptext' ] = $question_helptext;
868:
869: }
870:
871: return $question_data;
872:
873: }
874:
875: 876: 877: 878: 879: 880: 881: 882: 883: 884: 885: 886:
887: public static function multiple_choice_load_question_data( $question_data, $question_id, $quiz_id ){
888:
889: if( 'multiple-choice' == Sensei()->question->get_question_type( $question_id ) ) {
890:
891:
892: $answer_type = 'radio';
893: if ( is_array( $question_data[ 'question_right_answer' ] ) && ( 1 < count( $question_data[ 'question_right_answer' ] ) ) ) {
894:
895: $answer_type = 'checkbox';
896:
897: }
898:
899:
900: if ( is_array( $question_data[ 'question_right_answer' ] ) ) {
901:
902: $merged_options = array_merge( $question_data[ 'question_wrong_answers' ], $question_data[ 'question_right_answer' ] );
903:
904: } else {
905:
906: array_push( $question_data[ 'question_wrong_answers' ], $question_data[ 'question_right_answer' ] );
907: $merged_options = $question_data[ 'question_wrong_answers' ];
908:
909: }
910:
911:
912: $question_answers_options = array();
913: $count = 0;
914:
915: foreach( $merged_options as $answer ) {
916:
917: $count++;
918: $question_option = array();
919:
920: if( ( $question_data[ 'lesson_completed' ] && $question_data[ 'user_quiz_grade' ] != '' )
921: || ( $question_data[ 'lesson_completed' ] && ! $question_data[ 'reset_quiz_allowed' ] && $question_data[ 'user_quiz_grade' ] != '' )
922: || ( 'auto' == $question_data[ 'quiz_grade_type' ] && ! $question_data[ 'reset_quiz_allowed' ] && ! empty( $question_data[ 'user_quiz_grade' ] ) ) ) {
923:
924: $user_correct = false;
925:
926:
927:
928: if ( 0 == $question_data[ 'question_grade' ] ) {
929:
930: $user_correct = true;
931:
932: } else if( $question_data[ 'user_question_grade' ] > 0 ) {
933:
934: $user_correct = true;
935:
936: }
937:
938: }
939:
940:
941: $answer_class = '';
942: if( isset( $user_correct ) && 0 < $question_data[ 'question_grade' ] ) {
943: if ( is_array( $question_data['question_right_answer'] ) && in_array($answer, $question_data['question_right_answer']) ) {
944:
945: $answer_class .= ' right_answer';
946:
947: } elseif( !is_array($question_data['question_right_answer']) && $question_data['question_right_answer'] == $answer ) {
948:
949: $answer_class .= ' right_answer';
950:
951: } elseif( ( is_array( $question_data['user_answer_entry'] ) && in_array($answer, $question_data['user_answer_entry'] ) )
952: || ( ! $question_data['user_answer_entry'] && $question_data['user_answer_entry'] == $answer ) ) {
953:
954: $answer_class = 'user_wrong';
955: if( $user_correct ) {
956:
957: $answer_class = 'user_right';
958:
959: }
960:
961: }
962:
963: }
964:
965:
966: $checked = '';
967: if ( isset( $question_data['user_answer_entry'] ) && 0 < count( $question_data['user_answer_entry'] ) ) {
968: if ( is_array( $question_data['user_answer_entry'] ) && in_array( $answer, $question_data['user_answer_entry'] ) ) {
969:
970: $checked = 'checked="checked"';
971:
972: } elseif ( !is_array( $question_data['user_answer_entry'] ) ) {
973:
974: $checked = checked( $answer, $question_data['user_answer_entry'] , false );
975:
976: }
977:
978: }
979:
980:
981: $question_option[ 'ID' ] = Sensei()->lesson->get_answer_id( $answer );
982: $question_option[ 'answer' ] = $answer;
983: $question_option[ 'option_class'] = $answer_class;
984: $question_option[ 'checked'] = $checked;
985: $question_option[ 'count' ] = $count;
986: $question_option[ 'type' ] = $answer_type;
987:
988:
989: $question_answers_options[$question_option[ 'ID' ]] = $question_option;
990:
991: }
992:
993:
994:
995: $answer_options_sorted = array();
996: $random_order = get_post_meta( $question_data['ID'], '_random_order', true );
997: if( $random_order && $random_order == 'yes' ) {
998:
999: $answer_options_sorted = $question_answers_options;
1000: shuffle( $answer_options_sorted );
1001:
1002: } else {
1003:
1004: $answer_order = array();
1005: $answer_order_string = get_post_meta( $question_data['ID'], '_answer_order', true );
1006: if( $answer_order_string ) {
1007:
1008: $answer_order = array_filter( explode( ',', $answer_order_string ) );
1009: if( count( $answer_order ) > 0 ) {
1010:
1011: foreach( $answer_order as $answer_id ) {
1012:
1013: if( isset( $question_answers_options[ $answer_id ] ) ) {
1014:
1015: $answer_options_sorted[ $answer_id ] = $question_answers_options[ $answer_id ];
1016: unset( $question_answers_options[ $answer_id ] );
1017:
1018: }
1019:
1020: }
1021:
1022: if( count( $question_answers_options ) > 0 ) {
1023: foreach( $question_answers_options as $id => $answer ) {
1024:
1025: $answer_options_sorted[ $id ] = $answer;
1026:
1027: }
1028: }
1029:
1030: }else{
1031:
1032: $answer_options_sorted = $question_answers_options;
1033:
1034: }
1035:
1036: }else{
1037:
1038: $answer_options_sorted = $question_answers_options;
1039:
1040: }
1041:
1042: }
1043:
1044:
1045:
1046: $question_data[ 'answer_options' ] = $answer_options_sorted;
1047:
1048: }
1049:
1050: return $question_data;
1051:
1052: }
1053:
1054: 1055: 1056: 1057: 1058: 1059: 1060: 1061: 1062: 1063: 1064: 1065:
1066: public static function gap_fill_load_question_data( $question_data, $question_id, $quiz_id ){
1067:
1068: if( 'gap-fill' == Sensei()->question->get_question_type( $question_id ) ) {
1069:
1070: $gapfill_array = explode( '||', $question_data[ 'question_right_answer' ] );
1071: $question_data[ 'gapfill_pre' ] = isset( $gapfill_array[0] ) ? $gapfill_array[0] : '';
1072: $question_data[ 'gapfill_gap' ] = isset( $gapfill_array[1] ) ? $gapfill_array[1] : '';
1073: $question_data[ 'gapfill_post' ] = isset( $gapfill_array[2] ) ? $gapfill_array[2] : '';
1074:
1075: }
1076:
1077: return $question_data;
1078:
1079: }
1080:
1081:
1082: 1083: 1084: 1085: 1086: 1087:
1088: public static function get_correct_answer( $question_id ){
1089:
1090: $right_answer = get_post_meta( $question_id, '_question_right_answer', true );
1091: $type = Sensei()->question->get_question_type( $question_id );
1092: $type_name = __( 'Multiple Choice', 'woothemes-sensei' );
1093: $grade_type = 'manual-grade';
1094:
1095: if ('boolean'== $type ) {
1096:
1097: $right_answer = ucfirst($right_answer);
1098:
1099: }elseif( 'multiple-choice' == $type ) {
1100:
1101: $right_answer = (array) $right_answer;
1102: $right_answer = implode( ', ', $right_answer );
1103:
1104: }elseif( 'gap-fill' == $type ) {
1105:
1106: $right_answer_array = explode( '||', $right_answer );
1107: if ( isset( $right_answer_array[0] ) ) { $gapfill_pre = $right_answer_array[0]; } else { $gapfill_pre = ''; }
1108: if ( isset( $right_answer_array[1] ) ) { $gapfill_gap = $right_answer_array[1]; } else { $gapfill_gap = ''; }
1109: if ( isset( $right_answer_array[2] ) ) { $gapfill_post = $right_answer_array[2]; } else { $gapfill_post = ''; }
1110:
1111: $right_answer = $gapfill_pre . ' <span class="highlight">' . $gapfill_gap . '</span> ' . $gapfill_post;
1112:
1113: }else{
1114:
1115:
1116: $right_answer = '';
1117:
1118: }
1119:
1120: return $right_answer;
1121:
1122: }
1123:
1124: }
1125:
1126: 1127: 1128: 1129: 1130:
1131: class WooThemes_Sensei_Question extends Sensei_Question{}
1132: