og_notifications.module in Organic groups 5
Same filename and directory in other branches
Subscriptions to content in groups.
Group subscriptions are allowed for users who have view access to the group node. Whether a user can get a notification about a specific post will be decided later.
File
og_notifications/og_notifications.moduleView source
<?php
/**
* @file
* Subscriptions to content in groups.
*
* Group subscriptions are allowed for users who have view access to the group
* node. Whether a user can get a notification about a specific post will be
* decided later.
*/
/**
* Implementation of hook_menu_()
*/
function og_notifications_menu($may_cache) {
global $user;
// we need the user to to build some urls
$items = array();
if (!$may_cache) {
if ($user->uid && arg(0) == 'user' && is_numeric(arg(1)) && arg(2) == 'notifications' && ($user->uid == arg(1) || user_access('administer notifications'))) {
$account = $user->uid == arg(1) ? $user : user_load(array(
'uid' => arg(1),
));
$items[] = array(
'path' => 'user/' . $account->uid . '/notifications/group',
'access' => user_access('subscribe to content in groups'),
'title' => t('Groups'),
'callback' => 'drupal_get_form',
'callback arguments' => array(
'og_notifications_user_page',
$account,
),
'type' => MENU_LOCAL_TASK,
'weight' => 10,
);
$items[] = array(
'path' => 'user/' . $account->uid . '/notifications/grouptype',
'access' => user_access('subscribe to content in groups'),
'title' => t('Groups'),
'callback' => 'og_notifications_grouptype_user_page',
'callback arguments' => array(
$account,
),
'type' => MENU_CALLBACK,
);
}
}
return $items;
}
/**
* Implementation of hook_perm()
*/
function og_notifications_perm() {
return array(
'subscribe to content in groups',
);
}
/**
* Implementation of hook_form_alter().
*/
function og_notifications_form_alter($form_id, &$form) {
switch ($form_id) {
case 'notifications_content_settings_form':
$form['group'] = array(
'#type' => 'fieldset',
'#title' => t('Group subscriptions'),
'#collapsible' => TRUE,
'#weight' => 0,
);
// General content settings
$select = array();
$nodetypes = node_get_types();
$ogtypes = og_get_types('group_post');
foreach ($ogtypes as $ntype) {
$select[$ntype] = $nodetypes[$ntype]->name;
}
$form['group']['og_notifications_content_types'] = array(
'#type' => 'checkboxes',
'#title' => t('Allowed content types'),
'#default_value' => variable_get('og_notifications_content_types', array()),
'#options' => $select,
'#description' => t('Select specific content types which should be <em>allowed</em> for subscriptions to <em>group + content type</em>.'),
'#multiple' => TRUE,
);
break;
case 'user_edit':
// TODO: Is perm checking necessary here?
// Insert autosubscribe option into the messaging section of the user edit
// form.
$account = $form['_account']['#value'];
// TODO: Strings need to conform with OG and notifications terminology.
$form['messaging']['og_notifications_autosubscribe'] = array(
'#type' => 'checkbox',
'#title' => t('Automatically enable notifications for any organic groups that I join.'),
'#description' => t('Group notifications can be <a href="!manage-url">customised</a> in greater detail if necessary.', array(
'!manage-url' => url('user/' . $account->uid . '/notifications/group'),
)),
'#default_value' => isset($account->og_notifications_autosubscribe) ? $account->og_notifications_autosubscribe : variable_get('og_notifications_autosubscribe', 1),
);
break;
case 'og_admin_settings':
// Insert the global autosubsribe checkbox into the OG administration
// page. The fieldset should probably be renamed?
$form['og_settings']['email']['og_notifications_autosubscribe'] = array(
'#type' => 'checkbox',
'#title' => t('Autosubscribe users to any groups that they join.'),
'#description' => t('Automatically enable notifications by default. Users can override this via their account page.'),
'#default_value' => variable_get('og_notifications_autosubscribe', 1),
'#weight' => -1,
);
break;
}
}
/**
* Implementation of hook_nodeapi()
*/
function og_notifications_nodeapi(&$node, $op, $arg = 0) {
switch ($op) {
case 'delete':
// Remove all group subscriptions for this node
notifications_delete_subscriptions(array(
'type' => 'group',
), array(
'group' => $node->nid,
));
notifications_delete_subscriptions(array(
'type' => 'grouptype',
), array(
'group' => $node->nid,
));
}
}
/**
* Implementation of hook_og().
*/
function og_notifications_og($op, $gid, $uid, $args) {
switch ($op) {
case 'user insert':
$account = user_load(array(
'uid' => $uid,
));
og_notifications_user_autosubscribe($account, $gid);
break;
case 'user delete':
$account = user_load(array(
'uid' => $uid,
));
og_notifications_user_unsubscribe($account, $gid);
break;
}
}
/**
* Temporary implementation of hook_og_notify() to override og's inbuilt
* notification system.
*/
function og_notifications_og_notify() {
return TRUE;
}
/**
* Implementation of hook_notifications().
*/
function og_notifications_notifications($op, &$arg0, $arg1 = NULL, $arg2 = NULL) {
switch ($op) {
case 'names':
$subs =& $arg0;
if ($subs->event_type == 'node') {
if (!empty($subs->fields['group']) && ($group = node_load($subs->fields['group']))) {
$subs->names['group'] = t('Group: %name', array(
'%name' => $group->title,
));
}
}
break;
case 'subscription types':
$types['group'] = array(
'event_type' => 'node',
'title' => t('Groups'),
'access' => 'subscribe to content in groups',
'page' => 'og_notifications_user_page',
'fields' => array(
'group',
),
);
$types['grouptype'] = array(
'event_type' => 'node',
'title' => t('Content type in group'),
'access' => 'subscribe to content in groups',
'fields' => array(
'group',
'type',
),
);
return $types;
case 'query':
// $arg0 = 'event' and $arg1 = 'node' and $event = $arg2
// $arg0 = 'user' and $arg1 = 'noe' and $node = $arg2
if ($arg0 == 'event' && $arg1 == 'node' && ($node = $arg2->node) || $arg0 == 'user' && $arg1 == 'node' && ($node = $arg2)) {
$query = array();
if ($node->og_groups) {
$query[] = array(
'join' => "LEFT JOIN {og_ancestry} og ON f.field = 'group' AND f.value = CAST(og.group_nid AS CHAR(255))",
'where' => 'og.nid = %d',
'args' => array(
$node->nid,
),
);
}
if ($arg0 == 'user' && og_is_group_type($node->type)) {
$query[]['fields']['group'] = $node->nid;
}
return $query;
}
break;
case 'node options':
return _og_notifications_node_options($arg0, $arg1);
case 'event load':
// $arg0 is event
// Nothing to load here, the user may be subscribed through one of many parent groups
break;
case 'event types':
// Event types for this are defined in notifications_content module
break;
case 'access':
$type = $arg0;
$account =& $arg1;
$object =& $arg2;
if ($type == 'subscription' && !empty($object->fields['group'])) {
if (($group = node_load($object->fields['group'])) && og_is_group_type($group->type) && notifications_content_node_allow($account, $group)) {
return array(
TRUE,
);
}
else {
return array(
FALSE,
);
}
}
break;
}
}
/**
* Menu callback: Group and grouptype subscription management form. This should
* ideally play nicer with notifications_user_form. However, due to issues with
* support for multi-field subscriptions, it is currently going about things in
* a roundabout manner.
*
* @param Object $account
* User object of the user whose page is to be displayed.
* @return Array $form
* Form array.
*/
function og_notifications_user_page($account = NULL) {
global $user;
$account = $account ? $account : $user;
if (!empty($user->og_groups)) {
$ngroups = _og_notifications_user_groups($account->uid);
$ngrouptypes = _og_notifications_user_grouptypes($account->uid);
// Tap into notifications_user_form to retrieve variables and defaults.
$group_form = notifications_user_form($account, 'group', $ngroups, $user->og_groups, array(
'type' => 'group',
'event_type' => 'node',
), array(
'title' => t('Group'),
));
// Grouptype uses multiple fields which are not addressed adequately by
// notifications_user_form.
$grouptype_form = notifications_user_form($account, 'grouptype', $ngrouptypes, variable_get('og_notifications_content_types', array()), array(
'type' => 'grouptype',
'event_type' => 'node',
), array(
'title' => t('Group Type'),
));
// TODO: Trim unnecessary items.
$form = array(
'account' => $group_form['account'],
'group_defaults' => $group_form['defaults'],
'group_current' => $group_form['current'],
'group_subscription_fields' => $group_form['subscription_fields'],
'grouptype_defaults' => $grouptype_form['defaults'],
'grouptype_current' => $grouptype_form['current'],
'grouptype_subscription_fields' => $grouptype_form['subscription_fields'],
);
$content_types = array_filter(variable_get('og_notifications_content_types', array()));
foreach ($user->og_groups as $gid => $group) {
$group_index = 'groups-' . $gid;
$types = array();
foreach ($content_types as $type => $title) {
// Check if value exists; Only enable node type subscriptions if the
// group is not already subscribed to (for all posts).
$bool = isset($ngrouptypes[$gid]) && isset($ngrouptypes[$gid][$type]);
$types[$type] = array(
'title' => $title,
'checkbox' => $bool,
'send_interval' => $bool ? $ngrouptypes[$gid][$type]->send_interval : $grouptype_form['defaults']['#value']['send_interval'],
'send_method' => $bool ? $ngrouptypes[$gid][$type]->send_method : $grouptype_form['defaults']['#value']['send_method'],
);
}
$all = array(
'all' => array(
'title' => t('All'),
'checkbox' => isset($ngroups[$gid]),
'send_interval' => isset($ngroups[$gid]) ? $ngroups[$gid]->send_interval : $group_form['defaults']['#value']['send_interval'],
'send_method' => $ngroups[$gid]->send_method,
),
);
$types = $all + $types;
$form[$group_index] = array(
'#type' => 'fieldset',
'#title' => check_plain($group['title']),
'#collapsible' => TRUE,
'#collapsed' => !isset($ngroups[$gid]) && empty($ngrouptypes[$gid]),
);
// Reuse theme function.
$form[$group_index]['subscriptions'] = array(
'#tree' => TRUE,
'#parents' => array(
'groups',
$gid,
),
'#theme' => 'notifications_form_table',
'#header' => array(
theme('table_select_header_cell'),
t('Type'),
t('Send interval'),
t('Send method'),
),
);
foreach ($types as $key => $value) {
$form[$group_index]['subscriptions']['checkbox'][$key] = array(
'#type' => 'checkbox',
'#default_value' => $value['checkbox'],
);
$form[$group_index]['subscriptions']['title'][$key] = array(
'#value' => t('%type posts in this group', array(
'%type' => $value['title'],
)),
);
$form[$group_index]['subscriptions']['send_interval'][$key] = array(
'#type' => 'select',
'#options' => _notifications_send_intervals(),
'#default_value' => $value['send_interval'],
);
$form[$group_index]['subscriptions']['send_method'][$key] = array(
'#type' => 'select',
'#options' => _notifications_send_methods(),
'#default_value' => $value['send_method'],
);
}
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
}
else {
drupal_set_message(t('There are no active group subscriptions available.'));
}
return $form;
}
/**
* Process og_notifications_user_page form submission.
*
* @todo Decide on whether to allow contenttype and "all" subscriptions for the
* same group.
*/
function og_notifications_user_page_submit($form, $form_values) {
$groups = $grouptypes = array();
$current = $form_values['grouptype_current'];
foreach ($form_values['groups'] as $gid => $values) {
$groups['checkbox'][$gid] = $values['checkbox']['all'];
$groups['send_interval'][$gid] = $values['send_interval']['all'];
$groups['send_method'][$gid] = $values['send_method']['all'];
unset($form_values['groups'][$gid]['checkbox']['all'], $form_values['groups'][$gid]['send_interval']['all'], $form_values['groups'][$gid]['send_method']['all']);
// Save grouptype subscriptions directly as notifications_user_form_submit
// does not handle multiple-field notifications very well.
foreach ($form_values['groups'][$gid]['checkbox'] as $type => $check) {
$subscription = NULL;
if ($check == 1) {
if (!isset($current[$gid]) || !isset($current[$gid][$type])) {
$subscription = $form_values['grouptype_defaults'] + array(
'uid' => $form_values['account']->uid,
);
}
elseif ($current[$gid][$type]->send_interval != $values['send_interval'][$type] || $current[$gid][$type]->send_method != $values['send_method'][$type]) {
$subscription = (array) $current[$gid][$type];
}
if ($subscription) {
$subscription['send_interval'] = $values['send_interval'][$type];
$subscription['send_method'] = $values['send_method'][$type];
$subscription['fields'] = array(
'group' => $gid,
'type' => $type,
);
notifications_save_subscription($subscription);
}
}
elseif (isset($current[$gid]) && isset($current[$gid][$type])) {
notifications_delete_subscription($current[$gid][$type]->sid);
}
}
}
// Save group changes.
$group_submit = array(
'account' => $form_values['account'],
'current' => $form_values['group_current'],
'defaults' => $form_values['group_defaults'],
'subscription_fields' => $form_values['group_subscription_fields'],
'subscriptions' => $groups,
);
notifications_user_form_submit('og_notifications_user_page', $group_submit);
}
/**
* Menu callback: Since the default notifications UI lists group and grouptype
* as separate entries, redirect the grouptype management link to the group
* management page.
*
* @param Object $account
* User object of the user whose grouptypes are to be managed.
*/
function og_notifications_grouptype_user_page($account) {
drupal_goto('user/' . $account->uid . '/notifications/group');
}
/**
* Handle autosubscriptions for users when they join a group.
*
* @param Object $account
* The user account object.
* @param Integer $gid
* The node ID of the group being subscribed to.
*/
function og_notifications_user_autosubscribe($account, $gid) {
if (isset($account->og_notifications_autosubscribe) ? $account->og_notifications_autosubscribe : variable_get('og_notifications_autosubscribe', 1)) {
og_notifications_user_subscribe($account, $gid);
}
}
/**
* Subscribe a user to a group.
*
* @param Object $account
* The user account object.
* @param Integer $gid
* The node ID of the group being subscribed to.
*/
function og_notifications_user_subscribe($account, $gid) {
$subscription = _notifications_subscription_defaults($account);
$subscription['uid'] = $account->uid;
$subscription['type'] = 'group';
$subscription['event_type'] = 'node';
$subscription['fields'] = array(
'group' => $gid,
);
notifications_save_subscription($subscription);
}
/**
* Unsubscribe a user from a group. This also unsunscribes the user from any
* grouptype subscriptions within the group.
*
* @param Object $account
* The user account object.
* @param Integer $gid
* The node ID of the group being subscribed to.
*/
function og_notifications_user_unsubscribe($account, $gid) {
// @todo: Handle direct node subscriptions for private groups.
// Niche cases include multi-group nodes.
notifications_delete_subscriptions(array(
'uid' => $account->uid,
'type' => 'grouptype',
), array(
'group' => $gid,
));
notifications_delete_subscriptions(array(
'uid' => $account->uid,
'type' => 'group',
), array(
'group' => $gid,
));
}
/**
* Retrieve a list of organic groups that a user is subscribed (via
* notifications) to.
*
* @param Integer $uid
* The user ID of the user whose groups are to be retrieved.
* @return Array $ngroups
* An associative array of the resulting groups.
*/
function _og_notifications_user_groups($uid) {
// No checks for group published or not?
$query = "SELECT no.*, nof.value AS nid, n.type AS node_type, n.title FROM {notifications} no\n INNER JOIN {notifications_fields} nof ON no.sid = nof.sid LEFT JOIN {node} n ON nof.value = CAST(n.nid AS CHAR(255))\n WHERE no.uid = %d AND (no.type = 'group') AND no.conditions = 1 AND nof.field = 'group'\n ORDER BY node_type, n.title";
$results = db_query($query, $uid);
$ngroups = array();
while ($sub = db_fetch_object($results)) {
$ngroups[$sub->nid] = $sub;
}
return $ngroups;
}
/**
* Retrieve a list of organic group content types that a user is subscribed (via
* notifications) to.
*
* @param Integer $uid
* The user ID of the user whose groups are to be retrieved.
* @return Array $ngrouptypes
* An associative array of the resulting content types sorted by groups.
*/
function _og_notifications_user_grouptypes($uid) {
$query = "SELECT no.*, nof1.value AS group_nid, nof2.value AS node_type FROM {notifications} no\n INNER JOIN {notifications_fields} nof1 ON no.sid = nof1.sid\n INNER JOIN {notifications_fields} nof2 ON no.sid = nof2.sid\n WHERE no.uid = %d AND (no.type = 'grouptype') AND no.conditions = 2 AND nof1.field = 'group' AND nof2.field = 'type'\n ORDER BY group_nid, node_type";
$results = db_query($query, $uid);
$ngrouptypes = array();
while ($sub = db_fetch_object($results)) {
$ngrouptypes[$sub->group_nid][$sub->node_type] = $sub;
}
return $ngrouptypes;
}
/**
* Options to display for node subscriptions.
*/
function _og_notifications_node_options($account, $node) {
// If node is a group type
if (og_is_group_type($node->type)) {
$options[] = array(
'name' => t('To all posts in this group'),
'type' => 'group',
'fields' => array(
'group' => $node->nid,
),
);
foreach (array_filter(variable_get('og_notifications_content_types', array())) as $type) {
$options[] = array(
'name' => t('%type posts in this group', array(
'%type' => node_get_types('name', $type),
)),
'type' => 'grouptype',
'fields' => array(
'group' => $node->nid,
'type' => $type,
),
);
}
}
// If node is part of a group user may be subscribed to the node through one of the groups
if ($node->og_groups) {
foreach ($node->og_groups as $index => $gid) {
// Content type
$options[] = array(
'name' => t('Posts in group %name', array(
'%name' => $node->og_groups_both[$gid],
)),
'type' => 'group',
'fields' => array(
'group' => $gid,
),
);
$options[] = array(
'name' => t('%type posts in this group', array(
'%type' => node_get_types('name', $node->type),
)),
'type' => 'grouptype',
'fields' => array(
'group' => $gid,
'type' => $node->type,
),
);
}
}
return $options;
}
Functions
Name | Description |
---|---|
og_notifications_form_alter | Implementation of hook_form_alter(). |
og_notifications_grouptype_user_page | Menu callback: Since the default notifications UI lists group and grouptype as separate entries, redirect the grouptype management link to the group management page. |
og_notifications_menu | Implementation of hook_menu_() |
og_notifications_nodeapi | Implementation of hook_nodeapi() |
og_notifications_notifications | Implementation of hook_notifications(). |
og_notifications_og | Implementation of hook_og(). |
og_notifications_og_notify | Temporary implementation of hook_og_notify() to override og's inbuilt notification system. |
og_notifications_perm | Implementation of hook_perm() |
og_notifications_user_autosubscribe | Handle autosubscriptions for users when they join a group. |
og_notifications_user_page | Menu callback: Group and grouptype subscription management form. This should ideally play nicer with notifications_user_form. However, due to issues with support for multi-field subscriptions, it is currently going about things in a roundabout manner. |
og_notifications_user_page_submit | Process og_notifications_user_page form submission. |
og_notifications_user_subscribe | Subscribe a user to a group. |
og_notifications_user_unsubscribe | Unsubscribe a user from a group. This also unsunscribes the user from any grouptype subscriptions within the group. |
_og_notifications_node_options | Options to display for node subscriptions. |
_og_notifications_user_groups | Retrieve a list of organic groups that a user is subscribed (via notifications) to. |
_og_notifications_user_grouptypes | Retrieve a list of organic group content types that a user is subscribed (via notifications) to. |