Newer
Older
<?php
// $Id$
/**
* @file
* Allows users to send private messages to other users.
*/
/**
* Status constant for read messages.
*/
define('PRIVATEMSG_READ', 0);
/**
* Status constant for unread messages.
*/
define('PRIVATEMSG_UNREAD', 1);
function privatemsg_perm() {
return array(
'read privatemsg',
'read all private messages',
/**
* Generate aray of user objects based on a string.
*
*
* @param $userstring
* A string with user id, for example 1,2,4. Returned by the list query
*
* @return
* Array with user objects.
*/
litwol
committed
function _privatemsg_generate_user_array($userstring, $slice = NULL) {
static $user_cache = array();
litwol
committed
// Convert user uid list (uid1,uid2,uid3) into an array. If $slice is not NULL
// pass that as argument to array_slice(). For example, -4 will only load the
// last four users.
$users = explode(',', $userstring);
if (!is_null($slice)) {
$users = array_slice($users, $slice);
}
litwol
committed
foreach ($users as $uid) {
if (!array_key_exists($uid, $user_cache)) {
$user_cache[$uid] = user_load($uid);
litwol
committed
if (is_object($user_cache[$uid])) {
$participants[$uid] = $user_cache[$uid];
}
}
return $participants;
}
/**
* Format an array of user objects.
*
* @param $part_array
* Array with user objects, for example the one returnd by
* _privatemsg_generate_user_array.
*
* @param $limit
* Limit the number of user objects which should be displayed.
* @param $no_text
* When TRUE, don't display the Participants/From text.
* @return
* String with formated user objects, like user1, user2.
*/
function _privatemsg_format_participants($part_array, $limit = 20, $no_text = FALSE) {
if (count($part_array) > 0) {
$limited = FALSE;
foreach ($part_array as $account) {
if (count($to) >= $limit) {
}
$limit_string = '';
if ($limited) {
$limit_string = t(' and others');
}
return implode(', ', $to) . $limit_string;
}
$last = array_pop($to);
if (count($to) == 0) { // Only one participant
return t("From !last", array('!last' => $last));
}
else { // Multipe participants..
$participants = implode(', ', $to);
return t('Participants: !participants and !last', array('!participants' => $participants, '!last' => $last));
}
}
return '';
}
$items['messages'] = array(
'title' => 'Messages',
'title callback' => 'privatemsg_title_callback',
'page callback' => 'drupal_get_form',
litwol
committed
'page arguments' => array('privatemsg_list', 'list'),
'access callback' => 'privatemsg_user_access',
litwol
committed
$items['messages/list'] = array(
'title' => 'Messages',
'page callback' => 'drupal_get_form',
litwol
committed
'page arguments' => array('privatemsg_list', 'list'),
'access callback' => 'privatemsg_user_access',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
$items['messages/view/%privatemsg_thread'] = array(
'title' => 'Read message',
'page callback' => 'privatemsg_view',
'page arguments' => array(2),
'access callback' => 'privatemsg_view_access',
'type' => MENU_LOCAL_TASK,
$items['messages/delete/%'] = array(
'title' => 'Delete message',
'page callback' => 'drupal_get_form',
'page arguments' => array('privatemsg_delete', 2),
'access callback' => 'privatemsg_user_access',
'type' => MENU_CALLBACK,
'weight' => -10,
);
$items['messages/new'] = array(
'title' => 'Write new message',
'page callback' => 'drupal_get_form',
litwol
committed
'page arguments' => array('privatemsg_new', 2, 3, NULL),
'access callback' => 'privatemsg_user_access',
'access arguments' => array('write privatemsg'),
'type' => MENU_LOCAL_TASK,
'weight' => -7,
);
// Auto-completes available user names & removes duplicates.
$items['messages/user-name-autocomplete'] = array(
'page callback' => 'privatemsg_user_name_autocomplete',
'access callback' => 'privatemsg_user_access',
'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('private_message_settings'),
'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('private_message_settings'),
'access arguments' => array('administer privatemsg settings'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['messages/undo/action'] = array(
'title' => 'Private messages',
'description' => 'Undo last thread action',
'page callback' => 'privatemsg_undo_action',
'access arguments' => array('read privatemsg'),
'type' => MENU_CALLBACK,
);
/**
* Privatemsg wrapper for user_access.
*
* Never allows anonymous user access as that doesn't makes sense.
* @param $permission
* Permission string, defaults to read privatemsg
* @return
* TRUE if user has access, FALSE if not
*/
function privatemsg_user_access($permission = 'read privatemsg', $account = NULL) {
if ( $account === NULL ) {
global $user;
$account = $user;
}
if (!$account->uid) { // Disallow anonymous access, regardless of permissions
return FALSE;
}
if (!user_access($permission, $account)) {
return FALSE;
}
return TRUE;
}
/**
* Check access to the view messages page.
*
* Function to restrict the access of the view messages page to just the
* messages/view/% pages and not to leave tabs artifact on other lower
* level pages such as the messages/new/%.
*
* @ingroup api
*/
function privatemsg_view_access() {
if (privatemsg_user_access('read privatemsg') && arg(1) == 'view') {
return TRUE;
}
return FALSE;
}
/**
* Load a thread with all the messages and participants.
*
* This function is called by the menu system through the %privatemsg_thread
* wildcard.
*
* @param $thread_id
* Thread id, pmi.thread_id or pm.mid of the first message in that thread.
* @param $account
* User object for which the thread should be loaded, defaults to
* the current user.
* @return
* $thread object, with keys messages, participants, title and user. messages
* contains an array of messages, participants an array of user, subject the
* subject of the thread and user the user viewing the thread.
*
* If no messages are found, or the thread_id is invalid, the function returns
* FALSE.
*/
function privatemsg_thread_load($thread_id, $account = NULL) {
if ((int)$thread_id > 0) {
litwol
committed
$thread = array('thread_id' => $thread_id);
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
if (is_null($account)) {
global $user;
$account = drupal_clone($user);
}
// load messages returned by the messages query with _privatemsg_load().
$query = _privatemsg_assemble_query('messages', array($thread_id), $account);
$conversation = db_query($query['query']);
while ($result = db_fetch_array($conversation)) {
if ($message = _privatemsg_load($result['mid'], $account)) {
$thread['messages'][$result['mid']] = $message;
}
}
// if there are no messages, don't allow access to the thread.
if (empty($thread['messages'])) {
return FALSE;
}
// general data, assume subject is the same for all messages of that thread.
$thread['user'] = $account;
$message = current($thread['messages']);
$thread['subject'] = $message['subject'];
// Load the list of participants.
$query = _privatemsg_assemble_query('participants', $thread_id);
$participants = db_query($query['query']);
while ($result = db_fetch_array($participants)) {
$thread['participants'][$result['uid']] = user_load($result['uid']);
}
return $thread;
}
return FALSE;
}
function private_message_view_options() {
$options = module_invoke_all('privatemsg_view_template');
return $options;
* Implementation of hook_privatemsg_view_template().
*
* Allows modules to define different message view template.
*
* This hook returns information about available themes for privatemsg viewing.
*
* array(
* 'machine_template_name' => 'Human readable template name',
* 'machine_template_name_2' => 'Human readable template name 2'
* };
*/
function privatemsg_privatemsg_view_template() {
return array(
function private_message_settings() {
$form = array();
'#type' => 'fieldset',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#title' => t('Theming settings'),
);
$form['theming_settings']['private_message_view_template'] = array(
'#type' => 'radios',
'#title' => t('Private message display template'),
'#default_value' => variable_get('private_message_view_template', 'privatemsg-view'),
'#options' => private_message_view_options(),
);
$form['privatemsg_per_page'] = array(
'#type' => 'select',
'#title' => t('Messages per page'),
'#default_value' => variable_get('privatemsg_per_page', 25),
'#options' => drupal_map_assoc(array(10, 25, 50, 75, 100)),
'#description' => t('Choose the number of conversations that should be listed per page.'),
$form['privatemsg_display_loginmessage'] = array(
'#type' => 'checkbox',
'#title' => t('Inform the user about new messages on login'),
'#default_value' => variable_get('privatemsg_display_loginmessage', TRUE),
'#description' => t('This option can safely be disabled if the "New message indication" block is used instead.'),
);
$form['privatemsg_listing'] = array(
'#type' => 'fieldset',
'#title' => t('Configure listings'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['privatemsg_listing']['privatemsg_display_fields'] = array(
'#type' => 'checkboxes',
'#title' => t('Configure fields'),
'#description' => t('Select which columns/fields should be displayed in the message listings. Subject and Last updated cannot be disabled.'),
'#options' => array(
litwol
committed
'participants' => t('Participants'),
'thread_started' => t('Started'),
'count' => t('Answers'),
),
litwol
committed
'#default_value' => variable_get('privatemsg_display_fields', array('participants')),
$form['#submit'][] = 'private_message_settings_submit';
return system_settings_form($form);
}
function private_message_settings_submit() {
drupal_rebuild_theme_registry();
}
function privatemsg_theme() {
return array(
'privatemsg_view' => array(
'template' => variable_get('private_message_view_template', 'privatemsg-view'), // 'privatemsg',
'arguments' => array('author' => NULL),
'template' => 'privatemsg-from',
'privatemsg_to' => 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'),
),
// Define pattern for header/field templates. The theme system will register all
// theme functions that start with the defined pattern.
'privatemsg_list_header' => array(
'file' => 'privatemsg.theme.inc',
'path' => drupal_get_path('module', 'privatemsg'),
'pattern' => 'privatemsg_list_header__',
'arguments' => array(),
),
'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'),
),
function privatemsg_preprocess_privatemsg_view(&$vars) {
// drupal_set_message('<pre>'. print_r($vars,1 ) . '</pre>');
$vars['mid'] = isset($message['mid']) ? $message['mid']:null;
$vars['author_picture'] = theme('user_picture', $message['author']);
$vars['author_name_link'] = theme('username', $message['author']);
/**
* @todo perhaps make this timestamp configurable via admin UI?
*/
$vars['message_timestamp'] = format_date($message['timestamp'], 'small');
$vars['message_body'] = check_markup($message['body']);
litwol
committed
if (isset($vars['mid'])) {
litwol
committed
$vars['message_actions'][] = array('title' => t('Delete message'), 'href' => 'messages/delete/'. $vars['mid']);
litwol
committed
// call hook_privatemsg_message_view_alter
drupal_alter('privatemsg_message_view', $vars);
litwol
committed
$vars['message_actions'] = !empty($vars['message_actions']) ? theme('links', $vars['message_actions'], array('class' => 'message-actions')) : '';
Marco Molinari
committed
}
function privatemsg_preprocess_privatemsg_to(&$vars) {
$vars['participants'] = ''; // assign a default empty value
if (isset($vars['message']['participants'])) {
$vars['participants'] = _privatemsg_format_participants($vars['message']['participants']);
Marco Molinari
committed
}
}
litwol
committed
* @param $form_state
* Form state array
* @param $argument
* An argument to pass through to the query builder.
litwol
committed
* User id messages of another user should be displayed
*
litwol
committed
* Form array
litwol
committed
function privatemsg_list(&$form_state, $argument = 'list', $uid = NULL) {
// Because uid is submitted by the menu system, it's a string not a integer.
if ((int)$uid > 0 && $uid != $user->uid) {
if (!privatemsg_user_access('read all private messages')) {
drupal_set_message(t("You do not have sufficient rights to view someone else's messages"), 'warning');
elseif ($account_check = user_load(array('uid' => $uid))) {
// Has rights and user_load return an array so user does exist
$account = $account_check;
}
// By this point we have figured out for which user we are listing messages and now it is safe to use $account->uid in the listing query.
litwol
committed
$query = _privatemsg_assemble_query('list', $account, $argument);
$result = pager_query($query['query'], variable_get('privatemsg_per_page', 25), 0, $query['count']);
$threads = array();
$form['#data'] = array();
while ($row = db_fetch_array($result)) {
// Store the raw row data.
$form['#data'][$row['thread_id']] = $row;
// Store the themed row data.
$form['#rows'][$row['thread_id']] = _privatemsg_list_thread($row);
// store thread id for the checkboxes array
$threads[$row['thread_id']] = '';
if (empty($form['#data'])) {
// If no threads are displayed, use these default columns.
$keys = array('subject', 'author', 'last_updated');
// Load the keys of the first row in data, we don't know the key
$keys = array_keys($form['#data'][key($form['#data'])]);
$form['actions'] = _privatemsg_action_form();
// Load the themed list headers based on the available data
$form['#headers'] = _privatemsg_list_headers(!empty($form['#data']), $keys);
// Define checkboxes, pager and theme
$form['threads'] = array('#type' => 'checkboxes', '#options' => $threads);
$form['pager'] = array('#value' => theme('pager'), '#weight' => 20);
$form['#theme'] = 'privatemsg_list';
// Store the account for which the threads are displayed.
$form['#account'] = $account;
return $form;
}
* Changes the read/new status of a single message.
* @param $pmid
* Message id
* @param $status
* Either PRIVATEMSG_READ or PRIVATEMSG_UNREAD
* @param $account
* User object, defaults to the current user
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 uid = %d";
db_query($query, $status, $pmid, $account->uid);
}
/**
* Return number of unread messages for an account.
*
* @param $account
* Specifiy the user for which the unread count should be loaded.
*
* @ingroup api
*/
function privatemsg_unread_count($account = NULL) {
static $counts = array();
if (!$account || $account->uid == 0) {
global $user;
$query = _privatemsg_assemble_query('unread_count', $account);
$counts[$account->uid] = db_result(db_query($query['query']));
}
return $counts[$account->uid];
}
/**
* Menu callback for viewing a thread.
*
* @param $thread
* A array containing all information about a specific thread, generated by
* privatemsg_thread_load().
* @return
* The page content.
* @see privatemsg_thread_load().
*/
function privatemsg_view($thread) {
drupal_set_title(check_plain($thread['subject']));
// Render the participants.
$content['participants']['#value'] = theme('privatemsg_to', $thread);
// Render the messages.
$output = '';
foreach ($thread['messages'] as $pmid => $message) {
// Set message as read and theme it.
litwol
committed
if (!empty($message['is_new'])) {
privatemsg_message_change_status($pmid, PRIVATEMSG_READ, $thread['user']);
}
$content['messages']['#value'] = $output;
// Display the reply form if user is allowed to use it.
if (privatemsg_user_access('write privatemsg')) {
litwol
committed
$content['reply']['#value'] = drupal_get_form('privatemsg_new', $thread['participants'], $thread['subject'], $thread['thread_id']);
//allow other modules to hook into the $content array and alter it
drupal_alter('privatemsg_view_messages', $content, $thread);
return drupal_render($content);
Marco Molinari
committed
}
litwol
committed
function privatemsg_new(&$form_state, $recipients = array(), $subject = '', $thread_id = NULL) {
Marco Molinari
committed
global $user;
litwol
committed
$recipients_string = '';
litwol
committed
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
// convert recipients to array of user objects
if (!empty($recipients) && is_string($recipients) || is_int($recipients)) {
$recipients = _privatemsg_generate_user_array($recipients);
}
elseif (is_object($recipients)) {
$recipients = array($recipients);
}
elseif (empty($recipients) && is_string($recipients)) {
$recipients = array();
}
$usercount = 0;
$to = array();
foreach ($recipients as $recipient) {
if (in_array($recipient->name, $to)) {
// We already added the recipient to the list, skip him.
continue;
}
// Check if another module is blocking the sending of messages to the recipient by current user.
$user_blocked = module_invoke_all('privatemsg_block_message', $user, array($recipient));
if (!count($user_blocked) <> 0 && $recipient->uid) {
if ($recipient->uid == $user->uid) {
$usercount++;
// Skip putting author in the recipients list for now.
continue;
}
$to[] = $recipient->name;
}
}
if (empty($to) && $usercount >= 1) {
// Assume the user sent message to own account as if the usercount is one or less, then the user sent a message but not to self.
$to[] = $user->name;
}
if (!empty($to)) {
$recipients_string = implode(', ', $to);
litwol
committed
$recipients_string = $form_state['values']['recipient'];
$subject = $form_state['values']['subject'];
$body = $form_state['values']['body'];
litwol
committed
if (!$thread_id && !empty($recipients_string)) {
drupal_set_title(t('Write new message to %recipient', array('%recipient' => $recipients_string)));
} elseif (!$thread_id) {
drupal_set_title(t('Write new message'));
}
Marco Molinari
committed
$form = array();
if (isset($form_state['privatemsg_preview'])) {
$form['message_header'] = array(
'#type' => 'fieldset',
);
$form['message_header']['message_preview'] = array(
'#value' => $form_state['privatemsg_preview'],
);
}
$form['privatemsg'] = array(
'#type' => 'fieldset',
'#access' => privatemsg_user_access('write privatemsg'),
);
$form['privatemsg']['author'] = array(
'#type' => 'value',
'#value' => $user,
'#type' => 'textfield',
'#title' => t('To'),
'#description' => t('Separate multiple names with commas.'),
litwol
committed
'#default_value' => $recipients_string,
litwol
committed
'#weight' => -10,
'#autocomplete_path' => 'messages/user-name-autocomplete',
// Do not hardcode #maxlength, make it configurable by number of recipients, not their name length.
'#type' => 'textfield',
'#title' => t('Subject'),
'#size' => 50,
'#maxlength' => 255,
'#default_value' => $subject,
litwol
committed
'#weight' => -5,
'#type' => 'textarea',
'#title' => t('Message'),
'#cols' => 10,
'#rows' => 6,
litwol
committed
'#weight' => 0,
litwol
committed
'#weight' => 10,
litwol
committed
'#weight' => 15,
$url = 'messages';
if (isset($_REQUEST['destination'])) {
$url = $_REQUEST['destination'];
}
litwol
committed
elseif (!is_null($thread_id)) {
$url = $_GET['q'];
}
'#value' => l(t('Cancel'), $url, array('attributes' => array('id' => 'edit-cancel'))),
litwol
committed
'#weight' => 20,
litwol
committed
if (!is_null($thread_id)) {
$form['privatemsg']['thread_id'] = array(
'#type' => 'value',
'#value' => $thread_id,
);
$form['privatemsg']['subject'] = array(
'#type' => 'value',
'#default_value' => $subject,
);
$form['privatemsg']['recipient_display'] = array(
'#value' => '<p>'. t('<strong>Reply to thread</strong>:<br /> Recipients: %to', array('%to' => $recipients_string)) .'</p>',
litwol
committed
'#weight' => -10,
);
$form['privatemsg']['recipient'] = array(
'#type' => 'value',
'#default_value' => $recipients_string,
);
if (empty($recipients_string)) {
// If there are no valid recipients, unset the message reply form.
$form['privatemsg']['#access'] = FALSE;
}
}
}
// The actual message that is being sent, we create this during validation and pass to submit to send out.
$message = array();
litwol
committed
$message['body'] = $form_state['values']['body'];
$message['subject'] = $form_state['values']['subject'];
$message['author'] = $form_state['values']['author'];
if (isset($form_state['values']['thread_id']) && $form_state['values']['thread_id']) {
$message['thread_id'] = $form_state['values']['thread_id'];
}
$trimed_body = trim(truncate_utf8(strip_tags($message['body']), 50, TRUE, TRUE));
if (empty($message['subject']) && !empty($trimed_body)) {
$message['subject'] = $trimed_body;
}
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
list($message['recipients'], $invalid) = _privatemsg_parse_userstring($form_state['values']['recipient']);
$validated = _privatemsg_validate_message($message, TRUE);
foreach ($validated['messages'] as $type => $text) {
drupal_set_message($text, $type);
}
$form_state['validate_built_message'] = $message;
if (!empty($invalid)) {
drupal_set_message(t('The following users will not receive this private message: !invalid', array('!invalid' => implode(", ", $invalid))), 'error');
}
}
/**
* Extract the valid usernames of a string and loads them.
*
* This function is used to parse a string supplied by a username autocomplete
* field and load all user objects.
*
* @param $string
* A string in the form "usernameA, usernameB, ...".
* @return
* Array, first element is an array of loaded user objects, second an array
* with invalid names.
*
*/
function _privatemsg_parse_userstring($string) {
$fragments = explode(',', $string);
$invalid = array();
$valid = array();
foreach ($fragments as $index => $name) {
$name = trim($name);
if (!empty($name)) { // We don't care about white space names.
if (empty($name) || $error = module_invoke('user', 'validate_name', $name)) {
// These names are invalid due to incorrect user name syntax.
$valid[$name] = $name; // These are valid only due to user name syntax. We still need to check if the user exists and accepts messages.
$users = array();
foreach ($valid as $index => $name) {
if ($recipient = user_load(array('name' => $name))) {
$users[$recipient->uid] = $recipient;
// Here we add more invalid names due to the fact that they don't exist.
return array($users, $invalid);
if (_privatemsg_send($form_state['validate_built_message'])) { // Load usernames to which the message was sent to
$recipient_names = array();
foreach ($form_state['validate_built_message']['recipients'] as $recipient) {
$recipient_names[] = theme('username', $recipient);
}
drupal_set_message(t('A message has been sent to !recipients.', array('!recipients' => implode(', ', $recipient_names))));
drupal_validate_form($form['form_id']['#value'], $form, $form_state);
if (!form_get_errors()) {
$form_state['privatemsg_preview'] = theme('privatemsg_view', $form_state['validate_built_message']);
$form_state['rebuild'] = TRUE; // this forces our form to be rebuilt instead of being submitted.
litwol
committed
function privatemsg_sql_list(&$fragments, $account, $argument = 'list') {
litwol
committed
$fields = array_filter(variable_get('privatemsg_display_fields', array('participants')));
$fragments['select'][] = 'pmi.thread_id';
$fragments['select'][] = 'MIN(pm.subject) as subject';
$fragments['select'][] = 'MAX(pm.timestamp) as last_updated';
$fragments['select'][] = 'MAX(pmi.is_new) as is_new';
if (in_array('count', $fields)) {
$fragments['select'][] = 'COUNT(distinct pmi.mid) as count'; // We only want the distinct number of messages in this thread.
litwol
committed
if (in_array('participants', $fields)) {
// Query for a string with uid's, for example "1,6,7". This needs a subquery on PostgreSQL.
if ($GLOBALS['db_type'] == 'pgsql') {
litwol
committed
$fragments['select'][] = "array_to_string(array(SELECT DISTINCT textin(int4out(pmia.uid))
FROM {pm_index} pmia
WHERE pmia.thread_id = pmi.thread_id), ',') AS participants";
litwol
committed
$fragments['select'][] = '(SELECT GROUP_CONCAT(DISTINCT pmia.uid SEPARATOR ",")
FROM {pm_index} pmia
WHERE pmia.thread_id = pmi.thread_id) AS participants';
}
}
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['query_args']['where'][] = $account->uid;
$fragments['where'][] = 'pmi.deleted = 0';
$fragments['group_by'][] = 'pmi.thread_id';
// We can use tablesort_sql now, but we don't need the ORDER BY part of the query.
// Because of that, we need to cut off the first 9 characters of the generated string
$order_by = drupal_substr(tablesort_sql(_privatemsg_list_headers( FALSE, array('subject', 'last_updated') + $fields), 'is_new DESC,'), 9);
$fragments['order_by'][] = $order_by;
/**
* @addtogroup sql
* @{
*/
/**
* Query function for load.
*/
litwol
committed
function privatemsg_sql_load(&$fragments, $pmid, $account) {
// drupal_set_message('<pre>'. print_r(func_get_args(), 1) . '</pre>');
$fragments['primary_table'] = '{pm_message} pm'; // Our primary table
$fragments['select'][] = "pm.mid";
$fragments['select'][] = "pm.author";
$fragments['select'][] = "pm.subject";
$fragments['select'][] = "pm.body";
$fragments['select'][] = "pm.timestamp";
$fragments['select'][] = "pmi.is_new";
$fragments['inner_join'][] = 'INNER JOIN {pm_index} pmi ON pm.mid = pmi.mid';
$fragments['where'][] = 'pmi.mid = %d';
$fragments['query_args']['where'][] = $pmid;
$fragments['query_args']['where'][] = $account->uid;
/**
* Query definition to load messages of one or multiple threads.
*
* @param $fragments
* Query fragments array.
* @param $threads
* Array with one or multiple thread id's.
* @param $account
litwol
committed
* User object for which the messages are being loaded.
litwol
committed
* Deleted messages are only loaded if this is set to TRUE.
*/
function privatemsg_sql_messages(&$fragments, $threads, $account, $load_all = FALSE) {
$fragments['primary_table'] = '{pm_index} pmi';
$fragments['select'][] = 'DISTINCT(pmi.mid) as mid';
$fragments['where'][] = 'pmi.thread_id IN ('. db_placeholders($threads) .')';
$fragments['query_args']['where'] += $threads;
$fragments['query_args']['where'][] = $account->uid;
if (!$load_all) {
$fragments['where'][] = 'pmi.deleted = 0';
}
function privatemsg_sql_participants(&$fragments, $thread_id) {
$fragments['select'][] = 'DISTINCT(pmi.uid) as uid';
$fragments['where'][] = 'pmi.thread_id = %d';
$fragments['query_args']['where'][] = $thread_id;
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.uid = %d';
$fragments['query_args']['where'][] = $account->uid;
function privatemsg_sql_autocomplete(&$fragments, $search, $names) {
$fragments['primary_table'] = '{users} u';
$fragments['select'][] = 'u.name';
$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';
}
/**
* Return autocomplete results for usernames.
* Prevents usernames from being used and/or suggested twice.
*/
function privatemsg_user_name_autocomplete($string) {
$names = array();
// 1: Parse $string and build list of valid user names.
$fragments = explode(',', $string);
foreach ($fragments as $index => $name) {
$name = trim($name);
if ($error = module_invoke('user', 'validate_name', $name)) {
}
else {
$names[$name] = $name;
}
}
// By using user_validate_user we can ensure that names included in $names are at least logisticaly possible.
// 2: Find the next user name suggestion.
$query = _privatemsg_assemble_query('autocomplete', $fragment, $names);
$result = db_query_range($query['query'], $fragment, 0, 10);
$prefix = count($names) ? implode(", ", $names) .", " : '';
// 3: Build proper suggestions and print.