Skip to content

Commit

Permalink
Merge branch 'MDL-56653-39' of git://github.com/lameze/moodle into MO…
Browse files Browse the repository at this point in the history
…ODLE_39_STABLE
  • Loading branch information
abgreeve committed Nov 19, 2020
2 parents f66c4fa + 12d4c82 commit 662d208
Show file tree
Hide file tree
Showing 2 changed files with 174 additions and 18 deletions.
50 changes: 32 additions & 18 deletions enrol/meta/lib.php
Expand Up @@ -328,31 +328,45 @@ public function edit_instance_form($instance, MoodleQuickForm $mform, $coursecon
*/
public function edit_instance_validation($data, $files, $instance, $context) {
global $DB;

$errors = array();
$thiscourseid = $context->instanceid;
$c = false;

if (!empty($data['customint1'])) {
$courses = is_array($data['customint1']) ? $data['customint1'] : [$data['customint1']];
foreach ($courses as $courseid) {
$c = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
$coursecontext = context_course::instance($c->id);

$sqlexists = 'enrol = :meta AND courseid = :currentcourseid AND customint1 = :courseid AND id != :id';
$existing = $DB->record_exists_select('enrol', $sqlexists, [
$coursesidarr = is_array($data['customint1']) ? $data['customint1'] : [$data['customint1']];
list($coursesinsql, $coursesinparams) = $DB->get_in_or_equal($coursesidarr, SQL_PARAMS_NAMED, 'metacourseid');
if ($coursesrecords = $DB->get_records_select('course', "id {$coursesinsql}",
$coursesinparams, '', 'id,visible')) {
// Cast NULL to 0 to avoid possible mess with the SQL.
$instanceid = $instance->id ?? 0;

$existssql = "enrol = :meta AND courseid = :currentcourseid AND id != :id AND customint1 {$coursesinsql}";
$existsparams = [
'meta' => 'meta',
'currentcourseid' => $thiscourseid,
'courseid' => $c->id,
'id' => $instance->id
]);

if (!$c->visible and !has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
$errors['customint1'] = get_string('error');
} else if (!has_capability('enrol/meta:selectaslinked', $coursecontext)) {
$errors['customint1'] = get_string('error');
} else if ($c->id == SITEID or $c->id == $thiscourseid or $existing) {
$errors['customint1'] = get_string('error');
'id' => $instanceid
];
$existsparams += $coursesinparams;
if ($DB->record_exists_select('enrol', $existssql, $existsparams)) {
// We may leave right here as further checks do not make sense in case we have existing enrol records
// with the parameters from above.
$errors['customint1'] = get_string('invalidcourseid', 'error');
} else {
foreach ($coursesrecords as $coursesrecord) {
$coursecontext = context_course::instance($coursesrecord->id);
if (!$coursesrecord->visible and !has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
$errors['customint1'] = get_string('nopermissions', 'error',
'moodle/course:viewhiddencourses');
} else if (!has_capability('enrol/meta:selectaslinked', $coursecontext)) {
$errors['customint1'] = get_string('nopermissions', 'error',
'enrol/meta:selectaslinked');
} else if ($coursesrecord->id == SITEID or $coursesrecord->id == $thiscourseid) {
$errors['customint1'] = get_string('invalidcourseid', 'error');
}
}
}
} else {
$errors['customint1'] = get_string('invalidcourseid', 'error');
}
} else {
$errors['customint1'] = get_string('required');
Expand Down
142 changes: 142 additions & 0 deletions enrol/meta/tests/plugin_test.php
Expand Up @@ -922,4 +922,146 @@ public function test_get_user_enrolment_actions() {
// Meta-link enrolment has enrol actions for suspended students -- unenrol.
$this->assertCount(1, $actions);
}

/**
* Test how data for instance editing is validated.
*/
public function test_edit_instance_validation() {
global $DB;

$this->resetAfterTest();

$metaplugin = enrol_get_plugin('meta');

// A course with meta enrolment.
$course = $this->getDataGenerator()->create_course();
$coursecontext = context_course::instance($course->id);

// Create a meta enrolment instance.
$instance = (object)$metaplugin->get_instance_defaults();
$instance->id = null;
$instance->courseid = $course->id;
$instance->status = ENROL_INSTANCE_ENABLED;
// Emulate the form data.
$data = [
'customint1' => 0,
'customint2' => 0
];
// Test when no valid 'customint1' field (meta courses links) is provided.
$errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
// We're going to check the string contents of the errors returned as this is the only way
// to differentiate the errors produced by the 'edit_instance_validation()' method somehow.
// The method always returns what the edit instance form expects and this is an array of form fields
// with the corresponding errors messages.
$this->assertEquals('Required', $errors['customint1']);

// Test when 'customint1' contains an unknown course.
// Fetch the max course id from the courses table and increment it to get
// the course id which surely doesn't exist.
$maxid = $DB->get_field_sql('SELECT MAX(id) FROM {course}');
// Use the same instance as before but set another data.
$data = [
'customint1' => [$maxid + 1],
'customint2' => 0
];
$errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
$this->assertEquals('You are trying to use an invalid course ID', $errors['customint1']);

// Test when 'customint1' field already contains courses meta linked with the current one.
$metacourse1 = $this->getDataGenerator()->create_course();
$metaplugin->add_instance($course, array('customint1' => $metacourse1->id));
// Use the same instance as before but set another data.
$data = [
'customint1' => [$metacourse1->id],
'customint2' => 0
];
$errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
$this->assertEquals('You are trying to use an invalid course ID', $errors['customint1']);

// Test when a course is set as a not visible and a user doesn't have the capability to use it here.
$metacourse2record = new stdClass();
$metacourse2record->visible = 0;
$metacourse2 = $this->getDataGenerator()->create_course($metacourse2record);
$metacourse2context = context_course::instance($metacourse2->id);

$user = $this->getDataGenerator()->create_user();
$teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
role_assign($teacherrole->id, $user->id, $metacourse2context->id);
unassign_capability('moodle/course:viewhiddencourses', $teacherrole->id);
$this->setUser($user);

// Use the same instance as before but set another data.
$data = [
'customint1' => [$metacourse2->id],
'customint2' => 0
];
$errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
$this->assertEquals('Sorry, but you do not currently have permissions to do that (moodle/course:viewhiddencourses).',
$errors['customint1']);

// Revert some changes from the last assertion to reuse the course.
$metacourse2->visible = 1;
$DB->update_record('course', $metacourse2);
assign_capability('moodle/course:viewhiddencourses', CAP_ALLOW,
$teacherrole->id, context_course::instance($metacourse2->id));

// Test with no 'enrol/meta:selectaslinked' capability.
unassign_capability('enrol/meta:selectaslinked', $teacherrole->id);
$errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
$this->assertEquals('Sorry, but you do not currently have permissions to do that (enrol/meta:selectaslinked).',
$errors['customint1']);

// Back to admin user to regain the capabilities quickly.
$this->setAdminUser();

// Test when meta course id is the site id.
$site = $DB->get_record('course', ['id' => SITEID]);
// Use the same instance as before but set another data.
$data = [
'customint1' => [$site->id],
'customint2' => 0
];
$errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
$this->assertEquals('You are trying to use an invalid course ID', $errors['customint1']);

// Test when meta course id is id of the current course.
// Use the same instance as before but set another data.
$data = [
'customint1' => [$course->id],
'customint2' => 0
];
$errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
$this->assertEquals('You are trying to use an invalid course ID', $errors['customint1']);

// Test with the 'customint2' field set (which is groups).
// Prepare some groups data.
$this->getDataGenerator()->create_group(array('courseid' => $course->id));
$this->getDataGenerator()->create_group(array('courseid' => $course->id));
$groups = [];
foreach (groups_get_all_groups($course->id) as $group) {
$groups[$group->id] = format_string($group->name, true, array('context' => $coursecontext));
}

// Use the same instance as before but set another data.
// Use a non-existing group id.
if (!$maxid = $DB->get_field_sql('SELECT MAX(id) FROM {groups}')) {
$maxid = 0;
}
$data = [
'customint1' => [$metacourse2->id],
'customint2' => [$maxid + 1]
];
$errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
$this->assertArrayHasKey('customint2', $errors);

// Test with valid data.
$validgroup = reset($groups);
$data = [
'customint1' => [$metacourse2->id],
'customint2' => $validgroup
];
$errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
$this->assertArrayNotHasKey('customint1', $errors);
$this->assertArrayNotHasKey('customint2', $errors);
}
}

0 comments on commit 662d208

Please sign in to comment.