MDL-17929 enrol_meta: synchronise with groups

This commit is contained in:
Marina Glancy
2015-04-22 14:36:34 +08:00
parent 98177a4510
commit 9e37d365d8
4 changed files with 291 additions and 48 deletions
+78
View File
@@ -170,4 +170,82 @@ class enrol_meta_plugin extends enrol_plugin {
$context = context_course::instance($instance->courseid);
return has_capability('enrol/meta:config', $context);
}
/**
* Restore instance and map settings.
*
* @param restore_enrolments_structure_step $step
* @param stdClass $data
* @param stdClass $course
* @param int $oldid
*/
public function restore_instance(restore_enrolments_structure_step $step, stdClass $data, $course, $oldid) {
global $DB, $CFG;
if (!$step->get_task()->is_samesite()) {
// No meta restore from other sites.
$step->set_mapping('enrol', $oldid, 0);
return;
}
if (!empty($data->customint2)) {
$data->customint2 = $step->get_mappingid('group', $data->customint2);
}
if ($DB->record_exists('course', array('id' => $data->customint1))) {
$instance = $DB->get_record('enrol', array('roleid' => $data->roleid, 'customint1' => $data->customint1,
'courseid' => $course->id, 'enrol' => $this->get_name()));
if ($instance) {
$instanceid = $instance->id;
} else {
$instanceid = $this->add_instance($course, (array)$data);
}
$step->set_mapping('enrol', $oldid, $instanceid);
require_once("$CFG->dirroot/enrol/meta/locallib.php");
enrol_meta_sync($data->customint1);
} else {
$step->set_mapping('enrol', $oldid, 0);
}
}
/**
* Restore user enrolment.
*
* @param restore_enrolments_structure_step $step
* @param stdClass $data
* @param stdClass $instance
* @param int $userid
* @param int $oldinstancestatus
*/
public function restore_user_enrolment(restore_enrolments_structure_step $step, $data, $instance, $userid, $oldinstancestatus) {
global $DB;
if ($this->get_config('unenrolaction') != ENROL_EXT_REMOVED_SUSPENDNOROLES) {
// Enrolments were already synchronised in restore_instance(), we do not want any suspended leftovers.
return;
}
// ENROL_EXT_REMOVED_SUSPENDNOROLES means all previous enrolments are restored
// but without roles and suspended.
if (!$DB->record_exists('user_enrolments', array('enrolid' => $instance->id, 'userid' => $userid))) {
$this->enrol_user($instance, $userid, null, $data->timestart, $data->timeend, ENROL_USER_SUSPENDED);
if ($instance->customint2) {
groups_add_member($instance->customint2, $userid, 'enrol_meta', $instance->id);
}
}
}
/**
* Restore user group membership.
* @param stdClass $instance
* @param int $groupid
* @param int $userid
*/
public function restore_group_member($instance, $groupid, $userid) {
// Nothing to do here, the group members are added in $this->restore_group_restored().
return;
}
}
+12 -9
View File
@@ -150,13 +150,11 @@ class enrol_meta_handler {
}
}
// enrol user if not enrolled yet or fix status
if ($ue) {
if ($parentstatus != $ue->status) {
$plugin->update_user_enrol($instance, $userid, $parentstatus);
$ue->status = $parentstatus;
groups_add_member($instance->customint2, $userid, 'enrol_meta', $instance->courseid);
}
} else {
$plugin->enrol_user($instance, $userid, NULL, 0, 0, $parentstatus);
@@ -164,7 +162,9 @@ class enrol_meta_handler {
$ue->userid = $userid;
$ue->enrolid = $instance->id;
$ue->status = $parentstatus;
groups_add_member($instance->customint2, $userid, 'enrol_meta', $instance->courseid);
if ($instance->customint2) {
groups_add_member($instance->customint2, $userid, 'enrol_meta', $instance->id);
}
}
$unenrolaction = $plugin->get_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
@@ -174,7 +174,6 @@ class enrol_meta_handler {
if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND) {
// Always keep the roles.
} else if ($roles) {
groups_remove_member($instance->customint2, $userid);
role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id, 'component'=>'enrol_meta', 'itemid'=>$instance->id));
}
return;
@@ -184,7 +183,6 @@ class enrol_meta_handler {
foreach ($parentroles as $rid) {
if (!isset($roles[$rid])) {
role_assign($rid, $userid, $context->id, 'enrol_meta', $instance->id);
groups_add_member($instance->customint2, $userid, 'enrol_meta', $instance->courseid);
}
}
@@ -232,8 +230,6 @@ class enrol_meta_handler {
if ($ue->status != ENROL_USER_SUSPENDED) {
$plugin->update_user_enrol($instance, $userid, ENROL_USER_SUSPENDED);
}
// Remove from metagroup.
groups_remove_member($instance->customint2, $userid);
role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id, 'component'=>'enrol_meta', 'itemid'=>$instance->id));
} else {
@@ -318,6 +314,9 @@ function enrol_meta_sync($courseid = NULL, $verbose = false) {
}
$meta->enrol_user($instance, $ue->userid, $ue->status);
if ($instance->customint2) {
groups_add_member($instance->customint2, $ue->userid, 'enrol_meta', $instance->id);
}
if ($verbose) {
mtrace(" enrolling: $ue->userid ==> $instance->courseid");
}
@@ -568,7 +567,9 @@ function enrol_meta_sync($courseid = NULL, $verbose = false) {
$rs = $DB->get_recordset_sql($sql, $params);
foreach ($rs as $gm) {
groups_remove_member($gm->groupid, $gm->userid);
mtrace("removing user from group: $gm->userid ==> $gm->courseid - $gm->groupname", 1);
if ($verbose) {
mtrace("removing user from group: $gm->userid ==> $gm->courseid - $gm->groupname", 1);
}
}
$rs->close();
@@ -586,7 +587,9 @@ function enrol_meta_sync($courseid = NULL, $verbose = false) {
$rs = $DB->get_recordset_sql($sql, $params);
foreach ($rs as $ue) {
groups_add_member($ue->groupid, $ue->userid, 'enrol_meta', $ue->enrolid);
mtrace("adding user to group: $ue->userid ==> $ue->courseid - $ue->groupname", 1);
if ($verbose) {
mtrace("adding user to group: $ue->userid ==> $ue->courseid - $ue->groupname", 1);
}
}
$rs->close();
+107
View File
@@ -0,0 +1,107 @@
@enrol @enrol_meta
Feature: Enrolments are synchronised with meta courses
In order to simplify enrolments in parent courses
As a teacher
I need to be able to set up meta enrolments
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@asd.com |
| student2 | Student | 2 | student2@asd.com |
| student3 | Student | 3 | student3@asd.com |
| student4 | Student | 4 | student4@asd.com |
And the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
| Course 2 | C2 |
| Course 3 | C3 |
And the following "groups" exist:
| name | course | idnumber |
| Groupcourse 1 | C3 | G1 |
| Groupcourse 2 | C3 | G2 |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
| student2 | C1 | student |
| student3 | C1 | student |
| student4 | C1 | student |
| student1 | C2 | student |
| student2 | C2 | student |
And I log in as "admin"
And I navigate to "Manage enrol plugins" node in "Site administration > Plugins > Enrolments"
And I click on "Enable" "link" in the "Course meta link" "table_row"
And I am on homepage
And I follow "Courses"
@javascript
Scenario: Add meta enrolment instance without groups
When I follow "Course 3"
And I add "Course meta link" enrolment method with:
| Link course | Course 1 |
And I navigate to "Enrolled users" node in "Course administration > Users"
Then I should see "Student 1"
And I should see "Student 4"
And I should not see "Groupcourse" in the "table.userenrolment" "css_element"
@javascript
Scenario: Add meta enrolment instance with groups
When I follow "Course 3"
And I navigate to "Enrolment methods" node in "Course administration > Users"
And I set the field "Add method" to "Course meta link"
And I wait to be redirected
And I set the following fields to these values:
| Link course | Course 1 |
| Add to group | Groupcourse 1 |
And I press "Add method and create another"
And I set the following fields to these values:
| Link course | Course 2 |
| Add to group | Groupcourse 2 |
And I press "Add method"
And I navigate to "Enrolled users" node in "Course administration > Users"
Then I should see "Groupcourse 1" in the "Student 1" "table_row"
And I should see "Groupcourse 1" in the "Student 2" "table_row"
And I should see "Groupcourse 1" in the "Student 3" "table_row"
And I should see "Groupcourse 1" in the "Student 4" "table_row"
And I should see "Groupcourse 2" in the "Student 1" "table_row"
And I should see "Groupcourse 2" in the "Student 2" "table_row"
And I should not see "Groupcourse 2" in the "Student 3" "table_row"
And I should not see "Groupcourse 2" in the "Student 4" "table_row"
@javascript
Scenario: Backup and restore of meta enrolment instance
When I follow "Course 3"
And I navigate to "Enrolment methods" node in "Course administration > Users"
And I set the field "Add method" to "Course meta link"
And I wait to be redirected
And I set the following fields to these values:
| Link course | Course 1 |
| Add to group | Groupcourse 1 |
And I press "Add method and create another"
And I set the following fields to these values:
| Link course | Course 2 |
And I press "Add method"
When I backup "Course 3" course using this options:
| Confirmation | Filename | test_backup.mbz |
And I click on "Restore" "link" in the "test_backup.mbz" "table_row"
And I press "Continue"
And I set the field "targetid" to "1"
And I click on "Continue" "button" in the ".bcs-new-course" "css_element"
And I press "Next"
And I set the field "Course name" to "Course 4"
And I press "Next"
And I press "Perform restore"
And I trigger cron
And I am on homepage
And I follow "Courses"
And I follow "Course 4"
And I navigate to "Enrolment methods" node in "Course administration > Users"
Then I should see "Course meta link (Course 1)"
And I should see "Course meta link (Course 2)"
And I navigate to "Enrolled users" node in "Course administration > Users"
And I should see "Groupcourse 1" in the "Student 1" "table_row"
And I should see "Groupcourse 1" in the "Student 2" "table_row"
And I should see "Groupcourse 1" in the "Student 3" "table_row"
And I should see "Groupcourse 1" in the "Student 4" "table_row"
And I should see "Course 2" in the "Student 1" "table_row"
And I should not see "Course 2" in the "Student 3" "table_row"
+94 -39
View File
@@ -100,13 +100,6 @@ class enrol_meta_plugin_testcase extends advanced_testcase {
$teacher = $DB->get_record('role', array('shortname'=>'teacher'));
$manager = $DB->get_record('role', array('shortname'=>'manager'));
$id = groups_create_group((object)array('name'=>'Group 1', 'courseid'=>$course1->id));
$group1 = $DB->get_record('groups', array('id'=>$id), '*', MUST_EXIST);
$id = groups_create_group((object)array('name'=>'Group 2', 'courseid'=>$course1->id));
$group2 = $DB->get_record('groups', array('id'=>$id), '*', MUST_EXIST);
$id = groups_create_group((object)array('name'=>'Group 3', 'courseid'=>$course2->id));
$group3 = $DB->get_record('groups', array('id'=>$id), '*', MUST_EXIST);
$this->disable_plugin();
$this->getDataGenerator()->enrol_user($user1->id, $course1->id, $student->id);
@@ -135,14 +128,12 @@ class enrol_meta_plugin_testcase extends advanced_testcase {
$this->assertEquals(7, $DB->count_records('user_enrolments'));
$this->assertEquals(6, $DB->count_records('role_assignments'));
$e1 = $metalplugin->add_instance($course3, array('customint1'=>$course1->id, 'customint2'=>$group1->id));
$e2 = $metalplugin->add_instance($course3, array('customint1'=>$course2->id, 'customint2'=>$group2->id));
$e1 = $metalplugin->add_instance($course3, array('customint1'=>$course1->id));
$e2 = $metalplugin->add_instance($course3, array('customint1'=>$course2->id));
$e3 = $metalplugin->add_instance($course4, array('customint1'=>$course2->id));
$e4 = $metalplugin->add_instance($course4, array('customint1'=>$course2->id, 'customint2'=>$group3->id));
$enrol1 = $DB->get_record('enrol', array('id'=>$e1));
$enrol2 = $DB->get_record('enrol', array('id'=>$e2));
$enrol3 = $DB->get_record('enrol', array('id'=>$e3));
$enrol4 = $DB->get_record('enrol', array('id'=>$e3));
enrol_meta_sync($course4->id, false);
$this->assertEquals(9, $DB->count_records('user_enrolments'));
@@ -185,34 +176,6 @@ class enrol_meta_plugin_testcase extends advanced_testcase {
$this->enable_plugin();
$this->assertTrue(is_enrolled(context_course::instance($course1->id), $user4));
$this->assertTrue(groups_add_member($group1, $user4));
$this->assertTrue(groups_add_member($group2, $user4));
$this->assertFalse(groups_is_member($group1->id, $user1->id));
groups_add_member($group1->id, $user1->id);
$this->assertTrue(groups_is_member($group1->id, $user1->id));
$this->assertTrue($DB->record_exists('groups_members', array('groupid'=>$group1->id, 'userid'=>$user1->id, 'component'=>'enrol_cohort', 'itemid'=>$cohortinstance1->id)));
groups_add_member($group1->id, $user4->id);
$this->assertTrue(groups_is_member($group1->id, $user4->id));
$this->assertFalse($DB->record_exists('groups_members', array('groupid'=>$group1->id, 'userid'=>$user4->id, 'component'=>'enrol_cohort', 'itemid'=>$cohortinstance1->id)));
set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL, 'enrol_meta');
groups_remove_member($group1->id, $user1->id);
$this->assertFalse(groups_is_member($group1->id, $user1->id));
groups_remove_member($group1->id, $user4->id);
$this->assertTrue(groups_is_member($group1->id, $user4->id));
$this->assertTrue(groups_is_member($group2->id, $user4->id));
set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES, 'enrol_meta');
groups_add_member($group1->id, $user1->id);
groups_remove_member($group1->id, $user1->id);
$this->assertTrue(groups_is_member($group1->id, $user1->id));
set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPEND, 'enrol_meta');
enrol_meta_sync($course4->id, false);
$this->assertEquals(14, $DB->count_records('user_enrolments'));
@@ -477,6 +440,98 @@ class enrol_meta_plugin_testcase extends advanced_testcase {
}
public function test_add_to_group() {
global $CFG, $DB;
require_once($CFG->dirroot.'/group/lib.php');
$this->resetAfterTest(true);
$metalplugin = enrol_get_plugin('meta');
$user1 = $this->getDataGenerator()->create_user();
$user4 = $this->getDataGenerator()->create_user();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$course3 = $this->getDataGenerator()->create_course();
$manualenrol1 = $DB->get_record('enrol', array('courseid' => $course1->id, 'enrol' => 'manual'), '*', MUST_EXIST);
$manualenrol2 = $DB->get_record('enrol', array('courseid' => $course2->id, 'enrol' => 'manual'), '*', MUST_EXIST);
$student = $DB->get_record('role', array('shortname' => 'student'));
$teacher = $DB->get_record('role', array('shortname' => 'teacher'));
$id = groups_create_group((object)array('name' => 'Group 1 in course 3', 'courseid' => $course3->id));
$group31 = $DB->get_record('groups', array('id' => $id), '*', MUST_EXIST);
$id = groups_create_group((object)array('name' => 'Group 2 in course 4', 'courseid' => $course3->id));
$group32 = $DB->get_record('groups', array('id' => $id), '*', MUST_EXIST);
$this->enable_plugin();
$e1 = $metalplugin->add_instance($course3, array('customint1' => $course1->id, 'customint2' => $group31->id));
$e2 = $metalplugin->add_instance($course3, array('customint1' => $course2->id, 'customint2' => $group32->id));
$this->getDataGenerator()->enrol_user($user1->id, $course1->id, $student->id);
$this->getDataGenerator()->enrol_user($user4->id, $course1->id, $teacher->id);
$this->getDataGenerator()->enrol_user($user1->id, $course2->id, $student->id);
// Now make sure users are in the correct groups.
$this->assertTrue(groups_is_member($group31->id, $user1->id));
$this->assertTrue($DB->record_exists('groups_members', array('groupid' => $group31->id, 'userid' => $user1->id,
'component' => 'enrol_meta', 'itemid' => $e1)));
$this->assertTrue(groups_is_member($group32->id, $user1->id));
$this->assertTrue($DB->record_exists('groups_members', array('groupid' => $group32->id, 'userid' => $user1->id,
'component' => 'enrol_meta', 'itemid' => $e2)));
$this->assertTrue(groups_is_member($group31->id, $user4->id));
$this->assertTrue($DB->record_exists('groups_members', array('groupid' => $group31->id, 'userid' => $user4->id,
'component' => 'enrol_meta', 'itemid' => $e1)));
// Make sure everything is the same after sync.
enrol_meta_sync(null, false);
$this->assertTrue(groups_is_member($group31->id, $user1->id));
$this->assertTrue($DB->record_exists('groups_members', array('groupid' => $group31->id, 'userid' => $user1->id,
'component' => 'enrol_meta', 'itemid' => $e1)));
$this->assertTrue(groups_is_member($group32->id, $user1->id));
$this->assertTrue($DB->record_exists('groups_members', array('groupid' => $group32->id, 'userid' => $user1->id,
'component' => 'enrol_meta', 'itemid' => $e2)));
$this->assertTrue(groups_is_member($group31->id, $user4->id));
$this->assertTrue($DB->record_exists('groups_members', array('groupid' => $group31->id, 'userid' => $user4->id,
'component' => 'enrol_meta', 'itemid' => $e1)));
set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL, 'enrol_meta');
// When user 1 is unenrolled from course1, he is removed from group31 but still present in group32.
enrol_get_plugin('manual')->unenrol_user($manualenrol1, $user1->id);
$this->assertFalse(groups_is_member($group31->id, $user1->id));
$this->assertTrue(groups_is_member($group32->id, $user1->id));
$this->assertTrue(is_enrolled(context_course::instance($course3->id), $user1, '', true)); // He still has active enrolment.
// And the same after sync.
enrol_meta_sync(null, false);
$this->assertFalse(groups_is_member($group31->id, $user1->id));
$this->assertTrue(groups_is_member($group32->id, $user1->id));
$this->assertTrue(is_enrolled(context_course::instance($course3->id), $user1, '', true));
// Unenroll user1 from course2 and make sure he is completely unenrolled from course3.
enrol_get_plugin('manual')->unenrol_user($manualenrol2, $user1->id);
$this->assertFalse(groups_is_member($group32->id, $user1->id));
$this->assertFalse(is_enrolled(context_course::instance($course3->id), $user1));
set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES, 'enrol_meta');
// When user is unenrolled in this case, he is still a member of a group (but enrolment is suspended).
enrol_get_plugin('manual')->unenrol_user($manualenrol1, $user4->id);
$this->assertTrue(groups_is_member($group31->id, $user4->id));
$this->assertTrue(is_enrolled(context_course::instance($course3->id), $user4));
$this->assertFalse(is_enrolled(context_course::instance($course3->id), $user4, '', true));
enrol_meta_sync(null, false);
$this->assertTrue(groups_is_member($group31->id, $user4->id));
$this->assertTrue(is_enrolled(context_course::instance($course3->id), $user4));
$this->assertFalse(is_enrolled(context_course::instance($course3->id), $user4, '', true));
}
/**
* Test user_enrolment_created event.
*/