コード例 #1
0
function xmldb_enrol_delayedcohort_uninstall()
{
    global $CFG, $DB;
    $cohort = enrol_get_plugin('delayedcohort');
    $rs = $DB->get_recordset('enrol', array('enrol' => 'delayedcohort'));
    foreach ($rs as $instance) {
        $cohort->delete_instance($instance);
    }
    $rs->close();
    role_unassign_all(array('component' => 'enrol_delayedcohort'));
    return true;
}
コード例 #2
0
function xmldb_enrol_metaplus_uninstall()
{
    global $CFG, $DB;
    $meta = enrol_get_plugin('metaplus');
    $rs = $DB->get_recordset('enrol', array('enrol' => 'metaplus'));
    foreach ($rs as $instance) {
        $meta->delete_instance($instance);
    }
    $rs->close();
    role_unassign_all(array('component' => 'enrol_metaplus'));
    return true;
}
コード例 #3
0
ファイル: lib.php プロジェクト: vuchannguyen/web
 /**
  * Forces synchronisation of all enrolments with external database.
  *
  * @return void
  */
 public function sync_enrolments()
 {
     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')) {
         return;
     }
     // we may need a lot of memory here
     @set_time_limit(0);
     raise_memory_limit(MEMORY_HUGE);
     $extdb = $this->db_init();
     // 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');
     $localcoursefiled = $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;
     }
     // first find all existing courses with enrol instance
     $sql = "SELECT c.id, c.visible, c.{$localcoursefiled} AS mapping, e.id AS enrolid\n                  FROM {course} c\n                  JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'database')";
     $existing = array();
     $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;
     $sql = $this->db_get_sql($table, array(), array($coursefield), true);
     if ($rs = $extdb->Execute($sql)) {
         if (!$rs->EOF) {
             $sql = "SELECT c.id, c.visible\n                          FROM {course} c\n                          JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'database')\n                         WHERE c.{$localcoursefiled} = :mapping";
             $params = array();
             while ($mapping = $rs->FetchRow()) {
                 $mapping = reset($mapping);
                 $mapping = $this->db_decode($mapping);
                 if (!empty($mapping) and !isset($existing[$mapping])) {
                     $params['mapping'] = $mapping;
                     if ($course = $DB->get_record_sql($sql, $params, IGNORE_MULTIPLE)) {
                         $new = new stdClass();
                         $new->id = $course->id;
                         $new->visible = $course->visible;
                         $new->mapping = $mapping;
                         $new->enrolid = $this->add_instance($course);
                         $existing[$mapping] = $new;
                     }
                 }
             }
         }
         $rs->Close();
     } else {
         debugging('Error while communicating with external enrolment database');
         $extdb->Close();
         return;
     }
     // sync enrolments
     $ignorehidden = $this->get_config('ignorehiddencourses');
     $fields = array($userfield);
     if ($rolefield) {
         $fields[] = $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), $fields);
         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 {
             debugging('Error while communicating with external enrolment database');
             $extdb->Close();
             return;
         }
         unset($user_mapping);
         // enrol all users and sync roles
         foreach ($requested_roles as $userid => $roles) {
             foreach ($roles as $roleid) {
                 if (empty($current_roles[$userid])) {
                     $this->enrol_user($instance, $userid, $roleid);
                     $current_roles[$userid][$roleid] = $roleid;
                     $current_status[$userid] = ENROL_USER_ACTIVE;
                 }
             }
             // unassign removed roles
             foreach ($current_roles[$userid] as $cr) {
                 if (empty($roles[$cr])) {
                     role_unassign($cr, $userid, $context->id, 'enrol_database', $instance->id);
                     unset($current_roles[$userid][$cr]);
                 }
             }
             // reenable enrolment when previously disable enrolment refreshed
             if ($current_status[$userid] == ENROL_USER_SUSPENDED) {
                 $DB->set_field('user_enrolments', 'status', ENROL_USER_ACTIVE, array('enrolid' => $instance->id, 'userid' => $userid));
             }
         }
         // deal with enrolments removed from external table
         if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
             // unenrol
             if (!empty($requested_roles)) {
                 // we might get some error or connection problem, better not unenrol everybody
                 foreach ($current_status as $userid => $status) {
                     if (isset($requested_roles[$userid])) {
                         continue;
                     }
                     $this->unenrol_user($instance, $userid);
                 }
             }
         } 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) {
                             $DB->set_field('user_enrolments', 'status', ENROL_USER_SUSPENDED, array('enrolid' => $instance->id, 'userid' => $userid));
                         }
                         if ($unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
                             role_unassign_all(array('contextid' => $context->id, 'userid' => $userid, 'component' => 'enrol_database', 'itemid' => $instance->id));
                         }
                     }
                 }
             }
         }
     }
     // close db connection
     $extdb->Close();
 }
コード例 #4
0
ファイル: lib.php プロジェクト: masaterutakeno/MoodleMobile
 /**
  * Sync all meta course links.
  *
  * @param progress_trace $trace
  * @param int $courseid one course, empty mean all
  * @return int 0 means ok, 1 means error, 2 means plugin disabled
  */
 public function sync(progress_trace $trace, $courseid = null)
 {
     global $DB;
     if (!enrol_is_enabled('manual')) {
         $trace->finished();
         return 2;
     }
     // Unfortunately this may take a long time, execution can be interrupted safely here.
     @set_time_limit(0);
     raise_memory_limit(MEMORY_HUGE);
     $trace->output('Verifying manual enrolment expiration...');
     $params = array('now' => time(), 'useractive' => ENROL_USER_ACTIVE, 'courselevel' => CONTEXT_COURSE);
     $coursesql = "";
     if ($courseid) {
         $coursesql = "AND e.courseid = :courseid";
         $params['courseid'] = $courseid;
     }
     // 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 = 'manual')\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];
             // Always remove all manually assigned roles here, this may break enrol_self roles but we do not want hardcoded hacks here.
             role_unassign_all(array('userid' => $ue->userid, 'contextid' => $ue->contextid, 'component' => '', 'itemid' => 0), true);
             $this->unenrol_user($instance, $ue->userid);
             $trace->output("unenrolling expired user {$ue->userid} from course {$instance->courseid}", 1);
         }
         $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 = 'manual')\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];
                 // Always remove all manually assigned roles here, this may break enrol_self roles but we do not want hardcoded hacks here.
                 role_unassign_all(array('userid' => $ue->userid, 'contextid' => $ue->contextid, 'component' => '', 'itemid' => 0), true);
                 $this->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED);
                 $trace->output("suspending expired user {$ue->userid} in course {$instance->courseid}", 1);
             }
             $rs->close();
             unset($instances);
         } else {
             // ENROL_EXT_REMOVED_KEEP means no changes.
         }
     }
     $trace->output('...manual enrolment updates finished.');
     $trace->finished();
     return 0;
 }
コード例 #5
0
ファイル: lib.php プロジェクト: vinoth4891/clinique
 /**
  * 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;
 }
コード例 #6
0
ファイル: moodlelib.php プロジェクト: lucaboesch/moodle
/**
 * 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, $DB;
    require_once $CFG->libdir . '/gradelib.php';
    require_once $CFG->libdir . '/completionlib.php';
    require_once $CFG->dirroot . '/group/lib.php';
    $data->courseid = $data->id;
    $context = context_course::instance($data->courseid);
    $eventparams = array('context' => $context, 'courseid' => $data->id, 'other' => array('reset_options' => (array) $data));
    $event = \core\event\course_reset_started::create($eventparams);
    $event->trigger();
    // 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.
        $DB->set_field('course', 'startdate', $data->reset_start_date, array('id' => $data->courseid));
        // Update all course and group events - do not move activity events.
        $updatesql = "UPDATE {event}\n                         SET timestart = timestart + ?\n                       WHERE courseid=? AND instance=0";
        $DB->execute($updatesql, array($data->timeshift, $data->courseid));
        // Update any date activity restrictions.
        if ($CFG->enableavailability) {
            \availability_date\condition::update_all_dates($data->courseid, $data->timeshift);
        }
        $status[] = array('component' => $componentstr, 'item' => get_string('datechanged'), 'error' => false);
    }
    if (!empty($data->reset_end_date)) {
        // If the user set a end date value respect it.
        $DB->set_field('course', 'enddate', $data->reset_end_date, array('id' => $data->courseid));
    } else {
        if ($data->timeshift > 0 && $data->reset_end_date_old) {
            // If there is a time shift apply it to the end date as well.
            $enddate = $data->reset_end_date_old + $data->timeshift;
            $DB->set_field('course', 'enddate', $enddate, array('id' => $data->courseid));
        }
    }
    if (!empty($data->reset_events)) {
        $DB->delete_records('event', array('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);
    }
    if (!empty($data->delete_blog_associations)) {
        require_once $CFG->dirroot . '/blog/lib.php';
        blog_remove_associations_for_course($data->courseid);
        $status[] = array('component' => $componentstr, 'item' => get_string('deleteblogassociations', 'blog'), 'error' => false);
    }
    if (!empty($data->reset_completion)) {
        // Delete course and activity completion information.
        $course = $DB->get_record('course', array('id' => $data->courseid));
        $cc = new completion_info($course);
        $cc->delete_all_completion_data();
        $status[] = array('component' => $componentstr, 'item' => get_string('deletecompletiondata', 'completion'), 'error' => false);
    }
    if (!empty($data->reset_competency_ratings)) {
        \core_competency\api::hook_course_reset_competency_ratings($data->courseid);
        $status[] = array('component' => $componentstr, 'item' => get_string('deletecompetencyratings', 'core_competency'), 'error' => false);
    }
    $componentstr = get_string('roles');
    if (!empty($data->reset_roles_overrides)) {
        $children = $context->get_child_contexts();
        foreach ($children as $child) {
            $DB->delete_records('role_capabilities', array('contextid' => $child->id));
        }
        $DB->delete_records('role_capabilities', array('contextid' => $context->id));
        // Force refresh for logged in users.
        $context->mark_dirty();
        $status[] = array('component' => $componentstr, 'item' => get_string('deletecourseoverrides', 'role'), 'error' => false);
    }
    if (!empty($data->reset_roles_local)) {
        $children = $context->get_child_contexts();
        foreach ($children as $child) {
            role_unassign_all(array('contextid' => $child->id));
        }
        // Force refresh for logged in users.
        $context->mark_dirty();
        $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->unenrol_users)) {
        $plugins = enrol_get_plugins(true);
        $instances = enrol_get_instances($data->courseid, true);
        foreach ($instances as $key => $instance) {
            if (!isset($plugins[$instance->enrol])) {
                unset($instances[$key]);
                continue;
            }
        }
        foreach ($data->unenrol_users as $withroleid) {
            if ($withroleid) {
                $sql = "SELECT ue.*\n                          FROM {user_enrolments} ue\n                          JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid)\n                          JOIN {context} c ON (c.contextlevel = :courselevel AND c.instanceid = e.courseid)\n                          JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.roleid = :roleid AND ra.userid = ue.userid)";
                $params = array('courseid' => $data->courseid, 'roleid' => $withroleid, 'courselevel' => CONTEXT_COURSE);
            } else {
                // Without any role assigned at course context.
                $sql = "SELECT ue.*\n                          FROM {user_enrolments} ue\n                          JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid)\n                          JOIN {context} c ON (c.contextlevel = :courselevel AND c.instanceid = e.courseid)\n                     LEFT JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.userid = ue.userid)\n                         WHERE ra.id IS null";
                $params = array('courseid' => $data->courseid, 'courselevel' => CONTEXT_COURSE);
            }
            $rs = $DB->get_recordset_sql($sql, $params);
            foreach ($rs as $ue) {
                if (!isset($instances[$ue->enrolid])) {
                    continue;
                }
                $instance = $instances[$ue->enrolid];
                $plugin = $plugins[$instance->enrol];
                if (!$plugin->allow_unenrol($instance) and !$plugin->allow_unenrol_user($instance, $ue)) {
                    continue;
                }
                $plugin->unenrol_user($instance, $ue->userid);
                $data->unenrolled[$ue->userid] = $ue->userid;
            }
            $rs->close();
        }
    }
    if (!empty($data->unenrolled)) {
        $status[] = array('component' => $componentstr, 'item' => get_string('unenrol', 'enrol') . ' (' . 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.
    $unsupportedmods = array();
    if ($allmods = $DB->get_records('modules')) {
        foreach ($allmods as $mod) {
            $modname = $mod->name;
            $modfile = $CFG->dirroot . '/mod/' . $modname . '/lib.php';
            $moddeleteuserdata = $modname . '_reset_userdata';
            // Function to delete user data.
            if (file_exists($modfile)) {
                if (!$DB->count_records($modname, array('course' => $data->courseid))) {
                    continue;
                    // Skip mods with no instances.
                }
                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 {
                    $unsupportedmods[] = $mod;
                }
            } else {
                debugging('Missing lib.php in ' . $modname . ' module!');
            }
        }
    }
    // Mention unsupported mods.
    if (!empty($unsupportedmods)) {
        foreach ($unsupportedmods 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);
        }
    }
    // Reset comments.
    if (!empty($data->reset_comments)) {
        require_once $CFG->dirroot . '/comment/lib.php';
        comment::reset_course_page_comments($context);
    }
    $event = \core\event\course_reset_ended::create($eventparams);
    $event->trigger();
    return $status;
}
コード例 #7
0
ファイル: lib.php プロジェクト: abhilash1994/moodle
 /**
  * Forces synchronisation of all enrolments with LDAP server.
  * It creates courses if the plugin is configured to do so.
  *
  * @param progress_trace $trace
  * @param int|null $onecourse limit sync to one course->id, null if all courses
  * @return void
  */
 public function sync_enrolments(progress_trace $trace, $onecourse = null)
 {
     global $CFG, $DB;
     if (!$this->ldap_connect($trace)) {
         $trace->finished();
         return;
     }
     $ldap_pagedresults = ldap_paged_results_supported($this->get_config('ldap_version'));
     // we may need a lot of memory here
     core_php_time_limit::raise();
     raise_memory_limit(MEMORY_HUGE);
     $oneidnumber = null;
     if ($onecourse) {
         if (!($course = $DB->get_record('course', array('id' => $onecourse), 'id,' . $this->enrol_localcoursefield))) {
             // Course does not exist, nothing to do.
             $trace->output("Requested course {$onecourse} does not exist, no sync performed.");
             $trace->finished();
             return;
         }
         if (empty($course->{$this->enrol_localcoursefield})) {
             $trace->output("Requested course {$onecourse} does not have {$this->enrol_localcoursefield}, no sync performed.");
             $trace->finished();
             return;
         }
         $oneidnumber = ldap_filter_addslashes(core_text::convert($course->idnumber, 'utf-8', $this->get_config('ldapencoding')));
     }
     // Get enrolments for each type of role.
     $roles = get_all_roles();
     $enrolments = array();
     foreach ($roles as $role) {
         // Get all contexts
         $ldap_contexts = explode(';', $this->config->{'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', $this->config->course_idnumber);
         if (!empty($this->config->course_fullname)) {
             array_push($ldap_fields_wanted, $this->config->course_fullname);
         }
         if (!empty($this->config->course_shortname)) {
             array_push($ldap_fields_wanted, $this->config->course_shortname);
         }
         if (!empty($this->config->course_summary)) {
             array_push($ldap_fields_wanted, $this->config->course_summary);
         }
         array_push($ldap_fields_wanted, $this->config->{'memberattribute_role' . $role->id});
         // Define the search pattern
         $ldap_search_pattern = $this->config->objectclass;
         if ($oneidnumber !== null) {
             $ldap_search_pattern = "(&{$ldap_search_pattern}({$this->config->course_idnumber}={$oneidnumber}))";
         }
         $ldap_cookie = '';
         foreach ($ldap_contexts as $ldap_context) {
             $ldap_context = trim($ldap_context);
             if (empty($ldap_context)) {
                 continue;
                 // Next;
             }
             $flat_records = array();
             do {
                 if ($ldap_pagedresults) {
                     ldap_control_paged_result($this->ldapconnection, $this->config->pagesize, true, $ldap_cookie);
                 }
                 if ($this->config->course_search_sub) {
                     // Use ldap_search to find first user from subtree
                     $ldap_result = @ldap_search($this->ldapconnection, $ldap_context, $ldap_search_pattern, $ldap_fields_wanted);
                 } else {
                     // Search only in this context
                     $ldap_result = @ldap_list($this->ldapconnection, $ldap_context, $ldap_search_pattern, $ldap_fields_wanted);
                 }
                 if (!$ldap_result) {
                     continue;
                     // Next
                 }
                 if ($ldap_pagedresults) {
                     ldap_control_paged_result_response($this->ldapconnection, $ldap_result, $ldap_cookie);
                 }
                 // Check and push results
                 $records = ldap_get_entries($this->ldapconnection, $ldap_result);
                 // LDAP libraries return an odd array, really. fix it:
                 for ($c = 0; $c < $records['count']; $c++) {
                     array_push($flat_records, $records[$c]);
                 }
                 // Free some mem
                 unset($records);
             } while ($ldap_pagedresults && !empty($ldap_cookie));
             // If LDAP paged results were used, the current connection must be completely
             // closed and a new one created, to work without paged results from here on.
             if ($ldap_pagedresults) {
                 $this->ldap_close();
                 $this->ldap_connect($trace);
             }
             if (count($flat_records)) {
                 $ignorehidden = $this->get_config('ignorehiddencourses');
                 foreach ($flat_records as $course) {
                     $course = array_change_key_case($course, CASE_LOWER);
                     $idnumber = $course[$this->config->course_idnumber][0];
                     $trace->output(get_string('synccourserole', 'enrol_ldap', array('idnumber' => $idnumber, 'role_shortname' => $role->shortname)));
                     // Does the course exist in moodle already?
                     $course_obj = $DB->get_record('course', array($this->enrol_localcoursefield => $idnumber));
                     if (empty($course_obj)) {
                         // Course doesn't exist
                         if ($this->get_config('autocreate')) {
                             // Autocreate
                             $trace->output(get_string('createcourseextid', 'enrol_ldap', array('courseextid' => $idnumber)));
                             if (!($newcourseid = $this->create_course($course, $trace))) {
                                 continue;
                             }
                             $course_obj = $DB->get_record('course', array('id' => $newcourseid));
                         } else {
                             $trace->output(get_string('createnotcourseextid', 'enrol_ldap', array('courseextid' => $idnumber)));
                             continue;
                             // Next; skip this one!
                         }
                     } else {
                         // Check if course needs update & update as needed.
                         $this->update_course($course_obj, $course, $trace);
                     }
                     // Enrol & unenrol
                     // Pull the ldap membership into a nice array
                     // this is an odd array -- mix of hash and array --
                     $ldapmembers = array();
                     if (array_key_exists('memberattribute_role' . $role->id, $this->config) && !empty($this->config->{'memberattribute_role' . $role->id}) && !empty($course[$this->config->{'memberattribute_role' . $role->id}])) {
                         // May have no membership!
                         $ldapmembers = $course[$this->config->{'memberattribute_role' . $role->id}];
                         unset($ldapmembers['count']);
                         // Remove oddity ;)
                         // If we have enabled nested groups, we need to expand
                         // the groups to get the real user list. We need to do
                         // this before dealing with 'memberattribute_isdn'.
                         if ($this->config->nested_groups) {
                             $users = array();
                             foreach ($ldapmembers as $ldapmember) {
                                 $grpusers = $this->ldap_explode_group($ldapmember, $this->config->{'memberattribute_role' . $role->id});
                                 $users = array_merge($users, $grpusers);
                             }
                             $ldapmembers = array_unique($users);
                             // There might be duplicates.
                         }
                         // Deal with the case where the member attribute holds distinguished names,
                         // but only if the user attribute is not a distinguished name itself.
                         if ($this->config->memberattribute_isdn && $this->config->idnumber_attribute !== 'dn' && $this->config->idnumber_attribute !== 'distinguishedname') {
                             // We need to retrieve the idnumber for all the users in $ldapmembers,
                             // as the idnumber does not match their dn and we get dn's from membership.
                             $memberidnumbers = array();
                             foreach ($ldapmembers as $ldapmember) {
                                 $result = ldap_read($this->ldapconnection, $ldapmember, '(objectClass=*)', array($this->config->idnumber_attribute));
                                 $entry = ldap_first_entry($this->ldapconnection, $result);
                                 $values = ldap_get_values($this->ldapconnection, $entry, $this->config->idnumber_attribute);
                                 array_push($memberidnumbers, $values[0]);
                             }
                             $ldapmembers = $memberidnumbers;
                         }
                     }
                     // Prune old ldap enrolments
                     // hopefully they'll fit in the max buffer size for the RDBMS
                     $sql = "SELECT u.id as userid, u.username, ue.status,\n                                      ra.contextid, ra.itemid as instanceid\n                                 FROM {user} u\n                                 JOIN {role_assignments} ra ON (ra.userid = u.id AND ra.component = 'enrol_ldap' AND ra.roleid = :roleid)\n                                 JOIN {user_enrolments} ue ON (ue.userid = u.id AND ue.enrolid = ra.itemid)\n                                 JOIN {enrol} e ON (e.id = ue.enrolid)\n                                WHERE u.deleted = 0 AND e.courseid = :courseid ";
                     $params = array('roleid' => $role->id, 'courseid' => $course_obj->id);
                     $context = context_course::instance($course_obj->id);
                     if (!empty($ldapmembers)) {
                         list($ldapml, $params2) = $DB->get_in_or_equal($ldapmembers, SQL_PARAMS_NAMED, 'm', false);
                         $sql .= "AND u.idnumber {$ldapml}";
                         $params = array_merge($params, $params2);
                         unset($params2);
                     } else {
                         $shortname = format_string($course_obj->shortname, true, array('context' => $context));
                         $trace->output(get_string('emptyenrolment', 'enrol_ldap', array('role_shortname' => $role->shortname, 'course_shortname' => $shortname)));
                     }
                     $todelete = $DB->get_records_sql($sql, $params);
                     if (!empty($todelete)) {
                         $transaction = $DB->start_delegated_transaction();
                         foreach ($todelete as $row) {
                             $instance = $DB->get_record('enrol', array('id' => $row->instanceid));
                             switch ($this->get_config('unenrolaction')) {
                                 case ENROL_EXT_REMOVED_UNENROL:
                                     $this->unenrol_user($instance, $row->userid);
                                     $trace->output(get_string('extremovedunenrol', 'enrol_ldap', array('user_username' => $row->username, 'course_shortname' => $course_obj->shortname, 'course_id' => $course_obj->id)));
                                     break;
                                 case ENROL_EXT_REMOVED_KEEP:
                                     // Keep - only adding enrolments
                                     break;
                                 case ENROL_EXT_REMOVED_SUSPEND:
                                     if ($row->status != ENROL_USER_SUSPENDED) {
                                         $DB->set_field('user_enrolments', 'status', ENROL_USER_SUSPENDED, array('enrolid' => $instance->id, 'userid' => $row->userid));
                                         $trace->output(get_string('extremovedsuspend', 'enrol_ldap', array('user_username' => $row->username, 'course_shortname' => $course_obj->shortname, 'course_id' => $course_obj->id)));
                                     }
                                     break;
                                 case ENROL_EXT_REMOVED_SUSPENDNOROLES:
                                     if ($row->status != ENROL_USER_SUSPENDED) {
                                         $DB->set_field('user_enrolments', 'status', ENROL_USER_SUSPENDED, array('enrolid' => $instance->id, 'userid' => $row->userid));
                                     }
                                     role_unassign_all(array('contextid' => $row->contextid, 'userid' => $row->userid, 'component' => 'enrol_ldap', 'itemid' => $instance->id));
                                     $trace->output(get_string('extremovedsuspendnoroles', 'enrol_ldap', array('user_username' => $row->username, 'course_shortname' => $course_obj->shortname, 'course_id' => $course_obj->id)));
                                     break;
                             }
                         }
                         $transaction->allow_commit();
                     }
                     // Insert current enrolments
                     // bad we can't do INSERT IGNORE with postgres...
                     // Add necessary enrol instance if not present yet;
                     $sql = "SELECT c.id, c.visible, e.id as enrolid\n                                  FROM {course} c\n                                  JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'ldap')\n                                 WHERE c.id = :courseid";
                     $params = array('courseid' => $course_obj->id);
                     if (!($course_instance = $DB->get_record_sql($sql, $params, IGNORE_MULTIPLE))) {
                         $course_instance = new stdClass();
                         $course_instance->id = $course_obj->id;
                         $course_instance->visible = $course_obj->visible;
                         $course_instance->enrolid = $this->add_instance($course_instance);
                     }
                     if (!($instance = $DB->get_record('enrol', array('id' => $course_instance->enrolid)))) {
                         continue;
                         // Weird; skip this one.
                     }
                     if ($ignorehidden && !$course_instance->visible) {
                         continue;
                     }
                     $transaction = $DB->start_delegated_transaction();
                     foreach ($ldapmembers as $ldapmember) {
                         $sql = 'SELECT id,username,1 FROM {user} WHERE idnumber = ? AND deleted = 0';
                         $member = $DB->get_record_sql($sql, array($ldapmember));
                         if (empty($member) || empty($member->id)) {
                             $trace->output(get_string('couldnotfinduser', 'enrol_ldap', $ldapmember));
                             continue;
                         }
                         $sql = "SELECT ue.status\n                                     FROM {user_enrolments} ue\n                                     JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'ldap')\n                                    WHERE e.courseid = :courseid AND ue.userid = :userid";
                         $params = array('courseid' => $course_obj->id, 'userid' => $member->id);
                         $userenrolment = $DB->get_record_sql($sql, $params, IGNORE_MULTIPLE);
                         if (empty($userenrolment)) {
                             $this->enrol_user($instance, $member->id, $role->id);
                             // Make sure we set the enrolment status to active. If the user wasn't
                             // previously enrolled to the course, enrol_user() sets it. But if we
                             // configured the plugin to suspend the user enrolments _AND_ remove
                             // the role assignments on external unenrol, then enrol_user() doesn't
                             // set it back to active on external re-enrolment. So set it
                             // unconditionally to cover both cases.
                             $DB->set_field('user_enrolments', 'status', ENROL_USER_ACTIVE, array('enrolid' => $instance->id, 'userid' => $member->id));
                             $trace->output(get_string('enroluser', 'enrol_ldap', array('user_username' => $member->username, 'course_shortname' => $course_obj->shortname, 'course_id' => $course_obj->id)));
                         } else {
                             if (!$DB->record_exists('role_assignments', array('roleid' => $role->id, 'userid' => $member->id, 'contextid' => $context->id, 'component' => 'enrol_ldap', 'itemid' => $instance->id))) {
                                 // This happens when reviving users or when user has multiple roles in one course.
                                 $context = context_course::instance($course_obj->id);
                                 role_assign($role->id, $member->id, $context->id, 'enrol_ldap', $instance->id);
                                 $trace->output("Assign role to user '{$member->username}' in course '{$course_obj->shortname} ({$course_obj->id})'");
                             }
                             if ($userenrolment->status == ENROL_USER_SUSPENDED) {
                                 // Reenable enrolment that was previously disabled. Enrolment refreshed
                                 $DB->set_field('user_enrolments', 'status', ENROL_USER_ACTIVE, array('enrolid' => $instance->id, 'userid' => $member->id));
                                 $trace->output(get_string('enroluserenable', 'enrol_ldap', array('user_username' => $member->username, 'course_shortname' => $course_obj->shortname, 'course_id' => $course_obj->id)));
                             }
                         }
                     }
                     $transaction->allow_commit();
                 }
             }
         }
     }
     @$this->ldap_close();
     $trace->finished();
 }
コード例 #8
0
ファイル: moodlelib.php プロジェクト: hitphp/moodle
/**
 * 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, $DB;
    require_once $CFG->libdir . '/gradelib.php';
    require_once $CFG->libdir . '/completionlib.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
        $DB->set_field('course', 'startdate', $data->reset_start_date, array('id' => $data->courseid));
        // update all course and group events - do not move activity events
        $updatesql = "UPDATE {event}\n                         SET timestart = timestart + ?\n                       WHERE courseid=? AND instance=0";
        $DB->execute($updatesql, array($data->timeshift, $data->courseid));
        $status[] = array('component' => $componentstr, 'item' => get_string('datechanged'), 'error' => false);
    }
    if (!empty($data->reset_logs)) {
        $DB->delete_records('log', array('course' => $data->courseid));
        $status[] = array('component' => $componentstr, 'item' => get_string('deletelogs'), 'error' => false);
    }
    if (!empty($data->reset_events)) {
        $DB->delete_records('event', array('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);
    }
    if (!empty($data->delete_blog_associations)) {
        require_once $CFG->dirroot . '/blog/lib.php';
        blog_remove_associations_for_course($data->courseid);
        $status[] = array('component' => $componentstr, 'item' => get_string('deleteblogassociations', 'blog'), 'error' => false);
    }
    if (!empty($data->reset_course_completion)) {
        // Delete course completion information
        $course = $DB->get_record('course', array('id' => $data->courseid));
        $cc = new completion_info($course);
        $cc->delete_course_completion_data();
        $status[] = array('component' => $componentstr, 'item' => get_string('deletecoursecompletiondata', 'completion'), 'error' => false);
    }
    $componentstr = get_string('roles');
    if (!empty($data->reset_roles_overrides)) {
        $children = get_child_contexts($context);
        foreach ($children as $child) {
            $DB->delete_records('role_capabilities', array('contextid' => $child->id));
        }
        $DB->delete_records('role_capabilities', array('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_all(array('contextid' => $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->unenrol_users)) {
        $plugins = enrol_get_plugins(true);
        $instances = enrol_get_instances($data->courseid, true);
        foreach ($instances as $key => $instance) {
            if (!isset($plugins[$instance->enrol])) {
                unset($instances[$key]);
                continue;
            }
            if (!$plugins[$instance->enrol]->allow_unenrol($instance)) {
                unset($instances[$key]);
            }
        }
        $sqlempty = $DB->sql_empty();
        foreach ($data->unenrol_users as $withroleid) {
            $sql = "SELECT DISTINCT ue.userid, ue.enrolid\n                      FROM {user_enrolments} ue\n                      JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid)\n                      JOIN {context} c ON (c.contextlevel = :courselevel AND c.instanceid = e.courseid)\n                      JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.roleid = :roleid AND ra.userid = ue.userid)";
            $params = array('courseid' => $data->courseid, 'roleid' => $withroleid, 'courselevel' => CONTEXT_COURSE);
            $rs = $DB->get_recordset_sql($sql, $params);
            foreach ($rs as $ue) {
                if (!isset($instances[$ue->enrolid])) {
                    continue;
                }
                $plugins[$instances[$ue->enrolid]->enrol]->unenrol_user($instances[$ue->enrolid], $ue->userid);
                $data->unenrolled[$ue->userid] = $ue->userid;
            }
        }
    }
    if (!empty($data->unenrolled)) {
        $status[] = array('component' => $componentstr, 'item' => get_string('unenrol', 'enrol') . ' (' . 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 = $DB->get_records('modules')) {
        foreach ($allmods as $mod) {
            $modname = $mod->name;
            if (!$DB->count_records($modname, array('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);
        }
    }
    // reset comments
    if (!empty($data->reset_comments)) {
        require_once $CFG->dirroot . '/comment/lib.php';
        comment::reset_course_page_comments($context);
    }
    return $status;
}
コード例 #9
0
ファイル: locallib.php プロジェクト: Keneth1212/moodle
 /**
  * Deal with users that are not supposed to be enrolled via this instance
  * @static
  * @param stdClass $instance
  * @param stdClass $ue
  * @param context_course $context
  * @param enrol_meta $plugin
  * @return void
  */
 protected static function user_not_supposed_to_be_here($instance, $ue, context_course $context, $plugin)
 {
     if (!$ue) {
         // Not enrolled yet - simple!
         return;
     }
     $userid = $ue->userid;
     $unenrolaction = $plugin->get_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
     if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
         // Purges grades, group membership, preferences, etc. - admins were warned!
         $plugin->unenrol_user($instance, $userid);
     } else {
         if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND) {
             if ($ue->status != ENROL_USER_SUSPENDED) {
                 $plugin->update_user_enrol($instance, $userid, ENROL_USER_SUSPENDED);
             }
         } else {
             if ($unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
                 if ($ue->status != ENROL_USER_SUSPENDED) {
                     $plugin->update_user_enrol($instance, $userid, ENROL_USER_SUSPENDED);
                 }
                 role_unassign_all(array('userid' => $userid, 'contextid' => $context->id, 'component' => 'enrol_meta', 'itemid' => $instance->id));
             } else {
                 debugging('Unknown unenrol action ' . $unenrolaction);
             }
         }
     }
 }
コード例 #10
0
 /**
  * A small functional test of accesslib functions and classes.
  */
 public function test_everything_in_accesslib()
 {
     global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE;
     // First of all finalize the session, we must not carry over any of this mess to the next page via SESSION!!!
     session_get_instance()->write_close();
     // hack - this is going to take very long time
     set_time_limit(3600);
     // Get rid of current user that would not work anyway,
     // do NOT even think about using $this->switch_global_user_id()!
     if (!isset($this->accesslibprevuser)) {
         $this->accesslibprevuser = clone $USER;
         $USER = new stdClass();
         $USER->id = 0;
     }
     // Backup $SITE global
     if (!isset($this->accesslibprevsite)) {
         $this->accesslibprevsite = $SITE;
     }
     // Switch DB, if it somehow fails or you specified wrong unittest prefix it will nuke real data, you have been warned!
     $this->switch_to_test_db();
     // Let's switch the CFG
     $prevcfg = clone $CFG;
     $this->switch_to_test_cfg();
     $CFG->config_php_settings = $prevcfg->config_php_settings;
     $CFG->noemailever = true;
     $CFG->admin = $prevcfg->admin;
     $CFG->lang = 'en';
     $CFG->tempdir = $prevcfg->tempdir;
     $CFG->cachedir = $prevcfg->cachedir;
     $CFG->directorypermissions = $prevcfg->directorypermissions;
     $CFG->filepermissions = $prevcfg->filepermissions;
     // Reset all caches
     accesslib_clear_all_caches_for_unit_testing();
     // Add some core tables - this is known to break constantly because we keep adding dependencies...
     $tablenames = array('config', 'config_plugins', 'modules', 'course', 'course_modules', 'course_sections', 'course_categories', 'mnet_host', 'mnet_application', 'capabilities', 'context', 'context_temp', 'role', 'role_capabilities', 'role_allow_switch', 'license', 'my_pages', 'block', 'block_instances', 'block_positions', 'role_allow_assign', 'role_allow_override', 'role_assignments', 'role_context_levels', 'enrol', 'user_enrolments', 'filter_active', 'filter_config', 'comments', 'user', 'groups_members', 'cache_flags', 'events_handlers', 'user_lastaccess', 'rating', 'files', 'role_names', 'user_preferences');
     $this->create_test_tables($tablenames, 'lib');
     // Create all core default records and default settings
     require_once "{$CFG->libdir}/db/install.php";
     xmldb_main_install();
     // installs the capabilities too
     // Fake mod_page install
     $tablenames = array('page');
     $this->create_test_tables($tablenames, 'mod/page');
     $module = new stdClass();
     require $CFG->dirroot . '/mod/page/version.php';
     $module->name = 'page';
     $pagemoduleid = $DB->insert_record('modules', $module);
     update_capabilities('mod_page');
     // Fake block_online_users install
     $plugin = new stdClass();
     $plugin->version = NULL;
     $plugin->cron = 0;
     include $CFG->dirroot . '/blocks/online_users/version.php';
     $plugin->name = 'online_users';
     $onlineusersblockid = $DB->insert_record('block', $plugin);
     update_capabilities('block_online_users');
     // Finish roles setup
     set_config('defaultfrontpageroleid', $DB->get_field('role', 'id', array('archetype' => 'frontpage')));
     set_config('defaultuserroleid', $DB->get_field('role', 'id', array('archetype' => 'user')));
     set_config('notloggedinroleid', $DB->get_field('role', 'id', array('archetype' => 'guest')));
     set_config('rolesactive', 1);
     // Init manual enrol
     set_config('status', ENROL_INSTANCE_ENABLED, 'enrol_manual');
     set_config('defaultperiod', 0, 'enrol_manual');
     $manualenrol = enrol_get_plugin('manual');
     // 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 = new stdClass();
     $bi->blockname = 'online_users';
     $bi->parentcontextid = $systemcontext->id;
     $bi->showinsubcontexts = 1;
     $bi->pagetypepattern = '';
     $bi->subpagepattern = '';
     $bi->defaultregion = '';
     $bi->defaultweight = 0;
     $bi->configdata = '';
     $biid = $DB->insert_record('block_instances', $bi);
     context_block::instance($biid);
     $testblocks[] = $biid;
     // Some users
     $testusers = array();
     for ($i = 0; $i < 20; $i++) {
         $user = new stdClass();
         $user->auth = 'manual';
         $user->firstname = 'user' . $i;
         $user->lastname = 'user' . $i;
         $user->username = '******' . $i;
         $user->password = '******';
         $user->email = "user{$i}@example.com";
         $user->confirmed = 1;
         $user->mnethostid = $CFG->mnet_localhost_id;
         $user->lang = $CFG->lang;
         $user->maildisplay = 1;
         $user->timemodified = time();
         $user->deleted = 0;
         $user->lastip = '0.0.0.0';
         $userid = $DB->insert_record('user', $user);
         $testusers[$i] = $userid;
         $usercontext = context_user::instance($userid);
         // Add block to user profile
         $bi->parentcontextid = $usercontext->id;
         $biid = $DB->insert_record('block_instances', $bi);
         context_block::instance($biid);
         $testblocks[] = $biid;
     }
     // Deleted user - should be ignored everywhere, can not have context
     $user = new stdClass();
     $user->auth = 'manual';
     $user->firstname = '';
     $user->lastname = '';
     $user->username = '******';
     $user->password = '';
     $user->email = '';
     $user->confirmed = 1;
     $user->mnethostid = $CFG->mnet_localhost_id;
     $user->lang = $CFG->lang;
     $user->maildisplay = 1;
     $user->timemodified = time();
     $user->deleted = 1;
     $user->lastip = '0.0.0.0';
     $DB->insert_record('user', $user);
     unset($user);
     // Add block to frontpage
     $bi->parentcontextid = $frontpagecontext->id;
     $biid = $DB->insert_record('block_instances', $bi);
     $frontpageblockcontext = context_block::instance($biid);
     $testblocks[] = $biid;
     // Add a resource to frontpage
     $page = new stdClass();
     $page->course = $SITE->id;
     $page->intro = '...';
     $page->introformat = FORMAT_HTML;
     $page->content = '...';
     $page->contentformat = FORMAT_HTML;
     $pageid = $DB->insert_record('page', $page);
     $testpages[] = $pageid;
     $cm = new stdClass();
     $cm->course = $SITE->id;
     $cm->module = $pagemoduleid;
     $cm->section = 1;
     $cm->instance = $pageid;
     $cmid = $DB->insert_record('course_modules', $cm);
     $frontpagepagecontext = context_module::instance($cmid);
     // Add block to frontpage resource
     $bi->parentcontextid = $frontpagepagecontext->id;
     $biid = $DB->insert_record('block_instances', $bi);
     $frontpagepageblockcontext = context_block::instance($biid);
     $testblocks[] = $biid;
     // Some nested course categories with courses
     require_once "{$CFG->dirroot}/course/lib.php";
     $path = '';
     $parentcat = 0;
     for ($i = 0; $i < 5; $i++) {
         $cat = new stdClass();
         $cat->name = 'category' . $i;
         $cat->parent = $parentcat;
         $cat->depth = $i + 1;
         $cat->sortorder = MAX_COURSES_IN_CATEGORY * ($i + 2);
         $cat->timemodified = time();
         $catid = $DB->insert_record('course_categories', $cat);
         $path = $path . '/' . $catid;
         $DB->set_field('course_categories', 'path', $path, array('id' => $catid));
         $parentcat = $catid;
         $testcategories[] = $catid;
         $catcontext = context_coursecat::instance($catid);
         if ($i >= 4) {
             continue;
         }
         // Add resource to each category
         $bi->parentcontextid = $catcontext->id;
         $biid = $DB->insert_record('block_instances', $bi);
         context_block::instance($biid);
         // Add a few courses to each category
         for ($j = 0; $j < 6; $j++) {
             $course = new stdClass();
             $course->fullname = 'course' . $j;
             $course->shortname = 'c' . $j;
             $course->summary = 'bah bah bah';
             $course->newsitems = 0;
             $course->numsections = 1;
             $course->category = $catid;
             $course->format = 'topics';
             $course->timecreated = time();
             $course->visible = 1;
             $course->timemodified = $course->timecreated;
             $courseid = $DB->insert_record('course', $course);
             $section = new stdClass();
             $section->course = $courseid;
             $section->section = 0;
             $section->summaryformat = FORMAT_HTML;
             $DB->insert_record('course_sections', $section);
             $section->section = 1;
             $DB->insert_record('course_sections', $section);
             $testcourses[] = $courseid;
             $coursecontext = context_course::instance($courseid);
             if ($j >= 5) {
                 continue;
             }
             // Add manual enrol instance
             $manualenrol->add_default_instance($DB->get_record('course', array('id' => $courseid)));
             // Add block to each course
             $bi->parentcontextid = $coursecontext->id;
             $biid = $DB->insert_record('block_instances', $bi);
             context_block::instance($biid);
             $testblocks[] = $biid;
             // Add a resource to each course
             $page->course = $courseid;
             $pageid = $DB->insert_record('page', $page);
             $testpages[] = $pageid;
             $cm->course = $courseid;
             $cm->instance = $pageid;
             $cm->id = $DB->insert_record('course_modules', $cm);
             $modcontext = context_module::instance($cm->id);
             // Add block to each module
             $bi->parentcontextid = $modcontext->id;
             $biid = $DB->insert_record('block_instances', $bi);
             context_block::instance($biid);
             $testblocks[] = $biid;
         }
     }
     // 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->assertEqual($DB->count_records('context'), $count);
     $this->assertEqual($DB->count_records('context', array('depth' => 0)), 0);
     $this->assertEqual($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->assertidentical($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->assertIdentical(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->assertIdentical($frontpagecontext->get_course_context(true), $frontpagecontext);
     $this->assertIdentical($frontpagepagecontext->get_course_context(true), $frontpagecontext);
     $this->assertIdentical($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->assertIdentical($usercontext->get_parent_context(), $systemcontext);
     $this->assertIdentical($usercontext->get_parent_contexts(), array($systemcontext->id => $systemcontext));
     $this->assertIdentical($usercontext->get_parent_contexts(true), array($usercontext->id => $usercontext, $systemcontext->id => $systemcontext));
     $this->assertIdentical($systemcontext->get_parent_contexts(), array());
     $this->assertIdentical($systemcontext->get_parent_contexts(true), array($systemcontext->id => $systemcontext));
     $this->assertIdentical($systemcontext->get_parent_context_ids(), array());
     $this->assertIdentical($systemcontext->get_parent_context_ids(true), array($systemcontext->id));
     $this->assertIdentical($frontpagecontext->get_parent_context(), $systemcontext);
     $this->assertIdentical($frontpagecontext->get_parent_contexts(), array($systemcontext->id => $systemcontext));
     $this->assertIdentical($frontpagecontext->get_parent_contexts(true), array($frontpagecontext->id => $frontpagecontext, $systemcontext->id => $systemcontext));
     $this->assertIdentical($frontpagecontext->get_parent_context_ids(), array($systemcontext->id));
     $this->assertEqual($frontpagecontext->get_parent_context_ids(true), array($frontpagecontext->id, $systemcontext->id));
     $this->assertIdentical($systemcontext->get_parent_context(), false);
     $frontpagecontext = context_course::instance($SITE->id);
     $parent = $systemcontext;
     foreach ($testcategories as $catid) {
         $catcontext = context_coursecat::instance($catid);
         $this->assertIdentical($catcontext->get_parent_context(), $parent);
         $parent = $catcontext;
     }
     $this->assertIdentical($frontpagepagecontext->get_parent_context(), $frontpagecontext);
     $this->assertIdentical($frontpageblockcontext->get_parent_context(), $frontpagecontext);
     $this->assertIdentical($frontpagepageblockcontext->get_parent_context(), $frontpagepagecontext);
     // ====== $context->get_child_contexts() ================================
     $children = $systemcontext->get_child_contexts();
     $this->assertEqual(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->assertEqual(count($children), 8);
     $this->assertEqual($countcats, 1);
     $this->assertEqual($countcourses, 6);
     $this->assertEqual($countblocks, 1);
     $context = context_course::instance($testcourses[2]);
     $children = $context->get_child_contexts();
     $this->assertEqual(count($children), 3);
     $context = context_module::instance($testpages[3]);
     $children = $context->get_child_contexts();
     $this->assertEqual(count($children), 1);
     $context = context_block::instance($testblocks[1]);
     $children = $context->get_child_contexts();
     $this->assertEqual(count($children), 0);
     unset($children);
     unset($countcats);
     unset($countcourses);
     unset($countblocks);
     // ======= context_helper::reset_caches() ============================
     context_helper::reset_caches();
     $this->assertEqual(context_inspection::test_context_cache_size(), 0);
     context_course::instance($SITE->id);
     $this->assertEqual(context_inspection::test_context_cache_size(), 1);
     // ======= context preloading ========================================
     context_helper::reset_caches();
     $sql = "SELECT " . context_helper::get_preload_record_columns_sql('c') . "\n                  FROM {context} c\n                 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->assertIdentical(array_keys($firstrecord), array_values($columns));
     context_helper::reset_caches();
     foreach ($records as $record) {
         context_helper::preload_from_record($record);
         $this->assertIdentical($record, new stdClass());
     }
     $this->assertEqual(context_inspection::test_context_cache_size(), count($records));
     unset($records);
     unset($columns);
     context_helper::reset_caches();
     context_helper::preload_course($SITE->id);
     $this->assertEqual(context_inspection::test_context_cache_size(), 4);
     // ====== 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->assertEqual($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->assertEqual($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->assertEqual($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->assertEqual($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->assertEqual($DB->count_records('role_assignments', array('contextid' => $context->id)), 3);
     role_unassign($allroles['teacher'], $testusers[1], $context->id);
     $this->assertEqual($DB->count_records('role_assignments', array('contextid' => $context->id)), 2);
     role_unassign_all(array('contextid' => $context->id));
     $this->assertEqual($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->assertEqual(count($enrolled), 10);
     for ($i = 0; $i < 10; $i++) {
         $this->assertTrue(isset($enrolled[$testusers[$i]]));
     }
     $enrolled = get_enrolled_users($coursecontext, 'moodle/course:update');
     $this->assertEqual(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->assertEqual($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->assertEqual($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->assertEqual($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']);
     // Random time!
     srand(666);
     foreach ($testusers as $userid) {
         // no guest or deleted
         // each user gets 0-20 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);
     for ($j = 0; $j < 10000; $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);
     unset($contexts);
     unset($users);
     unset($capabilities);
     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();
     $contexts = $DB->get_records('context', array(), 'id');
     $users = $DB->get_records('user', array(), 'id', 'id');
     $capabilities = $DB->get_records('capabilities', array(), 'id');
     $users[0] = null;
     // not-logged-in user
     $users[-1] = null;
     // 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 ($users as $userid => $unused) {
                 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->assertIdentical($hascap, isset($allowed[$userid]), "Capability result mismatch user:{$userid}, context:{$context->id}, {$cap->name}, hascap: " . (int) $hascap . " ");
                     if (isset($enrolled[$userid])) {
                         $this->assertIdentical(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($users);
     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->assertIdentical($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->assertIdentical($DB->get_field('context', 'path', array('id' => $context->id)), NULL);
     $this->assertEqual($DB->get_field('context', 'depth', array('id' => $context->id)), 0);
     foreach ($children as $child) {
         $this->assertIdentical($DB->get_field('context', 'path', array('id' => $child->id)), NULL);
         $this->assertEqual($DB->get_field('context', 'depth', array('id' => $child->id)), 0);
     }
     $this->assertEqual(count($children) + 1, $DB->count_records('context', array('depth' => 0)));
     $this->assertEqual(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->assertEqual($DB->get_field('context', 'path', array('id' => $context->id)), $context->path);
     $this->assertEqual($DB->get_field('context', 'depth', array('id' => $context->id)), $context->depth);
     $this->assertEqual(0, $DB->count_records('context', array('depth' => 0)));
     $this->assertEqual(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->assertIdentical($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->assertEqual(1, $DB->count_records('block_instances', array('parentcontextid' => $context->id)));
     $context->delete_content();
     $this->assertTrue($DB->record_exists('context', array('id' => $context->id)));
     $this->assertEqual(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->assertEqual(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->assertEqual(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->assertEqual(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->assertEqual(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->assertIdentical($DB->count_records('context'), $prevcount);
     $this->assertEqual($DB->count_records('context', array('depth' => 0)), 0);
     $this->assertEqual($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->assertIdentical($DB->count_records('context'), $prevcount);
     $this->assertEqual($DB->count_records('context', array('depth' => 0)), 0);
     $this->assertEqual($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->assertEqual($DB->count_records('context'), $count);
     // ======= context cache size restrictions ==============================
     $testusers = array();
     for ($i = 0; $i < CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
         $user = new stdClass();
         $user->auth = 'manual';
         $user->firstname = 'xuser' . $i;
         $user->lastname = 'xuser' . $i;
         $user->username = '******' . $i;
         $user->password = '******';
         $user->email = "xuser{$i}@example.com";
         $user->confirmed = 1;
         $user->mnethostid = $CFG->mnet_localhost_id;
         $user->lang = $CFG->lang;
         $user->maildisplay = 1;
         $user->timemodified = time();
         $user->lastip = '0.0.0.0';
         $userid = $DB->insert_record('user', $user);
         $testusers[$i] = $userid;
     }
     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->assertEqual(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->assertEqual(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->assertEqual(context_inspection::test_context_cache_size(), $prevsize);
     }
     context_user::instance($testusers[102]);
     $this->assertEqual(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->assertIdentical(get_system_context(), context_system::instance());
     foreach ($DB->get_records('context') as $contextid => $record) {
         $context = context::instance_by_id($contextid);
         $this->assertIdentical(get_context_instance_by_id($contextid), $context);
         $this->assertIdentical(get_context_instance($record->contextlevel, $record->instanceid), $context);
         $this->assertIdentical(get_parent_contexts($context), $context->get_parent_context_ids());
         if ($context->id == SYSCONTEXTID) {
             $this->assertIdentical(get_parent_contextid($context), false);
         } else {
             $this->assertIdentical(get_parent_contextid($context), $context->get_parent_context()->id);
         }
     }
     $children = get_child_contexts($systemcontext);
     $this->assertEqual(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->assertEqual($DB->count_records('context'), $count);
     context_helper::reset_caches();
     preload_course_contexts($SITE->id);
     $this->assertEqual(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->assertEqual(1, count($record));
         // only id left
     }
     $this->assertEqual(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->assertIdentical($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->assertEqual($coursecontext->contextlevel, CONTEXT_COURSE);
     $this->assertEqual(get_courseid_from_context($context), $page->course);
     $caps = fetch_context_capabilities($systemcontext);
     $this->assertTrue(is_array($caps));
     unset($caps);
 }
コード例 #11
0
ファイル: enrol.php プロジェクト: evltuma/moodle
 /**
  * Pre-uninstall hook.
  *
  * This is intended for disabling of plugin, some DB table purging, etc.
  *
  * NOTE: to be called from uninstall_plugin() only.
  * @private
  */
 public function uninstall_cleanup()
 {
     global $DB, $CFG;
     // NOTE: this is a bit brute force way - it will not trigger events and hooks properly.
     // Nuke all role assignments.
     role_unassign_all(array('component' => 'enrol_' . $this->name));
     // Purge participants.
     $DB->delete_records_select('user_enrolments', "enrolid IN (SELECT id FROM {enrol} WHERE enrol = ?)", array($this->name));
     // Purge enrol instances.
     $DB->delete_records('enrol', array('enrol' => $this->name));
     // Tweak enrol settings.
     if (!empty($CFG->enrol_plugins_enabled)) {
         $enabledenrols = explode(',', $CFG->enrol_plugins_enabled);
         $enabledenrols = array_unique($enabledenrols);
         $enabledenrols = array_flip($enabledenrols);
         unset($enabledenrols[$this->name]);
         $enabledenrols = array_flip($enabledenrols);
         if (is_array($enabledenrols)) {
             set_config('enrol_plugins_enabled', implode(',', $enabledenrols));
         }
     }
     parent::uninstall_cleanup();
 }
コード例 #12
0
ファイル: lib.php プロジェクト: nottmoo/moodle
    /**
     * Called for all enabled enrol plugins that returned true from is_cron_required().
     * @return void
     */
    public function cron() {
        global $CFG;

        // purge all roles if cohort sync disabled, those can be recreated later here in cron
        if (!enrol_is_enabled('cohort')) {
            role_unassign_all(array('component'=>'cohort_enrol'));
            return;
        }

        require_once("$CFG->dirroot/enrol/cohort/locallib.php");
        enrol_cohort_sync();
    }
コード例 #13
0
                                 // If its a company created course then assign the editor role to the user.
                                 if ($DB->record_exists('company_created_courses', array('companyid' => $companyid, 'courseid' => $companycourse->courseid))) {
                                     company_user::enrol($user, array($companycourse->courseid), $companycourse->companyid, $companycourseeditorrole->id);
                                 } else {
                                     company_user::enrol($user, array($companycourse->courseid), $companycourse->companyid, $companycoursenoneditorrole->id);
                                 }
                             }
                         }
                     }
                 } else {
                     $departmentmanagerrole = $DB->get_record('role', array('shortname' => 'companydepartmentmanager'));
                     $companyinstructorrole = $DB->get_record('role', array('shortname' => 'instructor'));
                     $companymanagerrole = $DB->get_record('role', array('shortname' => 'companymanager'));
                     role_unassign_all(array('roleid' => $departmentmanagerrole->id, 'userid' => $userid, 'contextid' => $systemcontext->id), false, false);
                     role_unassign_all(array('roleid' => $companyinstructorrole->id, 'userid' => $userid, 'contextid' => $systemcontext->id), false, false);
                     role_unassign_all(array('roleid' => $companymanagerrole->id, 'userid' => $userid, 'contextid' => $systemcontext->id), false, false);
                 }
             }
         }
     }
     // End of code
     $usercreated = false;
 }
 $usercontext = context_user::instance($usernew->id);
 // Update preferences.
 useredit_update_user_preference($usernew);
 // Update tags.
 /* if (!empty($CFG->usetags)) {
    useredit_update_interests($usernew, $usernew->interests);
    } */
 // Update user picture.
コード例 #14
0
/**
 * Sync all ilios course links.
 * @param progress_trace $trace
 * @param int $courseid one course, empty mean all
 * @return int 0 means ok, 1 means error, 2 means plugin disabled
 */
function enrol_ilios_sync(progress_trace $trace, $courseid = NULL)
{
    global $CFG, $DB;
    require_once "{$CFG->dirroot}/group/lib.php";
    // Purge all roles if ilios sync disabled, those can be recreated later here by cron or CLI.
    if (!enrol_is_enabled('ilios')) {
        $trace->output('Ilios enrolment sync plugin is disabled, unassigning all plugin roles and stopping.');
        role_unassign_all(array('component' => 'enrol_ilios'));
        return 2;
    }
    // Unfortunately this may take a long time, this script can be interrupted without problems.
    @set_time_limit(0);
    raise_memory_limit(MEMORY_HUGE);
    $trace->output('Starting user enrolment synchronisation...');
    $allroles = get_all_roles();
    $iliosusers = array();
    // cache
    $plugin = enrol_get_plugin('ilios');
    $http = $plugin->get_http_client();
    $unenrolaction = $plugin->get_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
    $moodleusersyncfield = 'idnumber';
    $iliosusersyncfield = 'campusId';
    // Iterate through all not enrolled yet users.
    $onecourse = $courseid ? "AND e.courseid = :courseid" : "";
    $sql = "SELECT *\n              FROM {enrol} e\n             WHERE e.enrol = 'ilios' {$onecourse}";
    $params = array();
    $params['courseid'] = $courseid;
    $params['suspended'] = ENROL_USER_SUSPENDED;
    $instances = $DB->get_recordset_sql($sql, $params);
    foreach ($instances as $instance) {
        $synctype = $instance->customchar1;
        $syncid = $instance->customint1;
        $groups = $http->get($synctype . 's', array("id" => $syncid));
        if (!empty($groups) && is_array($groups)) {
            $group = $groups[0];
            if (!empty($group->users)) {
                $users = $http->getbyids('users', $group->users);
                $userids = array();
                foreach ($users as $user) {
                    if (!isset($iliosusers[$user->id])) {
                        $iliosusers[$user->id] = null;
                        if (!empty($user->{$iliosusersyncfield})) {
                            $urec = $DB->get_record('user', array("{$moodleusersyncfield}" => $user->{$iliosusersyncfield}));
                            if (!empty($urec)) {
                                $iliosusers[$user->id] = array('id' => $urec->id, 'syncfield' => $urec->{$moodleusersyncfield});
                            }
                        }
                    }
                    if ($iliosusers[$user->id] === null) {
                        if (!empty($user->{$iliosusersyncfield})) {
                            $trace->output("skipping: Cannot find {$iliosusersyncfield} " . $user->{$iliosusersyncfield} . " that matches Moodle user field {$moodleusersyncfield}.", 1);
                        } else {
                            $trace->output("skipping: Ilios user " . $user->id . " does not have a {$iliosusersyncfield} field.", 1);
                        }
                    } else {
                        $userids[] = $userid = $iliosusers[$user->id]['id'];
                        $ue = $DB->get_record('user_enrolments', array('enrolid' => $instance->id, 'userid' => $userid));
                        if (!empty($ue) && isset($ue->status)) {
                            if ($ue->status == ENROL_USER_SUSPENDED) {
                                $plugin->update_user_enrol($instance, $userid, ENROL_USER_ACTIVE);
                                $trace->output("unsuspending: userid {$userid} ==> courseid " . $instance->courseid . " via Ilios {$synctype} {$syncid}", 1);
                            }
                        } else {
                            $plugin->enrol_user($instance, $userid);
                            $trace->output("enrolling: userid {$userid} ==> courseid " . $instance->courseid . " via Ilios {$synctype} {$syncid}", 1);
                        }
                    }
                }
                // Unenrol as necessary.
                if (!empty($userids)) {
                    $sql = "SELECT ue.*\n                              FROM {user_enrolments} ue\n                             WHERE ue.enrolid = {$instance->id}\n                               AND ue.userid NOT IN ( " . implode(",", $userids) . " )";
                    $rs = $DB->get_recordset_sql($sql);
                    foreach ($rs as $ue) {
                        if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
                            // Remove enrolment together with group membership, grades, preferences, etc.
                            $plugin->unenrol_user($instance, $ue->userid);
                            $trace->output("unenrolling: {$ue->userid} ==> " . $instance->courseid . " via Ilios {$synctype} {$syncid}", 1);
                        } else {
                            // ENROL_EXT_REMOVED_SUSPENDNOROLES
                            // Just disable and ignore any changes.
                            if ($ue->status != ENROL_USER_SUSPENDED) {
                                $plugin->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED);
                                $context = context_course::instance($instance->courseid);
                                role_unassign_all(array('userid' => $ue->userid, 'contextid' => $context->id, 'component' => 'enrol_ilios', 'itemid' => $instance->id));
                                $trace->output("suspending and unsassigning all roles: userid " . $ue->userid . " ==> courseid " . $instance->courseid, 1);
                            }
                        }
                    }
                    $rs->close();
                }
            }
        }
    }
    $instances->close();
    unset($iliosusers);
    // Now assign all necessary roles to enrolled users - skip suspended instances and users.
    $onecourse = $courseid ? "AND e.courseid = :courseid" : "";
    $sql = "SELECT e.roleid, ue.userid, c.id AS contextid, e.id AS itemid, e.courseid\n              FROM {user_enrolments} ue\n              JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'ilios' AND e.status = :statusenabled {$onecourse})\n              JOIN {role} r ON (r.id = e.roleid)\n              JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :coursecontext)\n              JOIN {user} u ON (u.id = ue.userid AND u.deleted = 0)\n         LEFT JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.userid = ue.userid AND ra.itemid = e.id AND ra.component = 'enrol_ilios' AND e.roleid = ra.roleid)\n             WHERE ue.status = :useractive AND ra.id IS NULL";
    $params = array();
    $params['statusenabled'] = ENROL_INSTANCE_ENABLED;
    $params['useractive'] = ENROL_USER_ACTIVE;
    $params['coursecontext'] = CONTEXT_COURSE;
    $params['courseid'] = $courseid;
    $rs = $DB->get_recordset_sql($sql, $params);
    foreach ($rs as $ra) {
        role_assign($ra->roleid, $ra->userid, $ra->contextid, 'enrol_ilios', $ra->itemid);
        $trace->output("assigning role: {$ra->userid} ==> {$ra->courseid} as " . $allroles[$ra->roleid]->shortname, 1);
    }
    $rs->close();
    // Remove unwanted roles - sync role can not be changed, we only remove role when unenrolled.
    $onecourse = $courseid ? "AND e.courseid = :courseid" : "";
    $sql = "SELECT ra.roleid, ra.userid, ra.contextid, ra.itemid, e.courseid\n              FROM {role_assignments} ra\n              JOIN {context} c ON (c.id = ra.contextid AND c.contextlevel = :coursecontext)\n              JOIN {enrol} e ON (e.id = ra.itemid AND e.enrol = 'ilios' {$onecourse})\n         LEFT JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = ra.userid AND ue.status = :useractive)\n             WHERE ra.component = 'enrol_ilios' AND (ue.id IS NULL OR e.status <> :statusenabled)";
    $params = array();
    $params['statusenabled'] = ENROL_INSTANCE_ENABLED;
    $params['useractive'] = ENROL_USER_ACTIVE;
    $params['coursecontext'] = CONTEXT_COURSE;
    $params['courseid'] = $courseid;
    $rs = $DB->get_recordset_sql($sql, $params);
    foreach ($rs as $ra) {
        role_unassign($ra->roleid, $ra->userid, $ra->contextid, 'enrol_ilios', $ra->itemid);
        $trace->output("unassigning role: {$ra->userid} ==> {$ra->courseid} as " . $allroles[$ra->roleid]->shortname, 1);
    }
    $rs->close();
    // Finally sync groups.
    $onecourse = $courseid ? "AND e.courseid = :courseid" : "";
    // Remove invalid.
    $sql = "SELECT gm.*, e.courseid, g.name AS groupname\n              FROM {groups_members} gm\n              JOIN {groups} g ON (g.id = gm.groupid)\n              JOIN {enrol} e ON (e.enrol = 'ilios' AND e.courseid = g.courseid {$onecourse})\n              JOIN {user_enrolments} ue ON (ue.userid = gm.userid AND ue.enrolid = e.id)\n             WHERE gm.component='enrol_ilios' AND gm.itemid = e.id AND g.id <> e.customint6";
    $params = array();
    $params['courseid'] = $courseid;
    $rs = $DB->get_recordset_sql($sql, $params);
    foreach ($rs as $gm) {
        groups_remove_member($gm->groupid, $gm->userid);
        $trace->output("removing user from group: {$gm->userid} ==> {$gm->courseid} - {$gm->groupname}", 1);
    }
    $rs->close();
    // Add missing.
    $sql = "SELECT ue.*, g.id AS groupid, e.courseid, g.name AS groupname\n              FROM {user_enrolments} ue\n              JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'ilios' {$onecourse})\n              JOIN {groups} g ON (g.courseid = e.courseid AND g.id = e.customint6)\n              JOIN {user} u ON (u.id = ue.userid AND u.deleted = 0)\n         LEFT JOIN {groups_members} gm ON (gm.groupid = g.id AND gm.userid = ue.userid)\n             WHERE gm.id IS NULL";
    $params = array();
    $params['courseid'] = $courseid;
    $rs = $DB->get_recordset_sql($sql, $params);
    foreach ($rs as $ue) {
        groups_add_member($ue->groupid, $ue->userid, 'enrol_ilios', $ue->enrolid);
        $trace->output("adding user to group: {$ue->userid} ==> {$ue->courseid} - {$ue->groupname}", 1);
    }
    $rs->close();
    $trace->output('...user enrolment synchronisation finished.');
    return 0;
}
コード例 #15
0
ファイル: observer.php プロジェクト: educakanchay/campus
 /**
  * Triggered via course_deleted event.
  *
  * @param \core\event\course_deleted $event
  * @return bool true on success
  */
 public static function course_deleted(\core\event\course_deleted $event)
 {
     global $DB;
     if (!enrol_is_enabled('meta')) {
         // This is slow, let enrol_meta_sync() deal with disabled plugin.
         return true;
     }
     // Does anything want to sync with this parent?
     if (!($enrols = $DB->get_records('enrol', array('customint1' => $event->objectid, 'enrol' => 'meta'), 'courseid ASC, id ASC'))) {
         return true;
     }
     $plugin = enrol_get_plugin('meta');
     $unenrolaction = $plugin->get_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
     if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
         // Simple, just delete this instance which purges all enrolments,
         // admins were warned that this is risky setting!
         foreach ($enrols as $enrol) {
             $plugin->delete_instance($enrol);
         }
         return true;
     }
     foreach ($enrols as $enrol) {
         if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND or $unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
             // This makes all enrolments suspended very quickly.
             $plugin->update_status($enrol, ENROL_INSTANCE_DISABLED);
         }
         if ($unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
             $context = context_course::instance($enrol->courseid);
             role_unassign_all(array('contextid' => $context->id, 'component' => 'enrol_meta', 'itemid' => $enrol->id));
         }
     }
     return true;
 }
コード例 #16
0
ファイル: lib.php プロジェクト: evltuma/moodle
 /**
  * Process user enrolment line.
  *
  * @param progress_trace $trace
  * @param string $action
  * @param int $roleid
  * @param stdClass $user
  * @param stdClass $course
  * @param int $timestart
  * @param int $timeend
  * @param bool $buffer_if_future
  */
 protected function process_records(progress_trace $trace, $action, $roleid, $user, $course, $timestart, $timeend, $buffer_if_future = true)
 {
     global $CFG, $DB;
     // Check if timestart is for future processing.
     if ($timestart > time() and $buffer_if_future) {
         // Populate into enrol_flatfile table as a future role to be assigned by cron.
         // Note: since 2.0 future enrolments do not cause problems if you disable guest access.
         $future_en = new stdClass();
         $future_en->action = $action;
         $future_en->roleid = $roleid;
         $future_en->userid = $user->id;
         $future_en->courseid = $course->id;
         $future_en->timestart = $timestart;
         $future_en->timeend = $timeend;
         $future_en->timemodified = time();
         $DB->insert_record('enrol_flatfile', $future_en);
         $trace->output("User {$user->id} will be enrolled later into course {$course->id} using role {$roleid} ({$timestart}, {$timeend})", 1);
         return;
     }
     $context = context_course::instance($course->id);
     if ($action === 'add') {
         // Clear the buffer just in case there were some future enrolments.
         $DB->delete_records('enrol_flatfile', array('userid' => $user->id, 'courseid' => $course->id, 'roleid' => $roleid));
         $instance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'flatfile'));
         if (empty($instance)) {
             // Only add an enrol instance to the course if non-existent.
             $enrolid = $this->add_instance($course);
             $instance = $DB->get_record('enrol', array('id' => $enrolid));
         }
         $notify = false;
         if ($ue = $DB->get_record('user_enrolments', array('enrolid' => $instance->id, 'userid' => $user->id))) {
             // Update only.
             $this->update_user_enrol($instance, $user->id, ENROL_USER_ACTIVE, $timestart, $timeend);
             if (!$DB->record_exists('role_assignments', array('contextid' => $context->id, 'roleid' => $roleid, 'userid' => $user->id, 'component' => 'enrol_flatfile', 'itemid' => $instance->id))) {
                 role_assign($roleid, $user->id, $context->id, 'enrol_flatfile', $instance->id);
             }
             $trace->output("User {$user->id} enrolment updated in course {$course->id} using role {$roleid} ({$timestart}, {$timeend})", 1);
         } else {
             // Enrol the user with this plugin instance.
             $this->enrol_user($instance, $user->id, $roleid, $timestart, $timeend);
             $trace->output("User {$user->id} enrolled in course {$course->id} using role {$roleid} ({$timestart}, {$timeend})", 1);
             $notify = true;
         }
         if ($notify and $this->get_config('mailstudents')) {
             $oldforcelang = force_current_language($user->lang);
             // Send welcome notification to enrolled users.
             $a = new stdClass();
             $a->coursename = format_string($course->fullname, true, array('context' => $context));
             $a->profileurl = "{$CFG->wwwroot}/user/view.php?id={$user->id}&amp;course={$course->id}";
             $subject = get_string('enrolmentnew', 'enrol', format_string($course->shortname, true, array('context' => $context)));
             $eventdata = new stdClass();
             $eventdata->modulename = 'moodle';
             $eventdata->component = 'enrol_flatfile';
             $eventdata->name = 'flatfile_enrolment';
             $eventdata->userfrom = $this->get_enroller($course->id);
             $eventdata->userto = $user;
             $eventdata->subject = $subject;
             $eventdata->fullmessage = get_string('welcometocoursetext', '', $a);
             $eventdata->fullmessageformat = FORMAT_PLAIN;
             $eventdata->fullmessagehtml = '';
             $eventdata->smallmessage = '';
             if (message_send($eventdata)) {
                 $trace->output("Notified enrolled user", 1);
             } else {
                 $trace->output("Failed to notify enrolled user", 1);
             }
             force_current_language($oldforcelang);
         }
         if ($notify and $this->get_config('mailteachers', 0)) {
             // Notify person responsible for enrolments.
             $enroller = $this->get_enroller($course->id);
             $oldforcelang = force_current_language($enroller->lang);
             $a = new stdClass();
             $a->course = format_string($course->fullname, true, array('context' => $context));
             $a->user = fullname($user);
             $subject = get_string('enrolmentnew', 'enrol', format_string($course->shortname, true, array('context' => $context)));
             $eventdata = new stdClass();
             $eventdata->modulename = 'moodle';
             $eventdata->component = 'enrol_flatfile';
             $eventdata->name = 'flatfile_enrolment';
             $eventdata->userfrom = get_admin();
             $eventdata->userto = $enroller;
             $eventdata->subject = $subject;
             $eventdata->fullmessage = get_string('enrolmentnewuser', 'enrol', $a);
             $eventdata->fullmessageformat = FORMAT_PLAIN;
             $eventdata->fullmessagehtml = '';
             $eventdata->smallmessage = '';
             if (message_send($eventdata)) {
                 $trace->output("Notified enroller {$eventdata->userto->id}", 1);
             } else {
                 $trace->output("Failed to notify enroller {$eventdata->userto->id}", 1);
             }
             force_current_language($oldforcelang);
         }
         return;
     } else {
         if ($action === 'del') {
             // Clear the buffer just in case there were some future enrolments.
             $DB->delete_records('enrol_flatfile', array('userid' => $user->id, 'courseid' => $course->id, 'roleid' => $roleid));
             $action = $this->get_config('unenrolaction');
             if ($action == ENROL_EXT_REMOVED_KEEP) {
                 $trace->output("del action is ignored", 1);
                 return;
             }
             // Loops through all enrolment methods, try to unenrol if roleid somehow matches.
             $instances = $DB->get_records('enrol', array('courseid' => $course->id));
             $unenrolled = false;
             foreach ($instances as $instance) {
                 if (!($ue = $DB->get_record('user_enrolments', array('enrolid' => $instance->id, 'userid' => $user->id)))) {
                     continue;
                 }
                 if ($instance->enrol === 'flatfile') {
                     $plugin = $this;
                 } else {
                     if (!enrol_is_enabled($instance->enrol)) {
                         continue;
                     }
                     if (!($plugin = enrol_get_plugin($instance->enrol))) {
                         continue;
                     }
                     if (!$plugin->allow_unenrol_user($instance, $ue)) {
                         continue;
                     }
                 }
                 // For some reason the del action includes a role name, this complicates everything.
                 $componentroles = array();
                 $manualroles = array();
                 $ras = $DB->get_records('role_assignments', array('userid' => $user->id, 'contextid' => $context->id));
                 foreach ($ras as $ra) {
                     if ($ra->component === '') {
                         $manualroles[$ra->roleid] = $ra->roleid;
                     } else {
                         if ($ra->component === 'enrol_' . $instance->enrol and $ra->itemid == $instance->id) {
                             $componentroles[$ra->roleid] = $ra->roleid;
                         }
                     }
                 }
                 if ($componentroles and !isset($componentroles[$roleid])) {
                     // Do not unenrol using this method, user has some other protected role!
                     continue;
                 } else {
                     if (empty($ras)) {
                         // If user does not have any roles then let's just suspend as many methods as possible.
                     } else {
                         if (!$plugin->roles_protected()) {
                             if (!$componentroles and $manualroles and !isset($manualroles[$roleid])) {
                                 // Most likely we want to keep users enrolled because they have some other course roles.
                                 continue;
                             }
                         }
                     }
                 }
                 if ($action == ENROL_EXT_REMOVED_UNENROL) {
                     $unenrolled = true;
                     if (!$plugin->roles_protected()) {
                         role_unassign_all(array('contextid' => $context->id, 'userid' => $user->id, 'roleid' => $roleid, 'component' => '', 'itemid' => 0), true);
                     }
                     $plugin->unenrol_user($instance, $user->id);
                     $trace->output("User {$user->id} was unenrolled from course {$course->id} (enrol_{$instance->enrol})", 1);
                 } else {
                     if ($action == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
                         if ($plugin->allow_manage($instance)) {
                             if ($ue->status == ENROL_USER_ACTIVE) {
                                 $unenrolled = true;
                                 $plugin->update_user_enrol($instance, $user->id, ENROL_USER_SUSPENDED);
                                 if (!$plugin->roles_protected()) {
                                     role_unassign_all(array('contextid' => $context->id, 'userid' => $user->id, 'component' => 'enrol_' . $instance->enrol, 'itemid' => $instance->id), true);
                                     role_unassign_all(array('contextid' => $context->id, 'userid' => $user->id, 'roleid' => $roleid, 'component' => '', 'itemid' => 0), true);
                                 }
                                 $trace->output("User {$user->id} enrolment was suspended in course {$course->id} (enrol_{$instance->enrol})", 1);
                             }
                         }
                     }
                 }
             }
             if (!$unenrolled) {
                 if (0 == $DB->count_records('role_assignments', array('userid' => $user->id, 'contextid' => $context->id))) {
                     role_unassign_all(array('contextid' => $context->id, 'userid' => $user->id, 'component' => '', 'itemid' => 0), true);
                 }
                 $trace->output("User {$user->id} (with role {$roleid}) not unenrolled from course {$course->id}", 1);
             }
             return;
         }
     }
 }
コード例 #17
0
ファイル: enrollib.php プロジェクト: vinoth4891/clinique
 /**
  * Unenrol user from course,
  * the last unenrolment removes all remaining roles.
  *
  * @param stdClass $instance
  * @param int $userid
  * @return void
  */
 public function unenrol_user(stdClass $instance, $userid)
 {
     global $CFG, $USER, $DB;
     require_once "{$CFG->dirroot}/group/lib.php";
     $name = $this->get_name();
     $courseid = $instance->courseid;
     if ($instance->enrol !== $name) {
         throw new coding_exception('invalid enrol instance!');
     }
     $context = context_course::instance($instance->courseid, MUST_EXIST);
     if (!($ue = $DB->get_record('user_enrolments', array('enrolid' => $instance->id, 'userid' => $userid)))) {
         // weird, user not enrolled
         return;
     }
     // Remove all users groups linked to this enrolment instance.
     if ($gms = $DB->get_records('groups_members', array('userid' => $userid, 'component' => 'enrol_' . $name, 'itemid' => $instance->id))) {
         foreach ($gms as $gm) {
             groups_remove_member($gm->groupid, $gm->userid);
         }
     }
     role_unassign_all(array('userid' => $userid, 'contextid' => $context->id, 'component' => 'enrol_' . $name, 'itemid' => $instance->id));
     $DB->delete_records('user_enrolments', array('id' => $ue->id));
     // add extra info and trigger event
     $ue->courseid = $courseid;
     $ue->enrol = $name;
     $sql = "SELECT 'x'\n                  FROM {user_enrolments} ue\n                  JOIN {enrol} e ON (e.id = ue.enrolid)\n                 WHERE ue.userid = :userid AND e.courseid = :courseid";
     if ($DB->record_exists_sql($sql, array('userid' => $userid, 'courseid' => $courseid))) {
         $ue->lastenrol = false;
         events_trigger('user_unenrolled', $ue);
         // user still has some enrolments, no big cleanup yet
     } else {
         // the big cleanup IS necessary!
         require_once "{$CFG->libdir}/gradelib.php";
         // remove all remaining roles
         role_unassign_all(array('userid' => $userid, 'contextid' => $context->id), true, false);
         //clean up ALL invisible user data from course if this is the last enrolment - groups, grades, etc.
         groups_delete_group_members($courseid, $userid);
         grade_user_unenrol($courseid, $userid);
         $DB->delete_records('user_lastaccess', array('userid' => $userid, 'courseid' => $courseid));
         $ue->lastenrol = true;
         // means user not enrolled any more
         events_trigger('user_unenrolled', $ue);
     }
     // reset all enrol caches
     $context->mark_dirty();
     // reset current user enrolment caching
     if ($userid == $USER->id) {
         if (isset($USER->enrol['enrolled'][$courseid])) {
             unset($USER->enrol['enrolled'][$courseid]);
         }
         if (isset($USER->enrol['tempguest'][$courseid])) {
             unset($USER->enrol['tempguest'][$courseid]);
             remove_temp_course_roles($context);
         }
     }
 }
コード例 #18
0
ファイル: lib.php プロジェクト: hit-moodle/moodle-enrol_jwc
 /**
  * Called for all enabled enrol plugins that returned true from is_cron_required().
  * @return void
  */
 public function cron()
 {
     global $DB, $CFG;
     // purge all roles if jwc sync disabled, those can be recreated later here in cron
     if (!enrol_is_enabled('jwc')) {
         role_unassign_all(array('component' => 'jwc_enrol'));
         return;
     }
     // 管理员可以设定清除所有选课
     if ($this->get_config('unenrolall')) {
         $instances = $DB->get_records('enrol', array('enrol' => 'jwc'));
         foreach ($instances as $instance) {
             //first unenrol all users
             $participants = $DB->get_recordset('user_enrolments', array('enrolid' => $instance->id));
             foreach ($participants as $participant) {
                 $this->unenrol_user($instance, $participant->userid);
             }
             $participants->close();
             // now clean up all remainders that were not removed correctly
             $DB->delete_records('role_assignments', array('itemid' => $instance->id, 'component' => 'jwc'));
             $DB->delete_records('user_enrolments', array('enrolid' => $instance->id));
         }
         $this->set_config('unenrolall', 0);
         return;
     }
     // 暂时禁用cron。将来通过是否有数据更改来决定cron同步周期
     // require_once("$CFG->dirroot/enrol/jwc/locallib.php");
     // enrol_jwc_sync();
 }
コード例 #19
0
ファイル: lib.php プロジェクト: JP-Git/moodle
 /**
  * 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;
 }
コード例 #20
0
ファイル: edit.php プロジェクト: alanaipe2015/moodle
}
// Try and make the manage instances node on the navigation active.
$courseadmin = $PAGE->settingsnav->get('courseadmin');
if ($courseadmin && $courseadmin->get('users') && $courseadmin->get('users')->get('manageinstances')) {
    $courseadmin->get('users')->get('manageinstances')->make_active();
}
$mform = new enrol_cohort_edit_form(null, array($instance, $enrol, $course));
if ($mform->is_cancelled()) {
    redirect($returnurl);
} else {
    if ($data = $mform->get_data()) {
        if ($data->id) {
            // NOTE: no cohort changes here!!!
            if ($data->roleid != $instance->roleid) {
                // The sync script can only add roles, for perf reasons it does not modify them.
                role_unassign_all(array('contextid' => $context->id, 'roleid' => $instance->roleid, 'component' => 'enrol_cohort', 'itemid' => $instance->id));
            }
            $instance->name = $data->name;
            $instance->status = $data->status;
            $instance->roleid = $data->roleid;
            $instance->customint2 = $data->customint2;
            $instance->timemodified = time();
            // Create a new group for the cohort if requested.
            if ($data->customint2 == COHORT_CREATE_GROUP) {
                require_capability('moodle/course:managegroups', $context);
                $groupid = enrol_cohort_create_new_group($course->id, $data->customint1);
                $instance->customint2 = $groupid;
            }
            $DB->update_record('enrol', $instance);
            \core\event\enrol_instance_updated::create_from_record($instance)->trigger();
        } else {
コード例 #21
0
ファイル: accesslib_test.php プロジェクト: numbas/moodle
    /**
     * 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);
    }
コード例 #22
0
ファイル: install.php プロジェクト: frapersan/group-magic
function xmldb_enrol_database_install()
{
    global $CFG, $DB;
    // migrate old config settings first
    if (isset($CFG->enrol_dbtype)) {
        set_config('dbtype', $CFG->enrol_dbtype, 'enrol_database');
        unset_config('enrol_dbtype');
    }
    if (isset($CFG->enrol_dbhost)) {
        set_config('dbhost', $CFG->enrol_dbhost, 'enrol_database');
        unset_config('enrol_dbhost');
    }
    if (isset($CFG->enrol_dbuser)) {
        set_config('dbuser', $CFG->enrol_dbuser, 'enrol_database');
        unset_config('enrol_dbuser');
    }
    if (isset($CFG->enrol_dbpass)) {
        set_config('dbpass', $CFG->enrol_dbpass, 'enrol_database');
        unset_config('enrol_dbpass');
    }
    if (isset($CFG->enrol_dbname)) {
        set_config('dbname', $CFG->enrol_dbname, 'enrol_database');
        unset_config('enrol_dbname');
    }
    if (isset($CFG->enrol_dbtable)) {
        set_config('remoteenroltable', $CFG->enrol_dbtable, 'enrol_database');
        unset_config('enrol_dbtable');
    }
    if (isset($CFG->enrol_localcoursefield)) {
        set_config('localcoursefield', $CFG->enrol_localcoursefield, 'enrol_database');
        unset_config('enrol_localcoursefield');
    }
    if (isset($CFG->enrol_localuserfield)) {
        set_config('localuserfield', $CFG->enrol_localuserfield, 'enrol_database');
        unset_config('enrol_localuserfield');
    }
    if (isset($CFG->enrol_localrolefield)) {
        set_config('localrolefield', $CFG->enrol_localrolefield, 'enrol_database');
        unset_config('enrol_localrolefield');
    }
    if (isset($CFG->enrol_remotecoursefield)) {
        set_config('remotecoursefield', $CFG->enrol_remotecoursefield, 'enrol_database');
        unset_config('enrol_remotecoursefield');
    }
    if (isset($CFG->enrol_remoteuserfield)) {
        set_config('remoteuserfield', $CFG->enrol_remoteuserfield, 'enrol_database');
        unset_config('enrol_remoteuserfield');
    }
    if (isset($CFG->enrol_remoterolefield)) {
        set_config('remoterolefield', $CFG->enrol_remoterolefield, 'enrol_database');
        unset_config('enrol_remoterolefield');
    }
    if (isset($CFG->enrol_db_defaultcourseroleid)) {
        set_config('defaultrole', $CFG->enrol_db_defaultcourseroleid, 'enrol_database');
        unset_config('enrol_db_defaultcourseroleid');
    }
    unset_config('enrol_db_autocreate');
    // replaced by new coruse temple sync
    if (isset($CFG->enrol_db_category)) {
        set_config('defaultcategory', $CFG->enrol_db_category, 'enrol_database');
        unset_config('enrol_db_category');
    }
    if (isset($CFG->enrol_db_template)) {
        set_config('templatecourse', $CFG->enrol_db_template, 'enrol_database');
        unset_config('enrol_db_template');
    }
    if (isset($CFG->enrol_db_ignorehiddencourse)) {
        set_config('ignorehiddencourses', $CFG->enrol_db_ignorehiddencourse, 'enrol_database');
        unset_config('enrol_db_ignorehiddencourse');
    }
    // just make sure there are no leftovers after disabled plugin
    if (!$DB->record_exists('enrol', array('enrol' => 'database'))) {
        role_unassign_all(array('component' => 'enrol_database'));
        return;
    }
}
コード例 #23
0
ファイル: lib.php プロジェクト: numbas/moodle
 /**
  * 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;
 }
コード例 #24
0
ファイル: sync_test.php プロジェクト: JP-Git/moodle
 public function test_sync_full()
 {
     global $DB;
     $this->resetAfterTest();
     // Setup a few courses and categories.
     $studentrole = $DB->get_record('role', array('shortname' => 'student'));
     $this->assertNotEmpty($studentrole);
     $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
     $this->assertNotEmpty($teacherrole);
     $managerrole = $DB->get_record('role', array('shortname' => 'manager'));
     $this->assertNotEmpty($managerrole);
     $cat1 = $this->getDataGenerator()->create_category();
     $cat2 = $this->getDataGenerator()->create_category();
     $cat3 = $this->getDataGenerator()->create_category(array('parent' => $cat2->id));
     $course1 = $this->getDataGenerator()->create_course(array('category' => $cat1->id));
     $course2 = $this->getDataGenerator()->create_course(array('category' => $cat2->id));
     $course3 = $this->getDataGenerator()->create_course(array('category' => $cat3->id));
     $course4 = $this->getDataGenerator()->create_course(array('category' => $cat3->id));
     $user1 = $this->getDataGenerator()->create_user();
     $user2 = $this->getDataGenerator()->create_user();
     $user3 = $this->getDataGenerator()->create_user();
     $user4 = $this->getDataGenerator()->create_user();
     $this->enable_role_sync($studentrole->id);
     $this->enable_role_sync($teacherrole->id);
     $this->enable_plugin();
     $this->assertEquals(0, $DB->count_records('role_assignments', array()));
     role_assign($managerrole->id, $user1->id, context_coursecat::instance($cat1->id));
     role_assign($managerrole->id, $user3->id, context_course::instance($course1->id));
     role_assign($managerrole->id, $user3->id, context_course::instance($course2->id));
     $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
     $result = enrol_category_sync_full();
     $this->assertSame(0, $result);
     $this->disable_plugin();
     role_assign($studentrole->id, $user1->id, context_coursecat::instance($cat2->id));
     $this->enable_plugin();
     $result = enrol_category_sync_full();
     $this->assertSame(0, $result);
     $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
     $this->assertTrue(is_enrolled(context_course::instance($course2->id), $user1->id));
     $this->assertTrue(is_enrolled(context_course::instance($course3->id), $user1->id));
     $this->assertTrue(is_enrolled(context_course::instance($course4->id), $user1->id));
     $this->disable_plugin();
     role_unassign($studentrole->id, $user1->id, context_coursecat::instance($cat2->id)->id);
     role_assign($studentrole->id, $user2->id, context_coursecat::instance($cat1->id));
     role_assign($teacherrole->id, $user4->id, context_coursecat::instance($cat1->id));
     role_assign($teacherrole->id, $user3->id, context_coursecat::instance($cat2->id));
     role_assign($managerrole->id, $user3->id, context_course::instance($course3->id));
     $this->enable_plugin();
     $result = enrol_category_sync_full();
     $this->assertSame(0, $result);
     $this->assertEquals(5, $DB->count_records('user_enrolments', array()));
     $this->assertTrue(is_enrolled(context_course::instance($course1->id), $user2->id));
     $this->assertTrue(is_enrolled(context_course::instance($course1->id), $user4->id));
     $this->assertTrue(is_enrolled(context_course::instance($course2->id), $user3->id));
     $this->assertTrue(is_enrolled(context_course::instance($course3->id), $user3->id));
     $this->assertTrue(is_enrolled(context_course::instance($course4->id), $user3->id));
     // Cleanup everything.
     $this->assertNotEmpty($DB->count_records('role_assignments', array()));
     $this->assertNotEmpty($DB->count_records('user_enrolments', array()));
     $this->disable_plugin();
     role_unassign_all(array('roleid' => $studentrole->id));
     role_unassign_all(array('roleid' => $managerrole->id));
     role_unassign_all(array('roleid' => $teacherrole->id));
     $result = enrol_category_sync_full();
     $this->assertSame(2, $result);
     $this->assertEquals(0, $DB->count_records('role_assignments', array()));
     $this->assertNotEmpty($DB->count_records('user_enrolments', array()));
     $this->disable_role_sync($studentrole->id);
     $this->disable_role_sync($teacherrole->id);
     $this->enable_plugin();
     $result = enrol_category_sync_full();
     $this->assertSame(0, $result);
     $this->assertEquals(0, $DB->count_records('role_assignments', array()));
     $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
     $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'category')));
 }
コード例 #25
0
 /**
  * Triggered via course_deleted event.
  * @static
  * @param stdClass $course
  * @return bool success
  */
 public static function course_deleted($course)
 {
     global $DB;
     // NOTE: do not test if plugin enabled, we want to keep disabling instances with invalid course links
     // does anything want to sync with this parent?
     if (!($enrols = $DB->get_records('enrol', array('customint1' => $course->id, 'enrol' => 'meta'), 'courseid ASC, id ASC'))) {
         return true;
     }
     $plugin = enrol_get_plugin('meta');
     // hack the DB info for all courses first
     foreach ($enrols as $enrol) {
         $enrol->customint1 = 0;
         $enrol->status = ENROL_INSTANCE_DISABLED;
         $DB->update_record('enrol', $enrol);
         $context = context_course::instance($enrol->courseid);
         role_unassign_all(array('contextid' => $context->id, 'component' => 'enrol_meta', 'itemid' => $enrol->id));
     }
     // now trigger sync for each instance and purge caches
     foreach ($enrols as $enrol) {
         $plugin->update_status($enrol, ENROL_INSTANCE_DISABLED);
     }
     return true;
 }
コード例 #26
0
ファイル: locallib.php プロジェクト: stronk7/moodle
 /**
  * Event processor - cohort deleted.
  * @param \core\event\cohort_deleted $event
  * @return bool
  */
 public static function deleted(\core\event\cohort_deleted $event)
 {
     global $DB;
     // Does anything want to sync with this cohort?
     if (!($instances = $DB->get_records('enrol', array('customint1' => $event->objectid, 'enrol' => 'cohort'), 'id ASC'))) {
         return true;
     }
     $plugin = enrol_get_plugin('cohort');
     $unenrolaction = $plugin->get_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
     foreach ($instances as $instance) {
         if ($unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
             $context = context_course::instance($instance->courseid);
             role_unassign_all(array('contextid' => $context->id, 'component' => 'enrol_cohort', 'itemid' => $instance->id));
             $plugin->update_status($instance, ENROL_INSTANCE_DISABLED);
         } else {
             $plugin->delete_instance($instance);
         }
     }
     return true;
 }
コード例 #27
0
ファイル: adminlib.php プロジェクト: raymondAntonio/moodle
/**
 * Automatically clean-up all plugin data and remove the plugin DB tables
 *
 * @param string $type The plugin type, eg. 'mod', 'qtype', 'workshopgrading' etc.
 * @param string $name The plugin name, eg. 'forum', 'multichoice', 'accumulative' etc.
 * @uses global $OUTPUT to produce notices and other messages
 * @return void
 */
function uninstall_plugin($type, $name)
{
    global $CFG, $DB, $OUTPUT;
    // recursively uninstall all module subplugins first
    if ($type === 'mod') {
        if (file_exists("{$CFG->dirroot}/mod/{$name}/db/subplugins.php")) {
            $subplugins = array();
            include "{$CFG->dirroot}/mod/{$name}/db/subplugins.php";
            foreach ($subplugins as $subplugintype => $dir) {
                $instances = get_plugin_list($subplugintype);
                foreach ($instances as $subpluginname => $notusedpluginpath) {
                    uninstall_plugin($subplugintype, $subpluginname);
                }
            }
        }
    }
    $component = $type . '_' . $name;
    // eg. 'qtype_multichoice' or 'workshopgrading_accumulative' or 'mod_forum'
    if ($type === 'mod') {
        $pluginname = $name;
        // eg. 'forum'
        if (get_string_manager()->string_exists('modulename', $component)) {
            $strpluginname = get_string('modulename', $component);
        } else {
            $strpluginname = $component;
        }
    } else {
        $pluginname = $component;
        if (get_string_manager()->string_exists('pluginname', $component)) {
            $strpluginname = get_string('pluginname', $component);
        } else {
            $strpluginname = $component;
        }
    }
    echo $OUTPUT->heading($pluginname);
    $plugindirectory = get_plugin_directory($type, $name);
    $uninstalllib = $plugindirectory . '/db/uninstall.php';
    if (file_exists($uninstalllib)) {
        require_once $uninstalllib;
        $uninstallfunction = 'xmldb_' . $pluginname . '_uninstall';
        // eg. 'xmldb_workshop_uninstall()'
        if (function_exists($uninstallfunction)) {
            if (!$uninstallfunction()) {
                echo $OUTPUT->notification('Encountered a problem running uninstall function for ' . $pluginname);
            }
        }
    }
    if ($type === 'mod') {
        // perform cleanup tasks specific for activity modules
        if (!($module = $DB->get_record('modules', array('name' => $name)))) {
            print_error('moduledoesnotexist', 'error');
        }
        // delete all the relevant instances from all course sections
        if ($coursemods = $DB->get_records('course_modules', array('module' => $module->id))) {
            foreach ($coursemods as $coursemod) {
                if (!delete_mod_from_section($coursemod->id, $coursemod->section)) {
                    echo $OUTPUT->notification("Could not delete the {$strpluginname} with id = {$coursemod->id} from section {$coursemod->section}");
                }
            }
        }
        // clear course.modinfo for courses that used this module
        $sql = "UPDATE {course}\n                   SET modinfo=''\n                 WHERE id IN (SELECT DISTINCT course\n                                FROM {course_modules}\n                               WHERE module=?)";
        $DB->execute($sql, array($module->id));
        // delete all the course module records
        $DB->delete_records('course_modules', array('module' => $module->id));
        // delete module contexts
        if ($coursemods) {
            foreach ($coursemods as $coursemod) {
                if (!delete_context(CONTEXT_MODULE, $coursemod->id)) {
                    echo $OUTPUT->notification("Could not delete the context for {$strpluginname} with id = {$coursemod->id}");
                }
            }
        }
        // delete the module entry itself
        $DB->delete_records('modules', array('name' => $module->name));
        // cleanup the gradebook
        require_once $CFG->libdir . '/gradelib.php';
        grade_uninstalled_module($module->name);
        // Perform any custom uninstall tasks
        if (file_exists($CFG->dirroot . '/mod/' . $module->name . '/lib.php')) {
            require_once $CFG->dirroot . '/mod/' . $module->name . '/lib.php';
            $uninstallfunction = $module->name . '_uninstall';
            if (function_exists($uninstallfunction)) {
                debugging("{$uninstallfunction}() has been deprecated. Use the plugin's db/uninstall.php instead", DEBUG_DEVELOPER);
                if (!$uninstallfunction()) {
                    echo $OUTPUT->notification('Encountered a problem running uninstall function for ' . $module->name . '!');
                }
            }
        }
    } else {
        if ($type === 'enrol') {
            // NOTE: this is a bit brute force way - it will not trigger events and hooks properly
            // nuke all role assignments
            role_unassign_all(array('component' => $component));
            // purge participants
            $DB->delete_records_select('user_enrolments', "enrolid IN (SELECT id FROM {enrol} WHERE enrol = ?)", array($name));
            // purge enrol instances
            $DB->delete_records('enrol', array('enrol' => $name));
            // tweak enrol settings
            if (!empty($CFG->enrol_plugins_enabled)) {
                $enabledenrols = explode(',', $CFG->enrol_plugins_enabled);
                $enabledenrols = array_unique($enabledenrols);
                $enabledenrols = array_flip($enabledenrols);
                unset($enabledenrols[$name]);
                $enabledenrols = array_flip($enabledenrols);
                if (is_array($enabledenrols)) {
                    set_config('enrol_plugins_enabled', implode(',', $enabledenrols));
                }
            }
        } else {
            if ($type === 'block') {
                if ($block = $DB->get_record('block', array('name' => $name))) {
                    // Inform block it's about to be deleted
                    if (file_exists("{$CFG->dirroot}/blocks/{$block->name}/block_{$block->name}.php")) {
                        $blockobject = block_instance($block->name);
                        if ($blockobject) {
                            $blockobject->before_delete();
                            //only if we can create instance, block might have been already removed
                        }
                    }
                    // First delete instances and related contexts
                    $instances = $DB->get_records('block_instances', array('blockname' => $block->name));
                    foreach ($instances as $instance) {
                        blocks_delete_instance($instance);
                    }
                    // Delete block
                    $DB->delete_records('block', array('id' => $block->id));
                }
            }
        }
    }
    // perform clean-up task common for all the plugin/subplugin types
    // delete calendar events
    $DB->delete_records('event', array('modulename' => $pluginname));
    // delete all the logs
    $DB->delete_records('log', array('module' => $pluginname));
    // delete log_display information
    $DB->delete_records('log_display', array('component' => $component));
    // delete the module configuration records
    unset_all_config_for_plugin($pluginname);
    // delete message provider
    message_provider_uninstall($component);
    // delete message processor
    if ($type === 'message') {
        message_processor_uninstall($name);
    }
    // delete the plugin tables
    $xmldbfilepath = $plugindirectory . '/db/install.xml';
    drop_plugin_tables($component, $xmldbfilepath, false);
    if ($type === 'mod' or $type === 'block') {
        // non-frankenstyle table prefixes
        drop_plugin_tables($name, $xmldbfilepath, false);
    }
    // delete the capabilities that were defined by this module
    capabilities_cleanup($component);
    // remove event handlers and dequeue pending events
    events_uninstall($component);
    echo $OUTPUT->notification(get_string('success'), 'notifysuccess');
}
コード例 #28
0
ファイル: enrollib.php プロジェクト: nikita777/moodle
    /**
     * Unenrol user from course,
     * the last unenrolment removes all remaining roles.
     *
     * @param stdClass $instance
     * @param int $userid
     * @return void
     */
    public function unenrol_user(stdClass $instance, $userid) {
        global $CFG, $USER, $DB;

        $name = $this->get_name();
        $courseid = $instance->courseid;

        if ($instance->enrol !== $name) {
            throw new coding_exception('invalid enrol instance!');
        }
        $context = get_context_instance(CONTEXT_COURSE, $instance->courseid, MUST_EXIST);

        if (!$ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid))) {
            // weird, user not enrolled
            return;
        }

        role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id, 'component'=>'enrol_'.$name, 'itemid'=>$instance->id));
        $DB->delete_records('user_enrolments', array('id'=>$ue->id));

        // add extra info and trigger event
        $ue->courseid  = $courseid;
        $ue->enrol     = $name;

        $sql = "SELECT 'x'
                  FROM {user_enrolments} ue
                  JOIN {enrol} e ON (e.id = ue.enrolid)
                  WHERE ue.userid = :userid AND e.courseid = :courseid";
        if ($DB->record_exists_sql($sql, array('userid'=>$userid, 'courseid'=>$courseid))) {
            $ue->lastenrol = false;
            events_trigger('user_unenrolled', $ue);
            // user still has some enrolments, no big cleanup yet
        } else {
            // the big cleanup IS necessary!

            require_once("$CFG->dirroot/group/lib.php");
            require_once("$CFG->libdir/gradelib.php");

            // remove all remaining roles
            role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id), true, false);

            //clean up ALL invisible user data from course if this is the last enrolment - groups, grades, etc.
            groups_delete_group_members($courseid, $userid);

            grade_user_unenrol($courseid, $userid);

            $DB->delete_records('user_lastaccess', array('userid'=>$userid, 'courseid'=>$courseid));

            $ue->lastenrol = true; // means user not enrolled any more
            events_trigger('user_unenrolled', $ue);
        }
        // reset primitive require_login() caching
        if ($userid == $USER->id) {
            if (isset($USER->enrol['enrolled'][$courseid])) {
                unset($USER->enrol['enrolled'][$courseid]);
            }
            if (isset($USER->enrol['tempguest'][$courseid])) {
                unset($USER->enrol['tempguest'][$courseid]);
                $USER->access = remove_temp_roles($context, $USER->access);
            }
        }
    }
コード例 #29
0
ファイル: accesslib.php プロジェクト: rolandovanegas/moodle
/**
 * Removes multiple role assignments, parameters may contain:
 *   'roleid', 'userid', 'contextid', 'component', 'enrolid'.
 *
 * @param array $params role assignment parameters
 * @param bool $subcontexts unassign in subcontexts too
 * @param bool $includemanual include manual role assignments too
 * @return void
 */
function role_unassign_all(array $params, $subcontexts = false, $includemanual = false)
{
    global $USER, $CFG, $DB;
    if (!$params) {
        throw new coding_exception('Missing parameters in role_unsassign_all() call');
    }
    $allowed = array('roleid', 'userid', 'contextid', 'component', 'itemid');
    foreach ($params as $key => $value) {
        if (!in_array($key, $allowed)) {
            throw new coding_exception('Unknown role_unsassign_all() parameter key', 'key:' . $key);
        }
    }
    if (isset($params['component']) and $params['component'] !== '' and strpos($params['component'], '_') === false) {
        throw new coding_exception('Invalid component paramter in role_unsassign_all() call', 'component:' . $params['component']);
    }
    if ($includemanual) {
        if (!isset($params['component']) or $params['component'] === '') {
            throw new coding_exception('include manual parameter requires component parameter in role_unsassign_all() call');
        }
    }
    if ($subcontexts) {
        if (empty($params['contextid'])) {
            throw new coding_exception('subcontexts paramtere requires component parameter in role_unsassign_all() call');
        }
    }
    $ras = $DB->get_records('role_assignments', $params);
    foreach ($ras as $ra) {
        $DB->delete_records('role_assignments', array('id' => $ra->id));
        if ($context = context::instance_by_id($ra->contextid, IGNORE_MISSING)) {
            // this is a bit expensive but necessary
            $context->mark_dirty();
            /// If the user is the current user, then do full reload of capabilities too.
            if (!empty($USER->id) && $USER->id == $ra->userid) {
                reload_all_capabilities();
            }
        }
        events_trigger('role_unassigned', $ra);
    }
    unset($ras);
    // process subcontexts
    if ($subcontexts and $context = context::instance_by_id($params['contextid'], IGNORE_MISSING)) {
        if ($params['contextid'] instanceof context) {
            $context = $params['contextid'];
        } else {
            $context = context::instance_by_id($params['contextid'], IGNORE_MISSING);
        }
        if ($context) {
            $contexts = $context->get_child_contexts();
            $mparams = $params;
            foreach ($contexts as $context) {
                $mparams['contextid'] = $context->id;
                $ras = $DB->get_records('role_assignments', $mparams);
                foreach ($ras as $ra) {
                    $DB->delete_records('role_assignments', array('id' => $ra->id));
                    // this is a bit expensive but necessary
                    $context->mark_dirty();
                    /// If the user is the current user, then do full reload of capabilities too.
                    if (!empty($USER->id) && $USER->id == $ra->userid) {
                        reload_all_capabilities();
                    }
                    events_trigger('role_unassigned', $ra);
                }
            }
        }
    }
    // do this once more for all manual role assignments
    if ($includemanual) {
        $params['component'] = '';
        role_unassign_all($params, $subcontexts, false);
    }
}
コード例 #30
0
 /**
  * Do any enrolments need expiration processing.
  *
  * Plugins that want to call this functionality must implement 'expiredaction' config setting.
  *
  * @param progress_trace $trace
  * @param int $courseid one course, empty mean all
  * @return bool true if any data processed, false if not
  */
 public function process_expirations(progress_trace $trace, $courseid = null)
 {
     global $DB;
     $name = $this->get_name();
     if (!enrol_is_enabled($name)) {
         $trace->finished();
         return false;
     }
     $processed = false;
     $params = array();
     $coursesql = "";
     if ($courseid) {
         $coursesql = "AND e.courseid = :courseid";
     }
     // 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 = :enrol)\n                      JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)\n                     WHERE ue.timeend > 0 AND ue.timeend < :now {$coursesql}";
         $params = array('now' => time(), 'courselevel' => CONTEXT_COURSE, 'enrol' => $name, 'courseid' => $courseid);
         $rs = $DB->get_recordset_sql($sql, $params);
         foreach ($rs as $ue) {
             if (!$processed) {
                 $trace->output("Starting processing of enrol_{$name} expirations...");
                 $processed = true;
             }
             if (empty($instances[$ue->enrolid])) {
                 $instances[$ue->enrolid] = $DB->get_record('enrol', array('id' => $ue->enrolid));
             }
             $instance = $instances[$ue->enrolid];
             if (!$this->roles_protected()) {
                 // Let's just guess what extra roles are supposed to be removed.
                 if ($instance->roleid) {
                     role_unassign($instance->roleid, $ue->userid, $ue->contextid);
                 }
             }
             // The unenrol cleans up all subcontexts if this is the only course enrolment for this user.
             $this->unenrol_user($instance, $ue->userid);
             $trace->output("Unenrolling expired user {$ue->userid} from course {$instance->courseid}", 1);
         }
         $rs->close();
         unset($instances);
     } else {
         if ($action == ENROL_EXT_REMOVED_SUSPENDNOROLES or $action == ENROL_EXT_REMOVED_SUSPEND) {
             $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 = :enrol)\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 {$coursesql}";
             $params = array('now' => time(), 'courselevel' => CONTEXT_COURSE, 'useractive' => ENROL_USER_ACTIVE, 'enrol' => $name, 'courseid' => $courseid);
             $rs = $DB->get_recordset_sql($sql, $params);
             foreach ($rs as $ue) {
                 if (!$processed) {
                     $trace->output("Starting processing of enrol_{$name} expirations...");
                     $processed = true;
                 }
                 if (empty($instances[$ue->enrolid])) {
                     $instances[$ue->enrolid] = $DB->get_record('enrol', array('id' => $ue->enrolid));
                 }
                 $instance = $instances[$ue->enrolid];
                 if ($action == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
                     if (!$this->roles_protected()) {
                         // Let's just guess what roles should be removed.
                         $count = $DB->count_records('role_assignments', array('userid' => $ue->userid, 'contextid' => $ue->contextid));
                         if ($count == 1) {
                             role_unassign_all(array('userid' => $ue->userid, 'contextid' => $ue->contextid, 'component' => '', 'itemid' => 0));
                         } else {
                             if ($count > 1 and $instance->roleid) {
                                 role_unassign($instance->roleid, $ue->userid, $ue->contextid, '', 0);
                             }
                         }
                     }
                     // In any case remove all roles that belong to this instance and user.
                     role_unassign_all(array('userid' => $ue->userid, 'contextid' => $ue->contextid, 'component' => 'enrol_' . $name, 'itemid' => $instance->id), true);
                     // Final cleanup of subcontexts if there are no more course roles.
                     if (0 == $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);
                     }
                 }
                 $this->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED);
                 $trace->output("Suspending expired user {$ue->userid} in course {$instance->courseid}", 1);
             }
             $rs->close();
             unset($instances);
         } else {
             // ENROL_EXT_REMOVED_KEEP means no changes.
         }
     }
     if ($processed) {
         $trace->output("...finished processing of enrol_{$name} expirations");
     } else {
         $trace->output("No expired enrol_{$name} enrolments detected");
     }
     $trace->finished();
     return $processed;
 }