l(t('theme configuration page'), 'admin/theme'))); } } function og_menu($may_cache) { global $user; if ($may_cache) { // anon users should be able to get to the subscribe page $items[] = array('path' => 'og/subscribe', 'type' => MENU_CALLBACK, 'callback' => 'og_subscribe', 'access' => TRUE, 'title' => t('subscribe to group')); $items[] = array('path' => 'og/image', 'callback' => 'og_image', 'title' => t('group image (large)'), 'weight' => 4, 'access' => user_access('access content'), 'type' => MENU_CALLBACK); $items[] = array('path' => 'node/add/og', 'title' => t('group'), 'access' => user_access('create groups')); $items[] = array('path' => 'og', 'callback' => 'og_list_groups_page', 'title' => t('groups'), 'weight' => 3, 'access' => user_access('access content')); $access = $user->uid; // login is required $items[] = array('path' => 'og/unsubscribe', 'type' => MENU_CALLBACK, 'callback' => 'og_unsubscribe', 'access' => $access, 'title' => t('unsubscribe from group')); $items[] = array('path' => 'og/approve', 'type' => MENU_CALLBACK, 'callback' => 'og_approve', 'access' => $access, 'title' => t('approve subscription request')); $items[] = array('path' => 'og/deny', 'type' => MENU_CALLBACK, 'callback' => 'og_deny', 'access' => $access, 'title' => t('deny subscription request')); $items[] = array('path' => 'og/create_admin', 'type' => MENU_CALLBACK, 'callback' => 'og_create_admin', 'access' => $access, 'title' => t('create group administrator')); $items[] = array('path' => 'og/delete_admin', 'type' => MENU_CALLBACK, 'callback' => 'og_delete_admin', 'access' => $access, 'title' => t('delete group administrator')); $items[] = array('path' => 'og/remove_node', 'type' => MENU_CALLBACK, 'callback' => 'og_remove_node', 'access' => $access, 'title' => t('remove post from group')); $items[] = array('path' => 'og/feed', 'callback' => 'og_feed', 'title' => t('group feed'), 'type' => MENU_CALLBACK, 'access' => user_access('access content')); $items[] = array('path' => 'og/albums', 'callback' => 'og_albums_page', 'title' => t('albums'), 'type' => MENU_CALLBACK, 'access' => user_access('access content')); $items[] = array('path' => 'og/albums/form', 'callback' => 'og_albums_form', 'title' => t('album'), 'type' => MENU_CALLBACK, 'access' => user_access('create images')); $items[] = array('path' => 'og/albums/validate', 'callback' => 'og_albums_validate', 'title' => t('album'), 'type' => MENU_CALLBACK, 'access' => user_access('create images')); } else { // we have to perform a load in order to assure that the $user->og_groups bits are present. $user = user_load(array('uid' => $user->uid)); foreach ($user->og_groups as $key => $sub) { $items[] = array('path' => "og/view/$key", 'callback' => 'og_nodeview', 'title' => $sub['title'], 'callback arguments' => array($key), 'access' => TRUE, 'type' => MENU_CALLBACK); $items[] = array('path' => "og/users/$key", 'callback' => 'og_list_users_page', 'title' => t('subscriber management'), 'callback arguments' => array($key), 'type' => MENU_CALLBACK, 'access' => TRUE); $items[] = array('path' => "og/users/$key/list", 'callback' => 'og_list_users_page', 'title' => t('list'), 'callback arguments' => array($key), 'type' => MENU_DEFAULT_LOCAL_TASK, 'access' => TRUE); $items[] = array('path' => "og/users/$key/add", 'callback' => 'og_add_users_page', 'title' => t('add subscribers'), 'callback arguments' => array($key), 'type' => MENU_LOCAL_TASK, 'access' => TRUE, 'weight' => 5); $items[] = array('path' => "og/manage/$key", 'callback' => 'og_manage', 'title' => t('manage subscription'), 'callback arguments' => array($key), 'type' => MENU_CALLBACK, 'access' => user_access('access content')); $items[] = array('path' => "og/invite/$key", 'callback' => 'og_invite', 'title' => t('send invitation'), 'callback arguments' => array($key), 'type' => MENU_CALLBACK, 'access' => user_access('access content')); } if (arg(0) == 'node' && is_numeric(arg(1))) { $node = node_load(array('nid' => arg(1))); if ($node->type == 'og') { $items[] = array('path' => 'node/'. arg(1). '/email', 'title' => t('email'), 'callback' => 'og_email', 'callback arguments' => array(arg(1)), 'access' => node_access('update', $node), 'type' => MENU_LOCAL_TASK, 'weight' => 7); } } og_theme(); } return $items; } function og_perm() { return array('create groups', 'administer organic groups'); } /** * override theme based on what group is being displayed (if any). * be smart about selecting the 'active' group for ambigous urls like node/$nid * * * @param * none * @return * none */ function og_theme() { global $custom_theme; $group_node = NULL; // a node object containing the 'active' group for this request $pages = array('users', 'albums', 'feed', 'invite', 'remove_node', 'manage', 'all'); if (arg(0) == 'og' && arg(1) == 'albums' && arg(2) == 'form' && $gid = $_REQUEST['edit']['og_groups'][0]) { $group_node = node_load(array('nid' => $gid)); $custom_theme = $group_node->og_theme; } elseif (arg(0) == 'og' && in_array(arg(1), $pages)) { $group_node = og_set_theme(arg(2)); } elseif (arg(0) == 'node' && is_numeric(arg(1))) { $group_node = og_set_theme(arg(1)); } elseif (arg(0) == 'node' && arg(1) == 'add' && $gid = $_REQUEST['edit']['og_groups'][0]) { $group_node = node_load(array('nid' => $gid)); $custom_theme = $group_node->og_theme; } elseif (arg(0) == 'comment' && is_numeric(arg(2))) { $og_node = og_set_theme(arg(2)); } $_SESSION['og_last'] = $group_node; } function og_set_theme($nid) { global $custom_theme; $node = node_load(array('nid' => $nid)); if ($node->type == 'og') { $custom_theme = $node->og_theme; return $node; } else { switch (count($node->og_groups)) { case 0: return NULL; case 1: $group_node = node_load(array('nid' => $node->og_groups[0])); $custom_theme = $group_node->og_theme; default: // node is in multiple groups. preference goes to the group we showed on the prior page view (if any) if (in_array($_SESSION['og_last']->nid, $node->og_groups)) { $group_node = node_load(array('nid' => $_SESSION['og_last']->nid)); $custom_theme = $group_node->og_theme; } else { $group_node = node_load(array('nid' => $node->og_groups[0])); $custom_theme = $group_node->og_theme; } } // we know everything we need to know here to determine the node breadcrumb // instead of reproducing this logic elsewhere, save in a GLOBAL and set_breadcrumb() in og_nodeapi('view') $GLOBALS['og_node_bc'][] = l(t('home'), ''); $GLOBALS['og_node_bc'][] = l(t('groups'), 'og'); $GLOBALS['og_node_bc'][] = l($group_node->title, "node/$group_node->nid"); return $group_node; } } function og_nodeview($gid) { drupal_goto("node/$gid"); } /** * Admins may broadcast email to all their subscribers * * @param $gid * the nid of a group. */ function og_email($gid) { $node = node_load(array('nid' => $gid)); drupal_set_title(t('Send email to %group', array('%group' => $node->title))); if ($edit = $_POST['edit']) { if (!$edit['body']) { form_set_error('body', t("Your email body may not be blank")); $err = TRUE; } if (!$edit['subject']) { form_set_error('subject', t('Your email subject may not be blank')); $err = TRUE; } if (!$err) { $msg = $edit['body']. t("\n\n--------------------------------\nThis message was sent by an administrator in the '%group' group at %site. To visit this group, browse to %url1. To unsubscribe from this group, visit %url2", array('%group' => $node->title, '%site' => variable_get('site_name', drupal), '%url1' => url("node/$node->nid", NULL, NULL, TRUE), '%url2' => url("og/unsubscribe/$node->nid", NULL, NULL, TRUE))); global $user; $from = $user->mail; $headers = "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from"; $sql = og_list_users_sql(1); $result = db_query($sql, $gid); while ($row = db_fetch_object($result)) { $emails[] = $row->mail; } foreach ($emails as $mail) { user_mail(trim($mail), $edit['subject'], $msg, $headers); } drupal_set_message(t('%count emails sent.', array('%count' => count($emails)))); drupal_goto("node/$gid"); } else { print theme('page', og_email_form($gid)); } } else { print theme('page', og_email_form($gid)); } } function og_email_form($gid) { $edit = $_POST['edit']; $result = db_query(og_list_users_sql(1), $gid); $txt = format_plural(db_num_rows($result), '1 subscriber', 'all %count subscribers'); drupal_set_message(t('Your email will be sent to %count in this group. Please use this feature sparingly.', array('%count' => l($txt, "og/users/$gid")))); $form .= form_textfield(t('Subject'), 'subject', $edit['subject'], 70, 250, t("Enter a subject for your email."), NULL, TRUE); $form .= form_textarea(t('Body'), 'body', $edit['body'], 90, 5, t('Enter a body for your email.'), NULL, TRUE); $form .= form_button(t('Send email')); return form($form); } function og_manage($gid) { global $user; if ($edit = $_POST['edit']) { $sql = "DELETE FROM {og_uid} WHERE nid=%d AND uid=%d"; db_query($sql, $gid, $user->uid); $sql = "INSERT INTO {og_uid} (mail_type, nid, uid) VALUES (%d, %d, %d)"; db_query($sql, $edit['mail_type'], $gid, $user->uid); drupal_set_message(t('Subscription saved.')); } $group = node_load(array('nid' => $gid)); // group owner can't unsubscribe if ($group->uid != $user->uid) { $output .= form_item(t('Goodbye'), l(t('Unsubscribe from this group'), "og/unsubscribe/$gid"), NULL, 'destination=og'); } $output .= form_radios('Email notification', "mail_type", $edit["mail_type"] ? $edit["mail_type"] : $user->og_groups[$gid]['mail_type'], array(t('disabled'), t('enabled')), t('Do you want to receive an email each time a message is posted to this group?')); $output .= form_button(t('Submit')); $output = form($output); $bc = array(l(t('home'), ''), l(t('groups'), 'og'), l($group->title, "node/$gid")); drupal_set_breadcrumb($bc); print theme('page', $output); } function og_approve($gid, $uid) { if (node_access('update', array('nid' => $gid, 'status' => 1))) { $sql = "REPLACE INTO {node_access} (nid, gid, realm, grant_view) VALUES (%d, %d, 'og_uid', 1)"; db_query($sql, $gid, $uid); drupal_set_message(t('Subscription request approved.')); $node = node_load(array('nid' => $gid)); $subj = t("Subscription request approved for '%title'", array('%title' => $node->title)); $body = t('You may now post messages in this group located at %url', array('%url' => url("node/$node->nid", NULL, NULL, TRUE))); $from = variable_get('site_mail', ini_get('sendmail_from')); $headers = "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from"; $account = user_load(array('uid' => $uid)); user_mail($account->mail, $subj, $body, $headers); drupal_goto("node/$gid"); } else { drupal_access_denied(); } } function og_deny($gid, $uid) { if (node_access('update', array('nid' => $gid, 'status' => 1))) { $sql = "DELETE FROM {node_access} WHERE nid=%d AND gid=%d AND realm='og_uid'"; db_query($sql, $gid, $uid); drupal_set_message(t('Subscription request denied.')); $subj = t('Subscription request denied for %title', array('title' => $node->title)); $body = t('Sorry, your subscription request was denied.'); $from = variable_get('site_mail', ini_get('sendmail_from')); $headers = "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from"; $account = user_load(array('uid' => $uid)); user_mail($account->mail, $subj, $body, $headers); drupal_goto("node/$gid"); } else { drupal_access_denied(); } } function og_create_admin($gid, $uid) { if (node_access('update', array('nid' => $gid, 'status' => 1))) { $sql = "REPLACE INTO {node_access} (nid, gid, realm, grant_view, grant_update) VALUES (%d, %d, 'og_uid', 1, 1)"; db_query($sql, $gid, $uid); drupal_set_message(t('User was promoted to group administrator')); drupal_goto("node/$gid"); } else { drupal_access_denied(); } } function og_delete_admin($gid, $uid) { if (node_access('update', array('nid' => $gid, 'status' => 1))) { $sql = "REPLACE INTO {node_access} (nid, gid, realm, grant_view, grant_update) VALUES (%d, %d, 'og_uid', 1, 0)"; db_query($sql, $gid, $uid); drupal_set_message(t('User is no longer a group administrator')); drupal_goto("node/$gid"); } else { drupal_access_denied(); } } function og_remove_node($gid, $nid) { if (node_access('update', array('nid' => $gid, 'status' => 1))) { $node = node_load(array('nid' => $nid)); if ($_POST['op']['og_confirm']) { og_delete_folksonomy($node); $sql = "DELETE FROM {node_access} WHERE nid=%d AND gid=%d AND realm='og_group'"; db_query($sql, $nid, $gid); drupal_set_message(t('Post removed from group.')); drupal_goto("node/$gid"); } else { $output = form_item(t('Confirmation'), t('Remove %title from this group.', array('%title' => ''. $node->title. ''))); $output .= form_hidden('og_confirm', 1); $output .= form_button(t('Remove')); print theme('page', form($output)); } } else { drupal_access_denied(); } } function og_delete_folksonomy($node) { if ($node->og_groups) { foreach ($node->og_groups as $gid) { $realm = "og_group_$gid"; module_invoke('folksonomy', 'delete', array('realm' => $realm, 'id' => $node->nid)); } } } function og_invite($gid) { $node = node_load(array('nid' => $gid)); if ($node->og_selective < OG_INVITE_ONLY || node_access('update', $node)) { $max = variable_get('og_email_max', 10); if ($edit = $_POST['edit']) { $emails = explode(',', $edit['mails']); if (count($emails) > $max) { form_set_error('mails', t("You may not specify more than %max email addresses.", array('%max' => $max))); $err = TRUE; } else { foreach ($emails as $email) { if (!valid_email_address(trim($email))) { $bad[] = $email; } } if ($bad) { form_set_error('mails', t('invalid email address: '). implode(' ', $bad)); $err = TRUE; } } if (!$err) { $node = node_load(array('nid' => $gid)); $subj = t('Invitation to join the group "%group" at %site', array('%group' => $node->title, '%site' => variable_get('site_name', 'drupal'))); $body = t("Hi. I'm a member of '%group' and I welcome you to join this group as well. Please see the link and message below.\n\n", array('%group' => $node->title)); $body .= $node->title. "\n"; $body .= $node->og_description. "\n"; $body .= t('Subscribe: %url', array('%url' => url("og/subscribe/$gid", NULL, NULL, TRUE))); $body .= $edit['pmessage'] ? "\n\n ----------------------------\n". $edit['pmessage']. "\n--------------------------------" : ''; global $user; $from = $user->mail; global $user; $headers = "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from"; foreach ($emails as $mail) { user_mail(trim($mail), $subj, $body, $headers); } drupal_set_message(t('%count invitations sent.', array('%count' => count($emails)))); print theme('page', og_invite_form($gid)); } else { print theme('page', og_invite_form($gid)); } } else { print theme('page', og_invite_form($gid)); } } else { drupal_access_denied(); } } function og_invite_form($gid) { $edit = $_POST['edit']; $max = variable_get('og_email_max', 10); $form .= form_textfield(t('Email addresses'), 'mails', $edit['mails'], 90, 250, t("Enter up to %max email addresses. Separate multiple addresses by commas. Each will receive an invitation message from you.", array('%max' => $max)), NULL, TRUE); $form .= form_textarea(t('Personal message'), 'pmessage', $edit['pmessage'], 90, 5, t('Optional. Enter a message which will become part of the invitation email')); $form .= form_button(t('Send invitation')); return form($form); } function og_subscribe($gid, $uid = NULL) { global $user; if (is_null($uid)) { if ($user->uid) { $account = $user; } else { drupal_set_message(t('In order to subscribe to this group, you must login or register a new account. After you have successfully done so, you will need to follow the subscribe link again.')); drupal_goto('user'); } } else { $account = user_load(array('uid' => $uid)); } if ($account->uid != $user->uid && !node_access('update', array('nid' => $gid, 'status' => 1))) { // only admins can subscribe another person drupal_access_denied(); } $return = og_subscribe_user($gid, $account); if ($return == 'approved') { drupal_set_message(t('Subscription request awaits approval by an administrator.')); } else if ($return == 'subscribed') { drupal_set_message(t('User subscribed to group,')); } drupal_goto("node/$gid"); } /** * subscribe given user to given group. no access control since this is an API function * * @return string 'approval' or 'subscribed' depending on the group's configuration. **/ function og_subscribe_user($gid, $account) { $names = array('nid', 'realm', 'gid', 'grant_view', 'grant_update'); $values = array($gid, "'og_uid'", $account->uid); // moderated groups must approve all members (selective=1) // if you can't view/edit/delete, you are *requesting* membership in the group // if you can view, you are a member // if you can edit, you are an admin $node = node_load(array('nid' => $gid)); if ($node->og_selective) { $values[] = 0; $values[] = 0; $sql = og_list_users_sql(1, 1); $res = db_query($sql, $node->nid); while ($row = db_fetch_object($res)) { $admins[] = $row->mail ? $row->mail : NULL; } $subj = t("Subscription request for '%group' from '%name'", array('%group' => $node->title, '%name' => $account->name)); $body = t('You may approve or deny this request at %url', array('%url' => url("og/approve/$node->nid/$account->uid", NULL, NULL, TRUE))); $from = variable_get('site_mail', ini_get('sendmail_from')); $headers = "From: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from"; user_mail(implode(', ', $admins), $subj, $body, $headers); $return_value = 'approval'; } else { $values[] = 1; $values[] = 0; $return_value = 'subscribed'; } $sql = 'REPLACE INTO {node_access} ('. implode(',', $names). ') VALUES ('. implode(',', $values). ')'; db_query($sql); return $return_value; } function og_unsubscribe($gid, $uid = NULL) { global $user; if (is_null($uid)) { $uid = $user->uid; } if ($uid != $user->uid && !node_access('update', array('nid' => $gid, 'status' => 1))) { // only admins can unsubscribe another person drupal_access_denied(); } $sql = "DELETE FROM {node_access} WHERE gid = %d AND nid = %d AND realm = 'og_uid'"; db_query($sql, $uid, $gid); $sql = "DELETE FROM {og_uid} WHERE nid=%d AND uid=%d"; db_query($sql, $gid, $uid); drupal_set_message(t('User unsubscribed from group.')); drupal_goto("node/$gid"); } // since a user's subscriptions are loaded into $user object, this function is only occassionally useful to get group subs for users other than the current user // even then, it often makes sense to call user_load() instead of this function. // load all subscriptions for a given user function og_get_subscriptions($uid) { static $subscriptions = array(); if (!isset($subscriptions[$uid])) { $sql = "SELECT na.*, n.title, ou.mail_type FROM {node_access} na INNER JOIN {node} n ON na.nid = n.nid LEFT JOIN {og_uid} ou ON n.nid=ou.nid WHERE gid = %d AND realm = 'og_uid' AND grant_view = 1"; $result = db_query($sql, $uid); while ($row = db_fetch_object($result)) { $subscriptions[$uid][$row->nid]['title'] = $row->title; $subscriptions[$uid][$row->nid]['mail_type'] = $row->mail_type; $subscriptions[$uid][$row->nid]['grant_view'] = $row->grant_view; $subscriptions[$uid][$row->nid]['grant_update'] = $row->grant_update; $subscriptions[$uid][$row->nid]['grant_delete'] = $row->grant_delete; } if (!$subscriptions[$uid]) { $subscriptions[$uid] = array(); } } return $subscriptions[$uid]; } /** * Implementation of hook_access(). */ function og_access($op, $node) { global $user; if ($op == 'create') { return user_access('create groups') && $user->uid; } } function og_list_users_sql($min_grant_view = 1, $min_grant_update = 0) { return "SELECT u.uid, u.name, u.mail, u.picture, na.* FROM {node_access} na INNER JOIN {users} u ON na.gid = u.uid AND na.nid = %d WHERE u.status > 0 AND realm = 'og_uid' AND grant_view >= $min_grant_view AND grant_update >= $min_grant_update ORDER BY u.name ASC"; } function og_add_users_page($gid) { if (node_access('update', array('nid' => $gid, 'status' => 1))) { if ($edit = $_POST['edit']) { $names = explode(',', $edit['og_names']); foreach ($names as $name) { $account = user_load(array('name' => trim($name))); if ($account->uid) { $accounts[] = $account; $uids[] = $account->uid; } else { $bad[] = $name; $err = TRUE; } } if (!$err && $accounts) { // safest option is to do a select, filter existing subscribers, then insert foreach ($accounts as $account) { $sql = "INSERT INTO {node_access} (nid, gid, realm, grant_view) VALUES (%d, %d, 'og_uid', 1)"; db_query($sql, $gid, $account->uid); } drupal_set_message(t('%count added to the group', array('%count' => format_plural(count($accounts), '1 user', '%count users')))); } else { form_set_error('og_names', t('Unrecognized %names: ', array('%names' => format_plural(count($bad), 'name', 'names'))). implode(', ', $bad)); } } $output = form_textarea(t('List of users'), 'og_names', $edit['og_names'], 70, 5, t('Add one or more usernames in order to associate users with this group. Multiple usernames should be separated by a comma.')); $output .= form_submit(t('Submit')); $output = form($output); print theme('page', $output); } else { drupal_access_denied(); } } function og_list_users_page($gid) { $sql = og_list_users_sql(0); $result = pager_query($sql, 500, 0, NULL, $gid); $header[] = t("Name"); $access = node_access('update', array('nid' => $gid, 'status' => 1)); if ($access) { $header[] = array('data' => t('Operations'), 'colspan' => 2); } // prepend the group owner $node = node_load(array('nid' => $gid)); $i=0; $rows[$i][] = format_name($node). ' '. t('manager'). ''; if ($access) { $rows[$i][] = l(t('edit group'), "node/$gid/edit"); $rows[$i][] = ' '; } $i++; while ($account = db_fetch_object($result)) { if ($account->uid != $node->uid) { $rows[$i][] = format_name($account); if ($access) { if ($account->grant_view) { $rows[$i][] = l(t('unsubscribe'), "og/unsubscribe/$gid/$account->uid", array(), "destination=og/users/$gid"); if ($account->grant_update) { $rows[$i][] = l(t('admin: remove'), "og/delete_admin/$gid/$account->uid", array(), 'destination='. $_GET['q']); } else { $rows[$i][] = l(t('admin: create'), "og/create_admin/$gid/$account->uid", array(), 'destination='. $_GET['q']); } } else { $rows[$i][] = l(t('approve'), "og/approve/$gid/$account->uid", array(), "destination=og/users/$gid"); $rows[$i][] = l(t('deny'), "og/deny/$gid/$account->uid", array(), "destination=og/users/$gid"); } } $i++; } } if ($pager = theme('pager', NULL, 500)) { $rows[$i][] = array('data' => $pager, 'colspan' => 2); } $output = theme('table', $header, $rows); $bc = array(l(t('Home'), ''), l(t('groups'), 'og'), l($node->title, "node/$node->nid")); drupal_set_breadcrumb($bc); drupal_set_title(t('Subscribers')); print theme('page', $output); } function og_list_groups_page() { global $user; $result = pager_query(db_rewrite_sql("SELECT n.nid, n.title, n.body, n.uid, u.name, og.description FROM {og} og INNER JOIN {node} n ON og.nid = n.nid INNER JOIN {users} u ON n.uid = u.uid WHERE og.directory=1 AND n.status=1 ORDER BY n.nid DESC"), 50); $header = array(t("Title"), t('Subscribers'), t("Owner"), t('Description')); while ($node = db_fetch_object($result)) { $cnt = db_num_rows(db_query(og_list_users_sql(), $node->nid)); $rows[] = array( array("data" => l($node->title, "node/$node->nid")), array("data" => in_array($node->nid, array_keys($user->og_groups)) ? l($cnt, "og/users/$node->nid") : $cnt), array("data" => format_name($node)), array("data" => check_plain($node->description)), ); } if (!$rows) { $rows[] = array(array('data' => t('No groups'), 'colspan' => 4)); } $output = theme('table', $header, $rows). theme('pager', NULL, 50); print theme('page', $output); } // str_types is a list of types which should be selected. if not provided, we return all but a couple function og_get_home_nodes_sql($str_types = NULL) { if ($str_types) { $str_types = db_escape_string($str_types); $where = " n.type IN ('$str_types')"; } else { $where = "n.type NOT IN ('og', 'image')"; } return "SELECT DISTINCT(n.nid), n.title, n.uid, u.name, n.created, l.comment_count, l.last_comment_timestamp FROM {node} n INNER JOIN {node_access} og_na ON n.nid = og_na.nid INNER JOIN {node_comment_statistics} l ON n.nid = l.nid INNER JOIN {users} u ON n.uid = u.uid WHERE og_na.gid = %d AND og_na.realm = 'og_group' AND n.status=1 AND $where ORDER BY n.sticky DESC, l.last_comment_timestamp DESC"; } // when you view a group, you really see some facts about the group in a block and then lists of nodes affiliated with that group. // each of these lists is presented by default in a table, although that can be changed by the theme function og_view(&$node, $teaser = FALSE, $page = FALSE) { $node = theme('og_view', $node, $teaser, $page); return $node; } // if you want a totally different group home page, you may redefine this function in your theme // if you just want to change the presentation of a group home page section, redefine theme_og_list_generic() function theme_og_view(&$node, $teaser = FALSE, $page = FALSE) { if ($teaser || !$page) { $node->teaser = $node->og_description; $node = node_prepare($node, $teaser); } else { $bc = array(l(t('Home'), ''), l(t('groups'), 'og')); drupal_set_breadcrumb($bc); $output =''; $mode = 'all'; if (!$types[] = $_GET['ntype']) { $types = node_list(); $mode = 'brief'; } foreach ($types as $type) { // image is filtered out here because we expect images to be added from within albums $exempt = array_merge(array('og', 'image'), variable_get('og_omitted', array())); if (!in_array($type, $exempt)) { if ($table = og_list_og($node->nid, $type, $mode)) { $output .= $table; } } } if (!$output) { drupal_set_message(t('No posts in this group.')); } $url = url("og/feed/$node->nid"); $icon = theme('xml_icon', $url); drupal_set_html_head("title RSS feed\" type=\"application/rss+xml\" />"); // metzlerd - tag on the node body $node = node_prepare($node,$teaser); $node->body = $node->body . $output. $icon; } return $node; } function og_form(&$node, &$param) { $edit = $_POST['edit']; if (function_exists('taxonomy_node_form')) { $output .= implode('', taxonomy_node_form('og', $node)); } $output .= form_textfield(t('Description'), 'og_description', $node->og_description, 70, 150, '', NULL, TRUE); // $output .= filter_form('format', $node->format); if (isset($edit['og_selective'])) { $selective = $edit['og_selective']; } elseif ($node->nid) { $selective = $node->og_selective; } else { $selective = OG_OPEN; } if (isset($edit['og_register'])) { $register = $edit['og_register']; } elseif ($node->nid) { $register = $node->og_register; } else { $register = 0; } if (isset($edit['og_directory'])) { $directory = $edit['og_directory']; } elseif ($node->nid) { $directory = $node->og_directory; } else { $directory = 1; } $output .= form_radios(t('Subscription requests'), 'og_selective', $selective, array(t('open - subscription requests are accepted immediately'), t('moderated - subscription requests must be approved.'), t('invite only - subscriptions must be created by an administrator.')), t('How should subscription requests be handled in this group?')); $output .= form_checkbox(t('registration form'), 'og_register', 1, $register, t('Should this group be available for subscription during registration?. If checked, a corresponding checkbox will be added to the registration form.')); $output .= form_checkbox(t('list in groups directory'), 'og_directory', 1, $directory, t('Should this group appear on the %page', array('%page' => l(t('list of groups page'),'og')))); //metzlerd - Add the ability to specify body to the form. $output .= form_textarea(t('Body'), 'body', $node->body, 60, 20, '', NULL, TRUE); $output .= filter_form('format', $node->format); // group image if (module_exist('image')) { if (is_array($node->images)) { foreach ($node->images as $label => $image) { $output .= form_hidden('images]['.$label, $image); } } if ($node->images['thumbnail']) { $output.= form_item(t('Thumbnail'), image_display($node, 'thumbnail')); } $output .= form_file(t('Image'), 'image', 50, t('Click "Browse..." to select an image to upload.')); $param['options'] = array("enctype" => "multipart/form-data", "name" => "image_forms"); } $allthemes = list_themes(); // list only active themes foreach ($allthemes as $key => $theme) { if ($theme->status) { $themes[$key] = $theme; } } if (count($themes) > 1) { $rows = array(); foreach ($themes as $key => $value) { $row = array(); // Screenshot column. $screenshot = dirname($value->filename) .'/screenshot.png'; $row[] = file_exists($screenshot) ? theme('image', $screenshot, t('Screenshot for %theme theme', array('%theme' => $value->name)), '', 'class="screenshot"', false) : t('no screenshot'); // Information field. $field = ''. $value->name .''; $row[] = $field; // Reset to follow site default theme if user selects the site default if ($key == variable_get('theme_default', 'bluemarine')) { $key = ''; if ($node->og_theme == variable_get('theme_default', 'bluemarine')) { $node->og_theme = ''; } } // Selected column. $row[] = array('data' => form_radio('', 'og_theme', $key, ($node->og_theme == $key) ? 1 : 0), 'align' => 'center'); $rows[] = $row; } $header = array(t('Screenshot'), t('Name'), t('Selected')); $output .= form_item(t('Group theme'), theme('table', $header, $rows), t('Select a theme for your group.')); } return $output; } // set og_public property for given node function og_node_load_public($node) { $sql = "SELECT grant_view FROM {node_access} WHERE nid = %d AND gid=0 AND realm='og_group'"; $gv = db_result(db_query($sql, $node->nid)); $node->og_public = $gv; return $node; } // returns all the group affiliations for a given node. function og_get_node_groups($node) { if ($node->type != 'og') { $sql = "SELECT na.gid, n.title FROM {node_access} na INNER JOIN {node} n ON na.gid = n.nid WHERE na.nid = %d AND na.realm='og_group' AND na.gid != 0"; $result = db_query($sql, $node->nid); while ($row = db_fetch_object($result)) { $groups[$row->gid] = $row->title; } return $groups ? $groups : array(); } } function og_image($gid) { $node = node_load(array('nid' => $gid)); $request = ($_GET['size']) ? $_GET['size'] : 'preview'; $output = image_display($node, $request); print theme('page', $output); } /** * Implementation of hook_validate */ function og_validate(&$node) { // comments are not allowed on group nodes, since we don't have any nice way to present them $node->comment = 0; // Reset to follow site default theme if user selects the site default if ($node->og_theme == variable_get('theme_default', 'bluemarine')) { $node->og_theme = NULL; } if (module_exist('image')) { image_validate($node, 'image'); } } function og_node_name($node) { return t('group'); } function og_load(&$node) { $sql = 'SELECT selective AS og_selective, description AS og_description, theme AS og_theme, register AS og_register, directory AS og_directory FROM {og} WHERE nid = %d'; $result = db_query($sql, $node->nid); $node = (object) array_merge((array)$node, db_fetch_array($result)); // module_invoke does not pass references and image_load() requires this if ($node->og_image && function_exists('image_load')) { image_load($node); } } function og_insert($node) { $sql = "INSERT INTO {og} (nid, theme, selective, description, register, directory) VALUES (%d, '%s', %d, '%s', %d, %d)"; db_query($sql, $node->nid, $node->og_theme, $node->og_selective, $node->og_description, $node->og_register, $node->og_directory); } function og_update($node) { if ($node->images) { foreach ($node->images as $label => $image) { $old_path = db_result(db_query("SELECT filepath FROM {files} WHERE filename='%s' AND nid=%d", $label, $node->nid)); // This is a new image. if ($old_path != $image) { file_delete(file_create_path($old_path)); db_query("DELETE FROM {files} WHERE filename='%s' AND nid=%d", $label, $node->nid); _image_insert($node->nid, $label, file_create_path($image)); } } } $sql = "UPDATE {og} SET theme = '%s', selective = %d, register = %d, description = '%s', directory = %d WHERE nid = %d"; db_query($sql, $node->og_theme, $node->og_selective, $node->og_register, $node->og_description, $node->og_directory, $node->nid); } /** * Implementation of hook_nodeapi(). * */ function og_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) { switch ($op) { case 'view': if ($bc = $GLOBALS['og_node_bc']) { drupal_set_breadcrumb($bc); } break; case 'load': if ($node->type != 'og') { $node = og_node_load_public($node); } if ($grps = og_get_node_groups($node)) { // TODO: Refactor so we don't need 2 arrays. $node->og_groups = array_keys($grps); $node->og_groups_names = array_values($grps); } break; case 'validate': global $user; if ($node->type != 'og') { // 'og/album/validate' is a special case. We want the audience validation even if 'image' node type is omitted // Used for album module galleries if (!in_array($node->type, variable_get('og_omitted', array())) || substr_count($_GET['q'], 'og/album/validate')) { if (variable_get('og_audience_required', 0) && empty($node->og_groups) && $_POST) { form_set_error('og_groups', t('You must select an audience in order to post.')); } else { if (is_array($node->og_groups)) { foreach($node->og_groups as $gid) { if (!in_array($gid, array_keys($user->og_groups))) { form_set_error('og_groups', t('%name must be a subscriber in order to post into %group', array('%name' => $node->name, '%group' => $$user->og_groups[$gid]['title']))); } } } } if (!user_access('administer organic groups')) { $vis = variable_get('og_visibility', 0); switch ($vis) { case OG_VISIBLE_BOTH: $node->og_public = 1; break; case OG_VISIBLE_GROUPONLY: $node->og_public = 0; break; } } } // if a post isn't in any groups. it must be public if (empty($node->og_groups)) { $node->og_public = 1; } } break; case 'delete': og_delete_folksonomy($node); og_delete_permissions($node); break; case 'insert': og_save_permissions($node); og_mail($node); break; case 'update': og_save_permissions($node); break; case 'form post': return og_nodeapi_form($node); } } function og_nodeapi_form($node) { $edit = $_REQUEST['edit']; // 'og/albums/form' is a special case. We want the audience selection and 'public' checkbox even if 'image' node type is omitted // Used for album module galleries if ( substr_count($_GET['q'], 'og/albums/form') == 0 && ( $node->type == 'og' || ( in_array($node->type, variable_get('og_omitted', array()))))) { return form_hidden('og_public', 1); } else { $required = variable_get('og_audience_required', 0); $subs = og_get_subscriptions($node->uid); foreach ($subs as $key => $val) { $options[$key] = $val['title']; } if (!$options && $required && $_POST) { drupal_set_message(t('You must subscribe to a group before posting.'), 'error'); } if (user_access('administer organic groups')) { $vis = OG_VISIBLE_CHOOSE; drupal_set_message(t('Admins: If you want to assign this post to a group whose checkbox does not appear below, you must first change the %author. The author\'s subscriptions are always shown.', array('%author' => theme('placeholder', t('Author'))))); } else { $vis = variable_get('og_visibility', 0); } switch ($vis) { case OG_VISIBLE_CHOOSE: //user decides how public the post is if (isset($edit['og_public'])) { $public = $edit['og_public']; } elseif ($node->nid) { $public = $node->og_public; } else { $public = 1; } $output .= form_checkbox(t('Public'), 'og_public', 1, $public, t('Show this post to everyone or only to members of the checked selected below.')); break; } if (isset($edit['og_groups'])) { $groups = $edit['og_groups']; } elseif ($node->nid) { $groups = $node->og_groups; } else { $groups = array(); } $output .= form_checkboxes(t('Audience'), 'og_groups', $groups, $options, t('Show this post in these groups.'), NULL, $required); return $output; } } /** * Send this node via email to all email subscribers. Called from og_nodeapi() * * @param $node * the node which was just added or updated * @return * none */ function og_mail($node) { if ($node->og_groups) { $url = url("node/$node->nid", NULL, NULL, TRUE); $author = user_load(array('uid' => $node->uid)); $sitemail = variable_get("site_mail", ini_get("sendmail_from")); $headers = "From: $sitemail\nReply-to: $sitemail\nX-Mailer: Drupal\nReturn-path: $sitemail\nErrors-to: $sitemail"; //get email subscribers $groups = implode(', ', $node->og_groups); $sql = "SELECT DISTINCT(u.mail) as mail, ou.nid AS gid, n.title AS group_name FROM {og_uid} ou INNER JOIN {users} u ON ou.uid=u.uid INNER JOIN {node} n ON ou.nid=n.nid WHERE ou.nid IN ($groups) AND ou.mail_type=1"; $result = db_query($sql); while ($row = db_fetch_object($result)) { $subj = "[$row->group_name] ". t('%author added \'%title\' at %site', array('%author' => $author->name, '%title' => $node->title, '%site' => variable_get('site_name', drupal))); $txt = "'$node->title' by $author->name\n$url\n\n"; $txt .= $node->read_more ? t('EXCERPT') : t('FULL POST'); $txt .= "\n". og_mail_output($node->teaser, 1, $node->format); $txt .= "\n\n-----------------------\n"; $txt .= t("You are subscribed to the group '%group_name' at '%site'. To manage your subscription, visit %group_url", array('%group_name' => $row->group_name, '%site' => variable_get('site_name', drupal), '%group_url' => url("og/manage/$row->gid", NULL, NULL, TRUE))); $subject = "[]"; user_mail($row->mail, $subj, $txt, $headers); } } } // 2 functions blatantly ripped from mail.inc in project.module package function og_mail_urls($url = 0) { static $urls = array(); if ($url) { $urls[] = strpos($url, '://') ? $url : url($url, NULL, NULL, 1); return count($urls); } return $urls; } function og_mail_output(&$body, $html = 1, $format = FILTER_FORMAT_DEFAULT) { static $i = 0; if ($html) { $pattern = '@((.+?))@ei'; $body = preg_replace($pattern, "'\\3 ['. og_mail_urls('\\2') .']'", $body); $urls = og_mail_urls(); if (count($urls)) { $body .= "\n"; for ($max = count($urls); $i < $max; $i++) { $body .= '['. ($i + 1) .'] '. $urls[$i] ."\n"; } } $body = check_output($body, $format); $body = preg_replace('!!i', '"', $body); $body = preg_replace('!!i', '/', $body); $body = preg_replace('!!i', '*', $body); $body = preg_replace("@
(?!\n)@i", "\n", $body); $body = preg_replace("@

(?!\n\n)@i", "\n\n", $body); $body = preg_replace("@
  • @i", "* ", $body); $body = preg_replace("@
  • \n?@i", "\n", $body); $body = strip_tags($body); $body = decode_entities($body); $body = wordwrap($body, 72); } else { $body = decode_entities($body); } } function og_user($op, &$edit, &$account, $category = NULL) { global $user; switch ($op) { case 'register': $options = array(); $values = array(); $result = db_query(db_rewrite_sql("SELECT n.nid, n.title, o.* FROM {node} n INNER JOIN {og} o ON n.nid = o.nid WHERE n.type = 'og' AND o.register = 1")); while ($group = db_fetch_object($result)) { $options[$group->nid] = t('Subscribe to %name', array('%name' => theme('placeholder', $group->title))); $values[$group->nid] = in_array($group->nid, (array) $edit['og_register']) ? $group->nid : 0; if ($group->selective) { $options[$group->nid] .= ' '. theme('placeholder', t('(approval needed)')); } } if (count($options)) { return array(array('title' => t('Groups'), 'data' => form_checkboxes('', 'og_register', $values, $options))); } break; case 'insert': if (($_GET['q'] == 'user/register') ? 1 : 0) { $result = db_query(db_rewrite_sql("SELECT n.nid, n.title, o.* FROM {node} n INNER JOIN {og} o ON n.nid = o.nid WHERE n.type = 'og' AND n.status = 1 AND o.register = 1")); while ($group = db_fetch_object($result)) { if (in_array($group->nid, (array) $edit['og_register'])) { og_subscribe_user($group->nid, $account); } } } break; case 'load': $account->og_groups = og_get_subscriptions($account->uid); break; case 'view': // only show to self and admins if ($account->uid == $user->uid || user_access('administer organic groups')) { if ($account->og_groups) { foreach ($account->og_groups as $key => $val) { $links[] = l($val['title'], "node/$key"); } return array(t('Groups') => form_item('', theme('item_list', $links), t('your group subscriptions are here for your convenience. they do not appear on the public profile page.'))); } } break; } } /** * In the 'og_uid' realm, the gid is a uid. This is used to determine a whether a user * is a member of a group, and what his permissions are in that group (view/update/delete of the 'group' node). When a * user has permissions of 0,0,0 he is considered to be 'applying' for access to a private group * * In the 'og_group' realm, the gid is a nid of a group. This is used * to store which nodes should show up in which groups. When applied to an og node, this record is * always 1 but you can set it to 0 in order to have a completely private group. **/ function og_node_grants($account, $op) { $grants['og_uid'][] = $account->uid; $grants['og_group'][] = 0; // get subscriptions if ($subscriptions = og_get_subscriptions($account->uid)) { foreach ($subscriptions as $key => $val) { if ($val["grant_$op"]) { $grants['og_group'][] = $key; } } } return $grants ? $grants : array(); } function og_save_permissions(&$node) { global $user; $sql = "DELETE FROM {node_access} WHERE realm = 'og_group' AND nid = %d"; db_query($sql, $node->nid); if ($node->type != 'og') { // put the post into each selected group if (is_array($node->og_groups)) { foreach($node->og_groups as $gid) { $sql = "INSERT INTO {node_access} (nid, gid, realm, grant_view) VALUES (%d, %d, 'og_group', 1)"; db_query($sql, $node->nid, $gid); } } // if the public checkbox was selected, give a universal grant for this node if ($node->og_public) { $sql = "INSERT INTO {node_access} (nid, gid, realm, grant_view) VALUES (%d, 0, 'og_group', 1)"; db_query($sql, $node->nid); } } else { // all groups are publically accessible, although their posts may not be // if you really want a hidden group, you should go to node_access table and delete the record which is inserted here. $sql = "INSERT INTO {node_access} (nid, gid, realm, grant_view) VALUES (%d, 0, 'og_group', 1)"; db_query($sql, $node->nid); // make sure the node owner is a full powered subscriber $sql = "REPLACE INTO {node_access} (nid, gid, realm, grant_view, grant_update, grant_delete) VALUES (%d, %d, 'og_uid', 1, 1, 1)"; db_query($sql, $node->nid, $node->uid); } } function og_delete_permissions(&$node) { // delete all existing grants for this module $sql = "DELETE FROM {node_access} WHERE realm = '%s' AND nid = $node->nid"; $realms = array('og_group', 'og_uid'); foreach ($realms as $realm) { db_query($sql, $realm); } } /** * Update the node_access table when a user enables/disables the module in the * settings page. Because Drupal does not, at this * time, provide hooks that run automatically upon the enabling/disabling of a * module in the admin/modules page, we must force the site-admin to explicitly * enable/disable a module on the settings page, in * addition to enabling/disabling the module in the admin/modules page. * * Here, if the user is enabling the module, we make sure the default entry in * the node_access table is deleted and walk through all the nodes in the node table * and grant all view access as is the default case when this module is not * enabled. We only do this for nodes whose permissions haven't been set before by * this module. It is possible that a site-admin may have previously enabled the * module before disabling it. Upon re-enabling, we want to account for the old * permissions set by the module by not re-inserting entries for them. * * Disabling the module simply requires re-inserting the default entry back into * the node access table to give 'view' perms to everyone for everything: * (0, 0, 'all', 1, 0, 0) */ function _og_update_db($enable) { if (!$enable) { // We use the delete statement to avoid inserting a duplicate entry into the database. // Without the DELETE query, this can happen when a site admin has already enabled the modules // from the settings page and goes back to it and resaves the enabled setting. db_query('REPLACE INTO {node_access} VALUES (0, 0, \'all\', 1, 0, 0)'); drupal_set_message(t('Organic groups access control has been disabled. You may now disable the module on the %modules page', array('%modules' => l(t('admin/modules'), 'admin/modules')))); } else { // the module was just enabled or re-enabled; provide default view access to everyone for nodes that were created // between the previous disabling of the module and the current enabling of the module; // nodes that were created during a previous enabled period are left-alone. // Permissions for those nodes will be the same as when the module was previously enabled. db_query('DELETE from {node_access} WHERE nid=0 AND gid=0 AND realm=\'all\' AND grant_view=1 AND grant_update=0 AND grant_delete=0'); // Assign universal grant to all non-group nodes which don't already have any grants from this module $result = db_query("SELECT n.nid FROM {node} n LEFT JOIN {node_access} na ON n.nid = na.nid AND realm LIKE '%og%' WHERE n.type != 'og' AND ISNULL(na.gid)"); while ($row = db_fetch_object($result)) { $sql = "INSERT INTO {node_access} (nid, gid, realm, grant_view) VALUES (%d, 0, 'og_group', 1)"; db_query($sql, $row->nid); } drupal_set_message(t('Organic groups access control enabled.')); } } function og_feed($gid) { $group = (object) array('nid' => $gid, 'status' => 1); if (node_access('view', $group)) { $sql = og_get_home_nodes_sql(); $result = db_query(db_rewrite_sql($sql), $gid); while ($onenode = db_fetch_array($result)) { $nodes[] = $onenode['nid']; } if ($nodes) { $sql = 'SELECT nid FROM {node} WHERE nid IN (%s)'; $result = db_query($sql, implode(', ', $nodes)); $node = node_load(array('nid' => $gid)); $channel['title'] = $node->title; $channel['link'] = url("node/$gid", NULL, NULL, TRUE); $channel['description'] = $node->og_description; node_feed($result, $channel); } else { die('no posts in this group'); } } else { drupal_access_denied(); } } function og_albums_page($gid, $str_tags, $operator = 'or') { if (strstr($str_tags, ',')) { $tags = explode(',', $str_tags); } else { $tags = array($str_tags); } if ($tags) { $title = str_replace(array(',', '+'), ', ', $str_tags); $node = node_load(array('nid' => $gid)); $bc = array(l(t('Home'), ''), l(t('groups'), 'og'), l($node->title, "node/$node->nid")); $result = folksonomy_select_nodes($tags, $operator, 'image', 'og_group_'. $node->nid); // append 'create album' link if available and permitted. if (user_access('create images') && module_exist('folksonomy')) { global $user; if ($user->og_groups[$node->nid]['grant_view']) { $links[] = l(t('add to this album'), 'og/albums/form', array(), "edit[og_groups][]=$node->nid&edit[og_tags]=". urlencode($str_tags)); $output .= theme('links', $links); } } $output .= taxonomy_render_nodes($result); drupal_set_breadcrumb($bc); drupal_set_title($title); print theme('page', $output); } else { drupal_not_found(); } } function og_albums_form() { $edit = $_REQUEST['edit']; $output = form_textfield(t('Album Title'), 'og_tags', $edit['og_tags'], 100, 255); // TODO: output 100 form fields but show/hide the remaining 90 only if user clicks a button. requires a touch of javascript // change n below to show more or less file upload fields $n = 15; for ($i=1; $i <= $n; $i++) { $output .= form_file(t('Photo'). $i, "photo$i", 100); } global $user; $edit = array_merge(array('type' => 'image', 'uid' => $user->uid), $edit); $output .= og_nodeapi(array2object($edit), 'form post'); $output .= form_button(t('Submit')); if ($gid = $edit['og_groups'][0]) { $node = node_load(array('nid' => $gid)); $bc = array(l(t('Home'), ''), l(t('groups'), 'og'), l($node->title, "node/$node->nid")); drupal_set_breadcrumb($bc); } print theme('page', form($output, 'post', url('og/albums/validate'), array("enctype" => "multipart/form-data"))); } function og_albums_validate() { $edit = $_REQUEST['edit']; $uploads = $_FILES['edit']['name']; if (!$edit['og_tags']) { $msg = t('You must specify an album title.'); form_set_error('og_tags', $msg); $errors[] = $msg; } foreach ($uploads as $field => $filename) { if ($filename) { $node = new stdClass(); $node->title = $filename; global $user; $node->uid = $user->uid; $tag = array('name' => $edit['og_tags']); if ($edit['og_groups']) { $node->og_groups = $edit['og_groups']; foreach ($node->og_groups as $group) { $node->folksonomy['og_group_'. $group] = $tag; } } $node->og_public = $edit['og_public']; $node->type = 'image'; // TODO: in HEAD, use node_submit() instead of node_save() and simplify this greatly // Validate for normal users: $node->uid = $user->uid ? $user->uid : 0; // Force defaults in case people modify the form: $node->status = variable_get("node_status_$node->type", 1); $node->promote = variable_get("node_promote_$node->type", 1); $node->moderate = variable_get("node_moderate_$node->type", 0); $node->sticky = variable_get("node_sticky_$node->type", 0); $node->revision = variable_get("node_revision_$node->type", 0); unset($node->created); // the line below needs some work before transforming into node_submit(). maybe move up before calling node_submit() image_validate($node, $field); node_invoke_nodeapi($node, 'validate'); $node->validated = TRUE; if ($error = form_get_errors()) { $errors[] = $error; unset($error); } else { $nodes[] = $node; } } } if ($errors) { og_albums_form(); } else { $links = og_albums_save($nodes); drupal_set_message(t('album saved.')); $gid = $edit['og_groups'][0]; $dest = "og/albums/$gid/". urlencode($tag[name]); drupal_goto($dest); } } function og_albums_save($nodes) { global $user; foreach ($nodes as $node) { $nid = node_save($node); // $links[] = $nid ? l($node->title, "node/$nid") : t('failed to save %title', array('title' => $node->title)); } // return $links; } /** * Implementation of hook_block(). */ function og_block($op = 'list', $delta = 0, $edit = array()) { if ($op == 'list') { $blocks[0]['info'] = t('Group details'); $blocks[1]['info'] = t('Group albums'); $blocks[2]['info'] = t('Group subscribers'); $blocks[3]['info'] = t('New groups'); $blocks[4]['info'] = t('My groups'); return $blocks; } elseif ($op == 'view') { switch ($delta) { case 0: return og_block_details(); case 1: return og_block_albums(); case 2: return og_block_subscribers(); case 3: return og_block_new(); case 4: return og_block_my(); } } else if ($op == 'configure') { switch ($delta) { case 2: case 3: return form_textfield(t('Maximum number of items to show'), 'og_block_cnt', $edit['og_block_cnt'] ? $edit['og_block_cnt'] : variable_get("og_block_cnt_$delta", 10), 5, 255, ''); } } else if ($op == 'save') { switch ($delta) { case 2: case 3: if (isset($edit['og_block_cnt'])) { variable_set("og_block_cnt_$delta", $edit['og_block_cnt']); } break; } } } function og_block_my() { global $user; if ($user->og_groups) { foreach ($user->og_groups as $key => $val) { $items[] = l($val['title'], "node/$key"); } $block['subject'] = t('My groups'); $block['content'] = theme('item_list', $items); return $block; } } function og_block_new() { $sql = "SELECT COUNT(*) FROM {node} n INNER JOIN {og} og ON n.nid = og.nid WHERE og.directory=1 AND n.type = 'og' AND n.status = 1"; $cnt = db_result(db_query(db_rewrite_sql($sql))); if ($cnt > 0) { $max = variable_get('og_block_new_cnt', 10); $sql = "SELECT n.nid, n.title FROM {node} n INNER JOIN {og} og ON n.nid = og.nid WHERE n.status = 1 AND n.type = 'og' AND og.directory=1 ORDER BY nid DESC"; $result = db_query_range(db_rewrite_sql($sql), 0, $max); $output = node_title_list($result); if ($cnt > $max) { $output .= ''; } $block['subject'] = t('New groups'); $block['content'] = $output; return $block; } } function og_block_albums() { if (module_exist('image') && module_exist('folksonomy') && $gid = $_SESSION['og_last']->nid) { $sql = "SELECT n.nid, f.name AS fname, COUNT(f.name) AS fcount, u.name, u.uid FROM {folksonomy} f INNER JOIN {node} n ON f.id = n.nid INNER JOIN {users} u ON n.uid = u.uid WHERE f.realm = 'og_group_$gid' GROUP BY f.name ORDER BY id DESC"; $result = db_query($sql); while ($row = db_fetch_object($result)) { $submitter = t('submitted by %name. ', array('%name' => $row->name)); $count = format_plural($row->fcount, '1 image', '%count images'); $links[] = l($row->fname, "og/albums/$gid/". urlencode($row->fname), array('title' => $submitter. ' '. $count)); } if ($links) { $block['content'] = theme('item_list', $links); $block['subject'] = t('Albums'); return $block; } } } function og_block_subscribers() { global $user; if ($gid = $_SESSION['og_last']->nid) { if (in_array($gid, array_keys($user->og_groups))) { $max = variable_get('og_block_subscribers_cnt', 10); $sql = og_list_users_sql(0); $result = db_query_range($sql, $gid, 0, $max); while ($row = db_fetch_object($result)) { //showing member pictures if (variable_get('og_member_pics', 1)) { $link = theme('user_picture', $row). format_name($row); } else { $link = format_name($row); } if (!$row->grant_view) { $link .= theme_mark(); } $links[] = $link; } if ($links) { if (count($links) > $max-1) { array_pop($links); $append = '';; } $block['content'] = theme('item_list', $links). $append; $block['subject'] = t('Recent subscribers'); return $block; } } } } function og_block_details() { global $user; if ($gid = $_SESSION['og_last']->nid) { $node = node_load(array('nid' => $gid)); $result = db_query(og_list_users_sql(0), $node->nid); $cntall = db_num_rows($result); $cntpending = 0; while ($row = db_fetch_object($result)) { if ($row->grant_view == 0) { $cntpending++; } if ($row->uid == $user->uid) { if ($row->grant_view) { $subscription = 'active'; } else { $subscription = 'requested'; } } } $output = "
    ". check_plain($node->og_description). "

    "; if ($subscription == 'active') { $links = og_create_links($node); if ($node->og_selective < OG_INVITE_ONLY) { $links[] = l(t('invite friend'), "og/invite/$node->nid"); } $txt = format_plural($cntall-$cntpending, '1 subscriber', '%count subscribers'); $txt = l($txt, "og/users/$node->nid"); $txt .= $cntpending ? " ($cntpending)" : ''; $links[] = $txt; $links[] = t('age: %age', array('%age' => format_interval(time()-$node->created, 2))); if (variable_get('og_member_pics',1)) { $links[] = t('group manager: '). theme('user_picture',$node). format_name($node); } else { $links[] = t('group manager: '). format_name($node); } $links[] = l(t('my subscription'), "og/manage/$node->nid"); } elseif ($subscription == 'requested') { $links[] = t('Your subscription request awaits approval.'); $links[] = l(t('delete request'), "og/unsubscribe/$node->nid", array(), 'destination=og'); } elseif ($user->uid && $node->og_selective < OG_INVITE_ONLY) { if ($node->og_selective == OG_MODERATED) { $txt = t('request subscription'); } elseif ($node->og_selective == OG_OPEN) { $txt = t('subscribe'); } $links[] = l($txt, "og/subscribe/$node->nid", array(), "destination=node/$node->nid"); } $output .= theme('item_list', $links); $block['content'] = $output; // display group image. $block['content'] .= $node->images ? image_display($node, 'thumbnail') : ''; $block['subject'] = l($node->title, "node/$node->nid"); return $block; } } // $group is an object containing the group node function og_create_links($group) { foreach (node_list() as $type) { // image is filtered out here because we expect images to be added from within albums $exempt = array_merge(array('og', 'image'), variable_get('og_omitted', array())); if (!in_array($type, $exempt) && node_access('create', $type)) { $name = node_invoke($type, 'node_name', array()); $links[] = l(t('create %type', array('%type' => $name)), "node/add/$type", array('title' => t('Add a new %s in this group.', array('%s' => $name))), "edit[og_groups][]=$group->nid"); } } // append 'create album' link if available. if (user_access('create images') && module_exist('folksonomy')) { $sql = "SELECT DISTINCT(name) FROM {folksonomy} WHERE realm = 'og_group_$group->nid'"; $unlimited = variable_get('og_album_unlimited', TRUE); if ($unlimited || db_num_rows(db_query($sql)) == 0) { $links[] = l(t('create album'), 'og/albums/form', array(), "edit[og_groups][]=$group->nid"); } } return $links ? $links : array(); } function og_link($type, $node = 0, $main) { global $user; if ($gid = $_SESSION['og_last']->nid) { if ($type == 'node' && $node->type != 'og' && node_access('update', array('nid' => $gid, 'status' => 1))) { $links[] = l(t('remove from group'), "og/remove_node/$gid/$node->nid", array(), "destination=node/$gid"); } } return $links ? $links : array(); } function og_settings() { $op = $_POST['op']; drupal_set_title(t('Organic groups configuration')); $status = t('disabled'); $btn_text = t('Enable'); if (variable_get('og_enabled', 0)) { $status = t('enabled'); $btn_text = t('Disable'); } $group = t('Organic groups access control is currently') . ' ' . theme('placeholder', $status). '.
    '; $group .= form_button($btn_text). '
    '; $output = form_group(t('Module status'), $group, t('After enabling this module via the module settings page or before disabling this module, use the above button to restore default permissions.')); if ($op) { if ($op == t('Enable')) { _og_update_db(TRUE); variable_set('og_enabled', 1); } elseif ($op == t('Disable')) { _og_update_db(FALSE); variable_set('og_enabled', 0); } drupal_goto('admin/settings/og'); } $output .= form_textarea(t('Explanation or submission guidelines'), 'og_help', variable_get('og_help', ''), 70, 5, t('This text will be displayed at the top of the group submission form. It is useful for helping or instructing your users.')); $output .= form_checkbox(t('Unlimited albums'), 'og_album_unlimited', 1, variable_get('og_album_unlimited', TRUE), t('If you want to limit your groups to a single album, uncheck this box.')); $options = array(t('Visible only within the targeted groups'), t('Visible within the targeted groups and on other pages'), t('Visibility to be determined by the author/editor using a checkbox on the posting form')); $output .= form_radios(t('Visibility of posts'), 'og_visibility', variable_get('og_visibility', 0), $options, t('Determine how broadly available a given post should be when it is affiliated with a group. OG admins always see the checkbox for making a post %pub. Note that changing this setting has no effect on existing posts. Re-save those posts to acquire this new setting.', array('%pub' => theme('placeholder', t('Public'))))); $output .= form_textfield(t('Maximum posts on group home page'),'og_max_posts',variable_get('og_max_posts', 10), 3, 2, t("How many posts of a given type should display on the group home page.")); // TODO: move this to block config? Will be used elsewhere? $output .= form_checkbox( t('Show member pictures'), 'og_member_pics', 1, variable_get('og_member_pics', 1), t('Should member pictures be shown in the group subscribers and group details blocks? You must also enable pictures in %user.', array('%user' => l(t('User configuration'), 'admin/user/configure')))); $options = array(t('optional'), t('required')); $output .= form_radios(t('Audience required'), 'og_audience_required', variable_get('og_audience_required', 0), $options, t('Do you require that all posts be affiliated with a group? If so, new users will be unable to complete a post until they join a group. Note that changing this setting has affect existing posts when they are edited.')); unset($options); foreach (node_list() as $type) { $options[$type] = module_invoke(node_get_module_name($type), 'node_name', array()); } unset($options['og']); $output .= form_select(t('Omitted content types'), 'og_omitted', variable_get('og_omitted', array()), $options, t('Select any node types which should not participate in the Audience targetting system.'), 0, TRUE); return $output; } // try to get the theme's preferred way to show each type's node listing. if not specified, show the generic node listing (which is also themeable) // $mode can be 'brief' or 'all' function og_list_og($gid, $type, $mode = 'all') { $output = theme(node_get_module_name($type). '_list_og', $gid, $mode); if (!$output) { $output = theme('og_list_generic', $gid, $type, $mode); } return $output; } // you may theme this function, or even theme each node type listing separately function theme_og_list_generic($gid, $type, $mode) { static $i; $header = array(t('Title'), t('Author'), t('Replies'), t('Last reply')); $sql = og_get_home_nodes_sql($type); $num = $mode == 'brief' ? variable_get('og_max_posts', 10) : 50; $i++; // multiple pagers on a page need a unique integer $result = pager_query(db_rewrite_sql($sql), $num, $i, NULL, $gid); while ($row = db_fetch_object($result)) { $rows[] = array(l($row->title, "node/$row->nid"), format_name($row), $row->comment_count, format_date($row->created, 'small')); } if ($pager = theme('pager', NULL, $num, $i, array('ntype' => $type))) { $rows[] = array(array('data' => $pager, 'colspan' => '4')); } return $rows ? form_group(node_invoke($type, 'node_name'), theme('table', $header, $rows)) : NULL; } ?>