1
0
mirror of https://github.com/moodle/moodle.git synced 2025-05-13 03:36:09 +02:00

MDL-36014 cohorts: Allow teachers to view cohorts

Added property 'visible' for cohorts. Unsetting it hides the cohort from users in the course.

AMOS BEGIN
 CPY [visible,core_moodle],[visible,core_cohort]
AMOS END
This commit is contained in:
Marina Glancy 2014-07-29 17:44:25 +08:00
parent 78fb7110e0
commit 80f98467f8
22 changed files with 667 additions and 218 deletions

@ -30,6 +30,8 @@ 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);
$show = optional_param('show', 0, PARAM_BOOL);
$hide = optional_param('hide', 0, PARAM_BOOL);
$confirm = optional_param('confirm', 0, PARAM_BOOL);
$returnurl = optional_param('returnurl', '', PARAM_LOCALURL);
@ -98,6 +100,22 @@ if ($delete and $cohort->id) {
die;
}
if ($show && $cohort->id && confirm_sesskey()) {
if (!$cohort->visible) {
$record = (object)array('id' => $cohort->id, 'visible' => 1, 'contextid' => $cohort->contextid);
cohort_update_cohort($record);
}
redirect($returnurl);
}
if ($hide && $cohort->id && confirm_sesskey()) {
if ($cohort->visible) {
$record = (object)array('id' => $cohort->id, 'visible' => 0, 'contextid' => $cohort->contextid);
cohort_update_cohort($record);
}
redirect($returnurl);
}
$editoroptions = array('maxfiles'=>0, 'context'=>$context);
if ($cohort->id) {
// Edit existing.

@ -47,6 +47,10 @@ class cohort_edit_form extends moodleform {
$mform->addElement('text', 'idnumber', get_string('idnumber', 'cohort'), 'maxlength="254" size="50"');
$mform->setType('idnumber', PARAM_RAW); // Idnumbers are plain text, must not be changed.
$mform->addElement('advcheckbox', 'visible', get_string('visible', 'cohort'));
$mform->setDefault('visible', 1);
$mform->addHelpButton('visible', 'visible', 'cohort');
$mform->addElement('editor', 'description_editor', get_string('description', 'cohort'), null, $editoroptions);
$mform->setType('description_editor', PARAM_RAW);

@ -51,6 +51,7 @@ class core_cohort_external extends external_api {
'idnumber' => new external_value(PARAM_RAW, 'cohort idnumber'),
'description' => new external_value(PARAM_RAW, 'cohort description', VALUE_OPTIONAL),
'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
'visible' => new external_value(PARAM_BOOL, 'cohort visible', VALUE_OPTIONAL, true),
)
)
)
@ -133,6 +134,7 @@ class core_cohort_external extends external_api {
'idnumber' => new external_value(PARAM_RAW, 'cohort idnumber'),
'description' => new external_value(PARAM_RAW, 'cohort description'),
'descriptionformat' => new external_format_value('description'),
'visible' => new external_value(PARAM_BOOL, 'cohort visible'),
)
)
);
@ -263,6 +265,7 @@ class core_cohort_external extends external_api {
'idnumber' => new external_value(PARAM_RAW, 'cohort idnumber'),
'description' => new external_value(PARAM_RAW, 'cohort description'),
'descriptionformat' => new external_format_value('description'),
'visible' => new external_value(PARAM_BOOL, 'cohort visible'),
)
)
);
@ -293,6 +296,7 @@ class core_cohort_external extends external_api {
'idnumber' => new external_value(PARAM_RAW, 'cohort idnumber'),
'description' => new external_value(PARAM_RAW, 'cohort description', VALUE_OPTIONAL),
'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
'visible' => new external_value(PARAM_BOOL, 'cohort visible', VALUE_OPTIONAL),
)
)
)

@ -147,20 +147,36 @@ foreach($cohorts['cohorts'] as $cohort) {
$cohortcanassign = has_capability('moodle/cohort:assign', $cohortcontext);
$urlparams = array('id' => $cohort->id, 'returnurl' => $baseurl->out_as_local_url());
$showhideurl = new moodle_url('/cohort/edit.php', $urlparams + array('sesskey' => sesskey()));
if ($cohort->visible) {
$showhideurl->param('hide', 1);
$visibleimg = html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/hide'), 'alt' => get_string('hide'), 'class' => 'iconsmall'));
$buttons[] = html_writer::link($showhideurl, $visibleimg, array('title' => get_string('hide')));
} else {
$showhideurl->param('show', 1);
$visibleimg = html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/show'), 'alt' => get_string('show'), 'class' => 'iconsmall'));
$buttons[] = html_writer::link($showhideurl, $visibleimg, array('title' => get_string('show')));
}
if ($cohortmanager) {
$buttons[] = html_writer::link(new moodle_url('/cohort/edit.php', $urlparams + array('delete' => 1)),
html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/delete'), 'alt' => get_string('delete'), 'class' => 'iconsmall')));
html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/delete'), 'alt' => get_string('delete'), 'class' => 'iconsmall')),
array('title' => get_string('delete')));
$buttons[] = html_writer::link(new moodle_url('/cohort/edit.php', $urlparams),
html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/edit'), 'alt' => get_string('edit'), 'class' => 'iconsmall')));
html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/edit'), 'alt' => get_string('edit'), 'class' => 'iconsmall')),
array('title' => get_string('edit')));
}
if ($cohortcanassign) {
$buttons[] = html_writer::link(new moodle_url('/cohort/assign.php', $urlparams),
html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('i/users'), 'alt' => get_string('assign', 'core_cohort'), 'class' => 'iconsmall')));
html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('i/users'), 'alt' => get_string('assign', 'core_cohort'), 'class' => 'iconsmall')),
array('title' => get_string('assign', 'core_cohort')));
}
}
$line[] = implode(' ', $buttons);
$data[] = $line;
$data[] = $row = new html_table_row($line);
if (!$cohort->visible) {
$row->attributes['class'] = 'dimmed_text';
}
}
$table = new html_table();
$table->head = array(get_string('name', 'cohort'), get_string('idnumber', 'cohort'), get_string('description', 'cohort'),

@ -24,6 +24,13 @@
defined('MOODLE_INTERNAL') || die();
define('COHORT_ALL', 0);
define('COHORT_COUNT_MEMBERS', 1);
define('COHORT_COUNT_ENROLLED_MEMBERS', 3);
define('COHORT_WITH_MEMBERS_ONLY', 5);
define('COHORT_WITH_ENROLLED_MEMBERS_ONLY', 17);
define('COHORT_WITH_NOTENROLLED_MEMBERS_ONLY', 23);
/**
* Add new cohort.
*
@ -45,6 +52,9 @@ function cohort_add_cohort($cohort) {
if (!isset($cohort->descriptionformat)) {
$cohort->descriptionformat = FORMAT_HTML;
}
if (!isset($cohort->visible)) {
$cohort->visible = 1;
}
if (empty($cohort->component)) {
$cohort->component = '';
}
@ -200,76 +210,143 @@ function cohort_is_member($cohortid, $userid) {
}
/**
* Returns list of cohorts from course parent contexts.
* Returns the list of cohorts visible to the current user in the given course.
*
* Note: this function does not implement any capability checks,
* it means it may disclose existence of cohorts,
* make sure it is displayed to users with appropriate rights only.
* The following fields are returned in each record: id, name, contextid, idnumber, visible
* Fields memberscnt and enrolledcnt will be also returned if requested
*
* @param stdClass $course
* @param bool $onlyenrolled true means include only cohorts with enrolled users
* @return array of cohort names with number of enrolled users
* @param context $currentcontext
* @param int $withmembers one of the COHORT_XXX constants that allows to return non empty cohorts only
* or cohorts with enroled/not enroled users, or just return members count
* @param int $offset
* @param int $limit
* @param string $search
* @return array
*/
function cohort_get_visible_list($course, $onlyenrolled=true) {
function cohort_get_available_cohorts($currentcontext, $withmembers = 0, $offset = 0, $limit = 25, $search = '') {
global $DB;
$context = context_course::instance($course->id);
list($esql, $params) = get_enrolled_sql($context);
list($parentsql, $params2) = $DB->get_in_or_equal($context->get_parent_context_ids(), SQL_PARAMS_NAMED);
$params = array_merge($params, $params2);
$params = array();
if ($onlyenrolled) {
$left = "";
$having = "HAVING COUNT(u.id) > 0";
} else {
$left = "LEFT";
$having = "";
// Build context subquery. Find the list of parent context where user is able to see any or visible-only cohorts.
// Since this method is normally called for the current course all parent contexts are already preloaded.
$contextsany = array_filter($currentcontext->get_parent_context_ids(),
create_function('$a', 'return has_capability("moodle/cohort:view", context::instance_by_id($a));'));
$contextsvisible = array_diff($currentcontext->get_parent_context_ids(), $contextsany);
if (empty($contextsany) && empty($contextsvisible)) {
// User does not have any permissions to view cohorts.
return array();
}
$subqueries = array();
if (!empty($contextsany)) {
list($parentsql, $params1) = $DB->get_in_or_equal($contextsany, SQL_PARAMS_NAMED, 'ctxa');
$subqueries[] = 'c.contextid ' . $parentsql;
$params = array_merge($params, $params1);
}
if (!empty($contextsvisible)) {
list($parentsql, $params1) = $DB->get_in_or_equal($contextsvisible, SQL_PARAMS_NAMED, 'ctxv');
$subqueries[] = '(c.visible = 1 AND c.contextid ' . $parentsql. ')';
$params = array_merge($params, $params1);
}
$wheresql = '(' . implode(' OR ', $subqueries) . ')';
$sql = "SELECT c.id, c.name, c.contextid, c.idnumber, COUNT(u.id) AS cnt
FROM {cohort} c
$left JOIN ({cohort_members} cm
JOIN ($esql) u ON u.id = cm.userid) ON cm.cohortid = c.id
WHERE c.contextid $parentsql
GROUP BY c.id, c.name, c.contextid, c.idnumber
$having
ORDER BY c.name, c.idnumber";
$cohorts = $DB->get_records_sql($sql, $params);
foreach ($cohorts as $cid=>$cohort) {
$cohorts[$cid] = format_string($cohort->name, true, array('context'=>$cohort->contextid));
if ($cohort->cnt) {
$cohorts[$cid] .= ' (' . $cohort->cnt . ')';
// Build the rest of the query.
$fromsql = "";
$fieldssql = 'c.id, c.name, c.contextid, c.idnumber, c.visible';
$groupbysql = '';
$havingsql = '';
if ($withmembers) {
$groupbysql = " GROUP BY $fieldssql";
$fromsql = " LEFT JOIN {cohort_members} cm ON cm.cohortid = c.id ";
$fieldssql .= ', COUNT(DISTINCT cm.userid) AS memberscnt';
if (in_array($withmembers,
array(COHORT_COUNT_ENROLLED_MEMBERS, COHORT_WITH_ENROLLED_MEMBERS_ONLY, COHORT_WITH_NOTENROLLED_MEMBERS_ONLY))) {
list($esql, $params2) = get_enrolled_sql($currentcontext);
$fromsql .= " LEFT JOIN ($esql) u ON u.id = cm.userid ";
$params = array_merge($params2, $params);
$fieldssql .= ', COUNT(DISTINCT u.id) AS enrolledcnt';
}
if ($withmembers == COHORT_WITH_MEMBERS_ONLY) {
$havingsql = " HAVING COUNT(DISTINCT cm.userid) > 0";
} else if ($withmembers == COHORT_WITH_ENROLLED_MEMBERS_ONLY) {
$havingsql = " HAVING COUNT(DISTINCT u.id) > 0";
} else if ($withmembers == COHORT_WITH_NOTENROLLED_MEMBERS_ONLY) {
$havingsql = " HAVING COUNT(DISTINCT cm.userid) > COUNT(DISTINCT u.id)";
}
}
if ($search) {
list($searchsql, $searchparams) = cohort_get_search_query($search);
$wheresql .= ' AND ' . $searchsql;
$params = array_merge($params, $searchparams);
}
return $cohorts;
$sql = "SELECT $fieldssql
FROM {cohort} c
$fromsql
WHERE $wheresql
$groupbysql
$havingsql
ORDER BY c.name, c.idnumber";
return $DB->get_records_sql($sql, $params, $offset, $limit);
}
/**
* Check if cohort exists and user is allowed to access it from the given context.
*
* @param stdClass|int $cohortorid cohort object or id
* @param context $currentcontext current context (course) where visibility is checked
* @return boolean
*/
function cohort_can_view_cohort($cohortorid, $currentcontext) {
global $DB;
if (is_numeric($cohortorid)) {
$cohort = $DB->get_record('cohort', array('id' => $cohortorid), 'id, contextid, visible');
} else {
$cohort = $cohortorid;
}
if ($cohort && in_array($cohort->contextid, $currentcontext->get_parent_context_ids())) {
if ($cohort->visible) {
return true;
}
$cohortcontext = context::instance_by_id($cohort->contextid);
if (has_capability('moodle/cohort:view', $cohortcontext)) {
return true;
}
}
return false;
}
/**
* Produces a part of SQL query to filter cohorts by the search string
*
* Called from {@link cohort_get_cohorts()} and {@link cohort_get_all_cohorts()}
* Called from {@link cohort_get_cohorts()}, {@link cohort_get_all_cohorts()} and {@link cohort_get_available_cohorts()}
*
* @access private
*
* @param string $search
* @return array of two elements - SQL condition and array of unnamed parameters
* @param string $search search string
* @param string $tablealias alias of cohort table in the SQL query (highly recommended if other tables are used in query)
* @return array of two elements - SQL condition and array of named parameters
*/
function cohort_get_search_query($search) {
function cohort_get_search_query($search, $tablealias = '') {
global $DB;
$params = array();
if (empty($search)) {
// This function should not be called if there is no search string, just in case return dummy query.
return array('1=1', $params);
}
if ($tablealias && substr($tablealias, -1) !== '.') {
$tablealias .= '.';
}
$searchparam = '%' . $DB->sql_like_escape($search) . '%';
$conditions = array();
$fields = array('name', 'idnumber', 'description');
$cnt = 0;
foreach ($fields as $field) {
$conditions[] = $DB->sql_like($field, "?", false);
$params[] = $searchparam;
$conditions[] = $DB->sql_like($tablealias . $field, ':csearch' . $cnt, false);
$params['csearch' . $cnt] = $searchparam;
$cnt++;
}
$sql = '(' . implode(' OR ', $conditions) . ')';
return array($sql, $params);
@ -293,8 +370,8 @@ function cohort_get_cohorts($contextid, $page = 0, $perpage = 25, $search = '')
$fields = "SELECT *";
$countfields = "SELECT COUNT(1)";
$sql = " FROM {cohort}
WHERE contextid = ?";
$params = array($contextid);
WHERE contextid = :contextid";
$params = array('contextid' => $contextid);
$order = " ORDER BY name ASC, idnumber ASC";
if (!empty($search)) {
@ -335,7 +412,7 @@ function cohort_get_all_cohorts($page = 0, $perpage = 25, $search = '') {
$wheresql = '';
if ($excludedcontexts = cohort_get_invisible_contexts()) {
list($excludedsql, $excludedparams) = $DB->get_in_or_equal($excludedcontexts, SQL_PARAMS_QM, null, false);
list($excludedsql, $excludedparams) = $DB->get_in_or_equal($excludedcontexts, SQL_PARAMS_NAMED, 'excl', false);
$wheresql = ' WHERE c.contextid '.$excludedsql;
$params = array_merge($params, $excludedparams);
}
@ -343,7 +420,7 @@ function cohort_get_all_cohorts($page = 0, $perpage = 25, $search = '') {
$totalcohorts = $allcohorts = $DB->count_records_sql($countfields . $sql . $wheresql, $params);
if (!empty($search)) {
list($searchcondition, $searchparams) = cohort_get_search_query($search);
list($searchcondition, $searchparams) = cohort_get_search_query($search, 'c');
$wheresql .= ($wheresql ? ' AND ' : ' WHERE ') . $searchcondition;
$params = array_merge($params, $searchparams);
$totalcohorts = $DB->count_records_sql($countfields . $sql . $wheresql, $params);
@ -429,4 +506,4 @@ function cohort_edit_controls(context $context, moodle_url $currenturl) {
return new tabtree($tabs, $currenttab);
}
return null;
}
}

@ -0,0 +1,127 @@
@core @core_cohort @enrol_cohort
Feature: Access visible and hidden cohorts
In order to enrol users from cohorts
As an manager or teacher
I need to be able to view the list of cohorts defined above the course
Background:
Given the following "categories" exist:
| name | category | idnumber |
| Cat 1 | 0 | CAT1 |
| Cat 2 | 0 | CAT2 |
And the following "cohorts" exist:
| name | idnumber | visible |
| System cohort | CV0 | 1 |
| System hidden cohort | CH0 | 0 |
| System empty cohort | CVE0 | 1 |
And the following "cohorts" exist:
| name | idnumber | contextlevel | reference | visible |
| Cohort in category 1 | CV1 | Category | CAT1 | 1 |
| Cohort in category 2 | CV2 | Category | CAT2 | 1 |
| Cohort hidden in category 1 | CH1 | Category | CAT1 | 0 |
| Cohort empty in category 1 | CVE1 | Category | CAT1 | 1 |
Given the following "users" exist:
| username | firstname | lastname | email |
| user1 | First | User | first@user.com |
| user2 | Second | User | second@user.com |
| student | Sam | User | student@user.com |
| teacher | Terry | User | teacher@user.com |
And the following "cohort members" exist:
| user | cohort |
| student | CV0 |
| student | CV1 |
| student | CV2 |
| student | CH0 |
| student | CH1 |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| user1 | manager | System | |
| user2 | manager | Category | CAT1 |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | CAT1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher | C1 | editingteacher |
@javascript
Scenario: Teacher can see visible cohorts defined in the above contexts
When I log in as "teacher"
And I follow "Course 1"
And I navigate to "Enrolment methods" node in "Course administration > Users"
And I set the field "Add method" to "Cohort sync"
Then the "Cohort" select box should contain "Cohort in category 1"
And the "Cohort" select box should contain "System cohort"
And the "Cohort" select box should not contain "Cohort hidden in category 1"
And the "Cohort" select box should not contain "System hidden cohort"
And the "Cohort" select box should not contain "Cohort in category 2"
And the "Cohort" select box should contain "Cohort empty in category 1"
And the "Cohort" select box should contain "System empty cohort"
And I set the field "Cohort" to "System cohort"
And I press "Add method"
And I navigate to "Enrolled users" node in "Course administration > Users"
And I should see "student@user.com"
And I navigate to "Groups" node in "Course administration > Users"
And I press "Auto-create groups"
And the "Select members from cohort" select box should contain "Cohort in category 1"
And the "Select members from cohort" select box should contain "System cohort"
And the "Select members from cohort" select box should not contain "Cohort hidden in category 1"
And the "Select members from cohort" select box should not contain "System hidden cohort"
And the "Select members from cohort" select box should not contain "Cohort in category 2"
And the "Select members from cohort" select box should not contain "Cohort empty in category 1"
And the "Select members from cohort" select box should not contain "System empty cohort"
@javascript
Scenario: System manager can see all cohorts defined in the above contexts
When I log in as "user1"
And I follow "Course 1"
And I navigate to "Enrolment methods" node in "Course administration > Users"
And I set the field "Add method" to "Cohort sync"
Then the "Cohort" select box should contain "Cohort in category 1"
And the "Cohort" select box should contain "System cohort"
And the "Cohort" select box should contain "Cohort hidden in category 1"
And the "Cohort" select box should contain "System hidden cohort"
And the "Cohort" select box should not contain "Cohort in category 2"
And the "Cohort" select box should contain "Cohort empty in category 1"
And the "Cohort" select box should contain "System empty cohort"
And I set the field "Cohort" to "System cohort"
And I press "Add method"
And I navigate to "Enrolled users" node in "Course administration > Users"
And I should see "student@user.com"
And I navigate to "Groups" node in "Course administration > Users"
And I press "Auto-create groups"
And the "Select members from cohort" select box should contain "Cohort in category 1"
And the "Select members from cohort" select box should contain "System cohort"
And the "Select members from cohort" select box should contain "Cohort hidden in category 1"
And the "Select members from cohort" select box should contain "System hidden cohort"
And the "Select members from cohort" select box should not contain "Cohort in category 2"
And the "Select members from cohort" select box should not contain "Cohort empty in category 1"
And the "Select members from cohort" select box should not contain "System empty cohort"
@javascript
Scenario: Category manager can see all cohorts defined in his category and visible cohorts defined above
When I log in as "user2"
And I follow "Course 1"
And I navigate to "Enrolment methods" node in "Course administration > Users"
And I set the field "Add method" to "Cohort sync"
Then the "Cohort" select box should contain "Cohort in category 1"
And the "Cohort" select box should contain "System cohort"
And the "Cohort" select box should contain "Cohort hidden in category 1"
And the "Cohort" select box should not contain "System hidden cohort"
And the "Cohort" select box should not contain "Cohort in category 2"
And the "Cohort" select box should contain "Cohort empty in category 1"
And the "Cohort" select box should contain "System empty cohort"
And I set the field "Cohort" to "System cohort"
And I press "Add method"
And I navigate to "Enrolled users" node in "Course administration > Users"
And I should see "student@user.com"
And I navigate to "Groups" node in "Course administration > Users"
And I press "Auto-create groups"
And the "Select members from cohort" select box should contain "Cohort in category 1"
And the "Select members from cohort" select box should contain "System cohort"
And the "Select members from cohort" select box should contain "Cohort hidden in category 1"
And the "Select members from cohort" select box should not contain "System hidden cohort"
And the "Select members from cohort" select box should not contain "Cohort in category 2"
And the "Select members from cohort" select box should not contain "Cohort empty in category 1"
And the "Select members from cohort" select box should not contain "System empty cohort"

@ -380,7 +380,13 @@ class core_cohort_cohortlib_testcase extends advanced_testcase {
cohort_add_member($cohort1->id, $user3->id);
cohort_add_member($cohort2->id, $user2->id);
// Cohort1 (Cat1) has 2 users total, 2 user enrolled in course1, 0 users enrolled in course2.
// Cohort2 (Cat2) has 1 users total, 0 user enrolled in course1, 1 users enrolled in course2.
// Cohort3 (Syst) has 1 users total, 1 user enrolled in course1, 0 users enrolled in course2.
// Cohort4 (Syst) has 0 users total.
$list = cohort_get_visible_list($course1);
$this->assertDebuggingCalled();
$this->assertEquals(2, count($list));
$this->assertNotEmpty($list[$cohort1->id]);
$this->assertRegExp('/\(2\)$/', $list[$cohort1->id]);
@ -388,6 +394,7 @@ class core_cohort_cohortlib_testcase extends advanced_testcase {
$this->assertRegExp('/\(1\)$/', $list[$cohort3->id]);
$list = cohort_get_visible_list($course1, false);
$this->assertDebuggingCalled();
$this->assertEquals(3, count($list));
$this->assertNotEmpty($list[$cohort1->id]);
$this->assertRegExp('/\(2\)$/', $list[$cohort1->id]);
@ -397,11 +404,13 @@ class core_cohort_cohortlib_testcase extends advanced_testcase {
$this->assertRegExp('/[^\)]$/', $list[$cohort4->id]);
$list = cohort_get_visible_list($course2);
$this->assertDebuggingCalled();
$this->assertEquals(1, count($list));
$this->assertNotEmpty($list[$cohort2->id]);
$this->assertRegExp('/\(1\)$/', $list[$cohort2->id]);
$list = cohort_get_visible_list($course2, false);
$this->assertDebuggingCalled();
$this->assertEquals(3, count($list));
$this->assertNotEmpty($list[$cohort2->id]);
$this->assertRegExp('/\(1\)$/', $list[$cohort2->id]);
@ -411,9 +420,11 @@ class core_cohort_cohortlib_testcase extends advanced_testcase {
$this->assertRegExp('/[^\)]$/', $list[$cohort4->id]);
$list = cohort_get_visible_list($course3);
$this->assertDebuggingCalled();
$this->assertEquals(0, count($list));
$list = cohort_get_visible_list($course3, false);
$this->assertDebuggingCalled();
$this->assertEquals(2, count($list));
$this->assertNotEmpty($list[$cohort3->id]);
$this->assertRegExp('/[^\)]$/', $list[$cohort3->id]);
@ -543,4 +554,187 @@ class core_cohort_cohortlib_testcase extends advanced_testcase {
$this->assertEquals(array($cohort2->id=>$cohort2), $result['cohorts']);
$this->assertEquals(2, $result['allcohorts']);
}
public function test_cohort_get_available_cohorts() {
global $DB;
$this->resetAfterTest();
$category1 = $this->getDataGenerator()->create_category();
$category2 = $this->getDataGenerator()->create_category();
$course1 = $this->getDataGenerator()->create_course(array('category' => $category1->id));
$course2 = $this->getDataGenerator()->create_course(array('category' => $category2->id));
$category1ctx = context_coursecat::instance($category1->id);
$category2ctx = context_coursecat::instance($category2->id);
$course1ctx = context_course::instance(($course1->id));
$course2ctx = context_course::instance(($course2->id));
$systemctx = context_system::instance();
$cohort1 = $this->getDataGenerator()->create_cohort(array('contextid'=>$category1ctx->id, 'name'=>'aaagrrryyy', 'idnumber'=>'','description'=>''));
$cohort2 = $this->getDataGenerator()->create_cohort(array('contextid'=>$category1ctx->id, 'name'=>'bbb', 'idnumber'=>'', 'description'=>'yyybrrr', 'visible'=>0));
$cohort3 = $this->getDataGenerator()->create_cohort(array('contextid'=>$category2ctx->id, 'name'=>'ccc', 'idnumber'=>'xxarrrghyyy', 'description'=>'po_us'));
$cohort4 = $this->getDataGenerator()->create_cohort(array('contextid'=>$systemctx->id));
$cohort5 = $this->getDataGenerator()->create_cohort(array('contextid'=>$systemctx->id, 'visible'=>0));
/*
Structure of generated course categories, courses and cohort:
system
-cohort4 (visible, has 3 members)
-cohort5 (not visible, no members)
category1
-cohort1 (visible, no members)
-cohort2 (not visible, has 1 member)
course1
category2
-cohort3 (visible, has 2 member)
course2
In this test we call cohort_get_available_cohorts() for users with different roles
and with different paramteres ($withmembers, $search, $offset, $limit) to make sure we go
through all possible options of SQL query.
*/
// Admin can see visible and invisible cohorts defined in above contexts.
$this->setAdminUser();
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 0, 0, '');
$this->assertEquals(array($cohort1->id, $cohort2->id, $cohort4->id, $cohort5->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 0, 2, '');
$this->assertEquals(array($cohort1->id, $cohort2->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 1, 2, '');
$this->assertEquals(array($cohort2->id, $cohort4->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 0, 100, 'yyy');
$this->assertEquals(array($cohort1->id, $cohort2->id), array_keys($result));
$result = cohort_get_available_cohorts($course2ctx, COHORT_ALL, 0, 0, '');
$this->assertEquals(array($cohort3->id, $cohort4->id, $cohort5->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_MEMBERS_ONLY);
$this->assertEmpty($result);
$result = cohort_get_available_cohorts($course2ctx, COHORT_WITH_MEMBERS_ONLY);
$this->assertEmpty($result);
// Get list of available cohorts as a teacher in the course.
$user1 = $this->getDataGenerator()->create_user();
$teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
role_assign($teacherrole->id, $user1->id, $course1ctx->id);
role_assign($teacherrole->id, $user1->id, $course2ctx->id);
$this->setUser($user1);
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 0, 0, '');
$this->assertEquals(array($cohort1->id, $cohort4->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 0, 1, '');
$this->assertEquals(array($cohort1->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 1, 1, '');
$this->assertEquals(array($cohort4->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 0, 100, 'yyy');
$this->assertEquals(array($cohort1->id), array_keys($result));
$result = cohort_get_available_cohorts($course2ctx, COHORT_ALL, 0, 0, '');
$this->assertEquals(array($cohort3->id, $cohort4->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_MEMBERS_ONLY);
$this->assertEmpty($result);
// Now add members to cohorts.
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$user4 = $this->getDataGenerator()->create_user();
$user5 = $this->getDataGenerator()->create_user();
$user6 = $this->getDataGenerator()->create_user();
cohort_add_member($cohort2->id, $user3->id);
cohort_add_member($cohort3->id, $user2->id);
cohort_add_member($cohort3->id, $user3->id);
cohort_add_member($cohort4->id, $user4->id);
cohort_add_member($cohort4->id, $user5->id);
cohort_add_member($cohort4->id, $user6->id);
// Check filtering non-empty cohorts as admin.
$this->setAdminUser();
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_MEMBERS_ONLY, 0, 0, '');
$this->assertEquals(array($cohort2->id, $cohort4->id), array_keys($result));
$this->assertEquals(1, $result[$cohort2->id]->memberscnt);
$this->assertEquals(3, $result[$cohort4->id]->memberscnt);
$result = cohort_get_available_cohorts($course2ctx, COHORT_WITH_MEMBERS_ONLY, 0, 0, '');
$this->assertEquals(array($cohort3->id, $cohort4->id), array_keys($result));
$this->assertEquals(2, $result[$cohort3->id]->memberscnt);
$this->assertEquals(3, $result[$cohort4->id]->memberscnt);
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_MEMBERS_ONLY, 0, 0, 'yyy');
$this->assertEquals(array($cohort2->id), array_keys($result));
$this->assertEquals(1, $result[$cohort2->id]->memberscnt);
// Check filtering non-empty cohorts as teacher.
$this->setUser($user1);
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_MEMBERS_ONLY, 0, 0, '');
$this->assertEquals(array($cohort4->id), array_keys($result));
$this->assertEquals(3, $result[$cohort4->id]->memberscnt);
$result = cohort_get_available_cohorts($course2ctx, COHORT_WITH_MEMBERS_ONLY, 0, 0, '');
$this->assertEquals(array($cohort3->id, $cohort4->id), array_keys($result));
$this->assertEquals(2, $result[$cohort3->id]->memberscnt);
$this->assertEquals(3, $result[$cohort4->id]->memberscnt);
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_MEMBERS_ONLY, 0, 0, 'yyy');
$this->assertEmpty($result);
// Enrol users.
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($user2->id, $course1->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user3->id, $course1->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user5->id, $course1->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user6->id, $course1->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user3->id, $course2->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user4->id, $course2->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user5->id, $course2->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user6->id, $course2->id, $studentrole->id);
// Check cohorts with enrolments as admin.
$this->setAdminUser();
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_ENROLLED_MEMBERS_ONLY, 0, 0, '');
$this->assertEquals(array($cohort2->id, $cohort4->id), array_keys($result));
$this->assertEquals(1, $result[$cohort2->id]->enrolledcnt);
$this->assertEquals(2, $result[$cohort4->id]->enrolledcnt);
$this->assertEquals(1, $result[$cohort2->id]->memberscnt);
$this->assertEquals(3, $result[$cohort4->id]->memberscnt);
$result = cohort_get_available_cohorts($course2ctx, COHORT_WITH_ENROLLED_MEMBERS_ONLY, 0, 0, '');
$this->assertEquals(array($cohort3->id, $cohort4->id), array_keys($result));
$this->assertEquals(1, $result[$cohort3->id]->enrolledcnt);
$this->assertEquals(3, $result[$cohort4->id]->enrolledcnt);
$this->assertEquals(2, $result[$cohort3->id]->memberscnt);
$this->assertEquals(3, $result[$cohort4->id]->memberscnt);
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_ENROLLED_MEMBERS_ONLY, 0, 0, 'yyy');
$this->assertEquals(array($cohort2->id), array_keys($result));
$this->assertEquals(1, $result[$cohort2->id]->enrolledcnt);
$this->assertEquals(1, $result[$cohort2->id]->memberscnt);
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_NOTENROLLED_MEMBERS_ONLY, 0, 0, '');
$this->assertEquals(array($cohort4->id), array_keys($result));
$this->assertEquals(2, $result[$cohort4->id]->enrolledcnt);
$this->assertEquals(3, $result[$cohort4->id]->memberscnt);
// Assign user1 additional 'manager' role in the category context. He can now see hidden cohort in category1
// but still can not see hidden category in system.
$managerrole = $DB->get_record('role', array('shortname' => 'manager'));
role_assign($managerrole->id, $user1->id, context_coursecat::instance($category1->id));
$this->setUser($user1);
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 0, 0, '');
$this->assertEquals(array($cohort1->id, $cohort2->id, $cohort4->id), array_keys($result));
}
}

@ -41,9 +41,10 @@ class core_cohort_externallib_testcase extends externallib_advanced_testcase {
$this->resetAfterTest(true);
$contextid = context_system::instance()->id;
$category = $this->getDataGenerator()->create_category();
$cohort1 = array(
'categorytype' => array('type' => 'id', 'value' => '1'),
'categorytype' => array('type' => 'id', 'value' => $category->id),
'name' => 'cohort test 1',
'idnumber' => 'cohorttest1',
'description' => 'This is a description for cohorttest1'
@ -53,11 +54,12 @@ class core_cohort_externallib_testcase extends externallib_advanced_testcase {
'categorytype' => array('type' => 'system', 'value' => ''),
'name' => 'cohort test 2',
'idnumber' => 'cohorttest2',
'description' => 'This is a description for cohorttest2'
'description' => 'This is a description for cohorttest2',
'visible' => 0
);
$cohort3 = array(
'categorytype' => array('type' => 'id', 'value' => '1'),
'categorytype' => array('type' => 'id', 'value' => $category->id),
'name' => 'cohort test 3',
'idnumber' => 'cohorttest3',
'description' => 'This is a description for cohorttest3'
@ -65,21 +67,31 @@ class core_cohort_externallib_testcase extends externallib_advanced_testcase {
$roleid = $this->assignUserCapability('moodle/cohort:manage', $contextid);
// Call the external function.
$this->setCurrentTimeStart();
$createdcohorts = core_cohort_external::create_cohorts(array($cohort1, $cohort2));
// Check we retrieve the good total number of created cohorts + no error on capability.
$this->assertEquals(2, count($createdcohorts));
foreach ($createdcohorts as $createdcohort) {
$dbcohort = $DB->get_record('cohort', array('id' => $createdcohort['id']));
if ($createdcohort['idnumber'] == $cohort1['idnumber']) {
$dbcohort = $DB->get_record('cohort', array('id' => $createdcohort['id']));
$conid = $DB->get_field('context', 'id', array('instanceid' => $cohort1['categorytype']['value'],
'contextlevel' => CONTEXT_COURSECAT));
$this->assertEquals($dbcohort->contextid, $conid);
$this->assertEquals($dbcohort->name, $cohort1['name']);
$this->assertEquals($dbcohort->idnumber, $cohort1['idnumber']);
$this->assertEquals($dbcohort->description, $cohort1['description']);
$this->assertEquals($dbcohort->visible, 1); // Field was not specified, ensure it is visible by default.
} else if ($createdcohort['idnumber'] == $cohort2['idnumber']) {
$this->assertEquals($dbcohort->contextid, context_system::instance()->id);
$this->assertEquals($dbcohort->name, $cohort2['name']);
$this->assertEquals($dbcohort->description, $cohort2['description']);
$this->assertEquals($dbcohort->visible, $cohort2['visible']);
} else {
$this->fail('Unrecognised cohort found');
}
$this->assertTimeCurrent($dbcohort->timecreated);
$this->assertTimeCurrent($dbcohort->timemodified);
}
// Call without required capability.
@ -151,6 +163,7 @@ class core_cohort_externallib_testcase extends externallib_advanced_testcase {
if ($enrolledcohort['idnumber'] == $cohort1->idnumber) {
$this->assertEquals($cohort1->name, $enrolledcohort['name']);
$this->assertEquals($cohort1->description, $enrolledcohort['description']);
$this->assertEquals($cohort1->visible, $enrolledcohort['visible']);
}
}
@ -173,7 +186,7 @@ class core_cohort_externallib_testcase extends externallib_advanced_testcase {
$this->resetAfterTest(true);
$cohort1 = self::getDataGenerator()->create_cohort();
$cohort1 = self::getDataGenerator()->create_cohort(array('visible' => 0));
$cohort1 = array(
'id' => $cohort1->id,
@ -196,6 +209,15 @@ class core_cohort_externallib_testcase extends externallib_advanced_testcase {
$this->assertEquals($dbcohort->name, $cohort1['name']);
$this->assertEquals($dbcohort->idnumber, $cohort1['idnumber']);
$this->assertEquals($dbcohort->description, $cohort1['description']);
$this->assertEquals($dbcohort->visible, 0);
// Since field 'visible' was added in 2.8, make sure that update works correctly with and without this parameter.
core_cohort_external::update_cohorts(array($cohort1 + array('visible' => 1)));
$dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id']));
$this->assertEquals(1, $dbcohort->visible);
core_cohort_external::update_cohorts(array($cohort1));
$dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id']));
$this->assertEquals(1, $dbcohort->visible);
// Call without required capability.
$this->unassignUserCapability('moodle/cohort:manage', $context->id, $roleid);

@ -31,6 +31,7 @@ require('../../config.php');
require_once($CFG->dirroot.'/enrol/locallib.php');
require_once($CFG->dirroot.'/enrol/cohort/locallib.php');
require_once($CFG->dirroot.'/group/lib.php');
require_once($CFG->dirroot.'/cohort/lib.php');
// Must have the sesskey.
$id = required_param('id', PARAM_INT); // course id
@ -87,7 +88,7 @@ switch ($action) {
$cohortid = required_param('cohortid', PARAM_INT);
$roles = $manager->get_assignable_roles();
if (!enrol_cohort_can_view_cohort($cohortid) || !array_key_exists($roleid, $roles)) {
if (!cohort_can_view_cohort($cohortid, $context) || !array_key_exists($roleid, $roles)) {
throw new enrol_ajax_exception('errorenrolcohort');
}
$enrol = enrol_get_plugin('cohort');
@ -103,7 +104,7 @@ switch ($action) {
$cohortid = required_param('cohortid', PARAM_INT);
$roles = $manager->get_assignable_roles();
if (!enrol_cohort_can_view_cohort($cohortid) || !array_key_exists($roleid, $roles)) {
if (!cohort_can_view_cohort($cohortid, $context) || !array_key_exists($roleid, $roles)) {
throw new enrol_ajax_exception('errorenrolcohort');
}

@ -65,20 +65,10 @@ class enrol_cohort_edit_form extends moodleform {
} else {
$cohorts = array('' => get_string('choosedots'));
list($sqlparents, $params) = $DB->get_in_or_equal($coursecontext->get_parent_context_ids());
$sql = "SELECT id, name, idnumber, contextid
FROM {cohort}
WHERE contextid $sqlparents
ORDER BY name ASC, idnumber ASC";
$rs = $DB->get_recordset_sql($sql, $params);
foreach ($rs as $c) {
$context = context::instance_by_id($c->contextid);
if (!has_capability('moodle/cohort:view', $context)) {
continue;
}
$allcohorts = cohort_get_available_cohorts($coursecontext);
foreach ($allcohorts as $c) {
$cohorts[$c->id] = format_string($c->name);
}
$rs->close();
$mform->addElement('select', 'customint1', get_string('cohort', 'cohort'), $cohorts);
$mform->addRule('customint1', get_string('required'), 'required', null, 'client');
}

@ -95,25 +95,13 @@ class enrol_cohort_plugin extends enrol_plugin {
* @return bool
*/
protected function can_add_new_instances($courseid) {
global $DB;
global $CFG;
require_once($CFG->dirroot . '/cohort/lib.php');
$coursecontext = context_course::instance($courseid);
if (!has_capability('moodle/course:enrolconfig', $coursecontext) or !has_capability('enrol/cohort:config', $coursecontext)) {
return false;
}
list($sqlparents, $params) = $DB->get_in_or_equal($coursecontext->get_parent_context_ids());
$sql = "SELECT id, contextid
FROM {cohort}
WHERE contextid $sqlparents
ORDER BY name ASC";
$cohorts = $DB->get_records_sql($sql, $params);
foreach ($cohorts as $c) {
$context = context::instance_by_id($c->contextid);
if (has_capability('moodle/cohort:view', $context)) {
return true;
}
}
return false;
return cohort_get_available_cohorts($coursecontext) ? true : false;
}
/**

@ -25,6 +25,7 @@
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/enrol/locallib.php');
require_once($CFG->dirroot . '/cohort/lib.php');
/**
@ -376,65 +377,6 @@ function enrol_cohort_enrol_all_users(course_enrolment_manager $manager, $cohort
return $count;
}
/**
* Gets all the cohorts the user is able to view.
*
* @global moodle_database $DB
* @param course_enrolment_manager $manager
* @return array
*/
function enrol_cohort_get_cohorts(course_enrolment_manager $manager) {
global $DB;
$context = $manager->get_context();
$cohorts = array();
$instances = $manager->get_enrolment_instances();
$enrolled = array();
foreach ($instances as $instance) {
if ($instance->enrol == 'cohort') {
$enrolled[] = $instance->customint1;
}
}
list($sqlparents, $params) = $DB->get_in_or_equal($context->get_parent_context_ids());
$sql = "SELECT id, name, idnumber, contextid
FROM {cohort}
WHERE contextid $sqlparents
ORDER BY name ASC, idnumber ASC";
$rs = $DB->get_recordset_sql($sql, $params);
foreach ($rs as $c) {
$context = 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, true, array('context'=>context::instance_by_id($c->contextid))),
'users'=>$DB->count_records('cohort_members', array('cohortid'=>$c->id)),
'enrolled'=>in_array($c->id, $enrolled)
);
}
$rs->close();
return $cohorts;
}
/**
* Check if cohort exists and user is allowed to enrol it.
*
* @global moodle_database $DB
* @param int $cohortid Cohort ID
* @return boolean
*/
function enrol_cohort_can_view_cohort($cohortid) {
global $DB;
$cohort = $DB->get_record('cohort', array('id' => $cohortid), 'id, contextid');
if ($cohort) {
$context = context::instance_by_id($cohort->contextid);
if (has_capability('moodle/cohort:view', $context)) {
return true;
}
}
return false;
}
/**
* Gets cohorts the user is able to view.
*
@ -446,67 +388,26 @@ function enrol_cohort_can_view_cohort($cohortid) {
* @return array Array(more => bool, offset => int, cohorts => array)
*/
function enrol_cohort_search_cohorts(course_enrolment_manager $manager, $offset = 0, $limit = 25, $search = '') {
global $DB;
$context = $manager->get_context();
$cohorts = array();
$instances = $manager->get_enrolment_instances();
$enrolled = array();
foreach ($instances as $instance) {
if ($instance->enrol == 'cohort') {
if ($instance->enrol === 'cohort') {
$enrolled[] = $instance->customint1;
}
}
list($sqlparents, $params) = $DB->get_in_or_equal($context->get_parent_context_ids());
// Add some additional sensible conditions.
$tests = array('contextid ' . $sqlparents);
// Modify the query to perform the search if required.
if (!empty($search)) {
$conditions = array(
'name',
'idnumber',
'description'
);
$searchparam = '%' . $DB->sql_like_escape($search) . '%';
foreach ($conditions as $key=>$condition) {
$conditions[$key] = $DB->sql_like($condition, "?", false);
$params[] = $searchparam;
}
$tests[] = '(' . implode(' OR ', $conditions) . ')';
}
$wherecondition = implode(' AND ', $tests);
$sql = "SELECT id, name, idnumber, contextid, description
FROM {cohort}
WHERE $wherecondition
ORDER BY name ASC, idnumber ASC";
$rs = $DB->get_recordset_sql($sql, $params, $offset);
$rawcohorts = cohort_get_available_cohorts($context, COHORT_COUNT_MEMBERS, $offset, $limit, $search);
// Produce the output respecting parameters.
foreach ($rs as $c) {
// Track offset.
$offset++;
// Check capabilities.
$context = context::instance_by_id($c->contextid);
if (!has_capability('moodle/cohort:view', $context)) {
continue;
}
if ($limit === 0) {
// We have reached the required number of items and know that there are more, exit now.
$offset--;
break;
}
foreach ($rawcohorts as $c) {
$cohorts[$c->id] = array(
'cohortid' => $c->id,
'name' => shorten_text(format_string($c->name, true, array('context'=>context::instance_by_id($c->contextid))), 35),
'users' => $DB->count_records('cohort_members', array('cohortid'=>$c->id)),
'users' => $c->memberscnt,
'enrolled' => in_array($c->id, $enrolled)
);
// Count items.
$limit--;
}
$rs->close();
return array('more' => !(bool)$limit, 'offset' => $offset, 'cohorts' => $cohorts);
}

@ -26,6 +26,7 @@
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir.'/formslib.php');
require_once($CFG->dirroot.'/cohort/lib.php');
class enrol_self_edit_form extends moodleform {
@ -105,28 +106,22 @@ class enrol_self_edit_form extends moodleform {
$mform->setType('customint3', PARAM_INT);
$cohorts = array(0 => get_string('no'));
list($sqlparents, $params) = $DB->get_in_or_equal($context->get_parent_context_ids(), SQL_PARAMS_NAMED);
$params['current'] = $instance->customint5;
$sql = "SELECT id, name, idnumber, contextid
FROM {cohort}
WHERE contextid $sqlparents OR id = :current
ORDER BY name ASC, idnumber ASC";
$rs = $DB->get_recordset_sql($sql, $params);
foreach ($rs as $c) {
$ccontext = context::instance_by_id($c->contextid);
if ($c->id != $instance->customint5 and !has_capability('moodle/cohort:view', $ccontext)) {
continue;
}
$cohorts[$c->id] = format_string($c->name, true, array('context'=>$context));
$allcohorts = cohort_get_available_cohorts($context);
if ($instance->customint5 && !isset($allcohorts[$instance->customint5]) &&
($c = $DB->get_record('cohort', array('id' => $instance->customint5), 'id, name, idnumber, contextid, visible', IGNORE_MISSING))) {
// Current cohort was not found because current user can not see it. Still keep it.
$allcohorts[$instance->customint5] = $c;
}
foreach ($allcohorts as $c) {
$cohorts[$c->id] = format_string($c->name, true, array('context' => context::instance_by_id($c->contextid)));
if ($c->idnumber) {
$cohorts[$c->id] .= ' ['.s($c->idnumber).']';
}
}
if (!isset($cohorts[$instance->customint5])) {
if ($instance->customint5 && !isset($allcohorts[$instance->customint5])) {
// Somebody deleted a cohort, better keep the wrong value so that random ppl can not enrol.
$cohorts[$instance->customint5] = get_string('unknowncohort', 'cohort', $instance->customint5);
}
$rs->close();
if (count($cohorts) > 1) {
$mform->addElement('select', 'customint5', get_string('cohortonly', 'enrol_self'), $cohorts);
$mform->addHelpButton('customint5', 'cohortonly', 'enrol_self');

@ -82,18 +82,13 @@ class autogroup_form extends moodleform {
$mform->setDefault('roleid', $student->id);
}
$context = context_course::instance($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');
if ($cohorts = cohort_get_available_cohorts(context_course::instance($COURSE->id), COHORT_WITH_ENROLLED_MEMBERS_ONLY)) {
$options = array(0 => get_string('anycohort', 'cohort'));
foreach ($cohorts as $c) {
$options[$c->id] = format_string($c->name, true, context::instance_by_id($c->contextid));
}
$mform->addElement('select', 'cohortid', get_string('selectfromcohort', 'cohort'), $options);
$mform->setDefault('cohortid', '0');
} else {
$mform->addElement('hidden','cohortid');
$mform->setType('cohortid', PARAM_INT);

@ -83,3 +83,6 @@ $string['uploadcohorts_help'] = 'Cohorts may be uploaded via text file. The form
* Required fieldname is name
* Optional fieldnames are idnumber, description, descriptionformat, context, category, category_id, category_idnumber, category_path
';
$string['visible'] = 'Visible';
$string['visible_help'] = "Any cohort can be viewed by users who have 'moodle/cohort:view' capability in the cohort context.<br/>
Visible cohorts can also be viewed by users in the underlying courses.";

@ -723,8 +723,7 @@ $capabilities = array(
)
),
// view members of a cohort, this can be used in course context too,
// this also controls the ability to actually use cohort
// View visible and hidden cohorts defined in the current context.
'moodle/cohort:view' => array(
'captype' => 'read',

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="lib/db" VERSION="20140918" COMMENT="XMLDB file for core Moodle tables"
<XMLDB PATH="lib/db" VERSION="20141003" COMMENT="XMLDB file for core Moodle tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
>
@ -2086,6 +2086,7 @@
<FIELD NAME="idnumber" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false" COMMENT="Unique identifier of a cohort, useful especially for mapping to external entities"/>
<FIELD NAME="description" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Standard description text box"/>
<FIELD NAME="descriptionformat" TYPE="int" LENGTH="2" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="visible" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false" COMMENT="Visibility to teachers"/>
<FIELD NAME="component" TYPE="char" LENGTH="100" NOTNULL="true" SEQUENCE="false" COMMENT="Component (plugintype_pluignname) that manages the cohort, manual modifications are allowed only when set to NULL"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>

@ -3837,5 +3837,20 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2014100100.00);
}
if ($oldversion < 2014100300.01) {
// Define field visible to be added to cohort.
$table = new xmldb_table('cohort');
$field = new xmldb_field('visible', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'descriptionformat');
// Conditionally launch add field visible.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Main savepoint reached.
upgrade_main_savepoint(true, 2014100300.01);
}
return true;
}

@ -4448,3 +4448,93 @@ function coursemodule_visible_for_user($cm, $userid=0) {
'Replace with \core_availability\info_module::is_user_visible().');
return \core_availability\info_module::is_user_visible($cm, $userid, false);
}
/**
* Gets all the cohorts the user is able to view.
*
* @deprecated since Moodle 2.8 MDL-36014 please use enrol_cohort_search_cohorts()
*
* @param course_enrolment_manager $manager
* @return array
*/
function enrol_cohort_get_cohorts(course_enrolment_manager $manager) {
global $CFG;
require_once($CFG->dirroot . '/enrol/cohort/locallib.php');
debugging('Function enrol_cohort_get_cohorts() is deprecated, use enrol_cohort_search_cohorts() or '.
'cohort_get_available_cohorts() instead', DEBUG_DEVELOPER);
return enrol_cohort_search_cohorts($manager, 0, 0, '');
}
/**
* Check if cohort exists and user is allowed to enrol it.
*
* This function is deprecated, use {@link cohort_can_view_cohort()} instead since it also
* takes into account current context
*
* @deprecated since Moodle 2.8 MDL-36014 please use cohort_can_view_cohort()
*
* @param int $cohortid Cohort ID
* @return boolean
*/
function enrol_cohort_can_view_cohort($cohortid) {
global $CFG;
require_once($CFG->dirroot . '/cohort/lib.php');
debugging('Function enrol_cohort_can_view_cohort() is deprecated, use cohort_can_view_cohort() instead',
DEBUG_DEVELOPER);
return cohort_can_view_cohort($cohortid, null);
}
/**
* Returns list of cohorts from course parent contexts.
*
* Note: this function does not implement any capability checks,
* it means it may disclose existence of cohorts,
* make sure it is displayed to users with appropriate rights only.
*
* It is advisable to use {@link cohort_get_available_cohorts()} instead.
*
* @deprecated since Moodle 2.8 MDL-36014 use cohort_get_available_cohorts() instead
*
* @param stdClass $course
* @param bool $onlyenrolled true means include only cohorts with enrolled users
* @return array of cohort names with number of enrolled users
*/
function cohort_get_visible_list($course, $onlyenrolled=true) {
global $DB;
debugging('Function cohort_get_visible_list() is deprecated. Please use function cohort_get_available_cohorts() ".
"that correctly checks capabilities.', DEBUG_DEVELOPER);
$context = context_course::instance($course->id);
list($esql, $params) = get_enrolled_sql($context);
list($parentsql, $params2) = $DB->get_in_or_equal($context->get_parent_context_ids(), SQL_PARAMS_NAMED);
$params = array_merge($params, $params2);
if ($onlyenrolled) {
$left = "";
$having = "HAVING COUNT(u.id) > 0";
} else {
$left = "LEFT";
$having = "";
}
$sql = "SELECT c.id, c.name, c.contextid, c.idnumber, c.visible, COUNT(u.id) AS cnt
FROM {cohort} c
$left JOIN ({cohort_members} cm
JOIN ($esql) u ON u.id = cm.userid) ON cm.cohortid = c.id
WHERE c.contextid $parentsql
GROUP BY c.id, c.name, c.contextid, c.idnumber
$having
ORDER BY c.name, c.idnumber, c.visible";
$cohorts = $DB->get_records_sql($sql, $params);
foreach ($cohorts as $cid=>$cohort) {
$cohorts[$cid] = format_string($cohort->name, true, array('context'=>$cohort->contextid));
if ($cohort->cnt) {
$cohorts[$cid] .= ' (' . $cohort->cnt . ')';
}
}
return $cohorts;
}

@ -335,6 +335,10 @@ EOD;
$record['descriptionformat'] = FORMAT_MOODLE;
}
if (!isset($record['visible'])) {
$record['visible'] = 1;
}
if (!isset($record['component'])) {
$record['component'] = '';
}

@ -28,6 +28,11 @@ DEPRECATIONS:
access the activity.
* Constant FEATURE_GROUPMEMBERSONLY (used in module _supports functions) is
deprecated.
* cohort_get_visible_list() is deprecated. There is a better function cohort_get_available_cohorts()
that respects user capabilities to view cohorts.
* enrol_cohort_get_cohorts() is deprecated; replace with enrol_cohort_search_cohorts() or
cohort_get_available_cohorts()
* enrol_cohort_can_view_cohort() is deprecated; replace with cohort_can_view_cohort()
=== 2.6.4 / 2.7.1 ===

@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
$version = 2014100200.00; // YYYYMMDD = weekly release date of this DEV branch.
$version = 2014100300.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.