Skip to content

Commit

Permalink
MDL-67798 core_contentbank: Add privacy provider
Browse files Browse the repository at this point in the history
  • Loading branch information
cescobedo committed Apr 24, 2020
1 parent 9df4a4d commit aeacd6c
Show file tree
Hide file tree
Showing 4 changed files with 557 additions and 43 deletions.
235 changes: 194 additions & 41 deletions contentbank/classes/privacy/provider.php
Expand Up @@ -26,9 +26,14 @@

use core_privacy\local\metadata\collection;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\approved_userlist;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\transform;
use core_privacy\local\request\writer;
use core_privacy\local\request\userlist;
use core_privacy\local\request\approved_userlist;
use context_system;
use context_coursecat;
use context_course;

/**
* Privacy provider implementation for core_contentbank.
Expand All @@ -42,88 +47,236 @@ class provider implements
\core_privacy\local\request\plugin\provider {

/**
* Returns metadata.
* TODO: MDL-67798.
* Returns meta data about this system.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection) : collection {
// We are not implementing a proper privacy provider for now.
// A right privacy provider will be implemented in MDL-67798.

$collection->add_database_table('contentbank_content', [
'name' => 'privacy:metadata:content:name',
'contenttype' => 'privacy:metadata:content:contenttype',
'usercreated' => 'privacy:metadata:content:usercreated',
'usermodified' => 'privacy:metadata:content:usermodified',
], 'privacy:metadata:userid');
'timecreated' => 'privacy:metadata:content:timecreated',
'timemodified' => 'privacy:metadata:content:timemodified',
], 'privacy:metadata:contentbankcontent');

return $collection;
}

/**
* TODO: MDL-67798.
* Get the list of contexts that contain user information for the specified user.
*
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
* @param int $userid The user to search.
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
*/
public static function get_users_in_context(userlist $userlist) {
// We are not implementing a proper privacy provider for now.
// A right privacy provider will be implemented in MDL-67798.
}
public static function get_contexts_for_userid(int $userid) : contextlist {
$sql = "SELECT DISTINCT ctx.id
FROM {context} ctx
JOIN {contentbank_content} cb
ON cb.contextid = ctx.id
WHERE cb.usercreated = :userid
AND (ctx.contextlevel = :contextlevel1
OR ctx.contextlevel = :contextlevel2
OR ctx.contextlevel = :contextlevel3)";

/**
* TODO: MDL-67798.
*
* @param approved_userlist $userlist The approved context and user information to delete information for.
*/
public static function delete_data_for_users(approved_userlist $userlist) {
// We are not implementing a proper privacy provider for now.
// A right privacy provider will be implemented in MDL-67798.
$params = [
'userid' => $userid,
'contextlevel1' => CONTEXT_SYSTEM,
'contextlevel2' => CONTEXT_COURSECAT,
'contextlevel3' => CONTEXT_COURSE
];

$contextlist = new contextlist();
$contextlist->add_from_sql($sql, $params);

return $contextlist;
}

/**
* TODO: MDL-67798.
* Get the list of contexts that contain user information for the specified user.
* Get the list of users within a specific context.
*
* @param int $userid The user to search.
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
*/
public static function get_contexts_for_userid(int $userid) : contextlist {
// We are not implementing a proper privacy provider for now.
// A right privacy provider will be implemented in MDL-67798.
public static function get_users_in_context(userlist $userlist) {
$context = $userlist->get_context();

$allowedcontextlevels = [
CONTEXT_SYSTEM,
CONTEXT_COURSECAT,
CONTEXT_COURSE
];

if (!in_array($context->contextlevel, $allowedcontextlevels)) {
return;
}

return (new contextlist());
$sql = "SELECT cb.usercreated as userid
FROM {contentbank_content} cb
WHERE cb.contextid = :contextid";

$params = [
'contextid' => $context->id
];

$userlist->add_from_sql('userid', $sql, $params);
}

/**
* TODO: MDL-67798.
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts to export information for.
* @param approved_contextlist $contextlist The approved contexts to export information for.
*/
public static function export_user_data(approved_contextlist $contextlist) {
// We are not implementing a proper privacy provider for now.
// A right privacy provider will be implemented in MDL-67798.
global $DB;

// Remove contexts different from SYSTEM, COURSECAT or COURSE.
$contextids = array_reduce($contextlist->get_contexts(), function($carry, $context) {
if ($context->contextlevel == CONTEXT_SYSTEM || $context->contextlevel == CONTEXT_COURSECAT
|| $context->contextlevel == CONTEXT_COURSE) {
$carry[] = $context->id;
}
return $carry;
}, []);

if (empty($contextids)) {
return;
}

$userid = $contextlist->get_user()->id;

list($contextsql, $contextparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED);
// Retrieve the contentbank_content records created for the user.
$sql = "SELECT cb.id,
cb.name,
cb.contenttype,
cb.usercreated,
cb.usermodified,
cb.timecreated,
cb.timemodified,
cb.contextid
FROM {contentbank_content} cb
WHERE cb.usercreated = :userid
AND cb.contextid {$contextsql}
ORDER BY cb.contextid";

$params = ['userid' => $userid] + $contextparams;

$contents = $DB->get_recordset_sql($sql, $params);
$data = [];
$lastcontextid = null;
$subcontext = [
get_string('name', 'core_contentbank')
];
foreach ($contents as $content) {
// The core_contentbank data export is organised in:
// {Sytem|Course Category|Course Context Level}/Content/data.json.
if ($lastcontextid && $lastcontextid != $content->contextid) {
$context = \context::instance_by_id($lastcontextid);
writer::with_context($context)->export_data($subcontext, (object)$data);
$data = [];
}
$data[] = (object) [
'name' => $content->name,
'contenttype' => $content->contenttype,
'usercreated' => transform::user($content->usercreated),
'usermodified' => transform::user($content->usermodified),
'timecreated' => transform::datetime($content->timecreated),
'timemodified' => transform::datetime($content->timemodified)
];
$lastcontextid = $content->contextid;

// The core_contentbank files export is organised in:
// {Sytem|Course Category|Course Context Level}/Content/_files/public/_itemid/filename.
$context = \context::instance_by_id($lastcontextid);
writer::with_context($context)->export_area_files($subcontext, 'contentbank', 'public', $content->id);
}
if (!empty($data)) {
$context = \context::instance_by_id($lastcontextid);
writer::with_context($context)->export_data($subcontext, (object)$data);
}
$contents->close();
}

/**
* TODO: MDL-67798.
* Delete all data for all users in the specified context.
*
* @param context $context The specific context to delete data for.
* @param context $context The specific context to delete data for.
*/
public static function delete_data_for_all_users_in_context(\context $context) {
// We are not implementing a proper privacy provider for now.
// A right privacy provider will be implemented in MDL-67798.
global $DB;

if (!$context instanceof context_system && !$context instanceof context_coursecat
&& !$context instanceof context_course) {
return;
}

static::delete_data($context, []);
}

/**
* Delete multiple users within a single context.
*
* @param approved_userlist $userlist The approved context and user information to delete information for.
*/
public static function delete_data_for_users(approved_userlist $userlist) {
$context = $userlist->get_context();

if (!$context instanceof context_system && !$context instanceof context_coursecat
&& !$context instanceof context_course) {
return;
}

static::delete_data($context, $userlist->get_userids());
}

/**
* TODO: MDL-67798.
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
// We are not implementing a proper privacy provider for now.
// A right privacy provider will be implemented in MDL-67798.
if (empty($contextlist->count())) {
return;
}

$userid = $contextlist->get_user()->id;
foreach ($contextlist->get_contexts() as $context) {
if (!$context instanceof context_system && !$context instanceof context_coursecat
&& !$context instanceof context_course) {
continue;
}
static::delete_data($context, [$userid]);
}
}

/**
* Delete data related to a context and users (if defined).
*
* @param context $context A context.
* @param array $userids The user IDs.
*/
protected static function delete_data(\context $context, array $userids) {
global $DB;

$params = ['contextid' => $context->id];
$select = 'contextid = :contextid';

// Delete the Content Bank files.
if (!empty($userids)) {
list($insql, $inparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
$params += $inparams;
$select .= ' AND usercreated '.$insql;
}
$fs = get_file_storage();
$contents = $DB->get_records_select('contentbank_content',
$select, $params);
foreach ($contents as $content) {
$fs->delete_area_files($content->contextid, 'contentbank', 'public', $content->id);
}

// Delete all the contents.
$DB->delete_records_select('contentbank_content', $select, $params);
}
}

0 comments on commit aeacd6c

Please sign in to comment.