PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 1.7.9
Tutor LMS – eLearning and online course solution v1.7.9
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 / classes / Quiz.php
tutor / classes Last commit date
Addons.php 5 years ago Admin.php 5 years ago Ajax.php 5 years ago Assets.php 5 years ago Course.php 5 years ago Course_Filter.php 5 years ago Course_Settings_Tabs.php 5 years ago Course_Widget.php 5 years ago Custom_Validation.php 5 years ago Dashboard.php 5 years ago Delete_Enrollment_With_Order.php 5 years ago Email.php 5 years ago FormHandler.php 5 years ago Frontend.php 5 years ago Gutenberg.php 5 years ago Instructor.php 5 years ago Instructors_List.php 5 years ago Lesson.php 5 years ago Options.php 5 years ago Post_types.php 5 years ago Private_Course_Access.php 5 years ago Q_and_A.php 5 years ago Question_Answers_List.php 5 years ago Quiz.php 5 years ago Quiz_Attempts_List.php 5 years ago RestAPI.php 5 years ago Rewrite_Rules.php 5 years ago Shortcode.php 5 years ago Student.php 5 years ago Students_List.php 5 years ago Taxonomies.php 5 years ago Template.php 5 years ago Theme_Compatibility.php 5 years ago Tools.php 5 years ago Tutor.php 5 years ago TutorEDD.php 5 years ago Tutor_Base.php 5 years ago Tutor_List_Table.php 5 years ago Tutor_Setup.php 5 years ago Upgrader.php 5 years ago User.php 5 years ago Utils.php 5 years ago Video_Stream.php 5 years ago Withdraw.php 5 years ago Withdraw_Requests_List.php 5 years ago WooCommerce.php 5 years ago
Quiz.php
1192 lines
1 <?php
2
3 /**
4 * Quize class
5 *
6 * @author: themeum
7 * @author_uri: https://themeum.com
8 * @package Tutor
9 * @since v.1.0.0
10 */
11
12 namespace TUTOR;
13
14 if ( ! defined( 'ABSPATH' ) )
15 exit;
16
17 class Quiz {
18
19 public function __construct() {
20 add_action('save_post_tutor_quiz', array($this, 'save_quiz_meta'));
21
22 add_action('wp_ajax_tutor_load_quiz_builder_modal', array($this, 'tutor_load_quiz_builder_modal'));
23 add_action('wp_ajax_remove_quiz_from_post', array($this, 'remove_quiz_from_post'));
24
25 add_action('wp_ajax_tutor_quiz_timeout', array($this, 'tutor_quiz_timeout'));
26
27 //User take the quiz
28 add_action('template_redirect', array($this, 'start_the_quiz'));
29 add_action('template_redirect', array($this, 'answering_quiz'));
30 add_action('template_redirect', array($this, 'finishing_quiz_attempt'));
31
32 add_action('admin_action_review_quiz_answer', array($this, 'review_quiz_answer'));
33 add_action('wp_ajax_review_quiz_answer', array($this, 'review_quiz_answer'));
34 add_action('wp_ajax_tutor_instructor_feedback', array($this, 'tutor_instructor_feedback')); // Instructor Feedback Action
35
36 /**
37 * New Design Quiz
38 */
39
40 add_action('wp_ajax_tutor_create_quiz_and_load_modal', array($this, 'tutor_create_quiz_and_load_modal'));
41 add_action('wp_ajax_tutor_delete_quiz_by_id', array($this, 'tutor_delete_quiz_by_id'));
42 add_action('wp_ajax_tutor_quiz_builder_quiz_update', array($this, 'tutor_quiz_builder_quiz_update'));
43 add_action('wp_ajax_tutor_load_edit_quiz_modal', array($this, 'tutor_load_edit_quiz_modal'));
44 add_action('wp_ajax_tutor_quiz_builder_get_question_form', array($this, 'tutor_quiz_builder_get_question_form'));
45 add_action('wp_ajax_tutor_quiz_modal_update_question', array($this, 'tutor_quiz_modal_update_question'));
46 add_action('wp_ajax_tutor_quiz_builder_question_delete', array($this, 'tutor_quiz_builder_question_delete'));
47 add_action('wp_ajax_tutor_quiz_add_question_answers', array($this, 'tutor_quiz_add_question_answers'));
48 add_action('wp_ajax_tutor_quiz_edit_question_answer', array($this, 'tutor_quiz_edit_question_answer'));
49 add_action('wp_ajax_tutor_save_quiz_answer_options', array($this, 'tutor_save_quiz_answer_options'));
50 add_action('wp_ajax_tutor_update_quiz_answer_options', array($this, 'tutor_update_quiz_answer_options'));
51 add_action('wp_ajax_tutor_quiz_builder_get_answers_by_question', array($this, 'tutor_quiz_builder_get_answers_by_question'));
52 add_action('wp_ajax_tutor_quiz_builder_delete_answer', array($this, 'tutor_quiz_builder_delete_answer'));
53 add_action('wp_ajax_tutor_quiz_question_sorting', array($this, 'tutor_quiz_question_sorting'));
54 add_action('wp_ajax_tutor_quiz_answer_sorting', array($this, 'tutor_quiz_answer_sorting'));
55 add_action('wp_ajax_tutor_mark_answer_as_correct', array($this, 'tutor_mark_answer_as_correct'));
56 add_action('wp_ajax_tutor_quiz_modal_update_settings', array($this, 'tutor_quiz_modal_update_settings'));
57
58 /**
59 * Frontend Stuff
60 */
61 add_action('wp_ajax_tutor_render_quiz_content', array($this, 'tutor_render_quiz_content'));
62 }
63
64 public function tutor_instructor_feedback(){
65 tutils()->checking_nonce();
66
67 $feedback = sanitize_text_field($_POST['feedback']);
68 $attempt_id = (int) tutor_utils()->avalue_dot('attempts_id', $_POST);
69
70 if ($attempt_id && tutils()->can_user_manage('attempt', $attempt_id)) {
71 update_post_meta($attempt_id, 'instructor_feedback', $feedback);
72 do_action('tutor_quiz/attempt/submitted/feedback', $attempt_id);
73 }
74 }
75
76 public function save_quiz_meta($post_ID){
77 if (isset($_POST['quiz_option'])){
78 $quiz_option = tutor_utils()->sanitize_array($_POST['quiz_option']);
79 update_post_meta($post_ID, 'tutor_quiz_option', $quiz_option);
80 }
81 }
82
83 /**
84 * Tutor Quiz Builder Modal
85 */
86 public function tutor_load_quiz_builder_modal(){
87 tutils()->checking_nonce();
88
89 ob_start();
90 include tutor()->path.'views/modal/add_quiz.php';
91 $output = ob_get_clean();
92
93 wp_send_json_success(array('output' => $output));
94 }
95
96 public function remove_quiz_from_post(){
97 tutils()->checking_nonce();
98
99 global $wpdb;
100 $quiz_id = (int) tutor_utils()->avalue_dot('quiz_id', $_POST);
101
102 if(!tutils()->can_user_manage('quiz', $quiz_id)) {
103 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
104 }
105
106 $wpdb->update($wpdb->posts, array('post_parent' => 0), array('ID' => $quiz_id) );
107 wp_send_json_success();
108 }
109
110 /**
111 *
112 * Start Quiz from here...
113 *
114 * @since v.1.0.0
115 */
116
117 public function start_the_quiz(){
118 if ( ! isset($_POST['tutor_action']) || $_POST['tutor_action'] !== 'tutor_start_quiz' ){
119 return;
120 }
121 //Checking nonce
122 tutor_utils()->checking_nonce();
123
124 if ( ! is_user_logged_in()){
125 //TODO: need to set a view in the next version
126 die('Please sign in to do this operation');
127 }
128
129 global $wpdb;
130
131 $user_id = get_current_user_id();
132 $user = get_userdata($user_id);
133
134 $quiz_id = (int) sanitize_text_field($_POST['quiz_id']);
135
136 $quiz = get_post($quiz_id);
137 $course = tutor_utils()->get_course_by_quiz($quiz_id);
138 if ( empty($course->ID)){
139 die('There is something went wrong with course, please check if quiz attached with a course');
140 }
141
142 do_action('tutor_quiz/start/before', $quiz_id, $user_id);
143
144 $date = date("Y-m-d H:i:s", tutor_time());
145
146 $tutor_quiz_option = (array) maybe_unserialize(get_post_meta($quiz_id, 'tutor_quiz_option', true));
147 $attempts_allowed = tutor_utils()->get_quiz_option($quiz_id, 'attempts_allowed', 0);
148
149 $time_limit = tutor_utils()->get_quiz_option($quiz_id, 'time_limit.time_value');
150 $time_limit_seconds = 0;
151 $time_type = 'seconds';
152 if ($time_limit){
153 $time_type = tutor_utils()->get_quiz_option($quiz_id, 'time_limit.time_type');
154
155 switch ($time_type){
156 case 'seconds':
157 $time_limit_seconds = $time_limit;
158 break;
159 case 'minutes':
160 $time_limit_seconds = $time_limit * 60;
161 break;
162 case 'hours':
163 $time_limit_seconds = $time_limit * 60 * 60;
164 break;
165 case 'days':
166 $time_limit_seconds = $time_limit * 60 * 60 * 24;
167 break;
168 case 'weeks':
169 $time_limit_seconds = $time_limit * 60 * 60 * 24 * 7;
170 break;
171 }
172 }
173
174 $max_question_allowed = tutor_utils()->max_questions_for_take_quiz($quiz_id);
175 $tutor_quiz_option['time_limit']['time_limit_seconds'] = $time_limit_seconds;
176
177 $attempt_data = array(
178 'course_id' => $course->ID,
179 'quiz_id' => $quiz_id,
180 'user_id' => $user_id,
181 'total_questions' => $max_question_allowed,
182 'total_answered_questions' => 0,
183 'attempt_info' => maybe_serialize($tutor_quiz_option),
184 'attempt_status' => 'attempt_started',
185 'attempt_ip' => tutor_utils()->get_ip(),
186 'attempt_started_at' => $date,
187 );
188
189 $wpdb->insert($wpdb->prefix.'tutor_quiz_attempts', $attempt_data);
190 $attempt_id = (int) $wpdb->insert_id;
191
192 do_action('tutor_quiz/start/after', $quiz_id, $user_id, $attempt_id);
193
194 wp_redirect(get_permalink($quiz_id));
195 die();
196 }
197
198 public function answering_quiz(){
199
200 if ( tutils()->array_get('tutor_action', $_POST) !== 'tutor_answering_quiz_question' ){
201 return;
202 }
203 //Checking nonce
204 tutor_utils()->checking_nonce();
205
206 $attempt_id = (int) sanitize_text_field(tutor_utils()->avalue_dot('attempt_id', $_POST));
207 $attempt = tutor_utils()->get_attempt($attempt_id);
208
209 $attempt_answers = isset($_POST['attempt']) ? $_POST['attempt'] : false;
210 if ( ! is_user_logged_in()){
211 die('Please sign in to do this operation');
212 }
213
214 global $wpdb;
215 $user_id = get_current_user_id();
216
217 do_action('tutor_quiz/attempt_analysing/before', $attempt_id);
218
219 if ($attempt_answers && is_array($attempt_answers) && count($attempt_answers)){
220 foreach ($attempt_answers as $attempt_id => $attempt_answer){
221
222 /**
223 * Get total marks of all question comes
224 */
225 $question_ids = tutor_utils()->avalue_dot('quiz_question_ids', $attempt_answer);
226 if (is_array($question_ids) && count($question_ids)){
227 $question_ids_string = "'".implode("','", $question_ids)."'";
228 $total_question_marks = $wpdb->get_var("SELECT SUM(question_mark) FROM {$wpdb->prefix}tutor_quiz_questions WHERE question_id IN({$question_ids_string}) ;");
229 $wpdb->update($wpdb->prefix.'tutor_quiz_attempts', array('total_marks' =>$total_question_marks ), array('attempt_id' => $attempt_id ));
230 }
231
232 if ( ! $attempt || $user_id != $attempt->user_id){
233 die('Operation not allowed, attempt not found or permission denied');
234 }
235
236 $quiz_answers = tutor_utils()->avalue_dot('quiz_question', $attempt_answer);
237
238 $total_marks = 0;
239 $review_required = false;
240
241 if ( tutils()->count($quiz_answers)) {
242
243 foreach ( $quiz_answers as $question_id => $answers ) {
244 $question = tutor_utils()->get_quiz_question_by_id( $question_id );
245 $question_type = $question->question_type;
246
247 $is_answer_was_correct = false;
248 $given_answer = '';
249
250 if ( $question_type === 'true_false' || $question_type === 'single_choice' ) {
251
252 $given_answer = $answers;
253 $is_answer_was_correct = (bool) $wpdb->get_var( "SELECT is_correct FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE answer_id = {$answers} " );
254
255 } elseif ( $question_type === 'multiple_choice' ) {
256
257 $given_answer = (array) ( $answers );
258 $get_original_answers = (array) $wpdb->get_col($wpdb->prepare(
259 "SELECT answer_id
260 FROM {$wpdb->prefix}tutor_quiz_question_answers
261 WHERE belongs_question_id = %d AND belongs_question_type = %s AND is_correct = 1 ;", $question->question_id, $question_type));
262
263
264 if (count(array_diff($get_original_answers, $given_answer)) === 0 && count($get_original_answers) === count($given_answer)) {
265 $is_answer_was_correct = true;
266 }
267 $given_answer = maybe_serialize( $answers );
268
269 } elseif ( $question_type === 'fill_in_the_blank' ) {
270
271 $given_answer = (array) array_map( 'sanitize_text_field', $answers );
272 $given_answer = maybe_serialize( $given_answer );
273
274 $get_original_answer = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE belongs_question_id = {$question->question_id} AND belongs_question_type = '{$question_type}' ;" );
275 $gap_answer = (array) explode( '|', $get_original_answer->answer_two_gap_match );
276
277 $gap_answer = array_map( 'sanitize_text_field', $gap_answer );
278 if ( strtolower($given_answer) == strtolower(maybe_serialize( $gap_answer )) ) {
279 $is_answer_was_correct = true;
280 }
281 } elseif ( $question_type === 'open_ended' || $question_type === 'short_answer' ) {
282 $review_required = true;
283 $given_answer = wp_kses_post( $answers );
284
285 } elseif ( $question_type === 'ordering' || $question_type === 'matching' || $question_type === 'image_matching' ) {
286
287 $given_answer = (array) array_map( 'sanitize_text_field', tutor_utils()->avalue_dot( 'answers', $answers ) );
288 $given_answer = maybe_serialize( $given_answer );
289
290 $get_original_answers = (array) $wpdb->get_col($wpdb->prepare(
291 "SELECT answer_id
292 FROM {$wpdb->prefix}tutor_quiz_question_answers
293 WHERE belongs_question_id = %d AND belongs_question_type = %s ORDER BY answer_order ASC ;", $question->question_id, $question_type));
294
295 $get_original_answers = array_map( 'sanitize_text_field', $get_original_answers );
296
297 if ( $given_answer == maybe_serialize( $get_original_answers ) ) {
298 $is_answer_was_correct = true;
299 }
300
301 } elseif ( $question_type === 'image_answering' ) {
302 $image_inputs = tutor_utils()->avalue_dot( 'answer_id', $answers );
303 $image_inputs = (array) array_map( 'sanitize_text_field', $image_inputs );
304 $given_answer = maybe_serialize( $image_inputs );
305 $is_answer_was_correct = false;
306
307 $db_answer = $wpdb->get_col($wpdb->prepare(
308 "SELECT answer_title
309 FROM {$wpdb->prefix}tutor_quiz_question_answers
310 WHERE belongs_question_id = %d AND belongs_question_type = 'image_answering' ORDER BY answer_order asc ;", $question_id));
311
312 if ( is_array( $db_answer ) && count( $db_answer ) ) {
313 $is_answer_was_correct = ( strtolower( maybe_serialize( array_values( $image_inputs ) ) ) == strtolower( maybe_serialize( $db_answer ) ) );
314 }
315 }
316
317 $question_mark = $is_answer_was_correct ? $question->question_mark : 0;
318 $total_marks += $question_mark;
319
320 $answers_data = array(
321 'user_id' => $user_id,
322 'quiz_id' => $attempt->quiz_id,
323 'question_id' => $question_id,
324 'quiz_attempt_id' => $attempt_id,
325 'given_answer' => $given_answer,
326 'question_mark' => $question->question_mark,
327 'achieved_mark' => $question_mark,
328 'minus_mark' => 0,
329 'is_correct' => $is_answer_was_correct ? 1 : 0,
330 );
331
332 /*
333 check if question_type open ended or short ans the set is_correct default value null before saving
334 */
335 if($question_type==="open_ended" || $question_type ==="short_answer")
336 {
337 $answers_data['is_correct'] = NULL;
338 }
339
340 $wpdb->insert( $wpdb->prefix . 'tutor_quiz_attempt_answers', $answers_data );
341 }
342 }
343
344 $attempt_info = array(
345 'total_answered_questions' => tutils()->count($quiz_answers),
346 'earned_marks' => $total_marks,
347 'attempt_status' => 'attempt_ended',
348 'attempt_ended_at' => date("Y-m-d H:i:s", tutor_time()),
349 );
350
351 if ($review_required){
352 $attempt_info['attempt_status'] = 'review_required';
353 }
354
355 $wpdb->update($wpdb->prefix.'tutor_quiz_attempts', $attempt_info, array('attempt_id' => $attempt_id));
356 }
357
358 do_action('tutor_quiz/attempt_ended', $attempt_id);
359 }
360
361 wp_redirect(get_the_permalink($attempt->quiz_id));
362 die();
363 }
364
365
366 /**
367 * Quiz attempt will be finish here
368 *
369 */
370
371 public function finishing_quiz_attempt(){
372
373 if ( ! isset($_POST['tutor_action']) || $_POST['tutor_action'] !== 'tutor_finish_quiz_attempt' ){
374 return;
375 }
376 //Checking nonce
377 tutor_utils()->checking_nonce();
378
379 if ( ! is_user_logged_in()){
380 die('Please sign in to do this operation');
381 }
382
383 global $wpdb;
384
385 $quiz_id = (int) sanitize_text_field($_POST['quiz_id']);
386 $attempt = tutor_utils()->is_started_quiz($quiz_id);
387 $attempt_id = $attempt->attempt_id;
388
389 $attempt_info = array(
390 'total_answered_questions' => 0,
391 'earned_marks' => 0,
392 'attempt_status' => 'attempt_ended',
393 'attempt_ended_at' => date("Y-m-d H:i:s", tutor_time()),
394 );
395
396 do_action('tutor_quiz_before_finish', $attempt_id, $quiz_id, $attempt->user_id);
397 $wpdb->update($wpdb->prefix.'tutor_quiz_attempts', $attempt_info, array('attempt_id' => $attempt_id));
398 do_action('tutor_quiz_finished', $attempt_id, $quiz_id, $attempt->user_id);
399
400 wp_redirect(tutor_utils()->input_old('_wp_http_referer'));
401 }
402
403 /**
404 * Quiz timeout by ajax
405 */
406 public function tutor_quiz_timeout(){
407 tutils()->checking_nonce();
408
409 global $wpdb;
410
411 $quiz_id = (int) sanitize_text_field($_POST['quiz_id']);
412
413 if(!tutils()->can_user_manage('quiz', $quiz_id)) {
414 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
415 }
416
417 $attempt = tutor_utils()->is_started_quiz($quiz_id);
418
419 if ($attempt) {
420 $attempt_id = $attempt->attempt_id;
421
422 $data = array(
423 'attempt_status' => 'attempt_timeout',
424 'attempt_ended_at' => date("Y-m-d H:i:s", tutor_time()),
425 );
426 $wpdb->update($wpdb->prefix.'tutor_quiz_attempts', $data, array('attempt_id' => $attempt->attempt_id));
427
428 do_action('tutor_quiz_timeout', $attempt_id, $quiz_id, $attempt->user_id);
429
430 wp_send_json_success();
431 }
432
433 wp_send_json_error(__('Quiz has been timeout already', 'tutor'));
434 }
435
436 /**
437 * Review the answer and change individual answer result
438 */
439
440 public function review_quiz_answer() {
441
442 tutils()->checking_nonce(strtolower($_SERVER['REQUEST_METHOD']));
443
444 global $wpdb;
445
446 $attempt_id = (int) sanitize_text_field($_GET['attempt_id']);
447 $attempt_answer_id = (int) sanitize_text_field($_GET['attempt_answer_id']);
448 $mark_as = sanitize_text_field($_GET['mark_as']);
449
450 if(!tutils()->can_user_manage('attempt', $attempt_id) || !tutils()->can_user_manage('attempt_answer', $attempt_answer_id)) {
451 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
452 }
453
454 $attempt_answer = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}tutor_quiz_attempt_answers WHERE attempt_answer_id = %d ", $attempt_answer_id));
455
456 $attempt = tutor_utils()->get_attempt($attempt_id);
457 $question = tutils()->get_quiz_question_by_id($attempt_answer->question_id);
458
459 $previous_ans = $attempt_answer->is_correct;
460
461 do_action('tutor_quiz_review_answer_before', $attempt_answer_id, $attempt_id, $mark_as);
462
463 if ($mark_as === 'correct'){
464
465 $answer_update_data = array(
466 'achieved_mark' => $attempt_answer->question_mark,
467 'is_correct' => 1,
468 );
469 $wpdb->update($wpdb->prefix.'tutor_quiz_attempt_answers', $answer_update_data, array('attempt_answer_id' => $attempt_answer_id ));
470 if($previous_ans ==0 OR $previous_ans ==null)
471 {
472
473 //if previous answer was wrong or in review then add point as correct
474 $attempt_update_data = array(
475 'earned_marks' => $attempt->earned_marks + $attempt_answer->question_mark,
476 'is_manually_reviewed' => 1,
477 'manually_reviewed_at' => date("Y-m-d H:i:s", tutor_time()),
478 );
479
480
481 }
482
483 if ($question->question_type === 'open_ended' || $question->question_type === 'short_answer' ){
484 $attempt_update_data['attempt_status'] = 'attempt_ended';
485 }
486 $wpdb->update($wpdb->prefix.'tutor_quiz_attempts', $attempt_update_data, array('attempt_id' => $attempt_id ));
487 }
488 elseif($mark_as === 'incorrect')
489 {
490
491 $answer_update_data = array(
492 'achieved_mark' => '0.00',
493 'is_correct' => 0,
494 );
495 $wpdb->update($wpdb->prefix.'tutor_quiz_attempt_answers', $answer_update_data, array('attempt_answer_id' => $attempt_answer_id ));
496
497
498 if($previous_ans ==1)
499 {
500
501 //if previous ans was right then mynus
502 $attempt_update_data = array(
503 'earned_marks' => $attempt->earned_marks - $attempt_answer->question_mark,
504 'is_manually_reviewed' => 1,
505 'manually_reviewed_at' => date("Y-m-d H:i:s", tutor_time()),
506 );
507
508 }
509 if ($question->question_type === 'open_ended' || $question->question_type === 'short_answer' ){
510 $attempt_update_data['attempt_status'] = 'attempt_ended';
511 }
512
513 $wpdb->update($wpdb->prefix.'tutor_quiz_attempts', $attempt_update_data, array('attempt_id' => $attempt_id ));
514 }
515 do_action('tutor_quiz_review_answer_after', $attempt_answer_id, $attempt_id, $mark_as);
516
517 if (wp_doing_ajax())
518 {
519 wp_send_json_success();
520 }
521 else{
522 wp_redirect(admin_url("admin.php?page=tutor_quiz_attempts&sub_page=view_attempt&attempt_id=".$attempt_id));
523 }
524
525 die();
526 }
527
528
529 /**
530 * New Design Quiz
531 */
532 public function tutor_create_quiz_and_load_modal(){
533 tutils()->checking_nonce();
534
535 $topic_id = sanitize_text_field($_POST['topic_id']);
536 $quiz_title = sanitize_text_field($_POST['quiz_title']);
537 $quiz_description = sanitize_text_field($_POST['quiz_description']);
538 $next_order_id = tutor_utils()->get_next_course_content_order_id($topic_id);
539
540 if(!tutils()->can_user_manage('topic', $topic_id)) {
541 wp_send_json_error( array('message'=>__('Access Denied', 'tutor'), 'data'=>$_POST) );
542 }
543
544 $post_arr = array(
545 'post_type' => 'tutor_quiz',
546 'post_title' => $quiz_title,
547 'post_content' => $quiz_description,
548 'post_status' => 'publish',
549 'post_author' => get_current_user_id(),
550 'post_parent' => $topic_id,
551 'menu_order' => $next_order_id,
552 );
553 $quiz_id = wp_insert_post( $post_arr );
554 do_action('tutor_initial_quiz_created', $quiz_id);
555
556 ob_start();
557 include tutor()->path.'views/modal/edit_quiz.php';
558 $output = ob_get_clean();
559
560 ob_start();
561 ?>
562 <div id="tutor-quiz-<?php echo $quiz_id; ?>" class="course-content-item tutor-quiz tutor-quiz-<?php echo $quiz_id; ?>">
563 <div class="tutor-lesson-top">
564 <i class="tutor-icon-move"></i>
565 <a href="javascript:;" class="open-tutor-quiz-modal" data-quiz-id="<?php echo $quiz_id; ?>" data-topic-id="<?php echo $topic_id;
566 ?>"> <i class=" tutor-icon-doubt"></i>[<?php _e('QUIZ', 'tutor'); ?>] <?php echo stripslashes($quiz_title); ?> </a>
567 <?php do_action('tutor_course_builder_before_quiz_btn_action', $quiz_id); ?>
568 <a href="javascript:;" class="tutor-delete-quiz-btn" data-quiz-id="<?php echo $quiz_id; ?>"><i class="tutor-icon-garbage"></i></a>
569 </div>
570 </div>
571 <?php
572 $output_quiz_row = ob_get_clean();
573
574 wp_send_json_success(array('output' => $output, 'output_quiz_row' => $output_quiz_row));
575 }
576
577 public function tutor_delete_quiz_by_id(){
578 tutils()->checking_nonce();
579
580 global $wpdb;
581
582 $quiz_id = (int) sanitize_text_field($_POST['quiz_id']);
583 $post = get_post($quiz_id);
584
585
586 if(!tutils()->can_user_manage('quiz', $quiz_id)) {
587 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
588 }
589
590 if ( $post->post_type === 'tutor_quiz'){
591 do_action('tutor_delete_quiz_before', $quiz_id);
592
593 $wpdb->delete($wpdb->prefix.'tutor_quiz_attempts', array('quiz_id' => $quiz_id));
594 $wpdb->delete($wpdb->prefix.'tutor_quiz_attempt_answers', array('quiz_id' => $quiz_id));
595
596 $questions_ids = $wpdb->get_col($wpdb->prepare("SELECT question_id FROM {$wpdb->prefix}tutor_quiz_questions WHERE quiz_id = %d ", $quiz_id));
597
598 if (is_array($questions_ids) && count($questions_ids)){
599 $in_question_ids = "'".implode("','", $questions_ids)."'";
600 $wpdb->query("DELETE FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE belongs_question_id IN({$in_question_ids}) ");
601 }
602
603 $wpdb->delete($wpdb->prefix.'tutor_quiz_questions', array('quiz_id' => $quiz_id));
604
605 wp_delete_post($quiz_id, true);
606 delete_post_meta($quiz_id, '_tutor_course_id_for_lesson');
607
608 do_action('tutor_delete_quiz_after', $quiz_id);
609
610
611 wp_send_json_success();
612 }
613
614 wp_send_json_error();
615 }
616
617 /**
618 * Update Quiz from quiz builder modal
619 *
620 * @since v.1.0.0
621 */
622 public function tutor_quiz_builder_quiz_update(){
623 tutils()->checking_nonce();
624
625 $quiz_id = sanitize_text_field($_POST['quiz_id']);
626 $topic_id = sanitize_text_field($_POST['topic_id']);
627 $quiz_title = sanitize_text_field($_POST['quiz_title']);
628 $quiz_description = sanitize_text_field($_POST['quiz_description']);
629
630 if(!tutils()->can_user_manage('quiz', $quiz_id)) {
631 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
632 }
633
634 $post_arr = array(
635 'ID' => $quiz_id,
636 'post_title' => $quiz_title,
637 'post_content' => $quiz_description,
638
639 );
640 $quiz_id = wp_update_post( $post_arr );
641
642 do_action('tutor_quiz_updated', $quiz_id);
643
644 ob_start();
645 ?>
646 <div class="tutor-lesson-top">
647 <i class="tutor-icon-move"></i>
648 <a href="javascript:;" class="open-tutor-quiz-modal" data-quiz-id="<?php echo $quiz_id; ?>" data-topic-id="<?php echo $topic_id;
649 ?>"> <i class=" tutor-icon-doubt"></i>[<?php _e('QUIZ', 'tutor'); ?>] <?php echo stripslashes($quiz_title); ?> </a>
650 <?php do_action('tutor_course_builder_before_quiz_btn_action', $quiz_id); ?>
651 <a href="javascript:;" class="tutor-delete-quiz-btn" data-quiz-id="<?php echo $quiz_id; ?>"><i class="tutor-icon-garbage"></i></a>
652 </div>
653 <?php
654 $output_quiz_row = ob_get_clean();
655
656 wp_send_json_success(array('output_quiz_row' => $output_quiz_row));
657 }
658
659 /**
660 * Load quiz Modal for edit quiz
661 *
662 * @since v.1.0.0
663 */
664 public function tutor_load_edit_quiz_modal(){
665 tutils()->checking_nonce();
666
667 $quiz_id = sanitize_text_field($_POST['quiz_id']);
668
669 if(!tutils()->can_user_manage('quiz', $quiz_id)) {
670 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
671 }
672
673 ob_start();
674 include tutor()->path.'views/modal/edit_quiz.php';
675 $output = ob_get_clean();
676
677 wp_send_json_success(array('output' => $output));
678 }
679
680 /**
681 * Load quiz question form for quiz
682 *
683 * @since v.1.0.0
684 */
685 public function tutor_quiz_builder_get_question_form(){
686 tutils()->checking_nonce();
687
688 global $wpdb;
689 $quiz_id = sanitize_text_field($_POST['quiz_id']);
690 $question_id = sanitize_text_field(tutor_utils()->avalue_dot('question_id', $_POST));
691
692 if(!tutils()->can_user_manage('quiz', $quiz_id)) {
693 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
694 }
695
696 if ( ! $question_id){
697 $next_question_id = tutor_utils()->quiz_next_question_id();
698 $next_question_order = tutor_utils()->quiz_next_question_order_id($quiz_id);
699
700 $new_question_data = array(
701 'quiz_id' => $quiz_id,
702 'question_title' => __('Question', 'tutor').' '.$next_question_id,
703 'question_description' => '',
704 'question_type' => 'true_false',
705 'question_mark' => 1,
706 'question_settings' => maybe_serialize(array()),
707 'question_order' => esc_sql( $next_question_order ) ,
708 );
709
710 $wpdb->insert($wpdb->prefix.'tutor_quiz_questions', $new_question_data);
711 $question_id = $wpdb->insert_id;
712 }
713
714 $question = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}tutor_quiz_questions where question_id = %d ", $question_id));
715
716 ob_start();
717 include tutor()->path.'views/modal/question_form.php';
718 $output = ob_get_clean();
719
720 wp_send_json_success(array('output' => $output));
721 }
722
723 public function tutor_quiz_modal_update_question(){
724 tutils()->checking_nonce();
725
726 global $wpdb;
727
728 $question_data = $_POST['tutor_quiz_question'];
729
730 foreach ($question_data as $question_id => $question) {
731
732 if(!tutils()->can_user_manage('question', $question_id)) {
733 continue;
734 }
735
736 $question_title = sanitize_text_field($question['question_title']);
737 $question_description = sanitize_text_field($question['question_description']);
738 $question_type = sanitize_text_field($question['question_type']);
739 $question_mark = sanitize_text_field($question['question_mark']);
740
741 unset($question['question_title']);
742 unset($question['question_description']);
743
744 $data = array(
745 'question_title' => $question_title,
746 'question_description' => $question_description,
747 'question_type' => $question_type,
748 'question_mark' => $question_mark,
749 'question_settings' => maybe_serialize($question),
750 );
751
752 $wpdb->update($wpdb->prefix.'tutor_quiz_questions', $data, array('question_id' => $question_id) );
753
754
755 /**
756 * Validation
757 */
758 if ($question_type === 'true_false' || $question_type === 'single_choice'){
759 $question_options = tutils()->get_answers_by_quiz_question($question_id);
760 if (tutils()->count($question_options)){
761 $required_validate = true;
762 foreach ($question_options as $question_option){
763 if ($question_option->is_correct){
764 $required_validate = false;
765 }
766 }
767 if ($required_validate){
768 $validation_msg = "<p class='tutor-error-msg'>".__('Please select the correct answer', 'tutor')."</p>";
769 wp_send_json_error(array('validation_msg' => $validation_msg ));
770 }
771 }else{
772 $validation_msg = "<p class='tutor-error-msg'>".__('Please make sure you have added more than one option and saved them', 'tutor')."</p>";
773 wp_send_json_error(array('validation_msg' => $validation_msg ));
774 }
775 }
776 }
777
778 wp_send_json_success();
779 }
780
781 public function tutor_quiz_builder_question_delete(){
782 tutils()->checking_nonce();
783
784 global $wpdb;
785
786 $question_id = sanitize_text_field(tutor_utils()->avalue_dot('question_id', $_POST));
787
788 if(!tutils()->can_user_manage('question', $question_id)) {
789 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
790 }
791
792 if ($question_id){
793 $wpdb->delete($wpdb->prefix.'tutor_quiz_questions', array('question_id' => esc_sql( $question_id ) ));
794 }
795
796 wp_send_json_success();
797 }
798
799 /**
800 * Get answers options form for quiz question
801 *
802 * @since v.1.0.0
803 */
804 public function tutor_quiz_add_question_answers(){
805 tutils()->checking_nonce();
806
807 $question_id = sanitize_text_field($_POST['question_id']);
808 $question = tutor_utils()->avalue_dot($question_id, $_POST['tutor_quiz_question']);
809 $question_type = $question['question_type'];
810
811 if(!tutils()->can_user_manage('question', $question_id)) {
812 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
813 }
814
815 ob_start();
816 include tutor()->path.'views/modal/question_answer_form.php';
817 $output = ob_get_clean();
818
819 wp_send_json_success(array('output' => $output));
820 }
821
822 /**
823 * Edit Answer Form
824 *
825 * @since v.1.0.0
826 */
827 public function tutor_quiz_edit_question_answer(){
828 tutils()->checking_nonce();
829
830 $answer_id = (int) sanitize_text_field($_POST['answer_id']);
831
832 if(!tutils()->can_user_manage('quiz_answer', $answer_id)) {
833 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
834 }
835
836 $old_answer = tutor_utils()->get_answer_by_id($answer_id);
837 foreach ($old_answer as $old_answer);
838 $question_id = $old_answer->belongs_question_id;
839 $question_type = $old_answer->belongs_question_type;
840
841 ob_start();
842 include tutor()->path.'views/modal/question_answer_edit_form.php';
843 $output = ob_get_clean();
844
845 wp_send_json_success(array('output' => $output));
846 }
847
848 public function tutor_save_quiz_answer_options(){
849 tutils()->checking_nonce();
850
851 global $wpdb;
852
853 $questions = $_POST['tutor_quiz_question'];
854 $answers = $_POST['quiz_answer'];
855
856 foreach ($answers as $question_id => $answer){
857
858 if(!tutils()->can_user_manage('question', $question_id)) {
859 continue;
860 }
861
862 $question = tutor_utils()->avalue_dot($question_id, $questions);
863 $question_type = $question['question_type'];
864
865 //Getting next sorting order
866 $next_order_id = (int) $wpdb->get_var($wpdb->prepare(
867 "SELECT MAX(answer_order)
868 FROM {$wpdb->prefix}tutor_quiz_question_answers
869 where belongs_question_id = %d
870 AND belongs_question_type = %s ", $question_id, esc_sql( $question_type )));
871
872 $next_order_id = $next_order_id + 1;
873
874 if ($question){
875 if ($question_type === 'true_false'){
876 $wpdb->delete($wpdb->prefix.'tutor_quiz_question_answers', array('belongs_question_id' => $question_id, 'belongs_question_type' => $question_type));
877 $data_true_false = array(
878 array(
879 'belongs_question_id' => esc_sql( $question_id ) ,
880 'belongs_question_type' => $question_type,
881 'answer_title' => __('True', 'tutor'),
882 'is_correct' => $answer['true_false'] == 'true' ? 1 : 0,
883 'answer_two_gap_match' => 'true',
884 ),
885 array(
886 'belongs_question_id' => esc_sql( $question_id ) ,
887 'belongs_question_type' => $question_type,
888 'answer_title' => __('False', 'tutor'),
889 'is_correct' => $answer['true_false'] == 'false' ? 1 : 0,
890 'answer_two_gap_match' => 'false',
891 ),
892 );
893
894 foreach ($data_true_false as $true_false_data){
895 $wpdb->insert($wpdb->prefix.'tutor_quiz_question_answers', $true_false_data);
896 }
897
898 }elseif($question_type === 'multiple_choice' || $question_type === 'single_choice' || $question_type === 'ordering' ||
899 $question_type === 'matching' || $question_type === 'image_matching' || $question_type === 'image_answering' ){
900
901 $answer_data = array(
902 'belongs_question_id' => sanitize_text_field( $question_id ),
903 'belongs_question_type' => $question_type,
904 'answer_title' => sanitize_text_field( $answer['answer_title'] ),
905 'image_id' => isset($answer['image_id']) ? $answer['image_id'] : 0,
906 'answer_view_format' => isset($answer['answer_view_format']) ? $answer['answer_view_format'] : 0,
907 'answer_order' => $next_order_id,
908 );
909 if (isset($answer['matched_answer_title'])){
910 $answer_data['answer_two_gap_match'] = sanitize_text_field( $answer['matched_answer_title'] );
911 }
912
913 $wpdb->insert($wpdb->prefix.'tutor_quiz_question_answers', $answer_data);
914
915 }elseif($question_type === 'fill_in_the_blank'){
916 $wpdb->delete($wpdb->prefix.'tutor_quiz_question_answers', array('belongs_question_id' => $question_id, 'belongs_question_type' => $question_type));
917 $answer_data = array(
918 'belongs_question_id' => sanitize_text_field( $question_id ) ,
919 'belongs_question_type' => $question_type,
920 'answer_title' => sanitize_text_field( $answer['answer_title'] ),
921 'answer_two_gap_match' => isset($answer['answer_two_gap_match']) ? sanitize_text_field( trim($answer['answer_two_gap_match']) ) : null,
922 );
923 $wpdb->insert($wpdb->prefix.'tutor_quiz_question_answers', $answer_data);
924 }
925 }
926 }
927
928 wp_send_json_success();
929 }
930
931 /**
932 * Tutor Update Answer
933 *
934 * @since v.1.0.0
935 */
936 public function tutor_update_quiz_answer_options(){
937 tutils()->checking_nonce();
938
939 global $wpdb;
940
941 $answer_id = (int) sanitize_text_field($_POST['tutor_quiz_answer_id']);
942
943 if(!tutils()->can_user_manage('quiz_answer', $answer_id)) {
944 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
945 }
946
947 $questions = $_POST['tutor_quiz_question'];
948 $answers = $_POST['quiz_answer'];
949
950 foreach ($answers as $question_id => $answer){
951 $question = tutor_utils()->avalue_dot($question_id, $questions);
952 $question_type = $question['question_type'];
953
954 if ($question){
955 if($question_type === 'multiple_choice' || $question_type === 'single_choice' || $question_type === 'ordering' || $question_type === 'matching' || $question_type === 'image_matching' || $question_type === 'fill_in_the_blank' || $question_type === 'image_answering' ){
956
957 $answer_data = array(
958 'belongs_question_id' => $question_id,
959 'belongs_question_type' => $question_type,
960 'answer_title' => sanitize_text_field( $answer['answer_title'] ) ,
961 'image_id' => isset($answer['image_id']) ? $answer['image_id'] : 0,
962 'answer_view_format' => isset($answer['answer_view_format']) ? sanitize_text_field( $answer['answer_view_format'] ) : '',
963 );
964 if (isset($answer['matched_answer_title'])){
965 $answer_data['answer_two_gap_match'] = sanitize_text_field( $answer['matched_answer_title'] ) ;
966 }
967
968 if ($question_type === 'fill_in_the_blank'){
969 $answer_data['answer_two_gap_match'] = isset($answer['answer_two_gap_match']) ? sanitize_text_field(trim($answer['answer_two_gap_match'])) : null;
970 }
971
972 $wpdb->update($wpdb->prefix.'tutor_quiz_question_answers', $answer_data, array('answer_id' => $answer_id));
973 }
974 }
975 }
976
977 //die(print_r($_POST));
978 wp_send_json_success();
979 }
980
981 public function tutor_quiz_builder_get_answers_by_question(){
982 tutils()->checking_nonce();
983
984 global $wpdb;
985 $question_id = sanitize_text_field($_POST['question_id']);
986 $question_type = sanitize_text_field($_POST['question_type']);
987
988 if(!tutils()->can_user_manage('question', $question_id)) {
989 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
990 }
991
992 $question = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}tutor_quiz_questions WHERE question_id = %d ", $question_id));
993 $answers = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}tutor_quiz_question_answers where belongs_question_id = %d AND belongs_question_type = %s order by answer_order asc ;", $question_id, esc_sql( $question_type ) ));
994
995 ob_start();
996
997 switch ($question_type){
998 case 'true_false':
999 echo '<label>'.__('Answer options &amp; mark correct', 'tutor').'</label>';
1000 break;
1001 case 'ordering':
1002 echo '<label>'.__('Make sure you’re saving the answers in the right order. Students will have to match this order exactly.', 'tutor').'</label>';
1003 break;
1004 }
1005
1006 if (is_array($answers) && count($answers)){
1007 foreach ($answers as $answer){
1008 ?>
1009 <div class="tutor-quiz-answer-wrap" data-answer-id="<?php echo $answer->answer_id; ?>">
1010 <div class="tutor-quiz-answer">
1011 <span class="tutor-quiz-answer-title">
1012 <?php
1013 echo stripslashes($answer->answer_title);
1014 if ($answer->belongs_question_type === 'fill_in_the_blank'){
1015 echo ' ('.__('Answer', 'tutor').' : ';
1016 echo '<strong>'. stripslashes($answer->answer_two_gap_match). '</strong>)';
1017 }
1018 if ($answer->belongs_question_type === 'matching'){
1019 echo ' - '.stripslashes($answer->answer_two_gap_match);
1020 }
1021 ?>
1022 </span>
1023
1024 <?php
1025 if ($answer->image_id){
1026 echo '<span class="tutor-question-answer-image"><img src="'.wp_get_attachment_image_url($answer->image_id).'" /> </span>';
1027 }
1028 if ($question_type === 'true_false' || $question_type === 'single_choice'){
1029 ?>
1030 <span class="tutor-quiz-answers-mark-correct-wrap">
1031 <input type="radio" name="mark_as_correct[<?php echo $answer->belongs_question_id; ?>]" value="<?php echo $answer->answer_id; ?>" title="<?php _e('Mark as correct', 'tutor'); ?>" <?php checked(1, $answer->is_correct); ?> >
1032 </span>
1033 <?php
1034 }elseif ($question_type === 'multiple_choice'){
1035 ?>
1036 <span class="tutor-quiz-answers-mark-correct-wrap">
1037 <input type="checkbox" name="mark_as_correct[<?php echo $answer->belongs_question_id; ?>]" value="<?php echo $answer->answer_id; ?>" title="<?php _e('Mark as correct', 'tutor'); ?>" <?php checked(1, $answer->is_correct); ?> >
1038 </span>
1039 <?php
1040 }
1041 ?>
1042 <span class="tutor-quiz-answer-edit">
1043 <a href="javascript:;"><i class="tutor-icon-pencil"></i> </a>
1044 </span>
1045 <span class="tutor-quiz-answer-sort-icon"><i class="tutor-icon-menu-2"></i> </span>
1046 </div>
1047
1048 <div class="tutor-quiz-answer-trash-wrap">
1049 <a href="javascript:;" class="answer-trash-btn" data-answer-id="<?php echo $answer->answer_id; ?>"><i class="tutor-icon-garbage"></i> </a>
1050 </div>
1051 </div>
1052 <?php
1053 }
1054 }
1055 $output = ob_get_clean();
1056
1057 wp_send_json_success(array('output' => $output));
1058 }
1059
1060 public function tutor_quiz_builder_delete_answer(){
1061 tutils()->checking_nonce();
1062
1063 global $wpdb;
1064 $answer_id = sanitize_text_field($_POST['answer_id']);
1065
1066 if(!tutils()->can_user_manage('quiz_answer', $answer_id)) {
1067 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
1068 }
1069
1070 $wpdb->delete($wpdb->prefix.'tutor_quiz_question_answers', array('answer_id' => esc_sql( $answer_id ) ));
1071 wp_send_json_success();
1072 }
1073
1074 /**
1075 * Save quiz questions sorting
1076 */
1077 public function tutor_quiz_question_sorting(){
1078 tutils()->checking_nonce();
1079
1080 global $wpdb;
1081
1082 $question_ids = tutor_utils()->avalue_dot('sorted_question_ids', $_POST);
1083 if (is_array($question_ids) && count($question_ids) ){
1084 $i = 0;
1085 foreach ($question_ids as $key => $question_id){
1086 if(tutils()->can_user_manage('question', $question_id)) {
1087 $i++;
1088 $wpdb->update($wpdb->prefix.'tutor_quiz_questions', array('question_order' => $i), array('question_id' => $question_id));
1089 }
1090 }
1091 }
1092 }
1093
1094 /**
1095 * Save sorting data for quiz answers
1096 */
1097 public function tutor_quiz_answer_sorting(){
1098 tutils()->checking_nonce();
1099
1100 global $wpdb;
1101
1102 if ( ! empty($_POST['sorted_answer_ids']) && is_array($_POST['sorted_answer_ids']) && count($_POST['sorted_answer_ids']) ){
1103 $answer_ids = $_POST['sorted_answer_ids'];
1104 $i = 0;
1105 foreach ($answer_ids as $key => $answer_id){
1106 if(tutils()->can_user_manage('quiz_answer', $answer_id)) {
1107 $i++;
1108 $wpdb->update($wpdb->prefix.'tutor_quiz_question_answers', array('answer_order' => $i), array('answer_id' => $answer_id));
1109 }
1110 }
1111 }
1112 }
1113
1114 /**
1115 * Mark answer as correct
1116 */
1117
1118 public function tutor_mark_answer_as_correct(){
1119 tutils()->checking_nonce();
1120
1121 global $wpdb;
1122
1123 $answer_id = sanitize_text_field($_POST['answer_id']);
1124 $inputValue = sanitize_text_field($_POST['inputValue']);
1125
1126 if(!tutils()->can_user_manage('quiz_answer', $answer_id)) {
1127 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
1128 }
1129
1130 $answer = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE answer_id = %d LIMIT 0,1 ;", $answer_id));
1131 if ($answer->belongs_question_type === 'single_choice') {
1132 $wpdb->update($wpdb->prefix.'tutor_quiz_question_answers', array('is_correct' => 0), array('belongs_question_id' => esc_sql( $answer->belongs_question_id ) ));
1133 }
1134 $wpdb->update($wpdb->prefix.'tutor_quiz_question_answers', array('is_correct' => esc_sql( $inputValue ) ), array('answer_id' => esc_sql( $answer_id ) ));
1135 }
1136
1137 /**
1138 * Update quiz settings from modal
1139 *
1140 * @since : v.1.0.0
1141 */
1142 public function tutor_quiz_modal_update_settings(){
1143 tutils()->checking_nonce();
1144
1145 $quiz_id = sanitize_text_field($_POST['quiz_id']);
1146 $quiz_option = tutor_utils()->sanitize_array($_POST['quiz_option']);
1147
1148 if(!tutils()->can_user_manage('quiz', $quiz_id)) {
1149 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
1150 }
1151
1152 update_post_meta($quiz_id, 'tutor_quiz_option', $quiz_option);
1153 do_action('tutor_quiz_settings_updated', $quiz_id);
1154 wp_send_json_success();
1155 }
1156
1157
1158 //=========================//
1159 // Front end stuffs
1160 //=========================//
1161
1162 /**
1163 * Rendering quiz for frontend
1164 *
1165 * @since v.1.0.0
1166 */
1167
1168 public function tutor_render_quiz_content(){
1169
1170 tutils()->checking_nonce();
1171
1172 $quiz_id = (int) sanitize_text_field(tutor_utils()->avalue_dot('quiz_id', $_POST));
1173
1174 if(!tutils()->can_user_manage('quiz', $quiz_id)) {
1175 wp_send_json_error( array('message'=>__('Access Denied.', 'tutor')) );
1176 }
1177
1178 ob_start();
1179 global $post;
1180
1181 $post = get_post($quiz_id);
1182 setup_postdata($post);
1183 //tutor_lesson_content();
1184
1185 single_quiz_contents();
1186 wp_reset_postdata();
1187
1188 $html = ob_get_clean();
1189 wp_send_json_success(array('html' => $html));
1190 }
1191
1192 }