weekly release 4.5dev
[moodle.git] / notes / classes / privacy / provider.php
blobd97837e6fa3b677062beb65c5ecfa9f5f386953f
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.
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/>.
17 /**
18 * Privacy Subsystem implementation for core_notes.
20 * @package core_notes
21 * @copyright 2018 Zig Tan <zig@moodle.com>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 namespace core_notes\privacy;
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;
35 defined('MOODLE_INTERNAL') || die();
37 global $CFG;
38 require_once($CFG->dirroot . '/notes/lib.php');
40 /**
41 * Implementation of the privacy subsystem plugin provider for core_notes.
43 * @copyright 2018 Zig Tan <zig@moodle.com>
44 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
46 class provider implements
47 \core_privacy\local\metadata\provider,
48 \core_privacy\local\request\core_userlist_provider,
49 \core_privacy\local\request\plugin\provider {
51 /**
52 * Return the fields which contain personal data.
54 * @param collection $items a reference to the collection to use to store the metadata.
55 * @return collection the updated collection of metadata items.
57 public static function get_metadata(collection $items): collection {
58 // The core_notes components utilises the shared mdl_post table.
59 $items->add_database_table(
60 'post',
62 'content' => 'privacy:metadata:core_notes:content',
63 'courseid' => 'privacy:metadata:core_notes:courseid',
64 'created' => 'privacy:metadata:core_notes:created',
65 'lastmodified' => 'privacy:metadata:core_notes:lastmodified',
66 'publishstate' => 'privacy:metadata:core_notes:publishstate',
67 'userid' => 'privacy:metadata:core_notes:userid'
69 'privacy:metadata:core_notes'
72 return $items;
75 /**
76 * Get the list of contexts that contain user information for the specified user.
78 * @param int $userid the userid.
79 * @return contextlist the list of contexts containing user info for the user.
81 public static function get_contexts_for_userid(int $userid): contextlist {
82 global $DB;
84 $contextlist = new contextlist();
86 $publishstates = [
87 NOTES_STATE_PUBLIC,
88 NOTES_STATE_SITE
90 list($publishstatesql, $publishstateparams) = $DB->get_in_or_equal($publishstates, SQL_PARAMS_NAMED);
92 // Retrieve all the Course contexts associated with notes written by the user, and also written about the user.
93 // Only notes written about the user that are public or site wide will be exported.
94 $sql = "SELECT c.id
95 FROM {context} c
96 INNER JOIN {post} p ON p.courseid = c.instanceid AND c.contextlevel = :contextcoursewrittenby
97 WHERE p.module = 'notes'
98 AND p.usermodified = :usermodified";
100 $params = [
101 'contextcoursewrittenby' => CONTEXT_COURSE,
102 'usermodified' => $userid,
105 $contextlist->add_from_sql($sql, $params);
107 $sql = "SELECT c.id
108 FROM {context} c
109 INNER JOIN {post} p ON p.courseid = c.instanceid AND c.contextlevel = :contextcoursewrittenfor
110 WHERE p.module = 'notes'
111 AND p.userid = :userid
112 AND p.publishstate {$publishstatesql}";
114 $params = [
115 'contextcoursewrittenfor' => CONTEXT_COURSE,
116 'userid' => $userid
118 $params += $publishstateparams;
120 $contextlist->add_from_sql($sql, $params);
122 return $contextlist;
126 * Get the list of users who have data within a context.
128 * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
130 public static function get_users_in_context(userlist $userlist) {
131 global $DB;
133 $context = $userlist->get_context();
135 if (!$context instanceof \context_course) {
136 return;
139 $params = [
140 'instanceid' => $context->instanceid
143 $sql = "SELECT usermodified as userid
144 FROM {post}
145 WHERE module = 'notes'
146 AND courseid = :instanceid";
148 $userlist->add_from_sql('userid', $sql, $params);
150 $publishstates = [
151 NOTES_STATE_PUBLIC,
152 NOTES_STATE_SITE
155 list($publishstatesql, $publishstateparams) = $DB->get_in_or_equal($publishstates, SQL_PARAMS_NAMED);
156 $params += $publishstateparams;
158 $sql = "SELECT userid
159 FROM {post}
160 WHERE module = 'notes'
161 AND courseid = :instanceid
162 AND publishstate {$publishstatesql}";
164 $userlist->add_from_sql('userid', $sql, $params);
168 * Export personal data for the given approved_contextlist.
169 * User and context information is contained within the contextlist.
171 * @param approved_contextlist $contextlist a list of contexts approved for export.
173 public static function export_user_data(approved_contextlist $contextlist) {
174 global $DB;
176 if (empty($contextlist->count())) {
177 return;
180 $userid = $contextlist->get_user()->id;
182 list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
184 // Export all notes written by and written about the user, and organize it by the associated Course context(s).
185 $sql = "SELECT p.courseid as courseid,
186 p.content as content,
187 p.publishstate as publishstate,
188 p.userid as userid,
189 p.usermodified as usermodified,
190 p.created as datecreated,
191 p.lastmodified as datemodified
192 FROM {context} c
193 INNER JOIN {post} p ON p.courseid = c.instanceid AND c.contextlevel = :contextcourse
194 WHERE p.module = 'notes'
195 AND (p.usermodified = :usermodified OR p.userid = :userid)
196 AND c.id {$contextsql}";
198 $params = [
199 'contextcourse' => CONTEXT_COURSE,
200 'usermodified' => $userid,
201 'userid' => $userid
203 $params += $contextparams;
205 $notes = $DB->get_recordset_sql($sql, $params);
206 foreach ($notes as $note) {
207 $contextcourse = \context_course::instance($note->courseid);
209 // The exported notes will be organized in {Course Context}/Notes/{publishstate}/usernote-{userid}.json.
210 $subcontext = [
211 get_string('notes', 'notes'),
212 $note->publishstate
215 $name = 'usernote-' . transform::user($note->userid);
217 $notecontent = (object) [
218 'content' => $note->content,
219 'publishstate' => $note->publishstate,
220 'userid' => transform::user($note->userid),
221 'usermodified' => transform::user($note->usermodified),
222 'datecreated' => transform::datetime($note->datecreated),
223 'datemodified' => transform::datetime($note->datemodified)
226 writer::with_context($contextcourse)->export_related_data($subcontext, $name, $notecontent);
228 $notes->close();
232 * Delete all data for all users in the specified context.
234 * @param \context $context the context to delete in.
236 public static function delete_data_for_all_users_in_context(\context $context) {
237 global $DB;
239 if ($context->contextlevel != CONTEXT_COURSE) {
240 return;
243 $DB->delete_records('post', ['module' => 'notes', 'courseid' => $context->instanceid]);
247 * Delete multiple users within a single context.
249 * @param approved_userlist $userlist The approved context and user information to delete information for.
251 public static function delete_data_for_users(approved_userlist $userlist) {
252 global $DB;
254 $context = $userlist->get_context();
255 if ($context->contextlevel != CONTEXT_COURSE) {
256 return;
259 $userids = $userlist->get_userids();
260 if (empty($userids)) {
261 return;
264 list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
265 $select = "module = :module AND courseid = :courseid AND usermodified {$usersql}";
266 $params = ['module' => 'notes', 'courseid' => $context->instanceid] + $userparams;
268 $DB->delete_records_select('post', $select, $params);
272 * Delete all user data for the specified user, in the specified contexts.
274 * @param approved_contextlist $contextlist a list of contexts approved for deletion.
276 public static function delete_data_for_user(approved_contextlist $contextlist) {
277 global $DB;
279 if (empty($contextlist->count())) {
280 return;
283 $userid = $contextlist->get_user()->id;
285 foreach ($contextlist->get_contexts() as $context) {
286 $conditions = [
287 'module' => 'notes',
288 'courseid' => $context->instanceid,
289 'usermodified' => $userid
292 $DB->delete_records('post', $conditions);