1: <?php
2: if ( ! defined( 'ABSPATH' ) ) exit;
3:
4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14: class Sensei_Grading {
15:
16: public $name;
17: public $file;
18: public $page_slug;
19:
20: 21: 22: 23: 24: 25:
26: public function __construct ( $file ) {
27: $this->name = __( 'Grading', 'woothemes-sensei' );
28: $this->file = $file;
29: $this->page_slug = 'sensei_grading';
30:
31:
32: if ( is_admin() ) {
33: add_action( 'admin_menu', array( $this, 'grading_admin_menu' ), 20);
34: add_action( 'grading_wrapper_container', array( $this, 'wrapper_container' ) );
35: if ( isset( $_GET['page'] ) && ( $_GET['page'] == $this->page_slug ) ) {
36: add_action( 'admin_print_scripts', array( $this, 'enqueue_scripts' ) );
37: add_action( 'admin_print_styles', array( $this, 'enqueue_styles' ) );
38: }
39:
40: add_action( 'admin_init', array( $this, 'admin_process_grading_submission' ) );
41:
42: add_action( 'admin_notices', array( $this, 'add_grading_notices' ) );
43:
44: }
45:
46:
47: if ( is_admin() ) {
48: add_action( 'wp_ajax_get_lessons_dropdown', array( $this, 'get_lessons_dropdown' ) );
49: add_action( 'wp_ajax_get_redirect_url', array( $this, 'get_redirect_url' ) );
50: }
51: }
52:
53: 54: 55: 56: 57: 58:
59: public function grading_admin_menu() {
60: global $menu;
61:
62: if ( current_user_can( 'manage_sensei_grades' ) ) {
63: $grading_page = add_submenu_page('sensei', __('Grading', 'woothemes-sensei'), __('Grading', 'woothemes-sensei') , 'manage_sensei_grades', $this->page_slug, array( $this, 'grading_page' ) );
64: }
65:
66: }
67:
68: 69: 70: 71: 72: 73: 74: 75:
76: public function enqueue_scripts () {
77:
78: $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
79:
80:
81: wp_enqueue_script( 'sensei-grading-general', Sensei()->plugin_url . 'assets/js/grading-general' . $suffix . '.js', array( 'jquery' ), Sensei()->version );
82:
83: }
84:
85: 86: 87: 88: 89: 90: 91: 92:
93: public function enqueue_styles () {
94:
95: wp_enqueue_style( Sensei()->token . '-admin' );
96:
97: wp_enqueue_style( 'woothemes-sensei-settings-api', Sensei()->plugin_url . 'assets/css/settings.css', '', Sensei()->version );
98:
99: }
100:
101: 102: 103: 104: 105:
106: public function load_data_table_files() {
107:
108:
109: $classes_to_load = array( 'list-table',
110: 'grading-main',
111: 'grading-user-quiz'
112: );
113: foreach ( $classes_to_load as $class_file ) {
114: Sensei()->load_class( $class_file );
115: }
116: }
117:
118: 119: 120: 121: 122: 123: 124: 125:
126: public function load_data_object( $name = '', $data = 0, $optional_data = null ) {
127:
128: $object_name = 'WooThemes_Sensei_Grading_' . $name;
129: if ( is_null($optional_data) ) {
130: $sensei_grading_object = new $object_name( $data );
131: }
132: else {
133: $sensei_grading_object = new $object_name( $data, $optional_data );
134: }
135: if ( 'Main' == $name ) {
136: $sensei_grading_object->prepare_items();
137: }
138: return $sensei_grading_object;
139: }
140:
141: 142: 143: 144: 145: 146:
147: public function grading_page() {
148:
149: if ( isset( $_GET['quiz_id'] ) && 0 < intval( $_GET['quiz_id'] ) && isset( $_GET['user'] ) && 0 < intval( $_GET['user'] ) ) {
150: $this->grading_user_quiz_view();
151: }
152: else {
153: $this->grading_default_view();
154: }
155: }
156:
157: 158: 159: 160: 161:
162: public function grading_default_view() {
163:
164:
165: if( !empty( $_GET['course_id'] ) ) {
166: $course_id = intval( $_GET['course_id'] );
167: }
168: if( !empty( $_GET['lesson_id'] ) ) {
169: $lesson_id = intval( $_GET['lesson_id'] );
170: }
171: if( !empty( $_GET['user_id'] ) ) {
172: $user_id = intval( $_GET['user_id'] );
173: }
174: if( !empty( $_GET['view'] ) ) {
175: $view = esc_html( $_GET['view'] );
176: }
177: $sensei_grading_overview = $this->load_data_object( 'Main', compact( 'course_id', 'lesson_id', 'user_id', 'view' ) );
178:
179:
180: do_action( 'grading_before_container' );
181: do_action( 'grading_wrapper_container', 'top' );
182: $this->grading_headers();
183: ?>
184: <div id="poststuff" class="sensei-grading-wrap">
185: <div class="sensei-grading-main">
186: <?php $sensei_grading_overview->display(); ?>
187: </div>
188: <div class="sensei-grading-extra">
189: <?php do_action( 'sensei_grading_extra' ); ?>
190: </div>
191: </div>
192: <?php
193: do_action( 'grading_wrapper_container', 'bottom' );
194: do_action( 'grading_after_container' );
195: }
196:
197: 198: 199: 200: 201:
202: public function grading_user_quiz_view() {
203:
204:
205: $user_id = 0;
206: $quiz_id = 0;
207: if( isset( $_GET['user'] ) ) {
208: $user_id = intval( $_GET['user'] );
209: }
210: if( isset( $_GET['quiz_id'] ) ) {
211: $quiz_id = intval( $_GET['quiz_id'] );
212: }
213: $sensei_grading_user_profile = $this->load_data_object( 'User_Quiz', $user_id, $quiz_id );
214:
215: do_action( 'grading_before_container' );
216: do_action( 'grading_wrapper_container', 'top' );
217: $this->grading_headers( array( 'nav' => 'user_quiz' ) );
218: ?>
219: <div id="poststuff" class="sensei-grading-wrap user-profile">
220: <div class="sensei-grading-main">
221: <?php
222: <?php $sensei_grading_user_profile->display(); ?>
223: </div>
224: </div>
225: <?php
226: do_action( 'grading_wrapper_container', 'bottom' );
227: do_action( 'grading_after_container' );
228: }
229:
230: 231: 232: 233: 234: 235:
236: public function grading_headers( $args = array( 'nav' => 'default' ) ) {
237:
238: $function = 'grading_' . $args['nav'] . '_nav';
239: $this->$function();
240: do_action( 'sensei_grading_after_headers' );
241: }
242:
243: 244: 245: 246: 247: 248:
249: public function wrapper_container( $which ) {
250: if ( 'top' == $which ) {
251: ?><div id="woothemes-sensei" class="wrap woothemes-sensei"><?php
252: } elseif ( 'bottom' == $which ) {
253: ?></div><!--/
254: }
255: }
256:
257: 258: 259: 260: 261:
262: public function grading_default_nav() {
263:
264: global $wp_version;
265:
266: $title = $this->name;
267: if ( isset( $_GET['course_id'] ) ) {
268: $course_id = intval( $_GET['course_id'] );
269: if ( version_compare($wp_version, '4.1', '>=') ) {
270: $title .= '<span class="course-title">> '.get_the_title( $course_id ).'</span>';
271: }
272: else {
273: $title .= sprintf( ' <span class="course-title">> %s</span>', get_the_title( $course_id ) );
274: }
275: }
276: if ( isset( $_GET['lesson_id'] ) ) {
277: $lesson_id = intval( $_GET['lesson_id'] );
278: $title .= ' <span class="lesson-title">> ' . get_the_title( intval( $lesson_id ) ) . '</span>';
279: }
280: if ( isset( $_GET['user_id'] ) && 0 < intval( $_GET['user_id'] ) ) {
281:
282: $user_name = Sensei_Learner::get_full_name( $_GET['user_id'] );
283: $title .= ' <span class="user-title">> ' . $user_name . '</span>';
284:
285: }
286: ?>
287: <h1><?php echo apply_filters( 'sensei_grading_nav_title', $title ); ?></h1>
288: <?php
289: }
290:
291: 292: 293: 294: 295:
296: public function grading_user_quiz_nav() {
297: global $wp_version;
298:
299: $title = $this->name;
300: if ( isset( $_GET['quiz_id'] ) ) {
301: $quiz_id = intval( $_GET['quiz_id'] );
302: $lesson_id = get_post_meta( $quiz_id, '_quiz_lesson', true );
303: $course_id = get_post_meta( $lesson_id, '_lesson_course', true );
304: if ( version_compare($wp_version, '4.1', '>=') ) {
305: $url = add_query_arg( array( 'page' => $this->page_slug, 'course_id' => $course_id ), admin_url( 'admin.php' ) );
306: $title .= sprintf( ' <span class="course-title">> <a href="%s">%s</a></span>', esc_url( $url ), get_the_title( $course_id ) );
307: }
308: else {
309: $title .= sprintf( ' <span class="course-title">> %s</span>', get_the_title( $course_id ) );
310: }
311: $url = add_query_arg( array( 'page' => $this->page_slug, 'lesson_id' => $lesson_id ), admin_url( 'admin.php' ) );
312: $title .= sprintf( ' <span class="lesson-title">> <a href="%s">%s</a></span>', esc_url( $url ), get_the_title( $lesson_id ) );
313: }
314: if ( isset( $_GET['user'] ) && 0 < intval( $_GET['user'] ) ) {
315:
316: $user_name = Sensei_Learner::get_full_name( $_GET['user'] );
317: $title .= ' <span class="user-title">> ' . $user_name . '</span>';
318:
319: }
320: ?>
321: <h2><?php echo apply_filters( 'sensei_grading_nav_title', $title ); ?></h2>
322: <?php
323: }
324:
325: 326: 327: 328: 329:
330: public function get_stati( $type ) {
331: $statuses = array();
332: switch( $type ) {
333: case 'course' :
334: $statuses = array(
335: 'in-progress',
336: 'complete',
337: );
338: break;
339:
340: case 'lesson' :
341: $statuses = array(
342: 'in-progress',
343: 'complete',
344: 'ungraded',
345: 'graded',
346: 'passed',
347: 'failed',
348: );
349: break;
350:
351: }
352: return $statuses;
353: }
354:
355: 356: 357: 358: 359: 360: 361:
362: public function count_statuses( $args = array() ) {
363: global $wpdb;
364:
365: 366: 367: 368: 369: 370: 371: 372:
373: $args = apply_filters( 'sensei_count_statuses_args', $args );
374:
375: if ( 'course' == $args['type'] ) {
376: $type = 'sensei_course_status';
377: }
378: else {
379: $type = 'sensei_lesson_status';
380: }
381: $cache_key = 'sensei-' . $args['type'] . '-statuses';
382:
383: $query = "SELECT comment_approved, COUNT( * ) AS total FROM {$wpdb->comments} WHERE comment_type = %s ";
384:
385:
386: if ( isset( $args['post__in'] ) && !empty( $args['post__in'] ) && is_array( $args['post__in'] ) ) {
387: $query .= ' AND comment_post_ID IN (' . implode( ',', array_map( 'absint', $args['post__in'] ) ) . ')';
388: }
389: elseif ( !empty( $args['post_id'] ) ) {
390: $query .= $wpdb->prepare( ' AND comment_post_ID = %d', $args['post_id'] );
391: }
392:
393: if ( isset( $args['user_id'] ) && is_array( $args['user_id'] ) ) {
394: $query .= ' AND user_id IN (' . implode( ',', array_map( 'absint', $args['user_id'] ) ) . ')';
395: }
396: elseif ( !empty( $args['user_id'] ) ) {
397: $query .= $wpdb->prepare( ' AND user_id = %d', $args['user_id'] );
398: }
399: $query .= ' GROUP BY comment_approved';
400:
401: $counts = wp_cache_get( $cache_key, 'counts' );
402: if ( false === $counts ) {
403: $sql = $wpdb->prepare( $query, $type );
404: $results = (array) $wpdb->get_results( $sql, ARRAY_A );
405: $counts = array_fill_keys( $this->get_stati( $type ), 0 );
406:
407: foreach ( $results as $row ) {
408: $counts[ $row['comment_approved'] ] = $row['total'];
409: }
410: wp_cache_set( $cache_key, $counts, 'counts' );
411: }
412:
413: if( ! isset( $counts['graded'] ) ) {
414: $counts['graded'] = 0;
415: }
416:
417: if( ! isset( $counts['ungraded'] ) ) {
418: $counts['ungraded'] = 0;
419: }
420:
421: if( ! isset( $counts['passed'] ) ) {
422: $counts['passed'] = 0;
423: }
424:
425: if( ! isset( $counts['failed'] ) ) {
426: $counts['failed'] = 0;
427: }
428:
429: if( ! isset( $counts['in-progress'] ) ) {
430: $counts['in-progress'] = 0;
431: }
432:
433: if( ! isset( $counts['complete'] ) ) {
434: $counts['complete'] = 0;
435: }
436:
437: return apply_filters( 'sensei_count_statuses', $counts, $type );
438: }
439:
440: 441: 442: 443: 444:
445: public function courses_drop_down_html( $selected_course_id = 0 ) {
446:
447: $html = '';
448:
449: $course_args = array( 'post_type' => 'course',
450: 'posts_per_page' => -1,
451: 'orderby' => 'title',
452: 'order' => 'ASC',
453: 'post_status' => 'any',
454: 'suppress_filters' => 0,
455: 'fields' => 'ids',
456: );
457: $courses = get_posts( apply_filters( 'sensei_grading_filter_courses', $course_args ) );
458:
459: $html .= '<option value="">' . __( 'Select a course', 'woothemes-sensei' ) . '</option>';
460: if ( count( $courses ) > 0 ) {
461: foreach ($courses as $course_id){
462: $html .= '<option value="' . esc_attr( absint( $course_id ) ) . '" ' . selected( $course_id, $selected_course_id, false ) . '>' . esc_html( get_the_title( $course_id ) ) . '</option>' . "\n";
463: }
464: }
465:
466: return $html;
467: }
468:
469: 470: 471: 472: 473:
474: public function get_lessons_dropdown() {
475:
476: $posts_array = array();
477:
478:
479: $data = $_POST['data'];
480: $course_data = array();
481: parse_str($data, $course_data);
482:
483: $course_id = intval( $course_data['course_id'] );
484:
485: $html = $this->lessons_drop_down_html( $course_id );
486:
487: echo $html;
488: die();
489: }
490:
491: public function lessons_drop_down_html( $course_id = 0, $selected_lesson_id = 0 ) {
492:
493: $html = '';
494: if ( 0 < intval( $course_id ) ) {
495:
496: $lesson_args = array( 'post_type' => 'lesson',
497: 'posts_per_page' => -1,
498: 'orderby' => 'title',
499: 'order' => 'ASC',
500: 'meta_key' => '_lesson_course',
501: 'meta_value' => $course_id,
502: 'post_status' => 'publish',
503: 'suppress_filters' => 0,
504: 'fields' => 'ids',
505: );
506: $lessons = get_posts( apply_filters( 'sensei_grading_filter_lessons', $lesson_args ) );
507:
508: $html .= '<option value="">' . __( 'Select a lesson', 'woothemes-sensei' ) . '</option>';
509: if ( count( $lessons ) > 0 ) {
510: foreach ( $lessons as $lesson_id ){
511: $html .= '<option value="' . esc_attr( absint( $lesson_id ) ) . '" ' . selected( $lesson_id, $selected_lesson_id, false ) . '>' . esc_html( get_the_title( $lesson_id ) ) . '</option>' . "\n";
512: }
513: }
514:
515: }
516:
517: return $html;
518: }
519:
520: 521: 522: 523: 524: 525: 526: 527: 528:
529: public function admin_process_grading_submission() {
530:
531:
532: if( ! isset( $_POST['sensei_manual_grade'] )
533: || ! wp_verify_nonce( $_POST['_wp_sensei_manual_grading_nonce'], 'sensei_manual_grading' )
534: || ! isset( $_GET['quiz_id'] )
535: || $_GET['quiz_id'] != $_POST['sensei_manual_grade'] ) {
536:
537: return false;
538:
539: }
540:
541: $quiz_id = $_GET['quiz_id'];
542: $user_id = $_GET['user'];
543:
544:
545: $questions = Sensei_Utils::sensei_get_quiz_questions( $quiz_id );
546: $quiz_lesson_id = Sensei()->quiz->get_lesson_id( $quiz_id );
547: $quiz_grade = 0;
548: $count = 0;
549: $quiz_grade_total = $_POST['quiz_grade_total'];
550: $all_question_grades = array();
551: $all_answers_feedback = array();
552:
553: foreach( $questions as $question ) {
554:
555: ++$count;
556: $question_id = $question->ID;
557:
558: if( isset( $_POST[ 'question_' . $question_id ] ) ) {
559:
560: $question_grade = 0;
561: if( $_POST[ 'question_' . $question_id ] == 'right' ) {
562:
563: $question_grade = $_POST[ 'question_' . $question_id . '_grade' ];
564:
565: }
566:
567:
568: $all_question_grades[ $question_id ] = $question_grade;
569:
570:
571: $quiz_grade += $question_grade;
572:
573: }
574:
575:
576: $question_feedback = '';
577: if( isset( $_POST[ 'questions_feedback' ][ $question_id ] ) ){
578:
579: $question_feedback = wp_unslash( $_POST[ 'questions_feedback' ][ $question_id ] );
580:
581: }
582: $all_answers_feedback[ $question_id ] = $question_feedback;
583:
584: }
585:
586:
587: Sensei()->quiz->set_user_grades( $all_question_grades, $quiz_lesson_id , $user_id );
588:
589:
590: Sensei()->quiz->save_user_answers_feedback( $all_answers_feedback, $quiz_lesson_id , $user_id );
591:
592:
593:
594: if( $_POST['all_questions_graded'] == 'yes' ) {
595:
596:
597: if ( 0 < intval( $quiz_grade_total ) ) {
598: $grade = abs( round( ( doubleval( $quiz_grade ) * 100 ) / ( $quiz_grade_total ), 2 ) );
599: }
600: else {
601: $grade = 0;
602: }
603: Sensei_Utils::sensei_grade_quiz( $quiz_id, $grade, $user_id );
604:
605:
606: $pass_required = get_post_meta( $quiz_id, '_pass_required', true );
607: $quiz_passmark = abs( round( doubleval( get_post_meta( $quiz_id, '_quiz_passmark', true ) ), 2 ) );
608: $lesson_metadata = array();
609: if ( $pass_required ) {
610:
611: if ( $quiz_passmark <= $grade ) {
612: $lesson_status = 'passed';
613: }
614: else {
615: $lesson_status = 'failed';
616: }
617: }
618:
619: else {
620: $lesson_status = 'graded';
621: }
622: $lesson_metadata['grade'] = $grade;
623:
624: Sensei_Utils::update_lesson_status( $user_id, $quiz_lesson_id, $lesson_status, $lesson_metadata );
625:
626: if( in_array( $lesson_status, array( 'passed', 'graded' ) ) ) {
627:
628: 629: 630: 631: 632: 633: 634: 635: 636: 637:
638: do_action( 'sensei_user_lesson_end', $user_id, $quiz_lesson_id );
639:
640: }
641:
642: }
643:
644: if( isset( $_POST['sensei_grade_next_learner'] ) && strlen( $_POST['sensei_grade_next_learner'] ) > 0 ) {
645:
646: $load_url = add_query_arg( array( 'message' => 'graded' ) );
647:
648: } elseif ( isset( $_POST['_wp_http_referer'] ) ) {
649:
650: $load_url = add_query_arg( array( 'message' => 'graded' ), $_POST['_wp_http_referer'] );
651:
652: } else {
653:
654: $load_url = add_query_arg( array( 'message' => 'graded' ) );
655:
656: }
657:
658: wp_safe_redirect( esc_url_raw( $load_url ) );
659: exit;
660:
661: }
662:
663: public function get_redirect_url() {
664:
665: $data = $_POST['data'];
666: $lesson_data = array();
667: parse_str($data, $lesson_data);
668:
669: $lesson_id = intval( $lesson_data['lesson_id'] );
670: $course_id = intval( $lesson_data['course_id'] );
671: $grading_view = sanitize_text_field( $lesson_data['view'] );
672:
673: $redirect_url = '';
674: if ( 0 < $lesson_id && 0 < $course_id ) {
675: $redirect_url = esc_url_raw( apply_filters( 'sensei_ajax_redirect_url', add_query_arg( array( 'page' => $this->page_slug, 'lesson_id' => $lesson_id, 'course_id' => $course_id, 'view' => $grading_view ), admin_url( 'admin.php' ) ) ) );
676: }
677:
678: echo $redirect_url;
679: die();
680: }
681:
682: public function add_grading_notices() {
683: if( isset( $_GET['page'] ) && $this->page_slug == $_GET['page'] && isset( $_GET['message'] ) && $_GET['message'] ) {
684: if( 'graded' == $_GET['message'] ) {
685: $msg = array(
686: 'updated',
687: __( 'Quiz Graded Successfully!', 'woothemes-sensei' ),
688: );
689: }
690: ?>
691: <div class="grading-notice <?php echo $msg[0]; ?>">
692: <p><?php echo $msg[1]; ?></p>
693: </div>
694: <?php
695: }
696: }
697:
698: public function sensei_grading_notices() {
699: if ( isset( $_GET['action'] ) && 'graded' == $_GET['action'] ) {
700: echo '<div class="grading-notice updated">';
701: echo '<p>' . __( 'Quiz Graded Successfully!', 'woothemes-sensei' ) . '</p>';
702: echo '</div>';
703: }
704: }
705:
706: 707: 708: 709: 710: 711: 712: 713: 714: 715: 716: 717: 718: 719: 720: 721: 722: 723:
724: public static function grade_quiz_auto( $quiz_id = 0, $submitted = array(), $total_questions = 0, $quiz_grade_type = 'auto' ) {
725:
726: if( ! ( intval( $quiz_id ) > 0 ) || ! $submitted
727: || $quiz_grade_type != 'auto' ) {
728: return false;
729: }
730:
731:
732: $user_id = get_current_user_id();
733: $lesson_id = Sensei()->quiz->get_lesson_id( $quiz_id ) ;
734: $quiz_autogradable = true;
735:
736: 737: 738: 739: 740: 741: 742: 743: 744: 745: 746:
747: $autogradable_question_types = apply_filters( 'sensei_autogradable_question_types', array( 'multiple-choice', 'boolean', 'gap-fill' ) );
748:
749: $grade_total = 0;
750: $all_question_grades = array();
751: foreach( $submitted as $question_id => $answer ) {
752:
753:
754: $question_type = Sensei()->question->get_question_type( $question_id );
755: $achievable_grade = Sensei()->question->get_question_grade( $question_id );
756:
757: if ( 0 == $achievable_grade ) {
758: $all_question_grades[ $question_id ] = $achievable_grade;
759: }
760: elseif ( in_array( $question_type, $autogradable_question_types ) ) {
761:
762: $question_grade = Sensei_Utils::sensei_grade_question_auto( $question_id, $question_type, $answer, $user_id );
763: $all_question_grades[ $question_id ] = $question_grade;
764: $grade_total += $question_grade;
765:
766: } else {
767:
768:
769: $quiz_autogradable = false;
770:
771: }
772:
773: }
774:
775:
776: if ( $quiz_autogradable ) {
777:
778: $quiz_total = Sensei_Utils::sensei_get_quiz_total( $quiz_id );
779:
780: if ( 0 < $quiz_total ) {
781: $grade = abs( round( ( doubleval( $grade_total ) * 100 ) / ( $quiz_total ), 2 ) );
782: }
783: else {
784: $grade = 0;
785: }
786: Sensei_Utils::sensei_grade_quiz( $quiz_id, $grade, $user_id, $quiz_grade_type );
787:
788: } else {
789:
790: $grade = new WP_Error( 'autograde', __( 'This quiz is not able to be automatically graded.', 'woothemes-sensei' ) );
791:
792: }
793:
794:
795:
796: Sensei()->quiz-> set_user_grades( $all_question_grades, $lesson_id, $user_id );
797:
798: return $grade;
799:
800: }
801:
802: 803: 804: 805: 806: 807: 808: 809: 810: 811: 812: 813: 814: 815:
816: public static function grade_question_auto( $question_id = 0, $question_type = '', $answer = '', $user_id = 0 ) {
817:
818: if( intval( $user_id ) == 0 ) {
819:
820: $user_id = get_current_user_id();
821:
822: }
823:
824: if( ! ( intval( $question_id ) > 0 ) ) {
825:
826: return false;
827:
828: }
829:
830:
831: Sensei()->question->get_question_type( $question_id );
832:
833: 834: 835: 836: 837: 838: 839: 840: 841: 842: 843: 844:
845: $question_grade = apply_filters( 'sensei_pre_grade_question_auto', false, $question_id, $question_type, $answer );
846:
847: if ( false !== $question_grade ) {
848:
849: return $question_grade;
850:
851: }
852:
853:
854: if( in_array( $question_type , array( 'multiple-choice' , 'boolean' ) ) ){
855:
856: $right_answer = (array) get_post_meta( $question_id, '_question_right_answer', true );
857:
858: if( 0 == get_magic_quotes_gpc() ) {
859: $answer = wp_unslash( $answer );
860: }
861: $answer = (array) $answer;
862: if ( is_array( $right_answer ) && count( $right_answer ) == count( $answer ) ) {
863:
864: $all_correct = true;
865: foreach ( $answer as $check_answer ) {
866: if ( !in_array( $check_answer, $right_answer ) ) {
867: $all_correct = false;
868: }
869: }
870:
871: if ( $all_correct ) {
872: $question_grade = Sensei()->question->get_question_grade( $question_id );
873: }
874: }
875:
876: } elseif( 'gap-fill' == $question_type ){
877:
878: $question_grade = self::grade_gap_fill_question( $question_id ,$answer );
879:
880: } else{
881:
882: 883: 884: 885: 886: 887: 888: 889: 890: 891: 892:
893: $question_grade = ( int ) apply_filters( 'sensei_grade_question_auto', $question_grade, $question_id, $question_type, $answer );
894:
895: }
896:
897: return $question_grade;
898: }
899:
900: 901: 902: 903: 904: 905: 906: 907: 908:
909: public static function grade_gap_fill_question( $question_id, $user_answer ){
910:
911: $right_answer = get_post_meta( $question_id, '_question_right_answer', true );
912: $gapfill_array = explode( '||', $right_answer );
913:
914: if( 0 == get_magic_quotes_gpc() ) {
915: $user_answer = wp_unslash( $user_answer );
916: }
917:
918: 919: 920: 921: 922: 923: 924: 925: 926: 927:
928: $do_case_sensitive_comparison = apply_filters('sensei_gap_fill_case_sensitive_grading', false );
929:
930: if( $do_case_sensitive_comparison ){
931:
932:
933: if ( trim(($gapfill_array[1])) == trim( $user_answer ) ) {
934:
935: return Sensei()->question->get_question_grade( $question_id );
936:
937: } else if (@preg_match('/' . $gapfill_array[1] . '/i', null) !== FALSE) {
938:
939: if (preg_match('/' . $gapfill_array[1] . '/i', $user_answer)) {
940:
941: return Sensei()->question->get_question_grade($question_id);
942:
943: }else{
944:
945: return false;
946:
947: }
948:
949: }else{
950:
951: return false;
952:
953: }
954:
955: }else{
956:
957:
958: if ( trim(strtolower($gapfill_array[1])) == trim(strtolower( $user_answer )) ) {
959:
960: return Sensei()->question->get_question_grade( $question_id );
961:
962: } else if (@preg_match('/' . $gapfill_array[1] . '/i', null) !== FALSE) {
963:
964: if (preg_match('/' . $gapfill_array[1] . '/i', $user_answer)) {
965:
966: return Sensei()->question->get_question_grade( $question_id );
967:
968: }else{
969:
970: return false;
971:
972: }
973:
974: }else{
975:
976: return false;
977:
978: }
979:
980: }
981:
982: }
983:
984: 985: 986: 987: 988: 989:
990: public static function get_graded_lessons_count(){
991:
992: global $wpdb;
993:
994: $comment_query_piece[ 'select'] = "SELECT COUNT(*) AS total";
995: $comment_query_piece[ 'from'] = " FROM {$wpdb->comments} INNER JOIN {$wpdb->commentmeta} ON ( {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id ) ";
996: $comment_query_piece[ 'where'] = " WHERE {$wpdb->comments}.comment_type IN ('sensei_lesson_status') AND ( {$wpdb->commentmeta}.meta_key = 'grade')";
997: $comment_query_piece[ 'orderby'] = " ORDER BY {$wpdb->comments}.comment_date_gmt DESC ";
998:
999: $comment_query = $comment_query_piece['select'] . $comment_query_piece['from'] . $comment_query_piece['where'] . $comment_query_piece['orderby'];
1000: $number_of_graded_lessons = intval( $wpdb->get_var( $comment_query, 0, 0 ) );
1001:
1002: return $number_of_graded_lessons;
1003: }
1004:
1005: 1006: 1007: 1008: 1009: 1010:
1011: public static function get_graded_lessons_sum(){
1012:
1013: global $wpdb;
1014:
1015: $comment_query_piece[ 'select'] = "SELECT SUM({$wpdb->commentmeta}.meta_value) AS meta_sum";
1016: $comment_query_piece[ 'from'] = " FROM {$wpdb->comments} INNER JOIN {$wpdb->commentmeta} ON ( {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id ) ";
1017: $comment_query_piece[ 'where'] = " WHERE {$wpdb->comments}.comment_type IN ('sensei_lesson_status') AND ( {$wpdb->commentmeta}.meta_key = 'grade')";
1018: $comment_query_piece[ 'orderby'] = " ORDER BY {$wpdb->comments}.comment_date_gmt DESC ";
1019:
1020: $comment_query = $comment_query_piece['select'] . $comment_query_piece['from'] . $comment_query_piece['where'] . $comment_query_piece['orderby'];
1021: $sum_of_all_grades = intval( $wpdb->get_var( $comment_query, 0, 0 ) );
1022:
1023: return $sum_of_all_grades;
1024:
1025: }
1026:
1027: 1028: 1029: 1030: 1031: 1032: 1033:
1034: public static function get_user_graded_lessons_sum( $user_id ){
1035: global $wpdb;
1036:
1037: $clean_user_id = esc_sql( $user_id);
1038: $comment_query_piece[ 'select'] = "SELECT SUM({$wpdb->commentmeta}.meta_value) AS meta_sum";
1039: $comment_query_piece[ 'from'] = " FROM {$wpdb->comments} INNER JOIN {$wpdb->commentmeta} ON ( {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id ) ";
1040: $comment_query_piece[ 'where'] = " WHERE {$wpdb->comments}.comment_type IN ('sensei_lesson_status') AND ( {$wpdb->commentmeta}.meta_key = 'grade') AND {$wpdb->comments}.user_id = {$clean_user_id} ";
1041: $comment_query_piece[ 'orderby'] = " ORDER BY {$wpdb->comments}.comment_date_gmt DESC ";
1042:
1043: $comment_query = $comment_query_piece['select'] . $comment_query_piece['from'] . $comment_query_piece['where'] . $comment_query_piece['orderby'];
1044: $sum_of_all_grades = intval( $wpdb->get_var( $comment_query, 0, 0 ) );
1045:
1046: return $sum_of_all_grades;
1047: }
1048:
1049: 1050: 1051: 1052: 1053: 1054: 1055: 1056:
1057: public static function get_lessons_users_grades_sum( $lesson_id ){
1058:
1059: global $wpdb;
1060:
1061: $clean_lesson_id = esc_sql( $lesson_id);
1062: $comment_query_piece[ 'select'] = "SELECT SUM({$wpdb->commentmeta}.meta_value) AS meta_sum";
1063: $comment_query_piece[ 'from'] = " FROM {$wpdb->comments} INNER JOIN {$wpdb->commentmeta} ON ( {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id ) ";
1064: $comment_query_piece[ 'where'] = " WHERE {$wpdb->comments}.comment_type IN ('sensei_lesson_status') AND ( {$wpdb->commentmeta}.meta_key = 'grade') AND {$wpdb->comments}.comment_post_ID = {$clean_lesson_id} ";
1065: $comment_query_piece[ 'orderby'] = " ORDER BY {$wpdb->comments}.comment_date_gmt DESC ";
1066:
1067: $comment_query = $comment_query_piece['select'] . $comment_query_piece['from'] . $comment_query_piece['where'] . $comment_query_piece['orderby'];
1068: $sum_of_all_grades = intval( $wpdb->get_var( $comment_query, 0, 0 ) );
1069:
1070: return $sum_of_all_grades;
1071:
1072: }
1073:
1074: 1075: 1076: 1077: 1078: 1079: 1080: 1081:
1082: public static function get_course_users_grades_sum( $course_id ){
1083:
1084: global $wpdb;
1085:
1086: $clean_course_id = esc_sql( $course_id);
1087: $comment_query_piece[ 'select'] = "SELECT SUM({$wpdb->commentmeta}.meta_value) AS meta_sum";
1088: $comment_query_piece[ 'from'] = " FROM {$wpdb->comments} INNER JOIN {$wpdb->commentmeta} ON ( {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id ) ";
1089: $comment_query_piece[ 'where'] = " WHERE {$wpdb->comments}.comment_type IN ('sensei_course_status') AND ( {$wpdb->commentmeta}.meta_key = 'percent') AND {$wpdb->comments}.comment_post_ID = {$clean_course_id} ";
1090: $comment_query_piece[ 'orderby'] = " ORDER BY {$wpdb->comments}.comment_date_gmt DESC ";
1091:
1092: $comment_query = $comment_query_piece['select'] . $comment_query_piece['from'] . $comment_query_piece['where'] . $comment_query_piece['orderby'];
1093: $sum_of_all_grades = intval( $wpdb->get_var( $comment_query, 0, 0 ) );
1094:
1095: return $sum_of_all_grades;
1096:
1097: }
1098:
1099: }
1100:
1101: 1102: 1103: 1104: 1105:
1106: class WooThemes_Sensei_Grading extends Sensei_Grading{}
1107: