Index: cohort/index.php
===================================================================
--- cohort/index.php (revision )
+++ cohort/index.php (revision )
@@ -0,0 +1,115 @@
+.
+
+/**
+ * Cohort related management functions, this file needs to be included manually.
+ *
+ * @package moodlecore
+ * @subpackage cohort
+ * @copyright 2010 Petr Skoda (info@skodak.org)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require('../config.php');
+require_once($CFG->libdir.'/adminlib.php');
+
+$contextid = optional_param('contextid', 0, PARAM_INT);
+
+require_login();
+
+if ($contextid) {
+ $context = get_context_instance_by_id($contextid, MUST_EXIST);
+} else {
+ $context = get_context_instance(CONTEXT_SYSTEM);
+}
+
+if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
+ print_error('invalidcontext');
+}
+
+$category = null;
+if ($context->contextlevel == CONTEXT_COURSECAT) {
+ $category = $DB->get_record('course_categories', array('id'=>$context->instanceid), '*', MUST_EXIST);
+}
+
+$manager = has_capability('moodle/cohort:manage', $context);
+if (!$manager) {
+ require_capability('moodle/cohort:view', $context);
+}
+
+$strcohorts = get_string('cohorts', 'cohort');
+
+if ($category) {
+ $PAGE->set_url('/cohort/index.php', array('contextid'=>$context->id));
+ $PAGE->set_title($strcohorts);
+ $PAGE->set_context($context);
+ $PAGE->navbar->add($category->name, new moodle_url('/course/index.php', array('categoryedit'=>'1')));
+ $PAGE->navbar->add($strcohorts);
+} else {
+ admin_externalpage_setup('cohorts');
+}
+
+echo $OUTPUT->header();
+
+echo $OUTPUT->heading(get_string('cohortsin', 'cohort', print_context_name($context)));
+
+$cohorts = $DB->get_records('cohort', array('contextid'=>$context->id));
+
+$data = array();
+foreach($cohorts as $cohort) {
+ $line = array();
+ $line[] = format_string($cohort->name);
+ $line[] = $cohort->idnumber;
+ $line[] = format_text($cohort->description, $cohort->descriptionformat);
+
+ $line[] = $DB->count_records('cohort_members', array('cohortid'=>$cohort->id));
+
+ if (empty($cohort->component)) {
+ $line[] = get_string('nocomponent', 'cohort');
+ } else {
+ $line[] = get_string('pluginname', $cohort->component);
+ }
+
+ if ($manager) {
+ if (empty($cohort->component)) {
+ $buttons = html_writer::link(new moodle_url('/cohort/edit.php', array('id'=>$cohort->id)), get_string('edit'));
+ $buttons .= ' '.html_writer::link(new moodle_url('/cohort/edit.php', array('id'=>$cohort->id, 'delete'=>1)), get_string('delete'));
+ $buttons .= ' '.html_writer::link(new moodle_url('/cohort/assign.php', array('id'=>$cohort->id)), get_string('assign', 'cohort'));
+ } else {
+ $buttons = '';
+ }
+ } else {
+ $buttons = '';
+ }
+ $line[] = $buttons;
+
+ $data[] = $line;
+}
+$table = new html_table();
+$table->head = array(get_string('name', 'cohort'), get_string('idnumber', 'cohort'), get_string('description', 'cohort'),
+ get_string('memberscount', 'cohort'), get_string('component', 'cohort'), get_string('edit'));
+$table->size = array('20%', '10%', '40%', '10%', '10%', '10%');
+$table->align = array('left', 'left', 'left', 'left','center', 'center');
+$table->width = '80%';
+$table->data = $data;
+echo html_writer::table($table);
+
+if ($manager) {
+ echo $OUTPUT->single_button(new moodle_url('/cohort/edit.php', array('contextid'=>$context->id)), get_string('add'));
+}
+
+echo $OUTPUT->footer();
\ No newline at end of file
Index: cohort/edit.php
===================================================================
--- cohort/edit.php (revision )
+++ cohort/edit.php (revision )
@@ -0,0 +1,129 @@
+.
+
+
+/**
+ * Cohort related management functions, this file needs to be included manually.
+ *
+ * @package moodlecore
+ * @subpackage cohort
+ * @copyright 2010 Petr Skoda (info@skodak.org)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require('../config.php');
+require($CFG->dirroot.'/cohort/lib.php');
+require($CFG->dirroot.'/cohort/edit_form.php');
+
+$id = optional_param('id', 0, PARAM_INT);
+$contextid = optional_param('contextid', 0, PARAM_INT);
+$delete = optional_param('delete', 0, PARAM_BOOL);
+$confirm = optional_param('confirm', 0, PARAM_BOOL);
+
+require_login();
+
+$category = null;
+if ($id) {
+ $cohort = $DB->get_record('cohort', array('id'=>$id), '*', MUST_EXIST);
+ $context = get_context_instance_by_id($cohort->contextid, MUST_EXIST);
+} else {
+ $context = get_context_instance_by_id($contextid, MUST_EXIST);
+ if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
+ print_error('invalidcontext');
+ }
+ $cohort = new object();
+ $cohort->id = 0;
+ $cohort->contextid = $context->id;
+ $cohort->name = '';
+ $cohort->description = '';
+}
+
+require_capability('moodle/cohort:manage', $context);
+
+$returnurl = new moodle_url('/cohort/index.php', array('contextid'=>$context->id));
+
+if (!empty($cohort->component)) {
+ // we can not manually edit cohorts that were created by external systems, sorry
+ redirect($returnurl);
+}
+
+$PAGE->set_context($context);
+$PAGE->set_url('/cohort/edit.php', array('contextid'=>$context->id, 'id'=>$cohort->id));
+$PAGE->set_context($context);
+
+if ($context->contextlevel == CONTEXT_COURSECAT) {
+ $category = $DB->get_record('course_categories', array('id'=>$context->instanceid), '*', MUST_EXIST);
+ $PAGE->navbar->add($category->name, new moodle_url('/course/index.php', array('categoryedit'=>'1')));
+}
+$PAGE->navbar->add(get_string('cohorts', 'cohort'), new moodle_url('/cohort/', array('contextid'=>$context->id)));
+
+if ($delete and $cohort->id) {
+ $PAGE->url->param('delete', 1);
+ if ($confirm and confirm_sesskey()) {
+ cohort_delete_cohort($cohort);
+ redirect($returnurl);
+ }
+ $strheading = get_string('delcohort', 'cohort');
+ $PAGE->navbar->add($strheading);
+ $PAGE->set_title($strheading);
+ echo $OUTPUT->header();
+ echo $OUTPUT->heading($strheading);
+ $yesurl = new moodle_url('/cohort/edit.php', array('id'=>$cohort->id, 'delete'=>1, 'confirm'=>1,'sesskey'=>sesskey()));
+ $message = get_string('delconfirm', 'cohort', format_string($cohort->name));
+ echo $OUTPUT->confirm($message, $yesurl, $returnurl);
+ echo $OUTPUT->footer();
+ die;
+}
+
+$editoroptions = array('maxfiles'=>0, 'context'=>$context);
+if ($cohort->id) {
+ // edit existing
+ $cohort = file_prepare_standard_editor($cohort, 'description', $editoroptions);
+ $strheading = get_string('editcohort', 'cohort');
+
+} else {
+ // add new
+ $cohort = file_prepare_standard_editor($cohort, 'description', $editoroptions);
+ $strheading = get_string('addcohort', 'cohort');
+}
+
+$PAGE->set_title($strheading);
+$PAGE->navbar->add($strheading);
+
+$editform = new cohort_edit_form(null, array('editoroptions'=>$editoroptions, 'data'=>$cohort));
+
+if ($editform->is_cancelled()) {
+ redirect($returnurl);
+
+} else if ($data = $editform->get_data()) {
+ $data = file_postupdate_standard_editor($data, 'description', $editoroptions, $context);
+
+ if ($data->id) {
+ cohort_update_cohort($data);
+ } else {
+ cohort_add_cohort($data);
+ }
+
+ // use new context id, it could have been changed
+ redirect(new moodle_url('/cohort/index.php', array('contextid'=>$data->contextid)));
+}
+
+echo $OUTPUT->header();
+echo $OUTPUT->heading($strheading);
+echo $editform->display();
+echo $OUTPUT->footer();
+
Index: lib/db/upgrade.php
===================================================================
--- lib/db/upgrade.php (revision fd1d5455fde49baa64a37126f25f3d3fd6b6f3f2)
+++ lib/db/upgrade.php (revision )
@@ -3517,6 +3517,61 @@
upgrade_main_savepoint($result, 2010041301);
}
+ if ($result && $oldversion < 2010041800) {
+ // Define table cohort to be created
+ $table = new xmldb_table('cohort');
+
+ // Adding fields to table cohort
+ $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
+ $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
+ $table->add_field('name', XMLDB_TYPE_CHAR, '254', null, XMLDB_NOTNULL, null, null);
+ $table->add_field('idnumber', XMLDB_TYPE_CHAR, '100', null, null, null, null);
+ $table->add_field('description', XMLDB_TYPE_TEXT, 'small', null, null, null, null);
+ $table->add_field('descriptionformat', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
+ $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, null, null, null);
+ $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
+ $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
+
+ // Adding keys to table cohort
+ $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+ $table->add_key('context', XMLDB_KEY_FOREIGN, array('contextid'), 'context', array('id'));
+
+ // Conditionally launch create table for cohort
+ if (!$dbman->table_exists($table)) {
+ $dbman->create_table($table);
+ }
+
+ upgrade_main_savepoint($result, 2010041800);
+ }
+
+ if ($result && $oldversion < 2010041801) {
+ // Define table cohort_members to be created
+ $table = new xmldb_table('cohort_members');
+
+ // Adding fields to table cohort_members
+ $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
+ $table->add_field('cohortid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
+ $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
+ $table->add_field('timeadded', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
+
+ // Adding keys to table cohort_members
+ $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+ $table->add_key('cohortid', XMLDB_KEY_FOREIGN, array('cohortid'), 'cohort', array('id'));
+ $table->add_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
+
+ // Adding indexes to table cohort_members
+ $table->add_index('cohortid-userid', XMLDB_INDEX_UNIQUE, array('cohortid', 'userid'));
+
+ // Conditionally launch create table for cohort_members
+ if (!$dbman->table_exists($table)) {
+ $dbman->create_table($table);
+ }
+
+ // Main savepoint reached
+ upgrade_main_savepoint($result, 2010041801);
+ }
+
+
return $result;
}
@@ -3524,4 +3579,4 @@
// 1/ remove the automatic enabling of completion lib if debug enabled ( in 2008121701 block)
// 2/ move 2009061300 block to the top of the file so that we may log upgrade queries
// 3/ remove 2010033101 block
-// 4/ remove 2010032400 block
\ No newline at end of file
+// 4/ remove 2010032400 block
Index: lib/moodlelib.php
===================================================================
--- lib/moodlelib.php (revision fd1d5455fde49baa64a37126f25f3d3fd6b6f3f2)
+++ lib/moodlelib.php (revision )
@@ -3422,6 +3422,9 @@
//move unread messages from this user to read
message_move_userfrom_unread2read($user->id);
+ // remove from all cohorts
+ $DB->delete_records('cohort_members', array('userid'=>$user->id));
+
// remove from all groups
$DB->delete_records('groups_members', array('userid'=>$user->id));
@@ -6837,6 +6840,7 @@
'blog' => 'blog',
'bulkusers' => NULL,
'calendar' => 'calendar',
+ 'cohort' => 'cohort',
'condition' => NULL,
'completion' => NULL,
'countries' => NULL,
Index: lang/en/cohort.php
===================================================================
--- lang/en/cohort.php (revision )
+++ lang/en/cohort.php (revision )
@@ -0,0 +1,52 @@
+.
+
+/**
+ * Strings for component 'cohort', language 'en', branch 'MOODLE_20_STABLE'
+ *
+ * @package moodlecore
+ * @subpackage cohort
+ * @copyright 2010 Petr Skoda (info@skodak.org)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$string['addcohort'] = 'Add new cohort';
+$string['anycohort'] = 'Any';
+$string['assign'] = 'Assign';
+$string['assignto'] = 'Cohort \'{$a}\' members';
+$string['backtocohorts'] = 'Back to cohorts';
+$string['cohort'] = 'Cohort';
+$string['cohorts'] = 'Cohorts';
+$string['cohortsin'] = '{$a}: available cohorts';
+$string['cohort:assign'] = 'Assign cohort members';
+$string['cohort:manage'] = 'Manager cohorts';
+$string['cohort:view'] = 'Use cohorts and view members';
+$string['component'] = 'Source';
+$string['currentusers'] = 'Current users';
+$string['currentusersmatching'] = 'Current users matching';
+$string['delcohort'] = 'Delete cohort';
+$string['delconfirm'] = 'Do you really want to delete cohort \'{$a}\'?';
+$string['description'] = 'Description';
+$string['duplicateidnumber'] = 'Cohort with the same ID number already exists';
+$string['editcohort'] = 'Edit cohort';
+$string['idnumber'] = 'Cohort ID';
+$string['memberscount'] = 'Cohort size';
+$string['name'] = 'Name';
+$string['nocomponent'] = 'Created manually';
+$string['potusers'] = 'Potential users';
+$string['potusersmatching'] = 'Potential matching users';
+$string['selectfromcohort'] = 'Select members from cohort';
Index: group/lib.php
===================================================================
--- group/lib.php (revision fd1d5455fde49baa64a37126f25f3d3fd6b6f3f2)
+++ group/lib.php (revision )
@@ -513,10 +513,11 @@
* Gets potential group members for grouping
* @param int $courseid The id of the course
* @param int $roleid The role to select users from
+ * @param int $cohortid restrict to cohort id
* @param string $orderby The colum to sort users by
* @return array An array of the users
*/
-function groups_get_potential_members($courseid, $roleid = null, $orderby = 'lastname ASC, firstname ASC') {
+function groups_get_potential_members($courseid, $roleid = null, $cohortid = null, $orderby = 'lastname ASC, firstname ASC') {
global $DB;
$context = get_context_instance(CONTEXT_COURSE, $courseid);
@@ -535,9 +536,17 @@
$where = "";
}
+ if ($cohortid) {
+ $cohortjoin = "JOIN {cohort_members} cm ON cm.userid = u.id
+ JOIN {cohort} c ON c.id = cm.cohortid";
+ } else {
+ $cohortjoin = "";
+ }
+
$sql = "SELECT u.id, u.username, u.firstname, u.lastname, u.idnumber
FROM {user} u
JOIN ($esql) e ON e.id = u.id
+ $cohortjoin
$where
ORDER BY $orderby";
Index: admin/settings/users.php
===================================================================
--- admin/settings/users.php (revision fd1d5455fde49baa64a37126f25f3d3fd6b6f3f2)
+++ admin/settings/users.php (revision )
@@ -12,7 +12,9 @@
or has_capability('moodle/user:update', $systemcontext)
or has_capability('moodle/user:delete', $systemcontext)
or has_capability('moodle/role:manage', $systemcontext)
- or has_capability('moodle/role:assign', $systemcontext)) { // speedup for non-admins, add all caps used on this page
+ or has_capability('moodle/role:assign', $systemcontext)
+ or has_capability('moodle/cohort:manage', $systemcontext)
+ or has_capability('moodle/cohort:view', $systemcontext)) { // speedup for non-admins, add all caps used on this page
$temp = new admin_settingpage('manageauths', get_string('authsettings', 'admin'));
@@ -75,6 +77,7 @@
$ADMIN->add('accounts', new admin_externalpage('uploadusers', get_string('uploadusers'), "$CFG->wwwroot/$CFG->admin/uploaduser.php", 'moodle/site:uploadusers'));
$ADMIN->add('accounts', new admin_externalpage('uploadpictures', get_string('uploadpictures','admin'), "$CFG->wwwroot/$CFG->admin/uploadpicture.php", 'moodle/site:uploadusers'));
$ADMIN->add('accounts', new admin_externalpage('profilefields', get_string('profilefields','admin'), "$CFG->wwwroot/user/profile/index.php", 'moodle/site:config'));
+ $ADMIN->add('accounts', new admin_externalpage('cohorts', get_string('cohorts', 'cohort'), $CFG->wwwroot . '/cohort/index.php', array('moodle/cohort:manage', 'moodle/cohort:view')));
// stuff under the "roles" subcategory
Index: version.php
===================================================================
--- version.php (revision fd1d5455fde49baa64a37126f25f3d3fd6b6f3f2)
+++ version.php (revision )
@@ -6,7 +6,7 @@
// This is compared against the values stored in the database to determine
// whether upgrades should be performed (see lib/db/*.php)
- $version = 2010041301; // YYYYMMDD = date of the last version bump
+ $version = 2010041801; // YYYYMMDD = date of the last version bump
// XX = daily increments
$release = '2.0 dev (Build: 20100421)'; // Human-friendly version name
Index: course/index.php
===================================================================
--- course/index.php (revision fd1d5455fde49baa64a37126f25f3d3fd6b6f3f2)
+++ course/index.php (revision )
@@ -295,6 +295,7 @@
$str->edit = get_string('editthiscategory');
$str->hide = get_string('hide');
$str->show = get_string('show');
+ $str->cohorts = get_string('cohorts', 'cohort');
$str->spacer = '
';
}
@@ -333,6 +334,11 @@
' src="'.$OUTPUT->pix_url('t/show') . '" class="iconsmall" alt="'.$str->show.'" /> ';
}
+ if (has_capability('moodle/cohort:manage', $category->context) or has_capability('moodle/cohort:view', $category->context)) {
+ echo '
';
+ }
+
if ($up) {
echo '
';
Index: cohort/lib.php
===================================================================
--- cohort/lib.php (revision )
+++ cohort/lib.php (revision )
@@ -0,0 +1,278 @@
+.
+
+/**
+ * Cohort related management functions, this file needs to be included manually.
+ *
+ * @package moodlecore
+ * @subpackage cohort
+ * @copyright 2010 Petr Skoda (info@skodak.org)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once($CFG->dirroot . '/user/selector/lib.php');
+
+/**
+ * Add new cohort.
+ * @param object $data
+ * @return void
+ */
+function cohort_add_cohort($data) {
+ global $DB;
+ $data->timecreated = time();
+ $data->timemodified = $data->timecreated;
+ $DB->insert_record('cohort', $data);
+}
+
+/**
+ * Update existing cohort.
+ * @param object $data
+ * @return void
+ */
+function cohort_update_cohort($data) {
+ global $DB;
+ $data->timemodified = time();
+ $DB->update_record('cohort', $data);
+}
+
+/**
+ * Delete cohort.
+ * @param object $cohort
+ * @return void
+ */
+function cohort_delete_cohort($cohort) {
+ global $DB;
+
+ if ($cohort->component) {
+ // TODO: add component delete callback
+ }
+
+ $DB->delete_records('cohort_members', array('cohortid'=>$cohort->id));
+ $DB->delete_records('cohort', array('id'=>$cohort->id));
+}
+
+/**
+ * Somehow deal with cohorts when deleting course category,
+ * we can not just delete them because they might be used in enrol
+ * plugins or referenced in external systems.
+ * @param object $category
+ * @return void
+ */
+function cohort_delete_category($category) {
+ global $DB;
+ // TODO: make sure that cohorts are really, really not used anywhere and delete, for now just move to parent or system context
+
+ $oldcontext = get_context_instance(CONTEXT_COURSECAT, $category->id, MUST_EXIST);
+
+ if ($category->parent and $parent = $DB->get_record('course_categories', array('id'=>$category->parent))) {
+ $parentcontext = get_context_instance(CONTEXT_COURSECAT, $parent->id, MUST_EXIST);
+ $sql = "UPDATE {cohort} SET contextid = :newcontext WHERE contextid = :oldcontext";
+ $params = array('oldcontext'=>$oldcontext->id, 'newcontext'=>$parentcontext->id);
+ } else {
+ $syscontext = get_context_instance(CONTEXT_SYSTEM);
+ $sql = "UPDATE {cohort} SET contextid = :newcontext WHERE contextid = :oldcontext";
+ $params = array('oldcontext'=>$oldcontext->id, 'newcontext'=>$syscontext->id);
+ }
+
+ $DB->execute($sql, $params);
+}
+
+/**
+ * Remove cohort member
+ * @param int $cohortid
+ * @param int $userid
+ * @return void
+ */
+function cohort_add_member($cohortid, $userid) {
+ global $DB;
+ $record = new object();
+ $record->cohortid = $cohortid;
+ $record->userid = $userid;
+ $record->timeadded = time();
+ $DB->insert_record('cohort_members', $record);
+}
+
+/**
+ * Add cohort member
+ * @param int $cohortid
+ * @param int $userid
+ * @return void
+ */
+function cohort_remove_member($cohortid, $userid) {
+ global $DB;
+ $DB->delete_records('cohort_members', array('cohortid'=>$cohortid, 'userid'=>$userid));
+}
+
+/**
+ * Returns list of visible cohorts in course.
+ *
+ * @param object $course
+ * @param bool $enrolled true means include only cohorts with enrolled users
+ * @return array
+ */
+function cohort_get_visible_list($course) {
+ global $DB, $USER;
+
+ $context = get_context_instance(CONTEXT_COURSE, $course->id, MUST_EXIST);
+ list($esql, $params) = get_enrolled_sql($context);
+ $parentsql = get_related_contexts_string($context);
+
+ $sql = "SELECT c.id, c.name, c.idnumber, COUNT(u.id) AS cnt
+ FROM {cohort} c
+ JOIN {cohort_members} cm ON cm.cohortid = c.id
+ JOIN ($esql) u ON u.id = cm.userid
+ WHERE c.contextid $parentsql
+ GROUP BY c.id, c.name, c.idnumber
+ HAVING COUNT(u.id) > 0
+ ORDER BY c.name, c.idnumber";
+ $params['ctx'] = $context->id;
+
+ $cohorts = $DB->get_records_sql($sql, $params);
+
+ foreach ($cohorts as $cid=>$cohort) {
+ $cohorts[$cid] = format_string($cohort->name);
+ if ($cohort->idnumber) {
+ $cohorts[$cid] .= ' (' . $cohort->cnt . ')';
+ }
+ }
+
+ return $cohorts;
+}
+
+/**
+ * Cohort assignment candidates
+ */
+class cohort_candidate_selector extends user_selector_base {
+ protected $cohortid;
+
+ public function __construct($name, $options) {
+ $this->cohortid = $options['cohortid'];
+ parent::__construct($name, $options);
+ }
+
+ /**
+ * Candidate users
+ * @param $search
+ * @return array
+ */
+ public function find_users($search) {
+ global $DB;
+ //by default wherecondition retrieves all users except the deleted, not confirmed and guest
+ list($wherecondition, $params) = $this->search_sql($search, 'u');
+ $params['cohortid'] = $this->cohortid;
+
+ $fields = 'SELECT ' . $this->required_fields_sql('u');
+ $countfields = 'SELECT COUNT(1)';
+
+ $sql = " FROM {user} u
+ LEFT JOIN {cohort_members} cm ON (cm.userid = u.id AND cm.cohortid = :cohortid)
+ WHERE cm.id IS NULL AND $wherecondition";
+
+ $order = ' ORDER BY u.lastname ASC, u.firstname ASC';
+
+ if (!$this->is_validating()) {
+ $potentialmemberscount = $DB->count_records_sql($countfields . $sql, $params);
+ if ($potentialmemberscount > 100) {
+ return $this->too_many_results($search, $potentialmemberscount);
+ }
+ }
+
+ $availableusers = $DB->get_records_sql($fields . $sql . $order, $params);
+
+ if (empty($availableusers)) {
+ return array();
+ }
+
+
+ if ($search) {
+ $groupname = get_string('potusersmatching', 'cohort', $search);
+ } else {
+ $groupname = get_string('potusers', 'cohort');
+ }
+
+ return array($groupname => $availableusers);
+ }
+
+ protected function get_options() {
+ $options = parent::get_options();
+ $options['cohortid'] = $this->cohortid;
+ $options['file'] = 'cohort/lib.php';
+ return $options;
+ }
+}
+
+/**
+ * Cohort assignment candidates
+ */
+class cohort_existing_selector extends user_selector_base {
+ protected $cohortid;
+
+ public function __construct($name, $options) {
+ $this->cohortid = $options['cohortid'];
+ parent::__construct($name, $options);
+ }
+
+ /**
+ * Candidate users
+ * @param $search
+ * @return array
+ */
+ public function find_users($search) {
+ global $DB;
+ //by default wherecondition retrieves all users except the deleted, not confirmed and guest
+ list($wherecondition, $params) = $this->search_sql($search, 'u');
+ $params['cohortid'] = $this->cohortid;
+
+ $fields = 'SELECT ' . $this->required_fields_sql('u');
+ $countfields = 'SELECT COUNT(1)';
+
+ $sql = " FROM {user} u
+ JOIN {cohort_members} cm ON (cm.userid = u.id AND cm.cohortid = :cohortid)
+ WHERE $wherecondition";
+
+ $order = ' ORDER BY u.lastname ASC, u.firstname ASC';
+
+ if (!$this->is_validating()) {
+ $potentialmemberscount = $DB->count_records_sql($countfields . $sql, $params);
+ if ($potentialmemberscount > 100) {
+ return $this->too_many_results($search, $potentialmemberscount);
+ }
+ }
+
+ $availableusers = $DB->get_records_sql($fields . $sql . $order, $params);
+
+ if (empty($availableusers)) {
+ return array();
+ }
+
+
+ if ($search) {
+ $groupname = get_string('currentusersmatching', 'cohort', $search);
+ } else {
+ $groupname = get_string('currentusers', 'cohort');
+ }
+
+ return array($groupname => $availableusers);
+ }
+
+ protected function get_options() {
+ $options = parent::get_options();
+ $options['cohortid'] = $this->cohortid;
+ $options['file'] = 'cohort/lib.php';
+ return $options;
+ }
+}
Index: course/lib.php
===================================================================
--- course/lib.php (revision fd1d5455fde49baa64a37126f25f3d3fd6b6f3f2)
+++ course/lib.php (revision )
@@ -3025,6 +3025,7 @@
global $CFG, $DB;
require_once($CFG->libdir.'/gradelib.php');
require_once($CFG->libdir.'/questionlib.php');
+ require_once($CFG->dirroot.'/cohort/lib.php');
if ($children = $DB->get_records('course_categories', array('parent'=>$category->id), 'sortorder ASC')) {
foreach ($children as $childcat) {
@@ -3042,6 +3043,9 @@
}
}
+ // move or delete cohorts in this context
+ cohort_delete_category($category);
+
// now delete anything that may depend on course category context
grade_course_category_delete($category->id, 0, $showfeedback);
if (!question_delete_course_category($category, 0, $showfeedback)) {
@@ -3067,6 +3071,7 @@
global $CFG, $DB, $OUTPUT;
require_once($CFG->libdir.'/gradelib.php');
require_once($CFG->libdir.'/questionlib.php');
+ require_once($CFG->dirroot.'/cohort/lib.php');
if (!$newparentcat = $DB->get_record('course_categories', array('id'=>$newparentid))) {
return false;
@@ -3086,6 +3091,9 @@
echo $OUTPUT->notification(get_string('coursesmovedout', '', format_string($category->name)), 'notifysuccess');
}
+ // move or delete cohorts in this context
+ cohort_delete_category($category);
+
// now delete anything that may depend on course category context
grade_course_category_delete($category->id, $newparentid, $showfeedback);
if (!question_delete_course_category($category, $newparentcat, $showfeedback)) {
Index: cohort/assign.php
===================================================================
--- cohort/assign.php (revision )
+++ cohort/assign.php (revision )
@@ -0,0 +1,130 @@
+.
+
+/**
+ * Cohort related management functions, this file needs to be included manually.
+ *
+ * @package moodlecore
+ * @subpackage cohort
+ * @copyright 2010 Petr Skoda (info@skodak.org)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once('../config.php');
+require_once($CFG->dirroot.'/cohort/lib.php');
+
+$id = required_param('id', PARAM_INT);
+
+require_login();
+
+$cohort = $DB->get_record('cohort', array('id'=>$id), '*', MUST_EXIST);
+$context = get_context_instance_by_id($cohort->contextid, MUST_EXIST);
+
+require_capability('moodle/cohort:assign', $context);
+
+$PAGE->set_url('/cohort/assign.php', array('id'=>$id));
+$PAGE->set_context($context);
+
+$returnurl = new moodle_url('/cohort/index.php', array('contextid'=>$cohort->contextid));
+
+if (!empty($cohort->component)) {
+ // we can not manually edit cohorts that were created by external systems, sorry
+ redirect($returnurl);
+}
+
+if (optional_param('cancel', false, PARAM_BOOL)) {
+ redirect($returnurl);
+}
+
+if ($context->contextlevel == CONTEXT_COURSECAT) {
+ $category = $DB->get_record('course_categories', array('id'=>$context->instanceid), '*', MUST_EXIST);
+ $PAGE->navbar->add($category->name, new moodle_url('/course/index.php', array('categoryedit'=>'1')));
+}
+$PAGE->navbar->add(get_string('cohorts', 'cohort'), new moodle_url('/cohort/', array('contextid'=>$context->id)));
+$PAGE->navbar->add(get_string('assign', 'cohort'));
+
+echo $OUTPUT->header();
+echo $OUTPUT->heading(get_string('assignto', 'cohort', format_string($cohort->name)));
+
+// Get the user_selector we will need.
+$potentialuserselector = new cohort_candidate_selector('addselect', array('cohortid'=>$cohort->id));
+$existinguserselector = new cohort_existing_selector('removeselect', array('cohortid'=>$cohort->id));
+
+// Process incoming user assignments to the cohort
+
+if (optional_param('add', false, PARAM_BOOL) && confirm_sesskey()) {
+ $userstoassign = $potentialuserselector->get_selected_users();
+ if (!empty($userstoassign)) {
+
+ foreach ($userstoassign as $adduser) {
+ // no duplicates please
+ if (!$DB->record_exists('cohort_members', array('cohortid'=>$cohort->id, 'userid'=>$adduser->id))) {
+ cohort_add_member($cohort->id, $adduser->id);
+ }
+ }
+
+ $potentialuserselector->invalidate_selected_users();
+ $existinguserselector->invalidate_selected_users();
+ }
+}
+
+// Process removing user assignments to the cohort
+if (optional_param('remove', false, PARAM_BOOL) && confirm_sesskey()) {
+ $userstoremove = $existinguserselector->get_selected_users();
+ if (!empty($userstoremove)) {
+ foreach ($userstoremove as $removeuser) {
+ cohort_remove_member($cohort->id, $removeuser->id);
+ }
+ $potentialuserselector->invalidate_selected_users();
+ $existinguserselector->invalidate_selected_users();
+ }
+}
+
+// Print the form.
+?>
+
+
+footer();
Index: cohort/edit_form.php
===================================================================
--- cohort/edit_form.php (revision )
+++ cohort/edit_form.php (revision )
@@ -0,0 +1,104 @@
+.
+
+/**
+ * Cohort related management functions, this file needs to be included manually.
+ *
+ * @package moodlecore
+ * @subpackage cohort
+ * @copyright 2010 Petr Skoda (info@skodak.org)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once($CFG->dirroot . '/lib/formslib.php');
+
+class cohort_edit_form extends moodleform {
+
+ /**
+ * Define the cohort edit form
+ */
+ public function definition() {
+
+ $mform = $this->_form;
+ $editoroptions = $this->_customdata['editoroptions'];
+ $cohort = $this->_customdata['data'];
+
+ $mform->addElement('text', 'name', get_string('name', 'cohort'), 'maxlength="254" size="50"');
+ $mform->addRule('name', get_string('required'), 'required', null, 'client');
+ $mform->setType('name', PARAM_MULTILANG);
+
+ $options = $this->get_category_options($cohort->contextid);
+ $mform->addElement('select', 'contextid', get_string('context', 'role'), $options);
+
+ $mform->addElement('text', 'idnumber', get_string('idnumber', 'cohort'), 'maxlength="254" size="50"');
+ $mform->setType('name', PARAM_RAW);
+
+ $mform->addElement('editor', 'description_editor', get_string('description', 'cohort'), null, $editoroptions);
+ $mform->setType('description_editor', PARAM_RAW);
+
+ $mform->addElement('hidden', 'id');
+ $mform->setType('id', PARAM_INT);
+
+ $this->add_action_buttons();
+
+ $this->set_data($cohort);
+ }
+
+ public function validation($data, $files) {
+ global $DB;
+
+ $errors = parent::validation($data, $files);
+
+ $idnumber = trim($data['idnumber']);
+ if ($data['id']) {
+ $current = $DB->get_record('cohort', array('id'=>$data['id']), '*', MUST_EXIST);
+ if ($current->idnumber !== $idnumber) {
+ if ($DB->record_exists('cohort', array('idnumber'=>$idnumber))) {
+ $errors['idnumber'] = get_string('duplicateidnumber', 'cohort');
+ }
+ }
+ } else {
+ if ($DB->record_exists('cohort', array('idnumber'=>$idnumber))) {
+ $errors['idnumber'] = get_string('duplicateidnumber', 'cohort');
+ }
+ }
+
+ return $errors;
+ }
+
+ protected function get_category_options($currentcontextid) {
+ $displaylist = array();
+ $parentlist = array();
+ make_categories_list($displaylist, $parentlist, 'moodle/cohort:manage');
+ $options = array();
+ $syscontext = get_context_instance(CONTEXT_SYSTEM);
+ if (has_capability('moodle/cohort:manage', $syscontext)) {
+ $options[$syscontext->id] = print_context_name($syscontext);
+ }
+ foreach ($displaylist as $cid=>$name) {
+ $context = get_context_instance(CONTEXT_COURSECAT, $cid, MUST_EXIST);
+ $options[$context->id] = $name;
+ }
+ // always add current - this is not likely, but if the logic get's changed it might be a problem
+ if (!isset($options[$currentcontextid])) {
+ $context = get_context_instance_by_id($currentcontextid, MUST_EXIST);
+ $options[$context->id] = print_context_name($syscontext);
+ }
+ return $options;
+ }
+}
+
\ No newline at end of file
Index: group/autogroup.php
===================================================================
--- group/autogroup.php (revision fd1d5455fde49baa64a37126f25f3d3fd6b6f3f2)
+++ group/autogroup.php (revision )
@@ -71,7 +71,7 @@
default:
print_error('unknoworder');
}
- $users = groups_get_potential_members($data->courseid, $data->roleid, $orderby);
+ $users = groups_get_potential_members($data->courseid, $data->roleid, $data->cohortid, $orderby);
$usercnt = count($users);
if ($data->allocateby == 'random') {
Index: group/autogroup_form.php
===================================================================
--- group/autogroup_form.php (revision fd1d5455fde49baa64a37126f25f3d3fd6b6f3f2)
+++ group/autogroup_form.php (revision )
@@ -1,6 +1,7 @@
dirroot.'/lib/formslib.php');
+require_once($CFG->dirroot.'/cohort/lib.php');
/// get url variables
class autogroup_form extends moodleform {
@@ -22,6 +23,24 @@
$mform->setDefault('roleid', $CFG->defaultcourseroleid);
}
+ $context = get_context_instance(CONTEXT_COURSE, $COURSE->id);
+ if (has_capability('moodle/cohort:view', $context)) {
+ $options = cohort_get_visible_list($COURSE);
+ if ($options) {
+ $options = array(0=>get_string('anycohort', 'cohort')) + $options;
+ $mform->addElement('select', 'cohortid', get_string('selectfromcohort', 'cohort'), $options);
+ $mform->setDefault('cohortid', '0');
+ } else {
+ $mform->addElement('hidden','cohortid');
+ $mform->setType('cohortid', PARAM_INT);
+ $mform->setConstant('cohortid', '0');
+ }
+ } else {
+ $mform->addElement('hidden','cohortid');
+ $mform->setType('cohortid', PARAM_INT);
+ $mform->setConstant('cohortid', '0');
+ }
+
$options = array('groups' => get_string('numgroups', 'group'),
'members' => get_string('nummembers', 'group'));
$mform->addElement('select', 'groupby', get_string('groupby', 'group'), $options);
@@ -91,7 +110,7 @@
$errors = parent::validation($data, $files);
if ($data['allocateby'] != 'no') {
- if (!$users = groups_get_potential_members($data['courseid'], $data['roleid'])) {
+ if (!$users = groups_get_potential_members($data['courseid'], $data['roleid'], $data['cohortid'])) {
$errors['roleid'] = get_string('nousersinrole', 'group');
}
Index: lib/db/access.php
===================================================================
--- lib/db/access.php (revision fd1d5455fde49baa64a37126f25f3d3fd6b6f3f2)
+++ lib/db/access.php (revision )
@@ -470,6 +470,39 @@
'clonepermissionsfrom' => 'moodle/category:visibility'
),
+ // create, delete, move cohorts in system and course categories,
+ // (cohorts with component !== null can be only moved)
+ 'moodle/cohort:manage' => array(
+
+ 'captype' => 'write',
+ 'contextlevel' => CONTEXT_COURSECAT,
+ 'legacy' => array(
+ 'manager' => CAP_ALLOW
+ )
+ ),
+
+ // add and remove cohort members (only for cohorts where component !== null)
+ 'moodle/cohort:assign' => array(
+
+ 'captype' => 'write',
+ 'contextlevel' => CONTEXT_COURSECAT,
+ 'legacy' => array(
+ 'manager' => CAP_ALLOW
+ )
+ ),
+
+ // view members of a cohort, this can be used in course context too,
+ // this also controls the ability to actually use cohort
+ 'moodle/cohort:view' => array(
+
+ 'captype' => 'read',
+ 'contextlevel' => CONTEXT_COURSE,
+ 'legacy' => array(
+ 'editingteacher' => CAP_ALLOW,
+ 'manager' => CAP_ALLOW
+ )
+ ),
+
'moodle/course:create' => array(
'riskbitmask' => RISK_XSS,
Index: lib/db/install.xml
===================================================================
--- lib/db/install.xml (revision fd1d5455fde49baa64a37126f25f3d3fd6b6f3f2)
+++ lib/db/install.xml (revision )
@@ -1,5 +1,5 @@
-
@@ -1879,7 +1879,7 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+