Quiz And Survey Master (Formerly Quiz Master Next) - Version 7.3.2

Version Description

(September 06, 2021) = * Bug: Added Translation for Time is up and Cancel button. * Bug: Fixed the issue of category name not visible. * Bug: Fixed the issue of limit number of questions per category is not working. * Bug: Fixed the issue of results page and email showing only 1 question and its answer multiple times. * Bug: Fixed the issue of %POLL_RESULT_X% not displaying images while using rich answers. * Bug: Fixed the issue of %AVERAGE_CATEGORY_POINTS_X% variable not working. * Bug: Fixed the issue of validation errors appearing on the questions before entering the responses. * Bug: Fixed the issue of timer not showing on the quiz. * Bug: Fixed security issue to prevent Cross-Site Scripting attacks.

Download this release

Release Info

Developer expresstech
Plugin Icon 128x128 Quiz And Survey Master (Formerly Quiz Master Next)
Version 7.3.2
Comparing to
See all releases

Code changes from version 7.3.1 to 7.3.2

js/qsm-quiz.js CHANGED
@@ -66,25 +66,7 @@ var QSMPageTimer;
66
  // If we are using the newer pagination system...
67
  if (0 < $quizForm.children('.qsm-page').length) {
68
  // If there is a first page...
69
- if (qmn_quiz_data[quizID].hasOwnProperty('first_page') && qmn_quiz_data[quizID].first_page) {
70
- // ... attach an event handler to the click event to activate the timer.
71
- $('#quizForm' + quizID).closest('.qmn_quiz_container').find('.mlw_next').on('click', function (event) {
72
- event.preventDefault();
73
- if (qmn_quiz_data[quizID].hasOwnProperty('advanced_timer')) {
74
- var start_timer = parseInt(qmn_quiz_data[quizID].advanced_timer.start_timer_page);
75
- if ($('#quizForm' + quizID).closest('.qmn_quiz_container').find('.qmn_pagination > .current_page_hidden').val() == start_timer) {
76
- QSM.activateTimer(quizID);
77
- $('#quizForm' + quizID).closest('.qmn_quiz_container').find('.stoptimer-p').show();
78
- }
79
- } else {
80
- if (!qmn_quiz_data[quizID].timerStatus && qmnValidatePage('quizForm' + quizID)) {
81
- QSM.activateTimer(quizID);
82
- $('#quizForm' + quizID).closest('.qmn_quiz_container').find('.stoptimer-p').show();
83
- }
84
- }
85
- });
86
- // ...else, activate the timer on page load.
87
- } else {
88
  QSM.activateTimer(quizID);
89
  $('#quizForm' + quizID).closest('.qmn_quiz_container').find('.stoptimer-p').show();
90
  }
@@ -445,12 +427,26 @@ var QSMPageTimer;
445
  * @param int quizID The ID of the quiz
446
  * @param int difference The number of pages to forward or back
447
  */
448
- changePage: function (quizID, difference) {
449
- var page = QSM.getPage(quizID);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450
  page += difference;
451
  QSM.goToPage(quizID, page);
452
  },
453
- nextPage: function (quizID) {
454
  if (qmnValidatePage('quizForm' + quizID)) {
455
  QSM.changePage(quizID, 1);
456
  }
66
  // If we are using the newer pagination system...
67
  if (0 < $quizForm.children('.qsm-page').length) {
68
  // If there is a first page...
69
+ if (!qmn_quiz_data[quizID].hasOwnProperty('first_page') && qmn_quiz_data[quizID].first_page) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  QSM.activateTimer(quizID);
71
  $('#quizForm' + quizID).closest('.qmn_quiz_container').find('.stoptimer-p').show();
72
  }
427
  * @param int quizID The ID of the quiz
428
  * @param int difference The number of pages to forward or back
429
  */
430
+ changePage: function (quizID, difference) {
431
+ var page = QSM.getPage(quizID);
432
+ if(page=="1" && qmn_quiz_data[quizID].hasOwnProperty('first_page') && qmn_quiz_data[quizID].first_page){
433
+ if (qmn_quiz_data[quizID].hasOwnProperty('advanced_timer')) {
434
+ var start_timer = parseInt(qmn_quiz_data[quizID].advanced_timer.start_timer_page);
435
+ if ($('#quizForm' + quizID).closest('.qmn_quiz_container').find('.qmn_pagination > .current_page_hidden').val() == start_timer) {
436
+ QSM.activateTimer(quizID);
437
+ $('#quizForm' + quizID).closest('.qmn_quiz_container').find('.stoptimer-p').show();
438
+ }
439
+ } else {
440
+ if (!qmn_quiz_data[quizID].timerStatus ) {
441
+ QSM.activateTimer(quizID);
442
+ $('#quizForm' + quizID).closest('.qmn_quiz_container').find('.stoptimer-p').show();
443
+ }
444
+ }
445
+ }
446
  page += difference;
447
  QSM.goToPage(quizID, page);
448
  },
449
+ nextPage: function (quizID) {
450
  if (qmnValidatePage('quizForm' + quizID)) {
451
  QSM.changePage(quizID, 1);
452
  }
lang/quiz-master-next.pot CHANGED
@@ -862,6 +862,7 @@ msgstr ""
862
  #: php/admin/functions.php:552 php/admin/quizzes-page.php:496
863
  #: php/admin/quizzes-page.php:524 php/admin/quizzes-page.php:551
864
  #: php/admin/quizzes-page.php:570
 
865
  msgid "Cancel"
866
  msgstr ""
867
 
@@ -2804,3 +2805,17 @@ msgstr ""
2804
  #, php-format
2805
  msgid "Every %d Minutes"
2806
  msgstr ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
862
  #: php/admin/functions.php:552 php/admin/quizzes-page.php:496
863
  #: php/admin/quizzes-page.php:524 php/admin/quizzes-page.php:551
864
  #: php/admin/quizzes-page.php:570
865
+ #: php/shortcodes.php:252,269
866
  msgid "Cancel"
867
  msgstr ""
868
 
2805
  #, php-format
2806
  msgid "Every %d Minutes"
2807
  msgstr ""
2808
+
2809
+ #: php/shortcodes.php:250
2810
+ msgid "Time is Up!"
2811
+ msgstr ""
2812
+
2813
+ #: php/shortcodes.php:250
2814
+ #, php-format
2815
+ msgid "Time's up"
2816
+ msgstr ""
2817
+
2818
+ #: php/shortcodes.php:252
2819
+ #, php-format
2820
+ msgid "Submit Quiz"
2821
+ msgstr ""
mlw_quizmaster2.php CHANGED
@@ -2,14 +2,14 @@
2
  /**
3
  * Plugin Name: Quiz And Survey Master
4
  * Description: Easily and quickly add quizzes and surveys to your website.
5
- * Version: 7.3.1
6
  * Author: ExpressTech
7
  * Author URI: https://quizandsurveymaster.com/
8
  * Plugin URI: https://expresstech.io/
9
  * Text Domain: quiz-master-next
10
  *
11
  * @author QSM Team
12
- * @version 7.3.1
13
  * @package QSM
14
  */
15
 
@@ -41,7 +41,7 @@ class MLWQuizMasterNext {
41
  * @var string
42
  * @since 4.0.0
43
  */
44
- public $version = '7.3.1';
45
 
46
  /**
47
  * QSM Alert Manager Object
2
  /**
3
  * Plugin Name: Quiz And Survey Master
4
  * Description: Easily and quickly add quizzes and surveys to your website.
5
+ * Version: 7.3.2
6
  * Author: ExpressTech
7
  * Author URI: https://quizandsurveymaster.com/
8
  * Plugin URI: https://expresstech.io/
9
  * Text Domain: quiz-master-next
10
  *
11
  * @author QSM Team
12
+ * @version 7.3.2
13
  * @package QSM
14
  */
15
 
41
  * @var string
42
  * @since 4.0.0
43
  */
44
+ public $version = '7.3.2';
45
 
46
  /**
47
  * QSM Alert Manager Object
php/admin/admin-results-details-page.php CHANGED
@@ -268,7 +268,7 @@ if ( is_serialized( $results_data->quiz_results ) && is_array( @unserialize( $re
268
  }
269
 
270
  // Prepare full results array.
271
- $results_array = array(
272
  'quiz_id' => $results_data->quiz_id,
273
  'quiz_name' => $results_data->quiz_name,
274
  'quiz_system' => $results_data->quiz_system,
@@ -289,7 +289,7 @@ $results_array = array(
289
  'contact' => $results["contact"],
290
  'result_id' => $result_id,
291
  'results' => $results,
292
- );
293
 
294
  // Pass through template variable filter
295
  $template = apply_filters( 'mlw_qmn_template_variable_results_page', $template, $results_array );
268
  }
269
 
270
  // Prepare full results array.
271
+ $results_array = apply_filters( 'mlw_qmn_template_variable_results_array', array(
272
  'quiz_id' => $results_data->quiz_id,
273
  'quiz_name' => $results_data->quiz_name,
274
  'quiz_system' => $results_data->quiz_system,
289
  'contact' => $results["contact"],
290
  'result_id' => $result_id,
291
  'results' => $results,
292
+ ) );
293
 
294
  // Pass through template variable filter
295
  $template = apply_filters( 'mlw_qmn_template_variable_results_page', $template, $results_array );
php/admin/admin-results-page.php CHANGED
@@ -156,7 +156,7 @@ function qsm_results_overview_tab_content() {
156
  $search_phrase_sql = '';
157
  $delete = 'deleted=0';
158
  $delete = apply_filters( 'qsm_results_delete_clause', $delete );
159
- $order_by_sql = 'ORDER BY result_id DESC';
160
  if ( isset( $_GET['qsm_search_phrase'] ) && ! empty( $_GET['qsm_search_phrase'] ) ) {
161
  // Sanitizes the search phrase and then uses $wpdb->prepare to properly escape the queries after using $wpdb->esc_like.
162
  $sanitized_search_phrase = sanitize_text_field( $_GET['qsm_search_phrase'] );
@@ -190,8 +190,8 @@ function qsm_results_overview_tab_content() {
190
  $order_by_sql = ' ORDER BY correct_score DESC';
191
  break;
192
  default:
193
- $order_by = 'quiz_name';
194
- $order_by_sql = ' ORDER BY result_id DESC';
195
  }
196
  }
197
 
@@ -316,18 +316,20 @@ function deleteResults(id, quizName) {
316
  <input type="hidden" name="quiz_id" value="<?php echo esc_attr( intval( $_GET['quiz_id'] ) ); ?>" />
317
  <?php
318
  }
 
 
319
  ?>
320
  <input type="hidden" name="page" value="mlw_quiz_results">
321
  <p class="search-box">
322
  <label for="qsm_search_phrase"><?php esc_html_e( 'Search Results', 'quiz-master-next' ); ?></label>
323
- <input type="search" id="qsm_search_phrase" name="qsm_search_phrase" value="">
324
  <label for="qmn_order_by"><?php esc_html_e( 'Order By', 'quiz-master-next' ); ?></label>
325
  <select id="qmn_order_by" name="qmn_order_by">
326
- <option value="quiz_name"><?php esc_html_e( 'Quiz Name', 'quiz-master-next' ); ?></option>
327
- <option value="name"><?php esc_html_e( 'User Name', 'quiz-master-next' ); ?></option>
328
- <option value="point_score"><?php esc_html_e( 'Points', 'quiz-master-next' ); ?></option>
329
- <option value="correct_score"><?php esc_html_e( 'Correct Percent', 'quiz-master-next' ); ?></option>
330
- <option value="default"><?php esc_html_e( 'Default (Time)', 'quiz-master-next' ); ?></option>
331
  </select>
332
  <button class="button"><?php esc_html_e( 'Search Results', 'quiz-master-next' ); ?></button>
333
  </p>
156
  $search_phrase_sql = '';
157
  $delete = 'deleted=0';
158
  $delete = apply_filters( 'qsm_results_delete_clause', $delete );
159
+ $order_by_sql = 'ORDER BY time_taken_real DESC';
160
  if ( isset( $_GET['qsm_search_phrase'] ) && ! empty( $_GET['qsm_search_phrase'] ) ) {
161
  // Sanitizes the search phrase and then uses $wpdb->prepare to properly escape the queries after using $wpdb->esc_like.
162
  $sanitized_search_phrase = sanitize_text_field( $_GET['qsm_search_phrase'] );
190
  $order_by_sql = ' ORDER BY correct_score DESC';
191
  break;
192
  default:
193
+ $order_by = 'time_taken_real';
194
+ $order_by_sql = ' ORDER BY time_taken_real DESC';
195
  }
196
  }
197
 
316
  <input type="hidden" name="quiz_id" value="<?php echo esc_attr( intval( $_GET['quiz_id'] ) ); ?>" />
317
  <?php
318
  }
319
+ $qsm_search_phrase = ( isset( $_GET['qsm_search_phrase'] ) ) ? $_GET['qsm_search_phrase'] : '';
320
+ $qmn_order_by = ( isset( $_GET['qmn_order_by'] ) && ! empty( $_GET['qmn_order_by'] ) ) ? $_GET['qmn_order_by'] : 'default';
321
  ?>
322
  <input type="hidden" name="page" value="mlw_quiz_results">
323
  <p class="search-box">
324
  <label for="qsm_search_phrase"><?php esc_html_e( 'Search Results', 'quiz-master-next' ); ?></label>
325
+ <input type="search" id="qsm_search_phrase" name="qsm_search_phrase" value="<?php echo $qsm_search_phrase; ?>">
326
  <label for="qmn_order_by"><?php esc_html_e( 'Order By', 'quiz-master-next' ); ?></label>
327
  <select id="qmn_order_by" name="qmn_order_by">
328
+ <option value="default" <?php selected( $qmn_order_by, 'default' ); ?>><?php esc_html_e( 'Default (Time)', 'quiz-master-next' ); ?></option>
329
+ <option value="quiz_name" <?php selected( $qmn_order_by, 'quiz_name' ); ?>><?php esc_html_e( 'Quiz Name', 'quiz-master-next' ); ?></option>
330
+ <option value="name" <?php selected( $qmn_order_by, 'name' ); ?>><?php esc_html_e( 'User Name', 'quiz-master-next' ); ?></option>
331
+ <option value="point_score" <?php selected( $qmn_order_by, 'point_score' ); ?>><?php esc_html_e( 'Points', 'quiz-master-next' ); ?></option>
332
+ <option value="correct_score" <?php selected( $qmn_order_by, 'correct_score' ); ?>><?php esc_html_e( 'Correct Percent', 'quiz-master-next' ); ?></option>
333
  </select>
334
  <button class="button"><?php esc_html_e( 'Search Results', 'quiz-master-next' ); ?></button>
335
  </p>
php/admin/options-page-results-page-tab.php CHANGED
@@ -110,7 +110,6 @@ function qsm_options_results_tab_content() {
110
  <?php foreach ( $categories as $cat ) { ?>
111
  <option value="<?php echo $cat[0]; ?>" <# if (data.category == '<?php echo $cat[0]; ?>') { #>selected<# } #>><?php echo $cat[0]; ?></option>
112
  <?php } ?>
113
- <?php do_action( 'qsm_results_page_condition_criteria' ); ?>
114
  </select>
115
  <?php } ?>
116
  <select class="results-page-condition-criteria">
110
  <?php foreach ( $categories as $cat ) { ?>
111
  <option value="<?php echo $cat[0]; ?>" <# if (data.category == '<?php echo $cat[0]; ?>') { #>selected<# } #>><?php echo $cat[0]; ?></option>
112
  <?php } ?>
 
113
  </select>
114
  <?php } ?>
115
  <select class="results-page-condition-criteria">
php/admin/settings-page.php CHANGED
@@ -36,6 +36,10 @@ class QMNGlobalSettingsPage {
36
  private function add_hooks() {
37
  add_action( 'admin_init', array( $this, 'init' ) );
38
  add_action( 'admin_init', array( $this, 'quiz_default_global_option_init' ) );
 
 
 
 
39
  }
40
 
41
  /**
36
  private function add_hooks() {
37
  add_action( 'admin_init', array( $this, 'init' ) );
38
  add_action( 'admin_init', array( $this, 'quiz_default_global_option_init' ) );
39
+ add_filter( 'pre_update_option_qmn-settings', function( $new_value ) {
40
+ $new_value['cpt_slug'] = sanitize_title( $new_value['cpt_slug'] ) ;
41
+ return $new_value;
42
+ }, 10, 2 );
43
  }
44
 
45
  /**
php/classes/class-qmn-plugin-helper.php CHANGED
@@ -416,8 +416,11 @@ class QMNPluginHelper
416
  $display .= "<span class='mlw_qmn_question_number'>$qmn_total_questions. </span>";
417
  }
418
  }
419
- if ($quiz_options->show_category_on_front && $question->category != '') {
420
- $display .= '<div class="quiz-cat">[ ' . $question->category . ' ]</div>';
 
 
 
421
  }
422
  $display .= call_user_func($type['display'], intval($question_id), $question->question_name, $answers);
423
  }
416
  $display .= "<span class='mlw_qmn_question_number'>$qmn_total_questions. </span>";
417
  }
418
  }
419
+ if ($quiz_options->show_category_on_front ) {
420
+ $categories = QSM_Questions::get_question_categories( $question_id );
421
+ if(!empty($categories['category_name'])){
422
+ $display .= '<div class="quiz-cat">[ ' .implode(',' ,$categories['category_name']) . ' ]</div>';
423
+ }
424
  }
425
  $display .= call_user_func($type['display'], intval($question_id), $question->question_name, $answers);
426
  }
php/classes/class-qmn-quiz-manager.php CHANGED
@@ -516,83 +516,43 @@ public function load_questions( $quiz_id, $quiz_options, $is_quiz_page, $questio
516
  } else {
517
  $question_ids[] = intval( $question );
518
  }
519
-
520
-
521
  }
522
  }
523
- $question_ids = apply_filters( 'qsm_load_questions_ids', $question_ids, $quiz_id, $quiz_options );
524
- $question_sql = implode( ', ', $question_ids );
525
-
526
- //check If we should load a specific number of question
527
- if( $quiz_options->question_per_category != 0 && $is_quiz_page ){
528
-
529
-
530
- //processing Categories checking. removing commas and making them arrays
531
- $cat_sql = $wpdb->get_results( $wpdb->prepare("SELECT category FROM {$wpdb->prefix}mlw_questions WHERE quiz_id = %d ", $quiz_id) );
532
- $all_cat = array();
533
- foreach($cat_sql as $cat){
534
- array_push($all_cat, $cat->category);
535
- }
536
- //processing the categories
537
- $all_cat = array_unique($all_cat);
538
-
539
- $all_cat = array_values($all_cat);
540
-
541
-
542
- $categories = $quiz_options->randon_category != '' ? $quiz_options->randon_category : $all_cat;
543
-
544
- if($quiz_options->randon_category != ''){
545
-
546
- $categories = explode(",",$categories);
547
-
548
- $categories = str_replace(',', '', $categories) ;
549
- }
550
- //Running a loop for each category and getting a limited number of questions
551
- for ($i=0; $i < count($categories) ; $i++) {
552
- $catSQL = isset( $quiz_options->randon_category )&& !empty( $quiz_options->randon_category) ? : '';
553
- $piece1 = $wpdb->prepare("SELECT * FROM {$wpdb->prefix}mlw_questions WHERE question_id IN (%1s) AND category IN (%s) LIMIT %d",
554
- $question_sql,$categories[$i],
555
- $quiz_options->question_per_category );
556
-
557
- $piece_res = $wpdb->get_results( stripslashes( $piece1 ) );
558
- //add them to the big_array
559
- $big_array = array_merge($big_array, $piece_res);
560
-
561
-
562
- }
563
-
564
- // Check If the no category Question is less or equal to the question limit
565
-
566
- if (count($big_array) <= $quiz_options->question_from_total )
567
- {
568
- $big_range = range(0, count($big_array) - 1);
569
- $quiz_options->randomness_order == 1 || $quiz_options->randomness_order == 2 ? shuffle($big_range) : $big_range;
570
- for ($i=0; $i < count($big_array) ; $i++) {
571
-
572
- array_push($questions, $big_array[$big_range[$i]]);
573
- }
574
-
575
- }
576
- //If Category Question are more then run array_rand to get random entries
577
- else{
578
-
579
- $range = range(0, $quiz_options->question_from_total);
580
-
581
- $quiz_options->randomness_order == 1 || $quiz_options->randomness_order == 2 ? shuffle($range) : $range;
582
- for ($i=0; $i < $quiz_options->question_from_total ; $i++) {
583
-
584
- array_push($questions, $big_array[$range[$i]]);
585
- }
586
-
587
- }
588
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
589
  }
590
- else{
591
-
 
592
  $query = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}mlw_questions WHERE question_id IN (%1s) %2s %3s %4s", $question_sql, $cat_query, $order_by_sql, $limit_sql );
593
  $questions = $wpdb->get_results( stripslashes( $query ) );
594
-
595
- }
596
 
597
  // If we are not using randomization, we need to put the questions in the order of the new question editor.
598
  // If a user has saved the pages in the question editor but still uses the older pagination options
@@ -619,11 +579,13 @@ $range = range(0, $quiz_options->question_from_total);
619
  $questions = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}mlw_questions WHERE quiz_id=%d AND deleted=0 %1s %2s %3s", $quiz_id, $question_sql, $order_by_sql, $limit_sql ) );
620
  }
621
  $questions = apply_filters( 'qsm_load_questions_filter', $questions, $quiz_id, $quiz_options );
622
- $qsm_random_que_ids = array_column($questions,'question_id');
623
- update_option('qsm_random_que_ids',$qsm_random_que_ids);
 
 
 
624
  // Returns an array of all the loaded questions.
625
  return $questions;
626
-
627
  }
628
 
629
  /**
@@ -1497,8 +1459,12 @@ $range = range(0, $quiz_options->question_from_total);
1497
 
1498
  $result_display .= $this->display_social( $qmn_quiz_options, $qmn_array_for_variables );
1499
  $result_display = apply_filters( 'qmn_after_social_media', $result_display, $qmn_quiz_options, $qmn_array_for_variables );
1500
- if ( $this->qsm_plugin_active( 'qsm-save-resume/qsm-save-resume.php' ) != 1 && $qmn_quiz_options->enable_retake_quiz_button == 1 ) {
1501
- $result_display .= '<a style="float: right;" class="button btn-reload-quiz" data-quiz_id="' . $qmn_array_for_variables['quiz_id'] . '" href="#" >' . apply_filters( 'qsm_retake_quiz_text', __( 'Retake Quiz', 'quiz-master-next' ) ) . '</a>';
 
 
 
 
1502
  }
1503
 
1504
  /*
@@ -1655,9 +1621,11 @@ $range = range(0, $quiz_options->question_from_total);
1655
  if ( $question_type_new == 4 || $question_type_new == 10 ) {
1656
  foreach ( $question['answers'] as $single_answerk_key => $single_answer_arr ) {
1657
  if ( $options->system == 1 && isset( $single_answer_arr[1] ) ) {
 
1658
  $total_possible_points = $total_possible_points + $single_answer_arr[1];
1659
  }
1660
  if ( $options->system == 3 && isset( $single_answer_arr[2] ) && $single_answer_arr[2] == 1 ) {
 
1661
  $total_possible_points = $total_possible_points + $single_answer_arr[1];
1662
  }
1663
  }
@@ -1761,9 +1729,11 @@ $range = range(0, $quiz_options->question_from_total);
1761
  if ( $question_type_new == 4 || $question_type_new == 10 ) {
1762
  foreach ( $question['answers'] as $single_answerk_key => $single_answer_arr ) {
1763
  if ( $options->system == 1 && isset( $single_answer_arr[1] ) ) {
 
1764
  $total_possible_points = $total_possible_points + $single_answer_arr[1];
1765
  }
1766
  if ( $options->system == 3 && isset( $single_answer_arr[2] ) && $single_answer_arr[2] == 1 ) {
 
1767
  $total_possible_points = $total_possible_points + $single_answer_arr[1];
1768
  }
1769
  }
@@ -1840,21 +1810,27 @@ $range = range(0, $quiz_options->question_from_total);
1840
  } else {
1841
  $total_score = 0;
1842
  }
1843
- $qsm_random_que_ids = get_option('qsm_random_que_ids');
1844
- if(!empty($qsm_random_que_ids))
1845
- {
1846
-
1847
- $new_question_data = array();
1848
- foreach($qsm_random_que_ids as $que_id)
1849
- {
1850
- $key = array_search($que_id,array_column($question_data,'id'));
1851
- array_push($new_question_data,$question_data[$key]);
 
 
 
 
 
 
 
1852
  }
1853
- $question_data = $new_question_data;
 
1854
  }
1855
 
1856
- // We no need longer this option
1857
- delete_option('qsm_random_que_ids');
1858
  // Return array to be merged with main user response array
1859
  return apply_filters('qsm_check_answers_results' , array(
1860
  'total_points' => $points_earned,
516
  } else {
517
  $question_ids[] = intval( $question );
518
  }
 
 
519
  }
520
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
521
 
522
+ //check If we should load a specific number of question
523
+ if($quiz_options->question_per_category != 0 && $is_quiz_page){
524
+ $categories = QSM_Questions::get_quiz_categories( $quiz_id );
525
+ $category_ids = (isset($categories['list']) ? array_keys($categories['list']) : array());
526
+ $categories_tree = (isset($categories['tree']) ? $categories['tree'] : array());
527
+ if (!empty($category_ids)) {
528
+ $term_ids = implode(',', $category_ids);
529
+ $term_ids = ($quiz_options->randon_category != '') ? $quiz_options->randon_category : $term_ids;
530
+ $tq_ids = $wpdb->get_results( "SELECT `term_id`, `question_id` FROM `{$wpdb->prefix}mlw_question_terms` WHERE `quiz_id`='{$quiz_id}' AND `term_id` IN ({$term_ids}) AND `taxonomy`='qsm_category'", ARRAY_A );
531
+ $random = array();
532
+ if (!empty($tq_ids)) {
533
+ $term_data = array();
534
+ foreach ($tq_ids as $key => $val) {
535
+ $term_data[$val['term_id']][] = $val['question_id'];
536
+ }
537
+ if ($quiz_options->randon_category == '') {
538
+ foreach ($categories_tree as $cat) {
539
+ if (!empty($cat->children)) {
540
+ unset($term_data[$cat->term_id]);
541
+ }
542
+ }
543
+ }
544
+ foreach ($term_data as $tv) {
545
+ $random = array_merge($random, array_slice($tv, 0, $quiz_options->question_per_category));
546
+ }
547
+ }
548
+ $question_ids = array_unique( $random );
549
+ }
550
  }
551
+ $question_ids = apply_filters( 'qsm_load_questions_ids', $question_ids, $quiz_id, $quiz_options );
552
+ $question_sql = implode( ', ', $question_ids );
553
+
554
  $query = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}mlw_questions WHERE question_id IN (%1s) %2s %3s %4s", $question_sql, $cat_query, $order_by_sql, $limit_sql );
555
  $questions = $wpdb->get_results( stripslashes( $query ) );
 
 
556
 
557
  // If we are not using randomization, we need to put the questions in the order of the new question editor.
558
  // If a user has saved the pages in the question editor but still uses the older pagination options
579
  $questions = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}mlw_questions WHERE quiz_id=%d AND deleted=0 %1s %2s %3s", $quiz_id, $question_sql, $order_by_sql, $limit_sql ) );
580
  }
581
  $questions = apply_filters( 'qsm_load_questions_filter', $questions, $quiz_id, $quiz_options );
582
+
583
+ // Create question ids array
584
+ $qsm_random_que_ids = array_column( $questions,'question_id' );
585
+ update_option( 'qsm_random_que_ids', $qsm_random_que_ids );
586
+
587
  // Returns an array of all the loaded questions.
588
  return $questions;
 
589
  }
590
 
591
  /**
1459
 
1460
  $result_display .= $this->display_social( $qmn_quiz_options, $qmn_array_for_variables );
1461
  $result_display = apply_filters( 'qmn_after_social_media', $result_display, $qmn_quiz_options, $qmn_array_for_variables );
1462
+ if ( $qmn_quiz_options->enable_retake_quiz_button == 1 ) {
1463
+
1464
+ $result_display .= '<form method="POST">';
1465
+ $result_display .= '<input type="hidden" value="' . $qmn_array_for_variables['quiz_id'] . '" name="qsm_retake_quiz_id" />';
1466
+ $result_display .= '<input type="submit" value="' . apply_filters( 'qsm_retake_quiz_text', __( 'Retake Quiz', 'quiz-master-next' ) ). '" name="qsm_retake_button" />';
1467
+ $result_display .= '</form>';
1468
  }
1469
 
1470
  /*
1621
  if ( $question_type_new == 4 || $question_type_new == 10 ) {
1622
  foreach ( $question['answers'] as $single_answerk_key => $single_answer_arr ) {
1623
  if ( $options->system == 1 && isset( $single_answer_arr[1] ) ) {
1624
+ $single_answer_arr[1] = apply_filters( 'qsm_single_answer_arr', $single_answer_arr[1] );
1625
  $total_possible_points = $total_possible_points + $single_answer_arr[1];
1626
  }
1627
  if ( $options->system == 3 && isset( $single_answer_arr[2] ) && $single_answer_arr[2] == 1 ) {
1628
+ $single_answer_arr[1] = apply_filters( 'qsm_single_answer_arr', $single_answer_arr[1] );
1629
  $total_possible_points = $total_possible_points + $single_answer_arr[1];
1630
  }
1631
  }
1729
  if ( $question_type_new == 4 || $question_type_new == 10 ) {
1730
  foreach ( $question['answers'] as $single_answerk_key => $single_answer_arr ) {
1731
  if ( $options->system == 1 && isset( $single_answer_arr[1] ) ) {
1732
+ $single_answer_arr[1] = apply_filters( 'qsm_single_answer_arr', $single_answer_arr[1] );
1733
  $total_possible_points = $total_possible_points + $single_answer_arr[1];
1734
  }
1735
  if ( $options->system == 3 && isset( $single_answer_arr[2] ) && $single_answer_arr[2] == 1 ) {
1736
+ $single_answer_arr[1] = apply_filters( 'qsm_single_answer_arr', $single_answer_arr[1] );
1737
  $total_possible_points = $total_possible_points + $single_answer_arr[1];
1738
  }
1739
  }
1810
  } else {
1811
  $total_score = 0;
1812
  }
1813
+
1814
+ // Get random order
1815
+ $qsm_random_que_ids = get_option( 'qsm_random_que_ids' );
1816
+ if ( ! empty( $qsm_random_que_ids ) && is_array( $qsm_random_que_ids ) ) {
1817
+ $qs_ids = array_column( $question_data, 'id' );
1818
+ $has_diff = array_diff( $qs_ids, $qsm_random_que_ids );
1819
+ // Check random option value has all the questions in previous order
1820
+ if ( empty( $has_diff ) ) {
1821
+ $new_question_data = [];
1822
+ foreach( $qsm_random_que_ids as $que_id ) {
1823
+ $key = array_search( $que_id, $qs_ids );
1824
+ $new_question_data[] = $question_data[$key];
1825
+ }
1826
+ if ( ! empty( $new_question_data ) ) {
1827
+ $question_data = $new_question_data;
1828
+ }
1829
  }
1830
+ // We no need longer this option
1831
+ delete_option( 'qsm_random_que_ids' );
1832
  }
1833
 
 
 
1834
  // Return array to be merged with main user response array
1835
  return apply_filters('qsm_check_answers_results' , array(
1836
  'total_points' => $points_earned,
php/classes/class-qsm-fields.php CHANGED
@@ -416,55 +416,41 @@ jQuery(function() {
416
  <?php } ?>
417
  </th>
418
  <td>
419
- <?php
 
 
420
  $questions = QSM_Questions::load_questions_by_pages( $quiz_id );
421
- $cat_array = array();
422
- if($questions){
423
- $multiple_category_system = false;
424
  // check if multiple category is enabled.
425
- $enabled = get_option( 'qsm_multiple_category_enabled' );
426
- if( $enabled && $enabled != 'cancelled' ){
427
- $multiple_category_system = true;
428
- }
429
- foreach( $questions as $single_question ){
430
- if( $multiple_category_system ){
431
- foreach($single_question['multicategories'] as $category_id ){
432
- $cat_array[] = $category_id;
433
- }
434
- } else {
435
  $cat_array[] = $single_question['category'];
436
  }
437
  }
438
- $cat_array = array_unique($cat_array);
439
- if($cat_array){
440
-
441
- ?>
442
- <select class="category_selection_random" multiple="">
443
- <option value="">Select Categories</option>
444
- <?php
445
- foreach( $cat_array as $single_cat ){ ?>
446
- <option <?php if( in_array($single_cat, $explode_cat) ){ echo "selected"; } ?>
447
- value="<?php echo $single_cat; ?>">
448
- <?php
449
- if($multiple_category_system){
450
- $cat_data = get_term_by('term_id', $single_cat, 'qsm_category' );
451
- echo $cat_data->name;
452
  } else {
453
- echo $single_cat;
 
 
454
  }
455
- ?>
456
- </option>
457
- <?php
458
- } ?>
459
- </select>
460
- <?php
461
- }else{
462
- echo 'No category found.';
463
- }
464
- }else{
465
- echo 'No catergory found.';
466
- }
467
- ?>
468
  <input type="hidden" class="catergory_comma_values" name="<?php echo $field["id"]; ?>"
469
  value='<?php echo $value; ?>'>
470
  <?php if( isset($field['help']) && $field['help'] != ''){ ?>
@@ -475,6 +461,19 @@ jQuery(function() {
475
  <?php
476
  }
477
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  /**
479
  * @since 7.0
480
  * @param Array $field
416
  <?php } ?>
417
  </th>
418
  <td>
419
+ <?php
420
+ $categories = QSM_Questions::get_quiz_categories( $quiz_id );
421
+ $categories_tree = (isset($categories['tree']) ? $categories['tree'] : array());
422
  $questions = QSM_Questions::load_questions_by_pages( $quiz_id );
423
+ $cat_array = array();
424
+ if ( $questions ) {
425
+ $multiple_category_system = false;
426
  // check if multiple category is enabled.
427
+ $enabled = get_option( 'qsm_multiple_category_enabled' );
428
+ if ( $enabled && $enabled != 'cancelled' ) {
429
+ $multiple_category_system = true;
430
+ }
431
+ foreach ( $questions as $single_question ) {
432
+ if ( ! $multiple_category_system ) {
 
 
 
 
433
  $cat_array[] = $single_question['category'];
434
  }
435
  }
436
+ $cat_array = array_unique( $cat_array );
437
+ if ( $cat_array || $categories_tree ) {
438
+ ?><select class="category_selection_random" multiple=""><option value="">Select Categories</option><?php
439
+ if ( $multiple_category_system ) {
440
+ echo QSM_Fields::get_category_hierarchical_options( $categories_tree, $explode_cat );
 
 
 
 
 
 
 
 
 
441
  } else {
442
+ foreach ( $cat_array as $single_cat ) {
443
+ ?><option <?php echo in_array( $single_cat, $explode_cat ) ? 'selected' : ''; ?> value="<?php echo $single_cat; ?>"><?php echo $single_cat; ?></option><?php
444
+ }
445
  }
446
+ ?></select><?php
447
+ } else {
448
+ echo 'No category found.';
449
+ }
450
+ } else {
451
+ echo 'No catergory found.';
452
+ }
453
+ ?>
 
 
 
 
 
454
  <input type="hidden" class="catergory_comma_values" name="<?php echo $field["id"]; ?>"
455
  value='<?php echo $value; ?>'>
456
  <?php if( isset($field['help']) && $field['help'] != ''){ ?>
461
  <?php
462
  }
463
 
464
+ public static function get_category_hierarchical_options($categories = array(), $selected = array(), $prefix = '') {
465
+ $options = '';
466
+ if (! empty($categories)) {
467
+ foreach ($categories as $cat) {
468
+ $options .= '<option value="' . $cat->term_id . '" ' . ( in_array( $cat->term_id, $selected ) ? 'selected' : '' ) . '>' . $prefix . $cat->name . '</option>';
469
+ if (! empty($cat->children)) {
470
+ $options .= QSM_Fields::get_category_hierarchical_options( $cat->children, $selected, $prefix . '&nbsp;&nbsp;&nbsp;' );
471
+ }
472
+ }
473
+ }
474
+ return $options;
475
+ }
476
+
477
  /**
478
  * @since 7.0
479
  * @param Array $field
php/classes/class-qsm-install.php CHANGED
@@ -253,6 +253,44 @@ class QSM_Install {
253
  );
254
  $mlwQuizMasterNext->pluginHelper->register_quiz_setting( $field_array, 'quiz_options' );
255
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  // Registers scheduled_time_start setting
257
  $field_array = array(
258
  'id' => 'scheduled_time_start',
@@ -292,44 +330,6 @@ class QSM_Install {
292
  );
293
  $mlwQuizMasterNext->pluginHelper->register_quiz_setting( $field_array, 'quiz_options' );
294
 
295
- // Registers randomness_order setting
296
- $field_array = array(
297
- 'id' => 'randomness_order',
298
- 'label' => __( 'Random Questions', 'quiz-master-next' ),
299
- 'type' => 'select',
300
- 'options' => array(
301
- array(
302
- 'label' => __( 'Random Questions', 'quiz-master-next' ),
303
- 'value' => 1,
304
- ),
305
- array(
306
- 'label' => __( 'Random Questions And Answers', 'quiz-master-next' ),
307
- 'value' => 2,
308
- ),
309
- array(
310
- 'label' => __( 'Random Answers', 'quiz-master-next' ),
311
- 'value' => 3,
312
- ),
313
- array(
314
- 'label' => __( 'Disabled', 'quiz-master-next' ),
315
- 'value' => 0,
316
- ),
317
- ),
318
- 'default' => 0,
319
- 'tooltip' => __( 'Randomize the order of questions or answers every time a quiz loads', 'quiz' ),
320
- );
321
- $mlwQuizMasterNext->pluginHelper->register_quiz_setting( $field_array, 'quiz_options' );
322
-
323
- // Registers category setting
324
- $field_array = array(
325
- 'id' => 'randon_category',
326
- 'label' => __( 'Questions Categories', 'quiz-master-next' ),
327
- 'type' => 'category',
328
- 'default' => '',
329
- 'help' => __( 'Questions will load only from selected categories. This option works only with Random Questions ', 'quiz-master-next' ),
330
- );
331
- $mlwQuizMasterNext->pluginHelper->register_quiz_setting( $field_array, 'quiz_options' );
332
-
333
  // Registers contact_info_location setting
334
  $field_array = array(
335
  'id' => 'contact_info_location',
253
  );
254
  $mlwQuizMasterNext->pluginHelper->register_quiz_setting( $field_array, 'quiz_options' );
255
 
256
+ // Registers category setting
257
+ $field_array = array(
258
+ 'id' => 'randon_category',
259
+ 'label' => __( 'Questions Categories', 'quiz-master-next' ),
260
+ 'type' => 'category',
261
+ 'default' => '',
262
+ 'help' => __( 'Questions will load only from selected categories. This option works only with Random Questions ', 'quiz-master-next' ),
263
+ );
264
+ $mlwQuizMasterNext->pluginHelper->register_quiz_setting( $field_array, 'quiz_options' );
265
+
266
+ // Registers randomness_order setting
267
+ $field_array = array(
268
+ 'id' => 'randomness_order',
269
+ 'label' => __( 'Random Questions', 'quiz-master-next' ),
270
+ 'type' => 'select',
271
+ 'options' => array(
272
+ array(
273
+ 'label' => __( 'Random Questions', 'quiz-master-next' ),
274
+ 'value' => 1,
275
+ ),
276
+ array(
277
+ 'label' => __( 'Random Questions And Answers', 'quiz-master-next' ),
278
+ 'value' => 2,
279
+ ),
280
+ array(
281
+ 'label' => __( 'Random Answers', 'quiz-master-next' ),
282
+ 'value' => 3,
283
+ ),
284
+ array(
285
+ 'label' => __( 'Disabled', 'quiz-master-next' ),
286
+ 'value' => 0,
287
+ ),
288
+ ),
289
+ 'default' => 0,
290
+ 'tooltip' => __( 'Randomize the order of questions or answers every time a quiz loads', 'quiz' ),
291
+ );
292
+ $mlwQuizMasterNext->pluginHelper->register_quiz_setting( $field_array, 'quiz_options' );
293
+
294
  // Registers scheduled_time_start setting
295
  $field_array = array(
296
  'id' => 'scheduled_time_start',
330
  );
331
  $mlwQuizMasterNext->pluginHelper->register_quiz_setting( $field_array, 'quiz_options' );
332
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
  // Registers contact_info_location setting
334
  $field_array = array(
335
  'id' => 'contact_info_location',
php/classes/class-qsm-questions.php CHANGED
@@ -91,14 +91,11 @@ class QSM_Questions {
91
 
92
  // Loop through questions and prepare serialized data.
93
  foreach ( $question_array as $question ) {
94
- $multicategories = array();
95
- $multicategories_res = $wpdb->get_results("SELECT `term_id` FROM `{$wpdb->prefix}mlw_question_terms` WHERE `question_id`='{$question['question_id']}' AND `taxonomy`='qsm_category'", ARRAY_A);
96
- if (!empty($multicategories_res)){
97
- foreach ($multicategories_res as $cat) {
98
- $multicategories[] = $cat['term_id'];
99
- }
100
- }
101
- $question['multicategories'] = $multicategories;
102
  // Prepare answers.
103
  $answers = maybe_unserialize( $question['answer_array'] );
104
  if ( ! is_array( $answers ) ) {
@@ -393,7 +390,36 @@ class QSM_Questions {
393
  }
394
  return $categories;
395
  }
396
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
397
  /**
398
  * Create tree structure of terms.
399
  *
91
 
92
  // Loop through questions and prepare serialized data.
93
  foreach ( $question_array as $question ) {
94
+ $multicategories = self::get_question_categories($question['question_id']);
95
+ //get_question_categories
96
+
97
+ $question['multicategories'] = isset($multicategories['category_tree']) && !empty($multicategories['category_tree'] ) ? array_keys($multicategories['category_name']) : array();
98
+ $question['multicategoriesobject'] = isset($multicategories['category_tree']) && !empty($multicategories['category_tree'] ) ? $multicategories['category_tree'] : array();
 
 
 
99
  // Prepare answers.
100
  $answers = maybe_unserialize( $question['answer_array'] );
101
  if ( ! is_array( $answers ) ) {
390
  }
391
  return $categories;
392
  }
393
+ /**
394
+ * Get categories for a Question
395
+ *
396
+ * @since 7.2.1
397
+ * @param int $quiz_id The ID of the quiz.
398
+ * @return array The array of categories.
399
+ */
400
+ public static function get_question_categories( $question_id = 0 ) {
401
+ global $wpdb;
402
+ $categories_tree = array();
403
+ $categories_names = array();
404
+ if ( 0 !== $question_id ) {
405
+ $question_terms = $wpdb->get_results( "SELECT `term_id` FROM `{$wpdb->prefix}mlw_question_terms` WHERE `question_id`='{$question_id}' AND `taxonomy`='qsm_category'", ARRAY_A );
406
+ if ( ! empty( $question_terms ) ) {
407
+ $term_ids = array_unique( array_column( $question_terms, 'term_id' ) );
408
+ if ( ! empty( $term_ids ) ) {
409
+ $terms = get_terms( array( 'taxonomy' => 'qsm_category', 'include' => array_unique( $term_ids ), 'hide_empty' => false, 'orderby' => '', 'order' => '' ) );
410
+ if ( ! empty( $terms ) ) {
411
+ foreach ( $terms as $tax ) {
412
+ $categories_names[$tax->term_id] = $tax->name;
413
+ $taxs[$tax->parent][] = $tax;
414
+ }
415
+ $categories_tree = self::create_terms_tree( $taxs, $taxs[0] );
416
+
417
+ }
418
+ }
419
+ }
420
+ }
421
+ return array('category_name'=>$categories_names,"category_tree"=>$categories_tree);
422
+ }
423
  /**
424
  * Create tree structure of terms.
425
  *
php/classes/class-qsm-results-pages.php CHANGED
@@ -111,8 +111,7 @@ class QSM_Results_Pages {
111
  }
112
  break;
113
 
114
- case 'equal':
115
- default:
116
  if ( $test != $value ) {
117
  $show = false;
118
  }
111
  }
112
  break;
113
 
114
+ case 'equal':
 
115
  if ( $test != $value ) {
116
  $show = false;
117
  }
php/rest-api.php CHANGED
@@ -518,6 +518,8 @@ function qsm_rest_get_questions( WP_REST_Request $request ) {
518
  foreach ( $questions as $question ) {
519
  $quiz_name = $wpdb->get_row( $wpdb->prepare( "SELECT quiz_name FROM {$wpdb->prefix}mlw_quizzes WHERE quiz_id = %d", $question['quiz_id'] ), ARRAY_A );
520
  $question['page'] = isset( $question['page'] ) ? $question['page'] : 0;
 
 
521
  $question_data = array(
522
  'id' => $question['question_id'],
523
  'quizID' => $question['quiz_id'],
@@ -526,7 +528,7 @@ function qsm_rest_get_questions( WP_REST_Request $request ) {
526
  'answerInfo' => htmlspecialchars_decode( $question['question_answer_info'], ENT_QUOTES ),
527
  'comments' => $question['comments'],
528
  'hint' => $question['hints'],
529
- 'category' => $question['category'],
530
  'multicategories' => $question['multicategories'],
531
  'required' => $question['settings']['required'],
532
  'answers' => $question['answers'],
518
  foreach ( $questions as $question ) {
519
  $quiz_name = $wpdb->get_row( $wpdb->prepare( "SELECT quiz_name FROM {$wpdb->prefix}mlw_quizzes WHERE quiz_id = %d", $question['quiz_id'] ), ARRAY_A );
520
  $question['page'] = isset( $question['page'] ) ? $question['page'] : 0;
521
+ $categorysArray = QSM_Questions::get_question_categories($question['question_id']);
522
+
523
  $question_data = array(
524
  'id' => $question['question_id'],
525
  'quizID' => $question['quiz_id'],
528
  'answerInfo' => htmlspecialchars_decode( $question['question_answer_info'], ENT_QUOTES ),
529
  'comments' => $question['comments'],
530
  'hint' => $question['hints'],
531
+ 'category' => (isset($categorysArray['category_name']) && !empty($categorysArray['category_name']) ? implode(',',$categorysArray['category_name']):"" ) ,
532
  'multicategories' => $question['multicategories'],
533
  'required' => $question['settings']['required'],
534
  'answers' => $question['answers'],
php/shortcodes.php CHANGED
@@ -247,10 +247,9 @@ function qsm_display_popup_div( $return_display, $qmn_quiz_options ) {
247
  $return_display .= '<div class="qsm-popup__container qmn_quiz_container" role="dialog" aria-modal="true">';
248
  $return_display .= '<div class="qsm-popup__content">';
249
  $return_display .= '<img src="' . QSM_PLUGIN_URL . 'assets/clock.png' . '" alt="clock.png"/>';
250
- $return_display .= '<p class="qsm-time-up-text">Time is Up!</p>';
251
- $return_display .= '</div>';
252
- $return_display .= '<footer class="qsm-popup__footer"><button class="qsm-popup-secondary-button qmn_btn" data-micromodal-close="" aria-label="Close this dialog window">Cancel</button><button data-quiz_id="' . $qmn_quiz_options->quiz_id . '" class="submit-the-form qmn_btn">Submit Quiz</button></footer>';
253
  $return_display .= '</div>';
 
254
  $return_display .= '</div>';
255
  $return_display .= '</div>';
256
  }
@@ -264,9 +263,9 @@ function qsm_display_popup_div_expired_quiz( $return_display, $qmn_quiz_options
264
  $return_display .= '<div class="qsm-popup__container qmn_quiz_container" role="dialog" aria-modal="true">';
265
  $return_display .= '<div class="qsm-popup__content">';
266
  $return_display .= '<img src="' . QSM_PLUGIN_URL . 'assets/clock.png' . '" alt="clock.png"/>';
267
- $return_display .= '<p class="qsm-time-up-text">Time\'s up</p>';
268
  $return_display .= '</div>';
269
- $return_display .= '<footer class="qsm-popup__footer"><button class="qsm-popup-secondary-button qmn_btn" data-micromodal-close="" aria-label="Close this dialog window" onclick="location.reload();">Cancel</button></footer>';
270
  $return_display .= '</div>';
271
  $return_display .= '</div>';
272
  $return_display .= '</div>';
247
  $return_display .= '<div class="qsm-popup__container qmn_quiz_container" role="dialog" aria-modal="true">';
248
  $return_display .= '<div class="qsm-popup__content">';
249
  $return_display .= '<img src="' . QSM_PLUGIN_URL . 'assets/clock.png' . '" alt="clock.png"/>';
250
+ $return_display .= '<p class="qsm-time-up-text">'. __( 'Time is Up!', 'quiz-master-next' ) .'</p>';
 
 
251
  $return_display .= '</div>';
252
+ $return_display .= '<footer class="qsm-popup__footer"><button class="qsm-popup-secondary-button qmn_btn" data-micromodal-close="" aria-label="Close this dialog window">'. __( 'Cancel', 'quiz-master-next' ).'</button><button data-quiz_id="' . $qmn_quiz_options->quiz_id . '" class="submit-the-form qmn_btn">'.__( 'Submit Quiz', 'quiz-master-next' ).'</button></footer>'; $return_display .= '</div>';
253
  $return_display .= '</div>';
254
  $return_display .= '</div>';
255
  }
263
  $return_display .= '<div class="qsm-popup__container qmn_quiz_container" role="dialog" aria-modal="true">';
264
  $return_display .= '<div class="qsm-popup__content">';
265
  $return_display .= '<img src="' . QSM_PLUGIN_URL . 'assets/clock.png' . '" alt="clock.png"/>';
266
+ $return_display .= '<p class="qsm-time-up-text"> '.__( 'Time\'s up', 'quiz-master-next' ) .'</p>';
267
  $return_display .= '</div>';
268
+ $return_display .= '<footer class="qsm-popup__footer"><button class="qsm-popup-secondary-button qmn_btn" data-micromodal-close="" aria-label="Close this dialog window" onclick="location.reload();">'. __('Cancel', 'quiz-master-next' ).'</button></footer>';
269
  $return_display .= '</div>';
270
  $return_display .= '</div>';
271
  $return_display .= '</div>';
php/template-variables.php CHANGED
@@ -65,6 +65,7 @@ add_filter( 'mlw_qmn_template_variable_results_page', 'qsm_variable_single_quest
65
  add_filter( 'mlw_qmn_template_variable_results_page', 'qsm_variable_total_possible_points', 10, 2 );
66
  add_filter( 'mlw_qmn_template_variable_results_page', 'qsm_variable_total_attempted_questions', 10, 2 );
67
  add_filter( 'mlw_qmn_template_variable_results_page', 'mlw_qmn_variable_user_full_name', 10, 2 );
 
68
  add_filter( 'qmn_end_results', 'qsm_variable_poll_result', 10, 3 );
69
  add_filter( 'mlw_qmn_template_variable_quiz_page', 'mlw_qmn_variable_quiz_name', 10, 2 );
70
  add_filter( 'mlw_qmn_template_variable_quiz_page', 'mlw_qmn_variable_quiz_links', 10, 2 );
@@ -161,7 +162,7 @@ function qsm_variable_total_attempted_questions( $content, $mlw_quiz_array ) {
161
  * @param str $content
162
  * @param arr $mlw_quiz_array
163
  */
164
- function qsm_variable_poll_result( $content, $mlw_quiz_array, $variables ) {
165
  $quiz_id = is_object( $mlw_quiz_array ) ? $mlw_quiz_array->quiz_id : $mlw_quiz_array['quiz_id'];
166
  while ( false !== strpos( $content, '%POLL_RESULTS_' ) ) {
167
  $question_id = mlw_qmn_get_string_between( $content, '%POLL_RESULTS_', '%' );
@@ -172,8 +173,9 @@ function qsm_variable_poll_result( $content, $mlw_quiz_array, $variables ) {
172
  global $wpdb;
173
  $total_query = $wpdb->get_row( $wpdb->prepare( "SELECT count(*) AS total_count FROM {$wpdb->prefix}mlw_results WHERE quiz_id = %d", $quiz_id ), ARRAY_A );
174
  $total_result = $total_query['total_count'];
175
- $ser_answer = $wpdb->get_row( $wpdb->prepare( "SELECT answer_array FROM {$wpdb->prefix}mlw_questions WHERE question_id = %d", $question_id ), ARRAY_A );
176
  $ser_answer_arry = unserialize( $ser_answer['answer_array'] );
 
177
  $ser_answer_arry_change = array_filter( array_merge( array( 0 ), $ser_answer_arry ) );
178
  $total_quiz_results = $wpdb->get_results( $wpdb->prepare( "SELECT quiz_results FROM {$wpdb->prefix}mlw_results WHERE quiz_id = %d", $quiz_id ), ARRAY_A );
179
  $answer_array = array();
@@ -190,11 +192,12 @@ function qsm_variable_poll_result( $content, $mlw_quiz_array, $variables ) {
190
  $str = '';
191
  if ( $vals ) {
192
  $str .= '<h4>' . __( 'Poll Result', 'quiz-master-next' ) . ':</h4>';
193
- foreach ( $vals as $answer_str => $answer_count ) {
194
  if ( $answer_str != '' && qsm_find_key_from_array( $answer_str, $ser_answer_arry_change ) ) {
195
  $percentage = number_format( $answer_count / $total_result * 100, 2 );
196
- $str .= $answer_str . ' : ' . $percentage . '%<br/>';
197
- $str .= '<progress value="' . $percentage . '" max="100">' . $percentage . ' %</progress><br/>';
 
198
  }
199
  }
200
  }
@@ -202,7 +205,20 @@ function qsm_variable_poll_result( $content, $mlw_quiz_array, $variables ) {
202
  }
203
  return $content;
204
  }
205
-
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  function mlw_qmn_get_string_between( $string, $start, $end ) {
207
  $string = ' ' . $string;
208
  $ini = strpos( $string, $start );
@@ -612,12 +628,18 @@ function qmn_variable_average_category_points( $content, $mlw_quiz_array ) {
612
  } else {
613
  $category_name = $answer_text[1];
614
  }
615
- foreach ( $mlw_quiz_array['question_answers_array'] as $answer ) {
616
- if ( $answer['category'] == $category_name ) {
617
- if ( $answer['question_type'] !== '11' ) {
618
- $total_questions += 1;
 
 
 
 
 
 
 
619
  }
620
- $return_points += $answer['points'];
621
  }
622
  }
623
  if ( $total_questions !== 0 ) {
@@ -1246,6 +1268,7 @@ function qsm_get_question_maximum_points( $question = array() ) {
1246
  $answer_points = array_slice( $answer_points, 0, $limit_multiple_response, true );
1247
  }
1248
  $question_max_point = array_sum( $answer_points );
 
1249
  }
1250
  }
1251
  return $question_max_point;
65
  add_filter( 'mlw_qmn_template_variable_results_page', 'qsm_variable_total_possible_points', 10, 2 );
66
  add_filter( 'mlw_qmn_template_variable_results_page', 'qsm_variable_total_attempted_questions', 10, 2 );
67
  add_filter( 'mlw_qmn_template_variable_results_page', 'mlw_qmn_variable_user_full_name', 10, 2 );
68
+ add_filter( 'mlw_qmn_template_variable_results_page', 'qsm_variable_poll_result', 10, 3);
69
  add_filter( 'qmn_end_results', 'qsm_variable_poll_result', 10, 3 );
70
  add_filter( 'mlw_qmn_template_variable_quiz_page', 'mlw_qmn_variable_quiz_name', 10, 2 );
71
  add_filter( 'mlw_qmn_template_variable_quiz_page', 'mlw_qmn_variable_quiz_links', 10, 2 );
162
  * @param str $content
163
  * @param arr $mlw_quiz_array
164
  */
165
+ function qsm_variable_poll_result( $content, $mlw_quiz_array, $variables = "" ) {
166
  $quiz_id = is_object( $mlw_quiz_array ) ? $mlw_quiz_array->quiz_id : $mlw_quiz_array['quiz_id'];
167
  while ( false !== strpos( $content, '%POLL_RESULTS_' ) ) {
168
  $question_id = mlw_qmn_get_string_between( $content, '%POLL_RESULTS_', '%' );
173
  global $wpdb;
174
  $total_query = $wpdb->get_row( $wpdb->prepare( "SELECT count(*) AS total_count FROM {$wpdb->prefix}mlw_results WHERE quiz_id = %d", $quiz_id ), ARRAY_A );
175
  $total_result = $total_query['total_count'];
176
+ $ser_answer = $wpdb->get_row( $wpdb->prepare( "SELECT answer_array,question_settings FROM {$wpdb->prefix}mlw_questions WHERE question_id = %d", $question_id ), ARRAY_A );
177
  $ser_answer_arry = unserialize( $ser_answer['answer_array'] );
178
+ $question_settings = unserialize( $ser_answer['question_settings'] );
179
  $ser_answer_arry_change = array_filter( array_merge( array( 0 ), $ser_answer_arry ) );
180
  $total_quiz_results = $wpdb->get_results( $wpdb->prepare( "SELECT quiz_results FROM {$wpdb->prefix}mlw_results WHERE quiz_id = %d", $quiz_id ), ARRAY_A );
181
  $answer_array = array();
192
  $str = '';
193
  if ( $vals ) {
194
  $str .= '<h4>' . __( 'Poll Result', 'quiz-master-next' ) . ':</h4>';
195
+ foreach ( $vals as $answer_str => $answer_count ) {
196
  if ( $answer_str != '' && qsm_find_key_from_array( $answer_str, $ser_answer_arry_change ) ) {
197
  $percentage = number_format( $answer_count / $total_result * 100, 2 );
198
+ $answer_str = qsm_answers_type_evaluated( $answer_str, $question_settings );
199
+ $str .= $answer_str. ' : ' . $percentage . '%<br/>';
200
+ $str .= '<progress value="' . $percentage . '" max="100">' . $percentage . ' %</progress><br/>';
201
  }
202
  }
203
  }
205
  }
206
  return $content;
207
  }
208
+ /**
209
+ * Show Answer type evaluated
210
+ *
211
+ * @param str $answer
212
+ * @param arr $question_settings
213
+ */
214
+ function qsm_answers_type_evaluated ( $answer, $question_settings ) {
215
+ if ( 'rich' === $question_settings['answerEditor'] ) {
216
+ $answer = htmlspecialchars_decode( $answer );
217
+ } elseif ( 'image' === $question_settings['answerEditor'] ) {
218
+ $answer = '<span class="qmn_image_option" ><img src="' . htmlspecialchars_decode( $answer, ENT_QUOTES ) . '"/></span>';
219
+ }
220
+ return $answer;
221
+ }
222
  function mlw_qmn_get_string_between( $string, $start, $end ) {
223
  $string = ' ' . $string;
224
  $ini = strpos( $string, $start );
628
  } else {
629
  $category_name = $answer_text[1];
630
  }
631
+ foreach ( $mlw_quiz_array['question_answers_array'] as $answer ) {
632
+ if( is_array( $answer['multicategories'] ) ) {
633
+ foreach ( $answer['multicategories'] as $category ) {
634
+ $category_name_object = get_term_by( 'ID', $category, 'qsm_category' );
635
+ $category_name_of_question= ( !empty( $category_name_object->name ) ? $category_name_object->name : '' );
636
+ if ( $category_name_object->name == $category_name ) {
637
+ if ( '11' !== $answer['question_type'] ) {
638
+ $total_questions = +1;
639
+ }
640
+ $return_points += $answer['points'];
641
+ }
642
  }
 
643
  }
644
  }
645
  if ( $total_questions !== 0 ) {
1268
  $answer_points = array_slice( $answer_points, 0, $limit_multiple_response, true );
1269
  }
1270
  $question_max_point = array_sum( $answer_points );
1271
+ $question_max_point = apply_filters( 'qsm_question_max_point', $question_max_point, $answer_points );
1272
  }
1273
  }
1274
  return $question_max_point;
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: quiz, survey, lead, test, score, exam, questionnaire, question,wordpress q
4
  Requires at least: 4.9
5
  Tested up to: 5.8
6
  Requires PHP: 5.4
7
- Stable tag: 7.3.1
8
  License: GPLv2
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -151,6 +151,17 @@ This is usually a theme conflict. You can [checkout out our common conflict solu
151
  18. Database
152
 
153
  == Changelog ==
 
 
 
 
 
 
 
 
 
 
 
154
 
155
  = 7.3.1 (August 13, 2021) =
156
  * Bug: Fixed the error on updating database.
4
  Requires at least: 4.9
5
  Tested up to: 5.8
6
  Requires PHP: 5.4
7
+ Stable tag: 7.3.2
8
  License: GPLv2
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
151
  18. Database
152
 
153
  == Changelog ==
154
+ = 7.3.2 (September 06, 2021) =
155
+ * Bug: Added Translation for Time is up and Cancel button.
156
+ * Bug: Fixed the issue of category name not visible.
157
+ * Bug: Fixed the issue of limit number of questions per category is not working.
158
+ * Bug: Fixed the issue of results page and email showing only 1 question and its answer multiple times.
159
+ * Bug: Fixed the issue of %POLL_RESULT_X% not displaying images while using rich answers.
160
+ * Bug: Fixed the issue of %AVERAGE_CATEGORY_POINTS_X% variable not working.
161
+ * Bug: Fixed the issue of validation errors appearing on the questions before entering the responses.
162
+ * Bug: Fixed the issue of timer not showing on the quiz.
163
+ * Bug: Fixed security issue to prevent Cross-Site Scripting attacks.
164
+
165
 
166
  = 7.3.1 (August 13, 2021) =
167
  * Bug: Fixed the error on updating database.
templates/qmn_primary.css CHANGED
@@ -121,7 +121,7 @@
121
  .quiz_section>.quiz-cat {
122
  margin-left: 15px;
123
  font-size: 14px;
124
- font-weight: bold;
125
  float: right;
126
  }
127
 
121
  .quiz_section>.quiz-cat {
122
  margin-left: 15px;
123
  font-size: 14px;
124
+ font-style: italic;
125
  float: right;
126
  }
127