[inviter-name] at [site-name] has invited you to a [type] called [title]!\n

Use this form to confirm (or deny) attendance.

"); define('NODE_INVITE_MESSAGE_DEFAULT', '

[inviter-name] invites you to rsvp for a [type]!

Visit [title] for more information or just check out the RSVP Page to confirm your attendance!

'); define('NODE_INVITE_SUBJECT_DEFAULT', "[inviter-name] at [site-name] has invited you to a [type] called [title]!"); define('NODE_INVITE_NOTIFY_SITE_ADMIN_YES_SUBJECT', '[site-name] - Invite ACCEPT notification'); define('NODE_INVITE_NOTIFY_SITE_ADMIN_YES', 'An invite was accepted for node [nid]. Login to the site to view it.'); define('NODE_INVITE_NOTIFY_SITE_ADMIN_ALL_SUBJECT', '[site-name] - Invite response notification'); define('NODE_INVITE_NOTIFY_SITE_ADMIN_ALL', 'An invite was acted upon for node [nid]. Login to the site to view it.'); define('NODE_INVITE_NOTIFY_INVITEE_CONFIRM_SUBJECT', '[site-name] - Invite response confirmation'); define('NODE_INVITE_NOTIFY_INVITEE_CONFIRM', 'Your invite selection for [title] has been processed. Thanks!'); define('NODE_INVITE_NOTIFY_INVITER_NOTIFY_SUBJECT', '[site-name] - Invite response!'); define('NODE_INVITE_NOTIFY_INVITER_NOTIFY', 'Your invite selection for [title] has been acted upon. Please login to the site and click "Invites" to view it. Thanks!'); /* added to enable per-node override with a checkbox */ define('NODE_INVITE_DEFAULT_FOR_ENABLED_NODES', 1); /** * Implementation of hook_help(). */ function node_invite_help( $path, $arg ) { $output = ''; switch ($path) { case 'admin/help/node_invite': $output .= t('

Node Invite Provides a means to invite people to nodes. Customized email message is token enabled.

'); $output .= t('

Here are tokens you can use:

'); $output .= theme('token_help'); break; case 'admin/settings/node_invite': $output .= '

Node invite allows you to invite people to nodes. The email they receive is token-enabled.

'; break; } return $output; } /** * Implementation of hook_perm(). */ function node_invite_perm() { return array( 'invite users to invite-enabled nodes', 'admin node invite settings', 'respond to invites', 'manage all invites', 'manage own invites', ); } /** * Implementation of hook_menu(). */ function node_invite_menu() { $items = array(); $items['admin/settings/node_invite'] = array( 'title' => t('Node Invite'), 'description' => t('Node Invite module is similar to RSVP. Invite people to nodes, manage your invites, etc.'), 'access arguments' => array('admin node invite settings'), 'page callback' => 'drupal_get_form', 'page arguments' => array('node_invite_admin_settings_form'), 'file' => 'node_invite.admin.inc', ); $items['admin/settings/node_invite/settings'] = array( 'title' => t('Settings'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => 0, ); $items['admin/settings/node_invite/notifications'] = array( 'title' => t('Notifications'), 'type' => MENU_LOCAL_TASK, 'access arguments' => array('admin node invite settings'), 'page callback' => 'drupal_get_form', 'page arguments' => array('node_invite_notifications_form'), 'weight' => 1, 'file' => 'node_invite.admin.inc', ); $items['admin/settings/node_invite/manage'] = array( 'title' => t('Manage Invites'), 'type' => MENU_LOCAL_TASK, 'access arguments' => array('manage all invites'), 'page callback' => 'drupal_get_form', 'page arguments' => array('user_invites_form'), 'weight' => 2, 'file' => 'node_invite.admin.inc', ); $items['node_invite/invite/%'] = array( 'title' => t('Invite'), 'type' => MENU_CALLBACK, 'access arguments' => array('invite users to invite-enabled nodes'), 'page callback' => 'drupal_get_form', 'page arguments' => array('node_invite_send', 2), 'file' => 'node_invite.send.inc', ); $items['node_invite/rsvp/%node/%'] = array( 'title' => t('Invite'), 'type' => MENU_CALLBACK, 'access arguments' => array('respond to invites'), 'page callback' => 'drupal_get_form', 'page arguments' => array('node_invite_rsvp', 2, 3), 'file' => 'node_invite.rsvp.inc', ); $items['node_invite/revoke/%'] = array( 'title' => t('Revoke'), 'type' => MENU_CALLBACK, 'access callback' => 'node_invite_access_revoke', 'page callback' => 'drupal_get_form', 'page arguments' => array('node_invite_revoke', 2), ); $items['node_invite/resend/%'] = array( 'title' => t('Resend'), 'type' => MENU_CALLBACK, 'access callback' => 'node_invite_access_resend', 'page callback' => 'drupal_get_form', 'page arguments' => array('node_invite_resend', 2), ); $items['user/%user/invites'] = array( 'title' => 'My Invites', 'page callback' => 'node_invite_user_invites', 'page arguments' => array(1), 'type' => MENU_LOCAL_TASK, 'access arguments' => array('manage own invites'), 'weight' => 2, ); /* $items['node_invite/resend'] = array( 'title' => t('Invite'), 'type' => MENU_CALLBACK, 'access arguments' => array('invite users to invite-enabled nodes'), 'page callback' => 'drupal_get_form', 'page arguments' => array('node_invite_resend'), ); */ return $items; } /** * Implementation of hook_link(). */ function node_invite_link( $type, $node = NULL, $teaser = FALSE ) { global $user; $links = array(); if ($type == 'node' && _node_invite_type_is_allowed($node->type) && user_access('invite users to invite-enabled nodes') && _ni_node_is_enabled($node->nid)) { $links['node_invite'] = array( 'title' => t('Invite people to this @type', array('@type' => $node->type)), 'href' => "node_invite/invite/$node->nid", ); } return $links; } function _ni_node_is_enabled( $nid ) { $sth = db_query("SELECT invites_enabled FROM {node_invite_settings} WHERE nid = %d", $nid); $enabled = variable_get('node_invite_default', NODE_INVITE_DEFAULT_FOR_ENABLED_NODES); if ($row = db_fetch_array($sth)) { // if there's a row in the table, then they're being explicit... override the default $enabled = $row['invites_enabled']; } return $enabled; } function _node_invite_type_is_allowed( $type ) { if ( in_array( $type, variable_get('node_invite_node_types', array() ), TRUE ) ) { return TRUE; } return FALSE; } /** * Implementation of hook_mail(). */ function node_invite_mail( $key, &$message, $params ) { $message['headers']['Content-Type'] = 'text/html; charset=UTF-8; format=flowed'; $message['subject'] = $params['subject']; $message['body'] = $params['body']; } /** * Implementation of hook_token_values(). */ function node_invite_token_values($type, $object = NULL) { $values = array(); if (in_array($type, array('all', 'node_invite', 'node'))) { global $user; $values['inviter-name'] = $user->name; $values['inviter-mail'] = $user->mail; $values['inviter-rsvp-url'] = url('node_invite/invite/' . $object->nid, array('absolute' => TRUE)); $values['inviter-node-url'] = url('node/' . $object->nid, array('absolute' => TRUE)); // this is hacked in for each invite sent. Won't exist other times if (isset($object->invite_specific_info)) { $values['node-invite-iid'] = $object->invite_specific_info['node-invite-iid']; $values['node-invite-recip-name'] = $object->invite_specific_info['node-invite-recip-name']; $values['node-invite-recip-mail'] = $object->invite_specific_info['node-invite-recip-mail']; // the above were defaults... this comes in if alternatives are available $values['inviter-name'] = $object->invite_specific_info['inviter-name']; $values['inviter-mail'] = $object->invite_specific_info['inviter-mail']; } //drupal_set_message("Token values =
" . print_r( $values, TRUE ) . "
"); } return $values; } /** * Implementation of hook_token_list(). */ function node_invite_token_list( $type='all') { /* global $user; drupal_set_message("
" . sprint_r( $user )  . "
"); */ $tokens = array(); if (in_array($type, array('all', 'node_invite', 'node'))) { $tokens['node_invite']['inviter-name'] = t('The username of the person currently logged in (and thus sending the invite). This will not work as a page-title token since the person rendering the page title will be logged in as someone different (or anonymous).'); $tokens['node_invite']['inviter-mail'] = t('The email address of the person currently logged in (and thus sending the invite). This will not work as a page-title token since the person rendering the page title will be logged in as someone different (or anonymous).'); $tokens['node_invite']['inviter-rsvp-url'] = t('This is the URL of the RSVP form. Send users here to confirm or deny attendance.'); $tokens['node_invite']['inviter-node-url'] = t('This is the URL of the node to which they are being invited. Send them here "for more details."'); $tokens['node_invite']['node-invite-recip-mail'] = t('The email of the person receiving the invite'); $tokens['node_invite']['node-invite-recip-name'] = t('The name of the person receiving the invite'); $tokens['node_invite']['node-invite-iid'] = t('The invite_id (unique identifier) of the invite being sent'); } return $tokens; } /** * Implementation of hook_content_extra_fields(). */ function node_invite_content_extra_fields($type_name) { $extra = array(); if (_node_invite_type_is_allowed($type_name)) { $extra['node_invite_group'] = array( 'label' => t('Node invite settings'), 'description' => t('Node invite module form.'), 'weight' => 10, ); } return $extra; } function node_invite_user_invites( $account ) { $headers = _node_invite_user_invites_headers(); $q = db_query(" SELECT iid, ni.nid, email_invitee, uid_inviter, ni.status, ni.sent, acted_upon, notes_invitee, notes_inviter, n.title, u.name FROM {node_invites} AS ni JOIN {node} AS n ON ni.nid = n.nid JOIN {users} AS u ON ni.uid_inviter = u.uid WHERE uid_inviter = %d " . tablesort_sql($headers) . " ", $account->uid ); $destination = drupal_get_destination(); $rows = array(); while ( $data = db_fetch_array($q) ) { $row = array(); $row[] = $data['title']; $row[] = check_plain($data['email_invitee']); if ( user_access('manage all invites') ) { $row[] = $data['name']; } $row[] = date('m/d/Y g:i a', $data['sent'] ); $row[] = $data['status']; $row[] = $data['acted_upon'] ? date('m/d/Y g:i a', $row['acted_upon']) : ' '; if ( $row['status'] != 'Yes' && $row['status'] != 'Revoked' && _node_invite_can_manage_this_invite($data['iid']) ) { $row[] = l('Revoke', 'node_invite/revoke/' . $data['iid'], array('query' => $destination)); $row[] = l('Resend', 'node_invite/resend/' . $data['iid'], array('query' => $destination)); } $rows[] = $row; } return theme('table', $headers, $rows); } function _node_invite_user_invites_headers() { $headers = array(); $headers[] = array( 'data' => 'What', 'field' => 'title', ); $headers[] = array( 'data' => 'Sent to', 'field' => 'email_invitee', ); if ( user_access('manage all invites') ) { $headers[] = array( 'data' => 'Sent by', 'field' => 'name', ); } $headers[] = array( 'data' => 'Invite Sent', 'field' => 'sent', ); $headers[] = array( 'data' => 'Status', 'field' => 'status', ); $headers[] = array( 'data' => 'Acted Upon', 'field' => 'acted_upon', ); return $headers; } function _node_invite_can_manage_this_invite( $iid ) { global $user; $sth = db_query( "SELECT uid_inviter FROM {node_invites} WHERE iid = %d", $iid ); if ( $row = db_fetch_array($sth) ) { if ( ( $row['uid_inviter'] == $user->uid ) && user_access('manage own invites')) { return TRUE; } elseif ( user_access('manage all invites') ) { return TRUE; } } return FALSE; } function node_invite_access_revoke() { return TRUE; } function node_invite_access_resend() { return TRUE; } function node_invite_revoke($form_state, $iid) { // ask for confirmation that they really want to revoke the invite. if ( !intval($iid) ) { drupal_set_message("$iid is not a number. This form should only be called with a invite-id as the 3rd argument in the URL.", 'error'); return; } if (_node_invite_can_manage_this_invite($iid)) { $form['iid'] = array( '#type' => 'value', '#value' => $iid, ); $form['referer'] = array( '#type' => 'hidden', '#value' => $_GET['destination'], ); return confirm_form( $form, 'Are you sure you wish to revoke this invite?', $_GET['destination'] ); } else { drupal_set_message('Access denied', 'error'); return; } } function node_invite_revoke_submit( $form, &$form_state ) { db_query("UPDATE {node_invites} SET status = '%s', acted_upon = %d WHERE iid = %d", 'Revoked', time(), $form_state['values']['iid']); drupal_goto($form_state['values']['referer']); } function node_invite_resend($form_state, $iid) { // ask for confirmation that they really want to revoke the invite. if ( !intval($iid) ) { drupal_set_message("$iid is not a number. This form should only be called with a invite-id as the 3rd argument in the URL.", 'error'); return; } if (_node_invite_can_manage_this_invite($iid)) { $form['iid'] = array( '#type' => 'value', '#value' => $iid, ); $form['referer'] = array( '#type' => 'hidden', '#value' => $_GET['destination'], ); return confirm_form($form, 'Are you sure you wish to resend this invite?', $_GET['destination']); } else { drupal_set_message('Access denied', 'error'); return; } } function node_invite_resend_submit($form, &$form_state) { db_query("UPDATE {node_invites} SET status = '%s', acted_upon = NULL WHERE iid = %d", 'NEW', time(), $form_state['values']['iid']); $q = db_query("SELECT ni.*, u.mail FROM {node_invites} AS ni JOIN {users} AS u ON ni.uid_inviter = u.uid WHERE iid = %d", $form_state['values']['iid']); if ($row = db_fetch_array($q)) { $default_message = variable_get('node_invite_message_default', NODE_INVITE_MESSAGE_DEFAULT); $node = node_load($row['nid']); $inviter_rsvp_url = url('node_invite/rsvp/' . $row['nid'] . '/' . $row['iid'], array('absolute' => TRUE)); $new_default_message = str_replace("[inviter-rsvp-url]", $inviter_rsvp_url, $default_message); $replaced_message = token_replace($new_default_message, 'node', $node); $subj = token_replace( variable_get('node_invite_subject_default', NODE_INVITE_SUBJECT_DEFAULT), 'node', $node ); $msg = drupal_mail( // module 'node_invite', // key 'invite', // to $row['email_invitee'], // language language_default(), // params array( 'subject' => $subj, 'body' => $replaced_message, ), // from $row['mail'], // send TRUE ); } else { drupal_set_message('Unable to fetch information about this invite. Resend failed.', 'error'); } drupal_goto($form_state['values']['referer']); } function user_invites_form() { global $user; $uid_inviter = $user->uid; drupal_add_css(drupal_get_path('module', 'node_invite') . '/node_invite.css', 'module', 'all', TRUE); // 1. Who is this? (we're showing their stuff only, right?) // 2. Get their invites (where uid_inviter == $user->uid // 3. Make a table of results // 4. Provide ajax(?) text links to alter status of invites // 5. Provide csv export(?) $form['ni_ui_intro'] = array( '#value' => '

This form allows you to manage those invites you\'ve sent out.

', ); $statement = " SELECT iid ,ni.nid ,email_invitee ,uid_inviter ,ni.status ,ni.sent ,acted_upon ,notes_invitee ,notes_inviter ,n.title ,u.name FROM {node_invites} as ni ,{node} as n ,{users} as u WHERE uid_inviter = $uid_inviter AND n.nid = ni.nid AND u.uid = ni.uid_inviter "; $sort_fields = _ni_sort_order_determine(); $statement .= " ORDER BY " . $sort_fields['field'] . ' ' . $sort_fields['order'] . " , iid DESC "; $sth = db_query($statement); $table_output = " "; // if this is someone who can manage ALL then add a column for who sent it. if (user_access('manage all invites')) { $table_output .= " "; } $table_output .= " "; $counter = 0; while ($row = db_fetch_array($sth)) { $counter++; // format the "actued upon" date field if ($row['acted_upon'] == '' ) { $acted_upon = ''; } else { $acted_upon = date('m/d/Y g:i a', $row['acted_upon']); } // zebra stripes $trclass = 'odd'; if ( $counter % 2 == 0 ) { $trclass = 'even'; } // add a row to the table. $table_output .= " "; // if they can manage all, show who sent it if (user_access('manage all invites')) { $table_output .= " "; } $table_output .= " "; // can they revoke/resend this invite? (depends on perms too...farm that out) if ($row['status'] != 'Yes' && $row['status'] != 'Revoked' && _ni_can_manage_this_invite($row['iid'])) { $table_output .=" "; $table_output .=" "; } else { $table_output .= " "; } $table_output .= " "; } $table_output .= "
What Sent toSent byInvite Sent Status Acted Upon Actions
" . $row['title'] . " " . $row['email_invitee'] . "" . $row['name'] . "" . date('m/d/Y g:i a', $row['sent'] ) . " " . $row['status'] . " $acted_uponRevokeResendRevoke Resend
"; $form['ni_ui_table'] = array( '#value' => $table_output, ); return $form; } function _ni_can_manage_this_invite( $iid ) { global $user; $sth = db_query("SELECT uid_inviter FROM {node_invites} WHERE iid = %d", $iid); if ($row = db_fetch_array($sth)) { if (($row['uid_inviter'] == $user->uid ) && user_access('manage own invites')) { return TRUE; } elseif (user_access('manage all invites')) { return TRUE; } } return FALSE; } function _ni_sort_order_determine() { global $user; // defaults $sort_fields = array( 'field' => 'sent', 'order' => '', 'order_new' => 'DESC', 'existing_url' => '', ); // what fields can we sort by? $acceptable_sort_fields = array('iid', 'email_invitee', 'sent', 'status', 'title', 'name', 'acted_upon'); // path will be of 2 formats: // A. user/$nid/invites/sort_field/sort_order if ( ( arg(0) == 'user') && ( arg(2) == 'invites' ) ) { if ( in_array( arg(3), $acceptable_sort_fields )) { $sort_fields['field'] = arg(3); } if ( arg(4) == 'DESC') { $sort_fields['order'] = 'DESC'; $sort_fields['order_new'] = ''; } $sort_fields['existing_url'] = 'user/' . $user->uid . '/invites'; } // B. admin/settings/node_invite/manage/sort_field/sort_order elseif (arg(0) == 'admin' && arg(1) == 'settings' && arg(2) =='node_invite' && arg(3) == 'manage') { if (in_array(arg(4), $acceptable_sort_fields)) { $sort_fields['field'] = arg(4); } if (arg(5) == 'DESC') { $sort_fields['order'] = 'DESC'; $sort_fields['order_new'] = ''; } else { $sort_fields['order'] = ''; $sort_fields['order_new'] = 'DESC'; } $sort_fields['existing_url'] = 'admin/settings/node_invite/manage'; } else { drupal_set_message("_ni_sort_order_determine called with weird args.", 'error'); } return $sort_fields; } function node_invite_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { // decides whether or not to enable disable invites for this node. if ($op == 'load') { $node->node_invites_enabled = _ni_node_is_enabled($node->nid); } elseif ($op == 'update' || $op == 'insert') { if (!isset($node->node_invites_enabled)) { drupal_set_message("had to get defaults for node->node_invites_enabled"); $node->node_invites_enabled = _ni_node_is_enabled($node->nid); } $sth = db_query("DELETE FROM {node_invite_settings} WHERE nid = %d", $node->nid); $sth = db_query("INSERT INTO {node_invite_settings} (nid, invites_enabled, subject, message) VALUES (%d, %d, '%s', '%s')", $node->nid, $node->node_invites_enabled, $node->node_invite_subject_override, $node->node_invite_message_override); } } function node_invite_form_alter(&$form, &$form_state, $form_id) { $matches = array(); if ( preg_match("/(.+)_node_form$/", $form_id, $matches) && _node_invite_type_is_allowed( $matches[1] ) ) { // put in a form element for node_invite // figure out whether or not to check the box // if this is "edit an existing node" $node = isset( $form['#node'] ) ? $form['#node'] : NULL; $enabled = variable_get('node_invite_default', NODE_INVITE_DEFAULT_FOR_ENABLED_NODES); if (isset($node->node_invites_enabled)) { $enabled = $node->node_invites_enabled; } // grab the default message/subject (if they exist) // only if node isn't new (DUH) $node_invite_subject = $node_invite_message = ''; if (isset($node->nid)) { $statement = "SELECT COUNT(*) as the_count FROM {node_invite_settings} WHERE nid=" . $node->nid; $ni_counter_sth = db_query($statement); $ni_counter_row = db_fetch_array($ni_counter_sth); if ($ni_counter_row['the_count'] > 0) { $ni_sth = db_query("SELECT * FROM {node_invite_settings} WHERE nid = %d", $node->nid); $ni_row = db_fetch_array($ni_sth); $node_invite_subject = $ni_row['subject']; $node_invite_message = $ni_row['message']; } } // add a form element to override $form['node_invite_group'] = array( '#type' => 'fieldset', '#title' => t('Node Invite'), '#weight' => 0, '#collapsed' => TRUE, '#collapsible' => TRUE, '#description' => t('Set invite settings for this specific node here.'), ); $form['node_invite_group']['node_invites_enabled'] = array( '#type' => 'radios', '#title' => t('Enable invites for this node'), '#options' => array( '1' => t('Yes'), '0' => t('No'), ), '#default_value' => $enabled, ); $form['node_invite_group']['node_invite_subject_override'] = array( '#type' => 'textfield', '#title' => t('Override default subject?'), '#description' => t('Leave this textarea BLANK to use the site-default invite subject.'), '#default_value' => $node_invite_subject, ); $form['node_invite_group']['node_invite_message_override'] = array( '#type' => 'textarea', '#title' => t('Override default message?'), '#description' => t('Leave this textarea BLANK to use the site-default invite message.'), '#default_value' => $node_invite_message, ); $form['node_invite_group']['node_invite_token_wrapper'] = array( '#type' => 'fieldset', '#description' => theme_token_help('node'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#title' => t('Available Tokens'), ); } }