mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 16:32:18 +02:00
MDL-61814 core_portfolio: Update to portfolio provider.
This commit is contained in:
parent
c49f309204
commit
ab78499bbd
@ -167,6 +167,12 @@ $string['pluginismisconfigured'] = 'Portfolio plugin is misconfigured, skipping.
|
||||
$string['portfolio'] = 'Portfolio';
|
||||
$string['portfolios'] = 'Portfolios';
|
||||
$string['privacy:metadata'] = 'The portfolio subsystem acts as a channel, passing requests from plugins to the various portfolio plugins.';
|
||||
$string['privacy:metadata:name'] = 'Name of the preference.';
|
||||
$string['privacy:metadata:instance'] = 'Identifier for the portfolio.';
|
||||
$string['privacy:metadata:instancesummary'] = 'This stores portfolio both instances and preferences for the portfolios user is using.';
|
||||
$string['privacy:metadata:value'] = 'Value for the preference';
|
||||
$string['privacy:metadata:userid'] = 'The user Identifier.';
|
||||
$string['privacy:path'] = 'Portfolio instances';
|
||||
$string['queuesummary'] = 'Currently queued transfers';
|
||||
$string['returntowhereyouwere'] = 'Return to where you were';
|
||||
$string['save'] = 'Save';
|
||||
@ -184,3 +190,4 @@ $string['wait'] = 'Wait';
|
||||
$string['wanttowait_high'] = 'It is not recommended that you wait for this transfer to complete, but you can if you\'re sure and know what you\'re doing';
|
||||
$string['wanttowait_moderate'] = 'Do you want to wait for this transfer? It might take a few minutes';
|
||||
|
||||
|
||||
|
@ -27,6 +27,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core_privacy\local\metadata\collection;
|
||||
use core_privacy\local\request\context;
|
||||
use core_privacy\local\request\contextlist;
|
||||
use core_privacy\local\request\approved_contextlist;
|
||||
|
||||
/**
|
||||
* Provider for the portfolio API.
|
||||
@ -35,10 +37,9 @@ use core_privacy\local\request\context;
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements
|
||||
// The Portfolio subsystem does not store any data itself.
|
||||
// It has no database tables, and it purely acts as a conduit to the various portfolio plugins.
|
||||
// The core portfolio system stores preferences related to the other portfolio subsystems.
|
||||
\core_privacy\local\metadata\provider,
|
||||
|
||||
\core_privacy\local\request\plugin\provider,
|
||||
// The portfolio subsystem will be called by other components.
|
||||
\core_privacy\local\request\subsystem\plugin_provider {
|
||||
|
||||
@ -49,7 +50,100 @@ class provider implements
|
||||
* @return collection A listing of user data stored through this system.
|
||||
*/
|
||||
public static function get_metadata(collection $collection) : collection {
|
||||
return $collection->add_plugintype_link('portfolio', [], 'privacy:metadata');
|
||||
$collection->add_database_table('portfolio_instance_user', [
|
||||
'instance' => 'privacy:metadata:instance',
|
||||
'userid' => 'privacy:metadata:userid',
|
||||
'name' => 'privacy:metadata:name',
|
||||
'value' => 'privacy:metadata:value'
|
||||
], 'privacy:metadata:instancesummary');
|
||||
$collection->add_plugintype_link('portfolio', [], 'privacy:metadata');
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of contexts that contain user information for the specified user.
|
||||
*
|
||||
* @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_contexts_for_userid(int $userid) : contextlist {
|
||||
$sql = "SELECT ctx.id
|
||||
FROM {context} ctx
|
||||
JOIN {portfolio_instance_user} piu ON ctx.instanceid = piu.userid AND ctx.contextlevel = :usercontext
|
||||
WHERE piu.userid = :userid";
|
||||
$params = ['userid' => $userid, 'usercontext' => CONTEXT_USER];
|
||||
$contextlist = new contextlist();
|
||||
$contextlist->add_from_sql($sql, $params);
|
||||
return $contextlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The approved contexts to export information for.
|
||||
*/
|
||||
public static function export_user_data(approved_contextlist $contextlist) {
|
||||
global $DB;
|
||||
|
||||
if ($contextlist->get_component() != 'core_portfolio') {
|
||||
return;
|
||||
}
|
||||
|
||||
$correctusercontext = array_filter($contextlist->get_contexts(), function($context) use ($contextlist) {
|
||||
if ($context->contextlevel == CONTEXT_USER && $context->instanceid == $contextlist->get_user()->id) {
|
||||
return $context;
|
||||
}
|
||||
});
|
||||
|
||||
$usercontext = array_shift($correctusercontext);
|
||||
|
||||
|
||||
$sql = "SELECT pi.name, piu.name AS preference, piu.value
|
||||
FROM {portfolio_instance_user} piu
|
||||
JOIN {portfolio_instance} pi ON piu.instance = pi.id
|
||||
WHERE piu.userid = :userid";
|
||||
$params = ['userid' => $usercontext->instanceid];
|
||||
$instances = $DB->get_records_sql($sql, $params);
|
||||
if (!empty($instances)) {
|
||||
\core_privacy\local\request\writer::with_context($contextlist->current())->export_data(
|
||||
[get_string('privacy:path', 'portfolio')], (object) $instances);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all data for all users in the specified context.
|
||||
*
|
||||
* @param context $context The specific context to delete data for.
|
||||
*/
|
||||
public static function delete_data_for_all_users_in_context(\context $context) {
|
||||
global $DB;
|
||||
// Context could be anything, BEWARE!
|
||||
if ($context->contextlevel == CONTEXT_USER) {
|
||||
$DB->delete_records('portfolio_instance_user', ['userid' => $context->instanceid]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public static function delete_data_for_user(approved_contextlist $contextlist) {
|
||||
global $DB;
|
||||
|
||||
if ($contextlist->get_component() != 'core_portfolio') {
|
||||
return;
|
||||
}
|
||||
|
||||
$correctusercontext = array_filter($contextlist->get_contexts(), function($context) use ($contextlist) {
|
||||
if ($context->contextlevel == CONTEXT_USER && $context->instanceid == $contextlist->get_user()->id) {
|
||||
return $context;
|
||||
}
|
||||
});
|
||||
|
||||
$usercontext = array_shift($correctusercontext);
|
||||
|
||||
$DB->delete_records('portfolio_instance_user', ['userid' => $usercontext->instanceid]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,15 +32,110 @@ defined('MOODLE_INTERNAL') || die();
|
||||
*/
|
||||
class portfolio_privacy_provider_test extends \core_privacy\tests\provider_testcase {
|
||||
|
||||
protected function create_portfolio_data($plugin, $name, $user, $preference, $value) {
|
||||
global $DB;
|
||||
$portfolioinstance = (object) [
|
||||
'plugin' => $plugin,
|
||||
'name' => $name,
|
||||
'visible' => 1
|
||||
];
|
||||
$portfolioinstance->id = $DB->insert_record('portfolio_instance', $portfolioinstance);
|
||||
$userinstance = (object) [
|
||||
'instance' => $portfolioinstance->id,
|
||||
'userid' => $user->id,
|
||||
'name' => $preference,
|
||||
'value' => $value
|
||||
];
|
||||
$DB->insert_record('portfolio_instance_user', $userinstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that a collection of metadata is returned for this component and that it just links to the plugintype 'portfolio'.
|
||||
* Verify that a collection of metadata is returned for this component and that it just returns the righ types for 'portfolio'.
|
||||
*/
|
||||
public function test_get_metadata() {
|
||||
$collection = new \core_privacy\local\metadata\collection('core_portfolio');
|
||||
$collection = \core_portfolio\privacy\provider::get_metadata($collection);
|
||||
$this->assertNotEmpty($collection);
|
||||
$items = $collection->get_collection();
|
||||
$this->assertEquals(1, count($items));
|
||||
$this->assertInstanceOf(\core_privacy\local\metadata\types\plugintype_link::class, $items[0]);
|
||||
$this->assertEquals(2, count($items));
|
||||
$this->assertInstanceOf(\core_privacy\local\metadata\types\database_table::class, $items[0]);
|
||||
$this->assertInstanceOf(\core_privacy\local\metadata\types\plugintype_link::class, $items[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the export for a user id returns a user context.
|
||||
*/
|
||||
public function test_get_contexts_for_userid() {
|
||||
$this->resetAfterTest();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$context = context_user::instance($user->id);
|
||||
$this->create_portfolio_data('googledocs', 'Google Docs', $user, 'visible', 1);
|
||||
$contextlist = \core_portfolio\privacy\provider::get_contexts_for_userid($user->id);
|
||||
$this->assertEquals($context->id, $contextlist->current()->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that exporting user data works as expected.
|
||||
*/
|
||||
public function test_export_user_data() {
|
||||
$this->resetAfterTest();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$context = context_user::instance($user->id);
|
||||
$this->create_portfolio_data('googledocs', 'Google Docs', $user, 'visible', 1);
|
||||
$contextlist = new \core_privacy\local\request\approved_contextlist($user, 'core_portfolio', [$context->id]);
|
||||
\core_portfolio\privacy\provider::export_user_data($contextlist);
|
||||
$writer = \core_privacy\local\request\writer::with_context($context);
|
||||
$portfoliodata = $writer->get_data([get_string('privacy:path', 'portfolio')]);
|
||||
$this->assertEquals('Google Docs', $portfoliodata->{'Google Docs'}->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that deleting only results in the one context being removed.
|
||||
*/
|
||||
public function test_delete_data_for_all_users_in_context() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$this->create_portfolio_data('googledocs', 'Google Docs', $user1, 'visible', 1);
|
||||
$this->create_portfolio_data('onedrive', 'Microsoft onedrive', $user2, 'visible', 1);
|
||||
// Check a system context sent through.
|
||||
$systemcontext = context_system::instance();
|
||||
\core_portfolio\privacy\provider::delete_data_for_all_users_in_context($systemcontext);
|
||||
$records = $DB->get_records('portfolio_instance_user');
|
||||
$this->assertCount(2, $records);
|
||||
$context = context_user::instance($user1->id);
|
||||
\core_portfolio\privacy\provider::delete_data_for_all_users_in_context($context);
|
||||
$records = $DB->get_records('portfolio_instance_user');
|
||||
// Only one entry should remain for user 2.
|
||||
$this->assertCount(1, $records);
|
||||
$data = array_shift($records);
|
||||
$this->assertEquals($user2->id, $data->userid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that deleting only results in one user's data being removed.
|
||||
*/
|
||||
public function test_delete_data_for_user() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$this->create_portfolio_data('googledocs', 'Google Docs', $user1, 'visible', 1);
|
||||
$this->create_portfolio_data('onedrive', 'Microsoft onedrive', $user2, 'visible', 1);
|
||||
|
||||
$records = $DB->get_records('portfolio_instance_user');
|
||||
$this->assertCount(2, $records);
|
||||
|
||||
$context = context_user::instance($user1->id);
|
||||
$contextlist = new \core_privacy\local\request\approved_contextlist($user1, 'core_portfolio', [$context->id]);
|
||||
\core_portfolio\privacy\provider::delete_data_for_user($contextlist);
|
||||
$records = $DB->get_records('portfolio_instance_user');
|
||||
// Only one entry should remain for user 2.
|
||||
$this->assertCount(1, $records);
|
||||
$data = array_shift($records);
|
||||
$this->assertEquals($user2->id, $data->userid);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user