3

I am working on Leandash Project , Now my requirement is some students have completed the course offline , So I have created a screen for a group leader in which the group leader can select group/user/course and also add date like this ( https://prnt.sc/1bfcq3a ) and can mark complete COURSE.

So my question is how do I mark complete COURSE. programmatically on link click.

here is my code , which is not working

jQuery(document).on('click', '.course_complete_save', function(event) {
    event.preventDefault();

    var selected_group_id = jQuery('#group_name_select_dropdown').val();
    var selected_user_id = jQuery('#user_name_select_dropdown').val();
    var selected_course_id = jQuery('#course_name_select_dropdown').val();
    var mark_complete_date = jQuery('#input_date_field').val();

    var params =  {"mark_complete_date":mark_complete_date,"selected_group_id":selected_group_id,"selected_user_id":selected_user_id,"selected_course_id":selected_course_id,action:"mark_complete_course_ajax"}

    jQuery.post(groupcustomisation.ajaxurl,params,function(data){
        if(data){
            jQuery(".mark_complete_success").empty().append("Mark Completed");
        }else{
            jQuery(".mark_complete_success").empty().append("No data Found");
        }

    });
});


<?php 
add_action('wp_ajax_nopriv_mark_complete_course_ajax', 'mark_complete_course_ajax');
add_action('wp_ajax_mark_complete_course_ajax', 'mark_complete_course_ajax');
function mark_complete_course_ajax() {

    $selected_group_id = $_POST['selected_group_id'];
    $selected_user_id = $_POST['selected_user_id'];
    $selected_course_id = $_POST['selected_course_id'];
    $mark_complete_date = $_POST['mark_complete_date'];

    learndash_process_mark_complete( $selected_user_id, $selected_course_id, true, $selected_course_id );
        
    echo "1";
         
    die();
}
Parthavi Patel
  • 739
  • 11
  • 28

1 Answers1

3

Funny enough, i found myself needing solution to same problem minutes after you posted this yesterday and as you see, that function above failed to work and nothing useful online. In short, i spent the whole day on it trying to find why until i realized all lessons and quiz need to be marked as complete too and after writing the function that do exactly this based on my research on learndash source code as primary source, i decided to come back here and post the function just incase you haven't fix it

Usage: sci_learndash_mark_course_complete($course_id, $user_id)

Here's the function:

/**
 * Mark learndash course as complete.
 *
 * @param int $id Course ID.
 * @param int $user_id User ID.
 */
function sci_learndash_mark_course_complete($id, $user_id)
{


    //retreive current course progress
    $user_progress['course'][$id] = learndash_user_get_course_progress($user_id, $id, 'legacy');

    if (isset($user_progress['course'][$id]['lessons'])) {

        //update lessons progress to complete
        $lesson_array                            = $user_progress['course'][$id]['lessons'];
        $lessons                                 = array_flip($lesson_array);
        $lessons                                 = array_fill_keys(array_keys($lesson_array), 1);
        $user_progress['course'][$id]['lessons'] = $lessons;

    }


    //update topics progress to complete
    if (isset($user_progress['course'][$id]['topics'])) {
        foreach($user_progress['course'][$id]['topics'] as $ldtopic_key => $ldtopic){
            if(count($ldtopic) > 0){
                $new_ldtopic                                 = array_flip($ldtopic);
                $new_ldtopic                                 = array_fill_keys(array_keys($ldtopic), 1);
                $user_progress['course'][$id]['topics'][$ldtopic_key] = $new_ldtopic;
            }
        }
    
    }

    //update quiz progress to complete
    if (isset($user_progress['quiz'][$id])) {
        $quiz_array                           = $user_progress['course'][$id]['quiz'];
        $quiz                                 = array_flip($quiz_array);
        $quiz                                 = array_fill_keys(array_keys($quiz_array), 1);
        $user_progress['course'][$id]['quiz'] = $quiz;
    }else{
        $quiz_list = [];
        if ( isset($user_progress['course'][$id]['lessons'])  && count($user_progress['course'][$id]['lessons']) > 0 ) {
            $ld_lesson_keys = array_keys($user_progress['course'][$id]['lessons']);
            foreach($ld_lesson_keys as $course_lesson_id){
                    $topic_quizzes = learndash_get_lesson_quiz_list( $course_lesson_id );
                    if (!empty($topic_quizzes)){
                        foreach ($topic_quizzes as $topic_quiz) {
                            $quiz_list[$topic_quiz['post']->ID] = 1;
                        }
                    }
            }
        }
        if (!empty($quiz_list)){
            $user_progress['quiz'][$id] = $quiz_list;
        }
    }

    $processed_course_ids = [];

    if ((isset($user_progress['course'])) && (!empty($user_progress['course']))) {

        $usermeta        = get_user_meta($user_id, '_sfwd-course_progress', true);
        $course_progress = empty($usermeta) ? [] : $usermeta;

        $course_changed = false; // Simple flag to let us know we changed the quiz data so we can save it back to user meta.

        foreach ($user_progress['course'] as $course_id => $course_data_new) {

            $processed_course_ids[intval($course_id)] = intval($course_id);

            if (isset($course_progress[$course_id])) {
                $course_data_old = $course_progress[$course_id];
            } else {
                $course_data_old = [];
            }

            $course_data_new = learndash_course_item_to_activity_sync($user_id, $course_id, $course_data_new,
                $course_data_old);

            $course_progress[$course_id] = $course_data_new;

            $course_changed = true;
        }

        if (true === $course_changed) {
            update_user_meta($user_id, '_sfwd-course_progress', $course_progress);
        }
    }

    
    if ((isset($user_progress['quiz'])) && (!empty($user_progress['quiz']))) {

        $usermeta       = get_user_meta($user_id, '_sfwd-quizzes', true);
        $quizz_progress = empty($usermeta) ? [] : $usermeta;
        $quiz_changed   = false; // Simple flag to let us know we changed the quiz data so we can save it back to user meta.

        foreach ($user_progress['quiz'] as $course_id => $course_quiz_set) {
            foreach ($course_quiz_set as $quiz_id => $quiz_new_status) {
                $quiz_meta = get_post_meta($quiz_id, '_sfwd-quiz', true);

                if (!empty($quiz_meta)) {
                    $quiz_old_status = !learndash_is_quiz_notcomplete($user_id, [$quiz_id => 1], false, $course_id);

                    // For Quiz if the admin marks a qiz complete we don't attempt to update an existing attempt for the user quiz.
                    // Instead we add a new entry. LD doesn't care as it will take the complete one for calculations where needed.
                    if ((bool)true === (bool)$quiz_new_status) {
                        if ((bool)true !== (bool)$quiz_old_status) {

                            if (isset($quiz_meta['sfwd-quiz_lesson'])) {
                                $lesson_id = absint($quiz_meta['sfwd-quiz_lesson']);
                            } else {
                                $lesson_id = 0;
                            }

                            if (isset($quiz_meta['sfwd-quiz_topic'])) {
                                $topic_id = absint($quiz_meta['sfwd-quiz_topic']);
                            } else {
                                $topic_id = 0;
                            }

                            // If the admin is marking the quiz complete AND the quiz is NOT already complete...
                            // Then we add the minimal quiz data to the user profile.
                            $quizdata = [
                                'quiz'                => $quiz_id,
                                'score'               => 0,
                                'count'               => 0,
                                'question_show_count' => 0,
                                'pass'                => true,
                                'rank'                => '-',
                                'time'                => time(),
                                'pro_quizid'          => absint($quiz_meta['sfwd-quiz_quiz_pro']),
                                'course'              => $course_id,
                                'lesson'              => $lesson_id,
                                'topic'               => $topic_id,
                                'points'              => 0,
                                'total_points'        => 0,
                                'percentage'          => 0,
                                'timespent'           => 0,
                                'has_graded'          => false,
                                'statistic_ref_id'    => 0,
                                'm_edit_by'           => get_current_user_id(), // Manual Edit By ID.
                                'm_edit_time'         => time(), // Manual Edit timestamp.
                            ];

                            $quizz_progress[] = $quizdata;

                            if (true === $quizdata['pass']) {
                                $quizdata_pass = true;
                            } else {
                                $quizdata_pass = false;
                            }

                            // Then we add the quiz entry to the activity database.
                            learndash_update_user_activity(
                                [
                                    'course_id'          => $course_id,
                                    'user_id'            => $user_id,
                                    'post_id'            => $quiz_id,
                                    'activity_type'      => 'quiz',
                                    'activity_action'    => 'insert',
                                    'activity_status'    => $quizdata_pass,
                                    'activity_started'   => $quizdata['time'],
                                    'activity_completed' => $quizdata['time'],
                                    'activity_meta'      => $quizdata,
                                ]
                            );

                            $quiz_changed = true;

                            if ((isset($quizdata['course'])) && (!empty($quizdata['course']))) {
                                $quizdata['course'] = get_post($quizdata['course']);
                            }

                            if ((isset($quizdata['lesson'])) && (!empty($quizdata['lesson']))) {
                                $quizdata['lesson'] = get_post($quizdata['lesson']);
                            }

                            if ((isset($quizdata['topic'])) && (!empty($quizdata['topic']))) {
                                $quizdata['topic'] = get_post($quizdata['topic']);
                            }

                            /**
                             * Fires after the quiz is marked as complete.
                             *
                             * @param arrat $quizdata An array of quiz data.
                             * @param WP_User $user WP_User object.
                             */
                            do_action('learndash_quiz_completed', $quizdata, get_user_by('ID', $user_id));

                        }
                    } elseif (true !== $quiz_new_status) {
                        // If we are unsetting a quiz ( changing from complete to incomplete). We need to do some complicated things...
                        if (true === $quiz_old_status) {

                            if (!empty($quizz_progress)) {
                                foreach ($quizz_progress as $quiz_idx => $quiz_item) {

                                    if (($quiz_item['quiz'] == $quiz_id) && (true === $quiz_item['pass'])) {
                                        $quizz_progress[$quiz_idx]['pass'] = false;

                                        // We need to update the activity database records for this quiz_id
                                        $activity_query_args = [
                                            'post_ids'      => $quiz_id,
                                            'user_ids'      => $user_id,
                                            'activity_type' => 'quiz',
                                        ];
                                        $quiz_activity       = learndash_reports_get_activity($activity_query_args);
                                        if ((isset($quiz_activity['results'])) && (!empty($quiz_activity['results']))) {
                                            foreach ($quiz_activity['results'] as $result) {
                                                if ((isset($result->activity_meta['pass'])) && (true === $result->activity_meta['pass'])) {

                                                    // If the activity meta 'pass' element is set to true we want to update it to false.
                                                    learndash_update_user_activity_meta($result->activity_id, 'pass',
                                                        false);

                                                    // Also we need to update the 'activity_status' for this record
                                                    learndash_update_user_activity(
                                                        [
                                                            'activity_id'     => $result->activity_id,
                                                            'course_id'       => $course_id,
                                                            'user_id'         => $user_id,
                                                            'post_id'         => $quiz_id,
                                                            'activity_type'   => 'quiz',
                                                            'activity_action' => 'update',
                                                            'activity_status' => false,
                                                        ]
                                                    );
                                                }
                                            }
                                        }

                                        $quiz_changed = true;
                                    }

                                    /**
                                     * Remove the quiz lock.
                                     *
                                     * @since 2.3.1
                                     */
                                    if ((isset($quiz_item['pro_quizid'])) && (!empty($quiz_item['pro_quizid']))) {
                                        learndash_remove_user_quiz_locks($user_id, $quiz_item['quiz']);
                                    }
                                }
                            }
                        }
                    }

                    $processed_course_ids[intval($course_id)] = intval($course_id);
                }
            }
        }

        if (true === $quiz_changed) {
            update_user_meta($user_id, '_sfwd-quizzes', $quizz_progress);
        }
    }

    if (!empty($processed_course_ids)) {
        foreach (array_unique($processed_course_ids) as $course_id) {
            learndash_process_mark_complete($user_id, $course_id);
            learndash_update_group_course_user_progress($course_id, $user_id);
        }
    }
}
  • Hi @olawale-adesina So what I need to do here is , instead of calling this function `learndash_process_mark_complete` , I need to use this function `sci_learndash_mark_course_complete` and pass `$course_id` and `$user_id` right ? – Parthavi Patel Jul 15 '21 at 13:09
  • Hi @olawale-adesina I have used this function , but it only mark complete LESSON ( https://prnt.sc/1bfhljl ) , not even topics and NOT WHOLE COURSE – Parthavi Patel Jul 15 '21 at 13:16
  • Place the new function in your child theme or plugin and after then, replace `learndash_process_mark_complete( $selected_user_id, $selected_course_id, true, $selected_course_id );` with `sci_learndash_mark_course_complete($course_id, $user_id)` and make sure to pass $course_id and $user_id alone @ParthaviPatel – Olawale Adesina Jul 15 '21 at 14:21
  • I did that , but it only mark complete LESSON as complete : https://prnt.sc/1bfhljl – Parthavi Patel Jul 15 '21 at 14:30
  • ...send screenshot of your application/source code – Olawale Adesina Jul 15 '21 at 14:33
  • See it only mark complete this : https://prnt.sc/1bfhljl I want something like this : https://prnt.sc/1bfyhst – Parthavi Patel Jul 15 '21 at 14:34
  • See this : 1) Network parameters : https://prnt.sc/1bfzwxr 2) Passing static for now : https://prnt.sc/1bg096c 3) Result : https://prnt.sc/1bfhljl – Parthavi Patel Jul 15 '21 at 14:46
  • I've seen the problem, give me 2 minutes to update it – Olawale Adesina Jul 15 '21 at 14:48
  • I've updated the function now. Can you copy new function and test ? @ParthaviPatel – Olawale Adesina Jul 15 '21 at 15:15
  • It still does the same , only change is it Mark Complete LAST TOPIC : https://prnt.sc/1bgbw97 – Parthavi Patel Jul 15 '21 at 15:38
  • Okay, i think the problem here is because we had a different setup. But i've made another edit with consideration for course, topic and quiz. Check again and i hope it work for you :) @ParthaviPatel – Olawale Adesina Jul 15 '21 at 17:55
  • Great, happy to help :) – Olawale Adesina Jul 15 '21 at 18:18
  • I had a similar problem and the only way i found was to mark all lessons as complete. Of course quiz are a problem. I never seen anything as badly programmed as learndash. Please stay away. – Marek Maurizio May 10 '23 at 15:33