1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file handles tasks related to personal messages. It performs all |
5
|
|
|
* the necessary (database updates, statistics updates) to add, delete, mark |
6
|
|
|
* etc personal messages. |
7
|
|
|
* |
8
|
|
|
* The functions in this file do NOT check permissions. |
9
|
|
|
* |
10
|
|
|
* @name ElkArte Forum |
11
|
|
|
* @copyright ElkArte Forum contributors |
12
|
|
|
* @license BSD http://opensource.org/licenses/BSD-3-Clause |
13
|
|
|
* |
14
|
|
|
* This file contains code covered by: |
15
|
|
|
* copyright: 2011 Simple Machines (http://www.simplemachines.org) |
16
|
|
|
* license: BSD, See included LICENSE.TXT for terms and conditions. |
17
|
|
|
* |
18
|
|
|
* @version 1.1.4 |
19
|
|
|
* |
20
|
|
|
*/ |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Loads information about the users personal message limit. |
24
|
|
|
* |
25
|
|
|
* @package PersonalMessage |
26
|
|
|
*/ |
27
|
|
|
function loadMessageLimit() |
28
|
|
|
{ |
29
|
|
|
global $user_info; |
30
|
|
|
|
31
|
|
|
$db = database(); |
32
|
|
|
|
33
|
|
|
$message_limit = 0; |
34
|
|
|
if ($user_info['is_admin']) |
35
|
|
|
$message_limit = 0; |
36
|
|
|
elseif (!Cache::instance()->getVar($message_limit, 'msgLimit:' . $user_info['id'], 360)) |
37
|
|
|
{ |
38
|
|
|
$request = $db->query('', ' |
39
|
|
|
SELECT |
40
|
|
|
MAX(max_messages) AS top_limit, MIN(max_messages) AS bottom_limit |
41
|
|
|
FROM {db_prefix}membergroups |
42
|
|
|
WHERE id_group IN ({array_int:users_groups})', |
43
|
|
|
array( |
44
|
|
|
'users_groups' => $user_info['groups'], |
45
|
|
|
) |
46
|
|
|
); |
47
|
|
|
list ($maxMessage, $minMessage) = $db->fetch_row($request); |
48
|
|
|
$db->free_result($request); |
49
|
|
|
|
50
|
|
|
$message_limit = $minMessage == 0 ? 0 : $maxMessage; |
51
|
|
|
|
52
|
|
|
// Save us doing it again! |
53
|
|
|
Cache::instance()->put('msgLimit:' . $user_info['id'], $message_limit, 360); |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
return $message_limit; |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Loads the count of messages on a per label basis. |
61
|
|
|
* |
62
|
|
|
* @param $labels mixed[] array of labels that we are calculating the message count |
63
|
|
|
* @package PersonalMessage |
64
|
|
|
*/ |
65
|
|
|
function loadPMLabels($labels) |
66
|
|
|
{ |
67
|
|
|
global $user_info; |
68
|
|
|
|
69
|
|
|
$db = database(); |
70
|
|
|
|
71
|
|
|
// Looks like we need to reseek! |
72
|
|
|
$result = $db->query('', ' |
73
|
|
|
SELECT |
74
|
|
|
labels, is_read, COUNT(*) AS num |
75
|
|
|
FROM {db_prefix}pm_recipients |
76
|
|
|
WHERE id_member = {int:current_member} |
77
|
|
|
AND deleted = {int:not_deleted} |
78
|
|
|
GROUP BY labels, is_read', |
79
|
|
|
array( |
80
|
|
|
'current_member' => $user_info['id'], |
81
|
|
|
'not_deleted' => 0, |
82
|
|
|
) |
83
|
|
|
); |
84
|
|
View Code Duplication |
while ($row = $db->fetch_assoc($result)) |
85
|
|
|
{ |
86
|
|
|
$this_labels = explode(',', $row['labels']); |
87
|
|
|
foreach ($this_labels as $this_label) |
88
|
|
|
{ |
89
|
|
|
$labels[(int) $this_label]['messages'] += $row['num']; |
90
|
|
|
|
91
|
|
|
if (!($row['is_read'] & 1)) |
92
|
|
|
{ |
93
|
|
|
$labels[(int) $this_label]['unread_messages'] += $row['num']; |
94
|
|
|
} |
95
|
|
|
} |
96
|
|
|
} |
97
|
|
|
$db->free_result($result); |
98
|
|
|
|
99
|
|
|
// Store it please! |
100
|
|
|
Cache::instance()->put('labelCounts:' . $user_info['id'], $labels, 720); |
101
|
|
|
|
102
|
|
|
return $labels; |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* Get the number of PMs. |
107
|
|
|
* |
108
|
|
|
* @package PersonalMessage |
109
|
|
|
* @param bool $descending |
110
|
|
|
* @param int|null $pmID |
111
|
|
|
* @param string $labelQuery |
112
|
|
|
* @return int |
113
|
|
|
*/ |
114
|
|
|
function getPMCount($descending = false, $pmID = null, $labelQuery = '') |
115
|
|
|
{ |
116
|
|
|
global $user_info, $context; |
117
|
|
|
|
118
|
|
|
$db = database(); |
119
|
|
|
|
120
|
|
|
// Figure out how many messages there are. |
121
|
|
|
if ($context['folder'] == 'sent') |
122
|
|
|
{ |
123
|
|
|
$request = $db->query('', ' |
124
|
|
|
SELECT |
125
|
|
|
COUNT(' . ($context['display_mode'] == 2 ? 'DISTINCT id_pm_head' : '*') . ') |
126
|
|
|
FROM {db_prefix}personal_messages |
127
|
|
|
WHERE id_member_from = {int:current_member} |
128
|
|
|
AND deleted_by_sender = {int:not_deleted}' . ($pmID !== null ? ' |
129
|
|
|
AND id_pm ' . ($descending ? '>' : '<') . ' {int:id_pm}' : ''), |
130
|
|
|
array( |
131
|
|
|
'current_member' => $user_info['id'], |
132
|
|
|
'not_deleted' => 0, |
133
|
|
|
'id_pm' => $pmID, |
134
|
|
|
) |
135
|
|
|
); |
136
|
|
|
} |
137
|
|
|
else |
138
|
|
|
{ |
139
|
|
|
$request = $db->query('', ' |
140
|
|
|
SELECT |
141
|
|
|
COUNT(' . ($context['display_mode'] == 2 ? 'DISTINCT pm.id_pm_head' : '*') . ') |
142
|
|
|
FROM {db_prefix}pm_recipients AS pmr' . ($context['display_mode'] == 2 ? ' |
143
|
|
|
INNER JOIN {db_prefix}personal_messages AS pm ON (pm.id_pm = pmr.id_pm)' : '') . ' |
144
|
|
|
WHERE pmr.id_member = {int:current_member} |
145
|
|
|
AND pmr.deleted = {int:not_deleted}' . $labelQuery . ($pmID !== null ? ' |
146
|
|
|
AND pmr.id_pm ' . ($descending ? '>' : '<') . ' {int:id_pm}' : ''), |
147
|
|
|
array( |
148
|
|
|
'current_member' => $user_info['id'], |
149
|
|
|
'not_deleted' => 0, |
150
|
|
|
'id_pm' => $pmID, |
151
|
|
|
) |
152
|
|
|
); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
list ($count) = $db->fetch_row($request); |
156
|
|
|
$db->free_result($request); |
157
|
|
|
|
158
|
|
|
return $count; |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* Delete the specified personal messages. |
163
|
|
|
* |
164
|
|
|
* @package PersonalMessage |
165
|
|
|
* @param int[]|null $personal_messages array of pm ids |
166
|
|
|
* @param string|null $folder = null |
167
|
|
|
* @param int|int[]|null $owner = null |
168
|
|
|
*/ |
169
|
|
|
function deleteMessages($personal_messages, $folder = null, $owner = null) |
170
|
|
|
{ |
171
|
|
|
global $user_info; |
172
|
|
|
|
173
|
|
|
$db = database(); |
174
|
|
|
|
175
|
|
|
if ($owner === null) |
176
|
|
|
$owner = array($user_info['id']); |
177
|
|
|
elseif (empty($owner)) |
178
|
|
|
return; |
179
|
|
|
elseif (!is_array($owner)) |
180
|
|
|
$owner = array($owner); |
181
|
|
|
|
182
|
|
|
if ($personal_messages !== null) |
183
|
|
|
{ |
184
|
|
|
if (empty($personal_messages) || !is_array($personal_messages)) |
185
|
|
|
return; |
186
|
|
|
|
187
|
|
|
foreach ($personal_messages as $index => $delete_id) |
188
|
|
|
$personal_messages[$index] = (int) $delete_id; |
189
|
|
|
|
190
|
|
|
$where = ' |
191
|
|
|
AND id_pm IN ({array_int:pm_list})'; |
192
|
|
|
} |
193
|
|
|
else |
194
|
|
|
$where = ''; |
195
|
|
|
|
196
|
|
|
if ($folder == 'sent' || $folder === null) |
197
|
|
|
{ |
198
|
|
|
$db->query('', ' |
199
|
|
|
UPDATE {db_prefix}personal_messages |
200
|
|
|
SET deleted_by_sender = {int:is_deleted} |
201
|
|
|
WHERE id_member_from IN ({array_int:member_list}) |
202
|
|
|
AND deleted_by_sender = {int:not_deleted}' . $where, |
203
|
|
|
array( |
204
|
|
|
'member_list' => $owner, |
205
|
|
|
'is_deleted' => 1, |
206
|
|
|
'not_deleted' => 0, |
207
|
|
|
'pm_list' => $personal_messages !== null ? array_unique($personal_messages) : array(), |
208
|
|
|
) |
209
|
|
|
); |
210
|
|
|
} |
211
|
|
|
if ($folder != 'sent' || $folder === null) |
212
|
|
|
{ |
213
|
|
|
// Calculate the number of messages each member's gonna lose... |
214
|
|
|
$request = $db->query('', ' |
215
|
|
|
SELECT |
216
|
|
|
id_member, COUNT(*) AS num_deleted_messages, CASE WHEN is_read & 1 >= 1 THEN 1 ELSE 0 END AS is_read |
217
|
|
|
FROM {db_prefix}pm_recipients |
218
|
|
|
WHERE id_member IN ({array_int:member_list}) |
219
|
|
|
AND deleted = {int:not_deleted}' . $where . ' |
220
|
|
|
GROUP BY id_member, is_read', |
221
|
|
|
array( |
222
|
|
|
'member_list' => $owner, |
223
|
|
|
'not_deleted' => 0, |
224
|
|
|
'pm_list' => $personal_messages !== null ? array_unique($personal_messages) : array(), |
225
|
|
|
) |
226
|
|
|
); |
227
|
|
|
require_once(SUBSDIR . '/Members.subs.php'); |
228
|
|
|
// ...And update the statistics accordingly - now including unread messages!. |
229
|
|
|
while ($row = $db->fetch_assoc($request)) |
230
|
|
|
{ |
231
|
|
|
if ($row['is_read']) |
232
|
|
|
updateMemberData($row['id_member'], array('personal_messages' => $where == '' ? 0 : 'personal_messages - ' . $row['num_deleted_messages'])); |
233
|
|
|
else |
234
|
|
|
updateMemberData($row['id_member'], array('personal_messages' => $where == '' ? 0 : 'personal_messages - ' . $row['num_deleted_messages'], 'unread_messages' => $where == '' ? 0 : 'unread_messages - ' . $row['num_deleted_messages'])); |
235
|
|
|
|
236
|
|
|
// If this is the current member we need to make their message count correct. |
237
|
|
|
if ($user_info['id'] == $row['id_member']) |
238
|
|
|
{ |
239
|
|
|
$user_info['messages'] -= $row['num_deleted_messages']; |
240
|
|
|
if (!($row['is_read'])) |
241
|
|
|
$user_info['unread_messages'] -= $row['num_deleted_messages']; |
242
|
|
|
} |
243
|
|
|
} |
244
|
|
|
$db->free_result($request); |
245
|
|
|
|
246
|
|
|
// Do the actual deletion. |
247
|
|
|
$db->query('', ' |
248
|
|
|
UPDATE {db_prefix}pm_recipients |
249
|
|
|
SET deleted = {int:is_deleted} |
250
|
|
|
WHERE id_member IN ({array_int:member_list}) |
251
|
|
|
AND deleted = {int:not_deleted}' . $where, |
252
|
|
|
array( |
253
|
|
|
'member_list' => $owner, |
254
|
|
|
'is_deleted' => 1, |
255
|
|
|
'not_deleted' => 0, |
256
|
|
|
'pm_list' => $personal_messages !== null ? array_unique($personal_messages) : array(), |
257
|
|
|
) |
258
|
|
|
); |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
// If sender and recipients all have deleted their message, it can be removed. |
262
|
|
|
$request = $db->query('', ' |
263
|
|
|
SELECT |
264
|
|
|
pm.id_pm AS sender, pmr.id_pm |
265
|
|
|
FROM {db_prefix}personal_messages AS pm |
266
|
|
|
LEFT JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm AND pmr.deleted = {int:not_deleted}) |
267
|
|
|
WHERE pm.deleted_by_sender = {int:is_deleted} |
268
|
|
|
' . str_replace('id_pm', 'pm.id_pm', $where) . ' |
269
|
|
|
GROUP BY sender, pmr.id_pm |
270
|
|
|
HAVING pmr.id_pm IS null', |
271
|
|
|
array( |
272
|
|
|
'not_deleted' => 0, |
273
|
|
|
'is_deleted' => 1, |
274
|
|
|
'pm_list' => $personal_messages !== null ? array_unique($personal_messages) : array(), |
275
|
|
|
) |
276
|
|
|
); |
277
|
|
|
$remove_pms = array(); |
278
|
|
|
while ($row = $db->fetch_assoc($request)) |
279
|
|
|
$remove_pms[] = $row['sender']; |
280
|
|
|
$db->free_result($request); |
281
|
|
|
|
282
|
|
|
if (!empty($remove_pms)) |
283
|
|
|
{ |
284
|
|
|
$db->query('', ' |
285
|
|
|
DELETE FROM {db_prefix}personal_messages |
286
|
|
|
WHERE id_pm IN ({array_int:pm_list})', |
287
|
|
|
array( |
288
|
|
|
'pm_list' => $remove_pms, |
289
|
|
|
) |
290
|
|
|
); |
291
|
|
|
|
292
|
|
|
$db->query('', ' |
293
|
|
|
DELETE FROM {db_prefix}pm_recipients |
294
|
|
|
WHERE id_pm IN ({array_int:pm_list})', |
295
|
|
|
array( |
296
|
|
|
'pm_list' => $remove_pms, |
297
|
|
|
) |
298
|
|
|
); |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
// Any cached numbers may be wrong now. |
302
|
|
|
Cache::instance()->put('labelCounts:' . $user_info['id'], null, 720); |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
/** |
306
|
|
|
* Mark the specified personal messages read. |
307
|
|
|
* |
308
|
|
|
* @package PersonalMessage |
309
|
|
|
* @param int[]|int|null $personal_messages null or array of pm ids |
310
|
|
|
* @param string|null $label = null, if label is set, only marks messages with that label |
311
|
|
|
* @param int|null $owner = null, if owner is set, marks messages owned by that member id |
312
|
|
|
*/ |
313
|
|
|
function markMessages($personal_messages = null, $label = null, $owner = null) |
314
|
|
|
{ |
315
|
|
|
global $user_info; |
316
|
|
|
|
317
|
|
|
$db = database(); |
318
|
|
|
|
319
|
|
|
if ($owner === null) |
320
|
|
|
$owner = $user_info['id']; |
321
|
|
|
|
322
|
|
|
if (!is_null($personal_messages) && !is_array($personal_messages)) |
323
|
|
|
$personal_messages = array($personal_messages); |
324
|
|
|
|
325
|
|
|
$db->query('', ' |
326
|
|
|
UPDATE {db_prefix}pm_recipients |
327
|
|
|
SET is_read = is_read | 1 |
328
|
|
|
WHERE id_member = {int:id_member} |
329
|
|
|
AND NOT (is_read & 1 >= 1)' . ($label === null ? '' : ' |
330
|
|
|
AND FIND_IN_SET({string:label}, labels) != 0') . ($personal_messages !== null ? ' |
331
|
|
|
AND id_pm IN ({array_int:personal_messages})' : ''), |
332
|
|
|
array( |
333
|
|
|
'personal_messages' => $personal_messages, |
334
|
|
|
'id_member' => $owner, |
335
|
|
|
'label' => $label, |
336
|
|
|
) |
337
|
|
|
); |
338
|
|
|
|
339
|
|
|
// If something wasn't marked as read, get the number of unread messages remaining. |
340
|
|
|
if ($db->affected_rows() > 0) |
341
|
|
|
updatePMMenuCounts($owner); |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
/** |
345
|
|
|
* Mark the specified personal messages as unread. |
346
|
|
|
* |
347
|
|
|
* @package PersonalMessage |
348
|
|
|
* @param int|int[] $personal_messages |
349
|
|
|
*/ |
350
|
|
|
function markMessagesUnread($personal_messages) |
351
|
|
|
{ |
352
|
|
|
global $user_info; |
353
|
|
|
|
354
|
|
|
$db = database(); |
355
|
|
|
|
356
|
|
|
if (empty($personal_messages)) |
357
|
|
|
return; |
358
|
|
|
|
359
|
|
|
if (!is_array($personal_messages)) |
360
|
|
|
$personal_messages = array($personal_messages); |
361
|
|
|
|
362
|
|
|
$owner = $user_info['id']; |
363
|
|
|
|
364
|
|
|
// Flip the "read" bit on this |
365
|
|
|
$db->query('', ' |
366
|
|
|
UPDATE {db_prefix}pm_recipients |
367
|
|
|
SET is_read = is_read & 2 |
368
|
|
|
WHERE id_member = {int:id_member} |
369
|
|
|
AND (is_read & 1 >= 1) |
370
|
|
|
AND id_pm IN ({array_int:personal_messages})', |
371
|
|
|
array( |
372
|
|
|
'personal_messages' => $personal_messages, |
373
|
|
|
'id_member' => $owner, |
374
|
|
|
) |
375
|
|
|
); |
376
|
|
|
|
377
|
|
|
// If something was marked unread, update the number of unread messages remaining. |
378
|
|
|
if ($db->affected_rows() > 0) |
379
|
|
|
updatePMMenuCounts($owner); |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
/** |
383
|
|
|
* Updates the number of unread messages for a user |
384
|
|
|
* |
385
|
|
|
* - Updates the per label totals as well as the overall total |
386
|
|
|
* |
387
|
|
|
* @package PersonalMessage |
388
|
|
|
* @param int $owner |
389
|
|
|
*/ |
390
|
|
|
function updatePMMenuCounts($owner) |
391
|
|
|
{ |
392
|
|
|
global $user_info, $context; |
393
|
|
|
|
394
|
|
|
$db = database(); |
395
|
|
|
|
396
|
|
|
if ($owner == $user_info['id']) |
397
|
|
|
{ |
398
|
|
|
foreach ($context['labels'] as $label) |
399
|
|
|
$context['labels'][(int) $label['id']]['unread_messages'] = 0; |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
$result = $db->query('', ' |
403
|
|
|
SELECT |
404
|
|
|
labels, COUNT(*) AS num |
405
|
|
|
FROM {db_prefix}pm_recipients |
406
|
|
|
WHERE id_member = {int:id_member} |
407
|
|
|
AND NOT (is_read & 1 >= 1) |
408
|
|
|
AND deleted = {int:is_not_deleted} |
409
|
|
|
GROUP BY labels', |
410
|
|
|
array( |
411
|
|
|
'id_member' => $owner, |
412
|
|
|
'is_not_deleted' => 0, |
413
|
|
|
) |
414
|
|
|
); |
415
|
|
|
$total_unread = 0; |
416
|
|
View Code Duplication |
while ($row = $db->fetch_assoc($result)) |
417
|
|
|
{ |
418
|
|
|
$total_unread += $row['num']; |
419
|
|
|
|
420
|
|
|
if ($owner != $user_info['id']) |
421
|
|
|
continue; |
422
|
|
|
|
423
|
|
|
$this_labels = explode(',', $row['labels']); |
424
|
|
|
foreach ($this_labels as $this_label) |
425
|
|
|
$context['labels'][(int) $this_label]['unread_messages'] += $row['num']; |
426
|
|
|
} |
427
|
|
|
$db->free_result($result); |
428
|
|
|
|
429
|
|
|
// Need to store all this. |
430
|
|
|
Cache::instance()->put('labelCounts:' . $owner, $context['labels'], 720); |
431
|
|
|
require_once(SUBSDIR . '/Members.subs.php'); |
432
|
|
|
updateMemberData($owner, array('unread_messages' => $total_unread)); |
433
|
|
|
|
434
|
|
|
// If it was for the current member, reflect this in the $user_info array too. |
435
|
|
|
if ($owner == $user_info['id']) |
436
|
|
|
$user_info['unread_messages'] = $total_unread; |
437
|
|
|
} |
438
|
|
|
|
439
|
|
|
/** |
440
|
|
|
* Check if the PM is available to the current user. |
441
|
|
|
* |
442
|
|
|
* @package PersonalMessage |
443
|
|
|
* @param int $pmID |
444
|
|
|
* @param string $validFor |
445
|
|
|
* @return boolean|null |
446
|
|
|
*/ |
447
|
|
|
function isAccessiblePM($pmID, $validFor = 'in_or_outbox') |
448
|
|
|
{ |
449
|
|
|
global $user_info; |
450
|
|
|
|
451
|
|
|
$db = database(); |
452
|
|
|
|
453
|
|
|
$request = $db->query('', ' |
454
|
|
|
SELECT |
455
|
|
|
pm.id_member_from = {int:id_current_member} AND pm.deleted_by_sender = {int:not_deleted} AS valid_for_outbox, |
456
|
|
|
pmr.id_pm IS NOT NULL AS valid_for_inbox |
457
|
|
|
FROM {db_prefix}personal_messages AS pm |
458
|
|
|
LEFT JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm AND pmr.id_member = {int:id_current_member} AND pmr.deleted = {int:not_deleted}) |
459
|
|
|
WHERE pm.id_pm = {int:id_pm} |
460
|
|
|
AND ((pm.id_member_from = {int:id_current_member} AND pm.deleted_by_sender = {int:not_deleted}) OR pmr.id_pm IS NOT NULL)', |
461
|
|
|
array( |
462
|
|
|
'id_pm' => $pmID, |
463
|
|
|
'id_current_member' => $user_info['id'], |
464
|
|
|
'not_deleted' => 0, |
465
|
|
|
) |
466
|
|
|
); |
467
|
|
|
if ($db->num_rows($request) === 0) |
468
|
|
|
{ |
469
|
|
|
$db->free_result($request); |
470
|
|
|
return false; |
471
|
|
|
} |
472
|
|
|
$validationResult = $db->fetch_assoc($request); |
473
|
|
|
$db->free_result($request); |
474
|
|
|
|
475
|
|
|
switch ($validFor) |
476
|
|
|
{ |
477
|
|
|
case 'inbox': |
478
|
|
|
return !empty($validationResult['valid_for_inbox']); |
479
|
|
|
|
480
|
|
|
case 'outbox': |
481
|
|
|
return !empty($validationResult['valid_for_outbox']); |
482
|
|
|
|
483
|
|
|
case 'in_or_outbox': |
484
|
|
|
return !empty($validationResult['valid_for_inbox']) || !empty($validationResult['valid_for_outbox']); |
485
|
|
|
|
486
|
|
|
default: |
487
|
|
|
trigger_error('Undefined validation type given', E_USER_ERROR); |
488
|
|
|
} |
489
|
|
|
} |
490
|
|
|
|
491
|
|
|
/** |
492
|
|
|
* Sends a personal message from the specified person to the specified people |
493
|
|
|
* ($from defaults to the user) |
494
|
|
|
* |
495
|
|
|
* @package PersonalMessage |
496
|
|
|
* @param mixed[] $recipients - an array containing the arrays 'to' and 'bcc', both containing id_member's. |
497
|
|
|
* @param string $subject - should have no slashes and no html entities |
498
|
|
|
* @param string $message - should have no slashes and no html entities |
499
|
|
|
* @param bool $store_outbox |
500
|
|
|
* @param mixed[]|null $from - an array with the id, name, and username of the member. |
501
|
|
|
* @param int $pm_head - the ID of the chain being replied to - if any. |
502
|
|
|
* @return mixed[] an array with log entries telling how many recipients were successful and which recipients it failed to send to. |
503
|
|
|
* @throws Elk_Exception |
504
|
|
|
*/ |
505
|
|
|
function sendpm($recipients, $subject, $message, $store_outbox = true, $from = null, $pm_head = 0) |
506
|
|
|
{ |
507
|
|
|
global $scripturl, $txt, $user_info, $language, $modSettings, $webmaster_email; |
508
|
|
|
|
509
|
|
|
$db = database(); |
510
|
|
|
|
511
|
|
|
// Make sure the PM language file is loaded, we might need something out of it. |
512
|
|
|
loadLanguage('PersonalMessage'); |
513
|
|
|
|
514
|
|
|
// Needed for our email and post functions |
515
|
|
|
require_once(SUBSDIR . '/Mail.subs.php'); |
516
|
|
|
require_once(SUBSDIR . '/Post.subs.php'); |
517
|
|
|
|
518
|
|
|
// Initialize log array. |
519
|
|
|
$log = array( |
520
|
|
|
'failed' => array(), |
521
|
|
|
'sent' => array() |
522
|
|
|
); |
523
|
|
|
|
524
|
|
|
if ($from === null) |
525
|
|
|
$from = array( |
526
|
|
|
'id' => $user_info['id'], |
527
|
|
|
'name' => $user_info['name'], |
528
|
|
|
'username' => $user_info['username'] |
529
|
|
|
); |
530
|
|
|
// Probably not needed. /me something should be of the typer. |
531
|
|
|
else |
532
|
|
|
$user_info['name'] = $from['name']; |
533
|
|
|
|
534
|
|
|
// Integrated PMs |
535
|
|
|
call_integration_hook('integrate_personal_message', array(&$recipients, &$from, &$subject, &$message)); |
536
|
|
|
|
537
|
|
|
// This is the one that will go in their inbox. |
538
|
|
|
$htmlmessage = Util::htmlspecialchars($message, ENT_QUOTES, 'UTF-8', true); |
539
|
|
|
preparsecode($htmlmessage); |
540
|
|
|
$htmlsubject = strtr(Util::htmlspecialchars($subject), array("\r" => '', "\n" => '', "\t" => '')); |
541
|
|
|
if (Util::strlen($htmlsubject) > 100) |
542
|
|
|
$htmlsubject = Util::substr($htmlsubject, 0, 100); |
543
|
|
|
|
544
|
|
|
// Make sure is an array |
545
|
|
|
if (!is_array($recipients)) |
546
|
|
|
$recipients = array($recipients); |
547
|
|
|
|
548
|
|
|
// Get a list of usernames and convert them to IDs. |
549
|
|
|
$usernames = array(); |
550
|
|
|
foreach ($recipients as $rec_type => $rec) |
551
|
|
|
{ |
552
|
|
|
foreach ($rec as $id => $member) |
553
|
|
|
{ |
554
|
|
|
if (!is_numeric($recipients[$rec_type][$id])) |
555
|
|
|
{ |
556
|
|
|
$recipients[$rec_type][$id] = Util::strtolower(trim(preg_replace('/[<>&"\'=\\\]/', '', $recipients[$rec_type][$id]))); |
557
|
|
|
$usernames[$recipients[$rec_type][$id]] = 0; |
558
|
|
|
} |
559
|
|
|
} |
560
|
|
|
} |
561
|
|
|
|
562
|
|
|
if (!empty($usernames)) |
563
|
|
|
{ |
564
|
|
|
$request = $db->query('pm_find_username', ' |
565
|
|
|
SELECT |
566
|
|
|
id_member, member_name |
567
|
|
|
FROM {db_prefix}members |
568
|
|
|
WHERE ' . (defined('DB_CASE_SENSITIVE') ? 'LOWER(member_name)' : 'member_name') . ' IN ({array_string:usernames})', |
569
|
|
|
array( |
570
|
|
|
'usernames' => array_keys($usernames), |
571
|
|
|
) |
572
|
|
|
); |
573
|
|
|
while ($row = $db->fetch_assoc($request)) |
574
|
|
|
if (isset($usernames[Util::strtolower($row['member_name'])])) |
575
|
|
|
$usernames[Util::strtolower($row['member_name'])] = $row['id_member']; |
576
|
|
|
$db->free_result($request); |
577
|
|
|
|
578
|
|
|
// Replace the usernames with IDs. Drop usernames that couldn't be found. |
579
|
|
|
foreach ($recipients as $rec_type => $rec) |
580
|
|
|
{ |
581
|
|
|
foreach ($rec as $id => $member) |
582
|
|
|
{ |
583
|
|
|
if (is_numeric($recipients[$rec_type][$id])) |
584
|
|
|
continue; |
585
|
|
|
|
586
|
|
|
if (!empty($usernames[$member])) |
587
|
|
|
$recipients[$rec_type][$id] = $usernames[$member]; |
588
|
|
|
else |
589
|
|
|
{ |
590
|
|
|
$log['failed'][$id] = sprintf($txt['pm_error_user_not_found'], $recipients[$rec_type][$id]); |
591
|
|
|
unset($recipients[$rec_type][$id]); |
592
|
|
|
} |
593
|
|
|
} |
594
|
|
|
} |
595
|
|
|
} |
596
|
|
|
|
597
|
|
|
// Make sure there are no duplicate 'to' members. |
598
|
|
|
$recipients['to'] = array_unique($recipients['to']); |
599
|
|
|
|
600
|
|
|
// Only 'bcc' members that aren't already in 'to'. |
601
|
|
|
$recipients['bcc'] = array_diff(array_unique($recipients['bcc']), $recipients['to']); |
602
|
|
|
|
603
|
|
|
// Combine 'to' and 'bcc' recipients. |
604
|
|
|
$all_to = array_merge($recipients['to'], $recipients['bcc']); |
605
|
|
|
|
606
|
|
|
// Check no-one will want it deleted right away! |
607
|
|
|
$request = $db->query('', ' |
608
|
|
|
SELECT |
609
|
|
|
id_member, criteria, is_or |
610
|
|
|
FROM {db_prefix}pm_rules |
611
|
|
|
WHERE id_member IN ({array_int:to_members}) |
612
|
|
|
AND delete_pm = {int:delete_pm}', |
613
|
|
|
array( |
614
|
|
|
'to_members' => $all_to, |
615
|
|
|
'delete_pm' => 1, |
616
|
|
|
) |
617
|
|
|
); |
618
|
|
|
$deletes = array(); |
619
|
|
|
// Check whether we have to apply anything... |
620
|
|
|
while ($row = $db->fetch_assoc($request)) |
621
|
|
|
{ |
622
|
|
|
$criteria = Util::unserialize($row['criteria']); |
623
|
|
|
|
624
|
|
|
// Note we don't check the buddy status, cause deletion from buddy = madness! |
625
|
|
|
$delete = false; |
626
|
|
|
foreach ($criteria as $criterium) |
627
|
|
|
{ |
628
|
|
|
if (($criterium['t'] == 'mid' && $criterium['v'] == $from['id']) || ($criterium['t'] == 'gid' && in_array($criterium['v'], $user_info['groups'])) || ($criterium['t'] == 'sub' && strpos($subject, $criterium['v']) !== false) || ($criterium['t'] == 'msg' && strpos($message, $criterium['v']) !== false)) |
629
|
|
|
$delete = true; |
630
|
|
|
// If we're adding and one criteria don't match then we stop! |
631
|
|
|
elseif (!$row['is_or']) |
632
|
|
|
{ |
633
|
|
|
$delete = false; |
634
|
|
|
break; |
635
|
|
|
} |
636
|
|
|
} |
637
|
|
|
if ($delete) |
638
|
|
|
$deletes[$row['id_member']] = 1; |
639
|
|
|
} |
640
|
|
|
$db->free_result($request); |
641
|
|
|
|
642
|
|
|
// Load the membergroup message limits. |
643
|
|
|
static $message_limit_cache = array(); |
644
|
|
View Code Duplication |
if (!allowedTo('moderate_forum') && empty($message_limit_cache)) |
645
|
|
|
{ |
646
|
|
|
$request = $db->query('', ' |
647
|
|
|
SELECT |
648
|
|
|
id_group, max_messages |
649
|
|
|
FROM {db_prefix}membergroups', |
650
|
|
|
array( |
651
|
|
|
) |
652
|
|
|
); |
653
|
|
|
while ($row = $db->fetch_assoc($request)) |
654
|
|
|
$message_limit_cache[$row['id_group']] = $row['max_messages']; |
655
|
|
|
$db->free_result($request); |
656
|
|
|
} |
657
|
|
|
|
658
|
|
|
// Load the groups that are allowed to read PMs. |
659
|
|
|
// @todo move into a separate function on $permission. |
660
|
|
|
$allowed_groups = array(); |
661
|
|
|
$disallowed_groups = array(); |
662
|
|
|
$request = $db->query('', ' |
663
|
|
|
SELECT |
664
|
|
|
id_group, add_deny |
665
|
|
|
FROM {db_prefix}permissions |
666
|
|
|
WHERE permission = {string:read_permission}', |
667
|
|
|
array( |
668
|
|
|
'read_permission' => 'pm_read', |
669
|
|
|
) |
670
|
|
|
); |
671
|
|
|
|
672
|
|
|
while ($row = $db->fetch_assoc($request)) |
673
|
|
|
{ |
674
|
|
|
if (empty($row['add_deny'])) |
675
|
|
|
$disallowed_groups[] = $row['id_group']; |
676
|
|
|
else |
677
|
|
|
$allowed_groups[] = $row['id_group']; |
678
|
|
|
} |
679
|
|
|
|
680
|
|
|
$db->free_result($request); |
681
|
|
|
|
682
|
|
|
if (empty($modSettings['permission_enable_deny'])) |
683
|
|
|
$disallowed_groups = array(); |
684
|
|
|
|
685
|
|
|
$request = $db->query('', ' |
686
|
|
|
SELECT |
687
|
|
|
member_name, real_name, id_member, email_address, lngfile, |
688
|
|
|
pm_email_notify, personal_messages,' . (allowedTo('moderate_forum') ? ' 0' : ' |
689
|
|
|
(receive_from = {int:admins_only}' . (empty($modSettings['enable_buddylist']) ? '' : ' OR |
690
|
|
|
(receive_from = {int:buddies_only} AND FIND_IN_SET({string:from_id}, buddy_list) = 0) OR |
691
|
|
|
(receive_from = {int:not_on_ignore_list} AND FIND_IN_SET({string:from_id}, pm_ignore_list) != 0)') . ')') . ' AS ignored, |
692
|
|
|
FIND_IN_SET({string:from_id}, buddy_list) != 0 AS is_buddy, is_activated, |
693
|
|
|
additional_groups, id_group, id_post_group |
694
|
|
|
FROM {db_prefix}members |
695
|
|
|
WHERE id_member IN ({array_int:recipients}) |
696
|
|
|
ORDER BY lngfile |
697
|
|
|
LIMIT {int:count_recipients}', |
698
|
|
|
array( |
699
|
|
|
'not_on_ignore_list' => 1, |
700
|
|
|
'buddies_only' => 2, |
701
|
|
|
'admins_only' => 3, |
702
|
|
|
'recipients' => $all_to, |
703
|
|
|
'count_recipients' => count($all_to), |
704
|
|
|
'from_id' => $from['id'], |
705
|
|
|
) |
706
|
|
|
); |
707
|
|
|
$notifications = array(); |
708
|
|
|
while ($row = $db->fetch_assoc($request)) |
709
|
|
|
{ |
710
|
|
|
// Don't do anything for members to be deleted! |
711
|
|
|
if (isset($deletes[$row['id_member']])) |
712
|
|
|
continue; |
713
|
|
|
|
714
|
|
|
// We need to know this members groups. |
715
|
|
|
$groups = explode(',', $row['additional_groups']); |
716
|
|
|
$groups[] = $row['id_group']; |
717
|
|
|
$groups[] = $row['id_post_group']; |
718
|
|
|
|
719
|
|
|
$message_limit = -1; |
720
|
|
|
|
721
|
|
|
// For each group see whether they've gone over their limit - assuming they're not an admin. |
722
|
|
|
if (!in_array(1, $groups)) |
723
|
|
|
{ |
724
|
|
|
foreach ($groups as $id) |
725
|
|
|
{ |
726
|
|
|
if (isset($message_limit_cache[$id]) && $message_limit != 0 && $message_limit < $message_limit_cache[$id]) |
727
|
|
|
$message_limit = $message_limit_cache[$id]; |
728
|
|
|
} |
729
|
|
|
|
730
|
|
|
if ($message_limit > 0 && $message_limit <= $row['personal_messages']) |
731
|
|
|
{ |
732
|
|
|
$log['failed'][$row['id_member']] = sprintf($txt['pm_error_data_limit_reached'], $row['real_name']); |
733
|
|
|
unset($all_to[array_search($row['id_member'], $all_to)]); |
734
|
|
|
continue; |
735
|
|
|
} |
736
|
|
|
|
737
|
|
|
// Do they have any of the allowed groups? |
738
|
|
|
if (count(array_intersect($allowed_groups, $groups)) == 0 || count(array_intersect($disallowed_groups, $groups)) != 0) |
739
|
|
|
{ |
740
|
|
|
$log['failed'][$row['id_member']] = sprintf($txt['pm_error_user_cannot_read'], $row['real_name']); |
741
|
|
|
unset($all_to[array_search($row['id_member'], $all_to)]); |
742
|
|
|
continue; |
743
|
|
|
} |
744
|
|
|
} |
745
|
|
|
|
746
|
|
|
// Note that PostgreSQL can return a lowercase t/f for FIND_IN_SET |
747
|
|
|
if (!empty($row['ignored']) && $row['ignored'] != 'f' && $row['id_member'] != $from['id']) |
748
|
|
|
{ |
749
|
|
|
$log['failed'][$row['id_member']] = sprintf($txt['pm_error_ignored_by_user'], $row['real_name']); |
750
|
|
|
unset($all_to[array_search($row['id_member'], $all_to)]); |
751
|
|
|
continue; |
752
|
|
|
} |
753
|
|
|
|
754
|
|
|
// If the receiving account is banned (>=10) or pending deletion (4), refuse to send the PM. |
755
|
|
|
if ($row['is_activated'] >= 10 || ($row['is_activated'] == 4 && !$user_info['is_admin'])) |
756
|
|
|
{ |
757
|
|
|
$log['failed'][$row['id_member']] = sprintf($txt['pm_error_user_cannot_read'], $row['real_name']); |
758
|
|
|
unset($all_to[array_search($row['id_member'], $all_to)]); |
759
|
|
|
continue; |
760
|
|
|
} |
761
|
|
|
|
762
|
|
|
// Send a notification, if enabled - taking the buddy list into account. |
763
|
|
|
if (!empty($row['email_address']) && ($row['pm_email_notify'] == 1 || ($row['pm_email_notify'] > 1 && (!empty($modSettings['enable_buddylist']) && $row['is_buddy']))) && $row['is_activated'] == 1) |
764
|
|
|
$notifications[empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']][] = $row['email_address']; |
765
|
|
|
|
766
|
|
|
$log['sent'][$row['id_member']] = sprintf(isset($txt['pm_successfully_sent']) ? $txt['pm_successfully_sent'] : '', $row['real_name']); |
767
|
|
|
} |
768
|
|
|
$db->free_result($request); |
769
|
|
|
|
770
|
|
|
// Only 'send' the message if there are any recipients left. |
771
|
|
|
if (empty($all_to)) |
772
|
|
|
return $log; |
773
|
|
|
|
774
|
|
|
// Track the pm count for our stats |
775
|
|
|
if (!empty($modSettings['trackStats'])) |
776
|
|
|
trackStats(array('pm' => '+')); |
777
|
|
|
|
778
|
|
|
// Insert the message itself and then grab the last insert id. |
779
|
|
|
$db->insert('', |
780
|
|
|
'{db_prefix}personal_messages', |
781
|
|
|
array( |
782
|
|
|
'id_pm_head' => 'int', 'id_member_from' => 'int', 'deleted_by_sender' => 'int', |
783
|
|
|
'from_name' => 'string-255', 'msgtime' => 'int', 'subject' => 'string-255', 'body' => 'string-65534', |
784
|
|
|
), |
785
|
|
|
array( |
786
|
|
|
$pm_head, $from['id'], ($store_outbox ? 0 : 1), |
787
|
|
|
$from['username'], time(), $htmlsubject, $htmlmessage, |
788
|
|
|
), |
789
|
|
|
array('id_pm') |
790
|
|
|
); |
791
|
|
|
$id_pm = $db->insert_id('{db_prefix}personal_messages', 'id_pm'); |
792
|
|
|
|
793
|
|
|
// Add the recipients. |
794
|
|
|
$to_list = array(); |
795
|
|
|
if (!empty($id_pm)) |
796
|
|
|
{ |
797
|
|
|
// If this is new we need to set it part of it's own conversation. |
798
|
|
|
if (empty($pm_head)) |
799
|
|
|
$db->query('', ' |
800
|
|
|
UPDATE {db_prefix}personal_messages |
801
|
|
|
SET id_pm_head = {int:id_pm_head} |
802
|
|
|
WHERE id_pm = {int:id_pm_head}', |
803
|
|
|
array( |
804
|
|
|
'id_pm_head' => $id_pm, |
805
|
|
|
) |
806
|
|
|
); |
807
|
|
|
|
808
|
|
|
// Some people think manually deleting personal_messages is fun... it's not. We protect against it though :) |
809
|
|
|
$db->query('', ' |
810
|
|
|
DELETE FROM {db_prefix}pm_recipients |
811
|
|
|
WHERE id_pm = {int:id_pm}', |
812
|
|
|
array( |
813
|
|
|
'id_pm' => $id_pm, |
814
|
|
|
) |
815
|
|
|
); |
816
|
|
|
|
817
|
|
|
$insertRows = array(); |
818
|
|
|
foreach ($all_to as $to) |
819
|
|
|
{ |
820
|
|
|
$insertRows[] = array($id_pm, $to, in_array($to, $recipients['bcc']) ? 1 : 0, isset($deletes[$to]) ? 1 : 0, 1); |
821
|
|
|
if (!in_array($to, $recipients['bcc'])) |
822
|
|
|
$to_list[] = $to; |
823
|
|
|
} |
824
|
|
|
|
825
|
|
|
$db->insert('insert', |
826
|
|
|
'{db_prefix}pm_recipients', |
827
|
|
|
array( |
828
|
|
|
'id_pm' => 'int', 'id_member' => 'int', 'bcc' => 'int', 'deleted' => 'int', 'is_new' => 'int' |
829
|
|
|
), |
830
|
|
|
$insertRows, |
831
|
|
|
array('id_pm', 'id_member') |
832
|
|
|
); |
833
|
|
|
} |
834
|
|
|
|
835
|
|
|
$maillist = !empty($modSettings['maillist_enabled']) && !empty($modSettings['pbe_pm_enabled']); |
836
|
|
|
|
837
|
|
|
// If they have post by email enabled, override disallow_sendBody |
838
|
|
|
if (!$maillist && !empty($modSettings['disallow_sendBody'])) |
839
|
|
|
{ |
840
|
|
|
$message = ''; |
841
|
|
|
$subject = censor($subject); |
842
|
|
|
} |
843
|
|
|
else |
844
|
|
|
{ |
845
|
|
|
require_once(SUBSDIR . '/Emailpost.subs.php'); |
846
|
|
|
pbe_prepare_text($message, $subject); |
847
|
|
|
} |
848
|
|
|
|
849
|
|
|
$to_names = array(); |
850
|
|
|
if (count($to_list) > 1) |
851
|
|
|
{ |
852
|
|
|
require_once(SUBSDIR . '/Members.subs.php'); |
853
|
|
|
$result = getBasicMemberData($to_list); |
854
|
|
|
foreach ($result as $row) |
855
|
|
|
$to_names[] = un_htmlspecialchars($row['real_name']); |
856
|
|
|
} |
857
|
|
|
|
858
|
|
|
$replacements = array( |
859
|
|
|
'SUBJECT' => $subject, |
860
|
|
|
'MESSAGE' => $message, |
861
|
|
|
'SENDER' => un_htmlspecialchars($from['name']), |
862
|
|
|
'READLINK' => $scripturl . '?action=pm;pmsg=' . $id_pm . '#msg' . $id_pm, |
863
|
|
|
'REPLYLINK' => $scripturl . '?action=pm;sa=send;f=inbox;pmsg=' . $id_pm . ';quote;u=' . $from['id'], |
864
|
|
|
'TOLIST' => implode(', ', $to_names), |
865
|
|
|
); |
866
|
|
|
|
867
|
|
|
// Select the right template |
868
|
|
|
$email_template = ($maillist && empty($modSettings['disallow_sendBody']) ? 'pbe_' : '') . 'new_pm' . (empty($modSettings['disallow_sendBody']) ? '_body' : '') . (!empty($to_names) ? '_tolist' : ''); |
869
|
|
|
|
870
|
|
|
foreach ($notifications as $lang => $notification_list) |
871
|
|
|
{ |
872
|
|
|
// Using maillist functionality |
873
|
|
|
if ($maillist) |
874
|
|
|
{ |
875
|
|
|
$sender_details = query_sender_wrapper($from['id']); |
876
|
|
|
$from_wrapper = !empty($modSettings['maillist_mail_from']) ? $modSettings['maillist_mail_from'] : (empty($modSettings['maillist_sitename_address']) ? $webmaster_email : $modSettings['maillist_sitename_address']); |
877
|
|
|
|
878
|
|
|
// Add in the signature |
879
|
|
|
$replacements['SIGNATURE'] = $sender_details['signature']; |
880
|
|
|
|
881
|
|
|
// And off it goes, looking a bit more personal |
882
|
|
|
$mail = loadEmailTemplate($email_template, $replacements, $lang); |
883
|
|
|
$reference = !empty($pm_head) ? $pm_head : null; |
884
|
|
|
sendmail($notification_list, $mail['subject'], $mail['body'], $from['name'], 'p' . $id_pm, false, 2, null, true, $from_wrapper, $reference); |
885
|
|
|
} |
886
|
|
|
else |
887
|
|
|
{ |
888
|
|
|
// Off the notification email goes! |
889
|
|
|
$mail = loadEmailTemplate($email_template, $replacements, $lang); |
890
|
|
|
sendmail($notification_list, $mail['subject'], $mail['body'], null, 'p' . $id_pm, false, 2, null, true); |
891
|
|
|
} |
892
|
|
|
} |
893
|
|
|
|
894
|
|
|
// Integrated After PMs |
895
|
|
|
call_integration_hook('integrate_personal_message_after', array(&$id_pm, &$log, &$recipients, &$from, &$subject, &$message)); |
896
|
|
|
|
897
|
|
|
// Back to what we were on before! |
898
|
|
|
loadLanguage('index+PersonalMessage'); |
899
|
|
|
|
900
|
|
|
// Add one to their unread and read message counts. |
901
|
|
|
foreach ($all_to as $k => $id) |
902
|
|
|
{ |
903
|
|
|
if (isset($deletes[$id])) |
904
|
|
|
unset($all_to[$k]); |
905
|
|
|
} |
906
|
|
|
|
907
|
|
|
if (!empty($all_to)) |
908
|
|
|
{ |
909
|
|
|
require_once(SUBSDIR . '/Members.subs.php'); |
910
|
|
|
updateMemberData($all_to, array('personal_messages' => '+', 'unread_messages' => '+', 'new_pm' => 1)); |
911
|
|
|
} |
912
|
|
|
|
913
|
|
|
return $log; |
914
|
|
|
} |
915
|
|
|
|
916
|
|
|
/** |
917
|
|
|
* Load personal messages. |
918
|
|
|
* |
919
|
|
|
* This function loads messages considering the options given, an array of: |
920
|
|
|
* - 'display_mode' - the PMs display mode (i.e. conversation, all) |
921
|
|
|
* - 'is_postgres' - (temporary) boolean to allow choice of PostgreSQL-specific sorting query |
922
|
|
|
* - 'sort_by_query' - query to sort by |
923
|
|
|
* - 'descending' - whether to sort descending |
924
|
|
|
* - 'sort_by' - field to sort by |
925
|
|
|
* - 'pmgs' - personal message id (if any). Note: it may not be set. |
926
|
|
|
* - 'label_query' - query by labels |
927
|
|
|
* - 'start' - start id, if any |
928
|
|
|
* |
929
|
|
|
* @package PersonalMessage |
930
|
|
|
* @param mixed[] $pm_options options for loading |
931
|
|
|
* @param int $id_member id member |
932
|
|
|
*/ |
933
|
|
|
function loadPMs($pm_options, $id_member) |
934
|
|
|
{ |
935
|
|
|
global $options; |
936
|
|
|
|
937
|
|
|
$db = database(); |
938
|
|
|
|
939
|
|
|
// First work out what messages we need to see - if grouped is a little trickier... |
940
|
|
|
// Conversation mode |
941
|
|
|
if ($pm_options['display_mode'] == 2) |
942
|
|
|
{ |
943
|
|
|
// On a non-default sort, when using PostgreSQL we have to do a harder sort. |
944
|
|
|
if ($db->db_title() == 'PostgreSQL' && $pm_options['sort_by_query'] != 'pm.id_pm') |
945
|
|
|
{ |
946
|
|
|
$sub_request = $db->query('', ' |
947
|
|
|
SELECT |
948
|
|
|
MAX({raw:sort}) AS sort_param, pm.id_pm_head |
949
|
|
|
FROM {db_prefix}personal_messages AS pm' . ($pm_options['folder'] == 'sent' ? ($pm_options['sort_by'] == 'name' ? ' |
950
|
|
|
LEFT JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm)' : '') : ' |
951
|
|
|
INNER JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm |
952
|
|
|
AND pmr.id_member = {int:current_member} |
953
|
|
|
AND pmr.deleted = {int:not_deleted} |
954
|
|
|
' . $pm_options['label_query'] . ')') . ($pm_options['sort_by'] == 'name' ? (' |
955
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = {raw:id_member})') : '') . ' |
956
|
|
|
WHERE ' . ($pm_options['folder'] == 'sent' ? 'pm.id_member_from = {int:current_member} |
957
|
|
|
AND pm.deleted_by_sender = {int:not_deleted}' : '1=1') . (empty($pm_options['pmsg']) ? '' : ' |
958
|
|
|
AND pm.id_pm = {int:id_pm}') . ' |
959
|
|
|
GROUP BY pm.id_pm_head |
960
|
|
|
ORDER BY sort_param' . ($pm_options['descending'] ? ' DESC' : ' ASC') . (empty($pm_options['pmsg']) ? ' |
961
|
|
|
LIMIT ' . $pm_options['start'] . ', ' . $pm_options['limit'] : ''), |
962
|
|
|
array( |
963
|
|
|
'current_member' => $id_member, |
964
|
|
|
'not_deleted' => 0, |
965
|
|
|
'id_member' => $pm_options['folder'] == 'sent' ? 'pmr.id_member' : 'pm.id_member_from', |
966
|
|
|
'id_pm' => isset($pm_options['pmsg']) ? $pm_options['pmsg'] : '0', |
967
|
|
|
'sort' => $pm_options['sort_by_query'], |
968
|
|
|
) |
969
|
|
|
); |
970
|
|
|
$sub_pms = array(); |
971
|
|
|
while ($row = $db->fetch_assoc($sub_request)) |
972
|
|
|
$sub_pms[$row['id_pm_head']] = $row['sort_param']; |
973
|
|
|
$db->free_result($sub_request); |
974
|
|
|
|
975
|
|
|
// Now we use those results in the next query |
976
|
|
|
$request = $db->query('', ' |
977
|
|
|
SELECT |
978
|
|
|
pm.id_pm AS id_pm, pm.id_pm_head |
979
|
|
|
FROM {db_prefix}personal_messages AS pm' . ($pm_options['folder'] == 'sent' ? ($pm_options['sort_by'] == 'name' ? ' |
980
|
|
|
LEFT JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm)' : '') : ' |
981
|
|
|
INNER JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm |
982
|
|
|
AND pmr.id_member = {int:current_member} |
983
|
|
|
AND pmr.deleted = {int:not_deleted} |
984
|
|
|
' . $pm_options['label_query'] . ')') . ($pm_options['sort_by'] == 'name' ? (' |
985
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = {raw:id_member})') : '') . ' |
986
|
|
|
WHERE ' . (empty($sub_pms) ? '0=1' : 'pm.id_pm IN ({array_int:pm_list})') . ' |
987
|
|
|
ORDER BY ' . ($pm_options['sort_by_query'] == 'pm.id_pm' && $pm_options['folder'] != 'sent' ? 'id_pm' : '{raw:sort}') . ($pm_options['descending'] ? ' DESC' : ' ASC') . (empty($pm_options['pmsg']) ? ' |
988
|
|
|
LIMIT ' . $pm_options['start'] . ', ' . $pm_options['limit'] : ''), |
989
|
|
|
array( |
990
|
|
|
'current_member' => $id_member, |
991
|
|
|
'pm_list' => array_keys($sub_pms), |
992
|
|
|
'not_deleted' => 0, |
993
|
|
|
'sort' => $pm_options['sort_by_query'], |
994
|
|
|
'id_member' => $pm_options['folder'] == 'sent' ? 'pmr.id_member' : 'pm.id_member_from', |
995
|
|
|
) |
996
|
|
|
); |
997
|
|
|
} |
998
|
|
|
// Otherwise we can just use the the pm_conversation_list option |
999
|
|
View Code Duplication |
else |
1000
|
|
|
{ |
1001
|
|
|
$request = $db->query('pm_conversation_list', ' |
1002
|
|
|
SELECT |
1003
|
|
|
MAX(pm.id_pm) AS id_pm, pm.id_pm_head |
1004
|
|
|
FROM {db_prefix}personal_messages AS pm' . ($pm_options['folder'] == 'sent' ? ($pm_options['sort_by'] == 'name' ? ' |
1005
|
|
|
LEFT JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm)' : '') : ' |
1006
|
|
|
INNER JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm |
1007
|
|
|
AND pmr.id_member = {int:current_member} |
1008
|
|
|
AND pmr.deleted = {int:deleted_by} |
1009
|
|
|
' . $pm_options['label_query'] . ')') . ($pm_options['sort_by'] == 'name' ? (' |
1010
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = {raw:pm_member})') : '') . ' |
1011
|
|
|
WHERE ' . ($pm_options['folder'] == 'sent' ? 'pm.id_member_from = {int:current_member} |
1012
|
|
|
AND pm.deleted_by_sender = {int:deleted_by}' : '1=1') . (empty($pm_options['pmsg']) ? '' : ' |
1013
|
|
|
AND pm.id_pm = {int:pmsg}') . ' |
1014
|
|
|
GROUP BY pm.id_pm_head |
1015
|
|
|
ORDER BY ' . ($pm_options['sort_by_query'] == 'pm.id_pm' && $pm_options['folder'] != 'sent' ? 'id_pm' : '{raw:sort}') . ($pm_options['descending'] ? ' DESC' : ' ASC') . (isset($pm_options['pmsg']) ? ' |
1016
|
|
|
LIMIT ' . $pm_options['start'] . ', ' . $pm_options['limit'] : ''), |
1017
|
|
|
array( |
1018
|
|
|
'current_member' => $id_member, |
1019
|
|
|
'deleted_by' => 0, |
1020
|
|
|
'sort' => $pm_options['sort_by_query'], |
1021
|
|
|
'pm_member' => $pm_options['folder'] == 'sent' ? 'pmr.id_member' : 'pm.id_member_from', |
1022
|
|
|
'pmsg' => isset($pm_options['pmsg']) ? (int) $pm_options['pmsg'] : 0, |
1023
|
|
|
) |
1024
|
|
|
); |
1025
|
|
|
} |
1026
|
|
|
} |
1027
|
|
|
// If not in conversation view, then this is kinda simple! |
1028
|
|
View Code Duplication |
else |
1029
|
|
|
{ |
1030
|
|
|
// @todo SLOW This query uses a filesort. (inbox only.) |
1031
|
|
|
$request = $db->query('', ' |
1032
|
|
|
SELECT |
1033
|
|
|
pm.id_pm, pm.id_pm_head, pm.id_member_from |
1034
|
|
|
FROM {db_prefix}personal_messages AS pm' . ($pm_options['folder'] == 'sent' ? '' . ($pm_options['sort_by'] == 'name' ? ' |
1035
|
|
|
LEFT JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm)' : '') : ' |
1036
|
|
|
INNER JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm |
1037
|
|
|
AND pmr.id_member = {int:current_member} |
1038
|
|
|
AND pmr.deleted = {int:is_deleted} |
1039
|
|
|
' . $pm_options['label_query'] . ')') . ($pm_options['sort_by'] == 'name' ? (' |
1040
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = {raw:pm_member})') : '') . ' |
1041
|
|
|
WHERE ' . ($pm_options['folder'] == 'sent' ? 'pm.id_member_from = {raw:current_member} |
1042
|
|
|
AND pm.deleted_by_sender = {int:is_deleted}' : '1=1') . (empty($pm_options['pmsg']) ? '' : ' |
1043
|
|
|
AND pm.id_pm = {int:pmsg}') . ' |
1044
|
|
|
ORDER BY ' . ($pm_options['sort_by_query'] == 'pm.id_pm' && $pm_options['folder'] != 'sent' ? 'pmr.id_pm' : '{raw:sort}') . ($pm_options['descending'] ? ' DESC' : ' ASC') . (isset($pm_options['pmsg']) ? ' |
1045
|
|
|
LIMIT ' . $pm_options['start'] . ', ' . $pm_options['limit'] : ''), |
1046
|
|
|
array( |
1047
|
|
|
'current_member' => $id_member, |
1048
|
|
|
'is_deleted' => 0, |
1049
|
|
|
'sort' => $pm_options['sort_by_query'], |
1050
|
|
|
'pm_member' => $pm_options['folder'] == 'sent' ? 'pmr.id_member' : 'pm.id_member_from', |
1051
|
|
|
'pmsg' => isset($pm_options['pmsg']) ? (int) $pm_options['pmsg'] : 0, |
1052
|
|
|
) |
1053
|
|
|
); |
1054
|
|
|
} |
1055
|
|
|
// Load the id_pms and initialize recipients. |
1056
|
|
|
$pms = array(); |
1057
|
|
|
$lastData = array(); |
1058
|
|
|
$posters = $pm_options['folder'] == 'sent' ? array($id_member) : array(); |
1059
|
|
|
$recipients = array(); |
1060
|
|
|
while ($row = $db->fetch_assoc($request)) |
1061
|
|
|
{ |
1062
|
|
|
if (!isset($recipients[$row['id_pm']])) |
1063
|
|
|
{ |
1064
|
|
|
if (isset($row['id_member_from'])) |
1065
|
|
|
$posters[$row['id_pm']] = $row['id_member_from']; |
1066
|
|
|
|
1067
|
|
|
$pms[$row['id_pm']] = $row['id_pm']; |
1068
|
|
|
|
1069
|
|
|
$recipients[$row['id_pm']] = array( |
1070
|
|
|
'to' => array(), |
1071
|
|
|
'bcc' => array() |
1072
|
|
|
); |
1073
|
|
|
} |
1074
|
|
|
|
1075
|
|
|
// Keep track of the last message so we know what the head is without another query! |
1076
|
|
|
if ((empty($pm_options['pmid']) && (empty($options['view_newest_pm_first']) || !isset($lastData))) || empty($lastData) || (!empty($pm_options['pmid']) && $pm_options['pmid'] == $row['id_pm'])) |
1077
|
|
|
$lastData = array( |
1078
|
|
|
'id' => $row['id_pm'], |
1079
|
|
|
'head' => $row['id_pm_head'], |
1080
|
|
|
); |
1081
|
|
|
} |
1082
|
|
|
$db->free_result($request); |
1083
|
|
|
|
1084
|
|
|
return array($pms, $posters, $recipients, $lastData); |
1085
|
|
|
} |
1086
|
|
|
|
1087
|
|
|
/** |
1088
|
|
|
* How many PMs have you sent lately? |
1089
|
|
|
* |
1090
|
|
|
* @package PersonalMessage |
1091
|
|
|
* @param int $id_member id member |
1092
|
|
|
* @param int $time time interval (in seconds) |
1093
|
|
|
*/ |
1094
|
|
|
function pmCount($id_member, $time) |
1095
|
|
|
{ |
1096
|
|
|
$db = database(); |
1097
|
|
|
|
1098
|
|
|
$request = $db->query('', ' |
1099
|
|
|
SELECT |
1100
|
|
|
COUNT(*) AS post_count |
1101
|
|
|
FROM {db_prefix}personal_messages AS pm |
1102
|
|
|
INNER JOIN {db_prefix}pm_recipients AS pr ON (pr.id_pm = pm.id_pm) |
1103
|
|
|
WHERE pm.id_member_from = {int:current_member} |
1104
|
|
|
AND pm.msgtime > {int:msgtime}', |
1105
|
|
|
array( |
1106
|
|
|
'current_member' => $id_member, |
1107
|
|
|
'msgtime' => time() - $time, |
1108
|
|
|
) |
1109
|
|
|
); |
1110
|
|
|
list ($pmCount) = $db->fetch_row($request); |
1111
|
|
|
$db->free_result($request); |
1112
|
|
|
|
1113
|
|
|
return $pmCount; |
1114
|
|
|
} |
1115
|
|
|
|
1116
|
|
|
/** |
1117
|
|
|
* This will apply rules to all unread messages. |
1118
|
|
|
* |
1119
|
|
|
* - If all_messages is set will, clearly, do it to all! |
1120
|
|
|
* |
1121
|
|
|
* @package PersonalMessage |
1122
|
|
|
* @param bool $all_messages = false |
1123
|
|
|
*/ |
1124
|
|
|
function applyRules($all_messages = false) |
1125
|
|
|
{ |
1126
|
|
|
global $user_info, $context, $options; |
1127
|
|
|
|
1128
|
|
|
$db = database(); |
1129
|
|
|
|
1130
|
|
|
// Want this - duh! |
1131
|
|
|
loadRules(); |
1132
|
|
|
|
1133
|
|
|
// No rules? |
1134
|
|
|
if (empty($context['rules'])) |
1135
|
|
|
return; |
1136
|
|
|
|
1137
|
|
|
// Just unread ones? |
1138
|
|
|
$ruleQuery = $all_messages ? '' : ' AND pmr.is_new = 1'; |
1139
|
|
|
|
1140
|
|
|
// @todo Apply all should have timeout protection! |
1141
|
|
|
// Get all the messages that match this. |
1142
|
|
|
$request = $db->query('', ' |
1143
|
|
|
SELECT |
1144
|
|
|
pmr.id_pm, pm.id_member_from, pm.subject, pm.body, mem.id_group, pmr.labels |
1145
|
|
|
FROM {db_prefix}pm_recipients AS pmr |
1146
|
|
|
INNER JOIN {db_prefix}personal_messages AS pm ON (pm.id_pm = pmr.id_pm) |
1147
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = pm.id_member_from) |
1148
|
|
|
WHERE pmr.id_member = {int:current_member} |
1149
|
|
|
AND pmr.deleted = {int:not_deleted} |
1150
|
|
|
' . $ruleQuery, |
1151
|
|
|
array( |
1152
|
|
|
'current_member' => $user_info['id'], |
1153
|
|
|
'not_deleted' => 0, |
1154
|
|
|
) |
1155
|
|
|
); |
1156
|
|
|
$actions = array(); |
1157
|
|
|
while ($row = $db->fetch_assoc($request)) |
1158
|
|
|
{ |
1159
|
|
|
foreach ($context['rules'] as $rule) |
1160
|
|
|
{ |
1161
|
|
|
$match = false; |
1162
|
|
|
|
1163
|
|
|
// Loop through all the criteria hoping to make a match. |
1164
|
|
|
foreach ($rule['criteria'] as $criterium) |
1165
|
|
|
{ |
1166
|
|
|
if (($criterium['t'] == 'mid' && $criterium['v'] == $row['id_member_from']) || ($criterium['t'] == 'gid' && $criterium['v'] == $row['id_group']) || ($criterium['t'] == 'sub' && strpos($row['subject'], $criterium['v']) !== false) || ($criterium['t'] == 'msg' && strpos($row['body'], $criterium['v']) !== false)) |
1167
|
|
|
$match = true; |
1168
|
|
|
// If we're adding and one criteria don't match then we stop! |
1169
|
|
|
elseif ($rule['logic'] == 'and') |
1170
|
|
|
{ |
1171
|
|
|
$match = false; |
1172
|
|
|
break; |
1173
|
|
|
} |
1174
|
|
|
} |
1175
|
|
|
|
1176
|
|
|
// If we have a match the rule must be true - act! |
1177
|
|
|
if ($match) |
1178
|
|
|
{ |
1179
|
|
|
if ($rule['delete']) |
1180
|
|
|
$actions['deletes'][] = $row['id_pm']; |
1181
|
|
|
else |
1182
|
|
|
{ |
1183
|
|
|
foreach ($rule['actions'] as $ruleAction) |
1184
|
|
|
{ |
1185
|
|
|
if ($ruleAction['t'] == 'lab') |
1186
|
|
|
{ |
1187
|
|
|
// Get a basic pot started! |
1188
|
|
|
if (!isset($actions['labels'][$row['id_pm']])) |
1189
|
|
|
$actions['labels'][$row['id_pm']] = empty($row['labels']) ? array() : explode(',', $row['labels']); |
1190
|
|
|
|
1191
|
|
|
$actions['labels'][$row['id_pm']][] = $ruleAction['v']; |
1192
|
|
|
} |
1193
|
|
|
} |
1194
|
|
|
} |
1195
|
|
|
} |
1196
|
|
|
} |
1197
|
|
|
} |
1198
|
|
|
$db->free_result($request); |
1199
|
|
|
|
1200
|
|
|
// Deletes are easy! |
1201
|
|
|
if (!empty($actions['deletes'])) |
1202
|
|
|
deleteMessages($actions['deletes']); |
1203
|
|
|
|
1204
|
|
|
// Re-label? |
1205
|
|
|
if (!empty($actions['labels'])) |
1206
|
|
|
{ |
1207
|
|
|
foreach ($actions['labels'] as $pm => $labels) |
1208
|
|
|
{ |
1209
|
|
|
// Quickly check each label is valid! |
1210
|
|
|
$realLabels = array(); |
1211
|
|
|
foreach ($context['labels'] as $label) |
1212
|
|
|
if (in_array($label['id'], $labels) && ($label['id'] != -1 || empty($options['pm_remove_inbox_label']))) |
1213
|
|
|
$realLabels[] = $label['id']; |
1214
|
|
|
|
1215
|
|
|
$db->query('', ' |
1216
|
|
|
UPDATE {db_prefix}pm_recipients |
1217
|
|
|
SET labels = {string:new_labels} |
1218
|
|
|
WHERE id_pm = {int:id_pm} |
1219
|
|
|
AND id_member = {int:current_member}', |
1220
|
|
|
array( |
1221
|
|
|
'current_member' => $user_info['id'], |
1222
|
|
|
'id_pm' => $pm, |
1223
|
|
|
'new_labels' => empty($realLabels) ? '' : implode(',', $realLabels), |
1224
|
|
|
) |
1225
|
|
|
); |
1226
|
|
|
} |
1227
|
|
|
} |
1228
|
|
|
} |
1229
|
|
|
|
1230
|
|
|
/** |
1231
|
|
|
* Load up all the rules for the current user. |
1232
|
|
|
* |
1233
|
|
|
* @package PersonalMessage |
1234
|
|
|
* @param bool $reload = false |
1235
|
|
|
*/ |
1236
|
|
|
function loadRules($reload = false) |
1237
|
|
|
{ |
1238
|
|
|
global $user_info, $context; |
1239
|
|
|
|
1240
|
|
|
$db = database(); |
1241
|
|
|
|
1242
|
|
|
if (isset($context['rules']) && !$reload) |
1243
|
|
|
return; |
1244
|
|
|
|
1245
|
|
|
// This is just a simple list of "all" known rules |
1246
|
|
|
$context['known_rules'] = array( |
1247
|
|
|
// member_id == "Sender Name" |
1248
|
|
|
'mid', |
1249
|
|
|
// group_id == "Sender's Groups" |
1250
|
|
|
'gid', |
1251
|
|
|
// subject == "Message Subject Contains" |
1252
|
|
|
'sub', |
1253
|
|
|
// message == "Message Body Contains" |
1254
|
|
|
'msg', |
1255
|
|
|
// buddy == "Sender is Buddy" |
1256
|
|
|
'bud', |
1257
|
|
|
); |
1258
|
|
|
|
1259
|
|
|
$request = $db->query('', ' |
1260
|
|
|
SELECT |
1261
|
|
|
id_rule, rule_name, criteria, actions, delete_pm, is_or |
1262
|
|
|
FROM {db_prefix}pm_rules |
1263
|
|
|
WHERE id_member = {int:current_member}', |
1264
|
|
|
array( |
1265
|
|
|
'current_member' => $user_info['id'], |
1266
|
|
|
) |
1267
|
|
|
); |
1268
|
|
|
$context['rules'] = array(); |
1269
|
|
|
// Simply fill in the data! |
1270
|
|
|
while ($row = $db->fetch_assoc($request)) |
1271
|
|
|
{ |
1272
|
|
|
$context['rules'][$row['id_rule']] = array( |
1273
|
|
|
'id' => $row['id_rule'], |
1274
|
|
|
'name' => $row['rule_name'], |
1275
|
|
|
'criteria' => Util::unserialize($row['criteria']), |
1276
|
|
|
'actions' => Util::unserialize($row['actions']), |
1277
|
|
|
'delete' => $row['delete_pm'], |
1278
|
|
|
'logic' => $row['is_or'] ? 'or' : 'and', |
1279
|
|
|
); |
1280
|
|
|
|
1281
|
|
|
if ($row['delete_pm']) |
1282
|
|
|
$context['rules'][$row['id_rule']]['actions'][] = array('t' => 'del', 'v' => 1); |
1283
|
|
|
} |
1284
|
|
|
$db->free_result($request); |
1285
|
|
|
} |
1286
|
|
|
|
1287
|
|
|
/** |
1288
|
|
|
* Update PM recipient when they receive or read a new PM |
1289
|
|
|
* |
1290
|
|
|
* @package PersonalMessage |
1291
|
|
|
* @param int $id_member |
1292
|
|
|
* @param boolean $new = false |
1293
|
|
|
*/ |
1294
|
|
|
function toggleNewPM($id_member, $new = false) |
1295
|
|
|
{ |
1296
|
|
|
$db = database(); |
1297
|
|
|
|
1298
|
|
|
$db->query('', ' |
1299
|
|
|
UPDATE {db_prefix}pm_recipients |
1300
|
|
|
SET is_new = ' . ($new ? '{int:new}' : '{int:not_new}') . ' |
1301
|
|
|
WHERE id_member = {int:current_member}', |
1302
|
|
|
array( |
1303
|
|
|
'current_member' => $id_member, |
1304
|
|
|
'new' => 1, |
1305
|
|
|
'not_new' => 0 |
1306
|
|
|
) |
1307
|
|
|
); |
1308
|
|
|
} |
1309
|
|
|
|
1310
|
|
|
/** |
1311
|
|
|
* Load the PM limits for each group or for a specified group |
1312
|
|
|
* |
1313
|
|
|
* @package PersonalMessage |
1314
|
|
|
* @param int|bool $id_group (optional) the id of a membergroup |
1315
|
|
|
*/ |
1316
|
|
|
function loadPMLimits($id_group = false) |
1317
|
|
|
{ |
1318
|
|
|
$db = database(); |
1319
|
|
|
|
1320
|
|
|
$request = $db->query('', ' |
1321
|
|
|
SELECT |
1322
|
|
|
id_group, group_name, max_messages |
1323
|
|
|
FROM {db_prefix}membergroups' . ($id_group ? ' |
1324
|
|
|
WHERE id_group = {int:id_group}' : ' |
1325
|
|
|
ORDER BY min_posts, CASE WHEN id_group < {int:newbie_group} THEN id_group ELSE 4 END, group_name'), |
1326
|
|
|
array( |
1327
|
|
|
'id_group' => $id_group, |
1328
|
|
|
'newbie_group' => 4, |
1329
|
|
|
) |
1330
|
|
|
); |
1331
|
|
|
$groups = array(); |
1332
|
|
|
while ($row = $db->fetch_assoc($request)) |
1333
|
|
|
{ |
1334
|
|
|
if ($row['id_group'] != 1) |
1335
|
|
|
$groups[$row['id_group']] = $row; |
1336
|
|
|
} |
1337
|
|
|
$db->free_result($request); |
1338
|
|
|
|
1339
|
|
|
return $groups; |
1340
|
|
|
} |
1341
|
|
|
|
1342
|
|
|
/** |
1343
|
|
|
* Retrieve the discussion one or more PMs belong to |
1344
|
|
|
* |
1345
|
|
|
* @package PersonalMessage |
1346
|
|
|
* @param int[] $id_pms |
1347
|
|
|
*/ |
1348
|
|
|
function getDiscussions($id_pms) |
1349
|
|
|
{ |
1350
|
|
|
$db = database(); |
1351
|
|
|
|
1352
|
|
|
$request = $db->query('', ' |
1353
|
|
|
SELECT |
1354
|
|
|
id_pm_head, id_pm |
1355
|
|
|
FROM {db_prefix}personal_messages |
1356
|
|
|
WHERE id_pm IN ({array_int:id_pms})', |
1357
|
|
|
array( |
1358
|
|
|
'id_pms' => $id_pms, |
1359
|
|
|
) |
1360
|
|
|
); |
1361
|
|
|
$pm_heads = array(); |
1362
|
|
|
while ($row = $db->fetch_assoc($request)) |
1363
|
|
|
$pm_heads[$row['id_pm_head']] = $row['id_pm']; |
1364
|
|
|
$db->free_result($request); |
1365
|
|
|
|
1366
|
|
|
return $pm_heads; |
1367
|
|
|
} |
1368
|
|
|
|
1369
|
|
|
/** |
1370
|
|
|
* Return all the PMs belonging to one or more discussions |
1371
|
|
|
* |
1372
|
|
|
* @package PersonalMessage |
1373
|
|
|
* @param int[] $pm_heads array of pm id head nodes |
1374
|
|
|
*/ |
1375
|
|
|
function getPmsFromDiscussion($pm_heads) |
1376
|
|
|
{ |
1377
|
|
|
$db = database(); |
1378
|
|
|
|
1379
|
|
|
$pms = array(); |
1380
|
|
|
$request = $db->query('', ' |
1381
|
|
|
SELECT |
1382
|
|
|
id_pm, id_pm_head |
1383
|
|
|
FROM {db_prefix}personal_messages |
1384
|
|
|
WHERE id_pm_head IN ({array_int:pm_heads})', |
1385
|
|
|
array( |
1386
|
|
|
'pm_heads' => $pm_heads, |
1387
|
|
|
) |
1388
|
|
|
); |
1389
|
|
|
// Copy the action from the single to PM to the others. |
1390
|
|
|
while ($row = $db->fetch_assoc($request)) |
1391
|
|
|
$pms[$row['id_pm']] = $row['id_pm_head']; |
1392
|
|
|
$db->free_result($request); |
1393
|
|
|
|
1394
|
|
|
return $pms; |
1395
|
|
|
} |
1396
|
|
|
|
1397
|
|
|
/** |
1398
|
|
|
* Determines the PMs which need an updated label. |
1399
|
|
|
* |
1400
|
|
|
* @package PersonalMessage |
1401
|
|
|
* @param mixed[] $to_label |
1402
|
|
|
* @param string[] $label_type |
1403
|
|
|
* @param int $user_id |
1404
|
|
|
* @return integer|null |
1405
|
|
|
*/ |
1406
|
|
|
function changePMLabels($to_label, $label_type, $user_id) |
1407
|
|
|
{ |
1408
|
|
|
global $options; |
1409
|
|
|
|
1410
|
|
|
$db = database(); |
1411
|
|
|
|
1412
|
|
|
$to_update = array(); |
1413
|
|
|
|
1414
|
|
|
// Get information about each message... |
1415
|
|
|
$request = $db->query('', ' |
1416
|
|
|
SELECT |
1417
|
|
|
id_pm, labels |
1418
|
|
|
FROM {db_prefix}pm_recipients |
1419
|
|
|
WHERE id_member = {int:current_member} |
1420
|
|
|
AND id_pm IN ({array_int:to_label}) |
1421
|
|
|
LIMIT ' . count($to_label), |
1422
|
|
|
array( |
1423
|
|
|
'current_member' => $user_id, |
1424
|
|
|
'to_label' => array_keys($to_label), |
1425
|
|
|
) |
1426
|
|
|
); |
1427
|
|
|
while ($row = $db->fetch_assoc($request)) |
1428
|
|
|
{ |
1429
|
|
|
$labels = $row['labels'] == '' ? array('-1') : explode(',', trim($row['labels'])); |
1430
|
|
|
|
1431
|
|
|
// Already exists? Then... unset it! |
1432
|
|
|
$id_label = array_search($to_label[$row['id_pm']], $labels); |
1433
|
|
|
|
1434
|
|
|
if ($id_label !== false && $label_type[$row['id_pm']] !== 'add') |
1435
|
|
|
unset($labels[$id_label]); |
1436
|
|
|
elseif ($label_type[$row['id_pm']] !== 'rem') |
1437
|
|
|
$labels[] = $to_label[$row['id_pm']]; |
1438
|
|
|
|
1439
|
|
|
if (!empty($options['pm_remove_inbox_label']) && $to_label[$row['id_pm']] != '-1' && ($key = array_search('-1', $labels)) !== false) |
1440
|
|
|
unset($labels[$key]); |
1441
|
|
|
|
1442
|
|
|
$set = implode(',', array_unique($labels)); |
1443
|
|
|
if ($set == '') |
1444
|
|
|
$set = '-1'; |
1445
|
|
|
|
1446
|
|
|
$to_update[$row['id_pm']] = $set; |
1447
|
|
|
} |
1448
|
|
|
$db->free_result($request); |
1449
|
|
|
|
1450
|
|
|
if (!empty($to_update)) |
1451
|
|
|
return updatePMLabels($to_update, $user_id); |
1452
|
|
|
} |
1453
|
|
|
|
1454
|
|
|
/** |
1455
|
|
|
* Detects personal messages which need a new label. |
1456
|
|
|
* |
1457
|
|
|
* @package PersonalMessage |
1458
|
|
|
* @param mixed[] $searchArray |
1459
|
|
|
* @param mixed[] $new_labels |
1460
|
|
|
* @param int $user_id |
1461
|
|
|
* @return integer|null |
1462
|
|
|
*/ |
1463
|
|
|
function updateLabelsToPM($searchArray, $new_labels, $user_id) |
1464
|
|
|
{ |
1465
|
|
|
$db = database(); |
1466
|
|
|
|
1467
|
|
|
// Now find the messages to change. |
1468
|
|
|
$request = $db->query('', ' |
1469
|
|
|
SELECT |
1470
|
|
|
id_pm, labels |
1471
|
|
|
FROM {db_prefix}pm_recipients |
1472
|
|
|
WHERE FIND_IN_SET({raw:find_label_implode}, labels) != 0 |
1473
|
|
|
AND id_member = {int:current_member}', |
1474
|
|
|
array( |
1475
|
|
|
'current_member' => $user_id, |
1476
|
|
|
'find_label_implode' => '\'' . implode('\', labels) != 0 OR FIND_IN_SET(\'', $searchArray) . '\'', |
1477
|
|
|
) |
1478
|
|
|
); |
1479
|
|
|
$to_update = array(); |
1480
|
|
|
while ($row = $db->fetch_assoc($request)) |
1481
|
|
|
{ |
1482
|
|
|
// Do the long task of updating them... |
1483
|
|
|
$toChange = explode(',', $row['labels']); |
1484
|
|
|
|
1485
|
|
|
foreach ($toChange as $key => $value) |
1486
|
|
|
{ |
1487
|
|
|
if (in_array($value, $searchArray)) |
1488
|
|
|
{ |
1489
|
|
|
if (isset($new_labels[$value])) |
1490
|
|
|
$toChange[$key] = $new_labels[$value]; |
1491
|
|
|
else |
1492
|
|
|
unset($toChange[$key]); |
1493
|
|
|
} |
1494
|
|
|
} |
1495
|
|
|
|
1496
|
|
|
if (empty($toChange)) |
1497
|
|
|
$toChange[] = '-1'; |
1498
|
|
|
|
1499
|
|
|
$to_update[$row['id_pm']] = implode(',', array_unique($toChange)); |
1500
|
|
|
} |
1501
|
|
|
$db->free_result($request); |
1502
|
|
|
|
1503
|
|
|
if (!empty($to_update)) |
1504
|
|
|
return updatePMLabels($to_update, $user_id); |
1505
|
|
|
} |
1506
|
|
|
|
1507
|
|
|
/** |
1508
|
|
|
* Updates PMs with their new label. |
1509
|
|
|
* |
1510
|
|
|
* @package PersonalMessage |
1511
|
|
|
* @param mixed[] $to_update |
1512
|
|
|
* @param int $user_id |
1513
|
|
|
* @return int |
1514
|
|
|
*/ |
1515
|
|
|
function updatePMLabels($to_update, $user_id) |
1516
|
|
|
{ |
1517
|
|
|
$db = database(); |
1518
|
|
|
|
1519
|
|
|
$updateErrors = 0; |
1520
|
|
|
|
1521
|
|
|
foreach ($to_update as $id_pm => $set) |
1522
|
|
|
{ |
1523
|
|
|
// Check that this string isn't going to be too large for the database. |
1524
|
|
|
if (strlen($set) > 60) |
1525
|
|
|
{ |
1526
|
|
|
$updateErrors++; |
1527
|
|
|
|
1528
|
|
|
// Make the string as long as possible and update anyway |
1529
|
|
|
$set = substr($set, 0, 60); |
1530
|
|
|
$set = substr($set, 0, strrpos($set, ',')); |
1531
|
|
|
} |
1532
|
|
|
|
1533
|
|
|
$db->query('', ' |
1534
|
|
|
UPDATE {db_prefix}pm_recipients |
1535
|
|
|
SET labels = {string:labels} |
1536
|
|
|
WHERE id_pm = {int:id_pm} |
1537
|
|
|
AND id_member = {int:current_member}', |
1538
|
|
|
array( |
1539
|
|
|
'current_member' => $user_id, |
1540
|
|
|
'id_pm' => $id_pm, |
1541
|
|
|
'labels' => $set, |
1542
|
|
|
) |
1543
|
|
|
); |
1544
|
|
|
} |
1545
|
|
|
|
1546
|
|
|
return $updateErrors; |
1547
|
|
|
} |
1548
|
|
|
|
1549
|
|
|
/** |
1550
|
|
|
* Gets PMs older than a specific date. |
1551
|
|
|
* |
1552
|
|
|
* @package PersonalMessage |
1553
|
|
|
* @param int $user_id the user's id. |
1554
|
|
|
* @param int $time timestamp with a specific date |
1555
|
|
|
* @return array |
1556
|
|
|
*/ |
1557
|
|
|
function getPMsOlderThan($user_id, $time) |
1558
|
|
|
{ |
1559
|
|
|
$db = database(); |
1560
|
|
|
|
1561
|
|
|
// Array to store the IDs in. |
1562
|
|
|
$pm_ids = array(); |
1563
|
|
|
|
1564
|
|
|
// Select all the messages they have sent older than $time. |
1565
|
|
|
$request = $db->query('', ' |
1566
|
|
|
SELECT |
1567
|
|
|
id_pm |
1568
|
|
|
FROM {db_prefix}personal_messages |
1569
|
|
|
WHERE deleted_by_sender = {int:not_deleted} |
1570
|
|
|
AND id_member_from = {int:current_member} |
1571
|
|
|
AND msgtime < {int:msgtime}', |
1572
|
|
|
array( |
1573
|
|
|
'current_member' => $user_id, |
1574
|
|
|
'not_deleted' => 0, |
1575
|
|
|
'msgtime' => $time, |
1576
|
|
|
) |
1577
|
|
|
); |
1578
|
|
|
while ($row = $db->fetch_row($request)) |
1579
|
|
|
$pm_ids[] = $row[0]; |
1580
|
|
|
$db->free_result($request); |
1581
|
|
|
|
1582
|
|
|
// This is the inbox |
1583
|
|
|
$request = $db->query('', ' |
1584
|
|
|
SELECT |
1585
|
|
|
pmr.id_pm |
1586
|
|
|
FROM {db_prefix}pm_recipients AS pmr |
1587
|
|
|
INNER JOIN {db_prefix}personal_messages AS pm ON (pm.id_pm = pmr.id_pm) |
1588
|
|
|
WHERE pmr.deleted = {int:not_deleted} |
1589
|
|
|
AND pmr.id_member = {int:current_member} |
1590
|
|
|
AND pm.msgtime < {int:msgtime}', |
1591
|
|
|
array( |
1592
|
|
|
'current_member' => $user_id, |
1593
|
|
|
'not_deleted' => 0, |
1594
|
|
|
'msgtime' => $time, |
1595
|
|
|
) |
1596
|
|
|
); |
1597
|
|
|
while ($row = $db->fetch_row($request)) |
1598
|
|
|
$pm_ids[] = $row[0]; |
1599
|
|
|
$db->free_result($request); |
1600
|
|
|
|
1601
|
|
|
return $pm_ids; |
1602
|
|
|
} |
1603
|
|
|
|
1604
|
|
|
/** |
1605
|
|
|
* Used to delete PM rules from the given member. |
1606
|
|
|
* |
1607
|
|
|
* @package PersonalMessage |
1608
|
|
|
* @param int $id_member |
1609
|
|
|
* @param int[] $rule_changes |
1610
|
|
|
*/ |
1611
|
|
|
function deletePMRules($id_member, $rule_changes) |
1612
|
|
|
{ |
1613
|
|
|
$db = database(); |
1614
|
|
|
|
1615
|
|
|
$db->query('', ' |
1616
|
|
|
DELETE FROM {db_prefix}pm_rules |
1617
|
|
|
WHERE id_rule IN ({array_int:rule_list}) |
1618
|
|
|
AND id_member = {int:current_member}', |
1619
|
|
|
array( |
1620
|
|
|
'current_member' => $id_member, |
1621
|
|
|
'rule_list' => $rule_changes, |
1622
|
|
|
) |
1623
|
|
|
); |
1624
|
|
|
} |
1625
|
|
|
|
1626
|
|
|
/** |
1627
|
|
|
* Updates a personal messaging rule action for the given member. |
1628
|
|
|
* |
1629
|
|
|
* @package PersonalMessage |
1630
|
|
|
* @param int $id_rule |
1631
|
|
|
* @param int $id_member |
1632
|
|
|
* @param mixed[] $actions |
1633
|
|
|
*/ |
1634
|
|
|
function updatePMRuleAction($id_rule, $id_member, $actions) |
1635
|
|
|
{ |
1636
|
|
|
$db = database(); |
1637
|
|
|
|
1638
|
|
|
$db->query('', ' |
1639
|
|
|
UPDATE {db_prefix}pm_rules |
1640
|
|
|
SET actions = {string:actions} |
1641
|
|
|
WHERE id_rule = {int:id_rule} |
1642
|
|
|
AND id_member = {int:current_member}', |
1643
|
|
|
array( |
1644
|
|
|
'current_member' => $id_member, |
1645
|
|
|
'id_rule' => $id_rule, |
1646
|
|
|
'actions' => serialize($actions), |
1647
|
|
|
) |
1648
|
|
|
); |
1649
|
|
|
} |
1650
|
|
|
|
1651
|
|
|
/** |
1652
|
|
|
* Add a new PM rule to the database. |
1653
|
|
|
* |
1654
|
|
|
* @package PersonalMessage |
1655
|
|
|
* @param int $id_member |
1656
|
|
|
* @param string $ruleName |
1657
|
|
|
* @param string $criteria |
1658
|
|
|
* @param string $actions |
1659
|
|
|
* @param int $doDelete |
1660
|
|
|
* @param int $isOr |
1661
|
|
|
*/ |
1662
|
|
|
function addPMRule($id_member, $ruleName, $criteria, $actions, $doDelete, $isOr) |
1663
|
|
|
{ |
1664
|
|
|
$db = database(); |
1665
|
|
|
|
1666
|
|
|
$db->insert('', |
1667
|
|
|
'{db_prefix}pm_rules', |
1668
|
|
|
array( |
1669
|
|
|
'id_member' => 'int', 'rule_name' => 'string', 'criteria' => 'string', 'actions' => 'string', |
1670
|
|
|
'delete_pm' => 'int', 'is_or' => 'int', |
1671
|
|
|
), |
1672
|
|
|
array( |
1673
|
|
|
$id_member, $ruleName, $criteria, $actions, $doDelete, $isOr, |
1674
|
|
|
), |
1675
|
|
|
array('id_rule') |
1676
|
|
|
); |
1677
|
|
|
} |
1678
|
|
|
|
1679
|
|
|
/** |
1680
|
|
|
* Updates a personal messaging rule for the given member. |
1681
|
|
|
* |
1682
|
|
|
* @package PersonalMessage |
1683
|
|
|
* @param int $id_member |
1684
|
|
|
* @param int $id_rule |
1685
|
|
|
* @param string $ruleName |
1686
|
|
|
* @param string $criteria |
1687
|
|
|
* @param string $actions |
1688
|
|
|
* @param int $doDelete |
1689
|
|
|
* @param int $isOr |
1690
|
|
|
*/ |
1691
|
|
|
function updatePMRule($id_member, $id_rule, $ruleName, $criteria, $actions, $doDelete, $isOr) |
1692
|
|
|
{ |
1693
|
|
|
$db = database(); |
1694
|
|
|
|
1695
|
|
|
$db->query('', ' |
1696
|
|
|
UPDATE {db_prefix}pm_rules |
1697
|
|
|
SET rule_name = {string:rule_name}, criteria = {string:criteria}, actions = {string:actions}, |
1698
|
|
|
delete_pm = {int:delete_pm}, is_or = {int:is_or} |
1699
|
|
|
WHERE id_rule = {int:id_rule} |
1700
|
|
|
AND id_member = {int:current_member}', |
1701
|
|
|
array( |
1702
|
|
|
'current_member' => $id_member, |
1703
|
|
|
'delete_pm' => $doDelete, |
1704
|
|
|
'is_or' => $isOr, |
1705
|
|
|
'id_rule' => $id_rule, |
1706
|
|
|
'rule_name' => $ruleName, |
1707
|
|
|
'criteria' => $criteria, |
1708
|
|
|
'actions' => $actions, |
1709
|
|
|
) |
1710
|
|
|
); |
1711
|
|
|
} |
1712
|
|
|
|
1713
|
|
|
/** |
1714
|
|
|
* Used to set a replied status for a given PM. |
1715
|
|
|
* |
1716
|
|
|
* @package PersonalMessage |
1717
|
|
|
* @param int $id_member |
1718
|
|
|
* @param int $replied_to |
1719
|
|
|
*/ |
1720
|
|
|
function setPMRepliedStatus($id_member, $replied_to) |
1721
|
|
|
{ |
1722
|
|
|
$db = database(); |
1723
|
|
|
|
1724
|
|
|
$db->query('', ' |
1725
|
|
|
UPDATE {db_prefix}pm_recipients |
1726
|
|
|
SET is_read = is_read | 2 |
1727
|
|
|
WHERE id_pm = {int:replied_to} |
1728
|
|
|
AND id_member = {int:current_member}', |
1729
|
|
|
array( |
1730
|
|
|
'current_member' => $id_member, |
1731
|
|
|
'replied_to' => $replied_to, |
1732
|
|
|
) |
1733
|
|
|
); |
1734
|
|
|
} |
1735
|
|
|
|
1736
|
|
|
/** |
1737
|
|
|
* Given the head PM, loads all other PM's that share the same head node |
1738
|
|
|
* |
1739
|
|
|
* - Used to load the conversation view of a PM |
1740
|
|
|
* |
1741
|
|
|
* @package PersonalMessage |
1742
|
|
|
* @param int $head id of the head pm of the conversation |
1743
|
|
|
* @param mixed[] $recipients |
1744
|
|
|
* @param string $folder the current folder we are working in |
1745
|
|
|
*/ |
1746
|
|
|
function loadConversationList($head, &$recipients, $folder = '') |
1747
|
|
|
{ |
1748
|
|
|
global $user_info; |
1749
|
|
|
|
1750
|
|
|
$db = database(); |
1751
|
|
|
|
1752
|
|
|
$request = $db->query('', ' |
1753
|
|
|
SELECT |
1754
|
|
|
pm.id_pm, pm.id_member_from, pm.deleted_by_sender, pmr.id_member, pmr.deleted |
1755
|
|
|
FROM {db_prefix}personal_messages AS pm |
1756
|
|
|
INNER JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm) |
1757
|
|
|
WHERE pm.id_pm_head = {int:id_pm_head} |
1758
|
|
|
AND ((pm.id_member_from = {int:current_member} AND pm.deleted_by_sender = {int:not_deleted}) |
1759
|
|
|
OR (pmr.id_member = {int:current_member} AND pmr.deleted = {int:not_deleted})) |
1760
|
|
|
ORDER BY pm.id_pm', |
1761
|
|
|
array( |
1762
|
|
|
'current_member' => $user_info['id'], |
1763
|
|
|
'id_pm_head' => $head, |
1764
|
|
|
'not_deleted' => 0, |
1765
|
|
|
) |
1766
|
|
|
); |
1767
|
|
|
$display_pms = array(); |
1768
|
|
|
$posters = array(); |
1769
|
|
|
while ($row = $db->fetch_assoc($request)) |
1770
|
|
|
{ |
1771
|
|
|
// This is, frankly, a joke. We will put in a workaround for people sending to themselves - yawn! |
1772
|
|
|
if ($folder == 'sent' && $row['id_member_from'] == $user_info['id'] && $row['deleted_by_sender'] == 1) |
1773
|
|
|
continue; |
1774
|
|
|
elseif (($row['id_member'] == $user_info['id']) && $row['deleted'] == 1) |
1775
|
|
|
continue; |
1776
|
|
|
|
1777
|
|
|
if (!isset($recipients[$row['id_pm']])) |
1778
|
|
|
$recipients[$row['id_pm']] = array( |
1779
|
|
|
'to' => array(), |
1780
|
|
|
'bcc' => array() |
1781
|
|
|
); |
1782
|
|
|
|
1783
|
|
|
$display_pms[] = $row['id_pm']; |
1784
|
|
|
$posters[$row['id_pm']] = $row['id_member_from']; |
1785
|
|
|
} |
1786
|
|
|
$db->free_result($request); |
1787
|
|
|
|
1788
|
|
|
return array($display_pms, $posters); |
1789
|
|
|
} |
1790
|
|
|
|
1791
|
|
|
/** |
1792
|
|
|
* Used to determine if any message in a conversation thread is unread |
1793
|
|
|
* |
1794
|
|
|
* - Returns array of keys with the head id and value details of the the newest |
1795
|
|
|
* unread message. |
1796
|
|
|
* |
1797
|
|
|
* @package PersonalMessage |
1798
|
|
|
* @param int[] $pms array of pm ids to search |
1799
|
|
|
*/ |
1800
|
|
|
function loadConversationUnreadStatus($pms) |
1801
|
|
|
{ |
1802
|
|
|
global $user_info; |
1803
|
|
|
|
1804
|
|
|
$db = database(); |
1805
|
|
|
|
1806
|
|
|
// Make it an array if its not |
1807
|
|
|
if (!is_array($pms)) |
1808
|
|
|
$pms = array($pms); |
1809
|
|
|
|
1810
|
|
|
// Find the heads for this group of PM's |
1811
|
|
|
$request = $db->query('', ' |
1812
|
|
|
SELECT |
1813
|
|
|
id_pm_head, id_pm |
1814
|
|
|
FROM {db_prefix}personal_messages |
1815
|
|
|
WHERE id_pm IN ({array_int:id_pm})', |
1816
|
|
|
array( |
1817
|
|
|
'id_pm' => $pms, |
1818
|
|
|
) |
1819
|
|
|
); |
1820
|
|
|
$head_pms = array(); |
1821
|
|
|
while ($row = $db->fetch_assoc($request)) |
1822
|
|
|
$head_pms[$row['id_pm_head']] = $row['id_pm']; |
1823
|
|
|
$db->free_result($request); |
1824
|
|
|
|
1825
|
|
|
// Find any unread PM's this member has under these head pm id's |
1826
|
|
|
$request = $db->query('', ' |
1827
|
|
|
SELECT |
1828
|
|
|
MAX(pm.id_pm) AS id_pm, pm.id_pm_head |
1829
|
|
|
FROM {db_prefix}personal_messages AS pm |
1830
|
|
|
INNER JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm) |
1831
|
|
|
WHERE pm.id_pm_head IN ({array_int:id_pm_head}) |
1832
|
|
|
AND (pmr.id_member = {int:current_member} AND pmr.deleted = {int:not_deleted}) |
1833
|
|
|
AND (pmr.is_read & 1 = 0) |
1834
|
|
|
GROUP BY pm.id_pm_head', |
1835
|
|
|
array( |
1836
|
|
|
'current_member' => $user_info['id'], |
1837
|
|
|
'id_pm_head' => array_keys($head_pms), |
1838
|
|
|
'not_deleted' => 0, |
1839
|
|
|
) |
1840
|
|
|
); |
1841
|
|
|
$unread_pms = array(); |
1842
|
|
|
while ($row = $db->fetch_assoc($request)) |
1843
|
|
|
{ |
1844
|
|
|
// Return the results under the original index since thats what we are |
1845
|
|
|
// displaying in the subject list |
1846
|
|
|
$index = $head_pms[$row['id_pm_head']]; |
1847
|
|
|
$unread_pms[$index] = $row; |
1848
|
|
|
} |
1849
|
|
|
$db->free_result($request); |
1850
|
|
|
|
1851
|
|
|
return $unread_pms; |
1852
|
|
|
} |
1853
|
|
|
|
1854
|
|
|
/** |
1855
|
|
|
* Get all recipients for a given group of PM's, loads some basic member information for each |
1856
|
|
|
* |
1857
|
|
|
* - Will not include bcc-recipients for an inbox |
1858
|
|
|
* - Keeps track if a message has been replied / read |
1859
|
|
|
* - Tracks any message labels in use |
1860
|
|
|
* - If optional search parameter is set to true will return message first label, useful for linking |
1861
|
|
|
* |
1862
|
|
|
* @package PersonalMessage |
1863
|
|
|
* @param int[] $all_pms |
1864
|
|
|
* @param mixed[] $recipients |
1865
|
|
|
* @param string $folder |
1866
|
|
|
* @param boolean $search |
1867
|
|
|
*/ |
1868
|
|
|
function loadPMRecipientInfo($all_pms, &$recipients, $folder = '', $search = false) |
1869
|
|
|
{ |
1870
|
|
|
global $txt, $user_info, $scripturl, $context; |
1871
|
|
|
|
1872
|
|
|
$db = database(); |
1873
|
|
|
|
1874
|
|
|
// Get the recipients for all these PM's |
1875
|
|
|
$request = $db->query('', ' |
1876
|
|
|
SELECT |
1877
|
|
|
pmr.id_pm, pmr.bcc, pmr.labels, pmr.is_read, |
1878
|
|
|
mem_to.id_member AS id_member_to, mem_to.real_name AS to_name |
1879
|
|
|
FROM {db_prefix}pm_recipients AS pmr |
1880
|
|
|
LEFT JOIN {db_prefix}members AS mem_to ON (mem_to.id_member = pmr.id_member) |
1881
|
|
|
WHERE pmr.id_pm IN ({array_int:pm_list})', |
1882
|
|
|
array( |
1883
|
|
|
'pm_list' => $all_pms, |
1884
|
|
|
) |
1885
|
|
|
); |
1886
|
|
|
|
1887
|
|
|
$message_labels = array(); |
1888
|
|
|
foreach ($all_pms as $pmid) |
1889
|
|
|
{ |
1890
|
|
|
$message_labels[$pmid] = array(); |
1891
|
|
|
} |
1892
|
|
|
$message_replied = array(); |
1893
|
|
|
$message_unread = array(); |
1894
|
|
|
$message_first_label = array(); |
1895
|
|
|
while ($row = $db->fetch_assoc($request)) |
1896
|
|
|
{ |
1897
|
|
|
// Sent folder recipients |
1898
|
|
|
if ($folder === 'sent' || empty($row['bcc'])) |
1899
|
|
|
$recipients[$row['id_pm']][empty($row['bcc']) ? 'to' : 'bcc'][] = empty($row['id_member_to']) ? $txt['guest_title'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member_to'] . '">' . $row['to_name'] . '</a>'; |
1900
|
|
|
|
1901
|
|
|
// Don't include bcc-recipients if its your inbox, you're not supposed to know :P |
1902
|
|
|
if ($row['id_member_to'] == $user_info['id'] && $folder !== 'sent') |
1903
|
|
|
{ |
1904
|
|
|
// Read and replied to status for this message |
1905
|
|
|
$message_replied[$row['id_pm']] = $row['is_read'] & 2; |
1906
|
|
|
$message_unread[$row['id_pm']] = $row['is_read'] == 0; |
1907
|
|
|
$message_labels[$row['id_pm']] = array(); |
1908
|
|
|
|
1909
|
|
|
$row['labels'] = $row['labels'] == '' ? array() : explode(',', $row['labels']); |
1910
|
|
|
foreach ($row['labels'] as $v) |
1911
|
|
|
{ |
1912
|
|
|
if (isset($context['labels'][(int) $v])) |
1913
|
|
|
$message_labels[$row['id_pm']][(int) $v] = array('id' => $v, 'name' => $context['labels'][(int) $v]['name']); |
1914
|
|
|
|
1915
|
|
|
// Here we find the first label on a message - used for linking to posts |
1916
|
|
|
if ($search && (!isset($message_first_label[$row['id_pm']]) && !in_array('-1', $row['labels']))) |
1917
|
|
|
$message_first_label[$row['id_pm']] = (int) $v; |
1918
|
|
|
} |
1919
|
|
|
} |
1920
|
|
|
} |
1921
|
|
|
$db->free_result($request); |
1922
|
|
|
|
1923
|
|
|
return array($message_labels, $message_replied, $message_unread, ($search ? $message_first_label : '')); |
1924
|
|
|
} |
1925
|
|
|
|
1926
|
|
|
/** |
1927
|
|
|
* This is used by preparePMContext_callback. |
1928
|
|
|
* |
1929
|
|
|
* - That function uses these query results and handles the free_result action as well. |
1930
|
|
|
* |
1931
|
|
|
* @package PersonalMessage |
1932
|
|
|
* @param int[] $pms array of PM ids to fetch |
1933
|
|
|
* @param string[] $orderBy raw query defining how to order the results |
1934
|
|
|
*/ |
1935
|
|
|
function loadPMSubjectRequest($pms, $orderBy) |
1936
|
|
|
{ |
1937
|
|
|
$db = database(); |
1938
|
|
|
|
1939
|
|
|
// Separate query for these bits! |
1940
|
|
|
$subjects_request = $db->query('', ' |
1941
|
|
|
SELECT |
1942
|
|
|
pm.id_pm, pm.subject, pm.id_member_from, pm.msgtime, COALESCE(mem.real_name, pm.from_name) AS from_name, |
1943
|
|
|
COALESCE(mem.id_member, 0) AS not_guest |
1944
|
|
|
FROM {db_prefix}personal_messages AS pm |
1945
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = pm.id_member_from) |
1946
|
|
|
WHERE pm.id_pm IN ({array_int:pm_list}) |
1947
|
|
|
ORDER BY ' . implode(', ', $orderBy) . ' |
1948
|
|
|
LIMIT ' . count($pms), |
1949
|
|
|
array( |
1950
|
|
|
'pm_list' => $pms, |
1951
|
|
|
) |
1952
|
|
|
); |
1953
|
|
|
|
1954
|
|
|
return $subjects_request; |
1955
|
|
|
} |
1956
|
|
|
|
1957
|
|
|
/** |
1958
|
|
|
* Similar to loadSubjectRequest, this is used by preparePMContext_callback. |
1959
|
|
|
* |
1960
|
|
|
* - That function uses these query results and handles the free_result action as well. |
1961
|
|
|
* |
1962
|
|
|
* @package PersonalMessage |
1963
|
|
|
* @param int[] $display_pms list of PM's to fetch |
1964
|
|
|
* @param string $sort_by_query raw query used in the sorting option |
1965
|
|
|
* @param string $sort_by used to signal when addition joins are needed |
1966
|
|
|
* @param boolean $descending if true descending order of display |
1967
|
|
|
* @param int|string $display_mode how are they being viewed, all, conversation, etc |
1968
|
|
|
* @param string $folder current pm folder |
1969
|
|
|
*/ |
1970
|
|
|
function loadPMMessageRequest($display_pms, $sort_by_query, $sort_by, $descending, $display_mode = '', $folder = '') |
1971
|
|
|
{ |
1972
|
|
|
$db = database(); |
1973
|
|
|
|
1974
|
|
|
$messages_request = $db->query('', ' |
1975
|
|
|
SELECT |
1976
|
|
|
pm.id_pm, pm.subject, pm.id_member_from, pm.body, pm.msgtime, pm.from_name |
1977
|
|
|
FROM {db_prefix}personal_messages AS pm' . ($folder == 'sent' ? ' |
1978
|
|
|
LEFT JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm)' : '') . ($sort_by == 'name' ? ' |
1979
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = {raw:id_member})' : '') . ' |
1980
|
|
|
WHERE pm.id_pm IN ({array_int:display_pms})' . ($folder == 'sent' ? ' |
1981
|
|
|
GROUP BY pm.id_pm, pm.subject, pm.id_member_from, pm.body, pm.msgtime, pm.from_name' : '') . ' |
1982
|
|
|
ORDER BY ' . ($display_mode == 2 ? 'pm.id_pm' : $sort_by_query) . ($descending ? ' DESC' : ' ASC') . ' |
1983
|
|
|
LIMIT ' . count($display_pms), |
1984
|
|
|
array( |
1985
|
|
|
'display_pms' => $display_pms, |
1986
|
|
|
'id_member' => $folder == 'sent' ? 'pmr.id_member' : 'pm.id_member_from', |
1987
|
|
|
) |
1988
|
|
|
); |
1989
|
|
|
|
1990
|
|
|
return $messages_request; |
1991
|
|
|
} |
1992
|
|
|
|
1993
|
|
|
/** |
1994
|
|
|
* Simple function to validate that a PM was sent to the current user |
1995
|
|
|
* |
1996
|
|
|
* @package PersonalMessage |
1997
|
|
|
* @param int $pmsg id of the pm we are checking |
1998
|
|
|
*/ |
1999
|
|
|
function checkPMReceived($pmsg) |
2000
|
|
|
{ |
2001
|
|
|
global $user_info; |
2002
|
|
|
|
2003
|
|
|
$db = database(); |
2004
|
|
|
|
2005
|
|
|
$request = $db->query('', ' |
2006
|
|
|
SELECT |
2007
|
|
|
id_pm |
2008
|
|
|
FROM {db_prefix}pm_recipients |
2009
|
|
|
WHERE id_pm = {int:id_pm} |
2010
|
|
|
AND id_member = {int:current_member} |
2011
|
|
|
LIMIT 1', |
2012
|
|
|
array( |
2013
|
|
|
'current_member' => $user_info['id'], |
2014
|
|
|
'id_pm' => $pmsg, |
2015
|
|
|
) |
2016
|
|
|
); |
2017
|
|
|
$isReceived = $db->num_rows($request) != 0; |
2018
|
|
|
$db->free_result($request); |
2019
|
|
|
|
2020
|
|
|
return $isReceived; |
2021
|
|
|
} |
2022
|
|
|
|
2023
|
|
|
/** |
2024
|
|
|
* Loads a pm by ID for use as a quoted pm in a new message |
2025
|
|
|
* |
2026
|
|
|
* @package PersonalMessage |
2027
|
|
|
* @param int $pmsg |
2028
|
|
|
* @param boolean $isReceived |
2029
|
|
|
*/ |
2030
|
|
|
function loadPMQuote($pmsg, $isReceived) |
2031
|
|
|
{ |
2032
|
|
|
global $user_info; |
2033
|
|
|
|
2034
|
|
|
$db = database(); |
2035
|
|
|
|
2036
|
|
|
// Get the quoted message (and make sure you're allowed to see this quote!). |
2037
|
|
|
$request = $db->query('', ' |
2038
|
|
|
SELECT |
2039
|
|
|
pm.id_pm, CASE WHEN pm.id_pm_head = {int:id_pm_head_empty} THEN pm.id_pm ELSE pm.id_pm_head END AS pm_head, |
2040
|
|
|
pm.body, pm.subject, pm.msgtime, |
2041
|
|
|
mem.member_name, COALESCE(mem.id_member, 0) AS id_member, COALESCE(mem.real_name, pm.from_name) AS real_name |
2042
|
|
|
FROM {db_prefix}personal_messages AS pm' . (!$isReceived ? '' : ' |
2043
|
|
|
INNER JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = {int:id_pm})') . ' |
2044
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = pm.id_member_from) |
2045
|
|
|
WHERE pm.id_pm = {int:id_pm}' . (!$isReceived ? ' |
2046
|
|
|
AND pm.id_member_from = {int:current_member}' : ' |
2047
|
|
|
AND pmr.id_member = {int:current_member}') . ' |
2048
|
|
|
LIMIT 1', |
2049
|
|
|
array( |
2050
|
|
|
'current_member' => $user_info['id'], |
2051
|
|
|
'id_pm_head_empty' => 0, |
2052
|
|
|
'id_pm' => $pmsg, |
2053
|
|
|
) |
2054
|
|
|
); |
2055
|
|
|
$row_quoted = $db->fetch_assoc($request); |
2056
|
|
|
$db->free_result($request); |
2057
|
|
|
|
2058
|
|
|
return empty($row_quoted) ? false : $row_quoted; |
2059
|
|
|
} |
2060
|
|
|
|
2061
|
|
|
/** |
2062
|
|
|
* For a given PM ID, loads all "other" recipients, (excludes the current member) |
2063
|
|
|
* |
2064
|
|
|
* - Will optionally count the number of bcc recipients and return that count |
2065
|
|
|
* |
2066
|
|
|
* @package PersonalMessage |
2067
|
|
|
* @param int $pmsg |
2068
|
|
|
* @param boolean $bcc_count |
2069
|
|
|
*/ |
2070
|
|
|
function loadPMRecipientsAll($pmsg, $bcc_count = false) |
2071
|
|
|
{ |
2072
|
|
|
global $user_info, $scripturl, $txt; |
2073
|
|
|
|
2074
|
|
|
$db = database(); |
2075
|
|
|
|
2076
|
|
|
$request = $db->query('', ' |
2077
|
|
|
SELECT |
2078
|
|
|
mem.id_member, mem.real_name, pmr.bcc |
2079
|
|
|
FROM {db_prefix}pm_recipients AS pmr |
2080
|
|
|
INNER JOIN {db_prefix}members AS mem ON (mem.id_member = pmr.id_member) |
2081
|
|
|
WHERE pmr.id_pm = {int:id_pm} |
2082
|
|
|
AND pmr.id_member != {int:current_member}' . ($bcc_count === true ? '' : ' |
2083
|
|
|
AND pmr.bcc = {int:not_bcc}'), |
2084
|
|
|
array( |
2085
|
|
|
'current_member' => $user_info['id'], |
2086
|
|
|
'id_pm' => $pmsg, |
2087
|
|
|
'not_bcc' => 0, |
2088
|
|
|
) |
2089
|
|
|
); |
2090
|
|
|
$recipients = array(); |
2091
|
|
|
$hidden_recipients = 0; |
2092
|
|
|
while ($row = $db->fetch_assoc($request)) |
2093
|
|
|
{ |
2094
|
|
|
// If it's hidden we still don't reveal their names |
2095
|
|
|
if ($bcc_count && $row['bcc']) |
2096
|
|
|
$hidden_recipients++; |
2097
|
|
|
|
2098
|
|
|
$recipients[] = array( |
2099
|
|
|
'id' => $row['id_member'], |
2100
|
|
|
'name' => htmlspecialchars($row['real_name'], ENT_COMPAT, 'UTF-8'), |
2101
|
|
|
'link' => '[url=' . $scripturl . '?action=profile;u=' . $row['id_member'] . ']' . $row['real_name'] . '[/url]', |
2102
|
|
|
); |
2103
|
|
|
} |
2104
|
|
|
|
2105
|
|
|
// If bcc count was requested, we return the number of bcc members, but not the names |
2106
|
|
|
if ($bcc_count) |
2107
|
|
|
$recipients[] = array( |
2108
|
|
|
'id' => 'bcc', |
2109
|
|
|
'name' => sprintf($txt['pm_report_pm_hidden'], $hidden_recipients), |
2110
|
|
|
'link' => sprintf($txt['pm_report_pm_hidden'], $hidden_recipients) |
2111
|
|
|
); |
2112
|
|
|
|
2113
|
|
|
$db->free_result($request); |
2114
|
|
|
|
2115
|
|
|
return $recipients; |
2116
|
|
|
} |
2117
|
|
|
|
2118
|
|
|
/** |
2119
|
|
|
* Simply loads a personal message by ID |
2120
|
|
|
* |
2121
|
|
|
* - Supplied ID must have been sent to the user id requesting it and it must not have been deleted |
2122
|
|
|
* |
2123
|
|
|
* @package PersonalMessage |
2124
|
|
|
* |
2125
|
|
|
* @param int $pm_id |
2126
|
|
|
* |
2127
|
|
|
* @return |
2128
|
|
|
* @throws Elk_Exception no_access |
2129
|
|
|
*/ |
2130
|
|
|
function loadPersonalMessage($pm_id) |
2131
|
|
|
{ |
2132
|
|
|
global $user_info; |
2133
|
|
|
|
2134
|
|
|
$db = database(); |
2135
|
|
|
|
2136
|
|
|
// First, pull out the message contents, and verify it actually went to them! |
2137
|
|
|
$request = $db->query('', ' |
2138
|
|
|
SELECT |
2139
|
|
|
pm.subject, pm.body, pm.msgtime, pm.id_member_from, |
2140
|
|
|
COALESCE(m.real_name, pm.from_name) AS sender_name, |
2141
|
|
|
pm.from_name AS poster_name, msgtime |
2142
|
|
|
FROM {db_prefix}personal_messages AS pm |
2143
|
|
|
INNER JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm) |
2144
|
|
|
LEFT JOIN {db_prefix}members AS m ON (m.id_member = pm.id_member_from) |
2145
|
|
|
WHERE pm.id_pm = {int:id_pm} |
2146
|
|
|
AND pmr.id_member = {int:current_member} |
2147
|
|
|
AND pmr.deleted = {int:not_deleted} |
2148
|
|
|
LIMIT 1', |
2149
|
|
|
array( |
2150
|
|
|
'current_member' => $user_info['id'], |
2151
|
|
|
'id_pm' => $pm_id, |
2152
|
|
|
'not_deleted' => 0, |
2153
|
|
|
) |
2154
|
|
|
); |
2155
|
|
|
// Can only be a hacker here! |
2156
|
|
|
if ($db->num_rows($request) == 0) |
2157
|
|
|
throw new Elk_Exception('no_access', false); |
2158
|
|
|
$pm_details = $db->fetch_row($request); |
2159
|
|
|
$db->free_result($request); |
2160
|
|
|
|
2161
|
|
|
return $pm_details; |
2162
|
|
|
} |
2163
|
|
|
|
2164
|
|
|
/** |
2165
|
|
|
* Finds the number of results that a search would produce |
2166
|
|
|
* |
2167
|
|
|
* @package PersonalMessage |
2168
|
|
|
* @param string $userQuery raw query, used if we are searching for specific users |
2169
|
|
|
* @param string $labelQuery raw query, used if we are searching only specific labels |
2170
|
|
|
* @param string $timeQuery raw query, used if we are limiting results to time periods |
2171
|
|
|
* @param string $searchQuery raw query, the actual thing you are searching for in the subject and/or body |
2172
|
|
|
* @param mixed[] $searchq_parameters value parameters used in the above query |
2173
|
|
|
* @return integer |
2174
|
|
|
*/ |
2175
|
|
|
function numPMSeachResults($userQuery, $labelQuery, $timeQuery, $searchQuery, $searchq_parameters) |
2176
|
|
|
{ |
2177
|
|
|
global $context, $user_info; |
2178
|
|
|
|
2179
|
|
|
$db = database(); |
2180
|
|
|
|
2181
|
|
|
// Get the amount of results. |
2182
|
|
|
$request = $db->query('', ' |
2183
|
|
|
SELECT |
2184
|
|
|
COUNT(*) |
2185
|
|
|
FROM {db_prefix}pm_recipients AS pmr |
2186
|
|
|
INNER JOIN {db_prefix}personal_messages AS pm ON (pm.id_pm = pmr.id_pm) |
2187
|
|
|
WHERE ' . ($context['folder'] == 'inbox' ? ' |
2188
|
|
|
pmr.id_member = {int:current_member} |
2189
|
|
|
AND pmr.deleted = {int:not_deleted}' : ' |
2190
|
|
|
pm.id_member_from = {int:current_member} |
2191
|
|
|
AND pm.deleted_by_sender = {int:not_deleted}') . ' |
2192
|
|
|
' . $userQuery . $labelQuery . $timeQuery . ' |
2193
|
|
|
AND (' . $searchQuery . ')', |
2194
|
|
|
array_merge($searchq_parameters, array( |
2195
|
|
|
'current_member' => $user_info['id'], |
2196
|
|
|
'not_deleted' => 0, |
2197
|
|
|
)) |
2198
|
|
|
); |
2199
|
|
|
list ($numResults) = $db->fetch_row($request); |
2200
|
|
|
$db->free_result($request); |
2201
|
|
|
|
2202
|
|
|
return $numResults; |
2203
|
|
|
} |
2204
|
|
|
|
2205
|
|
|
/** |
2206
|
|
|
* Gets all the matching message ids, senders and head pm nodes, using standard search only (No caching and the like!) |
2207
|
|
|
* |
2208
|
|
|
* @package PersonalMessage |
2209
|
|
|
* @param string $userQuery raw query, used if we are searching for specific users |
2210
|
|
|
* @param string $labelQuery raw query, used if we are searching only specific labels |
2211
|
|
|
* @param string $timeQuery raw query, used if we are limiting results to time periods |
2212
|
|
|
* @param string $searchQuery raw query, the actual thing you are searching for in the subject and/or body |
2213
|
|
|
* @param mixed[] $searchq_parameters value parameters used in the above query |
2214
|
|
|
* @param mixed[] $search_params additional search parameters, like sort and direction |
2215
|
|
|
*/ |
2216
|
|
|
function loadPMSearchMessages($userQuery, $labelQuery, $timeQuery, $searchQuery, $searchq_parameters, $search_params) |
2217
|
|
|
{ |
2218
|
|
|
global $context, $modSettings, $user_info; |
2219
|
|
|
|
2220
|
|
|
$db = database(); |
2221
|
|
|
|
2222
|
|
|
$request = $db->query('', ' |
2223
|
|
|
SELECT |
2224
|
|
|
pm.id_pm, pm.id_pm_head, pm.id_member_from |
2225
|
|
|
FROM {db_prefix}pm_recipients AS pmr |
2226
|
|
|
INNER JOIN {db_prefix}personal_messages AS pm ON (pm.id_pm = pmr.id_pm) |
2227
|
|
|
WHERE ' . ($context['folder'] == 'inbox' ? ' |
2228
|
|
|
pmr.id_member = {int:current_member} |
2229
|
|
|
AND pmr.deleted = {int:not_deleted}' : ' |
2230
|
|
|
pm.id_member_from = {int:current_member} |
2231
|
|
|
AND pm.deleted_by_sender = {int:not_deleted}') . ' |
2232
|
|
|
' . $userQuery . $labelQuery . $timeQuery . ' |
2233
|
|
|
AND (' . $searchQuery . ') |
2234
|
|
|
ORDER BY ' . $search_params['sort'] . ' ' . $search_params['sort_dir'] . ' |
2235
|
|
|
LIMIT ' . $context['start'] . ', ' . $modSettings['search_results_per_page'], |
2236
|
|
|
array_merge($searchq_parameters, array( |
2237
|
|
|
'current_member' => $user_info['id'], |
2238
|
|
|
'not_deleted' => 0, |
2239
|
|
|
)) |
2240
|
|
|
); |
2241
|
|
|
$foundMessages = array(); |
2242
|
|
|
$posters = array(); |
2243
|
|
|
$head_pms = array(); |
2244
|
|
|
while ($row = $db->fetch_assoc($request)) |
2245
|
|
|
{ |
2246
|
|
|
$foundMessages[] = $row['id_pm']; |
2247
|
|
|
$posters[] = $row['id_member_from']; |
2248
|
|
|
$head_pms[$row['id_pm']] = $row['id_pm_head']; |
2249
|
|
|
} |
2250
|
|
|
$db->free_result($request); |
2251
|
|
|
|
2252
|
|
|
return array($foundMessages, $posters, $head_pms); |
2253
|
|
|
} |
2254
|
|
|
|
2255
|
|
|
/** |
2256
|
|
|
* When we are in conversation view, we need to find the base head pm of the |
2257
|
|
|
* conversation. This will set the root head id to each of the node heads |
2258
|
|
|
* |
2259
|
|
|
* @package PersonalMessage |
2260
|
|
|
* @param int[] $head_pms array of pm ids that were found in the id_pm_head col |
2261
|
|
|
* during the initial search |
2262
|
|
|
*/ |
2263
|
|
View Code Duplication |
function loadPMSearchHeads($head_pms) |
|
|
|
|
2264
|
|
|
{ |
2265
|
|
|
global $user_info; |
2266
|
|
|
|
2267
|
|
|
$db = database(); |
2268
|
|
|
|
2269
|
|
|
$request = $db->query('', ' |
2270
|
|
|
SELECT |
2271
|
|
|
MAX(pm.id_pm) AS id_pm, pm.id_pm_head |
2272
|
|
|
FROM {db_prefix}personal_messages AS pm |
2273
|
|
|
INNER JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm) |
2274
|
|
|
WHERE pm.id_pm_head IN ({array_int:head_pms}) |
2275
|
|
|
AND pmr.id_member = {int:current_member} |
2276
|
|
|
AND pmr.deleted = {int:not_deleted} |
2277
|
|
|
GROUP BY pm.id_pm_head |
2278
|
|
|
LIMIT {int:limit}', |
2279
|
|
|
array( |
2280
|
|
|
'head_pms' => array_unique($head_pms), |
2281
|
|
|
'current_member' => $user_info['id'], |
2282
|
|
|
'not_deleted' => 0, |
2283
|
|
|
'limit' => count($head_pms), |
2284
|
|
|
) |
2285
|
|
|
); |
2286
|
|
|
$real_pm_ids = array(); |
2287
|
|
|
while ($row = $db->fetch_assoc($request)) |
2288
|
|
|
$real_pm_ids[$row['id_pm_head']] = $row['id_pm']; |
2289
|
|
|
$db->free_result($request); |
2290
|
|
|
|
2291
|
|
|
return $real_pm_ids; |
2292
|
|
|
} |
2293
|
|
|
|
2294
|
|
|
/** |
2295
|
|
|
* Loads the actual details of the PM's that were found during the search stage |
2296
|
|
|
* |
2297
|
|
|
* @package PersonalMessage |
2298
|
|
|
* @param int[] $foundMessages array of found message id's |
2299
|
|
|
* @param mixed[] $search_params as specified in the form, here used for sorting |
2300
|
|
|
*/ |
2301
|
|
|
function loadPMSearchResults($foundMessages, $search_params) |
2302
|
|
|
{ |
2303
|
|
|
$db = database(); |
2304
|
|
|
|
2305
|
|
|
// Prepare the query for the callback! |
2306
|
|
|
$request = $db->query('', ' |
2307
|
|
|
SELECT |
2308
|
|
|
pm.id_pm, pm.subject, pm.id_member_from, pm.body, pm.msgtime, pm.from_name |
2309
|
|
|
FROM {db_prefix}personal_messages AS pm |
2310
|
|
|
WHERE pm.id_pm IN ({array_int:message_list}) |
2311
|
|
|
ORDER BY ' . $search_params['sort'] . ' ' . $search_params['sort_dir'] . ' |
2312
|
|
|
LIMIT ' . count($foundMessages), |
2313
|
|
|
array( |
2314
|
|
|
'message_list' => $foundMessages, |
2315
|
|
|
) |
2316
|
|
|
); |
2317
|
|
|
$search_results = array(); |
2318
|
|
|
while ($row = $db->fetch_assoc($request)) |
2319
|
|
|
$search_results[] = $row; |
2320
|
|
|
$db->free_result($request); |
2321
|
|
|
|
2322
|
|
|
return $search_results; |
2323
|
|
|
} |
2324
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.