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
/**
18
 * Privacy Subsystem implementation for mod_customcert.
19
 *
20
 * @package    mod_customcert
21
 * @copyright  2018 Mark Nelson <markn@moodle.com>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
namespace mod_customcert\privacy;
25
 
26
use core_privacy\local\metadata\collection;
27
use core_privacy\local\request\approved_contextlist;
28
use core_privacy\local\request\approved_userlist;
29
use core_privacy\local\request\contextlist;
30
use core_privacy\local\request\helper;
31
use core_privacy\local\request\transform;
32
use core_privacy\local\request\userlist;
33
use core_privacy\local\request\writer;
34
 
35
/**
36
 * Privacy Subsystem implementation for mod_customcert.
37
 *
38
 * @copyright  2018 Mark Nelson <markn@moodle.com>
39
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40
 */
41
class provider implements
42
    \core_privacy\local\metadata\provider,
43
    \core_privacy\local\request\plugin\provider,
44
    \core_privacy\local\request\core_userlist_provider {
45
 
46
    /**
47
     * Return the fields which contain personal data.
48
     *
49
     * @param collection $items a reference to the collection to use to store the metadata.
50
     * @return collection the updated collection of metadata items.
51
     */
52
    public static function get_metadata(collection $items) : collection {
53
        $items->add_database_table(
54
            'customcert_issues',
55
            [
56
                'userid' => 'privacy:metadata:customcert_issues:userid',
57
                'customcertid' => 'privacy:metadata:customcert_issues:customcertid',
58
                'code' => 'privacy:metadata:customcert_issues:code',
59
                'emailed' => 'privacy:metadata:customcert_issues:emailed',
60
                'timecreated' => 'privacy:metadata:customcert_issues:timecreated',
61
            ],
62
            'privacy:metadata:customcert_issues'
63
        );
64
 
65
        return $items;
66
    }
67
 
68
    /**
69
     * Get the list of contexts that contain user information for the specified user.
70
     *
71
     * @param int $userid the userid.
72
     * @return contextlist the list of contexts containing user info for the user.
73
     */
74
    public static function get_contexts_for_userid(int $userid) : contextlist {
75
        $sql = "SELECT c.id
76
                  FROM {context} c
77
            INNER JOIN {course_modules} cm
78
                    ON cm.id = c.instanceid
79
                   AND c.contextlevel = :contextlevel
80
            INNER JOIN {modules} m
81
                    ON m.id = cm.module
82
                   AND m.name = :modulename
83
            INNER JOIN {customcert} customcert
84
                    ON customcert.id = cm.instance
85
            INNER JOIN {customcert_issues} customcertissues
86
                    ON customcertissues.customcertid = customcert.id
87
                 WHERE customcertissues.userid = :userid";
88
 
89
        $params = [
90
            'modulename' => 'customcert',
91
            'contextlevel' => CONTEXT_MODULE,
92
            'userid' => $userid,
93
        ];
94
        $contextlist = new contextlist();
95
        $contextlist->add_from_sql($sql, $params);
96
 
97
        return $contextlist;
98
    }
99
 
100
    /**
101
     * Get the list of users who have data within a context.
102
     *
103
     * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
104
     */
105
    public static function get_users_in_context(userlist $userlist) {
106
        $context = $userlist->get_context();
107
 
108
        if (!$context instanceof \context_module) {
109
            return;
110
        }
111
 
112
        // Fetch all users who have a custom certificate.
113
        $sql = "SELECT customcertissues.userid
114
                  FROM {course_modules} cm
115
                  JOIN {modules} m
116
                    ON m.id = cm.module AND m.name = :modname
117
                  JOIN {customcert} customcert
118
                    ON customcert.id = cm.instance
119
                  JOIN {customcert_issues} customcertissues
120
                    ON customcertissues.customcertid = customcert.id
121
                 WHERE cm.id = :cmid";
122
 
123
        $params = [
124
            'cmid'      => $context->instanceid,
125
            'modname'   => 'customcert',
126
        ];
127
 
128
        $userlist->add_from_sql('userid', $sql, $params);
129
    }
130
 
131
    /**
132
     * Export personal data for the given approved_contextlist. User and context information is contained within the contextlist.
133
     *
134
     * @param approved_contextlist $contextlist a list of contexts approved for export.
135
     */
136
    public static function export_user_data(approved_contextlist $contextlist) {
137
        global $DB;
138
 
139
        // Filter out any contexts that are not related to modules.
140
        $cmids = array_reduce($contextlist->get_contexts(), function($carry, $context) {
141
            if ($context->contextlevel == CONTEXT_MODULE) {
142
                $carry[] = $context->instanceid;
143
            }
144
            return $carry;
145
        }, []);
146
 
147
        if (empty($cmids)) {
148
            return;
149
        }
150
 
151
        $user = $contextlist->get_user();
152
 
153
        // Get all the customcert activities associated with the above course modules.
154
        $customcertidstocmids = self::get_customcert_ids_to_cmids_from_cmids($cmids);
155
 
156
        list($insql, $inparams) = $DB->get_in_or_equal(array_keys($customcertidstocmids), SQL_PARAMS_NAMED);
157
        $params = array_merge($inparams, ['userid' => $user->id]);
158
        $recordset = $DB->get_recordset_select('customcert_issues', "customcertid $insql AND userid = :userid",
159
            $params, 'timecreated, id ASC');
160
        self::recordset_loop_and_export($recordset, 'customcertid', [], function($carry, $record) {
161
            $carry[] = [
162
                'code' => $record->code,
163
                'emailed' => transform::yesno($record->emailed),
164
                'timecreated' => transform::datetime($record->timecreated),
165
            ];
166
            return $carry;
167
        }, function($customcertid, $data) use ($user, $customcertidstocmids) {
168
            $context = \context_module::instance($customcertidstocmids[$customcertid]);
169
            $contextdata = helper::get_context_data($context, $user);
170
            $finaldata = (object) array_merge((array) $contextdata, ['issues' => $data]);
171
            helper::export_context_files($context, $user);
172
            writer::with_context($context)->export_data([], $finaldata);
173
        });
174
    }
175
 
176
    /**
177
     * Delete all data for all users in the specified context.
178
     *
179
     * @param \context $context the context to delete in.
180
     */
181
    public static function delete_data_for_all_users_in_context(\context $context) {
182
        global $DB;
183
 
184
        if (!$context instanceof \context_module) {
185
            return;
186
        }
187
 
188
        if (!$cm = get_coursemodule_from_id('customcert', $context->instanceid)) {
189
            return;
190
        }
191
 
192
        $DB->delete_records('customcert_issues', ['customcertid' => $cm->instance]);
193
    }
194
 
195
    /**
196
     * Delete all user data for the specified user, in the specified contexts.
197
     *
198
     * @param approved_contextlist $contextlist a list of contexts approved for deletion.
199
     */
200
    public static function delete_data_for_user(approved_contextlist $contextlist) {
201
        global $DB;
202
 
203
        if (empty($contextlist->count())) {
204
            return;
205
        }
206
 
207
        $userid = $contextlist->get_user()->id;
208
        foreach ($contextlist->get_contexts() as $context) {
209
            if (!$context instanceof \context_module) {
210
                continue;
211
            }
212
            $instanceid = $DB->get_field('course_modules', 'instance', ['id' => $context->instanceid], MUST_EXIST);
213
            $DB->delete_records('customcert_issues', ['customcertid' => $instanceid, 'userid' => $userid]);
214
        }
215
    }
216
 
217
    /**
218
     * Delete multiple users within a single context.
219
     *
220
     * @param approved_userlist $userlist The approved context and user information to delete information for.
221
     */
222
    public static function delete_data_for_users(approved_userlist $userlist) {
223
        global $DB;
224
 
225
        $context = $userlist->get_context();
226
        if (!$context instanceof \context_module) {
227
            return;
228
        }
229
 
230
        $cm = get_coursemodule_from_id('customcert', $context->instanceid);
231
        if (!$cm) {
232
            // Only customcert module will be handled.
233
            return;
234
        }
235
 
236
        $userids = $userlist->get_userids();
237
        list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
238
 
239
        $select = "customcertid = :customcertid AND userid $usersql";
240
        $params = ['customcertid' => $cm->instance] + $userparams;
241
        $DB->delete_records_select('customcert_issues', $select, $params);
242
    }
243
 
244
    /**
245
     * Return a list of Customcert IDs mapped to their course module ID.
246
     *
247
     * @param array $cmids The course module IDs.
248
     * @return array In the form of [$customcertid => $cmid].
249
     */
250
    protected static function get_customcert_ids_to_cmids_from_cmids(array $cmids) {
251
        global $DB;
252
 
253
        list($insql, $inparams) = $DB->get_in_or_equal($cmids, SQL_PARAMS_NAMED);
254
        $sql = "SELECT customcert.id, cm.id AS cmid
255
                 FROM {customcert} customcert
256
                 JOIN {modules} m
257
                   ON m.name = :modulename
258
                 JOIN {course_modules} cm
259
                   ON cm.instance = customcert.id
260
                  AND cm.module = m.id
261
                WHERE cm.id $insql";
262
        $params = array_merge($inparams, ['modulename' => 'customcert']);
263
 
264
        return $DB->get_records_sql_menu($sql, $params);
265
    }
266
 
267
    /**
268
     * Loop and export from a recordset.
269
     *
270
     * @param \moodle_recordset $recordset The recordset.
271
     * @param string $splitkey The record key to determine when to export.
272
     * @param mixed $initial The initial data to reduce from.
273
     * @param callable $reducer The function to return the dataset, receives current dataset, and the current record.
274
     * @param callable $export The function to export the dataset, receives the last value from $splitkey and the dataset.
275
     * @return void
276
     */
277
    protected static function recordset_loop_and_export(\moodle_recordset $recordset, $splitkey, $initial,
278
            callable $reducer, callable $export) {
279
        $data = $initial;
280
        $lastid = null;
281
 
282
        foreach ($recordset as $record) {
283
            if ($lastid && $record->{$splitkey} != $lastid) {
284
                $export($lastid, $data);
285
                $data = $initial;
286
            }
287
            $data = $reducer($data, $record);
288
            $lastid = $record->{$splitkey};
289
        }
290
        $recordset->close();
291
 
292
        if (!empty($lastid)) {
293
            $export($lastid, $data);
294
        }
295
    }
296
}