diff -upwr /Users/bryn/projects/ogrc3orig/modules/og_access/og_access.module ./modules/og_access/og_access.module
--- /Users/bryn/projects/ogrc3orig/modules/og_access/og_access.module 2009-04-09 17:14:20.000000000 -0400
+++ ./modules/og_access/og_access.module 2009-08-11 19:43:14.000000000 -0400
@@ -1,5 +1,5 @@
type)) {
- $node->og_public = (bool)db_result(db_query("SELECT og_public FROM {og_access_post} WHERE nid = %d", $node->nid));
+ // Can't assume that og_access post records already exist. See http://drupal.org/node/522728.
+ $public_value = db_result(db_query("SELECT og_public FROM {og_access_post} WHERE nid = %d", $node->nid));
+ $node->og_public = ($public_value === '0') ? FALSE : TRUE;
}
break;
case 'insert':
@@ -40,8 +42,15 @@ function og_access_nodeapi(&$node, $op,
case 'update':
// Save og_public.
if (og_is_group_post_type($node->type)) {
+ // Can't assume that og_access post records already exist. See http://drupal.org/node/522728.
+ // TODO D7: use merge query.
+ if (!db_result(db_query_range("SELECT nid FROM {og_access_post} WHERE nid = %d", $node->nid, 0, 1))) {
+ drupal_write_record('og_access_post', $node);
+ }
+ else {
drupal_write_record('og_access_post', $node, 'nid');
}
+ }
break;
case 'delete':
if (og_is_group_post_type($node->type)) {
@@ -97,6 +106,12 @@ function og_access_content_extra_fields(
'description' => t('Checkbox for visibility of group home page to non-members.'),
'weight' => 0,
);
+
+ $extra['og_private_preview'] = array(
+ 'label' => t('Private group preview'),
+ 'description' => t('If this box is checked, users invited to private groups will be able to view the group in order to decide whether or not they want to join.'),
+ 'weight' => 0,
+ );
}
return $extra;
}
@@ -138,6 +153,14 @@ function og_access_alter_group_form(&$fo
'#weight' => module_exists('content') ? content_extra_field_weight($node->type, 'og_private') : 0,
'#description' => t('Should this group be visible only to its members? Disabled if the group is set to List in Directory or Membership requests: open.')
);
+
+ $form['og_private_preview'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Private group preview'),
+ '#default_value' => isset($node->nid) ? $node->og_private : 0,
+ '#weight' => module_exists('content') ? content_extra_field_weight($node->type, 'og_private_preview') : 0,
+ '#description' => t('If this box is checked, users invited to private groups will be able to view the group in order to decide whether or not they want to join.'),
+ );
break;
}
}
@@ -245,6 +268,9 @@ function og_access_form_alter(&$form, &$
function og_access_node_grants($account, $op) {
if ($op == 'view') {
$grants['og_public'][] = 0; // everyone can see a public node
+
+ $result = db_query('select group_nid from og_invite where mail=\'%s\'',$account->uid);
+ while($gid = db_result($result)) $grants['og_private_preview'][] = $gid;
}
// Subscribers get an admin or non-admin grant for each subscription
@@ -299,6 +325,17 @@ function og_access_node_access_records($
'priority' => 0,
);
+ if($node->og_private_preview) {
+ // If the group allows private previews for invited users, let those users view the group homepage.
+ $grants[] = array (
+ 'realm' => 'og_private_preview',
+ 'gid' => $node->nid,
+ 'grant_view' => 1,
+ 'grant_update' => 0,
+ 'grant_delete' => 0,
+ 'priority' => 0,
+ );
+ }
}
}
elseif (!empty($node->og_groups)) {
diff -upwr /Users/bryn/projects/ogrc3orig/modules/og_actions/og_actions.module ./modules/og_actions/og_actions.module
--- /Users/bryn/projects/ogrc3orig/modules/og_actions/og_actions.module 2009-06-08 21:04:44.000000000 -0400
+++ ./modules/og_actions/og_actions.module 2009-08-11 14:19:07.000000000 -0400
@@ -33,6 +33,12 @@ function og_actions_action_info() {
'nodeapi' => array('insert', 'update'),
),
),
+ 'og_invite_user_action' => array(
+ 'type' => 'user',
+ 'description' => t('Invite user to the specified groups'),
+ 'configurable' => TRUE,
+ 'hooks' => array(),
+ ),
'og_subscribe_user_action' => array(
'type' => 'user',
'description' => t('Subscribe user to the specified groups'),
@@ -274,6 +280,63 @@ function og_subscribe_user_action_submit
}
/**
+ * A configurable action to subscribe a user to specific groups.
+ */
+function og_invite_user_action($account, $context) {
+ if (isset($context['groups'])) {
+ require_once drupal_get_path('module', 'og') ."/og.pages.inc";
+ foreach ($context['groups'] as $gid) {
+ $form_state = array('values' => array('mails' => $account->name, 'gid' => $gid, 'pmessage' => $context['pmessage']));
+ drupal_execute('og_invite_form', $form_state, node_load($gid));
+ }
+ watchdog('action', 'Invited user %name to groups %groups.', array('%name' => $account->name, '%groups' => implode(',', $context['groups'])));
+ }
+}
+
+/**
+ * Configuration form for Invite User action.
+ */
+function og_invite_user_action_form($context) {
+ $form = array();
+
+ if (!isset($context['groups'])) {
+ $context['groups'] = array();
+ }
+
+ $groups = og_all_groups_options();
+ if (count($groups)) {
+ $form['groups'] = array(
+ '#type' => 'select',
+ '#title' => t('Groups'),
+ '#options' => $groups,
+ '#description' => t('Select the groups to which this user should be invited.'),
+ '#default_value' => $context['groups'],
+ '#required' => TRUE,
+ '#multiple' => TRUE,
+ );
+ $form['pmessage'] = array(
+ '#type' => 'textarea',
+ '#title' => t('Personal message'),
+ '#description' => t('Optional. Enter a message which will become part of the invitation email.')
+ );
+ }
+ else {
+ drupal_set_message(t('Please create a group first.', array('!url' => url('admin/content'))));
+ }
+ return $form;
+}
+
+/**
+ * Submission handler for Invite User action configuration form.
+ */
+function og_invite_user_action_submit($form, &$form_state) {
+ return array(
+ 'groups' => $form_state['values']['groups'],
+ 'pmessage' => $form_state['values']['pmessage'],
+ );
+}
+
+/**
* A configurable action to unsubscribe a user from specific groups.
*/
function og_unsubscribe_user_action($account, $context) {
diff -upwr /Users/bryn/projects/ogrc3orig/og.install ./og.install
--- /Users/bryn/projects/ogrc3orig/og.install 2009-05-15 13:28:02.000000000 -0400
+++ ./og.install 2009-08-11 18:47:06.000000000 -0400
@@ -143,6 +143,24 @@ function og_schema() {
),
'primary key' => array('nid', 'group_nid'),
);
+ $schema['og_invite'] = array(
+ 'description' => 'Pending OG Invitations',
+ 'fields' => array(
+ 'mail' => array(
+ 'type' => 'varchar',
+ 'length' => 64,
+ 'not null' => TRUE,
+ 'description' => "Invited email address.",
+ ),
+ 'group_nid' => array(
+ 'description' => "The group's {node}.nid.",
+ 'type' => 'int',
+ 'size' => 'normal',
+ 'not null' => TRUE,
+ ),
+ ),
+ 'primary key' => array('mail', 'group_nid'),
+ );
return $schema;
}
@@ -432,6 +450,50 @@ function og_update_6203() {
return $ret;
}
+// Add og_invite table to store emails for inviting non-users to groups.
+function og_update_6204() {
+ $ret = array();
+
+ $schema['og_invite'] = array(
+ 'description' => 'Pending OG Invitations',
+ 'fields' => array(
+ 'mail' => array(
+ 'type' => 'varchar',
+ 'length' => 64,
+ 'not null' => TRUE,
+ 'description' => "Invited email address.",
+ ),
+ 'group_nid' => array(
+ 'description' => "The group's {node}.nid.",
+ 'type' => 'int',
+ 'size' => 'normal',
+ 'not null' => TRUE,
+ ),
+ ),
+ 'primary key' => array('mail', 'group_nid'),
+ );
+ db_create_table($ret, 'og_invite', $schema['og_invite']);
+ return $ret;
+}
+
+// Add private_preview field to allow invited users to preview a private group before joining
+function og_update_6205() {
+ $ret = array();
+
+ $schema = array(
+ 'description' => 'Give invited users preview access to an otherwise private group?',
+ 'type' => 'int',
+ 'size' => 'tiny',
+ 'not null' => TRUE,
+ 'default' => 0,
+ );
+
+
+ db_add_field($ret, 'og', 'og_private_preview', $schema);
+ return $ret;
+}
+
+
// end updates //
function og_uninstall() {
diff -upwr /Users/bryn/projects/ogrc3orig/og.module ./og.module
--- /Users/bryn/projects/ogrc3orig/og.module 2009-06-09 07:42:46.000000000 -0400
+++ ./og.module 2009-08-11 18:32:22.000000000 -0400
@@ -1,5 +1,5 @@
'og.pages.inc',
'page callback' => 'og_subscribe',
'page arguments' => array(2),
- 'access callback' => 'node_access',
- 'access arguments' => array('view', 2),
+ 'access callback' => 'og_menu_access_subscribe',
+ 'access arguments' => array(2),
'title' => 'Join group'
);
@@ -258,6 +258,29 @@ function og_menu_access_invite($node) {
return og_is_group_member($node) && ($node->og_selective < OG_INVITE_ONLY || og_is_group_admin($node));
}
+function og_menu_access_subscribe($group_node) {
+ if($group_node->og_private) {
+ if(og_is_invited($group_node)) return TRUE;
+ else return FALSE;
+ }
+ else return node_access('view', $group_node);
+}
+
+function og_is_invited($group_node) {
+ global $user;
+
+ if (!isset($user->og_groups)) {
+ $user = user_load(array('uid' => $user->uid));
+ }
+
+ $sql = "SELECT COUNT(*) FROM {og_invite} WHERE group_nid = %d and mail = '%s'";
+ $query = db_query($sql, $group_node->nid, $user->uid);
+ $cnt = db_result($query);
+
+ if($cnt == 0) return FALSE;
+ else return TRUE;
+}
+
/**
* Check a user's membership in a group.
*
@@ -386,7 +409,8 @@ function og_init() {
// We have to perform a load in order to assure that the $user->og_groups bits are present.
global $user;
if ($user->uid) {
- $user = user_load(array('uid' => $user->uid));
+ // $user gets modified by reference.
+ og_user('load', array(), $user);
}
else {
$user->og_groups = array();
@@ -428,7 +452,8 @@ function og_set_language($node) {
if ($node->og_language) {
$map = language_list();
$og_language = $map[$node->og_language];
- $user_language = user_preferred_language($account, $og_language);
+ global $user;
+ $user_language = user_preferred_language($user, $og_language);
if ($og_language == $user_language) {
$GLOBALS['language'] = $og_language;
}
@@ -484,7 +509,7 @@ function og_determine_context() {
$gid = intval(current($_REQUEST['gids']));
$node = node_load($gid);
}
- elseif (($item['map'][0] == 'og' && !empty($item['map'][2])) || $path == 'comment/reply/%') {
+ elseif ((!empty($item['map'][2]) && $item['map'][0] == 'og') || $path == 'comment/reply/%') {
$node = menu_get_object('node', 2);
}
elseif ($path == 'comment/edit' || $path == 'comment/delete') {
@@ -617,6 +642,7 @@ function og_set_theme($group_node) {
is_active, is_admin, created. Other values are passed to hook implementations.
*/
function og_save_subscription($gid, $uid, $args = array()) {
+ if ($uid > 0) {
$sql = "SELECT COUNT(*) FROM {og_uid} WHERE nid = %d AND uid = %d";
$cnt = db_result(db_query($sql, $gid, $uid));
$time = time();
@@ -638,6 +664,7 @@ function og_save_subscription($gid, $uid
module_invoke_all('og', 'user update', $gid, $uid, $args);
}
}
+}
function og_delete_subscription($gid, $uid, $args = array()){
$sql = "DELETE FROM {og_uid} WHERE nid = %d AND uid = %d";
@@ -713,7 +740,15 @@ function og_mail($key, &$message, $param
* @return string 'approval', 'subscribed' or 'rejected' depending on the group's configuration.
**/
function og_subscribe_user($gid, $account, $request = NULL) {
- // moderated groups must approve all members (selective=1)
+ if ($account->uid == 0) {
+ // Silly admins can do this. Maybe code can too when an account gets deleted. See http://drupal.org/node/434632.
+ $return_value = array(
+ 'type' => 'rejected',
+ 'message' => t('Membership request to the %group group was rejected; the anonymous user may not join a group.', array('%group' => $node->title))
+ );
+ }
+ else {
+ // Moderated groups must approve all members (selective=1).
$node = node_load($gid);
switch ($node->og_selective) {
case OG_MODERATED:
@@ -750,7 +785,7 @@ function og_subscribe_user($gid, $accoun
case OG_OPEN:
og_save_subscription($gid, $account->uid, array('is_active' => 1));
$return_value = array('type' => 'subscribed',
- 'message' => t('You are now a member of the %group.', array('%group' => $node->title)));
+ 'message' => t('You are now a member of %group.', array('%group' => $node->title)));
break;
case OG_CLOSED:
case OG_INVITE_ONLY:
@@ -763,6 +798,8 @@ function og_subscribe_user($gid, $accoun
'message' => t('Membership request to the %group group was rejected, only group administrators can add users to this group.', array('%group' => $node->title)));
}
}
+ }
+
return $return_value;
}
@@ -1239,13 +1276,15 @@ function og_nodeapi(&$node, $op, $teaser
case 'update':
if (og_is_group_type($node->type)) {
og_update_group($node);
- // make sure the node owner is a full powered member
+ if ($node->uid > 0) {
+ // Make sure the node owner is a full powered member.
og_save_subscription($node->nid, $node->uid, array('is_active' => 1, 'is_admin' => 1));
- // load new group into $user->og_groups so that author can get redirected to the new group
+ // Load new group into $user->og_groups so that author can get redirected to the new group.
if ($node->uid == $user->uid) {
$user->og_groups = og_get_subscriptions($user->uid, 1, TRUE);
}
}
+ }
else {
og_save_ancestry($node);
}
@@ -1323,6 +1362,11 @@ function og_form_alter(&$form, &$form_st
}
drupal_set_breadcrumb($bc);
}
+ // Pass the gids if it exists in the request, and not set already by
+ // another module, so it can be used by og_form_add_og_audience().
+ if (!empty($_GET['gids']) && empty($form_state['og_gids'])) {
+ $form_state['og_gids'] = $_GET['gids'];
+ }
og_form_add_og_audience($form, $form_state);
}
}
@@ -1599,9 +1643,9 @@ function og_node_groups_distinguish($gro
*/
function og_form_add_og_audience(&$form, &$form_state) {
global $user;
- // Determine the selected groups if FAPI doesn't tell us.
- if (isset($_GET['gids'])) {
- $gids = $_GET['gids'];
+ // Determine the selected groups if it is stored in the form_state.
+ if (!empty($form_state['og_gids'][0]) && empty($form_state['og_groups'])) {
+ $gids = explode(',', $form_state['og_gids'][0]);
}
$node = $form['#node'];
@@ -1719,7 +1763,7 @@ function og_form_add_og_audience(&$form,
'#type' => $type,
'#title' => t('Audience'),
'#attributes' => array('class' => 'og-audience'),
- '#options' => $options,
+ '#options' => $type == 'checkboxes' ? array_map('filter_xss', $options) : $options,
'#required' => $required,
'#description' => format_plural(count($options), 'Show this post in this group.', 'Show this post in these groups.'),
'#default_value' => $groups ? $groups : array(),
@@ -2182,7 +2226,7 @@ function og_og_create_links($group) {
$type_url_str = str_replace('_', '-', $post_type);
if (module_invoke($types[$post_type]->module, 'access', 'create', $post_type, $user)) {
$links["create_$post_type"] = l(t('Create !type', array('!type' => $type_name)), "node/add/$type_url_str", array(
- 'title' => t('Add a new !type in this group.', array('!type' => $type_name)),
+ 'attributes' => array('title' => t('Add a new !type in this group.', array('!type' => $type_name))),
'query' => "gids[]=$group->nid",
));
}
@@ -2235,6 +2279,7 @@ function og_token_list($type = 'all') {
$tokens['node']['ogname-raw'] = t('Unfiltered title of top group. WARNING - raw user input.');
$tokens['node']['og-id'] = t('ID of top group');
$tokens['node']['og-type'] = t("Type of top group");
+ $tokens['node']['ogalias'] = t("URL alias for the top group.");
return $tokens;
}
}
@@ -2251,15 +2296,17 @@ function og_token_values($type, $object
$values['ogname-raw'] = '';
$values['og-id'] = '';
$values['og-type'] = '';
+ $values['ogalias'] = '';
if (!empty($object->og_groups) && is_array($object->og_groups)) {
$gids = array_filter($object->og_groups);
foreach ($gids as $gid) {
$group = db_fetch_object(db_query("SELECT title, type FROM {node} WHERE nid = %d", $gid));
$values['ogname'] = check_plain($group->title);
- $values['ogname-raw'] = $title;
+ $values['ogname-raw'] = $group->title;
$values['og-id'] = $gid;
$values['og-type'] = check_plain($group->type);
+ $values['ogalias'] = drupal_get_path_alias('node/'. $gid);
break;
}
return $values;
Only in ./: og.module.orig
diff -upwr /Users/bryn/projects/ogrc3orig/og.pages.inc ./og.pages.inc
--- /Users/bryn/projects/ogrc3orig/og.pages.inc 2009-06-09 21:07:27.000000000 -0400
+++ ./og.pages.inc 2009-08-11 16:13:23.000000000 -0400
@@ -214,6 +214,9 @@ function og_invite_form_validate($form,
elseif (in_array($user->mail, $emails)) {
form_set_error('mails', t('You may not invite yourself - @self.', array('@self' => $user->mail)));
}
+ elseif (in_array($user->name, $emails)) {
+ form_set_error('mails', t('You may not invite yourself - @self.', array('@self' => $user->name)));
+ }
else {
$valid_emails = array();
$bad = array();
@@ -253,16 +256,69 @@ function og_invite_form_submit($form, &$
'@group' => $node->title,
'@description' => $node->og_description,
'@site' => variable_get('site_name', 'drupal'),
- '!group_url' => url("og/subscribe/$node->nid", array('absolute' => TRUE)),
'@body' => $form_state['values']['pmessage'],
);
global $user;
$from = $user->mail;
+ $sent = 0;
foreach ($emails as $mail) {
+ $variables['!group_url'] = url("og/subscribe/$node->nid", array('absolute' => TRUE));
+ $account = user_load(array('mail' => $mail));
+ $wasinactive = FALSE;
+ if ($account) {
+ $sql = "SELECT is_active,uid FROM {og_uid} WHERE uid = %d AND nid = %d";
+ $oguid = db_fetch_array(db_query($sql, $account->uid, $node->nid));
+ if ($oguid['uid']) {
+ // user already active/pending
+ if($oguid['is_active']) {
+ drupal_set_message("@username is already a member of the group", array('@username' => $account->name));
+ continue;
+ } else {
+ $wasinactive = TRUE;
+ drupal_set_message('@username already requested group membership', array('@username' => $account->name));
+ }
+ }
+ }
+
+ if (og_is_group_admin($node)) {
+ if ($account) {
+ if ($wasinactive) {
+ // user wanted to be a member, we want them to be a member--oh happy day
+ db_query("UPDATE {og_uid} SET is_active = 1 WHERE uid = %d and nid = %d", $account->uid, $node->nid);
+ drupal_set_message('@username has now been approved as a member', array('@username' => $account->name));
+ } else {
+ $sql = "SELECT COUNT(*) FROM {og_invite} WHERE mail = '%d' AND group_nid = %d";
+ $cnt = db_result(db_query($sql, $account->uid, $node->nid));
+ if ($cnt) {
+ drupal_set_message(t('@username was already on the invitation list for this group, but will be re-invited.', array('@username' => $account->name)));
+ }
+ else {
+ $record = array('mail' => $account->uid, 'group_nid' => $node->nid);
+ $result = drupal_write_record('og_invite', $record);
+ }
+ }
+ } else {
+ $sql = "SELECT COUNT(*) FROM {og_invite} WHERE mail = '%s' AND group_nid = %d";
+ $cnt = db_result(db_query($sql, $mail, $node->nid));
+ if ($cnt) {
+ drupal_set_message(t('@email was already on the invitation list for this group, but will be re-invited.', array('@email' => $mail)));
+ }
+ else {
+ $record = array('mail' => $mail, 'group_nid' => $node->nid);
+ $result = drupal_write_record('og_invite', $record);
+ }
+ $variables['!group_url'] = url('user/register', array('absolute' => TRUE));
+ }
+ }
+ // could still be here if user in there but is_active = 0: don't send another invitation if they don't need one
+ if ($wasinactive) {
+ continue;
+ }
+ $sent ++;
drupal_mail('og', 'invite_user', $mail, $GLOBALS['language'], $variables, $from);
}
- drupal_set_message(format_plural(count($emails), '1 invitation sent.', '@count invitations sent.'));
+ drupal_set_message(format_plural($sent, '1 invitation sent.', '@count invitations sent.'));
}
function og_subscribe($node, $uid = NULL) {
@@ -286,7 +342,10 @@ function og_subscribe($node, $uid = NULL
$account = user_load(array('uid' => $uid));
}
- if ($node->og_selective >= OG_INVITE_ONLY || $node->status == 0 || !og_is_group_type($node->type)) {
+ $sql = "SELECT COUNT(*) FROM {og_invite} WHERE mail = '%d' AND group_nid = %d";
+ $cnt = db_result(db_query($sql, $account->uid, $node->nid));
+
+ if (($node->og_selective >= OG_INVITE_ONLY && !$cnt) || $node->og_selective >= OG_CLOSED || $node->status == 0 || !og_is_group_type($node->type)) {
drupal_access_denied();
exit();
}
@@ -312,7 +371,9 @@ function og_subscribe($node, $uid = NULL
function og_confirm_subscribe($form_state, $gid, $node, $account) {
$form['gid'] = array('#type' => 'value', '#value' => $gid);
$form['account'] = array('#type' => 'value', '#value' => $account);
- if ($node->og_selective == OG_MODERATED) {
+ $sql = "SELECT COUNT(*) FROM {og_invite} WHERE mail = '%d' AND group_nid = %d";
+ $cnt = db_result(db_query($sql, $account->uid, $node->nid));
+ if ($node->og_selective == OG_MODERATED && !$cnt) {
$form['request'] = array(
'#type' => 'textarea',
'#title' => t('Additional details'),
@@ -384,6 +445,7 @@ function og_add_users($form_state, $grou
'#description' => t('Add one or more usernames in order to associate users with this group. Multiple usernames should be separated by a comma.'),
'#element_validate' => array('og_add_users_og_names_validate'),
);
+ $form['og_names']['#description'] .= '
' . t('If you wish to use emails in addition to usernames, invite will accept a mix of both.', array( '@url' => url('og/invite/'. $group_node->nid)));
$form['op'] = array('#type' => 'submit', '#value' => t('Add users'));
$form['gid'] = array('#type' => 'value', '#value' => $group_node->nid);
return $form;