summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--privatemsg_filter/privatemsg_filter.install8
-rw-r--r--privatemsg_filter/privatemsg_filter.module323
2 files changed, 167 insertions, 164 deletions
diff --git a/privatemsg_filter/privatemsg_filter.install b/privatemsg_filter/privatemsg_filter.install
index ebfb287..a051ae7 100644
--- a/privatemsg_filter/privatemsg_filter.install
+++ b/privatemsg_filter/privatemsg_filter.install
@@ -66,5 +66,13 @@ function privatemsg_filter_install() {
function privatemsg_filter_uninstall() {
variable_del('privatemsg_filter_searchbody');
+ variable_del('privatemsg_filter_tagfield_weight');
drupal_uninstall_schema('privatemsg_filter');
}
+
+function privatemsg_filter_update_6001() {
+ $ret = array();
+ $ret[] = update_sql("UPDATE {permission} SET perm = REPLACE(perm, 'use privatemsg_filter', 'filter private messages') WHERE perm LIKE '%use privatemsg_filter%'");
+ $ret[] = update_sql("UPDATE {permission} SET perm = REPLACE(perm, 'create privatemsg_filter', 'create private message tags') WHERE perm LIKE '%create privatemsg_filter%'");
+ return $ret;
+} \ No newline at end of file
diff --git a/privatemsg_filter/privatemsg_filter.module b/privatemsg_filter/privatemsg_filter.module
index 690017b..51d2cc6 100644
--- a/privatemsg_filter/privatemsg_filter.module
+++ b/privatemsg_filter/privatemsg_filter.module
@@ -11,9 +11,9 @@
*/
function privatemsg_filter_perm() {
return array(
- 'use privatemsg_filter',
- 'create privatemsg_filter',
- 'delete privatemsg_filter',
+ 'filter private messages',
+ 'tag private messages',
+ 'create private message tags',
);
}
@@ -21,13 +21,6 @@ function privatemsg_filter_perm() {
* Implementation of hook_menu().
*/
function privatemsg_filter_menu() {
- $items['messages/tags'] = array(
- 'title' => 'Tags',
- 'page callback' => 'privatemsg_filter_page',
- 'access callback' => 'privatemsg_user_access',
- 'access arguments' => array('use privatemsg_filter'),
- 'type' => MENU_LOCAL_TASK,
- );
$items['admin/settings/messages/filter'] = array(
'title' => 'Filter',
'description' => 'Configure filter settings.',
@@ -67,6 +60,13 @@ function privatemsg_filter_menu() {
'type' => MENU_CALLBACK,
'weight' => -10,
);
+ $items['messages/filter/tag-autocomplete'] = array(
+ 'page callback' => 'privatemsg_filter_tags_autocomplete',
+ 'access callback' => 'privatemsg_user_access',
+ 'access arguments' => array('tag private messages'),
+ 'type' => MENU_CALLBACK,
+ 'weight' => -10,
+ );
return $items;
}
@@ -80,137 +80,23 @@ function privatemsg_filter_admin() {
'#default_value' => variable_get('privatemsg_filter_searchbody', FALSE),
);
- return system_settings_form($form);
-}
-
-function privatemsg_filter_page() {
- $content = '';
- drupal_set_title(t('Tags'));
-
- $sql = 'SELECT * FROM {pm_tags}';
- $query = db_query($sql);
- $tag_array = array();
-
- while ($result = db_fetch_object($query)) {
- $tag_array[] = l($result->tag, 'messages', array('query' => 'tags='. $result->tag));
- }
- if (count($tag_array)) {
- $content .= '<h2>'. t('Current tags:') .'</h2>';
- $content .= implode(', ', $tag_array) .'.';
- }
-
- if (privatemsg_user_access('create privatemsg_filter')) {
- $content .= drupal_get_form('privatemsg_filter_add_tags');
- }
- if (privatemsg_user_access('delete privatemsg_filter')) {
- $content .= drupal_get_form('privatemsg_filter_delete_tags');
- }
-
- return $content;
-}
-
-/**
- * Add new tags
- */
-function privatemsg_filter_add_tags($form_state) {
- $form['addtags'] = array(
- '#type' => 'fieldset',
- '#title' => t('Add tags'),
- '#collapsible' => TRUE,
- '#collapsed' => FALSE,
- );
-
- $form['addtags']['newtags'] = array(
- '#type' => 'textfield',
- '#title' => t('What tags would you like to add?'),
- '#description' => t('Please insert a comma separated list of new tags in the form of "tag1, tag2, tag3...". All spaces will be replaced by hyphens.'),
- '#default_value' => '',
- '#required' => 1,
+ $form['privatemsg_filter_tagfield_weight'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Position of the tagging textfield'),
+ '#description' => t('Use higher values to push the form lower down the page, lower or negative values to raise it higher.'),
+ '#size' => 4,
+ '#default_value' => variable_get('privatemsg_filter_tagfield_weight', 10),
);
- $form['addtags']['submit'] = array(
- '#type' => 'submit',
- '#value' => t('Add tags'),
- );
-
-
- return $form;
-}
-
-function privatemsg_filter_add_tags_submit($form, &$form_state) {
-
- if (isset($form_state['values']['submit'])) {
- $tags = explode(',', $form_state['values']['newtags']);
-
- foreach ($tags as $tag) {
- $tag = trim($tag);
- $tag = str_replace(' ', '-', $tag);
- $count = db_result(db_query("SELECT COUNT(*) FROM {pm_tags} WHERE tag = '%s'", $tag));
- if ($count == 0) {
- db_query("INSERT INTO {pm_tags} (tag) VALUES ('%s')", $tag);
- $inserted[] = $tag;
- }
- }
- }
- if (count($inserted)) {
- drupal_set_message(t('!count tags have been saved: !tags.', array('!count' => count($inserted), '!tags' => implode(', ', $inserted))));
- }
-}
-
-/**
- * Delete existing tags
- */
-function privatemsg_filter_delete_tags($form_state) {
-
- $form['deletetags'] = array(
- '#type' => 'fieldset',
- '#title' => t('Delete tags'),
- '#collapsible' => TRUE,
- '#collapsed' => TRUE,
- );
-
- $sql = 'SELECT * FROM {pm_tags}';
- $query = db_query($sql);
- $tag_array = array();
-
- while ($result = db_fetch_object($query)) {
- $checked = 0;
- $form_data = array('#type' => 'checkbox', '#title' => $result->tag, '#default_value' => $checked, '#return_value' => 1);
- $form['deletetags']['tag_'. $result->tag_id] = $form_data;
- }
-
- $form['deletetags']['submit'] = array(
- '#type' => 'submit',
- '#value' => t('Delete selected tags'),
- );
-
- return $form;
-
-}
-
-function privatemsg_filter_delete_tags_submit($form, &$form_state) {
- if (isset($form_state['values']['submit'])) {
- $sql = 'SELECT * FROM {pm_tags}';
- $query = db_query($sql);
-
- while ($result = db_fetch_object($query)) {
- if ($form_state['values']['tag_'. $result->tag_id] == 1) {
- db_query('DELETE FROM {pm_tags_index} WHERE tag_id = %d', $result->tag_id);
- db_query('DELETE FROM {pm_tags} WHERE tag_id = %d', $result->tag_id);
- $deleted[] = $result->tag;
- }
- }
- }
- if (count($deleted)) {
- drupal_set_message(t('!count tags have been deleted: !tags.', array('!count' => count($deleted), '!tags' => implode(', ', $deleted))));
- }
+ return system_settings_form($form);
}
function privatemsg_filter_get_filter($account) {
$filter = array();
if (isset($_GET['tags'])) {
+ $_GET['tags'] = urldecode($_GET['tags']);
$tag_data = privatemsg_filter_get_tags_data($account);
- foreach (explode(' ', $_GET['tags']) as $tag) {
+ foreach (explode(',', $_GET['tags']) as $tag) {
if (isset($tag_data[$tag])) {
$filter['tags'][$tag] = $tag;
}
@@ -245,12 +131,12 @@ function privatemsg_filter_get_tags_data($account) {
return $tag_data;
}
- // Only show the tags that a user has used.
- $sql = 'SELECT pmt.tag, pmt.tag_id FROM {pm_tags_index} pmti LEFT JOIN {pm_tags} pmt ON pmti.tag_id = pmt.tag_id WHERE pmti.uid = %d GROUP BY pmt.tag_id, pmt.tag';
- $query = db_query($sql, $account->uid);
+ // Only show the tags that a user have used.
+ $query = _privatemsg_assemble_query(array('used_tags', 'privatemsg_filter'), $account);
+ $results = db_query($query['query']);
$tag_data = array();
- while ($result = db_fetch_object($query)) {
+ while ($result = db_fetch_object($results)) {
$tag_data[$result->tag_id] = $result->tag;
}
return $tag_data;
@@ -394,7 +280,7 @@ function privatemsg_filter_create_get_query($filter)
}
if (isset($query['tags'])) {
- $query['tags'] = implode(' ', $query['tags']);
+ $query['tags'] = implode(',', $query['tags']);
}
}
@@ -419,10 +305,10 @@ function privatemsg_filter_create_get_query($filter)
}
/**
- * Implementation of hook_form_alter().
+ * Implementation of hook_form_alter() to add a filter widget to the message listing pages.
*/
function privatemsg_filter_form_privatemsg_list_alter(&$form, $form_state) {
- if (privatemsg_user_access('use privatemsg_filter')) {
+ if (privatemsg_user_access('filter private messages')) {
$form += privatemsg_filter_dropdown($form_state, $form['#account']);
}
}
@@ -479,22 +365,38 @@ function privatemsg_filter_privatemsg_sql_list_alter(&$fragments, $account, $arg
}
}
+/**
+ * Hook into the view messages page to add a form for tagging purposes.
+ */
function privatemsg_filter_privatemsg_view_messages_alter(&$content, $thread) {
- if (count($thread['messages']) > 0 && db_result(db_query('SELECT COUNT(*) FROM {pm_tags}')) > 0) {
+ if (count($thread['messages']) > 0) {
$content['tags']['#value'] = drupal_get_form('privatemsg_filter_form');
- $content['tags']['#weight'] = 10;
+ $content['tags']['#weight'] = variable_get('privatemsg_filter_tagfield_weight', 10);
}
}
+/**
+ * Form to show and allow modification of tagging information for a conversation.
+ */
function privatemsg_filter_form(&$form_state) {
global $user;
$thread_id = arg(2);
+ // Get a list of current tags for this thread
+ $query = _privatemsg_assemble_query(array('used_tags', 'privatemsg_filter'), $user, $thread_id);
+ $results = db_query($query['query']);
+ $count = db_result(db_query($query['count']));
+ $tags = '';
+ while ($tag = db_fetch_array($results)) {
+ $tags .= $tag['tag']. ', ';
+ }
+
$form['tags'] = array(
'#type' => 'fieldset',
'#title' => t('Tags'),
+ '#access' => privatemsg_user_access('tag private messages'),
'#collapsible' => TRUE,
- '#collapsed' => TRUE,
+ '#collapsed' => empty($count) ? TRUE : FALSE,
);
$form['tags']['user_id'] = array(
'#type' => 'value',
@@ -505,22 +407,18 @@ function privatemsg_filter_form(&$form_state) {
'#value' => $thread_id,
);
- $sql = 'SELECT * FROM {pm_tags}';
- $query = db_query($sql);
- $tag_array = array();
-
- while ($result = db_fetch_object($query)) {
- $checked = 0;
- if (db_result(db_query('SELECT COUNT(*) FROM {pm_tags_index} WHERE tag_id = %d AND (uid = %d AND thread_id = %d)', $result->tag_id, $user->uid, $thread_id))) {
- $checked = 1;
- }
- $form_data = array('#type' => 'checkbox', '#title' => $result->tag, '#default_value' => $checked, '#return_value' => 1);
- $form['tags']['tag_'. $result->tag_id] = $form_data;
- }
+ $form['tags']['tags'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Tags for this conversation'),
+ '#description' => t('Separate multiple tags with commas.'),
+ '#size' => 50,
+ '#default_value' => $tags,
+ '#autocomplete_path' => 'messages/filter/tag-autocomplete',
+ );
$form['tags']['submit'] = array(
'#type' => 'submit',
- '#value' => t('Tag this message'),
+ '#value' => t('Tag this conversation'),
'#submit' => array('privatemsg_filter_form_submit'),
);
@@ -529,19 +427,69 @@ function privatemsg_filter_form(&$form_state) {
function privatemsg_filter_form_submit($form, &$form_state) {
if (isset($form_state['values']['submit'])) {
- $sql = 'SELECT * FROM {pm_tags}';
- $query = db_query($sql);
+ $tags = explode(',', $form_state['values']['tags']);
- while ($result = db_fetch_object($query)) {
- if ($form_state['values']['tag_'. $result->tag_id] == 0) {
- db_query('DELETE FROM {pm_tags_index} WHERE tag_id = %d AND (uid = %d AND thread_id = %d)', $result->tag_id, $form_state['values']['user_id'], $form_state['values']['thread_id']);
+ // Step 1 - Delete all tag mapping. I cannot think of a better way to remove tags that are no longer in the textfield, so ideas welcome.
+ db_query('DELETE FROM {pm_tags_index} WHERE uid = %d AND thread_id = %d', $form_state['values']['user_id'], $form_state['values']['thread_id']);
+
+ foreach ($tags as $tag) {
+ // Step 2 - We need to sanitise the tag.
+ // Since we allow tags to be passed via the url, there needs to be some sanity testing of each tag.
+ // Currently we replace blank spaces and a # with a "-", but this needs to be expanded to cover all the url special cases.
+ $tag = trim($tag);
+ if (empty($tag)) {
+ // Do not save a blank tag.
+ continue;
}
- elseif (db_result(db_query('SELECT COUNT(*) FROM {pm_tags_index} WHERE tag_id = %d AND (uid = %d AND thread_id = %d)', $result->tag_id, $form_state['values']['user_id'], $form_state['values']['thread_id'])) == 0) {
- db_query('INSERT INTO {pm_tags_index} (tag_id, uid, thread_id) VALUES (%d, %d, %d)', $result->tag_id, $form_state['values']['user_id'], $form_state['values']['thread_id']);
+
+ // Step 3 - Make sure that the tag exists and if it does not, we need to create it.
+ $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;
}
+
+ // Step 4 - map the tag to the thread and the user.
+ db_query('INSERT INTO {pm_tags_index} (tag_id, uid, thread_id) VALUES (%d, %d, %d)', $tag_id, $form_state['values']['user_id'], $form_state['values']['thread_id']);
+ }
+ drupal_set_message(t('Tagging information has been saved.'));
+ }
+}
+
+/**
+ * Return autocomplete results for tags.
+ *
+ * Most of this code has been lifted/modified from privatemsg_user_name_autocomplete().
+ */
+function privatemsg_filter_tags_autocomplete($string) {
+
+ // 1: Parse $string and build a list of tags.
+ $tags = array();
+ $fragments = explode(',', $string);
+ foreach ($fragments as $index => $tag) {
+ $tag = trim($tag);
+ $tags[$tag] = $tag;
+ }
+
+ // 2: Find the next tag suggestion.
+ $fragment = array_pop($tags);
+ $matches = array();
+ if (!empty($fragment)) {
+ $query = _privatemsg_assemble_query(array('tags_autocomplete', 'privatemsg_filter'), $fragment, $tags);
+ $result = db_query_range($query['query'], $fragment, 0, 10);
+ $prefix = count($tags) ? implode(", ", $tags) .", " : '';
+ // 3: Build proper suggestions and print.
+ while ($tag = db_fetch_object($result)) {
+ $matches[$prefix . $tag->tag .", "] = $tag->tag;
}
- drupal_set_message(t('Tagging information has been saved.'));
}
+ // convert to object to prevent drupal bug, see http://drupal.org/node/175361
+ drupal_json((object)$matches);
}
/**
@@ -561,4 +509,51 @@ function privatemsg_filter_privatemsg_sql_autocomplete_alter(&$fragments, $searc
$fragments['inner_join'][] = 'INNER JOIN {pm_index} piu ON piu.uid = %d AND pip.mid = piu.mid';
$fragments['query_args']['join'][] = $user->uid;
}
+}
+
+/**
+ * Query definition to get the tags in use by the specified user.
+ *
+ * @param $fragments
+ * Query fragments array.
+ * @param $user
+ * User object for whom we want the tags.
+ * @param $thread_id
+ * The thread_id - Only needed if we want the tags for a specific thread instead of all used tags on any thread.
+ */
+function privatemsg_filter_sql_used_tags(&$fragments, $user, $thread_id = NULL) {
+ $fragments['primary_table'] = '{pm_tags} t';
+ $fragments['select'][] = 't.tag';
+ $fragments['select'][] = 't.tag_id';
+ $fragments['inner_join'][] = 'INNER JOIN {pm_tags_index} ti on ti.tag_id = t.tag_id';
+ if (!empty($thread_id)) {
+ $fragments['where'][] = 'ti.thread_id = %d';
+ $fragments['query_args']['where'][] = $thread_id;
+ }
+ $fragments['where'][] = 'ti.uid = %d';
+ $fragments['query_args']['where'][] = $user->uid;
+
+ $fragments['order_by'][] = 't.tag ASC';
+}
+
+/**
+ * Query definition to get autocomplete suggestions for tags
+ *
+ * @param $fragments
+ * Query fragments array.
+ * @param $search
+ * String fragment to use for tag suggestions.
+ * @param $tags
+ * Array of tags not to be used as suggestions.
+ */
+function privatemsg_filter_sql_tags_autocomplete(&$fragments, $search, $tags) {
+ $fragments['primary_table'] = '{pm_tags} pmt';
+ $fragments['select'][] = 'pmt.tag';
+ $fragments['where'][] = "pmt.tag LIKE '%s'";
+ $fragments['query_args']['where'][] = $search .'%%';
+ if (!empty($tags)) {
+ $fragments['where'][] = "pmt.tag NOT IN (". db_placeholders($tags, 'text') .")";
+ $fragments['query_args']['where'] += $tags;
+ }
+ $fragments['order_by'][] = 'pmt.tag ASC';
} \ No newline at end of file