MDL-62433 tool_policy: Review privacy provider for adding versions
[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
SA
104
105 $sql = "SELECT c.id
106 FROM {context} c
107 LEFT JOIN {tool_policy_versions} v ON v.usermodified = c.instanceid
108 LEFT JOIN {tool_policy_acceptances} a ON a.userid = c.instanceid
109 WHERE c.contextlevel = :contextlevel
110 AND (v.usermodified = :usermodified OR a.userid = :userid OR a.usermodified = :behalfuserid)";
111 $params = [
112 'contextlevel' => CONTEXT_USER,
113 'usermodified' => $userid,
114 'userid' => $userid,
115 'behalfuserid' => $userid,
116 ];
117 $contextlist->add_from_sql($sql, $params);
118
432a90f1 119 return $contextlist;
24966a26
SA
120 }
121
122 /**
123 * Export personal data for the given approved_contextlist. User and context information is contained within the contextlist.
124 *
125 * @param approved_contextlist $contextlist A list of contexts approved for export.
126 */
127 public static function export_user_data(approved_contextlist $contextlist) {
432a90f1 128 global $DB;
827c8e98
SA
129
130 // Remove contexts different from USER.
131 $contexts = array_reduce($contextlist->get_contexts(), function($carry, $context) {
132 if ($context->contextlevel == CONTEXT_USER) {
133 $carry[$context->instanceid] = $context;
432a90f1 134 }
827c8e98
SA
135 return $carry;
136 }, []);
137
138 if (empty($contexts)) {
139 return;
140 }
141
142 // Export user agreements.
143 $subcontext = [
144 get_string('privacyandpolicies', 'admin'),
145 get_string('useracceptances', 'tool_policy')
146 ];
147 $policyversionids = [];
148 foreach ($contexts as $context) {
432a90f1
MG
149 $user = $contextlist->get_user();
150 $agreements = $DB->get_records_sql('SELECT a.id, a.userid, v.name, v.revision, a.usermodified, a.timecreated,
151 a.timemodified, a.note, v.archived, p.currentversionid, a.status, a.policyversionid
152 FROM {tool_policy_acceptances} a
827c8e98 153 JOIN {tool_policy_versions} v ON v.id = a.policyversionid
432a90f1
MG
154 JOIN {tool_policy} p ON v.policyid = p.id
155 WHERE a.userid = ? AND (a.userid = ? OR a.usermodified = ?)
156 ORDER BY a.userid, v.archived, v.timecreated DESC',
157 [$context->instanceid, $user->id, $user->id]);
158 foreach ($agreements as $agreement) {
159 $context = \context_user::instance($agreement->userid);
432a90f1
MG
160 $name = 'policyagreement-' . $agreement->policyversionid;
161 $agreementcontent = (object) [
432a90f1
MG
162 'name' => $agreement->name,
163 'revision' => $agreement->revision,
164 'isactive' => transform::yesno($agreement->policyversionid == $agreement->currentversionid),
827c8e98
SA
165 'isagreed' => transform::yesno($agreement->status),
166 'agreedby' => transform::user($agreement->usermodified),
432a90f1
MG
167 'timecreated' => transform::datetime($agreement->timecreated),
168 'timemodified' => transform::datetime($agreement->timemodified),
169 'note' => $agreement->note,
170 ];
171 writer::with_context($context)->export_related_data($subcontext, $name, $agreementcontent);
827c8e98 172 $policyversionids[$agreement->policyversionid] = $agreement->policyversionid;
432a90f1
MG
173 }
174 }
827c8e98
SA
175
176 // Export policy versions (agreed or modified by the user).
177 $userid = $contextlist->get_user()->id;
178 $context = \context_system::instance();
179 $subcontext = [
180 get_string('policydocuments', 'tool_policy')
181 ];
182 $writer = writer::with_context($context);
183 list($contextsql, $contextparams) = $DB->get_in_or_equal(array_keys($contexts), SQL_PARAMS_NAMED);
184 list($versionsql, $versionparams) = $DB->get_in_or_equal($policyversionids, SQL_PARAMS_NAMED);
185 $sql = "SELECT v.id,
186 v.name,
187 v.revision,
188 v.summary,
189 v.content,
190 v.archived,
191 v.usermodified,
192 v.timecreated,
193 v.timemodified,
194 p.currentversionid
195 FROM {tool_policy_versions} v
196 JOIN {tool_policy} p ON p.id = v.policyid
197 WHERE v.usermodified {$contextsql} OR v.id {$versionsql}";
198 $params = array_merge($contextparams, $versionparams);
199 $versions = $DB->get_recordset_sql($sql, $params);
200 foreach ($versions as $version) {
201 $name = 'policyversion-' . $version->id;
202 $versioncontent = (object) [
203 'name' => $version->name,
204 'revision' => $version->revision,
205 'summary' => $writer->rewrite_pluginfile_urls(
206 $subcontext,
207 'tool_policy',
208 'policydocumentsummary',
209 $version->id,
210 $version->summary
211 ),
212 'content' => $writer->rewrite_pluginfile_urls(
213 $subcontext,
214 'tool_policy',
215 'policydocumentcontent',
216 $version->id,
217 $version->content
218 ),
219 'isactive' => transform::yesno($version->id == $version->currentversionid),
220 'isarchived' => transform::yesno($version->archived),
221 'createdbyme' => transform::yesno($version->usermodified == $userid),
222 'timecreated' => transform::datetime($version->timecreated),
223 'timemodified' => transform::datetime($version->timemodified),
224 ];
225 $writer->export_related_data($subcontext, $name, $versioncontent);
226 $writer->export_area_files($subcontext, 'tool_policy', 'policydocumentsummary', $version->id);
227 $writer->export_area_files($subcontext, 'tool_policy', 'policydocumentcontent', $version->id);
228 }
24966a26
SA
229 }
230
231 /**
232 * Delete all data for all users in the specified context.
233 *
432a90f1
MG
234 * We never delete user agreements to the policies because they are part of privacy data.
235 *
24966a26
SA
236 * @param \context $context The context to delete in.
237 */
238 public static function delete_data_for_all_users_in_context(\context $context) {
239 }
240
241 /**
242 * Delete all user data for the specified user, in the specified contexts.
243 *
432a90f1
MG
244 * We never delete user agreements to the policies because they are part of privacy data.
245 *
24966a26
SA
246 * @param approved_contextlist $contextlist A list of contexts approved for deletion.
247 */
248 public static function delete_data_for_user(approved_contextlist $contextlist) {
249 }
250}