Skip to content

Commit

Permalink
MDL-50647 group: add 'not in group' section to groups overview
Browse files Browse the repository at this point in the history
Also adds 'No group' and 'No grouping' filters to the top of the page
  • Loading branch information
davosmith authored and rajesh Taneja committed Oct 16, 2015
1 parent 74fad2c commit 294c4bb
Show file tree
Hide file tree
Showing 4 changed files with 253 additions and 6 deletions.
71 changes: 65 additions & 6 deletions group/overview.php
Expand Up @@ -26,6 +26,10 @@
require_once('../config.php');
require_once($CFG->libdir . '/filelib.php');

define('OVERVIEW_NO_GROUP', -1); // The fake group for users not in a group.
define('OVERVIEW_GROUPING_GROUP_NO_GROUPING', -1); // The fake grouping for groups that have no grouping.
define('OVERVIEW_GROUPING_NO_GROUP', -2); // The fake grouping for users with no group.

$courseid = required_param('id', PARAM_INT);
$groupid = optional_param('group', 0, PARAM_INT);
$groupingid = optional_param('grouping', 0, PARAM_INT);
Expand Down Expand Up @@ -61,6 +65,9 @@
$strfiltergroups = get_string('filtergroups', 'group');
$strnogroups = get_string('nogroups', 'group');
$strdescription = get_string('description');
$strnotingroup = get_string('notingrouplist', 'group');
$strnogroup = get_string('nogroup', 'group');
$strnogrouping = get_string('nogrouping', 'group');

// Get all groupings and sort them by formatted name.
$groupings = $DB->get_records('groupings', array('courseid'=>$courseid), 'name');
Expand All @@ -72,7 +79,7 @@
foreach ($groupings as $grouping) {
$members[$grouping->id] = array();
}
$members[-1] = array(); //groups not in a grouping
$members[OVERVIEW_GROUPING_GROUP_NO_GROUPING] = array(); //groups not in a grouping

// Get all groups
$groups = $DB->get_records('groups', array('courseid'=>$courseid), 'name');
Expand All @@ -86,8 +93,12 @@
}

if ($groupingid) {
$groupingwhere = "AND gg.groupingid = :groupingid";
$params['groupingid'] = $groupingid;
if ($groupingid < 0) { // No grouping filter.
$groupingwhere = "AND gg.groupingid IS NULL";
} else {
$groupingwhere = "AND gg.groupingid = :groupingid";
$params['groupingid'] = $groupingid;
}
} else {
$groupingwhere = "";
}
Expand All @@ -108,7 +119,7 @@
$user = new stdClass();
$user = username_load_fields_from_object($user, $row, null, array('id' => 'userid', 'username', 'idnumber'));
if (!$row->groupingid) {
$row->groupingid = -1;
$row->groupingid = OVERVIEW_GROUPING_GROUP_NO_GROUPING;
}
if (!array_key_exists($row->groupid, $members[$row->groupingid])) {
$members[$row->groupingid][$row->groupid] = array();
Expand All @@ -119,6 +130,47 @@
}
$rs->close();

// Add 'no groupings' / 'no groups' selectors.
$groupings[OVERVIEW_GROUPING_GROUP_NO_GROUPING] = (object)array(
'id' => OVERVIEW_GROUPING_GROUP_NO_GROUPING,
'formattedname' => $strnogrouping,
);
$groups[OVERVIEW_NO_GROUP] = (object)array(
'id' => OVERVIEW_NO_GROUP,
'courseid' => $courseid,
'idnumber' => '',
'name' => $strnogroup,
'description' => '',
'descriptionformat' => FORMAT_HTML,
'enrolmentkey' => '',
'picture' => 0,
'hidepicture' => 0,
'timecreated' => 0,
'timemodified' => 0,
);

// Add users who are not in a group.
if ($groupid <= 0 && $groupingid <= 0) {
list($esql, $params) = get_enrolled_sql($context, null, 0, true);
$sql = "SELECT u.id, $allnames, u.idnumber, u.username
FROM {user} u
JOIN ($esql) e ON e.id = u.id
LEFT JOIN (
SELECT gm.userid
FROM {groups_members} gm
JOIN {groups} g ON g.id = gm.groupid
WHERE g.courseid = :courseid
) grouped ON grouped.userid = u.id
WHERE grouped.userid IS NULL";
$params['courseid'] = $courseid;

$nogroupusers = $DB->get_records_sql($sql, $params);

if ($nogroupusers) {
$members[OVERVIEW_GROUPING_NO_GROUP][OVERVIEW_NO_GROUP] = $nogroupusers;
}
}

navigation_node::override_active_url(new moodle_url('/group/index.php', array('id'=>$courseid)));
$PAGE->navbar->add(get_string('overview', 'group'));

Expand Down Expand Up @@ -164,7 +216,9 @@
$hoverevents = array();
foreach ($members as $gpgid=>$groupdata) {
if ($groupingid and $groupingid != $gpgid) {
continue; // do not show
if ($groupingid > 0 || $gpgid > 0) { // Still show 'not in group' when 'no grouping' selected.
continue; // Do not show.
}
}
$table = new html_table();
$table->head = array(get_string('groupscount', 'group', count($groupdata)), get_string('groupmembers', 'group'), get_string('usercount', 'group'));
Expand Down Expand Up @@ -201,7 +255,12 @@
continue;
}
if ($gpgid < 0) {
echo $OUTPUT->heading($strnotingrouping, 3);
// Display 'not in group' for grouping id == OVERVIEW_GROUPING_NO_GROUP.
if ($gpgid == OVERVIEW_GROUPING_NO_GROUP) {
echo $OUTPUT->heading($strnotingroup, 3);
} else {
echo $OUTPUT->heading($strnotingrouping, 3);
}
} else {
echo $OUTPUT->heading($groupings[$gpgid]->formattedname, 3);
$description = file_rewrite_pluginfile_urls($groupings[$gpgid]->description, 'pluginfile.php', $context->id, 'grouping', 'description', $gpgid);
Expand Down
105 changes: 105 additions & 0 deletions group/tests/behat/behat_groups.php
Expand Up @@ -27,6 +27,7 @@

require_once(__DIR__ . '/../../../lib/behat/behat_base.php');

use Behat\Behat\Context\Step\Then;
use Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;

/**
Expand Down Expand Up @@ -84,4 +85,108 @@ public function i_add_user_to_group_members($userfullname, $groupname) {
$this->find_button(get_string('backtogroups', 'group'))->click();
}

/**
* A comma-separated list of groups expected on the page, with a list of groupings each of them should be found in.
*
* @Given /^the groups overview should include groups "(?P<group_list_string>(?:[^"]|\\")*)" in groupings "(?P<grouping_list_string>(?:[^"]|\\")*)"$/
* @param string $grouplist
* @param string $groupinglist
* @return Then[]
*/
public function the_groups_overview_should_include_groups($grouplist, $groupinglist) {
if (!$grouplist) {
return array();
}

$steps = array();
$groups = array_map('trim', explode(',', $grouplist));
$groupings = array_map('trim', explode(',', $groupinglist));
if (count($groups) != count($groupings)) {
throw new Exception('Groups and groupings lists must contain the same number of items');
}

$groupingname = reset($groupings);
foreach ($groups as $groupname) {
// Find the table after the H3 containing the grouping name, then look for the group name in the first column.
$xpath = "//h3[normalize-space(.) = '{$groupingname}']/following-sibling::table//tr//".
"td[contains(concat(' ', normalize-space(@class), ' '), ' c0 ')][normalize-space(.) = '{$groupname}' ]";

$steps[] = new Then('"'.$xpath.'" "xpath_element" should exist');

$groupingname = next($groupings);
}

return $steps;
}

/**
* A comma-separated list of the names of groups not expected on the page
*
* @Given /^the groups overview should not include groups "(?P<group_list_string>(?:[^"]|\\")*)"$/
* @param string $grouplist
* @return Then[]
*/
public function the_groups_overview_should_not_include_groups($grouplist) {
if (!$grouplist) {
return array();
}

$steps = array();
$groups = array_map('trim', explode(',', $grouplist));
foreach ($groups as $groupname) {
$steps[] = new Then('"'.$groupname.'" "table_row" should not exist');
}

return $steps;
}

/**
* A comma-separated list of the group members expected on the page, with a list of groups each of them should be found in.
*
* @Given /^the groups overview should include members "(?P<member_list_string>(?:[^"]|\\")*)" in groups "(?P<group_list_string>(?:[^"]|\\")*)"$/
* @param string $memberlist
* @param string $grouplist
* @return Then[]
*/
public function the_groups_overview_should_include_members($memberlist, $grouplist) {
if (!$memberlist) {
return array();
}

$steps = array();
$members = array_map('trim', explode(',', $memberlist));
$groups = array_map('trim', explode(',', $grouplist));
if (count($members) != count($groups)) {
throw new Exception('Group members and groups lists must contain the same number of items');
}

$groupname = reset($groups);
foreach ($members as $membername) {
$steps[] = new Then('"'.$membername.'" "text" should exist in the "'.$groupname.'" "table_row"');
$groupname = next($groups);
}

return $steps;
}

/**
* A comma-separated list of the names of group members not expected on the page
*
* @Given /^the groups overview should not include members "(?P<member_list_string>(?:[^"]|\\")*)"$/
* @param string $memberlist
* @return Then[]
*/
public function the_groups_overview_should_not_include_members($memberlist) {
if (!$memberlist) {
return array();
}

$steps = array();
$members = array_map('trim', explode(',', $memberlist));
foreach ($members as $membername) {
$steps[] = new Then('I should not see "'.$membername.'"');
}

return $steps;
}
}
80 changes: 80 additions & 0 deletions group/tests/behat/overview.feature
@@ -0,0 +1,80 @@
@core @core_group
Feature: Group overview
In order to view an overview of the groups
As a teacher
I need to visit the group overview page

Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student0 | Student | 0 | student0@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
| student3 | Student | 3 | student3@example.com |
| student4 | Student | 4 | student4@example.com |
| student5 | Student | 5 | student5@example.com |
| student6 | Student | 6 | student6@example.com |
| student7 | Student | 7 | student7@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student0 | C1 | student |
| student1 | C1 | student |
| student2 | C1 | student |
| student3 | C1 | student |
| student4 | C1 | student |
| student5 | C1 | student |
| student6 | C1 | student |
| student7 | C1 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
| Group 2 | C1 | G2 |
| Group 3 | C1 | G3 |
| Group 4 | C1 | G4 |
And the following "group members" exist:
| user | group |
| student0 | G1 |
| student1 | G1 |
| student2 | G2 |
| student3 | G3 |
| student4 | G3 |
| student5 | G4 |
And the following "groupings" exist:
| name | course | idnumber |
| Grouping 1 | C1 | GG1 |
| Grouping 2 | C1 | GG2 |
And the following "grouping groups" exist:
| grouping | group |
| GG1 | G1 |
| GG1 | G2 |
| GG2 | G2 |
| GG2 | G3 |

Scenario Outline: Filter the overview in various different ways
Given I log in as "teacher1"
And I follow "Course 1"
And I navigate to "Groups" node in "Course administration > Users"
And I follow "Overview"

When I select "<grouping>" from the "Grouping" singleselect
And I select "<group>" from the "group" singleselect

Then the groups overview should include groups "<expectedgroups>" in groupings "<expectedgroupings>"
And the groups overview should not include groups "<notexpectedgroups>"
And the groups overview should include members "<expectedmembers>" in groups "<expectedmembergroups>"
And the groups overview should not include members "<notexpectedmembers>"

Examples:
| grouping | group | expectedgroups | expectedgroupings | notexpectedgroups | expectedmembers | expectedmembergroups | notexpectedmembers |
| All | All | Group 1, Group 2, Group 2, Group 3, Group 4, No group | Grouping 1, Grouping 1, Grouping 2, Grouping 2, [Not in a grouping], [Not in a group] | | Student 0, Student 1, Student 2, Student 3, Student 4, Student 5, Student 6, Student 7 | Group 1, Group 1, Group 2, Group 3, Group 3, Group 4, No group, No group | |
| Grouping 1 | All | Group 1, Group 2 | Grouping 1, Grouping 1 | Group 3, No group | Student 0, Student 1, Student 2 | Group 1, Group 1, Group 2 | Student 3, Student 4, Student 5, Student 6, Student 7 |
| Grouping 2 | All | Group 2, Group 3 | Grouping 2, Grouping 2 | Group 1, No group | Student 2, Student 3, Student 4 | Group 2, Group 3, Group 3 | Student 0, Student 1, Student 5, Student 6, Student 7 |
| No grouping | All | Group 4, No group | [Not in a grouping], [Not in a group] | Group 1, Group 2, Group 3 | Student 5, Student 6, Student 7 | Group 4, No group, No group | Student 0, Student 1, Student 2, Student 3, Student 4 |
| All | Group 1 | Group 1 | Grouping 1 | Group 2, Group 3, Group 4, No group | Student 0, Student 1 | Group 1, Group 1 | Student 2, Student 3, Student 4, Student 5, Student 6, Student 7 |
| All | Group 2 | Group 2, Group 2 | Grouping 1, Grouping 2 | Group 1, Group 3, Group 4, No group | Student 2 | Group 2 | Student 0, Student 1, Student 3, Student 4, Student 5, Student 6, Student 7 |
| All | No group | No group | [Not in a group] | Group 1, Group 2, Group 3, Group 4 | Student 6, Student 7 | No group, No group | Student 0, Student 1, Student 2, Student 3, Student 4, Student 5 |
3 changes: 3 additions & 0 deletions lang/en/group.php
Expand Up @@ -149,12 +149,15 @@
$string['newpicture_help'] = 'Select an image in JPG or PNG format. The image will be cropped to a square and resized to 100x100 pixels.';
$string['noallocation'] = 'No allocation';
$string['nogrouping'] = 'No grouping';
$string['nogroup'] = 'No group';
$string['nogrouping'] = 'No grouping';
$string['nogroups'] = 'There are no groups set up in this course yet';
$string['nogroupsassigned'] = 'No groups assigned';
$string['nopermissionforcreation'] = 'Can\'t create group "{$a}" as you don\'t have the required permissions';
$string['nosmallgroups'] = 'Prevent last small group';
$string['notingroup'] = 'Ignore users in groups';
$string['notingrouping'] = '[Not in a grouping]';
$string['notingrouplist'] = '[Not in a group]';
$string['nousersinrole'] = 'There are no suitable users in the selected role';
$string['number'] = 'Group/member count';
$string['numgroups'] = 'Number of groups';
Expand Down

0 comments on commit 294c4bb

Please sign in to comment.