/** * Find users who have completed this criteria and mark them accordingly */ public function cron() { global $DB; // Get all users who meet this criteria $sql = ' SELECT DISTINCT c.id AS course, cr.id AS criteriaid, ra.userid AS userid, mc.timemodified AS timecompleted FROM {course_completion_criteria} cr INNER JOIN {course} c ON cr.course = c.id INNER JOIN {context} con ON con.instanceid = c.id INNER JOIN {role_assignments} ra ON ra.contextid = con.id INNER JOIN {course_modules_completion} mc ON mc.coursemoduleid = cr.moduleinstance AND mc.userid = ra.userid LEFT JOIN {course_completion_crit_compl} cc ON cc.criteriaid = cr.id AND cc.userid = ra.userid WHERE cr.criteriatype = ' . COMPLETION_CRITERIA_TYPE_ACTIVITY . ' AND con.contextlevel = ' . CONTEXT_COURSE . ' AND c.enablecompletion = 1 AND cc.id IS NULL AND ( mc.completionstate = ' . COMPLETION_COMPLETE . ' OR mc.completionstate = ' . COMPLETION_COMPLETE_PASS . ' ) '; // Loop through completions, and mark as complete $rs = $DB->get_recordset_sql($sql); foreach ($rs as $record) { $completion = new completion_criteria_completion((array) $record, DATA_OBJECT_FETCH_BY_KEY); $completion->mark_complete($record->timecompleted); } $rs->close(); }
/** * Get all course criteria's completion objects for a user * * @param int $user_id User id * @param int $criteriatype Specific criteria type to return (optional) * @return array */ public function get_completions($user_id, $criteriatype = null) { $criterion = $this->get_criteria($criteriatype); $completions = array(); foreach ($criterion as $criteria) { $params = array('course' => $this->course_id, 'userid' => $user_id, 'criteriaid' => $criteria->id); $completion = new completion_criteria_completion($params); $completion->attach_criteria($criteria); $completions[] = $completion; } return $completions; }
/** * Aggregate each user's criteria completions * * @return void */ function completion_cron_completions() { global $DB; if (debugging()) { mtrace('Aggregating completions'); } // Save time started $timestarted = time(); // Grab all criteria and their associated criteria completions $sql = ' SELECT DISTINCT c.id AS course, cr.id AS criteriaid, crc.userid AS userid, cr.criteriatype AS criteriatype, cc.timecompleted AS timecompleted FROM {course_completion_criteria} cr INNER JOIN {course} c ON cr.course = c.id INNER JOIN {course_completions} crc ON crc.course = c.id LEFT JOIN {course_completion_crit_compl} cc ON cc.criteriaid = cr.id AND crc.userid = cc.userid WHERE c.enablecompletion = 1 AND crc.timecompleted IS NULL AND crc.reaggregate > 0 AND crc.reaggregate < :timestarted ORDER BY course, userid '; // Check if result is empty if (!($rs = $DB->get_recordset_sql($sql, array('timestarted' => $timestarted)))) { return; } $current_user = null; $current_course = null; $completions = array(); while (1) { // Grab records for current user/course foreach ($rs as $record) { // If we are still grabbing the same users completions if ($record->userid === $current_user && $record->course === $current_course) { $completions[$record->criteriaid] = $record; } else { break; } } // Aggregate if (!empty($completions)) { if (debugging()) { mtrace('Aggregating completions for user ' . $current_user . ' in course ' . $current_course); } // Get course info object $info = new completion_info((object) array('id' => $current_course)); // Setup aggregation $overall = $info->get_aggregation_method(); $activity = $info->get_aggregation_method(COMPLETION_CRITERIA_TYPE_ACTIVITY); $prerequisite = $info->get_aggregation_method(COMPLETION_CRITERIA_TYPE_COURSE); $role = $info->get_aggregation_method(COMPLETION_CRITERIA_TYPE_ROLE); $overall_status = null; $activity_status = null; $prerequisite_status = null; $role_status = null; // Get latest timecompleted $timecompleted = null; // Check each of the criteria foreach ($completions as $params) { $timecompleted = max($timecompleted, $params->timecompleted); $completion = new completion_criteria_completion($params, false); // Handle aggregation special cases if ($params->criteriatype == COMPLETION_CRITERIA_TYPE_ACTIVITY) { completion_cron_aggregate($activity, $completion->is_complete(), $activity_status); } else { if ($params->criteriatype == COMPLETION_CRITERIA_TYPE_COURSE) { completion_cron_aggregate($prerequisite, $completion->is_complete(), $prerequisite_status); } else { if ($params->criteriatype == COMPLETION_CRITERIA_TYPE_ROLE) { completion_cron_aggregate($role, $completion->is_complete(), $role_status); } else { completion_cron_aggregate($overall, $completion->is_complete(), $overall_status); } } } } // Include role criteria aggregation in overall aggregation if ($role_status !== null) { completion_cron_aggregate($overall, $role_status, $overall_status); } // Include activity criteria aggregation in overall aggregation if ($activity_status !== null) { completion_cron_aggregate($overall, $activity_status, $overall_status); } // Include prerequisite criteria aggregation in overall aggregation if ($prerequisite_status !== null) { completion_cron_aggregate($overall, $prerequisite_status, $overall_status); } // If aggregation status is true, mark course complete for user if ($overall_status) { if (debugging()) { mtrace('Marking complete'); } $ccompletion = new completion_completion(array('course' => $params->course, 'userid' => $params->userid)); $ccompletion->mark_complete($timecompleted); } } // If this is the end of the recordset, break the loop if (!$rs->valid()) { $rs->close(); break; } // New/next user, update user details, reset completions $current_user = $record->userid; $current_course = $record->course; $completions = array(); $completions[$record->criteriaid] = $record; } // Mark all users as aggregated $sql = "\n UPDATE\n {course_completions}\n SET\n reaggregate = 0\n WHERE\n reaggregate < {$timestarted}\n "; $DB->execute($sql); }
/** * Find user's who have completed this criteria * @access public * @return void */ public function cron() { global $DB; // Get all users who meet this criteria $sql = "\n SELECT DISTINCT\n c.id AS course,\n cr.id AS criteriaid,\n ra.userid AS userid,\n cc.timecompleted AS timecompleted\n FROM\n {course_completion_criteria} cr\n INNER JOIN\n {course} c\n ON cr.course = c.id\n INNER JOIN\n {context} con\n ON con.instanceid = c.id\n INNER JOIN\n {role_assignments} ra\n ON ra.contextid = con.id\n INNER JOIN\n {course_completions} cc\n ON cc.course = cr.courseinstance\n AND cc.userid = ra.userid\n LEFT JOIN\n {course_completion_crit_compl} ccc\n ON ccc.criteriaid = cr.id\n AND ccc.userid = ra.userid\n WHERE\n cr.criteriatype = " . COMPLETION_CRITERIA_TYPE_COURSE . "\n AND con.contextlevel = " . CONTEXT_COURSE . "\n AND c.enablecompletion = 1\n AND ccc.id IS NULL\n AND cc.timecompleted IS NOT NULL\n "; // Loop through completions, and mark as complete $rs = $DB->get_recordset_sql($sql); foreach ($rs as $record) { $completion = new completion_criteria_completion((array) $record); $completion->mark_complete($record->timecompleted); } $rs->close(); }
/** * Find user's who have completed this criteria */ public function cron() { global $DB; // Get all users who match meet this criteria $sql = ' SELECT DISTINCT c.id AS course, cr.timeend AS timeend, cr.id AS criteriaid, ra.userid AS userid FROM {course_completion_criteria} cr INNER JOIN {course} c ON cr.course = c.id INNER JOIN {context} con ON con.instanceid = c.id INNER JOIN {role_assignments} ra ON ra.contextid = con.id LEFT JOIN {course_completion_crit_compl} cc ON cc.criteriaid = cr.id AND cc.userid = ra.userid WHERE cr.criteriatype = ' . COMPLETION_CRITERIA_TYPE_DATE . ' AND con.contextlevel = ' . CONTEXT_COURSE . ' AND c.enablecompletion = 1 AND cc.id IS NULL AND cr.timeend < ? '; // Loop through completions, and mark as complete $rs = $DB->get_recordset_sql($sql, array(time())); foreach ($rs as $record) { $completion = new completion_criteria_completion((array) $record); $completion->mark_complete($record->timeend); } $rs->close(); }
/** * Find user's who have completed this criteria */ public function cron() { global $DB; /* * Get all users who match meet this criteria * * We can safely ignore duplicate enrolments for * a user in a course here as we only care if * one of the enrolments has passed the set * duration. */ $sql = ' SELECT c.id AS course, cr.id AS criteriaid, u.id AS userid, ue.timestart AS otimestart, (ue.timestart + cr.enrolperiod) AS ctimestart, ue.timecreated AS otimeenrolled, (ue.timecreated + cr.enrolperiod) AS ctimeenrolled FROM {user} u INNER JOIN {user_enrolments} ue ON ue.userid = u.id INNER JOIN {enrol} e ON e.id = ue.enrolid INNER JOIN {course} c ON c.id = e.courseid INNER JOIN {course_completion_criteria} cr ON c.id = cr.course LEFT JOIN {course_completion_crit_compl} cc ON cc.criteriaid = cr.id AND cc.userid = u.id WHERE cr.criteriatype = ' . COMPLETION_CRITERIA_TYPE_DURATION . ' AND c.enablecompletion = 1 AND cc.id IS NULL AND ( ue.timestart > 0 AND ue.timestart + cr.enrolperiod < ? OR ue.timecreated > 0 AND ue.timecreated + cr.enrolperiod < ? ) '; // Loop through completions, and mark as complete $now = time(); $rs = $DB->get_recordset_sql($sql, array($now, $now)); foreach ($rs as $record) { $completion = new completion_criteria_completion((array) $record, DATA_OBJECT_FETCH_BY_KEY); // Use time start if not 0, otherwise use timeenrolled if ($record->otimestart) { $completion->mark_complete($record->ctimestart); } else { $completion->mark_complete($record->ctimeenrolled); } } $rs->close(); }
/** * Find user's who have completed this criteria */ public function cron() { global $DB; // Get all users who meet this criteria $sql = ' SELECT DISTINCT c.id AS course, cr.id AS criteriaid, ra.userid AS userid, gg.finalgrade AS gradefinal, gg.timemodified AS timecompleted FROM {course_completion_criteria} cr INNER JOIN {course} c ON cr.course = c.id INNER JOIN {context} con ON con.instanceid = c.id INNER JOIN {role_assignments} ra ON ra.contextid = con.id INNER JOIN {grade_items} gi ON gi.courseid = c.id AND gi.itemtype = \'course\' INNER JOIN {grade_grades} gg ON gg.itemid = gi.id AND gg.userid = ra.userid LEFT JOIN {course_completion_crit_compl} cc ON cc.criteriaid = cr.id AND cc.userid = ra.userid WHERE cr.criteriatype = ' . COMPLETION_CRITERIA_TYPE_GRADE . ' AND con.contextlevel = ' . CONTEXT_COURSE . ' AND c.enablecompletion = 1 AND cc.id IS NULL AND gg.finalgrade >= cr.gradepass '; // Loop through completions, and mark as complete $rs = $DB->get_recordset_sql($sql); foreach ($rs as $record) { $completion = new completion_criteria_completion((array) $record, DATA_OBJECT_FETCH_BY_KEY); $completion->mark_complete($record->timecompleted); } $rs->close(); }