See Release Notes
Long Term Support Release
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 provider implementation for core_contentbank. 19 * 20 * @package core_contentbank 21 * @copyright 2020 Amaia Anabitarte <amaia@moodle.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace core_contentbank\privacy; 26 27 use core_privacy\local\metadata\collection; 28 use core_privacy\local\request\approved_contextlist; 29 use core_privacy\local\request\contextlist; 30 use core_privacy\local\request\transform; 31 use core_privacy\local\request\writer; 32 use core_privacy\local\request\userlist; 33 use core_privacy\local\request\approved_userlist; 34 use context_system; 35 use context_coursecat; 36 use context_course; 37 38 /** 39 * Privacy provider implementation for core_contentbank. 40 * 41 * @copyright 2020 Amaia Anabitarte <amaia@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 \core_privacy\local\request\user_preference_provider { 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('contentbank_content', [ 58 'name' => 'privacy:metadata:content:name', 59 'contenttype' => 'privacy:metadata:content:contenttype', 60 'usercreated' => 'privacy:metadata:content:usercreated', 61 'usermodified' => 'privacy:metadata:content:usermodified', 62 'timecreated' => 'privacy:metadata:content:timecreated', 63 'timemodified' => 'privacy:metadata:content:timemodified', 64 ], 'privacy:metadata:contentbankcontent'); 65 66 return $collection; 67 } 68 69 /** 70 * Export all user preferences for the contentbank 71 * 72 * @param int $userid The userid of the user whose data is to be exported. 73 */ 74 public static function export_user_preferences(int $userid) { 75 $preference = get_user_preferences('core_contentbank_view_list', null, $userid); 76 if (isset($preference)) { 77 writer::export_user_preference( 78 'core_contentbank', 79 'core_contentbank_view_list', 80 $preference, 81 get_string('privacy:request:preference:set', 'core_contentbank', (object) [ 82 'name' => 'core_contentbank_view_list', 83 'value' => $preference, 84 ]) 85 ); 86 } 87 } 88 89 /** 90 * Get the list of contexts that contain user information for the specified user. 91 * 92 * @param int $userid The user to search. 93 * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin. 94 */ 95 public static function get_contexts_for_userid(int $userid): contextlist { 96 $sql = "SELECT DISTINCT ctx.id 97 FROM {context} ctx 98 JOIN {contentbank_content} cb 99 ON cb.contextid = ctx.id 100 WHERE cb.usercreated = :userid 101 AND (ctx.contextlevel = :contextlevel1 102 OR ctx.contextlevel = :contextlevel2 103 OR ctx.contextlevel = :contextlevel3)"; 104 105 $params = [ 106 'userid' => $userid, 107 'contextlevel1' => CONTEXT_SYSTEM, 108 'contextlevel2' => CONTEXT_COURSECAT, 109 'contextlevel3' => CONTEXT_COURSE, 110 ]; 111 112 $contextlist = new contextlist(); 113 $contextlist->add_from_sql($sql, $params); 114 115 return $contextlist; 116 } 117 118 /** 119 * Get the list of users within a specific context. 120 * 121 * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. 122 */ 123 public static function get_users_in_context(userlist $userlist) { 124 $context = $userlist->get_context(); 125 126 $allowedcontextlevels = [ 127 CONTEXT_SYSTEM, 128 CONTEXT_COURSECAT, 129 CONTEXT_COURSE, 130 ]; 131 132 if (!in_array($context->contextlevel, $allowedcontextlevels)) { 133 return; 134 } 135 136 $sql = "SELECT cb.usercreated as userid 137 FROM {contentbank_content} cb 138 WHERE cb.contextid = :contextid"; 139 140 $params = [ 141 'contextid' => $context->id 142 ]; 143 144 $userlist->add_from_sql('userid', $sql, $params); 145 } 146 147 /** 148 * Export all user data for the specified user, in the specified contexts. 149 * 150 * @param approved_contextlist $contextlist The approved contexts to export information for. 151 */ 152 public static function export_user_data(approved_contextlist $contextlist) { 153 global $DB; 154 155 // Remove contexts different from SYSTEM, COURSECAT or COURSE. 156 $contextids = array_reduce($contextlist->get_contexts(), function($carry, $context) { 157 if ($context->contextlevel == CONTEXT_SYSTEM || $context->contextlevel == CONTEXT_COURSECAT 158 || $context->contextlevel == CONTEXT_COURSE) { 159 $carry[] = $context->id; 160 } 161 return $carry; 162 }, []); 163 164 if (empty($contextids)) { 165 return; 166 } 167 168 $userid = $contextlist->get_user()->id; 169 170 list($contextsql, $contextparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED); 171 // Retrieve the contentbank_content records created for the user. 172 $sql = "SELECT cb.id, 173 cb.name, 174 cb.contenttype, 175 cb.usercreated, 176 cb.usermodified, 177 cb.timecreated, 178 cb.timemodified, 179 cb.contextid 180 FROM {contentbank_content} cb 181 WHERE cb.usercreated = :userid 182 AND cb.contextid {$contextsql} 183 ORDER BY cb.contextid"; 184 185 $params = ['userid' => $userid] + $contextparams; 186 187 $contents = $DB->get_recordset_sql($sql, $params); 188 $data = []; 189 $lastcontextid = null; 190 $subcontext = [ 191 get_string('name', 'core_contentbank'), 192 ]; 193 foreach ($contents as $content) { 194 // The core_contentbank data export is organised in: 195 // {Sytem|Course Category|Course Context Level}/Content/data.json. 196 if ($lastcontextid && $lastcontextid != $content->contextid) { 197 $context = \context::instance_by_id($lastcontextid); 198 writer::with_context($context)->export_data($subcontext, (object)$data); 199 $data = []; 200 } 201 $data[] = (object) [ 202 'name' => $content->name, 203 'contenttype' => $content->contenttype, 204 'usercreated' => transform::user($content->usercreated), 205 'usermodified' => transform::user($content->usermodified), 206 'timecreated' => transform::datetime($content->timecreated), 207 'timemodified' => transform::datetime($content->timemodified) 208 ]; 209 $lastcontextid = $content->contextid; 210 211 // The core_contentbank files export is organised in: 212 // {Sytem|Course Category|Course Context Level}/Content/_files/public/_itemid/filename. 213 $context = \context::instance_by_id($lastcontextid); 214 writer::with_context($context)->export_area_files($subcontext, 'contentbank', 'public', $content->id); 215 } 216 if (!empty($data)) { 217 $context = \context::instance_by_id($lastcontextid); 218 writer::with_context($context)->export_data($subcontext, (object)$data); 219 } 220 $contents->close(); 221 } 222 223 /** 224 * Delete all data for all users in the specified context. 225 * 226 * @param context $context The specific context to delete data for. 227 */ 228 public static function delete_data_for_all_users_in_context(\context $context) { 229 global $DB; 230 231 if (!$context instanceof context_system && !$context instanceof context_coursecat 232 && !$context instanceof context_course) { 233 return; 234 } 235 236 static::delete_data($context, []); 237 } 238 239 /** 240 * Delete multiple users within a single context. 241 * 242 * @param approved_userlist $userlist The approved context and user information to delete information for. 243 */ 244 public static function delete_data_for_users(approved_userlist $userlist) { 245 $context = $userlist->get_context(); 246 247 if (!$context instanceof context_system && !$context instanceof context_coursecat 248 && !$context instanceof context_course) { 249 return; 250 } 251 252 static::delete_data($context, $userlist->get_userids()); 253 } 254 255 /** 256 * Delete all user data for the specified user, in the specified contexts. 257 * 258 * @param approved_contextlist $contextlist The approved contexts and user information to delete information for. 259 */ 260 public static function delete_data_for_user(approved_contextlist $contextlist) { 261 if (empty($contextlist->count())) { 262 return; 263 } 264 265 $userid = $contextlist->get_user()->id; 266 foreach ($contextlist->get_contexts() as $context) { 267 if (!$context instanceof context_system && !$context instanceof context_coursecat 268 && !$context instanceof context_course) { 269 continue; 270 } 271 static::delete_data($context, [$userid]); 272 } 273 } 274 275 /** 276 * Delete data related to a context and users (if defined). 277 * 278 * @param context $context A context. 279 * @param array $userids The user IDs. 280 */ 281 protected static function delete_data(\context $context, array $userids) { 282 global $DB; 283 284 $params = ['contextid' => $context->id]; 285 $select = 'contextid = :contextid'; 286 287 // Delete the Content Bank files. 288 if (!empty($userids)) { 289 list($insql, $inparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED); 290 $params += $inparams; 291 $select .= ' AND usercreated '.$insql; 292 } 293 $fs = get_file_storage(); 294 $contents = $DB->get_records_select('contentbank_content', 295 $select, $params); 296 foreach ($contents as $content) { 297 $fs->delete_area_files($content->contextid, 'contentbank', 'public', $content->id); 298 } 299 300 // Delete all the contents. 301 $DB->delete_records_select('contentbank_content', $select, $params); 302 } 303 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body