MDL-37716 standardise enrolment expiration code

This commit is contained in:
Petr Škoda 2013-01-26 14:55:11 +01:00
parent b3778a0dec
commit d8f22c49b1
4 changed files with 127 additions and 269 deletions

View File

@ -614,112 +614,6 @@ class enrol_flatfile_plugin extends enrol_plugin {
}
}
/**
* Do any enrolment expiration processing.
*
* @param progress_trace $trace
* @return bool true if any data processed, false if not
*/
protected function process_expirations(progress_trace $trace) {
global $DB;
//TODO: this method should be moved to parent class once we refactor all existing enrols, see MDL-36504.
$processed = false;
$name = $this->get_name();
// 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
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = :enrol)
JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)
WHERE ue.timeend > 0 AND ue.timeend < :now";
$params = array('now'=>time(), 'courselevel'=>CONTEXT_COURSE, 'enrol'=>$name);
$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) {
$instances = array();
$sql = "SELECT ue.*, e.courseid, c.id AS contextid
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = :enrol)
JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)
WHERE ue.timeend > 0 AND ue.timeend < :now
AND ue.status = :useractive";
$params = array('now'=>time(), 'courselevel'=>CONTEXT_COURSE, 'useractive'=>ENROL_USER_ACTIVE, 'enrol'=>$name);
$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 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;
}
/**
* Returns the user who is responsible for flatfile enrolments in given curse.
*

View File

@ -302,110 +302,4 @@ class enrol_paypal_plugin extends enrol_plugin {
$this->process_expirations($trace);
return 0;
}
/**
* Do any enrolment expiration processing.
*
* @param progress_trace $trace
* @return bool true if any data processed, false if not
*/
protected function process_expirations(progress_trace $trace) {
global $DB;
//TODO: this method should be moved to parent class once we refactor all existing enrols, see MDL-36504.
$processed = false;
$name = $this->get_name();
// 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
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = :enrol)
JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)
WHERE ue.timeend > 0 AND ue.timeend < :now";
$params = array('now'=>time(), 'courselevel'=>CONTEXT_COURSE, 'enrol'=>$name);
$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) {
$instances = array();
$sql = "SELECT ue.*, e.courseid, c.id AS contextid
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = :enrol)
JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)
WHERE ue.timeend > 0 AND ue.timeend < :now
AND ue.status = :useractive";
$params = array('now'=>time(), 'courselevel'=>CONTEXT_COURSE, 'useractive'=>ENROL_USER_ACTIVE, 'enrol'=>$name);
$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 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;
}
}

View File

@ -446,65 +446,11 @@ class enrol_self_plugin extends enrol_plugin {
}
$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
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'self')
JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)
WHERE ue.timeend > 0 AND ue.timeend < :now
$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);
$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
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'self')
JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)
WHERE ue.timeend > 0 AND ue.timeend < :now
AND ue.status = :useractive
$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);
$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('...user self-enrolment updates finished.');
$trace->finished();
$this->process_expirations($trace, $courseid);
return 0;
}

View File

@ -1820,6 +1820,125 @@ abstract class enrol_plugin {
return array();
}
/**
* 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
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = :enrol)
JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)
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
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = :enrol)
JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)
WHERE ue.timeend > 0 AND ue.timeend < :now
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;
}
/**
* Send expiry notifications.
*
@ -1837,13 +1956,18 @@ abstract class enrol_plugin {
public function send_expiry_notifications($trace) {
global $DB, $CFG;
$name = $this->get_name();
if (!enrol_is_enabled($name)) {
$trace->finished();
return;
}
// Unfortunately this may take a long time, it should not be interrupted,
// otherwise users get duplicate notification.
@set_time_limit(0);
raise_memory_limit(MEMORY_HUGE);
$name = $this->get_name();
$expirynotifylast = $this->get_config('expirynotifylast', 0);
$expirynotifyhour = $this->get_config('expirynotifyhour');