MDL-21415 reports: Adding support of groups to course participation reports
authorAnkit Agarwal <ankit@moodle.com>
Tue, 30 Oct 2012 03:29:53 +0000 (11:29 +0800)
committerDan Poltawski <dan@moodle.com>
Tue, 10 Sep 2013 05:14:33 +0000 (13:14 +0800)
Also introducing new api groups_allgroups_course_menu() that generates a selector for all groups in course"

lib/grouplib.php
lib/tests/grouplib_test.php
report/participation/index.php

index 6669ac6..b30dae5 100644 (file)
@@ -556,6 +556,54 @@ function groups_print_course_menu($course, $urlroot, $return=false) {
     }
 }
 
+/**
+ * Generates html to print menu selector for course level, listing all groups.
+ * Note: This api does not do any group mode check use groups_print_course_menu() instead if you want proper checks.
+ *
+ * @param stdclass          $course  course object.
+ * @param string|moodle_url $urlroot return address. Accepts either a string or a moodle_url.
+ * @param bool              $update  set this to true to update current active group based on the group param.
+ * @param int               $activegroup Change group active to this group if $update set to true.
+ *
+ * @return string html or void
+ */
+function groups_allgroups_course_menu($course, $urlroot, $update = false, $activegroup = 0) {
+    global $SESSION, $OUTPUT, $USER;
+
+    $groupmode = groups_get_course_groupmode($course);
+    $context = context_course::instance($course->id);
+    $groupsmenu = array();
+
+    if (has_capability('moodle/site:accessallgroups', $context)) {
+        $groupsmenu[0] = get_string('allparticipants');
+        $allowedgroups = groups_get_all_groups($course->id, 0, $course->defaultgroupingid);
+    } else {
+        $allowedgroups = groups_get_all_groups($course->id, $USER->id, $course->defaultgroupingid);
+    }
+
+    if ($update) {
+        $SESSION->activegroup[$course->id][$groupmode][$course->defaultgroupingid] = $activegroup;
+    }
+
+    foreach ($allowedgroups as $group) {
+        $groupsmenu[$group->id] = format_string($group->name);
+    }
+    $grouplabel = get_string('groups');
+    if (count($groupsmenu) == 0) {
+        return '';
+    } else if (count($groupsmenu) == 1) {
+        $groupname = reset($groupsmenu);
+        $output = $grouplabel.': '.$groupname;
+    } else {
+        $select = new single_select(new moodle_url($urlroot), 'group', $groupsmenu, $activegroup, null, 'selectgroup');
+        $select->label = $grouplabel;
+        $output = $OUTPUT->render($select);
+    }
+
+    return $output;
+
+}
+
 /**
  * Print group menu selector for activity.
  *
index 9c16b45..f88c153 100644 (file)
@@ -660,4 +660,63 @@ class core_grouplib_testcase extends advanced_testcase {
         $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($cm3, $course1));
         $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($modinfo->cms[$cm3->id]));
     }
+
+    /**
+     * Tests for groups_allgroups_course_menu() .
+     */
+    public function test_groups_allgroups_course_menu() {
+        global $SESSION;
+
+        $this->resetAfterTest();
+
+        // Generate data.
+        $course = $this->getDataGenerator()->create_course();
+        $record = new stdClass();
+        $record->courseid = $course->id;
+        $group1 = $this->getDataGenerator()->create_group($record);
+        $group2 = $this->getDataGenerator()->create_group($record);
+        $user = $this->getDataGenerator()->create_user();
+        $this->getDataGenerator()->enrol_user($user->id, $course->id);
+        $this->setUser($user);
+
+        $html = groups_allgroups_course_menu($course, 'someurl.php');
+        // Since user is not a part of this group and doesn't have accessallgroups permission,
+        // the html should be empty.
+        $this->assertEmpty($html);
+
+        groups_add_member($group1->id, $user);
+        // Now user can access one of the group. We can't assert an exact match here because of random ids generated by yui. So do
+        // partial match to see if all groups are listed or not.
+        $html = groups_allgroups_course_menu($course, 'someurl.php');
+        $this->assertContains(format_string($group1->name), $html);
+        $this->assertNotContains(format_string($group2->name), $html);
+
+        $this->setAdminUser();
+
+        // Now user can access everything.
+        $html = groups_allgroups_course_menu($course, 'someurl.php');
+        $this->assertContains(format_string($group1->name), $html);
+        $this->assertContains(format_string($group2->name), $html);
+
+        // Make sure separate groups mode, doesn't change anything.
+        $course->groupmode = SEPARATEGROUPS;
+        update_course($course);
+        $html = groups_allgroups_course_menu($course, 'someurl.php');
+        $this->assertContains(format_string($group1->name), $html);
+        $this->assertContains(format_string($group2->name), $html);
+
+        // Make sure Visible groups mode, doesn't change anything.
+        $course->groupmode = VISIBLEGROUPS;
+        update_course($course);
+        $html = groups_allgroups_course_menu($course, 'someurl.php');
+        $this->assertContains(format_string($group1->name), $html);
+        $this->assertContains(format_string($group2->name), $html);
+
+        // Let us test activegroup changes now.
+        $SESSION->activegroup[$course->id][VISIBLEGROUPS][$course->defaultgroupingid] = 5;
+        groups_allgroups_course_menu($course, 'someurl.php', false); // Do not update session.
+        $this->assertSame(5, $SESSION->activegroup[$course->id][VISIBLEGROUPS][$course->defaultgroupingid]);
+        groups_allgroups_course_menu($course, 'someurl.php', true, 2); // Update session.
+        $this->assertSame(2, $SESSION->activegroup[$course->id][VISIBLEGROUPS][$course->defaultgroupingid]);
+    }
 }
index 34f5210..6b6a7ab 100644 (file)
@@ -36,6 +36,7 @@ $timefrom   = optional_param('timefrom', 0, PARAM_INT); // how far back to look.
 $action     = optional_param('action', '', PARAM_ALPHA);
 $page       = optional_param('page', 0, PARAM_INT);                     // which page to show
 $perpage    = optional_param('perpage', DEFAULT_PAGE_SIZE, PARAM_INT);  // how many per page
+$currentgroup = optional_param('group', 0, PARAM_INT); // Get the active group.
 
 $url = new moodle_url('/report/participation/index.php', array('id'=>$id));
 if ($roleid !== 0) $url->param('roleid');
@@ -164,10 +165,28 @@ echo '<input type="submit" value="'.get_string('go').'" />'."\n</div></form>\n";
 
 $baseurl =  $CFG->wwwroot.'/report/participation/index.php?id='.$course->id.'&amp;roleid='
     .$roleid.'&amp;instanceid='.$instanceid.'&amp;timefrom='.$timefrom.'&amp;action='.$action.'&amp;perpage='.$perpage;
+$select = groups_allgroups_course_menu($course, $baseurl, true, $currentgroup);
+
+// User cannot see any group.
+if (empty($select)) {
+    echo $OUTPUT->heading(get_string("notingroup"));
+    echo $OUTPUT->footer();
+    exit;
+} else {
+    echo $select;
+}
 
 if (!empty($instanceid) && !empty($roleid)) {
     // from here assume we have at least the module we're using.
     $cm = $modinfo->cms[$instanceid];
+
+    // Group security checks.
+    if (!groups_group_visible($currentgroup, $course, $cm)) {
+        echo $OUTPUT->heading(get_string("notingroup"));
+        echo $OUTPUT->footer();
+        exit;
+    }
+
     $modulename = get_string('modulename', $cm->modname);
 
     include_once($CFG->dirroot.'/mod/'.$cm->modname.'/lib.php');
@@ -223,9 +242,16 @@ if (!empty($instanceid) && !empty($roleid)) {
     // We want to query both the current context and parent contexts.
     list($relatedctxsql, $relatedctxparams) = $DB->get_in_or_equal($context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'relatedctx');
 
+    $groupsql = "";
+    if (!empty($currentgroup)) {
+        $groupsql = "JOIN {groups_members} gm ON (gm.userid = u.id AND gm.groupid = :groupid)";
+        $params['groupid'] = $currentgroup;
+    }
+
     $sql = "SELECT ra.userid, u.firstname, u.lastname, u.idnumber, l.actioncount AS count
             FROM (SELECT * FROM {role_assignments} WHERE contextid $relatedctxsql AND roleid = :roleid ) ra
             JOIN {user} u ON u.id = ra.userid
+            $groupsql
             LEFT JOIN (
                 SELECT userid, COUNT(action) AS actioncount FROM {log} WHERE cmid = :instanceid AND time > :timefrom AND $actionsql GROUP BY userid
             ) l ON (l.userid = ra.userid)";
@@ -247,6 +273,7 @@ if (!empty($instanceid) && !empty($roleid)) {
     $countsql = "SELECT COUNT(DISTINCT(ra.userid))
                    FROM {role_assignments} ra
                    JOIN {user} u ON u.id = ra.userid
+                   $groupsql
                   WHERE ra.contextid $relatedctxsql AND ra.roleid = :roleid";
 
     $totalcount = $DB->count_records_sql($countsql, $params);