You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
516 lines
21 KiB
516 lines
21 KiB
<?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 tests for core_grading.
|
|
*
|
|
* @package core_grading
|
|
* @category test
|
|
* @copyright 2018 Sara Arjona <sara@moodle.com>
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
|
|
defined('MOODLE_INTERNAL') || die();
|
|
|
|
global $CFG;
|
|
require_once($CFG->dirroot . '/grade/grading/tests/fixtures/marking_guide.php');
|
|
|
|
use \core_privacy\tests\provider_testcase;
|
|
use \core_privacy\local\request\approved_contextlist;
|
|
use \core_privacy\local\request\transform;
|
|
use \core_privacy\local\request\writer;
|
|
use \core_grading\privacy\provider;
|
|
|
|
/**
|
|
* Privacy tests for core_grading.
|
|
*
|
|
* @copyright 2018 Sara Arjona <sara@moodle.com>
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
class core_grading_privacy_testcase extends provider_testcase {
|
|
|
|
/** @var stdClass User without data. */
|
|
protected $user0;
|
|
|
|
/** @var stdClass User with data. */
|
|
protected $user1;
|
|
|
|
/** @var stdClass User with data. */
|
|
protected $user2;
|
|
|
|
/** @var context context_module of an activity without grading definitions. */
|
|
protected $instancecontext0;
|
|
|
|
/** @var context context_module of the activity where the grading definitions are. */
|
|
protected $instancecontext1;
|
|
|
|
/** @var context context_module of the activity where the grading definitions are. */
|
|
protected $instancecontext2;
|
|
|
|
/**
|
|
* Test getting the context for the user ID related to this plugin.
|
|
*/
|
|
public function test_get_contexts_for_userid() {
|
|
global $DB;
|
|
|
|
$this->resetAfterTest();
|
|
$this->grading_setup_test_scenario_data();
|
|
$this->assertCount(2, $DB->get_records('grading_definitions'));
|
|
|
|
// User1 has created grading definitions for instance1 and instance2.
|
|
$contextlist = provider::get_contexts_for_userid($this->user1->id);
|
|
$this->assertCount(2, $contextlist);
|
|
$this->assertContains($this->instancecontext1->id, $contextlist->get_contextids());
|
|
$this->assertContains($this->instancecontext2->id, $contextlist->get_contextids());
|
|
$this->assertNotContains($this->instancecontext0->id, $contextlist->get_contextids());
|
|
|
|
// User2 has only modified grading definitions for instance2.
|
|
$contextlist = provider::get_contexts_for_userid($this->user2->id);
|
|
$this->assertCount(1, $contextlist);
|
|
$this->assertContains($this->instancecontext2->id, $contextlist->get_contextids());
|
|
|
|
// User0 hasn't created or modified any grading definition.
|
|
$contextlist = provider::get_contexts_for_userid($this->user0->id);
|
|
$this->assertCount(0, $contextlist);
|
|
}
|
|
|
|
/**
|
|
* Test retrieval of user ids in a given context.
|
|
*/
|
|
public function test_get_users_in_context() {
|
|
$this->resetAfterTest();
|
|
$this->grading_setup_test_scenario_data();
|
|
// Instance two has one user who created the definitions and another who modified it.
|
|
$userlist = new \core_privacy\local\request\userlist($this->instancecontext2, 'core_grading');
|
|
provider::get_users_in_context($userlist);
|
|
// Check that we get both.
|
|
$this->assertCount(2, $userlist->get_userids());
|
|
}
|
|
|
|
/**
|
|
* Export for a user with no grading definitions created or modified will not have any data exported.
|
|
*/
|
|
public function test_export_user_data_no_content() {
|
|
$this->resetAfterTest();
|
|
|
|
$user = $this->getDataGenerator()->create_user();
|
|
$this->setUser($user);
|
|
$context = \context_system::instance();
|
|
|
|
$writer = writer::with_context($context);
|
|
$this->assertFalse($writer->has_any_data());
|
|
$this->export_context_data_for_user($user->id, $context, 'core_grading');
|
|
$this->assertFalse(writer::with_context($context)->has_any_data());
|
|
}
|
|
|
|
/**
|
|
* Test that data is exported correctly for this plugin.
|
|
*/
|
|
public function test_export_user_data() {
|
|
global $DB;
|
|
|
|
$this->resetAfterTest();
|
|
$now = time();
|
|
$defnameprefix = 'fakename';
|
|
$this->grading_setup_test_scenario_data($defnameprefix, $now);
|
|
$this->assertCount(2, $DB->get_records('grading_definitions'));
|
|
|
|
// Validate exported data: instance1 - user0 has NO data.
|
|
$this->setUser($this->user0);
|
|
writer::reset();
|
|
$writer = writer::with_context($this->instancecontext1);
|
|
$this->assertFalse($writer->has_any_data());
|
|
$this->export_context_data_for_user($this->user0->id, $this->instancecontext1, 'core_grading');
|
|
$data = $writer->get_data([get_string('gradingmethod', 'grading')]);
|
|
$this->assertEmpty($data);
|
|
|
|
// Validate exported data: instance0 - user1 has NO data.
|
|
$this->setUser($this->user1);
|
|
writer::reset();
|
|
$writer = writer::with_context($this->instancecontext0);
|
|
$this->assertFalse($writer->has_any_data());
|
|
$this->export_context_data_for_user($this->user1->id, $this->instancecontext0, 'core_grading');
|
|
$data = $writer->get_data([get_string('gradingmethod', 'grading')]);
|
|
$this->assertEmpty($data);
|
|
|
|
// Validate exported data: instance1 - user1 has data (user has created and modified it).
|
|
writer::reset();
|
|
$writer = writer::with_context($this->instancecontext1);
|
|
$this->assertFalse($writer->has_any_data());
|
|
$this->export_context_data_for_user($this->user1->id, $this->instancecontext1, 'core_grading');
|
|
$data = $writer->get_data([get_string('gradingmethod', 'grading')]);
|
|
$this->assertCount(1, $data->definitions);
|
|
|
|
$firstkey = reset($data->definitions);
|
|
$this->assertNotEmpty($firstkey->name);
|
|
$this->assertEquals('test_method', $firstkey->method);
|
|
$this->assertEquals(transform::datetime($now), $firstkey->timecreated);
|
|
$this->assertEquals($this->user1->id, $firstkey->usercreated);
|
|
$this->assertEquals($defnameprefix.'1', $firstkey->name);
|
|
|
|
// Validate exported data: instance2 - user1 has data (user has created it).
|
|
writer::reset();
|
|
$writer = writer::with_context($this->instancecontext2);
|
|
$this->assertFalse($writer->has_any_data());
|
|
$this->export_context_data_for_user($this->user1->id, $this->instancecontext2, 'core_grading');
|
|
$data = $writer->get_data([get_string('gradingmethod', 'grading')]);
|
|
$this->assertCount(1, $data->definitions);
|
|
|
|
$firstkey = reset($data->definitions);
|
|
$this->assertNotEmpty($firstkey->name);
|
|
$this->assertEquals('test_method', $firstkey->method);
|
|
$this->assertEquals(transform::datetime($now), $firstkey->timecreated);
|
|
$this->assertEquals($this->user1->id, $firstkey->usercreated);
|
|
$this->assertEquals($defnameprefix.'2', $firstkey->name);
|
|
|
|
// Validate exported data: instance1 - user2 has NO data.
|
|
$this->setUser($this->user2);
|
|
writer::reset();
|
|
$writer = writer::with_context($this->instancecontext1);
|
|
$this->assertFalse($writer->has_any_data());
|
|
$this->export_context_data_for_user($this->user2->id, $this->instancecontext1, 'core_grading');
|
|
$data = $writer->get_data([get_string('gradingmethod', 'grading')]);
|
|
$this->assertEmpty($data);
|
|
|
|
// Validate exported data: instance2 - user2 has data (user has modified it).
|
|
$this->setUser($this->user2);
|
|
writer::reset();
|
|
$writer = writer::with_context($this->instancecontext2);
|
|
$this->assertFalse($writer->has_any_data());
|
|
$this->export_context_data_for_user($this->user2->id, $this->instancecontext2, 'core_grading');
|
|
$data = $writer->get_data([get_string('gradingmethod', 'grading')]);
|
|
$this->assertCount(1, $data->definitions);
|
|
}
|
|
|
|
/**
|
|
* Test for provider::delete_data_for_all_users_in_context().
|
|
*/
|
|
public function test_delete_data_for_all_users_in_context() {
|
|
global $DB;
|
|
|
|
$this->resetAfterTest();
|
|
$this->grading_setup_test_scenario_data();
|
|
|
|
// Before deletion, we should have 2 grading_definitions.
|
|
$this->assertCount(2, $DB->get_records('grading_definitions'));
|
|
|
|
// Delete data.
|
|
provider::delete_data_for_all_users_in_context($this->instancecontext0);
|
|
provider::delete_data_for_all_users_in_context($this->instancecontext1);
|
|
provider::delete_data_for_all_users_in_context($this->instancecontext2);
|
|
|
|
// Before deletion, we should have same grading_definitions (nothing was deleted).
|
|
$this->assertCount(2, $DB->get_records('grading_definitions'));
|
|
}
|
|
|
|
/**
|
|
* Test for provider::delete_data_for_user().
|
|
*/
|
|
public function test_delete_data_for_user() {
|
|
global $DB;
|
|
|
|
$this->resetAfterTest();
|
|
$this->grading_setup_test_scenario_data();
|
|
|
|
// Before deletion, we should have 2 grading_definitions.
|
|
$this->assertCount(2, $DB->get_records('grading_definitions'));
|
|
|
|
// Delete data for $user0.
|
|
$contextlist = provider::get_contexts_for_userid($this->user0->id);
|
|
$approvedcontextlist = new approved_contextlist(
|
|
$this->user0,
|
|
'core_grading',
|
|
$contextlist->get_contextids()
|
|
);
|
|
provider::delete_data_for_user($approvedcontextlist);
|
|
|
|
// Delete data for $user1.
|
|
$contextlist = provider::get_contexts_for_userid($this->user1->id);
|
|
$approvedcontextlist = new approved_contextlist(
|
|
$this->user1,
|
|
'core_grading',
|
|
$contextlist->get_contextids()
|
|
);
|
|
provider::delete_data_for_user($approvedcontextlist);
|
|
|
|
// Delete data for $user2.
|
|
$contextlist = provider::get_contexts_for_userid($this->user2->id);
|
|
$approvedcontextlist = new approved_contextlist(
|
|
$this->user2,
|
|
'core_grading',
|
|
$contextlist->get_contextids()
|
|
);
|
|
provider::delete_data_for_user($approvedcontextlist);
|
|
|
|
// Before deletion, we should have same grading_definitions (nothing was deleted).
|
|
$this->assertCount(2, $DB->get_records('grading_definitions'));
|
|
}
|
|
|
|
/**
|
|
* Test exporting user data relating to an item ID.
|
|
*/
|
|
public function test_export_item_data() {
|
|
global $DB;
|
|
$this->resetAfterTest();
|
|
$course = $this->getDataGenerator()->create_course();
|
|
$module = $this->getDataGenerator()->create_module('assign', ['course' => $course]);
|
|
$user = $this->getDataGenerator()->create_user();
|
|
|
|
$this->setUser($user);
|
|
|
|
$modulecontext = context_module::instance($module->cmid);
|
|
$guide = new test_guide($modulecontext, 'testrubrib', 'Description text');
|
|
$guide->add_criteria(
|
|
'Spelling mistakes',
|
|
'Full marks will be given for no spelling mistakes.',
|
|
'Deduct 5 points per spelling mistake made.',
|
|
25
|
|
);
|
|
$guide->add_criteria(
|
|
'Pictures',
|
|
'Full marks will be given for including 3 pictures.',
|
|
'Give 5 points for each picture present',
|
|
15
|
|
);
|
|
$guide->create_guide();
|
|
|
|
// In the situation of mod_assign this would be the id from assign_grades.
|
|
$itemid = 1;
|
|
$gradedata = [
|
|
['remark' => 'This user made several mistakes.', 'score' => 5],
|
|
['remark' => 'This user has two pictures.', 'score' => 10]
|
|
];
|
|
$instance = $guide->grade_item($user->id, $itemid, $gradedata);
|
|
|
|
provider::export_item_data($modulecontext, $itemid, ['Test']);
|
|
$data = (array) writer::with_context($modulecontext)->get_data(['Test', 'Marking guide', $instance->get_data('id')]);
|
|
$this->assertCount(2, $data);
|
|
$this->assertEquals('This user made several mistakes.', $data['Spelling mistakes']->remark);
|
|
$this->assertEquals(5, $data['Spelling mistakes']->score);
|
|
$this->assertEquals('This user has two pictures.', $data['Pictures']->remark);
|
|
$this->assertEquals(10, $data['Pictures']->score);
|
|
}
|
|
|
|
/**
|
|
* Test deleting user data related to a context and item ID.
|
|
*/
|
|
public function test_delete_instance_data() {
|
|
global $DB;
|
|
$this->resetAfterTest();
|
|
$course = $this->getDataGenerator()->create_course();
|
|
$module = $this->getDataGenerator()->create_module('assign', ['course' => $course]);
|
|
$user = $this->getDataGenerator()->create_user();
|
|
|
|
$this->setUser($user);
|
|
|
|
$modulecontext = context_module::instance($module->cmid);
|
|
$guide = new test_guide($modulecontext, 'testrubrib', 'Description text');
|
|
$guide->add_criteria(
|
|
'Spelling mistakes',
|
|
'Full marks will be given for no spelling mistakes.',
|
|
'Deduct 5 points per spelling mistake made.',
|
|
25
|
|
);
|
|
$guide->add_criteria(
|
|
'Pictures',
|
|
'Full marks will be given for including 3 pictures.',
|
|
'Give 5 points for each picture present',
|
|
15
|
|
);
|
|
$guide->create_guide();
|
|
|
|
// In the situation of mod_assign this would be the id from assign_grades.
|
|
$itemid = 1;
|
|
$gradedata = [
|
|
['remark' => 'This user made several mistakes.', 'score' => 5],
|
|
['remark' => 'This user has two pictures.', 'score' => 10]
|
|
];
|
|
$instance = $guide->grade_item($user->id, $itemid, $gradedata);
|
|
|
|
$itemid = 2;
|
|
$gradedata = [
|
|
['remark' => 'This user made no mistakes.', 'score' => 25],
|
|
['remark' => 'This user has one picture.', 'score' => 5]
|
|
];
|
|
$instance = $guide->grade_item($user->id, $itemid, $gradedata);
|
|
|
|
// Check how many records we have in the fillings table.
|
|
$records = $DB->get_records('gradingform_guide_fillings');
|
|
$this->assertCount(4, $records);
|
|
// Let's delete one of the instances (the last one would be the easiest).
|
|
provider::delete_instance_data($modulecontext, $itemid);
|
|
$records = $DB->get_records('gradingform_guide_fillings');
|
|
$this->assertCount(2, $records);
|
|
foreach ($records as $record) {
|
|
$this->assertNotEquals($instance->get_id(), $record->instanceid);
|
|
}
|
|
// This will delete all the rest of the instances for this context.
|
|
provider::delete_instance_data($modulecontext);
|
|
$records = $DB->get_records('gradingform_guide_fillings');
|
|
$this->assertEmpty($records);
|
|
}
|
|
|
|
/**
|
|
* Test the deletion of multiple instances at once.
|
|
*/
|
|
public function test_delete_data_for_instances() {
|
|
global $DB;
|
|
$this->resetAfterTest();
|
|
$course = $this->getDataGenerator()->create_course();
|
|
$module = $this->getDataGenerator()->create_module('assign', ['course' => $course]);
|
|
$user1 = $this->getDataGenerator()->create_user();
|
|
$user2 = $this->getDataGenerator()->create_user();
|
|
$user3 = $this->getDataGenerator()->create_user();
|
|
|
|
$this->setUser($user1);
|
|
|
|
$modulecontext = context_module::instance($module->cmid);
|
|
$guide = new test_guide($modulecontext, 'testrubrib', 'Description text');
|
|
$guide->add_criteria(
|
|
'Spelling mistakes',
|
|
'Full marks will be given for no spelling mistakes.',
|
|
'Deduct 5 points per spelling mistake made.',
|
|
25
|
|
);
|
|
$guide->add_criteria(
|
|
'Pictures',
|
|
'Full marks will be given for including 3 pictures.',
|
|
'Give 5 points for each picture present',
|
|
15
|
|
);
|
|
$guide->create_guide();
|
|
|
|
// In the situation of mod_assign this would be the id from assign_grades.
|
|
$itemid1 = 1;
|
|
$gradedata = [
|
|
['remark' => 'This user made several mistakes.', 'score' => 5],
|
|
['remark' => 'This user has two pictures.', 'score' => 10]
|
|
];
|
|
$instance1 = $guide->grade_item($user1->id, $itemid1, $gradedata);
|
|
|
|
$itemid2 = 2;
|
|
$gradedata = [
|
|
['remark' => 'This user made a couple of mistakes.', 'score' => 15],
|
|
['remark' => 'This user has one picture.', 'score' => 10]
|
|
];
|
|
$instance2 = $guide->grade_item($user2->id, $itemid2, $gradedata);
|
|
|
|
$itemid3 = 3;
|
|
$gradedata = [
|
|
['remark' => 'This user made one mistakes.', 'score' => 20],
|
|
['remark' => 'This user has one picture.', 'score' => 10]
|
|
];
|
|
$instance3 = $guide->grade_item($user3->id, $itemid3, $gradedata);
|
|
|
|
$records = $DB->get_records('gradingform_guide_fillings');
|
|
$this->assertCount(6, $records);
|
|
|
|
// Delete all user data for items 1 and 3.
|
|
provider::delete_data_for_instances($modulecontext, [$itemid1, $itemid3]);
|
|
$records = $DB->get_records('gradingform_guide_fillings');
|
|
$this->assertCount(2, $records);
|
|
$instanceid = $instance2->get_data('id');
|
|
// The instance id should match for all remaining records.
|
|
foreach ($records as $record) {
|
|
$this->assertEquals($instanceid, $record->instanceid);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to setup the environment.
|
|
*
|
|
* course
|
|
* |
|
|
* +--instance0 (assignment)
|
|
* | |
|
|
* +--instance1 (assignment)
|
|
* | |
|
|
* | +--grading_definition1 (created and modified by user1)
|
|
* | |
|
|
* +--instance2 (assignment)
|
|
* | |
|
|
* | +--grading_definition2 (created by user1 and modified by user2)
|
|
*
|
|
*
|
|
* user0 hasn't any data.
|
|
*
|
|
* @param string $defnameprefix
|
|
* @param timestamp $now
|
|
*/
|
|
protected function grading_setup_test_scenario_data($defnameprefix = null, $now = null) {
|
|
global $DB;
|
|
|
|
$this->user0 = $this->getDataGenerator()->create_user();
|
|
$this->user1 = $this->getDataGenerator()->create_user();
|
|
$this->user2 = $this->getDataGenerator()->create_user();
|
|
|
|
// Create a course.
|
|
$course = $this->getDataGenerator()->create_course();
|
|
$coursecontext = context_course::instance($course->id);
|
|
|
|
// Create some assignment instances.
|
|
$params = (object)array(
|
|
'course' => $course->id,
|
|
'name' => 'Testing instance'
|
|
);
|
|
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
|
|
$instance0 = $generator->create_instance($params);
|
|
$cm0 = get_coursemodule_from_instance('assign', $instance0->id);
|
|
$this->instancecontext0 = context_module::instance($cm0->id);
|
|
$instance1 = $generator->create_instance($params);
|
|
$cm1 = get_coursemodule_from_instance('assign', $instance1->id);
|
|
$this->instancecontext1 = context_module::instance($cm1->id);
|
|
$instance2 = $generator->create_instance($params);
|
|
$cm2 = get_coursemodule_from_instance('assign', $instance2->id);
|
|
$this->instancecontext2 = context_module::instance($cm2->id);
|
|
|
|
// Create fake grading areas.
|
|
$fakearea1 = (object)array(
|
|
'contextid' => $this->instancecontext1->id,
|
|
'component' => 'mod_assign',
|
|
'areaname' => 'submissions',
|
|
'activemethod' => 'test_method'
|
|
);
|
|
$fakeareaid1 = $DB->insert_record('grading_areas', $fakearea1);
|
|
$fakearea2 = clone($fakearea1);
|
|
$fakearea2->contextid = $this->instancecontext2->id;
|
|
$fakeareaid2 = $DB->insert_record('grading_areas', $fakearea2);
|
|
|
|
// Create fake grading definitions.
|
|
if (empty($now)) {
|
|
$now = time();
|
|
}
|
|
if (empty($defnameprefix)) {
|
|
$defnameprefix = 'fakename';
|
|
}
|
|
$fakedefinition1 = (object)array(
|
|
'areaid' => $fakeareaid1,
|
|
'method' => 'test_method',
|
|
'name' => $defnameprefix.'1',
|
|
'status' => 0,
|
|
'timecreated' => $now,
|
|
'usercreated' => $this->user1->id,
|
|
'timemodified' => $now + 1,
|
|
'usermodified' => $this->user1->id,
|
|
);
|
|
$fakedefid1 = $DB->insert_record('grading_definitions', $fakedefinition1);
|
|
$fakedefinition2 = clone($fakedefinition1);
|
|
$fakedefinition2->areaid = $fakeareaid2;
|
|
$fakedefinition2->name = $defnameprefix.'2';
|
|
$fakedefinition2->usermodified = $this->user2->id;
|
|
$fakedefid2 = $DB->insert_record('grading_definitions', $fakedefinition2);
|
|
}
|
|
}
|
|
|