We have just implemented some changes that get around this problem. The fix allows you to manually add ANYBODY directly into the meta course.
The first part of the fix is to take out the capability check when assigning users. Remove the following line of code from /admin/roles/assign.php:
- if ($inmeta) {
- if (has_capability('moodle/course:managemetacourse', $context, $adduser)) {
- //ok
- } else {
- $managerroles = get_roles_with_capability('moodle/course:managemetacourse', CAP_ALLOW, $context);
- if (!empty($managerroles) and !array_key_exists($roleid, $managerroles)) {
- $erruser = get_record('user', 'id', $adduser, '','','','', 'id, firstname, lastname');
- $errors[] = get_string('metaassignerror', 'role', fullname($erruser));
- $allow = false;
- }
- }
- }
The next part of the fix allows the system to know which users were added via the auto meta sync process and then ignores manually created assigments during the sync process. To do this I am assigning the value of 'meta' to the enrol property of the role_asssignment record. The enrol property indicates the enrolment method used to create the assignment (normally set to 'manual'). 'meta' is not a valid enrolment type but I could not find any logic in Moodle that would have a negative impact. We need to modify the sync_metacourse() function within /lib/moodlelib.php. First we want to stop unassignment of users that were not created by the meta sync process. Add "ra.enrol = 'meta'" to the appropriate sql statement. The code should look something like this:
if (!$unassignments = get_records_sql("
SELECT
ra.id, ra.roleid, ra.userid
FROM
{$CFG->prefix}role_assignments ra
WHERE
ra.contextid = {$context->id} AND
ra.enrol = 'meta' AND
$roleexclusions
NOT EXISTS (
SELECT 1 FROM
{$CFG->prefix}role_assignments ra2,
{$CFG->prefix}context con2,
{$CFG->prefix}course_meta cm
WHERE
ra2.userid = ra.userid AND
ra2.roleid = ra.roleid AND
ra2.contextid = con2.id AND
con2.contextlevel = " . CONTEXT_COURSE . " AND
con2.instanceid = cm.child_course AND
cm.parent_course = {$course->id}
)
")) {
$unassignments = array();
}
Now we want to take out the check for those users who have 'moodle/course:managemetacourse' capability when performing the unassignment. I.e.: (notice the commented out lines)
foreach ($unassignments as $unassignment) {
//if (!in_array($unassignment->userid, $managers)) {
$success = role_unassign($unassignment->roleid, $unassignment->userid, 0, $context->id) && $success;
//}
}
Note that you can also remove the code which sets up the $managers variable as it is no longer referenced.
The final thing to do is set the enrol property to 'meta' for new assignments. Should now look like this:
foreach ($assignments as $assignment) {
$success = role_assign($assignment->roleid, $assignment->userid, 0, $context->id, 0, 0, 0, 'meta') && $success;
}
Sorry I could not provide a patch file as I have a variety of other changes that are not relevant.
But wait... there's more... You will need to set the enrol property for existing role_assignments when implementing the changes. I am attaching a script that will do the trick.
i confirm this. i cannot add a normal user to a metacourse, it gives me the same error. i can add a teacher though