mirror of
https://github.com/moodle/moodle.git
synced 2025-04-11 19:42:35 +02:00
MDL-61905 workshop: Implement privacy API in grading strategies
On low level, standard grading strategies subplugins do not store personal themselves. They make use of the grades storage provided by the workshop itself. What they do contain though is the information about how the assessment forms were defined. And they are also responsible for correctly interpreting the values in the central grades table. Grading strategies fulfil the contract with the parent workshop module by implementing the workshopform_provider interface. That gives them a chance to export data about the assessment form to each of exported assessment.
This commit is contained in:
parent
84a57322c2
commit
fe745a0a84
105
mod/workshop/form/accumulative/classes/privacy/provider.php
Normal file
105
mod/workshop/form/accumulative/classes/privacy/provider.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Provides the class {@link workshopform_accumulative\privacy\provider}
|
||||
*
|
||||
* @package workshopform_accumulative
|
||||
* @category privacy
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace workshopform_accumulative\privacy;
|
||||
|
||||
use core_privacy\local\request\writer;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy API implementation for the Accumulative grading strategy.
|
||||
*
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider, \mod_workshop\privacy\workshopform_provider {
|
||||
|
||||
/**
|
||||
* Explain that this plugin stores no personal data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return details of the filled assessment form.
|
||||
*
|
||||
* @param stdClass $user User we are exporting data for
|
||||
* @param context $context The workshop activity context
|
||||
* @param array $subcontext Subcontext within the context to export to
|
||||
* @param int $assessmentid ID of the assessment
|
||||
*/
|
||||
public static function export_assessment_form(\stdClass $user, \context $context, array $subcontext, int $assessmentid) {
|
||||
global $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
throw new \coding_exception('Unexpected context provided');
|
||||
}
|
||||
|
||||
$sql = "SELECT dim.id, dim.description, dim.descriptionformat, dim.grade AS dimgrade, dim.weight,
|
||||
wg.grade, wg.peercomment, wg.peercommentformat
|
||||
FROM {course_modules} cm
|
||||
JOIN {context} ctx ON ctx.contextlevel = :contextlevel AND ctx.instanceid = cm.id
|
||||
JOIN {workshop} w ON cm.instance = w.id
|
||||
JOIN {workshopform_accumulative} dim ON dim.workshopid = w.id
|
||||
LEFT JOIN {workshop_grades} wg ON wg.strategy = :strategy
|
||||
AND wg.dimensionid = dim.id AND wg.assessmentid = :assessmentid
|
||||
WHERE ctx.id = :contextid
|
||||
ORDER BY dim.sort";
|
||||
|
||||
$params = [
|
||||
'strategy' => 'accumulative',
|
||||
'contextlevel' => CONTEXT_MODULE,
|
||||
'contextid' => $context->id,
|
||||
'assessmentid' => $assessmentid,
|
||||
];
|
||||
|
||||
$writer = \core_privacy\local\request\writer::with_context($context);
|
||||
$data = [];
|
||||
$hasdata = false;
|
||||
$dimensionids = [];
|
||||
|
||||
foreach ($DB->get_records_sql($sql, $params) as $record) {
|
||||
if ($record->grade !== null) {
|
||||
$hasdata = true;
|
||||
}
|
||||
$record->description = $writer->rewrite_pluginfile_urls($subcontext, 'workshopform_accumulative',
|
||||
'description', $record->id, $record->description);
|
||||
$dimensionids[] = $record->id;
|
||||
unset($record->id);
|
||||
$data[] = $record;
|
||||
}
|
||||
|
||||
if ($hasdata) {
|
||||
$writer->export_data($subcontext, (object) ['aspects' => $data]);
|
||||
foreach ($dimensionids as $dimensionid) {
|
||||
$writer->export_area_files($subcontext, 'workshopform_accumulative', 'description', $dimensionid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -39,6 +39,7 @@ $string['mustchoosegrade'] = 'You have to select a grade for this aspect';
|
||||
$string['pluginname'] = 'Accumulative grading';
|
||||
$string['poor'] = 'Poor';
|
||||
$string['present'] = 'Present';
|
||||
$string['privacy:metadata'] = 'The Accumulative grading plugin only stores the details of the assessment form. Actual personal data of how the form has been filled are stored by the Workshop module itself and are attached to exported assessments.';
|
||||
$string['scalename0'] = 'Yes/No (2 point)';
|
||||
$string['scalename1'] = 'Present/Absent (2 point)';
|
||||
$string['scalename2'] = 'Correct/Incorrect (2 point)';
|
||||
|
122
mod/workshop/form/accumulative/tests/privacy_provider_test.php
Normal file
122
mod/workshop/form/accumulative/tests/privacy_provider_test.php
Normal file
@ -0,0 +1,122 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Provides the {@link workshopform_accumulative_privacy_provider_testcase} class.
|
||||
*
|
||||
* @package workshopform_accumulative
|
||||
* @category test
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use core_privacy\local\request\writer;
|
||||
|
||||
/**
|
||||
* Unit tests for the privacy API implementation.
|
||||
*
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class workshopform_accumulative_privacy_provider_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test {@link workshopform_accumulative\privacy\provider::export_assessment_form()} implementation.
|
||||
*/
|
||||
public function test_export_assessment_form() {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$this->generator = $this->getDataGenerator();
|
||||
$this->workshopgenerator = $this->generator->get_plugin_generator('mod_workshop');
|
||||
|
||||
$this->course1 = $this->generator->create_course();
|
||||
|
||||
$this->workshop11 = $this->generator->create_module('workshop', [
|
||||
'course' => $this->course1,
|
||||
'name' => 'Workshop11',
|
||||
]);
|
||||
$DB->set_field('workshop', 'phase', 50, ['id' => $this->workshop11->id]);
|
||||
|
||||
$this->dim1 = $DB->insert_record('workshopform_accumulative', [
|
||||
'workshopid' => $this->workshop11->id,
|
||||
'sort' => 1,
|
||||
'description' => 'Aspect 1 description',
|
||||
'descriptionformat' => FORMAT_MARKDOWN,
|
||||
'grade' => 6,
|
||||
'weight' => 1,
|
||||
]);
|
||||
|
||||
$this->dim2 = $DB->insert_record('workshopform_accumulative', [
|
||||
'workshopid' => $this->workshop11->id,
|
||||
'sort' => 2,
|
||||
'description' => 'Aspect 2 description',
|
||||
'descriptionformat' => FORMAT_MARKDOWN,
|
||||
'grade' => 4,
|
||||
'weight' => 1,
|
||||
]);
|
||||
|
||||
$this->student1 = $this->generator->create_user();
|
||||
$this->student2 = $this->generator->create_user();
|
||||
|
||||
$this->submission111 = $this->workshopgenerator->create_submission($this->workshop11->id, $this->student1->id);
|
||||
|
||||
$this->assessment1112 = $this->workshopgenerator->create_assessment($this->submission111, $this->student2->id, [
|
||||
'grade' => 92,
|
||||
]);
|
||||
|
||||
$DB->insert_record('workshop_grades', [
|
||||
'assessmentid' => $this->assessment1112,
|
||||
'strategy' => 'accumulative',
|
||||
'dimensionid' => $this->dim1,
|
||||
'grade' => 3,
|
||||
'peercomment' => 'Not awesome',
|
||||
'peercommentformat' => FORMAT_PLAIN,
|
||||
]);
|
||||
|
||||
$DB->insert_record('workshop_grades', [
|
||||
'assessmentid' => $this->assessment1112,
|
||||
'strategy' => 'accumulative',
|
||||
'dimensionid' => $this->dim2,
|
||||
'grade' => 4,
|
||||
'peercomment' => 'All good',
|
||||
'peercommentformat' => FORMAT_PLAIN,
|
||||
]);
|
||||
|
||||
$contextlist = new \core_privacy\local\request\approved_contextlist($this->student2, 'mod_workshop', [
|
||||
\context_module::instance($this->workshop11->cmid)->id,
|
||||
]);
|
||||
|
||||
\mod_workshop\privacy\provider::export_user_data($contextlist);
|
||||
|
||||
$writer = writer::with_context(\context_module::instance($this->workshop11->cmid));
|
||||
|
||||
$form = $writer->get_data([
|
||||
get_string('myassessments', 'mod_workshop'),
|
||||
$this->assessment1112,
|
||||
get_string('assessmentform', 'mod_workshop'),
|
||||
get_string('pluginname', 'workshopform_accumulative'),
|
||||
]);
|
||||
|
||||
$this->assertEquals('Aspect 1 description', $form->aspects[0]->description);
|
||||
$this->assertEquals(4, $form->aspects[1]->grade);
|
||||
}
|
||||
}
|
104
mod/workshop/form/comments/classes/privacy/provider.php
Normal file
104
mod/workshop/form/comments/classes/privacy/provider.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Provides the class {@link workshopform_comments\privacy\provider}
|
||||
*
|
||||
* @package workshopform_comments
|
||||
* @category privacy
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace workshopform_comments\privacy;
|
||||
|
||||
use core_privacy\local\request\writer;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy API implementation for the Comments grading strategy.
|
||||
*
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider, \mod_workshop\privacy\workshopform_provider {
|
||||
|
||||
/**
|
||||
* Explain that this plugin stores no personal data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return details of the filled assessment form.
|
||||
*
|
||||
* @param stdClass $user User we are exporting data for
|
||||
* @param context $context The workshop activity context
|
||||
* @param array $subcontext Subcontext within the context to export to
|
||||
* @param int $assessmentid ID of the assessment
|
||||
*/
|
||||
public static function export_assessment_form(\stdClass $user, \context $context, array $subcontext, int $assessmentid) {
|
||||
global $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
throw new \coding_exception('Unexpected context provided');
|
||||
}
|
||||
|
||||
$sql = "SELECT dim.id, dim.description, dim.descriptionformat, wg.peercomment, wg.peercommentformat
|
||||
FROM {course_modules} cm
|
||||
JOIN {context} ctx ON ctx.contextlevel = :contextlevel AND ctx.instanceid = cm.id
|
||||
JOIN {workshop} w ON cm.instance = w.id
|
||||
JOIN {workshopform_comments} dim ON dim.workshopid = w.id
|
||||
LEFT JOIN {workshop_grades} wg ON wg.strategy = :strategy
|
||||
AND wg.dimensionid = dim.id AND wg.assessmentid = :assessmentid
|
||||
WHERE ctx.id = :contextid
|
||||
ORDER BY dim.sort";
|
||||
|
||||
$params = [
|
||||
'strategy' => 'comments',
|
||||
'contextlevel' => CONTEXT_MODULE,
|
||||
'contextid' => $context->id,
|
||||
'assessmentid' => $assessmentid,
|
||||
];
|
||||
|
||||
$writer = \core_privacy\local\request\writer::with_context($context);
|
||||
$data = [];
|
||||
$hasdata = false;
|
||||
$dimensionids = [];
|
||||
|
||||
foreach ($DB->get_records_sql($sql, $params) as $record) {
|
||||
if ($record->peercomment !== null) {
|
||||
$hasdata = true;
|
||||
}
|
||||
$record->description = $writer->rewrite_pluginfile_urls($subcontext, 'workshopform_comments',
|
||||
'description', $record->id, $record->description);
|
||||
$dimensionids[] = $record->id;
|
||||
unset($record->id);
|
||||
$data[] = $record;
|
||||
}
|
||||
|
||||
if ($hasdata) {
|
||||
$writer->export_data($subcontext, (object) ['aspects' => $data]);
|
||||
foreach ($dimensionids as $dimensionid) {
|
||||
$writer->export_area_files($subcontext, 'workshopform_comments', 'description', $dimensionid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -28,4 +28,4 @@ $string['dimensioncommentfor'] = 'Comment for {$a}';
|
||||
$string['dimensiondescription'] = 'Description';
|
||||
$string['dimensionnumber'] = 'Aspect {$a}';
|
||||
$string['pluginname'] = 'Comments';
|
||||
|
||||
$string['privacy:metadata'] = 'The Comments grading plugin only stores the details of the assessment form. Actual personal data of how the form has been filled are stored by the Workshop module itself and are attached to exported assessments.';
|
||||
|
118
mod/workshop/form/comments/tests/privacy_provider_test.php
Normal file
118
mod/workshop/form/comments/tests/privacy_provider_test.php
Normal file
@ -0,0 +1,118 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Provides the {@link workshopform_comments_privacy_provider_testcase} class.
|
||||
*
|
||||
* @package workshopform_comments
|
||||
* @category test
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use core_privacy\local\request\writer;
|
||||
|
||||
/**
|
||||
* Unit tests for the privacy API implementation.
|
||||
*
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class workshopform_comments_privacy_provider_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test {@link workshopform_comments\privacy\provider::export_assessment_form()} implementation.
|
||||
*/
|
||||
public function test_export_assessment_form() {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$this->generator = $this->getDataGenerator();
|
||||
$this->workshopgenerator = $this->generator->get_plugin_generator('mod_workshop');
|
||||
|
||||
$this->course1 = $this->generator->create_course();
|
||||
|
||||
$this->workshop11 = $this->generator->create_module('workshop', [
|
||||
'course' => $this->course1,
|
||||
'name' => 'Workshop11',
|
||||
]);
|
||||
$DB->set_field('workshop', 'phase', 100, ['id' => $this->workshop11->id]);
|
||||
|
||||
$this->dim1 = $DB->insert_record('workshopform_comments', [
|
||||
'workshopid' => $this->workshop11->id,
|
||||
'sort' => 1,
|
||||
'description' => 'Aspect 1 description',
|
||||
'descriptionformat' => FORMAT_MARKDOWN,
|
||||
]);
|
||||
|
||||
$this->dim2 = $DB->insert_record('workshopform_comments', [
|
||||
'workshopid' => $this->workshop11->id,
|
||||
'sort' => 2,
|
||||
'description' => 'Aspect 2 description',
|
||||
'descriptionformat' => FORMAT_MARKDOWN,
|
||||
]);
|
||||
|
||||
$this->student1 = $this->generator->create_user();
|
||||
$this->student2 = $this->generator->create_user();
|
||||
|
||||
$this->submission111 = $this->workshopgenerator->create_submission($this->workshop11->id, $this->student1->id);
|
||||
|
||||
$this->assessment1112 = $this->workshopgenerator->create_assessment($this->submission111, $this->student2->id, [
|
||||
'grade' => 92,
|
||||
]);
|
||||
|
||||
$DB->insert_record('workshop_grades', [
|
||||
'assessmentid' => $this->assessment1112,
|
||||
'strategy' => 'comments',
|
||||
'dimensionid' => $this->dim1,
|
||||
'grade' => 100,
|
||||
'peercomment' => 'Not awesome',
|
||||
'peercommentformat' => FORMAT_PLAIN,
|
||||
]);
|
||||
|
||||
$DB->insert_record('workshop_grades', [
|
||||
'assessmentid' => $this->assessment1112,
|
||||
'strategy' => 'comments',
|
||||
'dimensionid' => $this->dim2,
|
||||
'grade' => 100,
|
||||
'peercomment' => 'All good',
|
||||
'peercommentformat' => FORMAT_PLAIN,
|
||||
]);
|
||||
|
||||
$contextlist = new \core_privacy\local\request\approved_contextlist($this->student2, 'mod_workshop', [
|
||||
\context_module::instance($this->workshop11->cmid)->id,
|
||||
]);
|
||||
|
||||
\mod_workshop\privacy\provider::export_user_data($contextlist);
|
||||
|
||||
$writer = writer::with_context(\context_module::instance($this->workshop11->cmid));
|
||||
|
||||
$form = $writer->get_data([
|
||||
get_string('myassessments', 'mod_workshop'),
|
||||
$this->assessment1112,
|
||||
get_string('assessmentform', 'mod_workshop'),
|
||||
get_string('pluginname', 'workshopform_comments'),
|
||||
]);
|
||||
|
||||
$this->assertEquals('Aspect 1 description', $form->aspects[0]->description);
|
||||
$this->assertEquals('All good', $form->aspects[1]->peercomment);
|
||||
}
|
||||
}
|
117
mod/workshop/form/numerrors/classes/privacy/provider.php
Normal file
117
mod/workshop/form/numerrors/classes/privacy/provider.php
Normal file
@ -0,0 +1,117 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Provides the class {@link workshopform_numerrors\privacy\provider}
|
||||
*
|
||||
* @package workshopform_numerrors
|
||||
* @category privacy
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace workshopform_numerrors\privacy;
|
||||
|
||||
use core_privacy\local\request\writer;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy API implementation for the Number of errors strategy.
|
||||
*
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider, \mod_workshop\privacy\workshopform_provider {
|
||||
|
||||
/**
|
||||
* Explain that this plugin stores no personal data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return details of the filled assessment form.
|
||||
*
|
||||
* @param stdClass $user User we are exporting data for
|
||||
* @param context $context The workshop activity context
|
||||
* @param array $subcontext Subcontext within the context to export to
|
||||
* @param int $assessmentid ID of the assessment
|
||||
*/
|
||||
public static function export_assessment_form(\stdClass $user, \context $context, array $subcontext, int $assessmentid) {
|
||||
global $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
throw new \coding_exception('Unexpected context provided');
|
||||
}
|
||||
|
||||
$sql = "SELECT dim.id, dim.workshopid, dim.description, dim.descriptionformat, dim.grade0, dim.grade1, dim.weight,
|
||||
wg.grade, wg.peercomment, wg.peercommentformat
|
||||
FROM {course_modules} cm
|
||||
JOIN {context} ctx ON ctx.contextlevel = :contextlevel AND ctx.instanceid = cm.id
|
||||
JOIN {workshop} w ON cm.instance = w.id
|
||||
JOIN {workshopform_numerrors} dim ON dim.workshopid = w.id
|
||||
LEFT JOIN {workshop_grades} wg ON wg.strategy = :strategy
|
||||
AND wg.dimensionid = dim.id AND wg.assessmentid = :assessmentid
|
||||
WHERE ctx.id = :contextid
|
||||
ORDER BY dim.sort";
|
||||
|
||||
$params = [
|
||||
'strategy' => 'numerrors',
|
||||
'contextlevel' => CONTEXT_MODULE,
|
||||
'contextid' => $context->id,
|
||||
'assessmentid' => $assessmentid,
|
||||
];
|
||||
|
||||
$writer = \core_privacy\local\request\writer::with_context($context);
|
||||
$data = [];
|
||||
$workshopid = null;
|
||||
$hasdata = false;
|
||||
$dimensionids = [];
|
||||
|
||||
foreach ($DB->get_records_sql($sql, $params) as $record) {
|
||||
if ($record->grade !== null) {
|
||||
$hasdata = true;
|
||||
}
|
||||
$record->description = $writer->rewrite_pluginfile_urls($subcontext, 'workshopform_numerrors',
|
||||
'description', $record->id, $record->description);
|
||||
$workshopid = $record->workshopid;
|
||||
$dimensionids[] = $record->id;
|
||||
unset($record->id);
|
||||
unset($record->workshopid);
|
||||
$data[] = $record;
|
||||
}
|
||||
|
||||
if ($hasdata) {
|
||||
$writer->export_data($subcontext, (object)['assertions' => $data]);
|
||||
foreach ($dimensionids as $dimensionid) {
|
||||
$writer->export_area_files($subcontext, 'workshopform_numerrors', 'description', $dimensionid);
|
||||
}
|
||||
foreach ($DB->get_records('workshopform_numerrors_map', ['workshopid' => $workshopid], 'nonegative',
|
||||
'id, nonegative, grade') as $mapping) {
|
||||
$writer->export_metadata($subcontext, 'map_'.$mapping->nonegative.'_errors', $mapping->grade,
|
||||
get_string('privacy:export:metadata:map', 'workshopform_numerrors', [
|
||||
'nonegative' => $mapping->nonegative,
|
||||
'grade' => $mapping->grade
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -40,4 +40,5 @@ $string['maperror'] = 'Weighted number of errors is less than or equals';
|
||||
$string['mapgrade'] = 'Grade for submission';
|
||||
$string['percents'] = '{$a} %';
|
||||
$string['pluginname'] = 'Number of errors';
|
||||
|
||||
$string['privacy:metadata'] = 'The Number of errors plugin only stores the details of the assessment form. Actual personal data of how the form has been filled are stored by the Workshop module itself and are attached to exported assessments.';
|
||||
$string['privacy:export:metadata:map'] = 'If the weighted number of errors reaches {$a->nonegative} then the grade is {$a->grade} percents.';
|
||||
|
127
mod/workshop/form/numerrors/tests/privacy_provider_test.php
Normal file
127
mod/workshop/form/numerrors/tests/privacy_provider_test.php
Normal file
@ -0,0 +1,127 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Provides the {@link workshopform_numerrors_privacy_provider_testcase} class.
|
||||
*
|
||||
* @package workshopform_numerrors
|
||||
* @category test
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use core_privacy\local\request\writer;
|
||||
|
||||
/**
|
||||
* Unit tests for the privacy API implementation.
|
||||
*
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class workshopform_numerrors_privacy_provider_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test {@link workshopform_numerrors\privacy\provider::export_assessment_form()} implementation.
|
||||
*/
|
||||
public function test_export_assessment_form() {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$this->generator = $this->getDataGenerator();
|
||||
$this->workshopgenerator = $this->generator->get_plugin_generator('mod_workshop');
|
||||
|
||||
$this->course1 = $this->generator->create_course();
|
||||
|
||||
$this->workshop11 = $this->generator->create_module('workshop', [
|
||||
'course' => $this->course1,
|
||||
'name' => 'Workshop11',
|
||||
]);
|
||||
$DB->set_field('workshop', 'phase', 50, ['id' => $this->workshop11->id]);
|
||||
|
||||
$this->dim1 = $DB->insert_record('workshopform_numerrors', [
|
||||
'workshopid' => $this->workshop11->id,
|
||||
'sort' => 1,
|
||||
'description' => 'Assertion 1 description',
|
||||
'descriptionformat' => FORMAT_MARKDOWN,
|
||||
'descriptiontrust' => 0,
|
||||
'grade0' => 'No',
|
||||
'grade1' => 'Yes',
|
||||
'weight' => 1,
|
||||
]);
|
||||
|
||||
$this->dim2 = $DB->insert_record('workshopform_numerrors', [
|
||||
'workshopid' => $this->workshop11->id,
|
||||
'sort' => 2,
|
||||
'description' => 'Assertion 2 description',
|
||||
'descriptionformat' => FORMAT_MARKDOWN,
|
||||
'descriptiontrust' => 0,
|
||||
'grade0' => 'Missing',
|
||||
'grade1' => 'Present',
|
||||
'weight' => 1,
|
||||
]);
|
||||
|
||||
$this->student1 = $this->generator->create_user();
|
||||
$this->student2 = $this->generator->create_user();
|
||||
|
||||
$this->submission111 = $this->workshopgenerator->create_submission($this->workshop11->id, $this->student1->id);
|
||||
|
||||
$this->assessment1112 = $this->workshopgenerator->create_assessment($this->submission111, $this->student2->id, [
|
||||
'grade' => 92,
|
||||
]);
|
||||
|
||||
$DB->insert_record('workshop_grades', [
|
||||
'assessmentid' => $this->assessment1112,
|
||||
'strategy' => 'numerrors',
|
||||
'dimensionid' => $this->dim1,
|
||||
'grade' => 1,
|
||||
'peercomment' => 'Awesome',
|
||||
'peercommentformat' => FORMAT_PLAIN,
|
||||
]);
|
||||
|
||||
$DB->insert_record('workshop_grades', [
|
||||
'assessmentid' => $this->assessment1112,
|
||||
'strategy' => 'numerrors',
|
||||
'dimensionid' => $this->dim2,
|
||||
'grade' => 0,
|
||||
'peercomment' => 'Missing',
|
||||
'peercommentformat' => FORMAT_PLAIN,
|
||||
]);
|
||||
|
||||
$contextlist = new \core_privacy\local\request\approved_contextlist($this->student2, 'mod_workshop', [
|
||||
\context_module::instance($this->workshop11->cmid)->id,
|
||||
]);
|
||||
|
||||
\mod_workshop\privacy\provider::export_user_data($contextlist);
|
||||
|
||||
$writer = writer::with_context(\context_module::instance($this->workshop11->cmid));
|
||||
|
||||
$form = $writer->get_data([
|
||||
get_string('myassessments', 'mod_workshop'),
|
||||
$this->assessment1112,
|
||||
get_string('assessmentform', 'mod_workshop'),
|
||||
get_string('pluginname', 'workshopform_numerrors'),
|
||||
]);
|
||||
|
||||
$this->assertEquals('Assertion 1 description', $form->assertions[0]->description);
|
||||
$this->assertEquals(0, $form->assertions[1]->grade);
|
||||
$this->assertEquals('Missing', $form->assertions[1]->peercomment);
|
||||
}
|
||||
}
|
127
mod/workshop/form/rubric/classes/privacy/provider.php
Normal file
127
mod/workshop/form/rubric/classes/privacy/provider.php
Normal file
@ -0,0 +1,127 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Provides the class {@link workshopform_rubric\privacy\provider}
|
||||
*
|
||||
* @package workshopform_rubric
|
||||
* @category privacy
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace workshopform_rubric\privacy;
|
||||
|
||||
use core_privacy\local\request\writer;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy API implementation for the Rubric strategy.
|
||||
*
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider, \mod_workshop\privacy\workshopform_provider {
|
||||
|
||||
/**
|
||||
* Explain that this plugin stores no personal data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return details of the filled assessment form.
|
||||
*
|
||||
* @param stdClass $user User we are exporting data for
|
||||
* @param context $context The workshop activity context
|
||||
* @param array $subcontext Subcontext within the context to export to
|
||||
* @param int $assessmentid ID of the assessment
|
||||
*/
|
||||
public static function export_assessment_form(\stdClass $user, \context $context, array $subcontext, int $assessmentid) {
|
||||
global $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
throw new \coding_exception('Unexpected context provided');
|
||||
}
|
||||
|
||||
$sql = "SELECT r.id, r.workshopid, r.description, r.descriptionformat,
|
||||
rl.id AS levelid, rl.grade AS levelgrade, rl.definition, rl.definitionformat,
|
||||
wg.grade
|
||||
FROM {course_modules} cm
|
||||
JOIN {context} ctx ON ctx.contextlevel = :contextlevel AND ctx.instanceid = cm.id
|
||||
JOIN {workshop} w ON cm.instance = w.id
|
||||
JOIN {workshopform_rubric} r ON r.workshopid = w.id
|
||||
JOIN {workshopform_rubric_levels} rl ON rl.dimensionid = r.id
|
||||
LEFT JOIN {workshop_grades} wg ON wg.strategy = :strategy AND wg.dimensionid = r.id AND wg.assessmentid = :assessmentid
|
||||
WHERE ctx.id = :contextid
|
||||
ORDER BY r.sort, rl.grade DESC";
|
||||
|
||||
$params = [
|
||||
'strategy' => 'rubric',
|
||||
'contextlevel' => CONTEXT_MODULE,
|
||||
'contextid' => $context->id,
|
||||
'assessmentid' => $assessmentid,
|
||||
];
|
||||
|
||||
$writer = \core_privacy\local\request\writer::with_context($context);
|
||||
$criteria = [];
|
||||
$workshopid = null;
|
||||
$hasdata = false;
|
||||
|
||||
$rs = $DB->get_recordset_sql($sql, $params);
|
||||
|
||||
foreach ($rs as $record) {
|
||||
if (empty($criteria[$record->id])) {
|
||||
$criteria[$record->id] = (object) [
|
||||
'description' => $writer->rewrite_pluginfile_urls($subcontext, 'workshopform_rubric', 'description',
|
||||
$record->id, $record->description),
|
||||
'descriptionformat' => $record->descriptionformat,
|
||||
'grade' => $record->grade,
|
||||
'levels' => [],
|
||||
];
|
||||
$workshopid = $record->workshopid;
|
||||
}
|
||||
$criteria[$record->id]->levels[] = (object) [
|
||||
'grade' => $record->levelgrade,
|
||||
'definition' => $record->definition,
|
||||
'definitionformat' => $record->definitionformat,
|
||||
];
|
||||
if ($record->grade !== null) {
|
||||
$hasdata = true;
|
||||
}
|
||||
}
|
||||
|
||||
$rs->close();
|
||||
|
||||
if ($hasdata) {
|
||||
$data = (object) [
|
||||
'criteria' => array_values($criteria),
|
||||
];
|
||||
$layout = $DB->get_field('workshopform_rubric_config', 'layout', ['workshopid' => $workshopid]);
|
||||
|
||||
foreach (array_keys($criteria) as $dimensionid) {
|
||||
$writer->export_area_files($subcontext, 'workshopform_rubric', 'description', $dimensionid);
|
||||
}
|
||||
|
||||
$writer->export_data($subcontext, $data);
|
||||
$writer->export_metadata($subcontext, 'layout', $layout, get_string('layout', 'workshopform_rubric'));
|
||||
}
|
||||
}
|
||||
}
|
@ -37,3 +37,4 @@ $string['mustbeunique'] = 'Level grades must be unique within a criterion';
|
||||
$string['mustdefinelevel'] = 'At least one level is required';
|
||||
$string['mustchooseone'] = 'You have to select one of these items';
|
||||
$string['pluginname'] = 'Rubric';
|
||||
$string['privacy:metadata'] = 'The Rubric plugin only stores the details of the assessment form. Actual personal data of how the form has been filled are stored by the Workshop module itself and are attached to exported assessments.';
|
||||
|
155
mod/workshop/form/rubric/tests/privacy_provider_test.php
Normal file
155
mod/workshop/form/rubric/tests/privacy_provider_test.php
Normal file
@ -0,0 +1,155 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Provides the {@link workshopform_rubric_privacy_provider_testcase} class.
|
||||
*
|
||||
* @package workshopform_rubric
|
||||
* @category test
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use core_privacy\local\request\writer;
|
||||
|
||||
/**
|
||||
* Unit tests for the privacy API implementation.
|
||||
*
|
||||
* @copyright 2018 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class workshopform_rubric_privacy_provider_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test {@link workshopform_rubric\privacy\provider::export_assessment_form()} implementation.
|
||||
*/
|
||||
public function test_export_assessment_form() {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$this->generator = $this->getDataGenerator();
|
||||
$this->workshopgenerator = $this->generator->get_plugin_generator('mod_workshop');
|
||||
|
||||
$this->course1 = $this->generator->create_course();
|
||||
|
||||
$this->workshop11 = $this->generator->create_module('workshop', [
|
||||
'course' => $this->course1,
|
||||
'name' => 'Workshop11',
|
||||
]);
|
||||
$DB->set_field('workshop', 'phase', 50, ['id' => $this->workshop11->id]);
|
||||
|
||||
$this->dim1 = $DB->insert_record('workshopform_rubric', [
|
||||
'workshopid' => $this->workshop11->id,
|
||||
'sort' => 1,
|
||||
'description' => 'Criterion 1 description',
|
||||
'descriptionformat' => FORMAT_MARKDOWN,
|
||||
]);
|
||||
|
||||
$DB->insert_record('workshopform_rubric_levels', [
|
||||
'dimensionid' => $this->dim1,
|
||||
'grade' => 0,
|
||||
'definition' => 'Missing',
|
||||
'definitionformat' => FORMAT_PLAIN,
|
||||
]);
|
||||
|
||||
$DB->insert_record('workshopform_rubric_levels', [
|
||||
'dimensionid' => $this->dim1,
|
||||
'grade' => 1,
|
||||
'definition' => 'Poor',
|
||||
'definitionformat' => FORMAT_PLAIN,
|
||||
]);
|
||||
|
||||
$DB->insert_record('workshopform_rubric_levels', [
|
||||
'dimensionid' => $this->dim1,
|
||||
'grade' => 2,
|
||||
'definition' => 'Good',
|
||||
'definitionformat' => FORMAT_PLAIN,
|
||||
]);
|
||||
|
||||
$this->dim2 = $DB->insert_record('workshopform_rubric', [
|
||||
'workshopid' => $this->workshop11->id,
|
||||
'sort' => 2,
|
||||
'description' => 'Criterion 2 description',
|
||||
'descriptionformat' => FORMAT_MARKDOWN,
|
||||
]);
|
||||
|
||||
$DB->insert_record('workshopform_rubric_levels', [
|
||||
'dimensionid' => $this->dim2,
|
||||
'grade' => 0,
|
||||
'definition' => 'Missing',
|
||||
'definitionformat' => FORMAT_PLAIN,
|
||||
]);
|
||||
|
||||
$DB->insert_record('workshopform_rubric_levels', [
|
||||
'dimensionid' => $this->dim2,
|
||||
'grade' => 5,
|
||||
'definition' => 'Great',
|
||||
'definitionformat' => FORMAT_PLAIN,
|
||||
]);
|
||||
|
||||
$this->student1 = $this->generator->create_user();
|
||||
$this->student2 = $this->generator->create_user();
|
||||
|
||||
$this->submission111 = $this->workshopgenerator->create_submission($this->workshop11->id, $this->student1->id);
|
||||
|
||||
$this->assessment1112 = $this->workshopgenerator->create_assessment($this->submission111, $this->student2->id, [
|
||||
'grade' => 92,
|
||||
]);
|
||||
|
||||
$DB->insert_record('workshop_grades', [
|
||||
'assessmentid' => $this->assessment1112,
|
||||
'strategy' => 'rubric',
|
||||
'dimensionid' => $this->dim1,
|
||||
'grade' => 1,
|
||||
'peercomment' => '',
|
||||
'peercommentformat' => FORMAT_PLAIN,
|
||||
]);
|
||||
|
||||
$DB->insert_record('workshop_grades', [
|
||||
'assessmentid' => $this->assessment1112,
|
||||
'strategy' => 'rubric',
|
||||
'dimensionid' => $this->dim2,
|
||||
'grade' => 5,
|
||||
'peercomment' => '',
|
||||
'peercommentformat' => FORMAT_PLAIN,
|
||||
]);
|
||||
|
||||
$contextlist = new \core_privacy\local\request\approved_contextlist($this->student2, 'mod_workshop', [
|
||||
\context_module::instance($this->workshop11->cmid)->id,
|
||||
]);
|
||||
|
||||
\mod_workshop\privacy\provider::export_user_data($contextlist);
|
||||
|
||||
$writer = writer::with_context(\context_module::instance($this->workshop11->cmid));
|
||||
|
||||
$form = $writer->get_data([
|
||||
get_string('myassessments', 'mod_workshop'),
|
||||
$this->assessment1112,
|
||||
get_string('assessmentform', 'mod_workshop'),
|
||||
get_string('pluginname', 'workshopform_rubric'),
|
||||
]);
|
||||
|
||||
$this->assertEquals('Criterion 1 description', $form->criteria[0]->description);
|
||||
$this->assertEquals(3, count($form->criteria[0]->levels));
|
||||
$this->assertEquals(2, count($form->criteria[1]->levels));
|
||||
$this->assertEquals(5, $form->criteria[1]->grade);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user