--- /dev/null
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+/**
+ * Privacy Subsystem implementation for core_role.
+ *
+ * @package core_role
+ * @copyright 2018 Carlos Escobedo <carlos@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace core_role\privacy;
+defined('MOODLE_INTERNAL') || die();
+
+use \core_privacy\local\metadata\collection;
+use \core_privacy\local\request\contextlist;
+use \core_privacy\local\request\approved_contextlist;
+use \core_privacy\local\request\transform;
+use \core_privacy\local\request\writer;
+
+/**
+ * Privacy provider for core_role.
+ *
+ * @copyright 2018 Carlos Escobedo <carlos@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class provider implements
+ \core_privacy\local\metadata\provider,
+ \core_privacy\local\request\subsystem\provider,
+ \core_privacy\local\request\subsystem\plugin_provider,
+ \core_privacy\local\request\user_preference_provider {
+
+ /**
+ * Get information about the user data stored by this plugin.
+ *
+ * @param collection $collection An object for storing metadata.
+ * @return collection The metadata.
+ */
+ public static function get_metadata(collection $collection) : collection {
+ $rolecapabilities = [
+ 'roleid' => 'privacy:metadata:role_capabilities:roleid',
+ 'capability' => 'privacy:metadata:role_capabilities:capability',
+ 'permission' => 'privacy:metadata:role_capabilities:permission',
+ 'timemodified' => 'privacy:metadata:role_capabilities:timemodified',
+ 'modifierid' => 'privacy:metadata:role_capabilities:modifierid'
+ ];
+ $roleassignments = [
+ 'roleid' => 'privacy:metadata:role_assignments:roleid',
+ 'userid' => 'privacy:metadata:role_assignments:userid',
+ 'timemodified' => 'privacy:metadata:role_assignments:timemodified',
+ 'modifierid' => 'privacy:metadata:role_assignments:modifierid',
+ 'component' => 'privacy:metadata:role_assignments:component',
+ 'itemid' => 'privacy:metadata:role_assignments:itemid'
+ ];
+ $collection->add_database_table('role_capabilities', $rolecapabilities,
+ 'privacy:metadata:role_capabilities:tableexplanation');
+ $collection->add_database_table('role_assignments', $roleassignments,
+ 'privacy:metadata:role_assignments:tableexplanation');
+
+ $collection->add_user_preference('definerole_showadvanced',
+ 'privacy:metadata:preference:showadvanced');
+
+ return $collection;
+ }
+ /**
+ * Export all user preferences for the plugin.
+ *
+ * @param int $userid The userid of the user whose data is to be exported.
+ */
+ public static function export_user_preferences(int $userid) {
+ $showadvanced = get_user_preferences('definerole_showadvanced', null, $userid);
+ if ($showadvanced !== null) {
+ writer::export_user_preference('core_role',
+ 'definerole_showadvanced',
+ transform::yesno($showadvanced),
+ get_string('privacy:metadata:preference:showadvanced', 'core_role')
+ );
+ }
+ }
+ /**
+ * Return all contexts for this userid.
+ *
+ * @param int $userid The user ID.
+ * @return contextlist The list of context IDs.
+ */
+ public static function get_contexts_for_userid(int $userid) : contextlist {
+ global $DB;
+
+ $contextlist = new contextlist();
+
+ // The role_capabilities table contains user data.
+ $contexts = [
+ CONTEXT_SYSTEM,
+ CONTEXT_USER,
+ CONTEXT_COURSECAT,
+ CONTEXT_COURSE,
+ CONTEXT_MODULE,
+ CONTEXT_BLOCK
+ ];
+ list($insql, $inparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
+ $sql = "SELECT ctx.id
+ FROM {context} ctx
+ JOIN {role_capabilities} rc
+ ON rc.contextid = ctx.id
+ AND ((ctx.contextlevel {$insql} AND rc.modifierid = :modifierid)
+ OR (ctx.contextlevel = :contextlevel AND ctx.instanceid = :userid))";
+ $params = [
+ 'modifierid' => $userid,
+ 'contextlevel' => CONTEXT_USER,
+ 'userid' => $userid
+ ];
+ $params += $inparams;
+
+ $contextlist->add_from_sql($sql, $params);
+
+ // The role_assignments table contains user data.
+ $contexts = [
+ CONTEXT_SYSTEM,
+ CONTEXT_USER,
+ CONTEXT_COURSECAT,
+ CONTEXT_COURSE,
+ CONTEXT_MODULE,
+ CONTEXT_BLOCK
+ ];
+ list($insql, $inparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
+ $params = [
+ 'userid' => $userid,
+ 'modifierid' => $userid
+ ];
+ $params += $inparams;
+ $sql = "SELECT ctx.id
+ FROM {role_assignments} ra
+ JOIN {context} ctx
+ ON ctx.id = ra.contextid
+ AND ctx.contextlevel {$insql}
+ WHERE (ra.userid = :userid
+ OR ra.modifierid = :modifierid)
+ AND ra.component != 'tool_cohortroles'";
+ $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 list of approved contexts for a user.
+ */
+ public static function export_user_data(approved_contextlist $contextlist) {
+ global $DB;
+
+ if (empty($contextlist)) {
+ return;
+ }
+
+ $rolesnames = self::get_roles_name();
+ $userid = $contextlist->get_user()->id;
+ $ctxfields = \context_helper::get_preload_record_columns_sql('ctx');
+ list($insql, $inparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
+
+ // Role Assignments export data.
+ $contexts = [
+ CONTEXT_SYSTEM,
+ CONTEXT_USER,
+ CONTEXT_COURSECAT,
+ CONTEXT_COURSE,
+ CONTEXT_MODULE,
+ CONTEXT_BLOCK
+ ];
+ list($inctxsql, $ctxparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
+ $sql = "SELECT ra.id, ra.contextid, ra.roleid, ra.userid, ra.timemodified, ra.modifierid, $ctxfields
+ FROM {role_assignments} ra
+ JOIN {context} ctx
+ ON ctx.id = ra.contextid
+ AND ctx.contextlevel {$inctxsql}
+ AND (ra.userid = :userid OR ra.modifierid = :modifierid)
+ AND ra.component != 'tool_cohortroles'
+ JOIN {role} r
+ ON r.id = ra.roleid
+ WHERE ctx.id {$insql}";
+ $params = ['userid' => $userid, 'modifierid' => $userid];
+ $params += $inparams;
+ $params += $ctxparams;
+ $assignments = $DB->get_recordset_sql($sql, $params);
+ foreach ($assignments as $assignment) {
+ \context_helper::preload_from_record($assignment);
+ $alldata[$assignment->contextid][$rolesnames[$assignment->roleid]][] = (object)[
+ 'timemodified' => transform::datetime($assignment->timemodified),
+ 'userid' => transform::user($assignment->userid),
+ 'modifierid' => transform::user($assignment->modifierid)
+ ];
+ }
+ $assignments->close();
+ if (!empty($alldata)) {
+ array_walk($alldata, function($roledata, $contextid) {
+ $context = \context::instance_by_id($contextid);
+ array_walk($roledata, function($data, $rolename) use ($context) {
+ writer::with_context($context)->export_data(
+ [get_string('privacy:metadata:role_assignments', 'core_role'), $rolename],
+ (object)$data);
+ });
+ });
+ unset($alldata);
+ }
+
+ // Role Capabilities export data.
+ $strpermissions = self::get_permissions_name();
+ $contexts = [
+ CONTEXT_SYSTEM,
+ CONTEXT_USER,
+ CONTEXT_COURSECAT,
+ CONTEXT_COURSE,
+ CONTEXT_MODULE,
+ CONTEXT_BLOCK
+ ];
+ list($inctxsql, $ctxparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
+ $sql = "SELECT rc.id, rc.contextid, rc.capability, rc.permission, rc.timemodified, rc.roleid, $ctxfields
+ FROM {context} ctx
+ JOIN {role_capabilities} rc
+ ON rc.contextid = ctx.id
+ AND ((ctx.contextlevel {$inctxsql} AND rc.modifierid = :modifierid)
+ OR (ctx.contextlevel = :contextlevel AND ctx.instanceid = :userid))
+ WHERE ctx.id {$insql}";
+ $params = [
+ 'modifierid' => $userid,
+ 'contextlevel' => CONTEXT_USER,
+ 'userid' => $userid
+ ];
+ $params += $inparams;
+ $params += $ctxparams;
+ $capabilities = $DB->get_recordset_sql($sql, $params);
+ foreach ($capabilities as $capability) {
+ \context_helper::preload_from_record($capability);
+ $alldata[$capability->contextid][$rolesnames[$capability->roleid]][] = (object)[
+ 'timemodified' => transform::datetime($capability->timemodified),
+ 'capability' => $capability->capability,
+ 'permission' => $strpermissions[$capability->permission]
+ ];
+ }
+ $capabilities->close();
+ if (!empty($alldata)) {
+ array_walk($alldata, function($capdata, $contextid) {
+ $context = \context::instance_by_id($contextid);
+ array_walk($capdata, function($data, $rolename) use ($context) {
+ writer::with_context($context)->export_data(
+ [get_string('privacy:metadata:role_capabilities', 'core_role'), $rolename],
+ (object)$data);
+ });
+ });
+ }
+ }
+ /**
+ * Exports the data relating to tool_cohortroles component on role assignments by
+ * Assign user roles to cohort feature.
+ *
+ * @param int $userid The user ID.
+ */
+ public static function export_user_role_to_cohort(int $userid) {
+ global $DB;
+
+ $rolesnames = self::get_roles_name();
+ $sql = "SELECT ra.id, ra.contextid, ra.roleid, ra.userid, ra.timemodified, ra.modifierid, r.id as roleid
+ FROM {role_assignments} ra
+ JOIN {context} ctx
+ ON ctx.id = ra.contextid
+ AND ctx.contextlevel = :contextlevel
+ AND ra.component = 'tool_cohortroles'
+ JOIN {role} r
+ ON r.id = ra.roleid
+ WHERE ctx.instanceid = :instanceid
+ OR ra.userid = :userid";
+ $params = ['userid' => $userid, 'instanceid' => $userid, 'contextlevel' => CONTEXT_USER];
+ $assignments = $DB->get_recordset_sql($sql, $params);
+ foreach ($assignments as $assignment) {
+ $alldata[$assignment->contextid][$rolesnames[$assignment->roleid]][] = (object)[
+ 'timemodified' => transform::datetime($assignment->timemodified),
+ 'userid' => transform::user($assignment->userid),
+ 'modifierid' => transform::user($assignment->modifierid)
+ ];
+ }
+ $assignments->close();
+ if (!empty($alldata)) {
+ array_walk($alldata, function($roledata, $contextid) {
+ $context = \context::instance_by_id($contextid);
+ array_walk($roledata, function($data, $rolename) use ($context) {
+ writer::with_context($context)->export_related_data(
+ [get_string('privacy:metadata:role_cohortroles', 'core_role'), $rolename], 'cohortroles',
+ (object)$data);
+ });
+ });
+ }
+ }
+ /**
+ * Delete all user data for this context.
+ *
+ * @param \context $context The context to delete data for.
+ */
+ public static function delete_data_for_all_users_in_context(\context $context) {
+ global $DB;
+
+ // Don't remove data from role_capabilities.
+ // Because this data affects the whole Moodle, there are override capabilities.
+ // Don't belong to the modifier user.
+
+ // Remove data from role_assignments.
+ if (empty($context)) {
+ return;
+ }
+ $DB->delete_records('role_assignments', ['contextid' => $context->id]);
+ }
+ /**
+ * Delete all user data for this user only.
+ *
+ * @param approved_contextlist $contextlist The list of approved contexts for a user.
+ */
+ public static function delete_data_for_user(approved_contextlist $contextlist) {
+ global $DB;
+
+ // Don't remove data from role_capabilities.
+ // Because this data affects the whole Moodle, there are override capabilities.
+ // Don't belong to the modifier user.
+
+ // Remove data from role_assignments.
+ if (empty($contextlist->count())) {
+ return;
+ }
+ $userid = $contextlist->get_user()->id;
+ foreach ($contextlist->get_contexts() as $context) {
+ // Only delete the roles assignments where the user is assigned in all contexts.
+ $DB->delete_records('role_assignments', ['userid' => $userid, 'contextid' => $context->id]);
+ }
+ }
+ /**
+ * Delete user entries in role_assignments related to the feature
+ * Assign user roles to cohort feature.
+ *
+ * @param int $userid The user ID.
+ */
+ public static function delete_user_role_to_cohort(int $userid) {
+ global $DB;
+
+ // Delete entries where userid is a mentor by tool_cohortroles.
+ $DB->delete_records('role_assignments', ['userid' => $userid, 'component' => 'tool_cohortroles']);
+ }
+ /**
+ * Get all the localised roles name in a simple array.
+ *
+ * @return array Array of name of the roles by roleid.
+ */
+ protected static function get_roles_name() {
+ $roles = role_fix_names(get_all_roles(), \context_system::instance(), ROLENAME_ORIGINAL);
+ $rolesnames = array();
+ foreach ($roles as $role) {
+ $rolesnames[$role->id] = $role->localname;
+ }
+ return $rolesnames;
+ }
+ /**
+ * Get all the permissions name in a simple array.
+ *
+ * @return array Array of permissions name.
+ */
+ protected static function get_permissions_name() {
+ $strpermissions = array(
+ CAP_INHERIT => get_string('inherit', 'role'),
+ CAP_ALLOW => get_string('allow', 'role'),
+ CAP_PREVENT => get_string('prevent', 'role'),
+ CAP_PROHIBIT => get_string('prohibit', 'role')
+ );
+ return $strpermissions;
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+/**
+ * Privacy test for core_role
+ *
+ * @package core_role
+ * @category test
+ * @copyright 2018 Carlos Escobedo <carlos@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+defined('MOODLE_INTERNAL') || die();
+use \core_role\privacy\provider;
+use \core_privacy\local\request\approved_contextlist;
+use \core_privacy\local\request\writer;
+use \core_privacy\tests\provider_testcase;
+use \core_privacy\local\request\transform;
+use \tool_cohortroles\api;
+
+/**
+ * Privacy test for core_role
+ *
+ * @copyright 2018 Carlos Escobedo <carlos@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class core_role_privacy_testcase extends provider_testcase {
+ /**
+ * Test to check export_user_preferences.
+ * returns user preferences data.
+ */
+ public function test_export_user_preferences() {
+ $this->resetAfterTest();
+ $this->setAdminUser();
+ $user = $this->getDataGenerator()->create_user();
+ $this->setUser($user);
+ $showadvanced = 1;
+ set_user_preference('definerole_showadvanced', $showadvanced);
+ provider::export_user_preferences($user->id);
+ $writer = writer::with_context(\context_system::instance());
+ $prefs = $writer->get_user_preferences('core_role');
+ $this->assertEquals(transform::yesno($showadvanced), transform::yesno($prefs->definerole_showadvanced->value));
+ $this->assertEquals(get_string('privacy:metadata:preference:showadvanced', 'core_role'),
+ $prefs->definerole_showadvanced->description);
+ }
+ /**
+ * Check all contexts are returned if there is any user data for this user.
+ */
+ public function test_get_contexts_for_userid() {
+ global $DB;
+
+ $this->resetAfterTest();
+ $this->setAdminUser();
+ $user = $this->getDataGenerator()->create_user();
+ $this->assertEmpty(provider::get_contexts_for_userid($user->id));
+
+ $user2 = $this->getDataGenerator()->create_user();
+ $usercontext2 = \context_user::instance($user2->id);
+ $course = $this->getDataGenerator()->create_course();
+ $course2 = $this->getDataGenerator()->create_course();
+ $coursecat = $this->getDataGenerator()->create_category();
+ $cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
+ $cmcontext = \context_module::instance($cm->cmid);
+ $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id));
+ $cmcontext2 = \context_module::instance($page->cmid);
+ $coursecontext = \context_course::instance($course->id);
+ $coursecontext2 = \context_course::instance($course2->id);
+ $coursecatcontext = \context_coursecat::instance($coursecat->id);
+ $systemcontext = \context_system::instance();
+ $block = $this->getDataGenerator()->create_block('online_users');
+ $blockcontext = \context_block::instance($block->id);
+
+ $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
+ $manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
+
+ // Role assignments, where the user is assigned.
+ role_assign($student->id, $user->id, $cmcontext2->id);
+ role_assign($student->id, $user->id, $coursecontext2->id);
+ role_assign($student->id, $user->id, $blockcontext->id);
+ role_assign($manager->id, $user->id, $usercontext2->id);
+ // Role assignments, where the user makes assignments.
+ $this->setUser($user);
+ role_assign($student->id, $user2->id, $coursecontext->id);
+ role_assign($manager->id, $user2->id, $coursecatcontext->id);
+ role_assign($manager->id, $user2->id, $systemcontext->id);
+
+ // Role capabilities.
+ $this->setUser($user);
+ $result = assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $cmcontext->id);
+
+ $contextlist = provider::get_contexts_for_userid($user->id)->get_contextids();
+ $this->assertCount(8, $contextlist);
+ $this->assertTrue(in_array($cmcontext->id, $contextlist));
+ }
+
+ /**
+ * Test that user data is exported correctly.
+ */
+ public function test_export_user_data() {
+ global $DB;
+
+ $this->resetAfterTest();
+ $this->setAdminUser();
+ $user = $this->getDataGenerator()->create_user();
+ $user2 = $this->getDataGenerator()->create_user();
+ $usercontext2 = \context_user::instance($user2->id);
+ $course = $this->getDataGenerator()->create_course();
+ $course2 = $this->getDataGenerator()->create_course();
+ $coursecat = $this->getDataGenerator()->create_category();
+ $cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
+ $cmcontext = \context_module::instance($cm->cmid);
+ $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id));
+ $cmcontext2 = \context_module::instance($page->cmid);
+ $coursecontext = \context_course::instance($course->id);
+ $coursecontext2 = \context_course::instance($course2->id);
+ $coursecatcontext = \context_coursecat::instance($coursecat->id);
+ $systemcontext = \context_system::instance();
+ $block = $this->getDataGenerator()->create_block('online_users');
+ $blockcontext = \context_block::instance($block->id);
+
+ $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
+ $manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
+ $rolesnames = self::get_roles_name();
+
+ $subcontextstudent = [
+ get_string('privacy:metadata:role_assignments', 'core_role'),
+ $rolesnames[$student->id]
+ ];
+ $subcontextmanager = [
+ get_string('privacy:metadata:role_assignments', 'core_role'),
+ $rolesnames[$manager->id]
+ ];
+ $subcontextrc = [
+ get_string('privacy:metadata:role_capabilities', 'core_role'),
+ $rolesnames[$student->id]
+ ];
+
+ // Test over role assignments.
+ // Where the user is assigned.
+ role_assign($student->id, $user->id, $cmcontext2->id);
+ role_assign($student->id, $user->id, $coursecontext2->id);
+ role_assign($student->id, $user->id, $blockcontext->id);
+ role_assign($manager->id, $user->id, $usercontext2->id);
+ // Where the user makes assignments.
+ $this->setUser($user);
+ role_assign($manager->id, $user2->id, $coursecatcontext->id);
+ role_assign($manager->id, $user2->id, $systemcontext->id);
+
+ // Test overridable roles in module, course, category, user, system and block.
+ assign_capability('moodle/backup:backupactivity', CAP_ALLOW, $student->id, $cmcontext->id, true);
+ assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $coursecontext->id, true);
+ assign_capability('moodle/category:manage', CAP_ALLOW, $student->id, $coursecatcontext->id, true);
+ assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $systemcontext->id, true);
+ assign_capability('moodle/block:edit', CAP_ALLOW, $student->id, $blockcontext->id, true);
+ assign_capability('moodle/competency:evidencedelete', CAP_ALLOW, $student->id, $usercontext2->id, true);
+
+ // Retrieve the user's context ids.
+ $contextlist = provider::get_contexts_for_userid($user->id);
+ $approvedcontextlist = new approved_contextlist($user, 'core_role', $contextlist->get_contextids());
+
+ $strpermissions = array(
+ CAP_INHERIT => get_string('inherit', 'role'),
+ CAP_ALLOW => get_string('allow', 'role'),
+ CAP_PREVENT => get_string('prevent', 'role'),
+ CAP_PROHIBIT => get_string('prohibit', 'role')
+ );
+ // Retrieve role capabilities and role assignments.
+ provider::export_user_data($approvedcontextlist);
+ foreach ($contextlist as $context) {
+ $writer = writer::with_context($context);
+ $this->assertTrue($writer->has_any_data());
+ if ($context->contextlevel == CONTEXT_MODULE) {
+ if ($data = $writer->get_data($subcontextstudent)) {
+ $this->assertEquals($user->id, reset($data)->userid);
+ }
+ if ($data = $writer->get_data($subcontextrc)) {
+ $this->assertEquals('moodle/backup:backupactivity', reset($data)->capability);
+ $this->assertEquals($strpermissions[CAP_ALLOW], reset($data)->permission);
+ }
+ }
+ if ($context->contextlevel == CONTEXT_COURSE) {
+ if ($data = $writer->get_data($subcontextstudent)) {
+ $this->assertEquals($user->id, reset($data)->userid);
+ }
+ if ($data = $writer->get_data($subcontextrc)) {
+ $this->assertEquals('moodle/backup:backupcourse', reset($data)->capability);
+ }
+ }
+ if ($context->contextlevel == CONTEXT_COURSECAT) {
+ if ($data = $writer->get_data($subcontextmanager)) {
+ $this->assertEquals($user->id, reset($data)->modifierid);
+ }
+ if ($data = $writer->get_data($subcontextrc)) {
+ $this->assertEquals('moodle/category:manage', reset($data)->capability);
+ }
+ }
+ if ($context->contextlevel == CONTEXT_SYSTEM) {
+ if ($data = $writer->get_data($subcontextmanager)) {
+ $this->assertEquals($user->id, reset($data)->modifierid);
+ }
+ if ($data = $writer->get_data($subcontextrc)) {
+ $this->assertEquals('moodle/backup:backupcourse', reset($data)->capability);
+ }
+ }
+ if ($context->contextlevel == CONTEXT_BLOCK) {
+ if ($data = $writer->get_data($subcontextstudent)) {
+ $this->assertEquals($user->id, reset($data)->userid);
+ }
+ if ($data = $writer->get_data($subcontextrc)) {
+ $this->assertEquals('moodle/block:edit', reset($data)->capability);
+ }
+ }
+ if ($context->contextlevel == CONTEXT_USER) {
+ if ($data = $writer->get_data($subcontextmanager)) {
+ $this->assertEquals($user->id, reset($data)->userid);
+ }
+ if ($data = $writer->get_data($subcontextrc)) {
+ $this->assertEquals('moodle/competency:evidencedelete', reset($data)->capability);
+ }
+ }
+ }
+ }
+ /**
+ * Test for provider::delete_data_for_all_users_in_context().
+ */
+ public function test_delete_data_for_all_users_in_context() {
+ global $DB;
+
+ $this->resetAfterTest();
+ $this->setAdminUser();
+ $user = $this->getDataGenerator()->create_user();
+ $user2 = $this->getDataGenerator()->create_user();
+ $usercontext2 = \context_user::instance($user2->id);
+ $user3 = $this->getDataGenerator()->create_user();
+ $course = $this->getDataGenerator()->create_course();
+ $coursecontext = \context_course::instance($course->id);
+ $coursecat = $this->getDataGenerator()->create_category();
+ $coursecatcontext = \context_coursecat::instance($coursecat->id);
+ $systemcontext = \context_system::instance();
+ $cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
+ $cmcontext = \context_module::instance($cm->cmid);
+ $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
+ $manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
+ $block = $this->getDataGenerator()->create_block('online_users');
+ $blockcontext = \context_block::instance($block->id);
+
+ // Role assignments CONTEXT_COURSE.
+ role_assign($student->id, $user->id, $coursecontext->id);
+ role_assign($student->id, $user2->id, $coursecontext->id);
+ role_assign($student->id, $user3->id, $coursecontext->id);
+ $count = $DB->count_records('role_assignments', ['contextid' => $coursecontext->id]);
+ $this->assertEquals(3, $count);
+ // Role assignments CONTEXT_COURSECAT.
+ role_assign($student->id, $user2->id, $coursecatcontext->id);
+ role_assign($student->id, $user3->id, $coursecatcontext->id);
+ $count = $DB->count_records('role_assignments', ['contextid' => $coursecatcontext->id]);
+ $this->assertEquals(2, $count);
+ // Role assignments CONTEXT_SYSTEM.
+ role_assign($student->id, $user->id, $systemcontext->id);
+ $count = $DB->count_records('role_assignments', ['contextid' => $systemcontext->id]);
+ $this->assertEquals(1, $count);
+ // Role assignments CONTEXT_MODULE.
+ role_assign($student->id, $user->id, $cmcontext->id);
+ $count = $DB->count_records('role_assignments', ['contextid' => $cmcontext->id]);
+ $this->assertEquals(1, $count);
+ // Role assigments CONTEXT_BLOCK.
+ role_assign($student->id, $user->id, $blockcontext->id);
+ $count = $DB->count_records('role_assignments', ['contextid' => $blockcontext->id]);
+ $this->assertEquals(1, $count);
+ // Role assigments CONTEXT_USER.
+ role_assign($manager->id, $user->id, $usercontext2->id);
+ $count = $DB->count_records('role_assignments', ['contextid' => $usercontext2->id]);
+ $this->assertEquals(1, $count);
+
+ // Delete data based on CONTEXT_COURSE context.
+ provider::delete_data_for_all_users_in_context($coursecontext);
+ // After deletion, the role_assignments entries for this context should have been deleted.
+ $count = $DB->count_records('role_assignments', ['contextid' => $coursecontext->id]);
+ $this->assertEquals(0, $count);
+ // Check it is not removing data on other contexts.
+ $count = $DB->count_records('role_assignments', ['contextid' => $coursecatcontext->id]);
+ $this->assertEquals(2, $count);
+ $count = $DB->count_records('role_assignments', ['contextid' => $systemcontext->id]);
+ $this->assertEquals(1, $count);
+ $count = $DB->count_records('role_assignments', ['contextid' => $cmcontext->id]);
+ $this->assertEquals(1, $count);
+ // Delete data based on CONTEXT_COURSECAT context.
+ provider::delete_data_for_all_users_in_context($coursecatcontext);
+ // After deletion, the role_assignments entries for this context should have been deleted.
+ $count = $DB->count_records('role_assignments', ['contextid' => $coursecatcontext->id]);
+ $this->assertEquals(0, $count);
+ // Delete data based on CONTEXT_SYSTEM context.
+ provider::delete_data_for_all_users_in_context($systemcontext);
+ // After deletion, the role_assignments entries for this context should have been deleted.
+ $count = $DB->count_records('role_assignments', ['contextid' => $systemcontext->id]);
+ $this->assertEquals(0, $count);
+ // Delete data based on CONTEXT_MODULE context.
+ provider::delete_data_for_all_users_in_context($cmcontext);
+ // After deletion, the role_assignments entries for this context should have been deleted.
+ $count = $DB->count_records('role_assignments', ['contextid' => $cmcontext->id]);
+ $this->assertEquals(0, $count);
+ // Delete data based on CONTEXT_BLOCK context.
+ provider::delete_data_for_all_users_in_context($usercontext2);
+ // After deletion, the role_assignments entries for this context should have been deleted.
+ $count = $DB->count_records('role_assignments', ['contextid' => $usercontext2->id]);
+ $this->assertEquals(0, $count);
+ }
+ /**
+ * Test for provider::delete_data_for_user().
+ */
+ public function test_delete_data_for_user() {
+ global $DB;
+
+ $this->resetAfterTest();
+ $this->setAdminUser();
+ $user = $this->getDataGenerator()->create_user();
+ $user2 = $this->getDataGenerator()->create_user();
+ $usercontext2 = \context_user::instance($user2->id);
+ $user3 = $this->getDataGenerator()->create_user();
+ $usercontext3 = \context_user::instance($user3->id);
+ $course = $this->getDataGenerator()->create_course();
+ $course2 = $this->getDataGenerator()->create_course();
+ $course3 = $this->getDataGenerator()->create_course();
+ $coursecontext = \context_course::instance($course->id);
+ $coursecontext2 = \context_course::instance($course2->id);
+ $coursecontext3 = \context_course::instance($course3->id);
+ $coursecat = $this->getDataGenerator()->create_category();
+ $coursecatcontext = \context_coursecat::instance($coursecat->id);
+ $systemcontext = \context_system::instance();
+ $cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
+ $cmcontext = \context_module::instance($cm->cmid);
+ $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
+ $manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
+ $block = $this->getDataGenerator()->create_block('online_users');
+ $blockcontext = \context_block::instance($block->id);
+
+ // Role assignments, Where the user is assigned.
+ role_assign($student->id, $user->id, $coursecontext->id);
+ role_assign($student->id, $user->id, $coursecontext2->id);
+ role_assign($student->id, $user->id, $coursecatcontext->id);
+ role_assign($student->id, $user->id, $cmcontext->id);
+ role_assign($student->id, $user->id, $systemcontext->id);
+ role_assign($student->id, $user->id, $blockcontext->id);
+ role_assign($manager->id, $user->id, $usercontext2->id);
+ role_assign($manager->id, $user->id, $usercontext3->id);
+ $count = $DB->count_records('role_assignments', ['userid' => $user->id]);
+ $this->assertEquals(8, $count);
+ // Role assignments, where the user makes assignments.
+ $this->setUser($user);
+ role_assign($student->id, $user2->id, $coursecontext3->id);
+ role_assign($student->id, $user3->id, $coursecontext3->id);
+ $count = $DB->count_records('role_assignments', ['modifierid' => $user->id]);
+ $this->assertEquals(2, $count);
+
+ $contextlist = provider::get_contexts_for_userid($user->id);
+ $approvedcontextlist = new approved_contextlist($user, 'core_role', $contextlist->get_contextids());
+ provider::delete_data_for_user($approvedcontextlist);
+ // After deletion, the role_assignments assigned to the user should have been deleted.
+ $count = $DB->count_records('role_assignments', ['userid' => $user->id]);
+ $this->assertEquals(0, $count);
+ // After deletion, the role_assignments assigned by the user should not have been deleted.
+ $count = $DB->count_records('role_assignments', ['modifierid' => $user->id]);
+ $this->assertEquals(2, $count);
+ }
+ /**
+ * Export for a user with a key against a script where no instance is specified.
+ */
+ public function test_export_user_role_to_cohort() {
+ global $DB;
+
+ $this->resetAfterTest();
+ $this->setAdminUser();
+ // Assign user roles to cohort.
+ $user = $this->getDataGenerator()->create_user();
+ $contextuser = \context_user::instance($user->id);
+ $teacher = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST);
+ $cohort = $this->getDataGenerator()->create_cohort();
+ $userassignover = $this->getDataGenerator()->create_user();
+ $contextuserassignover = \context_user::instance($userassignover->id);
+ cohort_add_member($cohort->id, $userassignover->id);
+ $this->setAdminUser();
+ $params = (object) array(
+ 'userid' => $user->id,
+ 'roleid' => $teacher->id,
+ 'cohortid' => $cohort->id
+ );
+ api::create_cohort_role_assignment($params);
+ api::sync_all_cohort_roles();
+ $rolesnames = self::get_roles_name();
+ $subcontextteacher = [
+ get_string('privacy:metadata:role_cohortroles', 'core_role'),
+ $rolesnames[$teacher->id]
+ ];
+ // Test User is assigned role teacher to cohort.
+ provider::export_user_role_to_cohort($user->id);
+ $writer = writer::with_context($contextuserassignover);
+ $this->assertTrue($writer->has_any_data());
+ $exported = $writer->get_related_data($subcontextteacher, 'cohortroles');
+ $this->assertEquals($user->id, reset($exported)->userid);
+
+ // Test User is member of a cohort which User2 is assigned to role to this cohort.
+ $user2 = $this->getDataGenerator()->create_user();
+ $cohort2 = $this->getDataGenerator()->create_cohort();
+ cohort_add_member($cohort2->id, $user->id);
+ $params = (object) array(
+ 'userid' => $user2->id,
+ 'roleid' => $teacher->id,
+ 'cohortid' => $cohort2->id
+ );
+ api::create_cohort_role_assignment($params);
+ api::sync_all_cohort_roles();
+ provider::export_user_role_to_cohort($user->id);
+ $writer = writer::with_context($contextuser);
+ $this->assertTrue($writer->has_any_data());
+ $exported = $writer->get_related_data($subcontextteacher, 'cohortroles');
+ $this->assertEquals($user2->id, reset($exported)->userid);
+ }
+ /**
+ * Test for provider::delete_user_role_to_cohort().
+ */
+ public function test_delete_user_role_to_cohort() {
+ global $DB;
+
+ $this->resetAfterTest();
+ $this->setAdminUser();
+ // Assign user roles to cohort.
+ $user = $this->getDataGenerator()->create_user();
+ $user2 = $this->getDataGenerator()->create_user();
+ $user3 = $this->getDataGenerator()->create_user();
+ $user4 = $this->getDataGenerator()->create_user();
+ $teacher = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST);
+ $cohort = $this->getDataGenerator()->create_cohort();
+ cohort_add_member($cohort->id, $user2->id);
+ cohort_add_member($cohort->id, $user3->id);
+ cohort_add_member($cohort->id, $user4->id);
+ $this->setAdminUser();
+ $params = (object) array(
+ 'userid' => $user->id,
+ 'roleid' => $teacher->id,
+ 'cohortid' => $cohort->id
+ );
+ api::create_cohort_role_assignment($params);
+ api::sync_all_cohort_roles();
+
+ $count = $DB->count_records('role_assignments', ['userid' => $user->id, 'component' => 'tool_cohortroles']);
+ $this->assertEquals(3, $count);
+
+ provider::delete_user_role_to_cohort($user->id);
+ $count = $DB->count_records('role_assignments', ['userid' => $user->id, 'component' => 'tool_cohortroles']);
+ $this->assertEquals(0, $count);
+ }
+ /**
+ * Supoort function to get all the localised roles name
+ * in a simple array for testing.
+ *
+ * @return array Array of name of the roles by roleid.
+ */
+ protected static function get_roles_name() {
+ $roles = role_fix_names(get_all_roles(), \context_system::instance(), ROLENAME_ORIGINAL);
+ $rolesnames = array();
+ foreach ($roles as $role) {
+ $rolesnames[$role->id] = $role->localname;
+ }
+ return $rolesnames;
+ }
+}
\ No newline at end of file
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_analytics'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->component = 'tool_assignmentupgrade';
-$plugin->dependencies = array('mod_assign' => 2017110800);
+$plugin->dependencies = array('mod_assign' => 2018050800);
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->component = 'tool_availabilityconditions';
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'tool_behat'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_capability'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_cohortroles'; // Full name of the plugin (used for diagnostics).
$plugin->dependencies = array(
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->component = 'tool_customlang'; // Full name of the plugin (used for diagnostics)
.nav-pills .nav-pills {
margin-left: 1rem;
}
-
+.data-registry > .top-nav > * {
+ margin-right: 0.5rem;
+}
/*Extra attribute selection to have preference over bs2's .moodle-actionmenu[data-enhance] */
.data-registry > .top-nav > .singlebutton,
.data-registry > .top-nav > .moodle-actionmenu[data-owner='dataregistry-actions'] {
}
}}
<div class="data-registry">
- <div class="top-nav">
+ <div class="top-nav d-flex">
{{#defaultsbutton}}
{{> core/action_link}}
{{/defaultsbutton}}
defined('MOODLE_INTERNAL') || die;
-$plugin->version = 2018040500;
-$plugin->requires = 2018040500; // Moodle 3.5dev (Build 2018031600) and upwards.
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800; // Moodle 3.5dev (Build 2018031600) and upwards.
$plugin->component = 'tool_dataprivacy';
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_dbtransfer'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->component = 'tool_filetypes';
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->component = 'tool_generator';
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'tool_health'; // Full name of the plugin (used for diagnostics)
$plugin->maturity = MATURITY_ALPHA; // this version's maturity level
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_httpsreplace'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'tool_innodb'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'tool_installaddon';
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->maturity = MATURITY_STABLE;
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'tool_langimport'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'logstore_database'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'logstore_legacy'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'logstore_standard'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_log'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_lp'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_lpimportcsv'; // Full name of the plugin (used for diagnostics).
-$plugin->dependencies = array('tool_lp' => 2017110800);
+$plugin->dependencies = array('tool_lp' => 2018050800);
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_lpmigrate'; // Full name of the plugin (used for diagnostics).
$plugin->dependencies = array(
'tool_lp' => ANY_VERSION
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->component = 'tool_messageinbound';
*/
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111301; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_mobile'; // Full name of the plugin (used for diagnostics).
$plugin->dependencies = array(
- 'webservice_rest' => 2017110800
+ 'webservice_rest' => 2018050800
);
defined('MOODLE_INTERNAL') || die;
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_monitor'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'tool_multilangupgrade'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_oauth2'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'tool_phpunit'; // Full name of the plugin (used for diagnostics)
$data = (object) [
'pluginbaseurl' => (new moodle_url('/admin/tool/policy'))->out(false),
'returnurl' => $this->returnurl ? (new moodle_url($this->returnurl))->out(false) : null,
- 'editurl' => ($this->manage && $this->policy->status != policy_version::STATUS_ARCHIVED) ?
- (new moodle_url('/admin/tool/policy/editpolicydoc.php',
- ['policyid' => $this->policy->policyid, 'versionid' => $this->policy->id]))->out(false) : null,
'numpolicy' => $this->numpolicy ? : null,
'totalpolicies' => $this->totalpolicies ? : null,
];
+ if ($this->manage && $this->policy->status != policy_version::STATUS_ARCHIVED) {
+ $paramsurl = ['policyid' => $this->policy->policyid, 'versionid' => $this->policy->id];
+ $data->editurl = (new moodle_url('/admin/tool/policy/editpolicydoc.php', $paramsurl))->out(false);
+ }
$data->policy = clone($this->policy);
// Create policies and agree to them as admin.
$this->setAdminUser();
$admin = fullclone($USER);
- $admincontext = context_user::instance($admin->id);
+ $admincontext = \context_user::instance($admin->id);
$CFG->sitepolicyhandler = 'tool_policy';
$policy1 = $this->add_policy();
api::make_current($policy1->get('id'));
// Agree to the policies for oneself.
$this->setUser($this->user);
- $usercontext = context_user::instance($this->user->id);
+ $usercontext = \context_user::instance($this->user->id);
api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
// Request export for this user.
$writer = writer::with_context($usercontext);
$datauser = $writer->get_related_data([get_string('userpoliciesagreements', 'tool_policy'), $this->user->id]);
- $this->assertEquals(2, count($datauser));
+ $this->assertCount(2, (array) $datauser);
$this->assertEquals($policy1->get('name'), $datauser['policyagreement-'.$policy1->get('id')]->name);
$this->assertEquals($this->user->id, $datauser['policyagreement-'.$policy1->get('id')]->usermodified);
$this->assertEquals($policy2->get('name'), $datauser['policyagreement-'.$policy2->get('id')]->name);
api::make_current($policy2->get('id'));
// Agree to the policies for oneself and for another user.
- $usercontext = context_user::instance($this->user->id);
- $admincontext = context_user::instance($USER->id);
+ $usercontext = \context_user::instance($this->user->id);
+ $admincontext = \context_user::instance($USER->id);
api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
api::accept_policies([$policy1->get('id'), $policy2->get('id')], $this->user->id, 'Mynote');
$writer = writer::with_context($usercontext);
$datauser = $writer->get_related_data([get_string('userpoliciesagreements', 'tool_policy'), $this->user->id]);
- $this->assertEquals(2, count($datauser));
+ $this->assertCount(2, (array) $datauser);
$this->assertEquals($policy1->get('name'), $datauser['policyagreement-'.$policy1->get('id')]->name);
$this->assertEquals($admin->id, $datauser['policyagreement-'.$policy1->get('id')]->usermodified);
$this->assertEquals('Mynote', $datauser['policyagreement-'.$policy1->get('id')]->note);
// Admin can see all four agreements.
$writer = writer::with_context($admincontext);
$dataadmin = $writer->get_related_data([get_string('userpoliciesagreements', 'tool_policy'), $admin->id]);
- $this->assertEquals(2, count($dataadmin));
+ $this->assertCount(2, (array) $dataadmin);
$this->assertEquals($policy1->get('name'), $dataadmin['policyagreement-'.$policy1->get('id')]->name);
$this->assertEquals($admin->id, $dataadmin['policyagreement-'.$policy1->get('id')]->usermodified);
$this->assertEquals($policy2->get('name'), $dataadmin['policyagreement-'.$policy2->get('id')]->name);
$writer = writer::with_context($usercontext);
$datauser = $writer->get_related_data([get_string('userpoliciesagreements', 'tool_policy'), $this->user->id]);
- $this->assertEquals(2, count($datauser));
+ $this->assertCount(2, (array) $datauser);
$this->assertEquals($policy1->get('name'), $datauser['policyagreement-'.$policy1->get('id')]->name);
$this->assertEquals($admin->id, $datauser['policyagreement-'.$policy1->get('id')]->usermodified);
$this->assertEquals('Mynote', $datauser['policyagreement-'.$policy1->get('id')]->note);
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2018032900; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2018032900; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_policy'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'tool_profiling'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_recyclebin'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'tool_replace'; // Full name of the plugin (used for diagnostics)
$plugin->maturity = MATURITY_ALPHA; // this version's maturity level
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->component = 'tool_spamcleaner'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'tool_task'; // Full name of the plugin (used for diagnostics)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_templatelibrary'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'tool_unsuproles'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_uploadcourse'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'tool_uploaduser'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current module version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current module version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'tool_usertours'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'tool_xmldb'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'auth_cas'; // Full name of the plugin (used for diagnostics)
-$plugin->dependencies = array('auth_ldap' => 2017110800);
+$plugin->dependencies = array('auth_ldap' => 2018050800);
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'auth_db'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die;
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'auth_email'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'auth_ldap'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'auth_lti'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'auth_manual'; // Full name of the plugin (used for diagnostics)
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
namespace auth_mnet\privacy;
+
defined('MOODLE_INTERNAL') || die();
+
+use \core_privacy\local\metadata\collection;
+use \core_privacy\local\request\contextlist;
+use \core_privacy\local\request\approved_contextlist;
+use core_privacy\local\request\transform;
+use \core_privacy\local\request\writer;
+
/**
- * Privacy Subsystem for auth_mnet implementing null_provider.
+ * Privacy provider for the mnet authentication
*
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class provider implements \core_privacy\local\metadata\null_provider {
+class provider implements
+ \core_privacy\local\metadata\provider,
+ \core_privacy\local\request\plugin\provider {
/**
- * Get the language string identifier with the component's language
- * file to explain why this plugin stores no data.
+ * Returns meta data about this system.
*
- * @return string
+ * @param collection $collection The initialised item collection to add items to.
+ * @return collection A listing of user data stored through this system.
*/
- public static function get_reason() : string {
- return 'privacy:metadata';
+ public static function get_metadata(collection $collection) : collection {
+
+ $sessionfields = [
+ 'userid' => 'privacy:metadata:mnet_session:userid',
+ 'username' => 'privacy:metadata:mnet_session:username',
+ 'token' => 'privacy:metadata:mnet_session:token',
+ 'mnethostid' => 'privacy:metadata:mnet_session:mnethostid',
+ 'useragent' => 'privacy:metadata:mnet_session:useragent',
+ 'expires' => 'privacy:metadata:mnet_session:expires'
+ ];
+
+ $collection->add_database_table('mnet_session', $sessionfields, 'privacy:metadata:mnet_session');
+
+ $logfields = [
+ 'hostid' => 'privacy:metadata:mnet_log:hostid',
+ 'remoteid' => 'privacy:metadata:mnet_log:remoteid',
+ 'time' => 'privacy:metadata:mnet_log:time',
+ 'userid' => 'privacy:metadata:mnet_log:userid',
+ 'ip' => 'privacy:metadata:mnet_log:ip',
+ 'course' => 'privacy:metadata:mnet_log:course',
+ 'coursename' => 'privacy:metadata:mnet_log:coursename',
+ 'module' => 'privacy:metadata:mnet_log:module',
+ 'cmid' => 'privacy:metadata:mnet_log:cmid',
+ 'action' => 'privacy:metadata:mnet_log:action',
+ 'url' => 'privacy:metadata:mnet_log:url',
+ 'info' => 'privacy:metadata:mnet_log:info'
+ ];
+
+ $collection->add_database_table('mnet_log', $logfields, 'privacy:metadata:mnet_log');
+
+ $externalfields = [
+ 'address' => 'privacy:metadata:mnet_external:address',
+ 'aim' => 'privacy:metadata:mnet_external:aim',
+ 'alternatename' => 'privacy:metadata:mnet_external:alternatename',
+ 'autosubscribe' => 'privacy:metadata:mnet_external:autosubscribe',
+ 'calendartype' => 'privacy:metadata:mnet_external:calendartype',
+ 'city' => 'privacy:metadata:mnet_external:city',
+ 'country' => 'privacy:metadata:mnet_external:country',
+ 'currentlogin' => 'privacy:metadata:mnet_external:currentlogin',
+ 'department' => 'privacy:metadata:mnet_external:department',
+ 'description' => 'privacy:metadata:mnet_external:description',
+ 'email' => 'privacy:metadata:mnet_external:email',
+ 'emailstop' => 'privacy:metadata:mnet_external:emailstop',
+ 'firstaccess' => 'privacy:metadata:mnet_external:firstaccess',
+ 'firstname' => 'privacy:metadata:mnet_external:firstname',
+ 'firstnamephonetic' => 'privacy:metadata:mnet_external:firstnamephonetic',
+ 'icq' => 'privacy:metadata:mnet_external:icq',
+ 'id' => 'privacy:metadata:mnet_external:id',
+ 'idnumber' => 'privacy:metadata:mnet_external:idnumber',
+ 'imagealt' => 'privacy:metadata:mnet_external:imagealt',
+ 'institution' => 'privacy:metadata:mnet_external:institution',
+ 'lang' => 'privacy:metadata:mnet_external:lang',
+ 'lastaccess' => 'privacy:metadata:mnet_external:lastaccess',
+ 'lastlogin' => 'privacy:metadata:mnet_external:lastlogin',
+ 'lastname' => 'privacy:metadata:mnet_external:lastname',
+ 'lastnamephonetic' => 'privacy:metadata:mnet_external:lastnamephonetic',
+ 'maildigest' => 'privacy:metadata:mnet_external:maildigest',
+ 'maildisplay' => 'privacy:metadata:mnet_external:maildisplay',
+ 'middlename' => 'privacy:metadata:mnet_external:middlename',
+ 'msn' => 'privacy:metadata:mnet_external:msn',
+ 'phone1' => 'privacy:metadata:mnet_external:phone1',
+ 'pnone2' => 'privacy:metadata:mnet_external:phone2',
+ 'picture' => 'privacy:metadata:mnet_external:picture',
+ 'policyagreed' => 'privacy:metadata:mnet_external:policyagreed',
+ 'skype' => 'privacy:metadata:mnet_external:skype',
+ 'suspended' => 'privacy:metadata:mnet_external:suspended',
+ 'timezone' => 'privacy:metadata:mnet_external:timezone',
+ 'trackforums' => 'privacy:metadata:mnet_external:trackforums',
+ 'trustbitmask' => 'privacy:metadata:mnet_external:trustbitmask',
+ 'url' => 'privacy:metadata:mnet_external:url',
+ 'username' => 'privacy:metadata:mnet_external:username',
+ 'yahoo' => 'privacy:metadata:mnet_external:yahoo',
+ ];
+
+ $collection->add_external_location_link('moodle', $externalfields, 'privacy:metadata:external:moodle');
+
+ $collection->add_external_location_link('mahara', $externalfields, 'privacy:metadata:external:mahara');
+
+ 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 list of contexts used in this plugin.
+ */
+ public static function get_contexts_for_userid(int $userid) : contextlist {
+ $sql = "SELECT ctx.id
+ FROM {mnet_log} ml
+ JOIN {context} ctx ON ctx.instanceid = ml.userid AND ctx.contextlevel = :contextlevel
+ WHERE ml.userid = :userid";
+ $params = ['userid' => $userid, 'contextlevel' => 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, using the supplied exporter instance.
+ *
+ * @param approved_contextlist $contextlist The approved contexts to export information for.
+ */
+ public static function export_user_data(approved_contextlist $contextlist) {
+ global $DB;
+
+ $context = \context_user::instance($contextlist->get_user()->id);
+
+ $sql = "SELECT ml.id, mh.wwwroot, mh.name, ml.remoteid, ml.time, ml.userid, ml.ip, ml.course,
+ ml.coursename, ml.module, ml.cmid, ml.action, ml.url, ml.info
+ FROM {mnet_log} ml
+ JOIN {mnet_host} mh ON mh.id = ml.hostid
+ WHERE ml.userid = :userid
+ ORDER BY mh.name, ml.coursename";
+ $params = ['userid' => $contextlist->get_user()->id];
+
+ $data = [];
+ $lastcourseid = null;
+
+ $logentries = $DB->get_recordset_sql($sql, $params);
+ foreach ($logentries as $logentry) {
+ $item = (object) [
+ 'time' => transform::datetime($logentry->time),
+ 'remoteid' => $logentry->remoteid,
+ 'ip' => $logentry->ip,
+ 'course' => $logentry->course,
+ 'coursename' => format_string($logentry->coursename),
+ 'module' => $logentry->module,
+ 'cmid' => $logentry->cmid,
+ 'action' => $logentry->action,
+ 'url' => $logentry->url,
+ 'info' => format_string($logentry->info)
+ ];
+
+ $item->externalhost =
+ ($logentry->name == '') ? preg_replace('#^https?://#', '', $logentry->wwwroot) :
+ preg_replace('#^https?://#', '', $logentry->name);
+
+ if ($lastcourseid && $lastcourseid != $logentry->course) {
+ $path = [get_string('pluginname', 'auth_mnet'), $data[0]->externalhost, $data[0]->coursename];
+ writer::with_context($context)->export_data($path, (object) $data);
+ $data = [];
+ }
+
+ $data[] = $item;
+ $lastcourseid = $logentry->course;
+ }
+ $logentries->close();
+
+ $path = [get_string('pluginname', 'auth_mnet'), $item->externalhost, $item->coursename];
+ writer::with_context($context)->export_data($path, (object) $data);
+ }
+
+ /**
+ * Delete all personal data for all users in the specified context.
+ *
+ * @param context $context Context to delete data from.
+ */
+ public static function delete_data_for_all_users_in_context(\context $context) {
+ global $DB;
+
+ if ($context->contextlevel != CONTEXT_USER) {
+ return;
+ }
+
+ $DB->delete_records('mnet_log', ['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 (empty($contextlist->count())) {
+ return;
+ }
+
+ foreach ($contextlist->get_contexts() as $context) {
+ if ($context->contextlevel != CONTEXT_USER) {
+ return;
+ }
+
+ // Because we only use user contexts the instance ID is the user ID.
+ $DB->delete_records('mnet_log', ['userid' => $context->instanceid]);
+ }
}
}
\ No newline at end of file
$string['sso_sp_description'] = 'Publish this service to allow authenticated users from {$a} to access your site without having to re-login. <ul><li><em>Dependency</em>: You must also <strong>subscribe</strong> to the SSO (Identity Provider) service on {$a}.</li></ul><br />Subscribe to this service to allow your users to roam to the {$a} site without having to re-login there. <ul><li><em>Dependency</em>: You must also <strong>publish</strong> the SSO (Identity Provider) service to {$a}.</li></ul><br />';
$string['sso_sp_name'] = 'SSO (Service Provider)';
$string['pluginname'] = 'MNet authentication';
-$string['privacy:metadata'] = 'The MNet authentication plugin does not store any personal data.';
+$string['privacy:metadata:external:mahara'] = 'This plugin can send data externally to a linked Mahara application.';
+$string['privacy:metadata:external:moodle'] = 'This plugin can send data externally to a linked Moodle application.';
+$string['privacy:metadata:mnet_external:address'] = 'The address of the user.';
+$string['privacy:metadata:mnet_external:aim'] = 'The AIM identifier of the user.';
+$string['privacy:metadata:mnet_external:alternatename'] = 'An alternative name for the user.';
+$string['privacy:metadata:mnet_external:autosubscribe'] = 'A preference as to if the user should be auto-subscribed to forums the user posts in.';
+$string['privacy:metadata:mnet_external:calendartype'] = 'A user preference for the type of calendar to use.';
+$string['privacy:metadata:mnet_external:city'] = 'The city of the user.';
+$string['privacy:metadata:mnet_external:country'] = 'The country that the user is in.';
+$string['privacy:metadata:mnet_external:currentlogin'] = 'The current login for this user.';
+$string['privacy:metadata:mnet_external:department'] = 'The department that this user can be found in.';
+$string['privacy:metadata:mnet_external:description'] = 'General details about this user.';
+$string['privacy:metadata:mnet_external:email'] = 'An email address for contact.';
+$string['privacy:metadata:mnet_external:emailstop'] = 'A preference to stop email being sent to the user.';
+$string['privacy:metadata:mnet_external:firstaccess'] = 'The time that this user first accessed the site.';
+$string['privacy:metadata:mnet_external:firstname'] = 'The first name of the user.';
+$string['privacy:metadata:mnet_external:firstnamephonetic'] = 'The phonetic details about the user\'s first name.';
+$string['privacy:metadata:mnet_external:icq'] = 'The ICQ number of the user.';
+$string['privacy:metadata:mnet_external:id'] = 'The identifier for the user.';
+$string['privacy:metadata:mnet_external:idnumber'] = 'An identification number given by the institution.';
+$string['privacy:metadata:mnet_external:imagealt'] = 'Alternative text for the user\'s image.';
+$string['privacy:metadata:mnet_external:institution'] = 'The institution that this user is a member of.';
+$string['privacy:metadata:mnet_external:lang'] = 'A user preference for the language shown.';
+$string['privacy:metadata:mnet_external:lastaccess'] = 'The time that the user last accessed the site.';
+$string['privacy:metadata:mnet_external:lastlogin'] = 'The last login of this user.';
+$string['privacy:metadata:mnet_external:lastname'] = 'The surname of the user.';
+$string['privacy:metadata:mnet_external:lastnamephonetic'] = 'The phonetic details about the user\'s surname.';
+$string['privacy:metadata:mnet_external:maildigest'] = 'A setting for the mail digest for this user.';
+$string['privacy:metadata:mnet_external:maildisplay'] = 'A preference for the user about displaying their email address to other users.';
+$string['privacy:metadata:mnet_external:middlename'] = 'The middle name of the user.';
+$string['privacy:metadata:mnet_external:msn'] = 'The MSN identifier of the user.';
+$string['privacy:metadata:mnet_external:phone1'] = 'A phone number for the user.';
+$string['privacy:metadata:mnet_external:phone2'] = 'An additional phone number for the user.';
+$string['privacy:metadata:mnet_external:picture'] = 'The picture details associated with this user.';
+$string['privacy:metadata:mnet_external:policyagreed'] = 'A flag to determine if the user has agreed to the site policy.';
+$string['privacy:metadata:mnet_external:skype'] = 'The skype identifier of the user.';
+$string['privacy:metadata:mnet_external:suspended'] = 'A flag to show if the user has been suspended on this system.';
+$string['privacy:metadata:mnet_external:timezone'] = 'The timezone that the user resides in.';
+$string['privacy:metadata:mnet_external:trackforums'] = 'A preference for forums and tracking them.';
+$string['privacy:metadata:mnet_external:trustbitmask'] = 'The trust bit mask';
+$string['privacy:metadata:mnet_external:url'] = 'A URL related to this user.';
+$string['privacy:metadata:mnet_external:username'] = 'The username for this user.';
+$string['privacy:metadata:mnet_external:yahoo'] = 'The yahoo identifier of the user.';
+$string['privacy:metadata:mnet_log'] = 'Details of remote actions carried out by a local user logged in a remote system.';
+$string['privacy:metadata:mnet_log:action'] = 'Action carried out by the user.';
+$string['privacy:metadata:mnet_log:cmid'] = 'ID of the course module.';
+$string['privacy:metadata:mnet_log:course'] = 'Remote system course ID where the action occurred.';
+$string['privacy:metadata:mnet_log:coursename'] = 'Remote system course full name where the action occurred.';
+$string['privacy:metadata:mnet_log:hostid'] = 'Remote system MNet ID.';
+$string['privacy:metadata:mnet_log:info'] = 'Additional information about the action.';
+$string['privacy:metadata:mnet_log:ip'] = 'The IP address used at the time of the action occurred.';
+$string['privacy:metadata:mnet_log:module'] = 'Remote system module where the event the action occurred.';
+$string['privacy:metadata:mnet_log:remoteid'] = 'Remote ID of the user who carried out the action in the remote system.';
+$string['privacy:metadata:mnet_log:time'] = 'Time when the action occurred.';
+$string['privacy:metadata:mnet_log:url'] = 'Remote system URL where the action occurred.';
+$string['privacy:metadata:mnet_log:userid'] = 'Local ID of the user who carried out the action in the remote system.';
+$string['privacy:metadata:mnet_session'] = 'The details of each MNet user session in a remote system is stored temporarily.';
+$string['privacy:metadata:mnet_session:expires'] = 'Time when the session expires.';
+$string['privacy:metadata:mnet_session:mnethostid'] = 'Remote system MNet ID.';
+$string['privacy:metadata:mnet_session:token'] = 'Unique session identifier.';
+$string['privacy:metadata:mnet_session:useragent'] = 'String denoting the user agent being which is accessing the page.';
+$string['privacy:metadata:mnet_session:userid'] = 'ID of the user jumping to remote system.';
+$string['privacy:metadata:mnet_session:username'] = 'Username of the user jumping to remote system.';
+$string['unknownhost'] = 'Unknown host';
\ No newline at end of file
--- /dev/null
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+/**
+ * Privacy test for the authentication mnet
+ *
+ * @package auth_mnet
+ * @category test
+ * @copyright 2018 Victor Deniz <victor@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+use \auth_mnet\privacy\provider;
+use \core_privacy\local\request\approved_contextlist;
+use \core_privacy\local\request\writer;
+use \core_privacy\tests\provider_testcase;
+use core_privacy\local\request\transform;
+
+/**
+ * Privacy test for the authentication mnet
+ *
+ * @package auth_mnet
+ * @category test
+ * @copyright 2018 Victor Deniz <victor@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class auth_mnet_privacy_testcase extends provider_testcase {
+ /**
+ * Set up method.
+ */
+ public function setUp() {
+ $this->resetAfterTest();
+ $this->setAdminUser();
+ }
+
+ /**
+ * Check that a user context is returned if there is any user data for this user.
+ */
+ public function test_get_contexts_for_userid() {
+ global $DB;
+
+ $user = $this->getDataGenerator()->create_user(['auth' => 'mnet']);
+ $this->assertEmpty(provider::get_contexts_for_userid($user->id));
+
+ // Insert mnet_log record.
+ $logrecord = new stdClass();
+ $logrecord->hostid = '';
+ $logrecord->remoteid = 65;
+ $logrecord->time = time();
+ $logrecord->userid = $user->id;
+
+ $DB->insert_record('mnet_log', $logrecord);
+
+ $contextlist = provider::get_contexts_for_userid($user->id);
+
+ // Check that we only get back one context.
+ $this->assertCount(1, $contextlist);
+
+ // Check that a context is returned is the expected.
+ $usercontext = \context_user::instance($user->id);
+ $this->assertEquals($usercontext->id, $contextlist->get_contextids()[0]);
+ }
+
+ /**
+ * Test that user data is exported correctly.
+ */
+ public function test_export_user_data() {
+ global $DB;
+
+ $user = $this->getDataGenerator()->create_user(['auth' => 'mnet']);
+
+ // Insert mnet_host record.
+ $hostrecord = new stdClass();
+ $hostrecord->wwwroot = 'https://external.moodle.com';
+ $hostrecord->name = 'External Moodle';
+ $hostrecord->public_key = '-----BEGIN CERTIFICATE-----';
+
+ $hostid = $DB->insert_record('mnet_host', $hostrecord);
+
+ // Insert mnet_log record.
+ $logrecord = new stdClass();
+ $logrecord->hostid = $hostid;
+ $logrecord->remoteid = 65;
+ $logrecord->time = time();
+ $logrecord->userid = $user->id;
+ $logrecord->course = 3;
+ $logrecord->coursename = 'test course';
+
+ $DB->insert_record('mnet_log', $logrecord);
+
+ $usercontext = \context_user::instance($user->id);
+
+ $writer = writer::with_context($usercontext);
+ $this->assertFalse($writer->has_any_data());
+ $approvedlist = new approved_contextlist($user, 'auth_mnet', [$usercontext->id]);
+ provider::export_user_data($approvedlist);
+
+ $data = $writer->get_data([get_string('pluginname', 'auth_mnet'), $hostrecord->name, $logrecord->coursename]);
+
+ $this->assertEquals($logrecord->remoteid, reset($data)->remoteid);
+ $this->assertEquals(transform::datetime($logrecord->time), reset($data)->time);
+ }
+
+ /**
+ * Test deleting all user data for a specific context.
+ */
+ public function test_delete_data_for_all_users_in_context() {
+ global $DB;
+
+ $user1 = $this->getDataGenerator()->create_user(['auth' => 'mnet']);
+
+ // Insert mnet_log record.
+ $logrecord1 = new stdClass();
+ $logrecord1->hostid = '';
+ $logrecord1->remoteid = 65;
+ $logrecord1->time = time();
+ $logrecord1->userid = $user1->id;
+
+ $DB->insert_record('mnet_log', $logrecord1);
+
+ $user1context = \context_user::instance($user1->id);
+
+ $user2 = $this->getDataGenerator()->create_user(['auth' => 'mnet']);
+
+ // Insert mnet_log record.
+ $logrecord2 = new stdClass();
+ $logrecord2->hostid = '';
+ $logrecord2->remoteid = 65;
+ $logrecord2->time = time();
+ $logrecord2->userid = $user2->id;
+
+ $DB->insert_record('mnet_log', $logrecord2);
+
+ // Get all mnet log records.
+ $mnetlogrecords = $DB->get_records('mnet_log', array());
+ // There should be two.
+ $this->assertCount(2, $mnetlogrecords);
+
+ // Delete everything for the first user context.
+ provider::delete_data_for_all_users_in_context($user1context);
+
+ // Get all user1 mnet log records.
+ $mnetlogrecords = $DB->get_records('mnet_log', ['userid' => $user1->id]);
+ $this->assertCount(0, $mnetlogrecords);
+
+ // Get all mnet log records.
+ $mnetlogrecords = $DB->get_records('mnet_log', array());
+ // There should be one (user2).
+ $this->assertCount(1, $mnetlogrecords);
+ }
+
+ /**
+ * This should work identical to the above test.
+ */
+ public function test_delete_data_for_user() {
+ global $DB;
+
+ $user1 = $this->getDataGenerator()->create_user(['auth' => 'mnet']);
+
+ // Insert mnet_log record.
+ $logrecord1 = new stdClass();
+ $logrecord1->hostid = '';
+ $logrecord1->remoteid = 65;
+ $logrecord1->time = time();
+ $logrecord1->userid = $user1->id;
+
+ $DB->insert_record('mnet_log', $logrecord1);
+
+ $user1context = \context_user::instance($user1->id);
+
+ $user2 = $this->getDataGenerator()->create_user(['auth' => 'mnet']);
+
+ // Insert mnet_log record.
+ $logrecord2 = new stdClass();
+ $logrecord2->hostid = '';
+ $logrecord2->remoteid = 65;
+ $logrecord2->time = time();
+ $logrecord2->userid = $user2->id;
+
+ $DB->insert_record('mnet_log', $logrecord2);
+
+ // Get all mnet log records.
+ $mnetlogrecords = $DB->get_records('mnet_log', array());
+ // There should be two.
+ $this->assertCount(2, $mnetlogrecords);
+
+ // Delete everything for the first user.
+ $approvedlist = new approved_contextlist($user1, 'auth_mnet', [$user1context->id]);
+ provider::delete_data_for_user($approvedlist);
+
+ // Get all user1 mnet log records.
+ $mnetlogrecords = $DB->get_records('mnet_log', ['userid' => $user1->id]);
+ $this->assertCount(0, $mnetlogrecords);
+
+ // Get all mnet log records.
+ $mnetlogrecords = $DB->get_records('mnet_log', array());
+ // There should be one (user2).
+ $this->assertCount(1, $mnetlogrecords);
+ }
+}
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'auth_mnet'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'auth_nologin'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'auth_none'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'auth_oauth2'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'auth_shibboleth'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'auth_webservice'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->component = 'availability_completion';
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->component = 'availability_date';
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->component = 'availability_grade';
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->component = 'availability_group';
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->component = 'availability_grouping';
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->component = 'availability_profile';
// Create DIV structure (without kids).
this.node = Y.Node.create('<div class="availability-list"><h3 class="accesshide"></h3>' +
'<div class="availability-inner">' +
- '<div class="availability-header"><span class="p-l-1">' +
+ '<div class="availability-header m-b-1"><span>' +
M.util.get_string('listheader_sign_before', 'availability') + '</span>' +
' <label><span class="accesshide">' + M.util.get_string('label_sign', 'availability') +
' </span><select class="availability-neg custom-select m-x-1"' +
'<div class="clearfix m-t-1"></div>' +
'<div class="availability-button"></div></div><div class="clearfix"></div></div>');
if (!root) {
- this.node.addClass('availability-childlist');
+ this.node.addClass('availability-childlist d-sm-flex align-items-center');
}
this.inner = this.node.one('> .availability-inner');
// Add entry for plugin.
li = Y.Node.create('<li class="clearfix row"></li>');
id = 'availability_addrestriction_' + type;
- button = Y.Node.create('<button type="button" class="btn btn-default col-xs-6"' +
- 'id="' + id + '">' + M.util.get_string('title', 'availability_' + type) + '</button>');
+ button = Y.Node.create('<div class="col-6"><button type="button" class="btn btn-default w-100"' +
+ 'id="' + id + '">' + M.util.get_string('title', 'availability_' + type) + '</button></div>');
button.on('click', this.getAddHandler(type, dialogRef), this);
li.appendChild(button);
- label = Y.Node.create('<label for="' + id + '" class="col-xs-6">' +
- M.util.get_string('description', 'availability_' + type) + '</label>');
+ label = Y.Node.create('<div class="col-6"><label for="' + id + '">' +
+ M.util.get_string('description', 'availability_' + type) + '</label></div>');
li.appendChild(label);
ul.appendChild(li);
}
// Extra entry for lists.
li = Y.Node.create('<li class="clearfix row"></li>');
id = 'availability_addrestriction_list_';
- button = Y.Node.create('<button type="button" class="btn btn-default col-xs-6"' +
- 'id="' + id + '">' + M.util.get_string('condition_group', 'availability') + '</button>');
+ button = Y.Node.create('<div class="col-6"><button type="button" class="btn btn-default w-100"' +
+ 'id="' + id + '">' + M.util.get_string('condition_group', 'availability') + '</button></div>');
button.on('click', this.getAddHandler(null, dialogRef), this);
li.appendChild(button);
- label = Y.Node.create('<label for="' + id + '" class="col-xs-6">' +
- M.util.get_string('condition_group_info', 'availability') + '</label>');
+ label = Y.Node.create('<div class="col-6"><label for="' + id + '">' +
+ M.util.get_string('condition_group_info', 'availability') + '</label></div>');
li.appendChild(label);
ul.appendChild(li);
this.pluginNode.addClass('availability_' + json.type);
}
- this.node = Y.Node.create('<div class="availability-item d-inline-block"><h3 class="accesshide"></h3></div>');
+ this.node = Y.Node.create('<div class="availability-item d-sm-flex align-items-center"><h3 class="accesshide"></h3></div>');
// Add eye icon if required. This icon is added for root items, but may be
// hidden depending on the selected list operator.
// Add the invalid marker (empty).
this.node.appendChild(document.createTextNode(' '));
- this.node.appendChild(Y.Node.create('<span class="m-t-1 label label-warning"/>'));
+ this.node.appendChild(Y.Node.create('<span class="label label-warning"/>'));
};
/**
* point is backup when some behavior/approach channged, in order to allow
* conditional coding based on it.
*/
- const VERSION = 2017111300;
+ const VERSION = 2018051400;
/**
* Usually same than major release zero version, mainly for informative/historic purposes.
*/
--- /dev/null
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Privacy provider tests.
+ *
+ * @package core_backup
+ * @copyright 2018 Mark Nelson <markn@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+use core_backup\privacy\provider;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Privacy provider tests class.
+ *
+ * @copyright 2018 Mark Nelson <markn@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class core_backup_privacy_provider_testcase extends \core_privacy\tests\provider_testcase {
+
+ /**
+ * @var stdClass The user
+ */
+ protected $user = null;
+
+ /**
+ * @var stdClass The course
+ */
+ protected $course = null;
+
+ /**
+ * Basic setup for these tests.
+ */
+ public function setUp() {
+ global $DB;
+
+ $this->resetAfterTest();
+
+ $this->course = $this->getDataGenerator()->create_course();
+
+ $this->user = $this->getDataGenerator()->create_user();
+
+ // Just insert directly into the 'backup_controllers' table.
+ $bcdata = (object) [
+ 'backupid' => 1,
+ 'operation' => 'restore',
+ 'type' => 'course',
+ 'itemid' => $this->course->id,
+ 'format' => 'moodle2',
+ 'interactive' => 1,
+ 'purpose' => 10,
+ 'userid' => $this->user->id,
+ 'status' => 1000,
+ 'execution' => 1,
+ 'executiontime' => 0,
+ 'checksum' => 'checksumyolo',
+ 'timecreated' => time(),
+ 'timemodified' => time(),
+ 'controller' => ''
+ ];
+ $DB->insert_record('backup_controllers', $bcdata);
+
+ // Create another user who will perform a backup operation.
+ $user = $this->getDataGenerator()->create_user();
+ $bcdata->backupid = 2;
+ $bcdata->userid = $user->id;
+ $DB->insert_record('backup_controllers', $bcdata);
+ }
+
+ /**
+ * Test getting the context for the user ID related to this plugin.
+ */
+ public function test_get_contexts_for_userid() {
+ $contextlist = provider::get_contexts_for_userid($this->user->id);
+ $this->assertCount(1, $contextlist);
+ $contextforuser = $contextlist->current();
+ $context = context_course::instance($this->course->id);
+ $this->assertEquals($context->id, $contextforuser->id);
+ }
+
+ /**
+ * Test for provider::export_user_data().
+ */
+ public function test_export_for_context() {
+ global $DB;
+
+ // Create another backup_controllers record.
+ $bcdata = (object) [
+ 'backupid' => 3,
+ 'operation' => 'backup',
+ 'type' => 'course',
+ 'itemid' => $this->course->id,
+ 'format' => 'moodle2',
+ 'interactive' => 1,
+ 'purpose' => 10,
+ 'userid' => $this->user->id,
+ 'status' => 1000,
+ 'execution' => 1,
+ 'executiontime' => 0,
+ 'checksum' => 'checksumyolo',
+ 'timecreated' => time() + DAYSECS,
+ 'timemodified' => time() + DAYSECS,
+ 'controller' => ''
+ ];
+ $DB->insert_record('backup_controllers', $bcdata);
+
+ $coursecontext = context_course::instance($this->course->id);
+
+ // Export all of the data for the context.
+ $this->export_context_data_for_user($this->user->id, $coursecontext, 'core_backup');
+ $writer = \core_privacy\local\request\writer::with_context($coursecontext);
+ $this->assertTrue($writer->has_any_data());
+
+ $data = (array) $writer->get_data([get_string('backup'), $this->course->id]);
+
+ $this->assertCount(2, $data);
+
+ $bc1 = array_shift($data);
+ $this->assertEquals('restore', $bc1['operation']);
+
+ $bc2 = array_shift($data);
+ $this->assertEquals('backup', $bc2['operation']);
+ }
+
+ /**
+ * Test for provider::delete_data_for_all_users_in_context().
+ */
+ public function test_delete_data_for_all_users_in_context() {
+ global $DB;
+
+ // Before deletion, we should have 2 operations.
+ $count = $DB->count_records('backup_controllers', ['itemid' => $this->course->id]);
+ $this->assertEquals(2, $count);
+
+ // Delete data based on context.
+ $coursecontext = context_course::instance($this->course->id);
+ provider::delete_data_for_all_users_in_context($coursecontext);
+
+ // After deletion, the operations for that course should have been deleted.
+ $count = $DB->count_records('backup_controllers', ['itemid' => $this->course->id]);
+ $this->assertEquals(0, $count);
+ }
+
+ /**
+ * Test for provider::delete_data_for_user().
+ */
+ public function test_delete_data_for_user() {
+ global $DB;
+
+ // Before deletion, we should have 2 operations.
+ $count = $DB->count_records('backup_controllers', ['itemid' => $this->course->id]);
+ $this->assertEquals(2, $count);
+
+ $coursecontext = context_course::instance($this->course->id);
+ $contextlist = new \core_privacy\local\request\approved_contextlist($this->user, 'core_backup',
+ [$coursecontext->id]);
+ provider::delete_data_for_user($contextlist);
+
+ // After deletion, the backup operation for the user should have been deleted.
+ $count = $DB->count_records('backup_controllers', ['itemid' => $this->course->id, 'userid' => $this->user->id]);
+ $this->assertEquals(0, $count);
+
+ // Confirm we still have the other users record.
+ $bcs = $DB->get_records('backup_controllers');
+ $this->assertCount(1, $bcs);
+ $lastsubmission = reset($bcs);
+ $this->assertNotEquals($this->user->id, $lastsubmission->userid);
+ }
+}
--- /dev/null
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Privacy Subsystem implementation for core_backup.
+ *
+ * @package core_backup
+ * @copyright 2018 Mark Nelson <markn@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core_backup\privacy;
+
+use core_privacy\local\metadata\collection;
+use core_privacy\local\request\approved_contextlist;
+use core_privacy\local\request\contextlist;
+use core_privacy\local\request\transform;
+use core_privacy\local\request\writer;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Privacy Subsystem implementation for core_backup.
+ *
+ * @copyright 2018 Mark Nelson <markn@moodle.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class provider implements
+ \core_privacy\local\metadata\provider,
+ \core_privacy\local\request\subsystem\provider {
+
+ /**
+ * Return the fields which contain personal data.
+ *
+ * @param collection $items a reference to the collection to use to store the metadata.
+ * @return collection the updated collection of metadata items.
+ */
+ public static function get_metadata(collection $items) : collection {
+ $items->link_external_location(
+ 'Backup',
+ [
+ 'detailsofarchive' => 'privacy:metadata:backup:detailsofarchive'
+ ],
+ 'privacy:metadata:backup:externalpurpose'
+ );
+
+ $items->add_database_table(
+ 'backup_controllers',
+ [
+ 'operation' => 'privacy:metadata:backup_controllers:operation',
+ 'type' => 'privacy:metadata:backup_controllers:type',
+ 'itemid' => 'privacy:metadata:backup_controllers:itemid',
+ 'timecreated' => 'privacy:metadata:backup_controllers:timecreated',
+ 'timemodified' => 'privacy:metadata:backup_controllers:timemodified'
+ ],
+ 'privacy:metadata:backup_controllers'
+ );
+
+ return $items;
+ }
+
+ /**
+ * Get the list of contexts that contain user information for the specified user.
+ *
+ * @param int $userid The user to search.
+ * @return contextlist The contextlist containing the list of contexts used in this plugin.
+ */
+ public static function get_contexts_for_userid(int $userid) : contextlist {
+ $contextlist = new contextlist();
+
+ $sql = "SELECT DISTINCT ctx.id
+ FROM {backup_controllers} bc
+ JOIN {context} ctx
+ ON ctx.instanceid = bc.itemid AND ctx.contextlevel = :contextlevel
+ WHERE bc.userid = :userid";
+ $params = ['contextlevel' => CONTEXT_COURSE, 'userid' => $userid];
+ $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 (empty($contextlist->count())) {
+ return;
+ }
+
+ $user = $contextlist->get_user();
+
+ list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
+
+ $sql = "SELECT bc.*
+ FROM {backup_controllers} bc
+ JOIN {context} ctx
+ ON ctx.instanceid = bc.itemid AND ctx.contextlevel = :contextlevel
+ WHERE ctx.id {$contextsql}
+ AND bc.userid = :userid
+ ORDER BY bc.timecreated ASC";
+ $params = ['contextlevel' => CONTEXT_COURSE, 'userid' => $user->id] + $contextparams;
+ $backupcontrollers = $DB->get_recordset_sql($sql, $params);
+ self::recordset_loop_and_export($backupcontrollers, 'itemid', [], function($carry, $record) {
+ $carry[] = [
+ 'operation' => $record->operation,
+ 'type' => $record->type,
+ 'itemid' => $record->itemid,
+ 'timecreated' => transform::datetime($record->timecreated),
+ 'timemodified' => transform::datetime($record->timemodified),
+ ];
+ return $carry;
+ }, function($courseid, $data) {
+ $context = \context_course::instance($courseid);
+ $finaldata = (object) $data;
+ writer::with_context($context)->export_data([get_string('backup'), $courseid], $finaldata);
+ });
+ }
+
+ /**
+ * Delete all user data which matches the specified context.
+ *
+ * @param \context $context A user context.
+ */
+ public static function delete_data_for_all_users_in_context(\context $context) {
+ global $DB;
+
+ if (!$context instanceof \context_course) {
+ return;
+ }
+
+ $DB->delete_records('backup_controllers', ['itemid' => $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 (empty($contextlist->count())) {
+ return;
+ }
+
+ $userid = $contextlist->get_user()->id;
+ foreach ($contextlist->get_contexts() as $context) {
+ if (!$context instanceof \context_course) {
+ return;
+ }
+
+ $DB->delete_records('backup_controllers', ['itemid' => $context->instanceid, 'userid' => $userid]);
+ }
+ }
+
+ /**
+ * Loop and export from a recordset.
+ *
+ * @param \moodle_recordset $recordset The recordset.
+ * @param string $splitkey The record key to determine when to export.
+ * @param mixed $initial The initial data to reduce from.
+ * @param callable $reducer The function to return the dataset, receives current dataset, and the current record.
+ * @param callable $export The function to export the dataset, receives the last value from $splitkey and the dataset.
+ * @return void
+ */
+ protected static function recordset_loop_and_export(\moodle_recordset $recordset, $splitkey, $initial,
+ callable $reducer, callable $export) {
+ $data = $initial;
+ $lastid = null;
+
+ foreach ($recordset as $record) {
+ if ($lastid && $record->{$splitkey} != $lastid) {
+ $export($lastid, $data);
+ $data = $initial;
+ }
+ $data = $reducer($data, $record);
+ $lastid = $record->{$splitkey};
+ }
+ $recordset->close();
+
+ if (!empty($lastid)) {
+ $export($lastid, $data);
+ }
+ }
+}
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_activity_modules'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'block_activity_results'; // Full name of the plugin (used for diagnostics).
\ No newline at end of file
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_admin_bookmarks'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'block_badges';
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_blog_menu'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_blog_recent'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_blog_tags'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_calendar_month'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_calendar_upcoming'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_comments'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_community'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'block_completionstatus';
-$plugin->dependencies = array('report_completion' => 2017110800);
+$plugin->dependencies = array('report_completion' => 2018050800);
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_course_list'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_course_summary'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_feedback'; // Full name of the plugin (used for diagnostics)
-$plugin->dependencies = array('mod_feedback' => 2017110800);
+$plugin->dependencies = array('mod_feedback' => 2018050800);
defined('MOODLE_INTERNAL') || die;
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->component = 'block_globalsearch';
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_glossary_random'; // Full name of the plugin (used for diagnostics)
-$plugin->dependencies = array('mod_glossary' => 2017110800);
+$plugin->dependencies = array('mod_glossary' => 2018050800);
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_html'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_login'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300;
-$plugin->requires = 2017110800;
+$plugin->version = 2018051400;
+$plugin->requires = 2018050800;
$plugin->component = 'block_lp';
$plugin->dependencies = array(
'tool_lp' => ANY_VERSION
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_mentees'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_mnet_hosts'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2017110800; // Requires this Moodle version.
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2018050800; // Requires this Moodle version.
$plugin->component = 'block_myoverview'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_myprofile'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_navigation'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_news_items'; // Full name of the plugin (used for diagnostics)
-$plugin->dependencies = array('mod_forum' => 2017110800);
+$plugin->dependencies = array('mod_forum' => 2018050800);
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_online_users'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_participants'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_private_files'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_quiz_results'; // Full name of the plugin (used for diagnostics)
-$plugin->dependencies = array('mod_quiz' => 2017110800);
+$plugin->dependencies = array('mod_quiz' => 2018050800);
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_recent_activity'; // Full name of the plugin (used for diagnostics)
$plugin->cron = 24*3600; // Cron interval 1 day.
\ No newline at end of file
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_rss_client'; // Full name of the plugin (used for diagnostics)
$plugin->cron = 300; // Set min time between cron executions to 300 secs (5 mins)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_search_forums'; // Full name of the plugin (used for diagnostics)
-$plugin->dependencies = array('mod_forum' => 2017110800);
+$plugin->dependencies = array('mod_forum' => 2018050800);
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_section_links'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_selfcompletion'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_settings'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_site_main_menu'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2018050800; // Requires this Moodle version
$plugin->component = 'block_social_activities'; // Full name of the plugin (used for diagnostics)
namespace block_tag_flickr\privacy;
+use core_privacy\local\metadata\collection;
+use core_privacy\local\request\approved_contextlist;
+use core_privacy\local\request\context;
+use core_privacy\local\request\contextlist;
+
defined('MOODLE_INTERNAL') || die();
/**
- * Privacy Subsystem for block_tag_flickr implementing null_provider.
+ * Privacy Subsystem for block_tag_flickr implementing metadata and plugin provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class provider implements \core_privacy\local\metadata\null_provider {
+class provider implements \core_privacy\local\metadata\provider, \core_privacy\local\request\plugin\provider {
+
+ /**
+ * 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 {
+ $collection->add_external_location_link(
+ 'flickr.com',
+ [
+ 'tags' => 'privacy:metadata:block_tag_flickr:tags'
+ ],
+ 'privacy:metadata:block_tag_flickr'
+ );
+
+ 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 {
+ return new contextlist();
+ }
/**
- * Get the language string identifier with the component's language
- * file to explain why this plugin stores no data.
+ * Export all user data for the specified user, in the specified contexts.
*
- * @return string
+ * @param approved_contextlist $contextlist The approved contexts to export information for.
*/
- public static function get_reason() : string {
- return 'privacy:metadata';
+ public static function export_user_data(approved_contextlist $contextlist) {
}
+
+ /**
+ * 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) {
+ }
+
+ /**
+ * 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) {
+ }
+
}
$string['relevance'] = 'Relevance';
$string['sortby'] = 'Sort by';
$string['tag_flickr:addinstance'] = 'Add a new flickr block';
-$string['privacy:metadata'] = 'The Flickr block only shows data stored in other locations.';
+$string['privacy:metadata:block_tag_flickr'] = 'The Flickr block plugin does not store any personal data, but does transmit user data from Moodle to the remote system.';
+$string['privacy:metadata:block_tag_flickr:tags'] = 'The tag values sent as CSV format to search for Flickr images.';
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2017110800; // Requires this Moodle version
+