MDL-66074 mod_forum: Forum grading GDPR provider

This commit is contained in:
Mathew May 2019-10-28 13:23:25 +08:00
parent a62c68fb5f
commit c38eb13585

View File

@ -24,6 +24,7 @@
namespace mod_forum\privacy;
use core_grades\component_gradeitem as gradeitem;
use \core_privacy\local\request\userlist;
use \core_privacy\local\request\approved_contextlist;
use \core_privacy\local\request\approved_userlist;
@ -32,6 +33,7 @@ use \core_privacy\local\request\writer;
use \core_privacy\local\request\helper as request_helper;
use \core_privacy\local\metadata\collection;
use \core_privacy\local\request\transform;
use tool_dataprivacy\context_instance;
defined('MOODLE_INTERNAL') || die();
@ -131,7 +133,7 @@ class provider implements
'timemodified' => 'privacy:metadata:forum_queue:timemodified'
], 'privacy:metadata:forum_queue');
//The 'forum_grades' table stores grade data.
// The 'forum_grades' table stores grade data.
$items->add_database_table('forum_grades', [
'userid' => 'privacy:metadata:forum_grades:userid',
'forum' => 'privacy:metadata:forum_grades:forum',
@ -263,7 +265,16 @@ class provider implements
$params += $ratingsql->params;
$contextlist->add_from_sql($sql, $params);
// TODO MDL-66358 forum_grades
// Forum grades.
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {forum} f ON f.id = cm.instance
JOIN {forum_grades} fg ON fg.forum = f.id
WHERE fg.userid = :userid
";
$contextlist->add_from_sql($sql, $params);
return $contextlist;
}
@ -358,6 +369,15 @@ class provider implements
JOIN {forum_track_prefs} pref ON pref.forumid = f.id
WHERE cm.id = :instanceid";
$userlist->add_from_sql('userid', $sql, $params);
// Forum grades.
$sql = "SELECT fg.userid
FROM {course_modules} cm
JOIN {modules} m ON m.id = cm.module AND m.name = :modulename
JOIN {forum} f ON f.id = cm.instance
JOIN {forum_grades} fg ON fg.forum = f.id
WHERE cm.id = :instanceid";
$userlist->add_from_sql('userid', $sql, $params);
}
/**
@ -520,6 +540,23 @@ class provider implements
$params['userid'] = $userid;
$tracked = $DB->get_records_sql_menu($sql, $params);
// Forum grades.
$sql = "SELECT
c.id AS contextid,
fg.grade AS grade,
f.grade_forum AS gradetype
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid
JOIN {forum} f ON f.id = cm.instance
JOIN {forum_grades} fg ON fg.forum = f.id
WHERE (
fg.userid = :userid AND
c.id {$contextsql}
)
";
$params['userid'] = $userid;
$grades = $DB->get_records_sql_menu($sql, $params);
$sql = "SELECT
c.id AS contextid,
f.*,
@ -559,6 +596,9 @@ class provider implements
if (isset($tracked[$forum->contextid])) {
static::export_tracking_data($userid, $forum, $tracked[$forum->contextid]);
}
if (isset($grades[$forum->contextid])) {
static::export_grading_data($userid, $forum, $grades[$forum->contextid]);
}
}
$forums->close();
@ -978,6 +1018,46 @@ class provider implements
return false;
}
protected static function export_grading_data(int $userid, \stdClass $forum, int $grade) {
global $USER;
if (null !== $grade) {
$context = \context_module::instance($forum->cmid);
$exportpath = array_merge([],
[get_string('privacy:metadata:forum_grades', 'mod_forum')]);
$gradingmanager = get_grading_manager($context, 'mod_forum', 'forum');
$controller = $gradingmanager->get_active_controller();
// Check for advanced grading and retrieve that information.
if (isset($controller)) {
$gradeduser = \core_user::get_user($userid);
// Fetch the gradeitem instance.
$gradeitem = gradeitem::instance($controller->get_component(), $context, $controller->get_area());
$grade = $gradeitem->get_grade_for_user($gradeduser, $USER);
$controllercontext = $controller->get_context();
\core_grading\privacy\provider::export_item_data($controllercontext, $grade->id, $exportpath);
} else {
self::export_grade_data($grade, $context, $forum, $exportpath);
}
// The user has a grade for this forum.
writer::with_context(\context_module::instance($forum->cmid))
->export_metadata($exportpath, 'gradingenabled', 1, get_string('privacy:metadata:forum_grades:grade', 'mod_forum'));
return true;
}
return false;
}
protected static function export_grade_data(int $grade, \context $context, \stdClass $forum, array $path) {
$gradedata = (object)[
'forum' => $forum->name,
'grade' => $grade,
];
writer::with_context($context)
->export_data($path, $gradedata);
}
/**
* Store read-tracking information about a particular forum post.
*
@ -1033,9 +1113,19 @@ class provider implements
$DB->delete_records('forum_track_prefs', ['forumid' => $forumid]);
$DB->delete_records('forum_subscriptions', ['forum' => $forumid]);
$DB->delete_records('forum_grades', ['forum' => $forumid]);
$DB->delete_records('forum_read', ['forumid' => $forumid]);
$DB->delete_records('forum_digests', ['forum' => $forumid]);
// Delete advanced grading information.
$gradingmanager = get_grading_manager($context, 'mod_forum', 'forum');
$controller = $gradingmanager->get_active_controller();
if (isset($controller)) {
\core_grading\privacy\provider::delete_instance_data($context);
}
$DB->delete_records('forum_grades', ['forum' => $forumid]);
// Delete all discussion items.
$DB->delete_records_select(
'forum_queue',
@ -1115,6 +1205,22 @@ class provider implements
'userid' => $userid,
]);
// Handle any advanced grading method data first.
$grades = $DB->get_records('forum_grades', ['forum' => $forum->id, 'userid' => $user->id]);
$gradingmanager = get_grading_manager($context, 'forum_grades', 'forum');
$controller = $gradingmanager->get_active_controller();
foreach ($grades as $grade) {
// Delete advanced grading information.
if (isset($controller)) {
\core_grading\privacy\provider::delete_instance_data($context, $grade->id);
}
}
// Advanced grading methods have been cleared, lets clear our module now.
$DB->delete_records('forum_grades', [
'forum' => $forum->id,
'userid' => $userid,
]);
// Do not delete discussion or forum posts.
// Instead update them to reflect that the content has been deleted.
$postsql = "userid = :userid AND discussion IN (SELECT id FROM {forum_discussions} WHERE forum = :forum)";
@ -1203,5 +1309,19 @@ class provider implements
$fs = get_file_storage();
$fs->delete_area_files_select($context->id, 'mod_forum', 'post', "IN ($postidsql)", $params);
$fs->delete_area_files_select($context->id, 'mod_forum', 'attachment', "IN ($postidsql)", $params);
list($sql, $params) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED);
$params['forum'] = $forum->id;
// Delete advanced grading information.
$grades = $DB->get_records_select('forum_grades', "forum = :forum AND userid $sql", $params);
$gradeids = array_keys($grades);
$gradingmanager = get_grading_manager($context, 'mod_forum', 'forum');
$controller = $gradingmanager->get_active_controller();
if (isset($controller)) {
// Careful here, if no gradeids are provided then all data is deleted for the context.
if (!empty($gradeids)) {
\core_grading\privacy\provider::delete_data_for_instances($context, $gradeids);
}
}
}
}