1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file contains the database work for likes. |
5
|
|
|
* |
6
|
|
|
* @package ElkArte Forum |
7
|
|
|
* @copyright ElkArte Forum contributors |
8
|
|
|
* @license BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file) |
9
|
|
|
* |
10
|
|
|
* @version 2.0 dev |
11
|
|
|
* |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
use BBC\ParserWrapper; |
15
|
|
|
use ElkArte\Helper\Util; |
16
|
|
|
use ElkArte\MembersList; |
17
|
|
|
use ElkArte\User; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* Updates the like value for a post/member combo if there are no problems with |
21
|
|
|
* the request, such as being a narcissist |
22
|
|
|
* |
23
|
|
|
* @param int $id_liker - user_id of the liker/disliker |
24
|
|
|
* @param mixed $liked_message - message array that is being worked on |
25
|
|
|
* @param string $direction - + for like - for unlike a previous liked one |
26
|
|
|
* |
27
|
|
|
* @return bool |
28
|
|
|
* @package Likes |
29
|
|
|
* |
30
|
|
|
*/ |
31
|
|
|
function likePost($id_liker, $liked_message, $direction) |
32
|
|
|
{ |
33
|
|
|
global $txt, $modSettings; |
34
|
6 |
|
|
35
|
|
|
// If we have a message, then we have passed all checks ... |
36
|
|
|
if (!empty($liked_message)) |
37
|
6 |
|
{ |
38
|
|
|
// You can't like your own stuff, no matter how brilliant you think you are |
39
|
|
|
if ($liked_message['id_member'] == $id_liker && empty($modSettings['likeAllowSelf'])) |
40
|
4 |
|
{ |
41
|
|
|
return $txt['cant_like_yourself']; |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
updateLike($id_liker, $liked_message, $direction); |
45
|
|
|
|
46
|
4 |
|
return true; |
47
|
|
|
} |
48
|
4 |
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
2 |
|
* Loads the likes for a group of messages |
52
|
|
|
* Returns an array of message_id to members who liked that post |
53
|
|
|
* If prepare is true, will also prep the array for template use |
54
|
|
|
* |
55
|
|
|
* @param int[]|int $messages |
56
|
|
|
* @param bool $prepare |
57
|
|
|
* |
58
|
|
|
* @return array|int[] |
59
|
|
|
* @package Likes |
60
|
|
|
* |
61
|
|
|
*/ |
62
|
|
|
function loadLikes($messages, $prepare = true) |
63
|
|
|
{ |
64
|
|
|
$db = database(); |
65
|
|
|
$likes = []; |
66
|
|
|
|
67
|
|
|
if (empty($messages)) |
68
|
8 |
|
{ |
69
|
8 |
|
return $likes; |
70
|
|
|
} |
71
|
8 |
|
|
72
|
|
|
if (!is_array($messages)) |
73
|
|
|
{ |
74
|
|
|
$messages = [(int) $messages]; |
75
|
|
|
} |
76
|
8 |
|
|
77
|
|
|
// Load up them likes from the db |
78
|
4 |
|
$db->fetchQuery(' |
79
|
|
|
SELECT |
80
|
|
|
l.id_member, l.id_msg, |
81
|
|
|
m.real_name |
82
|
8 |
|
FROM {db_prefix}message_likes AS l |
83
|
|
|
LEFT JOIN {db_prefix}members AS m ON (m.id_member = l.id_member) |
84
|
|
|
WHERE id_msg IN ({array_int:id_messages})', |
85
|
|
|
[ |
86
|
|
|
'id_messages' => $messages, |
87
|
|
|
] |
88
|
|
|
)->fetch_callback( |
89
|
|
|
function ($row) use (&$likes) { |
90
|
8 |
|
$likes[$row['id_msg']]['member'][$row['id_member']] = $row['real_name']; |
91
|
|
|
} |
92
|
8 |
|
); |
93
|
|
|
|
94
|
6 |
|
// Total likes for this group |
95
|
8 |
|
foreach ($likes as $msg_id => $like) |
96
|
|
|
{ |
97
|
|
|
$likes[$msg_id]['count'] = count($like['member']); |
98
|
|
|
} |
99
|
8 |
|
|
100
|
|
|
if ($prepare) |
101
|
6 |
|
{ |
102
|
|
|
$likes = prepareLikes($likes); |
103
|
|
|
} |
104
|
8 |
|
|
105
|
|
|
return $likes; |
106
|
6 |
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
8 |
|
* Prepares the like array for use in the template |
110
|
|
|
* |
111
|
|
|
* What it does: |
112
|
|
|
* |
113
|
|
|
* - Replaces the current member id with 'You' if they like a post and makes it first |
114
|
|
|
* - Truncates the like list at a given number and adds in +x others |
115
|
|
|
* |
116
|
|
|
* @param array $likes array of like ids to process |
117
|
|
|
* |
118
|
|
|
* @return int[] |
119
|
|
|
* @package Likes |
120
|
|
|
*/ |
121
|
|
|
function prepareLikes($likes) |
122
|
|
|
{ |
123
|
|
|
global $modSettings, $txt; |
124
|
|
|
|
125
|
|
|
// Prepare this like page context for the user |
126
|
|
|
foreach ($likes as $msg_id => $like) |
127
|
6 |
|
{ |
128
|
|
|
// Did they like this message ? |
129
|
|
|
$you_liked = isset($like['member'][User::$info->id]); |
|
|
|
|
130
|
6 |
|
if ($you_liked) |
131
|
|
|
{ |
132
|
|
|
unset($likes[$msg_id]['member'][User::$info->id]); |
133
|
4 |
|
} |
134
|
4 |
|
|
135
|
|
|
// Any limits on how many to display |
136
|
4 |
|
$limit = $modSettings['likeDisplayLimit'] ?? 0; |
137
|
|
|
|
138
|
|
|
// If there are a lot of likes for this message, we cull the herd |
139
|
|
|
if ($limit > 0 && $like['count'] > $limit) |
140
|
4 |
|
{ |
141
|
|
|
// Mix up the line, so we don't show the same ones every time |
142
|
|
|
shuffle($likes[$msg_id]['member']); |
143
|
4 |
|
$likes[$msg_id]['member'] = array_slice($likes[$msg_id]['member'], 0, $you_liked ? $limit - 1 : $limit); |
144
|
|
|
|
145
|
|
|
// Trick, member id's below $limit will cause a wrong +x others due to the slice above |
146
|
|
|
if (User::$info->id <= $limit) |
147
|
|
|
{ |
148
|
|
|
$like['count'] += 1; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
// How many others liked this |
152
|
|
|
$likes[$msg_id]['member'][] = sprintf('%+d %s', ($like['count'] - $limit), $txt['liked_more']); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
// Top billing just for you, the big lights, the grand stage, plus we need that key returned |
156
|
|
|
if ($you_liked) |
157
|
|
|
{ |
158
|
|
|
$likes[$msg_id]['member'] = [User::$info->id => $txt['liked_you']] + $likes[$msg_id]['member']; |
159
|
|
|
} |
160
|
4 |
|
} |
161
|
|
|
|
162
|
4 |
|
return $likes; |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
6 |
|
* Clear the likes log of older actions ... used to prevent a like love fest |
167
|
|
|
* |
168
|
|
|
* @param int $likeWaitTime |
169
|
|
|
* @package Likes |
170
|
|
|
*/ |
171
|
|
|
function clearLikes($likeWaitTime) |
172
|
|
|
{ |
173
|
|
|
$db = database(); |
174
|
|
|
|
175
|
|
|
// Delete all older items from the log |
176
|
|
|
$db->query('', ' |
177
|
|
|
DELETE FROM {db_prefix}log_likes |
178
|
2 |
|
WHERE {int:current_time} - log_time > {int:wait_time}', |
179
|
|
|
[ |
180
|
|
|
'wait_time' => $likeWaitTime * 60, |
181
|
2 |
|
'current_time' => time(), |
182
|
|
|
] |
183
|
|
|
); |
184
|
|
|
} |
185
|
2 |
|
|
186
|
2 |
|
/** |
187
|
|
|
* Checks if the member has exceeded the number of like actions they are |
188
|
|
|
* allowed in a given time period. |
189
|
2 |
|
* |
190
|
|
|
* - The log is maintained to the time period by the clearLikes function so |
191
|
|
|
* the count is always current. |
192
|
|
|
* - returns true if they can like again, or false if they have to wait a bit |
193
|
|
|
* |
194
|
|
|
* @param int $id_liker |
195
|
|
|
* |
196
|
|
|
* @return bool |
197
|
|
|
* @package Likes |
198
|
|
|
* |
199
|
|
|
*/ |
200
|
|
|
function lastLikeOn($id_liker) |
201
|
|
|
{ |
202
|
|
|
global $modSettings; |
203
|
|
|
|
204
|
|
|
if (empty($modSettings['likeWaitCount'])) |
205
|
|
|
{ |
206
|
|
|
return true; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
// Find out if, and how many, this user has done recently... |
210
|
|
|
$db = database(); |
211
|
|
|
$request = $db->query('', ' |
212
|
|
|
SELECT |
213
|
|
|
action |
214
|
|
|
FROM {db_prefix}log_likes |
215
|
|
|
WHERE id_member = {int:current_member}', |
216
|
|
|
[ |
217
|
|
|
'current_member' => $id_liker, |
218
|
|
|
] |
219
|
|
|
); |
220
|
|
|
$actions = $request->num_rows(); |
221
|
|
|
$request->free_result(); |
222
|
|
|
|
223
|
|
|
return $actions < $modSettings['likeWaitCount']; |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* Perform a like action, either + or - |
228
|
|
|
* |
229
|
|
|
* @param int $id_liker |
230
|
|
|
* @param int[] $liked_message |
231
|
|
|
* @param string $direction - options: - or + |
232
|
|
|
* @package Likes |
233
|
|
|
*/ |
234
|
|
|
function updateLike($id_liker, $liked_message, $direction) |
235
|
|
|
{ |
236
|
|
|
$db = database(); |
237
|
|
|
|
238
|
|
|
// See if they already likeyed this message |
239
|
|
|
$request = $db->query('', ' |
240
|
|
|
SELECT |
241
|
|
|
id_member |
242
|
|
|
FROM {db_prefix}message_likes |
243
|
4 |
|
WHERE id_member = {int:id_member} |
244
|
|
|
AND id_msg = {int:id_msg} |
245
|
|
|
LIMIT 1', |
246
|
4 |
|
[ |
247
|
|
|
'id_member' => $id_liker, |
248
|
|
|
'id_msg' => $liked_message['id_msg'], |
249
|
|
|
] |
250
|
|
|
); |
251
|
|
|
$count = $request->num_rows(); |
252
|
|
|
$request->free_result(); |
253
|
|
|
|
254
|
4 |
|
// Not previously liked, and you want to |
255
|
4 |
|
if ($count === 0 && $direction === '+') |
256
|
|
|
{ |
257
|
|
|
$db->insert('', |
258
|
4 |
|
'{db_prefix}message_likes', |
259
|
4 |
|
['id_member' => 'int', 'id_msg' => 'int', 'id_poster' => 'int', 'like_timestamp' => 'int',], |
260
|
|
|
[$id_liker, $liked_message['id_msg'], $liked_message['id_member'], time()], |
261
|
|
|
['id_msg', 'id_member', 'id_poster'] |
262
|
4 |
|
); |
263
|
|
|
|
264
|
4 |
|
// If we are liking the first message in a topic, we are de facto liking the topic |
265
|
4 |
|
if ($liked_message['id_msg'] === $liked_message['id_first_msg']) |
266
|
4 |
|
{ |
267
|
4 |
|
increaseTopicLikes($liked_message['id_topic'], $direction); |
268
|
4 |
|
} |
269
|
|
|
|
270
|
|
|
// And update the stats |
271
|
|
|
require_once(SUBSDIR . '/Members.subs.php'); |
272
|
4 |
|
updateMemberData($id_liker, ['likes_given' => '+']); |
273
|
|
|
updateMemberData($liked_message['id_member'], ['likes_received' => '+']); |
274
|
4 |
|
} |
275
|
|
|
// Or you are just being fickle? |
276
|
|
|
elseif ($count !== 0 && $direction === '-') |
277
|
|
|
{ |
278
|
4 |
|
$db->query('', ' |
279
|
4 |
|
DELETE FROM {db_prefix}message_likes |
280
|
4 |
|
WHERE id_member = {int:id_member} |
281
|
|
|
AND id_msg = {int:id_msg}', |
282
|
|
|
[ |
283
|
|
|
'id_member' => $id_liker, |
284
|
|
|
'id_msg' => $liked_message['id_msg'], |
285
|
|
|
] |
286
|
|
|
); |
287
|
|
|
|
288
|
|
|
// If we are unliking the first message in a topic, we are de facto unliking the topic |
289
|
|
|
if ($liked_message['id_msg'] === $liked_message['id_first_msg']) |
290
|
|
|
{ |
291
|
|
|
increaseTopicLikes($liked_message['id_topic'], $direction); |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
// And update the stats |
295
|
|
|
require_once(SUBSDIR . '/Members.subs.php'); |
296
|
|
|
updateMemberData($id_liker, ['likes_given' => '-']); |
297
|
|
|
updateMemberData($liked_message['id_member'], ['likes_received' => '-']); |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
// Put it in the log so we can prevent flooding the system with likes |
301
|
|
|
$db->replace( |
302
|
|
|
'{db_prefix}log_likes', |
303
|
|
|
['action' => 'string', 'id_target' => 'int', 'id_member' => 'int', 'log_time' => 'int'], |
304
|
|
|
[$direction, $liked_message['id_msg'], $id_liker, time()], |
305
|
|
|
['id_target', 'id_member'] |
306
|
|
|
); |
307
|
|
|
} |
308
|
4 |
|
|
309
|
4 |
|
/** |
310
|
4 |
|
* Increase the number of likes for this topic. |
311
|
4 |
|
* |
312
|
4 |
|
* @param int $id_topic - the topic |
313
|
|
|
* @param string $direction +/- liking or unliking |
314
|
4 |
|
* @package Likes |
315
|
|
|
*/ |
316
|
|
|
function increaseTopicLikes($id_topic, $direction) |
317
|
|
|
{ |
318
|
|
|
$db = database(); |
319
|
|
|
|
320
|
|
|
$db->query('', ' |
321
|
|
|
UPDATE {db_prefix}topics |
322
|
|
|
SET |
323
|
|
|
num_likes = num_likes ' . ($direction === '+' ? '+ 1' : '- 1') . ' |
324
|
|
|
WHERE id_topic = {int:current_topic}', |
325
|
|
|
[ |
326
|
4 |
|
'current_topic' => $id_topic, |
327
|
|
|
] |
328
|
4 |
|
); |
329
|
|
|
} |
330
|
|
|
|
331
|
4 |
|
/** |
332
|
|
|
* Return how many likes a user has given or the count of their posts that |
333
|
|
|
* have received a like (not the total likes received) |
334
|
4 |
|
* |
335
|
|
|
* @param int $memberID |
336
|
|
|
* @param bool $given |
337
|
4 |
|
* |
338
|
|
|
* @return int |
339
|
|
|
* @package Likes |
340
|
|
|
* |
341
|
|
|
*/ |
342
|
|
|
function likesCount($memberID, $given = true) |
343
|
|
|
{ |
344
|
|
|
$db = database(); |
345
|
|
|
|
346
|
|
|
// Give is a given, received takes a query so its only the unique messages |
347
|
|
|
if ($given) |
348
|
|
|
{ |
349
|
|
|
$likes = MembersList::get($memberID)->likes_given; |
|
|
|
|
350
|
|
|
} |
351
|
|
|
else |
352
|
|
|
{ |
353
|
2 |
|
$request = $db->query('', ' |
354
|
|
|
SELECT |
355
|
|
|
COUNT(*) |
356
|
2 |
|
FROM {db_prefix}message_likes |
357
|
|
|
WHERE id_poster = {int:id_member}', |
358
|
2 |
|
[ |
359
|
|
|
'id_member' => $memberID, |
360
|
|
|
] |
361
|
|
|
); |
362
|
|
|
$likes = $request->num_rows(); |
363
|
|
|
$request->free_result(); |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
return $likes; |
367
|
|
|
} |
368
|
|
|
|
369
|
|
|
/** |
370
|
|
|
* Return an array of details based on posts a user has liked |
371
|
|
|
* |
372
|
|
|
* Used for action=profile;area=showlikes;sa=given |
373
|
|
|
* |
374
|
|
|
* @param int $start The item to start with (for pagination purposes) |
375
|
|
|
* @param int $items_per_page The number of items to show per page |
376
|
2 |
|
* @param string $sort A string indicating how to sort the results |
377
|
|
|
* @param int $memberID |
378
|
|
|
* |
379
|
|
|
* @return array |
380
|
|
|
* @package Likes |
381
|
|
|
* |
382
|
|
|
*/ |
383
|
|
|
function likesPostsGiven($start, $items_per_page, $sort, $memberID) |
384
|
|
|
{ |
385
|
|
|
global $scripturl, $context, $modSettings; |
386
|
|
|
|
387
|
|
|
$db = database(); |
388
|
|
|
|
389
|
|
|
// Load up what the user likes from the db |
390
|
|
|
return $db->fetchQuery(' |
391
|
|
|
SELECT |
392
|
|
|
l.id_member, l.id_msg, |
393
|
|
|
m.subject, m.poster_name, m.id_board, m.id_topic, |
394
|
|
|
b.name |
395
|
|
|
FROM {db_prefix}message_likes AS l |
396
|
2 |
|
LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = l.id_msg) |
397
|
|
|
LEFT JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board) |
398
|
2 |
|
WHERE l.id_member = {int:id_member}' . (!empty($modSettings['recycle_enable']) ? (' |
399
|
|
|
AND b.id_board != ' . $modSettings['recycle_board']) : '') . ' |
400
|
|
|
ORDER BY {raw:sort} |
401
|
2 |
|
LIMIT {int:per_page} OFFSET {int:start}', |
402
|
|
|
[ |
403
|
|
|
'id_member' => $memberID, |
404
|
|
|
'sort' => $sort, |
405
|
|
|
'start' => $start, |
406
|
|
|
'per_page' => $items_per_page, |
407
|
|
|
] |
408
|
|
|
)->fetch_callback( |
409
|
2 |
|
function ($row) use ($scripturl, $context) { |
410
|
2 |
|
return [ |
411
|
|
|
'subject' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'] . '">' . $row['subject'] . '</a>', |
412
|
|
|
'poster_name' => $row['poster_name'], |
413
|
|
|
'name' => $row['name'], |
414
|
2 |
|
'delete' => $scripturl . '?action=likes;sa=unlikepost;profile;msg=' . $row['id_msg'] . ';' . $context['session_var'] . '=' . $context['session_id'], |
415
|
2 |
|
]; |
416
|
2 |
|
} |
417
|
2 |
|
); |
418
|
|
|
} |
419
|
2 |
|
|
420
|
|
|
/** |
421
|
|
|
* Returns an array of details based on posts that others have liked of this user |
422
|
|
|
* Creates links to show the users who liked a post |
423
|
|
|
* |
424
|
|
|
* Used by action=profile;area=showlikes;sa=received |
425
|
|
|
* |
426
|
|
|
* @param int $start The item to start with (for pagination purposes) |
427
|
2 |
|
* @param int $items_per_page The number of items to show per page |
428
|
|
|
* @param string $sort A string indicating how to sort the results |
429
|
|
|
* @param int $memberID |
430
|
|
|
* |
431
|
|
|
* @return array |
432
|
|
|
* @package Likes |
433
|
|
|
* |
434
|
|
|
*/ |
435
|
|
|
function likesPostsReceived($start, $items_per_page, $sort, $memberID) |
436
|
|
|
{ |
437
|
|
|
global $scripturl, $modSettings; |
438
|
|
|
|
439
|
|
|
$db = database(); |
440
|
|
|
|
441
|
|
|
// Load up what the user likes from the db |
442
|
|
|
return $db->fetchQuery(' |
443
|
|
|
SELECT |
444
|
|
|
m.subject, m.id_topic, |
445
|
|
|
b.name, m.id_msg, COUNT(l.id_msg) AS likes |
446
|
|
|
FROM {db_prefix}message_likes AS l |
447
|
|
|
LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = l.id_msg) |
448
|
|
|
LEFT JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board) |
449
|
|
|
WHERE l.id_poster = {int:id_member}' . (!empty($modSettings['recycle_enable']) ? (' |
450
|
|
|
AND b.id_board != ' . $modSettings['recycle_board']) : '') . ' |
451
|
|
|
GROUP BY m.subject, m.id_topic, b.name, m.id_msg |
452
|
|
|
ORDER BY {raw:sort} |
453
|
|
|
LIMIT {int:per_page} OFFSET {int:start}', |
454
|
|
|
[ |
455
|
|
|
'id_member' => $memberID, |
456
|
|
|
'sort' => $sort, |
457
|
|
|
'start' => $start, |
458
|
|
|
'per_page' => $items_per_page, |
459
|
|
|
] |
460
|
|
|
)->fetch_callback( |
461
|
|
|
function ($row) use ($scripturl) { |
462
|
|
|
return [ |
463
|
|
|
'subject' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'] . '">' . $row['subject'] . '</a>', |
464
|
|
|
'name' => $row['name'], |
465
|
|
|
'who' => $scripturl . '?action=likes;sa=showWhoLiked;msg=' . $row['id_msg'], |
466
|
|
|
'likes' => $row['likes'] |
467
|
|
|
]; |
468
|
|
|
} |
469
|
|
|
); |
470
|
|
|
} |
471
|
|
|
|
472
|
|
|
/** |
473
|
|
|
* Function to load all likers of a message |
474
|
|
|
* |
475
|
|
|
* @param int $start The item to start with (for pagination purposes) |
476
|
|
|
* @param int $items_per_page The number of items to show per page |
477
|
|
|
* @param string $sort A string indicating how to sort the results |
478
|
|
|
* @param int $messageID |
479
|
|
|
* @param bool $simple |
480
|
|
|
* |
481
|
|
|
* @return array |
482
|
|
|
* @package Likes |
483
|
|
|
* |
484
|
|
|
*/ |
485
|
|
|
function postLikers($start, $items_per_page, $sort, $messageID, $simple = true) |
486
|
|
|
{ |
487
|
|
|
global $scripturl; |
488
|
|
|
|
489
|
|
|
$db = database(); |
490
|
|
|
$likes = []; |
491
|
|
|
|
492
|
|
|
if (empty($messageID)) |
493
|
|
|
{ |
494
|
|
|
return $likes; |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
// Load up the likes for this message |
498
|
|
|
return $db->fetchQuery(' |
499
|
|
|
SELECT |
500
|
|
|
l.id_member, l.id_msg, |
501
|
|
|
m.real_name' . ($simple ? '' : ', |
502
|
|
|
COALESCE(a.id_attach, 0) AS id_attach, |
503
|
|
|
a.filename, a.attachment_type, m.avatar, m.email_address') . ' |
504
|
|
|
FROM {db_prefix}message_likes AS l |
505
|
|
|
LEFT JOIN {db_prefix}members AS m ON (m.id_member = l.id_member)' . ($simple ? '' : ' |
506
|
|
|
LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = m.id_member)') . ' |
507
|
|
|
WHERE l.id_msg = {int:id_message} |
508
|
|
|
ORDER BY {raw:sort} |
509
|
|
|
LIMIT {int:per_page} OFFSET {int:start}', |
510
|
|
|
[ |
511
|
|
|
'id_message' => $messageID, |
512
|
|
|
'sort' => $sort, |
513
|
|
|
'start' => $start, |
514
|
|
|
'per_page' => $items_per_page, |
515
|
|
|
] |
516
|
|
|
)->fetch_callback( |
517
|
|
|
function ($row) use ($scripturl, $simple) { |
518
|
|
|
$like = [ |
519
|
|
|
'real_name' => $row['real_name'], |
520
|
|
|
'id_member' => $row['id_member'], |
521
|
|
|
'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>', |
522
|
|
|
]; |
523
|
|
|
if (!$simple) |
524
|
|
|
{ |
525
|
|
|
$avatar = determineAvatar($row); |
526
|
|
|
$like['href'] = !empty($row['id_member']) ? $scripturl . '?action=profile;u=' . $row['id_member'] : ''; |
527
|
|
|
$like['avatar'] = $avatar['href']; |
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
return $like; |
531
|
|
|
} |
532
|
|
|
); |
533
|
|
|
} |
534
|
|
|
|
535
|
|
|
/** |
536
|
|
|
* Function to get the number of likes for a message |
537
|
|
|
* |
538
|
|
|
* @param int $message |
539
|
|
|
* |
540
|
|
|
* @return int |
541
|
|
|
* @package Likes |
542
|
|
|
* |
543
|
|
|
*/ |
544
|
|
|
function messageLikeCount($message) |
545
|
|
|
{ |
546
|
|
|
$db = database(); |
547
|
|
|
$total = 0; |
548
|
|
|
|
549
|
|
|
if (empty($message)) |
550
|
|
|
{ |
551
|
|
|
return $total; |
552
|
|
|
} |
553
|
|
|
|
554
|
|
|
// Count up the likes for this message |
555
|
|
|
$request = $db->query('', ' |
556
|
|
|
SELECT COUNT(*) |
557
|
|
|
FROM {db_prefix}message_likes |
558
|
|
|
WHERE id_msg = {int:id_message}', |
559
|
|
|
[ |
560
|
4 |
|
'id_message' => $message, |
561
|
4 |
|
] |
562
|
|
|
); |
563
|
4 |
|
list ($total) = $request->fetch_row(); |
564
|
|
|
$request->free_result(); |
565
|
|
|
|
566
|
|
|
return (int) $total; |
567
|
|
|
} |
568
|
|
|
|
569
|
4 |
|
/** |
570
|
|
|
* Function to get most liked messages |
571
|
|
|
* |
572
|
|
|
* @param int $limit the number of top liked messages to fetch |
573
|
|
|
* |
574
|
4 |
|
* @return array |
575
|
|
|
* @package Likes |
576
|
|
|
*/ |
577
|
4 |
|
function dbMostLikedMessage($limit = 10) |
578
|
4 |
|
{ |
579
|
|
|
global $txt; |
580
|
4 |
|
|
581
|
|
|
$db = database(); |
582
|
|
|
|
583
|
|
|
// Most liked Message |
584
|
|
|
$mostLikedMessages = []; |
585
|
|
|
$bbc_parser = ParserWrapper::instance(); |
586
|
|
|
$db->fetchQuery(' |
587
|
|
|
SELECT |
588
|
|
|
COALESCE(mem.real_name, m.poster_name) AS member_received_name, |
589
|
|
|
lp.id_msg, lp.like_count AS like_count, |
590
|
|
|
m.id_topic, m.id_board, m.id_member, m.subject, m.body, m.poster_time, m.smileys_enabled, |
591
|
|
|
COALESCE(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type, |
592
|
|
|
mem.avatar, mem.posts, mem.email_address |
593
|
|
|
FROM ( |
594
|
|
|
SELECT |
595
|
|
|
COUNT(lp.id_msg) AS like_count, lp.id_msg |
596
|
|
|
FROM {db_prefix}message_likes AS lp |
597
|
|
|
GROUP BY lp.id_msg |
598
|
|
|
ORDER BY like_count DESC |
599
|
|
|
LIMIT {int:limit} |
600
|
|
|
) AS lp |
601
|
|
|
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = lp.id_msg) |
602
|
|
|
INNER JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) |
603
|
|
|
INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board) |
604
|
|
|
LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = m.id_member) |
605
|
|
|
WHERE {query_wanna_see_board} |
606
|
|
|
ORDER BY like_count DESC |
607
|
|
|
LIMIT {int:limit}', |
608
|
|
|
[ |
609
|
|
|
'limit' => $limit, |
610
|
|
|
] |
611
|
|
|
)->fetch_callback( |
612
|
|
|
function ($row) use (&$mostLikedMessages, $bbc_parser) { |
613
|
|
|
global $scripturl; |
614
|
|
|
|
615
|
|
|
// Censor it! |
616
|
|
|
$row['subject'] = censor($row['subject']); |
617
|
|
|
$row['body'] = censor($row['body']); |
618
|
|
|
|
619
|
|
|
$row['body'] = $bbc_parser->parseMessage($row['body'], $row['smileys_enabled']); |
620
|
|
|
|
621
|
|
|
// Something short and sweet |
622
|
|
|
$msgString = Util::shorten_html($row['body'], 255); |
623
|
|
|
$preview = Util::htmlspecialchars(strtr($msgString, ['<br />' => "\n", ' ' => ' '])); |
624
|
|
|
|
625
|
|
|
// Love those avatars |
626
|
|
|
$avatar = determineAvatar($row); |
627
|
|
|
|
628
|
|
|
// Build it out |
629
|
|
|
$mostLikedMessages[] = [ |
630
|
|
|
'id_msg' => $row['id_msg'], |
631
|
|
|
'id_topic' => $row['id_topic'], |
632
|
|
|
'id_board' => $row['id_board'], |
633
|
|
|
'like_count' => $row['like_count'], |
634
|
|
|
'subject' => $row['subject'], |
635
|
|
|
'preview' => $preview, |
636
|
|
|
'body' => $msgString, |
637
|
|
|
'time' => standardTime($row['poster_time']), |
638
|
|
|
'html_time' => htmlTime($row['poster_time']), |
639
|
|
|
'timestamp' => forum_time(true, $row['poster_time']), |
640
|
|
|
'member_received' => [ |
641
|
|
|
'id_member' => $row['id_member'], |
642
|
|
|
'name' => $row['member_received_name'], |
643
|
|
|
'total_posts' => $row['posts'], |
644
|
|
|
'href' => !empty($row['id_member']) ? $scripturl . '?action=profile;u=' . $row['id_member'] : '', |
645
|
|
|
'avatar' => $avatar['href'], |
646
|
|
|
], |
647
|
|
|
'member_liked_data' => postLikers(0, min($row['like_count'], 50), 'l.id_member DESC', $row['id_msg'], false), |
648
|
|
|
]; |
649
|
|
|
} |
650
|
|
|
); |
651
|
|
|
|
652
|
|
|
// No likes in the system? |
653
|
|
|
if (empty($mostLikedMessages)) |
654
|
|
|
{ |
655
|
|
|
return [ |
656
|
|
|
'noDataMessage' => $txt['like_post_error_no_data'] |
657
|
|
|
]; |
658
|
|
|
} |
659
|
|
|
|
660
|
|
|
return $mostLikedMessages; |
661
|
|
|
} |
662
|
|
|
|
663
|
|
|
/** |
664
|
|
|
* Function to get most liked messages in a topic |
665
|
|
|
* |
666
|
|
|
* What it does: |
667
|
|
|
* |
668
|
|
|
* - For a supplied topic gets the, default 5, posts that have been liked |
669
|
|
|
* - Returns the messages in descending order of likes |
670
|
|
|
* |
671
|
|
|
* @param int $topic the topic_id we are going to look for liked posts within |
672
|
|
|
* @param int $limit the maximum number of liked posts to return |
673
|
|
|
* |
674
|
|
|
* @return array |
675
|
|
|
* @package Likes |
676
|
|
|
*/ |
677
|
|
|
function dbMostLikedMessagesByTopic($topic, $limit = 5) |
678
|
|
|
{ |
679
|
|
|
global $scripturl; |
680
|
|
|
|
681
|
|
|
$db = database(); |
682
|
|
|
$bbc_parser = ParserWrapper::instance(); |
683
|
|
|
|
684
|
|
|
// Most liked messages in a given topic |
685
|
|
|
return $db->fetchQuery(' |
686
|
|
|
SELECT |
687
|
|
|
COALESCE(mem.real_name, m.poster_name) AS member_received_name, lp.id_msg, |
688
|
|
|
m.id_topic, m.id_board, m.id_member, m.subject, m.body, m.poster_time, |
689
|
|
|
lp.like_count AS like_count, |
690
|
|
|
COALESCE(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type, |
691
|
|
|
mem.posts, m.smileys_enabled, mem.email_address, mem.avatar |
692
|
|
|
FROM ( |
693
|
|
|
SELECT |
694
|
|
|
COUNT(lp.id_msg) AS like_count, lp.id_msg |
695
|
|
|
FROM {db_prefix}message_likes AS lp |
696
|
|
|
GROUP BY lp.id_msg |
697
|
|
|
ORDER BY like_count DESC |
698
|
|
|
) AS lp |
699
|
|
|
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = lp.id_msg) |
700
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) |
701
|
|
|
INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) |
702
|
|
|
LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = m.id_member AND a.attachment_type = {int:type_avatar}) |
703
|
|
|
WHERE t.id_topic = {int:id_topic} |
704
|
|
|
ORDER BY lp.like_count DESC |
705
|
|
|
LIMIT {int:limit}', |
706
|
|
|
[ |
707
|
|
|
'id_topic' => $topic, |
708
|
|
|
'limit' => $limit, |
709
|
|
|
'type_avatar' => 1, |
710
|
|
|
] |
711
|
|
|
)->fetch_callback( |
712
|
|
|
function ($row) use ($scripturl, $bbc_parser) { |
713
|
|
|
// Censor those naughty words |
714
|
|
|
$row['body'] = censor($row['body']); |
715
|
|
|
$row['subject'] = censor($row['subject']); |
716
|
|
|
|
717
|
|
|
$row['body'] = $bbc_parser->parseMessage($row['body'], $row['smileys_enabled']); |
718
|
|
|
|
719
|
|
|
// Something short to show is all that's needed |
720
|
|
|
$msgString = Util::shorten_html($row['body'], 255); |
721
|
|
|
$preview = Util::htmlspecialchars(strtr($msgString, ['<br />' => "\n", ' ' => ' '])); |
722
|
|
|
|
723
|
|
|
$avatar = determineAvatar($row); |
724
|
|
|
|
725
|
|
|
return [ |
726
|
|
|
'id_msg' => $row['id_msg'], |
727
|
|
|
'id_topic' => $row['id_topic'], |
728
|
|
|
'id_board' => $row['id_board'], |
729
|
|
|
'like_count' => $row['like_count'], |
730
|
|
|
'subject' => $row['subject'], |
731
|
|
|
'body' => $msgString, |
732
|
|
|
'preview' => $preview, |
733
|
|
|
'time' => standardTime($row['poster_time']), |
734
|
|
|
'html_time' => htmlTime($row['poster_time']), |
735
|
|
|
'timestamp' => forum_time(true, $row['poster_time']), |
736
|
|
|
'member' => [ |
737
|
|
|
'id_member' => $row['id_member'], |
738
|
|
|
'name' => $row['member_received_name'], |
739
|
|
|
'total_posts' => $row['posts'], |
740
|
|
|
'href' => !empty($row['id_member']) ? $scripturl . '?action=profile;u=' . $row['id_member'] : '', |
741
|
|
|
'avatar' => $avatar['href'], |
742
|
|
|
], |
743
|
|
|
]; |
744
|
|
|
} |
745
|
|
|
); |
746
|
|
|
} |
747
|
|
|
|
748
|
|
|
/** |
749
|
|
|
* Function to get most liked topics. |
750
|
|
|
* |
751
|
|
|
* - Rewards threads that generate distinct likers in fewer posts. So if a thread generated 20 unique |
752
|
|
|
* likes in 3 posts vs 20 in 20 posts it would get more weight. |
753
|
|
|
* - The more unique members that like a thread the more popular it will be. |
754
|
|
|
* - Adds weight to threads which have posts with many likes vs threads with many posts with many single likes |
755
|
|
|
* - Can still be gamed but what can you do |
756
|
|
|
* |
757
|
|
|
* @param null|int $board - An optional board id to find most liked topics in. |
758
|
|
|
* If omitted, {query_wanna_see_board} is used to return the most liked topics in the boards |
759
|
|
|
* they can see |
760
|
|
|
* @param int $limit - Optional, number of topics to return (default 10). |
761
|
|
|
* |
762
|
|
|
* @return array |
763
|
|
|
* @package Likes |
764
|
|
|
* |
765
|
|
|
*/ |
766
|
|
|
function dbMostLikedTopic($board = null, $limit = 10) |
767
|
|
|
{ |
768
|
|
|
global $txt; |
769
|
|
|
|
770
|
|
|
$db = database(); |
771
|
|
|
|
772
|
|
|
// The most liked topics by sum of likes and distinct likers |
773
|
|
|
$mostLikedTopics = []; |
774
|
|
|
$db->fetchQuery(' |
775
|
|
|
SELECT |
776
|
|
|
t.id_topic, t.num_replies, t.id_board, |
777
|
|
|
COUNT(lp.id_msg) AS like_count, |
778
|
|
|
COUNT(DISTINCT lp.id_member) AS distinct_likers, |
779
|
|
|
COUNT(DISTINCT m.id_msg) AS num_messages_liked |
780
|
|
|
FROM {db_prefix}message_likes AS lp |
781
|
|
|
INNER JOIN {db_prefix}messages AS m ON (lp.id_msg = m.id_msg) |
782
|
|
|
INNER JOIN {db_prefix}topics AS t ON (m.id_topic = t.id_topic) |
783
|
|
|
INNER JOIN {db_prefix}boards AS b ON (t.id_board = b.id_board) |
784
|
|
|
WHERE ' . ($board === null ? '{query_wanna_see_board}' : 'b.id_board = {int:id_board}') . ' |
785
|
|
|
GROUP BY t.id_topic, t.num_replies, t.id_board |
786
|
|
|
ORDER BY distinct_likers DESC |
787
|
|
|
LIMIT {int:limit}', |
788
|
|
|
[ |
789
|
|
|
'id_board' => $board, |
790
|
|
|
'limit' => $limit * 10, |
791
|
|
|
] |
792
|
|
|
)->fetch_callback( |
793
|
|
|
function ($row) use (&$mostLikedTopics) { |
794
|
|
|
$row['num_replies'] = (int) $row['num_replies']; |
795
|
|
|
$row['like_count'] = (int) $row['like_count']; |
796
|
|
|
$row['distinct_likers'] = (int) $row['distinct_likers']; |
797
|
|
|
$row['num_messages_liked'] = (int) $row['num_messages_liked']; |
798
|
|
|
$mostLikedTopics[$row['id_topic']] = $row; |
799
|
|
|
|
800
|
|
|
$log = log($row['like_count'] / ($row['num_replies'] + ($row['num_replies'] === 0 || $row['like_count'] === $row['num_replies'] ? 1 : 0))); |
801
|
|
|
$distinct_likers = max(1, |
802
|
|
|
min($row['distinct_likers'], |
803
|
|
|
1 / ($log === 0 ? 1 : $log))); |
804
|
|
|
|
805
|
|
|
$mostLikedTopics[$row['id_topic']]['relevance'] = $row['distinct_likers'] + |
806
|
|
|
$row['distinct_likers'] / $row['num_messages_liked'] + |
807
|
|
|
$distinct_likers; |
808
|
|
|
} |
809
|
|
|
); |
810
|
|
|
|
811
|
|
|
// Sort the results from the net we cast, then cut it down to the top X limit |
812
|
|
|
uasort($mostLikedTopics, 'sort_by_relevance'); |
813
|
|
|
$mostLikedTopics = array_slice($mostLikedTopics, 0, $limit); |
814
|
|
|
|
815
|
|
|
// Fetch some sample posts for each of the top X topics |
816
|
|
|
foreach ($mostLikedTopics as $key => $topic) |
817
|
|
|
{ |
818
|
|
|
$mostLikedTopics[$key]['msg_data'] = dbMostLikedMessagesByTopic($topic['id_topic']); |
819
|
|
|
} |
820
|
|
|
|
821
|
|
|
// Looks like there is nothing liked |
822
|
|
|
if (empty($mostLikedTopics)) |
823
|
|
|
{ |
824
|
|
|
return [ |
825
|
|
|
'noDataMessage' => $txt['like_post_error_no_data'] |
826
|
|
|
]; |
827
|
|
|
} |
828
|
|
|
|
829
|
|
|
return $mostLikedTopics; |
830
|
|
|
} |
831
|
|
|
|
832
|
|
|
/** |
833
|
|
|
* Helper function to sort by topic like relevance |
834
|
|
|
* |
835
|
|
|
* @param float $a |
836
|
|
|
* @param float $b |
837
|
|
|
* |
838
|
|
|
* @return mixed |
839
|
|
|
*/ |
840
|
|
|
function sort_by_relevance($a, $b) |
841
|
|
|
{ |
842
|
|
|
return $b['relevance'] - $a['relevance']; |
843
|
|
|
} |
844
|
|
|
|
845
|
|
|
/** |
846
|
|
|
* Function to get most liked board |
847
|
|
|
* |
848
|
|
|
* @package Likes |
849
|
|
|
*/ |
850
|
|
|
function dbMostLikedBoard() |
851
|
|
|
{ |
852
|
|
|
global $txt; |
853
|
|
|
|
854
|
|
|
$db = database(); |
855
|
|
|
|
856
|
|
|
// Most liked board |
857
|
|
|
$request = $db->query('', ' |
858
|
|
|
SELECT |
859
|
|
|
b.id_board, b.name, b.num_topics, b.num_posts, |
860
|
|
|
tc.topics_liked, tc.msgs_liked, tc.like_count |
861
|
|
|
FROM {db_prefix}boards AS b |
862
|
|
|
INNER JOIN ( |
863
|
|
|
SELECT |
864
|
|
|
m.id_board, |
865
|
|
|
COUNT(DISTINCT(m.id_topic)) AS topics_liked, |
866
|
|
|
COUNT(DISTINCT(lp.id_msg)) AS msgs_liked, |
867
|
|
|
COUNT(m.id_board) AS like_count |
868
|
|
|
FROM {db_prefix}message_likes AS lp |
869
|
|
|
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = lp.id_msg) |
870
|
|
|
INNER JOIN {db_prefix}boards AS b ON (m.id_board = b.id_board) |
871
|
|
|
WHERE {query_wanna_see_board} |
872
|
|
|
GROUP BY m.id_board |
873
|
|
|
ORDER BY like_count DESC |
874
|
|
|
LIMIT {int:limit} |
875
|
|
|
) AS tc ON (tc.id_board = b.id_board) |
876
|
|
|
LIMIT {int:limit}', |
877
|
|
|
[ |
878
|
|
|
'limit' => 1 |
879
|
|
|
] |
880
|
|
|
); |
881
|
|
|
$mostLikedBoard = $request->fetch_assoc(); |
882
|
|
|
$request->free_result(); |
883
|
|
|
|
884
|
|
|
if (empty($mostLikedBoard['id_board'])) |
885
|
|
|
{ |
886
|
|
|
return [ |
887
|
|
|
'noDataMessage' => $txt['like_post_error_no_data'] |
888
|
|
|
]; |
889
|
|
|
} |
890
|
|
|
|
891
|
|
|
$mostLikedTopic = dbMostLikedTopic($mostLikedBoard['id_board']); |
892
|
|
|
$mostLikedBoard['topic_data'] = $mostLikedTopic[0]['msg_data']; |
893
|
|
|
|
894
|
|
|
return $mostLikedBoard; |
895
|
|
|
} |
896
|
|
|
|
897
|
|
|
/** |
898
|
|
|
* Function to get most liked members |
899
|
|
|
* |
900
|
|
|
* @param int $limit the number of most liked members to return |
901
|
|
|
* |
902
|
|
|
* @return array |
903
|
|
|
* @package Likes |
904
|
|
|
* |
905
|
|
|
*/ |
906
|
|
|
function dbMostLikesReceivedUser($limit = 10) |
907
|
|
|
{ |
908
|
|
|
global $txt; |
909
|
|
|
|
910
|
|
|
$db = database(); |
911
|
|
|
|
912
|
|
|
$mostLikedMembers = []; |
913
|
|
|
$db->fetchQuery(' |
914
|
|
|
SELECT |
915
|
|
|
lp.id_poster, lp.like_count, |
916
|
|
|
COALESCE(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type, |
917
|
|
|
COALESCE(mem.real_name, m.poster_name) AS real_name, |
918
|
|
|
mem.avatar, mem.date_registered, mem.posts, mem.email_address |
919
|
|
|
FROM ( |
920
|
|
|
SELECT |
921
|
|
|
id_poster, |
922
|
|
|
COUNT(id_msg) AS like_count, |
923
|
|
|
MAX(id_msg) AS id_msg |
924
|
|
|
FROM {db_prefix}message_likes |
925
|
|
|
WHERE id_poster != 0 |
926
|
|
|
GROUP BY id_poster |
927
|
|
|
ORDER BY like_count DESC |
928
|
|
|
LIMIT {int:limit} |
929
|
|
|
) AS lp |
930
|
|
|
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = lp.id_msg) |
931
|
|
|
INNER JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) |
932
|
|
|
LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = m.id_member) |
933
|
|
|
ORDER BY like_count DESC |
934
|
|
|
LIMIT {int:limit}', |
935
|
|
|
[ |
936
|
|
|
'limit' => $limit |
937
|
|
|
] |
938
|
|
|
)->fetch_callback( |
939
|
|
|
function ($row) use (&$mostLikedMembers) { |
940
|
|
|
global $scripturl; |
941
|
|
|
|
942
|
|
|
$avatar = determineAvatar($row); |
943
|
|
|
$mostLikedMembers[] = [ |
944
|
|
|
'member_received' => [ |
945
|
|
|
'id_member' => $row['id_poster'], |
946
|
|
|
'name' => $row['real_name'], |
947
|
|
|
'total_posts' => $row['posts'], |
948
|
|
|
'date_registered' => $row['date_registered'], |
949
|
|
|
'href' => !empty($row['id_poster']) ? $scripturl . '?action=profile;u=' . $row['id_poster'] : '', |
950
|
|
|
'avatar' => $avatar['href'], |
951
|
|
|
], |
952
|
|
|
'like_count' => $row['like_count'], |
953
|
|
|
'post_data' => dbMostLikedPostsByUser($row['id_poster']), |
954
|
|
|
]; |
955
|
|
|
} |
956
|
|
|
); |
957
|
|
|
|
958
|
|
|
if (empty($mostLikedMembers)) |
959
|
|
|
{ |
960
|
|
|
return [ |
961
|
|
|
'noDataMessage' => $txt['like_post_error_no_data'] |
962
|
|
|
]; |
963
|
|
|
} |
964
|
|
|
|
965
|
|
|
return $mostLikedMembers; |
966
|
|
|
} |
967
|
|
|
|
968
|
|
|
/** |
969
|
|
|
* Returns the most liked posts of a given user |
970
|
|
|
* |
971
|
|
|
* @param int $id_member find top posts for this member id |
972
|
|
|
* @param int $limit then number of top posts to return |
973
|
|
|
* |
974
|
|
|
* @return array |
975
|
|
|
*/ |
976
|
|
|
function dbMostLikedPostsByUser($id_member, $limit = 10) |
977
|
|
|
{ |
978
|
|
|
$db = database(); |
979
|
|
|
$bbc_parser = ParserWrapper::instance(); |
980
|
|
|
|
981
|
|
|
// Lets fetch highest liked posts by this user |
982
|
|
|
return $db->fetchQuery(' |
983
|
|
|
SELECT |
984
|
|
|
lp.id_msg, COUNT(lp.id_msg) AS like_count, |
985
|
|
|
m.body, m.poster_time, m.smileys_enabled, m.id_topic, m.subject |
986
|
|
|
FROM {db_prefix}message_likes AS lp |
987
|
|
|
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = lp.id_msg) |
988
|
|
|
INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board) |
989
|
|
|
WHERE {query_wanna_see_board} |
990
|
|
|
AND lp.id_poster = {int:id_member} |
991
|
|
|
GROUP BY lp.id_msg, m.id_topic, m.subject, m.body, m.poster_time, m.smileys_enabled |
992
|
|
|
ORDER BY like_count DESC |
993
|
|
|
LIMIT {int:limit}', |
994
|
|
|
[ |
995
|
|
|
'id_member' => $id_member, |
996
|
|
|
'limit' => $limit |
997
|
|
|
] |
998
|
|
|
)->fetch_callback( |
999
|
|
|
function ($row) use ($bbc_parser) { |
1000
|
|
|
// Censor those naughty words |
1001
|
|
|
$row['body'] = censor($row['body']); |
1002
|
|
|
$row['subject'] = censor($row['subject']); |
1003
|
|
|
|
1004
|
|
|
$row['body'] = $bbc_parser->parseMessage($row['body'], $row['smileys_enabled']); |
1005
|
|
|
|
1006
|
|
|
// Something short to show is all that's needed |
1007
|
|
|
$msgString = Util::shorten_html($row['body'], 255); |
1008
|
|
|
$preview = Util::htmlspecialchars(strtr($msgString, ['<br />' => "\n", ' ' => ' '])); |
1009
|
|
|
|
1010
|
|
|
return [ |
1011
|
|
|
'id_topic' => $row['id_topic'], |
1012
|
|
|
'id_msg' => $row['id_msg'], |
1013
|
|
|
'like_count' => $row['like_count'], |
1014
|
|
|
'subject' => $row['subject'], |
1015
|
|
|
'body' => $msgString, |
1016
|
|
|
'preview' => $preview, |
1017
|
|
|
'time' => standardTime($row['poster_time']), |
1018
|
|
|
'html_time' => htmlTime($row['poster_time']), |
1019
|
|
|
'timestamp' => forum_time(true, $row['poster_time']), |
1020
|
|
|
]; |
1021
|
|
|
} |
1022
|
|
|
); |
1023
|
|
|
} |
1024
|
|
|
|
1025
|
|
|
/** |
1026
|
|
|
* Function to get most likes giving user |
1027
|
|
|
* |
1028
|
|
|
* @param int $limit the number of members to return |
1029
|
|
|
* |
1030
|
|
|
* @return array |
1031
|
|
|
* @package Likes |
1032
|
|
|
* |
1033
|
|
|
*/ |
1034
|
|
|
function dbMostLikesGivenUser($limit = 10) |
1035
|
|
|
{ |
1036
|
|
|
global $txt; |
1037
|
|
|
|
1038
|
|
|
$db = database(); |
1039
|
|
|
|
1040
|
|
|
$mostLikeGivingMembers = []; |
1041
|
|
|
$db->fetchQuery(' |
1042
|
|
|
SELECT |
1043
|
|
|
lp.id_member, lp.like_count, |
1044
|
|
|
COALESCE(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type, |
1045
|
|
|
COALESCE(mem.real_name, m.poster_name) AS real_name, |
1046
|
|
|
mem.avatar, mem.date_registered, mem.posts, mem.email_address |
1047
|
|
|
FROM ( |
1048
|
|
|
SELECT |
1049
|
|
|
COUNT(id_msg) AS like_count, id_member, MAX(id_msg) AS id_msg |
1050
|
|
|
FROM {db_prefix}message_likes |
1051
|
|
|
GROUP BY id_member |
1052
|
|
|
ORDER BY like_count DESC |
1053
|
|
|
LIMIT {int:limit} |
1054
|
|
|
) AS lp |
1055
|
|
|
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = lp.id_msg) |
1056
|
|
|
INNER JOIN {db_prefix}members AS mem ON (mem.id_member = lp.id_member) |
1057
|
|
|
LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = lp.id_member) |
1058
|
|
|
ORDER BY like_count DESC', |
1059
|
|
|
[ |
1060
|
|
|
'limit' => $limit |
1061
|
|
|
] |
1062
|
|
|
)->fetch_callback( |
1063
|
|
|
function ($row) use (&$mostLikeGivingMembers) { |
1064
|
|
|
global $scripturl; |
1065
|
|
|
|
1066
|
|
|
$avatar = determineAvatar($row); |
1067
|
|
|
|
1068
|
|
|
$mostLikeGivingMembers[] = [ |
1069
|
|
|
'member_given' => [ |
1070
|
|
|
'id_member' => $row['id_member'], |
1071
|
|
|
'name' => $row['real_name'], |
1072
|
|
|
'total_posts' => $row['posts'], |
1073
|
|
|
'date_registered' => $row['date_registered'], |
1074
|
|
|
'href' => !empty($row['id_member_gave']) ? $scripturl . '?action=profile;u=' . $row['id_member_gave'] : '', |
1075
|
|
|
'avatar' => $avatar['href'], |
1076
|
|
|
], |
1077
|
|
|
'like_count' => $row['like_count'], |
1078
|
|
|
'post_data' => dbRecentlyLikedPostsGivenUser($row['id_member']) |
1079
|
|
|
]; |
1080
|
|
|
} |
1081
|
|
|
); |
1082
|
|
|
|
1083
|
|
|
if (empty($mostLikeGivingMembers)) |
1084
|
|
|
{ |
1085
|
|
|
return [ |
1086
|
|
|
'noDataMessage' => $txt['like_post_error_no_data'] |
1087
|
|
|
]; |
1088
|
|
|
} |
1089
|
|
|
|
1090
|
|
|
return $mostLikeGivingMembers; |
1091
|
|
|
} |
1092
|
|
|
|
1093
|
|
|
/** |
1094
|
|
|
* Returns posts that were recently liked by a given user |
1095
|
|
|
* |
1096
|
|
|
* @param int $id_liker the userid to find recently liked posts |
1097
|
|
|
* @param int $limit number of recently liked posts to fetch |
1098
|
|
|
* @return array |
1099
|
|
|
*/ |
1100
|
|
|
function dbRecentlyLikedPostsGivenUser($id_liker, $limit = 5) |
1101
|
|
|
{ |
1102
|
|
|
$db = database(); |
1103
|
|
|
$bbc_parser = ParserWrapper::instance(); |
1104
|
|
|
|
1105
|
|
|
// Lets fetch the latest liked posts by this user |
1106
|
|
|
return $db->fetchQuery(' |
1107
|
|
|
SELECT |
1108
|
|
|
m.id_msg, m.id_topic, m.subject, m.body, m.poster_time, m.smileys_enabled |
1109
|
|
|
FROM {db_prefix}message_likes AS ml |
1110
|
|
|
INNER JOIN {db_prefix}messages AS m ON (ml.id_msg = m.id_msg) |
1111
|
|
|
INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board) |
1112
|
|
|
WHERE {query_wanna_see_board} |
1113
|
|
|
AND ml.id_member = {int:id_member} |
1114
|
|
|
ORDER BY m.id_msg DESC |
1115
|
|
|
LIMIT {int:limit}', |
1116
|
|
|
[ |
1117
|
|
|
'id_member' => $id_liker, |
1118
|
|
|
'limit' => $limit |
1119
|
|
|
] |
1120
|
|
|
)->fetch_callback( |
1121
|
|
|
function ($row) use ($bbc_parser) { |
1122
|
|
|
// Censor those $%#^&% words |
1123
|
|
|
$row['body'] = censor($row['body']); |
1124
|
|
|
$row['subject'] = censor($row['subject']); |
1125
|
|
|
|
1126
|
|
|
$row['body'] = $bbc_parser->parseMessage($row['body'], $row['smileys_enabled']); |
1127
|
|
|
|
1128
|
|
|
// Something short to show is all that's required |
1129
|
|
|
$msgString = Util::shorten_html($row['body'], 255); |
1130
|
|
|
$preview = Util::htmlspecialchars(strtr($msgString, ['<br />' => "\n", ' ' => ' '])); |
1131
|
|
|
|
1132
|
|
|
return [ |
1133
|
|
|
'id_msg' => $row['id_msg'], |
1134
|
|
|
'id_topic' => $row['id_topic'], |
1135
|
|
|
'subject' => $row['subject'], |
1136
|
|
|
'body' => $msgString, |
1137
|
|
|
'preview' => $preview, |
1138
|
|
|
'time' => standardTime($row['poster_time']), |
1139
|
|
|
'html_time' => htmlTime($row['poster_time']), |
1140
|
|
|
'timestamp' => forum_time(true, $row['poster_time']), |
1141
|
|
|
]; |
1142
|
|
|
} |
1143
|
|
|
); |
1144
|
|
|
} |
1145
|
|
|
|
1146
|
|
|
/** |
1147
|
|
|
* Utility function to decrease member like counts when a message is removed |
1148
|
|
|
* |
1149
|
|
|
* When a message is removed, we need update the like counts for those who liked the message |
1150
|
|
|
* as well as those who posted the message |
1151
|
|
|
* - Members who liked the message have likes given decreased |
1152
|
|
|
* - The member who posted has the likes received decreased by the number of likers |
1153
|
|
|
* for that message. |
1154
|
|
|
* |
1155
|
|
|
* @param int[]|int $messages |
1156
|
|
|
*/ |
1157
|
|
|
function decreaseLikeCounts($messages) |
1158
|
|
|
{ |
1159
|
|
|
$db = database(); |
1160
|
|
|
|
1161
|
|
|
// Start off with no changes |
1162
|
|
|
$update_given = []; |
1163
|
|
|
$update_received = []; |
1164
|
|
|
|
1165
|
|
|
// Only a single message |
1166
|
|
|
if (is_numeric($messages)) |
1167
|
|
|
{ |
1168
|
|
|
$messages = [$messages]; |
1169
|
|
|
} |
1170
|
|
|
|
1171
|
|
|
// Load the members who liked and who posted for this group of messages |
1172
|
|
|
$posters = []; |
1173
|
|
|
$likers = []; |
1174
|
12 |
|
$db->fetchQuery(' |
1175
|
|
|
SELECT |
1176
|
|
|
id_member, id_poster |
1177
|
12 |
|
FROM {db_prefix}message_likes |
1178
|
12 |
|
WHERE id_msg IN ({array_int:messages})', |
1179
|
|
|
[ |
1180
|
|
|
'messages' => $messages, |
1181
|
12 |
|
] |
1182
|
|
|
)->fetch_callback( |
1183
|
|
|
function ($row) use (&$posters, &$likers) { |
1184
|
|
|
// Track how many likes each member gave and how many were received |
1185
|
|
|
$posters[$row['id_poster']] = isset($posters[$row['id_poster']]) ? $posters[$row['id_poster']]++ : 1; |
1186
|
|
|
$likers[$row['id_member']] = isset($likers[$row['id_member']]) ? $likers[$row['id_member']]++ : 1; |
1187
|
12 |
|
} |
1188
|
12 |
|
); |
1189
|
12 |
|
|
1190
|
|
|
// No one? |
1191
|
|
|
if (empty($posters) && empty($likers)) |
1192
|
|
|
{ |
1193
|
|
|
return; |
1194
|
|
|
} |
1195
|
12 |
|
|
1196
|
|
|
// Re-count the "likes given" totals for the likers |
1197
|
12 |
|
if (!empty($likers)) |
1198
|
|
|
{ |
1199
|
|
|
$db->fetchQuery(' |
1200
|
|
|
SELECT |
1201
|
|
|
COUNT(id_msg) AS likes, id_member |
1202
|
12 |
|
FROM {db_prefix}message_likes |
1203
|
|
|
WHERE id_member IN ({array_int:members}) |
1204
|
|
|
GROUP BY id_member', |
1205
|
|
|
[ |
1206
|
12 |
|
'members' => array_keys($likers), |
1207
|
|
|
] |
1208
|
12 |
|
)->fetch_callback( |
1209
|
|
|
function ($row) use (&$update_given, $likers) { |
1210
|
|
|
// All who liked these messages have their "likes given" reduced |
1211
|
|
|
$update_given[$row['id_member']] = $row['likes'] - $likers[$row['id_member']]; |
1212
|
|
|
} |
1213
|
|
|
); |
1214
|
|
|
} |
1215
|
|
|
|
1216
|
|
|
// Count the "likes received" totals for the message posters |
1217
|
|
|
if (!empty($posters)) |
1218
|
|
|
{ |
1219
|
|
|
$db->fetchQuery(' |
1220
|
|
|
SELECT |
1221
|
|
|
COUNT(id_msg) AS likes, id_poster |
1222
|
|
|
FROM {db_prefix}message_likes |
1223
|
|
|
WHERE id_poster IN ({array_int:members}) |
1224
|
|
|
GROUP BY id_poster', |
1225
|
|
|
[ |
1226
|
|
|
'members' => array_keys($posters), |
1227
|
|
|
] |
1228
|
|
|
)->fetch_callback( |
1229
|
|
|
function ($row) use (&$update_received, $posters) { |
1230
|
|
|
// The message posters have their "likes received" reduced |
1231
|
|
|
$update_received[$row['id_poster']] = $row['likes'] - $posters[$row['id_poster']]; |
1232
|
|
|
} |
1233
|
|
|
); |
1234
|
|
|
} |
1235
|
|
|
|
1236
|
|
|
// Update the totals for these members |
1237
|
|
|
require_once(SUBSDIR . '/Members.subs.php'); |
1238
|
|
|
|
1239
|
|
|
foreach ($update_given as $id_member => $total) |
1240
|
|
|
{ |
1241
|
|
|
updateMemberData($id_member, ['likes_given' => (int) $total]); |
1242
|
|
|
} |
1243
|
|
|
|
1244
|
|
|
foreach ($update_received as $id_member => $total) |
1245
|
|
|
{ |
1246
|
|
|
updateMemberData($id_member, ['likes_received' => (int) $total]); |
1247
|
|
|
} |
1248
|
|
|
} |
1249
|
|
|
|