Tutor LMS – eLearning and online course solution - Version 1.4.4

Version Description

  • 16 October, 2019 =

  • Fixed: quiz question sortable sorting item

  • Improved: quiz draggable answer drop accessibility

  • Fixed: prevented fatal error in single quiz question with no option and trying to finish quiz.

Download this release

Release Info

Developer themeum
Plugin Icon wp plugin Tutor LMS – eLearning and online course solution
Version 1.4.4
Comparing to
See all releases

Code changes from version 1.4.3 to 1.4.4

Files changed (5) hide show
  1. assets/js/tutor-front.js +21 -3
  2. classes/Quiz.php +67 -62
  3. classes/Utils.php +2 -1
  4. readme.txt +7 -1
  5. tutor.php +2 -2
assets/js/tutor-front.js CHANGED
@@ -515,7 +515,7 @@ jQuery(document).ready(function($){
515
  function init_quiz_builder() {
516
  if (jQuery().sortable) {
517
  $(".tutor-quiz-answers-wrap").sortable({
518
- //handle: ".answer-sorting-bar",
519
  start: function (e, ui) {
520
  ui.placeholder.css('visibility', 'visible');
521
  },
@@ -526,8 +526,7 @@ jQuery(document).ready(function($){
526
 
527
  $(".quiz-draggable-rand-answers, .quiz-answer-matching-droppable").sortable({
528
  connectWith: ".quiz-answer-matching-droppable",
529
- placeholder: "drop-hover"
530
-
531
  }).disableSelection();
532
  }
533
  }
@@ -591,6 +590,25 @@ jQuery(document).ready(function($){
591
  $that.closest('.tutor-quiz-answers-wrap').find('.characters_remaining').html(remaining);
592
  });
593
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
594
  /**
595
  * Add to cart in guest mode, show login form
596
  *
515
  function init_quiz_builder() {
516
  if (jQuery().sortable) {
517
  $(".tutor-quiz-answers-wrap").sortable({
518
+ handle: ".answer-sorting-bar",
519
  start: function (e, ui) {
520
  ui.placeholder.css('visibility', 'visible');
521
  },
526
 
527
  $(".quiz-draggable-rand-answers, .quiz-answer-matching-droppable").sortable({
528
  connectWith: ".quiz-answer-matching-droppable",
529
+ placeholder: "drop-hover",
 
530
  }).disableSelection();
531
  }
532
  }
590
  $that.closest('.tutor-quiz-answers-wrap').find('.characters_remaining').html(remaining);
591
  });
592
 
593
+ /**
594
+ *
595
+ * @type {jQuery}
596
+ *
597
+ * Improved Quiz draggable answers drop accessibility
598
+ * Answers draggable wrap will be now same height.
599
+ *
600
+ * @since v.1.4.4
601
+ */
602
+ var countDraggableAnswers = $('.quiz-draggable-rand-answers').length;
603
+ if (countDraggableAnswers){
604
+ $('.quiz-draggable-rand-answers').each(function(){
605
+ var $that = $(this);
606
+ var draggableDivHeight = $that.height();
607
+
608
+ $that.css({"height": draggableDivHeight});
609
+ });
610
+ }
611
+
612
  /**
613
  * Add to cart in guest mode, show login form
614
  *
classes/Quiz.php CHANGED
@@ -209,91 +209,96 @@ class Quiz {
209
  }
210
 
211
  $quiz_answers = tutor_utils()->avalue_dot('quiz_question', $attempt_answers);
 
212
  $total_marks = 0;
213
- foreach ($quiz_answers as $question_id => $answers){
214
- $question = tutor_utils()->get_quiz_question_by_id($question_id);
215
- $question_type = $question->question_type;
216
 
217
- $is_answer_was_correct = false;
218
- $given_answer = '';
219
 
220
- if ($question_type === 'true_false' || $question_type === 'single_choice'){
 
 
221
 
222
- $given_answer = $answers;
223
- $is_answer_was_correct = (bool) $wpdb->get_var("SELECT is_correct FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE answer_id = {$answers} ");
224
 
225
- }elseif ($question_type === 'multiple_choice'){
226
 
227
- $given_answer = maybe_serialize($answers);
228
- $get_original_answers = (array) $wpdb->get_col("SELECT answer_id FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE belongs_question_id = {$question->question_id} AND belongs_question_type = '{$question_type}' AND is_correct = 1 ;");
229
- if (maybe_serialize($get_original_answers) == $given_answer){
230
- $is_answer_was_correct = true;
231
- }
232
 
233
- }elseif ($question_type === 'fill_in_the_blank'){
234
 
235
- $given_answer = (array) array_map('sanitize_text_field', $answers);
236
- $given_answer = maybe_serialize($given_answer);
 
 
 
237
 
238
- $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}' ;");
239
- $gap_answer = (array) explode('|', $get_original_answer->answer_two_gap_match);
240
 
241
- $gap_answer = array_map('sanitize_text_field', $gap_answer);
242
- if ($given_answer == maybe_serialize($gap_answer)){
243
- $is_answer_was_correct = true;
244
- }
245
 
246
- }elseif ($question_type === 'open_ended' || $question_type === 'short_answer'){
 
247
 
248
- $given_answer = wp_kses_post($answers);
 
 
 
249
 
250
- }elseif ($question_type === 'ordering' || $question_type === 'matching'|| $question_type === 'image_matching' ){
251
 
252
- $given_answer = (array) array_map('sanitize_text_field', tutor_utils()->avalue_dot('answers', $answers));
253
- $given_answer = maybe_serialize($given_answer);
254
 
255
- $get_original_answers = (array) $wpdb->get_col("SELECT answer_id FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE belongs_question_id = {$question->question_id} AND belongs_question_type = '{$question_type}' ORDER BY answer_order ASC ;");
256
- $get_original_answers = array_map('sanitize_text_field', $get_original_answers);
257
 
258
- if ($given_answer == maybe_serialize($get_original_answers)){
259
- $is_answer_was_correct = true;
260
- }
261
 
262
- }elseif ($question_type === 'image_answering'){
263
- echo '<pre>';
264
 
265
- $image_inputs = tutor_utils()->avalue_dot('answer_id', $answers);
266
- $image_inputs = (array) array_map('sanitize_text_field', $image_inputs);
267
- $given_answer = maybe_serialize($image_inputs);
268
- $is_answer_was_correct = false;
269
 
270
- $db_answer = $wpdb->get_col("SELECT answer_title FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE belongs_question_id = {$question_id} AND belongs_question_type =
271
- 'image_answering' ORDER BY answer_order asc ;");
272
 
273
- if (is_array($db_answer) && count($db_answer)){
274
- $is_answer_was_correct = (strtolower(maybe_serialize(array_values($image_inputs))) == strtolower(maybe_serialize($db_answer)) );
275
- }
276
- }
277
-
278
- $question_mark = $is_answer_was_correct ? $question->question_mark : 0;
279
- $total_marks += $question_mark;
280
-
281
- $answers_data = array(
282
- 'user_id' => $user_id,
283
- 'quiz_id' => $attempt->quiz_id,
284
- 'question_id' => $question_id,
285
- 'quiz_attempt_id' => $attempt_id,
286
- 'given_answer' => $given_answer,
287
- 'question_mark' => $question->question_mark,
288
- 'achieved_mark' => $question_mark,
289
- 'minus_mark' => 0,
290
- 'is_correct' => $is_answer_was_correct ? 1 : 0,
291
- );
292
- $wpdb->insert($wpdb->prefix.'tutor_quiz_attempt_answers', $answers_data);
 
 
 
 
 
 
 
 
 
293
  }
294
 
295
  $attempt_info = array(
296
- 'total_answered_questions' => count($quiz_answers),
297
  'earned_marks' => $total_marks,
298
  'attempt_status' => 'attempt_ended',
299
  'attempt_ended_at' => date("Y-m-d H:i:s"),
209
  }
210
 
211
  $quiz_answers = tutor_utils()->avalue_dot('quiz_question', $attempt_answers);
212
+
213
  $total_marks = 0;
 
 
 
214
 
215
+ if ( tutils()->count($quiz_answers)) {
 
216
 
217
+ foreach ( $quiz_answers as $question_id => $answers ) {
218
+ $question = tutor_utils()->get_quiz_question_by_id( $question_id );
219
+ $question_type = $question->question_type;
220
 
221
+ $is_answer_was_correct = false;
222
+ $given_answer = '';
223
 
224
+ if ( $question_type === 'true_false' || $question_type === 'single_choice' ) {
225
 
226
+ $given_answer = $answers;
227
+ $is_answer_was_correct = (bool) $wpdb->get_var( "SELECT is_correct FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE answer_id = {$answers} " );
 
 
 
228
 
229
+ } elseif ( $question_type === 'multiple_choice' ) {
230
 
231
+ $given_answer = maybe_serialize( $answers );
232
+ $get_original_answers = (array) $wpdb->get_col( "SELECT answer_id FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE belongs_question_id = {$question->question_id} AND belongs_question_type = '{$question_type}' AND is_correct = 1 ;" );
233
+ if ( maybe_serialize( $get_original_answers ) == $given_answer ) {
234
+ $is_answer_was_correct = true;
235
+ }
236
 
237
+ } elseif ( $question_type === 'fill_in_the_blank' ) {
 
238
 
239
+ $given_answer = (array) array_map( 'sanitize_text_field', $answers );
240
+ $given_answer = maybe_serialize( $given_answer );
 
 
241
 
242
+ $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}' ;" );
243
+ $gap_answer = (array) explode( '|', $get_original_answer->answer_two_gap_match );
244
 
245
+ $gap_answer = array_map( 'sanitize_text_field', $gap_answer );
246
+ if ( $given_answer == maybe_serialize( $gap_answer ) ) {
247
+ $is_answer_was_correct = true;
248
+ }
249
 
250
+ } elseif ( $question_type === 'open_ended' || $question_type === 'short_answer' ) {
251
 
252
+ $given_answer = wp_kses_post( $answers );
 
253
 
254
+ } elseif ( $question_type === 'ordering' || $question_type === 'matching' || $question_type === 'image_matching' ) {
 
255
 
256
+ $given_answer = (array) array_map( 'sanitize_text_field', tutor_utils()->avalue_dot( 'answers', $answers ) );
257
+ $given_answer = maybe_serialize( $given_answer );
 
258
 
259
+ $get_original_answers = (array) $wpdb->get_col( "SELECT answer_id FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE belongs_question_id = {$question->question_id} AND belongs_question_type = '{$question_type}' ORDER BY answer_order ASC ;" );
260
+ $get_original_answers = array_map( 'sanitize_text_field', $get_original_answers );
261
 
262
+ if ( $given_answer == maybe_serialize( $get_original_answers ) ) {
263
+ $is_answer_was_correct = true;
264
+ }
 
265
 
266
+ } elseif ( $question_type === 'image_answering' ) {
267
+ echo '<pre>';
268
 
269
+ $image_inputs = tutor_utils()->avalue_dot( 'answer_id', $answers );
270
+ $image_inputs = (array) array_map( 'sanitize_text_field', $image_inputs );
271
+ $given_answer = maybe_serialize( $image_inputs );
272
+ $is_answer_was_correct = false;
273
+
274
+ $db_answer = $wpdb->get_col( "SELECT answer_title FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE belongs_question_id = {$question_id} AND belongs_question_type =
275
+ 'image_answering' ORDER BY answer_order asc ;" );
276
+
277
+ if ( is_array( $db_answer ) && count( $db_answer ) ) {
278
+ $is_answer_was_correct = ( strtolower( maybe_serialize( array_values( $image_inputs ) ) ) == strtolower( maybe_serialize( $db_answer ) ) );
279
+ }
280
+ }
281
+
282
+ $question_mark = $is_answer_was_correct ? $question->question_mark : 0;
283
+ $total_marks += $question_mark;
284
+
285
+ $answers_data = array(
286
+ 'user_id' => $user_id,
287
+ 'quiz_id' => $attempt->quiz_id,
288
+ 'question_id' => $question_id,
289
+ 'quiz_attempt_id' => $attempt_id,
290
+ 'given_answer' => $given_answer,
291
+ 'question_mark' => $question->question_mark,
292
+ 'achieved_mark' => $question_mark,
293
+ 'minus_mark' => 0,
294
+ 'is_correct' => $is_answer_was_correct ? 1 : 0,
295
+ );
296
+ $wpdb->insert( $wpdb->prefix . 'tutor_quiz_attempt_answers', $answers_data );
297
+ }
298
  }
299
 
300
  $attempt_info = array(
301
+ 'total_answered_questions' => tutils()->count($quiz_answers),
302
  'earned_marks' => $total_marks,
303
  'attempt_status' => 'attempt_ended',
304
  'attempt_ended_at' => date("Y-m-d H:i:s"),
classes/Utils.php CHANGED
@@ -501,6 +501,7 @@ class Utils {
501
  $where_post_status = "AND $wpdb->posts.post_status IN({$statuses}) ";
502
  }
503
 
 
504
  $querystr = "
505
  SELECT $wpdb->posts.*
506
  FROM $wpdb->posts
@@ -508,7 +509,7 @@ class Utils {
508
 
509
  WHERE 1 = 1 {$where_post_status}
510
  AND $wpdb->posts.post_type = '{$course_post_type}'
511
- AND $wpdb->posts.post_date < NOW()
512
  ORDER BY $wpdb->posts.post_date DESC";
513
 
514
  $pageposts = $wpdb->get_results($querystr, OBJECT);
501
  $where_post_status = "AND $wpdb->posts.post_status IN({$statuses}) ";
502
  }
503
 
504
+ //AND $wpdb->posts.post_date < NOW()
505
  $querystr = "
506
  SELECT $wpdb->posts.*
507
  FROM $wpdb->posts
509
 
510
  WHERE 1 = 1 {$where_post_status}
511
  AND $wpdb->posts.post_type = '{$course_post_type}'
512
+
513
  ORDER BY $wpdb->posts.post_date DESC";
514
 
515
  $pageposts = $wpdb->get_results($querystr, OBJECT);
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: lms, course, elearning, education, learning management system
5
  Requires at least: 4.5
6
  Tested up to: 5.2
7
  Requires PHP: 5.4.0
8
- Stable tag: 1.4.3
9
  License: GPLv3
10
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
11
 
@@ -241,6 +241,12 @@ Tutor enables you to use any third party plugins without facing any compatibilit
241
 
242
  == Changelog ==
243
 
 
 
 
 
 
 
244
  = 1.4.3 - 11 October, 2019 =
245
 
246
  * Added: Reset Password, Tutor LMS native login system
5
  Requires at least: 4.5
6
  Tested up to: 5.2
7
  Requires PHP: 5.4.0
8
+ Stable tag: 1.4.4
9
  License: GPLv3
10
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
11
 
241
 
242
  == Changelog ==
243
 
244
+ = 1.4.4 - 16 October, 2019 =
245
+
246
+ * Fixed: quiz question sortable sorting item
247
+ * Improved: quiz draggable answer drop accessibility
248
+ * Fixed: prevented fatal error in single quiz question with no option and trying to finish quiz.
249
+
250
  = 1.4.3 - 11 October, 2019 =
251
 
252
  * Added: Reset Password, Tutor LMS native login system
tutor.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: Tutor LMS
4
  Plugin URI: https://www.themeum.com/product/tutor-lms/
5
  Description: Tutor is a complete solution for creating a Learning Management System in WordPress way. It can help you to create small to large scale online education site very conveniently. Power features like report, certificate, course preview, private file sharing make Tutor a robust plugin for any educational institutes.
6
  Author: Themeum
7
- Version: 1.4.3
8
  Author URI: http://themeum.com
9
  Requires at least: 4.5
10
  Tested up to: 5.2
@@ -17,7 +17,7 @@ if ( ! defined( 'ABSPATH' ) )
17
  /**
18
  * Defined the tutor main file
19
  */
20
- define('TUTOR_VERSION', '1.4.3');
21
  define('TUTOR_FILE', __FILE__);
22
 
23
  /**
4
  Plugin URI: https://www.themeum.com/product/tutor-lms/
5
  Description: Tutor is a complete solution for creating a Learning Management System in WordPress way. It can help you to create small to large scale online education site very conveniently. Power features like report, certificate, course preview, private file sharing make Tutor a robust plugin for any educational institutes.
6
  Author: Themeum
7
+ Version: 1.4.4
8
  Author URI: http://themeum.com
9
  Requires at least: 4.5
10
  Tested up to: 5.2
17
  /**
18
  * Defined the tutor main file
19
  */
20
+ define('TUTOR_VERSION', '1.4.4');
21
  define('TUTOR_FILE', __FILE__);
22
 
23
  /**