Skip to: Site menu | Main content

New Drupal Module: OG Join Role

I recently released the Organic Groups Join Role module on the Drupal web site. The module is designed to add a "join orgranic groups" permission to the main Organic Groups (OG) module .

The basic programming of the module is quite easy, as it simply overrides the Organic Groups "og/subscribe" menu item in order to add the "access" parameter:

function og_joinrole_perm() {
return array('subscribe to organic groups');

function og_joinrole_menu($may_cache) {
$items = array();

if ($may_cache) {
$items[] = array(
'path' => 'admin/og/og_joinrole',
'title' => t('OG joinrole'),
'description' => t('Set various options for the OG join role module.'),
'callback' => 'drupal_get_form',
'callback arguments' => array('og_joinrole_admin_settings'),
'access' => user_access('administer organic groups'),
'description' => t('OG joinrole options.'),

// This menu item overrides the og menu item to add the access stuff. It is outside of $may_cache to help ensure that it is loaded after the og menu item that it is overriding
$items[] = array(
'path' => 'og/subscribe',
'type' => MENU_CALLBACK,
'callback' => 'og_subscribe',
'access' => user_access('subscribe to organic groups'),
'title' => t('Subscribe to group')

return $items;

The og_joinrole_perm hook adds the new access control and the og_joinrole_menu hook adds a callback to an administrative settings page and attempts to override the Organic Group's "og/subscribe" menu item. The tricky part is making sure that the og_joinrole_menu "og/subscribe" menu item gets loaded after the main OG og/subscribe menu item. I utilized 2 methods to help ensure that this happens.

First, I placed the og_joinrole "og/subscribe" menu item outside of the $may_cache block. If you look at the OG menu hook, you'll see that it is inside a $may_cache block. When Drupal builds the menu array, the cached items get loaded first, so the og_joinrole's "og/subscribe" menu item will get loaded after the OG "og/subscribe" menu item thus ensuring that it overwrites it.

The second (and mostly redundant) thing I did was to make sure that og_joinrole's module weight was higher than OG's module weight. I did this using the hook_enable:

function og_joinrole_enable() {
* -set the weight of the module to be higher than that of og so that the menu is sure to get overridden
* -if the weight of the og module gets manually changed, then the weight of this module will need to be manually changed as well to something higher
$ogweight = db_result(db_query("SELECT weight FROM {system} WHERE name='og'"));
db_query("UPDATE {system} SET weight=%d WHERE name='og_joinrole'", $ogweight + 1);

At this point, I could have stopped and the module would have worked, but it wouldn't have been too pretty. Most of the time, in order to subscribe to an OG, the user will click a "subscribe" link in the group's details block. So far, the module doesn't do anything to surpress this link. So, when I user without the proper permission clicked on a "subscribe" link, they'd get an "access denied" page. Effective, but not very user friendly.

Unfortunately, Drupal doesn't offer any sort of Block API to modify other module's blocks before they are displayed. So I turned to jQuery to solve my problem.

if (Drupal.jsEnabled) {
//----- replaces any subscribe links
theparent = $("a[@href*=og/subscribe]").parent();

//----- replaces any "you must register/login in order..." text
theli = $("div[@id^=block-og] li").contains("in order to post into this group");

The og_joinrole.js file uses jQuery to make a couple of substitutions in order to "hide" subscribe links and alter some group subscribe text. The og_joinrole_replacementtext is set by the site admin on the og_joinrole admin settings page and then added to the page's javascript using drupal_add_js in the og_joinrole_footer hook. This way, the site admin can easily modify the replacement text.

function og_joinrole_footer() {
/* This replaces any og subscribe links with the text specified on the settings page via javascript.
* One weakness of this is that the JavaScript uses some English-only searching to accomplish this.
* Non-English languages will need to modify the og_joinrole.js with the search text in their language.
if (!user_access('subscribe to organic groups')) {
$js = "var og_joinrole_replacementtext = '". variable_get('og_joinrole_replacementtext', t('You do not have the proper role to join this group or view its private messages.')) ."';";
drupal_add_js($js, 'inline');
drupal_add_js('sites/all/modules/og_joinrole/og_joinrole.js', 'module');

As is written in the code comments, the main weakness of this code is that it is geared towards the default Drupal english language distribution, as it uses some default english text to search for when replacing it.

This module was written for Drupal 5. It was sponsored by the Florida Green Building Association (FGBC). On their (future) web site, they wanted to allow only paid FGBC members to be able to join FGBC committees (groups). This module allows them to do this without hacking Organic Groups.

Let me know if you use this module, I'd love to see other applications for it.

Submitted by michael on Wed, 04/04/2007 - 1:00am
Filed under: