Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
 * Privacy Subsystem implementation for enrol_lti.
18
 *
19
 * @package    enrol_lti
20
 * @category   privacy
21
 * @copyright  2018 Mark Nelson <markn@moodle.com>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
namespace enrol_lti\privacy;
26
 
27
use core_privacy\local\metadata\collection;
28
use core_privacy\local\request\approved_contextlist;
29
use core_privacy\local\request\approved_userlist;
30
use core_privacy\local\request\contextlist;
31
use core_privacy\local\request\transform;
32
use core_privacy\local\request\userlist;
33
use core_privacy\local\request\writer;
34
 
35
defined('MOODLE_INTERNAL') || die();
36
 
37
/**
38
 * Privacy Subsystem for enrol_lti.
39
 *
40
 * @copyright  2018 Mark Nelson <markn@moodle.com>
41
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42
 */
43
class provider implements
44
    \core_privacy\local\metadata\provider,
45
    \core_privacy\local\request\plugin\provider,
46
    \core_privacy\local\request\core_userlist_provider {
47
 
48
    /**
49
     * Return the fields which contain personal data.
50
     *
51
     * @param collection $items a reference to the collection to use to store the metadata.
52
     * @return collection the updated collection of metadata items.
53
     */
54
    public static function get_metadata(collection $items): collection {
55
        $items->add_database_table(
56
            'enrol_lti_users',
57
            [
58
                'userid' => 'privacy:metadata:enrol_lti_users:userid',
59
                'lastgrade' => 'privacy:metadata:enrol_lti_users:lastgrade',
60
                'lastaccess' => 'privacy:metadata:enrol_lti_users:lastaccess',
61
                'timecreated' => 'privacy:metadata:enrol_lti_users:timecreated'
62
            ],
63
            'privacy:metadata:enrol_lti_users'
64
        );
65
 
66
        return $items;
67
    }
68
 
69
    /**
70
     * Get the list of contexts that contain user information for the specified user.
71
     *
72
     * @param int $userid The user to search.
73
     * @return contextlist The contextlist containing the list of contexts used in this plugin.
74
     */
75
    public static function get_contexts_for_userid(int $userid): contextlist {
76
        $contextlist = new contextlist();
77
 
78
        $sql = "SELECT DISTINCT ctx.id
79
                  FROM {enrol_lti_users} ltiusers
80
                  JOIN {enrol_lti_tools} ltitools
81
                    ON ltiusers.toolid = ltitools.id
82
                  JOIN {context} ctx
83
                    ON ctx.id = ltitools.contextid
84
                 WHERE ltiusers.userid = :userid";
85
        $params = ['userid' => $userid];
86
        $contextlist->add_from_sql($sql, $params);
87
 
88
        return $contextlist;
89
    }
90
 
91
    /**
92
     * Get the list of users who have data within a context.
93
     *
94
     * @param   userlist    $userlist   The userlist containing the list of users who have data in this context/plugin combination.
95
     */
96
    public static function get_users_in_context(userlist $userlist) {
97
        $context = $userlist->get_context();
98
 
99
        if (!($context instanceof \context_course || $context instanceof \context_module)) {
100
            return;
101
        }
102
 
103
        $sql = "SELECT ltiusers.userid
104
                  FROM {enrol_lti_users} ltiusers
105
                  JOIN {enrol_lti_tools} ltitools ON ltiusers.toolid = ltitools.id
106
                 WHERE ltitools.contextid = :contextid";
107
        $params = ['contextid' => $context->id];
108
        $userlist->add_from_sql('userid', $sql, $params);
109
    }
110
 
111
    /**
112
     * Export all user data for the specified user, in the specified contexts.
113
     *
114
     * @param approved_contextlist $contextlist The approved contexts to export information for.
115
     */
116
    public static function export_user_data(approved_contextlist $contextlist) {
117
        global $DB;
118
 
119
        if (empty($contextlist->count())) {
120
            return;
121
        }
122
 
123
        $user = $contextlist->get_user();
124
 
125
        list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
126
 
127
        $sql = "SELECT ltiusers.lastgrade, ltiusers.lastaccess, ltiusers.timecreated, ltitools.contextid
128
                  FROM {enrol_lti_users} ltiusers
129
                  JOIN {enrol_lti_tools} ltitools
130
                    ON ltiusers.toolid = ltitools.id
131
                  JOIN {context} ctx
132
                    ON ctx.id = ltitools.contextid
133
                 WHERE ctx.id {$contextsql}
134
                   AND ltiusers.userid = :userid";
135
        $params = $contextparams + ['userid' => $user->id];
136
        $ltiusers = $DB->get_recordset_sql($sql, $params);
137
        self::recordset_loop_and_export($ltiusers, 'contextid', [], function($carry, $record) {
138
            $carry[] = [
139
                'lastgrade' => $record->lastgrade,
140
                'timecreated' => transform::datetime($record->lastaccess),
141
                'timemodified' => transform::datetime($record->timecreated)
142
            ];
143
            return $carry;
144
        }, function($contextid, $data) {
145
            $context = \context::instance_by_id($contextid);
146
            $finaldata = (object) $data;
147
            writer::with_context($context)->export_data(['enrol_lti_users'], $finaldata);
148
        });
149
    }
150
 
151
    /**
152
     * Delete all user data which matches the specified context.
153
     *
154
     * @param \context $context A user context.
155
     */
156
    public static function delete_data_for_all_users_in_context(\context $context) {
157
        global $DB;
158
 
159
        if (!($context instanceof \context_course || $context instanceof \context_module)) {
160
            return;
161
        }
162
 
163
        $enrolltitools = $DB->get_fieldset_select('enrol_lti_tools', 'id', 'contextid = :contextid',
164
            ['contextid' => $context->id]);
165
        if (!empty($enrolltitools)) {
166
            list($sql, $params) = $DB->get_in_or_equal($enrolltitools, SQL_PARAMS_NAMED);
167
            $DB->delete_records_select('enrol_lti_users', 'toolid ' . $sql, $params);
168
        }
169
    }
170
 
171
    /**
172
     * Delete all user data for the specified user, in the specified contexts.
173
     *
174
     * @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
175
     */
176
    public static function delete_data_for_user(approved_contextlist $contextlist) {
177
        global $DB;
178
 
179
        $userid = $contextlist->get_user()->id;
180
 
181
        foreach ($contextlist->get_contexts() as $context) {
182
            if (!($context instanceof \context_course || $context instanceof \context_module)) {
183
                continue;
184
            }
185
 
186
            $enrolltitools = $DB->get_fieldset_select('enrol_lti_tools', 'id', 'contextid = :contextid',
187
                ['contextid' => $context->id]);
188
            if (!empty($enrolltitools)) {
189
                list($sql, $params) = $DB->get_in_or_equal($enrolltitools, SQL_PARAMS_NAMED);
190
                $params = array_merge($params, ['userid' => $userid]);
191
                $DB->delete_records_select('enrol_lti_users', "toolid $sql AND userid = :userid", $params);
192
            }
193
        }
194
    }
195
 
196
    /**
197
     * Delete multiple users within a single context.
198
     *
199
     * @param   approved_userlist   $userlist   The approved context and user information to delete information for.
200
     */
201
    public static function delete_data_for_users(approved_userlist $userlist) {
202
        global $DB;
203
 
204
        $context = $userlist->get_context();
205
 
206
        if (!($context instanceof \context_course || $context instanceof \context_module)) {
207
            return;
208
        }
209
 
210
        $enrolltitools = $DB->get_fieldset_select('enrol_lti_tools', 'id', 'contextid = :contextid',
211
                ['contextid' => $context->id]);
212
        if (!empty($enrolltitools)) {
213
            list($toolsql, $toolparams) = $DB->get_in_or_equal($enrolltitools, SQL_PARAMS_NAMED);
214
            $userids = $userlist->get_userids();
215
            list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
216
            $params = $toolparams + $userparams;
217
            $DB->delete_records_select('enrol_lti_users', "toolid $toolsql AND userid $usersql", $params);
218
        }
219
    }
220
 
221
    /**
222
     * Loop and export from a recordset.
223
     *
224
     * @param \moodle_recordset $recordset The recordset.
225
     * @param string $splitkey The record key to determine when to export.
226
     * @param mixed $initial The initial data to reduce from.
227
     * @param callable $reducer The function to return the dataset, receives current dataset, and the current record.
228
     * @param callable $export The function to export the dataset, receives the last value from $splitkey and the dataset.
229
     * @return void
230
     */
231
    protected static function recordset_loop_and_export(\moodle_recordset $recordset, $splitkey, $initial,
232
            callable $reducer, callable $export) {
233
        $data = $initial;
234
        $lastid = null;
235
 
236
        foreach ($recordset as $record) {
237
            if ($lastid && $record->{$splitkey} != $lastid) {
238
                $export($lastid, $data);
239
                $data = $initial;
240
            }
241
            $data = $reducer($data, $record);
242
            $lastid = $record->{$splitkey};
243
        }
244
        $recordset->close();
245
 
246
        if (!empty($lastid)) {
247
            $export($lastid, $data);
248
        }
249
    }
250
}