Differences Between: [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 * Privacy Subsystem implementation for core_enrol. 18 * 19 * @package core_enrol 20 * @copyright 2018 Carlos Escobedo <carlos@moodle.com> 21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 */ 23 24 namespace core_enrol\privacy; 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 use core_privacy\local\metadata\collection; 29 use core_privacy\local\request\approved_contextlist; 30 use core_privacy\local\request\context; 31 use core_privacy\local\request\contextlist; 32 use core_privacy\local\request\transform; 33 use core_privacy\local\request\writer; 34 use core_privacy\local\request\userlist; 35 use \core_privacy\local\request\approved_userlist; 36 37 /** 38 * Privacy Subsystem for core_enrol implementing metadata and plugin providers. 39 * 40 * @copyright 2018 Carlos Escobedo <carlos@moodle.com> 41 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 42 */ 43 class provider implements 44 \core_privacy\local\metadata\provider, 45 \core_privacy\local\request\core_userlist_provider, 46 \core_privacy\local\request\subsystem\provider { 47 /** 48 * Returns meta data about this system. 49 * 50 * @param collection $collection The initialised collection to add items to. 51 * @return collection A listing of user data stored through this system. 52 */ 53 public static function get_metadata(collection $collection) : collection { 54 $collection->add_database_table( 55 'user_enrolments', 56 [ 57 'status' => 'privacy:metadata:user_enrolments:status', 58 'enrolid' => 'privacy:metadata:user_enrolments:enrolid', 59 'userid' => 'privacy:metadata:user_enrolments:userid', 60 'timestart' => 'privacy:metadata:user_enrolments:timestart', 61 'timeend' => 'privacy:metadata:user_enrolments:timeend', 62 'modifierid' => 'privacy:metadata:user_enrolments:modifierid', 63 'timecreated' => 'privacy:metadata:user_enrolments:timecreated', 64 'timemodified' => 'privacy:metadata:user_enrolments:timemodified' 65 ], 66 'privacy:metadata:user_enrolments:tableexplanation' 67 ); 68 69 return $collection; 70 } 71 /** 72 * Get the list of contexts that contain user information for the specified user. 73 * 74 * @param int $userid The user to search. 75 * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin. 76 */ 77 public static function get_contexts_for_userid(int $userid) : contextlist { 78 $sql = "SELECT ctx.id 79 FROM {user_enrolments} ue 80 JOIN {enrol} e 81 ON e.id = ue.enrolid 82 AND ue.userid = :userid 83 JOIN {context} ctx 84 ON ctx.instanceid = e.courseid 85 AND ctx.contextlevel = :contextlevel"; 86 $params = [ 87 'contextlevel' => CONTEXT_COURSE, 88 'userid' => $userid 89 ]; 90 $contextlist = new contextlist(); 91 $contextlist->add_from_sql($sql, $params); 92 93 return $contextlist; 94 } 95 96 /** 97 * Get the list of users within a specific context. 98 * 99 * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. 100 */ 101 public static function get_users_in_context(userlist $userlist) { 102 $context = $userlist->get_context(); 103 104 if (!$context instanceof \context_course) { 105 return; 106 } 107 108 $sql = "SELECT ue.userid as userid 109 FROM {user_enrolments} ue 110 JOIN {enrol} e ON e.id = ue.enrolid 111 WHERE e.courseid = ?"; 112 $params = [$context->instanceid]; 113 $userlist->add_from_sql('userid', $sql, $params); 114 } 115 116 /** 117 * Export all user data for the specified user, in the specified contexts. 118 * 119 * @param approved_contextlist $contextlist The approved contexts to export information for. 120 */ 121 public static function export_user_data(approved_contextlist $contextlist) { 122 global $DB; 123 124 if (empty($contextlist->count())) { 125 return; 126 } 127 $userid = $contextlist->get_user()->id; 128 list($insql, $inparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED); 129 $params = [ 130 'contextlevel' => CONTEXT_COURSE, 131 'userid' => $userid 132 ]; 133 $params += $inparams; 134 $sql = "SELECT ue.id, 135 ue.status, 136 ue.timestart, 137 ue.timeend, 138 ue.timecreated, 139 ue.timemodified, 140 e.enrol, 141 ctx.id as contextid 142 FROM {user_enrolments} ue 143 JOIN {enrol} e 144 ON e.id = ue.enrolid 145 AND ue.userid = :userid 146 JOIN {context} ctx 147 ON ctx.instanceid = e.courseid 148 AND ctx.contextlevel = :contextlevel 149 WHERE ctx.id $insql 150 ORDER BY ctx.id, e.enrol"; 151 $data = []; 152 $lastcontextid = null; 153 $lastenrol = null; 154 $path = [get_string('privacy:metadata:user_enrolments', 'core_enrol')]; 155 $flush = function($lastcontextid, $lastenrol, $data) use ($path) { 156 $context = \context::instance_by_id($lastcontextid); 157 writer::with_context($context)->export_related_data( 158 $path, 159 $lastenrol, 160 (object)$data 161 ); 162 }; 163 $userenrolments = $DB->get_recordset_sql($sql, $params); 164 foreach ($userenrolments as $userenrolment) { 165 if (($lastcontextid && $lastcontextid != $userenrolment->contextid) || 166 ($lastenrol && $lastenrol != $userenrolment->enrol)) { 167 $flush($lastcontextid, $lastenrol, $data); 168 $data = []; 169 } 170 $data[] = (object) [ 171 'status' => $userenrolment->status, 172 'timecreated' => transform::datetime($userenrolment->timecreated), 173 'timemodified' => transform::datetime($userenrolment->timemodified), 174 'timestart' => transform::datetime($userenrolment->timestart), 175 'timeend' => transform::datetime($userenrolment->timeend) 176 ]; 177 $lastcontextid = $userenrolment->contextid; 178 $lastenrol = $userenrolment->enrol; 179 } 180 if (!empty($data)) { 181 $flush($lastcontextid, $lastenrol, $data); 182 } 183 $userenrolments->close(); 184 } 185 /** 186 * Delete all data for all users in the specified context. 187 * 188 * @param context $context The specific context to delete data for. 189 */ 190 public static function delete_data_for_all_users_in_context(\context $context) { 191 global $DB; 192 193 // Sanity check that context is at the User context level. 194 if ($context->contextlevel == CONTEXT_COURSE) { 195 $sql = "SELECT ue.id 196 FROM {user_enrolments} ue 197 JOIN {enrol} e ON e.id = ue.enrolid 198 WHERE e.courseid = :courseid"; 199 $params = ['courseid' => $context->instanceid]; 200 $enrolsids = $DB->get_fieldset_sql($sql, $params); 201 if (!empty($enrolsids)) { 202 list($insql, $inparams) = $DB->get_in_or_equal($enrolsids, SQL_PARAMS_NAMED); 203 static::delete_user_data($insql, $inparams); 204 } 205 } 206 } 207 208 /** 209 * Delete multiple users within a single context. 210 * 211 * @param approved_userlist $userlist The approved context and user information to delete information for. 212 */ 213 public static function delete_data_for_users(approved_userlist $userlist) { 214 global $DB; 215 216 $context = $userlist->get_context(); 217 218 if ($context instanceof \context_course) { 219 list($usersql, $userparams) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED); 220 221 $sql = "SELECT ue.id 222 FROM {user_enrolments} ue 223 JOIN {enrol} e ON e.id = ue.enrolid 224 WHERE e.courseid = :courseid 225 AND ue.userid {$usersql}"; 226 227 $params = ['courseid' => $context->instanceid] + $userparams; 228 $enrolsids = $DB->get_fieldset_sql($sql, $params); 229 230 if (!empty($enrolsids)) { 231 list($insql, $inparams) = $DB->get_in_or_equal($enrolsids, SQL_PARAMS_NAMED); 232 static::delete_user_data($insql, $inparams); 233 } 234 } 235 } 236 237 /** 238 * Delete all user data for the specified user, in the specified contexts. 239 * 240 * @param approved_contextlist $contextlist The approved contexts and user information to delete information for. 241 */ 242 public static function delete_data_for_user(approved_contextlist $contextlist) { 243 global $DB; 244 245 if (empty($contextlist->count())) { 246 return; 247 } 248 $userid = $contextlist->get_user()->id; 249 list($insql, $inparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED); 250 $params = [ 251 'contextlevel' => CONTEXT_COURSE, 252 'userid' => $userid 253 ]; 254 $params += $inparams; 255 $sql = "SELECT ue.id 256 FROM {user_enrolments} ue 257 JOIN {enrol} e 258 ON e.id = ue.enrolid 259 AND ue.userid = :userid 260 JOIN {context} ctx 261 ON ctx.instanceid = e.courseid 262 AND ctx.contextlevel = :contextlevel 263 WHERE ctx.id $insql"; 264 $enrolsids = $DB->get_fieldset_sql($sql, $params); 265 if (!empty($enrolsids)) { 266 list($insql, $inparams) = $DB->get_in_or_equal($enrolsids, SQL_PARAMS_NAMED); 267 static::delete_user_data($insql, $inparams); 268 } 269 } 270 271 /** 272 * Delete data from $tablename with the IDs returned by $sql query. 273 * 274 * @param string $sql SQL query for getting the IDs of the uer enrolments entries to delete. 275 * @param array $params SQL params for the query. 276 */ 277 protected static function delete_user_data(string $sql, array $params) { 278 global $DB; 279 280 $DB->delete_records_select('user_enrolments', "id $sql", $params); 281 } 282 283 /** 284 * Get the subcontext for export. 285 * 286 * @param array $subcontext Any additional subcontext to use. 287 * @return array The array containing the full subcontext, i.e. [enrolments, subcontext] 288 */ 289 public static function get_subcontext(array $subcontext) { 290 return array_merge( 291 [get_string('privacy:metadata:user_enrolments', 'core_enrol')], 292 $subcontext 293 ); 294 } 295 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body