Skip to end of metadata
Go to start of metadata

One of the features Code for Change is implementing for CiviCRM 2.0 is nestable groups. This means you can put groups inside groups inside groups inside... This is designed to make it easier to support multiple organizations in one installation of CiviCRM where the individual organizations need to be able to view and edit all their contacts and put them into groups, but a service provider or federation organization (think national organization w/ regional affiliates) needs to be able to aggregate the data across all the organizations. I go into more detail about the specific use case for U.S. PIRG (the sponsoring organization of Code for Change) here: There are certainly lots of other use cases for nestable groups, and this will be a generic implementation that should support any of them. There is further discussion of this in the forums here:,636.0.html

At first, we considered implementing this using the nested set model for hierarchical data in a relational database system. However, this model assumes single-parent relationships, and we want to support multiple parent groups. So the implementation we decided on was to create a civicrm_group_nesting table with the fields child_group_id and parent_group_id in it. This defines the parent<->child links between the groups. The code will enforce that circular references aren't created and aren't followed if they are created (e.g. by someone mucking around in the database).

We are then going to go through the code where it references the civicrm_group table and see where it makes sense to make those various methods aware of child groups and parent groups. As an example, we'll have to add awareness of child groups to any methods that search a group for something. In order to do that, we'll create a new method that gets called before the actual search query is run that takes the current group_id as an argument (the id of the group you'd otherwise just search under the non-nestable groups scenario) and returns an array of group_ids according to the following algorithm:

Find every row in the civicrm_group_nesting table where parent_group_id = group_id. If no results, return group_id. Else: Re-run this query w/ every returned child_group_id in a list (i.e. WHERE parent_group_id IN (list_of_child_group_ids_from_previous_call)). This will be repeated until no results are returned. It's a basic recursive function. This should be pretty efficient as it gets a whole level in the hierarchy each time it's called, and even the most complex group nestings shouldn't have more than 5 or so levels of nesting.

This is all now implemented (CRM/Contact/BAO/GroupNesting.php--should be in trunk by 7/31/07) and basically working. There are a collection of class methods in that file that allow you to traverse the group graph (multiple parents are allowed, so it's not strictly a tree/hierarchy structure). The methods should be fairly self-explanatory.

We have made most features that deal with groups pull up members of descendant groups as well. Where it makes sense, we're adding "Search subgroups" options to search forms. You can see an example of that in the hidden-by-default "Find members within this group" search box in the group "Members" page.

We also have added an "Add child group" drop-down box in the group "Settings" page. The groups list page will also show you the child groups when viewing the list of groups.

All of these changes should be merged to trunk on 7/31/07.

There are still several places where this needs to be implemented further (such as ACLs and some other search forms). 

  • None

Creative Commons License
Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution-Share Alike 3.0 United States Licence.