#376034 by Berdir: #288183 followup: user blocking doesnt work when sending to group...
[project/privatemsg.git] / privatemsg_filter / privatemsg_filter.module
CommitLineData
67189554
TGGM
1<?php
2// $Id$
3
4/**
5 * @file
6 * Allows users to tag private messages and to filter based upon those tags.
7 */
8
9/**
10 * Implementation of hook_perm().
11 */
12function privatemsg_filter_perm() {
13 return array(
14 'use privatemsg_filter',
15 'create privatemsg_filter',
16 'delete privatemsg_filter',
17 );
18}
19
20/**
21 * Implementation of hook_menu().
22 */
23function privatemsg_filter_menu() {
24 $items['messages/tags'] = array(
25 'title' => 'Tags',
26 'page callback' => 'privatemsg_filter_page',
bc4689a7 27 'access callback' => 'privatemsg_user_access',
67189554
TGGM
28 'access arguments' => array('use privatemsg_filter'),
29 'type' => MENU_LOCAL_TASK,
30 );
e5fe4a8d
OT
31 $items['admin/settings/messages/filter'] = array(
32 'title' => 'Filter',
33 'description' => 'Configure filter settings.',
34 'page callback' => 'drupal_get_form',
35 'page arguments' => array('privatemsg_filter_admin'),
36 'access arguments' => array('administer privatemsg settings'),
37 'type' => MENU_LOCAL_TASK,
38 );
67189554
TGGM
39 return $items;
40}
41
e5fe4a8d
OT
42function privatemsg_filter_admin() {
43 $form = array();
44
45 $form['privatemsg_filter_searchbody'] = array(
46 '#type' => 'checkbox',
47 '#title' => t('Search message body'),
48 '#description' => t('WARNING: turning on this feature will slow down search performance by a large factor. Gets worse as your messages database increases.'),
49 '#default_value' => variable_get('privatemsg_filter_searchbody', FALSE),
50 );
51
52 return system_settings_form($form);
53}
54
67189554
TGGM
55function privatemsg_filter_page() {
56 $content = '';
57 drupal_set_title('Tags');
58
59 $sql = 'SELECT * FROM {pm_tags}';
60 $query = db_query($sql);
61 $tag_array = array();
62
63 while ($result = db_fetch_object($query)) {
64 $tag_array[] = l($result->tag, 'messages', array('query' => 'tags='. $result->tag));
65 }
66 if (count($tag_array)) {
67 $content .= '<h2>'. t('Current tags:') .'</h2>';
68 $content .= implode(', ', $tag_array) .'.';
69 }
70
bc4689a7 71 if (privatemsg_user_access('create privatemsg_filter')) {
67189554
TGGM
72 $content .= drupal_get_form('privatemsg_filter_add_tags');
73 }
bc4689a7 74 if (privatemsg_user_access('delete privatemsg_filter')) {
67189554
TGGM
75 $content .= drupal_get_form('privatemsg_filter_delete_tags');
76 }
77
78 return $content;
79}
80
81/**
82 * Add new tags
83 */
84function privatemsg_filter_add_tags($form_state) {
85 $form['addtags'] = array(
86 '#type' => 'fieldset',
87 '#title' => t('Add tags'),
88 '#collapsible' => TRUE,
89 '#collapsed' => FALSE,
90 );
91
92 $form['addtags']['newtags'] = array(
93 '#type' => 'textfield',
94 '#title' => t('What tags would you like to add?'),
95 '#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.'),
96 '#default_value' => '',
97 '#required' => 1,
98 );
99
100 $form['addtags']['submit'] = array(
101 '#type' => 'submit',
102 '#value' => t('Add tags'),
103 );
104
105
106 return $form;
107}
108
109function privatemsg_filter_add_tags_submit($form, &$form_state) {
110
111 if (isset($form_state['values']['submit'])) {
112 $tags = explode(',', $form_state['values']['newtags']);
113
114 foreach ($tags as $tag) {
115 $tag = trim($tag);
116 $tag = str_replace(' ', '-', $tag);
117 $count = db_result(db_query("SELECT COUNT(*) FROM {pm_tags} WHERE tag = '%s'", $tag));
118 if ($count == 0) {
119 db_query("INSERT INTO {pm_tags} (tag) VALUES ('%s')", $tag);
120 $inserted[] = $tag;
121 }
122 }
123 }
124 if (count($inserted)) {
125 drupal_set_message(t('!count tags have been saved: !tags.', array('!count' => count($inserted), '!tags' => implode(', ', $inserted))));
126 }
127}
128
129/**
130 * Delete existing tags
131 */
132function privatemsg_filter_delete_tags($form_state) {
133
134 $form['deletetags'] = array(
135 '#type' => 'fieldset',
136 '#title' => t('Delete tags'),
137 '#collapsible' => TRUE,
138 '#collapsed' => TRUE,
139 );
140
141 $sql = 'SELECT * FROM {pm_tags}';
142 $query = db_query($sql);
143 $tag_array = array();
144
145 while ($result = db_fetch_object($query)) {
146 $checked = 0;
147 $form_data = array('#type' => 'checkbox', '#title' => $result->tag, '#default_value' => $checked, '#return_value' => 1);
148 $form['deletetags']['tag_'. $result->tag_id] = $form_data;
149 }
150
151 $form['deletetags']['submit'] = array(
152 '#type' => 'submit',
153 '#value' => t('Delete selected tags'),
154 );
155
156 return $form;
157
158}
159
160function privatemsg_filter_delete_tags_submit($form, &$form_state) {
161 if (isset($form_state['values']['submit'])) {
162 $sql = 'SELECT * FROM {pm_tags}';
163 $query = db_query($sql);
164
165 while ($result = db_fetch_object($query)) {
166 if ($form_state['values']['tag_'. $result->tag_id] == 1) {
167 db_query('DELETE FROM {pm_tags_index} WHERE tag_id = %d', $result->tag_id);
168 db_query('DELETE FROM {pm_tags} WHERE tag_id = %d', $result->tag_id);
169 $deleted[] = $result->tag;
170 }
171 }
172 }
173 if (count($deleted)) {
174 drupal_set_message(t('!count tags have been deleted: !tags.', array('!count' => count($deleted), '!tags' => implode(', ', $deleted))));
175 }
176}
177
178function privatemsg_filter_get_filter($account) {
179 $filter = array();
180 if (isset($_GET['tags'])) {
181 $tag_data = privatemsg_filter_get_tags_data($account);
182 foreach (explode(' ', $_GET['tags']) as $tag) {
183 if (isset($tag_data[$tag])) {
184 $filter['tags'][$tag] = $tag;
185 }
186 elseif (in_array($tag, $tag_data)) {
187 $filter['tags'][array_search($tag, $tag_data)] = array_search($tag, $tag_data);
188 }
189 }
190 }
191
192 if (isset($_GET['author'])) {
193 foreach (explode(' ', $_GET['author']) as $author) {
194 $author_data = privatemsg_filter_get_author_data($account);
195 if (isset($author_data[$author])) {
196 $filter[$author] = $author;
197 }
198 elseif (in_array($author, $author_data)) {
199 $filter['author'][array_search($author, $author_data)] = array_search($author, $author_data);
200 }
201 }
202 }
203
204 if (isset($_GET['search'])) {
205 $filter['search'] = $_GET['search'];
206 }
207
208 if(!empty($filter)) {
209 return $filter;
210 }
211
212 if (!empty($_SESSION['privatemsg_filter'])) {
213 return $_SESSION['privatemsg_filter'];
214 }
215
216}
217
218function privatemsg_filter_get_author_data($account) {
219 static $author_data;
220
221 if (is_array($author_data)) {
222 return $author_data;
223 }
18ed6a93 224 $sql = 'SELECT DISTINCT pm.author, u.name FROM {pm_message} pm INNER JOIN {pm_index} pmi ON pm.mid = pmi.mid INNER JOIN {users} u ON pm.author = u.uid WHERE pmi.uid = %d AND u.uid > 0 ORDER BY u.name';
67189554
TGGM
225 $query = db_query($sql, $account->uid);
226
227 $author_data = array();
228 while ($result = db_fetch_object($query)) {
229 $author_data[$result->author] = $result->name;
230 }
231 return $author_data;
232}
233
234function privatemsg_filter_get_tags_data($account) {
235 static $tag_data;
e5fe4a8d 236
67189554
TGGM
237 if (is_array($tag_data)) {
238 return $tag_data;
239 }
240
241 // Only show the tags that a user has used.
242 $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';
243 $query = db_query($sql, $account->uid);
244
245 $tag_data = array();
246 while ($result = db_fetch_object($query)) {
247 $tag_data[$result->tag_id] = $result->tag;
248 }
249 return $tag_data;
250}
251
252function privatemsg_filter_dropdown(&$form_state, $account) {
253
254 drupal_add_css(drupal_get_path('module', 'privatemsg_filter') .'/privatemsg_filter.css');
255
256 $form['filter'] = array(
e5fe4a8d
OT
257 '#type' => 'fieldset',
258 '#title' => t('Filter Messages'),
259 '#collapsible' => TRUE,
260 '#collapsed' => TRUE,
67189554
TGGM
261 );
262 $form['filter']['search'] = array(
e5fe4a8d
OT
263 '#type' => 'textfield',
264 '#title' => variable_get('privatemsg_filter_searchbody', FALSE) ? t('Search messages') : t('Search subjects'),
265 '#weight' => -20
67189554
TGGM
266 );
267
268 $form['filter']['author'] = array(
269 '#type' => 'select',
270 '#title' => t('Authors'),
271 '#options' => privatemsg_filter_get_author_data($account),
272 '#multiple' => TRUE,
273 '#size' => 5,
274 '#weight' => -10
275 );
276
277 // Only show form if the user has some messages tagged.
278 if (count($tag_data = privatemsg_filter_get_tags_data($account))) {
279 $form['filter']['tags'] = array(
280 '#type' => 'select',
281 '#title' => t('Tags'),
282 '#options' => $tag_data,
283 '#multiple' => TRUE,
284 '#size' => 5,
285 '#weight' => 0
286 );
287 }
288 $form['filter']['submit'] = array(
289 '#type' => 'submit',
290 '#value' => t('Filter'),
291 '#prefix' => '<div id="privatemsg-filter-buttons">',
292 '#weight' => 10,
293 );
294
295 $form['filter']['save'] = array(
296 '#type' => 'submit',
297 '#value' => t('Save Filter'),
298 '#suffix' => '</div>',
299 '#weight' => 11,
300 );
301
302 if ($filter = privatemsg_filter_get_filter($account)) {
303 privatemsg_filter_dropdown_set_active($form, $filter);
304 }
305
306 return $form;
307}
308
309function privatemsg_filter_dropdown_set_active(&$form, $filter) {
310 $form['filter']['#title'] = t('Filter Messages (Active)');
311 $form['filter']['#collapsed'] = FALSE;
312
313 if (isset($filter['author'])) {
314 $form['filter']['author']['#default_value'] = $filter['author'];
315 }
316 if (isset($filter['tags'])) {
317 $form['filter']['tags']['#default_value'] = $filter['tags'];
318 }
319 if (isset($filter['search'])) {
320 $form['filter']['search']['#default_value'] = $filter['search'];
321 }
e5fe4a8d 322
67189554
TGGM
323 $form['filter']['reset'] = array(
324 '#type' => 'submit',
325 '#value' => t('Reset'),
326 '#suffix' => '</div>',
327 '#weight' => 12
328 );
329 unset($form['filter']['save']['#suffix']);
330}
331
332function privatemsg_filter_dropdown_submit($form, &$form_state) {
333 switch ($form_state['values']['op']) {
334 case t('Save Filter'):
335 $filter = array();
336 if (!empty($form_state['values']['tags'])) {
337 $filter['tags'] = $form_state['values']['tags'];
338 }
339 if (!empty($form_state['values']['author'])) {
340 $filter['author'] = $form_state['values']['author'];
341 }
342 if (!empty($form_state['values']['search'])) {
343 $filter['search'] = $form_state['values']['search'];
344 }
345 $_SESSION['privatemsg_filter'] = $filter;
346 break;
347 case t('Filter'):
348 drupal_goto('messages', privatemsg_filter_create_get_query($form_state['values']));
349 return;
350 break;
351 case t('Reset'):
352 $_SESSION['privatemsg_filter'] = array();
353 break;
354 }
355 $form_state['redirect'] = 'messages';
356}
357
358function privatemsg_filter_create_get_query($filter)
359{
360 $query = array();
361 if (isset($filter['tags']) && !empty($filter['tags'])) {
362 $ids = array();
363 foreach ($filter['tags'] as $tag) {
364 if ((int)$tag > 0) {
365 $ids[] = $tag;
366 }
367 else {
368 $query['tags'][] = $tag;
369 }
370 }
371 $sql = 'SELECT pmt.tag FROM {pm_tags} pmt WHERE pmt.tag_id IN ('. implode(', ', $filter['tags']) .')';
372 $result = db_query($sql);
373 while ($row = db_fetch_object($result)) {
374 $query['tags'][] = $row->tag;
375 }
376
377 if (isset($query['tags'])) {
378 $query['tags'] = implode(' ', $query['tags']);
379 }
380 }
381
382 if (isset($filter['author']) && !empty($filter['author'])) {
383 array_map('user_load', $filter['author']);
384 foreach ($filter['author'] as $author) {
385 if (is_object($author) && isset($author->uid) && isset($author->name)) {
386 $query['author'][] = $author->name;
387 }
388 elseif ($author_obj = user_load($author)) {
389 $query['author'][] = $author_obj->name;
390 }
391 }
392 if (isset($query['author'])) {
393 $query['author'] = implode(' ', $query['author']);
394 }
395 }
396
397 if (isset($filter['search']) && !empty($filter['search'])) {
398 $query['search'] = $filter['search'];
399 }
400 return $query;
401}
402
403/**
404 * Implementation of hook_privatemsg_list_messages_alter().
405 */
406function privatemsg_filter_privatemsg_list_messages_alter(&$content, $account) {
407 if (!empty($content['list']['content']) || privatemsg_filter_get_filter($account)) {
408 $content['tags']['content'] = drupal_get_form('privatemsg_filter_dropdown', $account);
409 $content['tags']['#weight'] = -5;
410 }
411}
412
413
414/**
415 * Hook into the query builder to add the tagging info to the correct query
416 */
93a1235e 417function privatemsg_filter_privatemsg_sql_list_alter(&$fragments, $account) {
67189554 418 // Filter the message listing by any set tags.
93a1235e 419 if ($filter = privatemsg_filter_get_filter($account)) {
67189554
TGGM
420
421 if (isset($filter['tags']) && !empty($filter['tags'])) {
422 $count = 0;
423 foreach ($filter['tags'] as $tag) {
424 $fragments['inner_join'][] = "INNER JOIN {pm_tags_index} pmti$count ON (pmti$count.thread_id = pmi.thread_id AND pmti$count.uid = pmi.uid)";
425 $fragments['where'][] = "pmti$count.tag_id = %d";
426 $fragments['query_args'][] = $tag;
427 $count++;
428 }
429 }
430
431 if (isset($filter['author']) && !empty($filter['author'])) {
432 $count = 0;
433 foreach ($filter['author'] as $author) {
e107e0a7 434 $fragments['inner_join'][] = "INNER JOIN {users} u$count ON (u$count.uid = pm.author)";
67189554
TGGM
435 $fragments['where'][] = "u$count.uid = %d";
436 $fragments['query_args'][] = $author;
437 $count++;
438 }
439 }
440
441 if (isset($filter['search']) && !empty($filter['search'])) {
e5fe4a8d
OT
442 if (variable_get('privatemsg_filter_searchbody', FALSE)) {
443 $fragments['where'][] = "pm.subject LIKE '%s' OR pm.body LIKE '%s'";
444 $fragments['query_args'][] = '%%'. $filter['search'] .'%%';
445 $fragments['query_args'][] = '%%'. $filter['search'] .'%%';
446 }
447 else {
448 $fragments['where'][] = "pm.subject LIKE '%s'";
449 $fragments['query_args'][] = '%%'. $filter['search'] .'%%';
450 }
67189554
TGGM
451 }
452 }
453}
454
455function privatemsg_filter_privatemsg_view_messages_alter(&$content, $count) {
456 if ($count > 0) {
457 $content['tags']['content'] = drupal_get_form('privatemsg_filter_form');
458 $content['tags']['#weight'] = 10;
459 }
460}
461
462function privatemsg_filter_form(&$form_state) {
463 global $user;
464 $thread_id = arg(2);
465
466 $form['tags'] = array(
467 '#type' => 'fieldset',
468 '#title' => t('Tags'),
469 '#collapsible' => TRUE,
470 '#collapsed' => TRUE,
471 );
472 $form['tags']['user_id'] = array(
473 '#type' => 'value',
474 '#value' => $user->uid,
475 );
476 $form['tags']['thread_id'] = array(
477 '#type' => 'value',
478 '#value' => $thread_id,
479 );
480
481 $sql = 'SELECT * FROM {pm_tags}';
482 $query = db_query($sql);
483 $tag_array = array();
484
485 while ($result = db_fetch_object($query)) {
486 $checked = 0;
487 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))) {
488 $checked = 1;
489 }
490 $form_data = array('#type' => 'checkbox', '#title' => $result->tag, '#default_value' => $checked, '#return_value' => 1);
491 $form['tags']['tag_'. $result->tag_id] = $form_data;
492 }
493
494 $form['tags']['submit'] = array(
495 '#type' => 'submit',
496 '#value' => t('Tag this message'),
497 '#submit' => array('privatemsg_filter_form_submit'),
498 );
499
500 return $form;
501}
502
503function privatemsg_filter_form_submit($form, &$form_state) {
504 if (isset($form_state['values']['submit'])) {
505 $sql = 'SELECT * FROM {pm_tags}';
506 $query = db_query($sql);
507
508 while ($result = db_fetch_object($query)) {
509 if ($form_state['values']['tag_'. $result->tag_id] == 0) {
510 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']);
511 }
512 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) {
513 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']);
514 }
515 }
516 drupal_set_message(t('Tagging information has been saved.'));
517 }
d60dd59c 518}