PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 3.9.3
Tutor LMS – eLearning and online course solution v3.9.3
3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / views / quiz / attempt-details.php
tutor / views / quiz Last commit date
header-context 9 months ago attempt-details.php 9 months ago attempt-table.php 9 months ago contexts.php 3 years ago header.php 11 months ago instructor-feedback.php 11 months ago
attempt-details.php
768 lines
1 <?php
2 /**
3 * Attempt details page
4 *
5 * @package Tutor\Views
6 * @subpackage Tutor\Quiz
7 * @author Themeum <support@themeum.com>
8 * @link https://themeum.com
9 * @since 1.0.0
10 */
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit;
14 }
15
16 use Tutor\Models\QuizModel;
17
18 $enabled_hide_quiz_details = tutor_utils()->get_option( 'hide_quiz_details' );
19 if ( ! is_admin() && ! current_user_can( 'tutor_instructor' ) && true === $enabled_hide_quiz_details ) {
20 exit;
21 }
22
23 //phpcs:ignore
24 extract( $data ); // $user_id, $attempt_id, $attempt_data(nullable), $context(nullable)
25
26 ! isset( $attempt_data ) ? $attempt_data = tutor_utils()->get_attempt( $attempt_id ) : 0;
27 ! isset( $context ) ? $context = null : 0;
28
29 if ( ! $attempt_id || ! $attempt_data || $user_id != $attempt_data->user_id ) {
30 tutor_utils()->tutor_empty_state( __( 'Attempt not found or access permission denied', 'tutor' ) );
31 return;
32 }
33
34 if ( isset( $user_id ) && $user_id > 0 ) {
35 $user = get_userdata( $user_id );
36 if ( ! $user ) {
37 return;
38 }
39 }
40
41 /**
42 * Render answer list
43 *
44 * @param array $answers answers.
45 * @param boolean $dump_data dump data.
46 *
47 * @return void
48 */
49 function tutor_render_answer_list( $answers = array(), $dump_data = false ) {
50 if ( ! empty( $answers ) ) {
51
52 echo '<div class="correct-answer-wrap">';
53
54 $multi_texts = array();
55 foreach ( $answers as $key => $ans ) {
56 $type = isset( $ans->answer_view_format ) ? $ans->answer_view_format : 'text_image';
57
58 if ( ! empty( $ans->answer_two_gap_match ) ) {
59 echo '<div class="matching-type">';
60 }
61
62 switch ( $type ) {
63 case 'text_image':
64 echo '<div class="text-image-type tutor-mb-4">';
65 if ( isset( $ans->image_id ) ) {
66 $img_url = wp_get_attachment_image_url( $ans->image_id );
67 if ( $img_url ) {
68 echo '<span class="image"><img src="' . esc_url( $img_url ) . '" /></span>';
69 }
70 }
71 if ( isset( $ans->answer_title ) ) {
72 echo '<span class="caption">' . esc_html( stripslashes( $ans->answer_title ) ) . '</span>';
73 }
74 echo '</div>';
75 break;
76
77 case 'text':
78 $ans_string = '<span class="tutor-fs-7 tutor-fw-medium tutor-color-black">'
79 . esc_html( stripslashes( $ans->answer_title ) ) .
80 '</span>';
81
82 if ( isset( $ans->answer_title ) && empty( $ans->answer_two_gap_match ) ) {
83 $multi_texts[ $ans->answer_title ] = $ans_string;
84 } else {
85 echo $ans_string; //phpcs:ignore -- contain safe data
86 }
87 break;
88
89 case 'image':
90 echo '<div class="image-type">';
91 if ( isset( $ans->image_id ) ) {
92 $img_url = wp_get_attachment_image_url( $ans->image_id );
93 if ( $img_url ) {
94 echo '
95 <span class="image">
96 <img src="' . esc_url( $img_url ) . '" />
97 <span>';
98 }
99 }
100 echo '</div>';
101 break;
102 }
103
104 if ( ! empty( $ans->answer_two_gap_match ) ) {
105 echo '<div class="image-match">' . esc_html( stripslashes( $ans->answer_two_gap_match ) ) . '</div>';
106 echo '</div>';
107 }
108 }
109 //phpcs:ignore
110 echo count( $multi_texts ) ? implode( ', ', $multi_texts ) : '';
111
112 echo '</div>';
113 }
114 }
115
116 /**
117 * Render fill in the blank answer
118 *
119 * @param mixed $get_db_answers_by_question get db answers by question.
120 * @param mixed $answer_titles ans titles.
121 *
122 * @return void
123 */
124 function tutor_render_fill_in_the_blank_answer( $get_db_answers_by_question, $answer_titles ) {
125
126 $spaces = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
127
128 // Loop through the answers.
129 foreach ( $get_db_answers_by_question as $db_answer ) {
130 $count_dash_fields = substr_count( $db_answer->answer_title, '{dash}' );
131
132 if ( $count_dash_fields ) {
133 $dash_string = array();
134 $input_data = array();
135 for ( $i = 0; $i < $count_dash_fields; $i++ ) {
136 $ans_title = ( ! empty( $answer_titles[ $i ] ) && ! ctype_space( $answer_titles[ $i ] ) ) ? $answer_titles[ $i ] : null;
137 $input_data[] = $ans_title ? "<span class='filled_dash_unser'>{$ans_title}</span>" : $spaces;
138 }
139
140 $answer_title = $db_answer->answer_title;
141
142 foreach ( $input_data as $index => $replace ) {
143 $replace = '<span style="text-decoration:underline;">' . $replace . '</span>';
144 $answer_title = preg_replace( '/{dash}/i', $replace, $answer_title, 1 );
145 }
146 echo wp_kses(
147 str_replace( '{dash}', "<span class='filled_dash_unser'>{$spaces}</span>", stripslashes( $answer_title ) ),
148 array(
149 'span' => array(
150 'style' => true,
151 'class' => true,
152 ),
153 )
154 );
155 }
156 }
157 }
158
159 // Prepare student data.
160 if ( ! isset( $user_data ) ) {
161 $user_data = get_userdata( $user_id );
162 }
163
164 //phpcs:ignore
165 extract( QuizModel::get_quiz_attempt_timing( $attempt_data ) ); // $attempt_duration, $attempt_duration_taken;
166
167 // Prepare the correct/incorrect answer count for the first summary table.
168 $answers = QuizModel::get_quiz_answers_by_attempt_id( $attempt_id );
169 $correct = 0;
170 $incorrect = 0;
171 if ( is_array( $answers ) && count( $answers ) > 0 ) {
172 foreach ( $answers as $answer ) {
173 if ( (bool) isset( $answer->is_correct ) ? $answer->is_correct : '' ) {
174 $correct++;
175 } elseif ( 'open_ended' === $answer->question_type || 'short_answer' === $answer->question_type ) {
176 } else {
177 $incorrect++;
178 }
179 }
180 }
181
182 // Prepare the column list for the first summary table.
183 $page_key = 'attempt-details-summary';
184 $table_1_columns = include __DIR__ . '/contexts.php';
185
186 // Prepare the column list for the second table (eery single answer list).
187 $page_key = 'attempt-details-answers';
188 $table_2_columns = include __DIR__ . '/contexts.php';
189
190 require __DIR__ . '/header.php';
191
192 $attempt_info = @unserialize( $attempt_data->attempt_info );
193
194 if ( is_array( $attempt_info ) ) {
195 $attempt_type = '';
196 // Allowed duration.
197 if ( isset( $attempt_info['time_limit'] ) ) {
198 $attempt_duration = tutor_utils()->second_to_formated_time( $attempt_info['time_limit']['time_limit_seconds'], $attempt_info['time_limit']['time_type'] );
199 }
200 if ( 'days' === $attempt_info['time_limit']['time_type'] ) {
201 $attempt_type = 'hours';
202 }
203 if ( 'hours' === $attempt_info['time_limit']['time_type'] ) {
204 $attempt_type = 'minutes';
205 }
206 if ( 'minutes' === $attempt_info['time_limit']['time_type'] ) {
207 $attempt_type = 'minutes';
208 }
209
210 // Taken duration.
211 $seconds = strtotime( $attempt_data->attempt_ended_at ) - strtotime( $attempt_data->attempt_started_at );
212 $attempt_duration_taken = tutor_utils()->second_to_formated_time( $seconds, $attempt_type );
213 }
214 ?>
215
216 <?php echo is_admin() ? '<div class="tutor-admin-body">' : ''; ?>
217 <div class="tutor-table-responsive tutor-table-mobile tutor-mb-32">
218 <table class="tutor-table tutor-quiz-attempt-details">
219 <thead>
220 <tr>
221 <?php foreach ( $table_1_columns as $key => $column ) : ?>
222 <th><?php echo $column; //phpcs:ignore --contain safe data ?></th>
223 <?php endforeach; ?>
224 </tr>
225 </thead>
226
227 <tbody>
228 <tr>
229 <?php foreach ( $table_1_columns as $key => $column ) : ?>
230 <td data-title="<?php echo esc_attr( $column ); ?>">
231 <?php if ( 'user' == $key ) : ?>
232 <div class="tutor-d-flex tutor-align-center">
233 <?php
234 echo wp_kses(
235 tutor_utils()->get_tutor_avatar( $user_id ),
236 tutor_utils()->allowed_avatar_tags()
237 );
238 ?>
239 <div class="tutor-ml-16">
240 <div>
241 <?php
242 echo esc_html(
243 $user_data ? $user_data->display_name : ''
244 );
245 ?>
246 </div>
247 <a href="<?php echo esc_url( tutor_utils()->profile_url( $user_id, false ) ); ?>" class="tutor-iconic-btn">
248 <span class="tutor-icon-external-link"></span>
249 </a>
250 </div>
251 </div>
252
253 <?php elseif ( 'date' == $key ) : ?>
254 <?php echo esc_html( date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), strtotime( $attempt_data->attempt_started_at ) ) ); ?>
255 <?php elseif ( 'qeustion_count' === $key ) : ?>
256 <?php echo esc_html( $attempt_data->total_questions ); ?>
257 <?php elseif ( 'quiz_time' === $key ) : ?>
258 <?php echo esc_html( $attempt_duration ); ?>
259 <?php elseif ( 'attempt_time' === $key ) : ?>
260 <?php echo esc_html( $attempt_duration_taken ); ?>
261 <?php elseif ( 'total_marks' === $key ) : ?>
262 <?php echo esc_html( $attempt_data->total_marks ); ?>
263 <?php elseif ( 'pass_marks' === $key ) : ?>
264 <?php
265 $pass_marks = ( $total_marks * $passing_grade ) / 100;
266 echo esc_html( number_format_i18n( $pass_marks, 2 ) );
267
268 $pass_mark_percent = $passing_grade;
269 echo esc_html( ' (' . $pass_mark_percent . '%)' );
270 ?>
271 <?php elseif ( 'correct_answer' === $key ) : ?>
272 <?php echo esc_html( $correct ); ?>
273 <?php elseif ( 'incorrect_answer' === $key ) : ?>
274 <?php echo esc_html( $incorrect ); ?>
275 <?php elseif ( 'earned_marks' === $key ) : ?>
276 <?php
277 $earned_percentage = QuizModel::calculate_attempt_earned_percentage( $attempt_data );
278 echo esc_html( $attempt_data->earned_marks );
279 echo esc_html( ' (' . $earned_percentage . '%)' );
280 ?>
281 <?php elseif ( 'result' === $key ) : ?>
282 <?php
283 $attempt_result = QuizModel::get_attempt_result( $attempt_data->attempt_id );
284
285 if ( QuizModel::RESULT_PENDING === $attempt_result ) {
286 echo '<span class="tutor-badge-label label-warning">' . esc_html__( 'Pending', 'tutor' ) . '</span>';
287 } elseif ( QuizModel::RESULT_PASS === $attempt_result ) {
288 echo '<span class="tutor-badge-label label-success">' . esc_html__( 'Pass', 'tutor' ) . '</span>';
289 } else {
290 echo '<span class="tutor-badge-label label-danger">' . esc_html__( 'Fail', 'tutor' ) . '</span>';
291 }
292 ?>
293 <?php endif; ?>
294 </td>
295 <?php endforeach; ?>
296 </tr>
297 </tbody>
298 </table>
299 </div>
300
301 <?php
302 // instructor feedback.
303 global $wp_query;
304 $query_vars = $wp_query->query_vars;
305 $page_name = isset( $query_vars['tutor_dashboard_page'] ) ? $query_vars['tutor_dashboard_page'] : '';
306 $attempt_info = maybe_unserialize( $attempt_data->attempt_info );
307 $feedback = is_array( $attempt_info ) && isset( $attempt_info['instructor_feedback'] ) ? $attempt_info['instructor_feedback'] : '';
308 // don't show on instructor quiz attempt since below already have feedback box area.
309 if ( '' !== $feedback && 'my-quiz-attempts' === $page_name ) {
310 ?>
311 <div class="tutor-quiz-attempt-note tutor-instructor-note tutor-my-32 tutor-py-20 tutor-px-24 tutor-py-sm-32 tutor-px-sm-36">
312 <div class="tutor-in-title tutor-fs-6 tutor-fw-medium tutor-color-black">
313 <?php esc_html_e( 'Instructor Note', 'tutor' ); ?>
314 </div>
315 <div class="tutor-in-body tutor-fs-6 tutor-color-secondary tutor-pt-12 tutor-pt-sm-16">
316 <?php echo wp_kses_post( $feedback ); ?>
317 </div>
318 </div>
319 <?php } ?>
320
321 <?php
322 if ( is_array( $answers ) && count( $answers ) ) {
323 // Filter out not needed columns based on question type.
324 $table_2_columns = apply_filters( 'tutor_filter_attempt_answer_column', $table_2_columns, $answers );
325 $answers = apply_filters( 'tutor_filter_attempt_answers', $answers );
326 echo 'course-single-previous-attempts' !== $context ? '<div class="tutor-fs-6 tutor-fw-medium tutor-color-black tutor-mt-24">' . esc_html__( 'Quiz Overview', 'tutor' ) . '</div>' : '';
327 ?>
328 <div class="tutor-table-responsive tutor-table-mobile tutor-mt-16">
329 <table class="tutor-table tutor-quiz-attempt-details tutor-mb-32 tutor-table-data-td-target">
330 <thead>
331 <tr>
332 <?php foreach ( $table_2_columns as $key => $column ) : ?>
333 <th><?php echo $column; //phpcs:ignore --contain safe data ?></th>
334 <?php endforeach; ?>
335 </tr>
336 </thead>
337
338 <tbody>
339 <?php
340 $answer_i = 0;
341 foreach ( $answers as $answer ) {
342 $answer_i++;
343 $question_type = tutor_utils()->get_question_types( $answer->question_type );
344 $question_settings = maybe_unserialize( $answer->question_settings );
345 $is_image_matching = isset( $question_settings['is_image_matching'] ) && '1' === $question_settings['is_image_matching'];
346 $answer_status = 'wrong';
347
348 // If already correct, then show it.
349 if ( (bool) $answer->is_correct ) {
350 $answer_status = 'correct';
351 }
352
353 // Image answering also needs review since the answer texts are not meant to match exactly.
354 elseif ( in_array( $answer->question_type, array( 'open_ended', 'short_answer', 'image_answering' ), true ) ) {
355 $answer_status = null === $answer->is_correct ? 'pending' : 'wrong';
356 }
357 ?>
358
359 <tr class="tutor-quiz-answer-status-<?php echo esc_html( $answer_status ); ?>">
360 <?php foreach ( $table_2_columns as $key => $column ) : ?>
361 <?php
362 switch ( $key ) {
363 case 'no':
364 ?>
365 <td class="no" data-title="<?php echo esc_attr( $column ); ?>">
366 <span class="tutor-fs-7 tutor-fw-medium tutor-color-black">
367 <?php echo esc_html( $answer_i ); ?>
368 </span>
369 </td>
370 <?php
371 break;
372
373 case 'type':
374 ?>
375 <td class="type" data-title="<?php echo esc_attr( $column ); ?>">
376 <?php $type = tutor_utils()->get_question_types( $answer->question_type ); ?>
377 <?php ob_start(); ?>
378 <div class="tooltip-wrap tooltip-icon tutor-d-flex tutor-align-center">
379 <?php
380 echo wp_kses(
381 $question_type['icon'] ?? '',
382 tutor_utils()->allowed_icon_tags()
383 );
384 ?>
385 <span class="tooltip-txt tooltip-top">
386 <?php
387 echo esc_html( $type['name'] ?? '' );
388 ?>
389 </span>
390 </div>
391 <?php echo wp_kses_post( apply_filters( 'tutor_question_type_icon', ob_get_clean(), $answer ) ); ?>
392 </td>
393 <?php
394 break;
395
396 case 'questions':
397 ?>
398 <td class="questions" data-title="<?php echo esc_attr( $column ); ?>">
399 <span class="tutor-fs-7 tutor-fw-medium tutor-d-flex tutor-align-center">
400 <?php echo esc_html( stripslashes( $answer->question_title ) ); ?>
401 </span>
402 </td>
403 <?php
404 break;
405
406 case 'given_answer':
407 ?>
408 <td class="given-answer" data-title="<?php echo esc_attr( $column ); ?>">
409 <div>
410 <?php
411 // Single choice.
412 if ( 'single_choice' === $answer->question_type ) {
413 $get_answers = tutor_utils()->get_answer_by_id( $answer->given_answer );
414 tutor_render_answer_list( $get_answers );
415 }
416
417
418 // True false or single choice.
419 if ( 'true_false' === $answer->question_type ) {
420 $get_answers = tutor_utils()->get_answer_by_id( $answer->given_answer );
421 $answer_titles = wp_list_pluck( $get_answers, 'answer_title' );
422 $answer_titles = array_map( 'stripslashes', $answer_titles );
423
424 echo '<span class="tutor-fs-7 tutor-fw-medium tutor-color-black">' .
425 implode( '</p><p>', $answer_titles ) . //phpcs:ignore
426 '</span>';
427 }
428
429 // Multiple choice.
430 elseif ( 'multiple_choice' === $answer->question_type ) {
431 $get_answers = tutor_utils()->get_answer_by_id( maybe_unserialize( $answer->given_answer ) );
432 tutor_render_answer_list( $get_answers );
433 }
434
435 // Fill in the blank.
436 elseif ( 'fill_in_the_blank' === $answer->question_type ) {
437 $answer_titles = maybe_unserialize( $answer->given_answer );
438 $get_db_answers_by_question = QuizModel::get_answers_by_quiz_question( $answer->question_id );
439
440 echo tutor_render_fill_in_the_blank_answer( $get_db_answers_by_question, $answer_titles ); //phpcs:ignore --contain safe data
441 }
442
443 // Open ended or short answer.
444 elseif ( 'open_ended' === $answer->question_type || 'short_answer' === $answer->question_type ) {
445 if ( $answer->given_answer ) {
446 echo wp_kses(
447 wpautop( stripslashes( $answer->given_answer ) ),
448 array(
449 'p' => true,
450 'span' => true,
451 )
452 );
453 }
454 }
455
456 // Ordering.
457 elseif ( 'ordering' === $answer->question_type ) {
458 $ordering_ids = maybe_unserialize( $answer->given_answer );
459 foreach ( $ordering_ids as $ordering_id ) {
460 $get_answers = tutor_utils()->get_answer_by_id( $ordering_id );
461 tutor_render_answer_list( $get_answers );
462 }
463 }
464
465 // Matching.
466 elseif ( 'matching' === $answer->question_type ) {
467
468 $ordering_ids = maybe_unserialize( $answer->given_answer );
469 $original_saved_answers = QuizModel::get_answers_by_quiz_question( $answer->question_id );
470
471 $answers = array();
472
473 foreach ( $original_saved_answers as $key => $original_saved_answer ) {
474 $provided_answer_order_id = isset( $ordering_ids[ $key ] ) ? $ordering_ids[ $key ] : 0;
475 $provided_answer_order = tutor_utils()->get_answer_by_id( $provided_answer_order_id );
476 if ( tutor_utils()->count( $provided_answer_order ) ) {
477 foreach ( $provided_answer_order as $provided_answer_order ) {
478 if ( $is_image_matching ) {
479 $original_saved_answer->answer_view_format = 'text_image';
480 $original_saved_answer->answer_title = $provided_answer_order->answer_title;
481 $original_saved_answer->answer_two_gap_match = '';
482 $answers[] = $original_saved_answer;
483 } else {
484 $original_saved_answer->answer_two_gap_match = $provided_answer_order->answer_two_gap_match;
485 $answers[] = $original_saved_answer;
486 }
487 }
488 }
489 }
490
491 tutor_render_answer_list( $answers );
492 } elseif ( 'image_matching' === $answer->question_type ) {
493
494 $ordering_ids = maybe_unserialize( $answer->given_answer );
495 $original_saved_answers = QuizModel::get_answers_by_quiz_question( $answer->question_id );
496
497 $answers = array();
498
499 foreach ( $original_saved_answers as $key => $original_saved_answer ) {
500 $provided_answer_order_id = isset( $ordering_ids[ $key ] ) ? $ordering_ids[ $key ] : 0;
501 $provided_answer_order = tutor_utils()->get_answer_by_id( $provided_answer_order_id );
502 foreach ( $provided_answer_order as $p_answer ) {
503 if ( $p_answer->answer_title ) {
504 $original_saved_answer->answer_view_format = 'text_image';
505 $original_saved_answer->answer_title = $p_answer->answer_title;
506 $answers[] = $original_saved_answer;
507 }
508 }
509 }
510
511 tutor_render_answer_list( $answers );
512 } elseif ( 'image_answering' === $answer->question_type ) {
513
514 $ordering_ids = maybe_unserialize( $answer->given_answer );
515
516 $answers = array();
517
518 foreach ( $ordering_ids as $answer_id => $image_answer ) {
519 $db_answers = tutor_utils()->get_answer_by_id( $answer_id );
520 foreach ( $db_answers as $db_answer ) {
521 }
522 $db_answer->answer_title = $image_answer;
523 $db_answer->answer_view_format = 'text_image';
524 $answers[] = $db_answer;
525
526 }
527
528 tutor_render_answer_list( $answers );
529 }
530 ?>
531 </div>
532 </td>
533 <?php
534 break;
535
536 case 'correct_answer':
537 ?>
538 <td class="correct-answer" data-title="<?php echo esc_attr( $column ); ?>">
539 <div>
540 <?php
541 if ( ( $answer->question_type != 'open_ended' && $answer->question_type != 'short_answer' ) ) {
542
543 global $wpdb;
544
545 // True false.
546 if ( 'true_false' === $answer->question_type ) {
547 $correct_answer = $wpdb->get_var(
548 $wpdb->prepare(
549 "SELECT answer_title FROM {$wpdb->prefix}tutor_quiz_question_answers
550 WHERE belongs_question_id = %d
551 AND belongs_question_type='true_false'
552 AND is_correct = 1",
553 $answer->question_id
554 )
555 );
556
557 echo '<span class="tutor-fs-7 tutor-fw-medium tutor-color-black">' .
558 esc_html( $correct_answer ) .
559 '</span>';
560 }
561
562 // Single choice.
563 elseif ( 'single_choice' === $answer->question_type ) {
564 $correct_answer = $wpdb->get_results(
565 $wpdb->prepare(
566 "SELECT answer_title, image_id, answer_view_format
567 FROM {$wpdb->prefix}tutor_quiz_question_answers
568 WHERE belongs_question_id = %d
569 AND belongs_question_type='single_choice' AND
570 is_correct = 1",
571 $answer->question_id
572 )
573 );
574
575 tutor_render_answer_list( $correct_answer );
576 }
577
578 // Multiple choice.
579 elseif ( 'multiple_choice' === $answer->question_type ) {
580 $correct_answer = $wpdb->get_results(
581 $wpdb->prepare(
582 "SELECT answer_title, image_id, answer_view_format
583 FROM {$wpdb->prefix}tutor_quiz_question_answers
584 WHERE belongs_question_id = %d
585 AND belongs_question_type='multiple_choice'
586 AND is_correct = 1 ;",
587 $answer->question_id
588 )
589 );
590
591 tutor_render_answer_list( $correct_answer );
592 }
593
594 // Fill in the blanks.
595 elseif ( 'fill_in_the_blank' === $answer->question_type ) {
596 $correct_answer = $wpdb->get_var(
597 $wpdb->prepare(
598 "SELECT answer_two_gap_match FROM {$wpdb->prefix}tutor_quiz_question_answers
599 WHERE belongs_question_id = %d
600 AND belongs_question_type='fill_in_the_blank'",
601 $answer->question_id
602 )
603 );
604
605 $answer_titles = explode( '|', stripslashes( $correct_answer ) );
606 $get_db_answers_by_question = QuizModel::get_answers_by_quiz_question( $answer->question_id );
607
608 echo tutor_render_fill_in_the_blank_answer( $get_db_answers_by_question, $answer_titles ); //phpcs:ignore --contain safe data
609 }
610
611 // Ordering.
612 elseif ( 'ordering' === $answer->question_type ) {
613 $correct_answer = $wpdb->get_results(
614 $wpdb->prepare(
615 "SELECT answer_title, image_id, answer_view_format
616 FROM {$wpdb->prefix}tutor_quiz_question_answers
617 WHERE belongs_question_id = %d
618 AND belongs_question_type='ordering'
619 ORDER BY answer_order ASC;",
620 $answer->question_id
621 )
622 );
623
624 foreach ( $correct_answer as $ans ) {
625 tutor_render_answer_list( array( $ans ) );
626 }
627 }
628
629 // Matching.
630 elseif ( 'matching' === $answer->question_type ) {
631 $correct_answer = $wpdb->get_results(
632 $wpdb->prepare(
633 "SELECT answer_title, image_id, answer_two_gap_match, answer_view_format
634 FROM {$wpdb->prefix}tutor_quiz_question_answers
635 WHERE belongs_question_id = %d
636 AND belongs_question_type='matching'
637 ORDER BY answer_order ASC;",
638 $answer->question_id
639 )
640 );
641
642 if ( $is_image_matching ) {
643 array_map(
644 function( $ans ) {
645 $ans->answer_view_format = 'text_image';
646 $ans->answer_two_gap_match = '';
647 },
648 $correct_answer
649 );
650 }
651
652 tutor_render_answer_list( $correct_answer );
653 }
654
655 // Image matching.
656 elseif ( 'image_matching' === $answer->question_type ) {
657 $correct_answer = $wpdb->get_results(
658 $wpdb->prepare(
659 "SELECT answer_title, image_id, answer_two_gap_match
660 FROM {$wpdb->prefix}tutor_quiz_question_answers
661 WHERE belongs_question_id = %d
662 AND belongs_question_type='image_matching'
663 ORDER BY answer_order ASC;",
664 $answer->question_id
665 )
666 );
667
668 tutor_render_answer_list( $correct_answer, true );
669 }
670
671 // Image Answering.
672 elseif ( 'image_answering' === $answer->question_type ) {
673
674 $correct_answer = $wpdb->get_results(
675 $wpdb->prepare(
676 "SELECT answer_title, image_id, answer_two_gap_match
677 FROM {$wpdb->prefix}tutor_quiz_question_answers
678 WHERE belongs_question_id = %d
679 AND belongs_question_type='image_answering'
680 ORDER BY answer_order ASC;",
681 $answer->question_id
682 )
683 );
684
685 ! is_array( $correct_answer ) ? $correct_answer = array() : 0;
686
687 echo '<div class="answer-image-matched-wrap">';
688 foreach ( $correct_answer as $image_answer ) {
689 ?>
690 <div class="image-matching-item">
691 <p class="dragged-img-rap"><img src="<?php echo esc_url( wp_get_attachment_image_url( $image_answer->image_id ) ); ?>" /> </p>
692 <p class="dragged-caption"><?php echo esc_html( $image_answer->answer_title ); ?></p>
693 </div>
694 <?php
695 }
696 echo '</div>';
697 }
698 }
699 ?>
700 </div>
701 </td>
702 <?php
703 break;
704
705 case 'result':
706 ?>
707 <td class="result" data-title="<?php echo esc_attr( $column ); ?>">
708 <div class="tutor-d-flex tutor-align-center tutor-justify-between tutor-gap-4px">
709 <?php do_action( 'tutor_quiz_attempt_after_result_column', $answer, $answer_status ); ?>
710
711 <?php
712 if ( 'h5p' !== $answer->question_type ) {
713 switch ( $answer_status ) {
714 case 'correct':
715 echo '<span class="tutor-badge-label label-success">' . esc_html__( 'Correct', 'tutor' ) . '</span>';
716 break;
717
718 case 'pending':
719 echo '<span class="tutor-badge-label label-warning">' . esc_html__( 'Pending', 'tutor' ) . '</span>';
720 break;
721
722 case 'wrong':
723 echo '<span class="tutor-badge-label label-danger">' . esc_html__( 'Incorrect', 'tutor' ) . '</span>';
724 break;
725 }
726 }
727 ?>
728
729 <?php do_action( 'tutor_quiz_attempt_details_after_result', $answer, $answer_status ); ?>
730 </div>
731 </td>
732 <?php
733 break;
734
735 case 'manual_review':
736 ?>
737 <td class="tutor-text-center tutor-nowrap-ellipsis" data-title="<?php echo esc_attr( $column ); ?>">
738 <div class="tutor-manual-review-wrapper">
739 <a href="javascript:;" data-back-url="<?php echo esc_url( $back_url ); ?>" data-attempt-id="<?php echo esc_attr( $attempt_id ); ?>" data-attempt-answer-id="<?php echo esc_attr( $answer->attempt_answer_id ); ?>" data-mark-as="correct" data-context="<?php echo esc_attr( $context ); ?>" title="<?php esc_attr_e( 'Mark as correct', 'tutor' ); ?>" class="quiz-manual-review-action tutor-mr-12 tutor-icon-rounded tutor-color-success">
740 <i class="tutor-icon-mark"></i>
741 </a>
742
743 <a href="javascript:;" data-back-url="<?php echo esc_url( $back_url ); ?>" data-attempt-id="<?php echo esc_attr( $attempt_id ); ?>" data-attempt-answer-id="<?php echo esc_attr( $answer->attempt_answer_id ); ?>" data-mark-as="incorrect" data-context="<?php echo esc_attr( $context ); ?>" title="<?php esc_attr_e( 'Mark as In correct', 'tutor' ); ?>" class="quiz-manual-review-action tutor-icon-rounded tutor-color-danger">
744 <i class="tutor-icon-times"></i>
745 </a>
746 </div>
747 </td>
748 <?php
749 }
750 ?>
751 <?php endforeach; ?>
752 </tr>
753
754 <?php do_action( 'tutor_quiz_attempt_details_loop_after_row', $answer, $answer_status, $table_2_columns ); ?>
755
756 <?php
757 }
758 ?>
759 </tbody>
760 </table>
761 </div>
762 <?php
763 do_action( 'tutor_quiz_attempt_details_loop_after' );
764 }
765 ?>
766
767 <?php echo is_admin() ? '</div>' : ''; ?>
768