weekly back-to-dev release 4.2dev
[moodle.git] / enrol / flatfile / classes / privacy / provider.php
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/>.
17 /**
18  * Privacy Subsystem implementation for enrol_flatfile.
19  *
20  * @package    enrol_flatfile
21  * @category   privacy
22  * @copyright  2018 Carlos Escobedo <carlos@moodle.com>
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 namespace enrol_flatfile\privacy;
28 use core_privacy\local\metadata\collection;
29 use core_privacy\local\request\approved_contextlist;
30 use core_privacy\local\request\approved_userlist;
31 use core_privacy\local\request\context;
32 use core_privacy\local\request\contextlist;
33 use core_privacy\local\request\userlist;
34 use core_privacy\local\request\writer;
35 use core_privacy\local\request\transform;
37 defined('MOODLE_INTERNAL') || die();
39 /**
40  * Privacy Subsystem for enrol_flatfile implementing null_provider.
41  *
42  * @copyright  2018 Carlos Escobedo <carlos@moodle.com>
43  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
44  */
45 class provider implements
46         \core_privacy\local\metadata\provider,
47         \core_privacy\local\request\plugin\provider,
48         \core_privacy\local\request\core_userlist_provider {
50     /**
51      * Returns meta data about this system.
52      *
53      * @param   collection $collection The initialised collection to add items to.
54      * @return  collection     A listing of user data stored through this system.
55      */
56     public static function get_metadata(collection $collection) : collection {
57         return $collection->add_database_table('enrol_flatfile', [
58             'action' => 'privacy:metadata:enrol_flatfile:action',
59             'roleid' => 'privacy:metadata:enrol_flatfile:roleid',
60             'userid' => 'privacy:metadata:enrol_flatfile:userid',
61             'courseid' => 'privacy:metadata:enrol_flatfile:courseid',
62             'timestart' => 'privacy:metadata:enrol_flatfile:timestart',
63             'timeend' => 'privacy:metadata:enrol_flatfile:timeend',
64             'timemodified' => 'privacy:metadata:enrol_flatfile:timemodified'
65         ], 'privacy:metadata:enrol_flatfile');
66     }
68     /**
69      * Get the list of contexts that contain user information for the specified user.
70      *
71      * @param   int $userid The user to search.
72      * @return  contextlist   $contextlist  The contextlist containing the list of contexts used in this plugin.
73      */
74     public static function get_contexts_for_userid(int $userid) : contextlist {
75         $sql = "SELECT c.id
76                   FROM {enrol_flatfile} ef
77                   JOIN {context} c ON c.contextlevel = ? AND c.instanceid = ef.courseid
78                  WHERE ef.userid = ?";
79         $params = [CONTEXT_COURSE, $userid];
81         $contextlist = new contextlist();
82         $contextlist->set_component('enrol_flatfile');
83         return $contextlist->add_from_sql($sql, $params);
84     }
86     /**
87      * Get the list of users who have data within a context.
88      *
89      * @param   userlist    $userlist   The userlist containing the list of users who have data in this context/plugin combination.
90      */
91     public static function get_users_in_context(userlist $userlist) {
92         $context = $userlist->get_context();
94         if ($context->contextlevel != CONTEXT_COURSE) {
95             return;
96         }
98         $sql = "SELECT userid FROM {enrol_flatfile} WHERE courseid = ?";
99         $params = [$context->instanceid];
100         $userlist->add_from_sql('userid', $sql, $params);
101     }
103     /**
104      * Export all user data for the specified user, in the specified contexts.
105      *
106      * @param approved_contextlist $contextlist The approved contexts to export information for.
107      */
108     public static function export_user_data(approved_contextlist $contextlist) {
109         global $DB;
111         // Ensure all contexts are CONTEXT_COURSE.
112         $contexts = static::validate_contextlist_contexts($contextlist);
113         if (empty($contexts)) {
114             return;
115         }
117         // Get the context instance ids from the contexts. These  are the course ids..
118         $contextinstanceids = array_map(function($context) {
119             return $context->instanceid;
120         }, $contexts);
121         $userid = $contextlist->get_user()->id;
123         // Now, we just need to fetch and format all entries corresponding to the contextids provided.
124         $sql = "SELECT ef.action, r.shortname, ef.courseid, ef.timestart, ef.timeend, ef.timemodified
125                   FROM {enrol_flatfile} ef
126                   JOIN {context} c ON c.contextlevel = :contextlevel AND c.instanceid = ef.courseid
127                   JOIN {role} r ON r.id = ef.roleid
128                  WHERE ef.userid = :userid";
129         $params = ['contextlevel' => CONTEXT_COURSE, 'userid' => $userid];
130         list($insql, $inparams) = $DB->get_in_or_equal($contextinstanceids, SQL_PARAMS_NAMED);
131         $sql .= " AND ef.courseid $insql";
132         $params = array_merge($params, $inparams);
134         $futureenrolments = $DB->get_recordset_sql($sql, $params);
135         $enrolmentdata = [];
136         foreach ($futureenrolments as $futureenrolment) {
137             // It's possible to have more than one future enrolment per course.
138             $futureenrolment->timestart = transform::datetime($futureenrolment->timestart);
139             $futureenrolment->timeend = transform::datetime($futureenrolment->timeend);
140             $futureenrolment->timemodified = transform::datetime($futureenrolment->timemodified);
141             $enrolmentdata[$futureenrolment->courseid][] = $futureenrolment;
142         }
143         $futureenrolments->close();
145         // And finally, write out the data to the relevant course contexts.
146         $subcontext = \core_enrol\privacy\provider::get_subcontext([get_string('pluginname', 'enrol_flatfile')]);
147         foreach ($enrolmentdata as $courseid => $enrolments) {
148             $data = (object) [
149                 'pendingenrolments' => $enrolments,
150             ];
151             writer::with_context(\context_course::instance($courseid))->export_data($subcontext, $data);
152         }
153     }
155     /**
156      * Delete all data for all users in the specified context.
157      *
158      * @param \context $context The specific context to delete data for.
159      */
160     public static function delete_data_for_all_users_in_context(\context $context) {
161         if ($context->contextlevel != CONTEXT_COURSE) {
162             return;
163         }
164         global $DB;
165         $DB->delete_records('enrol_flatfile', ['courseid' => $context->instanceid]);
166     }
168     /**
169      * Delete all user data for the specified user, in the specified contexts.
170      *
171      * @param   approved_contextlist $contextlist The approved contexts and user information to delete information for.
172      */
173     public static function delete_data_for_user(approved_contextlist $contextlist) {
174         // Only delete data from contexts which are at the CONTEXT_COURSE contextlevel.
175         $contexts = self::validate_contextlist_contexts($contextlist);
176         if (empty($contexts)) {
177             return;
178         }
180         // Get the course ids based on the provided contexts.
181         $contextinstanceids = array_map(function($context) {
182             return $context->instanceid;
183         }, $contextlist->get_contexts());
185         global $DB;
186         $user = $contextlist->get_user();
187         list($insql, $inparams) = $DB->get_in_or_equal($contextinstanceids, SQL_PARAMS_NAMED);
188         $params = array_merge(['userid' => $user->id], $inparams);
189         $sql = "userid = :userid AND courseid $insql";
190         $DB->delete_records_select('enrol_flatfile', $sql, $params);
191     }
193     /**
194      * Delete multiple users within a single context.
195      *
196      * @param   approved_userlist       $userlist The approved context and user information to delete information for.
197      */
198     public static function delete_data_for_users(approved_userlist $userlist) {
199         global $DB;
201         $context = $userlist->get_context();
203         if ($context->contextlevel != CONTEXT_COURSE) {
204             return;
205         }
207         $userids = $userlist->get_userids();
209         list($insql, $inparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
210         $params = array_merge(['courseid' => $context->instanceid], $inparams);
211         $sql = "courseid = :courseid AND userid $insql";
212         $DB->delete_records_select('enrol_flatfile', $sql, $params);
213     }
215     /**
216      * Simple sanity check on the contextlist contexts, making sure they're of CONTEXT_COURSE contextlevel.
217      *
218      * @param approved_contextlist $contextlist
219      * @return array the array of contexts filtered to only include those of CONTEXT_COURSE contextlevel.
220      */
221     protected static function validate_contextlist_contexts(approved_contextlist $contextlist) {
222         return array_reduce($contextlist->get_contexts(), function($carry, $context) {
223             if ($context->contextlevel == CONTEXT_COURSE) {
224                 $carry[] = $context;
225             }
226             return $carry;
227         }, []);
228     }