MDL-62433 tool_policy: Adjustments to the data export
[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
SA
142
143 // Remove contexts different from USER.
144 $contexts = array_reduce($contextlist->get_contexts(), function($carry, $context) {
145 if ($context->contextlevel == CONTEXT_USER) {
146 $carry[$context->instanceid] = $context;
432a90f1 147 }
f63745ea
AN
148 if ($context->contextlevel == CONTEXT_SYSTEM) {
149 $carry[$context->instanceid] = $context;
150 }
827c8e98
SA
151 return $carry;
152 }, []);
153
154 if (empty($contexts)) {
155 return;
156 }
157
158 // Export user agreements.
159 $subcontext = [
160 get_string('privacyandpolicies', 'admin'),
161 get_string('useracceptances', 'tool_policy')
162 ];
163 $policyversionids = [];
f63745ea
AN
164
165 $agreementsql = "SELECT
166 a.id, a.userid, v.name, v.revision, a.usermodified, a.timecreated,
167 a.timemodified, a.note, v.archived, p.currentversionid, a.status, a.policyversionid
168 FROM {tool_policy_acceptances} a
169 JOIN {tool_policy_versions} v ON v.id = a.policyversionid
170 JOIN {tool_policy} p ON v.policyid = p.id
171 WHERE a.userid = :userid OR a.usermodified = :usermodified";
827c8e98 172 foreach ($contexts as $context) {
f63745ea
AN
173 if ($context->contextlevel == CONTEXT_USER) {
174 static::export_policy_agreements_for_context($context);
175 } else if ($context->contextlevel == CONTEXT_SYSTEM) {
176 static::export_authored_policies($contextlist->get_user());
432a90f1
MG
177 }
178 }
f63745ea
AN
179 }
180
181 /**
182 * Delete all data for all users in the specified context.
183 *
184 * We never delete user agreements to the policies because they are part of privacy data.
185 *
186 * @param \context $context The context to delete in.
187 */
188 public static function delete_data_for_all_users_in_context(\context $context) {
189 }
190
191 /**
192 * Delete all user data for the specified user, in the specified contexts.
193 *
194 * We never delete user agreements to the policies because they are part of privacy data.
195 *
196 * @param approved_contextlist $contextlist A list of contexts approved for deletion.
197 */
198 public static function delete_data_for_user(approved_contextlist $contextlist) {
199 }
200
201 /**
202 * Export all policy agreements relating to the specified user context.
203 *
204 * @param \context_user $context The context to export
205 */
206 protected static function export_policy_agreements_for_context(\context_user $context) {
207 global $DB;
208
209 $agreementsql = "
210 SELECT
211 a.id, a.userid, a.timemodified, a.note, a.status, a.policyversionid, a.usermodified, a.timecreated,
212 v.id AS versionid, v.archived, v.name, v.revision,
213 v.summary, v.summaryformat,
214 v.content, v.contentformat,
215 p.currentversionid
216 FROM {tool_policy_acceptances} a
217 JOIN {tool_policy_versions} v ON v.id = a.policyversionid
218 JOIN {tool_policy} p ON v.policyid = p.id
219 WHERE a.userid = :userid OR a.usermodified = :usermodified";
220
221 // Fetch all agreements related to this user.
222 $agreements = $DB->get_recordset_sql($agreementsql, [
223 'userid' => $context->instanceid,
224 'usermodified' => $context->instanceid,
225 ]);
226
227 $basecontext = [
228 get_string('privacyandpolicies', 'admin'),
229 get_string('useracceptances', 'tool_policy'),
230 ];
231
232 foreach ($agreements as $agreement) {
233 $subcontext = array_merge($basecontext, [get_string('policynamedversion', 'tool_policy', $agreement)]);
234
235 $summary = writer::with_context($context)->rewrite_pluginfile_urls(
236 $subcontext,
237 'tool_policy',
238 'policydocumentsummary',
239 $agreement->versionid,
240 $agreement->summary
241 );
242 $content = writer::with_context($context)->rewrite_pluginfile_urls(
243 $subcontext,
244 'tool_policy',
245 'policydocumentcontent',
246 $agreement->versionid,
247 $agreement->content
248 );
249 $agreementcontent = (object) [
250 'name' => $agreement->name,
251 'revision' => $agreement->revision,
252 'isactive' => transform::yesno($agreement->policyversionid == $agreement->currentversionid),
253 'isagreed' => transform::yesno($agreement->status),
254 'agreedby' => transform::user($agreement->usermodified),
255 'timecreated' => transform::datetime($agreement->timecreated),
256 'timemodified' => transform::datetime($agreement->timemodified),
257 'note' => $agreement->note,
258 'summary' => format_text($summary, $agreement->summaryformat),
259 'content' => format_text($content, $agreement->contentformat),
260 ];
261
262 writer::with_context($context)
263 ->export_data($subcontext, $agreementcontent)
264 ->export_area_files($subcontext, 'tool_policy', 'policydocumentsummary', $agreement->versionid)
265 ->export_area_files($subcontext, 'tool_policy', 'policydocumentcontent', $agreement->versionid);
266 }
267 $agreements->close();
268 }
827c8e98 269
f63745ea
AN
270 /**
271 * Export all policy agreements that the user authored.
272 */
273 protected static function export_authored_policies(\stdClass $user) {
274 global $DB;
275
276 // Authored policies are exported against the system.
827c8e98 277 $context = \context_system::instance();
f63745ea
AN
278 $basecontext = [
279 get_string('policydocuments', 'tool_policy'),
827c8e98 280 ];
f63745ea 281
827c8e98
SA
282 $sql = "SELECT v.id,
283 v.name,
284 v.revision,
285 v.summary,
286 v.content,
287 v.archived,
288 v.usermodified,
289 v.timecreated,
290 v.timemodified,
291 p.currentversionid
292 FROM {tool_policy_versions} v
293 JOIN {tool_policy} p ON p.id = v.policyid
f63745ea
AN
294 WHERE v.usermodified = :userid";
295 $versions = $DB->get_recordset_sql($sql, ['userid' => $user->id]);
827c8e98 296 foreach ($versions as $version) {
f63745ea
AN
297 $subcontext = array_merge($basecontext, [get_string('policynamedversion', 'tool_policy', $version)]);
298
827c8e98
SA
299 $versioncontent = (object) [
300 'name' => $version->name,
301 'revision' => $version->revision,
f63745ea 302 'summary' => writer::with_context($context)->rewrite_pluginfile_urls(
827c8e98
SA
303 $subcontext,
304 'tool_policy',
305 'policydocumentsummary',
306 $version->id,
307 $version->summary
308 ),
f63745ea 309 'content' => writer::with_context($context)->rewrite_pluginfile_urls(
827c8e98
SA
310 $subcontext,
311 'tool_policy',
312 'policydocumentcontent',
313 $version->id,
314 $version->content
315 ),
316 'isactive' => transform::yesno($version->id == $version->currentversionid),
317 'isarchived' => transform::yesno($version->archived),
f63745ea 318 'createdbyme' => transform::yesno($version->usermodified == $user->id),
827c8e98
SA
319 'timecreated' => transform::datetime($version->timecreated),
320 'timemodified' => transform::datetime($version->timemodified),
321 ];
f63745ea
AN
322 writer::with_context($context)
323 ->export_data($subcontext, $versioncontent)
324 ->export_area_files($subcontext, 'tool_policy', 'policydocumentsummary', $version->id)
325 ->export_area_files($subcontext, 'tool_policy', 'policydocumentcontent', $version->id);
827c8e98 326 }
f63745ea 327 $versions->close();
24966a26
SA
328 }
329}