mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 16:32:18 +02:00
Merge branch 'w43_MDL-35843_m42_expiryself' of git://github.com/skodak/moodle
This commit is contained in:
commit
06b33f67b0
@ -63,6 +63,6 @@ $plugin = enrol_get_plugin('manual');
|
||||
|
||||
$result = $plugin->sync(null, $verbose);
|
||||
|
||||
$plugin->send_notifications($verbose);
|
||||
$plugin->send_expiry_notifications($verbose);
|
||||
|
||||
exit($result);
|
||||
|
@ -38,6 +38,14 @@ function xmldb_enrol_manual_upgrade($oldversion) {
|
||||
upgrade_plugin_savepoint(true, 2012100702, 'enrol', 'manual');
|
||||
}
|
||||
|
||||
if ($oldversion < 2012101400) {
|
||||
// Delete obsoleted settings, now using expiry* prefix to make them more consistent.
|
||||
unset_config('notifylast', 'enrol_manual');
|
||||
unset_config('notifyhour', 'enrol_manual');
|
||||
upgrade_plugin_savepoint(true, 2012101400, 'enrol', 'manual');
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -54,12 +54,12 @@ class enrol_manual_edit_form extends moodleform {
|
||||
$mform->setDefault('enrolperiod', $plugin->get_config('enrolperiod'));
|
||||
$mform->addHelpButton('enrolperiod', 'defaultperiod', 'enrol_manual');
|
||||
|
||||
$options = array(0 => get_string('no'), 1 => get_string('expirynotifyteacher', 'enrol_manual'), 2 => get_string('expirynotifyall', 'enrol_manual'));
|
||||
$mform->addElement('select', 'expirynotify', get_string('expirynotify', 'enrol_manual'), $options);
|
||||
$mform->addHelpButton('expirynotify', 'expirynotify', 'enrol_manual');
|
||||
$options = array(0 => get_string('no'), 1 => get_string('expirynotifyenroller', 'core_enrol'), 2 => get_string('expirynotifyall', 'core_enrol'));
|
||||
$mform->addElement('select', 'expirynotify', get_string('expirynotify', 'core_enrol'), $options);
|
||||
$mform->addHelpButton('expirynotify', 'expirynotify', 'core_enrol');
|
||||
|
||||
$mform->addElement('duration', 'expirythreshold', get_string('expirythreshold', 'enrol_manual'), array('optional' => false, 'defaultunit' => 86400));
|
||||
$mform->addHelpButton('expirythreshold', 'expirythreshold', 'enrol_manual');
|
||||
$mform->addElement('duration', 'expirythreshold', get_string('expirythreshold', 'core_enrol'), array('optional' => false, 'defaultunit' => 86400));
|
||||
$mform->addHelpButton('expirythreshold', 'expirythreshold', 'core_enrol');
|
||||
$mform->disabledIf('expirythreshold', 'expirynotify', 'eq', 0);
|
||||
|
||||
$mform->addElement('hidden', 'courseid');
|
||||
@ -75,7 +75,7 @@ class enrol_manual_edit_form extends moodleform {
|
||||
$errors = parent::validation($data, $files);
|
||||
|
||||
if ($data['expirynotify'] > 0 and $data['expirythreshold'] < 86400) {
|
||||
$errors['expirythreshold'] = get_string('errorthresholdlow', 'enrol_manual');
|
||||
$errors['expirythreshold'] = get_string('errorthresholdlow', 'core_enrol');
|
||||
}
|
||||
|
||||
return $errors;
|
||||
|
@ -35,7 +35,6 @@ $string['editenrolment'] = 'Edit enrolment';
|
||||
$string['editselectedusers'] = 'Edit selected user enrolments';
|
||||
$string['enrolledincourserole'] = 'Enrolled in "{$a->course}" as "{$a->role}"';
|
||||
$string['enrolusers'] = 'Enrol users';
|
||||
$string['errorthresholdlow'] = 'Notification threshold must be at least 1 day.';
|
||||
$string['expiredaction'] = 'Enrolment expiration action';
|
||||
$string['expiredaction_help'] = 'Select action to carry out when user enrolment expires. Please note that some user data and settings are purged from course during course unenrolment.';
|
||||
$string['expirymessageenrollersubject'] = 'Enrolment expiry notification';
|
||||
@ -50,20 +49,12 @@ $string['expirymessageenrolledbody'] = 'Dear {$a->user},
|
||||
This is a notification that your enrolment in the course \'{$a->course}\' is due to expire on {$a->timeend}.
|
||||
|
||||
If you need help, please contact {$a->enroller}.';
|
||||
$string['expirynotify'] = 'Notify before enrolment expires';
|
||||
$string['expirynotify_help'] = 'This setting determines whether enrolment expiry notification messages are sent.';
|
||||
$string['expirynotifyall'] = 'Enroller and enrolled user';
|
||||
$string['expirynotifyteacher'] = 'Enroller only';
|
||||
$string['expirythreshold'] = 'Notification threshold';
|
||||
$string['expirythreshold_help'] = 'This setting specifies the number of days before enrolment expiry that a notification message is sent.';
|
||||
$string['expirythreshold_help'] = 'How long before expiration should be users notified?';
|
||||
$string['manual:config'] = 'Configure manual enrol instances';
|
||||
$string['manual:enrol'] = 'Enrol users';
|
||||
$string['manual:manage'] = 'Manage user enrolments';
|
||||
$string['manual:unenrol'] = 'Unenrol users from the course';
|
||||
$string['manual:unenrolself'] = 'Unenrol self from the course';
|
||||
$string['messageprovider:expiry_notification'] = 'Manual enrolment expiry notifications';
|
||||
$string['notifyhour'] = 'Hour to send enrolment expiry notifications';
|
||||
$string['pluginname'] = 'Manual enrolments';
|
||||
$string['pluginname_desc'] = 'The manual enrolments plugin allows users to be enrolled manually via a link in the course administration settings, by a user with appropriate permissions such as a teacher. The plugin should normally be enabled, since certain other enrolment plugins, such as self enrolment, require it.';
|
||||
$string['status'] = 'Enable manual enrolments';
|
||||
|
@ -27,7 +27,7 @@ defined('MOODLE_INTERNAL') || die();
|
||||
class enrol_manual_plugin extends enrol_plugin {
|
||||
|
||||
protected $lasternoller = null;
|
||||
protected $lasternollercourseid = 0;
|
||||
protected $lasternollerinstanceid = 0;
|
||||
|
||||
public function roles_protected() {
|
||||
// Users may tweak the roles later.
|
||||
@ -280,7 +280,7 @@ class enrol_manual_plugin extends enrol_plugin {
|
||||
*/
|
||||
public function cron() {
|
||||
$this->sync(null, true);
|
||||
$this->send_notifications(true);
|
||||
$this->send_expiry_notifications(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -376,257 +376,38 @@ class enrol_manual_plugin extends enrol_plugin {
|
||||
}
|
||||
|
||||
/**
|
||||
* Send notifications.
|
||||
*
|
||||
* @param bool $verbose verbose CLI output
|
||||
*/
|
||||
public function send_notifications($verbose = false) {
|
||||
global $DB, $CFG;
|
||||
|
||||
// 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);
|
||||
|
||||
$notifylast = $this->get_config('notifylast', 0);
|
||||
$notifyhour = $this->get_config('notifyhour', 6);
|
||||
$timenow = time();
|
||||
|
||||
$notifytime = usergetmidnight($timenow, $CFG->timezone) + ($notifyhour * 3600);
|
||||
|
||||
if ($notifylast > $notifytime) {
|
||||
if ($verbose) {
|
||||
mtrace('Manual enrolment notifications were already sent today at '.userdate($notifylast, '', $CFG->timezone).'.');
|
||||
}
|
||||
return;
|
||||
} else if ($timenow < $notifytime) {
|
||||
if ($verbose) {
|
||||
mtrace('Manual enrolment notifications will be sent at '.userdate($notifytime, '', $CFG->timezone).'.');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ($verbose) {
|
||||
mtrace('Processing manual enrolment notifications...');
|
||||
}
|
||||
|
||||
// Notify users responsible for enrolment once every day.
|
||||
$sql = "SELECT ue.*, e.expirynotify, e.notifyall, e.expirythreshold, e.courseid, c.fullname
|
||||
FROM {user_enrolments} ue
|
||||
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'manual' AND e.expirynotify > 0 AND e.status = :enabled)
|
||||
JOIN {course} c ON (c.id = e.courseid)
|
||||
JOIN {user} u ON (u.id = ue.userid AND u.deleted = 0 AND u.suspended = 0)
|
||||
WHERE ue.status = :active AND ue.timeend > 0 AND ue.timeend > :now1 AND ue.timeend < (e.expirythreshold + :now2)
|
||||
ORDER BY ue.enrolid ASC, u.lastname ASC, u.firstname ASC, u.id ASC";
|
||||
$params = array('enabled'=>ENROL_INSTANCE_ENABLED, 'active'=>ENROL_USER_ACTIVE, 'now1'=>$timenow, 'now2'=>$timenow);
|
||||
|
||||
$rs = $DB->get_recordset_sql($sql, $params);
|
||||
|
||||
$lastenrollid = 0;
|
||||
$users = array();
|
||||
|
||||
foreach($rs as $ue) {
|
||||
if ($lastenrollid and $lastenrollid != $ue->enrolid) {
|
||||
$this->notify_expiry_enroller($lastenrollid, $users, $verbose);
|
||||
$users = array();
|
||||
}
|
||||
$lastenrollid = $ue->enrolid;
|
||||
|
||||
$enroller = $this->get_enroller($ue->courseid);
|
||||
$context = context_course::instance($ue->courseid);
|
||||
|
||||
$user = $DB->get_record('user', array('id'=>$ue->userid));
|
||||
|
||||
$users[] = array('fullname'=>fullname($user, has_capability('moodle/site:viewfullnames', $context, $enroller)), 'timeend'=>$ue->timeend);
|
||||
|
||||
if (!$ue->notifyall) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($ue->timeend - $ue->expirythreshold + 86400 < $timenow) {
|
||||
// Notify enrolled users only once at the start of the threshold.
|
||||
if ($verbose) {
|
||||
mtrace(" user $ue->userid was already notified that enrolment in course $ue->courseid expires on ".userdate($ue->timeend, '', $CFG->timezone));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->notify_expiry_enrolled($user, $ue, $verbose);
|
||||
}
|
||||
$rs->close();
|
||||
|
||||
if ($lastenrollid and $users) {
|
||||
$this->notify_expiry_enroller($lastenrollid, $users, $verbose);
|
||||
}
|
||||
|
||||
if ($verbose) {
|
||||
mtrace('...notification processing finished.');
|
||||
}
|
||||
$this->set_config('notifylast', $timenow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user who is responsible for manual enrolments in given course.
|
||||
* Returns the user who is responsible for manual enrolments in given instance.
|
||||
*
|
||||
* Usually it is the first editing teacher - the person with "highest authority"
|
||||
* as defined by sort_by_roleassignment_authority() having 'enrol/manual:manage'
|
||||
* capability.
|
||||
*
|
||||
* @param int $courseid
|
||||
* @param int $instanceid enrolment instance id
|
||||
* @return stdClass user record
|
||||
*/
|
||||
protected function get_enroller($courseid) {
|
||||
if ($this->lasternollercourseid == $courseid and $this->lasternoller) {
|
||||
protected function get_enroller($instanceid) {
|
||||
global $DB;
|
||||
|
||||
if ($this->lasternollerinstanceid == $instanceid and $this->lasternoller) {
|
||||
return $this->lasternoller;
|
||||
}
|
||||
|
||||
$context = context_course::instance($courseid);
|
||||
$instance = $DB->get_record('enrol', array('id'=>$instanceid, 'enrol'=>$this->get_name()), '*', MUST_EXIST);
|
||||
$context = context_course::instance($instance->courseid);
|
||||
|
||||
if ($users = get_enrolled_users($context, 'enrol/manual:manage')) {
|
||||
$users = sort_by_roleassignment_authority($users, $context);
|
||||
$this->lasternoller = reset($users);
|
||||
unset($users);
|
||||
} else {
|
||||
$this->lasternoller = get_admin();
|
||||
$this->lasternoller = parent::get_enroller($instanceid);
|
||||
}
|
||||
|
||||
$this->lasternollercourseid = $courseid;
|
||||
$this->lasternollerinstanceid = $instanceid;
|
||||
|
||||
return $this->lasternoller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify user about incoming expiration of their enrolment,
|
||||
* it is called only if notification of enrolled users (aka students) is enabled in course.
|
||||
*
|
||||
* This is executed only once for each expiring enrolment right
|
||||
* at the start of the expiration threshold.
|
||||
*
|
||||
* @param stdClass $user
|
||||
* @param stdClass $ue
|
||||
* @param bool $verbose
|
||||
*/
|
||||
protected function notify_expiry_enrolled($user, $ue, $verbose) {
|
||||
global $CFG, $SESSION;
|
||||
|
||||
// Some nasty hackery to get strings and dates localised for target user.
|
||||
$sessionlang = isset($SESSION->lang) ? $SESSION->lang : null;
|
||||
if (get_string_manager()->translation_exists($user->lang, false)) {
|
||||
$SESSION->lang = $user->lang;
|
||||
moodle_setlocale();
|
||||
}
|
||||
|
||||
$enroller = $this->get_enroller($ue->courseid);
|
||||
$context = context_course::instance($ue->courseid);
|
||||
|
||||
$subject = get_string('expirymessageenrolledsubject', 'enrol_manual', null);
|
||||
$a = new stdClass();
|
||||
$a->course = format_string($ue->fullname, true, array('context'=>$context));
|
||||
$a->user = fullname($user, true);
|
||||
$a->timeend = userdate($ue->timeend, '', $user->timezone);
|
||||
$a->enroller = fullname($enroller, has_capability('moodle/site:viewfullnames', $context, $user));
|
||||
$body = get_string('expirymessageenrolledbody', 'enrol_manual', $a);
|
||||
|
||||
$message = new stdClass();
|
||||
$message->notification = 1;
|
||||
$message->component = 'enrol_manual';
|
||||
$message->name = 'expiry_notification';
|
||||
$message->userfrom = $enroller;
|
||||
$message->userto = $user;
|
||||
$message->subject = $subject;
|
||||
$message->fullmessage = $body;
|
||||
$message->fullmessageformat = FORMAT_MARKDOWN;
|
||||
$message->fullmessagehtml = markdown_to_html($body);
|
||||
$message->smallmessage = $subject;
|
||||
$message->contexturlname = $a->course;
|
||||
$message->contexturl = (string)new moodle_url('/course/view.php', array('id'=>$ue->courseid));
|
||||
|
||||
if (message_send($message)) {
|
||||
if ($verbose) {
|
||||
mtrace(" notifying user $ue->userid that enrolment in course $ue->courseid expires on ".userdate($ue->timeend, '', $CFG->timezone));
|
||||
}
|
||||
} else {
|
||||
if ($verbose) {
|
||||
mtrace(" error notifying user $ue->userid that enrolment in course $ue->courseid expires on ".userdate($ue->timeend, '', $CFG->timezone));
|
||||
}
|
||||
}
|
||||
|
||||
if ($SESSION->lang !== $sessionlang) {
|
||||
$SESSION->lang = $sessionlang;
|
||||
moodle_setlocale();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify person responsible for enrolments that some user enrolments will be expired soon,
|
||||
* it is called only if notification of enrollers (aka teachers) is enabled in course.
|
||||
*
|
||||
* This is called repeatedly every day for each course if there are any pending expiration
|
||||
* in the expiration threshold.
|
||||
*
|
||||
* @param int $eid
|
||||
* @param array $users
|
||||
* @param bool $verbose
|
||||
*/
|
||||
protected function notify_expiry_enroller($eid, $users, $verbose) {
|
||||
global $DB, $SESSION;
|
||||
|
||||
$instance = $DB->get_record('enrol', array('id'=>$eid, 'enrol'=>'manual'));
|
||||
$context = context_course::instance($instance->courseid);
|
||||
$course = $DB->get_record('course', array('id'=>$instance->courseid));
|
||||
|
||||
$enroller = $this->get_enroller($instance->courseid);
|
||||
$admin = get_admin();
|
||||
|
||||
// Some nasty hackery to get strings and dates localised for target user.
|
||||
$sessionlang = isset($SESSION->lang) ? $SESSION->lang : null;
|
||||
if (get_string_manager()->translation_exists($enroller->lang, false)) {
|
||||
$SESSION->lang = $enroller->lang;
|
||||
moodle_setlocale();
|
||||
}
|
||||
|
||||
foreach($users as $key=>$info) {
|
||||
$users[$key] = '* '.$info['fullname'].' - '.userdate($info['timeend'], '', $enroller->timezone);
|
||||
}
|
||||
|
||||
$subject = get_string('expirymessageenrollersubject', 'enrol_manual', null);
|
||||
$a = new stdClass();
|
||||
$a->course = format_string($course->fullname, true, array('context'=>$context));
|
||||
$a->threshold = get_string('numdays', '', $instance->expirythreshold / (60*60*24));
|
||||
$a->users = implode("\n", $users);
|
||||
$a->extendurl = (string)new moodle_url('/enrol/users.php', array('id'=>$instance->courseid));
|
||||
$body = get_string('expirymessageenrollerbody', 'enrol_manual', $a);
|
||||
|
||||
$message = new stdClass();
|
||||
$message->notification = 1;
|
||||
$message->component = 'enrol_manual';
|
||||
$message->name = 'expiry_notification';
|
||||
$message->userfrom = $admin;
|
||||
$message->userto = $enroller;
|
||||
$message->subject = $subject;
|
||||
$message->fullmessage = $body;
|
||||
$message->fullmessageformat = FORMAT_MARKDOWN;
|
||||
$message->fullmessagehtml = markdown_to_html($body);
|
||||
$message->smallmessage = $subject;
|
||||
$message->contexturlname = $a->course;
|
||||
$message->contexturl = $a->extendurl;
|
||||
|
||||
if (message_send($message)) {
|
||||
if ($verbose) {
|
||||
mtrace(" notifying user $enroller->id about all expiring manual enrolments in course $instance->courseid");
|
||||
}
|
||||
} else {
|
||||
if ($verbose) {
|
||||
mtrace(" error notifying user $enroller->id about all expiring manual enrolments in course $instance->courseid");
|
||||
}
|
||||
}
|
||||
|
||||
if ($SESSION->lang !== $sessionlang) {
|
||||
$SESSION->lang = $sessionlang;
|
||||
moodle_setlocale();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of the user enrolment actions.
|
||||
*
|
||||
|
@ -42,7 +42,7 @@ if ($ADMIN->fulltree) {
|
||||
for ($i=0; $i<24; $i++) {
|
||||
$options[$i] = $i;
|
||||
}
|
||||
$settings->add(new admin_setting_configselect('enrol_manual/notifyhour', get_string('notifyhour', 'enrol_manual'), '', 6, $options));
|
||||
$settings->add(new admin_setting_configselect('enrol_manual/expirynotifyhour', get_string('expirynotifyhour', 'core_enrol'), '', 6, $options));
|
||||
|
||||
|
||||
//--- enrol instance defaults ----------------------------------------------------------------------------
|
||||
@ -68,11 +68,11 @@ if ($ADMIN->fulltree) {
|
||||
$settings->add(new admin_setting_configduration('enrol_manual/enrolperiod',
|
||||
get_string('defaultperiod', 'enrol_manual'), get_string('defaultperiod_desc', 'enrol_manual'), 0));
|
||||
|
||||
$options = array(0 => get_string('no'), 1 => get_string('expirynotifyteacher', 'enrol_manual'), 2 => get_string('expirynotifyall', 'enrol_manual'));
|
||||
$options = array(0 => get_string('no'), 1 => get_string('expirynotifyenroller', 'core_enrol'), 2 => get_string('expirynotifyall', 'core_enrol'));
|
||||
$settings->add(new admin_setting_configselect('enrol_manual/expirynotify',
|
||||
get_string('expirynotify', 'enrol_manual'), get_string('expirynotify_help', 'enrol_manual'), 0, $options));
|
||||
get_string('expirynotify', 'core_enrol'), get_string('expirynotify_help', 'core_enrol'), 0, $options));
|
||||
|
||||
$settings->add(new admin_setting_configduration('enrol_manual/expirythreshold',
|
||||
get_string('expirythreshold', 'enrol_manual'), get_string('expirythreshold_help', 'enrol_manual'), 86400, 86400));
|
||||
get_string('expirythreshold', 'core_enrol'), get_string('expirythreshold_help', 'core_enrol'), 86400, 86400));
|
||||
|
||||
}
|
||||
|
@ -316,8 +316,8 @@ class enrol_manual_lib_testcase extends advanced_testcase {
|
||||
|
||||
// Note: hopefully nobody executes the unit tests the last second before midnight...
|
||||
|
||||
$manualplugin->set_config('notifylast', $now - 60*60*24);
|
||||
$manualplugin->set_config('notifyhour', 0);
|
||||
$manualplugin->set_config('expirynotifylast', $now - 60*60*24);
|
||||
$manualplugin->set_config('expirynotifyhour', 0);
|
||||
|
||||
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
|
||||
$this->assertNotEmpty($studentrole);
|
||||
@ -394,7 +394,7 @@ class enrol_manual_lib_testcase extends advanced_testcase {
|
||||
|
||||
$sink = $this->redirectMessages();
|
||||
|
||||
$manualplugin->send_notifications(false);
|
||||
$manualplugin->send_expiry_notifications(false);
|
||||
|
||||
$messages = $sink->get_messages();
|
||||
|
||||
@ -451,18 +451,18 @@ class enrol_manual_lib_testcase extends advanced_testcase {
|
||||
// Make sure that notifications are not repeated.
|
||||
$sink->clear();
|
||||
|
||||
$manualplugin->send_notifications(false);
|
||||
$manualplugin->send_expiry_notifications(false);
|
||||
$this->assertEquals(0, $sink->count());
|
||||
|
||||
// use invalid notification hour to verify that before the hour the notifications are not sent.
|
||||
$manualplugin->set_config('notifylast', time() - 60*60*24);
|
||||
$manualplugin->set_config('notifyhour', '24');
|
||||
$manualplugin->set_config('expirynotifylast', time() - 60*60*24);
|
||||
$manualplugin->set_config('expirynotifyhour', '24');
|
||||
|
||||
$manualplugin->send_notifications(false);
|
||||
$manualplugin->send_expiry_notifications(false);
|
||||
$this->assertEquals(0, $sink->count());
|
||||
|
||||
$manualplugin->set_config('notifyhour', '0');
|
||||
$manualplugin->send_notifications(false);
|
||||
$manualplugin->set_config('expirynotifyhour', '0');
|
||||
$manualplugin->send_expiry_notifications(false);
|
||||
$this->assertEquals(6, $sink->count());
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2012100705; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->version = 2012101400; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2012100500; // Requires this Moodle version
|
||||
$plugin->component = 'enrol_manual'; // Full name of the plugin (used for diagnostics)
|
||||
$plugin->cron = 600;
|
||||
|
@ -59,8 +59,11 @@ Example:
|
||||
|
||||
$verbose = !empty($options['verbose']);
|
||||
|
||||
/** @var $plugin enrol_self_plugin */
|
||||
$plugin = enrol_get_plugin('self');
|
||||
|
||||
$result = $plugin->sync(null, $verbose);
|
||||
|
||||
$plugin->send_expiry_notifications($verbose);
|
||||
|
||||
exit($result);
|
||||
|
29
enrol/self/db/messages.php
Normal file
29
enrol/self/db/messages.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Defines message providers for self enrolments.
|
||||
*
|
||||
* @package enrol_self
|
||||
* @copyright 2012 Petr Skoda {@link http://skodak.org}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$messageproviders = array (
|
||||
|
||||
'expiry_notification' => array(),
|
||||
|
||||
);
|
45
enrol/self/db/upgrade.php
Normal file
45
enrol/self/db/upgrade.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file keeps track of upgrades to the self enrolment plugin
|
||||
*
|
||||
* @package enrol_self
|
||||
* @copyright 2012 Petr Skoda {@link http://skodak.org
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
function xmldb_enrol_self_upgrade($oldversion) {
|
||||
global $CFG, $DB, $OUTPUT;
|
||||
|
||||
$dbman = $DB->get_manager();
|
||||
|
||||
// Moodle v2.3.0 release upgrade line
|
||||
// Put any upgrade step following this
|
||||
|
||||
if ($oldversion < 2012101400) {
|
||||
// Set default expiry threshold to 1 day.
|
||||
$DB->execute("UPDATE {enrol} SET expirythreshold = 86400 WHERE enrol = 'self' AND expirythreshold = 0");
|
||||
upgrade_plugin_savepoint(true, 2012101400, 'enrol', 'self');
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,12 @@ $plugin = enrol_get_plugin('self');
|
||||
|
||||
if ($instanceid) {
|
||||
$instance = $DB->get_record('enrol', array('courseid'=>$course->id, 'enrol'=>'self', 'id'=>$instanceid), '*', MUST_EXIST);
|
||||
// Merge these two settings to one value for the single selection element.
|
||||
if ($instance->notifyall and $instance->expirynotify) {
|
||||
$instance->expirynotify = 2;
|
||||
}
|
||||
unset($instance->notifyall);
|
||||
|
||||
} else {
|
||||
require_capability('moodle/course:enrolconfig', $context);
|
||||
// No instance yet, we have to add new instance.
|
||||
@ -63,6 +69,16 @@ if ($mform->is_cancelled()) {
|
||||
redirect($return);
|
||||
|
||||
} else if ($data = $mform->get_data()) {
|
||||
if ($data->expirynotify == 2) {
|
||||
$data->expirynotify = 1;
|
||||
$data->notifyall = 1;
|
||||
} else {
|
||||
$data->notifyall = 0;
|
||||
}
|
||||
if (!$data->expirynotify) {
|
||||
// Keep previous/default value of disabled expirythreshold option.
|
||||
$data->expirythreshold = $instance->expirythreshold;
|
||||
}
|
||||
if ($instance->id) {
|
||||
$reset = ($instance->status != $data->status);
|
||||
|
||||
@ -77,6 +93,9 @@ if ($mform->is_cancelled()) {
|
||||
$instance->customtext1 = $data->customtext1;
|
||||
$instance->roleid = $data->roleid;
|
||||
$instance->enrolperiod = $data->enrolperiod;
|
||||
$instance->expirynotify = $data->expirynotify;
|
||||
$instance->notifyall = $data->notifyall;
|
||||
$instance->expirythreshold = $data->expirythreshold;
|
||||
$instance->enrolstartdate = $data->enrolstartdate;
|
||||
$instance->enrolenddate = $data->enrolenddate;
|
||||
$instance->timemodified = time();
|
||||
@ -87,9 +106,23 @@ if ($mform->is_cancelled()) {
|
||||
}
|
||||
|
||||
} else {
|
||||
$fields = array('status'=>$data->status, 'name'=>$data->name, 'password'=>$data->password, 'customint1'=>$data->customint1, 'customint2'=>$data->customint2,
|
||||
'customint3'=>$data->customint3, 'customint4'=>$data->customint4, 'customint5'=>$data->customint5, 'customtext1'=>$data->customtext1,
|
||||
'roleid'=>$data->roleid, 'enrolperiod'=>$data->enrolperiod, 'enrolstartdate'=>$data->enrolstartdate, 'enrolenddate'=>$data->enrolenddate);
|
||||
$fields = array(
|
||||
'status' => $data->status,
|
||||
'name' => $data->name,
|
||||
'password' => $data->password,
|
||||
'customint1' => $data->customint1,
|
||||
'customint2' => $data->customint2,
|
||||
'customint3' => $data->customint3,
|
||||
'customint4' => $data->customint4,
|
||||
'customint5' => $data->customint5,
|
||||
'customtext1' => $data->customtext1,
|
||||
'roleid' => $data->roleid,
|
||||
'enrolperiod' => $data->enrolperiod,
|
||||
'expirynotify' => $data->expirynotify,
|
||||
'notifyall' => $data->notifyall,
|
||||
'expirythreshold' => $data->expirythreshold,
|
||||
'enrolstartdate' => $data->enrolstartdate,
|
||||
'enrolenddate' => $data->enrolenddate);
|
||||
$plugin->add_instance($course, $fields);
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,14 @@ class enrol_self_edit_form extends moodleform {
|
||||
$mform->setDefault('enrolperiod', $plugin->get_config('enrolperiod'));
|
||||
$mform->addHelpButton('enrolperiod', 'enrolperiod', 'enrol_self');
|
||||
|
||||
$options = array(0 => get_string('no'), 1 => get_string('expirynotifyenroller', 'core_enrol'), 2 => get_string('expirynotifyall', 'core_enrol'));
|
||||
$mform->addElement('select', 'expirynotify', get_string('expirynotify', 'core_enrol'), $options);
|
||||
$mform->addHelpButton('expirynotify', 'expirynotify', 'core_enrol');
|
||||
|
||||
$mform->addElement('duration', 'expirythreshold', get_string('expirythreshold', 'core_enrol'), array('optional' => false, 'defaultunit' => 86400));
|
||||
$mform->addHelpButton('expirythreshold', 'expirythreshold', 'core_enrol');
|
||||
$mform->disabledIf('expirythreshold', 'expirynotify', 'eq', 0);
|
||||
|
||||
$mform->addElement('date_selector', 'enrolstartdate', get_string('enrolstartdate', 'enrol_self'), array('optional' => true));
|
||||
$mform->setDefault('enrolstartdate', 0);
|
||||
$mform->addHelpButton('enrolstartdate', 'enrolstartdate', 'enrol_self');
|
||||
@ -187,6 +195,10 @@ class enrol_self_edit_form extends moodleform {
|
||||
}
|
||||
}
|
||||
|
||||
if ($data['expirynotify'] > 0 and $data['expirythreshold'] < 86400) {
|
||||
$errors['expirythreshold'] = get_string('errorthresholdlow', 'core_enrol');
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,18 @@ $string['enrolstartdate'] = 'Start date';
|
||||
$string['enrolstartdate_help'] = 'If enabled, users can enrol themselves from this date onward only.';
|
||||
$string['expiredaction'] = 'Enrolment expiration action';
|
||||
$string['expiredaction_help'] = 'Select action to carry out when user enrolment expires. Please note that some user data and settings are purged from course during course unenrolment.';
|
||||
$string['expirymessageenrollersubject'] = 'Self enrolment expiry notification';
|
||||
$string['expirymessageenrollerbody'] = 'Self enrolment in the course \'{$a->course}\' will expire within the next {$a->threshold} for the following users:
|
||||
|
||||
{$a->users}
|
||||
|
||||
To extend their enrolment, go to {$a->extendurl}';
|
||||
$string['expirymessageenrolledsubject'] = 'Self enrolment expiry notification';
|
||||
$string['expirymessageenrolledbody'] = 'Dear {$a->user},
|
||||
|
||||
This is a notification that your enrolment in the course \'{$a->course}\' is due to expire on {$a->timeend}.
|
||||
|
||||
If you need help, please contact {$a->enroller}.';
|
||||
$string['groupkey'] = 'Use group enrolment keys';
|
||||
$string['groupkey_desc'] = 'Use group enrolment keys by default.';
|
||||
$string['groupkey_help'] = 'In addition to restricting access to the course to only those who know the key, use of a group enrolment key means users are automatically added to the group when they enrol in the course.
|
||||
@ -56,6 +68,7 @@ $string['longtimenosee_help'] = 'If users haven\'t accessed a course for a long
|
||||
$string['maxenrolled'] = 'Max enrolled users';
|
||||
$string['maxenrolled_help'] = 'Specifies the maximum number of users that can self enrol. 0 means no limit.';
|
||||
$string['maxenrolledreached'] = 'Maximum number of users allowed to self-enrol was already reached.';
|
||||
$string['messageprovider:expiry_notification'] = 'Self enrolment expiry notifications';
|
||||
$string['nopassword'] = 'No enrolment key required.';
|
||||
$string['password'] = 'Enrolment key';
|
||||
$string['password_help'] = 'An enrolment key enables access to the course to be restricted to only those who know the key.
|
||||
|
@ -29,6 +29,9 @@
|
||||
*/
|
||||
class enrol_self_plugin extends enrol_plugin {
|
||||
|
||||
protected $lasternoller = null;
|
||||
protected $lasternollerinstanceid = 0;
|
||||
|
||||
/**
|
||||
* Returns optional enrolment information icons.
|
||||
*
|
||||
@ -261,12 +264,22 @@ class enrol_self_plugin extends enrol_plugin {
|
||||
* @return int id of new instance
|
||||
*/
|
||||
public function add_default_instance($course) {
|
||||
$expirynotify = $this->get_config('expirynotify', 0);
|
||||
if ($expirynotify == 2) {
|
||||
$expirynotify = 1;
|
||||
$notifyall = 1;
|
||||
} else {
|
||||
$notifyall = 0;
|
||||
}
|
||||
$fields = array('customint1' => $this->get_config('groupkey'),
|
||||
'customint2' => $this->get_config('longtimenosee'),
|
||||
'customint3' => $this->get_config('maxenrolled'),
|
||||
'customint4' => $this->get_config('sendcoursewelcomemessage'),
|
||||
'customint5' => 0,
|
||||
'enrolperiod' => $this->get_config('enrolperiod', 0),
|
||||
'expirynotify'=> $expirynotify,
|
||||
'notifyall' => $notifyall,
|
||||
'expirythreshold' => $this->get_config('expirythreshold', 86400),
|
||||
'status' => $this->get_config('status'),
|
||||
'roleid' => $this->get_config('roleid', 0));
|
||||
|
||||
@ -336,6 +349,7 @@ class enrol_self_plugin extends enrol_plugin {
|
||||
*/
|
||||
public function cron() {
|
||||
$this->sync(null, true);
|
||||
$this->send_expiry_notifications(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -475,7 +489,40 @@ class enrol_self_plugin extends enrol_plugin {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the user who is responsible for self enrolments in given instance.
|
||||
*
|
||||
* Usually it is the first editing teacher - the person with "highest authority"
|
||||
* as defined by sort_by_roleassignment_authority() having 'enrol/self:manage'
|
||||
* capability.
|
||||
*
|
||||
* @param int $instanceid enrolment instance id
|
||||
* @return stdClass user record
|
||||
*/
|
||||
protected function get_enroller($instanceid) {
|
||||
global $DB;
|
||||
|
||||
if ($this->lasternollerinstanceid == $instanceid and $this->lasternoller) {
|
||||
return $this->lasternoller;
|
||||
}
|
||||
|
||||
$instance = $DB->get_record('enrol', array('id'=>$instanceid, 'enrol'=>$this->get_name()), '*', MUST_EXIST);
|
||||
$context = context_course::instance($instance->courseid);
|
||||
|
||||
if ($users = get_enrolled_users($context, 'enrol/self:manage')) {
|
||||
$users = sort_by_roleassignment_authority($users, $context);
|
||||
$this->lasternoller = reset($users);
|
||||
unset($users);
|
||||
} else {
|
||||
$this->lasternoller = parent::get_enroller($instanceid);
|
||||
}
|
||||
|
||||
$this->lasternollerinstanceid = $instanceid;
|
||||
|
||||
return $this->lasternoller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of the user enrolment actions.
|
||||
*
|
||||
* @param course_enrolment_manager $manager
|
||||
|
@ -47,6 +47,12 @@ if ($ADMIN->fulltree) {
|
||||
);
|
||||
$settings->add(new admin_setting_configselect('enrol_self/expiredaction', get_string('expiredaction', 'enrol_self'), get_string('expiredaction_help', 'enrol_self'), ENROL_EXT_REMOVED_KEEP, $options));
|
||||
|
||||
$options = array();
|
||||
for ($i=0; $i<24; $i++) {
|
||||
$options[$i] = $i;
|
||||
}
|
||||
$settings->add(new admin_setting_configselect('enrol_self/expirynotifyhour', get_string('expirynotifyhour', 'core_enrol'), '', 6, $options));
|
||||
|
||||
//--- enrol instance defaults ----------------------------------------------------------------------------
|
||||
$settings->add(new admin_setting_heading('enrol_self_defaults',
|
||||
get_string('enrolinstancedefaults', 'admin'), get_string('enrolinstancedefaults_desc', 'admin')));
|
||||
@ -75,6 +81,13 @@ if ($ADMIN->fulltree) {
|
||||
$settings->add(new admin_setting_configduration('enrol_self/enrolperiod',
|
||||
get_string('enrolperiod', 'enrol_self'), get_string('enrolperiod_desc', 'enrol_self'), 0));
|
||||
|
||||
$options = array(0 => get_string('no'), 1 => get_string('expirynotifyenroller', 'core_enrol'), 2 => get_string('expirynotifyall', 'core_enrol'));
|
||||
$settings->add(new admin_setting_configselect('enrol_self/expirynotify',
|
||||
get_string('expirynotify', 'core_enrol'), get_string('expirynotify_help', 'core_enrol'), 0, $options));
|
||||
|
||||
$settings->add(new admin_setting_configduration('enrol_self/expirythreshold',
|
||||
get_string('expirythreshold', 'core_enrol'), get_string('expirythreshold_help', 'core_enrol'), 86400, 86400));
|
||||
|
||||
$options = array(0 => get_string('never'),
|
||||
1800 * 3600 * 24 => get_string('numdays', '', 1800),
|
||||
1000 * 3600 * 24 => get_string('numdays', '', 1000),
|
||||
|
@ -261,4 +261,177 @@ class enrol_self_testcase extends advanced_testcase {
|
||||
$this->assertEquals(5, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
|
||||
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
|
||||
}
|
||||
|
||||
public function test_send_expiry_notifications() {
|
||||
global $DB, $CFG;
|
||||
$this->resetAfterTest();
|
||||
$this->preventResetByRollback(); // Messaging does not like transactions...
|
||||
|
||||
/** @var $selfplugin enrol_self_plugin */
|
||||
$selfplugin = enrol_get_plugin('self');
|
||||
/** @var $manualplugin enrol_manual_plugin */
|
||||
$manualplugin = enrol_get_plugin('manual');
|
||||
$now = time();
|
||||
$admin = get_admin();
|
||||
|
||||
// Note: hopefully nobody executes the unit tests the last second before midnight...
|
||||
|
||||
$selfplugin->set_config('expirynotifylast', $now - 60*60*24);
|
||||
$selfplugin->set_config('expirynotifyhour', 0);
|
||||
|
||||
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
|
||||
$this->assertNotEmpty($studentrole);
|
||||
$editingteacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'));
|
||||
$this->assertNotEmpty($editingteacherrole);
|
||||
$managerrole = $DB->get_record('role', array('shortname'=>'manager'));
|
||||
$this->assertNotEmpty($managerrole);
|
||||
|
||||
$user1 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser1'));
|
||||
$user2 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser2'));
|
||||
$user3 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser3'));
|
||||
$user4 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser4'));
|
||||
$user5 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser5'));
|
||||
$user6 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser6'));
|
||||
$user7 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser6'));
|
||||
$user8 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser6'));
|
||||
|
||||
$course1 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse1'));
|
||||
$course2 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse2'));
|
||||
$course3 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse3'));
|
||||
$course4 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse4'));
|
||||
|
||||
$this->assertEquals(4, $DB->count_records('enrol', array('enrol'=>'manual')));
|
||||
$this->assertEquals(4, $DB->count_records('enrol', array('enrol'=>'self')));
|
||||
|
||||
$maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
|
||||
$instance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'self'), '*', MUST_EXIST);
|
||||
$instance1->expirythreshold = 60*60*24*4;
|
||||
$instance1->expirynotify = 1;
|
||||
$instance1->notifyall = 1;
|
||||
$instance1->status = ENROL_INSTANCE_ENABLED;
|
||||
$DB->update_record('enrol', $instance1);
|
||||
|
||||
$maninstance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
|
||||
$instance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'self'), '*', MUST_EXIST);
|
||||
$instance2->expirythreshold = 60*60*24*1;
|
||||
$instance2->expirynotify = 1;
|
||||
$instance2->notifyall = 1;
|
||||
$instance2->status = ENROL_INSTANCE_ENABLED;
|
||||
$DB->update_record('enrol', $instance2);
|
||||
|
||||
$maninstance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
|
||||
$instance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'self'), '*', MUST_EXIST);
|
||||
$instance3->expirythreshold = 60*60*24*1;
|
||||
$instance3->expirynotify = 1;
|
||||
$instance3->notifyall = 0;
|
||||
$instance3->status = ENROL_INSTANCE_ENABLED;
|
||||
$DB->update_record('enrol', $instance3);
|
||||
|
||||
$maninstance4 = $DB->get_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'manual'), '*', MUST_EXIST);
|
||||
$instance4 = $DB->get_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'self'), '*', MUST_EXIST);
|
||||
$instance4->expirythreshold = 60*60*24*1;
|
||||
$instance4->expirynotify = 0;
|
||||
$instance4->notifyall = 0;
|
||||
$instance4->status = ENROL_INSTANCE_ENABLED;
|
||||
$DB->update_record('enrol', $instance4);
|
||||
|
||||
$selfplugin->enrol_user($instance1, $user1->id, $studentrole->id, 0, $now + 60*60*24*1, ENROL_USER_SUSPENDED); // Suspended users are not notified.
|
||||
$selfplugin->enrol_user($instance1, $user2->id, $studentrole->id, 0, $now + 60*60*24*5); // Above threshold are not notified.
|
||||
$selfplugin->enrol_user($instance1, $user3->id, $studentrole->id, 0, $now + 60*60*24*3 + 60*60); // Less than one day after threshold - should be notified.
|
||||
$selfplugin->enrol_user($instance1, $user4->id, $studentrole->id, 0, $now + 60*60*24*4 - 60*3); // Less than one day after threshold - should be notified.
|
||||
$selfplugin->enrol_user($instance1, $user5->id, $studentrole->id, 0, $now + 60*60); // Should have been already notified.
|
||||
$selfplugin->enrol_user($instance1, $user6->id, $studentrole->id, 0, $now - 60); // Already expired.
|
||||
$manualplugin->enrol_user($maninstance1, $user7->id, $editingteacherrole->id);
|
||||
$manualplugin->enrol_user($maninstance1, $user8->id, $managerrole->id); // Highest role --> enroller.
|
||||
|
||||
$selfplugin->enrol_user($instance2, $user1->id, $studentrole->id);
|
||||
$selfplugin->enrol_user($instance2, $user2->id, $studentrole->id, 0, $now + 60*60*24*1 + 60*3); // Above threshold are not notified.
|
||||
$selfplugin->enrol_user($instance2, $user3->id, $studentrole->id, 0, $now + 60*60*24*1 - 60*60); // Less than one day after threshold - should be notified.
|
||||
|
||||
$manualplugin->enrol_user($maninstance3, $user1->id, $editingteacherrole->id);
|
||||
$selfplugin->enrol_user($instance3, $user2->id, $studentrole->id, 0, $now + 60*60*24*1 + 60); // Above threshold are not notified.
|
||||
$selfplugin->enrol_user($instance3, $user3->id, $studentrole->id, 0, $now + 60*60*24*1 - 60*60); // Less than one day after threshold - should be notified.
|
||||
|
||||
$manualplugin->enrol_user($maninstance4, $user4->id, $editingteacherrole->id);
|
||||
$selfplugin->enrol_user($instance4, $user5->id, $studentrole->id, 0, $now + 60*60*24*1 + 60);
|
||||
$selfplugin->enrol_user($instance4, $user6->id, $studentrole->id, 0, $now + 60*60*24*1 - 60*60);
|
||||
|
||||
// The notification is sent out in fixed order first individual users,
|
||||
// then summary per course by enrolid, user lastname, etc.
|
||||
$this->assertGreaterThan($instance1->id, $instance2->id);
|
||||
$this->assertGreaterThan($instance2->id, $instance3->id);
|
||||
|
||||
$sink = $this->redirectMessages();
|
||||
|
||||
$selfplugin->send_expiry_notifications(false);
|
||||
|
||||
$messages = $sink->get_messages();
|
||||
|
||||
$this->assertEquals(2+1 + 1+1 + 1 + 0, count($messages));
|
||||
|
||||
// First individual notifications from course1.
|
||||
$this->assertEquals($user3->id, $messages[0]->useridto);
|
||||
$this->assertEquals($user8->id, $messages[0]->useridfrom);
|
||||
$this->assertContains('xcourse1', $messages[0]->fullmessagehtml);
|
||||
|
||||
$this->assertEquals($user4->id, $messages[1]->useridto);
|
||||
$this->assertEquals($user8->id, $messages[1]->useridfrom);
|
||||
$this->assertContains('xcourse1', $messages[1]->fullmessagehtml);
|
||||
|
||||
// Then summary for course1.
|
||||
$this->assertEquals($user8->id, $messages[2]->useridto);
|
||||
$this->assertEquals($admin->id, $messages[2]->useridfrom);
|
||||
$this->assertContains('xcourse1', $messages[2]->fullmessagehtml);
|
||||
$this->assertNotContains('xuser1', $messages[2]->fullmessagehtml);
|
||||
$this->assertNotContains('xuser2', $messages[2]->fullmessagehtml);
|
||||
$this->assertContains('xuser3', $messages[2]->fullmessagehtml);
|
||||
$this->assertContains('xuser4', $messages[2]->fullmessagehtml);
|
||||
$this->assertContains('xuser5', $messages[2]->fullmessagehtml);
|
||||
$this->assertNotContains('xuser6', $messages[2]->fullmessagehtml);
|
||||
|
||||
// First individual notifications from course2.
|
||||
$this->assertEquals($user3->id, $messages[3]->useridto);
|
||||
$this->assertEquals($admin->id, $messages[3]->useridfrom);
|
||||
$this->assertContains('xcourse2', $messages[3]->fullmessagehtml);
|
||||
|
||||
// Then summary for course2.
|
||||
$this->assertEquals($admin->id, $messages[4]->useridto);
|
||||
$this->assertEquals($admin->id, $messages[4]->useridfrom);
|
||||
$this->assertContains('xcourse2', $messages[4]->fullmessagehtml);
|
||||
$this->assertNotContains('xuser1', $messages[4]->fullmessagehtml);
|
||||
$this->assertNotContains('xuser2', $messages[4]->fullmessagehtml);
|
||||
$this->assertContains('xuser3', $messages[4]->fullmessagehtml);
|
||||
$this->assertNotContains('xuser4', $messages[4]->fullmessagehtml);
|
||||
$this->assertNotContains('xuser5', $messages[4]->fullmessagehtml);
|
||||
$this->assertNotContains('xuser6', $messages[4]->fullmessagehtml);
|
||||
|
||||
// Only summary in course3.
|
||||
$this->assertEquals($user1->id, $messages[5]->useridto);
|
||||
$this->assertEquals($admin->id, $messages[5]->useridfrom);
|
||||
$this->assertContains('xcourse3', $messages[5]->fullmessagehtml);
|
||||
$this->assertNotContains('xuser1', $messages[5]->fullmessagehtml);
|
||||
$this->assertNotContains('xuser2', $messages[5]->fullmessagehtml);
|
||||
$this->assertContains('xuser3', $messages[5]->fullmessagehtml);
|
||||
$this->assertNotContains('xuser4', $messages[5]->fullmessagehtml);
|
||||
$this->assertNotContains('xuser5', $messages[5]->fullmessagehtml);
|
||||
$this->assertNotContains('xuser6', $messages[5]->fullmessagehtml);
|
||||
|
||||
|
||||
// Make sure that notifications are not repeated.
|
||||
$sink->clear();
|
||||
|
||||
$selfplugin->send_expiry_notifications(false);
|
||||
$this->assertEquals(0, $sink->count());
|
||||
|
||||
// use invalid notification hour to verify that before the hour the notifications are not sent.
|
||||
$selfplugin->set_config('expirynotifylast', time() - 60*60*24);
|
||||
$selfplugin->set_config('expirynotifyhour', '24');
|
||||
|
||||
$selfplugin->send_expiry_notifications(false);
|
||||
$this->assertEquals(0, $sink->count());
|
||||
|
||||
$selfplugin->set_config('expirynotifyhour', '0');
|
||||
$selfplugin->send_expiry_notifications(false);
|
||||
$this->assertEquals(6, $sink->count());
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2012091500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2012091400; // Requires this Moodle version
|
||||
$plugin->version = 2012101400; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2012100500; // Requires this Moodle version
|
||||
$plugin->component = 'enrol_self'; // Full name of the plugin (used for diagnostics)
|
||||
$plugin->cron = 600;
|
||||
|
@ -9,10 +9,11 @@ required changes in code:
|
||||
directly from database is not correct any more
|
||||
* new restore support: ENROL_RESTORE_EXACT, ENROL_RESTORE_NOUSERS
|
||||
and ENROL_RESTORE_CLASS were removed, implement new restore_* plugin methods instead
|
||||
* new support for protected group membership linked to enrol instance
|
||||
|
||||
other changes:
|
||||
other changes and new features:
|
||||
* course enrolment manager now works with disabled plugins too
|
||||
* new support for protected group membership linked to enrol instance
|
||||
* new support for expiry notifications - see enrol_plugin::send_expiry_notifications() method
|
||||
|
||||
|
||||
=== 2.2 ===
|
||||
|
@ -66,7 +66,15 @@ $string['errajaxsearch'] = 'Error when searching users';
|
||||
$string['erroreditenrolment'] = 'An error occurred while trying to edit a users enrolment';
|
||||
$string['errorenrolcohort'] = 'Error creating cohort sync enrolment instance in this course.';
|
||||
$string['errorenrolcohortusers'] = 'Error enrolling cohort members in this course.';
|
||||
$string['errorthresholdlow'] = 'Notification threshold must be at least 1 day.';
|
||||
$string['errorwithbulkoperation'] = 'There was an error while processing your bulk enrolment change.';
|
||||
$string['expirynotify'] = 'Notify before enrolment expires';
|
||||
$string['expirynotify_help'] = 'This setting determines whether enrolment expiry notification messages are sent.';
|
||||
$string['expirynotifyall'] = 'Enroller and enrolled user';
|
||||
$string['expirynotifyenroller'] = 'Enroller only';
|
||||
$string['expirynotifyhour'] = 'Hour to send enrolment expiry notifications';
|
||||
$string['expirythreshold'] = 'Notification threshold';
|
||||
$string['expirythreshold_help'] = 'How long before expiration should be users notified?';
|
||||
$string['finishenrollingusers'] = 'Finish enrolling users';
|
||||
$string['invalidenrolinstance'] = 'Invalid enrolment instance';
|
||||
$string['invalidrole'] = 'Invalid role';
|
||||
|
@ -659,26 +659,6 @@ $string['existingcreators'] = 'Existing course creators';
|
||||
$string['existingstudents'] = 'Enrolled students';
|
||||
$string['existingteachers'] = 'Existing teachers';
|
||||
$string['expandall'] = 'Expand all';
|
||||
$string['expirynotify'] = 'Enrolment expiry notification';
|
||||
$string['expirynotifyemail'] = 'The following students in this course are expiring after exactly {$a->threshold} days:
|
||||
|
||||
{$a->current}
|
||||
|
||||
The following students in this course are expiring in less than {$a->threshold} days:
|
||||
|
||||
{$a->past}
|
||||
|
||||
You may go to the following page to extend their enrolment period:
|
||||
{$a->extendurl}';
|
||||
$string['expirynotifystudents'] = 'Notify students';
|
||||
$string['expirynotifystudents_help'] = 'If an enrolment duration has been specified, then this setting determines whether students receive email notification when they are about to be unenrolled from the course.';
|
||||
$string['expirynotifystudentsemail'] = 'Dear {$a->studentstr}:
|
||||
|
||||
This is a notification that your enrolment in the course {$a->course} will expire in {$a->threshold} days.
|
||||
|
||||
Please contact {$a->teacherstr} for any further enquiries.';
|
||||
$string['expirythreshold'] = 'Threshold';
|
||||
$string['expirythreshold_help'] = 'If an enrolment duration has been specified, then this setting determines the number of days notice given before students are unenrolled from the course.';
|
||||
$string['explanation'] = 'Explanation';
|
||||
$string['extendenrol'] = 'Extend enrolment (individual)';
|
||||
$string['extendperiod'] = 'Extended period';
|
||||
|
256
lib/enrollib.php
256
lib/enrollib.php
@ -1770,6 +1770,262 @@ abstract class enrol_plugin {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send expiry notifications.
|
||||
*
|
||||
* Plugin that wants to have expiry notification MUST implement following:
|
||||
* - expirynotifyhour plugin setting,
|
||||
* - configuration options in instance edit form (expirynotify, notifyall and expirythreshold),
|
||||
* - notification strings (expirymessageenrollersubject, expirymessageenrollerbody,
|
||||
* expirymessageenrolledsubject and expirymessageenrolledbody),
|
||||
* - expiry_notification provider in db/messages.php,
|
||||
* - upgrade code that sets default thresholds for existing courses (should be 1 day),
|
||||
* - something that calls this method, such as cron.
|
||||
*
|
||||
* @param bool $verbose verbose CLI output
|
||||
*/
|
||||
public function send_expiry_notifications($verbose = false) {
|
||||
global $DB, $CFG;
|
||||
|
||||
// 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');
|
||||
if (is_null($expirynotifyhour)) {
|
||||
debugging("send_expiry_notifications() in $name enrolment plugin needs expirynotifyhour setting");
|
||||
return;
|
||||
}
|
||||
|
||||
$timenow = time();
|
||||
$notifytime = usergetmidnight($timenow, $CFG->timezone) + ($expirynotifyhour * 3600);
|
||||
|
||||
if ($expirynotifylast > $notifytime) {
|
||||
if ($verbose) {
|
||||
mtrace($name.' enrolment expiry notifications were already sent today at '.userdate($expirynotifylast, '', $CFG->timezone).'.');
|
||||
}
|
||||
return;
|
||||
} else if ($timenow < $notifytime) {
|
||||
if ($verbose) {
|
||||
mtrace($name.' enrolment expiry notifications will be sent at '.userdate($notifytime, '', $CFG->timezone).'.');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ($verbose) {
|
||||
mtrace('Processing '.$name.' enrolment expiration notifications...');
|
||||
}
|
||||
|
||||
// Notify users responsible for enrolment once every day.
|
||||
$sql = "SELECT ue.*, e.expirynotify, e.notifyall, e.expirythreshold, e.courseid, c.fullname
|
||||
FROM {user_enrolments} ue
|
||||
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = :name AND e.expirynotify > 0 AND e.status = :enabled)
|
||||
JOIN {course} c ON (c.id = e.courseid)
|
||||
JOIN {user} u ON (u.id = ue.userid AND u.deleted = 0 AND u.suspended = 0)
|
||||
WHERE ue.status = :active AND ue.timeend > 0 AND ue.timeend > :now1 AND ue.timeend < (e.expirythreshold + :now2)
|
||||
ORDER BY ue.enrolid ASC, u.lastname ASC, u.firstname ASC, u.id ASC";
|
||||
$params = array('enabled'=>ENROL_INSTANCE_ENABLED, 'active'=>ENROL_USER_ACTIVE, 'now1'=>$timenow, 'now2'=>$timenow, 'name'=>$name);
|
||||
|
||||
$rs = $DB->get_recordset_sql($sql, $params);
|
||||
|
||||
$lastenrollid = 0;
|
||||
$users = array();
|
||||
|
||||
foreach($rs as $ue) {
|
||||
if ($lastenrollid and $lastenrollid != $ue->enrolid) {
|
||||
$this->notify_expiry_enroller($lastenrollid, $users, $verbose);
|
||||
$users = array();
|
||||
}
|
||||
$lastenrollid = $ue->enrolid;
|
||||
|
||||
$enroller = $this->get_enroller($ue->enrolid);
|
||||
$context = context_course::instance($ue->courseid);
|
||||
|
||||
$user = $DB->get_record('user', array('id'=>$ue->userid));
|
||||
|
||||
$users[] = array('fullname'=>fullname($user, has_capability('moodle/site:viewfullnames', $context, $enroller)), 'timeend'=>$ue->timeend);
|
||||
|
||||
if (!$ue->notifyall) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($ue->timeend - $ue->expirythreshold + 86400 < $timenow) {
|
||||
// Notify enrolled users only once at the start of the threshold.
|
||||
if ($verbose) {
|
||||
mtrace(" user $ue->userid was already notified that enrolment in course $ue->courseid expires on ".userdate($ue->timeend, '', $CFG->timezone));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->notify_expiry_enrolled($user, $ue, $verbose);
|
||||
}
|
||||
$rs->close();
|
||||
|
||||
if ($lastenrollid and $users) {
|
||||
$this->notify_expiry_enroller($lastenrollid, $users, $verbose);
|
||||
}
|
||||
|
||||
if ($verbose) {
|
||||
mtrace('...notification processing finished.');
|
||||
}
|
||||
$this->set_config('expirynotifylast', $timenow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user who is responsible for enrolments for given instance.
|
||||
*
|
||||
* Override if plugin knows anybody better than admin.
|
||||
*
|
||||
* @param int $instanceid enrolment instance id
|
||||
* @return stdClass user record
|
||||
*/
|
||||
protected function get_enroller($instanceid) {
|
||||
return get_admin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify user about incoming expiration of their enrolment,
|
||||
* it is called only if notification of enrolled users (aka students) is enabled in course.
|
||||
*
|
||||
* This is executed only once for each expiring enrolment right
|
||||
* at the start of the expiration threshold.
|
||||
*
|
||||
* @param stdClass $user
|
||||
* @param stdClass $ue
|
||||
* @param bool $verbose
|
||||
*/
|
||||
protected function notify_expiry_enrolled($user, $ue, $verbose) {
|
||||
global $CFG, $SESSION;
|
||||
|
||||
$name = $this->get_name();
|
||||
|
||||
// Some nasty hackery to get strings and dates localised for target user.
|
||||
$sessionlang = isset($SESSION->lang) ? $SESSION->lang : null;
|
||||
if (get_string_manager()->translation_exists($user->lang, false)) {
|
||||
$SESSION->lang = $user->lang;
|
||||
moodle_setlocale();
|
||||
}
|
||||
|
||||
$enroller = $this->get_enroller($ue->enrolid);
|
||||
$context = context_course::instance($ue->courseid);
|
||||
|
||||
$a = new stdClass();
|
||||
$a->course = format_string($ue->fullname, true, array('context'=>$context));
|
||||
$a->user = fullname($user, true);
|
||||
$a->timeend = userdate($ue->timeend, '', $user->timezone);
|
||||
$a->enroller = fullname($enroller, has_capability('moodle/site:viewfullnames', $context, $user));
|
||||
|
||||
$subject = get_string('expirymessageenrolledsubject', 'enrol_'.$name, $a);
|
||||
$body = get_string('expirymessageenrolledbody', 'enrol_'.$name, $a);
|
||||
|
||||
$message = new stdClass();
|
||||
$message->notification = 1;
|
||||
$message->component = 'enrol_'.$name;
|
||||
$message->name = 'expiry_notification';
|
||||
$message->userfrom = $enroller;
|
||||
$message->userto = $user;
|
||||
$message->subject = $subject;
|
||||
$message->fullmessage = $body;
|
||||
$message->fullmessageformat = FORMAT_MARKDOWN;
|
||||
$message->fullmessagehtml = markdown_to_html($body);
|
||||
$message->smallmessage = $subject;
|
||||
$message->contexturlname = $a->course;
|
||||
$message->contexturl = (string)new moodle_url('/course/view.php', array('id'=>$ue->courseid));
|
||||
|
||||
if (message_send($message)) {
|
||||
if ($verbose) {
|
||||
mtrace(" notifying user $ue->userid that enrolment in course $ue->courseid expires on ".userdate($ue->timeend, '', $CFG->timezone));
|
||||
}
|
||||
} else {
|
||||
if ($verbose) {
|
||||
mtrace(" error notifying user $ue->userid that enrolment in course $ue->courseid expires on ".userdate($ue->timeend, '', $CFG->timezone));
|
||||
}
|
||||
}
|
||||
|
||||
if ($SESSION->lang !== $sessionlang) {
|
||||
$SESSION->lang = $sessionlang;
|
||||
moodle_setlocale();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify person responsible for enrolments that some user enrolments will be expired soon,
|
||||
* it is called only if notification of enrollers (aka teachers) is enabled in course.
|
||||
*
|
||||
* This is called repeatedly every day for each course if there are any pending expiration
|
||||
* in the expiration threshold.
|
||||
*
|
||||
* @param int $eid
|
||||
* @param array $users
|
||||
* @param bool $verbose
|
||||
*/
|
||||
protected function notify_expiry_enroller($eid, $users, $verbose) {
|
||||
global $DB, $SESSION;
|
||||
|
||||
$name = $this->get_name();
|
||||
|
||||
$instance = $DB->get_record('enrol', array('id'=>$eid, 'enrol'=>$name));
|
||||
$context = context_course::instance($instance->courseid);
|
||||
$course = $DB->get_record('course', array('id'=>$instance->courseid));
|
||||
|
||||
$enroller = $this->get_enroller($instance->id);
|
||||
$admin = get_admin();
|
||||
|
||||
// Some nasty hackery to get strings and dates localised for target user.
|
||||
$sessionlang = isset($SESSION->lang) ? $SESSION->lang : null;
|
||||
if (get_string_manager()->translation_exists($enroller->lang, false)) {
|
||||
$SESSION->lang = $enroller->lang;
|
||||
moodle_setlocale();
|
||||
}
|
||||
|
||||
foreach($users as $key=>$info) {
|
||||
$users[$key] = '* '.$info['fullname'].' - '.userdate($info['timeend'], '', $enroller->timezone);
|
||||
}
|
||||
|
||||
$a = new stdClass();
|
||||
$a->course = format_string($course->fullname, true, array('context'=>$context));
|
||||
$a->threshold = get_string('numdays', '', $instance->expirythreshold / (60*60*24));
|
||||
$a->users = implode("\n", $users);
|
||||
$a->extendurl = (string)new moodle_url('/enrol/users.php', array('id'=>$instance->courseid));
|
||||
|
||||
$subject = get_string('expirymessageenrollersubject', 'enrol_'.$name, $a);
|
||||
$body = get_string('expirymessageenrollerbody', 'enrol_'.$name, $a);
|
||||
|
||||
$message = new stdClass();
|
||||
$message->notification = 1;
|
||||
$message->component = 'enrol_'.$name;
|
||||
$message->name = 'expiry_notification';
|
||||
$message->userfrom = $admin;
|
||||
$message->userto = $enroller;
|
||||
$message->subject = $subject;
|
||||
$message->fullmessage = $body;
|
||||
$message->fullmessageformat = FORMAT_MARKDOWN;
|
||||
$message->fullmessagehtml = markdown_to_html($body);
|
||||
$message->smallmessage = $subject;
|
||||
$message->contexturlname = $a->course;
|
||||
$message->contexturl = $a->extendurl;
|
||||
|
||||
if (message_send($message)) {
|
||||
if ($verbose) {
|
||||
mtrace(" notifying user $enroller->id about all expiring $name enrolments in course $instance->courseid");
|
||||
}
|
||||
} else {
|
||||
if ($verbose) {
|
||||
mtrace(" error notifying user $enroller->id about all expiring $name enrolments in course $instance->courseid");
|
||||
}
|
||||
}
|
||||
|
||||
if ($SESSION->lang !== $sessionlang) {
|
||||
$SESSION->lang = $sessionlang;
|
||||
moodle_setlocale();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatic enrol sync executed during restore.
|
||||
* Useful for automatic sync by course->idnumber or course category.
|
||||
|
Loading…
x
Reference in New Issue
Block a user