Differences Between: [Versions 400 and 401] [Versions 400 and 402] [Versions 400 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 * Privacy class for requesting user data. 19 * 20 * @package core_completion 21 * @copyright 2018 Adrian Greeve <adrian@moodle.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace core_completion\privacy; 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 use core_privacy\local\metadata\collection; 30 use core_privacy\local\request\approved_userlist; 31 use core_privacy\local\request\contextlist; 32 use core_privacy\local\request\transform; 33 use core_privacy\local\request\userlist; 34 35 require_once($CFG->dirroot . '/comment/lib.php'); 36 37 /** 38 * Privacy class for requesting user data. 39 * 40 * @package core_completion 41 * @copyright 2018 Adrian Greeve <adrian@moodle.com> 42 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 43 */ 44 class provider implements 45 \core_privacy\local\metadata\provider, 46 \core_privacy\local\request\subsystem\plugin_provider, 47 \core_privacy\local\request\shared_userlist_provider 48 { 49 50 /** 51 * Returns meta data about this system. 52 * 53 * @param collection $collection The initialised collection to add items to. 54 * @return collection A listing of user data stored through this system. 55 */ 56 public static function get_metadata(collection $collection) : collection { 57 $collection->add_database_table('course_completions', [ 58 'userid' => 'privacy:metadata:userid', 59 'course' => 'privacy:metadata:course', 60 'timeenrolled' => 'privacy:metadata:timeenrolled', 61 'timestarted' => 'privacy:metadata:timestarted', 62 'timecompleted' => 'privacy:metadata:timecompleted', 63 'reaggregate' => 'privacy:metadata:reaggregate' 64 ], 'privacy:metadata:coursesummary'); 65 $collection->add_database_table('course_modules_completion', [ 66 'userid' => 'privacy:metadata:userid', 67 'coursemoduleid' => 'privacy:metadata:coursemoduleid', 68 'completionstate' => 'privacy:metadata:completionstate', 69 'viewed' => 'privacy:metadata:viewed', 70 'overrideby' => 'privacy:metadata:overrideby', 71 'timemodified' => 'privacy:metadata:timemodified' 72 ], 'privacy:metadata:coursemodulesummary'); 73 $collection->add_database_table('course_completion_crit_compl', [ 74 'userid' => 'privacy:metadata:userid', 75 'course' => 'privacy:metadata:course', 76 'gradefinal' => 'privacy:metadata:gradefinal', 77 'unenroled' => 'privacy:metadata:unenroled', 78 'timecompleted' => 'privacy:metadata:timecompleted' 79 ], 'privacy:metadata:coursecompletedsummary'); 80 return $collection; 81 } 82 83 /** 84 * Get join sql to retrieve courses the user is in. 85 * 86 * @param int $userid The user ID 87 * @param string $prefix A unique prefix for these joins. 88 * @param string $joinfield A field to join these tables to. Joins to course ID. 89 * @return array The join, where, and params for this join. 90 */ 91 public static function get_course_completion_join_sql(int $userid, string $prefix, string $joinfield) : array { 92 $cccalias = "{$prefix}_ccc"; // Course completion criteria. 93 $cmcalias = "{$prefix}_cmc"; // Course modules completion. 94 $ccccalias = "{$prefix}_cccc"; // Course completion criteria completion. 95 96 $join = "JOIN {course_completion_criteria} {$cccalias} ON {$joinfield} = {$cccalias}.course 97 LEFT JOIN {course_modules_completion} {$cmcalias} ON {$cccalias}.moduleinstance = {$cmcalias}.coursemoduleid 98 AND {$cmcalias}.userid = :{$prefix}_moduleuserid 99 LEFT JOIN {course_completion_crit_compl} {$ccccalias} ON {$ccccalias}.criteriaid = {$cccalias}.id 100 AND {$ccccalias}.userid = :{$prefix}_courseuserid"; 101 $where = "{$cmcalias}.id IS NOT NULL OR {$ccccalias}.id IS NOT NULL"; 102 $params = ["{$prefix}_moduleuserid" => $userid, "{$prefix}_courseuserid" => $userid]; 103 104 return [$join, $where, $params]; 105 } 106 107 /** 108 * Find users' course completion by context and add to the provided userlist. 109 * 110 * @param userlist $userlist The userlist to add to. 111 */ 112 public static function add_course_completion_users_to_userlist(userlist $userlist) { 113 $context = $userlist->get_context(); 114 115 if (!$context instanceof \context_course) { 116 return; 117 } 118 119 $params = ['courseid' => $context->instanceid]; 120 121 $sql = "SELECT cmc.userid 122 FROM {course} c 123 JOIN {course_completion_criteria} ccc ON ccc.course = c.id 124 JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = ccc.moduleinstance 125 WHERE c.id = :courseid"; 126 127 $userlist->add_from_sql('userid', $sql, $params); 128 129 $sql = "SELECT ccc_compl.userid 130 FROM {course} c 131 JOIN {course_completion_criteria} ccc ON ccc.course = c.id 132 JOIN {course_completion_crit_compl} ccc_compl ON ccc_compl.criteriaid = ccc.id 133 WHERE c.id = :courseid"; 134 135 $userlist->add_from_sql('userid', $sql, $params); 136 } 137 138 /** 139 * Returns activity completion information about a user. 140 * 141 * @param \stdClass $user The user to return information about. 142 * @param \stdClass $course The course the user is in. 143 * @param \stdClass $cm Course module information. 144 * @return \stdClass Activity completion information. 145 */ 146 public static function get_activity_completion_info(\stdClass $user, \stdClass $course, $cm) : \stdClass { 147 $completioninfo = new \completion_info($course); 148 $completion = $completioninfo->is_enabled($cm); 149 return ($completion != COMPLETION_TRACKING_NONE) ? $completioninfo->get_data($cm, true, $user->id) : new \stdClass(); 150 } 151 152 /** 153 * Returns course completion information for a user. 154 * 155 * @param \stdClass $user The user that we are getting completion information for. 156 * @param \stdClass $course The course we are interested in. 157 * @return \stdClass Course completion information. 158 */ 159 public static function get_course_completion_info(\stdClass $user, \stdClass $course) : array { 160 $completioninfo = new \completion_info($course); 161 $completion = $completioninfo->is_enabled(); 162 163 if ($completion != COMPLETION_ENABLED) { 164 return []; 165 } 166 167 $coursecomplete = $completioninfo->is_course_complete($user->id); 168 169 if ($coursecomplete) { 170 $status = get_string('complete'); 171 } else { 172 $criteriacomplete = $completioninfo->count_course_user_data($user->id); 173 $ccompletion = new \completion_completion(['userid' => $user->id, 'course' => $course->id]); 174 175 if (!$criteriacomplete && !$ccompletion->timestarted) { 176 $status = get_string('notyetstarted', 'completion'); 177 } else { 178 $status = get_string('inprogress', 'completion'); 179 } 180 } 181 182 $completions = $completioninfo->get_completions($user->id); 183 $overall = get_string('nocriteriaset', 'completion'); 184 if (!empty($completions)) { 185 if ($completioninfo->get_aggregation_method() == COMPLETION_AGGREGATION_ALL) { 186 $overall = get_string('criteriarequiredall', 'completion'); 187 } else { 188 $overall = get_string('criteriarequiredany', 'completion'); 189 } 190 } 191 192 $coursecompletiondata = [ 193 'status' => $status, 194 'required' => $overall, 195 ]; 196 197 $coursecompletiondata['criteria'] = array_map(function($completion) use ($completioninfo) { 198 $criteria = $completion->get_criteria(); 199 $aggregation = $completioninfo->get_aggregation_method($criteria->criteriatype); 200 $required = ($aggregation == COMPLETION_AGGREGATION_ALL) ? get_string('all', 'completion') : 201 get_string('any', 'completion'); 202 $data = [ 203 'required' => $required, 204 'completed' => transform::yesno($completion->is_complete()), 205 'timecompleted' => isset($completion->timecompleted) ? transform::datetime($completion->timecompleted) : '' 206 ]; 207 $details = $criteria->get_details($completion); 208 $data = array_merge($data, $details); 209 return $data; 210 }, $completions); 211 return $coursecompletiondata; 212 } 213 214 /** 215 * Delete completion information for users. 216 * 217 * @param \stdClass $user The user. If provided will delete completion information for just this user. Else all users. 218 * @param int $courseid The course id. Provide this if you want course completion and activity completion deleted. 219 * @param int $cmid The course module id. Provide this if you only want activity completion deleted. 220 */ 221 public static function delete_completion(\stdClass $user = null, int $courseid = null, int $cmid = null) { 222 global $DB; 223 224 if (isset($cmid)) { 225 $params = (isset($user)) ? ['userid' => $user->id, 'coursemoduleid' => $cmid] : ['coursemoduleid' => $cmid]; 226 // Only delete the record for course modules completion. 227 $DB->delete_records('course_modules_completion', $params); 228 return; 229 } 230 231 if (isset($courseid)) { 232 233 $usersql = isset($user) ? 'AND cmc.userid = :userid' : ''; 234 $params = isset($user) ? ['course' => $courseid, 'userid' => $user->id] : ['course' => $courseid]; 235 236 // Find records relating to course modules. 237 $sql = "SELECT cmc.id 238 FROM {course_completion_criteria} ccc 239 JOIN {course_modules_completion} cmc ON ccc.moduleinstance = cmc.coursemoduleid 240 WHERE ccc.course = :course $usersql"; 241 $recordids = $DB->get_records_sql($sql, $params); 242 $ids = array_keys($recordids); 243 if (!empty($ids)) { 244 list($deletesql, $deleteparams) = $DB->get_in_or_equal($ids); 245 $deletesql = 'id ' . $deletesql; 246 $DB->delete_records_select('course_modules_completion', $deletesql, $deleteparams); 247 } 248 $DB->delete_records('course_completion_crit_compl', $params); 249 $DB->delete_records('course_completions', $params); 250 } 251 } 252 253 /** 254 * Delete completion information for users within an approved userlist. 255 * 256 * @param approved_userlist $userlist The approved userlist of users to delete completion information for. 257 * @param int $courseid The course id. Provide this if you want course completion and activity completion deleted. 258 * @param int $cmid The course module id. Provide this if you only want activity completion deleted. 259 */ 260 public static function delete_completion_by_approved_userlist(approved_userlist $userlist, int $courseid = null, int $cmid = null) { 261 global $DB; 262 $userids = $userlist->get_userids(); 263 264 if (empty($userids)) { 265 return; 266 } 267 268 list($useridsql, $params) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED); 269 270 if (isset($cmid)) { 271 $params['coursemoduleid'] = $cmid; 272 273 // Only delete the record for course modules completion. 274 $sql = "coursemoduleid = :coursemoduleid AND userid {$useridsql}"; 275 $DB->delete_records_select('course_modules_completion', $sql, $params); 276 return; 277 } 278 279 if (isset($courseid)) { 280 $params['course'] = $courseid; 281 282 // Find records relating to course modules. 283 $sql = "SELECT cmc.id 284 FROM {course_completion_criteria} ccc 285 JOIN {course_modules_completion} cmc ON ccc.moduleinstance = cmc.coursemoduleid 286 WHERE ccc.course = :course AND cmc.userid {$useridsql}"; 287 $recordids = $DB->get_records_sql($sql, $params); 288 $ids = array_keys($recordids); 289 if (!empty($ids)) { 290 list($deletesql, $deleteparams) = $DB->get_in_or_equal($ids); 291 $deletesql = 'id ' . $deletesql; 292 $DB->delete_records_select('course_modules_completion', $deletesql, $deleteparams); 293 } 294 295 $sql = "course = :course AND userid {$useridsql}"; 296 $DB->delete_records_select('course_completion_crit_compl', $sql, $params); 297 $DB->delete_records_select('course_completions', $sql, $params); 298 } 299 } 300 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body