Groups documentation for module developers

From MoodleDocs
Warning: This page is no longer in use. The information contained on the page should NOT be seen as relevant or reliable.

See Groups for updated information.

Groups in Moodle for developers

This documentation does not refer to current versions of Moodle and is here at the moment purely in order to obtain comments. Descriptions of how groups work refer to how they hopefully work not how they will work now! This document is also written in the present tense even though it doesn't refer to the current version of Moodle. This is so I don't have to go through and change it all in a month or two's time.

How groups work in Moodle

There is a separate document on How groups work in Moodle which is worth reading for background especially if you are new to groups in Moodle, although most of the details aren't relevant for module developers. From a module developer's point of view, the differences aren't actually too big. The main changes is that there may be a different set of groups being used for each instance of you module in the course and that separate/visible groups have been replaced by a better system of permissions. The other big changes are all being handled by code elsewhere. There have also been some changes to the database structure for groups (for instance there is now a separate course_group table rather than courseid being a column in the groups table which may affect your code if it has been accessing the database directly for some reason).

As well as modules, there are also some blocks and global features such as blogs and the calendar that use groups in certain ways. We'll come to those later.

It is obviously good if modules support groups in the ways that users expect! This document is here to try and help you do that - if anything isn't clear, you have questions or can think of improvements to how groups work in Moodle, please post on the Groups forum on

How should modules support groups?

There are two main ways a module might need to support groups. There may of course be other more unusual ways in which your module should supports groups, but these should hopefully be the most common ones. The important thing is to think about how people would expect your module to behave if they chose to use groups for it.

From a student's point of view

From a student's point of view, groups are generally used as a way to enable parallel versions of the same activity with different groups of students e.g you might want a separate forum or wiki for each group. If your module is collaborative in any way (which includes the ability to view the existence of other students or their contributions) then you need to make sure that this is supported.

As well as the obvious views of activities being separated, you will need to make sure that things like searches return the correct results and that teachers can view the correct groups. You may also need to make a decision as to which teacher activity is part of the setup of the activity so is the same for every group and needs to be performed only once, and which teacher activity is the contribution after the activity has started and so is different for each group.

In general if your module needs to support groups in this way, you will find that the database table(s) where you store the students' contributions will probably need an extra 'groupid' column, for instance the forum table has a groupid column.

From a teacher's point of view

From a teacher's point of view, groups are generally used to manage different groups of students. For instance there may be several teachers on a course each assigned to one or more groups of students who mark the work for the groups of students that have been assigned to them but shouldn't be able to mark the work of the other groups. A single teacher may also want to be able to view marks for students by group when they teach the same material to two different classes. In general, if your module enables teachers to somehow view students' contribution, then you need to provide this type of support. You can usually do this by checking which students are in which group rather than needing to alter the module's database tables in any way.

Dealing with users in more than one group

Although users may be belong to more than one group, most of the time you can use the groups library for modules to deal with this rather than having to worry about this yourself. There will be more about this in the next section. The time you will probably find that you need to worry about this is when for instance you are doing a search for contributions that a particular student is allowed to view. In this case you will need to look for contributions for all the groups rather than just one group.

The groups library for modules

The functions at your disposal can be found in course/groups/lib/modulelib.php - go and have a quick look at it now. (Again you can't yet, but look here at the Groups API for modules instead) Here are some examples of common ways in which you might want to use the functions in it. Note that modules don't actually need to know anything about groupings directly - the correspondence between an instance of a module and a grouping is taken care of by the library.

1) Present a user with a page containing the right information for one of the groups that they belong to including a selector to see the equivalent page for any other groups that they belong to. e.g. present a user with a list of discussion for a group they belong to.

if (groups_m_uses_groups($cmid)) {
    $permissiontype = GROUPS_STUDENT_CONTRIBUTE;
    groups_m_print_group_selector($cmid, $urlroot, $permissiontype);
    $currentgroupid = groups_m_get_selected_group($cmid, $permissiontype);
    // This is your function that you've written. 
    do_whizzy_module_stuff_for_group($cmid, $currentgroupid); 
} else {
    // Do whatever you'd normally do

2) Present a user with search results only for the groups that they are allowed to view.

if (groups_m_uses_groups($cmid)) {
    $permissiontype = GROUPS_VIEW;
    $groupids = groups_m_get_groups_for_user($cmid, $permissiontype);
    // You might want the search funtion to check group permissions too to be 
    // on the safe side. 
   get_module_search_results_for_groups($groupids, $maybesomeotherparameters);
} else {
    // Do whatever you'd normally do

3) Get a list of users which a teacher should be able to mark work

if (groups_m_uses_groups($cmid)) {
    $permissiontype = GROUPS_TEACHER_CONTRIBUTE;
    groups_m_print_group_selector($cmid, $urlroot, $permissiontype);
    $groupid = groups_m_get_selected_group($cmid, $permissiontype);
    $userids = groups_m_get_members($groupid);
} else {
    // Get your userids the normal way
// Do whatever you'd normally do with the userids. 

It is still ok to use inner joins on the groups_members table in the database for this type of functionality as obviously this is sometimes required for performance reasons, but make sure you keep your code that queries the database clearly separated from your other code.

Support for legacy code

The following functions should still be supported but are deprecated:














Where appropriate, if a grouping has been specified in the course setting for use for all activities that grouping will be used in what was previously 'separate groups' mode. If no such grouping has been specified then the first grouping created for the course that still exists will be used, again in separate groups mode. If you want better support than this, then I'm afraid you will need to update the code for your module!

Accessing the groups_members table directly should still work (although it is not recommended unless you need to do an inner join on it for performance reasons). Directly accessing the groups table may not work because the course column has been removed.

The groupid argument in the function search_users from datalib.php will still work, but will only give members of a group, not those with a specific permission.

Blocks and other special cases

There is an essentially identical library for blocks as for modules, only all the _m_'s in the function names are replaced by _b_'s.

At the moment there is no standard way to set the grouping for a block and most blocks don't need to use groups. If you want to create a way for someone to set up a grouping for your block then you will need to do this yourself using the functions in the other parts of the groups library (under course/groups/lib/) but ask if you need help. There is a new column in the block_instance table called groupingid that you will need to set using the function groups_set_grouping_for_block_instance. If a grouping is set for all activities for a course then this will get automatically set however.

There are currently two 'global' features in the Moodle core - blogs and the calendar - a quick word on those in case anyone has plug-ins that provide similar global features.

Calendar - with the calendar a teacher can set group events when they are within a course, so basically all they need to do is get all the groups for the course that a teacher has a particular permission for. Then when displaying calendar entries to users, need to know which groups a particular has view permission for across all courses though it's a tiny bit more complicated that this because a grouping can be used for more than one course and someone may be a student on one course and a teacher on another.

Blog - It's possible for the admin to set a blog option that makes blogs view access group level. This means that users can only see blogs of people that they share a group with for some course - there's a function provided in one of the main groups libraries to find out if two users share a group. I'm guessing that you're mostly only wanting to use this with installations with a very small number of teachers and at some point global groups will get used here instead.

At the moment there is generally no general support for global features, but this will hopefully come!

Some rationale

I'll probably add stuff in here as it comes up :-)

Why doesn't this fit in with roles and permissions?

Mostly at the time I started doing this development the roles and permission code wasn't available yet! The changes to roles and permissions are big and the changes needed to fit in with them properly need some thought and would be even more massive than they currently are. It seemed better to get the main improvements to groups in first and give the roles and permissions code a bit of time to settle. It would be nice if they are integrated sensible eventually.

Why do I have to deal separately with the case where the module uses groups and the case where it doesn't? Isn't there a clever way to do this so I don't have to?

Yes, but I wanted to try and keep people's code fairly readable and make it as easy as possible to shift current over. In practice you shouldn't really have too much extra code this way anyhow - you can always write functions with a groupid argument that defaults to false.