Merge branch 'wip-MDL-36014-master' of git://github.com/marinaglancy/moodle

Conflicts:
	lib/db/install.xml
	lib/db/upgrade.php
	version.php
This commit is contained in:
Damyon Wiese 2014-10-07 12:34:34 +08:00
commit 4a813f3959
26 changed files with 704 additions and 238 deletions

View File

@ -62,7 +62,7 @@ if ($context->contextlevel == CONTEXT_COURSECAT) {
}
$PAGE->navbar->add(get_string('assign', 'cohort'));
$PAGE->set_title(get_string('cohort:assign', 'cohort'));
$PAGE->set_title(get_string('assigncohorts', 'cohort'));
$PAGE->set_heading($COURSE->fullname);
echo $OUTPUT->header();

View File

@ -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.

View File

@ -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);

View File

@ -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),
)
)
)

View File

@ -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'),

View File

@ -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;
}
}

View File

@ -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"

View File

@ -19,13 +19,13 @@ Feature: A privileged user can create cohorts using a CSV file
And I upload "cohort/tests/fixtures/uploadcohorts1.csv" file to "File" filemanager
And I click on "Preview" "button"
Then the following should exist in the "previewuploadedcohorts" table:
| name | idnumber | description | Context | Status |
| cohort name 1 | cohortid1 | first description | System | |
| cohort name 2 | cohortid2 | | System | |
| cohort name 3 | cohortid3 | | Miscellaneous | |
| cohort name 4 | cohortid4 | | Cat 1 | |
| cohort name 5 | cohortid5 | | Cat 2 | |
| cohort name 6 | cohortid6 | | Cat 3 | |
| name | idnumber | description | Context | visible | Status |
| cohort name 1 | cohortid1 | first description | System | 1 | |
| cohort name 2 | cohortid2 | | System | 1 | |
| cohort name 3 | cohortid3 | | Miscellaneous | 0 | |
| cohort name 4 | cohortid4 | | Cat 1 | 1 | |
| cohort name 5 | cohortid5 | | Cat 2 | 0 | |
| cohort name 6 | cohortid6 | | Cat 3 | 1 | |
And I press "Upload cohorts"
And I should see "Uploaded 6 cohorts"
And I press "Continue"
@ -42,6 +42,12 @@ Feature: A privileged user can create cohorts using a CSV file
| Cat 1 | cohort name 4 | cohortid4 | | 0 | Created manually |
| Cat 2 | cohort name 5 | cohortid5 | | 0 | Created manually |
| Cat 3 | cohort name 6 | cohortid6 | | 0 | Created manually |
And the "class" attribute of "cohort name 1" "table_row" should not contain "dimmed_text"
And the "class" attribute of "cohort name 2" "table_row" should not contain "dimmed_text"
And the "class" attribute of "cohort name 3" "table_row" should contain "dimmed_text"
And the "class" attribute of "cohort name 4" "table_row" should not contain "dimmed_text"
And the "class" attribute of "cohort name 5" "table_row" should contain "dimmed_text"
And the "class" attribute of "cohort name 6" "table_row" should not contain "dimmed_text"
@javascript
Scenario: Upload cohorts with default category context as admin

View File

@ -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, 'name' => 'ddd'));
$cohort5 = $this->getDataGenerator()->create_cohort(array('contextid'=>$systemctx->id, 'visible'=>0, 'name' => 'eee'));
/*
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));
}
}

View File

@ -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);

View File

@ -1,7 +1,7 @@
name,idnumber,description,category
cohort name 1,cohortid1,first description,
cohort name 2,cohortid2,,
cohort name 3,cohortid3,,Miscellaneous
cohort name 4,cohortid4,,CAT1
cohort name 5,cohortid5,,CAT2
cohort name 6,cohortid6,,CAT3
name,idnumber,description,category,visible
cohort name 1,cohortid1,first description,,
cohort name 2,cohortid2,,,
cohort name 3,cohortid3,,Miscellaneous,no
cohort name 4,cohortid4,,CAT1,yes
cohort name 5,cohortid5,,CAT2,0
cohort name 6,cohortid6,,CAT3,1

1 name idnumber description category visible
2 cohort name 1 cohortid1 first description
3 cohort name 2 cohortid2
4 cohort name 3 cohortid3 Miscellaneous no
5 cohort name 4 cohortid4 CAT1 yes
6 cohort name 5 cohortid5 CAT2 0
7 cohort name 6 cohortid6 CAT3 1

View File

@ -359,7 +359,7 @@ class cohort_upload_form extends moodleform {
$columns = $cir->get_columns();
// Check that columns include 'name' and warn about extra columns.
$allowedcolumns = array('contextid', 'name', 'idnumber', 'description', 'descriptionformat');
$allowedcolumns = array('contextid', 'name', 'idnumber', 'description', 'descriptionformat', 'visible');
$additionalcolumns = array('context', 'category', 'category_id', 'category_idnumber', 'category_path');
$displaycolumns = array();
$extracolumns = array();
@ -453,6 +453,19 @@ class cohort_upload_form extends moodleform {
case 'idnumber': $hash[$key] = core_text::substr(clean_param($value, PARAM_RAW), 0, 254); break;
case 'description': $hash[$key] = clean_param($value, PARAM_RAW); break;
case 'descriptionformat': $hash[$key] = clean_param($value, PARAM_INT); break;
case 'visible':
$tempstr = trim(core_text::strtolower($value));
if ($tempstr === '') {
// Empty string is treated as "YES" (the default value for cohort visibility).
$hash[$key] = 1;
} else {
if ($tempstr === core_text::strtolower(get_string('no')) || $tempstr === 'n') {
// Special treatment for 'no' string that is not included in clean_param().
$value = 0;
}
$hash[$key] = clean_param($value, PARAM_BOOL) ? 1 : 0;
}
break;
}
}
}

View File

@ -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');
}

View File

@ -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');
}

View File

@ -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;
}
/**

View File

@ -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);
}

View File

@ -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');

View File

@ -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);

View File

@ -36,9 +36,7 @@ $string['categorynotfound'] = 'Category <b>{$a}</b> not found or you don\'t have
$string['cohort'] = 'Cohort';
$string['cohorts'] = 'Cohorts';
$string['cohortsin'] = '{$a}: available cohorts';
$string['cohort:assign'] = 'Assign cohort members';
$string['cohort:manage'] = 'Manage cohorts';
$string['cohort:view'] = 'Use cohorts and view members';
$string['assigncohorts'] = 'Assign cohort members';
$string['component'] = 'Source';
$string['contextnotfound'] = 'Context <b>{$a}</b> not found or you don\'t have permission to create a cohort there. The default context will be used.';
$string['csvcontainserrors'] = 'Errors were found in CSV data. See details below.';
@ -83,5 +81,8 @@ $string['uploadcohorts_help'] = 'Cohorts may be uploaded via text file. The form
* Each record is a series of data separated by commas (or other delimiters)
* The first record contains a list of fieldnames defining the format of the rest of the file
* Required fieldname is name
* Optional fieldnames are idnumber, description, descriptionformat, context, category, category_id, category_idnumber, category_path
';
* Optional fieldnames are idnumber, description, descriptionformat, visible, 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.";

View File

@ -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',

View File

@ -2092,6 +2092,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"/>

View File

@ -3949,5 +3949,20 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2014100700.00);
}
if ($oldversion < 2014100700.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, 2014100700.01);
}
return true;
}

View File

@ -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;
}

View File

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

View File

@ -34,6 +34,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 ===

View File

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