Tutor LMS – eLearning and online course solution - Version 1.5.3

Version Description

  • 04 February, 2020 =

  • Added: Go auto next after finish lesson (When no video)

  • Added: Nonce field at add instructor form to determine that request comes from the dedicated page.

  • Updated: Instructor approved/blocked by ajax request in post method with the nonce check (Security Update)

Download this release

Release Info

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

Code changes from version 1.5.2 to 1.5.3

assets/js/tutor-admin.js CHANGED
@@ -332,7 +332,6 @@ jQuery(document).ready(function($){
332
  if (errors && Object.keys(errors).length){
333
  $.each(data.data.errors, function( index, value ) {
334
  if (isObject(value)){
335
-
336
  $.each(value, function( key, value1 ) {
337
  errorMsg += '<p class="tutor-required-fields">'+value1[0]+'</p>';
338
  });
@@ -348,11 +347,43 @@ jQuery(document).ready(function($){
348
  });
349
  });
350
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
351
  function isObject (value) {
352
  return value && typeof value === 'object' && value.constructor === Object;
353
  }
354
 
355
-
356
  /**
357
  * Tutor Assignments JS
358
  * @since v.1.3.3
332
  if (errors && Object.keys(errors).length){
333
  $.each(data.data.errors, function( index, value ) {
334
  if (isObject(value)){
 
335
  $.each(value, function( key, value1 ) {
336
  errorMsg += '<p class="tutor-required-fields">'+value1[0]+'</p>';
337
  });
347
  });
348
  });
349
 
350
+
351
+ /**
352
+ * Instructor block unblock action
353
+ * @since v.1.5.3
354
+ */
355
+
356
+ $(document).on('click', 'a.instructor-action', function(e){
357
+ e.preventDefault();
358
+
359
+ var $that = $(this);
360
+ var action = $that.attr('data-action');
361
+ var instructor_id = $that.attr('data-instructor-id');
362
+
363
+ var nonce_key = tutor_data.nonce_key;
364
+ var json_data = { instructor_id : instructor_id, action_name : action, action: 'instructor_approval_action'};
365
+ json_data[nonce_key] = tutor_data[nonce_key];
366
+
367
+ $.ajax({
368
+ url : ajaxurl,
369
+ type : 'POST',
370
+ data : json_data,
371
+ beforeSend: function () {
372
+ $that.addClass('tutor-updating-message');
373
+ },
374
+ success: function (data) {
375
+ location.reload(true);
376
+ },
377
+ complete: function () {
378
+ $that.removeClass('tutor-updating-message');
379
+ }
380
+ });
381
+ });
382
+
383
  function isObject (value) {
384
  return value && typeof value === 'object' && value.constructor === Object;
385
  }
386
 
 
387
  /**
388
  * Tutor Assignments JS
389
  * @since v.1.3.3
classes/Assets.php CHANGED
@@ -36,6 +36,9 @@ class Assets{
36
 
37
  $tutor_localize_data = array(
38
  'delete_confirm_text' => __('Are you sure? it can not be undone.', 'tutor'),
 
 
 
39
  );
40
  if ( ! empty($_GET['taxonomy']) && ( $_GET['taxonomy'] === 'course-category' || $_GET['taxonomy'] === 'course-tag') ){
41
  $tutor_localize_data['open_tutor_admin_menu'] = true;
36
 
37
  $tutor_localize_data = array(
38
  'delete_confirm_text' => __('Are you sure? it can not be undone.', 'tutor'),
39
+
40
+ 'nonce_key' => tutor()->nonce,
41
+ tutor()->nonce => wp_create_nonce( tutor()->nonce_action ),
42
  );
43
  if ( ! empty($_GET['taxonomy']) && ( $_GET['taxonomy'] === 'course-category' || $_GET['taxonomy'] === 'course-tag') ){
44
  $tutor_localize_data['open_tutor_admin_menu'] = true;
classes/Instructor.php CHANGED
@@ -22,6 +22,14 @@ class Instructor {
22
 
23
  //Add instructor from admin panel.
24
  add_action('wp_ajax_tutor_add_instructor', array($this, 'add_new_instructor'));
 
 
 
 
 
 
 
 
25
  }
26
 
27
  /**
@@ -135,6 +143,8 @@ class Instructor {
135
 
136
 
137
  public function add_new_instructor(){
 
 
138
  $required_fields = apply_filters('tutor_instructor_registration_required_fields', array(
139
  'first_name' => __('First name field is required', 'tutor'),
140
  'last_name' => __('Last name field is required', 'tutor'),
@@ -198,4 +208,37 @@ class Instructor {
198
  wp_send_json_error(array('errors' => $user_id));
199
  }
200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  }
22
 
23
  //Add instructor from admin panel.
24
  add_action('wp_ajax_tutor_add_instructor', array($this, 'add_new_instructor'));
25
+
26
+ /**
27
+ * Instructor Approval
28
+ * Block Unblock
29
+ *
30
+ * @since v.1.5.3
31
+ */
32
+ add_action('wp_ajax_instructor_approval_action', array($this, 'instructor_approval_action'));
33
  }
34
 
35
  /**
143
 
144
 
145
  public function add_new_instructor(){
146
+ tutils()->checking_nonce();
147
+
148
  $required_fields = apply_filters('tutor_instructor_registration_required_fields', array(
149
  'first_name' => __('First name field is required', 'tutor'),
150
  'last_name' => __('Last name field is required', 'tutor'),
208
  wp_send_json_error(array('errors' => $user_id));
209
  }
210
 
211
+ public function instructor_approval_action(){
212
+ tutils()->checking_nonce();
213
+
214
+ $instructor_id = (int) sanitize_text_field(tutils()->array_get('instructor_id', $_POST));
215
+ $action = sanitize_text_field(tutils()->array_get('action_name', $_POST));
216
+
217
+ if( 'approve' === $action ) {
218
+ do_action('tutor_before_approved_instructor', $instructor_id);
219
+
220
+ update_user_meta($instructor_id, '_tutor_instructor_status', 'approved');
221
+ update_user_meta($instructor_id, '_tutor_instructor_approved', tutor_time());
222
+
223
+ $instructor = new \WP_User($instructor_id);
224
+ $instructor->add_role(tutor()->instructor_role);
225
+
226
+ //TODO: send E-Mail to this user about instructor approval, should via hook
227
+ do_action('tutor_after_approved_instructor', $instructor_id);
228
+ }
229
+
230
+ if( 'blocked' === $action ) {
231
+ do_action('tutor_before_blocked_instructor', $instructor_id);
232
+ update_user_meta($instructor_id, '_tutor_instructor_status', 'blocked');
233
+
234
+ $instructor = new \WP_User($instructor_id);
235
+ $instructor->remove_role(tutor()->instructor_role);
236
+ do_action('tutor_after_blocked_instructor', $instructor_id);
237
+
238
+ //TODO: send E-Mail to this user about instructor blocked, should via hook
239
+ }
240
+
241
+ wp_send_json_success();
242
+ }
243
+
244
  }
classes/Instructors_List.php CHANGED
@@ -19,7 +19,7 @@ class Instructors_List extends \Tutor_List_Table {
19
  'ajax' => false //does this table support ajax?
20
  ) );
21
 
22
- $this->process_bulk_action();
23
  }
24
 
25
  function column_default($item, $column_name){
@@ -63,13 +63,13 @@ class Instructors_List extends \Tutor_List_Table {
63
 
64
  switch ($status){
65
  case 'pending':
66
- $actions['approved'] = sprintf('<a href="?page=%s&action=%s&instructor=%s">Approve</a>',$_REQUEST['page'],'approve',$item->ID);
67
  break;
68
  case 'approved':
69
- $actions['blocked'] = sprintf('<a href="?page=%s&action=%s&instructor=%s">Block</a>',$_REQUEST['page'],'blocked',$item->ID);
70
  break;
71
  case 'blocked':
72
- $actions['approved'] = sprintf('<a href="?page=%s&action=%s&instructor=%s">Un Block</a>',$_REQUEST['page'],'approve',$item->ID);
73
  break;
74
  }
75
  //Return the title contents
@@ -90,7 +90,7 @@ class Instructors_List extends \Tutor_List_Table {
90
 
91
  function get_columns(){
92
  $columns = array(
93
- 'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
94
  'display_name' => __('Name', 'tutor'),
95
  'user_email' => __('E-Mail', 'tutor'),
96
  'total_course' => __('Total Course', 'tutor'),
19
  'ajax' => false //does this table support ajax?
20
  ) );
21
 
22
+ //$this->process_bulk_action();
23
  }
24
 
25
  function column_default($item, $column_name){
63
 
64
  switch ($status){
65
  case 'pending':
66
+ $actions['approved'] = sprintf('<a class="instructor-action" data-action="approve" data-instructor-id="'.$item->ID.'" href="?page=%s&action=%s&instructor=%s">Approve</a>', $_REQUEST['page'],'approve',$item->ID);
67
  break;
68
  case 'approved':
69
+ $actions['blocked'] = sprintf('<a class="instructor-action" data-action="blocked" data-instructor-id="'.$item->ID.'" href="?page=%s&action=%s&instructor=%s">Block</a>', $_REQUEST['page'],'blocked',$item->ID);
70
  break;
71
  case 'blocked':
72
+ $actions['approved'] = sprintf('<a class="instructor-action" data-action="approve" data-instructor-id="'.$item->ID.'" href="?page=%s&action=%s&instructor=%s">Un Block</a>',$_REQUEST['page'],'approve',$item->ID);
73
  break;
74
  }
75
  //Return the title contents
90
 
91
  function get_columns(){
92
  $columns = array(
93
+ //'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
94
  'display_name' => __('Name', 'tutor'),
95
  'user_email' => __('E-Mail', 'tutor'),
96
  'total_course' => __('Total Course', 'tutor'),
classes/Lesson.php CHANGED
@@ -35,7 +35,12 @@ class Lesson extends Tutor_Base {
35
  * @since v.1.4.9
36
  */
37
  add_action('wp_ajax_autoload_next_course_content', array($this, 'autoload_next_course_content'));
38
- add_action('wp_ajax_nopriv_autoload_next_course_content', array($this, 'autoload_next_course_content_noprev'));
 
 
 
 
 
39
  }
40
 
41
  /**
@@ -267,8 +272,6 @@ class Lesson extends Tutor_Base {
267
 
268
  do_action('tutor_lesson_completed_after', $lesson_id);
269
 
270
-
271
- wp_redirect(get_the_permalink($lesson_id));
272
  }
273
 
274
  /**
@@ -308,8 +311,21 @@ class Lesson extends Tutor_Base {
308
  wp_send_json_success(array('next_url' => $next_url));
309
  }
310
 
311
- public function autoload_next_course_content_noprev(){
312
-
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  }
314
 
315
  }
35
  * @since v.1.4.9
36
  */
37
  add_action('wp_ajax_autoload_next_course_content', array($this, 'autoload_next_course_content'));
38
+
39
+ /**
40
+ * Load next course item after click complete button
41
+ * @since v.1.5.3
42
+ */
43
+ add_action('tutor_lesson_completed_after', array($this, 'tutor_lesson_completed_after'));
44
  }
45
 
46
  /**
272
 
273
  do_action('tutor_lesson_completed_after', $lesson_id);
274
 
 
 
275
  }
276
 
277
  /**
311
  wp_send_json_success(array('next_url' => $next_url));
312
  }
313
 
314
+ /**
315
+ * Load next course item after click complete button
316
+ *
317
+ * @since v.1.5.3
318
+ */
319
+ public function tutor_lesson_completed_after($content_id){
320
+ $contents = tutor_utils()->get_course_prev_next_contents_by_id($content_id);
321
+ $autoload_course_content = (bool) get_tutor_option('autoload_next_course_content');
322
+ if($autoload_course_content) {
323
+ echo get_the_permalink($contents->next_id);
324
+ wp_redirect(get_the_permalink($contents->next_id));
325
+ } else {
326
+ wp_redirect(get_the_permalink($content_id));
327
+ }
328
+ die();
329
  }
330
 
331
  }
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.3
7
  Requires PHP: 5.4.0
8
- Stable tag: 1.5.2
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.5.2 - 29 January, 2020 =
245
 
246
  * Tutor LMS plugin is now running under 'plugins_loaded' hook (Architectural update)
5
  Requires at least: 4.5
6
  Tested up to: 5.3
7
  Requires PHP: 5.4.0
8
+ Stable tag: 1.5.3
9
  License: GPLv3
10
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
11
 
241
 
242
  == Changelog ==
243
 
244
+ = 1.5.3 - 04 February, 2020 =
245
+
246
+ * Added: Go auto next after finish lesson (When no video)
247
+ * Added: Nonce field at add instructor form to determine that request comes from the dedicated page.
248
+ * Updated: Instructor approved/blocked by ajax request in post method with the nonce check (Security Update)
249
+
250
  = 1.5.2 - 29 January, 2020 =
251
 
252
  * Tutor LMS plugin is now running under 'plugins_loaded' hook (Architectural update)
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.5.2
8
  Author URI: http://themeum.com
9
  Requires at least: 4.5
10
  Tested up to: 5.3
@@ -17,7 +17,7 @@ if ( ! defined( 'ABSPATH' ) )
17
  /**
18
  * Defined the tutor main file
19
  */
20
- define('TUTOR_VERSION', '1.5.2');
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.5.3
8
  Author URI: http://themeum.com
9
  Requires at least: 4.5
10
  Tested up to: 5.3
17
  /**
18
  * Defined the tutor main file
19
  */
20
+ define('TUTOR_VERSION', '1.5.3');
21
  define('TUTOR_FILE', __FILE__);
22
 
23
  /**
views/pages/add_new_instructor.php CHANGED
@@ -4,6 +4,7 @@
4
  <hr class="wp-header-end">
5
 
6
  <form action="" id="new-instructor-form" method="post">
 
7
  <input type="hidden" name="action" value="add_new_instructor">
8
 
9
 
4
  <hr class="wp-header-end">
5
 
6
  <form action="" id="new-instructor-form" method="post">
7
+ <?php tutor_nonce_field(); ?>
8
  <input type="hidden" name="action" value="add_new_instructor">
9
 
10