/**
  * Test assign_roles
  */
 public function test_assign_roles()
 {
     global $USER;
     $this->resetAfterTest(true);
     $course = self::getDataGenerator()->create_course();
     // Set the required capabilities by the external function.
     $context = context_course::instance($course->id);
     $roleid = $this->assignUserCapability('moodle/role:assign', $context->id);
     $this->assignUserCapability('moodle/course:view', $context->id, $roleid);
     // Add manager role to $USER.
     // So $USER is allowed to assign 'manager', 'editingteacher', 'teacher' and 'student'.
     role_assign(1, $USER->id, context_system::instance()->id);
     // Check the teacher role has not been assigned to $USER.
     $users = get_role_users(3, $context);
     $this->assertEquals(count($users), 0);
     // Call the external function. Assign teacher role to $USER with contextid.
     core_role_external::assign_roles(array(array('roleid' => 3, 'userid' => $USER->id, 'contextid' => $context->id)));
     // Check the role has been assigned.
     $users = get_role_users(3, $context);
     $this->assertEquals(count($users), 1);
     // Unassign role.
     role_unassign(3, $USER->id, $context->id);
     $users = get_role_users(3, $context);
     $this->assertEquals(count($users), 0);
     // Call the external function. Assign teacher role to $USER.
     core_role_external::assign_roles(array(array('roleid' => 3, 'userid' => $USER->id, 'contextlevel' => "course", 'instanceid' => $course->id)));
     $users = get_role_users(3, $context);
     $this->assertEquals(count($users), 1);
     // Call without required capability.
     $this->unassignUserCapability('moodle/role:assign', $context->id, $roleid);
     $this->expectException('moodle_exception');
     $categories = core_role_external::assign_roles(array('roleid' => 3, 'userid' => $USER->id, 'contextid' => $context->id));
 }
Example #2
0
function _unenrollUserFromCourse($user, $course)
{
    $retVal = true;
    echo "<br> {$username} is now going to be unenrolled from {$course->fullname}.";
    if (unenrollQSUser($user, $course)) {
        echo "<br> unenrollQSUser for {$user->username} and {$course->fullname} was successful.";
        if (enrollUserInCourse($user->username, $user->username, $course->fullname, false)) {
            echo "<br> enrollUserInCourse for {$user->username} and {$course->fullname} and false was successful.";
            if (!($context = get_context_instance(CONTEXT_COURSE, $course->id))) {
                echo "<br> Course context for {$course->fullname} is invalid";
                admin_moodlefailed_email($user, 'unenrollUser', $course);
                $retVal = false;
            }
            echo "<br> Course context id is {$context->id}";
            if (!role_unassign(0, $user->id, 0, $context->id)) {
                echo "An error occurred in role_unassign while trying to unenroll {$username} from vLab via auto-delete.";
                admin_moodlefailed_email($user, 'unenrollUser', $course);
                $retVal = false;
            }
            echo "<br> role_unassign for user id of {$user->id} and context id of {$context->id} was successful.";
            send_unenrollment_notification($course, $user);
            add_to_log($course->id, 'course', 'unenrol', "auto-delete", $course->id);
        } else {
            enrollQSUser($user, $course);
            echo "An error occurred in enrollUserInCourse while trying to unenrll {$username} from vLab via auto-delete.";
            admin_moodlefailed_email($user, 'unenrollUser', $course);
            $retVal = false;
        }
    } else {
        echo "An error occurred in unenrollQSUser while trying to unenroll {$username} from vLab via auto-delete.";
        admin_moodlefailed_email($user, 'unenrollUser', $course);
        $retVal = false;
    }
    return $retVal;
}
Example #3
0
File: lib.php Project: rrusso/EARS
 function perform_remove($userid)
 {
     // Try to remove the necessary role
     $context = get_context_instance(CONTEXT_SYSTEM);
     $roleid = $this->check_role();
     // Regardless if the user has the role or not, remove the assignment
     if ($assign = get_record('block_student_' . $this->type, 'path', $this->path, 'usersid', $userid)) {
         $this->remove_assignment($assign);
     }
     $count = count_records('block_student_' . $this->type, 'usersid', $userid) + count_records('block_student_person', 'usersid', $userid);
     // If they don't have any mentor assignments, then remove them from that role
     if ($count == 0) {
         role_unassign($roleid, $userid, 0, $context->id);
     }
 }
Example #4
0
function delete_user($user)
{
    $updateuser = new object();
    $updateuser->id = $user->id;
    $updateuser->deleted = 1;
    $updateuser->username = addslashes("{$user->email}." . time());
    $updateuser->email = '';
    $updateuser->idnumber = '';
    $updateuser->timemodified = time();
    if (update_record('user', $updateuser)) {
        role_unassign(0, $user->id);
        return true;
    } else {
        return false;
    }
}
Example #5
0
} else {
    // Unenrol yourself
    require_capability('moodle/role:unassignself', $context, NULL, false);
}
if (!empty($USER->access['rsw'][$context->path])) {
    print_error('cantunenrollinthisrole', '', $CFG->wwwroot . '/course/view.php?id=' . $course->id);
}
if ($confirm and confirm_sesskey()) {
    if ($userid) {
        if (!role_unassign(0, $userid, 0, $context->id)) {
            print_error("unenrolerror");
        }
        add_to_log($course->id, 'course', 'unenrol', "view.php?id={$course->id}", $course->id);
        redirect($CFG->wwwroot . '/user/index.php?id=' . $course->id);
    } else {
        if (!role_unassign(0, $USER->id, 0, $context->id)) {
            print_error("unenrolerror");
        }
        // force a refresh of mycourses
        unset($USER->mycourses);
        add_to_log($course->id, 'course', 'unenrol', "view.php?id={$course->id}", $course->id);
        redirect($CFG->wwwroot);
    }
}
$strunenrol = get_string('unenrol');
$navlinks = array();
$navlinks[] = array('name' => $strunenrol, 'link' => null, 'type' => 'misc');
$navigation = build_navigation($navlinks);
print_header("{$course->shortname}: {$strunenrol}", $course->fullname, $navigation);
if ($userid) {
    if (!($user = $DB->get_record('user', array('id' => $userid)))) {
Example #6
0
 /**
  * Forces synchronisation of all enrolments with external database.
  *
  * @param bool $verbose
  * @param null|int $onecourse limit sync to one course only (used primarily in restore)
  * @return int 0 means success, 1 db connect failure, 2 db read failure
  */
 public function sync_enrolments($verbose = false, $onecourse = null)
 {
     global $CFG, $DB;
     // We do not create courses here intentionally because it requires full sync and is slow.
     if (!$this->get_config('dbtype') or !$this->get_config('dbhost') or !$this->get_config('remoteenroltable') or !$this->get_config('remotecoursefield') or !$this->get_config('remoteuserfield')) {
         if ($verbose) {
             mtrace('User enrolment synchronisation skipped.');
         }
         return 0;
     }
     if ($verbose) {
         mtrace('Starting user enrolment synchronisation...');
     }
     if (!($extdb = $this->db_init())) {
         mtrace('Error while communicating with external enrolment database');
         return 1;
     }
     // We may need a lot of memory here.
     @set_time_limit(0);
     raise_memory_limit(MEMORY_HUGE);
     $table = $this->get_config('remoteenroltable');
     $coursefield = trim($this->get_config('remotecoursefield'));
     $userfield = trim($this->get_config('remoteuserfield'));
     $rolefield = trim($this->get_config('remoterolefield'));
     // Lowercased versions - necessary because we normalise the resultset with array_change_key_case().
     $coursefield_l = strtolower($coursefield);
     $userfield_l = strtolower($userfield);
     $rolefield_l = strtolower($rolefield);
     $localrolefield = $this->get_config('localrolefield');
     $localuserfield = $this->get_config('localuserfield');
     $localcoursefield = $this->get_config('localcoursefield');
     $unenrolaction = $this->get_config('unenrolaction');
     $defaultrole = $this->get_config('defaultrole');
     // Create roles mapping.
     $allroles = get_all_roles();
     if (!isset($allroles[$defaultrole])) {
         $defaultrole = 0;
     }
     $roles = array();
     foreach ($allroles as $role) {
         $roles[$role->{$localrolefield}] = $role->id;
     }
     if ($onecourse) {
         $sql = "SELECT c.id, c.visible, c.{$localcoursefield} AS mapping, c.shortname, e.id AS enrolid\n                      FROM {course} c\n                 LEFT JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'database')\n                     WHERE c.id = :id";
         if (!($course = $DB->get_record_sql($sql, array('id' => $onecourse)))) {
             // Course does not exist, nothing to sync.
             return 0;
         }
         if (empty($course->mapping)) {
             // We can not map to this course, sorry.
             return 0;
         }
         if (empty($course->enrolid)) {
             $course->enrolid = $this->add_instance($course);
         }
         $existing = array($course->mapping => $course);
         // Feel free to unenrol everybody, no safety tricks here.
         $preventfullunenrol = false;
         // Course being restored are always hidden, we have to ignore the setting here.
         $ignorehidden = false;
     } else {
         // Get a list of courses to be synced that are in external table.
         $externalcourses = array();
         $sql = $this->db_get_sql($table, array(), array($coursefield), true);
         if ($rs = $extdb->Execute($sql)) {
             if (!$rs->EOF) {
                 while ($mapping = $rs->FetchRow()) {
                     $mapping = reset($mapping);
                     $mapping = $this->db_decode($mapping);
                     if (empty($mapping)) {
                         // invalid mapping
                         continue;
                     }
                     $externalcourses[$mapping] = true;
                 }
             }
             $rs->Close();
         } else {
             mtrace('Error reading data from the external enrolment table');
             $extdb->Close();
             return 2;
         }
         $preventfullunenrol = empty($externalcourses);
         if ($preventfullunenrol and $unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
             mtrace('  Preventing unenrolment of all current users, because it might result in major data loss, there has to be at least one record in external enrol table, sorry.');
         }
         // First find all existing courses with enrol instance.
         $existing = array();
         $sql = "SELECT c.id, c.visible, c.{$localcoursefield} AS mapping, e.id AS enrolid, c.shortname\n                      FROM {course} c\n                      JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'database')";
         $rs = $DB->get_recordset_sql($sql);
         // Watch out for idnumber duplicates.
         foreach ($rs as $course) {
             if (empty($course->mapping)) {
                 continue;
             }
             $existing[$course->mapping] = $course;
             unset($externalcourses[$course->mapping]);
         }
         $rs->close();
         // Add necessary enrol instances that are not present yet.
         $params = array();
         $localnotempty = "";
         if ($localcoursefield !== 'id') {
             $localnotempty = "AND c.{$localcoursefield} <> :lcfe";
             $params['lcfe'] = $DB->sql_empty();
         }
         $sql = "SELECT c.id, c.visible, c.{$localcoursefield} AS mapping, c.shortname\n                      FROM {course} c\n                 LEFT JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'database')\n                     WHERE e.id IS NULL {$localnotempty}";
         $rs = $DB->get_recordset_sql($sql, $params);
         foreach ($rs as $course) {
             if (empty($course->mapping)) {
                 continue;
             }
             if (!isset($externalcourses[$course->mapping])) {
                 // Course not synced or duplicate.
                 continue;
             }
             $course->enrolid = $this->add_instance($course);
             $existing[$course->mapping] = $course;
             unset($externalcourses[$course->mapping]);
         }
         $rs->close();
         // Print list of missing courses.
         if ($verbose and $externalcourses) {
             $list = implode(', ', array_keys($externalcourses));
             mtrace("  error: following courses do not exist - {$list}");
             unset($list);
         }
         // Free memory.
         unset($externalcourses);
         $ignorehidden = $this->get_config('ignorehiddencourses');
     }
     // Sync user enrolments.
     $sqlfields = array($userfield);
     if ($rolefield) {
         $sqlfields[] = $rolefield;
     }
     foreach ($existing as $course) {
         if ($ignorehidden and !$course->visible) {
             continue;
         }
         if (!($instance = $DB->get_record('enrol', array('id' => $course->enrolid)))) {
             continue;
             // Weird!
         }
         $context = context_course::instance($course->id);
         // Get current list of enrolled users with their roles.
         $current_roles = array();
         $current_status = array();
         $user_mapping = array();
         $sql = "SELECT u.{$localuserfield} AS mapping, u.id, ue.status, ue.userid, ra.roleid\n                      FROM {user} u\n                      JOIN {user_enrolments} ue ON (ue.userid = u.id AND ue.enrolid = :enrolid)\n                      JOIN {role_assignments} ra ON (ra.userid = u.id AND ra.itemid = ue.enrolid AND ra.component = 'enrol_database')\n                     WHERE u.deleted = 0";
         $params = array('enrolid' => $instance->id);
         if ($localuserfield === 'username') {
             $sql .= " AND u.mnethostid = :mnethostid";
             $params['mnethostid'] = $CFG->mnet_localhost_id;
         }
         $rs = $DB->get_recordset_sql($sql, $params);
         foreach ($rs as $ue) {
             $current_roles[$ue->userid][$ue->roleid] = $ue->roleid;
             $current_status[$ue->userid] = $ue->status;
             $user_mapping[$ue->mapping] = $ue->userid;
         }
         $rs->close();
         // Get list of users that need to be enrolled and their roles.
         $requested_roles = array();
         $sql = $this->db_get_sql($table, array($coursefield => $course->mapping), $sqlfields);
         if ($rs = $extdb->Execute($sql)) {
             if (!$rs->EOF) {
                 $usersearch = array('deleted' => 0);
                 if ($localuserfield === 'username') {
                     $usersearch['mnethostid'] = $CFG->mnet_localhost_id;
                 }
                 while ($fields = $rs->FetchRow()) {
                     $fields = array_change_key_case($fields, CASE_LOWER);
                     if (empty($fields[$userfield_l])) {
                         if ($verbose) {
                             mtrace("  error: skipping user without mandatory {$localuserfield} in course '{$course->mapping}'");
                         }
                         continue;
                     }
                     $mapping = $fields[$userfield_l];
                     if (!isset($user_mapping[$mapping])) {
                         $usersearch[$localuserfield] = $mapping;
                         if (!($user = $DB->get_record('user', $usersearch, 'id', IGNORE_MULTIPLE))) {
                             if ($verbose) {
                                 mtrace("  error: skipping unknown user {$localuserfield} '{$mapping}' in course '{$course->mapping}'");
                             }
                             continue;
                         }
                         $user_mapping[$mapping] = $user->id;
                         $userid = $user->id;
                     } else {
                         $userid = $user_mapping[$mapping];
                     }
                     if (empty($fields[$rolefield_l]) or !isset($roles[$fields[$rolefield_l]])) {
                         if (!$defaultrole) {
                             if ($verbose) {
                                 mtrace("  error: skipping user '{$userid}' in course '{$course->mapping}' - missing course and default role");
                             }
                             continue;
                         }
                         $roleid = $defaultrole;
                     } else {
                         $roleid = $roles[$fields[$rolefield_l]];
                     }
                     $requested_roles[$userid][$roleid] = $roleid;
                 }
             }
             $rs->Close();
         } else {
             mtrace("  error: skipping course '{$course->mapping}' - could not match with external database");
             continue;
         }
         unset($user_mapping);
         // Enrol all users and sync roles.
         foreach ($requested_roles as $userid => $userroles) {
             foreach ($userroles as $roleid) {
                 if (empty($current_roles[$userid])) {
                     $this->enrol_user($instance, $userid, $roleid, 0, 0, ENROL_USER_ACTIVE);
                     $current_roles[$userid][$roleid] = $roleid;
                     $current_status[$userid] = ENROL_USER_ACTIVE;
                     if ($verbose) {
                         mtrace("  enrolling: {$userid} ==> {$course->shortname} as " . $allroles[$roleid]->shortname);
                     }
                 }
             }
             // Assign extra roles.
             foreach ($userroles as $roleid) {
                 if (empty($current_roles[$userid][$roleid])) {
                     role_assign($roleid, $userid, $context->id, 'enrol_database', $instance->id);
                     $current_roles[$userid][$roleid] = $roleid;
                     if ($verbose) {
                         mtrace("  assigning roles: {$userid} ==> {$course->shortname} as " . $allroles[$roleid]->shortname);
                     }
                 }
             }
             // Unassign removed roles.
             foreach ($current_roles[$userid] as $cr) {
                 if (empty($userroles[$cr])) {
                     role_unassign($cr, $userid, $context->id, 'enrol_database', $instance->id);
                     unset($current_roles[$userid][$cr]);
                     if ($verbose) {
                         mtrace("  unsassigning roles: {$userid} ==> {$course->shortname}");
                     }
                 }
             }
             // Reenable enrolment when previously disable enrolment refreshed.
             if ($current_status[$userid] == ENROL_USER_SUSPENDED) {
                 $this->update_user_enrol($instance, $userid, ENROL_USER_ACTIVE);
                 if ($verbose) {
                     mtrace("  unsuspending: {$userid} ==> {$course->shortname}");
                 }
             }
         }
         // Deal with enrolments removed from external table.
         if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
             if (!$preventfullunenrol) {
                 // Unenrol.
                 foreach ($current_status as $userid => $status) {
                     if (isset($requested_roles[$userid])) {
                         continue;
                     }
                     $this->unenrol_user($instance, $userid);
                     if ($verbose) {
                         mtrace("  unenrolling: {$userid} ==> {$course->shortname}");
                     }
                 }
             }
         } else {
             if ($unenrolaction == ENROL_EXT_REMOVED_KEEP) {
                 // Keep - only adding enrolments.
             } else {
                 if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND or $unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
                     // Suspend enrolments.
                     foreach ($current_status as $userid => $status) {
                         if (isset($requested_roles[$userid])) {
                             continue;
                         }
                         if ($status != ENROL_USER_SUSPENDED) {
                             $this->update_user_enrol($instance, $userid, ENROL_USER_SUSPENDED);
                             if ($verbose) {
                                 mtrace("  suspending: {$userid} ==> {$course->shortname}");
                             }
                         }
                         if ($unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
                             role_unassign_all(array('contextid' => $context->id, 'userid' => $userid, 'component' => 'enrol_database', 'itemid' => $instance->id));
                             if ($verbose) {
                                 mtrace("  unsassigning all roles: {$userid} ==> {$course->shortname}");
                             }
                         }
                     }
                 }
             }
         }
     }
     // Close db connection.
     $extdb->Close();
     if ($verbose) {
         mtrace('...user enrolment synchronisation finished.');
     }
     return 0;
 }
Example #7
0
 /**
  * Synchronise user enrolments in given instance as fast as possible.
  *
  * All roles are removed if the meta plugin disabled.
  *
  * @static
  * @param stdClass $instance
  * @param int $userid
  * @return void
  */
 protected static function sync_with_parent_course(stdClass $instance, $userid)
 {
     global $DB, $CFG;
     $plugin = enrol_get_plugin('meta');
     if ($instance->customint1 == $instance->courseid) {
         // can not sync with self!!!
         return;
     }
     $context = context_course::instance($instance->courseid);
     if (!($parentcontext = context_course::instance($instance->customint1, IGNORE_MISSING))) {
         // linking to missing course is not possible
         role_unassign_all(array('userid' => $userid, 'contextid' => $context->id, 'component' => 'enrol_meta'));
         return;
     }
     // list of enrolments in parent course (we ignore meta enrols in parents completely)
     list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e');
     $params['userid'] = $userid;
     $params['parentcourse'] = $instance->customint1;
     $sql = "SELECT ue.*\n                  FROM {user_enrolments} ue\n                  JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol <> 'meta' AND e.courseid = :parentcourse AND e.enrol {$enabled})\n                 WHERE ue.userid = :userid";
     $parentues = $DB->get_records_sql($sql, $params);
     // current enrolments for this instance
     $ue = $DB->get_record('user_enrolments', array('enrolid' => $instance->id, 'userid' => $userid));
     // first deal with users that are not enrolled in parent
     if (empty($parentues)) {
         self::user_not_supposed_to_be_here($instance, $ue, $context, $plugin);
         return;
     }
     if (!enrol_is_enabled('meta')) {
         if ($ue) {
             role_unassign_all(array('userid' => $userid, 'contextid' => $context->id, 'component' => 'enrol_meta'));
         }
         return;
     }
     $skiproles = $plugin->get_config('nosyncroleids', '');
     $skiproles = empty($skiproles) ? array() : explode(',', $skiproles);
     $syncall = $plugin->get_config('syncall', 1);
     // roles in parent course (meta enrols must be ignored!)
     $parentroles = array();
     list($ignoreroles, $params) = $DB->get_in_or_equal($skiproles, SQL_PARAMS_NAMED, 'ri', false, -1);
     $params['contextid'] = $parentcontext->id;
     $params['userid'] = $userid;
     $select = "contextid = :contextid AND userid = :userid AND component <> 'enrol_meta' AND roleid {$ignoreroles}";
     foreach ($DB->get_records_select('role_assignments', $select, $params) as $ra) {
         $parentroles[$ra->roleid] = $ra->roleid;
     }
     // roles from this instance
     $roles = array();
     $ras = $DB->get_records('role_assignments', array('contextid' => $context->id, 'userid' => $userid, 'component' => 'enrol_meta', 'itemid' => $instance->id));
     foreach ($ras as $ra) {
         $roles[$ra->roleid] = $ra->roleid;
     }
     unset($ras);
     // do we want users without roles?
     if (!$syncall and empty($parentroles)) {
         self::user_not_supposed_to_be_here($instance, $ue, $context, $plugin);
         return;
     }
     // is parent enrol active? (we ignore enrol starts and ends, sorry it would be too complex)
     $parentstatus = ENROL_USER_SUSPENDED;
     foreach ($parentues as $pue) {
         if ($pue->status == ENROL_USER_ACTIVE) {
             $parentstatus = ENROL_USER_ACTIVE;
             break;
         }
     }
     // 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;
         }
     } else {
         $plugin->enrol_user($instance, $userid, NULL, 0, 0, $parentstatus);
         $ue = new stdClass();
         $ue->userid = $userid;
         $ue->enrolid = $instance->id;
         $ue->status = $parentstatus;
     }
     // only active users in enabled instances are supposed to have roles (we can reassign the roles any time later)
     if ($ue->status != ENROL_USER_ACTIVE or $instance->status != ENROL_INSTANCE_ENABLED) {
         if ($roles) {
             role_unassign_all(array('userid' => $userid, 'contextid' => $context->id, 'component' => 'enrol_meta', 'itemid' => $instance->id));
         }
         return;
     }
     // add new roles
     foreach ($parentroles as $rid) {
         if (!isset($roles[$rid])) {
             role_assign($rid, $userid, $context->id, 'enrol_meta', $instance->id);
         }
     }
     // remove roles
     foreach ($roles as $rid) {
         if (!isset($parentroles[$rid])) {
             role_unassign($rid, $userid, $context->id, 'enrol_meta', $instance->id);
         }
     }
 }
Example #8
0
     echo "<br> \$destination is set to {$destination}";
     if (!enrollQSUser($user, $course)) {
         //Added: 12.30.2010
         echo "<br> enrollQSUser was NOT successful";
         admin_webservicefailed_email($user, 'enrollUser', $course);
         if (!role_unassign(0, $user->id, 0, $context->id)) {
             // Should email the Admin if this happens
             error("An error occurred while trying to unenrol that person.");
             exit;
         }
         //admin_moodlefailed_email($user,'unenrollUser');
     } else {
         echo "<br> enrollQSUser was successful";
         if (!enrollUserInCourse($user->username, $user->username, $course->fullname, true)) {
             echo "<br> enrollUserInCourse was NOT successful";
             if (!role_unassign(0, $user->id, 0, $context->id)) {
                 error("An error occurred while trying to unenrol that person.");
                 exit;
             }
             echo "<br> role_unassign was successful";
             // Should email the Admin if this happens
             unenrollQSUser($user, $course);
             admin_webservicefailed_email($user, 'enrollUser', $course);
         }
         echo "<br> enrollUserInCourse was successful";
     }
     $payload = file_get_contents($destination);
     send_enrollment_notification($course, $user);
 } else {
     echo "<br> User {$user->username} was already enrolled in course {$course->fullname}";
 }
Example #9
0
 function sync_enrolments($type, $enrol = false)
 {
     global $CFG;
     // Get the role. If it doesn't exist, that is bad.
     $role = get_record('role', 'shortname', $type);
     if (!$role) {
         notify("No such role: {$type}");
         return false;
     }
     // Connect to the external database
     $ldap_connection = $this->enrol_ldap_connect();
     if (!$ldap_connection) {
         @ldap_close($ldap_connection);
         notify("LDAP-module cannot connect to server: {$CFG->ldap_host_url}");
         return false;
     }
     // we are connected OK, continue...
     $this->enrol_ldap_bind($ldap_connection);
     //get all contexts and look for first matching user
     $ldap_contexts = explode(";", $CFG->{'enrol_ldap_contexts_role' . $role->id});
     // get all the fields we will want for the potential course creation
     // as they are light. don't get membership -- potentially a lot of data.
     $ldap_fields_wanted = array('dn', $CFG->enrol_ldap_course_idnumber);
     if (!empty($CFG->enrol_ldap_course_fullname)) {
         array_push($ldap_fields_wanted, $CFG->enrol_ldap_course_fullname);
     }
     if (!empty($CFG->enrol_ldap_course_shortname)) {
         array_push($ldap_fields_wanted, $CFG->enrol_ldap_course_shortname);
     }
     if (!empty($CFG->enrol_ldap_course_summary)) {
         array_push($ldap_fields_wanted, $CFG->enrol_ldap_course_summary);
     }
     if ($enrol) {
         array_push($ldap_fields_wanted, $CFG->{'enrol_ldap_memberattribute_role' . $role->id});
     }
     // define the search pattern
     if (!empty($CFG->enrol_ldap_objectclass)) {
         $ldap_search_pattern = '(objectclass=' . $CFG->enrol_ldap_objectclass . ')';
     } else {
         $ldap_search_pattern = "(objectclass=*)";
     }
     // first, pack the sortorder...
     fix_course_sortorder();
     foreach ($ldap_contexts as $context) {
         $context = trim($context);
         if ($CFG->enrol_ldap_search_sub) {
             //use ldap_search to find first user from subtree
             $ldap_result = @ldap_search($ldap_connection, $context, $ldap_search_pattern, $ldap_fields_wanted);
         } else {
             //search only in this context
             $ldap_result = @ldap_list($ldap_connection, $context, $ldap_search_pattern, $ldap_fields_wanted, 0, 0);
         }
         // check and push results
         $records = $ldap_result ? ldap_get_entries($ldap_connection, $ldap_result) : array('count' => 0);
         // ldap libraries return an odd array, really. fix it:
         $flat_records = array();
         for ($c = 0; $c < $records['count']; $c++) {
             array_push($flat_records, $records["{$c}"]);
         }
         // free mem -- is there a leak?
         $records = 0;
         $ldap_result = 0;
         if (count($flat_records)) {
             foreach ($flat_records as $course) {
                 $idnumber = $course[$CFG->enrol_ldap_course_idnumber][0];
                 print "== Synching {$idnumber}\n";
                 // does the course exist in moodle already?
                 $course_obj = false;
                 $course_obj = get_record('course', $this->enrol_localcoursefield, $idnumber);
                 if (!is_object($course_obj)) {
                     // ok, now then let's create it!
                     print "Creating Course {$idnumber}...";
                     $newcourseid = $this->create_course($course, true);
                     // we are skipping fix_course_sortorder()
                     $course_obj = get_record('course', 'id', $newcourseid);
                     if (is_object($course_obj)) {
                         print "OK!\n";
                     } else {
                         print "failed\n";
                     }
                 }
                 // enrol&unenrol if required
                 if ($enrol && is_object($course_obj)) {
                     // Get a context object.
                     $context = get_context_instance(CONTEXT_COURSE, $course_obj->id);
                     // pull the ldap membership into a nice array
                     // this is an odd array -- mix of hash and array --
                     $ldapmembers = array();
                     if (array_key_exists('enrol_ldap_memberattribute_role' . $role->id, $CFG) && !empty($CFG->{'enrol_ldap_memberattribute_role' . $role->id}) && !empty($course[strtolower($CFG->{'enrol_ldap_memberattribute_role' . $role->id})])) {
                         // may have no membership!
                         $ldapmembers = $course[strtolower($CFG->{'enrol_ldap_memberattribute_role' . $role->id})];
                         unset($ldapmembers['count']);
                         // remove oddity ;)
                         $ldapmembers = addslashes_recursive($ldapmembers);
                     }
                     // prune old ldap enrolments
                     // hopefully they'll fit in the max buffer size for the RDBMS
                     $sql = '
                     SELECT enr.userid AS user, 1
                     FROM ' . $CFG->prefix . 'role_assignments enr
                     JOIN ' . $CFG->prefix . 'user usr ON usr.id=enr.userid
                     WHERE enr.roleid = ' . $role->id . '
                      AND enr.contextid = ' . $context->id . '
                      AND enr.enrol = \'ldap\' ';
                     if (!empty($ldapmembers)) {
                         $sql .= 'AND usr.idnumber NOT IN (\'' . join('\',\'', $ldapmembers) . '\')';
                     } else {
                         print "Empty enrolment for {$course_obj->shortname} \n";
                     }
                     $todelete = get_records_sql($sql);
                     if (!empty($todelete)) {
                         foreach ($todelete as $member) {
                             $member = $member->user;
                             if (role_unassign($role->id, $member, 0, $context->id, 'ldap')) {
                                 print "Unassigned {$type} from {$member} for course {$course_obj->id} ({$course_obj->shortname})\n";
                             } else {
                                 print "Failed to unassign {$type} from {$member} for course {$course_obj->id} ({$course_obj->shortname})\n";
                             }
                         }
                     }
                     // insert current enrolments
                     // bad we can't do INSERT IGNORE with postgres...
                     foreach ($ldapmembers as $ldapmember) {
                         $sql = 'SELECT id,1 FROM ' . $CFG->prefix . 'user ' . " WHERE idnumber='{$ldapmember}'";
                         $member = get_record_sql($sql);
                         //                        print "sql: $sql \nidnumber = ".stripslashes($ldapmember)." \n".var_dump($member);
                         if (empty($member) || empty($member->id)) {
                             print "Could not find user " . stripslashes($ldapmember) . ", skipping\n";
                             continue;
                         }
                         $member = $member->id;
                         if (!get_record('role_assignments', 'roleid', $role->id, 'contextid', $context->id, 'userid', $member, 'enrol', 'ldap')) {
                             if (role_assign($role->id, $member, 0, $context->id, 0, 0, 0, 'ldap')) {
                                 print "Assigned role {$type} to {$member} (" . stripslashes($ldapmember) . ") for course {$course_obj->id} ({$course_obj->shortname})\n";
                             } else {
                                 print "Failed to assign role {$type} to {$member} (" . stripslashes($ldapmember) . ") for course {$course_obj->id} ({$course_obj->shortname})\n";
                             }
                         }
                     }
                 }
             }
         }
     }
     // we are done now, a bit of housekeeping
     fix_course_sortorder();
     @ldap_close($ldap_connection);
     return true;
 }
Example #10
0
         $sysrolename = $user->{$column};
         if ($sysrolename[0] == '-') {
             $removing = true;
             $sysrolename = substr($sysrolename, 1);
         } else {
             $removing = false;
         }
         if (array_key_exists($sysrolename, $sysrolecache)) {
             $sysroleid = $sysrolecache[$sysrolename]->id;
         } else {
             $upt->track('enrolments', get_string('unknownrole', 'error', s($sysrolename)), 'error');
             continue;
         }
         if ($removing) {
             if (user_has_role_assignment($user->id, $sysroleid, SYSCONTEXTID)) {
                 role_unassign($sysroleid, $user->id, SYSCONTEXTID);
                 $upt->track('enrolments', get_string('unassignedsysrole', 'tool_uploaduser', $sysrolecache[$sysroleid]->name));
             }
         } else {
             if (!user_has_role_assignment($user->id, $sysroleid, SYSCONTEXTID)) {
                 role_assign($sysroleid, $user->id, SYSCONTEXTID);
                 $upt->track('enrolments', get_string('assignedsysrole', 'tool_uploaduser', $sysrolecache[$sysroleid]->name));
             }
         }
     }
     continue;
 }
 if (!preg_match('/^course\\d+$/', $column)) {
     continue;
 }
 $i = substr($column, 6);
Example #11
0
    echo "<p>Error: could not access paypal.com</p>";
    email_paypal_error_to_admin("Could not access paypal.com to verify payment", $data);
    die;
}
/// Connection is OK, so now we post the data to validate it
fputs($fp, $header . $req);
/// Now read the response and check if everything is OK.
while (!feof($fp)) {
    $result = fgets($fp, 1024);
    if (strcmp($result, "VERIFIED") == 0) {
        // VALID PAYMENT!
        // check the payment_status and payment_reason
        // If status is not completed or pending then unenrol the student if already enrolled
        // and notify admin
        if ($data->payment_status != "Completed" and $data->payment_status != "Pending") {
            role_unassign(0, $data->userid, 0, $context->id);
            // force accessinfo refresh for users visiting this context...
            mark_context_dirty($context->path);
            email_paypal_error_to_admin("Status not completed or pending. User unenrolled from course", $data);
            die;
        }
        // If status is pending and reason is other than echeck then we are on hold until further notice
        // Email user to let them know. Email admin.
        if ($data->payment_status == "Pending" and $data->pending_reason != "echeck") {
            email_to_user($user, get_admin(), "Moodle: PayPal payment", "Your PayPal payment is pending.");
            email_paypal_error_to_admin("Payment pending", $data);
            die;
        }
        // If our status is not completed or not pending on an echeck clearance then ignore and die
        // This check is redundant at present but may be useful if paypal extend the return codes in the future
        if (!($data->payment_status == "Completed" or $data->payment_status == "Pending" and $data->pending_reason == "echeck")) {
Example #12
0
 function remove_user_role($username, $course_id, $role_id)
 {
     global $DB;
     $username = utf8_decode($username);
     $username = strtolower($username);
     $params = array('username' => $username);
     $user = $DB->get_record('user', $params);
     if (!$user) {
         return;
     }
     $params = array('id' => $course_id);
     $course = $DB->get_record('course', $params);
     $context = context_course::instance($course->id);
     if (!$context) {
         return;
     }
     if (!role_unassign($role_id, $user->id, $context->id)) {
         return;
     }
 }
Example #13
0
 /**
  * sync enrolments with database, create courses if required.
  *
  * @param object The role to sync for. If no role is specified, defaults are
  * used.
  */
 function sync_enrolments($role = null)
 {
     global $CFG;
     global $db;
     error_reporting(E_ALL);
     // Connect to the external database
     $enroldb = $this->enrol_connect();
     if (!$enroldb) {
         notify("enrol/database cannot connect to server");
         return false;
     }
     if (isset($role)) {
         echo '=== Syncing enrolments for role: ' . $role->shortname . " ===\n";
     } else {
         echo "=== Syncing enrolments for default role ===\n";
     }
     // first, pack the sortorder...
     fix_course_sortorder();
     list($have_role, $remote_role_name, $remote_role_value) = $this->role_fields($enroldb, $role);
     if (!$have_role) {
         if (!empty($CFG->enrol_db_defaultcourseroleid) and $role = get_record('role', 'id', $CFG->enrol_db_defaultcourseroleid)) {
             echo "=== Using enrol_db_defaultcourseroleid: {$role->id} ({$role->shortname}) ===\n";
         } elseif (isset($role)) {
             echo "!!! WARNING: Role specified by caller, but no (or invalid) role configuration !!!\n";
         }
     }
     // get enrolments per-course
     $sql = "SELECT DISTINCT {$CFG->enrol_remotecoursefield} " . " FROM {$CFG->enrol_dbtable} " . " WHERE {$CFG->enrol_remoteuserfield} IS NOT NULL" . (isset($remote_role_name, $remote_role_value) ? ' AND ' . $remote_role_name . ' = ' . $remote_role_value : '');
     $rs = $enroldb->Execute($sql);
     if (!$rs) {
         trigger_error($enroldb->ErrorMsg() . ' STATEMENT: ' . $sql);
         return false;
     }
     if ($rs->EOF) {
         // no courses! outta here...
         return true;
     }
     begin_sql();
     $extcourses = array();
     while ($extcourse_obj = rs_fetch_next_record($rs)) {
         // there are more course records
         $extcourse_obj = (object) array_change_key_case((array) $extcourse_obj, CASE_LOWER);
         $extcourse = $extcourse_obj->{strtolower($CFG->enrol_remotecoursefield)};
         array_push($extcourses, $extcourse);
         // does the course exist in moodle already?
         $course = false;
         $course = get_record('course', $CFG->enrol_localcoursefield, $extcourse);
         if (!is_object($course)) {
             if (empty($CFG->enrol_db_autocreate)) {
                 // autocreation not allowed
                 if (debugging('', DEBUG_ALL)) {
                     error_log("Course {$extcourse} does not exist, skipping");
                 }
                 continue;
                 // next foreach course
             }
             // ok, now then let's create it!
             // prepare any course properties we actually have
             $course = new StdClass();
             $course->{$CFG->enrol_localcoursefield} = $extcourse;
             $course->fullname = $extcourse;
             $course->shortname = $extcourse;
             if (!($newcourseid = $this->create_course($course, true) and $course = get_record('course', 'id', $newcourseid))) {
                 error_log("Creating course {$extcourse} failed");
                 continue;
                 // nothing left to do...
             }
         }
         $context = get_context_instance(CONTEXT_COURSE, $course->id);
         // If we don't have a proper role setup, then we default to the default
         // role for the current course.
         if (!$have_role) {
             $role = get_default_course_role($course);
         }
         // get a list of the student ids the are enrolled
         // in the external db -- hopefully it'll fit in memory...
         $extenrolments = array();
         $sql = "SELECT {$CFG->enrol_remoteuserfield} " . " FROM {$CFG->enrol_dbtable} " . " WHERE {$CFG->enrol_remotecoursefield} = " . $enroldb->quote($extcourse) . ($have_role ? ' AND ' . $remote_role_name . ' = ' . $remote_role_value : '');
         $crs = $enroldb->Execute($sql);
         if (!$crs) {
             trigger_error($enroldb->ErrorMsg() . ' STATEMENT: ' . $sql);
             return false;
         }
         if ($crs->EOF) {
             // shouldn't happen, but cover all bases
             continue;
         }
         // slurp results into an array
         while ($crs_obj = rs_fetch_next_record($crs)) {
             $crs_obj = (object) array_change_key_case((array) $crs_obj, CASE_LOWER);
             array_push($extenrolments, $crs_obj->{strtolower($CFG->enrol_remoteuserfield)});
         }
         rs_close($crs);
         // release the handle
         //
         // prune enrolments to users that are no longer in ext auth
         // hopefully they'll fit in the max buffer size for the RDBMS
         //
         // TODO: This doesn't work perfectly.  If we are operating without
         // roles in the external DB, then this doesn't handle changes of role
         // within a course (because the user is still enrolled in the course,
         // so NOT IN misses the course).
         //
         // When the user logs in though, their role list will be updated
         // correctly.
         //
         if (!$CFG->enrol_db_disableunenrol) {
             $to_prune = get_records_sql("\n             SELECT ra.*\n             FROM {$CFG->prefix}role_assignments ra\n              JOIN {$CFG->prefix}user u ON ra.userid = u.id\n             WHERE ra.enrol = 'database'\n              AND ra.contextid = {$context->id}\n              AND ra.roleid = " . $role->id . ($extenrolments ? " AND u.{$CFG->enrol_localuserfield} NOT IN (" . join(", ", array_map(array(&$db, 'quote'), $extenrolments)) . ")" : ''));
             if ($to_prune) {
                 foreach ($to_prune as $role_assignment) {
                     if (role_unassign($role->id, $role_assignment->userid, 0, $role_assignment->contextid)) {
                         error_log("Unassigned {$role->shortname} assignment #{$role_assignment->id} for course {$course->id} (" . format_string($course->shortname) . "); user {$role_assignment->userid}");
                     } else {
                         error_log("Failed to unassign {$role->shortname} assignment #{$role_assignment->id} for course {$course->id} (" . format_string($course->shortname) . "); user {$role_assignment->userid}");
                     }
                 }
             }
         }
         //
         // insert current enrolments
         // bad we can't do INSERT IGNORE with postgres...
         //
         foreach ($extenrolments as $member) {
             // Get the user id and whether is enrolled in one fell swoop
             $sql = "\n                SELECT u.id AS userid, ra.id AS enrolmentid\n                FROM {$CFG->prefix}user u\n                 LEFT OUTER JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid\n                  AND ra.roleid = {$role->id}\n                  AND ra.contextid = {$context->id}\n                 WHERE u.{$CFG->enrol_localuserfield} = " . $db->quote($member) . " AND (u.deleted IS NULL OR u.deleted=0) ";
             $ers = $db->Execute($sql);
             if (!$ers) {
                 trigger_error($db->ErrorMsg() . ' STATEMENT: ' . $sql);
                 return false;
             }
             if ($ers->EOF) {
                 // if this returns empty, it means we don't have the student record.
                 // should not happen -- but skip it anyway
                 trigger_error('weird! no user record entry?');
                 continue;
             }
             $user_obj = rs_fetch_record($ers);
             $userid = $user_obj->userid;
             $enrolmentid = $user_obj->enrolmentid;
             rs_close($ers);
             // release the handle
             if ($enrolmentid) {
                 // already enrolled - skip
                 continue;
             }
             if (role_assign($role->id, $userid, 0, $context->id, 0, 0, 0, 'database')) {
                 error_log("Assigned role {$role->shortname} to user {$userid} in course {$course->id} (" . format_string($course->shortname) . ")");
             } else {
                 error_log("Failed to assign role {$role->shortname} to user {$userid} in course {$course->id} (" . format_string($course->shortname) . ")");
             }
         }
         // end foreach member
     }
     // end while course records
     rs_close($rs);
     //Close the main course recordset
     //
     // prune enrolments to courses that are no longer in ext auth
     //
     // TODO: This doesn't work perfectly.  If we are operating without
     // roles in the external DB, then this doesn't handle changes of role
     // within a course (because the user is still enrolled in the course,
     // so NOT IN misses the course).
     //
     // When the user logs in though, their role list will be updated
     // correctly.
     //
     if (!$CFG->enrol_db_disableunenrol) {
         $sql = "\n            SELECT ra.roleid, ra.userid, ra.contextid\n            FROM {$CFG->prefix}role_assignments ra\n                JOIN {$CFG->prefix}context cn ON cn.id = ra.contextid\n                JOIN {$CFG->prefix}course c ON c.id = cn.instanceid\n            WHERE ra.enrol = 'database'\n              AND cn.contextlevel = " . CONTEXT_COURSE . " " . ($have_role ? ' AND ra.roleid = ' . $role->id : '') . ($extcourses ? " AND c.{$CFG->enrol_localcoursefield} NOT IN (" . join(",", array_map(array(&$db, 'quote'), $extcourses)) . ")" : '');
         $ers = $db->Execute($sql);
         if (!$ers) {
             trigger_error($db->ErrorMsg() . ' STATEMENT: ' . $sql);
             return false;
         }
         if (!$ers->EOF) {
             while ($user_obj = rs_fetch_next_record($ers)) {
                 $user_obj = (object) array_change_key_case((array) $user_obj, CASE_LOWER);
                 $roleid = $user_obj->roleid;
                 $user = $user_obj->userid;
                 $contextid = $user_obj->contextid;
                 if (role_unassign($roleid, $user, 0, $contextid)) {
                     error_log("Unassigned role {$roleid} from user {$user} in context {$contextid}");
                 } else {
                     error_log("Failed unassign role {$roleid} from user {$user} in context {$contextid}");
                 }
             }
             rs_close($ers);
             // release the handle
         }
     }
     commit_sql();
     // we are done now, a bit of housekeeping
     fix_course_sortorder();
     $this->enrol_disconnect($enroldb);
     return true;
 }
 public function process($departmentid, $roletype)
 {
     global $DB, $USER;
     $companymanagerrole = $DB->get_record('role', array('shortname' => 'companymanager'));
     $departmentmanagerrole = $DB->get_record('role', array('shortname' => 'companydepartmentmanager'));
     $companycoursenoneditorrole = $DB->get_record('role', array('shortname' => 'companycoursenoneditor'));
     $companycourseeditorrole = $DB->get_record('role', array('shortname' => 'companycourseeditor'));
     // Process incoming assignments.
     if (optional_param('add', false, PARAM_BOOL) && confirm_sesskey()) {
         $userstoassign = $this->potentialusers->get_selected_users();
         if (!empty($userstoassign)) {
             foreach ($userstoassign as $adduser) {
                 $allow = true;
                 // GWL : Check the userid is valid.
                 if (!company::check_valid_user($this->selectedcompany, $adduser->id, $this->departmentid)) {
                     print_error('invaliduserdepartment', 'block_iomad_company_management');
                 }
                 if ($allow) {
                     if ($roletype != 0) {
                         // Adding a manager type.
                         // Add user to the company manager table.
                         if ($userrecord = $DB->get_record('company_users', array('companyid' => $this->selectedcompany, 'userid' => $adduser->id))) {
                             if ($roletype == 1 && $userrecord->managertype == 0) {
                                 // Give them the company manager role.
                                 role_assign($companymanagerrole->id, $adduser->id, $this->context->id);
                                 // Deal with company courses.
                                 if ($companycourses = $DB->get_records('company_course', array('companyid' => $this->selectedcompany))) {
                                     foreach ($companycourses as $companycourse) {
                                         if ($DB->record_exists('course', array('id' => $companycourse->courseid))) {
                                             if ($DB->record_exists('company_created_courses', array('companyid' => $companycourse->companyid, 'courseid' => $companycourse->courseid))) {
                                                 company_user::enrol($adduser, array($companycourse->courseid), $companycourse->companyid, $companycourseeditorrole->id);
                                             } else {
                                                 company_user::enrol($adduser, array($companycourse->courseid), $companycourse->companyid, $companycoursenoneditorrole->id);
                                             }
                                         }
                                     }
                                 }
                             } else {
                                 if ($roletype == 2 && $userrecord->managertype == 0) {
                                     // Give them the department manager role.
                                     role_assign($departmentmanagerrole->id, $adduser->id, $this->context->id);
                                     // Deal with company courses.
                                     if ($companycourses = $DB->get_records('company_course', array('companyid' => $this->selectedcompany))) {
                                         foreach ($companycourses as $companycourse) {
                                             if ($DB->record_exists('course', array('id' => $companycourse->courseid))) {
                                                 company_user::enrol($adduser, array($companycourse->courseid), $companycourse->companyid, $companycoursenoneditorrole->id);
                                             }
                                         }
                                     }
                                 } else {
                                     if ($roletype == 1 && ($userrecord->managertype = 2)) {
                                         // Give them the department manager role.
                                         role_unassign($departmentmanagerrole->id, $adduser->id, $this->context->id);
                                         role_assign($companymanagerrole->id, $adduser->id, $this->context->id);
                                         // Deal with course permissions.
                                         if ($companycourses = $DB->get_records('company_course', array('companyid' => $this->selectedcompany))) {
                                             foreach ($companycourses as $companycourse) {
                                                 if ($DB->record_exists('course', array('id' => $companycourse->courseid))) {
                                                     // If its a company created course then assign the editor role to the user.
                                                     if ($DB->record_exists('company_created_courses', array('companyid' => $this->selectedcompany, 'courseid' => $companycourse->courseid))) {
                                                         company_user::unenrol($adduser, array($companycourse->courseid), $companycourse->companyid);
                                                         company_user::enrol($adduser, array($companycourse->courseid), $companycourse->companyid, $companycourseeditorrole->id);
                                                     } else {
                                                         company_user::enrol($adduser, array($companycourse->courseid), $companycourse->companyid, $companycoursenoneditorrole->id);
                                                     }
                                                 }
                                             }
                                         }
                                     } else {
                                         if ($roletype == 2 && ($userrecord->managertype = 1)) {
                                             // Give them the department manager role.
                                             role_unassign($companymanagerrole->id, $adduser->id, $this->context->id);
                                             role_assign($departmentmanagerrole->id, $adduser->id, $this->context->id);
                                             // Deal with company course roles.
                                             if ($companycourses = $DB->get_records('company_course', array('companyid' => $this->selectedcompany))) {
                                                 foreach ($companycourses as $companycourse) {
                                                     if ($DB->record_exists('course', array('id' => $companycourse->courseid))) {
                                                         company_user::unenrol($adduser, array($companycourse->courseid), $companycourse->companyid);
                                                         company_user::enrol($adduser, array($companycourse->courseid), $companycourse->companyid, $companycoursenoneditorrole->id);
                                                     }
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                             $userrecord->managertype = $roletype;
                             $DB->update_record('company_users', $userrecord);
                         } else {
                             if ($roletype == 1 && $DB->get_records_sql('SELECT id FROM {company_users}
                                                         WHERE
                                                         userid = :userid
                                                         AND managertype = :roletype
                                                         AND companyid != :companyid', array('userid' => $adduser->id, 'roletype' => 1, 'companyid' => $this->selectedcompany))) {
                                 // We have a company manager from another company.
                                 // We need to add another record.
                                 $company = new company($this->selectedcompany);
                                 $company->assign_user_to_company($adduser->id);
                                 $DB->set_field('company_users', 'managertype', 1, array('userid' => $adduser->id, 'companyid' => $this->selectedcompany));
                                 // Deal with company courses.
                                 if ($companycourses = $DB->get_records('company_course', array('companyid' => $this->selectedcompany))) {
                                     foreach ($companycourses as $companycourse) {
                                         if ($DB->record_exists('course', array('id' => $companycourse->courseid))) {
                                             if ($DB->record_exists('company_created_courses', array('companyid' => $companycourse->companyid, 'courseid' => $companycourse->courseid))) {
                                                 company_user::enrol($adduser, array($companycourse->courseid), $companycourse->companyid, $companycourseeditorrole->id);
                                             } else {
                                                 company_user::enrol($adduser, array($companycourse->courseid), $companycourse->companyid, $companycoursenoneditorrole->id);
                                             }
                                         }
                                     }
                                 }
                             } else {
                                 // Assign the user to department as staff.
                                 company::assign_user_to_department($departmentid, $adduser->id);
                             }
                         }
                     } else {
                         // Assign the user to department as staff.
                         company::assign_user_to_department($departmentid, $adduser->id);
                     }
                 }
             }
             $this->potentialusers->invalidate_selected_users();
             $this->currentusers->invalidate_selected_users();
         }
     }
     // Process incoming unassignments.
     if (optional_param('remove', false, PARAM_BOOL) && confirm_sesskey()) {
         $userstounassign = $this->currentusers->get_selected_users();
         if (!empty($userstounassign)) {
             // Check if we are mearly removing the manager role.
             if ($roletype != 0) {
                 foreach ($userstounassign as $removeuser) {
                     // GWL : Check the userid is valid.
                     if (!company::check_valid_user($this->selectedcompany, $adduser->id, $this->departmentid)) {
                         print_error('invaliduserdepartment', 'block_iomad_company_management');
                     }
                     $userrecord = $DB->get_record('company_users', array('companyid' => $this->selectedcompany, 'userid' => $removeuser->id));
                     // Is this a manager from another company?
                     if ($DB->get_records_sql("SELECT id FROM {company_users}\n                                                  WHERE userid = :userid\n                                                  AND companyid != :companyid\n                                                  AND managertype = 1", array('userid' => $removeuser->id, 'companyid' => $this->selectedcompany))) {
                         // Remove the user from this company.
                         $DB->delete_records('company_users', (array) $userrecord);
                     } else {
                         // Remove the manager status from the user.
                         $userrecord->managertype = 0;
                         $DB->update_record('company_users', $userrecord);
                         role_unassign($companymanagerrole->id, $removeuser->id, $this->context->id);
                         role_unassign($departmentmanagerrole->id, $removeuser->id, $this->context->id);
                     }
                     // Remove their capabilities from the company courses.
                     if ($companycourses = $DB->get_records('company_course', array('companyid' => $this->selectedcompany))) {
                         foreach ($companycourses as $companycourse) {
                             if ($DB->record_exists('course', array('id' => $companycourse->courseid))) {
                                 company_user::unenrol($removeuser, array($companycourse->courseid), $companycourse->companyid);
                             }
                         }
                     }
                 }
             } else {
                 foreach ($userstounassign as $removeuser) {
                     // GWL : Check the userid is valid.
                     if (!company::check_valid_user($this->selectedcompany, $removeuser->id, $this->departmentid)) {
                         print_error('invaliduserdepartment', 'block_iomad_company_management');
                     }
                     // Assign the user to parent department as staff.
                     company::assign_user_to_department($this->companydepartment, $removeuser->id);
                 }
             }
             $this->potentialusers->invalidate_selected_users();
             $this->currentusers->invalidate_selected_users();
         }
     }
 }
/**
 * function that deletes a role and cleanups up after it
 * @param roleid - id of role to delete
 * @return success
 */
function delete_role($roleid)
{
    global $CFG, $USER;
    $success = true;
    // mdl 10149, check if this is the last active admin role
    // if we make the admin role not deletable then this part can go
    $systemcontext = get_context_instance(CONTEXT_SYSTEM);
    if ($role = get_record('role', 'id', $roleid)) {
        if (record_exists('role_capabilities', 'contextid', $systemcontext->id, 'roleid', $roleid, 'capability', 'moodle/site:doanything')) {
            // deleting an admin role
            $status = false;
            if ($adminroles = get_roles_with_capability('moodle/site:doanything', CAP_ALLOW, $systemcontext)) {
                foreach ($adminroles as $adminrole) {
                    if ($adminrole->id != $roleid) {
                        // some other admin role
                        if (record_exists('role_assignments', 'roleid', $adminrole->id, 'contextid', $systemcontext->id)) {
                            // found another admin role with at least 1 user assigned
                            $status = true;
                            break;
                        }
                    }
                }
            }
            if ($status !== true) {
                error('You can not delete this role because there is no other admin roles with users assigned');
            }
        }
    }
    // first unssign all users
    if (!role_unassign($roleid)) {
        debugging("Error while unassigning all users from role with ID {$roleid}!");
        $success = false;
    }
    // cleanup all references to this role, ignore errors
    if ($success) {
        // MDL-10679 find all contexts where this role has an override
        $contexts = get_records_sql("SELECT contextid, contextid\n                                     FROM {$CFG->prefix}role_capabilities\n                                     WHERE roleid = {$roleid}");
        delete_records('role_capabilities', 'roleid', $roleid);
        delete_records('role_allow_assign', 'roleid', $roleid);
        delete_records('role_allow_assign', 'allowassign', $roleid);
        delete_records('role_allow_override', 'roleid', $roleid);
        delete_records('role_allow_override', 'allowoverride', $roleid);
        delete_records('role_names', 'roleid', $roleid);
    }
    // finally delete the role itself
    // get this before the name is gone for logging
    $rolename = get_field('role', 'name', 'id', $roleid);
    if ($success and !delete_records('role', 'id', $roleid)) {
        debugging("Could not delete role record with ID {$roleid}!");
        $success = false;
    }
    if ($success) {
        add_to_log(SITEID, 'role', 'delete', 'admin/roles/action=delete&roleid=' . $roleid, $rolename, '', $USER->id);
    }
    return $success;
}
Example #16
0
 /**
  * Sync roles for this user
  *
  * @param $user object user object (without system magic quotes)
  */
 function sync_roles($user)
 {
     $iscreator = $this->iscreator($user->username);
     if ($iscreator === null) {
         return;
         // Nothing to sync - creators not configured
     }
     if ($roles = get_archetype_roles('coursecreator')) {
         $creatorrole = array_shift($roles);
         // We can only use one, let's use the first one
         $systemcontext = context_system::instance();
         if ($iscreator) {
             // Following calls will not create duplicates
             role_assign($creatorrole->id, $user->id, $systemcontext->id, $this->roleauth);
         } else {
             // Unassign only if previously assigned by this plugin!
             role_unassign($creatorrole->id, $user->id, $systemcontext->id, $this->roleauth);
         }
     }
 }
Example #17
0
/**
 * Removes a teacher from a given course (or ALL courses)
 * Does not delete the user account
 *
 * @param int $courseid The id of the course that is being viewed, if any
 * @param int $userid The id of the user that is being tested against.
 * @return bool
 */
function remove_teacher($userid, $courseid = 0)
{
    global $CFG;
    $roles = get_roles_with_capability('moodle/legacy:editingteacher', CAP_ALLOW);
    if ($roles) {
        $roles += get_roles_with_capability('moodle/legacy:teacher', CAP_ALLOW);
    } else {
        $roles = get_roles_with_capability('moodle/legacy:teacher', CAP_ALLOW);
    }
    if (empty($roles)) {
        return true;
    }
    $return = true;
    if ($courseid) {
        if (!($context = get_context_instance(CONTEXT_COURSE, $courseid))) {
            return false;
        }
        /// First delete any crucial stuff that might still send mail
        if ($forums = get_records('forum', 'course', $courseid)) {
            foreach ($forums as $forum) {
                delete_records('forum_subscriptions', 'forum', $forum->id, 'userid', $userid);
            }
        }
        /// No need to remove from groups now
        foreach ($roles as $role) {
            // Unassign them from all the teacher roles
            $newreturn = role_unassign($role->id, $userid, 0, $context->id);
            if (empty($newreturn)) {
                $return = false;
            }
        }
    } else {
        delete_records('forum_subscriptions', 'userid', $userid);
        $return = true;
        foreach ($roles as $role) {
            // Unassign them from all the teacher roles
            $newreturn = role_unassign($role->id, $userid, 0, 0);
            if (empty($newreturn)) {
                $return = false;
            }
        }
    }
    return $return;
}
Example #18
0
/**
 * function that deletes a role and cleanups up after it
 * @param roleid - id of role to delete
 * @return success
 */
function delete_role($roleid)
{
    global $CFG, $DB;
    $success = true;
    // mdl 10149, check if this is the last active admin role
    // if we make the admin role not deletable then this part can go
    $systemcontext = get_context_instance(CONTEXT_SYSTEM);
    if ($role = $DB->get_record('role', array('id' => $roleid))) {
        if ($DB->record_exists('role_capabilities', array('contextid' => $systemcontext->id, 'roleid' => $roleid, 'capability' => 'moodle/site:doanything'))) {
            // deleting an admin role
            $status = false;
            if ($adminroles = get_roles_with_capability('moodle/site:doanything', CAP_ALLOW, $systemcontext)) {
                foreach ($adminroles as $adminrole) {
                    if ($adminrole->id != $roleid) {
                        // some other admin role
                        if ($DB->record_exists('role_assignments', array('roleid' => $adminrole->id, 'contextid' => $systemcontext->id))) {
                            // found another admin role with at least 1 user assigned
                            $status = true;
                            break;
                        }
                    }
                }
            }
            if ($status !== true) {
                print_error('cannotdeleterolenoadmin', 'access');
            }
        }
    }
    // first unssign all users
    if (!role_unassign($roleid)) {
        debugging("Error while unassigning all users from role with ID {$roleid}!");
        $success = false;
    }
    // cleanup all references to this role, ignore errors
    if ($success) {
        $DB->delete_records('role_capabilities', array('roleid' => $roleid));
        $DB->delete_records('role_allow_assign', array('roleid' => $roleid));
        $DB->delete_records('role_allow_assign', array('allowassign' => $roleid));
        $DB->delete_records('role_allow_override', array('roleid' => $roleid));
        $DB->delete_records('role_allow_override', array('allowoverride' => $roleid));
        $DB->delete_records('role_names', array('roleid' => $roleid));
        $DB->delete_records('role_context_levels', array('roleid' => $roleid));
    }
    // finally delete the role itself
    // get this before the name is gone for logging
    $rolename = $DB->get_field('role', 'name', array('id' => $roleid));
    if ($success and !$DB->delete_records('role', array('id' => $roleid))) {
        debugging("Could not delete role record with ID {$roleid}!");
        $success = false;
    }
    if ($success) {
        add_to_log(SITEID, 'role', 'delete', 'admin/roles/action=delete&roleid=' . $roleid, $rolename, '');
    }
    return $success;
}
Example #19
0
 /**
  * Forces synchronisation of all enrolments with external database.
  *
  * @param bool $verbose
  * @return int 0 means success, 1 db connect failure, 2 db read failure
  */
 public function sync_enrolments($verbose = false)
 {
     global $CFG, $DB;
     // we do not create courses here intentionally because it requires full sync and is slow
     if (!$this->get_config('dbtype') or !$this->get_config('dbhost') or !$this->get_config('remoteenroltable') or !$this->get_config('remotecoursefield') or !$this->get_config('remoteuserfield')) {
         if ($verbose) {
             mtrace('User enrolment synchronisation skipped.');
         }
         return 0;
     }
     if ($verbose) {
         mtrace('Starting user enrolment synchronisation...');
     }
     if (!($extdb = $this->db_init())) {
         mtrace('Error while communicating with external enrolment database');
         return 1;
     }
     // we may need a lot of memory here
     @set_time_limit(0);
     raise_memory_limit(MEMORY_HUGE);
     // second step is to sync instances and users
     $table = $this->get_config('remoteenroltable');
     $coursefield = strtolower($this->get_config('remotecoursefield'));
     $userfield = strtolower($this->get_config('remoteuserfield'));
     $rolefield = strtolower($this->get_config('remoterolefield'));
     $localrolefield = $this->get_config('localrolefield');
     $localuserfield = $this->get_config('localuserfield');
     $localcoursefield = $this->get_config('localcoursefield');
     $unenrolaction = $this->get_config('unenrolaction');
     $defaultrole = $this->get_config('defaultrole');
     // create roles mapping
     $allroles = get_all_roles();
     if (!isset($allroles[$defaultrole])) {
         $defaultrole = 0;
     }
     $roles = array();
     foreach ($allroles as $role) {
         $roles[$role->{$localrolefield}] = $role->id;
     }
     // get a list of courses to be synced that are in external table
     $externalcourses = array();
     $sql = $this->db_get_sql($table, array(), array($coursefield), true);
     if ($rs = $extdb->Execute($sql)) {
         if (!$rs->EOF) {
             while ($mapping = $rs->FetchRow()) {
                 $mapping = reset($mapping);
                 $mapping = $this->db_decode($mapping);
                 if (empty($mapping)) {
                     // invalid mapping
                     continue;
                 }
                 $externalcourses[$mapping] = true;
             }
         }
         $rs->Close();
     } else {
         mtrace('Error reading data from the external enrolment table');
         $extdb->Close();
         return 2;
     }
     $preventfullunenrol = empty($externalcourses);
     if ($preventfullunenrol and $unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
         mtrace('  Preventing unenrolment of all current users, because it might result in major data loss, there has to be at least one record in external enrol table, sorry.');
     }
     // first find all existing courses with enrol instance
     $existing = array();
     $sql = "SELECT c.id, c.visible, c.{$localcoursefield} AS mapping, e.id AS enrolid, c.shortname\n                  FROM {course} c\n                  JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'database')";
     $rs = $DB->get_recordset_sql($sql);
     // watch out for idnumber duplicates
     foreach ($rs as $course) {
         if (empty($course->mapping)) {
             continue;
         }
         $existing[$course->mapping] = $course;
     }
     $rs->close();
     // add necessary enrol instances that are not present yet
     $params = array();
     $localnotempty = "";
     if ($localcoursefield !== 'id') {
         $localnotempty = "AND c.{$localcoursefield} <> :lcfe";
         $params['lcfe'] = $DB->sql_empty();
     }
     $sql = "SELECT c.id, c.visible, c.{$localcoursefield} AS mapping, c.shortname\n                  FROM {course} c\n             LEFT JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'database')\n                 WHERE e.id IS NULL {$localnotempty}";
     $rs = $DB->get_recordset_sql($sql, $params);
     foreach ($rs as $course) {
         if (empty($course->mapping)) {
             continue;
         }
         if (!isset($externalcourses[$course->mapping])) {
             // course not synced
             continue;
         }
         if (isset($existing[$course->mapping])) {
             // some duplicate, sorry
             continue;
         }
         $course->enrolid = $this->add_instance($course);
         $existing[$course->mapping] = $course;
     }
     $rs->close();
     // free memory
     unset($externalcourses);
     // sync enrolments
     $ignorehidden = $this->get_config('ignorehiddencourses');
     $sqlfields = array($userfield);
     if ($rolefield) {
         $sqlfields[] = $rolefield;
     }
     foreach ($existing as $course) {
         if ($ignorehidden and !$course->visible) {
             continue;
         }
         if (!($instance = $DB->get_record('enrol', array('id' => $course->enrolid)))) {
             continue;
             //weird
         }
         $context = get_context_instance(CONTEXT_COURSE, $course->id);
         // get current list of enrolled users with their roles
         $current_roles = array();
         $current_status = array();
         $user_mapping = array();
         $sql = "SELECT u.{$localuserfield} AS mapping, u.id, ue.status, ue.userid, ra.roleid\n                      FROM {user} u\n                      JOIN {user_enrolments} ue ON (ue.userid = u.id AND ue.enrolid = :enrolid)\n                      JOIN {role_assignments} ra ON (ra.userid = u.id AND ra.itemid = ue.enrolid AND ra.component = 'enrol_database')\n                     WHERE u.deleted = 0";
         $params = array('enrolid' => $instance->id);
         if ($localuserfield === 'username') {
             $sql .= " AND u.mnethostid = :mnethostid";
             $params['mnethostid'] = $CFG->mnet_localhost_id;
         }
         $rs = $DB->get_recordset_sql($sql, $params);
         foreach ($rs as $ue) {
             $current_roles[$ue->userid][$ue->roleid] = $ue->roleid;
             $current_status[$ue->userid] = $ue->status;
             $user_mapping[$ue->mapping] = $ue->userid;
         }
         $rs->close();
         // get list of users that need to be enrolled and their roles
         $requested_roles = array();
         $sql = $this->db_get_sql($table, array($coursefield => $course->mapping), $sqlfields);
         if ($rs = $extdb->Execute($sql)) {
             if (!$rs->EOF) {
                 if ($localuserfield === 'username') {
                     $usersearch = array('mnethostid' => $CFG->mnet_localhost_id, 'deleted' => 0);
                 }
                 while ($fields = $rs->FetchRow()) {
                     $fields = array_change_key_case($fields, CASE_LOWER);
                     if (empty($fields[$userfield])) {
                         //user identification is mandatory!
                     }
                     $mapping = $fields[$userfield];
                     if (!isset($user_mapping[$mapping])) {
                         $usersearch[$localuserfield] = $mapping;
                         if (!($user = $DB->get_record('user', $usersearch, 'id', IGNORE_MULTIPLE))) {
                             // user does not exist or was deleted
                             continue;
                         }
                         $user_mapping[$mapping] = $user->id;
                         $userid = $user->id;
                     } else {
                         $userid = $user_mapping[$mapping];
                     }
                     if (empty($fields[$rolefield]) or !isset($roles[$fields[$rolefield]])) {
                         if (!$defaultrole) {
                             // role is mandatory
                             continue;
                         }
                         $roleid = $defaultrole;
                     } else {
                         $roleid = $roles[$fields[$rolefield]];
                     }
                     $requested_roles[$userid][$roleid] = $roleid;
                 }
             }
             $rs->Close();
         } else {
             mtrace('Error while communicating with external enrolment database');
             $extdb->Close();
             return;
         }
         unset($user_mapping);
         // enrol all users and sync roles
         foreach ($requested_roles as $userid => $userroles) {
             foreach ($userroles as $roleid) {
                 if (empty($current_roles[$userid])) {
                     $this->enrol_user($instance, $userid, $roleid, 0, 0, ENROL_USER_ACTIVE);
                     $current_roles[$userid][$roleid] = $roleid;
                     $current_status[$userid] = ENROL_USER_ACTIVE;
                     if ($verbose) {
                         mtrace("  enrolling: {$userid} ==> {$course->shortname} as " . $allroles[$roleid]->shortname);
                     }
                 }
             }
             // assign extra roles
             foreach ($userroles as $roleid) {
                 if (empty($current_roles[$userid][$roleid])) {
                     role_assign($roleid, $userid, $context->id, 'enrol_database', $instance->id);
                     $current_roles[$userid][$roleid] = $roleid;
                     if ($verbose) {
                         mtrace("  assigning roles: {$userid} ==> {$course->shortname} as " . $allroles[$roleid]->shortname);
                     }
                 }
             }
             // unassign removed roles
             foreach ($current_roles[$userid] as $cr) {
                 if (empty($userroles[$cr])) {
                     role_unassign($cr, $userid, $context->id, 'enrol_database', $instance->id);
                     unset($current_roles[$userid][$cr]);
                     if ($verbose) {
                         mtrace("  unsassigning roles: {$userid} ==> {$course->shortname}");
                     }
                 }
             }
             // reenable enrolment when previously disable enrolment refreshed
             if ($current_status[$userid] == ENROL_USER_SUSPENDED) {
                 $this->update_user_enrol($instance, $userid, ENROL_USER_ACTIVE);
                 if ($verbose) {
                     mtrace("  unsuspending: {$userid} ==> {$course->shortname}");
                 }
             }
         }
         // deal with enrolments removed from external table
         if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
             if (!$preventfullunenrol) {
                 // unenrol
                 foreach ($current_status as $userid => $status) {
                     if (isset($requested_roles[$userid])) {
                         continue;
                     }
                     $this->unenrol_user($instance, $userid);
                     if ($verbose) {
                         mtrace("  unenrolling: {$userid} ==> {$course->shortname}");
                     }
                 }
             }
         } else {
             if ($unenrolaction == ENROL_EXT_REMOVED_KEEP) {
                 // keep - only adding enrolments
             } else {
                 if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND or $unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
                     // disable
                     foreach ($current_status as $userid => $status) {
                         if (isset($requested_roles[$userid])) {
                             continue;
                         }
                         if ($status != ENROL_USER_SUSPENDED) {
                             $this->update_user_enrol($instance, $userid, ENROL_USER_SUSPENDED);
                             if ($verbose) {
                                 mtrace("  suspending: {$userid} ==> {$course->shortname}");
                             }
                         }
                         if ($unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
                             role_unassign_all(array('contextid' => $context->id, 'userid' => $userid, 'component' => 'enrol_database', 'itemid' => $instance->id));
                             if ($verbose) {
                                 mtrace("  unsassigning all roles: {$userid} ==> {$course->shortname}");
                             }
                         }
                     }
                 }
             }
         }
     }
     // close db connection
     $extdb->Close();
     if ($verbose) {
         mtrace('...user enrolment synchronisation finished.');
     }
     return 0;
 }
Example #20
0
// checks permissions specified in settings.php
if ($action === 'delete') {
    $contextlevel = required_param('contextlevel', PARAM_INT);
    $roleid = required_param('roleid', PARAM_INT);
    $confirm = optional_param('confirm', 0, PARAM_BOOL);
    $role = $DB->get_record('role', array('id' => $roleid), '*', MUST_EXIST);
    if ($confirm and confirm_sesskey()) {
        $sql = "SELECT ra.*\n                  FROM {role_assignments} ra\n                  JOIN {context} c ON c.id = ra.contextid\n             LEFT JOIN {role_context_levels} rcl ON (rcl.roleid = ra.roleid AND rcl.contextlevel = c.contextlevel)\n                 WHERE rcl.id IS NULL AND ra.roleid = :roleid AND c.contextlevel = :contextlevel";
        $ras = $DB->get_records_sql($sql, array('roleid' => $roleid, 'contextlevel' => $contextlevel));
        foreach ($ras as $ra) {
            if (!empty($ra->component)) {
                //bad luck, we can not mess with plugin ras!
                //TODO: explain why not possible to remove ras
                continue;
            }
            role_unassign($ra->roleid, $ra->userid, $ra->contextid);
        }
        redirect($PAGE->url);
    }
    //show confirmation
    echo $OUTPUT->header();
    $yesurl = new moodle_url($PAGE->url, array('roleid' => $roleid, 'contextlevel' => $contextlevel, 'action' => 'delete', 'confirm' => 1, 'sesskey' => sesskey()));
    $levelname = get_contextlevel_name($contextlevel);
    $rolename = format_string($role->name);
    $message = get_string('confirmdelete', 'tool_unsuproles', array('level' => $levelname, 'role' => $rolename));
    echo $OUTPUT->confirm($message, $yesurl, $PAGE->url);
    echo $OUTPUT->footer();
    die;
}
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('pluginname', 'tool_unsuproles'));
Example #21
0
 public function test_sync()
 {
     global $CFG, $DB;
     $this->resetAfterTest(true);
     $metalplugin = enrol_get_plugin('meta');
     $manplugin = enrol_get_plugin('manual');
     $user1 = $this->getDataGenerator()->create_user();
     $user2 = $this->getDataGenerator()->create_user();
     $user3 = $this->getDataGenerator()->create_user();
     $user4 = $this->getDataGenerator()->create_user();
     $user5 = $this->getDataGenerator()->create_user();
     $course1 = $this->getDataGenerator()->create_course();
     $course2 = $this->getDataGenerator()->create_course();
     $course3 = $this->getDataGenerator()->create_course();
     $course4 = $this->getDataGenerator()->create_course();
     $manual1 = $DB->get_record('enrol', array('courseid' => $course1->id, 'enrol' => 'manual'), '*', MUST_EXIST);
     $manual2 = $DB->get_record('enrol', array('courseid' => $course2->id, 'enrol' => 'manual'), '*', MUST_EXIST);
     $manual3 = $DB->get_record('enrol', array('courseid' => $course3->id, 'enrol' => 'manual'), '*', MUST_EXIST);
     $manual4 = $DB->get_record('enrol', array('courseid' => $course4->id, 'enrol' => 'manual'), '*', MUST_EXIST);
     $student = $DB->get_record('role', array('shortname' => 'student'));
     $teacher = $DB->get_record('role', array('shortname' => 'teacher'));
     $manager = $DB->get_record('role', array('shortname' => 'manager'));
     $this->disable_plugin();
     $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $student->id);
     $this->getDataGenerator()->enrol_user($user2->id, $course1->id, $student->id);
     $this->getDataGenerator()->enrol_user($user3->id, $course1->id, 0);
     $this->getDataGenerator()->enrol_user($user4->id, $course1->id, $teacher->id);
     $this->getDataGenerator()->enrol_user($user5->id, $course1->id, $manager->id);
     $this->getDataGenerator()->enrol_user($user1->id, $course2->id, $student->id);
     $this->getDataGenerator()->enrol_user($user2->id, $course2->id, $teacher->id);
     $this->assertEquals(7, $DB->count_records('user_enrolments'));
     $this->assertEquals(6, $DB->count_records('role_assignments'));
     set_config('syncall', 0, 'enrol_meta');
     set_config('nosyncroleids', $manager->id, 'enrol_meta');
     require_once $CFG->dirroot . '/enrol/meta/locallib.php';
     enrol_meta_sync(null, false);
     $this->assertEquals(7, $DB->count_records('user_enrolments'));
     $this->assertEquals(6, $DB->count_records('role_assignments'));
     $this->enable_plugin();
     enrol_meta_sync(null, false);
     $this->assertEquals(7, $DB->count_records('user_enrolments'));
     $this->assertEquals(6, $DB->count_records('role_assignments'));
     // Disable the plugin to prevent add_instance from calling enrol_meta_sync.
     $this->disable_plugin();
     $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));
     $enrol1 = $DB->get_record('enrol', array('id' => $e1));
     $enrol2 = $DB->get_record('enrol', array('id' => $e2));
     $enrol3 = $DB->get_record('enrol', array('id' => $e3));
     $this->enable_plugin();
     enrol_meta_sync($course4->id, false);
     $this->assertEquals(9, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol3, $student));
     $this->assertTrue($this->is_meta_enrolled($user2, $enrol3, $teacher));
     enrol_meta_sync(null, false);
     $this->assertEquals(14, $DB->count_records('user_enrolments'));
     $this->assertEquals(13, $DB->count_records('role_assignments'));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     $this->assertTrue($this->is_meta_enrolled($user2, $enrol1, $student));
     $this->assertFalse($this->is_meta_enrolled($user3, $enrol1));
     $this->assertTrue($this->is_meta_enrolled($user4, $enrol1, $teacher));
     $this->assertFalse($this->is_meta_enrolled($user5, $enrol1));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol2, $student));
     $this->assertTrue($this->is_meta_enrolled($user2, $enrol2, $teacher));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol3, $student));
     $this->assertTrue($this->is_meta_enrolled($user2, $enrol3, $teacher));
     set_config('syncall', 1, 'enrol_meta');
     enrol_meta_sync(null, false);
     $this->assertEquals(16, $DB->count_records('user_enrolments'));
     $this->assertEquals(13, $DB->count_records('role_assignments'));
     $this->assertTrue($this->is_meta_enrolled($user3, $enrol1, false));
     $this->assertTrue($this->is_meta_enrolled($user5, $enrol1, false));
     $this->assertEquals(16, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->disable_plugin();
     $manplugin->unenrol_user($manual1, $user1->id);
     $manplugin->unenrol_user($manual2, $user1->id);
     $this->assertEquals(14, $DB->count_records('user_enrolments'));
     $this->assertEquals(11, $DB->count_records('role_assignments'));
     $this->assertEquals(14, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->enable_plugin();
     set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPEND, 'enrol_meta');
     enrol_meta_sync($course4->id, false);
     $this->assertEquals(14, $DB->count_records('user_enrolments'));
     $this->assertEquals(11, $DB->count_records('role_assignments'));
     $this->assertEquals(13, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol3, $student));
     $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid' => $enrol3->id, 'status' => ENROL_USER_SUSPENDED, 'userid' => $user1->id)));
     enrol_meta_sync(null, false);
     $this->assertEquals(14, $DB->count_records('user_enrolments'));
     $this->assertEquals(11, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid' => $enrol1->id, 'status' => ENROL_USER_SUSPENDED, 'userid' => $user1->id)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol2, $student));
     $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid' => $enrol2->id, 'status' => ENROL_USER_SUSPENDED, 'userid' => $user1->id)));
     set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES, 'enrol_meta');
     enrol_meta_sync($course4->id, false);
     $this->assertEquals(14, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol3, false));
     $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid' => $enrol3->id, 'status' => ENROL_USER_SUSPENDED, 'userid' => $user1->id)));
     enrol_meta_sync(null, false);
     $this->assertEquals(14, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, false));
     $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid' => $enrol1->id, 'status' => ENROL_USER_SUSPENDED, 'userid' => $user1->id)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol2, false));
     $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid' => $enrol2->id, 'status' => ENROL_USER_SUSPENDED, 'userid' => $user1->id)));
     set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL, 'enrol_meta');
     enrol_meta_sync($course4->id, false);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertFalse($this->is_meta_enrolled($user1, $enrol3));
     enrol_meta_sync(null, false);
     $this->assertEquals(11, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertFalse($this->is_meta_enrolled($user1, $enrol1));
     $this->assertFalse($this->is_meta_enrolled($user1, $enrol2));
     // Now try sync triggered by events.
     set_config('syncall', 1, 'enrol_meta');
     $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $student->id);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(13, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     enrol_meta_sync(null, false);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(13, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     $manplugin->unenrol_user($manual1, $user1->id);
     $this->assertEquals(11, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertFalse($this->is_meta_enrolled($user1, $enrol1));
     enrol_meta_sync(null, false);
     $this->assertEquals(11, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertFalse($this->is_meta_enrolled($user1, $enrol1));
     $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 0);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(13, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, false));
     enrol_meta_sync(null, false);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(13, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, false));
     $manplugin->unenrol_user($manual1, $user1->id);
     $this->assertEquals(11, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertFalse($this->is_meta_enrolled($user1, $enrol1));
     enrol_meta_sync(null, false);
     $this->assertEquals(11, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertFalse($this->is_meta_enrolled($user1, $enrol1));
     set_config('syncall', 0, 'enrol_meta');
     enrol_meta_sync(null, false);
     $this->assertEquals(9, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(9, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertFalse($this->is_meta_enrolled($user1, $enrol1));
     $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 0);
     $this->assertEquals(10, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(10, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertFalse($this->is_meta_enrolled($user1, $enrol1, $student));
     enrol_meta_sync(null, false);
     $this->assertEquals(10, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(10, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertFalse($this->is_meta_enrolled($user1, $enrol1, $student));
     role_assign($teacher->id, $user1->id, context_course::instance($course1->id)->id);
     $this->assertEquals(11, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $teacher));
     enrol_meta_sync(null, false);
     $this->assertEquals(11, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $teacher));
     role_unassign($teacher->id, $user1->id, context_course::instance($course1->id)->id);
     $this->assertEquals(10, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(10, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertFalse($this->is_meta_enrolled($user1, $enrol1, $student));
     enrol_meta_sync(null, false);
     $this->assertEquals(10, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(10, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertFalse($this->is_meta_enrolled($user1, $enrol1, $student));
     $manplugin->unenrol_user($manual1, $user1->id);
     $this->assertEquals(9, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(9, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertFalse($this->is_meta_enrolled($user1, $enrol1));
     set_config('syncall', 1, 'enrol_meta');
     set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPEND, 'enrol_meta');
     enrol_meta_sync(null, false);
     $this->assertEquals(11, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $student->id);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(13, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     enrol_meta_sync(null, false);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(13, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     $manplugin->update_user_enrol($manual1, $user1->id, ENROL_USER_SUSPENDED);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     enrol_meta_sync(null, false);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     $manplugin->unenrol_user($manual1, $user1->id);
     $this->assertEquals(12, $DB->count_records('user_enrolments'));
     $this->assertEquals(9, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     enrol_meta_sync(null, false);
     $this->assertEquals(12, $DB->count_records('user_enrolments'));
     $this->assertEquals(9, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $student->id);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(13, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     enrol_meta_sync(null, false);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(13, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     set_config('syncall', 1, 'enrol_meta');
     set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES, 'enrol_meta');
     enrol_meta_sync(null, false);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(13, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $student->id);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(13, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     enrol_meta_sync(null, false);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(13, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     $manplugin->unenrol_user($manual1, $user1->id);
     $this->assertEquals(12, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, false));
     enrol_meta_sync(null, false);
     $this->assertEquals(12, $DB->count_records('user_enrolments'));
     $this->assertEquals(8, $DB->count_records('role_assignments'));
     $this->assertEquals(11, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, false));
     $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $student->id);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(13, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     enrol_meta_sync(null, false);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(13, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
     set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL, 'enrol_meta');
     enrol_meta_sync(null, false);
     $this->assertEquals(13, $DB->count_records('user_enrolments'));
     $this->assertEquals(10, $DB->count_records('role_assignments'));
     $this->assertEquals(13, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     delete_course($course1, false);
     $this->assertEquals(3, $DB->count_records('user_enrolments'));
     $this->assertEquals(3, $DB->count_records('role_assignments'));
     $this->assertEquals(3, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     enrol_meta_sync(null, false);
     $this->assertEquals(3, $DB->count_records('user_enrolments'));
     $this->assertEquals(3, $DB->count_records('role_assignments'));
     $this->assertEquals(3, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     delete_course($course2, false);
     $this->assertEquals(0, $DB->count_records('user_enrolments'));
     $this->assertEquals(0, $DB->count_records('role_assignments'));
     $this->assertEquals(0, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     enrol_meta_sync(null, false);
     $this->assertEquals(0, $DB->count_records('user_enrolments'));
     $this->assertEquals(0, $DB->count_records('role_assignments'));
     $this->assertEquals(0, $DB->count_records('user_enrolments', array('status' => ENROL_USER_ACTIVE)));
     delete_course($course3, false);
     delete_course($course4, false);
 }
Example #22
0
/**
 * This function will empty a course of user data.
 * It will retain the activities and the structure of the course.
 * @param object $data an object containing all the settings including courseid (without magic quotes)
 * @return array status array of array component, item, error
 */
function reset_course_userdata($data)
{
    global $CFG, $USER;
    require_once $CFG->libdir . '/gradelib.php';
    require_once $CFG->dirroot . '/group/lib.php';
    $data->courseid = $data->id;
    $context = get_context_instance(CONTEXT_COURSE, $data->courseid);
    // calculate the time shift of dates
    if (!empty($data->reset_start_date)) {
        // time part of course startdate should be zero
        $data->timeshift = $data->reset_start_date - usergetmidnight($data->reset_start_date_old);
    } else {
        $data->timeshift = 0;
    }
    // result array: component, item, error
    $status = array();
    // start the resetting
    $componentstr = get_string('general');
    // move the course start time
    if (!empty($data->reset_start_date) and $data->timeshift) {
        // change course start data
        set_field('course', 'startdate', $data->reset_start_date, 'id', $data->courseid);
        // update all course and group events - do not move activity events
        $updatesql = "UPDATE {$CFG->prefix}event\n                         SET timestart = timestart + ({$data->timeshift})\n                       WHERE courseid={$data->courseid} AND instance=0";
        execute_sql($updatesql, false);
        $status[] = array('component' => $componentstr, 'item' => get_string('datechanged'), 'error' => false);
    }
    if (!empty($data->reset_logs)) {
        delete_records('log', 'course', $data->courseid);
        $status[] = array('component' => $componentstr, 'item' => get_string('deletelogs'), 'error' => false);
    }
    if (!empty($data->reset_events)) {
        delete_records('event', 'courseid', $data->courseid);
        $status[] = array('component' => $componentstr, 'item' => get_string('deleteevents', 'calendar'), 'error' => false);
    }
    if (!empty($data->reset_notes)) {
        require_once $CFG->dirroot . '/notes/lib.php';
        note_delete_all($data->courseid);
        $status[] = array('component' => $componentstr, 'item' => get_string('deletenotes', 'notes'), 'error' => false);
    }
    $componentstr = get_string('roles');
    if (!empty($data->reset_roles_overrides)) {
        $children = get_child_contexts($context);
        foreach ($children as $child) {
            delete_records('role_capabilities', 'contextid', $child->id);
        }
        delete_records('role_capabilities', 'contextid', $context->id);
        //force refresh for logged in users
        mark_context_dirty($context->path);
        $status[] = array('component' => $componentstr, 'item' => get_string('deletecourseoverrides', 'role'), 'error' => false);
    }
    if (!empty($data->reset_roles_local)) {
        $children = get_child_contexts($context);
        foreach ($children as $child) {
            role_unassign(0, 0, 0, $child->id);
        }
        //force refresh for logged in users
        mark_context_dirty($context->path);
        $status[] = array('component' => $componentstr, 'item' => get_string('deletelocalroles', 'role'), 'error' => false);
    }
    // First unenrol users - this cleans some of related user data too, such as forum subscriptions, tracking, etc.
    $data->unenrolled = array();
    if (!empty($data->reset_roles)) {
        foreach ($data->reset_roles as $roleid) {
            if ($users = get_role_users($roleid, $context, false, 'u.id', 'u.id ASC')) {
                foreach ($users as $user) {
                    role_unassign($roleid, $user->id, 0, $context->id);
                    if (!has_capability('moodle/course:view', $context, $user->id)) {
                        $data->unenrolled[$user->id] = $user->id;
                    }
                }
            }
        }
    }
    if (!empty($data->unenrolled)) {
        $status[] = array('component' => $componentstr, 'item' => get_string('unenrol') . ' (' . count($data->unenrolled) . ')', 'error' => false);
    }
    $componentstr = get_string('groups');
    // remove all group members
    if (!empty($data->reset_groups_members)) {
        groups_delete_group_members($data->courseid);
        $status[] = array('component' => $componentstr, 'item' => get_string('removegroupsmembers', 'group'), 'error' => false);
    }
    // remove all groups
    if (!empty($data->reset_groups_remove)) {
        groups_delete_groups($data->courseid, false);
        $status[] = array('component' => $componentstr, 'item' => get_string('deleteallgroups', 'group'), 'error' => false);
    }
    // remove all grouping members
    if (!empty($data->reset_groupings_members)) {
        groups_delete_groupings_groups($data->courseid, false);
        $status[] = array('component' => $componentstr, 'item' => get_string('removegroupingsmembers', 'group'), 'error' => false);
    }
    // remove all groupings
    if (!empty($data->reset_groupings_remove)) {
        groups_delete_groupings($data->courseid, false);
        $status[] = array('component' => $componentstr, 'item' => get_string('deleteallgroupings', 'group'), 'error' => false);
    }
    // Look in every instance of every module for data to delete
    $unsupported_mods = array();
    if ($allmods = get_records('modules')) {
        foreach ($allmods as $mod) {
            $modname = $mod->name;
            if (!count_records($modname, 'course', $data->courseid)) {
                continue;
                // skip mods with no instances
            }
            $modfile = $CFG->dirroot . '/mod/' . $modname . '/lib.php';
            $moddeleteuserdata = $modname . '_reset_userdata';
            // Function to delete user data
            if (file_exists($modfile)) {
                include_once $modfile;
                if (function_exists($moddeleteuserdata)) {
                    $modstatus = $moddeleteuserdata($data);
                    if (is_array($modstatus)) {
                        $status = array_merge($status, $modstatus);
                    } else {
                        debugging('Module ' . $modname . ' returned incorrect staus - must be an array!');
                    }
                } else {
                    $unsupported_mods[] = $mod;
                }
            } else {
                debugging('Missing lib.php in ' . $modname . ' module!');
            }
        }
    }
    // mention unsupported mods
    if (!empty($unsupported_mods)) {
        foreach ($unsupported_mods as $mod) {
            $status[] = array('component' => get_string('modulenameplural', $mod->name), 'item' => '', 'error' => get_string('resetnotimplemented'));
        }
    }
    $componentstr = get_string('gradebook', 'grades');
    // reset gradebook
    if (!empty($data->reset_gradebook_items)) {
        remove_course_grades($data->courseid, false);
        grade_grab_course_grades($data->courseid);
        grade_regrade_final_grades($data->courseid);
        $status[] = array('component' => $componentstr, 'item' => get_string('removeallcourseitems', 'grades'), 'error' => false);
    } else {
        if (!empty($data->reset_gradebook_grades)) {
            grade_course_reset($data->courseid);
            $status[] = array('component' => $componentstr, 'item' => get_string('removeallcoursegrades', 'grades'), 'error' => false);
        }
    }
    return $status;
}
Example #23
0
 /**
  * Removes an assigned role from a user.
  *
  * @global moodle_database $DB
  * @param int $userid
  * @param int $roleid
  * @return bool
  */
 public function unassign_role_from_user($userid, $roleid)
 {
     global $DB;
     // Admins may unassign any role, others only those they could assign.
     if (!is_siteadmin() and !array_key_exists($roleid, $this->get_assignable_roles())) {
         if (defined('AJAX_SCRIPT')) {
             throw new moodle_exception('invalidrole');
         }
         return false;
     }
     $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
     $ras = $DB->get_records('role_assignments', array('contextid' => $this->context->id, 'userid' => $user->id, 'roleid' => $roleid));
     foreach ($ras as $ra) {
         if ($ra->component) {
             if (strpos($ra->component, 'enrol_') !== 0) {
                 continue;
             }
             if (!($plugin = enrol_get_plugin(substr($ra->component, 6)))) {
                 continue;
             }
             if ($plugin->roles_protected()) {
                 continue;
             }
         }
         role_unassign($ra->roleid, $ra->userid, $ra->contextid, $ra->component, $ra->itemid);
     }
     return true;
 }
Example #24
0
 /**
  * Removes an assigned role from a user.
  *
  * @global moodle_database $DB
  * @param int $userid
  * @param int $roleid
  * @return bool
  */
 public function unassign_role_from_user($userid, $roleid) {
     global $DB;
     require_capability('moodle/role:assign', $this->context);
     $user = $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
     try {
         role_unassign($roleid, $user->id, $this->context->id, '', NULL);
     } catch (Exception $e) {
         if (defined('AJAX_SCRIPT')) {
             throw $e;
         }
         return false;
     }
     return true;
 }
            }
            $potentialuserselector->invalidate_selected_users();
            $currentuserselector->invalidate_selected_users();
            $rolename = $assignableroles[$roleid];
            add_to_log($course->id, 'role', 'assign', 'mod/adobeconnect/participant.php?contextid=' . $context->id . '&roleid=' . $roleid, $rolename, '', $USER->id);
            // Counts have changed, so reload.
            list($assignableroles, $assigncounts, $nameswithcounts) = get_assignable_roles($context, ROLENAME_BOTH, true);
        }
    }
    // Process incoming role unassignments
    if (optional_param('remove', false, PARAM_BOOL) && confirm_sesskey()) {
        $userstounassign = $currentuserselector->get_selected_users();
        if (!empty($userstounassign)) {
            foreach ($userstounassign as $removeuser) {
                //unassign only roles that are added manually, no messing with other components!!!
                role_unassign($roleid, $removeuser->id, $context->id, '');
            }
            $potentialuserselector->invalidate_selected_users();
            $currentuserselector->invalidate_selected_users();
            $rolename = $assignableroles[$roleid];
            add_to_log($course->id, 'role', 'unassign', 'mod/adobeconnect/participant.php?contextid=' . $context->id . '&roleid=' . $roleid, $rolename, '', $USER->id);
            // Counts have changed, so reload.
            list($assignableroles, $assigncounts, $nameswithcounts) = get_assignable_roles($context, ROLENAME_BOTH, true);
        }
    }
}
$PAGE->set_pagelayout('admin');
$PAGE->set_title($title);
switch ($context->contextlevel) {
    case CONTEXT_SYSTEM:
        admin_externalpage_setup('assignroles', '', array('contextid' => $contextid, 'roleid' => $roleid));
Example #26
0
 /**
  * Sync all meta course links.
  *
  * @param int $courseid one course, empty mean all
  * @param bool $verbose verbose CLI output
  * @return int 0 means ok, 1 means error, 2 means plugin disabled
  */
 public function sync($courseid = null, $verbose = false)
 {
     global $DB;
     if (!enrol_is_enabled('self')) {
         return 2;
     }
     // Unfortunately this may take a long time, execution can be interrupted safely here.
     @set_time_limit(0);
     raise_memory_limit(MEMORY_HUGE);
     if ($verbose) {
         mtrace('Verifying self-enrolments...');
     }
     $params = array('now' => time(), 'useractive' => ENROL_USER_ACTIVE, 'courselevel' => CONTEXT_COURSE);
     $coursesql = "";
     if ($courseid) {
         $coursesql = "AND e.courseid = :courseid";
         $params['courseid'] = $courseid;
     }
     // Note: the logic of self enrolment guarantees that user logged in at least once (=== u.lastaccess set)
     //       and that user accessed course at least once too (=== user_lastaccess record exists).
     // First deal with users that did not log in for a really long time - they do not have user_lastaccess records.
     $sql = "SELECT e.*, ue.userid\n                  FROM {user_enrolments} ue\n                  JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'self' AND e.customint2 > 0)\n                  JOIN {user} u ON u.id = ue.userid\n                 WHERE :now - u.lastaccess > e.customint2\n                       {$coursesql}";
     $rs = $DB->get_recordset_sql($sql, $params);
     foreach ($rs as $instance) {
         $userid = $instance->userid;
         unset($instance->userid);
         $this->unenrol_user($instance, $userid);
         if ($verbose) {
             $days = $instance->customint2 / 60 * 60 * 24;
             mtrace("  unenrolling user {$userid} from course {$instance->courseid} as they have did not log in for at least {$days} days");
         }
     }
     $rs->close();
     // Now unenrol from course user did not visit for a long time.
     $sql = "SELECT e.*, ue.userid\n                  FROM {user_enrolments} ue\n                  JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'self' AND e.customint2 > 0)\n                  JOIN {user_lastaccess} ul ON (ul.userid = ue.userid AND ul.courseid = e.courseid)\n                 WHERE :now - ul.timeaccess > e.customint2\n                       {$coursesql}";
     $rs = $DB->get_recordset_sql($sql, $params);
     foreach ($rs as $instance) {
         $userid = $instance->userid;
         unset($instance->userid);
         $this->unenrol_user($instance, $userid);
         if ($verbose) {
             $days = $instance->customint2 / 60 * 60 * 24;
             mtrace("  unenrolling user {$userid} from course {$instance->courseid} as they have did not access course for at least {$days} days");
         }
     }
     $rs->close();
     // Deal with expired accounts.
     $action = $this->get_config('expiredaction', ENROL_EXT_REMOVED_KEEP);
     if ($action == ENROL_EXT_REMOVED_UNENROL) {
         $instances = array();
         $sql = "SELECT ue.*, e.courseid, c.id AS contextid\n                      FROM {user_enrolments} ue\n                      JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'self')\n                      JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)\n                     WHERE ue.timeend > 0 AND ue.timeend < :now\n                           {$coursesql}";
         $rs = $DB->get_recordset_sql($sql, $params);
         foreach ($rs as $ue) {
             if (empty($instances[$ue->enrolid])) {
                 $instances[$ue->enrolid] = $DB->get_record('enrol', array('id' => $ue->enrolid));
             }
             $instance = $instances[$ue->enrolid];
             if ($instance->roleid) {
                 role_unassign($instance->roleid, $ue->userid, $ue->contextid, '', 0);
             }
             $this->unenrol_user($instance, $ue->userid);
             if ($verbose) {
                 mtrace("  unenrolling expired user {$ue->userid} from course {$instance->courseid}");
             }
         }
         $rs->close();
         unset($instances);
     } else {
         if ($action == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
             $instances = array();
             $sql = "SELECT ue.*, e.courseid, c.id AS contextid\n                      FROM {user_enrolments} ue\n                      JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'self')\n                      JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)\n                     WHERE ue.timeend > 0 AND ue.timeend < :now\n                           AND ue.status = :useractive\n                           {$coursesql}";
             $rs = $DB->get_recordset_sql($sql, $params);
             foreach ($rs as $ue) {
                 if (empty($instances[$ue->enrolid])) {
                     $instances[$ue->enrolid] = $DB->get_record('enrol', array('id' => $ue->enrolid));
                 }
                 $instance = $instances[$ue->enrolid];
                 if (1 == $DB->count_records('role_assignments', array('userid' => $ue->userid, 'contextid' => $ue->contextid))) {
                     role_unassign_all(array('userid' => $ue->userid, 'contextid' => $ue->contextid, 'component' => '', 'itemid' => 0), true);
                 } else {
                     if ($instance->roleid) {
                         role_unassign($instance->roleid, $ue->userid, $ue->contextid, '', 0);
                     }
                 }
                 $this->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED);
                 if ($verbose) {
                     mtrace("  suspending expired user {$ue->userid} in course {$instance->courseid}");
                 }
             }
             $rs->close();
             unset($instances);
         } else {
             // ENROL_EXT_REMOVED_KEEP means no changes.
         }
     }
     if ($verbose) {
         mtrace('...user self-enrolment updates finished.');
     }
     return 0;
 }
Example #27
0
/// Run all core cron jobs, but not every time since they aren't too important.
/// These don't have a timer to reduce load, so we'll use a random number
/// to randomly choose the percentage of times we should run these jobs.
srand((double) microtime() * 10000000);
$random100 = rand(0, 100);
if ($random100 < 20) {
    // Approximately 20% of the time.
    mtrace("Running clean-up tasks...");
    /// Unenrol users who haven't logged in for $CFG->longtimenosee
    if ($CFG->longtimenosee) {
        // value in days
        $cuttime = $timenow - $CFG->longtimenosee * 3600 * 24;
        $rs = get_recordset_sql("SELECT id, userid, courseid\n                                        FROM {$CFG->prefix}user_lastaccess\n                                       WHERE courseid != " . SITEID . "\n                                         AND timeaccess < {$cuttime} ");
        while ($assign = rs_fetch_next_record($rs)) {
            if ($context = get_context_instance(CONTEXT_COURSE, $assign->courseid)) {
                if (role_unassign(0, $assign->userid, 0, $context->id)) {
                    mtrace("Deleted assignment for user {$assign->userid} from course {$assign->courseid}");
                }
            }
        }
        rs_close($rs);
        /// Execute the same query again, looking for remaining records and deleting them
        /// if the user hasn't moodle/course:view in the CONTEXT_COURSE context (orphan records)
        $rs = get_recordset_sql("SELECT id, userid, courseid\n                                        FROM {$CFG->prefix}user_lastaccess\n                                       WHERE courseid != " . SITEID . "\n                                         AND timeaccess < {$cuttime} ");
        while ($assign = rs_fetch_next_record($rs)) {
            if ($context = get_context_instance(CONTEXT_COURSE, $assign->courseid)) {
                if (!has_capability('moodle/course:view', $context, $assign->userid)) {
                    delete_records('user_lastaccess', 'userid', $assign->userid, 'courseid', $assign->courseid);
                    mtrace("Deleted orphan user_lastaccess for user {$assign->userid} from course {$assign->courseid}");
                }
            }
Example #28
0
 /**
  * Unassign roles from users
  *
  * @param array $unassignments An array of unassignment
  */
 public static function unassign_roles($unassignments)
 {
     global $DB;
     // Do basic automatic PARAM checks on incoming data, using params description
     // If any problems are found then exceptions are thrown with helpful error messages
     $params = self::validate_parameters(self::unassign_roles_parameters(), array('unassignments' => $unassignments));
     $transaction = $DB->start_delegated_transaction();
     foreach ($params['unassignments'] as $unassignment) {
         // Ensure the current user is allowed to run this function in the unassignment context
         $context = self::get_context_from_params($unassignment);
         self::validate_context($context);
         require_capability('moodle/role:assign', $context);
         // throw an exception if user is not able to unassign the role in this context
         $roles = get_assignable_roles($context, ROLENAME_SHORT);
         if (!array_key_exists($unassignment['roleid'], $roles)) {
             throw new invalid_parameter_exception('Can not unassign roleid=' . $unassignment['roleid'] . ' in contextid=' . $unassignment['contextid']);
         }
         role_unassign($unassignment['roleid'], $unassignment['userid'], $context->id);
     }
     $transaction->allow_commit();
 }
Example #29
0
 $topleveladmin = false;
 // we only worry about this if the role has doanything capability at site level
 if ($context->id == $sitecontext->id && ($adminroles = get_roles_with_capability('moodle/site:doanything', CAP_ALLOW, $sitecontext))) {
     foreach ($adminroles as $adminrole) {
         if ($adminrole->id == $roleid) {
             $topleveladmin = true;
         }
     }
 }
 foreach ($frm->removeselect as $removeuser) {
     $removeuser = clean_param($removeuser, PARAM_INT);
     if ($topleveladmin && $removeuser == $USER->id) {
         // Prevent unassigning oneself from being admin
         continue;
     }
     if (!role_unassign($roleid, $removeuser, 0, $context->id)) {
         $errors[] = "Could not remove user with id {$removeuser} from this role!";
     } else {
         if ($inmeta) {
             sync_metacourse($courseid);
             $newroles = get_user_roles($context, $removeuser, false);
             if (!empty($newroles) and !array_key_exists($roleid, $newroles)) {
                 $erruser = get_record('user', 'id', $removeuser, '', '', '', '', 'id, firstname, lastname');
                 $errors[] = get_string('metaunassignerror', 'role', fullname($erruser));
                 $allow = false;
             }
         }
     }
 }
 $rolename = get_field('role', 'name', 'id', $roleid);
 add_to_log($course->id, 'role', 'unassign', 'admin/roles/assign.php?contextid=' . $context->id . '&roleid=' . $roleid, $rolename, '', $USER->id);
Example #30
0
    /**
     * A small functional test of accesslib functions and classes.
     * @return void
     */
    public function test_everything_in_accesslib() {
        global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE;

        $this->resetAfterTest(true);

        $generator = $this->getDataGenerator();

        // Fill the site with some real data
        $testcategories = array();
        $testcourses = array();
        $testpages = array();
        $testblocks = array();
        $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id');

        $systemcontext = context_system::instance();
        $frontpagecontext = context_course::instance(SITEID);

        // Add block to system context
        $bi = $generator->create_block('online_users');
        context_block::instance($bi->id);
        $testblocks[] = $bi->id;

        // Some users
        $testusers = array();
        for($i=0; $i<20; $i++) {
            $user = $generator->create_user();
            $testusers[$i] = $user->id;
            $usercontext = context_user::instance($user->id);

            // Add block to user profile
            $bi = $generator->create_block('online_users', array('parentcontextid'=>$usercontext->id));
            $testblocks[] = $bi->id;
        }
        // Deleted user - should be ignored everywhere, can not have context
        $generator->create_user(array('deleted'=>1));

        // Add block to frontpage
        $bi = $generator->create_block('online_users', array('parentcontextid'=>$frontpagecontext->id));
        $frontpageblockcontext = context_block::instance($bi->id);
        $testblocks[] = $bi->id;

        // Add a resource to frontpage
        $page = $generator->create_module('page', array('course'=>$SITE->id));
        $testpages[] = $page->id;
        $frontpagepagecontext = context_module::instance($page->cmid);

        // Add block to frontpage resource
        $bi = $generator->create_block('online_users', array('parentcontextid'=>$frontpagepagecontext->id));
        $frontpagepageblockcontext = context_block::instance($bi->id);
        $testblocks[] = $bi->id;

        // Some nested course categories with courses
        $manualenrol = enrol_get_plugin('manual');
        $parentcat = 0;
        for($i=0; $i<5; $i++) {
            $cat = $generator->create_category(array('parent'=>$parentcat));
            $testcategories[] = $cat->id;
            $catcontext = context_coursecat::instance($cat->id);
            $parentcat = $cat->id;

            if ($i >=4) {
                continue;
            }

            // Add resource to each category
            $bi = $generator->create_block('online_users', array('parentcontextid'=>$catcontext->id));
            context_block::instance($bi->id);

            // Add a few courses to each category
            for($j=0; $j<6; $j++) {
                $course = $generator->create_course(array('category'=>$cat->id));
                $testcourses[] = $course->id;
                $coursecontext = context_course::instance($course->id);

                if ($j >= 5) {
                    continue;
                }
                // Add manual enrol instance
                $manualenrol->add_default_instance($DB->get_record('course', array('id'=>$course->id)));

                // Add block to each course
                $bi = $generator->create_block('online_users', array('parentcontextid'=>$coursecontext->id));
                $testblocks[] = $bi->id;

                // Add a resource to each course
                $page = $generator->create_module('page', array('course'=>$course->id));
                $testpages[] = $page->id;
                $modcontext = context_module::instance($page->cmid);

                // Add block to each module
                $bi = $generator->create_block('online_users', array('parentcontextid'=>$modcontext->id));
                $testblocks[] = $bi->id;
            }
        }

        // Make sure all contexts were created properly
        $count = 1; //system
        $count += $DB->count_records('user', array('deleted'=>0));
        $count += $DB->count_records('course_categories');
        $count += $DB->count_records('course');
        $count += $DB->count_records('course_modules');
        $count += $DB->count_records('block_instances');
        $this->assertEquals($DB->count_records('context'), $count);
        $this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
        $this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);


        // ====== context_helper::get_level_name() ================================

        $levels = context_helper::get_all_levels();
        foreach ($levels as $level=>$classname) {
            $name = context_helper::get_level_name($level);
            $this->assertFalse(empty($name));
        }


        // ======= context::instance_by_id(), context_xxx::instance();

        $context = context::instance_by_id($frontpagecontext->id);
        $this->assertSame($context->contextlevel, CONTEXT_COURSE);
        $this->assertFalse(context::instance_by_id(-1, IGNORE_MISSING));
        try {
            context::instance_by_id(-1);
            $this->fail('exception expected');
        } catch (Exception $e) {
            $this->assertTrue(true);
        }
        $this->assertTrue(context_system::instance() instanceof context_system);
        $this->assertTrue(context_coursecat::instance($testcategories[0]) instanceof context_coursecat);
        $this->assertTrue(context_course::instance($testcourses[0]) instanceof context_course);
        $this->assertTrue(context_module::instance($testpages[0]) instanceof context_module);
        $this->assertTrue(context_block::instance($testblocks[0]) instanceof context_block);

        $this->assertFalse(context_coursecat::instance(-1, IGNORE_MISSING));
        $this->assertFalse(context_course::instance(-1, IGNORE_MISSING));
        $this->assertFalse(context_module::instance(-1, IGNORE_MISSING));
        $this->assertFalse(context_block::instance(-1, IGNORE_MISSING));
        try {
            context_coursecat::instance(-1);
            $this->fail('exception expected');
        } catch (Exception $e) {
            $this->assertTrue(true);
        }
        try {
            context_course::instance(-1);
            $this->fail('exception expected');
        } catch (Exception $e) {
            $this->assertTrue(true);
        }
        try {
            context_module::instance(-1);
            $this->fail('exception expected');
        } catch (Exception $e) {
            $this->assertTrue(true);
        }
        try {
            context_block::instance(-1);
            $this->fail('exception expected');
        } catch (Exception $e) {
            $this->assertTrue(true);
        }


        // ======= $context->get_url(), $context->get_context_name(), $context->get_capabilities() =========

        $testcontexts = array();
        $testcontexts[CONTEXT_SYSTEM]    = context_system::instance();
        $testcontexts[CONTEXT_COURSECAT] = context_coursecat::instance($testcategories[0]);
        $testcontexts[CONTEXT_COURSE]    = context_course::instance($testcourses[0]);
        $testcontexts[CONTEXT_MODULE]    = context_module::instance($testpages[0]);
        $testcontexts[CONTEXT_BLOCK]     = context_block::instance($testblocks[0]);

        foreach ($testcontexts as $context) {
            $name = $context->get_context_name(true, true);
            $this->assertFalse(empty($name));

            $this->assertTrue($context->get_url() instanceof moodle_url);

            $caps = $context->get_capabilities();
            $this->assertTrue(is_array($caps));
            foreach ($caps as $cap) {
                $cap = (array)$cap;
                $this->assertSame(array_keys($cap), array('id', 'name', 'captype', 'contextlevel', 'component', 'riskbitmask'));
            }
        }
        unset($testcontexts);

        // ===== $context->get_course_context() =========================================

        $this->assertFalse($systemcontext->get_course_context(false));
        try {
            $systemcontext->get_course_context();
            $this->fail('exception expected');
        } catch (Exception $e) {
            $this->assertTrue(true);
        }
        $context = context_coursecat::instance($testcategories[0]);
        $this->assertFalse($context->get_course_context(false));
        try {
            $context->get_course_context();
            $this->fail('exception expected');
        } catch (Exception $e) {
            $this->assertTrue(true);
        }
        $this->assertSame($frontpagecontext->get_course_context(true), $frontpagecontext);
        $this->assertSame($frontpagepagecontext->get_course_context(true), $frontpagecontext);
        $this->assertSame($frontpagepageblockcontext->get_course_context(true), $frontpagecontext);


        // ======= $context->get_parent_context(), $context->get_parent_contexts(), $context->get_parent_context_ids() =======

        $userid = reset($testusers);
        $usercontext = context_user::instance($userid);
        $this->assertSame($usercontext->get_parent_context(), $systemcontext);
        $this->assertSame($usercontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext));
        $this->assertSame($usercontext->get_parent_contexts(true), array($usercontext->id=>$usercontext, $systemcontext->id=>$systemcontext));

        $this->assertSame($systemcontext->get_parent_contexts(), array());
        $this->assertSame($systemcontext->get_parent_contexts(true), array($systemcontext->id=>$systemcontext));
        $this->assertSame($systemcontext->get_parent_context_ids(), array());
        $this->assertSame($systemcontext->get_parent_context_ids(true), array($systemcontext->id));

        $this->assertSame($frontpagecontext->get_parent_context(), $systemcontext);
        $this->assertSame($frontpagecontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext));
        $this->assertSame($frontpagecontext->get_parent_contexts(true), array($frontpagecontext->id=>$frontpagecontext, $systemcontext->id=>$systemcontext));
        $this->assertSame($frontpagecontext->get_parent_context_ids(), array($systemcontext->id));
        $this->assertEquals($frontpagecontext->get_parent_context_ids(true), array($frontpagecontext->id, $systemcontext->id));

        $this->assertSame($systemcontext->get_parent_context(), false);
        $frontpagecontext = context_course::instance($SITE->id);
        $parent = $systemcontext;
        foreach ($testcategories as $catid) {
            $catcontext = context_coursecat::instance($catid);
            $this->assertSame($catcontext->get_parent_context(), $parent);
            $parent = $catcontext;
        }
        $this->assertSame($frontpagepagecontext->get_parent_context(), $frontpagecontext);
        $this->assertSame($frontpageblockcontext->get_parent_context(), $frontpagecontext);
        $this->assertSame($frontpagepageblockcontext->get_parent_context(), $frontpagepagecontext);


        // ====== $context->get_child_contexts() ================================

        $CFG->debug = 0;
        $children = $systemcontext->get_child_contexts();
        $CFG->debug = DEBUG_DEVELOPER;
        $this->assertEquals(count($children)+1, $DB->count_records('context'));

        $context = context_coursecat::instance($testcategories[3]);
        $children = $context->get_child_contexts();
        $countcats    = 0;
        $countcourses = 0;
        $countblocks  = 0;
        foreach ($children as $child) {
            if ($child->contextlevel == CONTEXT_COURSECAT) {
                $countcats++;
            }
            if ($child->contextlevel == CONTEXT_COURSE) {
                $countcourses++;
            }
            if ($child->contextlevel == CONTEXT_BLOCK) {
                $countblocks++;
            }
        }
        $this->assertEquals(count($children), 8);
        $this->assertEquals($countcats, 1);
        $this->assertEquals($countcourses, 6);
        $this->assertEquals($countblocks, 1);

        $context = context_course::instance($testcourses[2]);
        $children = $context->get_child_contexts();
        $this->assertEquals(count($children), 7); // depends on number of default blocks

        $context = context_module::instance($testpages[3]);
        $children = $context->get_child_contexts();
        $this->assertEquals(count($children), 1);

        $context = context_block::instance($testblocks[1]);
        $children = $context->get_child_contexts();
        $this->assertEquals(count($children), 0);

        unset($children);
        unset($countcats);
        unset($countcourses);
        unset($countblocks);


        // ======= context_helper::reset_caches() ============================

        context_helper::reset_caches();
        $this->assertEquals(context_inspection::test_context_cache_size(), 0);
        context_course::instance($SITE->id);
        $this->assertEquals(context_inspection::test_context_cache_size(), 1);


        // ======= context preloading ========================================

        context_helper::reset_caches();
        $sql = "SELECT ".context_helper::get_preload_record_columns_sql('c')."
                  FROM {context} c
                 WHERE c.contextlevel <> ".CONTEXT_SYSTEM;
        $records = $DB->get_records_sql($sql);
        $firstrecord = reset($records);
        $columns = context_helper::get_preload_record_columns('c');
        $firstrecord = (array)$firstrecord;
        $this->assertSame(array_keys($firstrecord), array_values($columns));
        context_helper::reset_caches();
        foreach ($records as $record) {
            context_helper::preload_from_record($record);
            $this->assertEquals($record, new stdClass());
        }
        $this->assertEquals(context_inspection::test_context_cache_size(), count($records));
        unset($records);
        unset($columns);

        context_helper::reset_caches();
        context_helper::preload_course($SITE->id);
        $this->assertEquals(7, context_inspection::test_context_cache_size()); // depends on number of default blocks

        // ====== assign_capability(), unassign_capability() ====================

        $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
        $this->assertFalse($rc);
        assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext->id);
        $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
        $this->assertEquals($rc->permission, CAP_ALLOW);
        assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext->id);
        $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
        $this->assertEquals($rc->permission, CAP_ALLOW);
        assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext, true);
        $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
        $this->assertEquals($rc->permission, CAP_PREVENT);

        assign_capability('moodle/site:accessallgroups', CAP_INHERIT, $allroles['teacher'], $frontpagecontext);
        $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
        $this->assertFalse($rc);
        assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext);
        unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext, true);
        $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
        $this->assertFalse($rc);
        unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext->id, true);
        unset($rc);

        accesslib_clear_all_caches(false); // must be done after assign_capability()


        // ======= role_assign(), role_unassign(), role_unassign_all() ==============

        $context = context_course::instance($testcourses[1]);
        $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0);
        role_assign($allroles['teacher'], $testusers[1], $context->id);
        role_assign($allroles['teacher'], $testusers[2], $context->id);
        role_assign($allroles['manager'], $testusers[1], $context->id);
        $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 3);
        role_unassign($allroles['teacher'], $testusers[1], $context->id);
        $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 2);
        role_unassign_all(array('contextid'=>$context->id));
        $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0);
        unset($context);

        accesslib_clear_all_caches(false); // just in case


        // ====== has_capability(), get_users_by_capability(), role_switch(), reload_all_capabilities() and friends ========================

        $adminid = get_admin()->id;
        $guestid = $CFG->siteguest;

        // Enrol some users into some courses
        $course1 = $DB->get_record('course', array('id'=>$testcourses[22]), '*', MUST_EXIST);
        $course2 = $DB->get_record('course', array('id'=>$testcourses[7]), '*', MUST_EXIST);
        $cms = $DB->get_records('course_modules', array('course'=>$course1->id), 'id');
        $cm1 = reset($cms);
        $blocks = $DB->get_records('block_instances', array('parentcontextid'=>context_module::instance($cm1->id)->id), 'id');
        $block1 = reset($blocks);
        $instance1 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course1->id));
        $instance2 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course2->id));
        for($i=0; $i<9; $i++) {
            $manualenrol->enrol_user($instance1, $testusers[$i], $allroles['student']);
        }
        $manualenrol->enrol_user($instance1, $testusers[8], $allroles['teacher']);
        $manualenrol->enrol_user($instance1, $testusers[9], $allroles['editingteacher']);

        for($i=10; $i<15; $i++) {
            $manualenrol->enrol_user($instance2, $testusers[$i], $allroles['student']);
        }
        $manualenrol->enrol_user($instance2, $testusers[15], $allroles['editingteacher']);

        // Add tons of role assignments - the more the better
        role_assign($allroles['coursecreator'], $testusers[11], context_coursecat::instance($testcategories[2]));
        role_assign($allroles['manager'], $testusers[12], context_coursecat::instance($testcategories[1]));
        role_assign($allroles['student'], $testusers[9], context_module::instance($cm1->id));
        role_assign($allroles['teacher'], $testusers[8], context_module::instance($cm1->id));
        role_assign($allroles['guest'], $testusers[13], context_course::instance($course1->id));
        role_assign($allroles['teacher'], $testusers[7], context_block::instance($block1->id));
        role_assign($allroles['manager'], $testusers[9], context_block::instance($block1->id));
        role_assign($allroles['editingteacher'], $testusers[9], context_course::instance($course1->id));

        role_assign($allroles['teacher'], $adminid, context_course::instance($course1->id));
        role_assign($allroles['editingteacher'], $adminid, context_block::instance($block1->id));

        // Add tons of overrides - the more the better
        assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpageblockcontext, true);
        assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpageblockcontext, true);
        assign_capability('moodle/block:view', CAP_PROHIBIT, $allroles['guest'], $frontpageblockcontext, true);
        assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['user'], $frontpageblockcontext, true);
        assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['student'], $frontpageblockcontext, true);

        assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $CFG->defaultuserroleid, $frontpagepagecontext, true);
        assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagepagecontext, true);
        assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $frontpagepagecontext, true);
        assign_capability('mod/page:view', CAP_ALLOW, $allroles['user'], $frontpagepagecontext, true);
        assign_capability('moodle/page:view', CAP_ALLOW, $allroles['student'], $frontpagepagecontext, true);

        assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpagecontext, true);
        assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagecontext, true);
        assign_capability('mod/page:view', CAP_ALLOW, $allroles['guest'], $frontpagecontext, true);
        assign_capability('mod/page:view', CAP_PROHIBIT, $allroles['user'], $frontpagecontext, true);

        assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $systemcontext, true);

        accesslib_clear_all_caches(false); // must be done after assign_capability()

        // Extra tests for guests and not-logged-in users because they can not be verified by cross checking
        // with get_users_by_capability() where they are ignored
        $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, $guestid));
        $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, $guestid));
        $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, $guestid));
        $this->assertFalse(has_capability('mod/page:view', $systemcontext, $guestid));

        $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, 0));
        $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, 0));
        $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, 0));
        $this->assertFalse(has_capability('mod/page:view', $systemcontext, 0));

        $this->assertFalse(has_capability('moodle/course:create', $systemcontext, $testusers[11]));
        $this->assertTrue(has_capability('moodle/course:create', context_coursecat::instance($testcategories[2]), $testusers[11]));
        $this->assertFalse(has_capability('moodle/course:create', context_course::instance($testcourses[1]), $testusers[11]));
        $this->assertTrue(has_capability('moodle/course:create', context_course::instance($testcourses[19]), $testusers[11]));

        $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[1]), $testusers[9]));
        $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[19]), $testusers[9]));
        $this->assertFalse(has_capability('moodle/course:update', $systemcontext, $testusers[9]));

        // Test the list of enrolled users
        $coursecontext = context_course::instance($course1->id);
        $enrolled = get_enrolled_users($coursecontext);
        $this->assertEquals(count($enrolled), 10);
        for($i=0; $i<10; $i++) {
            $this->assertTrue(isset($enrolled[$testusers[$i]]));
        }
        $enrolled = get_enrolled_users($coursecontext, 'moodle/course:update');
        $this->assertEquals(count($enrolled), 1);
        $this->assertTrue(isset($enrolled[$testusers[9]]));
        unset($enrolled);

        // role switching
        $userid = $testusers[9];
        $USER = $DB->get_record('user', array('id'=>$userid));
        load_all_capabilities();
        $coursecontext = context_course::instance($course1->id);
        $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
        $this->assertFalse(is_role_switched($course1->id));
        role_switch($allroles['student'], $coursecontext);
        $this->assertTrue(is_role_switched($course1->id));
        $this->assertEquals($USER->access['rsw'][$coursecontext->path],  $allroles['student']);
        $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
        reload_all_capabilities();
        $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
        role_switch(0, $coursecontext);
        $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
        $userid = $adminid;
        $USER = $DB->get_record('user', array('id'=>$userid));
        load_all_capabilities();
        $coursecontext = context_course::instance($course1->id);
        $blockcontext = context_block::instance($block1->id);
        $this->assertTrue(has_capability('moodle/course:update', $blockcontext));
        role_switch($allroles['student'], $coursecontext);
        $this->assertEquals($USER->access['rsw'][$coursecontext->path],  $allroles['student']);
        $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
        reload_all_capabilities();
        $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
        load_all_capabilities();
        $this->assertTrue(has_capability('moodle/course:update', $blockcontext));

        // temp course role for enrol
        $DB->delete_records('cache_flags', array()); // this prevents problem with dirty contexts immediately resetting the temp role - this is a known problem...
        $userid = $testusers[5];
        $roleid = $allroles['editingteacher'];
        $USER = $DB->get_record('user', array('id'=>$userid));
        load_all_capabilities();
        $coursecontext = context_course::instance($course1->id);
        $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
        $this->assertFalse(isset($USER->access['ra'][$coursecontext->path][$roleid]));
        load_temp_course_role($coursecontext, $roleid);
        $this->assertEquals($USER->access['ra'][$coursecontext->path][$roleid], $roleid);
        $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
        remove_temp_course_roles($coursecontext);
        $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
        load_temp_course_role($coursecontext, $roleid);
        reload_all_capabilities();
        $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
        $USER = new stdClass();
        $USER->id = 0;

        // Now cross check has_capability() with get_users_by_capability(), each using different code paths,
        // they have to be kept in sync, usually only one of them breaks, so we know when something is wrong,
        // at the same time validate extra restrictions (guest read only no risks, admin exception, non existent and deleted users)
        $contexts = $DB->get_records('context', array(), 'id');
        $contexts = array_values($contexts);
        $capabilities = $DB->get_records('capabilities', array(), 'id');
        $capabilities = array_values($capabilities);
        $roles = array($allroles['guest'], $allroles['user'], $allroles['teacher'], $allroles['editingteacher'], $allroles['coursecreator'], $allroles['manager']);
        $userids = array_values($testusers);
        $userids[] = get_admin()->id;

        if (!PHPUNIT_LONGTEST) {
            $contexts = array_slice($contexts, 0, 10);
            $capabilities = array_slice($capabilities, 0, 5);
            $userids = array_slice($userids, 0, 5);
        }

        // Random time!
        //srand(666);
        foreach($userids as $userid) { // no guest or deleted
            // each user gets 0-10 random roles
            $rcount = rand(0, 10);
            for($j=0; $j<$rcount; $j++) {
                $roleid = $roles[rand(0, count($roles)-1)];
                $contextid = $contexts[rand(0, count($contexts)-1)]->id;
                role_assign($roleid, $userid, $contextid);
            }
        }

        $permissions = array(CAP_ALLOW, CAP_PREVENT, CAP_INHERIT, CAP_PREVENT);
        $maxoverrides = count($contexts)*10;
        for($j=0; $j<$maxoverrides; $j++) {
            $roleid = $roles[rand(0, count($roles)-1)];
            $contextid = $contexts[rand(0, count($contexts)-1)]->id;
            $permission = $permissions[rand(0,count($permissions)-1)];
            $capname = $capabilities[rand(0, count($capabilities)-1)]->name;
            assign_capability($capname, $permission, $roleid, $contextid, true);
        }
        unset($permissions);
        unset($roles);

        accesslib_clear_all_caches(false); // must be done after assign_capability()

        // Test time - let's set up some real user, just in case the logic for USER affects the others...
        $USER = $DB->get_record('user', array('id'=>$testusers[3]));
        load_all_capabilities();

        $userids[] = $CFG->siteguest;
        $userids[] = 0; // not-logged-in user
        $userids[] = -1; // non-existent user

        foreach ($contexts as $crecord) {
            $context = context::instance_by_id($crecord->id);
            if ($coursecontext = $context->get_course_context(false)) {
                $enrolled = get_enrolled_users($context);
            } else {
                $enrolled = array();
            }
            foreach ($capabilities as $cap) {
                $allowed = get_users_by_capability($context, $cap->name, 'u.id, u.username');
                if ($enrolled) {
                    $enrolledwithcap = get_enrolled_users($context, $cap->name);
                } else {
                    $enrolledwithcap = array();
                }
                foreach ($userids as $userid) {
                    if ($userid == 0 or isguestuser($userid)) {
                        if ($userid == 0) {
                            $CFG->forcelogin = true;
                            $this->assertFalse(has_capability($cap->name, $context, $userid));
                            unset($CFG->forcelogin);
                        }
                        if (($cap->captype === 'write') or ($cap->riskbitmask & (RISK_XSS | RISK_CONFIG | RISK_DATALOSS))) {
                            $this->assertFalse(has_capability($cap->name, $context, $userid));
                        }
                        $this->assertFalse(isset($allowed[$userid]));
                    } else {
                        if (is_siteadmin($userid)) {
                            $this->assertTrue(has_capability($cap->name, $context, $userid, true));
                        }
                        $hascap = has_capability($cap->name, $context, $userid, false);
                        $this->assertSame($hascap, isset($allowed[$userid]), "Capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
                        if (isset($enrolled[$userid])) {
                            $this->assertSame(isset($allowed[$userid]), isset($enrolledwithcap[$userid]), "Enrolment with capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
                        }
                    }
                }
            }
        }
        // Back to nobody
        $USER = new stdClass();
        $USER->id = 0;
        unset($contexts);
        unset($userids);
        unset($capabilities);

        // Now let's do all the remaining tests that break our carefully prepared fake site



        // ======= $context->mark_dirty() =======================================

        $DB->delete_records('cache_flags', array());
        accesslib_clear_all_caches(false);
        $systemcontext->mark_dirty();
        $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
        $this->assertTrue(isset($dirty[$systemcontext->path]));
        $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$systemcontext->path]));


        // ======= $context->reload_if_dirty(); =================================

        $DB->delete_records('cache_flags', array());
        accesslib_clear_all_caches(false);
        load_all_capabilities();
        $context = context_course::instance($testcourses[2]);
        $page = $DB->get_record('page', array('course'=>$testcourses[2]));
        $pagecontext = context_module::instance($page->id);

        $context->mark_dirty();
        $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
        $USER->access['test'] = true;
        $context->reload_if_dirty();
        $this->assertFalse(isset($USER->access['test']));

        $context->mark_dirty();
        $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
        $USER->access['test'] = true;
        $pagecontext->reload_if_dirty();
        $this->assertFalse(isset($USER->access['test']));


        // ======= context_helper::build_all_paths() ============================

        $oldcontexts = $DB->get_records('context', array(), 'id');
        $DB->set_field_select('context', 'path', NULL, "contextlevel <> ".CONTEXT_SYSTEM);
        $DB->set_field_select('context', 'depth', 0, "contextlevel <> ".CONTEXT_SYSTEM);
        context_helper::build_all_paths();
        $newcontexts = $DB->get_records('context', array(), 'id');
        $this->assertEquals($oldcontexts, $newcontexts);
        unset($oldcontexts);
        unset($newcontexts);


        // ======= $context->reset_paths() ======================================

        $context = context_course::instance($testcourses[2]);
        $children = $context->get_child_contexts();
        $context->reset_paths(false);
        $this->assertSame($DB->get_field('context', 'path', array('id'=>$context->id)), NULL);
        $this->assertEquals($DB->get_field('context', 'depth', array('id'=>$context->id)), 0);
        foreach ($children as $child) {
            $this->assertSame($DB->get_field('context', 'path', array('id'=>$child->id)), NULL);
            $this->assertEquals($DB->get_field('context', 'depth', array('id'=>$child->id)), 0);
        }
        $this->assertEquals(count($children)+1, $DB->count_records('context', array('depth'=>0)));
        $this->assertEquals(count($children)+1, $DB->count_records('context', array('path'=>NULL)));

        $context = context_course::instance($testcourses[2]);
        $context->reset_paths(true);
        $context = context_course::instance($testcourses[2]);
        $this->assertEquals($DB->get_field('context', 'path', array('id'=>$context->id)), $context->path);
        $this->assertEquals($DB->get_field('context', 'depth', array('id'=>$context->id)), $context->depth);
        $this->assertEquals(0, $DB->count_records('context', array('depth'=>0)));
        $this->assertEquals(0, $DB->count_records('context', array('path'=>NULL)));


        // ====== $context->update_moved(); ======================================

        accesslib_clear_all_caches(false);
        $DB->delete_records('cache_flags', array());
        $course = $DB->get_record('course', array('id'=>$testcourses[0]));
        $context = context_course::instance($course->id);
        $oldpath = $context->path;
        $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
        $categorycontext = context_coursecat::instance($miscid);
        $course->category = $miscid;
        $DB->update_record('course', $course);
        $context->update_moved($categorycontext);

        $context = context_course::instance($course->id);
        $this->assertEquals($context->get_parent_context(), $categorycontext);
        $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
        $this->assertTrue(isset($dirty[$oldpath]));
        $this->assertTrue(isset($dirty[$context->path]));


        // ====== $context->delete_content() =====================================

        context_helper::reset_caches();
        $context = context_module::instance($testpages[3]);
        $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
        $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
        $context->delete_content();
        $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
        $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));


        // ====== $context->delete() =============================

        context_helper::reset_caches();
        $context = context_module::instance($testpages[4]);
        $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
        $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
        $bi = $DB->get_record('block_instances', array('parentcontextid'=>$context->id));
        $bicontext = context_block::instance($bi->id);
        $DB->delete_records('cache_flags', array());
        $context->delete(); // should delete also linked blocks
        $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
        $this->assertTrue(isset($dirty[$context->path]));
        $this->assertFalse($DB->record_exists('context', array('id'=>$context->id)));
        $this->assertFalse($DB->record_exists('context', array('id'=>$bicontext->id)));
        $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_MODULE, 'instanceid'=>$testpages[4])));
        $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK, 'instanceid'=>$bi->id)));
        $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
        context_module::instance($testpages[4]);


        // ====== context_helper::delete_instance() =============================

        context_helper::reset_caches();
        $lastcourse = array_pop($testcourses);
        $this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
        $coursecontext = context_course::instance($lastcourse);
        $this->assertEquals(context_inspection::test_context_cache_size(), 1);
        $this->assertFalse($coursecontext->instanceid == CONTEXT_COURSE);
        $DB->delete_records('cache_flags', array());
        context_helper::delete_instance(CONTEXT_COURSE, $lastcourse);
        $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
        $this->assertTrue(isset($dirty[$coursecontext->path]));
        $this->assertEquals(context_inspection::test_context_cache_size(), 0);
        $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
        context_course::instance($lastcourse);


        // ======= context_helper::create_instances() ==========================

        $prevcount = $DB->count_records('context');
        $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
        context_helper::create_instances(null, true);
        $this->assertSame($DB->count_records('context'), $prevcount);
        $this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
        $this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);

        $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
        $DB->delete_records('block_instances', array());
        $prevcount = $DB->count_records('context');
        $DB->delete_records_select('context', 'contextlevel <> '.CONTEXT_SYSTEM);
        context_helper::create_instances(null, true);
        $this->assertSame($DB->count_records('context'), $prevcount);
        $this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
        $this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);


        // ======= context_helper::cleanup_instances() ==========================

        $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
        $DB->delete_records('course', array('id'=>$lastcourse));
        $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
        $DB->delete_records('course_categories', array('id'=>$lastcategory));
        $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
        $DB->delete_records('user', array('id'=>$lastuser));
        $DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id));
        $DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid));
        context_helper::cleanup_instances();
        $count = 1; //system
        $count += $DB->count_records('user', array('deleted'=>0));
        $count += $DB->count_records('course_categories');
        $count += $DB->count_records('course');
        $count += $DB->count_records('course_modules');
        $count += $DB->count_records('block_instances');
        $this->assertEquals($DB->count_records('context'), $count);


        // ======= context cache size restrictions ==============================

        $testusers= array();
        for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
            $user = $generator->create_user();
            $testusers[$i] = $user->id;
        }
        context_helper::create_instances(null, true);
        context_helper::reset_caches();
        for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
            context_user::instance($testusers[$i]);
            if ($i == CONTEXT_CACHE_MAX_SIZE - 1) {
                $this->assertEquals(context_inspection::test_context_cache_size(), CONTEXT_CACHE_MAX_SIZE);
            } else if ($i == CONTEXT_CACHE_MAX_SIZE) {
                // once the limit is reached roughly 1/3 of records should be removed from cache
                $this->assertEquals(context_inspection::test_context_cache_size(), (int)(CONTEXT_CACHE_MAX_SIZE * (2/3) +102));
            }
        }
        // We keep the first 100 cached
        $prevsize = context_inspection::test_context_cache_size();
        for ($i=0; $i<100; $i++) {
            context_user::instance($testusers[$i]);
            $this->assertEquals(context_inspection::test_context_cache_size(), $prevsize);
        }
        context_user::instance($testusers[102]);
        $this->assertEquals(context_inspection::test_context_cache_size(), $prevsize+1);
        unset($testusers);



        // =================================================================
        // ======= basic test of legacy functions ==========================
        // =================================================================
        // note: watch out, the fake site might be pretty borked already

        $this->assertSame(get_system_context(), context_system::instance());

        foreach ($DB->get_records('context') as $contextid=>$record) {
            $context = context::instance_by_id($contextid);
            $this->assertSame(get_context_instance_by_id($contextid), $context);
            $this->assertSame(get_context_instance($record->contextlevel, $record->instanceid), $context);
            $this->assertSame(get_parent_contexts($context), $context->get_parent_context_ids());
            if ($context->id == SYSCONTEXTID) {
                $this->assertSame(get_parent_contextid($context), false);
            } else {
                $this->assertSame(get_parent_contextid($context), $context->get_parent_context()->id);
            }
        }

        $CFG->debug = 0;
        $children = get_child_contexts($systemcontext);
        $CFG->debug = DEBUG_DEVELOPER;
        $this->assertEquals(count($children), $DB->count_records('context')-1);
        unset($children);

        $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
        create_contexts();
        $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK)));

        $DB->set_field('context', 'depth', 0, array('contextlevel'=>CONTEXT_BLOCK));
        build_context_path();
        $this->assertFalse($DB->record_exists('context', array('depth'=>0)));

        $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
        $DB->delete_records('course', array('id'=>$lastcourse));
        $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
        $DB->delete_records('course_categories', array('id'=>$lastcategory));
        $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
        $DB->delete_records('user', array('id'=>$lastuser));
        $DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id));
        $DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid));
        cleanup_contexts();
        $count = 1; //system
        $count += $DB->count_records('user', array('deleted'=>0));
        $count += $DB->count_records('course_categories');
        $count += $DB->count_records('course');
        $count += $DB->count_records('course_modules');
        $count += $DB->count_records('block_instances');
        $this->assertEquals($DB->count_records('context'), $count);

        context_helper::reset_caches();
        preload_course_contexts($SITE->id);
        $this->assertEquals(context_inspection::test_context_cache_size(), 1);

        context_helper::reset_caches();
        list($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSECAT, 'ctx');
        $sql = "SELECT c.id $select FROM {course_categories} c $join";
        $records = $DB->get_records_sql($sql);
        foreach ($records as $record) {
            context_instance_preload($record);
            $record = (array)$record;
            $this->assertEquals(1, count($record)); // only id left
        }
        $this->assertEquals(count($records), context_inspection::test_context_cache_size());

        accesslib_clear_all_caches(true);
        $DB->delete_records('cache_flags', array());
        mark_context_dirty($systemcontext->path);
        $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
        $this->assertTrue(isset($dirty[$systemcontext->path]));

        accesslib_clear_all_caches(false);
        $DB->delete_records('cache_flags', array());
        $course = $DB->get_record('course', array('id'=>$testcourses[2]));
        $context = get_context_instance(CONTEXT_COURSE, $course->id);
        $oldpath = $context->path;
        $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
        $categorycontext = context_coursecat::instance($miscid);
        $course->category = $miscid;
        $DB->update_record('course', $course);
        context_moved($context, $categorycontext);
        $context = get_context_instance(CONTEXT_COURSE, $course->id);
        $this->assertEquals($context->get_parent_context(), $categorycontext);

        $this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2])));
        delete_context(CONTEXT_COURSE, $testcourses[2]);
        $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2])));

        $name = get_contextlevel_name(CONTEXT_COURSE);
        $this->assertFalse(empty($name));

        $context = get_context_instance(CONTEXT_COURSE, $testcourses[2]);
        $name = print_context_name($context);
        $this->assertFalse(empty($name));

        $url = get_context_url($coursecontext);
        $this->assertFalse($url instanceof modole_url);

        $page = $DB->get_record('page', array('id'=>$testpages[7]));
        $context = get_context_instance(CONTEXT_MODULE, $page->id);
        $coursecontext = get_course_context($context);
        $this->assertEquals($coursecontext->contextlevel, CONTEXT_COURSE);
        $this->assertEquals(get_courseid_from_context($context), $page->course);

        $caps = fetch_context_capabilities($systemcontext);
        $this->assertTrue(is_array($caps));
        unset($caps);
    }