From 113ff6c1cb4c4a1defb5bcefbaa291e02943b22a Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Thu, 3 Aug 2023 16:21:06 +0600
Subject: [PATCH 22/78] Hook added for extend tutor functionality
---
views/pages/instructors.php | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/views/pages/instructors.php b/views/pages/instructors.php
index 63663c7930..4e15c43d05 100644
--- a/views/pages/instructors.php
+++ b/views/pages/instructors.php
@@ -116,14 +116,17 @@
-
+
-
+
-
+
+
+
+
@@ -175,6 +178,9 @@
?>
+
+ ID ); ?>
+
+
+
From 5b91256d7bfd207f555cddc6201befa1bd96dca5 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Fri, 4 Aug 2023 17:48:07 +0600
Subject: [PATCH 23/78] Quiz attempt list fix
---
models/QuizModel.php | 34 ++++++++++++++++++++++++++++------
1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/models/QuizModel.php b/models/QuizModel.php
index 0bf74b75a8..107a64d922 100644
--- a/models/QuizModel.php
+++ b/models/QuizModel.php
@@ -270,7 +270,19 @@ public static function get_total_quiz_attempts( $search_term = '', int $course_i
}
// Set query based on action tab.
- $pass_mark = "(((SUBSTRING_INDEX(SUBSTRING_INDEX(quiz_attempts.attempt_info, '\"passing_grade\";s:2:\"', -1), '\"', 1))/100)*quiz_attempts.total_marks)";
+ $pass_mark = "((( SUBSTRING_INDEX(
+ SUBSTRING_INDEX(
+ attempt_info,
+ CONCAT(
+ '\"passing_grade\";s:',
+ SUBSTRING_INDEX(SUBSTRING_INDEX(attempt_info, '\"passing_grade\";s:', -1), ':\"', 1),
+ ':\"'
+ ),
+ -1
+ ),
+ '\"',
+ 1
+ ))/100) * quiz_attempts.total_marks)";
$pending_count = "(SELECT COUNT(DISTINCT attempt_answer_id) FROM {$wpdb->prefix}tutor_quiz_attempt_answers WHERE quiz_attempt_id=quiz_attempts.attempt_id AND is_correct IS NULL)";
$tab_join = '';
@@ -287,8 +299,7 @@ public static function get_total_quiz_attempts( $search_term = '', int $course_i
case 'fail':
// Check if earned marks is less than pass mark and there is no pending question.
- $tab_clause = " AND quiz_attempts.earned_marks < {$pass_mark}
- AND {$pending_count} = 0 ";
+ $tab_clause = " AND quiz_attempts.earned_marks < {$pass_mark} AND {$pending_count} < 1 ";
break;
case 'pending':
$tab_clause = " AND {$pending_count} > 0 ";
@@ -392,7 +403,19 @@ public static function get_quiz_attempts( $start = 0, $limit = 10, $search_filte
$select_columns = $count_only ? 'COUNT(DISTINCT quiz_attempts.attempt_id)' : 'DISTINCT quiz_attempts.*, quiz.post_title, users.user_email, users.user_login, users.display_name';
$limit_offset = $count_only ? '' : ' LIMIT ' . $limit . ' OFFSET ' . $start;
- $pass_mark = "(((SUBSTRING_INDEX(SUBSTRING_INDEX(quiz_attempts.attempt_info, '\"passing_grade\";s:2:\"', -1), '\"', 1))/100)*quiz_attempts.total_marks)";
+ $pass_mark = "((( SUBSTRING_INDEX(
+ SUBSTRING_INDEX(
+ attempt_info,
+ CONCAT(
+ '\"passing_grade\";s:',
+ SUBSTRING_INDEX(SUBSTRING_INDEX(attempt_info, '\"passing_grade\";s:', -1), ':\"', 1),
+ ':\"'
+ ),
+ -1
+ ),
+ '\"',
+ 1
+ ))/100) * quiz_attempts.total_marks)";
$pending_count = "(SELECT COUNT(DISTINCT attempt_answer_id) FROM {$wpdb->prefix}tutor_quiz_attempt_answers WHERE quiz_attempt_id=quiz_attempts.attempt_id AND is_correct IS NULL)";
// Get attempts by instructor ID.
@@ -418,8 +441,7 @@ public static function get_quiz_attempts( $start = 0, $limit = 10, $search_filte
case 'fail':
// Check if earned marks is less than pass mark and there is no pending question.
- $result_clause = " AND quiz_attempts.earned_marks<{$pass_mark}
- AND {$pending_count}=0 ";
+ $result_clause = " AND quiz_attempts.earned_marks<{$pass_mark} AND {$pending_count} < 1 ";
break;
case 'pending':
From 43d01dccd3d116304c584e4fbe4a8ba88ba4e925 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Fri, 4 Aug 2023 17:53:40 +0600
Subject: [PATCH 24/78] WPCS fix
---
models/QuizModel.php | 34 +++++++++++++++++++++-------------
1 file changed, 21 insertions(+), 13 deletions(-)
diff --git a/models/QuizModel.php b/models/QuizModel.php
index 107a64d922..7c8bc0501d 100644
--- a/models/QuizModel.php
+++ b/models/QuizModel.php
@@ -862,21 +862,29 @@ public static function get_quiz_count_by_course( $course_id ) {
$and_clause = is_array( $course_id ) && count( $course_id ) ? ' AND post_parent IN (' . QueryHelper::prepare_in_clause( $course_id ) . ')' : "AND post_parent = $course_id";
+ //phpcs:disable
$count = $wpdb->get_var(
- "SELECT
- COUNT(ID)
- FROM {$wpdb->posts}
- WHERE post_parent IN
- (SELECT
- ID
- FROM {$wpdb->posts}
- WHERE post_type='topics'
- {$and_clause}
- AND post_status = 'publish'
- )
- AND post_type ='tutor_quiz'
- AND post_status = 'publish'"
+ $wpdb->prepare(
+ "SELECT
+ COUNT(ID)
+ FROM {$wpdb->posts}
+ WHERE post_parent IN
+ (SELECT
+ ID
+ FROM {$wpdb->posts}
+ WHERE post_type = %s
+ {$and_clause}
+ AND post_status = %s
+ )
+ AND post_type = %s
+ AND post_status = %s",
+ 'topics',
+ 'publish',
+ 'tutor_quiz',
+ 'publish'
+ )
);
+ //phpcs:enable
return $count ? $count : 0;
}
}
From 1878ef72d46ad6a6df6a2b644d6565a04a6e1f82 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Mon, 7 Aug 2023 11:32:20 +0600
Subject: [PATCH 25/78] Enable save button after remove image
---
assets/react/lib/media-chooser.js | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/assets/react/lib/media-chooser.js b/assets/react/lib/media-chooser.js
index d94769c9ff..65c2300ce0 100644
--- a/assets/react/lib/media-chooser.js
+++ b/assets/react/lib/media-chooser.js
@@ -49,21 +49,24 @@ window.jQuery(document).ready(function ($) {
});
frame.open();
});
+
/**
* Thumbnail Delete
- * @since v.1.5.6
+ * @since 1.5.6
*/
$(document).on('click', '.tutor-thumbnail-uploader .delete-btn', function (e) {
e.preventDefault();
- var $that = $(this);
- var wrapper = $that.closest('.tutor-thumbnail-uploader');
- var img = wrapper.find('img');
- var placeholder = img.data('placeholder') || '';
+ let $that = $(this),
+ wrapper = $that.closest('.tutor-thumbnail-uploader'),
+ img = wrapper.find('img'),
+ placeholder = img.data('placeholder') || '';
wrapper.find('input[type="hidden"].tutor-tumbnail-id-input').val('');
img.attr('src', placeholder);
-
$that.hide();
+
+ // Enable save button after thumbnail remove.
+ $('#save_tutor_option').prop('disabled', false);
});
});
\ No newline at end of file
From 56a91ae605ba63fa219a65dd4ddc60b7b7b042fe Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Mon, 7 Aug 2023 16:13:27 +0600
Subject: [PATCH 26/78] Missing white space bewteen label and value
---
.../header-context/course-single-previous-attempts.php | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/views/quiz/header-context/course-single-previous-attempts.php b/views/quiz/header-context/course-single-previous-attempts.php
index 98f05dfe35..0dc02487d0 100644
--- a/views/quiz/header-context/course-single-previous-attempts.php
+++ b/views/quiz/header-context/course-single-previous-attempts.php
@@ -26,26 +26,27 @@
+
-
+
:
-
+
:
-
+
:
-
+
:
Date: Mon, 7 Aug 2023 16:14:16 +0600
Subject: [PATCH 27/78] Latex expression inline support
---
assets/scss/front/course-spotlight/index.scss | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/assets/scss/front/course-spotlight/index.scss b/assets/scss/front/course-spotlight/index.scss
index b5aeef4ad9..0d9ad67b6a 100644
--- a/assets/scss/front/course-spotlight/index.scss
+++ b/assets/scss/front/course-spotlight/index.scss
@@ -160,6 +160,14 @@
}
@import './quiz';
}
+
+ /**
+ * Latex disply inline support.
+ * @since 2.2.4
+ */
+ mjx-container, .MathJax_Display {
+ display: inline!important;
+ }
}
@import './spotlight';
From b108f6e79d8de80a67567e3d798e51560b6b25e8 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Tue, 8 Aug 2023 14:57:54 +0600
Subject: [PATCH 28/78] Util helper added to get profile bio config
---
classes/Utils.php | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/classes/Utils.php b/classes/Utils.php
index 2545fa8a13..f8dc07d737 100644
--- a/classes/Utils.php
+++ b/classes/Utils.php
@@ -9060,6 +9060,28 @@ public function text_editor_config( $args = array() ) {
return wp_parse_args( $args, $default_args );
}
+ /**
+ * Get config for profile bio editor.
+ *
+ * @since 2.2.4
+ *
+ * @param string $textarea_name textarea name for post request.
+ *
+ * @return array
+ */
+ public function get_profile_bio_editor_config( $textarea_name = 'tutor_profile_bio' ) {
+ return $this->text_editor_config(
+ array(
+ 'textarea_name' => $textarea_name,
+ 'tinymce' => array(
+ 'toolbar1' => 'bold,italic,underline,blockquote,bullist,numlist,alignleft,aligncenter,alignright,undo,redo,removeformat',
+ 'toolbar2' => '',
+ 'toolbar3' => '',
+ ),
+ )
+ );
+ }
+
/**
* Get video sources.
*
From 848711ba64af6a62dd65506aafaf248c482c50d9 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Tue, 8 Aug 2023 14:58:43 +0600
Subject: [PATCH 29/78] profile bio input kses sanitize
---
classes/Student.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/classes/Student.php b/classes/Student.php
index 29dc4abdb0..7b96f04929 100644
--- a/classes/Student.php
+++ b/classes/Student.php
@@ -194,7 +194,7 @@ public function update_profile() {
$first_name = sanitize_text_field( tutor_utils()->input_old( 'first_name' ) );
$last_name = sanitize_text_field( tutor_utils()->input_old( 'last_name' ) );
$phone_number = sanitize_text_field( tutor_utils()->input_old( 'phone_number' ) );
- $tutor_profile_bio = wp_kses_post( tutor_utils()->input_old( 'tutor_profile_bio' ) );
+ $tutor_profile_bio = Input::post( 'tutor_profile_bio', '', Input::TYPE_KSES_POST );
$tutor_profile_job_title = sanitize_text_field( tutor_utils()->input_old( 'tutor_profile_job_title' ) );
$display_name = sanitize_text_field( tutor_utils()->input_old( 'display_name' ) );
From 45edf203cbedf361e12693e7269fc8f887939c48 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Tue, 8 Aug 2023 14:59:29 +0600
Subject: [PATCH 30/78] Tinymce content post to save profile bio
---
assets/react/front/dashboard/settings/profile.js | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/assets/react/front/dashboard/settings/profile.js b/assets/react/front/dashboard/settings/profile.js
index 14914d9103..26ce1dbed5 100644
--- a/assets/react/front/dashboard/settings/profile.js
+++ b/assets/react/front/dashboard/settings/profile.js
@@ -233,6 +233,15 @@ window.jQuery(document).ready(($) => {
var data = form.serializeObject();
let phone = document.querySelector('[name=phone_number]');
+ /**
+ * Basic markup for profile bio
+ * @since 2.2.4
+ */
+ if (window.tinyMCE !== undefined) {
+ let editor = tinyMCE.get('tutor_profile_bio');
+ data.tutor_profile_bio = editor.getContent({ format: 'html' });
+ }
+
if (data.phone_number && !data.phone_number.match(/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im)) {
phone.classList.add('invalid');
tutor_toast('Invalid', 'Invalid phone number', 'error');
From 03edeb2861f4c6ef804bdc3eece4caadb06b7bb7 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Tue, 8 Aug 2023 15:00:20 +0600
Subject: [PATCH 31/78] basic profile bio editor added to frontend dashboard
---
templates/dashboard/settings/profile.php | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/templates/dashboard/settings/profile.php b/templates/dashboard/settings/profile.php
index a5ed1215e5..414c5f9b46 100644
--- a/templates/dashboard/settings/profile.php
+++ b/templates/dashboard/settings/profile.php
@@ -104,10 +104,10 @@
';
@@ -162,7 +162,10 @@
-
+ ID, '_tutor_profile_bio', true );
+ wp_editor( $profile_bio, 'tutor_profile_bio', tutor_utils()->get_profile_bio_editor_config() );
+ ?>
@@ -174,7 +177,7 @@
$item ) {
+ foreach ( $public_display as $_id => $item ) {
?>
display_name, $item ); ?>>
Date: Tue, 8 Aug 2023 15:00:40 +0600
Subject: [PATCH 32/78] basic profile bio editor added to backend profile
---
views/metabox/user-profile-fields.php | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/views/metabox/user-profile-fields.php b/views/metabox/user-profile-fields.php
index 1ce1b882a3..de0b708ce4 100644
--- a/views/metabox/user-profile-fields.php
+++ b/views/metabox/user-profile-fields.php
@@ -34,13 +34,8 @@
true,
- 'media_buttons' => false,
- 'quicktags' => false,
- 'editor_height' => 200,
- );
- wp_editor( get_user_meta( $user->ID, '_tutor_profile_bio', true ), '_tutor_profile_bio', $settings );
+ $profile_bio = get_user_meta( $user->ID, '_tutor_profile_bio', true );
+ wp_editor( $profile_bio, '_tutor_profile_bio', tutor_utils()->get_profile_bio_editor_config( '_tutor_profile_bio' ) );
?>
From d98a67bd30ba4d8af2452700dbbe80f6b8402aa3 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Fri, 11 Aug 2023 16:26:39 +0600
Subject: [PATCH 33/78] tutor readme update
---
readme.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/readme.txt b/readme.txt
index cc5efc167b..db81173cc5 100644
--- a/readme.txt
+++ b/readme.txt
@@ -3,9 +3,9 @@ Contributors: themeum
Donate link: https://www.themeum.com
Tags: lms, course, elearning, education, learning management system
Requires at least: 5.3
-Tested up to: 6.2
+Tested up to: 6.3
Requires PHP: 7.1
-Stable tag: 2.2.3
+Stable tag: 2.2.4
License: GPLv3
License URI: https://www.gnu.org/licenses/gpl-3.0.html
From 5596dfcb1e9b7d346287ab831754ee13da4d5f05 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Fri, 11 Aug 2023 16:26:59 +0600
Subject: [PATCH 34/78] version update
---
tutor.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tutor.php b/tutor.php
index 4639494fcf..a1b09e585d 100644
--- a/tutor.php
+++ b/tutor.php
@@ -4,10 +4,10 @@
* Plugin URI: https://www.themeum.com/product/tutor-lms/
* 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.
* Author: Themeum
- * Version: 2.2.3
+ * Version: 2.2.4
* Author URI: https://themeum.com
* Requires at least: 5.3
- * Tested up to: 6.2
+ * Tested up to: 6.3
* License: GPLv2 or later
* Text Domain: tutor
*
From ad76742736560c6e8b083db0fbc06ebd0fa5fe02 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Fri, 11 Aug 2023 16:28:16 +0600
Subject: [PATCH 35/78] version update
---
tutor.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tutor.php b/tutor.php
index a1b09e585d..bcd8899aeb 100644
--- a/tutor.php
+++ b/tutor.php
@@ -23,7 +23,7 @@
/**
* Defined the tutor main file
*/
-define( 'TUTOR_VERSION', '2.2.3' );
+define( 'TUTOR_VERSION', '2.2.4' );
define( 'TUTOR_FILE', __FILE__ );
/**
From e1ba1e0d1fdbd4adbbec50ed29ebde4eb7c03c7b Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Thu, 17 Aug 2023 12:39:01 +0600
Subject: [PATCH 36/78] fix - video track info does not save
---
models/LessonModel.php | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/models/LessonModel.php b/models/LessonModel.php
index 4ee499709a..be59869e37 100644
--- a/models/LessonModel.php
+++ b/models/LessonModel.php
@@ -108,10 +108,8 @@ public static function update_lesson_reading_info( $lesson_id = 0, $user_id = 0,
$user_id = tutor_utils()->get_user_id( $user_id );
if ( $key && $value ) {
- $lesson_info = (array) maybe_unserialize( get_user_meta( $user_id, '_lesson_reading_info', true ) );
- if ( isset( $lesson_info[ $lesson_id ][ $key ] ) ) {
- $lesson_info[ $lesson_id ][ $key ] = $value;
- }
+ $lesson_info = (array) maybe_unserialize( get_user_meta( $user_id, '_lesson_reading_info', true ) );
+ $lesson_info[ $lesson_id ][ $key ] = $value;
update_user_meta( $user_id, '_lesson_reading_info', $lesson_info );
}
}
From ca95798c5f43a28ec4c394e7544aaaa15e08ad6d Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Thu, 17 Aug 2023 12:39:40 +0600
Subject: [PATCH 37/78] fix - _lesson_reading_info delete on course progress
delete
---
classes/Utils.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/classes/Utils.php b/classes/Utils.php
index f8dc07d737..43b6e7bb11 100644
--- a/classes/Utils.php
+++ b/classes/Utils.php
@@ -1278,6 +1278,7 @@ function ( $attempt ) {
$lesson_ids = $this->get_course_content_ids_by( tutor()->lesson_post_type, tutor()->course_post_type, $course_id );
foreach ( $lesson_ids as $id ) {
delete_user_meta( $user_id, '_tutor_completed_lesson_id_' . $id );
+ delete_user_meta( $user_id, '_lesson_reading_info' );
}
// Delete other addon-wise stuffs by hook, specially assignment.
From f049ce17b909064c15e361c20463c43e2161a27e Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Thu, 17 Aug 2023 12:55:01 +0600
Subject: [PATCH 38/78] json data added
---
templates/single/lesson/content.php | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/templates/single/lesson/content.php b/templates/single/lesson/content.php
index dd436d1682..f4794644f5 100644
--- a/templates/single/lesson/content.php
+++ b/templates/single/lesson/content.php
@@ -70,7 +70,13 @@
$source_key = is_object( $video_info ) && 'html5' !== $video_info->source ? 'source_' . $video_info->source : null;
$has_source = ( is_object( $video_info ) && $video_info->source_video_id ) || ( isset( $source_key ) ? $video_info->$source_key : null );
?>
-
+ get_option( 'course_completion_process' );
+ $json_data['strict_mode'] = ( 'strict' === $completion_mode );
+ $json_data['control_video_lesson_completion'] = (bool) tutor_utils()->get_option( 'control_video_lesson_completion', false );
+ $json_data['required_percentage'] = tutor_utils()->get_option( 'required_percentage_to_complete_video_lesson', 80 );
+ ?>
From 93a8a627deaff03355d277fa1cc61b16a5a42089 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Thu, 17 Aug 2023 12:58:47 +0600
Subject: [PATCH 39/78] value cast
---
templates/single/lesson/content.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/templates/single/lesson/content.php b/templates/single/lesson/content.php
index f4794644f5..56600b2ea4 100644
--- a/templates/single/lesson/content.php
+++ b/templates/single/lesson/content.php
@@ -75,7 +75,7 @@
$completion_mode = tutor_utils()->get_option( 'course_completion_process' );
$json_data['strict_mode'] = ( 'strict' === $completion_mode );
$json_data['control_video_lesson_completion'] = (bool) tutor_utils()->get_option( 'control_video_lesson_completion', false );
- $json_data['required_percentage'] = tutor_utils()->get_option( 'required_percentage_to_complete_video_lesson', 80 );
+ $json_data['required_percentage'] = (int) tutor_utils()->get_option( 'required_percentage_to_complete_video_lesson', 80 );
?>
From db51b22612c4508e9706a4e5117bde90c3fafa4b Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Thu, 17 Aug 2023 12:59:31 +0600
Subject: [PATCH 40/78] block lesson key added
---
classes/Options_V2.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/classes/Options_V2.php b/classes/Options_V2.php
index 4ab2a0f0a1..e67dc4b5f9 100644
--- a/classes/Options_V2.php
+++ b/classes/Options_V2.php
@@ -702,7 +702,7 @@ public function get_setting_fields() {
),
),
),
- array(
+ 'block_lesson' => array(
'label' => __( 'Lesson', 'tutor' ),
'slug' => 'lesson',
'block_type' => 'uniform',
From 821cf916cfb94d12dfa70da988339c27437f67af Mon Sep 17 00:00:00 2001
From: Sazedul Haque
Date: Fri, 18 Aug 2023 11:02:41 +0600
Subject: [PATCH 41/78] Control video lesson completion functions added to
video player
---
assets/react/front/tutor-front.js | 79 ++++++++++++++++++++++++++---
templates/single/lesson/content.php | 1 +
2 files changed, 72 insertions(+), 8 deletions(-)
diff --git a/assets/react/front/tutor-front.js b/assets/react/front/tutor-front.js
index 06a1edbd4b..6157caaa6d 100644
--- a/assets/react/front/tutor-front.js
+++ b/assets/react/front/tutor-front.js
@@ -136,16 +136,31 @@ jQuery(document).ready(function($) {
track_player: function() {
const that = this;
if (typeof Plyr !== 'undefined') {
- const player = new Plyr(this.player_DOM);
const video_data = that.video_data();
+ const player = new Plyr(this.player_DOM, {
+ keyboard: {
+ focused: that.isRequiredPercentage() ? false : true,
+ global: false,
+ },
+ listeners: {
+ ...(that.isRequiredPercentage() && {
+ seek(e) {
+ e.preventDefault();
+ tutor_toast(__('Warning', 'tutor'), __(`You have to complete ${video_data.required_percentage}% of the lesson.`, 'tutor'), 'error');
+ return false;
+ },
+ }),
+ }
+ });
player.on('ready', function(event) {
const instance = event.detail.plyr;
const { best_watch_time = 0 } = video_data || {};
- if (
- best_watch_time > 0 &&
- instance.duration > Math.round(best_watch_time)
- ) {
- instance.media.currentTime = best_watch_time;
+ if (best_watch_time > 0) {
+ if (instance.provider === 'youtube') {
+ instance.embed.seekTo(best_watch_time);
+ }else {
+ instance.media.currentTime = best_watch_time;
+ }
}
that.sync_time(instance);
});
@@ -182,13 +197,21 @@ jQuery(document).ready(function($) {
}
},
sync_time: function(instance, options) {
- const post_id = this.video_data().post_id;
+ const video_data = this.video_data();
+ if (!video_data) {
+ return;
+ }
+
+ if (this.isRequiredPercentage()) {
+ this.enable_complete_lesson_btn(instance);
+ }
+
//TUTOR is sending about video playback information to server.
let data = {
action: 'sync_video_playback',
currentTime: instance.currentTime,
duration: instance.duration,
- post_id,
+ post_id: video_data.post_id,
};
data[this.nonce_key] = _tutorobject[this.nonce_key];
let data_send = data;
@@ -209,9 +232,49 @@ jQuery(document).ready(function($) {
}
});
},
+ isRequiredPercentage: function() {
+ const video_data = this.video_data();
+ if (!video_data) {
+ return false;
+ }
+
+ const { strict_mode, control_video_lesson_completion } = video_data;
+ if (_tutorobject.tutor_pro_url && strict_mode && control_video_lesson_completion) {
+ return true;
+ }
+ return false;
+ },
+ enable_complete_lesson_btn: function(instance) {
+ const complete_lesson_btn = $('button[name="complete_lesson_btn"]');
+ const video_data = this.video_data();
+ const completedPercentage = (instance.currentTime / instance.duration) * 100;
+
+ if (completedPercentage >= video_data.required_percentage) {
+ complete_lesson_btn.attr('disabled', false);
+ complete_lesson_btn.next().remove();
+ }
+ },
+ disable_complete_lesson_btn: function() {
+ const video_data = this.video_data();
+ if (!video_data) {
+ return;
+ }
+
+ const { best_watch_time, video_duration, required_percentage } = video_data;
+ const completedPercentage = (Number(best_watch_time) / Number(video_duration)) * 100;
+
+ if (completedPercentage < required_percentage) {
+ const complete_lesson_btn = $('button[name="complete_lesson_btn"]');
+ complete_lesson_btn.attr('disabled', true);
+ complete_lesson_btn.wrap('
').after(`You have to complete ${video_data.required_percentage}% of the lesson. `);
+ }
+ },
init: function(element) {
this.player_DOM = element;
this.track_player();
+ if (this.isRequiredPercentage()) {
+ this.disable_complete_lesson_btn();
+ }
},
};
diff --git a/templates/single/lesson/content.php b/templates/single/lesson/content.php
index 56600b2ea4..81e9ba1ad6 100644
--- a/templates/single/lesson/content.php
+++ b/templates/single/lesson/content.php
@@ -76,6 +76,7 @@
$json_data['strict_mode'] = ( 'strict' === $completion_mode );
$json_data['control_video_lesson_completion'] = (bool) tutor_utils()->get_option( 'control_video_lesson_completion', false );
$json_data['required_percentage'] = (int) tutor_utils()->get_option( 'required_percentage_to_complete_video_lesson', 80 );
+ $json_data['video_duration'] = $video_info->duration_sec ?? 0;
?>
From ab94c8436e3ab2d7bfabcdf3b3d279050eca47a7 Mon Sep 17 00:00:00 2001
From: Sazedul Haque
Date: Fri, 18 Aug 2023 12:07:24 +0600
Subject: [PATCH 42/78] Add getPercentage function
---
assets/react/front/tutor-front.js | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/assets/react/front/tutor-front.js b/assets/react/front/tutor-front.js
index 6157caaa6d..f78c56cf31 100644
--- a/assets/react/front/tutor-front.js
+++ b/assets/react/front/tutor-front.js
@@ -247,7 +247,7 @@ jQuery(document).ready(function($) {
enable_complete_lesson_btn: function(instance) {
const complete_lesson_btn = $('button[name="complete_lesson_btn"]');
const video_data = this.video_data();
- const completedPercentage = (instance.currentTime / instance.duration) * 100;
+ const completedPercentage = getPercentage(Number(instance.currentTime), Number(instance.duration));
if (completedPercentage >= video_data.required_percentage) {
complete_lesson_btn.attr('disabled', false);
@@ -261,7 +261,7 @@ jQuery(document).ready(function($) {
}
const { best_watch_time, video_duration, required_percentage } = video_data;
- const completedPercentage = (Number(best_watch_time) / Number(video_duration)) * 100;
+ const completedPercentage = this.getPercentage(Number(best_watch_time), Number(video_duration));
if (completedPercentage < required_percentage) {
const complete_lesson_btn = $('button[name="complete_lesson_btn"]');
@@ -269,6 +269,12 @@ jQuery(document).ready(function($) {
complete_lesson_btn.wrap('
').after(`You have to complete ${video_data.required_percentage}% of the lesson. `);
}
},
+ getPercentage: function(value, total) {
+ if (value > 0 && total > 0) {
+ return Math.round((value / total) * 100);;
+ }
+ return 0;
+ },
init: function(element) {
this.player_DOM = element;
this.track_player();
From 95becc35ca4fd8344df89e9b3f5faa136aa0241b Mon Sep 17 00:00:00 2001
From: Sazedul Haque
Date: Fri, 18 Aug 2023 13:53:52 +0600
Subject: [PATCH 43/78] Fix typos in get percentage function
---
assets/react/front/tutor-front.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/assets/react/front/tutor-front.js b/assets/react/front/tutor-front.js
index f78c56cf31..d11322de5b 100644
--- a/assets/react/front/tutor-front.js
+++ b/assets/react/front/tutor-front.js
@@ -247,7 +247,7 @@ jQuery(document).ready(function($) {
enable_complete_lesson_btn: function(instance) {
const complete_lesson_btn = $('button[name="complete_lesson_btn"]');
const video_data = this.video_data();
- const completedPercentage = getPercentage(Number(instance.currentTime), Number(instance.duration));
+ const completedPercentage = this.getPercentage(Number(instance.currentTime), Number(instance.duration));
if (completedPercentage >= video_data.required_percentage) {
complete_lesson_btn.attr('disabled', false);
@@ -271,7 +271,7 @@ jQuery(document).ready(function($) {
},
getPercentage: function(value, total) {
if (value > 0 && total > 0) {
- return Math.round((value / total) * 100);;
+ return Math.round((value / total) * 100);
}
return 0;
},
From 1ed57c6e5670a52fcb52fb5b5881a4d91989dd1b Mon Sep 17 00:00:00 2001
From: Sazedul Haque
Date: Fri, 18 Aug 2023 15:31:07 +0600
Subject: [PATCH 44/78] Hide youtube information from tutor player videos
---
assets/scss/front/course-spotlight/_players.scss | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/assets/scss/front/course-spotlight/_players.scss b/assets/scss/front/course-spotlight/_players.scss
index 0ef10849c5..0aa59d9912 100644
--- a/assets/scss/front/course-spotlight/_players.scss
+++ b/assets/scss/front/course-spotlight/_players.scss
@@ -51,5 +51,10 @@
height: 100%;
border: none;
}
+
+ .plyr--youtube iframe {
+ top: -50%;
+ height: 200%;
+ }
}
}
From bcbd7848f92922f4090b31bea8e09129a2d903fd Mon Sep 17 00:00:00 2001
From: Sazedul Haque
Date: Fri, 18 Aug 2023 15:31:29 +0600
Subject: [PATCH 45/78] Update warning message
---
assets/react/front/tutor-front.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/assets/react/front/tutor-front.js b/assets/react/front/tutor-front.js
index d11322de5b..cfd953f4cf 100644
--- a/assets/react/front/tutor-front.js
+++ b/assets/react/front/tutor-front.js
@@ -146,7 +146,7 @@ jQuery(document).ready(function($) {
...(that.isRequiredPercentage() && {
seek(e) {
e.preventDefault();
- tutor_toast(__('Warning', 'tutor'), __(`You have to complete ${video_data.required_percentage}% of the lesson.`, 'tutor'), 'error');
+ tutor_toast(__('Warning', 'tutor'), __(`You have to watch ${video_data.required_percentage}% of this video lesson.`, 'tutor'), 'error');
return false;
},
}),
@@ -266,7 +266,7 @@ jQuery(document).ready(function($) {
if (completedPercentage < required_percentage) {
const complete_lesson_btn = $('button[name="complete_lesson_btn"]');
complete_lesson_btn.attr('disabled', true);
- complete_lesson_btn.wrap('
').after(`You have to complete ${video_data.required_percentage}% of the lesson. `);
+ complete_lesson_btn.wrap('
').after(`You have to watch ${video_data.required_percentage}% of this video lesson. `);
}
},
getPercentage: function(value, total) {
From a6d3f61e34a82c9d49dd86d37b0fdd61610a37a0 Mon Sep 17 00:00:00 2001
From: Sazedul Haque
Date: Fri, 18 Aug 2023 15:32:25 +0600
Subject: [PATCH 46/78] Filter hook added to validate lesson completion
---
classes/Lesson.php | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/classes/Lesson.php b/classes/Lesson.php
index bbadce3b4e..9b72290cd8 100644
--- a/classes/Lesson.php
+++ b/classes/Lesson.php
@@ -454,6 +454,15 @@ public function mark_lesson_complete() {
$lesson_id = Input::post( 'lesson_id', 0, Input::TYPE_INT );
+ if ( ! $lesson_id ) {
+ return;
+ }
+
+ $validated = apply_filters( 'tutor_validate_lesson_complete', true, $user_id, $lesson_id );
+ if ( ! $validated ) {
+ return;
+ }
+
do_action( 'tutor_lesson_completed_before', $lesson_id );
/**
* Marking lesson at user meta, meta format, _tutor_completed_lesson_id_{id} and value = tutor_time();
From a437d1919524e912380209b40545e48c1806799a Mon Sep 17 00:00:00 2001
From: Sazedul Haque
Date: Fri, 18 Aug 2023 16:29:36 +0600
Subject: [PATCH 47/78] PHPcbf fix
---
classes/Lesson.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/classes/Lesson.php b/classes/Lesson.php
index 9b72290cd8..c2f203ddf4 100644
--- a/classes/Lesson.php
+++ b/classes/Lesson.php
@@ -458,7 +458,7 @@ public function mark_lesson_complete() {
return;
}
- $validated = apply_filters( 'tutor_validate_lesson_complete', true, $user_id, $lesson_id );
+ $validated = apply_filters( 'tutor_validate_lesson_complete', true, $user_id, $lesson_id );
if ( ! $validated ) {
return;
}
From 804b3816aff4aa066d700e9aea3769366c517c22 Mon Sep 17 00:00:00 2001
From: Sazedul Haque
Date: Fri, 18 Aug 2023 16:50:25 +0600
Subject: [PATCH 48/78] Hide youtube information from all tutor player videos
---
assets/scss/front/course-spotlight/_players.scss | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/assets/scss/front/course-spotlight/_players.scss b/assets/scss/front/course-spotlight/_players.scss
index 0aa59d9912..405d84a8c7 100644
--- a/assets/scss/front/course-spotlight/_players.scss
+++ b/assets/scss/front/course-spotlight/_players.scss
@@ -7,6 +7,11 @@
margin-left: -25px;
}
}
+
+ .plyr--youtube iframe {
+ top: -50%;
+ height: 200%;
+ }
}
.tutor-video-player-wrapper {
@@ -51,10 +56,5 @@
height: 100%;
border: none;
}
-
- .plyr--youtube iframe {
- top: -50%;
- height: 200%;
- }
}
}
From e6180aa9daa440a4430617f03aa4dff2f62199f2 Mon Sep 17 00:00:00 2001
From: Sazedul Haque
Date: Wed, 23 Aug 2023 12:20:40 +0600
Subject: [PATCH 49/78] Fix tutor player design and seeking issue
---
assets/react/front/tutor-front.js | 39 +++++++++++++++----
.../scss/front/course-spotlight/_players.scss | 2 +-
2 files changed, 32 insertions(+), 9 deletions(-)
diff --git a/assets/react/front/tutor-front.js b/assets/react/front/tutor-front.js
index cfd953f4cf..940aa9122a 100644
--- a/assets/react/front/tutor-front.js
+++ b/assets/react/front/tutor-front.js
@@ -145,9 +145,15 @@ jQuery(document).ready(function($) {
listeners: {
...(that.isRequiredPercentage() && {
seek(e) {
- e.preventDefault();
- tutor_toast(__('Warning', 'tutor'), __(`You have to watch ${video_data.required_percentage}% of this video lesson.`, 'tutor'), 'error');
- return false;
+ var currentTime = player.currentTime;
+ var newTime = that.getTargetTime(player, e);
+ // Disallow moving forward
+ if (newTime > currentTime) {
+ e.preventDefault();
+ tutor_toast(__('Warning', 'tutor'), __(`Forward seeking is not allowed for this video lesson.`, 'tutor'), 'error');
+ return false;
+ }
+ return true;
},
}),
}
@@ -156,11 +162,18 @@ jQuery(document).ready(function($) {
const instance = event.detail.plyr;
const { best_watch_time = 0 } = video_data || {};
if (best_watch_time > 0) {
- if (instance.provider === 'youtube') {
- instance.embed.seekTo(best_watch_time);
- }else {
- instance.media.currentTime = best_watch_time;
- }
+ var previous_duration = Math.round(best_watch_time);
+ var previousTimeSetter = setInterval(function(){
+ if (player.playing !== true && player.currentTime != previous_duration) {
+ if (instance.provider === 'youtube') {
+ instance.embed.seekTo(best_watch_time);
+ } else {
+ instance.media.currentTime = previous_duration;
+ }
+ } else{
+ clearInterval(previousTimeSetter);
+ }
+ }, 800);
}
that.sync_time(instance);
});
@@ -275,6 +288,16 @@ jQuery(document).ready(function($) {
}
return 0;
},
+ getTargetTime: function(player, input) {
+ if (
+ typeof input === "object" &&
+ (input.type === "input" || input.type === "change")
+ ) {
+ return input.target.value / input.target.max * player.media.duration;
+ } else {
+ return Number(input);
+ }
+ },
init: function(element) {
this.player_DOM = element;
this.track_player();
diff --git a/assets/scss/front/course-spotlight/_players.scss b/assets/scss/front/course-spotlight/_players.scss
index 405d84a8c7..6a87388e4a 100644
--- a/assets/scss/front/course-spotlight/_players.scss
+++ b/assets/scss/front/course-spotlight/_players.scss
@@ -10,7 +10,7 @@
.plyr--youtube iframe {
top: -50%;
- height: 200%;
+ height: 200%!important;
}
}
From c44871a56b0f2b4a481b5ec7932cb6492d7b7d3c Mon Sep 17 00:00:00 2001
From: Sazedul Haque
Date: Wed, 23 Aug 2023 12:48:29 +0600
Subject: [PATCH 50/78] Use setTimeout instead of setInterval
---
assets/react/front/tutor-front.js | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/assets/react/front/tutor-front.js b/assets/react/front/tutor-front.js
index 940aa9122a..56e9b3f698 100644
--- a/assets/react/front/tutor-front.js
+++ b/assets/react/front/tutor-front.js
@@ -163,17 +163,17 @@ jQuery(document).ready(function($) {
const { best_watch_time = 0 } = video_data || {};
if (best_watch_time > 0) {
var previous_duration = Math.round(best_watch_time);
- var previousTimeSetter = setInterval(function(){
- if (player.playing !== true && player.currentTime != previous_duration) {
+ var previousTimeSetter = setTimeout(function(){
+ if (player.playing !== true && player.currentTime !== previous_duration) {
if (instance.provider === 'youtube') {
instance.embed.seekTo(best_watch_time);
} else {
instance.media.currentTime = previous_duration;
}
- } else{
- clearInterval(previousTimeSetter);
+ } else {
+ clearTimeout(previousTimeSetter);
}
- }, 800);
+ });
}
that.sync_time(instance);
});
From f455a0a6e17af6e6278d5be17fb1c897ccf7f7ef Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Wed, 23 Aug 2023 12:58:48 +0600
Subject: [PATCH 51/78] custom js event register on media selected for tutor
settings
---
assets/react/lib/media-chooser.js | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/assets/react/lib/media-chooser.js b/assets/react/lib/media-chooser.js
index 65c2300ce0..e27dc2b284 100644
--- a/assets/react/lib/media-chooser.js
+++ b/assets/react/lib/media-chooser.js
@@ -39,13 +39,24 @@ window.jQuery(document).ready(function ($) {
multiple: false, // Set to true to allow multiple files to be selected
});
frame.on('select', function () {
- var attachment = frame.state().get('selection').first().toJSON();
+ let attachment = frame.state().get('selection').first().toJSON(),
+ inputEl = wrapper.find('input[type="hidden"].tutor-tumbnail-id-input');
wrapper.find('img').attr('src', attachment.url);
- wrapper.find('input[type="hidden"].tutor-tumbnail-id-input').val(attachment.id);
+ inputEl.val(attachment.id);
wrapper.find('.delete-btn').show();
$('#save_tutor_option').prop('disabled', false);
+
+ document.querySelector('.tutor-option-form .tutor-thumbnail-uploader')
+ .dispatchEvent(new CustomEvent('tutor_settings_media_selected', {
+ detail: {
+ wrapper: wrapper,
+ settingsName: inputEl.attr('name').replace(/.*\[(.*?)\]/, '$1'),
+ attachment: attachment
+ }
+ }));
+
});
frame.open();
});
From 556974ebf19e3342eb4846210b1aa4eb7df37e1a Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Wed, 23 Aug 2023 14:58:32 +0600
Subject: [PATCH 52/78] whats new style
---
assets/scss/admin-dashboard/_tutor-admin.scss | 164 +++++++++++++++++-
1 file changed, 162 insertions(+), 2 deletions(-)
diff --git a/assets/scss/admin-dashboard/_tutor-admin.scss b/assets/scss/admin-dashboard/_tutor-admin.scss
index 253ce1eecc..f9acf47a72 100644
--- a/assets/scss/admin-dashboard/_tutor-admin.scss
+++ b/assets/scss/admin-dashboard/_tutor-admin.scss
@@ -965,8 +965,15 @@ span.filled_dash_unser {
height: auto;
}
-.tutor-get-pro-text {
- color: #e02424;
+a:has(> span.tutor-get-pro-text ) {
+ background-color: orange;
+ font-weight: 600;
+ color: #000 !important;
+
+ &:hover{
+ background-color: orange!important;
+ color: #000 !important;
+ }
}
.updating-icon:before {
@@ -1766,4 +1773,157 @@ h2.tutor-page-heading {
.mce-branding {
display: none;
}
+}
+
+.tutor-pro-badge{
+ background: #e5803c;
+ color: #fff;
+ font-weight: 400;
+ border-radius: 16px;
+ padding: 1px 6px;
+ font-size: 11px;
+ display: inline-block;
+ line-height: 15px;
+}
+
+.tutor-whats-new-wrapper{
+ max-width: 1080px;
+ background-color: white;
+ margin: 25px auto;
+ border-radius: 8px;
+
+ padding: 40px 0;
+
+ .tutor-whats-new-header{
+ text-align: center;
+ background-size: contain;
+ background-repeat: no-repeat;
+ min-height: 200px;
+ border-bottom: 1px solid #f0eaea;
+ position: relative;
+
+ h1{
+ font-size: 40px;
+ font-weight:700;
+ }
+
+ p{
+ font-size: 14px;
+ }
+
+ .tutor-logo-head{
+ position: absolute;
+ left: 0;
+ right: 0;
+ width: 40px;
+ bottom: -40px;
+ margin: 0 auto;
+ background: #FFF;
+ padding: 10px;
+ }
+
+ .tutor-whats-new-header-symbols {
+ position: absolute;
+
+ &.tutor-symbol-left-top {
+ top: 75px;
+ left: 100px;
+ height: 20px;
+ width: 20px;
+ }
+ &.tutor-symbol-left-bottom {
+ width: 60px;
+ left: 0;
+ bottom: 20px;
+ }
+ &.tutor-symbol-right-top {
+ top: 0;
+ right: 0;
+ width: 60px;
+ }
+ &.tutor-symbol-right-bottom {
+ height: 30px;
+ width: 30px;
+ right: 90px;
+ bottom: 60px;
+ }
+
+ }
+
+ @include breakpoint-max(tablet) {
+ h1{
+ font-size: 34px;
+ }
+ }
+
+ @include breakpoint-max(mobile) {
+ h1{
+ font-size: 28px;
+ }
+ }
+ }
+
+ .tutor-changelog-wrapper{
+ width: 75%;
+ margin: 0 auto;
+ margin-top: 100px;
+
+ h4{
+ font-size: 16px;
+ }
+
+ .tutor-changelog-list{
+ list-style: disc;
+ padding-left: 20px;
+ }
+ }
+
+ .tutor-whats-new-pro-section{
+ width: 75%;
+ margin: 0 auto;
+ margin-top: 100px;
+ text-align: center;
+
+ h2{
+ max-width: 50%;
+ margin: 0 auto 40px;
+ font-size: 22px;
+ line-height: 1.3;
+ }
+
+ @include breakpoint-max(992) {
+ h2{
+ max-width: 100%;
+ }
+ }
+
+ .tutor-whats-new-pro-banner{
+ border-radius: 8px;
+ overflow: hidden;
+ display: flex;
+ img{
+ width: 100%;
+ }
+ }
+
+ .tutor-whats-new-action-btn{
+ display: inline-block;
+ font-size: 15px;
+ padding: 10px 30px;
+ background: #0049F8;
+ border-radius: 6px;
+ text-decoration: none;
+ color: #fff;
+ margin-top: 36px;
+ margin-bottom: 30px;
+ &:hover{
+ background: #0b51f3;
+ }
+
+ .tutor-icon-crown {
+ color: #ED9700;
+ margin-right: 5px;
+ }
+ }
+ }
}
\ No newline at end of file
From 614179135575dce00ea76f3dac2c665459643002 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Wed, 23 Aug 2023 14:59:13 +0600
Subject: [PATCH 53/78] Whats new menu added
---
classes/Admin.php | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/classes/Admin.php b/classes/Admin.php
index e936a9692b..27a189340e 100644
--- a/classes/Admin.php
+++ b/classes/Admin.php
@@ -134,11 +134,26 @@ public function register_menu() {
add_submenu_page( 'tutor', __( 'Settings', 'tutor' ), __( 'Settings', 'tutor' ), 'manage_tutor', 'tutor_settings', array( new \TUTOR\Options_V2(), 'load_settings_page' ) );
+ do_action( 'tutor_after_settings_menu' );
+
+ add_submenu_page( 'tutor', __( "What's New", 'tutor' ), __( "What's New", 'tutor' ), 'manage_options', 'tutor-whats-new', array( $this, 'whats_new_page' ) );
+
if ( ! $has_pro ) {
- add_submenu_page( 'tutor', __( 'Get Pro', 'tutor' ), __( ' Get Pro', 'tutor' ), 'manage_options', 'tutor-get-pro', array( $this, 'tutor_get_pro' ) );
+ add_submenu_page( 'tutor', __( 'Upgrade to Pro', 'tutor' ), __( 'Upgrade to Pro ', 'tutor' ), 'manage_options', 'tutor-get-pro', array( $this, 'tutor_get_pro' ) );
}
}
+ /**
+ * What's new page.
+ *
+ * @since 2.2.4
+ *
+ * @return void
+ */
+ public function whats_new_page() {
+ include tutor()->path . 'views/pages/whats-new.php';
+ }
+
/**
* Show Course Bundle Page For Free User.
*
From 78146dde654fc8f40b6aea8e0825714dced0fb1e Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Wed, 23 Aug 2023 14:59:33 +0600
Subject: [PATCH 54/78] Whats new page
---
views/pages/whats-new.php | 170 ++++++++++++++++++++++++++++++++++++++
1 file changed, 170 insertions(+)
create mode 100644 views/pages/whats-new.php
diff --git a/views/pages/whats-new.php b/views/pages/whats-new.php
new file mode 100644
index 0000000000..7bab6edd98
--- /dev/null
+++ b/views/pages/whats-new.php
@@ -0,0 +1,170 @@
+
+ * @link https://themeum.com
+ * @since 2.2.4
+ */
+
+$changelogs = array(
+ 'new' => array(
+ array(
+ 'title' => 'E-mail background image change support added.',
+ 'is_pro' => true,
+ ),
+ array(
+ 'title' => 'Basic editor support for profile bio change.',
+ ),
+ array(
+ 'title' => 'Instructor\'s earning summary on instructor list.',
+ 'is_pro' => true,
+ ),
+ array(
+ 'title' => 'Latex support to lesson and quiz editor.',
+ ),
+ array(
+ 'title' => 'Delete cancelled enrollment from enrollment list.',
+ 'is_pro' => true,
+ ),
+ array(
+ 'title' => 'Private and Schedule filter tab in courses and course bundle listing page.',
+ ),
+ ),
+ 'update' => array(
+ array(
+ 'title' => 'Email address also added to Analytics CSV data along with display name.',
+ ),
+ array(
+ 'title' => 'Remove force password reset form to tutor.',
+ ),
+ ),
+ 'fix' => array(
+ array(
+ 'title' => 'Quiz attempt list showing wrong.',
+ ),
+ array(
+ 'title' => "Some strings aren't translatable.",
+ ),
+ array(
+ 'title' => 'In the Course List page of WP Admin, the Edit menu had design issue.',
+ ),
+ array(
+ 'title' => 'Instructors can make withdrawal requests greater than their available balance.',
+ ),
+ array(
+ 'title' => 'Invalid or no google client ID found for Google login.',
+ ),
+ array(
+ 'title' => 'Course enrollment email to student issue.',
+ ),
+ array(
+ 'title' => 'HTML code appearing on the course details page enrollment box, if user use the Restrict Content Pro.',
+ ),
+ array(
+ 'title' => 'Student can complete course without passing the quiz.',
+ ),
+ ),
+);
+
+function tutor_whatnew_item( $type, $log ) {
+ $obj = (object) $log;
+ ?>
+ : title ); ?>
+ is_pro ) && $obj->is_pro ) :
+ ?>
+ Pro
+
+
+
+
+
+
+
+
+
+
+
+
+ has_pro ) : ?>
+
+
+
You are not only missing these features, you are missing your revenues too!
+
+
+
+
+
+
+ Get Tutor Pro
+
+
+
+
+
+
+
From e60ba85d5f8dcc0c8906010ccab0d5d647e18182 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Wed, 23 Aug 2023 15:37:42 +0600
Subject: [PATCH 55/78] Rearrange addons order
---
classes/Addons.php | 118 ++++++++++++++++++++++-----------------------
1 file changed, 59 insertions(+), 59 deletions(-)
diff --git a/classes/Addons.php b/classes/Addons.php
index 671ebaaeae..3883a92349 100644
--- a/classes/Addons.php
+++ b/classes/Addons.php
@@ -38,89 +38,97 @@ public function __construct() {
*/
public function tutor_addons_lists_to_show() {
$addons = array(
- 'buddypress' => array(
- 'name' => __( 'BuddyPress', 'tutor' ),
- 'description' => 'Discuss about course and share your knowledge with your friends through BuddyPress',
+ 'course-bundle' => array(
+ 'name' => __( 'Course Bundle', 'tutor' ),
+ 'description' => __( 'Group multiple courses to sell together.', 'tutor' ),
),
- 'gradebook' => array(
- 'name' => __( 'Gradebook', 'tutor' ),
- 'description' => 'Shows student progress from assignment and quiz',
+ 'social-login' => array(
+ 'name' => __( 'Social Login', 'tutor' ),
+ 'description' => __( 'Let users register & login through social network like Facebook, Google, etc.', 'tutor' ),
),
'content-drip' => array(
'name' => __( 'Content Drip', 'tutor' ),
'description' => 'Unlock lessons by schedule or when the student meets specific condition.',
),
- 'enrollments' => array(
- 'name' => __( 'Enrollment', 'tutor' ),
- 'description' => 'Take advanced control on enrollment. Enroll the student manually.',
- ),
- 'wc-subscriptions' => array(
- 'name' => __( 'WooCommerce Subscriptions', 'tutor' ),
- 'description' => 'Capture Residual Revenue with Recurring Payments.',
- ),
- 'pmpro' => array(
- 'name' => __( 'Paid Memberships Pro', 'tutor' ),
- 'description' => 'Maximize revenue by selling membership access to all of your courses.',
- ),
- 'restrict-content-pro' => array(
- 'name' => __( 'Restrict Content Pro', 'tutor' ),
- 'description' => 'Unlock Course depending on Restrict Content Pro Plugin Permission.',
+ 'tutor-multi-instructors' => array(
+ 'name' => __( 'Tutor Multi Instructors', 'tutor' ),
+ 'description' => 'Start a course with multiple instructors by Tutor Multi Instructors',
),
'tutor-assignments' => array(
'name' => __( 'Tutor Assignments', 'tutor' ),
'description' => 'Tutor assignments is a great way to assign tasks to students.',
),
- 'tutor-certificate' => array(
- 'name' => __( 'Tutor Certificate', 'tutor' ),
- 'description' => 'Students will be able to download a certificate after course completion.',
+ 'tutor-course-preview' => array(
+ 'name' => __( 'Tutor Course Preview', 'tutor' ),
+ 'description' => 'Unlock some lessons for students before enrollment.',
),
'tutor-course-attachments' => array(
'name' => __( 'Tutor Course Attachments', 'tutor' ),
'description' => 'Add unlimited attachments/ private files to any Tutor course',
),
- 'tutor-course-preview' => array(
- 'name' => __( 'Tutor Course Preview', 'tutor' ),
- 'description' => 'Unlock some lessons for students before enrollment.',
+ 'google-meet' => array(
+ 'name' => __( 'Tutor Google Meet Integration', 'tutor' ),
+ 'description' => __( 'Connect Tutor LMS with Google Meet to host live online classes. Students can attend live classes right from the lesson page.', 'tutor' ),
+ ),
+ 'tutor-report' => array(
+ 'name' => __( 'Tutor Report', 'tutor' ),
+ 'description' => 'Check your course performance through Tutor Report stats.',
),
'tutor-email' => array(
'name' => __( 'Tutor E-Mail', 'tutor' ),
'description' => 'Send email on various tutor events',
),
- 'tutor-multi-instructors' => array(
- 'name' => __( 'Tutor Multi Instructors', 'tutor' ),
- 'description' => 'Start a course with multiple instructors by Tutor Multi Instructors',
+ 'tutor-calendar' => array(
+ 'name' => 'Calendar',
+ 'description' => 'Allow students to see everything in a calendar view in the front dashboard.',
),
- 'tutor-prerequisites' => array(
- 'name' => __( 'Tutor Prerequisites', 'tutor' ),
- 'description' => 'Specific course you must complete before you can enroll new course by Tutor Prerequisites',
+ 'tutor-notifications' => array(
+ 'name' => 'Notifications',
+ 'description' => 'Get On Site and Push Notifications on specified tutor events.',
),
- 'tutor-report' => array(
- 'name' => __( 'Tutor Report', 'tutor' ),
- 'description' => 'Check your course performance through Tutor Report stats.',
+ 'google-classroom' => array(
+ 'name' => __( 'Google Classroom Integration', 'tutor' ),
+ 'description' => __( 'Helps connect Google Classrooms with Tutor LMS courses, allowing you to use features like Classroom streams and files directly from the Tutor LMS course.', 'tutor' ),
+ ),
+ 'tutor-zoom' => array(
+ 'name' => __( 'Tutor Zoom Integration', 'tutor' ),
+ 'description' => __( 'Connect Tutor LMS with Zoom to host live online classes. Students can attend live classes right from the lesson page.', 'tutor' ),
),
'quiz-import-export' => array(
'name' => __( 'Quiz Export/Import', 'tutor' ),
'description' => __( 'Save time by exporting/importing quiz data with easy options.', 'tutor' ),
),
- 'tutor-zoom' => array(
- 'name' => __( 'Tutor Zoom Integration', 'tutor' ),
- 'description' => __( 'Connect Tutor LMS with Zoom to host live online classes. Students can attend live classes right from the lesson page.', 'tutor' ),
+ 'enrollments' => array(
+ 'name' => __( 'Enrollment', 'tutor' ),
+ 'description' => 'Take advanced control on enrollment. Enroll the student manually.',
),
- 'google-meet' => array(
- 'name' => __( 'Tutor Google Meet Integration', 'tutor' ),
- 'description' => __( 'Connect Tutor LMS with Google Meet to host live online classes. Students can attend live classes right from the lesson page.', 'tutor' ),
+ 'tutor-certificate' => array(
+ 'name' => __( 'Tutor Certificate', 'tutor' ),
+ 'description' => 'Students will be able to download a certificate after course completion.',
),
- 'google-classroom' => array(
- 'name' => __( 'Google Classroom Integration', 'tutor' ),
- 'description' => __( 'Helps connect Google Classrooms with Tutor LMS courses, allowing you to use features like Classroom streams and files directly from the Tutor LMS course.', 'tutor' ),
+ 'gradebook' => array(
+ 'name' => __( 'Gradebook', 'tutor' ),
+ 'description' => 'Shows student progress from assignment and quiz',
),
- 'tutor-calendar' => array(
- 'name' => 'Calendar',
- 'description' => 'Allow students to see everything in a calendar view in the front dashboard.',
+ 'tutor-prerequisites' => array(
+ 'name' => __( 'Tutor Prerequisites', 'tutor' ),
+ 'description' => 'Specific course you must complete before you can enroll new course by Tutor Prerequisites',
),
- 'tutor-notifications' => array(
- 'name' => 'Notifications',
- 'description' => 'Get On Site and Push Notifications on specified tutor events.',
+ 'buddypress' => array(
+ 'name' => __( 'BuddyPress', 'tutor' ),
+ 'description' => 'Discuss about course and share your knowledge with your friends through BuddyPress',
+ ),
+ 'wc-subscriptions' => array(
+ 'name' => __( 'WooCommerce Subscriptions', 'tutor' ),
+ 'description' => 'Capture Residual Revenue with Recurring Payments.',
+ ),
+ 'pmpro' => array(
+ 'name' => __( 'Paid Memberships Pro', 'tutor' ),
+ 'description' => 'Maximize revenue by selling membership access to all of your courses.',
+ ),
+ 'restrict-content-pro' => array(
+ 'name' => __( 'Restrict Content Pro', 'tutor' ),
+ 'description' => 'Unlock Course depending on Restrict Content Pro Plugin Permission.',
),
'tutor-weglot' => array(
'name' => 'Weglot',
@@ -130,14 +138,6 @@ public function tutor_addons_lists_to_show() {
'name' => __( 'WPML Multilingual CMS', 'tutor' ),
'description' => __( 'Create multilingual courses, lessons, dashboard and more for a global audience.', 'tutor' ),
),
- 'social-login' => array(
- 'name' => __( 'Social Login', 'tutor' ),
- 'description' => __( 'Let users register & login through social network like Facebook, Google, etc.', 'tutor' ),
- ),
- 'course-bundle' => array(
- 'name' => __( 'Course Bundle', 'tutor' ),
- 'description' => __( 'Group multiple courses to sell together.', 'tutor' ),
- ),
);
return $addons;
From ba5ce3786a8fa327111212c535eaa6aa6e25004d Mon Sep 17 00:00:00 2001
From: Mohammad Ibrahim
Date: Wed, 23 Aug 2023 23:01:47 +0600
Subject: [PATCH 56/78] Update TutorEDD.php
EDD issue fixed
---
classes/TutorEDD.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/classes/TutorEDD.php b/classes/TutorEDD.php
index 8c8bfa2021..60d698a239 100644
--- a/classes/TutorEDD.php
+++ b/classes/TutorEDD.php
@@ -198,7 +198,7 @@ public function tutor_course_sell_by() {
* @return void
*/
public function edd_update_payment_status( $payment_id, $new_status, $old_status ) {
- if ( 'publish' !== $new_status ) {
+ if ( 'complete' !== $new_status ) {
return;
}
From e14c48a4731f36dc44dff36c27efd3b3f99c575a Mon Sep 17 00:00:00 2001
From: Mohammad Ibrahim
Date: Thu, 24 Aug 2023 14:05:22 +0600
Subject: [PATCH 57/78] Update TutorEDD.php
edd not installed shows fatal issue fixed
---
classes/TutorEDD.php | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/classes/TutorEDD.php b/classes/TutorEDD.php
index 60d698a239..8fc1568a68 100644
--- a/classes/TutorEDD.php
+++ b/classes/TutorEDD.php
@@ -173,8 +173,10 @@ public function is_course_purchasable( $bool, $course_id ) {
*/
public function get_tutor_course_price( $price, $course_id ) {
$product_id = tutor_utils()->get_course_product_id( $course_id );
-
- return edd_price( $product_id, false );
+ if( tutils()->has_edd() ){
+ return edd_price( $product_id, false );
+ }
+
}
/**
From 906e5efbfedf1169fc40387e85632188b9c1fe5f Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Thu, 24 Aug 2023 15:17:06 +0600
Subject: [PATCH 58/78] css rules removed
---
assets/scss/front/course-spotlight/_players.scss | 5 -----
1 file changed, 5 deletions(-)
diff --git a/assets/scss/front/course-spotlight/_players.scss b/assets/scss/front/course-spotlight/_players.scss
index 6a87388e4a..0ef10849c5 100644
--- a/assets/scss/front/course-spotlight/_players.scss
+++ b/assets/scss/front/course-spotlight/_players.scss
@@ -7,11 +7,6 @@
margin-left: -25px;
}
}
-
- .plyr--youtube iframe {
- top: -50%;
- height: 200%!important;
- }
}
.tutor-video-player-wrapper {
From a7c99310f8337186bf9384b25235dbfb3d841466 Mon Sep 17 00:00:00 2001
From: Sazedul Haque
Date: Thu, 24 Aug 2023 15:17:24 +0600
Subject: [PATCH 59/78] Update require course complete condition
---
assets/react/front/tutor-front.js | 11 ++++++-----
templates/single/lesson/content.php | 2 ++
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/assets/react/front/tutor-front.js b/assets/react/front/tutor-front.js
index 56e9b3f698..d7edcc6146 100644
--- a/assets/react/front/tutor-front.js
+++ b/assets/react/front/tutor-front.js
@@ -129,6 +129,7 @@ jQuery(document).ready(function($) {
ajaxurl: window._tutorobject.ajaxurl,
nonce_key: window._tutorobject.nonce_key,
played_once: false,
+ max_seek_time: 0,
video_data: function() {
const video_track_data = $('#tutor_video_tracking_information').val();
return video_track_data ? JSON.parse(video_track_data) : {};
@@ -145,10 +146,9 @@ jQuery(document).ready(function($) {
listeners: {
...(that.isRequiredPercentage() && {
seek(e) {
- var currentTime = player.currentTime;
var newTime = that.getTargetTime(player, e);
// Disallow moving forward
- if (newTime > currentTime) {
+ if (newTime > that.max_seek_time) {
e.preventDefault();
tutor_toast(__('Warning', 'tutor'), __(`Forward seeking is not allowed for this video lesson.`, 'tutor'), 'error');
return false;
@@ -161,7 +161,7 @@ jQuery(document).ready(function($) {
player.on('ready', function(event) {
const instance = event.detail.plyr;
const { best_watch_time = 0 } = video_data || {};
- if (best_watch_time > 0) {
+ if (_tutorobject.tutor_pro_url && best_watch_time > 0) {
var previous_duration = Math.round(best_watch_time);
var previousTimeSetter = setTimeout(function(){
if (player.playing !== true && player.currentTime !== previous_duration) {
@@ -232,6 +232,7 @@ jQuery(document).ready(function($) {
data_send = Object.assign(data, options);
}
$.post(this.ajaxurl, data_send);
+ this.max_seek_time = video_data.best_watch_time > instance.currentTime ? video_data.best_watch_time : instance.currentTime;
},
autoload_content: function() {
console.log('Autoloader called');
@@ -251,8 +252,8 @@ jQuery(document).ready(function($) {
return false;
}
- const { strict_mode, control_video_lesson_completion } = video_data;
- if (_tutorobject.tutor_pro_url && strict_mode && control_video_lesson_completion) {
+ const { strict_mode, control_video_lesson_completion, lesson_completed, is_enrolled } = video_data;
+ if (_tutorobject.tutor_pro_url && is_enrolled && !lesson_completed && strict_mode && control_video_lesson_completion) {
return true;
}
return false;
diff --git a/templates/single/lesson/content.php b/templates/single/lesson/content.php
index 81e9ba1ad6..00e060c398 100644
--- a/templates/single/lesson/content.php
+++ b/templates/single/lesson/content.php
@@ -77,6 +77,8 @@
$json_data['control_video_lesson_completion'] = (bool) tutor_utils()->get_option( 'control_video_lesson_completion', false );
$json_data['required_percentage'] = (int) tutor_utils()->get_option( 'required_percentage_to_complete_video_lesson', 80 );
$json_data['video_duration'] = $video_info->duration_sec ?? 0;
+ $json_data['lesson_completed'] = tutor_utils()->is_completed_lesson( $content_id, get_current_user_id() ) !== false;
+ $json_data['is_enrolled'] = tutor_utils()->is_enrolled( $course_id, get_current_user_id() ) !== false;
?>
From 4367edc6582e12ff976c5de7629f23995511632a Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Thu, 24 Aug 2023 15:17:29 +0600
Subject: [PATCH 60/78] whats new menu re-position
---
classes/Admin.php | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/classes/Admin.php b/classes/Admin.php
index 27a189340e..8395110146 100644
--- a/classes/Admin.php
+++ b/classes/Admin.php
@@ -50,6 +50,7 @@ public function __construct() {
// Handle flash toast message for redirect_to util helper.
add_action( 'admin_head', array( new Utils(), 'handle_flash_message' ), 999 );
+ add_action( 'tutor_after_settings_menu', array( $this, 'whats_new_menu' ), 11 );
}
/**
@@ -136,8 +137,6 @@ public function register_menu() {
do_action( 'tutor_after_settings_menu' );
- add_submenu_page( 'tutor', __( "What's New", 'tutor' ), __( "What's New", 'tutor' ), 'manage_options', 'tutor-whats-new', array( $this, 'whats_new_page' ) );
-
if ( ! $has_pro ) {
add_submenu_page( 'tutor', __( 'Upgrade to Pro', 'tutor' ), __( 'Upgrade to Pro ', 'tutor' ), 'manage_options', 'tutor-get-pro', array( $this, 'tutor_get_pro' ) );
}
@@ -150,8 +149,29 @@ public function register_menu() {
*
* @return void
*/
- public function whats_new_page() {
- include tutor()->path . 'views/pages/whats-new.php';
+ public function whats_new_menu() {
+ $plugin_info = tutils()->get_remote_plugin_info();
+ $remote_version = $plugin_info->version ?? TUTOR_VERSION;
+ $installed_version = '1.0.0';
+ // $installed_version = TUTOR_VERSION;
+ $update_required = version_compare( $remote_version, $installed_version, '>' );
+
+
+ $menu_text = __( "What's New", 'tutor' );
+ if ( $update_required ) {
+ $menu_text .= ' 1 ';
+ }
+
+ add_submenu_page(
+ 'tutor',
+ __( "What's New", 'tutor' ),
+ $menu_text,
+ 'manage_options',
+ 'tutor-whats-new',
+ function() use ( $remote_version, $installed_version, $update_required ) {
+ include tutor()->path . 'views/pages/whats-new.php';
+ }
+ );
}
/**
From 5b699836d4690d302a4e9f35fe118ea4bfc7b2bc Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Thu, 24 Aug 2023 15:18:03 +0600
Subject: [PATCH 61/78] Button text changed
---
views/pages/course-bundle.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/views/pages/course-bundle.php b/views/pages/course-bundle.php
index a4a965dfe2..2f2567419d 100644
--- a/views/pages/course-bundle.php
+++ b/views/pages/course-bundle.php
@@ -18,7 +18,7 @@
From 9f7e72850008156418dcf449e399f46c42d8b86a Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Thu, 24 Aug 2023 15:19:09 +0600
Subject: [PATCH 62/78] whats new page css update
---
assets/scss/admin-dashboard/_tutor-admin.scss | 43 ++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/assets/scss/admin-dashboard/_tutor-admin.scss b/assets/scss/admin-dashboard/_tutor-admin.scss
index f9acf47a72..f29a1245a1 100644
--- a/assets/scss/admin-dashboard/_tutor-admin.scss
+++ b/assets/scss/admin-dashboard/_tutor-admin.scss
@@ -1791,8 +1791,49 @@ h2.tutor-page-heading {
background-color: white;
margin: 25px auto;
border-radius: 8px;
+ padding: 0 0 40px 0;
- padding: 40px 0;
+ .tutor-update-available{
+ background: #FFF5E0;
+ margin-bottom: 25px;
+ border-top-left-radius: 8px;
+ border-top-right-radius: 8px;
+ padding: 25px;
+
+ .tutor-version-alert{
+ display: flex;
+ gap: 15px;
+ justify-content: center;
+ align-items: center;
+ margin-bottom: 10px;
+ p{
+ margin: 0;
+ }
+ }
+
+ .tutor-update-version{
+ border-radius: 6px;
+ background-color: #fff;
+ padding: 20px 25px;
+ display: flex;
+ gap: 25px;
+ align-items: center;
+ width: 200px;
+ margin: 0 auto;
+
+ >div:nth-child(2) {
+ h3,p{
+ margin: 0;
+ }
+ p{
+ margin-top: 5px;
+ }
+ a{
+ text-decoration: none;
+ }
+ }
+ }
+ }
.tutor-whats-new-header{
text-align: center;
From 9e047e58b29876960f2985b563e90c94378e6ca9 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Thu, 24 Aug 2023 15:19:56 +0600
Subject: [PATCH 63/78] changelog added
---
views/pages/whats-new.php | 158 ++++++++++++++++++++++++--------------
1 file changed, 99 insertions(+), 59 deletions(-)
diff --git a/views/pages/whats-new.php b/views/pages/whats-new.php
index 7bab6edd98..91a286edbb 100644
--- a/views/pages/whats-new.php
+++ b/views/pages/whats-new.php
@@ -8,66 +8,77 @@
* @since 2.2.4
*/
-$changelogs = array(
- 'new' => array(
- array(
- 'title' => 'E-mail background image change support added.',
+ $changelogs = array(
+ 'new' => array(
+ array(
+ 'title' => 'Option to control when students can skip lessons on Tutor LMS Player',
'is_pro' => true,
- ),
- array(
- 'title' => 'Basic editor support for profile bio change.',
- ),
- array(
- 'title' => 'Instructor\'s earning summary on instructor list.',
+ ),
+ array(
+ 'title' => 'Hide video branding (YouTube) in Tutor LMS Player',
'is_pro' => true,
- ),
- array(
- 'title' => 'Latex support to lesson and quiz editor.',
- ),
- array(
- 'title' => 'Delete cancelled enrollment from enrollment list.',
+ ),
+ array(
+ 'title' => 'Let students resume lessons where they left off (Tutor LMS Player)',
'is_pro' => true,
- ),
- array(
- 'title' => 'Private and Schedule filter tab in courses and course bundle listing page.',
- ),
- ),
- 'update' => array(
- array(
- 'title' => 'Email address also added to Analytics CSV data along with display name.',
- ),
- array(
- 'title' => 'Remove force password reset form to tutor.',
- ),
- ),
- 'fix' => array(
- array(
- 'title' => 'Quiz attempt list showing wrong.',
- ),
- array(
- 'title' => "Some strings aren't translatable.",
- ),
- array(
- 'title' => 'In the Course List page of WP Admin, the Edit menu had design issue.',
- ),
- array(
- 'title' => 'Instructors can make withdrawal requests greater than their available balance.',
- ),
- array(
- 'title' => 'Invalid or no google client ID found for Google login.',
- ),
- array(
- 'title' => 'Course enrollment email to student issue.',
- ),
- array(
- 'title' => 'HTML code appearing on the course details page enrollment box, if user use the Restrict Content Pro.',
- ),
+ ),
+ array(
+ 'title' => 'Option to change background image in email Template',
+ 'is_pro' => true,
+ ),
+ array(
+ 'title' => 'WP editor support on the frontend instructor profile-bio field'
+ ),
+ array(
+ 'title' => "Showcase instructor's earning summary on the instructor list",
+ 'is_pro' => true,
+ ),
+ array(
+ 'title' => 'Latex support to lesson and quiz editor'
+ ),
+ array(
+ 'title' => 'Deletion of canceled enrollment from the enrollment list',
+ 'is_pro' => true,
+ ),
array(
- 'title' => 'Student can complete course without passing the quiz.',
- ),
- ),
+ 'title' => 'Private and Schedule filter tabs in course bundle listing page',
+ 'is_pro' => true,
+ ),
+ array(
+ 'title' => 'Private and Schedule filter tabs in course listing page'
+ ),
+ ),
+ 'update' => array(
+ array(
+ 'title' => 'Email address to Analytics CSV data'
+ ),
+ array(
+ 'title' => 'Tutor LMS password reset form only works for Tutor LMS login page'
+ ),
+ ),
+ 'fix' => array(
+ array(
+ 'title' => 'Incorrect information on the quiz attempt list'
+ ),
+ array(
+ 'title' => 'Instructors making withdrawal requests exceeding available balance'
+ ),
+ array(
+ 'title' => 'Invalid or missing Google client ID for Google login'
+ ),
+ array(
+ 'title' => 'Course enrollment email to students'
+ ),
+ array(
+ 'title' => 'Error on completing a course when the Certificate addon is disabled'
+ ),
+ array(
+ 'title' => 'Several known bugs'
+ ),
+ ),
);
+
function tutor_whatnew_item( $type, $log ) {
$obj = (object) $log;
?>
@@ -84,6 +95,29 @@ function tutor_whatnew_item( $type, $log ) {
+
+
+
+
+
+
+
New version available.
+
+
+
+
+
+
@@ -182,21 +195,32 @@ function tutor_whatnew_item( $type, $log ) {
has_pro ) : ?>
-
-
You are not only missing these features, you are missing your revenues too!
+
+
+
Upgrade to Tutor LMS Pro and Maximize Your Revenue Potential!
-
-
+
+
+
+
-
-
-
+
+
+
Users love Tutor LMS Pro, you will love it too!
-
- Get Tutor LMS Pro
+
+
+
+
+
Get access to plenty of functional addons, useful integrations, new exciting features and much more, so why wait!
+
+
+ Get Tutor LMS Pro
+
+
From 29c1be3c391a5f90c4ac0847749c8d92768e76e2 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Mon, 28 Aug 2023 12:52:17 +0600
Subject: [PATCH 74/78] warning message updated
---
assets/react/front/tutor-front.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/assets/react/front/tutor-front.js b/assets/react/front/tutor-front.js
index b97edb66b9..606b4c17b6 100644
--- a/assets/react/front/tutor-front.js
+++ b/assets/react/front/tutor-front.js
@@ -152,7 +152,7 @@ jQuery(document).ready(function($) {
// Disallow moving forward
if (newTime > max_seek_time) {
e.preventDefault();
- tutor_toast(__('Warning', 'tutor'), __(`Forward seeking is not allowed.`, 'tutor'), 'error');
+ tutor_toast(__('Warning', 'tutor'), __(`Forward seeking is disabled.`, 'tutor'), 'error');
return false;
}
return true;
From c85fc65d68662dd6795539483ca348b4a8f2fd8e Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Mon, 28 Aug 2023 13:05:18 +0600
Subject: [PATCH 75/78] esc_html js helper added
---
assets/react/lib/tutor.js | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/assets/react/lib/tutor.js b/assets/react/lib/tutor.js
index f8a0d9da1c..91f8dfb079 100644
--- a/assets/react/lib/tutor.js
+++ b/assets/react/lib/tutor.js
@@ -432,6 +432,28 @@ window.tutor_toast = function( title, description, type, autoClose = true ) {
}
};
+/**
+ * Escape HTML and return safe HTML
+ *
+ * @since 2.2.4
+ *
+ * @param {string} unsafeText HTML string
+ * @returns string
+ */
+window.tutor_esc_html = function (unsafeText) {
+ let safeHTML = ''
+ let div = document.createElement('div');
+ /**
+ * When set an HTML string to an element's innerText
+ * the browser automatically escapes any HTML tags and
+ * treats the content as plain text.
+ */
+ div.innerText = unsafeText;
+ safeHTML = div.innerHTML;
+ div.remove()
+
+ return safeHTML;
+}
// enable custom selector when modal opens
window.addEventListener('tutor_modal_shown', (e) => {
From d156d6fb59da374f33e0cb1afc88dc1f8a3e3597 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Mon, 28 Aug 2023 13:05:50 +0600
Subject: [PATCH 76/78] fix - xss security on tutor dropdown select
---
assets/react/front/_select_dd_search.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/assets/react/front/_select_dd_search.js b/assets/react/front/_select_dd_search.js
index 4af7f18023..d8cb8219f9 100644
--- a/assets/react/front/_select_dd_search.js
+++ b/assets/react/front/_select_dd_search.js
@@ -143,7 +143,7 @@ window.selectSearchField = (selectElement) => {
Array.from(options).forEach((item) => {
optionsList += `
- ${item.text}
+ ${tutor_esc_html(item.text)}
`;
});
From 6206b1bd78d175d2fb8c06a6b24cdfb11c6030a5 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Mon, 28 Aug 2023 13:32:32 +0600
Subject: [PATCH 77/78] readme changelog updated
---
readme.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/readme.txt b/readme.txt
index e08dbbbb92..f96ea15962 100644
--- a/readme.txt
+++ b/readme.txt
@@ -236,6 +236,7 @@ New: Added instructor’s earning summary on the instructor list.
New: Added Latex support to lesson and quiz editor.
New: Added deletion of canceled enrollment from the enrollment list.
New: Added Private and Schedule filter tabs in courses and course bundle listing page.
+Update: WordPress 6.3 compatibility.
Update: Added email address to Analytics CSV data.
Update: Removed Tutor LMS's force password reset form.
Fix: Fixed issue with displaying incorrect information on the quiz attempt list.
From 578434fd1990f8321ab74029dd0a702c02252de6 Mon Sep 17 00:00:00 2001
From: "Md.Harun-Ur-Rashid"
Date: Mon, 28 Aug 2023 15:02:38 +0600
Subject: [PATCH 78/78] removed tutor_esc_html helper call
---
assets/react/front/_select_dd_search.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/assets/react/front/_select_dd_search.js b/assets/react/front/_select_dd_search.js
index d8cb8219f9..4af7f18023 100644
--- a/assets/react/front/_select_dd_search.js
+++ b/assets/react/front/_select_dd_search.js
@@ -143,7 +143,7 @@ window.selectSearchField = (selectElement) => {
Array.from(options).forEach((item) => {
optionsList += `
- ${tutor_esc_html(item.text)}
+ ${item.text}
`;
});