Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

MDL-29684 improve enrol_meta plugin

List of changes:
* configurable unenrol action
* new setting for synchronisation of all enrolled users or users with at least one role
* cron period increased to 1 hour in order to lower server load, courses should not get out of sync often
* CLI sync script for debugging or manual sync
* phpdocs fixes
* when plugin is disabled all roles are removed, enrollments are kept
* uninstall script
* other bugfixing
  • Loading branch information...
commit 0007843de047eb0533220d5d5732f6c62bc0c8cc 1 parent 4d2f89f
@skodak skodak authored danmarsden committed
View
3  enrol/meta/addinstance_form.php
@@ -1,5 +1,4 @@
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
@@ -74,7 +73,7 @@ function definition() {
function validation($data, $files) {
global $DB, $CFG;
- // TODO: this is duplicated here because it may be necessary one we implement ajax course selection element
+ // TODO: this is duplicated here because it may be necessary once we implement ajax course selection element
$errors = parent::validation($data, $files);
if (!$c = $DB->get_record('course', array('id'=>$data['link']))) {
View
66 enrol/meta/cli/sync.php
@@ -0,0 +1,66 @@
+<?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/>.
+
+/**
+ * CLI sync for meta course enrolments, use for debugging or immediate sync
+ * of all courses.
+ *
+ * Notes:
+ * - it is required to use the web server account when executing PHP CLI scripts
+ * - you need to change the "www-data" to match the apache user account
+ * - use "su" if "sudo" not available
+ *
+ * @package enrol
+ * @subpackage meta
+ * @copyright 2011 Petr Skoda {@link http://skodak.org}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+define('CLI_SCRIPT', true);
+
+require(dirname(dirname(dirname(dirname(__FILE__)))).'/config.php');
+require_once($CFG->libdir.'/clilib.php');
+require_once("$CFG->dirroot/enrol/meta/locallib.php");
+
+// now get cli options
+list($options, $unrecognized) = cli_get_params(array('verbose'=>false, 'help'=>false), array('v'=>'verbose', 'h'=>'help'));
+
+if ($unrecognized) {
+ $unrecognized = implode("\n ", $unrecognized);
+ cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
+}
+
+if ($options['help']) {
+ $help =
+ "Execute meta course enrol sync.
+
+Options:
+-v, --verbose Print verbose progess information
+-h, --help Print out this help
+
+Example:
+\$sudo -u www-data /usr/bin/php enrol/meta/cli/sync.php
+";
+
+ echo $help;
+ die;
+}
+
+$verbose = !empty($options['verbose']);
+
+$result = enrol_meta_sync(null, $verbose);
+
+exit($result);
View
10 enrol/meta/db/access.php
@@ -44,6 +44,16 @@
'manager' => CAP_ALLOW,
)
),
+
+ /* This is used only when sync suspends users instead of full unenrolment */
+ 'enrol/meta:unenrol' => array(
+
+ 'captype' => 'write',
+ 'contextlevel' => CONTEXT_COURSE,
+ 'archetypes' => array(
+ 'manager' => CAP_ALLOW,
+ )
+ ),
);
View
41 enrol/meta/db/uninstall.php
@@ -0,0 +1,41 @@
+<?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/>.
+
+/**
+ * Meta link enrolment plugin uninstallation.
+ *
+ * @package enrol
+ * @subpackage meta
+ * @copyright 2011 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_meta_uninstall() {
+ global $CFG, $DB;
+
+ $meta = enrol_get_plugin('meta');
+ $rs = $DB->get_recordset('enrol', array('enrol'=>'meta'));
+ foreach ($rs as $instance) {
+ $meta->delete_instance($instance);
+ }
+ $rs->close();
+
+ role_unassign_all(array('component'=>'enrol_meta'));
+
+ return true;
+}
View
3  enrol/meta/lang/en/enrol_meta.php
@@ -27,7 +27,10 @@
$string['linkedcourse'] = 'Link course';
$string['meta:config'] = 'Configure meta enrol instances';
$string['meta:selectaslinked'] = 'Select course as meta linked';
+$string['meta:unenrol'] = 'Unenrol suspended users';
$string['nosyncroleids'] = 'Roles that are not synchronised';
$string['nosyncroleids_desc'] = 'By default all course level role assignments are synchronised from parent to child courses. Roles that are selected here will not be included in the synchronisation process. The roles available for synchronisation will be updated in the next cron execution.';
$string['pluginname'] = 'Course meta link';
$string['pluginname_desc'] = 'Course meta link enrolment plugin synchronises enrolments and roles in two different courses.';
+$string['syncall'] = 'Synchronise all enrolled users';
+$string['syncall_desc'] = 'If enabled all enrolled users are synchronised even if they have no role in parent course, if disabled only users that have at least one synchronised role are enrolled in child course.';
View
64 enrol/meta/lib.php
@@ -1,5 +1,4 @@
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
@@ -36,7 +35,7 @@ class enrol_meta_plugin extends enrol_plugin {
/**
* Returns localised name of enrol instance
*
- * @param object $instance (null is accepted too)
+ * @param stdClass $instance (null is accepted too)
* @return string
*/
public function get_instance_name($instance) {
@@ -67,13 +66,49 @@ public function get_newinstance_link($courseid) {
return new moodle_url('/enrol/meta/addinstance.php', array('id'=>$courseid));
}
+ /**
+ * Does this plugin allow manual unenrolment of a specific user?
+ * Yes, but only if user suspended...
+ *
+ * @param stdClass $instance course enrol instance
+ * @param stdClass $ue record from user_enrolments table
+ *
+ * @return bool - true means user with 'enrol/xxx:unenrol' may unenrol this user, false means nobody may touch this user enrolment
+ */
+ public function allow_unenrol_user(stdClass $instance, stdClass $ue) {
+ if ($ue->status == ENROL_USER_SUSPENDED) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Gets an array of the user enrolment actions
+ *
+ * @param course_enrolment_manager $manager
+ * @param stdClass $ue A user enrolment object
+ * @return array An array of user_enrolment_actions
+ */
+ public function get_user_enrolment_actions(course_enrolment_manager $manager, $ue) {
+ $actions = array();
+ $context = $manager->get_context();
+ $instance = $ue->enrolmentinstance;
+ $params = $manager->get_moodlepage()->url->params();
+ $params['ue'] = $ue->id;
+ if ($this->allow_unenrol_user($instance, $ue) && has_capability('enrol/meta:unenrol', $context)) {
+ $url = new moodle_url('/enrol/unenroluser.php', $params);
+ $actions[] = new user_enrolment_action(new pix_icon('t/delete', ''), get_string('unenrol', 'enrol'), $url, array('class'=>'unenrollink', 'rel'=>$ue->id));
+ }
+ return $actions;
+ }
/**
* Called after updating/inserting course.
*
* @param bool $inserted true if course just inserted
- * @param object $course
- * @param object $data form data
+ * @param stdClass $course
+ * @param stdClass $data form data
* @return void
*/
public function course_updated($inserted, $course, $data) {
@@ -86,7 +121,22 @@ public function course_updated($inserted, $course, $data) {
} else {
// cohorts are never inserted automatically
}
+ }
+
+ /**
+ * Update instance status
+ *
+ * @param stdClass $instance
+ * @param int $newstatus ENROL_INSTANCE_ENABLED, ENROL_INSTANCE_DISABLED
+ * @return void
+ */
+ public function update_status($instance, $newstatus) {
+ global $CFG;
+
+ parent::update_status($instance, $newstatus);
+ require_once("$CFG->dirroot/enrol/meta/locallib.php");
+ enrol_meta_sync($instance->courseid);
}
/**
@@ -96,12 +146,6 @@ public function course_updated($inserted, $course, $data) {
public function cron() {
global $CFG;
- // purge all roles if meta sync disabled, those can be recreated later here in cron
- if (!enrol_is_enabled('meta')) {
- role_unassign_all(array('component'=>'meta_enrol'));
- return;
- }
-
require_once("$CFG->dirroot/enrol/meta/locallib.php");
enrol_meta_sync();
}
View
751 enrol/meta/locallib.php
@@ -25,6 +25,7 @@
defined('MOODLE_INTERNAL') || die();
+
/**
* Event handler for meta enrolment plugin.
*
@@ -32,55 +33,212 @@
* it may fail sometimes, so we always do a full sync in cron too.
*/
class enrol_meta_handler {
- public function role_assigned($ra) {
+
+ /**
+ * Synchronise meta enrolments of this user in this course
+ * @static
+ * @param int $courseid
+ * @param int $userid
+ * @return void
+ */
+ protected static function sync_course_instances($courseid, $userid) {
global $DB;
+ static $preventrecursion = false;
+
+ // does anything want to sync with this parent?
+ if (!$enrols = $DB->get_records('enrol', array('customint1'=>$courseid, 'enrol'=>'meta'), 'id ASC')) {
+ return;
+ }
+
+ if ($preventrecursion) {
+ return;
+ }
+
+ $preventrecursion = true;
+
+ try {
+ foreach ($enrols as $enrol) {
+ self::sync_with_parent_course($enrol, $userid);
+ }
+ } catch (Exception $e) {
+ $preventrecursion = false;
+ throw $e;
+ }
+
+ $preventrecursion = false;
+ }
+
+ /**
+ * Synchronise user enrolments in given instance as fast as possible.
+ *
+ * All roles are removed if the meta plugin disabled.
+ *
+ * @static
+ * @param stdClass $instance
+ * @param int $userid
+ * @return void
+ */
+ protected static function sync_with_parent_course(stdClass $instance, $userid) {
+ global $DB, $CFG;
+
+ $plugin = enrol_get_plugin('meta');
+
+ if ($instance->customint1 == $instance->courseid) {
+ // can not sync with self!!!
+ return;
+ }
+
+ $context = context_course::instance($instance->courseid);
+
+ if (!$parentcontext = context_course::instance($instance->customint1, IGNORE_MISSING)) {
+ // linking to missing course is not possible
+ role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id, 'component'=>'enrol_meta'));
+ return;
+ }
+
+ // list of enrolments in parent course (we ignore meta enrols in parents completely)
+ list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e');
+ $params['userid'] = $userid;
+ $params['parentcourse'] = $instance->customint1;
+ $sql = "SELECT ue.*
+ FROM {user_enrolments} ue
+ JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol <> 'meta' AND e.courseid = :parentcourse AND e.enrol $enabled)
+ WHERE ue.userid = :userid";
+ $parentues = $DB->get_records_sql($sql, $params);
+ // current enrolments for this instance
+ $ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid));
+
+ // first deal with users that are not enrolled in parent
+ if (empty($parentues)) {
+ self::user_not_supposed_to_be_here($instance, $ue, $context, $plugin);
+ return;
+ }
+
if (!enrol_is_enabled('meta')) {
- return true;
+ if ($ue) {
+ role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id, 'component'=>'enrol_meta'));
+ }
+ return;
}
- // prevent circular dependencies - we can not sync meta roles recursively
- if ($ra->component === 'enrol_meta') {
- return true;
+ $skiproles = $plugin->get_config('nosyncroleids', '');
+ $skiproles = empty($skiproles) ? array() : explode(',', $skiproles);
+ $syncall = $plugin->get_config('syncall', 1);
+
+ // roles in parent course (meta enrols must be ignored!)
+ $parentroles = array();
+ list($ignoreroles, $params) = $DB->get_in_or_equal($skiproles, SQL_PARAMS_NAMED, 'ri', false, -1);
+ $params['contextid'] = $parentcontext->id;
+ $params['userid'] = $userid;
+ $select = "contextid = :contextid AND userid = :userid AND component <> 'enrol_meta' AND roleid $ignoreroles";
+ foreach($DB->get_records_select('role_assignments', $select, $params) as $ra) {
+ $parentroles[$ra->roleid] = $ra->roleid;
}
- // only course level roles are interesting
- $parentcontext = get_context_instance_by_id($ra->contextid);
- if ($parentcontext->contextlevel != CONTEXT_COURSE) {
- return true;
+ // roles from this instance
+ $roles = array();
+ $ras = $DB->get_records('role_assignments', array('contextid'=>$context->id, 'userid'=>$userid, 'component'=>'enrol_meta', 'itemid'=>$instance->id));
+ foreach($ras as $ra) {
+ $roles[$ra->roleid] = $ra->roleid;
}
+ unset($ras);
- // does anything want to sync with this parent?
- if (!$enrols = $DB->get_records('enrol', array('customint1'=>$parentcontext->instanceid, 'enrol'=>'meta'), 'id ASC')) {
- return true;
+ // do we want users without roles?
+ if (!$syncall and empty($parentroles)) {
+ self::user_not_supposed_to_be_here($instance, $ue, $context, $plugin);
+ return;
}
- // make sure the role sync is not prevented
- $plugin = enrol_get_plugin('meta');
- if ($disabled = $plugin->get_config('nosyncroleids')) {
- if (in_array($ra->roleid, explode(',', $disabled))) {
- return true;
+ // is parent enrol active? (we ignore enrol starts and ends, sorry it would be too complex)
+ $parentstatus = ENROL_USER_SUSPENDED;
+ foreach ($parentues as $pue) {
+ if ($pue->status == ENROL_USER_ACTIVE) {
+ $parentstatus = ENROL_USER_ACTIVE;
+ break;
}
}
- foreach ($enrols as $enrol) {
- // Is the user enrolled? We want to sync only really enrolled users
- if (!$DB->record_exists('user_enrolments', array('userid'=>$ra->userid, 'enrolid'=>$enrol->id))) {
- continue;
+ // enrol user if not enrolled yet or fix status
+ if ($ue) {
+ if ($parentstatus != $ue->status) {
+ $plugin->update_user_enrol($instance, $userid, $parentstatus);
+ $ue->status = $parentstatus;
+ }
+ } else {
+ $plugin->enrol_user($instance, $userid, NULL, 0, 0, $parentstatus);
+ $ue = new stdClass();
+ $ue->userid = $userid;
+ $ue->enrolid = $instance->id;
+ $ue->status = $parentstatus;
+ }
+
+ // only active users in enabled instances are supposed to have roles (we can reassign the roles any time later)
+ if ($ue->status != ENROL_USER_ACTIVE or $instance->status != ENROL_INSTANCE_ENABLED) {
+ if ($roles) {
+ role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id, 'component'=>'enrol_meta', 'itemid'=>$instance->id));
}
- $context = get_context_instance(CONTEXT_COURSE, $enrol->courseid);
+ return;
+ }
- // just try to assign role, no problem if role assignment already exists
- role_assign($ra->roleid, $ra->userid, $context->id, 'enrol_meta', $enrol->id);
+ // add new roles
+ foreach ($parentroles as $rid) {
+ if (!isset($roles[$rid])) {
+ role_assign($rid, $userid, $context->id, 'enrol_meta', $instance->id);
+ }
}
- return true;
+ // remove roles
+ foreach ($roles as $rid) {
+ if (!isset($parentroles[$rid])) {
+ role_unassign($rid, $userid, $context->id, 'enrol_meta', $instance->id);
+ }
+ }
}
- public function role_unassigned($ra) {
- global $DB;
+ /**
+ * 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_UNENROL);
+
+ if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
+ // purges grades, group membership, preferences, etc. - admins were warned!
+ $plugin->unenrol_user($instance, $userid);
+ return;
+
+ } else { // ENROL_EXT_REMOVED_SUSPENDNOROLES
+ // just suspend users and remove all roles (we can reassign the roles any time later)
+ 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));
+ }
+ return;
+ }
+ }
- // note: do not test if plugin enabled, we want to keep removing previous roles
+ /**
+ * Triggered via role assigned event.
+ * @static
+ * @param stdClass $ra
+ * @return bool success
+ */
+ public static function role_assigned($ra) {
+ if (!enrol_is_enabled('meta')) {
+ return true;
+ }
// prevent circular dependencies - we can not sync meta roles recursively
if ($ra->component === 'enrol_meta') {
@@ -88,42 +246,57 @@ public function role_unassigned($ra) {
}
// only course level roles are interesting
- $parentcontext = get_context_instance_by_id($ra->contextid);
- if ($parentcontext->contextlevel != CONTEXT_COURSE) {
+ if (!$parentcontext = context::instance_by_id($ra->contextid, IGNORE_MISSING)) {
return true;
}
-
- // does anything want to sync with this parent?
- if (!$enrols = $DB->get_records('enrol', array('customint1'=>$parentcontext->instanceid, 'enrol'=>'meta'), 'id ASC')) {
+ if ($parentcontext->contextlevel != CONTEXT_COURSE) {
return true;
}
- // note: do not check 'nosyncroleids', somebody might have just enabled it, we want to get rid of nosync roles gradually
+ self::sync_course_instances($parentcontext->instanceid, $ra->userid);
- foreach ($enrols as $enrol) {
- // Is the user enrolled? We want to sync only really enrolled users
- if (!$DB->record_exists('user_enrolments', array('userid'=>$ra->userid, 'enrolid'=>$enrol->id))) {
- continue;
- }
- $context = get_context_instance(CONTEXT_COURSE, $enrol->courseid);
+ return true;
+ }
- // now make sure the user does not have the role through some other enrol plugin
- $params = array('contextid'=>$ra->contextid, 'roleid'=>$ra->roleid, 'userid'=>$ra->userid);
- if ($DB->record_exists_select('role_assignments', "contextid = :contextid AND roleid = :roleid AND userid = :userid AND component <> 'enrol_meta'", $params)) {
- continue;
- }
+ /**
+ * Triggered via role unassigned event.
+ * @static
+ * @param stdClass $ra
+ * @return bool success
+ */
+ public static function role_unassigned($ra) {
+ if (!enrol_is_enabled('meta')) {
+ // all roles are removed via cron automatically
+ return true;
+ }
+
+ // prevent circular dependencies - we can not sync meta roles recursively
+ if ($ra->component === 'enrol_meta') {
+ return true;
+ }
- // unassign role, there is no other role assignment in parent course
- role_unassign($ra->roleid, $ra->userid, $context->id, 'enrol_meta', $enrol->id);
+ // only course level roles are interesting
+ if (!$parentcontext = context::instance_by_id($ra->contextid, IGNORE_MISSING)) {
+ return true;
+ }
+ if ($parentcontext->contextlevel != CONTEXT_COURSE) {
+ return true;
}
+ self::sync_course_instances($parentcontext->instanceid, $ra->userid);
+
return true;
}
- public function user_enrolled($ue) {
- global $DB;
-
+ /**
+ * Triggered via user enrolled event.
+ * @static
+ * @param stdClass $ue
+ * @return bool success
+ */
+ public static function user_enrolled($ue) {
if (!enrol_is_enabled('meta')) {
+ // no more enrolments for disabled plugins
return true;
}
@@ -132,63 +305,40 @@ public function user_enrolled($ue) {
return true;
}
- // does anything want to sync with this parent?
- if (!$enrols = $DB->get_records('enrol', array('customint1'=>$ue->courseid, 'enrol'=>'meta'), 'id ASC')) {
- return true;
- }
-
- $plugin = enrol_get_plugin('meta');
- foreach ($enrols as $enrol) {
- if ($ue->status == ENROL_USER_ACTIVE) {
- $status = ENROL_USER_ACTIVE;
- } else {
- $context = get_context_instance(CONTEXT_COURSE, $enrol->courseid);
- if (is_enrolled($context, $ue->userid)) {
- // user already has active enrolment, do not change it
- $status = ENROL_USER_ACTIVE;
- } else {
- $status = $ue->status;
- }
-
- }
- // no problem if already enrolled
- $plugin->enrol_user($enrol, $ue->userid, $status);
- }
+ self::sync_course_instances($ue->courseid, $ue->userid);
return true;
}
- public function user_unenrolled($ue) {
- global $DB;
-
- //note: do not test if plugin enabled, we want to keep removing previously linked courses
-
- // look for unenrolment candidates - it may be possible that user has multiple enrolments...
- $sql = "SELECT e.*
- FROM {enrol} e
- JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = :userid)
- JOIN {enrol} pe ON (pe.courseid = e.customint1 AND pe.enrol <> 'meta' AND pe.courseid = :courseid)
- LEFT JOIN {user_enrolments} pue ON (pue.enrolid = pe.id AND pue.userid = ue.userid)
- WHERE pue.id IS NULL AND e.enrol = 'meta'";
- $params = array('courseid'=>$ue->courseid, 'userid'=>$ue->userid);
+ /**
+ * Triggered via user unenrolled event.
+ * @static
+ * @param stdClass $ue
+ * @return bool success
+ */
+ public static function user_unenrolled($ue) {
- $rs = $DB->get_recordset_sql($sql, $params);
+ // keep unenrolling even if plugin disabled
- $plugin = enrol_get_plugin('meta');
- foreach ($rs as $enrol) {
- $plugin->unenrol_user($enrol, $ue->userid);
+ if ($ue->enrol === 'meta') {
+ // prevent circular dependencies - we can not sync meta enrolments recursively
+ return true;
}
- $rs->close();
+
+ self::sync_course_instances($ue->courseid, $ue->userid);
return true;
}
- public function user_enrol_modified($ue) {
- global $DB;
-
- // update enrolment status if necessary
-
+ /**
+ * Triggered via user enrolment modification event.
+ * @static
+ * @param stdClass $ue
+ * @return bool success
+ */
+ public static function user_enrol_modified($ue) {
if (!enrol_is_enabled('meta')) {
+ // no modifications if plugin disabled
return true;
}
@@ -197,37 +347,41 @@ public function user_enrol_modified($ue) {
return true;
}
- // does anything want to sync with this parent?
- if (!$enrols = $DB->get_records('enrol', array('customint1'=>$ue->courseid, 'enrol'=>'meta'), 'id ASC')) {
- return true;
- }
-
- $plugin = enrol_get_plugin('meta');
- foreach ($enrols as $enrol) {
- $plugin->update_user_enrol($enrol, $ue->userid, $ue->status);
- }
+ self::sync_course_instances($ue->courseid, $ue->userid);
return true;
}
- public function course_deleted($course) {
+ /**
+ * 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 removing previously linked courses
+ // 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'), 'id ASC')) {
+ 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) {
- // unenrol all users
- $ues = $DB->get_recordset('user_enrolments', array('enrolid'=>$enrol->id));
- foreach ($ues as $ue) {
- $plugin->unenrol_user($enrol, $ue->userid);
- }
- $ues->close();
+ $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;
@@ -237,104 +391,226 @@ public function course_deleted($course) {
/**
* Sync all meta course links.
+ *
* @param int $courseid one course, empty mean all
- * @return void
+ * @param bool $verbose verbose CLI output
+ * @return int 0 means ok, 1 means error, 2 means plugin disabled
*/
-function enrol_meta_sync($courseid = NULL) {
+function enrol_meta_sync($courseid = NULL, $verbose = false) {
global $CFG, $DB;
- // unfortunately this may take a loooong time
- @set_time_limit(0); //if this fails during upgrade we can continue from cron, no big deal
+ // purge all roles if meta sync disabled, those can be recreated later here in cron
+ if (!enrol_is_enabled('meta')) {
+ if ($verbose) {
+ mtrace('Meta sync plugin is disabled, unassigning all plugin roles and stopping.');
+ }
+ role_unassign_all(array('component'=>'enrol_meta'));
+ return 2;
+ }
+
+ // unfortunately this may take a long time, execution can be interrupted safely
+ @set_time_limit(0);
+ raise_memory_limit(MEMORY_HUGE);
- $instances = array(); //cache
+ if ($verbose) {
+ mtrace('Starting user enrolment synchronisation...');
+ }
+
+ $instances = array(); // cache instances
$meta = enrol_get_plugin('meta');
- $onecourse = $courseid ? "AND e.courseid = :courseid" : "";
+ $unenrolaction = $meta->get_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
+ $skiproles = $meta->get_config('nosyncroleids', '');
+ $skiproles = empty($skiproles) ? array() : explode(',', $skiproles);
+ $syncall = $meta->get_config('syncall', 1);
+
+ $allroles = get_all_roles();
+
// iterate through all not enrolled yet users
- if (enrol_is_enabled('meta')) {
- list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e');
- if ($courseid) {
- $params['courseid'] = $courseid;
+ $onecourse = $courseid ? "AND e.courseid = :courseid" : "";
+ list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e');
+ $params['courseid'] = $courseid;
+ $sql = "SELECT pue.userid, e.id AS enrolid, pue.status
+ FROM {user_enrolments} pue
+ JOIN {enrol} pe ON (pe.id = pue.enrolid AND pe.enrol <> 'meta' AND pe.enrol $enabled)
+ JOIN {enrol} e ON (e.customint1 = pe.courseid AND e.enrol = 'meta' $onecourse)
+ LEFT JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = pue.userid)
+ WHERE ue.id IS NULL";
+
+ $rs = $DB->get_recordset_sql($sql, $params);
+ foreach($rs as $ue) {
+ if (!isset($instances[$ue->enrolid])) {
+ $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
}
- $sql = "SELECT pue.userid, e.id AS enrolid
- FROM {user_enrolments} pue
- JOIN {enrol} pe ON (pe.id = pue.enrolid AND pe.enrol <> 'meta' AND pe.enrol $enabled )
- JOIN {enrol} e ON (e.customint1 = pe.courseid AND e.enrol = 'meta' AND e.status = :statusenabled $onecourse)
- LEFT JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = pue.userid)
- WHERE ue.id IS NULL";
- $params['statusenabled'] = ENROL_INSTANCE_ENABLED;
- $params['courseid'] = $courseid;
-
- $rs = $DB->get_recordset_sql($sql, $params);
- foreach($rs as $ue) {
- if (!isset($instances[$ue->enrolid])) {
- $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
+ $instance = $instances[$ue->enrolid];
+
+ if (!$syncall) {
+ // this may be slow if very many users are ignored in sync
+ $parentcontext = context_course::instance($instance->customint1);
+ list($ignoreroles, $params) = $DB->get_in_or_equal($skiproles, SQL_PARAMS_NAMED, 'ri', false, -1);
+ $params['contextid'] = $parentcontext->id;
+ $params['userid'] = $ue->userid;
+ $select = "contextid = :contextid AND userid = :userid AND component <> 'enrol_meta' AND roleid $ignoreroles";
+ if (!$DB->record_exists_select('role_assignments', $select, $params)) {
+ // bad luck, this user does not have any role we want in parent course
+ if ($verbose) {
+ mtrace(" skipping enrolling: $ue->userid ==> $instance->courseid (user without role)");
+ }
+ continue;
}
- $meta->enrol_user($instances[$ue->enrolid], $ue->userid);
}
- $rs->close();
+
+ $meta->enrol_user($instance, $ue->userid, $ue->status);
+ if ($verbose) {
+ mtrace(" enrolling: $ue->userid ==> $instance->courseid");
+ }
}
+ $rs->close();
+
- // unenrol as necessary - ignore enabled flag, we want to get rid of all
- $sql = "SELECT ue.userid, e.id AS enrolid
+ // unenrol as necessary - ignore enabled flag, we want to get rid of existing enrols in any case
+ $onecourse = $courseid ? "AND e.courseid = :courseid" : "";
+ list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e');
+ $params['courseid'] = $courseid;
+ $sql = "SELECT ue.*
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' $onecourse)
- LEFT JOIN (SELECT xue.userid, xe.courseid
- FROM {enrol} xe
- JOIN {user_enrolments} xue ON (xue.enrolid = xe.id)
+ LEFT JOIN (SELECT xpue.userid, xpe.courseid
+ FROM {user_enrolments} xpue
+ JOIN {enrol} xpe ON (xpe.id = xpue.enrolid AND xpe.enrol <> 'meta' AND xpe.enrol $enabled)
) pue ON (pue.courseid = e.customint1 AND pue.userid = ue.userid)
- WHERE pue.courseid IS NULL";
- //TODO: this may use a bit of SQL optimisation
- $rs = $DB->get_recordset_sql($sql, array('courseid'=>$courseid));
+ WHERE pue.userid IS NULL";
+ $rs = $DB->get_recordset_sql($sql, $params);
foreach($rs as $ue) {
if (!isset($instances[$ue->enrolid])) {
$instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
}
- $meta->unenrol_user($instances[$ue->enrolid], $ue->userid);
+ $instance = $instances[$ue->enrolid];
+
+ if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
+ $meta->unenrol_user($instance, $ue->userid);
+ if ($verbose) {
+ mtrace(" unenrolling: $ue->userid ==> $instance->courseid");
+ }
+ continue;
+
+ } else { // ENROL_EXT_REMOVED_SUSPENDNOROLES
+ // just disable and ignore any changes
+ if ($ue->status != ENROL_USER_SUSPENDED) {
+ $meta->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_meta'));
+ if ($verbose) {
+ mtrace(" suspending and removing all roles: $ue->userid ==> $instance->courseid");
+ }
+ }
+ continue;
+ }
}
$rs->close();
- // now assign all necessary roles
- if (enrol_is_enabled('meta')) {
- $enabled = explode(',', $CFG->enrol_plugins_enabled);
- foreach($enabled as $k=>$v) {
- if ($v === 'meta') {
- continue; // no meta sync of meta roles
+
+ // update status - meta enrols + start and end dates are ignored, sorry
+ // note the trick here is that the active enrolment and instance constants have value 0
+ $onecourse = $courseid ? "AND e.courseid = :courseid" : "";
+ list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e');
+ $params['courseid'] = $courseid;
+ $sql = "SELECT ue.userid, ue.enrolid, pue.pstatus
+ FROM {user_enrolments} ue
+ JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' $onecourse)
+ JOIN (SELECT xpue.userid, xpe.courseid, MIN(xpue.status + xpe.status) AS pstatus
+ FROM {user_enrolments} xpue
+ JOIN {enrol} xpe ON (xpe.id = xpue.enrolid AND xpe.enrol <> 'meta' AND xpe.enrol $enabled)
+ GROUP BY xpue.userid, xpe.courseid
+ ) pue ON (pue.courseid = e.customint1 AND pue.userid = ue.userid)
+ WHERE (pue.pstatus = 0 AND ue.status > 0) OR (pue.pstatus > 0 and ue.status = 0)";
+ $rs = $DB->get_recordset_sql($sql, $params);
+ foreach($rs as $ue) {
+ if (!isset($instances[$ue->enrolid])) {
+ $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
+ }
+ $instance = $instances[$ue->enrolid];
+ $ue->pstatus = ($ue->pstatus == ENROL_USER_ACTIVE) ? ENROL_USER_ACTIVE : ENROL_USER_SUSPENDED;
+
+ if ($ue->pstatus == ENROL_USER_ACTIVE and !$syncall and $unenrolaction != ENROL_EXT_REMOVED_UNENROL) {
+ // this may be slow if very many users are ignored in sync
+ $parentcontext = context_course::instance($instance->customint1);
+ list($ignoreroles, $params) = $DB->get_in_or_equal($skiproles, SQL_PARAMS_NAMED, 'ri', false, -1);
+ $params['contextid'] = $parentcontext->id;
+ $params['userid'] = $ue->userid;
+ $select = "contextid = :contextid AND userid = :userid AND component <> 'enrol_meta' AND roleid $ignoreroles";
+ if (!$DB->record_exists_select('role_assignments', $select, $params)) {
+ // bad luck, this user does not have any role we want in parent course
+ if ($verbose) {
+ mtrace(" skipping unsuspending: $ue->userid ==> $instance->courseid (user without role)");
+ }
+ continue;
}
- $enabled[$k] = 'enrol_'.$v;
- }
- $enabled[] = $DB->sql_empty(); // manual assignments are replicated too
-
- list($enabled, $params) = $DB->get_in_or_equal($enabled, SQL_PARAMS_NAMED, 'e');
- $sql = "SELECT DISTINCT pra.roleid, pra.userid, c.id AS contextid, e.id AS enrolid
- FROM {role_assignments} pra
- JOIN {user} u ON (u.id = pra.userid AND u.deleted = 0)
- JOIN {context} pc ON (pc.id = pra.contextid AND pc.contextlevel = :coursecontext AND pra.component $enabled)
- JOIN {enrol} e ON (e.customint1 = pc.instanceid AND e.enrol = 'meta' AND e.status = :statusenabled $onecourse)
- JOIN {context} c ON (c.contextlevel = pc.contextlevel AND c.instanceid = e.courseid)
- LEFT JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.userid = pra.userid AND ra.roleid = pra.itemid AND ra.itemid = e.id AND ra.component = 'enrol_meta')
- WHERE ra.id IS NULL";
- $params['statusenabled'] = ENROL_INSTANCE_ENABLED;
- $params['coursecontext'] = CONTEXT_COURSE;
- $params['courseid'] = $courseid;
-
- if ($ignored = $meta->get_config('nosyncroleids')) {
- list($notignored, $xparams) = $DB->get_in_or_equal(explode(',', $ignored), SQL_PARAMS_NAMED, 'ig', false);
- $params = array_merge($params, $xparams);
- $sql = "$sql AND pra.roleid $notignored";
- }
-
- $rs = $DB->get_recordset_sql($sql, $params);
- foreach($rs as $ra) {
- role_assign($ra->roleid, $ra->userid, $ra->contextid, 'enrol_meta', $ra->enrolid);
- }
- $rs->close();
+ }
+
+ $meta->update_user_enrol($instance, $ue->userid, $ue->pstatus);
+ if ($verbose) {
+ if ($ue->pstatus == ENROL_USER_ACTIVE) {
+ mtrace(" unsuspending: $ue->userid ==> $instance->courseid");
+ } else {
+ mtrace(" suspending: $ue->userid ==> $instance->courseid");
+ }
+ }
+ }
+ $rs->close();
+
+
+ // now assign all necessary roles
+ $enabled = explode(',', $CFG->enrol_plugins_enabled);
+ foreach($enabled as $k=>$v) {
+ if ($v === 'meta') {
+ continue; // no meta sync of meta roles
+ }
+ $enabled[$k] = 'enrol_'.$v;
+ }
+ $enabled[] = $DB->sql_empty(); // manual assignments are replicated too
+
+ $onecourse = $courseid ? "AND e.courseid = :courseid" : "";
+ list($enabled, $params) = $DB->get_in_or_equal($enabled, SQL_PARAMS_NAMED, 'e');
+ $params['coursecontext'] = CONTEXT_COURSE;
+ $params['courseid'] = $courseid;
+ $params['activeuser'] = ENROL_USER_ACTIVE;
+ $params['enabledinstance'] = ENROL_INSTANCE_ENABLED;
+ $sql = "SELECT DISTINCT pra.roleid, pra.userid, c.id AS contextid, e.id AS enrolid, e.courseid
+ FROM {role_assignments} pra
+ JOIN {user} u ON (u.id = pra.userid AND u.deleted = 0)
+ JOIN {context} pc ON (pc.id = pra.contextid AND pc.contextlevel = :coursecontext AND pra.component $enabled)
+ JOIN {enrol} e ON (e.customint1 = pc.instanceid AND e.enrol = 'meta' $onecourse AND e.status = :enabledinstance)
+ JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = u.id AND ue.status = :activeuser)
+ JOIN {context} c ON (c.contextlevel = pc.contextlevel AND c.instanceid = e.courseid)
+ LEFT JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.userid = pra.userid AND ra.roleid = pra.roleid AND ra.itemid = e.id AND ra.component = 'enrol_meta')
+ WHERE ra.id IS NULL";
+
+ if ($ignored = $meta->get_config('nosyncroleids')) {
+ list($notignored, $xparams) = $DB->get_in_or_equal(explode(',', $ignored), SQL_PARAMS_NAMED, 'ig', false);
+ $params = array_merge($params, $xparams);
+ $sql = "$sql AND pra.roleid $notignored";
}
+ $rs = $DB->get_recordset_sql($sql, $params);
+ foreach($rs as $ra) {
+ role_assign($ra->roleid, $ra->userid, $ra->contextid, 'enrol_meta', $ra->enrolid);
+ if ($verbose) {
+ mtrace(" assigning role: $ra->userid ==> $ra->courseid as ".$allroles[$ra->roleid]->shortname);
+ }
+ }
+ $rs->close();
+
+
// remove unwanted roles - include ignored roles and disabled plugins too
- $params = array('coursecontext' => CONTEXT_COURSE, 'courseid' => $courseid);
+ $onecourse = $courseid ? "AND e.courseid = :courseid" : "";
+ $params = array();
+ $params['coursecontext'] = CONTEXT_COURSE;
+ $params['courseid'] = $courseid;
+ $params['activeuser'] = ENROL_USER_ACTIVE;
+ $params['enabledinstance'] = ENROL_INSTANCE_ENABLED;
if ($ignored = $meta->get_config('nosyncroleids')) {
list($notignored, $xparams) = $DB->get_in_or_equal(explode(',', $ignored), SQL_PARAMS_NAMED, 'ig', false);
$params = array_merge($params, $xparams);
@@ -342,78 +618,81 @@ function enrol_meta_sync($courseid = NULL) {
} else {
$notignored = "";
}
- $sql = "SELECT ra.roleid, ra.userid, ra.contextid, ra.itemid
+ $sql = "SELECT ra.roleid, ra.userid, ra.contextid, ra.itemid, e.courseid
FROM {role_assignments} ra
JOIN {enrol} e ON (e.id = ra.itemid AND ra.component = 'enrol_meta' AND e.enrol = 'meta' $onecourse)
JOIN {context} pc ON (pc.instanceid = e.customint1 AND pc.contextlevel = :coursecontext)
LEFT JOIN {role_assignments} pra ON (pra.contextid = pc.id AND pra.userid = ra.userid AND pra.roleid = ra.roleid AND pra.component <> 'enrol_meta' $notignored)
- WHERE pra.id IS NULL";
+ LEFT JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = ra.userid AND ue.status = :activeuser)
+ WHERE pra.id IS NULL OR ue.id IS NULL OR e.status <> :enabledinstance";
$rs = $DB->get_recordset_sql($sql, $params);
foreach($rs as $ra) {
role_unassign($ra->roleid, $ra->userid, $ra->contextid, 'enrol_meta', $ra->itemid);
+ if ($verbose) {
+ mtrace(" unassigning role: $ra->userid ==> $ra->courseid as ".$allroles[$ra->roleid]->shortname);
+ }
}
$rs->close();
- // sync enrolment status
- if (enrol_is_enabled('meta')) {
- $enabled = explode(',', $CFG->enrol_plugins_enabled);
- foreach($enabled as $k=>$v) {
- if ($v === 'meta') {
- unset($enabled[$k]);
- }
- }
- list($enabled, $params) = $DB->get_in_or_equal($enabled, SQL_PARAMS_NAMED, 'e');
- if ($courseid) {
+
+ // kick out or suspend users without synced roles if syncall disabled
+ if (!$syncall) {
+ if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
+ $onecourse = $courseid ? "AND e.courseid = :courseid" : "";
+ $params = array();
+ $params['coursecontext'] = CONTEXT_COURSE;
$params['courseid'] = $courseid;
- }
- //note: this will probably take a long time on mysql...
- $sql = "SELECT ue.userid, e.id AS enrolid
- FROM {user_enrolments} ue
- JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' AND e.status = :statusenabled $onecourse)
- LEFT JOIN (SELECT pue.id, pue.userid, pe.courseid
- FROM {user_enrolments} pue
- JOIN {enrol} pe ON (pe.enrol $enabled)
- WHERE pue.enrolid = pe.id AND pue.status = :activestatus2) xx ON (xx.userid = ue.userid AND xx.courseid = e.customint1)
- WHERE ue.status = :activestatus1 AND xx.id IS NULL";
- $params['statusenabled'] = ENROL_INSTANCE_ENABLED;
- $params['activestatus1'] = ENROL_USER_ACTIVE;
- $params['activestatus2'] = ENROL_USER_ACTIVE;
- $params['courseid'] = $courseid;
-
- $rs = $DB->get_recordset_sql($sql, $params);
- foreach($rs as $ue) {
- if (!isset($instances[$ue->enrolid])) {
- $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
+ $sql = "SELECT ue.userid, ue.enrolid
+ FROM {user_enrolments} ue
+ JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' $onecourse)
+ JOIN {context} c ON (e.courseid = c.instanceid AND c.contextlevel = :coursecontext)
+ LEFT JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.itemid = e.id AND ra.userid = ue.userid)
+ WHERE ra.id IS NULL";
+ $ues = $DB->get_recordset_sql($sql, $params);
+ foreach($ues as $ue) {
+ if (!isset($instances[$ue->enrolid])) {
+ $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
+ }
+ $instance = $instances[$ue->enrolid];
+ $meta->unenrol_user($instance, $ue->userid);
+ if ($verbose) {
+ mtrace(" unenrolling: $ue->userid ==> $instance->courseid (user without role)");
+ }
}
- $meta->update_user_enrol($instances[$ue->enrolid], $ue->userid, ENROL_USER_SUSPENDED);
- }
- $rs->close();
+ $ues->close();
- list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e');
- if ($courseid) {
+ } else {
+ // just suspend the users
+ $onecourse = $courseid ? "AND e.courseid = :courseid" : "";
+ $params = array();
+ $params['coursecontext'] = CONTEXT_COURSE;
$params['courseid'] = $courseid;
- }
- // enable if at least one enrolment active in linked course
- $sql = "SELECT DISTINCT ue.userid, e.id AS enrolid
- FROM {user_enrolments} ue
- JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' AND e.status = :statusenabled $onecourse)
- JOIN {enrol} pe ON (pe.courseid = e.customint1 AND pe.enrol $enabled)
- JOIN {user_enrolments} pue ON (pue.enrolid = pe.id AND pue.userid = ue.userid AND pue.status = :activestatus)
- WHERE ue.status = :suspendedstatus";
- $params['statusenabled'] = ENROL_INSTANCE_ENABLED;
- $params['suspendedstatus'] = ENROL_USER_SUSPENDED;
- $params['activestatus'] = ENROL_USER_ACTIVE;
- $params['courseid'] = $courseid;
- $rs = $DB->get_recordset_sql($sql, $params);
- foreach($rs as $ue) {
- if (!isset($instances[$ue->enrolid])) {
- $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
+ $params['active'] = ENROL_USER_ACTIVE;
+ $sql = "SELECT ue.userid, ue.enrolid
+ FROM {user_enrolments} ue
+ JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' $onecourse)
+ JOIN {context} c ON (e.courseid = c.instanceid AND c.contextlevel = :coursecontext)
+ LEFT JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.itemid = e.id AND ra.userid = ue.userid)
+ WHERE ra.id IS NULL AND ue.status = :active";
+ $ues = $DB->get_recordset_sql($sql, $params);
+ foreach($ues as $ue) {
+ if (!isset($instances[$ue->enrolid])) {
+ $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
+ }
+ $instance = $instances[$ue->enrolid];
+ $meta->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED);
+ if ($verbose) {
+ mtrace(" suspending: $ue->userid ==> $instance->courseid (user without role)");
+ }
}
- $meta->update_user_enrol($instances[$ue->enrolid], $ue->userid, ENROL_USER_ACTIVE);
+ $ues->close();
}
- $rs->close();
+ }
+ if ($verbose) {
+ mtrace('...user enrolment synchronisation finished.');
}
+ return 0;
}
View
8 enrol/meta/settings.php
@@ -1,5 +1,4 @@
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
@@ -38,5 +37,12 @@
$allroles[$role->id] = $rolename;
}
$settings->add(new admin_setting_configmultiselect('enrol_meta/nosyncroleids', get_string('nosyncroleids', 'enrol_meta'), get_string('nosyncroleids_desc', 'enrol_meta'), array(), $allroles));
+
+ $settings->add(new admin_setting_configcheckbox('enrol_meta/syncall', get_string('syncall', 'enrol_meta'), get_string('syncall_desc', 'enrol_meta'), 1));
+
+ $options = array(
+ ENROL_EXT_REMOVED_UNENROL => get_string('extremovedunenrol', 'enrol'),
+ ENROL_EXT_REMOVED_SUSPENDNOROLES => get_string('extremovedsuspendnoroles', 'enrol'));
+ $settings->add(new admin_setting_configselect('enrol_meta/unenrolaction', get_string('extremovedaction', 'enrol'), get_string('extremovedaction_help', 'enrol'), ENROL_EXT_REMOVED_UNENROL, $options));
}
}
View
4 enrol/meta/version.php
@@ -25,7 +25,7 @@
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2011112900; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version = 2011112901; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2011112900; // Requires this Moodle version
$plugin->component = 'enrol_meta'; // Full name of the plugin (used for diagnostics)
-$plugin->cron = 60;
+$plugin->cron = 60*60; // run cron every hour by default, it is not out-of-sync often
Please sign in to comment.
Something went wrong with that request. Please try again.