Merge branch 'MDL-61951-master' of git://github.com/sarjona/moodle
[moodle.git] / grade / grading / classes / privacy / provider.php
blob490cc791dd2d336e78f3d75a8ff3cc898e8cc878
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.
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/>.
17 /**
18 * Privacy class for requesting user data.
20 * @package core_grading
21 * @copyright 2018 Sara Arjona <sara@moodle.com>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 namespace core_grading\privacy;
27 defined('MOODLE_INTERNAL') || die();
29 use \core_privacy\local\metadata\collection;
30 use \core_privacy\local\request\approved_contextlist;
31 use \core_privacy\local\request\contextlist;
32 use \core_privacy\local\request\transform;
33 use \core_privacy\local\request\writer;
34 use \core_privacy\manager;
36 /**
37 * Privacy class for requesting user data.
39 * @copyright 2018 Sara Arjona <sara@moodle.com>
40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42 class provider implements
43 \core_privacy\local\metadata\provider,
44 \core_privacy\local\request\subsystem\provider {
46 /**
47 * Returns meta data about this system.
49 * @param collection $collection The initialised collection to add items to.
50 * @return collection A listing of user data stored through this system.
52 public static function get_metadata(collection $collection) : collection {
53 $collection->add_database_table('grading_definitions', [
54 'method' => 'privacy:metadata:grading_definitions:method',
55 'areaid' => 'privacy:metadata:grading_definitions:areaid',
56 'name' => 'privacy:metadata:grading_definitions:name',
57 'description' => 'privacy:metadata:grading_definitions:description',
58 'status' => 'privacy:metadata:grading_definitions:status',
59 'copiedfromid' => 'privacy:metadata:grading_definitions:copiedfromid',
60 'timecopied' => 'privacy:metadata:grading_definitions:timecopied',
61 'timecreated' => 'privacy:metadata:grading_definitions:timecreated',
62 'usercreated' => 'privacy:metadata:grading_definitions:usercreated',
63 'timemodified' => 'privacy:metadata:grading_definitions:timemodified',
64 'usermodified' => 'privacy:metadata:grading_definitions:usermodified',
65 'options' => 'privacy:metadata:grading_definitions:options',
66 ], 'privacy:metadata:grading_definitions');
68 $collection->add_database_table('grading_instances', [
69 'raterid' => 'privacy:metadata:grading_instances:raterid',
70 'rawgrade' => 'privacy:metadata:grading_instances:rawgrade',
71 'status' => 'privacy:metadata:grading_instances:status',
72 'feedback' => 'privacy:metadata:grading_instances:feedback',
73 'feedbackformat' => 'privacy:metadata:grading_instances:feedbackformat',
74 'timemodified' => 'privacy:metadata:grading_instances:timemodified',
75 ], 'privacy:metadata:grading_instances');
77 // Link to subplugin.
78 $collection->add_plugintype_link('gradingform', [], 'privacy:metadata:gradingformpluginsummary');
80 return $collection;
83 /**
84 * Get the list of contexts that contain user information for the specified user.
86 * @param int $userid The user to search.
87 * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
89 public static function get_contexts_for_userid(int $userid) : contextlist {
90 $contextlist = new contextlist();
92 $sql = "SELECT c.id
93 FROM {context} c
94 JOIN {grading_areas} a ON a.contextid = c.id
95 JOIN {grading_definitions} d ON d.areaid = a.id
96 LEFT JOIN {grading_instances} i ON i.definitionid = d.id AND i.raterid = :raterid
97 WHERE c.contextlevel = :contextlevel
98 AND (d.usercreated = :usercreated OR d.usermodified = :usermodified OR i.id IS NOT NULL)";
99 $params = [
100 'usercreated' => $userid,
101 'usermodified' => $userid,
102 'raterid' => $userid,
103 'contextlevel' => CONTEXT_MODULE
105 $contextlist->add_from_sql($sql, $params);
107 return $contextlist;
111 * Export all user data for the specified user, in the specified contexts.
113 * @param approved_contextlist $contextlist The approved contexts to export information for.
115 public static function export_user_data(approved_contextlist $contextlist) {
116 // Remove contexts different from MODULE.
117 $contexts = array_reduce($contextlist->get_contexts(), function($carry, $context) {
118 if ($context->contextlevel == CONTEXT_MODULE) {
119 $carry[] = $context;
121 return $carry;
122 }, []);
124 if (empty($contexts)) {
125 return;
128 $userid = $contextlist->get_user()->id;
129 $subcontext = [get_string('gradingmethod', 'grading')];
130 foreach ($contexts as $context) {
131 // Export grading definitions created or modified on this context.
132 self::export_definitions($context, $subcontext, $userid);
137 * Exports the data related to grading definitions within the specified context/subcontext.
139 * @param \context $context Context owner of the data.
140 * @param array $subcontext Subcontext owner of the data.
141 * @param int $userid The user whose information is to be exported.
143 protected static function export_definitions(\context $context, array $subcontext, int $userid = 0) {
144 global $DB;
146 $join = "JOIN {grading_areas} a ON a.id = d.areaid
147 JOIN {context} c ON a.contextid = c.id AND c.contextlevel = :contextlevel";
148 $select = 'a.contextid = :contextid';
149 $params = [
150 'contextlevel' => CONTEXT_MODULE,
151 'contextid' => $context->id
154 if (!empty($userid)) {
155 $join .= ' LEFT JOIN {grading_instances} i ON i.definitionid = d.id AND i.raterid = :raterid';
156 $select .= ' AND (usercreated = :usercreated
157 OR usermodified = :usermodified OR i.id IS NOT NULL)';
158 $params['usercreated'] = $userid;
159 $params['usermodified'] = $userid;
160 $params['raterid'] = $userid;
163 $sql = "SELECT gd.id,
164 gd.method,
165 gd.name,
166 gd.description,
167 gd.timecopied,
168 gd.timecreated,
169 gd.usercreated,
170 gd.timemodified,
171 gd.usermodified
172 FROM (
173 SELECT DISTINCT d.id
174 FROM {grading_definitions} d
175 $join
176 WHERE $select
177 ) ids
178 JOIN {grading_definitions} gd ON gd.id = ids.id";
179 $definitions = $DB->get_recordset_sql($sql, $params);
180 $defdata = [];
181 foreach ($definitions as $definition) {
182 $tmpdata = [
183 'method' => $definition->method,
184 'name' => $definition->name,
185 'description' => $definition->description,
186 'timecreated' => transform::datetime($definition->timecreated),
187 'usercreated' => transform::user($definition->usercreated),
188 'timemodified' => transform::datetime($definition->timemodified),
189 'usermodified' => transform::user($definition->usermodified),
191 if (!empty($definition->timecopied)) {
192 $tmpdata['timecopied'] = transform::datetime($definition->timecopied);
194 // Export gradingform information (if needed).
195 $instancedata = manager::component_class_callback(
196 "gradingform_{$definition->method}",
197 gradingform_provider::class,
198 'get_gradingform_export_data',
199 [$context, $definition, $userid]
201 if (null !== $instancedata) {
202 $tmpdata = array_merge($tmpdata, $instancedata);
205 $defdata[] = (object) $tmpdata;
207 // Export grading_instances information.
208 self::export_grading_instances($context, $subcontext, $definition->id, $userid);
210 $definitions->close();
212 if (!empty($defdata)) {
213 $data = (object) [
214 'definitions' => $defdata,
217 writer::with_context($context)->export_data($subcontext, $data);
222 * Exports the data related to grading instances within the specified definition.
224 * @param \context $context Context owner of the data.
225 * @param array $subcontext Subcontext owner of the data.
226 * @param int $definitionid The definition ID whose grading instance information is to be exported.
227 * @param int $userid The user whose information is to be exported.
229 protected static function export_grading_instances(\context $context, array $subcontext, int $definitionid, int $userid = 0) {
230 global $DB;
232 $params = ['definitionid' => $definitionid];
233 if (!empty($userid)) {
234 $params['raterid'] = $userid;
236 $instances = $DB->get_recordset('grading_instances', $params);
237 $instancedata = [];
238 foreach ($instances as $instance) {
239 // TODO: Get the status name (instead of the ID).
240 $tmpdata = [
241 'rawgrade' => $instance->rawgrade,
242 'status' => $instance->status,
243 'feedback' => $instance->feedback,
244 'feedbackformat' => $instance->feedbackformat,
245 'timemodified' => transform::datetime($instance->timemodified),
247 $instancedata[] = (object) $tmpdata;
249 $instances->close();
251 if (!empty($instancedata)) {
252 $data = (object) [
253 'instances' => $instancedata,
256 writer::with_context($context)->export_related_data($subcontext, 'gradinginstances', $data);
261 * Delete all use data which matches the specified $context.
263 * We never delete grading content.
265 * @param context $context A user context.
267 public static function delete_data_for_all_users_in_context(\context $context) {
268 manager::plugintype_class_callback(
269 'gradingform',
270 gradingform_provider::class,
271 'delete_gradingform_for_context',
272 [$context]
277 * Delete all user data for the specified user, in the specified contexts.
279 * We never delete grading content.
281 * @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
283 public static function delete_data_for_user(approved_contextlist $contextlist) {
284 manager::plugintype_class_callback(
285 'gradingform',
286 gradingform_provider::class,
287 'delete_gradingform_for_userid',
288 [$contextlist]