$outcome->success = true;
$outcome->response = $manager->get_assignable_roles();
break;
-
+ case 'getcohorts':
+ require_capability('moodle/course:enrolconfig', $context);
+ $outcome->success = true;
+ $outcome->response = $manager->get_cohorts();
+ break;
+ case 'enrolcohort':
+ require_capability('moodle/course:enrolconfig', $context);
+ $roleid = required_param('roleid', PARAM_INT);
+ $cohortid = required_param('cohortid', PARAM_INT);
+ $outcome->success = $manager->enrol_cohort($cohortid, $roleid);
+ break;
+ case 'enrolcohortusers':
+ require_capability('moodle/course:enrolconfig', $context);
+ $roleid = required_param('roleid', PARAM_INT);
+ $cohortid = required_param('cohortid', PARAM_INT);
+ $result = $manager->enrol_cohort_users($cohortid, $roleid);
+ if ($result !== false) {
+ $outcome->success = true;
+ $outcome->response->users = $result;
+ $outcome->response->message = get_string('enrollednewusers', 'enrol', $result);
+ }
+ break;
case 'searchusers':
$enrolid = required_param('enrolid', PARAM_INT);
$search = optional_param('search', '', PARAM_CLEAN);
return $this->context;
}
+ /**
+ * Gets all the cohorts the user is able to view.
+ *
+ * @global moodle_database $DB
+ * @return array
+ */
+ public function get_cohorts() {
+ global $DB;
+ $context = $this->get_context();
+ $cohorts = array();
+ $instances = $this->get_enrolment_instances();
+ $enrolled = array();
+ foreach ($instances as $instance) {
+ if ($instance->enrol == 'cohort') {
+ $enrolled[] = $instance->customint1;
+ }
+ }
+ list($sqlparents, $params) = $DB->get_in_or_equal(get_parent_contexts($context));
+ $sql = "SELECT id, name, contextid
+ FROM {cohort}
+ WHERE contextid $sqlparents
+ ORDER BY name ASC";
+ $rs = $DB->get_recordset_sql($sql, $params);
+ foreach ($rs as $c) {
+ $context = get_context_instance_by_id($c->contextid);
+ if (!has_capability('moodle/cohort:view', $context)) {
+ continue;
+ }
+ $cohorts[$c->id] = array(
+ 'cohortid'=>$c->id,
+ 'name'=>format_string($c->name),
+ 'users'=>$DB->count_records('cohort_members', array('cohortid'=>$c->id)),
+ 'enrolled'=>in_array($c->id, $enrolled)
+ );
+ }
+ $rs->close();
+ return $cohorts;
+ }
+
+ /**
+ * Enrols a cohort in a course.
+ *
+ * Essentially this just adds a cohort enrolment plugin instance to the course
+ *
+ * @param int $cohortid
+ * @param int $roleid
+ * @return bool
+ */
+ public function enrol_cohort($cohortid, $roleid) {
+ global $CFG;
+ require_capability('moodle/course:enrolconfig', $this->get_context());
+ require_once($CFG->dirroot.'/enrol/cohort/locallib.php');
+ $roles = $this->get_assignable_roles();
+ $cohorts = $this->get_cohorts();
+ if (!array_key_exists($cohortid, $cohorts) || !array_key_exists($roleid, $roles)) {
+ return false;
+ }
+ $enrol = enrol_get_plugin('cohort');
+ $enrol->add_instance($this->course, array('customint1'=>$cohortid, 'roleid'=>$roleid));
+ enrol_cohort_sync($this->course->id);
+ return true;
+ }
+
+ /**
+ * Enrols all of the users in a cohort within this course.
+ *
+ * Note this is VERY different from creating an enrolment instance for a cohort.
+ *
+ * @global moodle_database $DB
+ * @param int $cohortid
+ * @param int $roleid
+ * @return bool
+ */
+ public function enrol_cohort_users($cohortid, $roleid) {
+ global $DB;
+ require_capability('moodle/course:enrolconfig', $this->get_context());
+ require_capability('enrol/manual:manage', $this->get_context());
+ $instances = $this->get_enrolment_instances();
+ $instance = false;
+ foreach ($instances as $i) {
+ if ($i->enrol == 'manual') {
+ $instance = $i;
+ break;
+ }
+ }
+ if (!$instance) {
+ return false;
+ }
+ $plugin = enrol_get_plugin('manual');
+
+ $sql = "SELECT com.userid
+ FROM {cohort_members} com
+ LEFT JOIN (
+ SELECT *
+ FROM {user_enrolments} ue
+ WHERE ue.enrolid = :enrolid
+ ) ue ON ue.userid=com.userid
+ WHERE com.cohortid = :cohortid AND ue.id IS NULL";
+ $params = array('cohortid'=>$cohortid, 'enrolid'=>$instance->id);
+ $rs = $DB->get_recordset_sql($sql, $params);
+ $count = 0;
+ foreach ($rs as $user) {
+ $count++;
+ $plugin->enrol_user($instance, $user->userid, $roleid);
+ }
+ $rs->close();
+ return $count;
+ }
+
/**
* Gets an array of users for display, this includes minimal user information
* as well as minimal information on the users roles, groups, and enrolments.
if ($enrolmentselector) {
$content .= $this->output->render($enrolmentselector);
}
+ $cohortenroller = $table->get_cohort_enrolment_control($this->page);
+ if ($cohortenroller) {
+ $content .= $this->output->render($cohortenroller);
+ }
$content .= $this->output->render($table->get_enrolment_type_filter());
$content .= $this->output->render($table->get_paging_bar());
$content .= html_writer::table($table);
if ($enrolmentselector) {
$content .= $this->output->render($enrolmentselector);
}
+ $cohortenroller = $table->get_cohort_enrolment_control($this->page);
+ if ($cohortenroller) {
+ $content .= $this->output->render($cohortenroller);
+ }
return $content;
}
*/
public function get_enrolment_type_filter() {
$url = new moodle_url($this->pageurl, $this->manager->get_url_params()+$this->get_url_params());
- $selector = new single_select($url, 'ifilter', array(0=>get_string('all')) + $this->manager->get_enrolment_instance_names(), $this->manager->get_enrolment_filter(), array());
+ $selector = new single_select($url, 'ifilter', array(0=>get_string('all')) + (array)$this->manager->get_enrolment_instance_names(), $this->manager->get_enrolment_filter(), array());
$selector->set_label( get_string('enrolmentinstances', 'enrol'));
return $selector;
}
+ /**
+ * Returns a button to enrol cohorts or thier users
+ *
+ * @staticvar int $count
+ * @param moodle_page $page
+ * @return single_button|false
+ */
+ public function get_cohort_enrolment_control(moodle_page $page) {
+ static $count = 0;
+
+ // First make sure that cohorts is enabled
+ $plugins = $this->manager->get_enrolment_plugins();
+ if (!array_key_exists('cohort', $plugins)) {
+ return false;
+ }
+ $count ++;
+ $course = $this->manager->get_course();
+ $cohorturl = new moodle_url('/enrol/cohort/addinstance.php', array('id'=>$course->id));
+ $control = new single_button($cohorturl, get_string('enrolcohort', 'enrol'), 'get');
+ $control->class = 'singlebutton enrolcohortbutton instance'.$count;
+ $control->formid = 'manuallyenrol_single_'+$count;
+ if ($count == 1) {
+ $page->requires->strings_for_js(array('enrol','synced','enrolcohort','enrolcohortusers'), 'enrol');
+ $page->requires->string_for_js('assignroles', 'role');
+ $page->requires->string_for_js('cohort', 'cohort');
+ $page->requires->string_for_js('users', 'moodle');
+ $url = new moodle_url($this->pageurl, $this->manager->get_url_params()+$this->get_url_params());
+
+ $hasmanualinstance = false;
+ // No point showing this at all if the user cant manually enrol users
+ if (has_capability('enrol/manual:manage', $this->manager->get_context())) {
+ // Make sure manual enrolments instance exists
+ $instances = $this->manager->get_enrolment_instances();
+ foreach ($instances as $instance) {
+ if ($instance->enrol == 'manual') {
+ $hasmanualinstance = true;
+ break;
+ }
+ }
+ }
+
+ $arguments = array(array(
+ 'courseid'=>$course->id,
+ 'ajaxurl'=>'/enrol/ajax.php',
+ 'url'=>$url->out(false),
+ 'manualEnrolment'=>$hasmanualinstance));
+ $page->requires->yui_module(array('moodle-enrol-quickcohortenrolment', 'moodle-enrol-quickcohortenrolment-skin'), 'M.enrol.quickcohortenrolment.init', $arguments);
+ }
+ return $control;
+ }
+
/**
* Gets the enrolment selector control for this table and initialises its
* JavaScript
}
return null;
}
-}
\ No newline at end of file
+}
--- /dev/null
+.qce-panel {background-color:#666;border:2px solid #666;border-width:0 2px 2px 0;width:420px;}
+.qce-panel .yui3-widget-hd {background:url("sprite.png");background-repeat:repeat-x;background-color:#DDD;background-position: 0 -15px;border-bottom:1px solid #555;border-top:1px solid #fff;}
+.qce-panel .yui3-widget-hd h2 {margin:3px 5px 2px;padding:0;font-size:110%;}
+.qce-panel .yui3-widget-hd .close {width:25px;height:15px;position:absolute;top:3px;right:1em;cursor:pointer;background:url("sprite.png") no-repeat scroll 0 0 transparent;}
+.qce-panel .yui3-overlay-content {background-color:#F6F6F6;border:1px solid #555;margin-top:-2px;margin-left:-2px;}
+.qce-panel .yui3-widget-bd .loading {height:300px;text-align:center;}
+.qce-panel .yui3-widget-bd .loading img {margin-top:130px;}
+.qce-panel .qce-enrollable-cohorts {overflow:auto;margin:5px;}
+.qce-panel .qce-cohorts {border:1px solid #666;width:408px;background-color:#FFF;height:250px;}
+.qce-panel .qce-cohort {width:100%;position:relative;clear:both;height:24px;}
+.qce-panel .qce-cohort.odd {background-color:#f4f4f4;}
+.qce-panel .qce-cohort .qce-cohort-button {width:70px;float:left;text-align:center;display:inline-block;font-size:80%;height:22px;line-height:22px;overflow:hidden;}
+.qce-panel .qce-cohort .qce-cohort-button.notenrolled {background-color:#ddd;border:1px outset #CCC;background:url("sprite.png");background-repeat:repeat-x;background-color:#DDD;background-position: 0 -25px;color:inherit;}
+.qce-panel .qce-cohort .qce-cohort-button.notenrolled:hover {background-position:0 -15px;cursor:pointer;}
+.qce-panel .qce-cohort .qce-cohort-button.alreadyenrolled {font-weight:bold;margin:2px;}
+.qce-panel .qce-cohort .qce-cohort-name {margin-left:80px;margin-right:40px;line-height:24px;}
+.qce-panel .canenrolusers .qce-cohort .qce-cohort-button.alreadyenrolled {width:140px;}
+.qce-panel .canenrolusers .qce-cohort .qce-cohort-name {margin-left:150px;margin-right:40px;line-height:24px;}
+.qce-panel .qce-cohort .qce-cohort-users {position:absolute;right:5px;top:0;width:30px;text-align:right;height:24px;line-height:24px;}
+.qce-panel .qce-assignable-roles {margin:3px 5px 2px;}
+.qce-panel .qce-cohort.headings {font-weight:bold;border-width:0;}
+.qce-panel .qce-cohort.headings .qce-cohort-button {display:none;}
\ No newline at end of file
--- /dev/null
+YUI.add('moodle-enrol-quickcohortenrolment', function(Y) {
+
+ var CONTROLLERNAME = 'Quick cohort enrolment controller',
+ COHORTNAME = 'Cohort',
+ COHORTID = 'cohortid',
+ ENROLLED = 'enrolled',
+ NAME = 'name',
+ USERS = 'users',
+ COURSEID = 'courseid',
+ ASSIGNABLEROLES = 'assignableRoles',
+ COHORTS = 'cohorts',
+ PANELID = 'qce-panel-',
+ URL = 'url',
+ AJAXURL = 'ajaxurl',
+ MANUALENROLMENT = 'manualEnrolment',
+ CSS = {
+ COHORT : 'qce-cohort',
+ COHORTS : 'qce-cohorts',
+ COHORTBUTTON : 'qce-cohort-button',
+ COHORTENROLLED : 'qce-cohort-enrolled',
+ COHORTNAME : 'qce-cohort-name',
+ COHORTUSERS : 'qce-cohort-users',
+ PANEL : 'qce-panel',
+ PANELCONTENT : 'qce-panel-content',
+ PANELCOHORTS : 'qce-enrollable-cohorts',
+ PANELROLES : 'qce-assignable-roles',
+ PANELCONTROLS : 'qce-panel-controls',
+ ENROLUSERS : 'canenrolusers'
+ },
+ COUNT = 0;
+
+
+ var CONTROLLER = function(config) {
+ CONTROLLER.superclass.constructor.apply(this, arguments);
+ }
+ Y.extend(CONTROLLER, Y.Base, {
+ initializer : function(config) {
+ COUNT ++;
+ this.publish('assignablerolesloaded');
+ this.publish('cohortsloaded');
+
+ var close = Y.Node.create('<div class="close"></div>');
+ var panel = new Y.Overlay({
+ headerContent : Y.Node.create('<div></div>').append(Y.Node.create('<h2>'+M.str.enrol.enrolcohort+'</h2>')).append(close),
+ bodyContent : Y.Node.create('<div class="loading"></div>').append(Y.Node.create('<img alt="loading" />').setAttribute('src', M.cfg.loadingicon)),
+ constrain : true,
+ centered : true,
+ id : PANELID+COUNT,
+ visible : false
+ });
+ panel.get('boundingBox').addClass(CSS.PANEL);
+ panel.render(Y.one(document.body));
+ this.on('show', panel.show, panel);
+ this.on('hide', function() {
+ this.set('bodyContent', Y.Node.create('<div class="loading"></div>').append(Y.Node.create('<img alt="loading" />').setAttribute('src', M.cfg.loadingicon)));
+ this.hide();
+ }, panel);
+ this.on('assignablerolesloaded', this.updateContent, this, panel);
+ this.on('cohortsloaded', this.updateContent, this, panel);
+ close.on('click', this.hide, this);
+
+ Y.all('.enrolcohortbutton input').each(function(node){
+ if (node.getAttribute('type', 'submit')) {
+ node.on('click', this.show, this);
+ }
+ }, this);
+
+ var base = panel.get('boundingBox');
+ base.plug(Y.Plugin.Drag);
+ base.dd.addHandle('.yui3-widget-hd h2');
+ base.one('.yui3-widget-hd h2').setStyle('cursor', 'move');
+ },
+ show : function(e) {
+ e.preventDefault();
+ this.getCohorts();
+ this.getAssignableRoles();
+ this.fire('show');
+ },
+ updateContent : function(e, panel) {
+ if (panel.get('contentBox').one('.loading')) {
+ panel.set('bodyContent', Y.Node.create('<div class="'+CSS.PANELCONTENT+'"></div>')
+ .append(Y.Node.create('<div class="'+CSS.PANELCOHORTS+'"><div class="'+CSS.COHORT+' headings"><div class="'+CSS.COHORTBUTTON+'"></div><div class="'+CSS.COHORTNAME+'">'+M.str.cohort.cohort+'</div><div class="'+CSS.COHORTUSERS+'">'+M.str.moodle.users+'</div></div></div>'))
+ .append(Y.Node.create('<div class="'+CSS.PANELROLES+'"></div>')));
+ }
+ var content, i, roles, cohorts, count=0, supportmanual = this.get(MANUALENROLMENT);
+ switch (e.type.replace(/^[^:]+:/, '')) {
+ case 'cohortsloaded' :
+ cohorts = this.get(COHORTS);
+ content = Y.Node.create('<div class="'+CSS.COHORTS+'"></div>');
+ if (supportmanual) {
+ content.addClass(CSS.ENROLUSERS);
+ }
+ for (i in cohorts) {
+ count++;
+ cohorts[i].on('enrolchort', this.enrolCohort, this, cohorts[i], panel.get('contentBox'), false);
+ cohorts[i].on('enrolusers', this.enrolCohort, this, cohorts[i], panel.get('contentBox'), true);
+ content.append(cohorts[i].toHTML(supportmanual).addClass((count%2)?'even':'odd'));
+ }
+ panel.get('contentBox').one('.'+CSS.PANELCOHORTS).append(content);
+ break;
+ case 'assignablerolesloaded':
+ roles = this.get(ASSIGNABLEROLES);
+ content = Y.Node.create('<select></select>');
+ for (i in roles) {
+ content.append(Y.Node.create('<option value="'+i+'">'+roles[i]+'</option>'));
+ }
+ panel.get('contentBox').one('.'+CSS.PANELROLES).setContent(Y.Node.create('<div>'+M.str.role.assignroles+': </div>').append(content));
+ break;
+ }
+ },
+ hide : function() {
+ this.fire('hide');
+ },
+ getCohorts : function() {
+ Y.io(M.cfg.wwwroot+this.get(AJAXURL), {
+ method:'POST',
+ data:'id='+this.get(COURSEID)+'&action=getcohorts&sesskey='+M.cfg.sesskey,
+ on: {
+ complete: function(tid, outcome, args) {
+ try {
+ var cohorts = Y.JSON.parse(outcome.responseText);
+ this.setCohorts(cohorts.response);
+ } catch (e) {
+ Y.fail(CONTROLLERNAME+': Failed to load cohorts');
+ }
+ this.getCohorts = function() {
+ this.fire('cohortsloaded');
+ }
+ this.getCohorts();
+ }
+ },
+ context:this
+ });
+ },
+ setCohorts : function(rawcohorts) {
+ var cohorts = [], i=0;
+ for (i in rawcohorts) {
+ cohorts[rawcohorts[i].cohortid] = new COHORT(rawcohorts[i]);
+ }
+ this.set(COHORTS, cohorts);
+ },
+ getAssignableRoles : function() {
+ Y.io(M.cfg.wwwroot+this.get(AJAXURL), {
+ method:'POST',
+ data:'id='+this.get(COURSEID)+'&action=getassignable&sesskey='+M.cfg.sesskey,
+ on: {
+ complete: function(tid, outcome, args) {
+ try {
+ var roles = Y.JSON.parse(outcome.responseText);
+ this.set(ASSIGNABLEROLES, roles.response);
+ } catch (e) {
+ Y.fail(CONTROLLERNAME+': Failed to load assignable roles');
+ }
+ this.getAssignableRoles = function() {
+ this.fire('assignablerolesloaded');
+ }
+ this.getAssignableRoles();
+ }
+ },
+ context:this
+ });
+ },
+ enrolCohort : function(e, cohort, node, usersonly) {
+ var params = {
+ id : this.get(COURSEID),
+ roleid : node.one('.'+CSS.PANELROLES+' select').get('value'),
+ cohortid : cohort.get(COHORTID),
+ action : (usersonly)?'enrolcohortusers':'enrolcohort',
+ sesskey : M.cfg.sesskey
+ }
+ Y.io(M.cfg.wwwroot+this.get(AJAXURL), {
+ method:'POST',
+ data:build_querystring(params),
+ on: {
+ complete: function(tid, outcome, args) {
+ try {
+ var result = Y.JSON.parse(outcome.responseText);
+ if (result.success) {
+ if (result.response && result.response.message) {
+ alert(result.response.message);
+ }
+ if (result.response.users) {
+ window.location.href = this.get(URL);
+ }
+ } else {
+ alert('Failed to enrol cohort');
+ }
+ } catch (e) {
+ Y.fail(CONTROLLERNAME+': Failed to enrol cohort');
+ }
+ }
+ },
+ context:this
+ });
+ }
+ }, {
+ NAME : CONTROLLERNAME,
+ ATTRS : {
+ url : {
+ validator : Y.Lang.isString
+ },
+ ajaxurl : {
+ validator : Y.Lang.isString
+ },
+ courseid : {
+ value : null
+ },
+ cohorts : {
+ validator : Y.Lang.isArray,
+ value : null
+ },
+ assignableRoles : {
+ value : null
+ },
+ manualEnrolment : {
+ value : false
+ }
+ }
+ });
+ Y.augment(CONTROLLER, Y.EventTarget);
+
+ var COHORT = function(config) {
+ COHORT.superclass.constructor.apply(this, arguments);
+ }
+ Y.extend(COHORT, Y.Base, {
+ toHTML : function(supportmanualenrolment){
+ var button, result, name, users, syncbutton, usersbutton;
+ result = Y.Node.create('<div class="'+CSS.COHORT+'"></div>');
+ if (this.get(ENROLLED)) {
+ button = Y.Node.create('<div class="'+CSS.COHORTBUTTON+' alreadyenrolled">'+M.str.enrol.synced+'</div>');
+ } else {
+ button = Y.Node.create('<div></div>');
+
+ syncbutton = Y.Node.create('<a class="'+CSS.COHORTBUTTON+' notenrolled enrolcohort">'+M.str.enrol.enrolcohort+'</a>');
+ syncbutton.on('click', function(){this.fire('enrolchort');}, this);
+ button.append(syncbutton);
+
+ if (supportmanualenrolment) {
+ usersbutton = Y.Node.create('<a class="'+CSS.COHORTBUTTON+' notenrolled enrolusers">'+M.str.enrol.enrolcohortusers+'</a>');
+ usersbutton.on('click', function(){this.fire('enrolusers');}, this);
+ button.append(usersbutton);
+ }
+ }
+ name = Y.Node.create('<div class="'+CSS.COHORTNAME+'">'+this.get(NAME)+'</div>');
+ users = Y.Node.create('<div class="'+CSS.COHORTUSERS+'">'+this.get(USERS)+'</div>');
+ if (this.get(ENROLLED)) {
+ button.one(CSS.COHORTENROLLED);
+ }
+ return result.append(button).append(name).append(users);
+ }
+ }, {
+ NAME : COHORTNAME,
+ ATTRS : {
+ cohortid : {
+
+ },
+ name : {
+ validator : Y.Lang.isString
+ },
+ enrolled : {
+ value : false
+ },
+ users : {
+ value : 0
+ }
+ }
+ });
+ Y.augment(COHORT, Y.EventTarget);
+
+ M.enrol = M.enrol || {};
+ M.enrol.quickcohortenrolment = {
+ init : function(cfg) {
+ new CONTROLLER(cfg);
+ }
+ }
+
+}, '@VERSION@', {requires:['base','node', 'overlay', 'io', 'test', 'json-parse', 'event-delegate', 'dd-plugin', 'event-key']});
\ No newline at end of file
$string['enrol'] = 'Enrol';
$string['enrolcandidates'] = 'Not enrolled users';
$string['enrolcandidatesmatching'] = 'Matching not enrolled users';
+$string['enrolcohort'] = 'Enrol cohort';
+$string['enrolcohortusers'] = 'Enrol users';
+$string['enrollednewusers'] = 'Successfully enrolled {$a} new users';
$string['enrolledusers'] = 'Enrolled users';
$string['enrolledusersmatching'] = 'Matching enrolled users';
$string['enrolme'] = 'Enrol me in this course';
$string['periodstart'] = 'from {$a}';
$string['periodstartend'] = 'from {$a->start} until {$a->end}';
$string['startdatetoday'] = 'Today';
+$string['synced'] = 'Synced';
$string['unenrol'] = 'Unenrol';
$string['unenrolconfirm'] = 'Do you really want to unenrol user "{$a->user}" from course "{$a->course}"?';
$string['unenrolme'] = 'Unenrol me from {$a}';
$string['extremovedsuspend'] = 'Disable course enrolment';
$string['extremovedsuspendnoroles'] = 'Disable course enrolment and remove roles';
$string['extremovedkeep'] = 'Keep user enrolled';
-$string['extremovedunenrol'] = 'Unenrol user from course';
+$string['extremovedunenrol'] = 'Unenrol user from course';
\ No newline at end of file
.userenrolment .col_group .addgroup {background-color:#DDD;border:1px outset #EEE;-moz-border-radius:5px;}
.userenrolment .col_enrol {max-width:300px;}
.userenrolment .col_enrol .enrolment {border:1px outset #E6E6E6;background-color:#EEE;line-height:10px;font-size:10px;-moz-border-radius:5px;}
-.path-enrol .enrolusersbutton.instance1 {float:right;}
\ No newline at end of file
+.path-enrol .enrolusersbutton,
+.path-enrol .enrolcohortbutton {float:left;}
+.path-enrol .enrolusersbutton.instance1,
+.path-enrol .enrolcohortbutton.instance1 {float:right;}
\ No newline at end of file