Skip to content

Commit 5d2dd88

Browse files
author
David Monllao
committed
Merge branch 'MDL-61943-master' of git://github.com/cescobedo/moodle
2 parents 02c7769 + a69de9b commit 5d2dd88

File tree

3 files changed

+876
-0
lines changed

3 files changed

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

0 commit comments

Comments
 (0)