MDL-61937 mod_data: implement privacy provider
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Contains interface datafield_provider
|
||||
*
|
||||
* @package mod_data
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace mod_data\privacy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Interface datafield_provider, all datafield plugins need to implement it
|
||||
*
|
||||
* @package mod_data
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
interface datafield_provider extends \core_privacy\local\request\plugin\subplugin_provider {
|
||||
|
||||
/**
|
||||
* Exports data about one record in {data_content} table.
|
||||
*
|
||||
* Datafield plugins providers should implement this method to:
|
||||
* - preprocess references to files in the response (examples - textarea, picture, file)
|
||||
* - make content more human-readable (example - replace values separators in multimenu, format date in date)
|
||||
* - add more information about the field itself (example - list all options for menu, multimenu, radio)
|
||||
*
|
||||
* Sample implementation (from datafield_textarea):
|
||||
*
|
||||
* $defaultvalue->content = writer::with_context($context)
|
||||
* ->rewrite_pluginfile_urls([$recordobj->id, $contentobj->id], 'mod_data', 'content', $contentobj->id,
|
||||
* $defaultvalue->content);
|
||||
* writer::with_context($context)->export_data([$recordobj->id, $contentobj->id], $defaultvalue);
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
* @param \stdClass $defaultvalue pre-populated default value that most of plugins will use
|
||||
*/
|
||||
public static function export_data_content($context, $recordobj, $fieldobj, $contentobj, $defaultvalue);
|
||||
|
||||
/**
|
||||
* Allows plugins to delete locally stored data.
|
||||
*
|
||||
* Usually datafield plugins do not store anything and this method will be empty.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
*/
|
||||
public static function delete_data_content($context, $recordobj, $fieldobj, $contentobj);
|
||||
}
|
||||
@@ -0,0 +1,445 @@
|
||||
<?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 mod_data.
|
||||
*
|
||||
* @package mod_data
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace mod_data\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\helper;
|
||||
use core_privacy\local\request\transform;
|
||||
use core_privacy\local\request\writer;
|
||||
use core_privacy\manager;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Implementation of the privacy subsystem plugin provider for the database activity module.
|
||||
*
|
||||
* @package mod_data
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements
|
||||
// This plugin stores personal data.
|
||||
\core_privacy\local\metadata\provider,
|
||||
|
||||
// This plugin is a core_user_data_provider.
|
||||
\core_privacy\local\request\plugin\provider {
|
||||
|
||||
/** @var array stores list of records marked for deletion */
|
||||
protected static $deletedrecords = [];
|
||||
|
||||
/**
|
||||
* Return the fields which contain personal data.
|
||||
*
|
||||
* @param collection $collection 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 $collection) : collection {
|
||||
$collection->add_database_table(
|
||||
'data_records',
|
||||
[
|
||||
'userid' => 'privacy:metadata:data_records:userid',
|
||||
'groupid' => 'privacy:metadata:data_records:groupid',
|
||||
'timecreated' => 'privacy:metadata:data_records:timecreated',
|
||||
'timemodified' => 'privacy:metadata:data_records:timemodified',
|
||||
'approved' => 'privacy:metadata:data_records:approved',
|
||||
],
|
||||
'privacy:metadata:data_records'
|
||||
);
|
||||
$collection->add_database_table(
|
||||
'data_content',
|
||||
[
|
||||
'fieldid' => 'privacy:metadata:data_content:fieldid',
|
||||
'content' => 'privacy:metadata:data_content:content',
|
||||
'content1' => 'privacy:metadata:data_content:content1',
|
||||
'content2' => 'privacy:metadata:data_content:content2',
|
||||
'content3' => 'privacy:metadata:data_content:content3',
|
||||
'content4' => 'privacy:metadata:data_content:content4',
|
||||
],
|
||||
'privacy:metadata:data_content'
|
||||
);
|
||||
|
||||
// Link to subplugins.
|
||||
$collection->add_plugintype_link('datafield', [], 'privacy:metadata:datafieldnpluginsummary');
|
||||
|
||||
// Subsystems used.
|
||||
$collection->link_subsystem('core_comment', 'privacy:metadata:commentpurpose');
|
||||
$collection->link_subsystem('core_files', 'privacy:metadata:filepurpose');
|
||||
$collection->link_subsystem('core_tag', 'privacy:metadata:tagpurpose');
|
||||
$collection->link_subsystem('core_rating', 'privacy:metadata:ratingpurpose');
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of contexts that contain user information for the specified user.
|
||||
*
|
||||
* @param int $userid the userid.
|
||||
* @return contextlist the list of contexts containing user info for the user.
|
||||
*/
|
||||
public static function get_contexts_for_userid(int $userid) : contextlist {
|
||||
// Fetch all data records.
|
||||
$sql = "SELECT c.id
|
||||
FROM {context} c
|
||||
INNER JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
|
||||
INNER JOIN {modules} m ON m.id = cm.module AND m.name = :modname
|
||||
INNER JOIN {data} d ON d.id = cm.instance
|
||||
INNER JOIN {data_records} dr ON dr.dataid = d.id
|
||||
LEFT JOIN {comments} com ON com.commentarea=:commentarea and com.itemid = dr.id
|
||||
LEFT JOIN {rating} r ON r.contextid = c.id AND r.itemid = dr.id AND r.component = :moddata AND r.ratingarea = :ratingarea
|
||||
WHERE dr.userid = :userid OR com.userid = :userid1 OR r.userid = :userid2";
|
||||
|
||||
$params = [
|
||||
'modname' => 'data',
|
||||
'contextlevel' => CONTEXT_MODULE,
|
||||
'userid' => $userid,
|
||||
'userid1' => $userid,
|
||||
'userid2' => $userid,
|
||||
'commentarea' => 'database_entry',
|
||||
'moddata' => 'mod_data',
|
||||
'ratingarea' => 'entry',
|
||||
];
|
||||
$contextlist = new contextlist();
|
||||
$contextlist->add_from_sql($sql, $params);
|
||||
|
||||
return $contextlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an object from all fields in the $record where key starts with $prefix
|
||||
*
|
||||
* @param \stdClass $record
|
||||
* @param string $prefix
|
||||
* @param array $additionalfields
|
||||
* @return \stdClass
|
||||
*/
|
||||
protected static function extract_object_from_record($record, $prefix, $additionalfields = []) {
|
||||
$object = new \stdClass();
|
||||
foreach ($record as $key => $value) {
|
||||
if (preg_match('/^'.preg_quote($prefix, '/').'(.*)/', $key, $matches)) {
|
||||
$object->{$matches[1]} = $value;
|
||||
}
|
||||
}
|
||||
if ($additionalfields) {
|
||||
foreach ($additionalfields as $key => $value) {
|
||||
$object->$key = $value;
|
||||
}
|
||||
}
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export one field answer in a record in database activity module
|
||||
*
|
||||
* @param \context $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
*/
|
||||
protected static function export_data_content($context, $recordobj, $fieldobj, $contentobj) {
|
||||
$value = (object)[
|
||||
'field' => [
|
||||
// Name and description are displayed in mod_data without applying format_string().
|
||||
'name' => $fieldobj->name,
|
||||
'description' => $fieldobj->description,
|
||||
'type' => $fieldobj->type,
|
||||
'required' => transform::yesno($fieldobj->required),
|
||||
],
|
||||
'content' => $contentobj->content
|
||||
];
|
||||
foreach (['content1', 'content2', 'content3', 'content4'] as $key) {
|
||||
if ($contentobj->$key !== null) {
|
||||
$value->$key = $contentobj->$key;
|
||||
}
|
||||
}
|
||||
$classname = manager::get_provider_classname_for_component('datafield_' . $fieldobj->type);
|
||||
if (class_exists($classname) && is_subclass_of($classname, datafield_provider::class)) {
|
||||
component_class_callback($classname, 'export_data_content',
|
||||
[$context, $recordobj, $fieldobj, $contentobj, $value]);
|
||||
} else {
|
||||
// Data field plugin does not implement datafield_provider, just export default value.
|
||||
writer::with_context($context)->export_data([$recordobj->id, $contentobj->id], $value);
|
||||
}
|
||||
writer::with_context($context)->export_area_files([$recordobj->id, $contentobj->id], 'mod_data',
|
||||
'content', $contentobj->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL query that returns all fields from {data_content}, {data_fields} and {data_records} tables
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function sql_fields() {
|
||||
return 'd.id AS dataid, dc.id AS contentid, dc.fieldid, df.type AS fieldtype, df.name AS fieldname,
|
||||
df.description AS fielddescription, df.required AS fieldrequired,
|
||||
df.param1 AS fieldparam1, df.param2 AS fieldparam2, df.param3 AS fieldparam3, df.param4 AS fieldparam4,
|
||||
df.param5 AS fieldparam5, df.param6 AS fieldparam6, df.param7 AS fieldparam7, df.param8 AS fieldparam8,
|
||||
df.param9 AS fieldparam9, df.param10 AS fieldparam10,
|
||||
dc.content AS contentcontent, dc.content1 AS contentcontent1, dc.content2 AS contentcontent2,
|
||||
dc.content3 AS contentcontent3, dc.content4 AS contentcontent4,
|
||||
dc.recordid, dr.timecreated AS recordtimecreated, dr.timemodified AS recordtimemodified,
|
||||
dr.approved AS recordapproved, dr.groupid AS recordgroupid, dr.userid AS recorduserid';
|
||||
}
|
||||
|
||||
/**
|
||||
* Export personal data for the given approved_contextlist. User and context information is contained within the contextlist.
|
||||
*
|
||||
* @param approved_contextlist $contextlist a list of contexts approved for export.
|
||||
*/
|
||||
public static function export_user_data(approved_contextlist $contextlist) {
|
||||
global $DB;
|
||||
|
||||
if (!$contextlist->count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$user = $contextlist->get_user();
|
||||
|
||||
list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
|
||||
$sql = "SELECT cm.id AS cmid, d.name AS dataname, cm.course AS courseid, " . self::sql_fields() . "
|
||||
FROM {context} ctx
|
||||
JOIN {course_modules} cm ON cm.id = ctx.instanceid
|
||||
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
|
||||
JOIN {data} d ON d.id = cm.instance
|
||||
JOIN {data_records} dr ON dr.dataid = d.id
|
||||
JOIN {data_content} dc ON dc.recordid = dr.id
|
||||
JOIN {data_fields} df ON df.id = dc.fieldid
|
||||
WHERE ctx.id {$contextsql} AND ctx.contextlevel = :contextlevel
|
||||
AND dr.userid = :userid OR
|
||||
EXISTS (SELECT 1 FROM {comments} com WHERE com.commentarea=:commentarea
|
||||
AND com.itemid = dr.id AND com.userid = :userid1) OR
|
||||
EXISTS (SELECT 1 FROM {rating} r WHERE r.contextid = ctx.id AND r.itemid = dr.id AND r.component = :moddata
|
||||
AND r.ratingarea = :ratingarea AND r.userid = :userid2)
|
||||
ORDER BY cm.id, dr.id, dc.fieldid";
|
||||
$rs = $DB->get_recordset_sql($sql, $contextparams + ['contextlevel' => CONTEXT_MODULE,
|
||||
'modname' => 'data', 'userid' => $user->id, 'userid1' => $user->id, 'commentarea' => 'database_entry',
|
||||
'userid2' => $user->id, 'ratingarea' => 'entry', 'moddata' => 'mod_data']);
|
||||
|
||||
$context = null;
|
||||
$recordobj = null;
|
||||
foreach ($rs as $row) {
|
||||
if (!$context || $context->instanceid != $row->cmid) {
|
||||
// This row belongs to the different data module than the previous row.
|
||||
// Export the data for the previous module.
|
||||
self::export_data($context, $user);
|
||||
// Start new data module.
|
||||
$context = \context_module::instance($row->cmid);
|
||||
}
|
||||
|
||||
if (!$recordobj || $row->recordid != $recordobj->id) {
|
||||
// Export previous data record.
|
||||
self::export_data_record($context, $user, $recordobj);
|
||||
// Prepare for exporting new data record.
|
||||
$recordobj = self::extract_object_from_record($row, 'record', ['dataid' => $row->dataid]);
|
||||
}
|
||||
$fieldobj = self::extract_object_from_record($row, 'field', ['dataid' => $row->dataid]);
|
||||
$contentobj = self::extract_object_from_record($row, 'content',
|
||||
['fieldid' => $fieldobj->id, 'recordid' => $recordobj->id]);
|
||||
self::export_data_content($context, $recordobj, $fieldobj, $contentobj);
|
||||
}
|
||||
$rs->close();
|
||||
self::export_data_record($context, $user, $recordobj);
|
||||
self::export_data($context, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export one entry in the database activity module (one record in {data_records} table)
|
||||
*
|
||||
* @param \context $context
|
||||
* @param \stdClass $user
|
||||
* @param \stdClass $recordobj
|
||||
*/
|
||||
protected static function export_data_record($context, $user, $recordobj) {
|
||||
if (!$recordobj) {
|
||||
return;
|
||||
}
|
||||
$data = [
|
||||
'userid' => transform::user($user->id),
|
||||
'groupid' => $recordobj->groupid,
|
||||
'timecreated' => transform::datetime($recordobj->timecreated),
|
||||
'timemodified' => transform::datetime($recordobj->timemodified),
|
||||
'approved' => transform::yesno($recordobj->approved),
|
||||
];
|
||||
// Data about the record.
|
||||
writer::with_context($context)->export_data([$recordobj->id], (object)$data);
|
||||
// Related tags.
|
||||
\core_tag\privacy\provider::export_item_tags($user->id, $context, [$recordobj->id],
|
||||
'mod_data', 'data_records', $recordobj->id);
|
||||
// Export comments. For records that were not made by this user export only this user's comments, for own records
|
||||
// export comments made by everybody.
|
||||
\core_comment\privacy\provider::export_comments($context, 'mod_data', 'database_entry', $recordobj->id,
|
||||
[$recordobj->id], $recordobj->userid != $user->id);
|
||||
// Export ratings. For records that were not made by this user export only this user's ratings, for own records
|
||||
// export ratings from everybody.
|
||||
\core_rating\privacy\provider::export_area_ratings($user->id, $context, [$recordobj->id], 'entry',
|
||||
$recordobj->id, $recordobj->userid != $user->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export basic info about database activity module
|
||||
*
|
||||
* @param \context $context
|
||||
* @param \stdClass $user
|
||||
*/
|
||||
protected static function export_data($context, $user) {
|
||||
if (!$context) {
|
||||
return;
|
||||
}
|
||||
$contextdata = helper::get_context_data($context, $user);
|
||||
helper::export_context_files($context, $user);
|
||||
writer::with_context($context)->export_data([], $contextdata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all data for all users in the specified context.
|
||||
*
|
||||
* @param \context $context the context to delete in.
|
||||
*/
|
||||
public static function delete_data_for_all_users_in_context(\context $context) {
|
||||
global $DB;
|
||||
|
||||
if (!$context instanceof \context_module) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sql = "SELECT " . self::sql_fields() . "
|
||||
FROM {course_modules} cm
|
||||
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
|
||||
JOIN {data} d ON d.id = cm.instance
|
||||
JOIN {data_records} dr ON dr.dataid = d.id
|
||||
LEFT JOIN {data_content} dc ON dc.recordid = dr.id
|
||||
LEFT JOIN {data_fields} df ON df.id = dc.fieldid
|
||||
WHERE cm.id = :cmid
|
||||
ORDER BY dr.id";
|
||||
$rs = $DB->get_recordset_sql($sql, ['cmid' => $context->instanceid, 'modname' => 'data']);
|
||||
foreach ($rs as $row) {
|
||||
self::mark_data_content_for_deletion($context, $row);
|
||||
}
|
||||
$rs->close();
|
||||
|
||||
self::delete_data_records($context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* @param approved_contextlist $contextlist a list of contexts approved for deletion.
|
||||
*/
|
||||
public static function delete_data_for_user(approved_contextlist $contextlist) {
|
||||
global $DB;
|
||||
|
||||
if (empty($contextlist->count())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$user = $contextlist->get_user();
|
||||
|
||||
foreach ($contextlist->get_contexts() as $context) {
|
||||
$sql = "SELECT " . self::sql_fields() . "
|
||||
FROM {context} ctx
|
||||
JOIN {course_modules} cm ON cm.id = ctx.instanceid
|
||||
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
|
||||
JOIN {data} d ON d.id = cm.instance
|
||||
JOIN {data_records} dr ON dr.dataid = d.id AND dr.userid = :userid
|
||||
LEFT JOIN {data_content} dc ON dc.recordid = dr.id
|
||||
LEFT JOIN {data_fields} df ON df.id = dc.fieldid
|
||||
WHERE ctx.id = :ctxid AND ctx.contextlevel = :contextlevel
|
||||
ORDER BY dr.id";
|
||||
$rs = $DB->get_recordset_sql($sql, ['ctxid' => $context->id, 'contextlevel' => CONTEXT_MODULE,
|
||||
'modname' => 'data', 'userid' => $user->id]);
|
||||
foreach ($rs as $row) {
|
||||
self::mark_data_content_for_deletion($context, $row);
|
||||
}
|
||||
$rs->close();
|
||||
self::delete_data_records($context);
|
||||
}
|
||||
|
||||
// Additionally remove comments this user made on other entries.
|
||||
\core_comment\privacy\provider::delete_comments_for_user($contextlist, 'mod_data', 'entry');
|
||||
|
||||
// We do not delete ratings made by this user on other records because it may change grades.
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a data_record/data_content for deletion
|
||||
*
|
||||
* Also invokes callback from datafield plugin in case it stores additional data that needs to be deleted
|
||||
*
|
||||
* @param \context $context
|
||||
* @param \stdClass $row result of SQL query - tables data_content, data_record, data_fields join together
|
||||
*/
|
||||
protected static function mark_data_content_for_deletion($context, $row) {
|
||||
$recordobj = self::extract_object_from_record($row, 'record', ['dataid' => $row->dataid]);
|
||||
if ($row->contentid && $row->fieldid) {
|
||||
$fieldobj = self::extract_object_from_record($row, 'field', ['dataid' => $row->dataid]);
|
||||
$contentobj = self::extract_object_from_record($row, 'content',
|
||||
['fieldid' => $fieldobj->id, 'recordid' => $recordobj->id]);
|
||||
|
||||
// Allow datafield plugin to implement their own deletion.
|
||||
$classname = manager::get_provider_classname_for_component('datafield_' . $fieldobj->type);
|
||||
if (class_exists($classname) && is_subclass_of($classname, datafield_provider::class)) {
|
||||
component_class_callback($classname, 'delete_data_content',
|
||||
[$context, $recordobj, $fieldobj, $contentobj]);
|
||||
}
|
||||
}
|
||||
|
||||
self::$deletedrecords[$recordobj->id] = $recordobj->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes records marked for deletion and all associated data
|
||||
*
|
||||
* Should be executed after all records were marked by {@link mark_data_content_for_deletion()}
|
||||
*
|
||||
* Deletes records from data_content and data_records tables, associated files, tags, comments and ratings.
|
||||
*
|
||||
* @param \context $context
|
||||
*/
|
||||
protected static function delete_data_records($context) {
|
||||
global $DB;
|
||||
if (empty(self::$deletedrecords)) {
|
||||
return;
|
||||
}
|
||||
|
||||
list($sql, $params) = $DB->get_in_or_equal(self::$deletedrecords, SQL_PARAMS_NAMED);
|
||||
|
||||
// Delete files.
|
||||
get_file_storage()->delete_area_files_select($context->id, 'mod_data', 'data_records',
|
||||
"IN (SELECT dc.id FROM {data_content} dc WHERE dc.recordid $sql)", $params);
|
||||
// Delete from data_content.
|
||||
$DB->delete_records_select('data_content', 'recordid ' . $sql, $params);
|
||||
// Delete from data_records.
|
||||
$DB->delete_records_select('data_records', 'id ' . $sql, $params);
|
||||
// Delete tags.
|
||||
\core_tag\privacy\provider::delete_item_tags_select($context, 'mod_data', 'data_records', $sql, $params);
|
||||
// Delete comments.
|
||||
\core_comment\privacy\provider::delete_comments_for_all_users_select($context, 'mod_data', 'entry', $sql, $params);
|
||||
// Delete ratings.
|
||||
\core_rating\privacy\provider::delete_ratings_select($context, 'mod_data', 'entry', $sql, $params);
|
||||
|
||||
self::$deletedrecords = [];
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,9 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace datafield_checkbox\privacy;
|
||||
use core_privacy\local\request\writer;
|
||||
use mod_data\privacy\datafield_provider;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Privacy Subsystem for datafield_checkbox implementing null_provider.
|
||||
@@ -28,7 +31,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @copyright 2018 Carlos Escobedo <[email protected]>
|
||||
* @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\null_provider,
|
||||
datafield_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
@@ -38,4 +42,31 @@ class provider implements \core_privacy\local\metadata\null_provider {
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports data about one record in {data_content} table.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
* @param \stdClass $defaultvalue pre-populated default value that most of plugins will use
|
||||
*/
|
||||
public static function export_data_content($context, $recordobj, $fieldobj, $contentobj, $defaultvalue) {
|
||||
$defaultvalue->field['options'] = preg_split('/\s*\n\s*/', trim($fieldobj->param1), -1, PREG_SPLIT_NO_EMPTY);
|
||||
$defaultvalue->content = explode('##', $defaultvalue->content);
|
||||
writer::with_context($context)->export_data([$recordobj->id, $contentobj->id], $defaultvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugins to delete locally stored data.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
*/
|
||||
public static function delete_data_content($context, $recordobj, $fieldobj, $contentobj) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,4 @@
|
||||
|
||||
$string['pluginname'] = 'Checkbox';
|
||||
$string['fieldtypelabel'] = 'Checkbox field';
|
||||
$string['privacy:metadata'] = 'The Checkbox field component does not store any personal data.';
|
||||
$string['privacy:metadata'] = 'The Checkbox field component does not store any personal data itself, it uses tables defined in mod_data.';
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace datafield_date\privacy;
|
||||
use core_privacy\local\request\transform;
|
||||
use core_privacy\local\request\writer;
|
||||
use mod_data\privacy\datafield_provider;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Privacy Subsystem for datafield_date implementing null_provider.
|
||||
@@ -28,7 +32,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @copyright 2018 Carlos Escobedo <[email protected]>
|
||||
* @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\null_provider,
|
||||
datafield_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
@@ -38,4 +43,30 @@ class provider implements \core_privacy\local\metadata\null_provider {
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports data about one record in {data_content} table.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
* @param \stdClass $defaultvalue pre-populated default value that most of plugins will use
|
||||
*/
|
||||
public static function export_data_content($context, $recordobj, $fieldobj, $contentobj, $defaultvalue) {
|
||||
$defaultvalue->content = transform::date($defaultvalue->content);
|
||||
writer::with_context($context)->export_data([$recordobj->id, $contentobj->id], $defaultvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugins to delete locally stored data.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
*/
|
||||
public static function delete_data_content($context, $recordobj, $fieldobj, $contentobj) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,4 @@
|
||||
|
||||
$string['pluginname'] = 'Date';
|
||||
$string['fieldtypelabel'] = 'Date field';
|
||||
$string['privacy:metadata'] = 'The Date field component does not store any personal data.';
|
||||
$string['privacy:metadata'] = 'The Date field component does not store any personal data, it uses tables defined in mod_data.';
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace datafield_file\privacy;
|
||||
use mod_data\privacy\datafield_provider;
|
||||
use core_privacy\local\request\writer;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Privacy Subsystem for datafield_file implementing null_provider.
|
||||
@@ -28,7 +31,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @copyright 2018 Carlos Escobedo <[email protected]>
|
||||
* @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\null_provider,
|
||||
datafield_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
@@ -38,4 +42,37 @@ class provider implements \core_privacy\local\metadata\null_provider {
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports data about one record in {data_content} table.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
* @param \stdClass $defaultvalue pre-populated default value that most of plugins will use
|
||||
*/
|
||||
public static function export_data_content($context, $recordobj, $fieldobj, $contentobj, $defaultvalue) {
|
||||
if ($fieldobj->param3) {
|
||||
$defaultvalue->field['maxbytes'] = $fieldobj->param3;
|
||||
}
|
||||
// Change file name to file path.
|
||||
$defaultvalue->file = writer::with_context($context)
|
||||
->rewrite_pluginfile_urls([$recordobj->id, $contentobj->id], 'mod_data', 'content', $contentobj->id,
|
||||
'@@PLUGINFILE@@/' . $defaultvalue->content);
|
||||
unset($defaultvalue->content);
|
||||
writer::with_context($context)->export_data([$recordobj->id, $contentobj->id], $defaultvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugins to delete locally stored data.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
*/
|
||||
public static function delete_data_content($context, $recordobj, $fieldobj, $contentobj) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,4 @@
|
||||
|
||||
$string['pluginname'] = 'File';
|
||||
$string['fieldtypelabel'] = 'File field';
|
||||
$string['privacy:metadata'] = 'The File field component does not store any personal data.';
|
||||
$string['privacy:metadata'] = 'The File field component does not store any personal data, it uses tables defined in mod_data.';
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace datafield_latlong\privacy;
|
||||
use core_privacy\local\request\writer;
|
||||
use mod_data\privacy\datafield_provider;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Privacy Subsystem for datafield_latlong implementing null_provider.
|
||||
@@ -28,7 +31,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @copyright 2018 Carlos Escobedo <[email protected]>
|
||||
* @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\null_provider,
|
||||
datafield_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
@@ -38,4 +42,41 @@ class provider implements \core_privacy\local\metadata\null_provider {
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports data about one record in {data_content} table.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
* @param \stdClass $defaultvalue pre-populated default value that most of plugins will use
|
||||
*/
|
||||
public static function export_data_content($context, $recordobj, $fieldobj, $contentobj, $defaultvalue) {
|
||||
$defaultvalue->field['services'] = explode(',', $fieldobj->param1);
|
||||
if ($fieldobj->param2 > 0) {
|
||||
$defaultvalue->field['label'] = 'Content of field '.$fieldobj->param2;
|
||||
} else if ($fieldobj->param2 == -2) {
|
||||
$defaultvalue->field['label'] = 'lattitude/longitude';
|
||||
} else {
|
||||
$defaultvalue->field['label'] = 'item #';
|
||||
}
|
||||
$defaultvalue->lattitude = $contentobj->content;
|
||||
$defaultvalue->longitude = $contentobj->content1;
|
||||
unset($defaultvalue->content);
|
||||
unset($defaultvalue->content1);
|
||||
writer::with_context($context)->export_data([$recordobj->id, $contentobj->id], $defaultvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugins to delete locally stored data.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
*/
|
||||
public static function delete_data_content($context, $recordobj, $fieldobj, $contentobj) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,4 @@
|
||||
|
||||
$string['pluginname'] = 'Latlong';
|
||||
$string['fieldtypelabel'] = 'Latitude/longitude field';
|
||||
$string['privacy:metadata'] = 'The Latitude/longitude field component does not store any personal data.';
|
||||
$string['privacy:metadata'] = 'The Latitude/longitude field component does not store any personal data, it uses tables defined in mod_data.';
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace datafield_menu\privacy;
|
||||
use core_privacy\local\request\writer;
|
||||
use mod_data\privacy\datafield_provider;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Privacy Subsystem for datafield_menu implementing null_provider.
|
||||
@@ -28,7 +31,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @copyright 2018 Carlos Escobedo <[email protected]>
|
||||
* @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\null_provider,
|
||||
datafield_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
@@ -38,4 +42,30 @@ class provider implements \core_privacy\local\metadata\null_provider {
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports data about one record in {data_content} table.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
* @param \stdClass $defaultvalue pre-populated default value that most of plugins will use
|
||||
*/
|
||||
public static function export_data_content($context, $recordobj, $fieldobj, $contentobj, $defaultvalue) {
|
||||
$defaultvalue->field['options'] = preg_split('/\s*\n\s*/', trim($fieldobj->param1), -1, PREG_SPLIT_NO_EMPTY);
|
||||
writer::with_context($context)->export_data([$recordobj->id, $contentobj->id], $defaultvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugins to delete locally stored data.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
*/
|
||||
public static function delete_data_content($context, $recordobj, $fieldobj, $contentobj) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,4 @@
|
||||
|
||||
$string['pluginname'] = 'Menu';
|
||||
$string['fieldtypelabel'] = 'Menu field';
|
||||
$string['privacy:metadata'] = 'The Menu field component does not store any personal data.';
|
||||
$string['privacy:metadata'] = 'The Menu field component does not store any personal data, it uses tables defined in mod_data.';
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace datafield_multimenu\privacy;
|
||||
use core_privacy\local\request\writer;
|
||||
use mod_data\privacy\datafield_provider;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Privacy Subsystem for datafield_multimenu implementing null_provider.
|
||||
@@ -28,7 +31,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @copyright 2018 Carlos Escobedo <[email protected]>
|
||||
* @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\null_provider,
|
||||
datafield_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
@@ -38,4 +42,34 @@ class provider implements \core_privacy\local\metadata\null_provider {
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports data about one record in {data_content} table.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
* @param \stdClass $defaultvalue pre-populated default value that most of plugins will use
|
||||
*/
|
||||
public static function export_data_content($context, $recordobj, $fieldobj, $contentobj, $defaultvalue) {
|
||||
$defaultvalue->field['options'] = preg_split('/\s*\n\s*/', trim($fieldobj->param1), -1, PREG_SPLIT_NO_EMPTY);
|
||||
for ($i = 1; $i <= 10; $i++) {
|
||||
unset($defaultvalue->field['param' . $i]);
|
||||
}
|
||||
$defaultvalue->content = explode('##', $defaultvalue->content);
|
||||
writer::with_context($context)->export_data([$recordobj->id, $contentobj->id], $defaultvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugins to delete locally stored data.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
*/
|
||||
public static function delete_data_content($context, $recordobj, $fieldobj, $contentobj) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,4 @@
|
||||
|
||||
$string['pluginname'] = 'Multimenu';
|
||||
$string['fieldtypelabel'] = 'Multiple-selection menu field';
|
||||
$string['privacy:metadata'] = 'The Multiple-selection menu field component does not store any personal data.';
|
||||
$string['privacy:metadata'] = 'The Multiple-selection menu field component does not store any personal data, it uses tables defined in mod_data.';
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace datafield_number\privacy;
|
||||
use core_privacy\local\request\writer;
|
||||
use mod_data\privacy\datafield_provider;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Privacy Subsystem for datafield_number implementing null_provider.
|
||||
@@ -28,7 +31,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @copyright 2018 Carlos Escobedo <[email protected]>
|
||||
* @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\null_provider,
|
||||
datafield_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
@@ -38,4 +42,32 @@ class provider implements \core_privacy\local\metadata\null_provider {
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports data about one record in {data_content} table.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
* @param \stdClass $defaultvalue pre-populated default value that most of plugins will use
|
||||
*/
|
||||
public static function export_data_content($context, $recordobj, $fieldobj, $contentobj, $defaultvalue) {
|
||||
if (preg_match("/^\d+$/", trim($fieldobj->param1))) {
|
||||
$defaultvalue->field['decimals'] = trim($fieldobj->param1);
|
||||
}
|
||||
writer::with_context($context)->export_data([$recordobj->id, $contentobj->id], $defaultvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugins to delete locally stored data.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
*/
|
||||
public static function delete_data_content($context, $recordobj, $fieldobj, $contentobj) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,4 @@
|
||||
|
||||
$string['pluginname'] = 'Number';
|
||||
$string['fieldtypelabel'] = 'Number field';
|
||||
$string['privacy:metadata'] = 'The Number field component does not store any personal data.';
|
||||
$string['privacy:metadata'] = 'The Number field component does not store any personal data, it uses tables defined in mod_data.';
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace datafield_picture\privacy;
|
||||
use core_privacy\local\request\writer;
|
||||
use mod_data\privacy\datafield_provider;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Privacy Subsystem for datafield_picture implementing null_provider.
|
||||
@@ -28,7 +31,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @copyright 2018 Carlos Escobedo <[email protected]>
|
||||
* @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\null_provider,
|
||||
datafield_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
@@ -38,4 +42,48 @@ class provider implements \core_privacy\local\metadata\null_provider {
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports data about one record in {data_content} table.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
* @param \stdClass $defaultvalue pre-populated default value that most of plugins will use
|
||||
*/
|
||||
public static function export_data_content($context, $recordobj, $fieldobj, $contentobj, $defaultvalue) {
|
||||
if ($fieldobj->param1) {
|
||||
$defaultvalue->field['width'] = $fieldobj->param1;
|
||||
}
|
||||
if ($fieldobj->param2) {
|
||||
$defaultvalue->field['height'] = $fieldobj->param2;
|
||||
}
|
||||
if ($fieldobj->param3) {
|
||||
$defaultvalue->field['maxbytes'] = $fieldobj->param3;
|
||||
}
|
||||
|
||||
// Change file name to file path.
|
||||
$defaultvalue->file = writer::with_context($context)
|
||||
->rewrite_pluginfile_urls([$recordobj->id, $contentobj->id], 'mod_data', 'content', $contentobj->id,
|
||||
'@@PLUGINFILE@@/' . $defaultvalue->content);
|
||||
if (isset($defaultvalue->content1)) {
|
||||
$defaultvalue->alttext = $defaultvalue->content1;
|
||||
}
|
||||
unset($defaultvalue->content);
|
||||
unset($defaultvalue->content1);
|
||||
writer::with_context($context)->export_data([$recordobj->id, $contentobj->id], $defaultvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugins to delete locally stored data.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
*/
|
||||
public static function delete_data_content($context, $recordobj, $fieldobj, $contentobj) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,4 @@
|
||||
|
||||
$string['pluginname'] = 'Picture';
|
||||
$string['fieldtypelabel'] = 'Picture field';
|
||||
$string['privacy:metadata'] = 'The Picture field component does not store any personal data.';
|
||||
$string['privacy:metadata'] = 'The Picture field component does not store any personal data, it uses tables defined in mod_data.';
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace datafield_radiobutton\privacy;
|
||||
use core_privacy\local\request\writer;
|
||||
use mod_data\privacy\datafield_provider;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Privacy Subsystem for datafield_radiobutton implementing null_provider.
|
||||
@@ -28,7 +31,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @copyright 2018 Carlos Escobedo <[email protected]>
|
||||
* @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\null_provider,
|
||||
datafield_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
@@ -38,4 +42,30 @@ class provider implements \core_privacy\local\metadata\null_provider {
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports data about one record in {data_content} table.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
* @param \stdClass $defaultvalue pre-populated default value that most of plugins will use
|
||||
*/
|
||||
public static function export_data_content($context, $recordobj, $fieldobj, $contentobj, $defaultvalue) {
|
||||
$defaultvalue->field['options'] = preg_split('/\s*\n\s*/', trim($fieldobj->param1), -1, PREG_SPLIT_NO_EMPTY);
|
||||
writer::with_context($context)->export_data([$recordobj->id, $contentobj->id], $defaultvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugins to delete locally stored data.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
*/
|
||||
public static function delete_data_content($context, $recordobj, $fieldobj, $contentobj) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,5 +26,5 @@
|
||||
|
||||
$string['pluginname'] = 'Radio button';
|
||||
$string['fieldtypelabel'] = 'Radio button field';
|
||||
$string['privacy:metadata'] = 'The Radio button field component does not store any personal data.';
|
||||
$string['privacy:metadata'] = 'The Radio button field component does not store any personal data, it uses tables defined in mod_data.';
|
||||
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace datafield_text\privacy;
|
||||
use core_privacy\local\request\writer;
|
||||
use mod_data\privacy\datafield_provider;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Privacy Subsystem for datafield_text implementing null_provider.
|
||||
@@ -28,7 +31,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @copyright 2018 Carlos Escobedo <[email protected]>
|
||||
* @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\null_provider,
|
||||
datafield_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
@@ -38,4 +42,29 @@ class provider implements \core_privacy\local\metadata\null_provider {
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports data about one record in {data_content} table.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
* @param \stdClass $defaultvalue pre-populated default value that most of plugins will use
|
||||
*/
|
||||
public static function export_data_content($context, $recordobj, $fieldobj, $contentobj, $defaultvalue) {
|
||||
writer::with_context($context)->export_data([$recordobj->id, $contentobj->id], $defaultvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugins to delete locally stored data.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
*/
|
||||
public static function delete_data_content($context, $recordobj, $fieldobj, $contentobj) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,4 @@
|
||||
|
||||
$string['pluginname'] = 'Text input';
|
||||
$string['fieldtypelabel'] = 'Text field';
|
||||
$string['privacy:metadata'] = 'The Text field component does not store any personal data.';
|
||||
$string['privacy:metadata'] = 'The Text field component does not store any personal data, it uses tables defined in mod_data.';
|
||||
|
||||
@@ -21,6 +21,11 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace datafield_textarea\privacy;
|
||||
|
||||
use core_privacy\local\request\transform;
|
||||
use core_privacy\local\request\writer;
|
||||
use mod_data\privacy\datafield_provider;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Privacy Subsystem for datafield_textarea implementing null_provider.
|
||||
@@ -28,7 +33,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @copyright 2018 Carlos Escobedo <[email protected]>
|
||||
* @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\null_provider,
|
||||
datafield_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
@@ -38,4 +44,42 @@ class provider implements \core_privacy\local\metadata\null_provider {
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports data about one record in {data_content} table.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
* @param \stdClass $defaultvalue pre-populated default value that most of plugins will use
|
||||
*/
|
||||
public static function export_data_content($context, $recordobj, $fieldobj, $contentobj, $defaultvalue) {
|
||||
$subcontext = [$recordobj->id, $contentobj->id];
|
||||
$defaultvalue->content = writer::with_context($context)
|
||||
->rewrite_pluginfile_urls($subcontext, 'mod_data', 'content', $contentobj->id,
|
||||
$defaultvalue->content);
|
||||
$defaultvalue->contentformat = $defaultvalue->content1;
|
||||
unset($defaultvalue->content1);
|
||||
|
||||
$defaultvalue->field['autolink'] = transform::yesno($fieldobj->param1);
|
||||
$defaultvalue->field['rows'] = $fieldobj->param3;
|
||||
$defaultvalue->field['cols'] = $fieldobj->param2;
|
||||
if ($fieldobj->param5) {
|
||||
$defaultvalue->field['maxbytes'] = $fieldobj->param5;
|
||||
}
|
||||
writer::with_context($context)->export_data($subcontext, $defaultvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugins to delete locally stored data.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
*/
|
||||
public static function delete_data_content($context, $recordobj, $fieldobj, $contentobj) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -28,4 +28,4 @@ $string['maxbytes'] = 'Maximum embedded file size (bytes)';
|
||||
$string['maxbytes_desc'] = 'If set to zero will be unlimited by default';
|
||||
$string['pluginname'] = 'Text area';
|
||||
$string['fieldtypelabel'] = 'Textarea field';
|
||||
$string['privacy:metadata'] = 'The Textarea field component does not store any personal data.';
|
||||
$string['privacy:metadata'] = 'The Textarea field component does not store any personal data, it uses tables defined in mod_data.';
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace datafield_url\privacy;
|
||||
use core_privacy\local\request\transform;
|
||||
use core_privacy\local\request\writer;
|
||||
use mod_data\privacy\datafield_provider;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Privacy Subsystem for datafield_url implementing null_provider.
|
||||
@@ -28,7 +32,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @copyright 2018 Carlos Escobedo <[email protected]>
|
||||
* @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\null_provider,
|
||||
datafield_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
@@ -38,4 +43,38 @@ class provider implements \core_privacy\local\metadata\null_provider {
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports data about one record in {data_content} table.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
* @param \stdClass $defaultvalue pre-populated default value that most of plugins will use
|
||||
*/
|
||||
public static function export_data_content($context, $recordobj, $fieldobj, $contentobj, $defaultvalue) {
|
||||
$defaultvalue->field['autolink'] = transform::yesno($fieldobj->param1);
|
||||
if (!empty($fieldobj->param2)) {
|
||||
$defaultvalue->field['forcetext'] = $fieldobj->param2;
|
||||
}
|
||||
$defaultvalue->field['blanktarget'] = transform::yesno($fieldobj->param3);
|
||||
$defaultvalue->url = $contentobj->content;
|
||||
$defaultvalue->text = $contentobj->content1;
|
||||
unset($defaultvalue->content);
|
||||
unset($defaultvalue->content1);
|
||||
writer::with_context($context)->export_data([$recordobj->id, $contentobj->id], $defaultvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugins to delete locally stored data.
|
||||
*
|
||||
* @param \context_module $context
|
||||
* @param \stdClass $recordobj record from DB table {data_records}
|
||||
* @param \stdClass $fieldobj record from DB table {data_fields}
|
||||
* @param \stdClass $contentobj record from DB table {data_content}
|
||||
*/
|
||||
public static function delete_data_content($context, $recordobj, $fieldobj, $contentobj) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -27,4 +27,4 @@
|
||||
$string['pluginname'] = 'URL';
|
||||
$string['openlinkinnewwindow'] = 'Open link in new window';
|
||||
$string['fieldtypelabel'] = 'URL field';
|
||||
$string['privacy:metadata'] = 'The URL field component does not store any personal data.';
|
||||
$string['privacy:metadata'] = 'The URL field component does not store any personal data, it uses tables defined in mod_data.';
|
||||
|
||||
@@ -302,6 +302,24 @@ $string['pluginname'] = 'Database';
|
||||
$string['portfolionotfile'] = 'Export to a portfolio rather than a file (csv and leap2a only)';
|
||||
$string['presetinfo'] = 'Saving as a preset will publish this template. Other users may be able to use it in their databases.';
|
||||
$string['presets'] = 'Presets';
|
||||
$string['privacy:metadata:commentpurpose'] = 'Comments on database records';
|
||||
$string['privacy:metadata:data_content'] = 'Represents one answer to one field in database activity module';
|
||||
$string['privacy:metadata:data_content:fieldid'] = 'Field definition id';
|
||||
$string['privacy:metadata:data_content:content'] = 'Content';
|
||||
$string['privacy:metadata:data_content:content1'] = 'Additional content 1';
|
||||
$string['privacy:metadata:data_content:content2'] = 'Additional content 2';
|
||||
$string['privacy:metadata:data_content:content3'] = 'Additional content 3';
|
||||
$string['privacy:metadata:data_content:content4'] = 'Additional content 4';
|
||||
$string['privacy:metadata:data_records'] = 'Represent records in database acitivity module';
|
||||
$string['privacy:metadata:data_records:userid'] = 'User who created the record';
|
||||
$string['privacy:metadata:data_records:groupid'] = 'Group';
|
||||
$string['privacy:metadata:data_records:timecreated'] = 'Time when record was created';
|
||||
$string['privacy:metadata:data_records:timemodified'] = 'Time when record was last modified';
|
||||
$string['privacy:metadata:data_records:approved'] = 'Approval status';
|
||||
$string['privacy:metadata:datafieldnpluginsummary'] = 'Fields for database activity module';
|
||||
$string['privacy:metadata:filepurpose'] = 'File attached to the database record';
|
||||
$string['privacy:metadata:tagpurpose'] = 'Tags on database records';
|
||||
$string['privacy:metadata:ratingpurpose'] = 'Ratings on database records';
|
||||
$string['radiobutton'] = 'Radio buttons';
|
||||
$string['recordapproved'] = 'Entry approved';
|
||||
$string['recorddeleted'] = 'Entry deleted';
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
<?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 mod_data
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use core_privacy\local\metadata\collection;
|
||||
use mod_data\privacy\provider;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy provider tests class.
|
||||
*
|
||||
* @package mod_data
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class mod_data_privacy_provider_testcase extends \core_privacy\tests\provider_testcase {
|
||||
/** @var stdClass The student object. */
|
||||
protected $student;
|
||||
/** @var stdClass The student object. */
|
||||
protected $student2;
|
||||
|
||||
/** @var stdClass The data object. */
|
||||
protected $datamodule;
|
||||
|
||||
/** @var stdClass The course object. */
|
||||
protected $course;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
global $DB;
|
||||
$generator = $this->getDataGenerator();
|
||||
$course = $generator->create_course();
|
||||
$params = [
|
||||
'course' => $course->id,
|
||||
'name' => 'Database module',
|
||||
'comments' => 1,
|
||||
'assessed' => 1,
|
||||
];
|
||||
|
||||
// The database activity.
|
||||
$datamodule = $this->get_generator()->create_instance($params);
|
||||
|
||||
$fieldtypes = array('checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url',
|
||||
'latlong', 'file', 'picture');
|
||||
// Creating test Fields with default parameter values.
|
||||
foreach ($fieldtypes as $count => $fieldtype) {
|
||||
// Creating variables dynamically.
|
||||
$fieldname = 'field' . $count;
|
||||
$record = new \stdClass();
|
||||
$record->name = $fieldname;
|
||||
$record->description = $fieldname . ' descr';
|
||||
$record->type = $fieldtype;
|
||||
|
||||
${$fieldname} = $this->get_generator()->create_field($record, $datamodule);
|
||||
}
|
||||
|
||||
$cm = get_coursemodule_from_instance('data', $datamodule->id);
|
||||
|
||||
// Create a student.
|
||||
$student1 = $generator->create_user();
|
||||
$student2 = $generator->create_user();
|
||||
$studentrole = $DB->get_record('role', ['shortname' => 'student']);
|
||||
$generator->enrol_user($student1->id, $course->id, $studentrole->id);
|
||||
$generator->enrol_user($student2->id, $course->id, $studentrole->id);
|
||||
|
||||
// Add records.
|
||||
$this->setUser($student1);
|
||||
$record1id = $this->generate_data_record($datamodule);
|
||||
$this->generate_data_record($datamodule);
|
||||
|
||||
$this->setUser($student2);
|
||||
$this->generate_data_record($datamodule);
|
||||
$this->generate_data_record($datamodule);
|
||||
$this->generate_data_record($datamodule);
|
||||
|
||||
$this->student = $student1;
|
||||
$this->student2 = $student2;
|
||||
$this->datamodule = $datamodule;
|
||||
$this->course = $course;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mod_data generator
|
||||
*
|
||||
* @return mod_data_generator
|
||||
*/
|
||||
protected function get_generator() {
|
||||
return $this->getDataGenerator()->get_plugin_generator('mod_data');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates one record in the database module as the current student
|
||||
*
|
||||
* @param stdClass $datamodule
|
||||
* @return mixed
|
||||
*/
|
||||
protected function generate_data_record($datamodule) {
|
||||
global $DB;
|
||||
|
||||
static $counter = 0;
|
||||
$counter++;
|
||||
|
||||
$contents = array();
|
||||
$contents[] = array('opt1', 'opt2', 'opt3', 'opt4');
|
||||
$contents[] = sprintf("%02f", $counter) . '-01-2000';
|
||||
$contents[] = 'menu1';
|
||||
$contents[] = array('multimenu1', 'multimenu2', 'multimenu3', 'multimenu4');
|
||||
$contents[] = 5 * $counter;
|
||||
$contents[] = 'radioopt1';
|
||||
$contents[] = 'text for testing' . $counter;
|
||||
$contents[] = "<p>text area testing $counter<br /></p>";
|
||||
$contents[] = array('example.url', 'sampleurl' . $counter);
|
||||
$contents[] = [-31.9489873, 115.8382036]; // Latlong.
|
||||
$contents[] = "Filename{$counter}.pdf"; // File - filename.
|
||||
$contents[] = array("Cat{$counter}.jpg", 'Cat' . $counter); // Picture - filename with alt text.
|
||||
$count = 0;
|
||||
$fieldcontents = array();
|
||||
$fields = $DB->get_records('data_fields', array('dataid' => $datamodule->id), 'id');
|
||||
foreach ($fields as $fieldrecord) {
|
||||
$fieldcontents[$fieldrecord->id] = $contents[$count++];
|
||||
}
|
||||
$tags = ['Cats', 'mice' . $counter];
|
||||
return $this->get_generator()->create_entry($datamodule, $fieldcontents, 0, $tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::get_metadata().
|
||||
*/
|
||||
public function test_get_metadata() {
|
||||
$collection = new collection('mod_data');
|
||||
$newcollection = provider::get_metadata($collection);
|
||||
$itemcollection = $newcollection->get_collection();
|
||||
$this->assertCount(7, $itemcollection);
|
||||
|
||||
$table = reset($itemcollection);
|
||||
$this->assertEquals('data_records', $table->get_name());
|
||||
|
||||
$table = next($itemcollection);
|
||||
$this->assertEquals('data_content', $table->get_name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::get_contexts_for_userid().
|
||||
*/
|
||||
public function test_get_contexts_for_userid() {
|
||||
$cm = get_coursemodule_from_instance('data', $this->datamodule->id);
|
||||
|
||||
$contextlist = provider::get_contexts_for_userid($this->student->id);
|
||||
$this->assertCount(1, $contextlist);
|
||||
$contextforuser = $contextlist->current();
|
||||
$cmcontext = context_module::instance($cm->id);
|
||||
$this->assertEquals($cmcontext->id, $contextforuser->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get test privacy writer
|
||||
*
|
||||
* @param context $context
|
||||
* @return \core_privacy\tests\request\content_writer
|
||||
*/
|
||||
protected function get_writer($context) {
|
||||
return \core_privacy\local\request\writer::with_context($context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::export_user_data().
|
||||
*/
|
||||
public function test_export_for_context() {
|
||||
global $DB;
|
||||
$cm = get_coursemodule_from_instance('data', $this->datamodule->id);
|
||||
$cmcontext = context_module::instance($cm->id);
|
||||
$records = $DB->get_records_select('data_records', 'userid = :userid ORDER BY id', ['userid' => $this->student->id]);
|
||||
$record = reset($records);
|
||||
$contents = $DB->get_records('data_content', ['recordid' => $record->id]);
|
||||
|
||||
// Export all of the data for the context.
|
||||
$this->export_context_data_for_user($this->student->id, $cmcontext, 'mod_data');
|
||||
$writer = $this->get_writer($cmcontext);
|
||||
$data = $writer->get_data([$record->id]);
|
||||
$this->assertNotEmpty($data);
|
||||
foreach ($contents as $content) {
|
||||
$data = $writer->get_data([$record->id, $content->id]);
|
||||
$this->assertNotEmpty($data);
|
||||
$hasfile = in_array($data->field['type'], ['file', 'picture']);
|
||||
$this->assertEquals($hasfile, !empty($writer->get_files([$record->id, $content->id])));
|
||||
}
|
||||
$tags = $writer->get_related_data([$record->id], 'tags');
|
||||
$this->assertNotEmpty($tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::delete_data_for_all_users_in_context().
|
||||
*/
|
||||
public function test_delete_data_for_all_users_in_context() {
|
||||
$cm = get_coursemodule_from_instance('data', $this->datamodule->id);
|
||||
$cmcontext = context_module::instance($cm->id);
|
||||
|
||||
provider::delete_data_for_all_users_in_context($cmcontext);
|
||||
|
||||
$appctxt = new \core_privacy\local\request\approved_contextlist($this->student, 'mod_data', [$cmcontext->id]);
|
||||
provider::export_user_data($appctxt);
|
||||
$this->assertFalse($this->get_writer($cmcontext)->has_any_data());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::delete_data_for_user().
|
||||
*/
|
||||
public function test_delete_data_for_user() {
|
||||
$cm = get_coursemodule_from_instance('data', $this->datamodule->id);
|
||||
$cmcontext = context_module::instance($cm->id);
|
||||
|
||||
$appctxt = new \core_privacy\local\request\approved_contextlist($this->student, 'mod_data', [$cmcontext->id]);
|
||||
provider::delete_data_for_user($appctxt);
|
||||
|
||||
provider::export_user_data($appctxt);
|
||||
$this->assertFalse($this->get_writer($cmcontext)->has_any_data());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user