Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Course autocomplete now sync with frontend and backend actions and review progress link generate #585

Merged
merged 14 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
34 changes: 11 additions & 23 deletions classes/Course.php
Original file line number Diff line number Diff line change
Expand Up @@ -845,48 +845,36 @@ public function mark_course_complete() {
* Set data for review popup.
*
* @since 2.2.5
* @since 2.4.0 removed $permalink param. store user meta instead of option data.
*
* @param int $user_id user id.
* @param int $course_id course id.
* @param string $permalink course permalink.
* @param int $user_id user id.
* @param int $course_id course id.
*
* @return void
*/
public static function set_review_popup_data( $user_id, $course_id, $permalink ) {
public static function set_review_popup_data( $user_id, $course_id ) {
if ( get_tutor_option( 'enable_course_review' ) ) {
$rating = tutor_utils()->get_course_rating_by_user( $course_id, $user_id );
if ( ! $rating || ( empty( $rating->rating ) && empty( $rating->review ) ) ) {
update_option(
'tutor_course_complete_popup_' . $user_id,
array(
'course_id' => $course_id,
'course_url' => $permalink,
'expires' => time() + 10,
)
);
add_user_meta( $user_id, User::REVIEW_POPUP_META, $course_id );
}
}
}

/**
* Popup review form
* Popup review form on course details
*
* @since 1.0.0
* @return void
*/
public function popup_review_form() {
if ( is_user_logged_in() ) {
$key = 'tutor_course_complete_popup_' . get_current_user_id();
$popup = get_option( $key );

if ( is_array( $popup ) ) {

if ( $popup['expires'] > time() ) {
$course_id = $popup['course_id'];
include tutor()->path . 'views/modal/review.php';
}
$user_id = get_current_user_id();
$course_id = (int) get_user_meta( $user_id, User::REVIEW_POPUP_META, true );

delete_option( $key );
if ( is_single() && get_the_ID() === $course_id ) {
include tutor()->path . 'views/modal/review.php';
delete_user_meta( $user_id, User::REVIEW_POPUP_META, $course_id );
}
}
}
Expand Down
23 changes: 23 additions & 0 deletions classes/Frontend.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

namespace TUTOR;

use Tutor\Models\CourseModel;

if ( ! defined( 'ABSPATH' ) ) {
exit;
}
Expand All @@ -34,6 +36,27 @@ public function __construct() {

// Handle flash toast message for redirect_to util helper.
add_action( 'wp_head', array( new Utils(), 'handle_flash_message' ), 999 );

add_action( 'tutor_course/single/before/wrap', array( $this, 'do_auto_course_complete' ) );
}

/**
* Do auto course complete on course details page.
*
* @return void
*/
public function do_auto_course_complete() {
if ( ! is_user_logged_in() ) {
return;
}

$course_id = get_the_ID();
$user_id = get_current_user_id();

if ( CourseModel::can_autocomplete_course( $course_id, $user_id ) ) {
CourseModel::mark_course_as_completed( $course_id, $user_id );
Course::set_review_popup_data( $user_id, $course_id );
}
}

/**
Expand Down
20 changes: 20 additions & 0 deletions classes/Quiz.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ public function __construct() {
* @since 2.1.0
*/
add_action( 'wp_ajax_tutor_attempt_delete', array( $this, 'attempt_delete' ) );

add_action( 'tutor_quiz/answer/review/after', array( $this, 'do_auto_course_complete' ), 10, 3 );
}

/**
Expand Down Expand Up @@ -799,6 +801,24 @@ public function review_quiz_answer() {
wp_send_json_success( array( 'html' => ob_get_clean() ) );
}

/**
* Do auto course complete after review a quiz attempt.
*
* @since 2.4.0
*
* @param int $attempt_answer_id attempt answer id.
* @param int $course_id course id.
* @param int $user_id student id.
*
* @return void
*/
public function do_auto_course_complete( $attempt_answer_id, $course_id, $user_id ) {
if ( CourseModel::can_autocomplete_course( $course_id, $user_id ) ) {
CourseModel::mark_course_as_completed( $course_id, $user_id );
Course::set_review_popup_data( $user_id, $course_id );
}
}

/**
* Save single quiz into database and send html response
*
Expand Down
6 changes: 4 additions & 2 deletions classes/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class User {
const INSTRUCTOR = 'tutor_instructor';
const ADMIN = 'administrator';

const REVIEW_POPUP_META = 'tutor_review_course_popup';

/**
* Registration notice
*
Expand Down Expand Up @@ -128,7 +130,7 @@ public static function is_admin() {
* @since 2.2.0
*
* @param bool $is_approved instructor is approved or not.
*
*
* @return boolean
*/
public static function is_instructor( $is_approved = true ) {
Expand Down Expand Up @@ -269,7 +271,7 @@ public function update_user_photo() {
* @return void
*/
public function profile_update( $user_id ) {
if ( tutor_utils()->array_get( 'tutor_action', $_POST ) !== 'tutor_profile_update_by_wp' ) {
if ( 'tutor_profile_update_by_wp' !== Input::post( 'tutor_action' ) ) {
return;
}

Expand Down
20 changes: 11 additions & 9 deletions classes/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,7 @@
"SELECT count(umeta_id)
FROM {$wpdb->usermeta}
WHERE user_id = %d
AND meta_key IN ('{$in_ids}')

Check failure on line 793 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb->prepare(); found interpolated variable $in_ids at AND meta_key IN ('{$in_ids}')

",
$user_id
)
Expand Down Expand Up @@ -883,7 +883,7 @@
WHERE comment_type = %s
AND comment_approved = %s
AND user_id = %d
AND comment_post_ID IN({$assignment_ids_str});

Check failure on line 886 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb->prepare(); found interpolated variable $assignment_ids_str at AND comment_post_ID IN({$assignment_ids_str});

",
'tutor_assignment',
'submitted',
Expand Down Expand Up @@ -1254,7 +1254,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 1257 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 @@ -1390,7 +1390,7 @@
* @since 1.0.0
* @since 1.4.8 Legacy Supports Added.
*
* @param int $lesson_id
* @param int $lesson_id lesson id.
*
* @return bool|mixed
*/
Expand All @@ -1413,7 +1413,8 @@
*
* @since 1.0.0
*
* @param int $course_id course ID.
* @param int $course_id course ID.
* @param mixed $post_type post type.
*
* @return bool|false|string
*/
Expand All @@ -1431,7 +1432,7 @@
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 1435 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

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

Check failure on line 1435 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

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

Check failure on line 1435 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 1435 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb->prepare(); found :
ORDER BY topic.menu_order ASC,
items.menu_order ASC;
',
Expand Down Expand Up @@ -1489,7 +1490,7 @@
* @param int $post_id post ID.
* @param array $video_data video data.
*
* @return bool
* @return void
*/
public function update_video( $post_id = 0, $video_data = array() ) {
$post_id = $this->get_post_id( $post_id );
Expand Down Expand Up @@ -1590,19 +1591,19 @@
}

/**
* return seconds to formatted playtime
* Return seconds to formatted playtime.
*
* @since 1.0.0
*
* @param $seconds seconds.
* @param int $seconds seconds.
*
* @return string
*/
public function playtime_string( $seconds ) {
$sign = ( ( $seconds < 0 ) ? '-' : '' );
$seconds = round( abs( $seconds ) );
$H = (int) floor( $seconds / 3600 );

Check failure on line 1605 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Variable &quot;$H&quot; is not in valid snake_case format, try &quot;$h&quot;
$M = (int) floor( ( $seconds - ( 3600 * $H ) ) / 60 );

Check failure on line 1606 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Variable &quot;$M&quot; is not in valid snake_case format, try &quot;$m&quot;

Check failure on line 1606 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Variable &quot;$H&quot; is not in valid snake_case format, try &quot;$h&quot;
$S = (int) round( $seconds - ( 3600 * $H ) - ( 60 * $M ) );
return $sign . ( $H ? $H . ':' : '' ) . ( $H ? str_pad( $M, 2, '0', STR_PAD_LEFT ) : intval( $M ) ) . ':' . str_pad( $S, 2, 0, STR_PAD_LEFT );
}
Expand All @@ -1612,7 +1613,7 @@
*
* @since 1.0.0
*
* @param $seconds seconds.
* @param int $seconds seconds.
*
* @return array
*/
Expand Down Expand Up @@ -1648,7 +1649,7 @@
*
* @since 1.0.0
*
* @param $seconds seconds.
* @param int $seconds seconds.
*
* @return string
*/
Expand Down Expand Up @@ -7137,7 +7138,7 @@
*
* @since 1.4.9
*
* @param int $course_id course id.
* @param int $content_id content id.
*
* @return array|null|object
*/
Expand Down Expand Up @@ -7442,7 +7443,8 @@
*
* @since 1.7.5
*
* @param int $course_id course id.
* @param int $course_or_product_id course or product id.
* @param bool $is_product_id is product id or not.
*
* @return bool
*/
Expand Down
74 changes: 74 additions & 0 deletions models/CourseModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -652,4 +652,78 @@ public static function can_complete_course( $course_id, $user_id ) {
return false;

}

/**
* Check a course can be auto complete by an enrolled student.
*
* @since 2.4.0
*
* @param int $course_id course id.
* @param int $user_id user id.
*
* @return boolean
*/
public static function can_autocomplete_course( $course_id, $user_id ) {
$auto_course_complete_option = (bool) tutor_utils()->get_option( 'auto_course_complete_on_all_lesson_completion' );
if ( ! $auto_course_complete_option ) {
return false;
}

$is_course_completed = tutor_utils()->is_completed_course( $course_id, $user_id );
if ( $is_course_completed ) {
return false;
}

$course_stats = tutor_utils()->get_course_completed_percent( $course_id, $user_id, true );
if ( $course_stats['completed_count'] === $course_stats['total_count'] ) {
return self::can_complete_course( $course_id, $user_id );
} else {
return false;
}
}

/**
* Get review progress link when course progress 100% and
* User has pending or fail quiz or assignment
*
* @since 2.4.0
*
* @param int $course_id course id.
* @param int $user_id user id.
*
* @return string course content permalink.
*/
public static function get_review_progress_link( $course_id, $user_id ) {
$course_progress = tutor_utils()->get_course_completed_percent( $course_id, $user_id, true );
$completed_percent = (int) $course_progress['completed_percent'];
$course_contents = tutor_utils()->get_course_contents_by_id( $course_id );
$permalink = '';

if ( tutor_utils()->count( $course_contents ) && 100 === $completed_percent ) {
foreach ( $course_contents as $content ) {
if ( 'tutor_quiz' === $content->post_type ) {
$result = QuizModel::get_quiz_result( $content->ID, $user_id );
if ( 'pass' !== $result ) {
$permalink = get_the_permalink( $content->ID );
break;
}
}

if ( tutor()->has_pro && 'tutor_assignments' === $content->post_type ) {
$result = \TUTOR_ASSIGNMENTS\Assignments::get_assignment_result( $content->ID, $user_id );
if ( 'pass' !== $result ) {
$permalink = get_the_permalink( $content->ID );
break;
}
}
}
}

// Fallback link.
if ( empty( $permalink ) ) {
$permalink = tutils()->get_course_first_lesson( $course_id );
}

return $permalink;
}
}
33 changes: 17 additions & 16 deletions templates/loop/course-continue.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,24 @@

if ( $lesson_url && ! $is_completed_course ) {
ob_start();
$link_text = __( 'Continue Learning', 'tutor' );
if ( 0 === (int) $completed_percent ) {
$link_text = __( 'Start Learning', 'tutor' );
} elseif ( $completed_percent > 0 && $completed_percent < 100 ) {
$link_text = __( 'Continue Learning', 'tutor' );
} elseif ( 100 === (int) $completed_percent && false === $can_complete_course ) {
$lesson_url = CourseModel::get_review_progress_link( $course_id, $user_id );
$link_text = __( 'Review Progress', 'tutor' );
} else {
$link_text = __( 'Continue Learning', 'tutor' );
}
?>
<a href="<?php echo esc_url( $lesson_url ); ?>" class="<?php echo esc_attr( $button_class ); ?>" data-course_id="<?php echo get_the_ID(); ?>">
<?php
if ( ! $is_completed_course ) {
if ( 0 === (int) $completed_percent ) {
esc_html_e( 'Start Learning', 'tutor' );
} elseif ( $completed_percent > 0 && $completed_percent < 100 ) {
esc_html_e( 'Continue Learning', 'tutor' );
} elseif ( 100 === (int) $completed_percent && false === $can_complete_course ) {
esc_html_e( 'Review Progress', 'tutor' );
} else {
esc_html_e( 'Continue Learning', 'tutor' );
}
}
?>
</a>
<?php
<a href="<?php echo esc_url( $lesson_url ); ?>"
class="<?php echo esc_attr( $button_class ); ?>"
data-course_id="<?php echo get_the_ID(); ?>">
<?php echo esc_html( $link_text ); ?>
</a>
<?php
$enroll_btn = ob_get_clean();
}

Expand Down
Loading
Loading