The changes shown in this file are only needed if you are worried about a short (60 second) delay between students completing an activity and it being checked-off on the checklist.

** If you are happy with this delay, then ignore all of these suggested changes below **
If this is not acceptable, then you should make the following changes to the Moodle core code (for extra help with this, scroll down to the bottom of this file to see, roughly what the modified files should look like):

*** THIS FIRST CORE MODIFICATION WILL NOT WORK IN MOODLE 2.7 AND ABOVE - DO NOT USE IT ***
Open the file - moodle/lib/datalib.php

Find the function 'add_to_log', then add these lines to the end of it:

    require_once($CFG->dirroot.'/mod/checklist/autoupdate.php');
    checklist_autoupdate($courseid, $module, $action, $cm, $userid, $url);

*** THIS SECOND CORE MODIFICATION WILL STILL WORK IN MOODLE 2.7, BUT LOGS WILL NOT BE CHECKED FOR COMPLETION ***
Now, open the file - moodle/lib/completionlib.php

Find the function 'update_state', then add these lines, just after the
line '$this->internal_set_data($cm, $current);':

    global $CFG;
    require_once($CFG->dirroot.'/mod/checklist/autoupdate.php');
    checklist_completion_autoupdate($cm->id, $userid, $newstate);

WARNING: This will slow your Moodle site down very slightly.
However, the difference is unlikely to be noticable.

You should also disable the cron updates, by changing the following line in 'mod/checklist/autoupdate.php' (it is at the top of the file):
$CFG->checklist_autoupdate_use_cron = true;
should be changed to:
$CFG->checklist_autoupdate_use_cron = false;

To help with modifying the core code to get the 'Check-off modules when complete' feature working, I have included below what the functions will look like after the modification has taken place. Look for the comment '/**** These are the extra lines of code to add for the checklist plugin *****/' to see where the changes have been made.

NOTE: This code is taken form Moodle 2.0.1. Do NOT copy and paste the whole functions, as this may not be compatible with your current Moodle version. 
Please only use this as a guide as to where to insert the extra lines of code.

*** lib/datalib.php:

function add_to_log($courseid, $module, $action, $url='', $info='', $cm=0, $user=0) {
    // Note that this function intentionally does not follow the normal Moodle DB access idioms.
    // This is for a good reason: it is the most frequently used DB update function,
    // so it has been optimised for speed.
    global $DB, $CFG, $USER;

    if ($cm === '' || is_null($cm)) { // postgres won't translate empty string to its default
        $cm = 0;
    }

    if ($user) {
        $userid = $user;
    } else {
        if (session_is_loggedinas()) {  // Don't log
            return;
        }
        $userid = empty($USER->id) ? '0' : $USER->id;
    }

    if (isset($CFG->logguests) and !$CFG->logguests) {
        if (!$userid or isguestuser($userid)) {
            return;
        }
    }

    $REMOTE_ADDR = getremoteaddr();

    $timenow = time();
    $info = $info;
    if (!empty($url)) { // could break doing html_entity_decode on an empty var.
        $url = html_entity_decode($url);
    }

    // Restrict length of log lines to the space actually available in the
    // database so that it doesn't cause a DB error. Log a warning so that
    // developers can avoid doing things which are likely to cause this on a
    // routine basis.
    $tl = textlib_get_instance();
    if(!empty($info) && $tl->strlen($info)>255) {
        $info = $tl->substr($info,0,252).'...';
        debugging('Warning: logged very long info',DEBUG_DEVELOPER);
    }

    // If the 100 field size is changed, also need to alter print_log in course/lib.php
    if(!empty($url) && $tl->strlen($url)>100) {
        $url=$tl->substr($url,0,97).'...';
        debugging('Warning: logged very long URL',DEBUG_DEVELOPER);
    }

    if (defined('MDL_PERFDB')) { global $PERF ; $PERF->logwrites++;};

    $log = array('time'=>$timenow, 'userid'=>$userid, 'course'=>$courseid, 'ip'=>$REMOTE_ADDR, 'module'=>$module,
                 'cmid'=>$cm, 'action'=>$action, 'url'=>$url, 'info'=>$info);

    try {
        $DB->insert_record_raw('log', $log, false);
    } catch (dml_write_exception $e) {
        debugging('Error: Could not insert a new entry to the Moodle log', DEBUG_ALL);
        // MDL-11893, alert $CFG->supportemail if insert into log failed
        if ($CFG->supportemail and empty($CFG->noemailever)) {
            // email_to_user is not usable because email_to_user tries to write to the logs table,
            // and this will get caught in an infinite loop, if disk is full
            $site = get_site();
            $subject = 'Insert into log failed at your moodle site '.$site->fullname;
            $message = "Insert into log table failed at ". date('l dS \of F Y h:i:s A') .".\n It is possible that your disk is full.\n\n";
            $message .= "The failed query parameters are:\n\n" . var_export($log, true);

            $lasttime = get_config('admin', 'lastloginserterrormail');
            if(empty($lasttime) || time() - $lasttime > 60*60*24) { // limit to 1 email per day
                //using email directly rather than messaging as they may not be able to log in to access a message
                mail($CFG->supportemail, $subject, $message);
                set_config('lastloginserterrormail', time(), 'admin');
            }
        }
    }

    /**** These are the extra lines of code to add for the checklist plugin *****/
    require_once($CFG->dirroot.'/mod/checklist/autoupdate.php');
    checklist_autoupdate($courseid, $module, $action, $cm, $userid, $url);
    /***** End of extra lines of code *****/
}

**** lib/completionlib.php:

    public function update_state($cm, $possibleresult=COMPLETION_UNKNOWN, $userid=0) {
        global $USER, $SESSION;

        // Do nothing if completion is not enabled for that activity
        if (!$this->is_enabled($cm)) {
            return;
        }

        // Get current value of completion state and do nothing if it's same as
        // the possible result of this change. If the change is to COMPLETE and the
        // current value is one of the COMPLETE_xx subtypes, ignore that as well
        $current = $this->get_data($cm, false, $userid);
        if ($possibleresult == $current->completionstate ||
            ($possibleresult == COMPLETION_COMPLETE &&
                ($current->completionstate == COMPLETION_COMPLETE_PASS ||
                $current->completionstate == COMPLETION_COMPLETE_FAIL))) {
            return;
        }

        if ($cm->completion == COMPLETION_TRACKING_MANUAL) {
            // For manual tracking we set the result directly
            switch($possibleresult) {
                case COMPLETION_COMPLETE:
                case COMPLETION_INCOMPLETE:
                    $newstate = $possibleresult;
                    break;
                default:
                    $this->internal_systemerror("Unexpected manual completion state for {$cm->id}: $possibleresult");
            }

        } else {
            // Automatic tracking; get new state
            $newstate = $this->internal_get_state($cm, $userid, $current);
        }

        // If changed, update
        if ($newstate != $current->completionstate) {
            $current->completionstate = $newstate;
            $current->timemodified    = time();
            $this->internal_set_data($cm, $current);

            /**** These are the extra lines of code to add for the checklist plugin *****/
            global $CFG;
    	    require_once($CFG->dirroot.'/mod/checklist/autoupdate.php');
            checklist_completion_autoupdate($cm->id, $userid, $newstate);
            /***** End of extra lines of code *****/
        }
    }

