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/>.
17 * Privacy Subsystem implementation for core_enrol.
20 * @copyright 2018 Carlos Escobedo <carlos@moodle.com>
21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 namespace core_enrol\privacy
;
26 defined('MOODLE_INTERNAL') ||
die();
28 use core_privacy\local\metadata\collection
;
29 use core_privacy\local\request\approved_contextlist
;
30 use core_privacy\local\request\context
;
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\local\request\userlist
;
35 use \core_privacy\local\request\approved_userlist
;
38 * Privacy Subsystem for core_enrol implementing metadata and plugin providers.
40 * @copyright 2018 Carlos Escobedo <carlos@moodle.com>
41 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
43 class provider
implements
44 \core_privacy\local\metadata\provider
,
45 \core_privacy\local\request\core_userlist_provider
,
46 \core_privacy\local\request\subsystem\provider
{
48 * Returns meta data about this system.
50 * @param collection $collection The initialised collection to add items to.
51 * @return collection A listing of user data stored through this system.
53 public static function get_metadata(collection
$collection): collection
{
54 $collection->add_database_table(
57 'status' => 'privacy:metadata:user_enrolments:status',
58 'enrolid' => 'privacy:metadata:user_enrolments:enrolid',
59 'userid' => 'privacy:metadata:user_enrolments:userid',
60 'timestart' => 'privacy:metadata:user_enrolments:timestart',
61 'timeend' => 'privacy:metadata:user_enrolments:timeend',
62 'modifierid' => 'privacy:metadata:user_enrolments:modifierid',
63 'timecreated' => 'privacy:metadata:user_enrolments:timecreated',
64 'timemodified' => 'privacy:metadata:user_enrolments:timemodified'
66 'privacy:metadata:user_enrolments:tableexplanation'
72 * Get the list of contexts that contain user information for the specified user.
74 * @param int $userid The user to search.
75 * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
77 public static function get_contexts_for_userid(int $userid): contextlist
{
79 FROM {user_enrolments} ue
82 AND ue.userid = :userid
84 ON ctx.instanceid = e.courseid
85 AND ctx.contextlevel = :contextlevel";
87 'contextlevel' => CONTEXT_COURSE
,
90 $contextlist = new contextlist();
91 $contextlist->add_from_sql($sql, $params);
97 * Get the list of users within a specific context.
99 * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
101 public static function get_users_in_context(userlist
$userlist) {
102 $context = $userlist->get_context();
104 if (!$context instanceof \context_course
) {
108 $sql = "SELECT ue.userid as userid
109 FROM {user_enrolments} ue
110 JOIN {enrol} e ON e.id = ue.enrolid
111 WHERE e.courseid = ?";
112 $params = [$context->instanceid
];
113 $userlist->add_from_sql('userid', $sql, $params);
117 * Export all user data for the specified user, in the specified contexts.
119 * @param approved_contextlist $contextlist The approved contexts to export information for.
121 public static function export_user_data(approved_contextlist
$contextlist) {
124 if (empty($contextlist->count())) {
127 $userid = $contextlist->get_user()->id
;
128 list($insql, $inparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED
);
130 'contextlevel' => CONTEXT_COURSE
,
133 $params +
= $inparams;
134 $sql = "SELECT ue.id,
142 FROM {user_enrolments} ue
145 AND ue.userid = :userid
147 ON ctx.instanceid = e.courseid
148 AND ctx.contextlevel = :contextlevel
150 ORDER BY ctx.id, e.enrol";
152 $lastcontextid = null;
154 $path = [get_string('privacy:metadata:user_enrolments', 'core_enrol')];
155 $flush = function($lastcontextid, $lastenrol, $data) use ($path) {
156 $context = \context
::instance_by_id($lastcontextid);
157 writer
::with_context($context)->export_related_data(
163 $userenrolments = $DB->get_recordset_sql($sql, $params);
164 foreach ($userenrolments as $userenrolment) {
165 if (($lastcontextid && $lastcontextid != $userenrolment->contextid
) ||
166 ($lastenrol && $lastenrol != $userenrolment->enrol
)) {
167 $flush($lastcontextid, $lastenrol, $data);
171 'status' => $userenrolment->status
,
172 'timecreated' => transform
::datetime($userenrolment->timecreated
),
173 'timemodified' => transform
::datetime($userenrolment->timemodified
),
174 'timestart' => transform
::datetime($userenrolment->timestart
),
175 'timeend' => transform
::datetime($userenrolment->timeend
)
177 $lastcontextid = $userenrolment->contextid
;
178 $lastenrol = $userenrolment->enrol
;
181 $flush($lastcontextid, $lastenrol, $data);
183 $userenrolments->close();
186 * Delete all data for all users in the specified context.
188 * @param \context $context The specific context to delete data for.
190 public static function delete_data_for_all_users_in_context(\context
$context) {
193 // Sanity check that context is at the User context level.
194 if ($context->contextlevel
== CONTEXT_COURSE
) {
196 FROM {user_enrolments} ue
197 JOIN {enrol} e ON e.id = ue.enrolid
198 WHERE e.courseid = :courseid";
199 $params = ['courseid' => $context->instanceid
];
200 $enrolsids = $DB->get_fieldset_sql($sql, $params);
201 if (!empty($enrolsids)) {
202 list($insql, $inparams) = $DB->get_in_or_equal($enrolsids, SQL_PARAMS_NAMED
);
203 static::delete_user_data($insql, $inparams);
209 * Delete multiple users within a single context.
211 * @param approved_userlist $userlist The approved context and user information to delete information for.
213 public static function delete_data_for_users(approved_userlist
$userlist) {
216 $context = $userlist->get_context();
218 if ($context instanceof \context_course
) {
219 list($usersql, $userparams) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED
);
222 FROM {user_enrolments} ue
223 JOIN {enrol} e ON e.id = ue.enrolid
224 WHERE e.courseid = :courseid
225 AND ue.userid {$usersql}";
227 $params = ['courseid' => $context->instanceid
] +
$userparams;
228 $enrolsids = $DB->get_fieldset_sql($sql, $params);
230 if (!empty($enrolsids)) {
231 list($insql, $inparams) = $DB->get_in_or_equal($enrolsids, SQL_PARAMS_NAMED
);
232 static::delete_user_data($insql, $inparams);
238 * Delete all user data for the specified user, in the specified contexts.
240 * @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
242 public static function delete_data_for_user(approved_contextlist
$contextlist) {
245 if (empty($contextlist->count())) {
248 $userid = $contextlist->get_user()->id
;
249 list($insql, $inparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED
);
251 'contextlevel' => CONTEXT_COURSE
,
254 $params +
= $inparams;
256 FROM {user_enrolments} ue
259 AND ue.userid = :userid
261 ON ctx.instanceid = e.courseid
262 AND ctx.contextlevel = :contextlevel
263 WHERE ctx.id $insql";
264 $enrolsids = $DB->get_fieldset_sql($sql, $params);
265 if (!empty($enrolsids)) {
266 list($insql, $inparams) = $DB->get_in_or_equal($enrolsids, SQL_PARAMS_NAMED
);
267 static::delete_user_data($insql, $inparams);
272 * Delete data from $tablename with the IDs returned by $sql query.
274 * @param string $sql SQL query for getting the IDs of the uer enrolments entries to delete.
275 * @param array $params SQL params for the query.
277 protected static function delete_user_data(string $sql, array $params) {
280 $DB->delete_records_select('user_enrolments', "id $sql", $params);
284 * Get the subcontext for export.
286 * @param array $subcontext Any additional subcontext to use.
287 * @return array The array containing the full subcontext, i.e. [enrolments, subcontext]
289 public static function get_subcontext(array $subcontext) {
291 [get_string('privacy:metadata:user_enrolments', 'core_enrol')],