on-demand release 3.6dev+
[moodle.git] / admin / tool / policy / classes / privacy / provider.php
CommitLineData
24966a26
SA
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 Subsystem implementation for tool_policy.
19 *
20 * @package tool_policy
21 * @copyright 2018 Sara Arjona <sara@moodle.com>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25namespace tool_policy\privacy;
26
27use core_privacy\local\metadata\collection;
28use core_privacy\local\request\approved_contextlist;
29use core_privacy\local\request\contextlist;
432a90f1
MG
30use core_privacy\local\request\moodle_content_writer;
31use core_privacy\local\request\transform;
32use core_privacy\local\request\writer;
24966a26
SA
33
34defined('MOODLE_INTERNAL') || die();
35
36/**
37 * Implementation of the privacy subsystem plugin provider for the policy tool.
38 *
39 * @copyright 2018 Sara Arjona <sara@moodle.com>
40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41 */
42class provider implements
43 // This tool stores user data.
44 \core_privacy\local\metadata\provider,
45
46 // This tool may provide access to and deletion of user data.
47 \core_privacy\local\request\plugin\provider {
48
49 /**
50 * Return the fields which contain personal data.
51 *
827c8e98
SA
52 * @param collection $collection The initialised collection to add items to.
53 * @return collection A listing of user data stored through this system.
24966a26 54 */
827c8e98
SA
55 public static function get_metadata(collection $collection) : collection {
56 $collection->add_database_table(
24966a26
SA
57 'tool_policy_acceptances',
58 [
59 'policyversionid' => 'privacy:metadata:acceptances:policyversionid',
60 'userid' => 'privacy:metadata:acceptances:userid',
61 'status' => 'privacy:metadata:acceptances:status',
62 'lang' => 'privacy:metadata:acceptances:lang',
63 'usermodified' => 'privacy:metadata:acceptances:usermodified',
64 'timecreated' => 'privacy:metadata:acceptances:timecreated',
65 'timemodified' => 'privacy:metadata:acceptances:timemodified',
66 'note' => 'privacy:metadata:acceptances:note',
67 ],
68 'privacy:metadata:acceptances'
69 );
70
827c8e98
SA
71 $collection->add_database_table(
72 'tool_policy_versions',
73 [
74 'name' => 'privacy:metadata:versions:name',
75 'type' => 'privacy:metadata:versions:type',
76 'audience' => 'privacy:metadata:versions:audience',
77 'archived' => 'privacy:metadata:versions:archived',
78 'usermodified' => 'privacy:metadata:versions:usermodified',
79 'timecreated' => 'privacy:metadata:versions:timecreated',
80 'timemodified' => 'privacy:metadata:versions:timemodified',
81 'policyid' => 'privacy:metadata:versions:policyid',
82 'revision' => 'privacy:metadata:versions:revision',
83 'summary' => 'privacy:metadata:versions:summary',
84 'summaryformat' => 'privacy:metadata:versions:summaryformat',
85 'content' => 'privacy:metadata:versions:content',
86 'contentformat' => 'privacy:metadata:versions:contentformat',
87 ],
88 'privacy:metadata:versions'
89 );
90
91 $collection->add_subsystem_link('core_files', [], 'privacy:metadata:subsystem:corefiles');
92
93 return $collection;
24966a26
SA
94 }
95
96 /**
97 * Get the list of contexts that contain user information for the specified user.
98 *
99 * @param int $userid The userid.
100 * @return contextlist The list of contexts containing user info for the user.
101 */
102 public static function get_contexts_for_userid(int $userid) : contextlist {
432a90f1 103 $contextlist = new contextlist();
827c8e98 104
f63745ea 105 // Policies a user has modified.
827c8e98
SA
106 $sql = "SELECT c.id
107 FROM {context} c
f63745ea
AN
108 JOIN {tool_policy_versions} v ON v.usermodified = :userid
109 WHERE c.contextlevel = :contextlevel";
110 $params = [
111 'contextlevel' => CONTEXT_SYSTEM,
112 'userid' => $userid,
113 ];
114 $contextlist->add_from_sql($sql, $params);
115
116 // Policies a user has accepted.
117 $sql = "SELECT c.id
118 FROM {context} c
119 JOIN {tool_policy_acceptances} a ON c.instanceid = a.userid
120 WHERE
121 c.contextlevel = :contextlevel
122 AND (
123 a.userid = :userid OR a.usermodified = :usermodified
124 )";
827c8e98
SA
125 $params = [
126 'contextlevel' => CONTEXT_USER,
f63745ea 127 'userid' => $userid,
827c8e98 128 'usermodified' => $userid,
827c8e98
SA
129 ];
130 $contextlist->add_from_sql($sql, $params);
131
432a90f1 132 return $contextlist;
24966a26
SA
133 }
134
135 /**
136 * Export personal data for the given approved_contextlist. User and context information is contained within the contextlist.
137 *
138 * @param approved_contextlist $contextlist A list of contexts approved for export.
139 */
140 public static function export_user_data(approved_contextlist $contextlist) {
432a90f1 141 global $DB;
827c8e98 142
827c8e98 143 // Export user agreements.
5e84f521 144 foreach ($contextlist->get_contexts() as $context) {
f63745ea
AN
145 if ($context->contextlevel == CONTEXT_USER) {
146 static::export_policy_agreements_for_context($context);
147 } else if ($context->contextlevel == CONTEXT_SYSTEM) {
148 static::export_authored_policies($contextlist->get_user());
432a90f1
MG
149 }
150 }
f63745ea
AN
151 }
152
153 /**
154 * Delete all data for all users in the specified context.
155 *
156 * We never delete user agreements to the policies because they are part of privacy data.
5e84f521 157 * We never delete policy versions because they are part of privacy data.
f63745ea
AN
158 *
159 * @param \context $context The context to delete in.
160 */
161 public static function delete_data_for_all_users_in_context(\context $context) {
162 }
163
164 /**
165 * Delete all user data for the specified user, in the specified contexts.
166 *
167 * We never delete user agreements to the policies because they are part of privacy data.
5e84f521 168 * We never delete policy versions because they are part of privacy data.
f63745ea
AN
169 *
170 * @param approved_contextlist $contextlist A list of contexts approved for deletion.
171 */
172 public static function delete_data_for_user(approved_contextlist $contextlist) {
173 }
174
175 /**
176 * Export all policy agreements relating to the specified user context.
177 *
178 * @param \context_user $context The context to export
179 */
180 protected static function export_policy_agreements_for_context(\context_user $context) {
181 global $DB;
182
5e84f521
SA
183 $sysctx = \context_system::instance();
184 $fs = get_file_storage();
f63745ea
AN
185 $agreementsql = "
186 SELECT
5e84f521
SA
187 a.id AS agreementid, a.userid, a.timemodified, a.note, a.status,
188 a.policyversionid AS versionid, a.usermodified, a.timecreated,
189 v.id, v.archived, v.name, v.revision,
f63745ea
AN
190 v.summary, v.summaryformat,
191 v.content, v.contentformat,
192 p.currentversionid
193 FROM {tool_policy_acceptances} a
194 JOIN {tool_policy_versions} v ON v.id = a.policyversionid
195 JOIN {tool_policy} p ON v.policyid = p.id
196 WHERE a.userid = :userid OR a.usermodified = :usermodified";
197
198 // Fetch all agreements related to this user.
199 $agreements = $DB->get_recordset_sql($agreementsql, [
200 'userid' => $context->instanceid,
201 'usermodified' => $context->instanceid,
202 ]);
203
204 $basecontext = [
205 get_string('privacyandpolicies', 'admin'),
206 get_string('useracceptances', 'tool_policy'),
207 ];
208
209 foreach ($agreements as $agreement) {
210 $subcontext = array_merge($basecontext, [get_string('policynamedversion', 'tool_policy', $agreement)]);
211
212 $summary = writer::with_context($context)->rewrite_pluginfile_urls(
213 $subcontext,
214 'tool_policy',
215 'policydocumentsummary',
216 $agreement->versionid,
217 $agreement->summary
218 );
219 $content = writer::with_context($context)->rewrite_pluginfile_urls(
220 $subcontext,
221 'tool_policy',
222 'policydocumentcontent',
223 $agreement->versionid,
224 $agreement->content
225 );
226 $agreementcontent = (object) [
227 'name' => $agreement->name,
228 'revision' => $agreement->revision,
5e84f521 229 'isactive' => transform::yesno($agreement->versionid == $agreement->currentversionid),
f63745ea
AN
230 'isagreed' => transform::yesno($agreement->status),
231 'agreedby' => transform::user($agreement->usermodified),
232 'timecreated' => transform::datetime($agreement->timecreated),
233 'timemodified' => transform::datetime($agreement->timemodified),
234 'note' => $agreement->note,
235 'summary' => format_text($summary, $agreement->summaryformat),
236 'content' => format_text($content, $agreement->contentformat),
237 ];
238
5e84f521
SA
239 writer::with_context($context)->export_data($subcontext, $agreementcontent);
240 // Manually export the files as they reside in the system context so we can't use
241 // the write's helper methods.
242 foreach ($fs->get_area_files($sysctx->id, 'tool_policy', 'policydocumentsummary', $agreement->versionid) as $file) {
243 writer::with_context($context)->export_file($subcontext, $file);
244 }
245 foreach ($fs->get_area_files($sysctx->id, 'tool_policy', 'policydocumentcontent', $agreement->versionid) as $file) {
246 writer::with_context($context)->export_file($subcontext, $file);
247 }
f63745ea
AN
248 }
249 $agreements->close();
250 }
827c8e98 251
f63745ea
AN
252 /**
253 * Export all policy agreements that the user authored.
5e84f521
SA
254 *
255 * @param stdClass $user The user who has created the policies to export.
f63745ea
AN
256 */
257 protected static function export_authored_policies(\stdClass $user) {
258 global $DB;
259
260 // Authored policies are exported against the system.
827c8e98 261 $context = \context_system::instance();
f63745ea
AN
262 $basecontext = [
263 get_string('policydocuments', 'tool_policy'),
827c8e98 264 ];
f63745ea 265
827c8e98
SA
266 $sql = "SELECT v.id,
267 v.name,
268 v.revision,
269 v.summary,
270 v.content,
271 v.archived,
272 v.usermodified,
273 v.timecreated,
274 v.timemodified,
275 p.currentversionid
276 FROM {tool_policy_versions} v
277 JOIN {tool_policy} p ON p.id = v.policyid
f63745ea
AN
278 WHERE v.usermodified = :userid";
279 $versions = $DB->get_recordset_sql($sql, ['userid' => $user->id]);
827c8e98 280 foreach ($versions as $version) {
f63745ea
AN
281 $subcontext = array_merge($basecontext, [get_string('policynamedversion', 'tool_policy', $version)]);
282
827c8e98
SA
283 $versioncontent = (object) [
284 'name' => $version->name,
285 'revision' => $version->revision,
f63745ea 286 'summary' => writer::with_context($context)->rewrite_pluginfile_urls(
827c8e98
SA
287 $subcontext,
288 'tool_policy',
289 'policydocumentsummary',
290 $version->id,
291 $version->summary
292 ),
f63745ea 293 'content' => writer::with_context($context)->rewrite_pluginfile_urls(
827c8e98
SA
294 $subcontext,
295 'tool_policy',
296 'policydocumentcontent',
297 $version->id,
298 $version->content
299 ),
300 'isactive' => transform::yesno($version->id == $version->currentversionid),
301 'isarchived' => transform::yesno($version->archived),
f63745ea 302 'createdbyme' => transform::yesno($version->usermodified == $user->id),
827c8e98
SA
303 'timecreated' => transform::datetime($version->timecreated),
304 'timemodified' => transform::datetime($version->timemodified),
305 ];
f63745ea
AN
306 writer::with_context($context)
307 ->export_data($subcontext, $versioncontent)
308 ->export_area_files($subcontext, 'tool_policy', 'policydocumentsummary', $version->id)
309 ->export_area_files($subcontext, 'tool_policy', 'policydocumentcontent', $version->id);
827c8e98 310 }
f63745ea 311 $versions->close();
24966a26
SA
312 }
313}