2 // This file is part of Moodle - http://moodle.org/
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.
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/>.
18 * Privacy Subsystem implementation for 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();
38 require_once($CFG->dirroot
. '/notes/lib.php');
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
{
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(
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'
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
{
84 $contextlist = new contextlist();
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.
96 INNER JOIN {post} p ON p.courseid = c.instanceid AND c.contextlevel = :contextcoursewrittenby
97 WHERE p.module = 'notes'
98 AND p.usermodified = :usermodified";
101 'contextcoursewrittenby' => CONTEXT_COURSE
,
102 'usermodified' => $userid,
105 $contextlist->add_from_sql($sql, $params);
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}";
115 'contextcoursewrittenfor' => CONTEXT_COURSE
,
118 $params +
= $publishstateparams;
120 $contextlist->add_from_sql($sql, $params);
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) {
133 $context = $userlist->get_context();
135 if (!$context instanceof \context_course
) {
140 'instanceid' => $context->instanceid
143 $sql = "SELECT usermodified as userid
145 WHERE module = 'notes'
146 AND courseid = :instanceid";
148 $userlist->add_from_sql('userid', $sql, $params);
155 list($publishstatesql, $publishstateparams) = $DB->get_in_or_equal($publishstates, SQL_PARAMS_NAMED
);
156 $params +
= $publishstateparams;
158 $sql = "SELECT userid
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) {
176 if (empty($contextlist->count())) {
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,
189 p.usermodified as usermodified,
190 p.created as datecreated,
191 p.lastmodified as datemodified
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}";
199 'contextcourse' => CONTEXT_COURSE
,
200 'usermodified' => $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.
211 get_string('notes', 'notes'),
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);
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) {
239 if ($context->contextlevel
!= CONTEXT_COURSE
) {
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) {
254 $context = $userlist->get_context();
255 if ($context->contextlevel
!= CONTEXT_COURSE
) {
259 $userids = $userlist->get_userids();
260 if (empty($userids)) {
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) {
279 if (empty($contextlist->count())) {
283 $userid = $contextlist->get_user()->id
;
285 foreach ($contextlist->get_contexts() as $context) {
288 'courseid' => $context->instanceid
,
289 'usermodified' => $userid
292 $DB->delete_records('post', $conditions);