2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * This file contains the core_privacy\local\request helper.
20 * @package core_privacy
21 * @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 namespace core_privacy\local\request
;
27 use \core_privacy\local\request\writer
;
29 defined('MOODLE_INTERNAL') ||
die();
31 require_once($CFG->libdir
. '/modinfolib.php');
32 require_once($CFG->dirroot
. '/course/modlib.php');
35 * The core_privacy\local\request\helper class with useful shared functionality.
37 * @package core_privacy
38 * @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
45 * Add core-controlled contexts which are related to a component but that component may know about.
47 * For example, most activities are not aware of activity completion, but the course implements it for them.
48 * These should be included.
50 * @param int $userid The user being added for.
51 * @param contextlist $contextlist The contextlist being appended to.
52 * @return contextlist The final contextlist
54 public static function add_shared_contexts_to_contextlist_for(int $userid, contextlist
$contextlist) : contextlist
{
55 if (strpos($contextlist->get_component(), 'mod_') === 0) {
56 // Activity modules support data stored by core about them - for example, activity completion.
57 $contextlist = static::add_shared_contexts_to_contextlist_for_course_module($userid, $contextlist);
64 * Add core-controlled contexts which are related to a component but that component may know about.
66 * For example, most activities are not aware of activity completion, but the course implements it for them.
67 * These should be included.
69 * @param \core_privacy\local\request\userlist $userlist
70 * @return contextlist The final contextlist
72 public static function add_shared_users_to_userlist(\core_privacy\local\request\userlist
$userlist) {
76 * Handle export of standard data for a plugin which implements the null provider and does not normally store data
79 * This is used in cases such as activities like mod_resource, which do not store their own data, but may still have
80 * data on them (like Activity Completion).
82 * Any context provided in a contextlist should have base data exported as a minimum.
84 * @param approved_contextlist $contextlist The approved contexts to export information for.
86 public static function export_data_for_null_provider(approved_contextlist
$contextlist) {
87 $user = $contextlist->get_user();
88 foreach ($contextlist as $context) {
89 $data = static::get_context_data($context, $user);
90 static::export_context_files($context, $user);
92 writer
::with_context($context)->export_data([], $data);
97 * Handle removal of 'standard' data for any plugin.
99 * This will handle deletion for things such as activity completion.
101 * @param string $component The component being deleted for.
102 * @param context $context The specific context to delete data for.
104 public static function delete_data_for_all_users_in_context(string $component, \context
$context) {
105 // Activity modules support data stored by core about them - for example, activity completion.
106 static::delete_data_for_all_users_in_context_course_module($component, $context);
110 * Delete all 'standard' user data for the specified user, in the specified contexts.
112 * This will handle deletion for things such as activity completion.
114 * @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
116 public static function delete_data_for_user(approved_contextlist
$contextlist) {
117 $component = $contextlist->get_component();
119 // Activity modules support data stored by core about them - for example, activity completion.
120 static::delete_data_for_user_in_course_module($contextlist);
124 * Get all general data for this context.
126 * @param \context $context The context to retrieve data for.
127 * @param \stdClass $user The user being written.
130 public static function get_context_data(\context
$context, \stdClass
$user) : \stdClass
{
133 $basedata = (object) [];
134 if ($context instanceof \context_module
) {
135 return static::get_context_module_data($context, $user);
137 if ($context instanceof \context_block
) {
138 return static::get_context_block_data($context, $user);
145 * Export all files for this context.
147 * @param \context $context The context to export files for.
148 * @param \stdClass $user The user being written.
151 public static function export_context_files(\context
$context, \stdClass
$user) {
152 if ($context instanceof \context_module
) {
153 return static::export_context_module_files($context, $user);
158 * Add core-controlled contexts which are related to a component but that component may know about.
160 * For example, most activities are not aware of activity completion, but the course implements it for them.
161 * These should be included.
163 * @param int $userid The user being added for.
164 * @param contextlist $contextlist The contextlist being appended to.
165 * @return contextlist The final contextlist
167 protected static function add_shared_contexts_to_contextlist_for_course_module(int $userid, contextlist
$contextlist) : contextlist
{
168 // Fetch all contexts where the user has activity completion enabled.
171 FROM {course_modules_completion} cmp
172 INNER JOIN {course_modules} cm ON cm.id = cmp.coursemoduleid
173 INNER JOIN {modules} m ON m.id = cm.module
174 INNER JOIN {context} c ON c.instanceid = cm.id AND c.contextlevel = :contextlevel
175 WHERE cmp.userid = :userid
176 AND m.name = :modname";
179 // Strip the mod_ from the name.
180 'modname' => substr($contextlist->get_component(), 4),
181 'contextlevel' => CONTEXT_MODULE
,
184 $contextlist->add_from_sql($sql, $params);
190 * Get all general data for the activity module at this context.
192 * @param \context_module $context The context to retrieve data for.
193 * @param \stdClass $user The user being written.
196 protected static function get_context_module_data(\context_module
$context, \stdClass
$user) : \stdClass
{
199 $coursecontext = $context->get_course_context();
200 $modinfo = get_fast_modinfo($coursecontext->instanceid
);
201 $cm = $modinfo->cms
[$context->instanceid
];
202 $component = "mod_{$cm->modname}";
203 $course = $cm->get_course();
204 $moduledata = $DB->get_record($cm->modname
, ['id' => $cm->instance
]);
206 $basedata = (object) [
207 'name' => $cm->get_formatted_name(),
210 if (plugin_supports('mod', $cm->modname
, FEATURE_MOD_INTRO
, true)) {
211 $intro = $moduledata->intro
;
213 $intro = writer
::with_context($context)
214 ->rewrite_pluginfile_urls([], $component, 'intro', 0, $intro);
219 'context' => $context,
220 'overflowdiv' => true,
222 $basedata->intro
= format_text($intro, $moduledata->introformat
, $options);
225 // Completion tracking.
226 $completiondata = \core_completion\privacy\provider
::get_activity_completion_info($user, $course, $cm);
227 if (isset($completiondata->completionstate
)) {
228 $basedata->completion
= (object) [
229 'state' => $completiondata->completionstate
,
237 * Get all general data for the block at this context.
239 * @param \context_block $context The context to retrieve data for.
240 * @param \stdClass $user The user being written.
241 * @return \stdClass General data about this block instance.
243 protected static function get_context_block_data(\context_block
$context, \stdClass
$user) : \stdClass
{
246 $block = $DB->get_record('block_instances', ['id' => $context->instanceid
]);
248 $basedata = (object) [
249 'blocktype' => get_string('pluginname', 'block_' . $block->blockname
)
256 * Get all general data for the activity module at this context.
258 * @param \context_module $context The context to retrieve data for.
259 * @param \stdClass $user The user being written.
262 protected static function export_context_module_files(\context_module
$context, \stdClass
$user) {
263 $coursecontext = $context->get_course_context();
264 $modinfo = get_fast_modinfo($coursecontext->instanceid
);
265 $cm = $modinfo->cms
[$context->instanceid
];
266 $component = "mod_{$cm->modname}";
268 writer
::with_context($context)
269 // Export the files for the intro.
270 ->export_area_files([], $component, 'intro', 0);
274 * Handle removal of 'standard' data for course modules.
276 * This will handle deletion for things such as activity completion.
278 * @param string $component The component being deleted for.
279 * @param \context $context The context to delete all data for.
281 public static function delete_data_for_all_users_in_context_course_module(string $component, \context
$context) {
284 if ($context instanceof \context_module
) {
285 // Delete course completion data for this context.
286 \core_completion\privacy\provider
::delete_completion(null, null, $context->instanceid
);
291 * Delete all 'standard' user data for the specified user in course modules.
293 * This will handle deletion for things such as activity completion.
295 * @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
297 protected static function delete_data_for_user_in_course_module(approved_contextlist
$contextlist) {
300 foreach ($contextlist as $context) {
301 if ($context instanceof \context_module
) {
302 // Delete course completion data for this context.
303 \core_completion\privacy\provider
::delete_completion($contextlist->get_user(), null, $context->instanceid
);