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 core_repository. 19 * 20 * @package core_repository 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 core_repository\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 core_repository 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 $collection->add_database_table( 57 'repository_instances', 58 [ 59 'name' => 'privacy:metadata:repository_instances:name', 60 'typeid' => 'privacy:metadata:repository_instances:typeid', 61 'userid' => 'privacy:metadata:repository_instances:userid', 62 'username' => 'privacy:metadata:repository_instances:username', 63 'password' => 'privacy:metadata:repository_instances:password', 64 'timecreated' => 'privacy:metadata:repository_instances:timecreated', 65 'timemodified' => 'privacy:metadata:repository_instances:timemodified', 66 ], 67 'privacy:metadata:repository_instances' 68 ); 69 70 $collection->add_plugintype_link('repository', [], 'privacy:metadata:repository'); 71 72 return $collection; 73 } 74 75 /** 76 * Get the list of contexts that contain user information for the specified user. 77 * 78 * @param int $userid The user to search. 79 * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin. 80 */ 81 public static function get_contexts_for_userid(int $userid) : contextlist { 82 $contextlist = new contextlist(); 83 84 // The repository_instances data is associated at the user context level, so retrieve the user's context id. 85 $sql = "SELECT c.id 86 FROM {repository_instances} ri 87 JOIN {context} c ON c.instanceid = ri.userid AND c.contextlevel = :contextuser 88 WHERE ri.userid = :userid 89 GROUP BY c.id"; 90 91 $params = [ 92 'contextuser' => CONTEXT_USER, 93 'userid' => $userid 94 ]; 95 96 $contextlist->add_from_sql($sql, $params); 97 return $contextlist; 98 } 99 100 /** 101 * Get the list of users within a specific context. 102 * 103 * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. 104 */ 105 public static function get_users_in_context(userlist $userlist) { 106 $context = $userlist->get_context(); 107 108 if (!$context instanceof \context_user) { 109 return; 110 } 111 112 $sql = "SELECT userid 113 FROM {repository_instances} 114 WHERE userid = ?"; 115 $params = [$context->instanceid]; 116 117 $userlist->add_from_sql('userid', $sql, $params); 118 } 119 120 /** 121 * Export all user data for the specified user, in the specified contexts. 122 * 123 * @param approved_contextlist $contextlist The approved contexts to export information for. 124 */ 125 public static function export_user_data(approved_contextlist $contextlist) { 126 global $DB; 127 128 // If the user has repository_instances data, then only the User context should be present so get the first context. 129 $contexts = $contextlist->get_contexts(); 130 if (count($contexts) == 0) { 131 return; 132 } 133 $context = reset($contexts); 134 135 // Sanity check that context is at the User context level, then get the userid. 136 if ($context->contextlevel !== CONTEXT_USER) { 137 return; 138 } 139 $userid = $context->instanceid; 140 141 $sql = "SELECT DISTINCT 142 ri.id as id, 143 r.type as type, 144 ri.name as name, 145 ri.timecreated as timecreated, 146 ri.timemodified as timemodified 147 FROM {repository_instances} ri 148 JOIN {repository} r ON r.id = ri.typeid 149 WHERE ri.userid = :userid"; 150 151 $params = [ 152 'userid' => $userid 153 ]; 154 155 $repositoryinstances = $DB->get_records_sql($sql, $params); 156 157 foreach ($repositoryinstances as $repositoryinstance) { 158 // The repository_instances data export is organised in: {User Context}/Repository plug-ins/{Plugin Name}/data.json. 159 $subcontext = [ 160 get_string('plugin', 'core_repository'), 161 get_string('pluginname', 'repository_' . $repositoryinstance->type) 162 ]; 163 164 $data = (object) [ 165 'type' => $repositoryinstance->type, 166 'name' => $repositoryinstance->name, 167 'timecreated' => transform::datetime($repositoryinstance->timecreated), 168 'timemodified' => transform::datetime($repositoryinstance->timemodified) 169 ]; 170 171 writer::with_context($context)->export_data($subcontext, $data); 172 } 173 } 174 175 /** 176 * Delete all data for all users in the specified context. 177 * 178 * @param context $context The specific context to delete data for. 179 */ 180 public static function delete_data_for_all_users_in_context(\context $context) { 181 global $DB; 182 183 // Sanity check that context is at the User context level, then get the userid. 184 if ($context->contextlevel !== CONTEXT_USER) { 185 return; 186 } 187 $userid = $context->instanceid; 188 189 // Delete the repository_instances records created for the userid. 190 $DB->delete_records('repository_instances', ['userid' => $userid]); 191 } 192 193 /** 194 * Delete multiple users within a single context. 195 * 196 * @param approved_userlist $userlist The approved context and user information to delete information for. 197 */ 198 public static function delete_data_for_users(approved_userlist $userlist) { 199 global $DB; 200 201 $context = $userlist->get_context(); 202 203 if ($context instanceof \context_user) { 204 $DB->delete_records('repository_instances', ['userid' => $context->instanceid]); 205 } 206 } 207 208 /** 209 * Delete all user data for the specified user, in the specified contexts. 210 * 211 * @param approved_contextlist $contextlist The approved contexts and user information to delete information for. 212 */ 213 public static function delete_data_for_user(approved_contextlist $contextlist) { 214 global $DB; 215 216 // If the user has repository_instances data, then only the User context should be present so get the first context. 217 $contexts = $contextlist->get_contexts(); 218 if (count($contexts) == 0) { 219 return; 220 } 221 $context = reset($contexts); 222 223 // Sanity check that context is at the User context level, then get the userid. 224 if ($context->contextlevel !== CONTEXT_USER) { 225 return; 226 } 227 $userid = $context->instanceid; 228 229 // Delete the repository_instances records created for the userid. 230 $DB->delete_records('repository_instances', ['userid' => $userid]); 231 } 232 233 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body