2222use Tutor \Models \QuizModel ;
2323use Tutor \Helpers \HttpHelper ;
2424use Tutor \Models \CourseModel ;
25+ use Tutor \Components \Tooltip ;
2526use Tutor \Ecommerce \Ecommerce ;
2627use Tutor \Helpers \DateTimeHelper ;
2728use Tutor \Traits \JsonResponse ;
2829use Tutor \Helpers \ValidationHelper ;
2930use Tutor \Models \EnrollmentModel ;
3031use Tutor \Options_V2 ;
32+ use TUTOR_ASSIGNMENTS \Assignments ;
3133
3234/**
3335 * Course Class
@@ -1833,7 +1835,7 @@ private function save_course_content_order( $sort_order = array() ) {
18331835
18341836 $ i = 0 ;
18351837 foreach ( $ sort_order as $ topic ) {
1836- $ i ++ ;
1838+ ++ $ i ;
18371839 $ wpdb ->update (
18381840 $ wpdb ->posts ,
18391841 array ( 'menu_order ' => $ i ),
@@ -2879,116 +2881,116 @@ public function remove_price_if_enrolled( $html ) {
28792881 }
28802882
28812883 /**
2882- * Check if all lessons and quizzes done before mark course complete .
2884+ * Get course completion missing requirements message .
28832885 *
2884- * @since 1.5.8
2886+ * @since 4.0.0
28852887 *
2886- * @param string $html HTML string.
2887- * @return string
2888+ * @param int $course_id Course ID.
2889+ * @param int $user_id User ID.
2890+ *
2891+ * @return string|null
28882892 */
2889- public function tutor_lms_hide_course_complete_btn ( $ html ) {
2893+ public static function get_course_completion_restrict_msg ( $ course_id = 0 , $ user_id = 0 ) {
2894+ $ course_id = tutor_utils ()->get_post_id ( $ course_id );
2895+ $ user_id = tutor_utils ()->get_user_id ( $ user_id );
28902896
2891- $ completion_mode = tutor_utils ()->get_option ( 'course_completion_process ' );
2892- if ( 'strict ' !== $ completion_mode ) {
2893- return $ html ;
2897+ if ( 'strict ' !== tutor_utils ()->get_option ( 'course_completion_process ' ) ) {
2898+ return null ;
28942899 }
28952900
2896- $ completed_lesson = tutor_utils ()->get_completed_lesson_count_by_course ();
2897- $ lesson_count = tutor_utils ()->get_lesson_count_by_course ();
2901+ $ completed_lessons = tutor_utils ()->get_completed_lesson_count_by_course ( $ course_id , $ user_id );
2902+ $ total_lessons = tutor_utils ()->get_lesson_count_by_course ( $ course_id );
28982903
2899- if ( $ completed_lesson < $ lesson_count ) {
2900- return '<div class="tutor-alert tutor-warning tutor-mt-28">
2901- <div class="tutor-alert-text">
2902- <span class="tutor-alert-icon tutor-fs-4 tutor-icon-circle-info tutor-mr-12"></span>
2903- <span> ' . __ ( 'Complete all lessons to mark this course as complete ' , 'tutor ' ) . '</span>
2904- </div>
2905- </div> ' ;
2904+ if ( $ completed_lessons < $ total_lessons ) {
2905+ return __ ( 'Complete all lessons to mark this course as complete ' , 'tutor ' );
29062906 }
29072907
2908- $ quizzes = array ();
2909- $ assignments = array ();
2910-
2911- $ course_contents = tutor_utils ()->get_course_contents_by_id ();
2912- if ( tutor_utils ()->count ( $ course_contents ) ) {
2913- foreach ( $ course_contents as $ content ) {
2914- if ( 'tutor_quiz ' === $ content ->post_type ) {
2915- $ quizzes [] = $ content ;
2916- }
2917- if ( 'tutor_assignments ' === $ content ->post_type ) {
2918- $ assignments [] = $ content ;
2919- }
2920- }
2921- }
2908+ $ course_contents = tutor_utils ()->get_course_contents_by_id ( $ course_id );
29222909
2923- $ required_assignment_pass = 0 ;
2910+ $ required_quiz_pass_count = 0 ;
2911+ $ required_assignment_pass_count = 0 ;
29242912
2925- foreach ( $ assignments as $ row ) {
2913+ $ is_assignment_addon_enabled = tutor_utils ()-> is_addon_enabled ( ' tutor- assignments' );
29262914
2927- $ assignment_submission = tutor_utils ()->is_assignment_submitted ( $ row ->ID );
2928- $ is_reviewed_by_instructor = ! count ( $ assignment_submission )
2929- ? false
2930- : get_comment_meta ( $ assignment_submission [0 ]->comment_ID , 'evaluate_time ' , true );
2915+ foreach ( $ course_contents as $ content ) {
29312916
2932- if ( $ assignment_submission && $ is_reviewed_by_instructor ) {
2933- $ pass_mark = tutor_utils ()->get_assignment_option ( $ row ->ID , 'pass_mark ' );
2934- $ has_passed = false ;
2935- foreach ( $ assignment_submission as $ submission ) {
2936- $ given_mark = (int ) get_comment_meta ( $ submission ->comment_ID , 'assignment_mark ' , true );
2937- if ( $ given_mark >= $ pass_mark ) {
2938- $ has_passed = true ;
2939- break ;
2940- }
2917+ if ( tutor ()->quiz_post_type === $ content ->post_type ) {
2918+ if ( ! QuizModel::is_quiz_passed ( $ content ->ID , $ user_id ) ) {
2919+ ++$ required_quiz_pass_count ;
29412920 }
2942- if ( ! $ has_passed ) {
2943- $ required_assignment_pass ++;
2921+ }
2922+
2923+ if ( $ is_assignment_addon_enabled && tutor ()->assignment_post_type === $ content ->post_type ) {
2924+ if ( ! Assignments::is_assignment_passed ( $ content ->ID , $ user_id ) ) {
2925+ ++$ required_assignment_pass_count ;
29442926 }
2945- } else {
2946- $ required_assignment_pass ++;
29472927 }
29482928 }
29492929
2950- $ is_quiz_pass = true ;
2951- $ required_quiz_pass = 0 ;
2930+ if ( ! $ required_quiz_pass_count && ! $ required_assignment_pass_count ) {
2931+ return null ;
2932+ }
29522933
2953- if ( tutor_utils ()->count ( $ quizzes ) ) {
2954- foreach ( $ quizzes as $ quiz ) {
2934+ return self ::get_course_completion_requirement_message (
2935+ $ required_quiz_pass_count ,
2936+ $ required_assignment_pass_count
2937+ );
2938+ }
29552939
2956- $ attempt = tutor_utils ()->get_quiz_attempt ( $ quiz ->ID );
2957- if ( $ attempt ) {
2958- $ passing_grade = tutor_utils ()->get_quiz_option ( $ quiz ->ID , 'passing_grade ' , 0 );
2959- $ earned_percentage = QuizModel::calculate_attempt_earned_percentage ( $ attempt );
2940+ /**
2941+ * Build missing course completion requirements message.
2942+ *
2943+ * @since 4.0.0
2944+ *
2945+ * @param int $quiz_count Total quiz count.
2946+ * @param int $assignment_count Total assignment count.
2947+ *
2948+ * @return string
2949+ */
2950+ private static function get_course_completion_requirement_message ( $ quiz_count , $ assignment_count ) {
2951+ $ quiz_label = _n ( 'quiz ' , 'quizzes ' , $ quiz_count , 'tutor ' );
2952+ $ assignment_label = _n ( 'assignment ' , 'assignments ' , $ assignment_count , 'tutor ' );
29602953
2961- if ( $ earned_percentage < $ passing_grade ) {
2962- $ required_quiz_pass ++;
2963- $ is_quiz_pass = false ;
2964- }
2965- } else {
2966- $ required_quiz_pass ++;
2967- $ is_quiz_pass = false ;
2968- }
2969- }
2954+ if ( $ quiz_count && ! $ assignment_count ) {
2955+ return sprintf (
2956+ /* translators: %1$s: quiz count; %2$s: quiz label */
2957+ __ ( 'You have to pass %1$s %2$s to complete this course. ' , 'tutor ' ),
2958+ $ quiz_count ,
2959+ $ quiz_label
2960+ );
29702961 }
29712962
2972- if ( ! $ is_quiz_pass || $ required_assignment_pass > 0 ) {
2973- $ _msg = '' ;
2974- $ quiz_str = _n ( 'quiz ' , 'quizzes ' , $ required_quiz_pass , 'tutor ' );
2975- $ assignment_str = _n ( 'assignment ' , 'assignments ' , $ required_assignment_pass , 'tutor ' );
2976-
2977- if ( ! $ is_quiz_pass && 0 == $ required_assignment_pass ) {
2978- /* translators: %1$s: number of quiz/assignment pass required; %2$s: quiz/assignment string */
2979- $ _msg = sprintf ( __ ( 'You have to pass %1$s %2$s to complete this course. ' , 'tutor ' ), $ required_quiz_pass , $ quiz_str );
2980- }
2963+ if ( ! $ quiz_count && $ assignment_count ) {
2964+ return sprintf (
2965+ /* translators: %1$s: assignment count; %2$s: assignment label */
2966+ __ ( 'You have to pass %1$s %2$s to complete this course. ' , 'tutor ' ),
2967+ $ assignment_count ,
2968+ $ assignment_label
2969+ );
2970+ }
29812971
2982- if ( $ is_quiz_pass && $ required_assignment_pass > 0 ) {
2983- //phpcs:ignore
2984- $ _msg = sprintf ( __ ( 'You have to pass %1$s %2$s to complete this course. ' , 'tutor ' ), $ required_assignment_pass , $ assignment_str );
2985- }
2972+ return sprintf (
2973+ /* translators: %1$s: quiz count; %2$s: quiz label; %3$s: assignment count; %4$s: assignment label */
2974+ __ ( 'You have to pass %1$s %2$s and %3$s %4$s to complete this course. ' , 'tutor ' ),
2975+ $ quiz_count ,
2976+ $ quiz_label ,
2977+ $ assignment_count ,
2978+ $ assignment_label
2979+ );
2980+ }
29862981
2987- if ( ! $ is_quiz_pass && $ required_assignment_pass > 0 ) {
2988- /* translators: %1$s: number of quiz pass required; %2$s: quiz string; %3$s: number of assignment pass required; %4$s: assignment string */
2989- $ _msg = sprintf ( __ ( 'You have to pass %1$s %2$s and %3$s %4$s to complete this course. ' , 'tutor ' ), $ required_quiz_pass , $ quiz_str , $ required_assignment_pass , $ assignment_str );
2990- }
2982+ /**
2983+ * Check if all lessons and quizzes done before mark course complete.
2984+ *
2985+ * @since 1.5.8
2986+ *
2987+ * @param string $html HTML string.
2988+ * @return string
2989+ */
2990+ public function tutor_lms_hide_course_complete_btn ( $ html ) {
2991+ $ _msg = self ::get_course_completion_restrict_msg ();
29912992
2993+ if ( $ _msg ) {
29922994 return '<div class="tutor-alert tutor-warning tutor-mt-28">
29932995 <div class="tutor-alert-text">
29942996 <span class="tutor-alert-icon tutor-fs-4 tutor-icon-circle-info tutor-mr-12"></span>
@@ -3511,17 +3513,24 @@ public static function get_complete_modal_content( float $course_progress = 0 ):
35113513 * @param int $course_id The ID of the course.
35123514 * @param float $course_progress The current completion percentage of the course.
35133515 * @param string $size The button size.
3516+ * @param string $tooltip Optional. Tooltip message.
3517+ * @param bool $block Optional. Whether the button is full-width.
35143518 *
35153519 * @return void
35163520 */
3517- public static function render_course_complete_btn ( string $ modal_id , int $ course_id , float $ course_progress = 0 , string $ size = Size::MEDIUM ): void {
3521+ public static function render_course_complete_btn ( string $ modal_id , int $ course_id , float $ course_progress = 0 , string $ size = Size::MEDIUM , string $ tooltip = '' , bool $ block = false ): void {
35183522 $ button = Button::make ()
35193523 ->variant ( Variant::PRIMARY_SOFT )
35203524 ->label ( __ ( 'Complete the Course ' , 'tutor ' ) )
35213525 ->icon ( Icon::TICK_MARK )
35223526 ->size ( $ size )
3527+ ->block ( $ block )
35233528 ->attr ( 'type ' , 'button ' );
35243529
3530+ if ( ! empty ( $ tooltip ) ) {
3531+ $ button ->disabled ();
3532+ }
3533+
35253534 if ( $ course_progress < 100 ) {
35263535 $ button ->attr ( '@click ' , "TutorCore.modal.showModal(' {$ modal_id }') " );
35273536 } else {
@@ -3530,7 +3539,16 @@ public static function render_course_complete_btn( string $modal_id, int $course
35303539 $ button ->attr ( ':disabled ' , 'courseCompleteMutation?.isPending ' );
35313540 }
35323541
3533- $ button ->render ();
3542+ if ( ! empty ( $ tooltip ) ) {
3543+ Tooltip::make ()
3544+ ->content ( $ tooltip )
3545+ ->placement ( Tooltip::PLACEMENT_BOTTOM )
3546+ ->arrow ( Tooltip::ARROW_CENTER )
3547+ ->trigger_element ( $ button ->get () )
3548+ ->render ();
3549+ } else {
3550+ $ button ->render ();
3551+ }
35343552 }
35353553
35363554 /**
@@ -3540,15 +3558,17 @@ public static function render_course_complete_btn( string $modal_id, int $course
35403558 *
35413559 * @param string $modal_id Modal id.
35423560 * @param string $size The button size.
3561+ * @param bool $block Optional. Whether the button is full-width.
35433562 *
35443563 * @return void
35453564 */
3546- public static function render_course_retake_btn ( string $ modal_id , string $ size = Size::MEDIUM ): void {
3565+ public static function render_course_retake_btn ( string $ modal_id , string $ size = Size::MEDIUM , bool $ block = false ): void {
35473566 Button::make ()
35483567 ->variant ( Variant::PRIMARY_SOFT )
35493568 ->label ( __ ( 'Retake this Course ' , 'tutor ' ) )
35503569 ->icon ( Icon::RELOAD_4 )
35513570 ->size ( $ size )
3571+ ->block ( $ block )
35523572 ->attr ( 'type ' , 'button ' )
35533573 ->attr ( '@click ' , "TutorCore.modal.showModal(' {$ modal_id }') " )
35543574 ->render ();
0 commit comments