View source
<?php
define('PRIVATEMSG_READ', 0);
define('PRIVATEMSG_UNREAD', 1);
define('PRIVATEMSG_UNLIMITED', 'unlimited');
function privatemsg_perm() {
return array(
'read privatemsg',
'read all private messages',
'allow disabling privatemsg',
'administer privatemsg settings',
'write privatemsg',
'delete privatemsg',
'reply only privatemsg',
'select text format for privatemsg',
'report private messages to mollom',
);
}
function _privatemsg_generate_user_array($string, $slice = NULL) {
$users = explode(',', $string);
if (!is_null($slice)) {
$users = array_slice($users, $slice);
}
$participants = array();
foreach ($users as $uid) {
if ((int) $uid > 0 && ($account = privatemsg_user_load($uid))) {
$participants[privatemsg_recipient_key($account)] = $account;
}
elseif (($pos = strrpos($uid, '_')) !== FALSE) {
$type = substr($uid, 0, $pos);
$id = substr($uid, $pos + 1);
$type_info = privatemsg_recipient_get_type($type);
if ($type_info && isset($type_info['load']) && is_callable($type_info['load'])) {
if ($participant = reset($type_info['load'](array(
$id,
)))) {
$participants[privatemsg_recipient_key($participant)] = $participant;
}
}
}
}
return $participants;
}
function _privatemsg_format_participants($part_array, $limit = NULL, $no_text = FALSE) {
global $user;
if (count($part_array) > 0) {
$to = array();
$limited = FALSE;
foreach ($part_array as $account) {
if (isset($account->type) && in_array($account->type, array(
'hidden',
'user',
)) && $account->recipient == $user->uid) {
array_unshift($to, $no_text ? t('You') : t('you'));
continue;
}
if (isset($account->type) && $account->type == 'hidden') {
continue;
}
if (is_int($limit) && count($to) >= $limit) {
$limited = TRUE;
break;
}
$to[] = privatemsg_recipient_format($account);
}
$limit_string = '';
if ($limited) {
$limit_string = t(' and others');
}
if ($no_text) {
return implode(', ', $to) . $limit_string;
}
$last = array_pop($to);
if (count($to) == 0) {
return t("From !last", array(
'!last' => $last,
));
}
else {
$participants = implode(', ', $to);
return t('Between !participants and !last', array(
'!participants' => $participants,
'!last' => $last,
));
}
}
return '';
}
function privatemsg_menu() {
$url_prefix = variable_get('privatemsg_url_prefix', 'messages');
$url_prefix_arg_count = substr_count($url_prefix, '/') + 1;
$url_prefix_user_arg_position = array_search('%user', explode('/', $url_prefix));
$items[$url_prefix] = array(
'title' => 'Messages',
'title callback' => 'privatemsg_title_callback',
'title arguments' => array(
$url_prefix_user_arg_position,
),
'page callback' => 'privatemsg_list_page',
'page arguments' => array(
'list',
$url_prefix_user_arg_position,
),
'file' => 'privatemsg.pages.inc',
'access callback' => 'privatemsg_menu_access',
'type' => $url_prefix_user_arg_position === FALSE ? MENU_NORMAL_ITEM : MENU_LOCAL_TASK,
);
$items[$url_prefix . '/list'] = array(
'title' => 'Messages',
'page callback' => 'privatemsg_list_page',
'page arguments' => array(
'list',
$url_prefix_user_arg_position,
),
'file' => 'privatemsg.pages.inc',
'access callback' => 'privatemsg_menu_access',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items[$url_prefix . '/view/%privatemsg_thread'] = array(
'title' => 'Read message',
'load arguments' => array(
NULL,
NULL,
TRUE,
),
'page callback' => 'privatemsg_view',
'page arguments' => array(
$url_prefix_arg_count + 1,
),
'file' => 'privatemsg.pages.inc',
'access callback' => 'privatemsg_view_access',
'access arguments' => array(
$url_prefix_arg_count + 1,
),
'type' => MENU_LOCAL_TASK,
'weight' => -5,
);
$items['messages/delete/%privatemsg_thread/%privatemsg_message'] = array(
'title' => 'Delete message',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'privatemsg_delete',
2,
3,
),
'file' => 'privatemsg.pages.inc',
'access callback' => 'privatemsg_menu_access',
'access arguments' => array(
'delete privatemsg',
),
'type' => MENU_CALLBACK,
);
$items[$url_prefix . '/new'] = array(
'title' => 'Write new message',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'privatemsg_new',
$url_prefix_arg_count + 1,
$url_prefix_arg_count + 2,
NULL,
),
'file' => 'privatemsg.pages.inc',
'access callback' => 'privatemsg_menu_access',
'access arguments' => array(
'write privatemsg',
TRUE,
),
'type' => MENU_LOCAL_TASK,
'weight' => -3,
);
$items['messages/autocomplete'] = array(
'page callback' => 'privatemsg_autocomplete',
'file' => 'privatemsg.pages.inc',
'access callback' => 'privatemsg_menu_access',
'access arguments' => array(
'write privatemsg',
),
'type' => MENU_CALLBACK,
'weight' => -10,
);
$items['admin/settings/messages'] = array(
'title' => 'Private messages',
'description' => 'Configure private messaging settings.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'privatemsg_admin_settings',
),
'file' => 'privatemsg.admin.inc',
'access arguments' => array(
'administer privatemsg settings',
),
'type' => MENU_NORMAL_ITEM,
);
$items['admin/settings/messages/default'] = array(
'title' => 'Private messages',
'description' => 'Configure private messaging settings.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'privatemsg_admin_settings',
),
'file' => 'privatemsg.admin.inc',
'access arguments' => array(
'administer privatemsg settings',
),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
if (module_exists('devel_generate')) {
$items['admin/generate/privatemsg'] = array(
'title' => 'Generate private messages',
'description' => 'Generate a given number of private messages. Optionally delete current private messages.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'privatemsg_devel_generate_form',
),
'access arguments' => array(
'administer privatemsg settings',
),
'file' => 'privatemsg.devel_generate.inc',
);
}
$items['messages/undo/action'] = array(
'title' => 'Private messages',
'description' => 'Undo last thread action',
'page callback' => 'privatemsg_undo_action',
'file' => 'privatemsg.pages.inc',
'access callback' => 'privatemsg_menu_access',
'type' => MENU_CALLBACK,
);
if ($url_prefix_user_arg_position === FALSE) {
$items['user/%user/messages'] = array(
'title' => 'Messages',
'page callback' => 'privatemsg_list_page',
'page arguments' => array(
'list',
1,
),
'file' => 'privatemsg.pages.inc',
'access callback' => 'privatemsg_menu_access',
'access arguments' => array(
'read all private messages',
),
'type' => MENU_LOCAL_TASK,
);
}
return $items;
}
function privatemsg_user_access($permission = 'read privatemsg', $account = NULL) {
if ($account === NULL) {
global $user;
$account = $user;
}
if (!$account->uid) {
return FALSE;
}
if (privatemsg_is_disabled($account) && $permission == 'write privatemsg') {
return FALSE;
}
if (!user_access($permission, $account)) {
return FALSE;
}
return TRUE;
}
function privatemsg_menu_access($permission = 'read privatemsg', $deny_if_other = FALSE) {
static $disabled_displayed = FALSE;
global $user;
if (!$user->uid) {
return FALSE;
}
$url_prefix = variable_get('privatemsg_url_prefix', 'messages');
$url_prefix_user_arg_position = array_search('%user', explode('/', $url_prefix));
if ($url_prefix_user_arg_position !== FALSE && (!user_access('read all private messages') || $deny_if_other) && arg($url_prefix_user_arg_position) > 0 && $user->uid != arg($url_prefix_user_arg_position)) {
return FALSE;
}
if (privatemsg_is_disabled($user) && $permission == 'write privatemsg') {
if (strpos($_GET['q'], variable_get('privatemsg_url_prefix', 'messages')) === 0 && variable_get('privatemsg_display_disabled_message', TRUE) && !$disabled_displayed) {
$disabled_displayed = TRUE;
drupal_set_message(t('You have disabled Privatemsg and are not allowed to write messages. Go to your <a href="@settings_url">Account settings</a> to enable it again.', array(
'@settings_url' => url('user/' . $user->uid . '/edit'),
)), 'warning');
}
return FALSE;
}
if (!user_access($permission)) {
return FALSE;
}
return TRUE;
}
function privatemsg_get_dynamic_url_prefix($uid = NULL) {
global $user;
if (!$uid) {
$uid = $user->uid;
$url_prefix = variable_get('privatemsg_url_prefix', 'messages');
$url_prefix_user_arg_position = array_search('%user', explode('/', $url_prefix));
if ($account = menu_get_object('user', $url_prefix_user_arg_position)) {
$uid = $account->uid;
}
}
return str_replace('%user', $uid, variable_get('privatemsg_url_prefix', 'messages'));
}
function privatemsg_view_access($thread) {
if (empty($thread['messages'])) {
return FALSE;
}
$arg = substr_count(variable_get('privatemsg_url_prefix', 'messages'), '/') + 1;
if (privatemsg_user_access('read privatemsg') && arg($arg) == 'view') {
return TRUE;
}
return FALSE;
}
function privatemsg_is_disabled($account) {
if (!$account || !isset($account->uid) || !$account->uid) {
return FALSE;
}
if ((!empty($account->roles) || ($account = user_load($account->uid))) && user_access('allow disabling privatemsg', $account)) {
$ids = privatemsg_get_default_setting_ids($account);
return (bool) privatemsg_get_setting('disabled', $ids);
}
else {
return FALSE;
}
}
function privatemsg_thread_load($thread_id, $account = NULL, $start = NULL, $useAccessDenied = FALSE) {
static $threads = array();
if ((int) $thread_id > 0) {
$thread = array(
'thread_id' => $thread_id,
);
if (is_null($account)) {
global $user;
$account = drupal_clone($user);
}
if (!isset($threads[$account->uid])) {
$threads[$account->uid] = array();
}
if (!array_key_exists($thread_id, $threads[$account->uid])) {
$query = _privatemsg_assemble_query('participants', $thread_id);
$participants = db_query($query['query']);
$thread['participants'] = _privatemsg_load_thread_participants($thread_id, $account, FALSE, 'view');
$thread['read_all'] = FALSE;
if (empty($thread['participants']) && privatemsg_user_access('read all private messages', $account)) {
$thread['read_all'] = TRUE;
$thread['participants'] = _privatemsg_load_thread_participants($thread_id, FALSE, FALSE, 'view');
}
$query = _privatemsg_assemble_query('messages', array(
$thread_id,
), $thread['read_all'] ? NULL : $account);
$thread['message_count'] = $thread['to'] = db_result(db_query($query['count']));
$thread['from'] = 1;
$max_amount = variable_get('privatemsg_view_max_amount', 20);
if (is_null($start)) {
if (isset($_GET['start']) && $_GET['start'] < $thread['message_count']) {
$start = $_GET['start'];
}
elseif (!variable_get('privatemsg_view_use_max_as_default', FALSE) && $max_amount == PRIVATEMSG_UNLIMITED) {
$start = PRIVATEMSG_UNLIMITED;
}
else {
$start = $thread['message_count'] - (variable_get('privatemsg_view_use_max_as_default', FALSE) ? variable_get('privatemsg_view_default_amount', 10) : $max_amount);
}
}
if ($start != PRIVATEMSG_UNLIMITED) {
if ($max_amount == PRIVATEMSG_UNLIMITED) {
$last_page = 0;
$max_amount = $thread['message_count'];
}
else {
$paging_count = variable_get('privatemsg_view_use_max_as_default', FALSE) ? $thread['message_count'] - variable_get('privatemsg_view_default_amount', 10) : $thread['message_count'];
$last_page = $paging_count % $max_amount;
}
if ($start < 0) {
$start = 0;
}
$thread['start'] = $start;
if ($start + $max_amount + 1 < $thread['message_count']) {
$thread['to'] = $start + $max_amount;
$thread['newer_start'] = $start + $max_amount;
}
if ($start - $max_amount >= 0) {
$thread['older_start'] = $start - $max_amount;
}
elseif ($start > 0) {
$thread['older_start'] = 0;
}
if ($start < $last_page && $max_amount != PRIVATEMSG_UNLIMITED && $max_amount < $thread['message_count']) {
unset($thread['older_start']);
$thread['to'] = $thread['newer_start'] = $max_amount = $last_page;
$start = 0;
}
$thread['from'] = $start + 1;
$conversation = db_query_range($query['query'], $start, $max_amount);
}
else {
$conversation = db_query($query['query']);
}
$mids = array();
while ($result = db_fetch_array($conversation)) {
$mids[] = $result['mid'];
}
$thread['messages'] = privatemsg_message_load_multiple($mids, $thread['read_all'] ? NULL : $account);
if (empty($thread['messages'])) {
if ($useAccessDenied) {
$query = _privatemsg_assemble_query('messages', array(
$thread_id,
), NULL);
$exists = db_result(db_query($query['count']));
if (!$exists) {
$thread = FALSE;
}
}
else {
$thread = FALSE;
}
}
else {
$thread['user'] = $account;
$message = current($thread['messages']);
$thread['subject'] = $message['subject'];
}
$threads[$account->uid][$thread_id] = $thread;
}
return $threads[$account->uid][$thread_id];
}
return FALSE;
}
function private_message_view_options() {
$options = module_invoke_all('privatemsg_view_template');
return $options;
}
function privatemsg_privatemsg_view_template() {
return array(
'privatemsg-view' => 'Default view',
);
}
function privatemsg_cron() {
if (variable_get('privatemsg_flush_enabled', FALSE)) {
$query = _privatemsg_assemble_query('deleted', variable_get('privatemsg_flush_days', 30));
$result = db_query($query['query']);
$flushed = 0;
while (($row = db_fetch_array($result)) && $flushed < variable_get('privatemsg_flush_max', 200)) {
$message = privatemsg_message_load($row['mid']);
module_invoke_all('privatemsg_message_flush', $message);
db_query('DELETE FROM {pm_index} WHERE mid = %d', $row['mid']);
db_query('DELETE FROM {pm_message} WHERE mid = %d', $row['mid']);
$flushed++;
}
}
$total_remaining = variable_get('privatemgs_cron_recipient_per_run', 1000);
$current_process = variable_get('privatemsg_cron_recipient_process', array());
$rows = array();
$types = privatemsg_recipient_get_types();
unset($types['user']);
$types = array_keys($types);
if (empty($types)) {
return;
}
$result = db_query("SELECT pmi.recipient, pmi.type, pmi.mid FROM {pm_index} pmi WHERE pmi.type IN (" . db_placeholders($types, 'varchar') . ") AND pmi.is_new = 1", $types);
while ($row = db_fetch_object($result)) {
if (!empty($current_process) && $current_process['mid'] == $row->mid && $current_process['type'] == $row->type && $current_process['recipient'] == $row->recipient) {
array_unshift($rows, $row);
}
else {
$rows[] = $row;
}
}
foreach ($rows as $row) {
$type = privatemsg_recipient_get_type($row->type);
if (isset($type['load']) && is_callable($type['load'])) {
$loaded = $type['load'](array(
$row->recipient,
));
if (empty($loaded)) {
continue;
}
$recipient = reset($loaded);
}
$offset = 0;
if (!empty($current_process) && $current_process['mid'] == $row->mid && $current_process['recipient'] == $row->recipient && $current_process['type'] == $row->type) {
$offset = $current_process['offset'];
}
$load_function = $type['generate recipients'];
$uids = $load_function($recipient, $total_remaining, $offset);
if (!empty($uids)) {
foreach ($uids as $uid) {
privatemsg_message_change_recipient($row->mid, $uid, 'hidden');
}
}
if (count($uids) < $total_remaining) {
$total_remaining -= count($uids);
db_query("UPDATE {pm_index} SET is_new = %d WHERE mid = %d AND recipient = %d AND type = '%s'", PRIVATEMSG_READ, $row->mid, $row->recipient, $row->type);
if ($offset > 0) {
variable_set('privatemsg_cron_recipient_process', array());
}
}
else {
$existing_offset = isset($current_process['offset']) ? $current_process['offset'] : 0;
$current_process = (array) $row;
$current_process['offset'] = $existing_offset + count($uids);
variable_set('privatemsg_cron_recipient_process', $current_process);
break;
}
}
}
function privatemsg_theme() {
return array(
'privatemsg_view' => array(
'arguments' => array(
'message' => NULL,
),
'template' => variable_get('private_message_view_template', 'privatemsg-view'),
),
'privatemsg_from' => array(
'arguments' => array(
'author' => NULL,
),
'template' => 'privatemsg-from',
),
'privatemsg_recipients' => array(
'arguments' => array(
'message' => NULL,
),
'template' => 'privatemsg-recipients',
),
'privatemsg_between' => array(
'arguments' => array(
'recipients' => NULL,
),
'template' => 'privatemsg-between',
),
'privatemsg_list' => array(
'file' => 'privatemsg.theme.inc',
'path' => drupal_get_path('module', 'privatemsg'),
'arguments' => array(
'form',
),
),
'privatemsg_list_field' => array(
'file' => 'privatemsg.theme.inc',
'path' => drupal_get_path('module', 'privatemsg'),
'pattern' => 'privatemsg_list_field__',
'arguments' => array(
'thread',
),
),
'privatemsg_new_block' => array(
'file' => 'privatemsg.theme.inc',
'path' => drupal_get_path('module', 'privatemsg'),
'arguments' => array(
'count',
),
),
'privatemsg_username' => array(
'file' => 'privatemsg.theme.inc',
'path' => drupal_get_path('module', 'privatemsg'),
'arguments' => array(
'recipient' => NULL,
'options' => array(),
),
),
'privatemsg_admin_settings_display_fields' => array(
'file' => 'privatemsg.theme.inc',
'path' => drupal_get_path('module', 'privatemsg'),
'arguments' => array(
'element' => array(),
),
),
);
}
function template_preprocess_privatemsg_view(&$vars) {
global $user;
$message = $vars['message'];
$vars['mid'] = isset($message['mid']) ? $message['mid'] : NULL;
$vars['classes'] = $message['classes'];
$vars['thread_id'] = isset($message['thread_id']) ? $message['thread_id'] : NULL;
$vars['author_picture'] = theme('user_picture', $message['author']);
if ($user->uid == $message['author']->uid) {
$vars['author_name_link'] = t('You');
}
else {
$vars['author_name_link'] = privatemsg_recipient_format($message['author']);
}
$vars['message_timestamp'] = format_date($message['timestamp'], 'small');
$vars['message_body'] = check_markup($message['body'], $message['format'], FALSE);
if (isset($vars['mid']) && isset($vars['thread_id']) && privatemsg_user_access('delete privatemsg')) {
$vars['message_actions'][] = array(
'title' => t('Delete'),
'href' => 'messages/delete/' . $vars['thread_id'] . '/' . $vars['mid'],
);
}
$vars['message_anchors'][] = 'privatemsg-mid-' . $vars['mid'];
if (!empty($message['is_new'])) {
$vars['message_anchors'][] = 'new';
$vars['new'] = drupal_ucfirst(t('new'));
}
drupal_alter('privatemsg_message_view', $vars);
$vars['message_actions'] = !empty($vars['message_actions']) ? theme('links', $vars['message_actions'], array(
'class' => 'privatemsg-message-actions links inline',
)) : '';
$vars['anchors'] = '';
foreach ($vars['message_anchors'] as $anchor) {
$vars['anchors'] .= '<a name="' . $anchor . '"></a>';
}
}
function template_preprocess_privatemsg_recipients(&$vars) {
$vars['participants'] = '';
if (isset($vars['message']['participants'])) {
$vars['participants'] = _privatemsg_format_participants($vars['message']['participants']);
}
}
function privatemsg_message_change_status($pmid, $status, $account = NULL) {
if (!$account) {
global $user;
$account = $user;
}
$query = "UPDATE {pm_index} SET is_new = %d WHERE mid = %d AND recipient = %d AND type IN ('user', 'hidden')";
db_query($query, $status, $pmid, $account->uid);
module_invoke_all('privatemsg_message_status_changed', $pmid, $status, $account);
}
function privatemsg_unread_count($account = NULL, $reset = FALSE) {
static $counts = array();
if ($reset) {
$counts = array();
}
if (!$account || $account->uid == 0) {
global $user;
$account = $user;
}
if (!isset($counts[$account->uid])) {
$query = _privatemsg_assemble_query('unread_count', $account);
$counts[$account->uid] = db_result(db_query($query['query']));
}
return $counts[$account->uid];
}
function _privatemsg_load_thread_participants($thread_id, $account, $ignore_hidden = TRUE, $access = 'write') {
$query = _privatemsg_assemble_query('participants', $thread_id, $account);
$result = db_query($query['query']);
$participants = array();
$to_load = array();
while ($participant = db_fetch_object($result)) {
if ($ignore_hidden && $participant->type == 'hidden') {
continue;
}
if ($participant->type == 'user' || $participant->type == 'hidden') {
if ($participant = privatemsg_user_load($participant->recipient)) {
$participants[privatemsg_recipient_key($participant)] = $participant;
}
}
elseif (privatemsg_recipient_access($participant->type, $access, $participant)) {
$to_load[$participant->type][] = $participant->recipient;
}
}
foreach ($to_load as $type => $ids) {
$type_info = privatemsg_recipient_get_type($type);
if (isset($type_info['load']) && is_callable($type_info['load'])) {
$loaded = $type_info['load']($ids);
if (is_array($loaded)) {
$participants += $loaded;
}
}
}
if ($access == 'write' && $account) {
if (isset($participants['user_' . $account->uid]) && count($participants) > 1) {
unset($participants['user_' . $account->uid]);
}
}
return $participants;
}
function _privatemsg_parse_userstring($input, $types_limitations = array()) {
if (is_string($input)) {
$input = explode(',', $input);
}
$invalid = array();
$recipients = array();
$duplicates = array();
$denieds = array();
foreach ($input as $string) {
$string = trim($string);
if (!empty($string)) {
$matches = array();
$access_denied = FALSE;
$types = privatemsg_recipient_get_types();
foreach (module_implements('privatemsg_name_lookup') as $module) {
$function = $module . '_privatemsg_name_lookup';
$return = $function($string);
if (isset($return) && is_array($return)) {
foreach ($return as $recipient) {
if (empty($recipient->type)) {
$recipient->type = 'user';
$recipient->recipient = $recipient->uid;
}
$matches[privatemsg_recipient_key($recipient)] = $recipient;
}
}
}
foreach ($matches as $key => $recipient) {
if (!privatemsg_recipient_access($recipient->type, 'write', $recipient)) {
unset($matches[$key]);
$access_denied = TRUE;
}
if (!empty($types_limitations) && !in_array($recipient->type, $types_limitations)) {
unset($matches[$key]);
}
}
drupal_alter('privatemsg_name_lookup_matches', $matches, $string);
$number_of_matches = count($matches);
switch ($number_of_matches) {
case 1:
$recipients += $matches;
break;
case 0:
if ($access_denied) {
$denieds[$string] = $string;
}
else {
$invalid[$string] = $string;
}
break;
default:
$duplicates[$string] = $matches;
break;
}
}
}
return array(
$recipients,
$invalid,
$duplicates,
$denieds,
);
}
function privatemsg_privatemsg_name_lookup($string) {
$string = trim(str_replace('[user]', '', $string));
if (!($error = module_invoke('user', 'validate_name', $string))) {
if ($recipient = user_load(array(
'name' => $string,
))) {
$recipient->recipient = $recipient->uid;
$recipient->type = 'user';
return array(
privatemsg_recipient_key($recipient) => $recipient,
);
}
}
}
function privatemsg_sql_list(&$fragments, $account, $argument = 'list') {
$fragments['primary_table'] = '{pm_message} pm';
$fields = privatemsg_get_enabled_headers();
$fragments['select'][] = 'pmi.thread_id';
$fragments['select'][] = 'MIN(pm.subject) as subject';
$fragments['select'][] = 'MAX(pm.timestamp) as last_updated';
$fragments['select'][] = 'SUM(pmi.is_new) as is_new';
if (in_array('count', $fields)) {
$fragments['select'][] = 'COUNT(distinct pmi.mid) as count';
}
if (in_array('participants', $fields)) {
if ($GLOBALS['db_type'] == 'pgsql') {
$fragments['select'][] = "array_to_string(array(SELECT DISTINCT pmia.type || '_' || textin(int4out(pmia.recipient))\n FROM {pm_index} pmia\n WHERE pmia.type <> 'hidden' AND pmia.thread_id = pmi.thread_id AND NOT (pmia.type = 'user' AND pmia.recipient = %d)), ',') AS participants";
}
else {
$fragments['select'][] = "(SELECT GROUP_CONCAT(DISTINCT CONCAT(pmia.type, '_', pmia.recipient) SEPARATOR ',')\n FROM {pm_index} pmia\n WHERE pmia.type <> 'hidden' AND pmia.thread_id = pmi.thread_id AND NOT (pmia.type = 'user' AND pmia.recipient = %d)) AS participants";
}
$fragments['query_args']['select'][] = $account->uid;
}
if (in_array('thread_started', $fields)) {
$fragments['select'][] = 'MIN(pm.timestamp) as thread_started';
}
$fragments['inner_join'][] = 'INNER JOIN {pm_index} pmi ON pm.mid = pmi.mid';
$fragments['where'][] = "pmi.recipient = %d AND pmi.type IN ('user', 'hidden')";
$fragments['query_args']['where'][] = $account->uid;
$fragments['where'][] = 'pmi.deleted = 0';
$fragments['group_by'][] = 'pmi.thread_id';
$order_by = drupal_substr(tablesort_sql(privatemsg_get_headers()), 9);
$fragments['order_by'][] = $order_by;
}
function privatemsg_sql_load(&$fragments, $pmids, $account = NULL) {
$fragments['primary_table'] = '{pm_message} pm';
$fragments['select'][] = "pm.mid";
$fragments['select'][] = "pm.author";
$fragments['select'][] = "pm.subject";
$fragments['select'][] = "pm.body";
$fragments['select'][] = "pm.timestamp";
$fragments['select'][] = "pm.format";
if ($account) {
$fragments['select'][] = "pmi.is_new";
}
$fragments['select'][] = "pmi.thread_id";
$fragments['inner_join'][] = 'INNER JOIN {pm_index} pmi ON pm.mid = pmi.mid';
$fragments['where'][] = 'pmi.mid IN (' . db_placeholders($pmids) . ')';
$fragments['query_args']['where'] += $pmids;
if ($account) {
$fragments['where'][] = "pmi.recipient = %d AND pmi.type IN ('user', 'hidden')";
$fragments['query_args']['where'][] = $account->uid;
}
else {
$fragments['group_by'][] = "pm.mid";
$fragments['group_by'][] = "pm.author";
$fragments['group_by'][] = "pm.subject";
$fragments['group_by'][] = "pm.body";
$fragments['group_by'][] = "pm.timestamp";
$fragments['group_by'][] = "pm.format";
$fragments['group_by'][] = "pmi.thread_id";
}
$fragments['order_by'][] = 'pm.timestamp ASC';
$fragments['order_by'][] = 'pm.mid ASC';
}
function privatemsg_sql_messages(&$fragments, $threads, $account = NULL, $load_all = FALSE) {
$fragments['primary_table'] = '{pm_index} pmi';
$fragments['select'][] = 'pmi.mid';
$fragments['where'][] = 'pmi.thread_id IN (' . db_placeholders($threads) . ')';
$fragments['query_args']['where'] += $threads;
$fragments['inner_join'][] = 'INNER JOIN {pm_message} pm ON (pm.mid = pmi.mid)';
if ($account) {
$fragments['where'][] = "pmi.recipient = %d AND pmi.type IN ('user', 'hidden')";
$fragments['query_args']['where'][] = $account->uid;
}
if (!$load_all) {
$fragments['where'][] = 'pmi.deleted = 0';
}
$fragments['group_by'][] = 'pmi.mid';
$fragments['group_by'][] = 'pm.timestamp';
$fragments['order_by'][] = 'pm.timestamp ASC';
$fragments['order_by'][] = 'pmi.mid ASC';
}
function privatemsg_sql_participants(&$fragments, $thread_id, $account = NULL) {
$fragments['primary_table'] = '{pm_index} pmi';
$fragments['select'][] = 'pmi.recipient';
$fragments['select'][] = 'u.name';
$fragments['select'][] = 'pmi.type';
$fragments['inner_join'][] = "LEFT JOIN {users} u ON (u.uid = pmi.recipient AND pmi.type IN ('user', 'hidden'))";
$fragments['where'][] = 'pmi.thread_id = %d';
$fragments['query_args']['where'][] = $thread_id;
if ($account) {
$fragments['where'][] = "(pmi.type <> 'hidden') OR (pmi.type = 'hidden' AND pmi.recipient = %d)";
$fragments['query_args']['where'][] = $account->uid;
$fragments['where'][] = '(SELECT 1 FROM {pm_index} pmiu WHERE pmi.mid = pmiu.mid AND pmiu.recipient = %d LIMIT 1) = 1';
$fragments['query_args']['where'][] = $account->uid;
}
else {
$fragments['where'][] = "pmi.type <> 'hidden'";
}
$fragments['group_by'][] = 'pmi.recipient';
$fragments['group_by'][] = 'u.name';
$fragments['group_by'][] = 'pmi.type';
}
function privatemsg_sql_unread_count(&$fragments, $account) {
$fragments['primary_table'] = '{pm_index} pmi';
$fragments['select'][] = 'COUNT(DISTINCT thread_id) as unread_count';
$fragments['where'][] = 'pmi.deleted = 0';
$fragments['where'][] = 'pmi.is_new = 1';
$fragments['where'][] = "pmi.recipient = %d AND pmi.type IN ('user', 'hidden')";
$fragments['query_args']['where'][] = $account->uid;
}
function privatemsg_sql_autocomplete(&$fragments, $search, $names) {
$fragments['primary_table'] = '{users} u';
$fragments['select'][] = 'u.uid';
$fragments['where'][] = "NOT EXISTS (SELECT 1 FROM {pm_setting} pms WHERE pms.id = u.uid AND pms.type = 'user' AND pms.setting = 'disabled')";
$fragments['where'][] = "u.name LIKE '%s'";
$fragments['query_args']['where'][] = $search . '%%';
if (!empty($names)) {
$fragments['where'][] = "u.name NOT IN (" . db_placeholders($names, 'text') . ")";
$fragments['query_args']['where'] += $names;
}
$fragments['where'][] = 'u.status <> 0';
$fragments['order_by'][] = 'u.name ASC';
}
function privatemsg_sql_deleted(&$fragments, $days) {
$fragments['primary_table'] = '{pm_message} pm';
$fragments['select'][] = 'pm.mid';
$fragments['select'][] = 'MIN(pmi.deleted) as is_deleted';
$fragments['select'][] = 'MAX(pmi.deleted) as last_deleted';
$fragments['inner_join'][] = 'INNER JOIN {pm_index} pmi ON (pmi.mid = pm.mid)';
$fragments['group_by'][] = 'pm.mid';
$fragments['having'][] = 'MIN(pmi.deleted) > 0';
$fragments['having'][] = 'MAX(pmi.deleted) < %d';
$fragments['query_args']['having'][] = time() - $days * 86400;
}
function privatemsg_sql_privatemsg_query_settings(&$fragments, $setting, $query_ids) {
$fragments['primary_table'] = '{pm_setting} pms';
$fragments['select'][] = 'pms.type';
$fragments['select'][] = 'pms.id';
$fragments['select'][] = 'pms.value';
$fragments['where'][] = "pms.setting = '%s'";
$fragments['query_args']['where'][] = $setting;
$ids_condition = array();
foreach ($query_ids as $type => $type_ids) {
$ids_condition[] = "pms.type = '%s' AND pms.id IN (" . db_placeholders($type_ids) . ")";
$fragments['query_args']['where'][] = $type;
$fragments['query_args']['where'] = array_merge($fragments['query_args']['where'], $type_ids);
}
$fragments['where'][] = '(' . implode(') OR (', $ids_condition) . ')';
}
function privatemsg_user($op, &$edit, &$account, $category = NULL) {
global $user;
switch ($op) {
case 'form':
if ($category == 'account') {
if (!isset($form['privatemsg'])) {
$form['privatemsg'] = array();
}
$form['privatemsg'] += array(
'#type' => 'fieldset',
'#title' => t('Private messages'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
'#weight' => 10,
'#after_build' => array(
'privatemsg_account_fieldset_remove_if_empty',
),
);
if ((user_access('write privatemsg') || user_access('read privatemsg')) && user_access('allow disabling privatemsg')) {
$form['privatemsg']['pm_enable'] = array(
'#type' => 'checkbox',
'#title' => t('Enable private messages'),
'#default_value' => !privatemsg_is_disabled($account),
'#description' => t('Disabling private messages prevents you from sending or receiving messages from other users.'),
'#weight' => -10,
);
}
}
return $form;
case 'submit':
if (isset($edit['pm_enable']) && (user_access('write privatemsg') || user_access('read privatemsg')) && user_access('allow disabling privatemsg')) {
$current = privatemsg_is_disabled($account);
$disabled = !$edit['pm_enable'];
unset($edit['pm_enable']);
if ($current != $disabled) {
privatemsg_set_setting('user', $account->uid, 'disabled', $disabled);
}
}
break;
case 'view':
if (($url = privatemsg_get_link(array(
$account,
))) && variable_get('privatemsg_display_profile_links', 1)) {
$account->content['privatemsg_send_new_message'] = array(
'#type' => 'markup',
'#value' => l(t('Send this user a private message'), $url, array(
'query' => drupal_get_destination(),
'title' => t('Send this user a message'),
'attributes' => array(
'class' => 'privatemsg-send-link privatemsg-send-link-profile',
),
)),
'#weight' => 10,
);
}
break;
case 'login':
if (variable_get('privatemsg_display_loginmessage', TRUE) && privatemsg_user_access()) {
$count = privatemsg_unread_count();
if ($count) {
global $user;
drupal_set_message(format_plural($count, 'You have <a href="@messages">1 unread message</a>.', 'You have <a href="@messages">@count unread messages</a>', array(
'@messages' => url(privatemsg_get_dynamic_url_prefix($user->uid)),
)));
}
}
break;
case 'delete':
$result = db_query("SELECT mid FROM {pm_message} WHERE author = %d", $account->uid);
$mids = array();
while ($row = db_fetch_array($result)) {
$mids[] = $row['mid'];
}
db_query('DELETE FROM {pm_message} WHERE author = %d', $account->uid);
if (!empty($mids)) {
db_query('DELETE FROM {pm_index} WHERE mid IN (' . db_placeholders($mids) . ')', $mids);
}
db_query("DELETE FROM {pm_index} WHERE recipient = %d and type IN ('user', 'hidden')", $account->uid);
privatemsg_del_setting('user', $account->uid, 'disabled');
break;
}
}
function privatemsg_account_fieldset_remove_if_empty($element) {
if (count(element_children($element)) == 0) {
$element['#access'] = FALSE;
}
else {
foreach (element_children($element) as $key) {
if ($element[$key]['#type'] != 'value' && (!isset($element[$key]['#access']) || $element[$key]['#access'])) {
return $element;
}
}
$element['#access'] = FALSE;
}
return $element;
}
function privatemsg_block($op = 'list', $delta = 0, $edit = array()) {
if ('list' == $op) {
$blocks = array();
$blocks['privatemsg-menu'] = array(
'info' => t('Privatemsg links'),
'cache' => BLOCK_NO_CACHE,
);
$blocks['privatemsg-new'] = array(
'info' => t('New message indication'),
'cache' => BLOCK_NO_CACHE,
);
return $blocks;
}
elseif ($op == 'configure' && $delta == 'privatemsg-new') {
$form['notification'] = array(
'#type' => 'checkbox',
'#title' => t('Display block when there are no new messages'),
'#default_value' => variable_get('privatemsg_no_messages_notification', 0),
'#description' => t('Enable this to have this block always displayed, even if there are no new messages'),
);
return $form;
}
elseif ($op == 'save' && $delta == 'privatemsg-new') {
variable_set('privatemsg_no_messages_notification', $edit['notification']);
}
elseif ('view' == $op) {
$block = array();
switch ($delta) {
case 'privatemsg-menu':
$block = _privatemsg_block_menu();
break;
case 'privatemsg-new':
$block = _privatemsg_block_new();
break;
}
return $block;
}
}
function privatemsg_title_callback($account = NULL) {
if ($account) {
$count = privatemsg_unread_count($account);
}
else {
$count = privatemsg_unread_count();
}
if ($count > 0) {
return format_plural($count, 'Messages (1 new)', 'Messages (@count new)');
}
return t('Messages');
}
function _privatemsg_block_new() {
$block = array();
if (!privatemsg_user_access()) {
return $block;
}
$count = privatemsg_unread_count();
if ($count || variable_get('privatemsg_no_messages_notification', 0)) {
$block = array(
'subject' => $count ? format_plural($count, 'New message', 'New messages') : t('No new messages'),
'content' => theme('privatemsg_new_block', $count),
);
return $block;
}
return array();
}
function _privatemsg_block_menu() {
global $user;
$block = array();
$links = array();
if (privatemsg_user_access('write privatemsg')) {
$links[] = l(t('Write new message'), privatemsg_get_dynamic_url_prefix($user->uid) . '/new', array(
'attributes' => array(
'title' => t('Write new message'),
),
));
}
if (privatemsg_user_access('read privatemsg') || privatemsg_user_access('read all private messages')) {
$links[] = l(privatemsg_title_callback(), privatemsg_get_dynamic_url_prefix($user->uid));
}
if (count($links)) {
$block = array(
'subject' => t('Private messages'),
'content' => theme('item_list', $links),
);
}
return $block;
}
function privatemsg_message_change_delete($pmid, $delete, $account = NULL) {
$delete_value = 0;
if ($delete == TRUE) {
$delete_value = time();
}
if ($account) {
db_query("UPDATE {pm_index} SET deleted = %d WHERE mid = %d AND recipient = %d AND type IN ('user', 'hidden')", $delete_value, $pmid, $account->uid);
}
else {
db_query('UPDATE {pm_index} SET deleted = %d WHERE mid = %d', $delete_value, $pmid);
}
module_invoke_all('privatemsg_message_status_delete', $pmid, $delete, $account);
}
function privatemsg_new_thread($recipients, $subject, $body = NULL, $options = array()) {
global $user;
$author = drupal_clone($user);
$message = array();
$message['subject'] = $subject;
$message['body'] = $body;
foreach ($recipients as $recipient) {
if (!isset($recipient->type)) {
$recipient->type = 'user';
$recipient->recipient = $recipient->uid;
}
$message['recipients'][privatemsg_recipient_key($recipient)] = $recipient;
}
if (!empty($options)) {
$message += $options;
}
$message += array(
'author' => $author,
'timestamp' => time(),
'format' => filter_resolve_format(FILTER_FORMAT_DEFAULT),
);
$validated = _privatemsg_validate_message($message);
if ($validated['success']) {
$validated['message'] = _privatemsg_send($message);
if ($validated['message'] !== FALSE) {
_privatemsg_handle_recipients($validated['message']['mid'], $validated['message']['recipients'], FALSE);
}
}
return $validated;
}
function privatemsg_reply($thread_id, $body, $options = array()) {
global $user;
$author = drupal_clone($user);
$message = array();
$message['body'] = $body;
if (!empty($options)) {
$message += $options;
}
$message += array(
'author' => $author,
'timestamp' => time(),
'format' => filter_resolve_format(FILTER_FORMAT_DEFAULT),
);
$first_message = privatemsg_message_load($thread_id, $message['author']);
if (!$first_message) {
return array(
t('Thread %thread_id not found, unable to answer', array(
'%thread_id' => $thread_id,
)),
);
}
$message['thread_id'] = $thread_id;
$message['recipients'] = _privatemsg_load_thread_participants($thread_id, $message['author']);
$message['subject'] = $first_message['subject'];
$validated = _privatemsg_validate_message($message);
if ($validated['success']) {
$validated['message'] = _privatemsg_send($message);
if ($validated['message'] !== FALSE) {
_privatemsg_handle_recipients($validated['message']['mid'], $validated['message']['recipients'], FALSE);
}
}
return $validated;
}
function _privatemsg_validate_message(&$message, $form = FALSE) {
$messages = array(
'error' => array(),
'warning' => array(),
);
if (!(privatemsg_user_access('write privatemsg', $message['author']) || privatemsg_user_access('reply only privatemsg', $message['author']) && isset($message['thread_id']))) {
if ($form) {
form_set_error('author', t('You are not allowed to write messages.'));
return array(
'success' => FALSE,
'messages' => $messages,
);
}
else {
$messages['error'][] = t('@user is not allowed to write messages.', array(
'@user' => privatemsg_recipient_format($message['author'], array(
'plain' => TRUE,
)),
));
return array(
'success' => FALSE,
'messages' => $messages,
);
}
}
$message['subject'] = trim($message['subject']);
if (empty($message['subject'])) {
if ($form) {
form_set_error('subject', t('You must include a subject line or a message.'));
}
else {
$messages['error'][] = t('A subject or message must be included.');
}
}
if (!empty($message['thread_id']) && ($message['body'] === NULL || $message['body'] === '')) {
if ($form) {
form_set_error('body', t('You must include a message in your reply.'));
}
else {
$messages['error'][] = t('A message must be included in your reply.');
}
}
global $user;
$original_user = drupal_clone($user);
session_save_session(FALSE);
$user = $message['author'];
if (!filter_access($message['format'])) {
if ($form) {
form_set_error('format', t('You are not allowed to use the specified format.'));
}
else {
$messages['error'][] = t('@user is not allowed to use the specified input format.', array(
'@user' => privatemsg_recipient_format($message['author'], array(
'plain' => TRUE,
)),
));
}
}
$user = $original_user;
session_save_session(TRUE);
if (empty($message['recipients']) || !is_array($message['recipients'])) {
if ($form) {
form_set_error('recipient', t('You must include at least one valid recipient.'));
}
else {
$messages['error'][] = t('At least one valid recipient must be included with the message.');
}
}
if (!empty($message['recipients']) && is_array($message['recipients'])) {
foreach (module_invoke_all('privatemsg_block_message', $message['author'], $message['recipients'], $message) as $blocked) {
unset($message['recipients'][$blocked['recipient']]);
if ($form) {
drupal_set_message($blocked['message'], 'warning');
}
else {
$messages['warning'][] = $blocked['message'];
}
}
}
if (empty($message['recipients'])) {
if ($form) {
form_set_error('recipient', t('You are not allowed to send this message because all recipients are blocked.'));
}
else {
$messages['error'][] = t('The message cannot be sent because all recipients are blocked.');
}
}
$messages = array_merge_recursive(module_invoke_all('privatemsg_message_validate', $message, $form), $messages);
$success = empty($messages['error']) || $form && count((array) form_get_errors()) > 0;
return array(
'success' => $success,
'messages' => $messages,
);
}
function _privatemsg_send($message) {
drupal_alter('privatemsg_message_presave', $message);
$index_sql = "INSERT INTO {pm_index} (mid, thread_id, recipient, type, is_new, deleted) VALUES (%d, %d, %d, '%s', %d, 0)";
if (isset($message['read_all']) && $message['read_all']) {
$query_messages = _privatemsg_assemble_query('messages', array(
$message['thread_id'],
), NULL);
$conversation = db_query($query_messages['query']);
while ($result = db_fetch_array($conversation)) {
if (!db_query($index_sql, $result['mid'], $message['thread_id'], $message['author']->uid, 'user', 0)) {
return FALSE;
}
}
}
$args = array();
$args[] = $message['subject'];
$args[] = $message['author']->uid;
$args[] = $message['body'];
$args[] = $message['format'];
$args[] = $message['timestamp'];
$message_sql = "INSERT INTO {pm_message} (subject, author, body, format, timestamp) VALUES ('%s', %d, '%s', %d, %d)";
db_query($message_sql, $args);
$mid = db_last_insert_id('pm_message', 'mid');
$message['mid'] = $mid;
if (!isset($message['thread_id'])) {
$message['thread_id'] = $mid;
}
foreach ($message['recipients'] as $recipient) {
if (!db_query($index_sql, $mid, $message['thread_id'], $recipient->recipient, $recipient->type, 1)) {
return FALSE;
}
}
if (!isset($message['recipients']['user_' . $message['author']->uid])) {
if (!db_query($index_sql, $mid, $message['thread_id'], $message['author']->uid, 'user', 0)) {
return FALSE;
}
}
module_invoke_all('privatemsg_message_insert', $message);
return $message;
}
function privatemsg_get_link($recipients, $account = array(), $subject = NULL) {
if ($account == NULL) {
global $user;
$account = $user;
}
if (!is_array($recipients)) {
$recipients = array(
$recipients,
);
}
if (!privatemsg_user_access('write privatemsg', $account) || $account->uid == 0) {
return FALSE;
}
$validated = array();
foreach ($recipients as $recipient) {
if (!privatemsg_user_access('read privatemsg', $recipient)) {
continue;
}
if (variable_get('privatemsg_display_link_self', TRUE) == FALSE && $account->uid == $recipient->uid) {
continue;
}
if (count(module_invoke_all('privatemsg_block_message', $account, array(
privatemsg_recipient_key($recipient) => $recipient,
))) > 0) {
continue;
}
$validated[] = $recipient->uid;
}
if (empty($validated)) {
return FALSE;
}
$url = privatemsg_get_dynamic_url_prefix($account->uid) . '/new/' . implode(',', $validated);
if (!is_null($subject)) {
if (variable_get('clean_url', 0)) {
$url .= '/' . str_replace('%2F', '%252F', rawurlencode($subject));
}
else {
$url .= '/' . str_replace('/', '%2F', $subject);
}
}
return $url;
}
function privatemsg_message_load($pmid, $account = NULL, $reset = FALSE) {
$messages = privatemsg_message_load_multiple(array(
$pmid,
), $account, $reset);
return current($messages);
}
function privatemsg_message_load_multiple($pmids, $account = NULL, $reset = FALSE) {
static $cache = array();
if ($reset) {
$cache = array();
}
if (empty($pmids)) {
return array();
}
if (isset($account->uid)) {
$uid = $account->uid;
}
else {
$uid = $GLOBALS['user']->uid;
}
$messages = array();
foreach ($pmids as $key => $pmid) {
if (isset($cache[$uid][$pmid])) {
$messages[$pmid] = $cache[$uid][$pmid];
unset($pmids[$key]);
}
}
if (!empty($pmids)) {
$query = _privatemsg_assemble_query('load', $pmids, $account);
$result = db_query($query['query']);
while ($message = db_fetch_array($result)) {
if (!($message['author'] = privatemsg_user_load($message['author']))) {
$message['author'] = privatemsg_user_load(0);
}
$returned = module_invoke_all('privatemsg_message_load', $message);
if (!empty($returned)) {
$message = array_merge_recursive($returned, $message);
}
$cache[$uid][$message['mid']] = $message;
$messages[$message['mid']] = $message;
}
}
return $messages;
}
function _privatemsg_assemble_query($query) {
if (is_array($query)) {
$query_id = $query[0];
$query_group = $query[1];
}
else {
$query_id = $query;
$query_group = 'privatemsg';
}
$SELECT = array();
$INNER_JOIN = array();
$WHERE = array();
$GROUP_BY = array();
$HAVING = array();
$ORDER_BY = array();
$QUERY_ARGS = array(
'select' => array(),
'where' => array(),
'join' => array(),
'having' => array(),
);
$primary_table = '';
$fragments = array(
'select' => $SELECT,
'inner_join' => $INNER_JOIN,
'where' => $WHERE,
'group_by' => $GROUP_BY,
'having' => $HAVING,
'order_by' => $ORDER_BY,
'query_args' => $QUERY_ARGS,
'primary_table' => $primary_table,
);
$args = func_get_args();
unset($args[0]);
$alterargs = array(
&$fragments,
);
$query_function = $query_group . '_sql_' . $query_id;
if (!empty($args)) {
$alterargs = array_merge($alterargs, $args);
}
if (!function_exists($query_function)) {
drupal_set_message(t('Query function %function does not exist', array(
'%function' => $query_function,
)), 'error');
return FALSE;
}
call_user_func_array($query_function, $alterargs);
array_unshift($alterargs, $query_function);
call_user_func_array('drupal_alter', $alterargs);
$SELECT = $fragments['select'];
$INNER_JOIN = $fragments['inner_join'];
$WHERE = $fragments['where'];
$GROUP_BY = $fragments['group_by'];
$HAVING = $fragments['having'];
$ORDER_BY = $fragments['order_by'];
$QUERY_ARGS = $fragments['query_args'];
$primary_table = $fragments['primary_table'];
if ($GLOBALS['db_type'] == 'pgsql') {
$WHERE = str_replace('LIKE', 'ILIKE', $WHERE);
}
if (empty($primary_table)) {
$primary_table = '{privatemsg} pm';
}
if (!empty($SELECT)) {
$str_select = implode(", ", $SELECT);
$query = "SELECT {$str_select} FROM " . $primary_table;
if (!empty($GROUP_BY)) {
$str_group_by_count = current($GROUP_BY);
$count = "SELECT COUNT(DISTINCT {$str_group_by_count}) FROM " . $primary_table;
}
else {
$count = "SELECT COUNT(*) FROM " . $primary_table;
}
if (!empty($INNER_JOIN)) {
$str_inner_join = implode(' ', $INNER_JOIN);
$query .= " {$str_inner_join}";
$count .= " {$str_inner_join}";
}
if (!empty($WHERE)) {
$str_where = '(' . implode(') AND (', $WHERE) . ')';
$query .= " WHERE {$str_where}";
$count .= " WHERE {$str_where}";
}
if (!empty($GROUP_BY)) {
$str_group_by = ' GROUP BY ' . implode(", ", $GROUP_BY);
$query .= " {$str_group_by}";
}
if (!empty($HAVING)) {
$str_having = '(' . implode(') AND (', $HAVING) . ')';
$query .= " HAVING {$str_having}";
$count = 'SELECT COUNT(*) FROM (' . $query . ') as count';
}
if (!empty($ORDER_BY)) {
$str_order_by = ' ORDER BY ' . implode(", ", $ORDER_BY);
$query .= " {$str_order_by}";
}
$query_args_query = array_merge($QUERY_ARGS['select'], $QUERY_ARGS['join'], $QUERY_ARGS['where'], $QUERY_ARGS['having']);
$query_args_count = array_merge($QUERY_ARGS['join'], $QUERY_ARGS['where'], $QUERY_ARGS['having']);
if (!empty($query_args_query)) {
_db_query_callback($query_args_query, TRUE);
$query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
}
if (!empty($query_args_count)) {
_db_query_callback($query_args_count, TRUE);
$count = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $count);
}
return array(
'query' => $query,
'count' => $count,
);
}
return FALSE;
}
function privatemsg_thread_change_status($threads, $status, $account = NULL) {
if (!is_array($threads)) {
$threads = array(
$threads,
);
}
if (empty($account)) {
global $user;
$account = drupal_clone($user);
}
$params = array_merge(array(
$status,
$account->uid,
), $threads);
$changed = array();
$result = db_query("SELECT mid FROM {pm_index} WHERE is_new <> %d AND recipient = %d and type IN ('user', 'hidden') AND thread_id IN (" . db_placeholders($threads) . ')', $params);
while ($row = db_fetch_object($result)) {
$changed[] = $row->mid;
}
db_query("UPDATE {pm_index} SET is_new = %d WHERE recipient = %d and type IN ('user', 'hidden') AND thread_id IN (" . db_placeholders($threads) . ')', $params);
foreach ($changed as $mid) {
module_invoke_all('privatemsg_message_status_changed', $mid, $status, $account);
}
if ($status == PRIVATEMSG_UNREAD) {
drupal_set_message(format_plural(count($threads), 'Marked 1 thread as unread.', 'Marked @count threads as unread.'));
}
else {
drupal_set_message(format_plural(count($threads), 'Marked 1 thread as read.', 'Marked @count threads as read.'));
}
}
function privatemsg_operation_execute($operation, $threads, $account = NULL) {
$threads = array_filter($threads);
if (empty($threads)) {
drupal_set_message(t('You must first select one (or more) messages before you can take that action.'), 'warning');
return FALSE;
}
if (isset($operation['callback arguments'])) {
$args = array_merge(array(
$threads,
), $operation['callback arguments']);
}
else {
$args = array(
$threads,
);
}
if ($account) {
$args[] = $account;
}
call_user_func_array($operation['callback'], $args);
if (!empty($operation['success message'])) {
drupal_set_message($operation['success message']);
}
if (isset($operation['undo callback']) && ($undo_function = $operation['undo callback'])) {
if (isset($operation['undo callback arguments'])) {
$undo_args = array_merge(array(
$threads,
), $operation['undo callback arguments']);
}
else {
$undo_args = array(
$threads,
);
}
if ($account) {
$undo_args['account'] = $account->uid;
}
$_SESSION['privatemsg']['undo callback'] = array(
'function' => $undo_function,
'args' => $undo_args,
);
$undo = url('messages/undo/action', array(
'query' => drupal_get_destination(),
));
drupal_set_message(t('The previous action can be <a href="!undo">undone</a>.', array(
'!undo' => $undo,
)));
}
module_invoke_all('privatemsg_operation_executed', $operation, $threads, $account);
return TRUE;
}
function privatemsg_thread_change_delete($threads, $delete, $account = NULL) {
if (!is_array($threads)) {
$threads = array(
$threads,
);
}
if (empty($account)) {
global $user;
$account = drupal_clone($user);
}
$changed = array();
$cond = $delete ? '=' : '>';
$result = db_query("SELECT mid FROM {pm_index} WHERE deleted {$cond} 0 AND recipient = %d and type IN ('user', 'hidden') AND thread_id IN (" . db_placeholders($threads) . ')', array_merge(array(
$account->uid,
), $threads));
while ($row = db_fetch_object($result)) {
$changed[] = $row->mid;
}
$delete_value = 0;
if ($delete == TRUE) {
$delete_value = time();
}
$params = array_merge(array(
$delete_value,
$account->uid,
), $threads);
db_query("UPDATE {pm_index} SET deleted = %d WHERE recipient = %d and type IN ('user', 'hidden') AND thread_id IN (" . db_placeholders($threads) . ')', $params);
foreach ($changed as $mid) {
module_invoke_all('privatemsg_message_status_delete', $mid, $delete, $account);
}
if ($delete) {
drupal_set_message(format_plural(count($threads), 'Deleted 1 thread.', 'Deleted @count threads.'));
}
else {
drupal_set_message(format_plural(count($threads), 'Restored 1 thread.', 'Restored @count threads.'));
}
}
function privatemsg_privatemsg_block_message($author, $recipients, $context = array()) {
$blocked = array();
if (privatemsg_is_disabled($author)) {
$blocked[] = array(
'recipient' => 'user_' . $author->uid,
'message' => t('You have disabled private message sending and receiving.'),
);
}
foreach ($recipients as $recipient) {
if (privatemsg_is_disabled($recipient)) {
$blocked[] = array(
'recipient' => 'user_' . $recipient->uid,
'message' => t('%recipient has disabled private message receiving.', array(
'%recipient' => privatemsg_recipient_format($recipient, array(
'plain' => TRUE,
)),
)),
);
}
}
return $blocked;
}
function privatemsg_privatemsg_thread_operations() {
$operations = array(
'mark as read' => array(
'label' => t('Mark as read'),
'callback' => 'privatemsg_thread_change_status',
'callback arguments' => array(
'status' => PRIVATEMSG_READ,
),
'undo callback' => 'privatemsg_thread_change_status',
'undo callback arguments' => array(
'status' => PRIVATEMSG_UNREAD,
),
),
'mark as unread' => array(
'label' => t('Mark as unread'),
'callback' => 'privatemsg_thread_change_status',
'callback arguments' => array(
'status' => PRIVATEMSG_UNREAD,
),
'undo callback' => 'privatemsg_thread_change_status',
'undo callback arguments' => array(
'status' => PRIVATEMSG_READ,
),
),
);
if (privatemsg_user_access('delete privatemsg')) {
$operations['delete'] = array(
'label' => t('Delete'),
'callback' => 'privatemsg_thread_change_delete',
'callback arguments' => array(
'delete' => 1,
),
'undo callback' => 'privatemsg_thread_change_delete',
'undo callback arguments' => array(
'delete' => 0,
),
'button' => TRUE,
);
}
return $operations;
}
function privatemsg_popups() {
if (variable_get('privatemsg_popups', TRUE)) {
return array(
'*' => array(
'a[href*=messages/new]',
),
);
}
}
function privatemsg_link($type, $object, $teaser = FALSE) {
global $user;
static $nodes = array();
$links = array();
if (!isset($nodes[$object->uid])) {
if ($type == 'node') {
$nodes[$object->nid] = $object;
}
elseif ($type == 'comment') {
$nodes[$object->nid] = node_load($object->nid);
}
}
$types = array_filter(variable_get('privatemsg_link_node_types', array()));
$url = privatemsg_get_link(privatemsg_user_load($object->uid));
if ($type == 'node' && in_array($object->type, $types) && !empty($url) && ($teaser == FALSE || variable_get('privatemsg_display_on_teaser', 1))) {
$links['privatemsg_link'] = array(
'title' => t('Send author a message'),
'href' => $url . '/' . t('Message regarding @node', array(
'@node' => $object->title,
)),
'query' => drupal_get_destination(),
'attributes' => array(
'class' => 'privatemsg-send-link privatemsg-send-link-node',
),
);
}
if ($type == 'comment' && in_array($nodes[$object->nid]->type, $types) && !empty($url) && variable_get('privatemsg_display_on_comments', 0)) {
$links['privatemsg_link'] = array(
'title' => t('Send private message'),
'href' => $url . '/' . t('Message regarding @comment', array(
'@comment' => $object->subject,
)),
'query' => drupal_get_destination(),
'attributes' => array(
'class' => 'privatemsg-send-link privatemsg-send-link-comment',
),
);
}
return $links;
}
function privatemsg_views_api() {
return array(
'api' => 2,
'path' => drupal_get_path('module', 'privatemsg') . '/views',
);
}
function privatemsg_mollom_form_list() {
$forms['privatemsg_new'] = array(
'title' => t('Send new message form'),
'entity' => 'privatemsg_message',
'delete form' => 'privatemsg_delete',
);
return $forms;
}
function privatemsg_mollom_form_info() {
$form_info = array(
'mode' => MOLLOM_MODE_ANALYSIS,
'bypass access' => array(
'administer privatemsg',
),
'report access' => array(
'report private messages to mollom',
),
'elements' => array(
'subject' => t('Subject'),
'body' => t('Body'),
),
'mapping' => array(
'post_id' => 'mid',
'post_title' => 'subject',
),
);
return $form_info;
}
function _privatemsg_list_thread($thread) {
$row = array(
'data' => array(),
);
if (!empty($thread['is_new'])) {
$row['class'] = 'privatemsg-unread';
}
$enabled_headers = privatemsg_get_enabled_headers();
$headers = privatemsg_get_headers();
foreach ($enabled_headers as $key) {
if ($return = theme($headers[$key]['#theme'], $thread)) {
$row['data'][$key] = $return;
}
}
if (empty($row['data'])) {
$row['data'] = _privatemsg_list_thread_fallback($thread);
}
return $row;
}
function _privatemsg_list_thread_fallback($thread) {
$row_data = array();
foreach ($thread as $key => $data) {
$theme_function = 'phptemplate_privatemsg_list_field__' . $key;
if (function_exists($theme_function)) {
$row_data[$key] = $theme_function($thread);
}
}
return $row_data;
}
function privatemsg_user_load($uids) {
static $user_cache = array();
$to_load = $uids;
if (!is_array($to_load)) {
$to_load = array(
$uids,
);
}
foreach ($to_load as $uid) {
if (!array_key_exists($uid, $user_cache)) {
$user_cache[$uid] = user_load($uid);
if (is_object($user_cache[$uid])) {
$user_cache[$uid]->recipient = $user_cache[$uid]->uid;
$user_cache[$uid]->type = 'user';
}
}
}
if (is_array($uids)) {
return array_intersect_key($user_cache, drupal_map_assoc($uids));
}
else {
return $user_cache[$uids];
}
}
function privatemsg_recipient_key($recipient) {
if (empty($recipient->type)) {
return 'user_' . $recipient->uid;
}
return $recipient->type . '_' . $recipient->recipient;
}
function privatemsg_recipient_get_types() {
static $types = NULL;
if ($types === NULL) {
$types = module_invoke_all('privatemsg_recipient_type_info');
if (!is_array($types)) {
$types = array();
}
drupal_alter('privatemsg_recipient_type_info', $types);
uasort($types, 'element_sort');
}
return $types;
}
function privatemsg_recipient_get_type($type) {
$types = privatemsg_recipient_get_types();
if (!is_string($type)) {
exit;
}
if (isset($types[$type])) {
return $types[$type];
}
}
function privatemsg_message_change_recipient($mid, $uid, $type = 'user', $add = TRUE) {
$message = privatemsg_message_load($mid);
$thread_id = $message['thread_id'];
if ($add) {
$recipient = privatemsg_user_load($uid);
$context = $thread_id == $mid ? array() : array(
'thread_id' => $thread_id,
);
$user_blocked = module_invoke_all('privatemsg_block_message', $message['author'], array(
privatemsg_recipient_key($recipient) => $recipient,
), $context);
if (count($user_blocked) != 0) {
return;
}
if ($type == 'user' || $type == 'hidden') {
$exists = db_result(db_query("SELECT 1 FROM {pm_index} WHERE type IN ('user', 'hidden') AND recipient = %d AND mid = %d", $uid, $mid));
}
else {
$exists = db_result(db_query("SELECT 1 FROM {pm_index} WHERE type = '%s' AND recipient = %d AND mid = %d", $type, $uid, $mid));
}
if (!$exists) {
$add_sql = "INSERT INTO {pm_index} (mid, thread_id, recipient, type, is_new, deleted) VALUES (%d, %d, %d, '%s', 1, 0)";
db_query($add_sql, $mid, $thread_id, $uid, $type);
}
}
else {
if ($type == 'hidden' || $type == 'user') {
$delete_sql = "DELETE FROM {pm_index} WHERE mid = %d AND thread_id = %d AND recipient = %d AND type IN ('user', 'hidden')";
}
else {
$delete_sql = "DELETE FROM {pm_index} WHERE mid = %d AND thread_id = %d AND recipient = %d AND type = '%s'";
}
db_query($delete_sql, $mid, $thread_id, $uid, $type);
}
module_invoke_all('privatemsg_message_recipient_changed', $mid, $thread_id, $uid, $type, $add);
}
function _privatemsg_handle_recipients($mid, $recipients, $use_batch = TRUE) {
$batch = array(
'title' => t('Processing recipients'),
'operations' => array(),
'file' => drupal_get_path('module', 'privatemsg') . '/privatemsg.pages.inc',
'progress_message' => t('Processing recipients'),
);
$small_threshold = variable_get('privatemsg_recipient_small_threshold', 100);
foreach ($recipients as $recipient) {
if ($recipient->type != 'user' && $recipient->type != 'hidden') {
$type = privatemsg_recipient_get_type($recipient->type);
$count_function = $type['count'];
if (!is_callable($count_function)) {
db_query("UPDATE {pm_index} SET is_new = %d WHERE mid = %d AND recipient = %d AND type = '%s'", PRIVATEMSG_READ, $mid, $recipient->recipient, $recipient->type);
drupal_set_message(t('Recipient type %type is not correctly implemented', array(
'%type' => $recipient->type,
)), 'error');
continue;
}
$count = $count_function($recipient);
if ($count < $small_threshold) {
$load_function = $type['generate recipients'];
if (!is_callable($load_function)) {
db_query("UPDATE {pm_index} SET is_new = %d WHERE mid = %d AND recipient = %d AND type = '%s'", PRIVATEMSG_READ, $mid, $recipient->recipient, $recipient->type);
drupal_set_message(t('Recipient type %type is not correctly implemented', array(
'%type' => $recipient->type,
)), 'error');
continue;
}
$uids = $load_function($recipient, $small_threshold, 0);
if (!empty($uids)) {
foreach ($uids as $uid) {
privatemsg_message_change_recipient($mid, $uid, 'hidden');
}
}
db_query("UPDATE {pm_index} SET is_new = %d WHERE mid = %d AND recipient = %d AND type = '%s'", PRIVATEMSG_READ, $mid, $recipient->recipient, $recipient->type);
continue;
}
if ($use_batch) {
$batch['operations'][] = array(
'privatemsg_load_recipients',
array(
$mid,
$recipient,
),
);
}
}
}
if ($use_batch && !empty($batch['operations'])) {
batch_set($batch);
}
}
function privatemsg_recipient_access($type_name, $permission, $recipient = NULL) {
if ($type = privatemsg_recipient_get_type($type_name)) {
if (!empty($type[$permission . ' callback']) && is_callable($type[$permission . ' callback'])) {
$callback = $type[$permission . ' callback'];
return $callback($recipient);
}
if (isset($type[$permission . ' access'])) {
if (is_bool($type[$permission . ' access'])) {
return $types[$permission . ' access'];
}
return user_access($type[$permission . ' access']);
}
}
return TRUE;
}
function privatemsg_recipient_format($recipient, $options = array()) {
if (!isset($recipient->type)) {
$recipient->type = 'user';
$recipient->recipient = $recipient->uid;
}
$type = privatemsg_recipient_get_type($recipient->type);
if (isset($type['format'])) {
$result = theme($type['format'], $recipient, $options);
if (empty($result) && isset($recipient->name)) {
$result = $recipient->name;
}
return $result;
}
return NULL;
}
function privatemsg_privatemsg_recipient_type_info() {
return array(
'user' => array(
'name' => t('User'),
'description' => t('Enter a user name to write a message to a user.'),
'load' => 'privatemsg_user_load',
'format' => 'privatemsg_username',
'autocomplete' => 'privatemsg_user_autocomplete',
'#weight' => 50,
),
);
}
function privatemsg_user_autocomplete($fragment, $names, $limit) {
$query = _privatemsg_assemble_query('autocomplete', $fragment, $names);
$result = db_query_range($query['query'], $fragment, 0, $limit);
$suggestions = array();
while ($user = db_fetch_object($result)) {
$account = privatemsg_user_load($user->uid);
$account->type = 'user';
$account->recipient = $account->uid;
$suggestions[privatemsg_recipient_key($account)] = $account;
}
return $suggestions;
}
function privatemsg_get_headers($visible_only = FALSE) {
static $headers = NULL;
if ($headers === NULL) {
$headers = module_invoke_all('privatemsg_header_info');
if (!is_array($headers)) {
$headers = array();
}
$weights = variable_get('privatemsg_display_fields_weights', array());
$enabled = variable_get('privatemsg_display_fields', array(
'subject',
'participants',
'last_updated',
));
foreach ($headers as $key => &$header) {
$header += array(
'#enabled' => FALSE,
'#weight' => 0,
'#title' => $header['data'],
'#access' => TRUE,
'#locked' => FALSE,
'#theme' => 'privatemsg_list_field__' . $key,
);
if (empty($header['#locked']) && isset($enabled[$key])) {
$header['#enabled'] = (bool) $enabled[$key];
}
if (isset($weights[$key])) {
$header['#weight'] = $weights[$key];
}
}
drupal_alter('privatemsg_header_info', $headers);
uasort($headers, 'element_sort');
}
if ($visible_only) {
$headers_visible = $headers;
foreach ($headers_visible as $header_key => &$header) {
if (!$header['#enabled'] || !$header['#access']) {
unset($headers_visible[$header_key]);
}
else {
foreach ($header as $key => $value) {
if ($key[0] == '#') {
unset($header[$key]);
}
}
}
}
return $headers_visible;
}
else {
return $headers;
}
}
function privatemsg_get_enabled_headers() {
static $header_keys = NULL;
if ($header_keys === NULL) {
$header_keys = array();
$headers = privatemsg_get_headers();
foreach ($headers as $key => $header) {
if ($header['#enabled']) {
$header_keys[] = $key;
}
}
}
return $header_keys;
}
function privatemsg_privatemsg_header_info() {
return array(
'subject' => array(
'data' => t('Subject'),
'field' => 'subject',
'class' => 'privatemsg-header-subject',
'#enabled' => TRUE,
'#locked' => TRUE,
'#weight' => -20,
),
'count' => array(
'data' => t('Messages'),
'class' => 'privatemsg-header-count',
'#weight' => -5,
),
'participants' => array(
'data' => t('Participants'),
'class' => 'privatemsg-header-participants',
'#weight' => -15,
'#enabled' => TRUE,
),
'last_updated' => array(
'data' => t('Last Updated'),
'field' => 'last_updated',
'sort' => 'desc',
'class' => 'privatemsg-header-lastupdated',
'#enabled' => TRUE,
'#locked' => TRUE,
'#weight' => 20,
),
'thread_started' => array(
'data' => t('Started'),
'field' => 'thread_started',
'class' => 'privatemsg-header-threadstarted',
'#weight' => -10,
),
);
}
function privatemsg_get_setting($setting, $ids = NULL, $default = NULL) {
$cache =& _privatemsg_setting_static_cache();
if (empty($ids)) {
$ids = privatemsg_get_default_setting_ids();
}
$type_ids = reset($ids);
$type = key($ids);
foreach ($type_ids as $type_id) {
if (isset($cache[$setting][$type][$type_id]) && $cache[$setting][$type][$type_id] !== FALSE && $cache[$setting][$type][$type_id] >= 0) {
return $cache[$setting][$type][$type_id];
}
}
$query_ids = array();
foreach ($ids as $type => $type_ids) {
foreach ($type_ids as $type_id) {
if (!isset($cache[$setting][$type][$type_id])) {
$query_ids[$type][] = $type_id;
$cache[$setting][$type][$type_id] = FALSE;
}
}
}
if (!empty($query_ids)) {
$query = _privatemsg_assemble_query('privatemsg_query_settings', $setting, $query_ids);
$result = db_query($query['query']);
while ($row = db_fetch_object($result)) {
$cache[$setting][$row->type][$row->id] = $row->value;
}
if ($cache[$setting]['global'][0] === FALSE) {
$cache[$setting]['global'][0] = variable_get('privatemsg_setting_' . $setting, FALSE);
}
}
foreach ($ids as $type => $type_ids) {
foreach ($type_ids as $type_id) {
if (isset($cache[$setting][$type][$type_id]) && $cache[$setting][$type][$type_id] !== FALSE && $cache[$setting][$type][$type_id] >= 0) {
return $cache[$setting][$type][$type_id];
}
}
}
return $default;
}
function privatemsg_set_setting($type, $id, $setting, $value) {
db_query("UPDATE {pm_setting} SET value = %d WHERE type = '%s' AND id = %d AND setting = '%s'", $value, $type, $id, $setting);
if (!db_affected_rows()) {
db_query("INSERT INTO {pm_setting} (type, id, setting, value) VALUES ('%s', %d, '%s', %d)", $type, $id, $setting, $value);
}
$cache =& _privatemsg_setting_static_cache();
$cache[$setting][$type][$id] = $value;
}
function privatemsg_del_setting($type, $id, $setting) {
db_query("DELETE FROM {pm_setting} WHERE type = '%s' AND id = %d AND setting = '%s'", $type, $id, $setting);
$cache =& _privatemsg_setting_static_cache();
unset($cache[$setting][$type][$id]);
}
function &_privatemsg_setting_static_cache() {
static $cache = array();
return $cache;
}
function privatemsg_get_default_setting_ids($account = NULL) {
if (!$account) {
global $user;
$account = $user;
}
return array(
'user' => array(
$account->uid,
),
'role' => array_keys($account->roles),
'global' => array(
0,
),
);
}