Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f712f42
Query Optimization
Anindra123 Jun 12, 2026
4a06b47
Merge branch '4.0.0-dev' of https://github.com/themeum/tutor into biv…
Anindra123 Jun 12, 2026
25bd13e
Merge branch '4.0.0-dev' of https://github.com/themeum/tutor into biv…
Anindra123 Jun 15, 2026
867794a
remove student count duplicate queries
Anindra123 Jun 15, 2026
62901e8
duplicate queries for instructor home page
Anindra123 Jun 16, 2026
5c251ca
Merge branch '4.0.0-dev' of https://github.com/themeum/tutor into biv…
Anindra123 Jun 16, 2026
fef2d00
updated get_course_price is getting called two times
Anindra123 Jun 17, 2026
506c81b
student dashboard area duplicate query fixes
Anindra123 Jun 17, 2026
6afc3ed
Merge branch '4.0.0-dev' of https://github.com/themeum/tutor into biv…
Anindra123 Jun 18, 2026
0678d40
Instructor quiz attempt list, analytics and student order invoice dup…
Anindra123 Jun 18, 2026
b2259f3
Fix: tax rate duplicate query on checkout and instructor list admin p…
Anindra123 Jun 19, 2026
5ff43b7
Merge branch '4.0.0-dev' of https://github.com/themeum/tutor into biv…
Anindra123 Jun 22, 2026
757cbbb
Merge branch '4.0.0-dev' into bivas-v4
Anindra123 Jun 22, 2026
96d7bd2
Fix learning area sidebar duplicate query
Anindra123 Jun 22, 2026
350d36a
fix(types): improve config type definitions and assertions
b-l-i-n-d Jun 22, 2026
2ec33df
Merge branch '4.0.0-dev' of https://github.com/themeum/tutor into biv…
Anindra123 Jun 23, 2026
35c9d4c
Fix: My course can be accessed from instructor student view
Anindra123 Jun 24, 2026
cc42349
Merge branch '4.0.0-dev' of https://github.com/themeum/tutor into biv…
Anindra123 Jun 25, 2026
798b8dd
Merge branch '4.0.0-dev' of https://github.com/themeum/tutor into biv…
Anindra123 Jun 25, 2026
89b0062
Merge branch '4.0.0-dev' of https://github.com/themeum/tutor into biv…
Anindra123 Jun 26, 2026
a93b2a6
added reviewed changes
Anindra123 Jun 29, 2026
7016133
added comments and updated code
Anindra123 Jun 29, 2026
33a8735
Merge branch '4.0.0-dev' of https://github.com/themeum/tutor into biv…
Anindra123 Jun 29, 2026
37f4cfe
Merge branch '4.0.0-dev' into bivas-v4
Anindra123 Jul 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions classes/Instructors_List.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
tutor_utils()->checking_nonce();

// Check if user is privileged.
if ( ! current_user_can( 'administrator' ) ) {

Check failure on line 153 in classes/Instructors_List.php

View workflow job for this annotation

GitHub Actions / WPCS

Capabilities should be used instead of roles. Found "administrator" in function call to current_user_can()
wp_send_json_error( tutor_utils()->error_message() );
}

Expand Down Expand Up @@ -384,16 +384,8 @@

$query = "SELECT
DISTINCT user.*,
ins_status.meta_value AS status,
(
SELECT
COUNT(*)
FROM {$wpdb->posts}
WHERE post_author = user.ID
AND post_type = 'courses'
) total_courses
ins_status.meta_value AS status
FROM {$wpdb->users} AS user

INNER JOIN {$wpdb->usermeta} AS ins_status
ON ( user.ID = ins_status.user_id )
AND ins_status.meta_key = '_tutor_instructor_status'
Expand Down
25 changes: 12 additions & 13 deletions classes/Quiz_Attempts_List.php
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ public function tabs_key_value( $user_id, $course_id, $date, $search ): array {
*
* @since 4.0.0
*
* @param int $quiz_attempts_count the quiz attempt count.
* @param string $url the url.
* @param string $result_filter the current result state.
* @param string $search_filter the search filter.
Expand All @@ -249,24 +248,24 @@ public function tabs_key_value( $user_id, $course_id, $date, $search ): array {
*
* @return array
*/
public function get_quiz_attempts_nav_data( $quiz_attempts_count = 0, $url = '', $result_filter = '', $search_filter = '', $course_filter = 0, $start_date = '', $end_date = '', $order_filter = 'DESC', $all_quizzes = array() ): array {
public function get_quiz_attempts_nav_data( $url = '', $result_filter = '', $search_filter = '', $course_filter = 0, $start_date = '', $end_date = '', $order_filter = 'DESC', $all_quizzes = array() ): array {
$quiz_model = new QuizModel();

if ( tutor_utils()->count( $all_quizzes ) ) {
$results = isset( $all_quizzes['results'] ) ? $all_quizzes['results'] : array();
$all_attempts = isset( $all_quizzes['total_count'] ) ? $all_quizzes['total_count'] : 0;
$quiz_attempts_count = $all_attempts;
$passed_attempts = count( $quiz_model->get_formatted_quiz_attempt_list_by_quiz_id( $results, QuizModel::RESULT_PASS ) );
$failed_attempts = count( $quiz_model->get_formatted_quiz_attempt_list_by_quiz_id( $results, QuizModel::RESULT_FAIL ) );
$pending_attempts = count( $quiz_model->get_formatted_quiz_attempt_list_by_quiz_id( $results, QuizModel::RESULT_PENDING ) );
$results = isset( $all_quizzes['results'] ) ? $all_quizzes['results'] : array();
$all_attempts = isset( $all_quizzes['total_count'] ) ? $all_quizzes['total_count'] : 0;
$passed_attempts = count( $quiz_model->get_formatted_quiz_attempt_list_by_quiz_id( $results, QuizModel::RESULT_PASS ) );
$failed_attempts = count( $quiz_model->get_formatted_quiz_attempt_list_by_quiz_id( $results, QuizModel::RESULT_FAIL ) );
$pending_attempts = count( $quiz_model->get_formatted_quiz_attempt_list_by_quiz_id( $results, QuizModel::RESULT_PENDING ) );
} else {
$all_attempts = QuizModel::get_quiz_attempts( 0, 0, $search_filter, $course_filter > 0 ? $course_filter : '', $start_date, $end_date, $order_filter, '', true, true );
$pending_attempts = QuizModel::get_quiz_attempts( 0, 0, $search_filter, $course_filter > 0 ? $course_filter : '', $start_date, $end_date, $order_filter, QuizModel::RESULT_PENDING, true, true );
$passed_attempts = QuizModel::get_quiz_attempts( 0, 0, $search_filter, $course_filter > 0 ? $course_filter : '', $start_date, $end_date, $order_filter, QuizModel::RESULT_PASS, true, true );
$failed_attempts = QuizModel::get_quiz_attempts( 0, 0, $search_filter, $course_filter > 0 ? $course_filter : '', $start_date, $end_date, $order_filter, QuizModel::RESULT_FAIL, true, true );
$all_attempts = (int) QuizModel::get_quiz_attempts( 0, 0, $search_filter, $course_filter > 0 ? $course_filter : '', $start_date, $end_date, $order_filter, '', true, true );
$pending_attempts = (int) QuizModel::get_quiz_attempts( 0, 0, $search_filter, $course_filter > 0 ? $course_filter : '', $start_date, $end_date, $order_filter, QuizModel::RESULT_PENDING, true, true );
$passed_attempts = (int) QuizModel::get_quiz_attempts( 0, 0, $search_filter, $course_filter > 0 ? $course_filter : '', $start_date, $end_date, $order_filter, QuizModel::RESULT_PASS, true, true );
$failed_attempts = (int) QuizModel::get_quiz_attempts( 0, 0, $search_filter, $course_filter > 0 ? $course_filter : '', $start_date, $end_date, $order_filter, QuizModel::RESULT_FAIL, true, true );
}

$filter_url = remove_query_arg( 'current_page', $url );
$quiz_attempts_count = array_sum( array( $passed_attempts, $failed_attempts, $pending_attempts ) );
$filter_url = remove_query_arg( 'current_page', $url );

$nav_links = array(
'type' => 'dropdown',
Expand Down
100 changes: 84 additions & 16 deletions classes/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -1300,7 +1300,7 @@
$user_id = $this->get_user_id( $user_id );

// Delete Quiz submissions.
$attempts = \Tutor\Models\QuizModel::get_quiz_attempts_by_course_ids( $start = 0, $limit = 99999999, $course_ids = array( $course_id ), $search_filter = '', $course_filter = '', $date_filter = '', $order_filter = '', $user_id = $user_id, false, true );

Check failure on line 1303 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Assignments must be the first block of code on a line

if ( is_array( $attempts ) ) {
$attempt_ids = array_map(
Expand Down Expand Up @@ -1470,22 +1470,31 @@
$course_id = $this->get_post_id( $course_id );
$user_id = get_current_user_id();

$lessons = $wpdb->get_results(
$wpdb->prepare(
"SELECT items.ID
$course_first_lesson_cache_key = 'tutor_course_first_lesson_' . $course_id . '_' . $post_type;
$cache = TutorCache::get( $course_first_lesson_cache_key );

if ( false === $cache ) {
$lessons = $wpdb->get_results(
$wpdb->prepare(
"SELECT items.ID
FROM {$wpdb->posts} topic
INNER JOIN {$wpdb->posts} items
ON topic.ID = items.post_parent
WHERE topic.post_parent = %d
AND items.post_status = %s
" . ( $post_type ? " AND items.post_type='{$post_type}' " : '' ) . '

Check failure on line 1485 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb->prepare(); found :

Check failure on line 1485 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb->prepare(); found interpolated variable {$post_type} at " AND items.post_type='{$post_type}' "

Check failure on line 1485 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb->prepare(); found ?

Check failure on line 1485 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb->prepare(); found $post_type
ORDER BY topic.menu_order ASC,
items.menu_order ASC;
',
$course_id,
'publish'
)
);
$course_id,
'publish'
)
);

TutorCache::set( $course_first_lesson_cache_key, $lessons );
} else {
$lessons = $cache;
}

$first_lesson = false;

Expand Down Expand Up @@ -2019,11 +2028,11 @@
ON user.ID = posts.post_author
WHERE posts.post_type = %s
AND posts.post_status = %s
{$course_query}

Check failure on line 2031 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb->prepare(); found interpolated variable {$course_query} at {$course_query}

{$date_query}

Check failure on line 2032 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb->prepare(); found interpolated variable {$date_query} at {$date_query}

AND (user.display_name LIKE %s OR user.user_email = %s OR user.user_login LIKE %s)
GROUP BY post_author
{$order_query}

Check failure on line 2035 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb->prepare(); found interpolated variable {$order_query} at {$order_query}

LIMIT %d, %d
",
'tutor_enrolled',
Expand Down Expand Up @@ -2078,7 +2087,7 @@
ON user.ID = posts.post_author
WHERE posts.post_type = %s
AND posts.post_status = %s
{$course_query}

Check failure on line 2090 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb->prepare(); found interpolated variable {$course_query} at {$course_query}

{$date_query}
AND (user.display_name LIKE %s OR user.user_email = %s OR user.user_login LIKE %s)
GROUP BY user.ID
Expand Down Expand Up @@ -2121,6 +2130,12 @@
);
}

$cache_key = 'tutor_completed_courses_ids_by_user_' . $user_id;
$cache = TutorCache::get( $cache_key );
if ( false !== $cache ) {
return $cache;
}

$course_ids = (array) $wpdb->get_col(
$wpdb->prepare(
"SELECT comment_post_ID AS course_id
Expand All @@ -2143,6 +2158,8 @@
)
);

TutorCache::set( $cache_key, $course_ids );

return $course_ids;
}

Expand Down Expand Up @@ -2174,6 +2191,12 @@
);
}

$cache_key = 'tutor_enrolled_courses_ids_by_user_' . $user_id . '_bundle_' . $with_bundle_enrolled_courses;
$cached = TutorCache::get( $cache_key );
if ( false !== $cached ) {
return $cached;
}

$course_ids = $wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT e.post_parent, e.post_date
Expand All @@ -2190,6 +2213,8 @@
)
);

TutorCache::set( $cache_key, (array) $course_ids );

return $course_ids;
}

Expand Down Expand Up @@ -3271,15 +3296,23 @@

$course_post_type = tutor()->course_post_type;
$enrollment_date_clause = '';
$cache_key = __FUNCTION__ . "_{$instructor_id}";

if ( ! empty( $args['from'] ) && ! empty( $args['to'] ) ) {
$from = Input::sanitize( $args['from'] );
$to = Input::sanitize( $args['to'] );

$cache_key .= "_{$from}_{$to}";

$where['enrollment.post_date'] = array( 'BETWEEN', array( $from, $to ) );
$enrollment_date_clause = ' AND ' . QueryHelper::prepare_where_clause( $where );
}

$cached = TutorCache::get( $cache_key );
if ( false !== $cached ) {
return $cached;
}

$count = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(DISTINCT(enrollment.post_author))
Expand All @@ -3300,6 +3333,8 @@
)
);

TutorCache::set( $cache_key, $count );

return (int) $count;
}

Expand Down Expand Up @@ -3500,9 +3535,16 @@
*/
public function get_completed_assignment( int $course_id, int $student_id ): int {
global $wpdb;

$course_id = sanitize_text_field( $course_id );
$student_id = sanitize_text_field( $student_id );
$count = $wpdb->get_var(
$cache_key = __FUNCTION__ . "_{$course_id}_{$student_id}";
$cached = TutorCache::get( $cache_key );
if ( false !== $cached ) {
return $cached;
}

$count = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT( DISTINCT ID ) FROM {$wpdb->posts}
INNER JOIN {$wpdb->comments} c ON c.comment_post_ID = ID AND c.user_id = %d AND c.comment_approved = %s
Expand All @@ -3519,6 +3561,8 @@
'publish'
)
);

TutorCache::set( $cache_key, (int) $count );
return (int) $count;
}

Expand All @@ -3536,7 +3580,13 @@
global $wpdb;
$course_id = sanitize_text_field( $course_id );
$student_id = sanitize_text_field( $student_id );
$count = $wpdb->get_var(
$cache_key = __FUNCTION__ . "_{$course_id}_{$student_id}";
$cached = TutorCache::get( $cache_key );
if ( false !== $cached ) {
return $cached;
}

$count = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(DISTINCT quiz_id) AS total
FROM {$wpdb->prefix}tutor_quiz_attempts
Expand All @@ -3549,6 +3599,8 @@
'attempt_ended'
)
);

TutorCache::set( $cache_key, (int) $count );
return (int) $count;
}

Expand Down Expand Up @@ -7281,6 +7333,11 @@
*/
public function get_single_comment_user_post_id( $post_id, $user_id ) {
global $wpdb;
$cache_key = __FUNCTION__ . "_{$post_id}_{$user_id}";
$cached = TutorCache::get( $cache_key );
if ( false !== $cached ) {
return $cached;
}
$table = $wpdb->prefix . 'comments';
$query = $wpdb->get_row(
$wpdb->prepare(
Expand All @@ -7294,6 +7351,8 @@
$user_id
)
);

TutorCache::set( $cache_key, $query );
return $query ? $query : false;
}

Expand Down Expand Up @@ -8477,17 +8536,26 @@
// Sanitize data.
$user_id = sanitize_text_field( $user_id );
$quiz_id = sanitize_text_field( $quiz_id );
$cache_key = 'tutor_has_attempted_quiz_' . $user_id . '_' . $quiz_id;
$cache = TutorCache::get( $cache_key );

if ( false !== $cache ) {
return $cache ? true : false;
}

$attempted = $wpdb->get_row(
$wpdb->prepare(
"SELECT quiz_id
FROM {$wpdb->tutor_quiz_attempts}
WHERE user_id = %d
AND quiz_id = %d
",
AND quiz_id = %d",
$user_id,
$quiz_id
)
);

TutorCache::set( $cache_key, $attempted );

return $attempted ? true : false;
}

Expand Down Expand Up @@ -9269,7 +9337,7 @@
if ( 0 === $s ) {
$r = $g = $b = $l; //phpcs:ignore
} else {
$hue2rgb = function( $p, $q, $t ) {
$hue2rgb = function ( $p, $q, $t ) {
if ( $t < 0 ) {
++$t;
}
Expand Down Expand Up @@ -9298,9 +9366,9 @@

/**
* Get brand color
*
*
* @since 4.0.0
*
*
* @return string
*/
public function get_brand_color() {
Expand All @@ -9310,9 +9378,9 @@

/**
* Get default brand color
*
*
* @since 4.0.0
*
*
* @return string
*/
public function get_default_brand_color() {
Expand Down
2 changes: 1 addition & 1 deletion ecommerce/CheckoutController.php
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ public function prepare_checkout_items( $item_ids, $order_type = OrderModel::TYP

$should_calculate_tax = Tax::should_calculate_tax();
$tax_included = Tax::is_tax_included_in_price();
$tax_rate = Tax::get_user_tax_rate();
$tax_rate = $should_calculate_tax ? Tax::get_user_tax_rate() : 0;

// Keep calculated price for each item.
foreach ( $items as $item ) {
Expand Down
Loading
Loading