'Filter', 'description' => 'Configure filter settings.', 'page callback' => 'drupal_get_form', 'page arguments' => array('privatemsg_filter_admin'), 'file' => 'privatemsg_filter.admin.inc', 'access arguments' => array('administer privatemsg settings'), 'type' => MENU_LOCAL_TASK, ); $items['admin/settings/messages/tags'] = array( 'title' => 'Tags', 'description' => 'Configure tags.', 'page callback' => 'privatemsg_tags_admin', 'file' => 'privatemsg_filter.admin.inc', 'access arguments' => array('administer privatemsg settings'), 'type' => MENU_LOCAL_TASK, 'file' => 'privatemsg_filter.admin.inc', ); $items['admin/settings/messages/tags/list'] = array( 'title' => 'List', 'description' => 'List all existing tags.', 'page callback' => 'privatemsg_tags_admin', 'file' => 'privatemsg_filter.admin.inc', 'access arguments' => array('administer privatemsg settings'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10, ); $items['admin/settings/messages/tags/add'] = array( 'title' => 'Add', 'description' => 'Add a new tag.', 'page callback' => 'drupal_get_form', 'page arguments' => array('privatemsg_tags_form'), 'file' => 'privatemsg_filter.admin.inc', 'access arguments' => array('administer privatemsg settings'), 'type' => MENU_LOCAL_TASK, ); $items['admin/settings/messages/tags/rebuild'] = array( 'title' => 'Rebuild inbox', 'description' => 'Tag all thread which should be displayed in the inbox.', 'page callback' => 'drupal_get_form', 'page arguments' => array('privatemsg_filter_inbox_rebuid_form'), 'file' => 'privatemsg_filter.admin.inc', 'access arguments' => array('administer privatemsg settings'), 'type' => MENU_LOCAL_TASK, ); $items['admin/settings/messages/tags/edit/%'] = array( 'title' => 'Add', 'description' => 'Configure tags.', 'page callback' => 'drupal_get_form', 'page arguments' => array('privatemsg_tags_form', 5), 'file' => 'privatemsg_filter.admin.inc', 'access arguments' => array('administer privatemsg settings'), 'type' => MENU_CALLBACK, ); $items['admin/settings/messages/tags/delete/%'] = array( 'title' => 'Add', 'description' => 'Configure tags.', 'page callback' => 'drupal_get_form', 'page arguments' => array('privatemsg_filter_tags_delete', 5), 'file' => 'privatemsg_filter.admin.inc', 'access arguments' => array('administer privatemsg settings'), 'type' => MENU_CALLBACK, ); $items[$url_prefix. '/inbox'] = array( 'title' => 'Inbox', 'page callback' => 'privatemsg_list_page', 'page arguments' => array('inbox', $user_arg_position), 'file' => 'privatemsg.pages.inc', 'file path' => drupal_get_path('module', 'privatemsg'), 'access callback' => 'privatemsg_menu_access', 'type' => variable_get('privatemsg_filter_default_list', 0) ? MENU_LOCAL_TASK : MENU_DEFAULT_LOCAL_TASK, 'weight' => -15, ); $items[$url_prefix . '/sent'] = array( 'title' => 'Sent Messages', 'page callback' => 'privatemsg_list_page', 'page arguments' => array('sent', $user_arg_position), 'file' => 'privatemsg.pages.inc', 'file path' => drupal_get_path('module', 'privatemsg'), 'access callback' => 'privatemsg_menu_access', 'type' => MENU_LOCAL_TASK, 'weight' => -12, ); $items['messages/filter/autocomplete'] = array( 'page callback' => 'privatemsg_autocomplete', 'file' => 'privatemsg.pages.inc', 'file path' => drupal_get_path('module', 'privatemsg'), 'access callback' => 'privatemsg_menu_access', 'access arguments' => array('write privatemsg'), 'type' => MENU_CALLBACK, ); $items['messages/filter/tag-autocomplete'] = array( 'page callback' => 'privatemsg_filter_tags_autocomplete', 'access callback' => 'privatemsg_menu_access', 'access arguments' => array('tag private messages'), 'type' => MENU_CALLBACK, 'weight' => -10, ); return $items; } /** * Implements hook_menu_alter(). */ function privatemsg_filter_menu_alter(&$items) { $url_prefix = variable_get('privatemsg_url_prefix', 'messages'); $user_arg_position = array_search('%user', explode('/', $url_prefix)); // Rename messages to "All messages". $items[$url_prefix . '/list']['title'] = 'All messages'; if (variable_get('privatemsg_filter_default_list', 0) == 0) { // Change default argument of /messages to inbox. and set the task to MENU_LOCAL_TASK. $items[$url_prefix]['page arguments'] = array('inbox', $user_arg_position); $items[$url_prefix . '/list']['type'] = MENU_LOCAL_TASK; } } /** * Implements hook_form_FORM_ID_alter(). * * Add a filter widget to the message listing pages. */ function privatemsg_filter_form_privatemsg_admin_settings_alter(&$form, $form_state) { $form['privatemsg_listing']['privatemsg_filter_default_list'] = array( '#type' => 'radios', '#default_value' => variable_get('privatemsg_filter_default_list', 0), '#options' => array(t('Inbox'), t('All messages')), '#title' => t('Choose the default list option'), '#description' => t('Choose which of the two lists are shown by default when following the messages link.'), ); // Add tags to the list of possible columns. $form['privatemsg_listing']['privatemsg_display_fields']['#options']['tags'] = t('Tags'); $form['#submit'][] = 'privatemsg_filter_settings_submit'; } /** * Rebuilding the menu if necessary. */ function privatemsg_filter_settings_submit($form, &$form_state) { if ($form['privatemsg_listing']['privatemsg_filter_default_list']['#default_value'] != $form_state['values']['privatemsg_filter_default_list']) { menu_rebuild(); } } /** * Function to create a tag * * @param $tags * A single tag or an array of tags. */ function privatemsg_filter_create_tags($tags) { if (!is_array($tags)) { $tags = array($tags); } $tag_ids = array(); foreach ($tags as $tag) { $tag = trim($tag); if (empty($tag)) { // Do not save a blank tag. continue; } // Check if the tag already exists and only create the tag if it does not. $tag_id = db_result(db_query("SELECT tag_id FROM {pm_tags} WHERE tag = '%s'", $tag)); if (empty($tag_id) && privatemsg_user_access('create private message tags')) { db_query("INSERT INTO {pm_tags} (tag) VALUES ('%s')", $tag); $tag_id = db_last_insert_id('pm_tags', 'tag_id'); } elseif (empty($tag_id)) { // The user does not have permission to create new tags - disregard this tag and move onto the next. drupal_set_message(t('Tag %tag was ignored because you do not have permission to create new tags.', array('%tag' => $tag))); continue; } $tag_ids[] = $tag_id; } return $tag_ids; } /** * Tag one or multiple threads with a tag. * * @param $threads * A single thread id or an array of thread ids. * @param $tag_id * Id of the tag. */ function privatemsg_filter_add_tags($threads, $tag_ids, $account = NULL) { if (!is_array($threads)) { $threads = array($threads); } if (!is_array($tag_ids)) { $tag_ids = array($tag_ids); } if (empty($account)) { global $user; $account = drupal_clone($user); } foreach ($tag_ids as $tag_id) { foreach ($threads as $thread) { // Make sure that we don't add a tag to a thread twice, // only insert if there is no such tag yet. if (!db_result(db_query('SELECT 1 FROM {pm_tags_index} WHERE tag_id = %d AND (uid = %d AND thread_id = %d)', $tag_id, $account->uid, $thread))) { db_query('INSERT INTO {pm_tags_index} (tag_id, uid, thread_id) VALUES (%d, %d, %d)', $tag_id, $account->uid, $thread); } } } } /** * Remove tag from one or multiple threads. * * @param $threads * A single thread id or an array of thread ids. * @param $tag_id * Id of the tag - set to NULL to remove all tags. */ function privatemsg_filter_remove_tags($threads, $tag_ids = NULL, $account = NULL) { if (!is_array($threads)) { $threads = array($threads); } if (!is_null($tag_ids) && !is_array($tag_ids)) { $tag_ids = array($tag_ids); } if (empty($account)) { global $user; $account = drupal_clone($user); } if (is_null($tag_ids)) { // Delete all tag mapping - all except for the inbox tag if it exists. $inbox_tag = variable_get('privatemsg_filter_inbox_tag', ''); foreach ($threads as $thread) { db_query('DELETE FROM {pm_tags_index} WHERE uid = %d AND thread_id = %d AND tag_id <> %d', $account->uid, $thread, $inbox_tag); } } else { // Delete tag mapping for the specified tags and threads. $sql = 'DELETE FROM {pm_tags_index} WHERE uid = %d AND thread_id IN (' . db_placeholders($threads) . ') AND tag_id IN (' . db_placeholders($tag_ids) . ')'; db_query($sql, array_merge(array($account->uid), $threads, $tag_ids)); } } function privatemsg_filter_get_filter($account) { $filter = array(); // Filtering by tags is either allowed if the user can use tags or he can // filter. if (privatemsg_user_access('filter private messages') || privatemsg_user_access('tag private messages')) { if (isset($_GET['tags'])) { $_GET['tags'] = urldecode($_GET['tags']); $tag_data = privatemsg_filter_get_tags_data($account); foreach (explode(',', $_GET['tags']) as $tag) { if (isset($tag_data[$tag])) { $filter['tags'][$tag] = $tag; } elseif (in_array($tag, $tag_data)) { $filter['tags'][array_search($tag, $tag_data)] = array_search($tag, $tag_data); } } } } // Users can only use the text search or search by author if they have the // necessary permission. if (privatemsg_user_access('filter private messages')) { if (isset($_GET['author'])) { list($filter['author']) = _privatemsg_parse_userstring($_GET['author']); } if (isset($_GET['search'])) { $filter['search'] = $_GET['search']; } } if (!empty($filter)) { return $filter; } if (!empty($_SESSION['privatemsg_filter'])) { return $_SESSION['privatemsg_filter']; } } function privatemsg_filter_get_tags_data($account) { static $tag_data; if (is_array($tag_data)) { return $tag_data; } // Only show the tags that a user have used. $query = _privatemsg_assemble_query(array('tags', 'privatemsg_filter'), $account); $results = db_query($query['query']); $tag_data = array(); while ($result = db_fetch_object($results)) { $tag_data[$result->tag_id] = $result->tag; } return $tag_data; } function privatemsg_filter_dropdown(&$form_state, $account) { drupal_add_css(drupal_get_path('module', 'privatemsg_filter') .'/privatemsg_filter.css'); $form['filter'] = array( '#type' => 'fieldset', '#title' => t('Filter messages'), '#collapsible' => TRUE, '#collapsed' => TRUE, // The form is always called when search arguments are passed in, even if // they don't have access to it. This is necessary to process the search // query. But we don't want to show them the form. '#access' => privatemsg_user_access('filter private messages'), '#weight' => -20, ); $form['filter']['search'] = array( '#type' => 'textfield', '#title' => variable_get('privatemsg_filter_searchbody', FALSE) ? t('By content') : t('By subject'), '#weight' => -20, '#size' => 25, ); $form['filter']['author'] = array( '#type' => 'textfield', '#title' => t('By participant'), '#weight' => -5, '#size' => 25, '#autocomplete_path' => 'messages/filter/autocomplete', ); // Only show form if the user has some messages tagged. if (count($tag_data = privatemsg_filter_get_tags_data($account))) { $form['filter']['tags'] = array( '#type' => 'select', '#title' => t('By tags'), '#options' => $tag_data, '#multiple' => TRUE, '#weight' => 0 ); } $form['filter']['submit'] = array( '#type' => 'submit', '#value' => t('Filter'), '#prefix' => '
', '#weight' => 11, '#submit' => array('privatemsg_filter_dropdown_submit'), ); if ($filter = privatemsg_filter_get_filter($account)) { // Display a message if the user will not see the filter form. if (!empty($filter['tags']) && !empty($_GET['tags']) && !privatemsg_user_access('filter private messages')) { drupal_set_message(t('Messages tagged with %tags are currently displayed. Click here to remove this filter.', array('%tags' => $_GET['tags'], '@remove_filter_url' => url($_GET['q'])))); } privatemsg_filter_dropdown_set_active($form, $filter); } return $form; } function privatemsg_filter_dropdown_set_active(&$form, $filter) { $form['filter']['#title'] = t('Filter messages (active)'); $form['filter']['#collapsed'] = FALSE; if (isset($filter['author'])) { $string = ''; foreach ($filter['author'] as $author) { $string .= privatemsg_recipient_format($author, array('plain' => TRUE)) . ', '; } $form['filter']['author']['#default_value'] = $string; } if (isset($filter['tags'])) { $form['filter']['tags']['#default_value'] = $filter['tags']; } if (isset($filter['search'])) { $form['filter']['search']['#default_value'] = $filter['search']; } $form['filter']['reset'] = array( '#type' => 'submit', '#value' => t('Reset'), '#suffix' => '', '#weight' => 12, '#submit' => array('privatemsg_filter_dropdown_submit'), ); unset($form['filter']['save']['#suffix']); } function privatemsg_filter_dropdown_submit($form, &$form_state) { if (!empty($form_state['values']['author'])) { list($form_state['values']['author']) = _privatemsg_parse_userstring($form_state['values']['author']); } switch ($form_state['values']['op']) { case t('Save filter'): $filter = array(); if (!empty($form_state['values']['tags'])) { $filter['tags'] = $form_state['values']['tags']; } if (!empty($form_state['values']['author'])) { $filter['author'] = $form_state['values']['author']; } if (!empty($form_state['values']['search'])) { $filter['search'] = $form_state['values']['search']; } $_SESSION['privatemsg_filter'] = $filter; break; case t('Filter'): drupal_goto($_GET['q'], privatemsg_filter_create_get_query($form_state['values'])); return; break; case t('Reset'): $_SESSION['privatemsg_filter'] = array(); break; } $form_state['redirect'] = $_GET['q']; } /** * Creates a GET query based on the selected filters. */ function privatemsg_filter_create_get_query($filter) { $query = array(); if (isset($filter['tags']) && !empty($filter['tags'])) { $ids = array(); foreach ($filter['tags'] as $tag) { if ((int)$tag > 0) { $ids[] = $tag; } else { $query['tags'][] = $tag; } } $sql = 'SELECT pmt.tag FROM {pm_tags} pmt WHERE pmt.tag_id IN ('. implode(', ', $filter['tags']) .')'; $result = db_query($sql); while ($row = db_fetch_object($result)) { $query['tags'][] = $row->tag; } if (isset($query['tags'])) { $query['tags'] = implode(',', $query['tags']); } } if (isset($filter['author']) && !empty($filter['author'])) { foreach ($filter['author'] as $author) { if (is_object($author) && isset($author->uid) && isset($author->name)) { $query['author'][] = privatemsg_recipient_format($author, array('plain' => TRUE)); } elseif (is_int($author) && $author_obj = _privatemsg_user_load($author)) { $query['author'][] = privatemsg_recipient_format($author, array('plain' => TRUE)); } } if (isset($query['author'])) { $query['author'] = implode(',', $query['author']); } } if (isset($filter['search']) && !empty($filter['search'])) { $query['search'] = $filter['search']; } return $query; } /** * Implements hook_form_FORM_ID_alter(). * * Adds a filter widget to the message listing pages. */ function privatemsg_filter_form_privatemsg_list_alter(&$form, $form_state) { global $user; if (!empty($form['#data']) || privatemsg_filter_get_filter($user)) { $form += privatemsg_filter_dropdown($form_state, $form['#account']); } $fields = array_filter(variable_get('privatemsg_display_fields', array('participants'))); if (privatemsg_user_access('tag private messages') && in_array('tags', $fields) && !empty($form['#data'])) { // Load thread id's of the current list. $threads = array_keys($form['#data']); // Fetch all tags of those threads. $query = _privatemsg_assemble_query(array('tags', 'privatemsg_filter'), $user, $threads, 3); // Add them to #data $result = db_query($query['query']); while ($tag = db_fetch_array($result)) { $form['#data'][$tag['thread_id']]['tags'][$tag['tag_id']] = $tag['tag']; } } if (privatemsg_user_access('tag private messages') && !empty($form['#data'])) { $form['actions']['tag-add'] = array( '#type' => 'textfield', '#size' => 15, '#autocomplete_path' => 'messages/filter/tag-autocomplete', ); $form['actions']['tag-add-submit'] = array( //'#prefix' => '