og_notifications.module in Organic groups 6.2
Same filename and directory in other branches
Provide notifications and messaging support for organic groups.
@author Karthik Kumar / Zen [ http://drupal.org/user/21209 ].
File
modules/og_notifications/og_notifications.moduleView source
<?php
/**
* @file
* Provide notifications and messaging support for organic groups.
*
* @author Karthik Kumar / Zen [ http://drupal.org/user/21209 ].
*/
/**
* Implementation of hook_help().
*/
function og_notifications_help($path, $arg) {
global $user;
switch ($path) {
case 'user/%/notifications/group':
return t('Customize notifications for each of your groups and each of their content types along with their frequency and delivery method.');
}
}
/**
* Implementation of hook_menu().
*/
function og_notifications_menu() {
$items = array();
$items['user/%user/notifications/add/grouptype'] = array(
'title' => 'Group notifications',
'page callback' => 'og_notifications_user_page',
'page arguments' => array(
1,
),
'access callback' => 'notifications_content_access',
'access arguments' => array(
1,
'subscribe to content in groups',
),
'type' => MENU_LOCAL_TASK,
'weight' => 10,
'file' => 'og_notifications.pages.inc',
);
return $items;
}
/**
* Implementation of hook_perm().
*/
function og_notifications_perm() {
return array(
'subscribe to content in groups',
);
}
/**
* Implementation of hook_user().
* Handle uid entry in the og_notifications table.
*/
function og_notifications_user($type, &$edit, &$user, $category = NULL) {
switch ($type) {
case 'insert':
db_query("INSERT INTO {og_notifications} (uid) VALUES (%d)", $user->uid);
break;
case 'update':
if (isset($edit['og_notifications_autosubscribe'])) {
og_notifications_user_autosubscribe_set($user->uid, $edit['og_notifications_autosubscribe']);
unset($edit['og_notifications_autosubscribe']);
}
break;
case 'delete':
db_query("DELETE FROM {og_notifications} WHERE uid = %d", $user->uid);
break;
}
}
/**
* Implementation of hook_form_alter().
*/
function og_notifications_form_alter(&$form, $form_state, $form_id) {
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 'notifications_add_subscription_form':
// Remove unauthorised node types.
if ($form['type']['#value'] == 'grouptype') {
$content_types = array_filter(variable_get('og_notifications_content_types', array()));
$form['info']['fields'][1]['value']['#options'] = array_intersect_key($form['info']['fields'][1]['value']['#options'], $content_types);
}
break;
case 'user_profile_form':
// Insert autosubscribe option into the messaging section of the user edit
// form.
// user_profile_form is, oddly enough, also the form_id for forms in other
// sub-tabs such as those added by the profile module.
if ($form['_category']['#value'] == 'account') {
$account = $form['_account']['#value'];
$form['messaging']['og_notifications_autosubscribe'] = array(
'#type' => 'checkbox',
'#title' => t('Automatically enable notifications for any groups that I join.'),
'#description' => t('Group notifications can also be <a href="!manage-url">customized</a> in greater detail if required.', array(
'!manage-url' => url('user/' . $account->uid . '/notifications/group'),
)),
'#default_value' => og_notifications_user_autosubscribe_get($account->uid),
'#access' => notifications_content_access($account, 'subscribe to content in groups'),
);
}
break;
case 'og_admin_settings':
unset($form['og_new_node_subject'], $form['og_new_node_body']);
$form['og_settings']['notifications']['#description'] = t('Node event notifications can be configured via the <a href="!url">messaging templates</a> interface.', array(
'!url' => url('admin/messaging/template'),
));
// Default autosubscription setting.
$form['og_settings']['notifications']['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. Changing this setting will only affect new users and those who have not overridden the system default.'),
'#default_value' => variable_get('og_notifications_autosubscribe', 1),
'#weight' => -5,
);
break;
}
}
/**
* Implementation of hook_nodeapi().
*/
function og_notifications_nodeapi(&$node, $op, $arg = 0) {
switch ($op) {
case 'delete':
notifications_delete_subscriptions(array(
'type' => 'grouptype',
), array(
'group' => $node->nid,
));
break;
}
}
/**
* 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;
case 'user request':
// This and other notifications related ops drop down to the same case.
// These different ops have been provided for consistency and flexibility
// during use by other modules.
case 'user approve':
case 'user deny':
case 'admin create':
case 'admin new':
case 'admin remove':
case 'user broadcast':
$destinations = is_array($uid) ? $uid : array(
$uid,
);
foreach ($destinations as $uid) {
notifications_lite_send($uid, $args['subject'], $args['body']);
}
break;
}
}
/**
* Implementation of hook_messaging().
*/
function og_notifications_messaging($op, $arg1 = NULL, $arg2 = NULL, $arg3 = NULL, $arg4 = NULL) {
switch ($op) {
case 'message groups':
// Generic notifications event
$info['og-notifications'] = array(
'module' => 'og_notifications',
'name' => t('OG notifications (default)'),
'help' => t('Most fields will be provided during the event.'),
'description' => t('Notifications for organic groups node events. Other group notification strings can be customized via the <a href="!url">OG config</a> page.', array(
'!url' => url('admin/og/og'),
)),
);
$info['og-notifications-insert'] = array(
'module' => 'og_notifications',
'name' => t('OG notifications for new content'),
'help' => t('Most fields will be provided during the event.'),
'description' => t('Notifications for organic groups node creation events.'),
);
$info['og-notifications-update'] = array(
'module' => 'og_notifications',
'name' => t('OG notifications for updated content'),
'help' => t('Most fields will be provided during the event.'),
'description' => t('Notifications for organic groups node update events.'),
);
$info['og-notifications-comment'] = array(
'module' => 'og_notifications',
'name' => t('OG notifications for comments'),
'help' => t('Most fields will be provided during the event.'),
'description' => t('Notifications for organic groups comment events.'),
);
return $info;
case 'message keys':
switch ($arg1) {
case 'og-notifications':
case 'og-notifications-insert':
case 'og-notifications-update':
case 'og-notifications-comment':
return array(
'subject' => t('Subject'),
'header' => t('Body header'),
'main' => t('Body'),
'footer' => t('Body footer'),
);
break;
}
break;
case 'messages':
$template = array(
'subject' => t('[site-name] [ogname]: [title]'),
'header' => t("Greetings, [user],"),
'main' => array(
t('A [type-name] has been updated in group [ogname]: [title]'),
t('[node-teaser]'),
t('Read more at [node-url].'),
),
'footer' => array(
t('This is an automatic message from [site-name]'),
t('To manage your subscriptions, browse to [subscriptions-manage]'),
),
);
switch ($arg1) {
case 'og-notifications':
case 'og-notifications-update':
return $template;
case 'og-notifications-insert':
$template['main'] = array(
t('A [type-name] has been created in group [ogname]: [title]'),
t('[node-teaser]'),
t('Read more at [node-url].'),
);
return $template;
case 'og-notifications-comment':
$template['main'] = array(
t('A new comment has been added by [comment-author-name] to this thread in group [ogname]: [comment-title]'),
t('[comment-body]'),
t('Read more at [comment-url] or reply via [comment-reply-url].'),
);
return $template;
}
break;
case 'tokens':
$tokens = array();
if (strpos($arg1, 'og-notifications') === 0) {
$tokens = array(
'global',
'subscription',
'user',
'node',
'comment',
);
}
return $tokens;
}
}
/**
* A workaround to ensure that OG can provide custom message templates for
* notifications.
*
* @param Object $message
* The message object.
* @param Object $info
* Sending method information.
*/
function og_notifications_message_alter(&$message, $info) {
if ($sid = _og_notification_check_message($message)) {
$event = $message->notifications['events'][0];
// Cater for different message groups (actions).
$group = 'og-notifications-' . $event->action;
$send_method = $message->method;
$subscription = notifications_load_subscription($sid);
$text = array(
'subject' => messaging_message_part($group, 'subject', $send_method, $event),
'header' => messaging_message_part($group, 'header', $send_method, $event),
'footer' => messaging_message_part($group, 'footer', $send_method, $event),
);
if (isset($message->body['main'])) {
$text['main'] = messaging_message_part($group, 'main', $send_method, $event);
}
else {
$text['event'] = messaging_message_part($group, 'main', $send_method, $event);
}
$objects = array(
'user' => $message->account,
'node' => $event->objects['node'],
'subscription' => $subscription,
);
if ($event->action == 'comment') {
$objects['comment'] = $event->objects['comment'];
}
$objects = array_merge($objects, $event->objects);
$text = messaging_text_replace($text, $objects);
$message->subject = $text['subject'];
unset($text['subject']);
$message->body = array_merge($message->body, $text);
}
}
/**
* 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['grouptype'] = array(
'event_type' => 'node',
'title' => t('Content type in group'),
'access' => 'subscribe to content in groups',
'page callback' => 'og_notifications_user_page',
'user page' => 'user/%user/notifications/group',
'fields' => array(
'group',
'type',
),
'description' => t('Subscribe to specific content within a group.'),
);
return $types;
case 'subscription fields':
$fields['group'] = array(
'name' => t('Group'),
'field' => 'nid',
'type' => 'int',
'options callback' => 'og_notifications_groups',
'format callback' => 'notifications_node_nid2title',
);
// Notifications does not allow custom callbacks for overlapping fields.
// This is resolved via a form_alter refines the field to only displsy
// authorised node types.
$fields['type'] = array(
'name' => t('Content type'),
'field' => 'type',
'type' => 'string',
'options callback' => 'notifications_content_types',
);
return $fields;
case 'query':
$query = array();
if ($arg0 == 'event' && $arg1 == 'node' && ($node = $arg2->node)) {
if (!empty($node->og_groups)) {
$query[]['fields']['group'] = $node->og_groups;
}
}
else {
if ($arg0 == 'user' && $arg1 == 'node') {
// Called by notifications_autosubscribe; $arg2 holds the nid.
$query[]['fields']['group'] = $arg2;
}
}
return $query;
case 'node options':
return _og_notifications_node_options($arg0, $arg1);
case 'event load':
// Piggy-backing on notifications_content.
break;
case 'event types':
// Piggy-backing on notifications_content.
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;
}
}
/**
* Options callback for subscription fields in hook_notifications. Returns a
* list of groups for the current user (presuming that this callback is only
* relevant in the "add subscriptions" page).
*
* @return Array $options
* An array of the users organic groups.
*/
function og_notifications_groups() {
$options = array();
$uid = arg(0) == 'user' && is_numeric(arg(1)) ? arg(1) : 0;
$result = db_query("SELECT n.nid, n.title FROM {og_uid} ogu INNER JOIN {node} n USING (nid) WHERE ogu.uid = %d", $uid);
while ($group = db_fetch_object($result)) {
$options[$group->nid] = $group->title;
}
return $options;
}
/**
* 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 (og_notifications_user_autosubscribe_get($account->uid)) {
og_notifications_user_subscribe($account, $gid);
}
}
/**
* Retrieve autosubscription setting for a particular user. -1 in the
* og_notifications table indicates that the site default is to be used.
*
* @param Integer $uid
* The uid of the user.
* @return Integer
* 1 or 0 as per the autosubscribe preference.
*/
function og_notifications_user_autosubscribe_get($uid) {
$autosubscribe = db_result(db_query("SELECT autosubscribe FROM {og_notifications} WHERE uid = %d", $uid));
return $autosubscribe == -1 ? variable_get('og_notifications_autosubscribe', 1) : $autosubscribe;
}
/**
* Retrieve autosubscription setting for a particular user.
*
* @param Integer $uid
* The uid of the user.
* @param Integer $autosubscribe
* Autosubscription option: 0 or 1.
*/
function og_notifications_user_autosubscribe_set($uid, $autosubscribe) {
return db_query("UPDATE {og_notifications} SET autosubscribe = %d WHERE uid = %d", $autosubscribe, $uid);
}
/**
* Subscribe a user to a group or to be more precise, to all subscribe-able
* content types within the group. This method is also called during the upgrade
* process in .install.
*
* @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) {
// Remove all existing user->group subscriptions.
og_notifications_user_unsubscribe($account, $gid);
$subscription_default = _notifications_subscription_defaults($account);
$subscription_default['uid'] = $account->uid;
$subscription_default['type'] = 'grouptype';
$subscription_default['event_type'] = 'node';
// Only subscribe the user to enabled types.
$content_types = array_filter(variable_get('og_notifications_content_types', array()));
// If the types array is empty, subscribe to all group types. This is mainly
// only valid during the upgrade.
if (empty($content_types)) {
$content_types = og_get_types('group_post');
}
foreach ($content_types as $type) {
// Reset $subscription as notifications_save_subscription casts the input
// array into an object.
$subscription = $subscription_default;
// String cast due to notifications requiring it (as the value field is
// a varchar).
$subscription['fields'] = array(
'group' => (string) $gid,
'type' => $type,
);
notifications_save_subscription($subscription);
}
}
/**
* Unsubscribe a user from a group. This also unsubscribes 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) {
notifications_delete_subscriptions(array(
'uid' => $account->uid,
'type' => 'grouptype',
), array(
'group' => $gid,
));
}
/**
* Options to display for node subscriptions.
*/
function _og_notifications_node_options($account, $node) {
$options = array();
// If node is a group type and the user is subscribed to this group.
if (og_is_group_type($node->type) && isset($account->og_groups[$node->nid])) {
foreach (array_filter(variable_get('og_notifications_content_types', array())) as $type) {
$options[] = array(
'name' => t('%type posts in %group', array(
'%group' => $node->title,
'%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 (isset($node->og_groups)) {
foreach ($node->og_groups as $index => $gid) {
// Only members get to see subscription options.
if (isset($account->og_groups[$gid]) && in_array($node->type, array_filter(variable_get('og_notifications_content_types', array())))) {
// Content type
$options[] = array(
'name' => t('%type posts in %group', array(
'%group' => $node->og_groups_both[$gid],
'%type' => node_get_types('name', $node->type),
)),
'type' => 'grouptype',
'fields' => array(
'group' => $gid,
'type' => $node->type,
),
);
}
}
}
return $options;
}
/**
* Helper function for og_notifications_message_alter. This function checks to
* see if the message object being passed is an OG notification.
*
* @param Object $message
* The message object.
* @return Integer
* The subscription ID if this is an OG notification message. 0,
* otherwise ...
*/
function _og_notification_check_message($message) {
$sid = 0;
if (isset($message->notifications) && isset($message->notifications['subscriptions'])) {
$params = current($message->notifications['subscriptions']);
// Check if "group" is one of the fields. This is a general presumption
// that any subscription with at least two fields, one of them being a
// group, is an OG subscription.
foreach ($params as $current_sid) {
$sid = db_result(db_query("SELECT sid FROM {notifications} WHERE type = 'grouptype' AND sid = %d", $current_sid));
if ($sid) {
break;
}
}
}
return $sid > 0 ? $sid : 0;
}
// Used by Views field/filter.
// TODO: Use constants instead of integers.
function og_notifications_autosubscribe_map() {
return array(
-1 => t('Site default'),
0 => t('Disabled'),
1 => t('Enabled'),
);
}
Functions
Name | Description |
---|---|
og_notifications_autosubscribe_map | |
og_notifications_form_alter | Implementation of hook_form_alter(). |
og_notifications_groups | Options callback for subscription fields in hook_notifications. Returns a list of groups for the current user (presuming that this callback is only relevant in the "add subscriptions" page). |
og_notifications_help | Implementation of hook_help(). |
og_notifications_menu | Implementation of hook_menu(). |
og_notifications_message_alter | A workaround to ensure that OG can provide custom message templates for notifications. |
og_notifications_messaging | Implementation of hook_messaging(). |
og_notifications_nodeapi | Implementation of hook_nodeapi(). |
og_notifications_notifications | Implementation of hook_notifications(). |
og_notifications_og | Implementation of hook_og(). |
og_notifications_perm | Implementation of hook_perm(). |
og_notifications_user | Implementation of hook_user(). Handle uid entry in the og_notifications table. |
og_notifications_user_autosubscribe | Handle autosubscriptions for users when they join a group. |
og_notifications_user_autosubscribe_get | Retrieve autosubscription setting for a particular user. -1 in the og_notifications table indicates that the site default is to be used. |
og_notifications_user_autosubscribe_set | Retrieve autosubscription setting for a particular user. |
og_notifications_user_subscribe | Subscribe a user to a group or to be more precise, to all subscribe-able content types within the group. This method is also called during the upgrade process in .install. |
og_notifications_user_unsubscribe | Unsubscribe a user from a group. This also unsubscribes the user from any grouptype subscriptions within the group. |
_og_notifications_node_options | Options to display for node subscriptions. |
_og_notification_check_message | Helper function for og_notifications_message_alter. This function checks to see if the message object being passed is an OG notification. |