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 core_role.
19
 *
20
 * @package    core_role
21
 * @copyright  2018 Carlos Escobedo <carlos@moodle.com>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
namespace core_role\privacy;
26
 
27
defined('MOODLE_INTERNAL') || die();
28
 
29
use \core_privacy\local\metadata\collection;
30
use \core_privacy\local\request\contextlist;
31
use \core_privacy\local\request\approved_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;
36
 
37
/**
38
 * Privacy provider for core_role.
39
 *
40
 * @copyright  2018 Carlos Escobedo <carlos@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\subsystem\provider,
46
    \core_privacy\local\request\subsystem\plugin_provider,
47
    \core_privacy\local\request\user_preference_provider,
48
    \core_privacy\local\request\core_userlist_provider {
49
 
50
    /**
51
     * Get information about the user data stored by this plugin.
52
     *
53
     * @param  collection $collection An object for storing metadata.
54
     * @return collection The metadata.
55
     */
56
    public static function get_metadata(collection $collection): collection {
57
        $rolecapabilities = [
58
            'roleid' => 'privacy:metadata:role_capabilities:roleid',
59
            'capability' => 'privacy:metadata:role_capabilities:capability',
60
            'permission' => 'privacy:metadata:role_capabilities:permission',
61
            'timemodified' => 'privacy:metadata:role_capabilities:timemodified',
62
            'modifierid' => 'privacy:metadata:role_capabilities:modifierid'
63
        ];
64
        $roleassignments = [
65
            'roleid' => 'privacy:metadata:role_assignments:roleid',
66
            'userid' => 'privacy:metadata:role_assignments:userid',
67
            'timemodified' => 'privacy:metadata:role_assignments:timemodified',
68
            'modifierid' => 'privacy:metadata:role_assignments:modifierid',
69
            'component' => 'privacy:metadata:role_assignments:component',
70
            'itemid' => 'privacy:metadata:role_assignments:itemid'
71
        ];
72
        $collection->add_database_table('role_capabilities', $rolecapabilities,
73
            'privacy:metadata:role_capabilities:tableexplanation');
74
        $collection->add_database_table('role_assignments', $roleassignments,
75
            'privacy:metadata:role_assignments:tableexplanation');
76
 
77
        $collection->add_user_preference('definerole_showadvanced',
78
            'privacy:metadata:preference:showadvanced');
79
 
80
        return $collection;
81
    }
82
    /**
83
     * Export all user preferences for the plugin.
84
     *
85
     * @param   int         $userid The userid of the user whose data is to be exported.
86
     */
87
    public static function export_user_preferences(int $userid) {
88
        $showadvanced = get_user_preferences('definerole_showadvanced', null, $userid);
89
        if ($showadvanced !== null) {
90
            writer::export_user_preference('core_role',
91
                'definerole_showadvanced',
92
                transform::yesno($showadvanced),
93
                get_string('privacy:metadata:preference:showadvanced', 'core_role')
94
            );
95
        }
96
    }
97
    /**
98
     * Return all contexts for this userid.
99
     *
100
     * @param  int $userid The user ID.
101
     * @return contextlist The list of context IDs.
102
     */
103
    public static function get_contexts_for_userid(int $userid): contextlist {
104
        global $DB;
105
 
106
        $contextlist = new contextlist();
107
 
108
        // The role_capabilities table contains user data.
109
        $contexts = [
110
            CONTEXT_SYSTEM,
111
            CONTEXT_USER,
112
            CONTEXT_COURSECAT,
113
            CONTEXT_COURSE,
114
            CONTEXT_MODULE,
115
            CONTEXT_BLOCK
116
        ];
117
        list($insql, $inparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
118
        $sql = "SELECT ctx.id
119
                  FROM {context} ctx
120
                  JOIN {role_capabilities} rc
121
                    ON rc.contextid = ctx.id
122
                   AND ((ctx.contextlevel {$insql} AND rc.modifierid = :modifierid)
123
                    OR (ctx.contextlevel = :contextlevel AND ctx.instanceid = :userid))";
124
        $params = [
125
            'modifierid' => $userid,
126
            'contextlevel' => CONTEXT_USER,
127
            'userid' => $userid
128
         ];
129
        $params += $inparams;
130
 
131
        $contextlist->add_from_sql($sql, $params);
132
 
133
        // The role_assignments table contains user data.
134
        $contexts = [
135
            CONTEXT_SYSTEM,
136
            CONTEXT_USER,
137
            CONTEXT_COURSECAT,
138
            CONTEXT_COURSE,
139
            CONTEXT_MODULE,
140
            CONTEXT_BLOCK
141
        ];
142
        list($insql, $inparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
143
        $params = [
144
            'userid' => $userid,
145
            'modifierid' => $userid
146
         ];
147
        $params += $inparams;
148
        $sql = "SELECT ctx.id
149
                  FROM {role_assignments} ra
150
                  JOIN {context} ctx
151
                    ON ctx.id = ra.contextid
152
                   AND ctx.contextlevel {$insql}
153
                 WHERE (ra.userid = :userid
154
                    OR ra.modifierid = :modifierid)
155
                   AND ra.component != 'tool_cohortroles'";
156
        $contextlist->add_from_sql($sql, $params);
157
 
158
        return $contextlist;
159
    }
160
 
161
    /**
162
     * Get the list of users within a specific context.
163
     *
164
     * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
165
     */
166
    public static function get_users_in_context(userlist $userlist) {
167
 
168
        if (empty($userlist)) {
169
            return;
170
        }
171
 
172
        $context = $userlist->get_context();
173
 
174
        // Include users who created or modified role capabilities.
175
        $sql = "SELECT modifierid as userid
176
                  FROM {role_capabilities}
177
                 WHERE contextid = :contextid";
178
 
179
        $params = [
180
            'contextid' => $context->id
181
        ];
182
 
183
        $userlist->add_from_sql('userid', $sql, $params);
184
 
185
        // Include users that have a role assigned to them.
186
        $sql = "SELECT userid
187
                  FROM {role_assignments}
188
                 WHERE contextid = :contextid";
189
 
190
        $userlist->add_from_sql('userid', $sql, $params);
191
 
192
        // Include users who created or modified the role assignment.
193
        // Differentiate and exclude special cases where tool_cohortroles adds records through the
194
        // "Assign user roles to cohort" feature into the role_assignments table.
195
        // These records should be separately processed in tool_cohortroles.
196
        $sql = "SELECT modifierid as userid
197
                  FROM {role_assignments}
198
                 WHERE contextid = :contextid
199
                       AND component != 'tool_cohortroles'";
200
 
201
        $userlist->add_from_sql('userid', $sql, $params);
202
    }
203
 
204
    /**
205
     * Export all user data for the specified user, in the specified contexts.
206
     *
207
     * @param  approved_contextlist $contextlist The list of approved contexts for a user.
208
     */
209
    public static function export_user_data(approved_contextlist $contextlist) {
210
        global $DB;
211
 
212
        if (empty($contextlist)) {
213
             return;
214
        }
215
 
216
        $rolesnames = self::get_roles_name();
217
        $userid = $contextlist->get_user()->id;
218
        $ctxfields = \context_helper::get_preload_record_columns_sql('ctx');
219
        list($insql, $inparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
220
 
221
        // Role Assignments export data.
222
        $contexts = [
223
            CONTEXT_SYSTEM,
224
            CONTEXT_USER,
225
            CONTEXT_COURSECAT,
226
            CONTEXT_COURSE,
227
            CONTEXT_MODULE,
228
            CONTEXT_BLOCK
229
        ];
230
        list($inctxsql, $ctxparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
231
        $sql = "SELECT ra.id, ra.contextid, ra.roleid, ra.userid, ra.timemodified, ra.modifierid, $ctxfields
232
                  FROM {role_assignments} ra
233
                  JOIN {context} ctx
234
                    ON ctx.id = ra.contextid
235
                   AND ctx.contextlevel {$inctxsql}
236
                   AND (ra.userid = :userid OR ra.modifierid = :modifierid)
237
                   AND ra.component != 'tool_cohortroles'
238
                  JOIN {role} r
239
                    ON r.id = ra.roleid
240
                 WHERE ctx.id {$insql}";
241
        $params = ['userid' => $userid, 'modifierid' => $userid];
242
        $params += $inparams;
243
        $params += $ctxparams;
244
        $assignments = $DB->get_recordset_sql($sql, $params);
245
        foreach ($assignments as $assignment) {
246
            \context_helper::preload_from_record($assignment);
247
            $alldata[$assignment->contextid][$rolesnames[$assignment->roleid]][] = (object)[
248
                'timemodified' => transform::datetime($assignment->timemodified),
249
                'userid' => transform::user($assignment->userid),
250
                'modifierid' => transform::user($assignment->modifierid)
251
            ];
252
        }
253
        $assignments->close();
254
        if (!empty($alldata)) {
255
            array_walk($alldata, function($roledata, $contextid) {
256
                $context = \context::instance_by_id($contextid);
257
                array_walk($roledata, function($data, $rolename) use ($context) {
258
                    writer::with_context($context)->export_data(
259
                            [get_string('privacy:metadata:role_assignments', 'core_role'), $rolename],
260
                            (object)$data);
261
                });
262
            });
263
            unset($alldata);
264
        }
265
 
266
        // Role Capabilities export data.
267
        $strpermissions = self::get_permissions_name();
268
        $contexts = [
269
            CONTEXT_SYSTEM,
270
            CONTEXT_USER,
271
            CONTEXT_COURSECAT,
272
            CONTEXT_COURSE,
273
            CONTEXT_MODULE,
274
            CONTEXT_BLOCK
275
        ];
276
        list($inctxsql, $ctxparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
277
        $sql = "SELECT rc.id, rc.contextid, rc.capability, rc.permission, rc.timemodified, rc.roleid, $ctxfields
278
                  FROM {context} ctx
279
                  JOIN {role_capabilities} rc
280
                    ON rc.contextid = ctx.id
281
                   AND ((ctx.contextlevel {$inctxsql} AND rc.modifierid = :modifierid)
282
                    OR (ctx.contextlevel = :contextlevel AND ctx.instanceid = :userid))
283
                 WHERE ctx.id {$insql}";
284
        $params = [
285
            'modifierid' => $userid,
286
            'contextlevel' => CONTEXT_USER,
287
            'userid' => $userid
288
         ];
289
        $params += $inparams;
290
        $params += $ctxparams;
291
        $capabilities = $DB->get_recordset_sql($sql, $params);
292
        foreach ($capabilities as $capability) {
293
            \context_helper::preload_from_record($capability);
294
            $alldata[$capability->contextid][$rolesnames[$capability->roleid]][] = (object)[
295
                'timemodified' => transform::datetime($capability->timemodified),
296
                'capability' => $capability->capability,
297
                'permission' => $strpermissions[$capability->permission]
298
            ];
299
        }
300
        $capabilities->close();
301
        if (!empty($alldata)) {
302
            array_walk($alldata, function($capdata, $contextid) {
303
                $context = \context::instance_by_id($contextid);
304
                array_walk($capdata, function($data, $rolename) use ($context) {
305
                    writer::with_context($context)->export_data(
306
                            [get_string('privacy:metadata:role_capabilities', 'core_role'), $rolename],
307
                            (object)$data);
308
                });
309
            });
310
        }
311
    }
312
    /**
313
     * Exports the data relating to tool_cohortroles component on role assignments by
314
     * Assign user roles to cohort feature.
315
     *
316
     * @param  int $userid The user ID.
317
     */
318
    public static function export_user_role_to_cohort(int $userid) {
319
        global $DB;
320
 
321
        $rolesnames = self::get_roles_name();
322
        $sql = "SELECT ra.id, ra.contextid, ra.roleid, ra.userid, ra.timemodified, ra.modifierid, r.id as roleid
323
                  FROM {role_assignments} ra
324
                  JOIN {context} ctx
325
                    ON ctx.id = ra.contextid
326
                   AND ctx.contextlevel = :contextlevel
327
                   AND ra.component = 'tool_cohortroles'
328
                  JOIN {role} r
329
                    ON r.id = ra.roleid
330
                 WHERE ctx.instanceid = :instanceid
331
                    OR ra.userid = :userid";
332
        $params = ['userid' => $userid, 'instanceid' => $userid, 'contextlevel' => CONTEXT_USER];
333
        $assignments = $DB->get_recordset_sql($sql, $params);
334
        foreach ($assignments as $assignment) {
335
            $alldata[$assignment->contextid][$rolesnames[$assignment->roleid]][] = (object)[
336
                'timemodified' => transform::datetime($assignment->timemodified),
337
                'userid' => transform::user($assignment->userid),
338
                'modifierid' => transform::user($assignment->modifierid)
339
            ];
340
        }
341
        $assignments->close();
342
        if (!empty($alldata)) {
343
            array_walk($alldata, function($roledata, $contextid) {
344
                $context = \context::instance_by_id($contextid);
345
                array_walk($roledata, function($data, $rolename) use ($context) {
346
                    writer::with_context($context)->export_related_data(
347
                            [get_string('privacy:metadata:role_cohortroles', 'core_role'), $rolename], 'cohortroles',
348
                            (object)$data);
349
                });
350
            });
351
        }
352
    }
353
    /**
354
     * Delete all user data for this context.
355
     *
356
     * @param  \context $context The context to delete data for.
357
     */
358
    public static function delete_data_for_all_users_in_context(\context $context) {
359
        global $DB;
360
 
361
        // Don't remove data from role_capabilities.
362
        // Because this data affects the whole Moodle, there are override capabilities.
363
        // Don't belong to the modifier user.
364
 
365
        // Remove data from role_assignments.
366
        $DB->delete_records('role_assignments', ['contextid' => $context->id]);
367
    }
368
 
369
    /**
370
     * Delete multiple users within a single context.
371
     *
372
     * @param approved_userlist $userlist The approved context and user information to delete information for.
373
     */
374
    public static function delete_data_for_users(approved_userlist $userlist) {
375
        global $DB;
376
 
377
        // Don't remove data from role_capabilities.
378
        // Because this data affects the whole Moodle, there are override capabilities.
379
        // Don't belong to the modifier user.
380
        $context = $userlist->get_context();
381
        $userids = $userlist->get_userids();
382
 
383
        if (empty($userids)) {
384
            return;
385
        }
386
        list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
387
        $params = ['contextid' => $context->id] + $userparams;
388
 
389
        // Remove data from role_assignments.
390
        $DB->delete_records_select('role_assignments',
391
            "contextid = :contextid AND userid {$usersql}", $params);
392
    }
393
 
394
    /**
395
     * Delete all user data for this user only.
396
     *
397
     * @param  approved_contextlist $contextlist The list of approved contexts for a user.
398
     */
399
    public static function delete_data_for_user(approved_contextlist $contextlist) {
400
        global $DB;
401
 
402
        // Don't remove data from role_capabilities.
403
        // Because this data affects the whole Moodle, there are override capabilities.
404
        // Don't belong to the modifier user.
405
 
406
        // Remove data from role_assignments.
407
        if (empty($contextlist->count())) {
408
            return;
409
        }
410
        $userid = $contextlist->get_user()->id;
411
        $contextids = $contextlist->get_contextids();
412
 
413
        list($contextsql, $contextparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED);
414
        $params = ['userid' => $userid] + $contextparams;
415
 
416
        // Only delete the roles assignments where the user is assigned in all contexts.
417
        $DB->delete_records_select('role_assignments',
418
            "userid = :userid AND contextid {$contextsql}", $params);
419
    }
420
    /**
421
     * Delete user entries in role_assignments related to the feature
422
     * Assign user roles to cohort feature.
423
     *
424
     * @param  int $userid The user ID.
425
     */
426
    public static function delete_user_role_to_cohort(int $userid) {
427
        global $DB;
428
 
429
        // Delete entries where userid is a mentor by tool_cohortroles.
430
        $DB->delete_records('role_assignments', ['userid' => $userid, 'component' => 'tool_cohortroles']);
431
    }
432
    /**
433
     * Get all the localised roles name in a simple array.
434
     *
435
     * @return array Array of name of the roles by roleid.
436
     */
437
    protected static function get_roles_name() {
438
        $roles = role_fix_names(get_all_roles(), \context_system::instance(), ROLENAME_ORIGINAL);
439
        $rolesnames = array();
440
        foreach ($roles as $role) {
441
            $rolesnames[$role->id] = $role->localname;
442
        }
443
        return $rolesnames;
444
    }
445
    /**
446
     * Get all the permissions name in a simple array.
447
     *
448
     * @return array Array of permissions name.
449
     */
450
    protected static function get_permissions_name() {
451
        $strpermissions = array(
452
            CAP_INHERIT => get_string('inherit', 'role'),
453
            CAP_ALLOW => get_string('allow', 'role'),
454
            CAP_PREVENT => get_string('prevent', 'role'),
455
            CAP_PROHIBIT => get_string('prohibit', 'role')
456
        );
457
        return $strpermissions;
458
    }
459
}