Differences Between: [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * A scheduled task. 19 * 20 * @package core 21 * @copyright 2015 Josh Willcock 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 namespace core\task; 25 26 /** 27 * Simple task to run the regular completion cron. 28 * @copyright 2015 Josh Willcock 29 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later. 30 */ 31 class completion_regular_task extends scheduled_task { 32 33 /** 34 * Get a descriptive name for this task (shown to admins). 35 * 36 * @return string 37 */ 38 public function get_name() { 39 return get_string('taskcompletionregular', 'admin'); 40 } 41 42 /** 43 * Do the job. 44 * Throw exceptions on errors (the job will be retried). 45 */ 46 public function execute() { 47 global $CFG, $COMPLETION_CRITERIA_TYPES, $DB; 48 49 if ($CFG->enablecompletion) { 50 require_once($CFG->libdir . "/completionlib.php"); 51 52 // Process each criteria type. 53 foreach ($COMPLETION_CRITERIA_TYPES as $type) { 54 $object = 'completion_criteria_' . $type; 55 require_once($CFG->dirroot . '/completion/criteria/' . $object . '.php'); 56 57 $class = new $object(); 58 // Run the criteria type's cron method, if it has one. 59 if (method_exists($class, 'cron')) { 60 if (debugging()) { 61 mtrace('Running '.$object.'->cron()'); 62 } 63 $class->cron(); 64 } 65 } 66 67 if (debugging()) { 68 mtrace('Aggregating completions'); 69 } 70 71 // Save time started. 72 $timestarted = time(); 73 74 // Grab all criteria and their associated criteria completions. 75 $sql = 'SELECT DISTINCT c.id AS course, cr.id AS criteriaid, crc.userid AS userid, 76 cr.criteriatype AS criteriatype, cc.timecompleted AS timecompleted 77 FROM {course_completion_criteria} cr 78 INNER JOIN {course} c ON cr.course = c.id 79 INNER JOIN {course_completions} crc ON crc.course = c.id 80 LEFT JOIN {course_completion_crit_compl} cc ON cc.criteriaid = cr.id AND crc.userid = cc.userid 81 WHERE c.enablecompletion = 1 82 AND crc.timecompleted IS NULL 83 AND crc.reaggregate > 0 84 AND crc.reaggregate < :timestarted 85 ORDER BY course, userid'; 86 $rs = $DB->get_recordset_sql($sql, ['timestarted' => $timestarted]); 87 88 // Check if result is empty. 89 if (!$rs->valid()) { 90 $rs->close(); 91 return; 92 } 93 94 $currentuser = null; 95 $currentcourse = null; 96 $completions = []; 97 while (1) { 98 // Grab records for current user/course. 99 foreach ($rs as $record) { 100 // If we are still grabbing the same users completions. 101 if ($record->userid === $currentuser && $record->course === $currentcourse) { 102 $completions[$record->criteriaid] = $record; 103 } else { 104 break; 105 } 106 } 107 108 // Aggregate. 109 if (!empty($completions)) { 110 if (debugging()) { 111 mtrace('Aggregating completions for user ' . $currentuser . ' in course ' . $currentcourse); 112 } 113 114 // Get course info object. 115 $info = new \completion_info((object)['id' => $currentcourse]); 116 117 // Setup aggregation. 118 $overall = $info->get_aggregation_method(); 119 $activity = $info->get_aggregation_method(COMPLETION_CRITERIA_TYPE_ACTIVITY); 120 $prerequisite = $info->get_aggregation_method(COMPLETION_CRITERIA_TYPE_COURSE); 121 $role = $info->get_aggregation_method(COMPLETION_CRITERIA_TYPE_ROLE); 122 123 $overallstatus = null; 124 $activitystatus = null; 125 $prerequisitestatus = null; 126 $rolestatus = null; 127 128 // Get latest timecompleted. 129 $timecompleted = null; 130 131 // Check each of the criteria. 132 foreach ($completions as $params) { 133 $timecompleted = max($timecompleted, $params->timecompleted); 134 $completion = new \completion_criteria_completion((array)$params, false); 135 136 // Handle aggregation special cases. 137 if ($params->criteriatype == COMPLETION_CRITERIA_TYPE_ACTIVITY) { 138 completion_cron_aggregate($activity, $completion->is_complete(), $activitystatus); 139 } else if ($params->criteriatype == COMPLETION_CRITERIA_TYPE_COURSE) { 140 completion_cron_aggregate($prerequisite, $completion->is_complete(), $prerequisitestatus); 141 } else if ($params->criteriatype == COMPLETION_CRITERIA_TYPE_ROLE) { 142 completion_cron_aggregate($role, $completion->is_complete(), $rolestatus); 143 } else { 144 completion_cron_aggregate($overall, $completion->is_complete(), $overallstatus); 145 } 146 } 147 148 // Include role criteria aggregation in overall aggregation. 149 if ($rolestatus !== null) { 150 completion_cron_aggregate($overall, $rolestatus, $overallstatus); 151 } 152 153 // Include activity criteria aggregation in overall aggregation. 154 if ($activitystatus !== null) { 155 completion_cron_aggregate($overall, $activitystatus, $overallstatus); 156 } 157 158 // Include prerequisite criteria aggregation in overall aggregation. 159 if ($prerequisitestatus !== null) { 160 completion_cron_aggregate($overall, $prerequisitestatus, $overallstatus); 161 } 162 163 // If aggregation status is true, mark course complete for user. 164 if ($overallstatus) { 165 if (debugging()) { 166 mtrace('Marking complete'); 167 } 168 169 $ccompletion = new \completion_completion([ 170 'course' => $params->course, 171 'userid' => $params->userid 172 ]); 173 $ccompletion->mark_complete($timecompleted); 174 } 175 } 176 177 // If this is the end of the recordset, break the loop. 178 if (!$rs->valid()) { 179 $rs->close(); 180 break; 181 } 182 183 // New/next user, update user details, reset completions. 184 $currentuser = $record->userid; 185 $currentcourse = $record->course; 186 $completions = []; 187 $completions[$record->criteriaid] = $record; 188 } 189 190 // Mark all users as aggregated. 191 $sql = "UPDATE {course_completions} 192 SET reaggregate = 0 193 WHERE reaggregate < :timestarted 194 AND reaggregate > 0"; 195 $DB->execute($sql, ['timestarted' => $timestarted]); 196 } 197 } 198 199 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body