Skip to content
privatemsg.module 84.8 KiB
Newer Older
Marco Molinari's avatar
Marco Molinari committed
// $Id$
define('PRIVATEMSG_FOLDER_RECYCLE_BIN', -1);
define('PRIVATEMSG_FOLDER_INBOX', 0);
define('PRIVATEMSG_FOLDER_SENT', 1);
Marco Molinari's avatar
Marco Molinari committed

Zen's avatar
Zen committed
/**
 * Implementation of hook_help().
 */
function privatemsg_help($section) {
  switch ($section) {
    case 'admin/help#privatemsg':
Zen's avatar
Zen committed
      $output = '<p>'. t('The private messaging module allows users to send messages to each other without having to share email addresses. An inbox link will appear in the navigation menu. The "write to author" links are included in posts, allowing users to write a private message instead of commenting openly. Allowing users to communicate directly is an important part of building the strength of the community.') .'</p>';
Zen's avatar
Zen committed
      $output .= '<p>'. t('The contacts list contains only users that you have previously messaged. To contact users not in your list, you need to know their local user name. Administrators can set messaging options such as frequency of emails, message status display, and number of messages to display per page. They can also configure \'Write to Author\' options.') .'</p>';
      $output .= t('<p>You can</p>
<ul>
<li>administer privatemsg at <a href="!admin-settings-privatemsg">administer &gt;&gt; settings &gt;&gt; private message</a>.</li>
<li>view your private messages at <a href="!privatemsg">view inbox</a>.</li>
</ul>', array('!admin-settings-privatemsg' => url('admin/settings/privatemsg'), '!privatemsg' => url('privatemsg')));
      $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="!privatemsg">Privatemsg page</a>.', array('!privatemsg' => 'http://drupal.org/handbook/modules/privatemsg/')) .'</p>';

      return $output;
  }
}

/**
 * Implementation of hook_menu().
 */
function privatemsg_menu($may_cache) {
  global $user;
Zen's avatar
Zen committed

  $items = array();
  $access = user_access('access private messages');
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/settings/privatemsg',
      'title' => t('Privatemsg'),
      'description' => t('Configure Privatemsg settings.'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array('privatemsg_configure'),
      'access' => user_access('administer private messages'),
    );
    $items[] = array(
      'path' => 'privatemsg',
      'title' => t('Private messages'),
      'callback' => 'privatemsg_list',
      'access' => !$user->uid || $access,
      'type' => MENU_SUGGESTED_ITEM,
    );
    $items[] = array(
      'path' => 'privatemsg/list',
      'title' => t('List'),
      'callback' => 'privatemsg_list',
chx's avatar
chx committed
      'callback arguments' => array(NULL),
      'access' => !$user->uid || $access,
      'type' => MENU_DEFAULT_LOCAL_TASK,
      'weight' => -10,
    );
    $items[] = array(
      'path' => 'privatemsg/new',
      'title' => t('Compose'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array('privatemsg_new_form'),
      'access' => $access,
      'type' => MENU_LOCAL_TASK,
      'weight' => -5,
    );
    $items[] = array(
      'path' => 'privatemsg/contacts',
      'title' => t('Contacts'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array('privatemsg_contacts_form'),
      'access' => $access,
      'type' => MENU_LOCAL_TASK,
      'weight' => 0,
    );
    $items[] = array(
      'path' => 'privatemsg/folders',
      'title' => t('Manage folders'),
      'callback' => 'privatemsg_manage_folders',
      'access' => user_access('create new folder') && $user->uid,
      'type' => MENU_LOCAL_TASK,
      'weight' => 5,
    );
    $items[] = array(
      'path' => 'privatemsg/folders/movetonew',
      'title' => t('Move to new folder'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array('privatemsg_new_folder_form'),
chx's avatar
chx committed
      'access' => user_access('create new folder') && $user->uid,
      'type' => MENU_CALLBACK,
    );
    $items[] = array(
      'path' => 'privatemsg/autocomplete',
      'title' => t('Privatemsg autocomplete'),
      'callback' => 'privatemsg_autocomplete',
      'access' => $access,
      'type' => MENU_CALLBACK,
    );
    $items[] = array(
      'path' => 'privatemsg/delete',
      'callback' => 'privatemsg_delete',
      'access' => $access && $user->uid, // No guest access
      'type' => MENU_CALLBACK
    );
  }
  else {
    if (!isset($user->privatemsg_allow)) {
      _privatemsg_user_add_defaults($user);
    }
    if (arg(0) == 'privatemsg' && arg(1) == 'view' && intval(arg(2)) > 0) {
      $items[] = array(
        'path' => 'privatemsg/view/'. arg(2),
        'title' => t('Read message'),
        'callback' => 'privatemsg_view',
        'callback arguments' => array(intval(arg(2)), FALSE),
        'access' => $access && $user->uid, // Check access/redirect in callback
        'type' => MENU_CALLBACK,
        'weight' => -10,
      );
      $items[] = array(
        'path' => 'privatemsg/view/'. arg(2) .'/read',
        'title' => t('Read message'),
        'access' => $access && $user->uid, // Check access/redirect in callback
        'type' => MENU_DEFAULT_LOCAL_TASK,
        'weight' => -10,
      );
      $items[] = array(
        'path' => 'privatemsg/view/'. arg(2) .'/back',
        'title' => t('Back to list'),
        'callback' => 'privatemsg_back_to_list',
        'callback arguments' => array(intval(arg(2))),
        'access' => TRUE, // Check access/redirect in callback
        'type' => MENU_LOCAL_TASK,
        'weight' => 0,
      );
    }

    if (arg(0) == 'privatemsg' && arg(1) == 'reply' && intval(arg(2)) > 0) {
      $items[] = array(
        'path' => 'privatemsg/reply/'. arg(2),
        'title' => t('Write a reply'),
        'callback' => 'drupal_get_form',
        'callback arguments' => array('privatemsg_new_form'),
        'access' => $access,
        'type' => MENU_CALLBACK,
      );
    }

    if (arg(0) == 'privatemsg' && arg(1) == 'new' && intval(arg(2)) > 0) {
      $items[] = array(
        'path' => 'privatemsg/new/'. arg(2),
        'title' => t('Write a new message'),
        'callback' => 'drupal_get_form',
        'callback arguments' => array('privatemsg_new_form'),
        'access' => $access,
        'type' => MENU_CALLBACK,
      );
    }
Zen's avatar
Zen committed
    if ($user-> uid != arg(2) && arg(0) == 'privatemsg' && arg(1) == 'block' && ($account = user_load(array('uid' => arg(2))))) {
chx's avatar
chx committed
      $blocked = privatemsg_user_blocked($account->uid);
      $title_args = array('@user' => $account->name);
      $items[] = array(
        'path' => 'privatemsg/block/'. arg(2),
        'title' => $blocked ? t('Unblock @user', $title_args) : t('Block @user', $title_args),
chx's avatar
chx committed
        'callback' => 'drupal_get_form',
chx's avatar
chx committed
        'callback arguments' => array($blocked ? 'privatemsg_unblock_user_form' : 'privatemsg_block_user_form', $account),
        'type' => MENU_CALLBACK,
      );
    }

    $new = _privatemsg_get_new_messages();
    $items[] = array(
      'path' => 'privatemsg/inbox',
      'title' => variable_get('privatemsg_menu_link', t('My inbox')) . ($new ? ' ('. $new .')' : ''),
      'callback' => 'drupal_goto',
      'callback arguments' => array('privatemsg'),
      'type' => $user->uid && $user->privatemsg_allow ? MENU_DYNAMIC_ITEM : MENU_CALLBACK,
    );

    if ($new && strncmp($_GET['q'], 'privatemsg', 10) && $user->privatemsg_setmessage_notify && user_access('access private messages')) {
      $m = drupal_set_message();
      if (empty($m)) {
        drupal_set_message(strtr(format_plural($new, 'You have a new <a href="!url">private message</a>.', 'You have @count new <a href="!url">private messages</a>.'), array('!url' => url('privatemsg'))));
      }
    }

    if (arg(0) == 'privatemsg' && arg(1) == 'folders' && intval(arg(2)) > 1) {
      $modify_folder = privatemsg_folder_access($user->uid, arg(2));
      if (!$modify_folder) {
        drupal_goto('privatemsg/folders');
      }

      $items[] = array(
        'path' => 'privatemsg/folders/'. arg(2) .'/rename',
        'title' => t('Rename folder'),
        'callback' => 'drupal_get_form',
        'callback arguments' => array('privatemsg_rename_folder_form', arg(2)),
        'access' => $access,
        'type' => MENU_CALLBACK,
      );
      $items[] = array(
        'path' => 'privatemsg/folders/'. arg(2) .'/empty',
        'title' => t('Empty folder?'),
        'callback' => 'drupal_get_form',
        'callback arguments' => array('privatemsg_empty_folder_form', arg(2)),
        'access' => $access,
        'type' => MENU_CALLBACK,
      );
      $items[] = array(
        'path' => 'privatemsg/folders/'. arg(2) .'/delete',
        'title' => t('Delete folder?'),
        'callback' => 'drupal_get_form',
        'callback arguments' => array('privatemsg_delete_folder_form', arg(2)),
        'access' => $access,
        'type' => MENU_CALLBACK,
      );
    }
    if (is_numeric(arg(1)) && (arg(0) == 'privatemsg' || arg(0) == 'user') && ($user->uid == arg(1) || user_access('administer private messages'))) {
      if (arg(0) == 'user' && arg(2) == 'privatemsg') {
        $account = $user->uid == arg(1) ? $user : user_load(array('uid' => arg(1)));
        $items[] = array(
          'path' => 'user/'. arg(1) .'/privatemsg',
          'title' => t('Privatemsg'),
          'callback' => 'privatemsg_list',
          'callback arguments' => array(arg(1)),
          'access' => $account->privatemsg_allow,
          'type' => MENU_LOCAL_TASK,
        );
      }
      if (arg(0) == 'privatemsg') {
        if ($user->uid == arg(1)) {
          $account = $user;
          $title = t('Private messages');
        }
        else {
          $account = user_load(array('uid' => arg(1)));
          $title = t('Private messages for @name', array('@name' => $account->name));
        }

        $items[] = array(
          'path' => 'privatemsg/'. arg(1),
          'title' => $title,
          'callback' => 'privatemsg_list',
          'callback arguments' => array(arg(1)),
          'access' => $account->privatemsg_allow,
          'type' => MENU_CALLBACK,
        );
      }
    }

    drupal_add_css('./'. drupal_get_path('module', 'privatemsg') .'/privatemsg.css');
  return $items;
}

/**
 * Implementation of hook_perm().
 */
function privatemsg_perm() {
Zen's avatar
Zen committed
  return array('access private messages', 'administer private messages', 'create new folder');
}

/**
 * Implementation of hook_cron().
 */
function privatemsg_cron() {
  // Perform these actions just once per day.
  if (variable_get('privatemsg_last_cron', 0) < (time() - 3600*24)) {
    _privatemsg_prune();
    variable_set('privatemsg_last_cron', time());
  }
}

/**
 * Implementation of hook_link().
 */
function privatemsg_link($type, $node = NULL, $teaser = FALSE) {
  global $user;
  static $access = array();
  $links = array();
  $uid = $node->uid;
  if ($type == 'comment' && $node->nid) {
    $node = node_load($node->nid);
  }
  if (user_access('access private messages') && in_array($teaser ? 'teaser' : $type, variable_get('privatemsg_link_'. $node->type, array())) && $uid != $user->uid && $user->privatemsg_allow) {
    if (!isset($access[$uid])) {
      $author = user_load(array('uid' => $uid));
      $access[$uid] = user_access('access private messages', $author) && $author->uid && $author->privatemsg_allow;
      $links['privatemsg_write_to_author'] = array(
        'title' => t('Write to author'),
        'href' => 'privatemsg/new/'. $uid,
/**
 * Implementation of hook_user().
 */
function privatemsg_user($type, &$edit, &$account, $category = NULL) {
Zen's avatar
Zen committed
  global $user;

  switch ($type) {
    case 'load':
      _privatemsg_user_add_defaults($account);
      break;
    case 'view':
      if (user_access('access private messages')) {
chx's avatar
chx committed
        if (privatemsg_message_allowed($account->uid)) {
          $return[t('Private messages')][] = array(
chx's avatar
chx committed
            'value' => l(t('Write private message'), 'privatemsg/new/'. $account->uid, array(
             'title' => t('Send private message to @name', array('@name' => $account->name)))),
            'class' => 'send-message');
        }
Zen's avatar
Zen committed
        if ($account->uid != $user->uid) {
          if (!privatemsg_user_blocked($account->uid) ) {
            $return[t('Private messages')][] = array(
              'value' => l(t('Block messages'), 'privatemsg/block/'. $account->uid, array(
              'title' => t('Block private messages from @name', array('@name' => $account->name)))),
              'class' => 'block-message'
            );
          }
Zen's avatar
Zen committed
          else {
Zen's avatar
Zen committed
            $return[t('Private messages')][] = array(
              'value' => l(t('Unblock messages'), 'privatemsg/block/'. $account->uid, array(
              'title' => t('Unblock private messages from @name', array('@name' => $account->name)))),
              'class' => 'unblock-message');
          }
Zen's avatar
Zen committed

Zen's avatar
Zen committed
      elseif ($user->uid) {
      elseif ($account->privatemsg_allow) {
        if (variable_get('user_register', 1)) {
          return array(t('Private messages') => array(array(
            'value' => t('<a href="!login">login</a> or <a href="!register">register</a> to send private messages to this user', array('!login' => url('user/login'), '!register' => url('user/register'))),
            'class' => 'need-login')));
          return array(t('Private messages') => array(array(
            'value' => t('<a href="!login">login</a> to send private messages to this user', array('!login' => url('user/login'))),
            'class' => 'need-login')));
Neil Drumm's avatar
Neil Drumm committed
      break;

    case 'form':
      if (user_access('access private messages') && $category == 'account') {
Neil Drumm's avatar
Neil Drumm committed
        $form = array();
        $form['privatemsg_settings'] = array(
            '#type' => 'fieldset',
            '#title' => t('Private message settings'),
            '#weight' => 4,
            '#collapsible' => TRUE
            );
        $form['privatemsg_settings']['privatemsg_allow'] = array(
            '#type' => 'checkbox',
            '#title' => t('Allow private messages'),
            '#default_value' => isset($edit['privatemsg_allow']) ? $edit['privatemsg_allow'] : 1,
            '#description' => t('Check this box to allow users to send you private messages.')
            );
        $form['privatemsg_settings']['privatemsg_setmessage_notify'] = array(
            '#type' => 'checkbox',
            '#title' => t('Aggressive notification of new messages'),
            '#default_value' => isset($edit['privatemsg_setmessage_notify']) ? $edit['privatemsg_setmessage_notify'] : 1,
            '#description' => t('Show status message on every page until new messages are read.')
            );
Neil Drumm's avatar
Neil Drumm committed
        return $form;
Neil Drumm's avatar
Neil Drumm committed
      break;

    case 'insert':
      if ($welcome_message = trim(variable_get('privatemsg_welcome_message', ''))) {
        $subject = variable_get('privatemsg_welcome_subject', t('Welcome'));
        $format = variable_get('privatemsg_welcome_format', FILTER_FORMAT_DEFAULT);
        $sender = user_load(array('uid' => variable_get('privatemsg_welcome_sender', 1)));
        if ($sender->uid) {
          _privatemsg_send($sender, $account, $subject, $welcome_message, $format);

    case 'delete':
      db_query('DELETE FROM {privatemsg} WHERE recipient = %d', $account->uid);
      db_query('DELETE FROM {privatemsg_archive} WHERE recipient = %d', $account->uid);
      db_query('DELETE FROM {privatemsg_folder} WHERE uid = %d', $account->uid);
      db_query('UPDATE {privatemsg} SET author = 0 WHERE author = %d', $account->uid);
      db_query('UPDATE {privatemsg_archive} SET author = 0 WHERE author = %d', $account->uid);
      break;
Marco Molinari's avatar
Marco Molinari committed
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
}
/**
 * Implementation of hook_form_alter().
 */
function privatemsg_form_alter($form_id, &$form) {
  switch ($form_id) {
    case 'node_type_form':
      $link = variable_get('privatemsg_link_'. $form['#node_type']->type, array());
      $form['workflow']['privatemsg_link'] = array(
        '#type' => 'checkboxes',
        '#title' => t('Private message "Write to author" links'),
        '#weight' => 30,
        'node' => array(
          '#type' => 'checkbox',
          '#title' => t('Link on node'),
          '#default_value' => in_array('node', $link),
        ),
        'teaser' => array(
          '#type' => 'checkbox',
          '#title' => t('Link on teaser'),
          '#default_value' => in_array('teaser', $link),
        ),
        'comment' => array(
          '#type' => module_exists('comment') ? 'checkbox' : 'hidden',
          '#title' => t('Link on comments'),
          '#default_value' => in_array('comment', $link),
        ),
      );
      break;
/**
 * Implementation of hook_block().
 */
function privatemsg_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    $blocks[0]['info'] = t('Private messages');
    return $blocks;
  }
  else if ($op == 'view') {
    switch ($delta) {
      case 0:
        return _privatemsg_block_inbox();
    }
  }
}

Zen's avatar
Zen committed
/**
Zen's avatar
Zen committed
 * Implementation of hook privatemsg_alter().
Zen's avatar
Zen committed
 */
function privatemsg_privatemsg_alter($sender = NULL, $recipient = NULL, $subject = NULL, $body = NULL, $format = NULL, $thread = NULL, $type = NULL) {
  $key = _privatemsg_get_type_key($type);
  // use isset() and ! here to determine if the user has actually set the preference to FALSE
  // explicitly - allow message otherwise (if the user has specified no preference)
  if (isset($recipient->$key) && !$recipient->$key) {
    return FALSE;
  }
  return TRUE;
}

function privatemsg_message_allowed($recipient, $author = NULL) {
Zen's avatar
Zen committed
  global $user;

  $author = $author ? $author : $user->uid;
  $account = user_load(array('uid' => $recipient));
  if (privatemsg_user_blocked($author, $recipient)) {
Zen's avatar
Zen committed
  if (isset($account->privatemsg_allow) && !$account->privatemsg_allow) {
    return FALSE;
  }
  return TRUE;
}

function privatemsg_user_blocked($author, $recipient = NULL) {
  global $user;
  $recipient = ($recipient) ? $recipient : $user->uid;
chx's avatar
chx committed
  return db_result(db_query("SELECT COUNT(*) FROM {privatemsg_block_user} WHERE author = %d AND recipient = %d", $author, $recipient));
}


function privatemsg_block_user($author, $recipient = NULL) {
  global $user;
  $recipient = ($recipient) ? $recipient : $user->uid;
  if (!privatemsg_user_blocked($author, $recipient)) {
    db_query("INSERT INTO {privatemsg_block_user} (author, recipient) VALUES (%d, %d)", $author, $recipient);
chx's avatar
chx committed
    drupal_set_message(t('User has been blocked'));
  }
}

function privatemsg_unblock_user($author, $recipient = NULL) {
  global $user;
  $recipient = ($recipient) ? $recipient : $user->uid;
  if (privatemsg_user_blocked($author, $recipient)) {
chx's avatar
chx committed
    db_query("DELETE FROM {privatemsg_block_user} WHERE author = %d AND recipient = %d", $author, $recipient);
chx's avatar
chx committed
    drupal_set_message(t('User has been unblocked'));
chx's avatar
chx committed
function privatemsg_block_user_form($account) {
chx's avatar
chx committed
  $form['uid'] = array('#type' => 'value', '#value' => $account->uid);
  return confirm_form($form, t('Are you sure you want to block !user from sending you any more messages?', array('!user' => $account->name)), 'user/'. $account->uid, '');
}

function privatemsg_block_user_form_submit($form_id, $form_values) {
  privatemsg_block_user($form_values['uid']);
  return 'user/'. $form_values['uid'];
}

chx's avatar
chx committed
function privatemsg_unblock_user_form($account) {
chx's avatar
chx committed
  $form['uid'] = array('#type' => 'value', '#value' => $account->uid);
  return confirm_form($form, t('Are you sure you want to allow !user to send you messages?', array('!user' => $account->name)), 'user/'. $account->uid, '');
}

function privatemsg_unblock_user_form_submit($form_id, $form_values) {
  privatemsg_unblock_user($form_values['uid']);
  return 'user/'. $form_values['uid'];
}

function _privatemsg_block_inbox() {
  global $user;
  if ($user->uid && user_access('access private messages') && $user->privatemsg_allow) {
chx's avatar
chx committed
    $block = theme('privatemsg_block_inbox', $new);
Neil Drumm's avatar
Neil Drumm committed
function privatemsg_configure() {
  $form['privatemsg_max_rate'] = array(
    '#type' => 'select',
    '#title' => t('Private messaging max rate'),
    '#default_value' => variable_get('privatemsg_max_rate', 15),
    '#options' => drupal_map_assoc(array(5, 10, 15, 20, 30, 60), 'format_interval'),
    '#description' => t('Max submit rate for private messaging. To prevent abuse.'),
  );
Neil Drumm's avatar
Neil Drumm committed
  $form['privatemsg_sent_status'] = array(
    '#type' => 'select',
    '#title' => t('Sent message status'),
    '#default_value' => variable_get('privatemsg_sent_status', 1),
    '#options' => array(t('Disabled'), t('Enabled')),
    '#description' => t('If enabled users can see whether a message has been read or not.'),
  );
Neil Drumm's avatar
Neil Drumm committed
  $form['privatemsg_per_page'] = array(
    '#type' => 'select',
    '#title' => t('Messages per page'),
    '#default_value' => variable_get('privatemsg_per_page', 10),
    '#options' => drupal_map_assoc(array(5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 80, 100)),
    '#description' => t('The maximum number of messages displayed per page; links to browse messages automatically appear.'),
  );
  $form['privatemsg_menu_link'] = array(
    '#type' => 'textfield',
    '#title' => t('Menu link'),
    '#default_value' => variable_get('privatemsg_menu_link', t('My inbox')),
    '#description' => t("Text shown in link to user's inbox."),
  );
  $options = array(
    '1' => t('Above the message'),
    '2' => t('Below the message'),
    '3' => t('Above and below the message'),
    '4' => t('Neither (show the old links)'),
  );
  $form['privatemsg_view_actions'] = array(
    '#type' => 'radios',
    '#title' => t('Display action form on view screens'),
    '#description' => t('Choose where to display the actions form on the view message screen.'),
    '#options' => $options,
    '#default_value' => variable_get('privatemsg_view_actions', '3'),
  );
  $options = array(
    '1' => t('Before other buttons'),
    '2' => t('After other buttons'),
  );
chx's avatar
chx committed
  $form['privatemsg_actions_loc'] = array(
    '#type' => 'radios',
    '#title' => t('Display delete button'),
chx's avatar
chx committed
    '#description' => t('Choose where to display the actions select on the folder view.'),
    '#options' => $options,
chx's avatar
chx committed
    '#default_value' => variable_get('privatemsg_actions_loc', '1'),
Neil Drumm's avatar
Neil Drumm committed

chx's avatar
chx committed
  $form['privatemsg_threaded_view'] = array(
    '#type' => 'radios',
    '#title' => t('How messages are displayed on the detail screen'),
    '#description' => t('You can choose between displaying a thread of messages (like for example on facebook) or just a single message.'),
    '#options' => array(t('Single message'), t('Full thread')),
    '#default_value' => variable_get('privatemsg_threaded_view', 0),
  );


Neil Drumm's avatar
Neil Drumm committed
  $form['links'] = array(
    '#type' => 'fieldset',
    '#title' => t('"Write to author" links'),
    '#description' => t('Edit <a href="!settings-url">content types</a> to select where these links are displayed.', array('!settings-url' => url('admin/content/types'))),
  );
    '#type' => 'fieldset',
    '#title' => t('Welcome message for new users'),
  );
  $form['welcome']['privatemsg_welcome_subject'] = array(
    '#type' => 'textfield',
    '#title' => t('Subject'),
    '#default_value' => variable_get('privatemsg_welcome_subject', t('Welcome')),
    '#size' => 50,
    '#maxlength' => 64,
  );
  $form['welcome']['privatemsg_welcome_message'] = array(
    '#type' => 'textarea',
    '#title' => t('Message'),
    '#default_value' => variable_get('privatemsg_welcome_message', ''),
    '#cols' => 80,
    '#rows' => 5,
    '#description' => t('Leave blank to disable this feature.'),
  );
chx's avatar
chx committed
  $form['welcome']['filterform'] = filter_form(variable_get('privatemsg_welcome_format', FILTER_FORMAT_DEFAULT));
  $sender = user_load(array('uid' => variable_get('privatemsg_welcome_sender', 1)));
  $form['welcome']['privatemsg_welcome_sender'] = array(
    '#type' => 'textfield',
    '#title' => t('Sender'),
    '#default_value' => $sender->name,
    '#autocomplete_path' => 'privatemsg/autocomplete',
    '#size' => 50,
    '#maxlength' => 64,
    '#required' => TRUE,
  );
  $form['admin_default'] = array(
    '#type' => 'fieldset',
    '#title' => t('Default user settings'),
    '#description' => 'Set the default values for user settings. These can be changed by each user.',
    '#collapsible' => TRUE,
  );

  $form['admin_default']['privatemsg_default_allow'] = array(
    '#type' => 'checkbox',
    '#title' => t("'Allow private messages' default"),
    '#default_value' => variable_get('privatemsg_default_allow', 1),
    '#description' => t("Check this box to set the default value of the 'Allow private messages' user setting."),
  );
  $form['admin_default']['privatemsg_default_setmessage_notify'] = array(
    '#type' => 'checkbox',
    '#title' => t("'Aggressive notification of new messages' default"),
    '#default_value' => variable_get('privatemsg_default_setmessage_notify', 1),
    '#description' => t("Check this box to set the default value of the 'Aggressive notification of new messages' user setting."),
  );
  return system_settings_form($form);
function privatemsg_configure_validate($form_id, $form_values, $form) {
  if (!empty($form_values['privatemsg_welcome_sender'])) {
    $sender = user_load(array('name' => $form_values['privatemsg_welcome_sender']));
    if ($sender->uid) {
      form_set_value($form['welcome']['privatemsg_welcome_sender'], $sender->uid);
    }
    else {
      form_set_error('privatemsg_welcome_sender', t('The <em>Sender</em> does not exist.'));
    }
  }
}

function privatemsg_list($uid = NULL) {
Zen's avatar
Zen committed
  global $user;

  if (!empty($uid) && is_numeric($uid) && user_access('administer private messages')) {
    $account = user_load(array('uid' => $uid));
  }
  else {
Zen's avatar
Zen committed
    $account = $user;
  // Notification emails link here, but the user may not be logged in yet.
  if ($account && !$account->uid) {
    drupal_goto('user/login', 'destination=privatemsg');
  }
Zen's avatar
Zen committed
  // wha? Disallow users who have set their pref to "don't contact me" from
  // seeing their inbox? Surely not: privatemsg_allow only determines whether a
  // user receives direct private messages, there are still other types of
  // messages that arrive in a user's inbox.
chx's avatar
chx committed
  if (!user_access('access private messages')) {// || !$account->privatemsg_allow) {
    return drupal_access_denied();
  }
chx's avatar
chx committed
  $args = array($account->uid);
  if (isset($_SESSION['privatemsg_type'])) {
    $type = " AND type = '%s'";
    $args[] = $_SESSION['privatemsg_type'];
  }
  else {
    $type = '';
  }
chx's avatar
chx committed
  $current_folder = intval(arg(2));
  $folder_name = _privatemsg_folder_map($current_folder, $account->uid);
  if ($current_folder == PRIVATEMSG_FOLDER_SENT) {
    $where_field = 'author';
    $join_field = 'recipient';
  }
  else {
    $where_field = 'recipient';
    $join_field = 'author';
  }
  $sql1 = "SELECT id, subject, p.timestamp, u.uid, u.name, newmsg, type FROM {privatemsg} p INNER JOIN {users} u ON ";
Zen's avatar
Zen committed
  $sql = $sql1 ."p.$join_field = u.uid WHERE p.$where_field = %d $type AND p.{$where_field}_del = %d";
  if ($current_folder == PRIVATEMSG_FOLDER_RECYCLE_BIN) {
    $args[] = 1;
    $sql .= " UNION $sql1 p.recipient = u.uid WHERE p.author = %d $type AND p.author_del = %d";
    $args = array_merge($args, $args);
    $count_query = "SELECT (SELECT COUNT(*) FROM {privatemsg} p INNER JOIN {users} u ON p.author = u.uid WHERE p.recipient = %d AND p.recipient_del = %d) + (SELECT COUNT(*) FROM {privatemsg} p INNER JOIN {users} u ON p.recipient = u.uid WHERE p.author = %d AND p.author_del = %d)";
  }
  else {
    $args[] = 0;
    if ($current_folder != PRIVATEMSG_FOLDER_SENT) {
chx's avatar
chx committed
      $args[] = $current_folder;
      $sql .= " AND folder = %d";
    }
Neil Drumm's avatar
Neil Drumm committed
  }
  $header = _privatemsg_list_header($current_folder);
  $ts = tablesort_init($header);
  $_SESSION['privatemsg_list_sql'] = array(
    'sql' => $sql,
    'args' => $args,
    'field' => db_escape_string($ts['sql']),
    'sort' =>  drupal_strtoupper(db_escape_string($ts['sort'])),
  );
  $result = pager_query($sql . tablesort_sql($header), variable_get('privatemsg_per_page', 10), 0, $count_query, $args);
  $messages = array();
  while ($message = db_fetch_object($result)) {
    if ($current_folder == PRIVATEMSG_FOLDER_SENT) {
      $message->newmsg = 0;
    }
    $messages[] = $message;
Marco Molinari's avatar
Marco Molinari committed
  }
  $folders = privatemsg_load_folders($account->uid);
  $output = drupal_get_form('privatemsg_cur_folder_form', $folders, $current_folder);
  $output .= drupal_get_form('privatemsg_list_form', $messages, $folders, $current_folder, $account);
Marco Molinari's avatar
Marco Molinari committed
}
function _privatemsg_folder_map($fid = NULL, $uid = NULL) {
  $map = array(
    PRIVATEMSG_FOLDER_SENT => t('Sent messages'),
    PRIVATEMSG_FOLDER_INBOX => t('Inbox'),
    PRIVATEMSG_FOLDER_RECYCLE_BIN => t('Recycle bin'),
  );
  if (!isset($fid)) {
    return $map;
  }
  return isset($map[$fid]) ? $map[$fid] : db_result(db_query('SELECT name FROM {privatemsg_folder} WHERE fid = %d AND uid = %d', $current_folder, $uid));
}

function _privatemsg_list_header($current_folder) {
  return array(
    array('data' => t('Type'), 'field' => 'type'),
chx's avatar
chx committed
    array('data' => ($current_folder == 1) ? t('To') : t('From'), 'field' => 'name'),
    array('data' => t('Subject'), 'field' => 'subject'),
    array('data' => t('Date'), 'field' => 'timestamp', 'sort' => 'desc'),
  );
}

function privatemsg_cur_folder_form($folders, $current_folder) {
Zen's avatar
Zen committed
  global $user;

  foreach ($folders as $folder) {
    $options[$folder['fid']] = $folder['name'];
Marco Molinari's avatar
Marco Molinari committed
  }
chx's avatar
chx committed
  $form['header'] = array(
    '#type' => 'fieldset',
    '#prefix' => '<div class="container-inline">',
    '#suffix' => '</div>',
  );
  $form['header']['folder_select'] = array(
    '#type' => 'select',
    '#title' => t('Current folder'),
    '#options' => $options,
    '#default_value' => $current_folder,
    '#attributes' => array('class' => 'pm-add-folder-select'),
  );
chx's avatar
chx committed
  $form['header']['go_folder'] = array(
    '#type' => 'submit',
    '#value' => t('Go'),
    '#attributes' => array('class' => 'js-hide'),
chx's avatar
chx committed
  );
  $actor = $current_folder == 1 ? 'author' : 'recipient';
Zen's avatar
Zen committed
  $result = db_query("SELECT DISTINCT type FROM {privatemsg} WHERE folder = %d AND {$actor}_del = 0 AND {$actor} = %d", $current_folder, $user->uid);
chx's avatar
chx committed
  $types = array(
    '_all' => t('All'),
    '_read' => t('Read'),
    '_unread' => t('Unread'),
    '_none' => t('None'),
    '_invert' => t('Invert'),
    '_privatemsg_delimiter' => '----------------',
    'all types' => t('All types'),
  $filter_types = array('all types' => t('All types'));
chx's avatar
chx committed
  while ($t = db_fetch_object($result)) {
    $type = check_plain($t->type);
    $types[$type] = $type;
chx's avatar
chx committed
    $filter_types[$type] = $type;
chx's avatar
chx committed
  }
  $form['header']['type'] = array(
    '#type' => 'select',
    '#title' => t('Select'),
    '#options' => $types,
chx's avatar
chx committed
    '#attributes' => array('class' => 'pm-filter-select'),
    '#default_value' => '_privatemsg_delimiter',
chx's avatar
chx committed
  );
chx's avatar
chx committed
  $form['header']['filter_type'] = array(
    '#type' => 'select',
    '#title' => t('Filter'),
    '#options' => $filter_types,
    '#default_value' => isset($_SESSION['privatemsg_type']) ? $_SESSION['privatemsg_type'] : 'all types',
  );
chx's avatar
chx committed
  if (isset($_SESSION['privatemsg_type'])) {
    $form['header']['type']['#default_value'] = $_SESSION['privatemsg_type'];
  }
  $form['header']['type_submit'] = array(
    '#type' => 'submit',
    '#value' => t('Filter'),
chx's avatar
chx committed
    '#attributes' => array('class' => 'js-hide'),
chx's avatar
chx committed
  );

  return $form;
function privatemsg_cur_folder_form_submit($form_id, $form_values) {
chx's avatar
chx committed
  switch ($form_values['op']) {
    case t('Go'):
      $redirect = 'privatemsg';
      if ($form_values['folder_select']) {
        $redirect .= '/'. (is_numeric(arg(1)) ? arg(1) : 'list');
        $redirect .= '/'. $form_values['folder_select'];
      }
      unset($_SESSION['privatemsg_type']);
      return $redirect;
    case t('Filter'):
chx's avatar
chx committed
      $type = $form_values['filter_type'];
chx's avatar
chx committed
      // all other '_' will be handled by JS.
      if ($type[0] != '_') {
        if ($type == 'all types') {
          unset($_SESSION['privatemsg_type']);
        }
        else {
chx's avatar
chx committed
          $_SESSION['privatemsg_type'] = $form_values['filter_type'];
chx's avatar
chx committed
        }
      }
      break;
Marco Molinari's avatar
Marco Molinari committed

function privatemsg_list_form($messages, $folders, $current_folder, $account) {
Zen's avatar
Zen committed

  $form['account'] = array('#type' => 'value', '#value' => $account);
  $form['messages'] = array(
    '#theme' => 'privatemsg_message_table',
    '#tree' => TRUE
  );
  $form['messages']['current_folder'] = array(
    '#type' => 'value',
    '#value' => $current_folder
  );
  foreach ($messages as $message) {
    if ($current_folder != 1) {
      $new = $message->newmsg;
      $new_text = theme('mark');
    }
    else {
      $new = variable_get('privatemsg_sent_status', 1) ? $message->newmsg : 0;
      $new_text = ' <span class="marker">'. t('unread') .'</span>';
    }

    $form['messages'][$message->id]['message'] = array(
      '#type' => 'value',
      '#value' => $message,
    );

chx's avatar
chx committed
    $form['messages'][$message->id]['#new'] = $new;

    $form['messages'][$message->id]['selected'] = array(
      '#type' => 'checkbox',
    );
chx's avatar
chx committed
    $form['messages'][$message->id]['type'] = array(
      '#value' => check_plain($message->type),
    );
    $form['messages'][$message->id]['user'] = array(
      '#type' => 'value',
chx's avatar
chx committed
      '#value' => theme('privatemsg_username', $message),
    );
    $form['messages'][$message->id]['subject'] = array(
      '#type' => 'value',
      '#value' => l($message->subject, 'privatemsg/view/'. $message->id, array(), NULL, 'message-'. $message->id) . ($new ? (' '. $new_text) : ''),
    );
    $form['messages'][$message->id]['date'] = array(
      '#type' => 'value',
      '#value' => format_date($message->timestamp, 'small'),
    );
  }
chx's avatar
chx committed
  $form['pager'] = array(
    '#value' => theme('pager', array(), variable_get('privatemsg_per_page', 10)),
  );

  if (count($messages) > 0) {
    $js = array('deleteMessage' => t('Are you sure you want to delete these messages?'));
chx's avatar
chx committed
    $del = variable_get('privatemsg_actions_loc', 1);
    $form['selected'] = array(
      '#type' => 'fieldset',
      '#collapsible' => FALSE,
      '#collapsed' => FALSE,
       '#prefix' => '<div class="container-inline" id="privatemsg-action-buttons">',
      '#suffix' => '</div>',
    );
    switch ($current_folder) {
      case PRIVATEMSG_FOLDER_RECYCLE_BIN:
        $actions['permanent'] = array(
          '#type' => 'submit',
          '#value' => t('Delete permanently'),
        );
        $actions['undelete'] = array(
          '#type' => 'submit',
          '#value' => t('Restore'),
        );
        $actions['empty'] = array(
          '#type' => 'submit',
          '#value' => t('Empty recycle bin'),
        );
        break;
      default:
        $actions['mark_read'] = array(
          '#type' => 'submit',
          '#value' => t('Mark as read'),
        );
        $actions['mark_unread'] = array(
          '#type' => 'submit',
          '#value' => t('Mark as unread'),
        );
        // deliberate no break.
      case PRIVATEMSG_FOLDER_SENT:
        $actions['delete'] = array(
          '#type' => 'submit',
chx's avatar
chx committed
    if ($del == 1) {
      $form['selected']['actions'] = $actions;
    if (user_access('create new folder')) {
      $extra_folders = array();
      foreach ($folders as $folder) {
        // Do not display the recycle bin in the move to folder drop down as the
        // delete button is already available. Similarly, avoid displaying
        // the sent items folder as it is for internal use only.
        if ($folder['fid'] != PRIVATEMSG_FOLDER_SENT && $folder['fid'] != PRIVATEMSG_FOLDER_RECYCLE_BIN && $folder['fid'] != $current_folder) {
          $extra_folders[$folder['fid']] = $folder['name'];
        }
      }
      $extra_folders['new'] = t('New folder...');
  
      // Control to move messages to a new folder. Display only for inbox and
      // custom folders.
      if ((arg(1) == NULL || arg(1) == 'list') && count($extra_folders) > 0 && $current_folder != PRIVATEMSG_FOLDER_RECYCLE_BIN && $current_folder != PRIVATEMSG_FOLDER_SENT) {
        $form['selected']['folder'] = array(
          '#prefix' => '<div class="pm-spacer">',
          '#type' => 'select',
          '#options' => $extra_folders,
        );
        $form['selected']['extra_folders'] = array('#type' => 'value', '#value' => $extra_folders);
        $form['selected']['move_messages'] = array(
          '#type' => 'submit',
          '#value' => t('Move to folder'),
          '#suffix' => '</div>',
        );
      }
chx's avatar
chx committed
    if ($del == 2) {
      $form['selected']['actions'] = $actions;
    }
  }

  $form['js_bypass'] = array(
    '#type' => 'hidden',
    '#value' => 0,
  );

  drupal_add_js(drupal_get_path('module', 'privatemsg') .'/privatemsg.js');
chx's avatar
chx committed
  drupal_add_js(array('privatemsg' => $js), 'setting');