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 Subsystem implementation for tool_cohortroles. 19 * 20 * @package tool_cohortroles 21 * @copyright 2018 Zig Tan <zig@moodle.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace tool_cohortroles\privacy; 26 27 use core_privacy\local\metadata\collection; 28 use core_privacy\local\request\approved_contextlist; 29 use core_privacy\local\request\context; 30 use core_privacy\local\request\contextlist; 31 use core_privacy\local\request\transform; 32 use core_privacy\local\request\writer; 33 use core_privacy\local\request\userlist; 34 use \core_privacy\local\request\approved_userlist; 35 36 defined('MOODLE_INTERNAL') || die(); 37 38 /** 39 * Privacy Subsystem for tool_cohortroles implementing metadata and plugin providers. 40 * 41 * @copyright 2018 Zig Tan <zig@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\core_userlist_provider, 47 \core_privacy\local\request\plugin\provider { 48 49 /** 50 * Returns meta data about this system. 51 * 52 * @param collection $collection The initialised collection to add items to. 53 * @return collection A listing of user data stored through this system. 54 */ 55 public static function get_metadata(collection $collection) : collection { 56 // The tool_cohortroles plugin utilises the mdl_tool_cohortroles table. 57 $collection->add_database_table( 58 'tool_cohortroles', 59 [ 60 'id' => 'privacy:metadata:tool_cohortroles:id', 61 'cohortid' => 'privacy:metadata:tool_cohortroles:cohortid', 62 'roleid' => 'privacy:metadata:tool_cohortroles:roleid', 63 'userid' => 'privacy:metadata:tool_cohortroles:userid', 64 'timecreated' => 'privacy:metadata:tool_cohortroles:timecreated', 65 'timemodified' => 'privacy:metadata:tool_cohortroles:timemodified', 66 'usermodified' => 'privacy:metadata:tool_cohortroles:usermodified' 67 ], 68 'privacy:metadata:tool_cohortroles' 69 ); 70 71 return $collection; 72 } 73 74 /** 75 * Get the list of contexts that contain user information for the specified user. 76 * 77 * @param int $userid The user to search. 78 * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin. 79 */ 80 public static function get_contexts_for_userid(int $userid) : contextlist { 81 $contextlist = new contextlist(); 82 83 // When we process user deletions and expiries, we always delete from the user context. 84 // As a result the cohort role assignments would be deleted, which has a knock-on effect with courses 85 // as roles may change and data may be removed earlier than it should be. 86 87 // Retrieve the context associated with tool_cohortroles records. 88 $sql = "SELECT DISTINCT c.contextid 89 FROM {tool_cohortroles} tc 90 JOIN {cohort} c 91 ON tc.cohortid = c.id 92 JOIN {context} ctx 93 ON ctx.id = c.contextid 94 WHERE tc.userid = :userid 95 AND (ctx.contextlevel = :contextlevel1 96 OR ctx.contextlevel = :contextlevel2)"; 97 98 $params = [ 99 'userid' => $userid, 100 'contextlevel1' => CONTEXT_SYSTEM, 101 'contextlevel2' => CONTEXT_COURSECAT 102 ]; 103 104 $contextlist->add_from_sql($sql, $params); 105 106 return $contextlist; 107 } 108 109 /** 110 * Get the list of users within a specific context. 111 * 112 * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. 113 */ 114 public static function get_users_in_context(userlist $userlist) { 115 $context = $userlist->get_context(); 116 117 // When we process user deletions and expiries, we always delete from the user context. 118 // As a result the cohort role assignments would be deleted, which has a knock-on effect with courses 119 // as roles may change and data may be removed earlier than it should be. 120 121 $allowedcontextlevels = [ 122 CONTEXT_SYSTEM, 123 CONTEXT_COURSECAT 124 ]; 125 126 if (!in_array($context->contextlevel, $allowedcontextlevels)) { 127 return; 128 } 129 130 $sql = "SELECT tc.userid as userid 131 FROM {tool_cohortroles} tc 132 JOIN {cohort} c 133 ON tc.cohortid = c.id 134 WHERE c.contextid = :contextid"; 135 136 $params = [ 137 'contextid' => $context->id 138 ]; 139 140 $userlist->add_from_sql('userid', $sql, $params); 141 } 142 143 /** 144 * Export all user data for the specified user, in the specified contexts. 145 * 146 * @param approved_contextlist $contextlist The approved contexts to export information for. 147 */ 148 public static function export_user_data(approved_contextlist $contextlist) { 149 global $DB; 150 151 // Remove contexts different from SYSTEM or COURSECAT. 152 $contextids = array_reduce($contextlist->get_contexts(), function($carry, $context) { 153 if ($context->contextlevel == CONTEXT_SYSTEM || $context->contextlevel == CONTEXT_COURSECAT) { 154 $carry[] = $context->id; 155 } 156 return $carry; 157 }, []); 158 159 if (empty($contextids)) { 160 return; 161 } 162 163 $userid = $contextlist->get_user()->id; 164 165 list($contextsql, $contextparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED); 166 167 // Retrieve the tool_cohortroles records created for the user. 168 $sql = "SELECT cr.id as cohortroleid, 169 c.name as cohortname, 170 c.idnumber as cohortidnumber, 171 c.description as cohortdescription, 172 c.contextid as contextid, 173 r.shortname as roleshortname, 174 cr.userid as userid, 175 cr.timecreated as timecreated, 176 cr.timemodified as timemodified 177 FROM {tool_cohortroles} cr 178 JOIN {cohort} c ON c.id = cr.cohortid 179 JOIN {role} r ON r.id = cr.roleid 180 WHERE cr.userid = :userid 181 AND c.contextid {$contextsql}"; 182 183 $params = ['userid' => $userid] + $contextparams; 184 185 $cohortroles = $DB->get_records_sql($sql, $params); 186 187 foreach ($cohortroles as $cohortrole) { 188 // The tool_cohortroles data export is organised in: 189 // {User Context}/Cohort roles management/{cohort name}/{role shortname}/data.json. 190 $subcontext = [ 191 get_string('pluginname', 'tool_cohortroles'), 192 $cohortrole->cohortname, 193 $cohortrole->roleshortname 194 ]; 195 196 $data = (object) [ 197 'cohortname' => $cohortrole->cohortname, 198 'cohortidnumber' => $cohortrole->cohortidnumber, 199 'cohortdescription' => $cohortrole->cohortdescription, 200 'roleshortname' => $cohortrole->roleshortname, 201 'userid' => transform::user($cohortrole->userid), 202 'timecreated' => transform::datetime($cohortrole->timecreated), 203 'timemodified' => transform::datetime($cohortrole->timemodified) 204 ]; 205 206 $context = \context::instance_by_id($cohortrole->contextid); 207 208 writer::with_context($context)->export_data($subcontext, $data); 209 } 210 } 211 212 /** 213 * Delete all data for all users in the specified context. 214 * 215 * @param context $context The specific context to delete data for. 216 */ 217 public static function delete_data_for_all_users_in_context(\context $context) { 218 global $DB; 219 220 // When we process user deletions and expiries, we always delete from the user context. 221 // As a result the cohort role assignments would be deleted, which has a knock-on effect with courses 222 // as roles may change and data may be removed earlier than it should be. 223 224 $allowedcontextlevels = [ 225 CONTEXT_SYSTEM, 226 CONTEXT_COURSECAT 227 ]; 228 229 if (!in_array($context->contextlevel, $allowedcontextlevels)) { 230 return; 231 } 232 233 $cohortids = $DB->get_fieldset_select('cohort', 'id', 'contextid = :contextid', 234 ['contextid' => $context->id]); 235 236 // Delete the tool_cohortroles records created in the specific context. 237 $DB->delete_records_list('tool_cohortroles', 'cohortid', $cohortids); 238 } 239 240 /** 241 * Delete multiple users within a single context. 242 * 243 * @param approved_userlist $userlist The approved context and user information to delete information for. 244 */ 245 public static function delete_data_for_users(approved_userlist $userlist) { 246 global $DB; 247 248 // When we process user deletions and expiries, we always delete from the user context. 249 // As a result the cohort role assignments would be deleted, which has a knock-on effect with courses 250 // as roles may change and data may be removed earlier than it should be. 251 252 $userids = $userlist->get_userids(); 253 254 if (empty($userids)) { 255 return; 256 } 257 258 $context = $userlist->get_context(); 259 260 $allowedcontextlevels = [ 261 CONTEXT_SYSTEM, 262 CONTEXT_COURSECAT 263 ]; 264 265 if (!in_array($context->contextlevel, $allowedcontextlevels)) { 266 return; 267 } 268 269 $cohortids = $DB->get_fieldset_select('cohort', 'id', 'contextid = :contextid', 270 ['contextid' => $context->id]); 271 272 if (empty($cohortids)) { 273 return; 274 } 275 276 list($cohortsql, $cohortparams) = $DB->get_in_or_equal($cohortids, SQL_PARAMS_NAMED); 277 list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED); 278 279 $params = $cohortparams + $userparams; 280 $select = "cohortid {$cohortsql} AND userid {$usersql}"; 281 282 // Delete the tool_cohortroles records created in the specific context for an approved list of users. 283 $DB->delete_records_select('tool_cohortroles', $select, $params); 284 } 285 286 /** 287 * Delete all user data for the specified user, in the specified contexts. 288 * 289 * @param approved_contextlist $contextlist The approved contexts and user information to delete information for. 290 */ 291 public static function delete_data_for_user(approved_contextlist $contextlist) { 292 global $DB; 293 294 // When we process user deletions and expiries, we always delete from the user context. 295 // As a result the cohort role assignments would be deleted, which has a knock-on effect with courses 296 // as roles may change and data may be removed earlier than it should be. 297 298 // Remove contexts different from SYSTEM or COURSECAT. 299 $contextids = array_reduce($contextlist->get_contexts(), function($carry, $context) { 300 if ($context->contextlevel == CONTEXT_SYSTEM || $context->contextlevel == CONTEXT_COURSECAT) { 301 $carry[] = $context->id; 302 } 303 return $carry; 304 }, []); 305 306 if (empty($contextids)) { 307 return; 308 } 309 310 $userid = $contextlist->get_user()->id; 311 312 list($contextsql, $contextparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED); 313 $selectcontext = "contextid {$contextsql}"; 314 // Get the cohorts in the specified contexts. 315 $cohortids = $DB->get_fieldset_select('cohort', 'id', $selectcontext, $contextparams); 316 317 if (empty($cohortids)) { 318 return; 319 } 320 321 list($cohortsql, $cohortparams) = $DB->get_in_or_equal($cohortids, SQL_PARAMS_NAMED); 322 $selectcohort = "cohortid {$cohortsql} AND userid = :userid"; 323 $params = ['userid' => $userid] + $cohortparams; 324 325 // Delete the tool_cohortroles records created for the userid. 326 $DB->delete_records_select('tool_cohortroles', $selectcohort, $params); 327 } 328 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body