PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 3.0.0
Tutor LMS – eLearning and online course solution v3.0.0
4.0.1 4.0.0 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 1 year ago attempt-details.php 1 year ago attempt-table.php 1 year ago contexts.php 3 years ago header.php 3 years ago instructor-feedback.php 3 years ago
attempt-details.php
842 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 ( isset( $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 ) && ! isset( $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 ( isset( $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( ', ', wp_unslash( $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 // Prepare attempt meta info.
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 echo esc_html( $attempt_data->earned_marks );
278 $earned_percentage = $attempt_data->earned_marks > 0 ? ( number_format( ( $attempt_data->earned_marks * 100 ) / $attempt_data->total_marks ) ) : 0;
279 echo esc_html( ' (' . $earned_percentage . '%)' );
280 ?>
281 <?php elseif ( 'result' === $key ) : ?>
282 <?php
283 $ans_array = is_array( $answers ) ? $answers : array();
284 $has_pending = count(
285 array_filter(
286 $ans_array,
287 function ( $ans ) {
288 return null === $ans->is_correct;
289 }
290 )
291 );
292
293 if ( $has_pending ) {
294 echo '<span class="tutor-badge-label label-warning">' . esc_html__( 'Pending', 'tutor' ) . '</span>';
295 } elseif ( $earned_percentage >= $pass_mark_percent ) {
296 echo '<span class="tutor-badge-label label-success">' . esc_html__( 'Pass', 'tutor' ) . '</span>';
297 } else {
298 echo '<span class="tutor-badge-label label-danger">' . esc_html__( 'Fail', 'tutor' ) . '</span>';
299 }
300 ?>
301 <?php endif; ?>
302 </td>
303 <?php endforeach; ?>
304 </tr>
305 </tbody>
306 </table>
307 </div>
308
309 <?php
310 // instructor feedback.
311 global $wp_query;
312 $query_vars = $wp_query->query_vars;
313 $page_name = isset( $query_vars['tutor_dashboard_page'] ) ? $query_vars['tutor_dashboard_page'] : '';
314 $attempt_info = unserialize( $attempt_data->attempt_info );
315 $feedback = is_array( $attempt_info ) && isset( $attempt_info['instructor_feedback'] ) ? $attempt_info['instructor_feedback'] : '';
316 // don't show on instructor quiz attempt since below already have feedback box area.
317 if ( '' !== $feedback && 'my-quiz-attempts' === $page_name ) {
318 ?>
319 <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">
320 <div class="tutor-in-title tutor-fs-6 tutor-fw-medium tutor-color-black">
321 <?php esc_html_e( 'Instructor Note', 'tutor' ); ?>
322 </div>
323 <div class="tutor-in-body tutor-fs-6 tutor-color-secondary tutor-pt-12 tutor-pt-sm-16">
324 <?php echo wp_kses_post( $feedback ); ?>
325 </div>
326 </div>
327 <?php } ?>
328
329 <?php
330 if ( is_array( $answers ) && count( $answers ) ) {
331 // Filter out not needed columns based on question type.
332 $table_2_columns = apply_filters( 'tutor_filter_attempt_answer_column', $table_2_columns, $answers );
333 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>' : '';
334 ?>
335 <div class="tutor-table-responsive tutor-table-mobile tutor-mt-16">
336 <table class="tutor-table tutor-quiz-attempt-details tutor-mb-32 tutor-table-data-td-target">
337 <thead>
338 <tr>
339 <?php foreach ( $table_2_columns as $key => $column ) : ?>
340 <th><?php echo $column; //phpcs:ignore --contain safe data ?></th>
341 <?php endforeach; ?>
342 </tr>
343 </thead>
344
345 <tbody>
346 <?php
347 $answer_i = 0;
348 foreach ( $answers as $answer ) {
349 $answer_i++;
350 $question_type = tutor_utils()->get_question_types( $answer->question_type );
351 $question_settings = maybe_unserialize( $answer->question_settings );
352 $is_image_matching = isset( $question_settings['is_image_matching'] ) && '1' === $question_settings['is_image_matching'];
353 $answer_status = 'wrong';
354
355 // If already correct, then show it.
356 if ( (bool) $answer->is_correct ) {
357 $answer_status = 'correct';
358 }
359
360 // Image answering also needs review since the answer texts are not meant to match exactly.
361 elseif ( in_array( $answer->question_type, array( 'open_ended', 'short_answer', 'image_answering' ), true ) ) {
362 $answer_status = null === $answer->is_correct ? 'pending' : 'wrong';
363 }
364 ?>
365
366 <tr class="tutor-quiz-answer-status-<?php echo esc_html( $answer_status ); ?>">
367 <?php foreach ( $table_2_columns as $key => $column ) : ?>
368 <?php
369 switch ( $key ) {
370 case 'no':
371 ?>
372 <td class="no" data-title="<?php echo esc_attr( $column ); ?>">
373 <span class="tutor-fs-7 tutor-fw-medium tutor-color-black">
374 <?php echo esc_html( $answer_i ); ?>
375 </span>
376 </td>
377 <?php
378 break;
379
380 case 'type':
381 ?>
382 <td class="type" data-title="<?php echo esc_attr( $column ); ?>">
383 <?php $type = tutor_utils()->get_question_types( $answer->question_type ); ?>
384 <div class="tooltip-wrap tooltip-icon tutor-d-flex tutor-align-center">
385 <?php
386 if ( 'h5p' === $answer->question_type ) {
387 ?>
388 <span class="tooltip-btn tutor-d-flex tutor-align-center">
389 <svg width="2e3" height="2e3" class="tutor-quiz-type-icon" version="1.1" viewBox="0 0 2e3 2e3" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
390 <metadata>
391 <rdf:RDF>
392 <cc:Work rdf:about="">
393 <dc:format>image/svg+xml</dc:format>
394 <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
395 <dc:title/>
396 </cc:Work>
397 </rdf:RDF>
398 </metadata>
399 <path d="m-5.2836 1004.2v-1e3h2009.7v2e3h-2009.7zm602.92 150v-90h160.78v180l185.4-0.166-5.0243-2.3086c-2.7634-1.2697-11.693-5.0995-19.843-8.5106-24.366-10.198-36.891-18.724-54.121-36.843-10.05-10.568-20.873-25.967-27.462-39.076-5.0966-10.139-13.346-31.394-13.809-35.581l-0.32475-2.9363 63.809-9.2284c35.095-5.0757 64.939-9.2468 66.321-9.2693 1.9741-0.032 3.1578 1.0489 5.5268 5.0472 9.524 16.075 29.045 28.375 48.934 30.835 39.402 4.8726 74.132-24.163 75.907-63.462 1.4168-31.358-16.291-56.906-46.942-67.723-8.1892-2.8901-25.607-3.543-35.585-1.3338-16.562 3.6667-34.105 15.999-41.818 29.397-1.9314 3.355-3.8993 6.1134-4.3731 6.1298-1.8758 0.065-131.66-18.014-132.04-18.393-0.33622-0.3346 56.264-250.94 59.022-261.33l0.86285-3.25h-124.44v208h-160.78v-208h-152.74v488h152.74v-90zm691.35 0.086v-89.914l61.046-0.4487c50.137-0.3686 63.102-0.7486 72.556-2.1265 45.532-6.6369 75.163-20.01 98.924-44.645 23.057-23.906 35.045-51.976 38.844-90.951 1.4392-14.766 0.7197-39.174-1.5623-53-10.033-60.784-46.103-98.57-106.52-111.58-22.373-4.8192-20.773-4.7584-135.41-5.1478l-108.27-0.3678v100.1h-220.85l-3.2413 13.75c-1.7827 7.5625-5.8428 24.699-9.0225 38.082-4.7451 19.971-5.4901 24.239-4.1566 23.813 0.89355-0.2855 6.3726-2.3074 12.176-4.4931 13.294-5.0069 37.711-11.701 47.748-13.09 9.7858-1.3545 38.914-1.3666 53.241-0.022 30.235 2.8372 56.58 11.691 79.31 26.652 12.878 8.4771 32.803 28.1 41.436 40.809 32.824 48.318 35.187 112.49 6.3454 172.29-3.2595 6.7578-8.3491 15.983-11.31 20.5-19.02 29.016-48.23 53.062-72.572 59.742-8.0702 2.2146-18.898 7.0389-20.084 8.9486-0.4308 0.6937 28.626 1.0224 90.365 1.0224h91zm0-244.09v-54h30.424c48.304 0 63.803 3.0493 76.569 15.065 11.117 10.463 16.624 23.326 16.581 38.724-0.045 16.066-3.6793 25.057-14.466 35.791-14.862 14.79-30.913 18.42-81.434 18.42h-27.673z" stroke-width="1.0024"/>
400 <path d="m445.74 1000.3v-243.31h150.85v209.25h163.02v-209.25h121.75l-1.307 5.4745c-2.5392 10.635-47.071 207.77-52.49 232.36-3.0226 13.718-4.9042 25.533-4.1815 26.256s30.515 5.3399 66.205 10.26l64.891 8.9462 9.8954-11.577c27.937-32.684 75.421-33.24 102.84-1.2047 35.938 41.985 4.7303 107.54-51.078 107.29-19.803-0.087-35.659-7.3743-50.547-23.231l-11.784-12.551-64.806 9.1844c-35.644 5.0515-65.351 9.7291-66.017 10.395-2.5401 2.5401 10.5 34.529 20.974 51.451 19.244 31.091 42.436 50.852 76.365 65.064 8.6293 3.6149 16.146 7.0049 16.703 7.5333 0.55756 0.5285-39.132 0.9609-88.2 0.9609h-89.213v-180.05h-163.02v180.05h-150.85z" fill="#fff" stroke="#fff" stroke-width="2.4331"/>
401 <path d="m1113.7 1241.5c1.2712-1.1737 7.9008-3.9462 14.732-6.1611 58.229-18.879 103.08-90.97 103.13-165.77 0.03-43.193-12.994-76.78-41.351-106.63-19.256-20.271-39.728-33.177-66.904-42.178-17.859-5.9149-22.878-6.4619-60.827-6.6287-38.795-0.17059-42.686 0.23875-62.676 6.5945-11.722 3.727-22.957 7.4073-24.967 8.1784-2.3603 0.90573-3.2737 0.22951-2.5802-1.9102 0.59044-1.8218 4.5292-18.367 8.7528-36.767l7.6793-33.455h220.99v-100.35l113.75 1.2124c106.04 1.1303 115.07 1.5628 133.21 6.383 50.455 13.403 80.167 40.402 95.377 86.669 5.6162 17.083 6.4237 23.632 6.601 53.528 0.1509 25.428-0.8842 38.073-4.0828 49.878-13.928 51.405-51.002 87.442-103.98 101.07-19.479 5.0099-65.583 8.1775-121.05 8.3168l-41.971 0.1053v180.05h-88.078c-50.624 0-87.095-0.9075-85.766-2.1341zm261.63-281.61c16.962-5.037 32.185-19.719 36.303-35.012 7.7315-28.713-8.2767-57.752-36.215-65.695-4.8411-1.3763-26.594-3.2014-48.34-4.0558l-39.538-1.5534v113.44l37.321-1.6092c22.552-0.97241 42.524-3.1542 50.468-5.5133z" fill="#fff" stroke="#fff" stroke-width="2.4331"/>
402 </svg>
403 </span>
404 <?php
405 } else {
406 echo wp_kses(
407 $question_type['icon'] ?? '',
408 tutor_utils()->allowed_icon_tags()
409 );
410 }
411 ?>
412 <span class="tooltip-txt tooltip-top">
413 <?php
414 if ( 'h5p' === $answer->question_type ) {
415 echo esc_html( 'H5P' );
416 } else {
417 echo esc_html( $type['name'] ?? '' );
418 }
419 ?>
420 </span>
421 </div>
422 </td>
423 <?php
424 break;
425
426 case 'questions':
427 ?>
428 <td class="questions" data-title="<?php echo esc_attr( $column ); ?>">
429 <span class="tutor-fs-7 tutor-fw-medium tutor-d-flex tutor-align-center">
430 <?php echo esc_html( stripslashes( $answer->question_title ) ); ?>
431 </span>
432 </td>
433 <?php
434 break;
435
436 case 'given_answer':
437 ?>
438 <td class="given-answer" data-title="<?php echo esc_attr( $column ); ?>">
439 <div>
440 <?php
441 // Single choice.
442 if ( 'single_choice' === $answer->question_type ) {
443 $get_answers = tutor_utils()->get_answer_by_id( $answer->given_answer );
444 tutor_render_answer_list( $get_answers );
445 }
446
447
448 // True false or single choice.
449 if ( 'true_false' === $answer->question_type ) {
450 $get_answers = tutor_utils()->get_answer_by_id( $answer->given_answer );
451 $answer_titles = wp_list_pluck( $get_answers, 'answer_title' );
452 $answer_titles = array_map( 'stripslashes', $answer_titles );
453
454 echo '<span class="tutor-fs-7 tutor-fw-medium tutor-color-black">' .
455 implode( '</p><p>', $answer_titles ) . //phpcs:ignore
456 '</span>';
457 }
458
459 // Multiple choice.
460 elseif ( 'multiple_choice' === $answer->question_type ) {
461 $get_answers = tutor_utils()->get_answer_by_id( maybe_unserialize( $answer->given_answer ) );
462 tutor_render_answer_list( $get_answers );
463 }
464
465 // Fill in the blank.
466 elseif ( 'fill_in_the_blank' === $answer->question_type ) {
467 $answer_titles = maybe_unserialize( $answer->given_answer );
468 $get_db_answers_by_question = QuizModel::get_answers_by_quiz_question( $answer->question_id );
469
470 echo tutor_render_fill_in_the_blank_answer( $get_db_answers_by_question, $answer_titles ); //phpcs:ignore --contain safe data
471 }
472
473 // Open ended or short answer.
474 elseif ( 'open_ended' === $answer->question_type || 'short_answer' === $answer->question_type ) {
475 if ( $answer->given_answer ) {
476 echo wp_kses(
477 wpautop( stripslashes( $answer->given_answer ) ),
478 array(
479 'p' => true,
480 'span' => true,
481 )
482 );
483 }
484 }
485
486 // Ordering.
487 elseif ( 'ordering' === $answer->question_type ) {
488 $ordering_ids = maybe_unserialize( $answer->given_answer );
489 foreach ( $ordering_ids as $ordering_id ) {
490 $get_answers = tutor_utils()->get_answer_by_id( $ordering_id );
491 tutor_render_answer_list( $get_answers );
492 }
493 }
494
495 // Matching.
496 elseif ( 'matching' === $answer->question_type ) {
497
498 $ordering_ids = maybe_unserialize( $answer->given_answer );
499 $original_saved_answers = QuizModel::get_answers_by_quiz_question( $answer->question_id );
500
501 $answers = array();
502
503 foreach ( $original_saved_answers as $key => $original_saved_answer ) {
504 $provided_answer_order_id = isset( $ordering_ids[ $key ] ) ? $ordering_ids[ $key ] : 0;
505 $provided_answer_order = tutor_utils()->get_answer_by_id( $provided_answer_order_id );
506 if ( tutor_utils()->count( $provided_answer_order ) ) {
507 foreach ( $provided_answer_order as $provided_answer_order ) {
508 if ( $is_image_matching ) {
509 $original_saved_answer->answer_view_format = 'text_image';
510 $original_saved_answer->answer_title = $provided_answer_order->answer_title;
511 $original_saved_answer->answer_two_gap_match = '';
512 $answers[] = $original_saved_answer;
513 } else {
514 $original_saved_answer->answer_two_gap_match = $provided_answer_order->answer_two_gap_match;
515 $answers[] = $original_saved_answer;
516 }
517 }
518 }
519 }
520
521 tutor_render_answer_list( $answers );
522 } elseif ( 'image_matching' === $answer->question_type ) {
523
524 $ordering_ids = maybe_unserialize( $answer->given_answer );
525 $original_saved_answers = QuizModel::get_answers_by_quiz_question( $answer->question_id );
526
527 $answers = array();
528
529 foreach ( $original_saved_answers as $key => $original_saved_answer ) {
530 $provided_answer_order_id = isset( $ordering_ids[ $key ] ) ? $ordering_ids[ $key ] : 0;
531 $provided_answer_order = tutor_utils()->get_answer_by_id( $provided_answer_order_id );
532 foreach ( $provided_answer_order as $p_answer ) {
533 if ( $p_answer->answer_title ) {
534 $original_saved_answer->answer_view_format = 'text_image';
535 $original_saved_answer->answer_title = $p_answer->answer_title;
536 $answers[] = $original_saved_answer;
537 }
538 }
539 }
540
541 tutor_render_answer_list( $answers );
542 } elseif ( 'image_answering' === $answer->question_type ) {
543
544 $ordering_ids = maybe_unserialize( $answer->given_answer );
545
546 $answers = array();
547
548 foreach ( $ordering_ids as $answer_id => $image_answer ) {
549 $db_answers = tutor_utils()->get_answer_by_id( $answer_id );
550 foreach ( $db_answers as $db_answer ) {
551 }
552 $db_answer->answer_title = $image_answer;
553 $db_answer->answer_view_format = 'text_image';
554 $answers[] = $db_answer;
555
556 }
557
558 tutor_render_answer_list( $answers );
559 }
560 ?>
561 </div>
562 </td>
563 <?php
564 break;
565
566 case 'correct_answer':
567 ?>
568 <td class="correct-answer" data-title="<?php echo esc_attr( $column ); ?>">
569 <div>
570 <?php
571 if ( ( $answer->question_type != 'open_ended' && $answer->question_type != 'short_answer' ) ) {
572
573 global $wpdb;
574
575 // True false.
576 if ( 'true_false' === $answer->question_type ) {
577 $correct_answer = $wpdb->get_var(
578 $wpdb->prepare(
579 "SELECT answer_title FROM {$wpdb->prefix}tutor_quiz_question_answers
580 WHERE belongs_question_id = %d
581 AND belongs_question_type='true_false'
582 AND is_correct = 1",
583 $answer->question_id
584 )
585 );
586
587 echo '<span class="tutor-fs-7 tutor-fw-medium tutor-color-black">' .
588 esc_html( $correct_answer ) .
589 '</span>';
590 }
591
592 // Single choice.
593 elseif ( 'single_choice' === $answer->question_type ) {
594 $correct_answer = $wpdb->get_results(
595 $wpdb->prepare(
596 "SELECT answer_title, image_id, answer_view_format
597 FROM {$wpdb->prefix}tutor_quiz_question_answers
598 WHERE belongs_question_id = %d
599 AND belongs_question_type='single_choice' AND
600 is_correct = 1",
601 $answer->question_id
602 )
603 );
604
605 tutor_render_answer_list( $correct_answer );
606 }
607
608 // Multiple choice.
609 elseif ( 'multiple_choice' === $answer->question_type ) {
610 $correct_answer = $wpdb->get_results(
611 $wpdb->prepare(
612 "SELECT answer_title, image_id, answer_view_format
613 FROM {$wpdb->prefix}tutor_quiz_question_answers
614 WHERE belongs_question_id = %d
615 AND belongs_question_type='multiple_choice'
616 AND is_correct = 1 ;",
617 $answer->question_id
618 )
619 );
620
621 tutor_render_answer_list( $correct_answer );
622 }
623
624 // Fill in the blanks.
625 elseif ( 'fill_in_the_blank' === $answer->question_type ) {
626 $correct_answer = $wpdb->get_var(
627 $wpdb->prepare(
628 "SELECT answer_two_gap_match FROM {$wpdb->prefix}tutor_quiz_question_answers
629 WHERE belongs_question_id = %d
630 AND belongs_question_type='fill_in_the_blank'",
631 $answer->question_id
632 )
633 );
634
635 $answer_titles = explode( '|', stripslashes( $correct_answer ) );
636 $get_db_answers_by_question = QuizModel::get_answers_by_quiz_question( $answer->question_id );
637
638 echo tutor_render_fill_in_the_blank_answer( $get_db_answers_by_question, $answer_titles ); //phpcs:ignore --contain safe data
639 }
640
641 // Ordering.
642 elseif ( 'ordering' === $answer->question_type ) {
643 $correct_answer = $wpdb->get_results(
644 $wpdb->prepare(
645 "SELECT answer_title, image_id, answer_view_format
646 FROM {$wpdb->prefix}tutor_quiz_question_answers
647 WHERE belongs_question_id = %d
648 AND belongs_question_type='ordering'
649 ORDER BY answer_order ASC;",
650 $answer->question_id
651 )
652 );
653
654 foreach ( $correct_answer as $ans ) {
655 tutor_render_answer_list( array( $ans ) );
656 }
657 }
658
659 // Matching.
660 elseif ( 'matching' === $answer->question_type ) {
661 $correct_answer = $wpdb->get_results(
662 $wpdb->prepare(
663 "SELECT answer_title, image_id, answer_two_gap_match, answer_view_format
664 FROM {$wpdb->prefix}tutor_quiz_question_answers
665 WHERE belongs_question_id = %d
666 AND belongs_question_type='matching'
667 ORDER BY answer_order ASC;",
668 $answer->question_id
669 )
670 );
671
672 if ( $is_image_matching ) {
673 array_map(
674 function( $ans ) {
675 $ans->answer_view_format = 'text_image';
676 $ans->answer_two_gap_match = '';
677 },
678 $correct_answer
679 );
680 }
681
682 tutor_render_answer_list( $correct_answer );
683 }
684
685 // Image matching.
686 elseif ( 'image_matching' === $answer->question_type ) {
687 $correct_answer = $wpdb->get_results(
688 $wpdb->prepare(
689 "SELECT answer_title, image_id, answer_two_gap_match
690 FROM {$wpdb->prefix}tutor_quiz_question_answers
691 WHERE belongs_question_id = %d
692 AND belongs_question_type='image_matching'
693 ORDER BY answer_order ASC;",
694 $answer->question_id
695 )
696 );
697
698 tutor_render_answer_list( $correct_answer, true );
699 }
700
701 // Image Answering.
702 elseif ( 'image_answering' === $answer->question_type ) {
703
704 $correct_answer = $wpdb->get_results(
705 $wpdb->prepare(
706 "SELECT answer_title, image_id, answer_two_gap_match
707 FROM {$wpdb->prefix}tutor_quiz_question_answers
708 WHERE belongs_question_id = %d
709 AND belongs_question_type='image_answering'
710 ORDER BY answer_order ASC;",
711 $answer->question_id
712 )
713 );
714
715 ! is_array( $correct_answer ) ? $correct_answer = array() : 0;
716
717 echo '<div class="answer-image-matched-wrap">';
718 foreach ( $correct_answer as $image_answer ) {
719 ?>
720 <div class="image-matching-item">
721 <p class="dragged-img-rap"><img src="<?php echo esc_url( wp_get_attachment_image_url( $image_answer->image_id ) ); ?>" /> </p>
722 <p class="dragged-caption"><?php echo esc_html( $image_answer->answer_title ); ?></p>
723 </div>
724 <?php
725 }
726 echo '</div>';
727 }
728 }
729 ?>
730 </div>
731 </td>
732 <?php
733 break;
734
735 case 'result':
736 ?>
737 <td class="result" data-title="<?php echo esc_attr( $column ); ?>">
738 <?php
739 if ( tutor()->has_pro && \TutorPro\H5P\H5P::is_enabled() && 'h5p' === $answer->question_type ) {
740 $attempt_results = \TutorPro\H5P\Utils::get_h5p_quiz_results( $answer->question_id, $answer->user_id, $answer->quiz_attempt_id, $answer->quiz_id, $answer->question_description );
741 $has_attempt_results = is_array( $attempt_results ) && count( $attempt_results );
742 $has_response = true;
743 if ( $has_attempt_results ) {
744 $score = $attempt_results[0]->raw_score . '/' . $attempt_results[0]->max_score;
745
746 if ( is_array( $attempt_results ) && 1 === count( $attempt_results ) ) {
747 if ( is_null( $attempt_results[0]->response ) ) {
748 $has_response = false;
749 }
750 }
751 if ( $has_response ) {
752 ?>
753 <a class=" tutor-btn tutor-btn-outline-primary tutor-btn-sm open-tutor-h5p-quiz-result-modal-btn" data-quiz-id="<?php echo esc_attr( $answer->quiz_id ); ?>"
754 data-question-id="<?php echo esc_attr( $answer->question_id ); ?>"
755 data-user-id="<?php echo esc_attr( $answer->user_id ); ?>"
756 data-attempt-id="<?php echo esc_attr( $answer->quiz_attempt_id ); ?>"
757 data-content-id="<?php echo esc_attr( $answer->question_description ); ?>"
758 >
759 <?php esc_html_e( 'View', 'tutor' ); ?>
760 </a>
761 <?php
762 } else {
763 ?>
764 <span class="<?php echo $attempt_results[0]->max_score === $attempt_results[0]->raw_score ? 'tutor-color-success' : 'tutor-color-danger'; ?> tutor-fw-normal"><?php echo esc_html( $score ); ?></span>
765 <?php
766 }
767 }
768 } else {
769 switch ( $answer_status ) {
770 case 'correct':
771 echo '<span class="tutor-badge-label label-success">' . esc_html__( 'Correct', 'tutor' ) . '</span>';
772 break;
773
774 case 'pending':
775 echo '<span class="tutor-badge-label label-warning">' . esc_html__( 'Pending', 'tutor' ) . '</span>';
776 break;
777
778 case 'wrong':
779 echo '<span class="tutor-badge-label label-danger">' . esc_html__( 'Incorrect', 'tutor' ) . '</span>';
780 break;
781 }
782 }
783 ?>
784 </td>
785 <?php
786 break;
787
788 case 'manual_review':
789 ?>
790 <td class="tutor-text-center tutor-nowrap-ellipsis" data-title="<?php echo esc_attr( $column ); ?>">
791 <div class="tutor-manual-review-wrapper">
792 <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">
793 <i class="tutor-icon-mark"></i>
794 </a>
795
796 <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">
797 <i class="tutor-icon-times"></i>
798 </a>
799 </div>
800 </td>
801 <?php
802 }
803 ?>
804 <?php endforeach; ?>
805 </tr>
806
807 <?php do_action( 'tutor_quiz_attempt_details_loop_after_row', $answer, $answer_status ); ?>
808
809 <?php
810 }
811 ?>
812 </tbody>
813 </table>
814 </div>
815 <?php
816 if ( tutor()->has_pro && \TutorPro\H5P\H5P::is_enabled() ) {
817 ?>
818 <div class="tutor-modal tutor-modal-scrollable<?php echo is_admin() ? ' tutor-admin-design-init' : ''; ?> h5p-quiz-result-modal">
819 <div class="tutor-modal-overlay"></div>
820 <div class="tutor-modal-window">
821 <div class="tutor-modal-content">
822 <div class="tutor-modal-header">
823 <div class="tutor-modal-title">
824 <?php esc_html_e( 'H5P Question Answer', 'tutor' ); ?>
825 </div>
826 <button class="tutor-iconic-btn tutor-modal-close" data-tutor-modal-close>
827 <span class="tutor-icon-times" area-hidden="true"></span>
828 </button>
829 </div>
830 <div class="tutor-modal-body tutor-modal-container"></div>
831 </div>
832 </div>
833 </div>
834 <?php
835 }
836 ?>
837 <?php
838 }
839 ?>
840
841 <?php echo is_admin() ? '</div>' : ''; ?>
842