Differences Between: [Versions 39 and 402]
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_grading 21 * @copyright 2018 Sara Arjona <sara@moodle.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace core_grading\privacy; 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 use \core_privacy\local\metadata\collection; 30 use \core_privacy\local\request\approved_contextlist; 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\manager; 35 36 /** 37 * Privacy class for requesting user data. 38 * 39 * @copyright 2018 Sara Arjona <sara@moodle.com> 40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 41 */ 42 class provider implements 43 \core_privacy\local\metadata\provider, 44 \core_privacy\local\request\plugin\provider, 45 \core_privacy\local\request\core_userlist_provider, 46 \core_privacy\local\request\subsystem\provider { 47 48 /** 49 * Returns meta data about this system. 50 * 51 * @param collection $collection The initialised collection to add items to. 52 * @return collection A listing of user data stored through this system. 53 */ 54 public static function get_metadata(collection $collection) : collection { 55 $collection->add_database_table('grading_definitions', [ 56 'method' => 'privacy:metadata:grading_definitions:method', 57 'areaid' => 'privacy:metadata:grading_definitions:areaid', 58 'name' => 'privacy:metadata:grading_definitions:name', 59 'description' => 'privacy:metadata:grading_definitions:description', 60 'status' => 'privacy:metadata:grading_definitions:status', 61 'copiedfromid' => 'privacy:metadata:grading_definitions:copiedfromid', 62 'timecopied' => 'privacy:metadata:grading_definitions:timecopied', 63 'timecreated' => 'privacy:metadata:grading_definitions:timecreated', 64 'usercreated' => 'privacy:metadata:grading_definitions:usercreated', 65 'timemodified' => 'privacy:metadata:grading_definitions:timemodified', 66 'usermodified' => 'privacy:metadata:grading_definitions:usermodified', 67 'options' => 'privacy:metadata:grading_definitions:options', 68 ], 'privacy:metadata:grading_definitions'); 69 70 $collection->add_database_table('grading_instances', [ 71 'raterid' => 'privacy:metadata:grading_instances:raterid', 72 'rawgrade' => 'privacy:metadata:grading_instances:rawgrade', 73 'status' => 'privacy:metadata:grading_instances:status', 74 'feedback' => 'privacy:metadata:grading_instances:feedback', 75 'feedbackformat' => 'privacy:metadata:grading_instances:feedbackformat', 76 'timemodified' => 'privacy:metadata:grading_instances:timemodified', 77 ], 'privacy:metadata:grading_instances'); 78 79 // Link to subplugin. 80 $collection->add_plugintype_link('gradingform', [], 'privacy:metadata:gradingformpluginsummary'); 81 82 return $collection; 83 } 84 85 /** 86 * Get the list of contexts that contain user information for the specified user. 87 * 88 * @param int $userid The user to search. 89 * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin. 90 */ 91 public static function get_contexts_for_userid(int $userid) : contextlist { 92 $contextlist = new contextlist(); 93 94 $sql = "SELECT c.id 95 FROM {context} c 96 JOIN {grading_areas} a ON a.contextid = c.id 97 JOIN {grading_definitions} d ON d.areaid = a.id 98 LEFT JOIN {grading_instances} i ON i.definitionid = d.id AND i.raterid = :raterid 99 WHERE c.contextlevel = :contextlevel 100 AND (d.usercreated = :usercreated OR d.usermodified = :usermodified OR i.id IS NOT NULL)"; 101 $params = [ 102 'usercreated' => $userid, 103 'usermodified' => $userid, 104 'raterid' => $userid, 105 'contextlevel' => CONTEXT_MODULE 106 ]; 107 $contextlist->add_from_sql($sql, $params); 108 109 return $contextlist; 110 } 111 112 /** 113 * Get the list of users who have data within a context. 114 * 115 * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. 116 */ 117 public static function get_users_in_context(\core_privacy\local\request\userlist $userlist) { 118 $context = $userlist->get_context(); 119 if ($context->contextlevel != CONTEXT_MODULE) { 120 return; 121 } 122 123 $params = ['contextid' => $context->id]; 124 125 $sql = "SELECT d.usercreated, d.usermodified 126 FROM {grading_definitions} d 127 JOIN {grading_areas} a ON a.id = d.areaid 128 WHERE a.contextid = :contextid"; 129 $userlist->add_from_sql('usercreated', $sql, $params); 130 $userlist->add_from_sql('usermodified', $sql, $params); 131 132 $sql = "SELECT i.raterid 133 FROM {grading_definitions} d 134 JOIN {grading_areas} a ON a.id = d.areaid 135 JOIN {grading_instances} i ON i.definitionid = d.id 136 WHERE a.contextid = :contextid"; 137 $userlist->add_from_sql('raterid', $sql, $params); 138 } 139 140 /** 141 * Export all user data for the specified user, in the specified contexts. 142 * 143 * @param approved_contextlist $contextlist The approved contexts to export information for. 144 */ 145 public static function export_user_data(approved_contextlist $contextlist) { 146 // Remove contexts different from MODULE. 147 $contexts = array_reduce($contextlist->get_contexts(), function($carry, $context) { 148 if ($context->contextlevel == CONTEXT_MODULE) { 149 $carry[] = $context; 150 } 151 return $carry; 152 }, []); 153 154 if (empty($contexts)) { 155 return; 156 } 157 158 $userid = $contextlist->get_user()->id; 159 $subcontext = [get_string('gradingmethod', 'grading')]; 160 foreach ($contexts as $context) { 161 // Export grading definitions created or modified on this context. 162 self::export_definitions($context, $subcontext, $userid); 163 } 164 } 165 166 /** 167 * Export all user data related to a context and itemid. 168 * 169 * @param \context $context Context to export on. 170 * @param int $itemid Item ID to export on. 171 * @param array $subcontext Directory location to export to. 172 */ 173 public static function export_item_data(\context $context, int $itemid, array $subcontext) { 174 global $DB; 175 176 $sql = "SELECT gi.id AS instanceid, gd.id AS definitionid, gd.method 177 FROM {grading_areas} ga 178 JOIN {grading_definitions} gd ON gd.areaid = ga.id 179 JOIN {grading_instances} gi ON gi.definitionid = gd.id AND gi.itemid = :itemid 180 WHERE ga.contextid = :contextid"; 181 $params = [ 182 'itemid' => $itemid, 183 'contextid' => $context->id, 184 ]; 185 $records = $DB->get_recordset_sql($sql, $params); 186 foreach ($records as $record) { 187 $instancedata = manager::component_class_callback( 188 "gradingform_{$record->method}", 189 gradingform_provider_v2::class, 190 'export_gradingform_instance_data', 191 [$context, $record->instanceid, $subcontext] 192 ); 193 } 194 $records->close(); 195 } 196 197 /** 198 * Deletes all user data related to a context and possibly an itemid. 199 * 200 * @param \context $context The context to delete on. 201 * @param int|null $itemid An optional item ID to refine the deletion. 202 */ 203 public static function delete_instance_data(\context $context, int $itemid = null) { 204 if (is_null($itemid)) { 205 self::delete_data_for_instances($context); 206 } else { 207 self::delete_data_for_instances($context, [$itemid]); 208 } 209 } 210 211 /** 212 * Deletes all user data related to a context and possibly itemids. 213 * 214 * @param \context $context The context to delete on. 215 * @param array $itemids An optional list of item IDs to refine the deletion. 216 */ 217 public static function delete_data_for_instances(\context $context, array $itemids = []) { 218 global $DB; 219 $itemsql = ''; 220 $params = ['contextid' => $context->id]; 221 if (!empty($itemids)) { 222 list($itemsql, $itemparams) = $DB->get_in_or_equal($itemids, SQL_PARAMS_NAMED); 223 $params = array_merge($params, $itemparams); 224 $itemsql = "AND itemid $itemsql"; 225 } 226 $sql = "SELECT gi.id AS instanceid, gd.id, gd.method 227 FROM {grading_definitions} gd 228 JOIN {grading_instances} gi ON gi.definitionid = gd.id 229 JOIN {grading_areas} ga ON ga.id = gd.areaid 230 WHERE ga.contextid = :contextid $itemsql"; 231 $records = $DB->get_records_sql($sql, $params); 232 if ($records) { 233 $firstrecord = current($records); 234 $method = $firstrecord->method; 235 $instanceids = array_map(function($record) { 236 return $record->instanceid; 237 }, $records); 238 manager::component_class_callback( 239 "gradingform_{$method}", 240 gradingform_provider_v2::class, 241 'delete_gradingform_for_instances', 242 [$instanceids]); 243 // Delete grading_instances rows. 244 $DB->delete_records_list('grading_instances', 'id', $instanceids); 245 } 246 } 247 248 /** 249 * Exports the data related to grading definitions within the specified context/subcontext. 250 * 251 * @param \context $context Context owner of the data. 252 * @param array $subcontext Subcontext owner of the data. 253 * @param int $userid The user whose information is to be exported. 254 */ 255 protected static function export_definitions(\context $context, array $subcontext, int $userid = 0) { 256 global $DB; 257 258 $join = "JOIN {grading_areas} a ON a.id = d.areaid 259 JOIN {context} c ON a.contextid = c.id AND c.contextlevel = :contextlevel"; 260 $select = 'a.contextid = :contextid'; 261 $params = [ 262 'contextlevel' => CONTEXT_MODULE, 263 'contextid' => $context->id 264 ]; 265 266 if (!empty($userid)) { 267 $join .= ' LEFT JOIN {grading_instances} i ON i.definitionid = d.id AND i.raterid = :raterid'; 268 $select .= ' AND (usercreated = :usercreated 269 OR usermodified = :usermodified OR i.id IS NOT NULL)'; 270 $params['usercreated'] = $userid; 271 $params['usermodified'] = $userid; 272 $params['raterid'] = $userid; 273 } 274 275 $sql = "SELECT gd.id, 276 gd.method, 277 gd.name, 278 gd.description, 279 gd.timecopied, 280 gd.timecreated, 281 gd.usercreated, 282 gd.timemodified, 283 gd.usermodified 284 FROM ( 285 SELECT DISTINCT d.id 286 FROM {grading_definitions} d 287 $join 288 WHERE $select 289 ) ids 290 JOIN {grading_definitions} gd ON gd.id = ids.id"; 291 $definitions = $DB->get_recordset_sql($sql, $params); 292 $defdata = []; 293 foreach ($definitions as $definition) { 294 $tmpdata = [ 295 'method' => $definition->method, 296 'name' => $definition->name, 297 'description' => $definition->description, 298 'timecreated' => transform::datetime($definition->timecreated), 299 'usercreated' => transform::user($definition->usercreated), 300 'timemodified' => transform::datetime($definition->timemodified), 301 'usermodified' => transform::user($definition->usermodified), 302 ]; 303 if (!empty($definition->timecopied)) { 304 $tmpdata['timecopied'] = transform::datetime($definition->timecopied); 305 } 306 307 $defdata[] = (object) $tmpdata; 308 309 // Export grading_instances information. 310 self::export_grading_instances($context, $subcontext, $definition->id, $userid); 311 } 312 $definitions->close(); 313 314 if (!empty($defdata)) { 315 $data = (object) [ 316 'definitions' => $defdata, 317 ]; 318 319 writer::with_context($context)->export_data($subcontext, $data); 320 } 321 } 322 323 /** 324 * Exports the data related to grading instances within the specified definition. 325 * 326 * @param \context $context Context owner of the data. 327 * @param array $subcontext Subcontext owner of the data. 328 * @param int $definitionid The definition ID whose grading instance information is to be exported. 329 * @param int $userid The user whose information is to be exported. 330 */ 331 protected static function export_grading_instances(\context $context, array $subcontext, int $definitionid, int $userid = 0) { 332 global $DB; 333 334 $params = ['definitionid' => $definitionid]; 335 if (!empty($userid)) { 336 $params['raterid'] = $userid; 337 } 338 $instances = $DB->get_recordset('grading_instances', $params); 339 $instancedata = []; 340 foreach ($instances as $instance) { 341 // TODO: Get the status name (instead of the ID). 342 $tmpdata = [ 343 'rawgrade' => $instance->rawgrade, 344 'status' => $instance->status, 345 'feedback' => $instance->feedback, 346 'feedbackformat' => $instance->feedbackformat, 347 'timemodified' => transform::datetime($instance->timemodified), 348 ]; 349 $instancedata[] = (object) $tmpdata; 350 } 351 $instances->close(); 352 353 if (!empty($instancedata)) { 354 $data = (object) [ 355 'instances' => $instancedata, 356 ]; 357 358 writer::with_context($context)->export_related_data($subcontext, 'gradinginstances', $data); 359 } 360 } 361 362 /** 363 * No deletion of the advanced grading is done. 364 * 365 * @param \context $context the context to delete in. 366 */ 367 public static function delete_data_for_all_users_in_context(\context $context) { 368 // The only information left to be deleted here is the grading definitions. Currently we are not deleting these. 369 } 370 371 /** 372 * Deletion of data in this provider is only related to grades and so can not be 373 * deleted for the creator of the advanced grade criteria. 374 * 375 * @param approved_contextlist $contextlist a list of contexts approved for deletion. 376 */ 377 public static function delete_data_for_user(approved_contextlist $contextlist) { 378 // The only information left to be deleted here is the grading definitions. Currently we are not deleting these. 379 } 380 381 /** 382 * Delete multiple users within a single context. 383 * 384 * @param approved_userlist $userlist The approved context and user information to delete information for. 385 */ 386 public static function delete_data_for_users(\core_privacy\local\request\approved_userlist $userlist) { 387 // The only information left to be deleted here is the grading definitions. Currently we are not deleting these. 388 } 389 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body