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
102 INNER JOIN {post} p ON p.courseid = c.instanceid AND c.contextlevel = :contextcoursewrittenfor
103 WHERE p.module = 'notes'
104 AND p.userid = :userid
105 AND p.publishstate {$publishstatesql}";
108 'contextcoursewrittenby' => CONTEXT_COURSE
,
109 'usermodified' => $userid,
110 'contextcoursewrittenfor' => CONTEXT_COURSE
,
113 $params +
= $publishstateparams;
115 $contextlist->add_from_sql($sql, $params);
121 * Get the list of users who have data within a context.
123 * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
125 public static function get_users_in_context(userlist
$userlist) {
128 $context = $userlist->get_context();
130 if (!$context instanceof \context_course
) {
135 'instanceid' => $context->instanceid
138 $sql = "SELECT usermodified as userid
140 WHERE module = 'notes'
141 AND courseid = :instanceid";
143 $userlist->add_from_sql('userid', $sql, $params);
150 list($publishstatesql, $publishstateparams) = $DB->get_in_or_equal($publishstates, SQL_PARAMS_NAMED
);
151 $params +
= $publishstateparams;
153 $sql = "SELECT userid
155 WHERE module = 'notes'
156 AND courseid = :instanceid
157 AND publishstate {$publishstatesql}";
159 $userlist->add_from_sql('userid', $sql, $params);
163 * Export personal data for the given approved_contextlist.
164 * User and context information is contained within the contextlist.
166 * @param approved_contextlist $contextlist a list of contexts approved for export.
168 public static function export_user_data(approved_contextlist
$contextlist) {
171 if (empty($contextlist->count())) {
175 $userid = $contextlist->get_user()->id
;
177 list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED
);
179 // Export all notes written by and written about the user, and organize it by the associated Course context(s).
180 $sql = "SELECT p.courseid as courseid,
181 p.content as content,
182 p.publishstate as publishstate,
184 p.usermodified as usermodified,
185 p.created as datecreated,
186 p.lastmodified as datemodified
188 INNER JOIN {post} p ON p.courseid = c.instanceid AND c.contextlevel = :contextcourse
189 WHERE p.module = 'notes'
190 AND (p.usermodified = :usermodified OR p.userid = :userid)
191 AND c.id {$contextsql}";
194 'contextcourse' => CONTEXT_COURSE
,
195 'usermodified' => $userid,
198 $params +
= $contextparams;
200 $notes = $DB->get_recordset_sql($sql, $params);
201 foreach ($notes as $note) {
202 $contextcourse = \context_course
::instance($note->courseid
);
204 // The exported notes will be organized in {Course Context}/Notes/{publishstate}/usernote-{userid}.json.
206 get_string('notes', 'notes'),
210 $name = 'usernote-' . transform
::user($note->userid
);
212 $notecontent = (object) [
213 'content' => $note->content
,
214 'publishstate' => $note->publishstate
,
215 'userid' => transform
::user($note->userid
),
216 'usermodified' => transform
::user($note->usermodified
),
217 'datecreated' => transform
::datetime($note->datecreated
),
218 'datemodified' => transform
::datetime($note->datemodified
)
221 writer
::with_context($contextcourse)->export_related_data($subcontext, $name, $notecontent);
227 * Delete all data for all users in the specified context.
229 * @param \context $context the context to delete in.
231 public static function delete_data_for_all_users_in_context(\context
$context) {
234 if ($context->contextlevel
!= CONTEXT_COURSE
) {
238 $DB->delete_records('post', ['module' => 'notes', 'courseid' => $context->instanceid
]);
242 * Delete multiple users within a single context.
244 * @param approved_userlist $userlist The approved context and user information to delete information for.
246 public static function delete_data_for_users(approved_userlist
$userlist) {
249 $context = $userlist->get_context();
250 if ($context->contextlevel
!= CONTEXT_COURSE
) {
254 $userids = $userlist->get_userids();
255 if (empty($userids)) {
259 list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED
);
260 $select = "module = :module AND courseid = :courseid AND usermodified {$usersql}";
261 $params = ['module' => 'notes', 'courseid' => $context->instanceid
] +
$userparams;
263 $DB->delete_records_select('post', $select, $params);
267 * Delete all user data for the specified user, in the specified contexts.
269 * @param approved_contextlist $contextlist a list of contexts approved for deletion.
271 public static function delete_data_for_user(approved_contextlist
$contextlist) {
274 if (empty($contextlist->count())) {
278 $userid = $contextlist->get_user()->id
;
280 foreach ($contextlist->get_contexts() as $context) {
283 'courseid' => $context->instanceid
,
284 'usermodified' => $userid
287 $DB->delete_records('post', $conditions);