|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* This file is holds low-level database work used by the Stats. |
|
5
|
|
|
* Some functions/queries (or all :P) might be duplicate, along Elk. |
|
6
|
|
|
* They'll be here to avoid including many files in action_stats, and |
|
7
|
|
|
* perhaps for use of addons in a similar way they were using some |
|
8
|
|
|
* SSI functions. |
|
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 2.0 dev |
|
19
|
|
|
* |
|
20
|
|
|
*/ |
|
21
|
|
|
|
|
22
|
|
|
/** |
|
23
|
|
|
* Return the number of currently online members. |
|
24
|
|
|
* |
|
25
|
|
|
* @return double |
|
26
|
|
|
*/ |
|
27
|
|
View Code Duplication |
function onlineCount() |
|
|
|
|
|
|
28
|
|
|
{ |
|
29
|
|
|
$db = database(); |
|
30
|
|
|
|
|
31
|
|
|
$result = $db->query('', ' |
|
32
|
|
|
SELECT COUNT(*) |
|
33
|
|
|
FROM {db_prefix}log_online', |
|
34
|
|
|
array( |
|
35
|
|
|
) |
|
36
|
|
|
); |
|
37
|
|
|
list ($users_online) = $db->fetch_row($result); |
|
38
|
|
|
$db->free_result($result); |
|
39
|
|
|
|
|
40
|
|
|
return $users_online; |
|
41
|
|
|
} |
|
42
|
|
|
|
|
43
|
|
|
/** |
|
44
|
|
|
* Gets totals for posts, topics, most online, new users, page views, emails |
|
45
|
|
|
* |
|
46
|
|
|
* - Can be used (and is) with days up value to generate averages. |
|
47
|
|
|
* |
|
48
|
|
|
* @return array |
|
49
|
|
|
*/ |
|
50
|
|
|
function getAverages() |
|
51
|
|
|
{ |
|
52
|
|
|
$db = database(); |
|
53
|
|
|
|
|
54
|
|
|
$result = $db->query('', ' |
|
55
|
|
|
SELECT |
|
56
|
|
|
SUM(posts) AS posts, SUM(topics) AS topics, SUM(registers) AS registers, |
|
57
|
|
|
SUM(most_on) AS most_on, MIN(date) AS date, SUM(hits) AS hits, SUM(email) AS email |
|
58
|
|
|
FROM {db_prefix}log_activity', |
|
59
|
|
|
array( |
|
60
|
|
|
) |
|
61
|
|
|
); |
|
62
|
|
|
$row = $db->fetch_assoc($result); |
|
63
|
|
|
$db->free_result($result); |
|
64
|
|
|
|
|
65
|
|
|
return $row; |
|
66
|
|
|
} |
|
67
|
|
|
|
|
68
|
|
|
/** |
|
69
|
|
|
* Get the count of categories |
|
70
|
|
|
* |
|
71
|
|
|
* @return int |
|
72
|
|
|
*/ |
|
73
|
|
View Code Duplication |
function numCategories() |
|
|
|
|
|
|
74
|
|
|
{ |
|
75
|
|
|
$db = database(); |
|
76
|
|
|
|
|
77
|
|
|
$result = $db->query('', ' |
|
78
|
|
|
SELECT COUNT(*) |
|
79
|
|
|
FROM {db_prefix}categories', |
|
80
|
|
|
array( |
|
81
|
|
|
) |
|
82
|
|
|
); |
|
83
|
|
|
list ($num_categories) = $db->fetch_row($result); |
|
84
|
|
|
$db->free_result($result); |
|
85
|
|
|
|
|
86
|
|
|
return $num_categories; |
|
87
|
|
|
} |
|
88
|
|
|
|
|
89
|
|
|
/** |
|
90
|
|
|
* Gets most online members for a specific date |
|
91
|
|
|
* |
|
92
|
|
|
* @param int $date |
|
93
|
|
|
* @return int |
|
94
|
|
|
*/ |
|
95
|
|
View Code Duplication |
function mostOnline($date) |
|
|
|
|
|
|
96
|
|
|
{ |
|
97
|
|
|
$db = database(); |
|
98
|
|
|
|
|
99
|
|
|
$result = $db->query('', ' |
|
100
|
|
|
SELECT most_on |
|
101
|
|
|
FROM {db_prefix}log_activity |
|
102
|
|
|
WHERE date = {date:given_date} |
|
103
|
|
|
LIMIT 1', |
|
104
|
|
|
array( |
|
105
|
|
|
'given_date' => $date, |
|
106
|
|
|
) |
|
107
|
|
|
); |
|
108
|
|
|
list ($online) = $db->fetch_row($result); |
|
109
|
|
|
$db->free_result($result); |
|
110
|
|
|
|
|
111
|
|
|
return (int) $online; |
|
112
|
|
|
} |
|
113
|
|
|
|
|
114
|
|
|
/** |
|
115
|
|
|
* Loads a list of top x posters |
|
116
|
|
|
* |
|
117
|
|
|
* - x is configurable via $modSettings['stats_limit']. |
|
118
|
|
|
* |
|
119
|
|
|
* @param int|null $limit if empty defaults to 10 |
|
120
|
|
|
* @return array |
|
121
|
|
|
*/ |
|
122
|
|
|
function topPosters($limit = null) |
|
123
|
|
|
{ |
|
124
|
|
|
global $scripturl, $modSettings; |
|
125
|
|
|
|
|
126
|
|
|
$db = database(); |
|
127
|
|
|
|
|
128
|
|
|
// If there is a default setting, let's not retrieve something bigger |
|
129
|
|
View Code Duplication |
if (isset($modSettings['stats_limit'])) |
|
130
|
|
|
$limit = empty($limit) ? $modSettings['stats_limit'] : ($limit < $modSettings['stats_limit'] ? $limit : $modSettings['stats_limit']); |
|
131
|
|
|
// Otherwise, fingers crossed and let's grab what is asked |
|
132
|
|
|
else |
|
133
|
|
|
$limit = empty($limit) ? 10 : $limit; |
|
134
|
|
|
|
|
135
|
|
|
// Make the query to the the x number of top posters |
|
136
|
|
|
$members_result = $db->query('', ' |
|
137
|
|
|
SELECT id_member, real_name, posts |
|
138
|
|
|
FROM {db_prefix}members |
|
139
|
|
|
WHERE posts > {int:no_posts} |
|
140
|
|
|
ORDER BY posts DESC |
|
141
|
|
|
LIMIT {int:limit_posts}', |
|
142
|
|
|
array( |
|
143
|
|
|
'no_posts' => 0, |
|
144
|
|
|
'limit_posts' => $limit, |
|
145
|
|
|
) |
|
146
|
|
|
); |
|
147
|
|
|
$top_posters = array(); |
|
148
|
|
|
$max_num_posts = 1; |
|
149
|
|
|
while ($row_members = $db->fetch_assoc($members_result)) |
|
150
|
|
|
{ |
|
151
|
|
|
// Build general member information for each top poster |
|
152
|
|
|
$top_posters[] = array( |
|
153
|
|
|
'name' => $row_members['real_name'], |
|
154
|
|
|
'id' => $row_members['id_member'], |
|
155
|
|
|
'num_posts' => $row_members['posts'], |
|
156
|
|
|
'href' => $scripturl . '?action=profile;u=' . $row_members['id_member'], |
|
157
|
|
|
'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row_members['id_member'] . '">' . $row_members['real_name'] . '</a>' |
|
158
|
|
|
); |
|
159
|
|
|
if ($max_num_posts < $row_members['posts']) |
|
160
|
|
|
$max_num_posts = $row_members['posts']; |
|
161
|
|
|
} |
|
162
|
|
|
$db->free_result($members_result); |
|
163
|
|
|
|
|
164
|
|
|
// Determine the percents and then format the num_posts |
|
165
|
|
View Code Duplication |
foreach ($top_posters as $i => $poster) |
|
166
|
|
|
{ |
|
167
|
|
|
$top_posters[$i]['post_percent'] = round(($poster['num_posts'] * 100) / $max_num_posts); |
|
168
|
|
|
$top_posters[$i]['num_posts'] = comma_format($top_posters[$i]['num_posts']); |
|
169
|
|
|
} |
|
170
|
|
|
|
|
171
|
|
|
return $top_posters; |
|
172
|
|
|
} |
|
173
|
|
|
|
|
174
|
|
|
/** |
|
175
|
|
|
* Loads a list of top x boards with number of board posts and board topics |
|
176
|
|
|
* |
|
177
|
|
|
* - x is configurable via $modSettings['stats_limit']. |
|
178
|
|
|
* |
|
179
|
|
|
* @param int|null $limit if not supplied, defaults to 10 |
|
180
|
|
|
* @param boolean $read_status |
|
181
|
|
|
* @return array |
|
182
|
|
|
*/ |
|
183
|
|
|
function topBoards($limit = null, $read_status = false) |
|
184
|
|
|
{ |
|
185
|
|
|
global $modSettings, $scripturl, $user_info; |
|
186
|
|
|
|
|
187
|
|
|
$db = database(); |
|
188
|
|
|
|
|
189
|
|
|
// If there is a default setting, let's not retrieve something bigger |
|
190
|
|
View Code Duplication |
if (isset($modSettings['stats_limit'])) |
|
191
|
|
|
$limit = empty($limit) ? $modSettings['stats_limit'] : ($limit < $modSettings['stats_limit'] ? $limit : $modSettings['stats_limit']); |
|
192
|
|
|
// Otherwise, fingers crossed and let's grab what is asked |
|
193
|
|
|
else |
|
194
|
|
|
$limit = empty($limit) ? 10 : $limit; |
|
195
|
|
|
|
|
196
|
|
|
$boards_result = $db->query('', ' |
|
197
|
|
|
SELECT b.id_board, b.name, b.num_posts, b.num_topics' . ($read_status ? ',' . (!$user_info['is_guest'] ? ' 1 AS is_read' : ' |
|
198
|
|
|
(COALESCE(lb.id_msg, 0) >= b.id_last_msg) AS is_read') : '') . ' |
|
199
|
|
|
FROM {db_prefix}boards AS b' . ($read_status ? ' |
|
200
|
|
|
LEFT JOIN {db_prefix}log_boards AS lb ON (lb.id_board = b.id_board AND lb.id_member = {int:current_member})' : '') . ' |
|
201
|
|
|
WHERE {query_see_board}' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? ' |
|
202
|
|
|
AND b.id_board != {int:recycle_board}' : '') . ' |
|
203
|
|
|
AND b.redirect = {string:blank_redirect} |
|
204
|
|
|
ORDER BY num_posts DESC |
|
205
|
|
|
LIMIT {int:limit_boards}', |
|
206
|
|
|
array( |
|
207
|
|
|
'recycle_board' => $modSettings['recycle_board'], |
|
208
|
|
|
'blank_redirect' => '', |
|
209
|
|
|
'limit_boards' => $limit, |
|
210
|
|
|
'current_member' => $user_info['id'], |
|
211
|
|
|
) |
|
212
|
|
|
); |
|
213
|
|
|
$top_boards = array(); |
|
214
|
|
|
$max_num_posts = 1; |
|
215
|
|
|
while ($row_board = $db->fetch_assoc($boards_result)) |
|
216
|
|
|
{ |
|
217
|
|
|
// Load the boards info, number of posts, topics etc |
|
218
|
|
|
$top_boards[$row_board['id_board']] = array( |
|
219
|
|
|
'id' => $row_board['id_board'], |
|
220
|
|
|
'name' => $row_board['name'], |
|
221
|
|
|
'num_posts' => $row_board['num_posts'], |
|
222
|
|
|
'num_topics' => $row_board['num_topics'], |
|
223
|
|
|
'href' => $scripturl . '?board=' . $row_board['id_board'] . '.0', |
|
224
|
|
|
'link' => '<a href="' . $scripturl . '?board=' . $row_board['id_board'] . '.0">' . $row_board['name'] . '</a>' |
|
225
|
|
|
); |
|
226
|
|
|
if ($read_status) |
|
227
|
|
|
$top_boards[$row_board['id_board']]['is_read'] = !empty($row_board['is_read']); |
|
228
|
|
|
|
|
229
|
|
|
if ($max_num_posts < $row_board['num_posts']) |
|
230
|
|
|
$max_num_posts = $row_board['num_posts']; |
|
231
|
|
|
} |
|
232
|
|
|
$db->free_result($boards_result); |
|
233
|
|
|
|
|
234
|
|
|
// Determine the post percentages for the boards, then format the numbers |
|
235
|
|
|
foreach ($top_boards as $i => $board) |
|
236
|
|
|
{ |
|
237
|
|
|
$top_boards[$i]['post_percent'] = round(($board['num_posts'] * 100) / $max_num_posts); |
|
238
|
|
|
$top_boards[$i]['num_posts'] = comma_format($top_boards[$i]['num_posts']); |
|
239
|
|
|
$top_boards[$i]['num_topics'] = comma_format($top_boards[$i]['num_topics']); |
|
240
|
|
|
} |
|
241
|
|
|
|
|
242
|
|
|
return $top_boards; |
|
243
|
|
|
} |
|
244
|
|
|
|
|
245
|
|
|
/** |
|
246
|
|
|
* Loads a list of top x topics by replies |
|
247
|
|
|
* |
|
248
|
|
|
* - x is configurable via $modSettings['stats_limit']. |
|
249
|
|
|
* |
|
250
|
|
|
* @param int $limit if not supplied, defaults to 10 |
|
251
|
|
|
* @return array |
|
252
|
|
|
*/ |
|
253
|
|
|
function topTopicReplies($limit = 10) |
|
254
|
|
|
{ |
|
255
|
|
|
global $modSettings, $scripturl; |
|
256
|
|
|
|
|
257
|
|
|
$db = database(); |
|
258
|
|
|
|
|
259
|
|
|
// If there is a default setting, let's not retrieve something bigger |
|
260
|
|
|
$limit = min($limit, $modSettings['stats_limit'] ?? 10); |
|
261
|
|
|
|
|
262
|
|
|
// Using the wrong alias here so that we can use {query_see_board}. |
|
263
|
|
|
$request = $db->query('', ' |
|
264
|
|
|
SELECT id_topic, num_replies |
|
265
|
|
|
FROM {db_prefix}topics AS b |
|
266
|
|
|
WHERE {query_see_board}' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? ' |
|
267
|
|
|
AND b.id_board != {int:recycle_board}' : '') . ' |
|
268
|
|
|
AND num_replies != {int:no_replies}' . ($modSettings['postmod_active'] ? ' |
|
269
|
|
|
AND approved = {int:is_approved}' : ''), |
|
270
|
|
|
array( |
|
271
|
|
|
'no_replies' => 0, |
|
272
|
|
|
'is_approved' => 1, |
|
273
|
|
|
'recycle_board' => $modSettings['recycle_board'], |
|
274
|
|
|
) |
|
275
|
|
|
); |
|
276
|
|
|
$topic_ids = array(); |
|
277
|
|
|
while ($row = $db->fetch_row($request)) |
|
278
|
|
|
$topic_ids[$row[0]] = $row[1]; |
|
279
|
|
|
$db->free_result($request); |
|
280
|
|
|
arsort($topic_ids); |
|
281
|
|
|
$topic_ids = array_slice($topic_ids, 0, $limit, true); |
|
282
|
|
|
$max_num_replies = max($topic_ids); |
|
283
|
|
|
|
|
284
|
|
|
// Find the top x topics by number of replies |
|
285
|
|
|
$topic_reply_result = $db->query('', ' |
|
286
|
|
|
SELECT m.subject, t.num_replies, t.num_views, t.id_board, t.id_topic |
|
287
|
|
|
FROM {db_prefix}topics AS t |
|
288
|
|
|
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) |
|
289
|
|
|
WHERE t.id_topic IN ({array_int:topic_list})', |
|
290
|
|
|
array( |
|
291
|
|
|
'topic_list' => $topic_ids, |
|
292
|
|
|
) |
|
293
|
|
|
); |
|
294
|
|
|
$top_topics_replies = array(); |
|
295
|
|
|
while ($row_topic_reply = $db->fetch_assoc($topic_reply_result)) |
|
296
|
|
|
{ |
|
297
|
|
|
// Build out this topics details for controller use |
|
298
|
|
|
$top_topics_replies[$row_topic_reply['id_topic']] = array( |
|
299
|
|
|
'id' => $row_topic_reply['id_topic'], |
|
300
|
|
|
'subject' => censor($row_topic_reply['subject']), |
|
301
|
|
|
'num_replies' => comma_format($row_topic_reply['num_replies']), |
|
302
|
|
|
'post_percent' => round(($row_topic_reply['num_replies'] * 100) / $max_num_replies), |
|
303
|
|
|
'num_views' => $row_topic_reply['num_views'], |
|
304
|
|
|
'href' => $scripturl . '?topic=' . $row_topic_reply['id_topic'] . '.0', |
|
305
|
|
|
'link' => '<a href="' . $scripturl . '?topic=' . $row_topic_reply['id_topic'] . '.0">' . $row_topic_reply['subject'] . '</a>' |
|
306
|
|
|
); |
|
307
|
|
|
} |
|
308
|
|
|
$db->free_result($topic_reply_result); |
|
309
|
|
|
|
|
310
|
|
|
// @todo dedupe this |
|
311
|
|
|
usort($top_topics_replies, function ($a, $b) { |
|
312
|
|
|
return $b['num_replies'] <=> $a['num_replies']; |
|
313
|
|
|
}); |
|
314
|
|
|
|
|
315
|
|
|
return $top_topics_replies; |
|
316
|
|
|
} |
|
317
|
|
|
|
|
318
|
|
|
/** |
|
319
|
|
|
* Loads a list of top x topics by number of views |
|
320
|
|
|
* |
|
321
|
|
|
* - x is configurable via $modSettings['stats_limit']. |
|
322
|
|
|
* |
|
323
|
|
|
* @param int|null $limit if not supplied, defaults to 10 |
|
324
|
|
|
* @return array |
|
325
|
|
|
*/ |
|
326
|
|
|
function topTopicViews($limit = null) |
|
327
|
|
|
{ |
|
328
|
|
|
global $modSettings, $scripturl; |
|
329
|
|
|
|
|
330
|
|
|
$db = database(); |
|
331
|
|
|
|
|
332
|
|
|
// If there is a default setting, let's not retrieve something bigger |
|
333
|
|
View Code Duplication |
if (isset($modSettings['stats_limit'])) |
|
334
|
|
|
$limit = empty($limit) ? $modSettings['stats_limit'] : ($limit < $modSettings['stats_limit'] ? $limit : $modSettings['stats_limit']); |
|
335
|
|
|
// Otherwise, fingers crossed and let's grab what is asked |
|
336
|
|
|
else |
|
337
|
|
|
$limit = empty($limit) ? 10 : $limit; |
|
338
|
|
|
|
|
339
|
|
|
// Large forums may need a bit more prodding... |
|
340
|
|
|
if ($modSettings['totalMessages'] > 100000) |
|
341
|
|
|
{ |
|
342
|
|
|
$request = $db->query('', ' |
|
343
|
|
|
SELECT id_topic |
|
344
|
|
|
FROM {db_prefix}topics |
|
345
|
|
|
WHERE num_views != {int:no_views} |
|
346
|
|
|
ORDER BY num_views DESC |
|
347
|
|
|
LIMIT 100', |
|
348
|
|
|
array( |
|
349
|
|
|
'no_views' => 0, |
|
350
|
|
|
) |
|
351
|
|
|
); |
|
352
|
|
|
$topic_ids = array(); |
|
353
|
|
|
while ($row = $db->fetch_assoc($request)) |
|
354
|
|
|
$topic_ids[] = $row['id_topic']; |
|
355
|
|
|
$db->free_result($request); |
|
356
|
|
|
} |
|
357
|
|
|
else |
|
358
|
|
|
$topic_ids = array(); |
|
359
|
|
|
|
|
360
|
|
|
$topic_view_result = $db->query('', ' |
|
361
|
|
|
SELECT m.subject, t.num_views, t.num_replies, t.id_board, t.id_topic, b.name |
|
362
|
|
|
FROM {db_prefix}topics AS t |
|
363
|
|
|
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) |
|
364
|
|
|
INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? ' |
|
365
|
|
|
AND b.id_board != {int:recycle_board}' : '') . ') |
|
366
|
|
|
WHERE {query_see_board}' . (!empty($topic_ids) ? ' |
|
367
|
|
|
AND t.id_topic IN ({array_int:topic_list})' : ($modSettings['postmod_active'] ? ' |
|
368
|
|
|
AND t.approved = {int:is_approved}' : '')) . ' |
|
369
|
|
|
ORDER BY t.num_views DESC |
|
370
|
|
|
LIMIT {int:topic_views}', |
|
371
|
|
|
array( |
|
372
|
|
|
'topic_list' => $topic_ids, |
|
373
|
|
|
'recycle_board' => $modSettings['recycle_board'], |
|
374
|
|
|
'is_approved' => 1, |
|
375
|
|
|
'topic_views' => $limit, |
|
376
|
|
|
) |
|
377
|
|
|
); |
|
378
|
|
|
$top_topics_views = array(); |
|
379
|
|
|
$max_num_views = 1; |
|
380
|
|
|
while ($row_topic_views = $db->fetch_assoc($topic_view_result)) |
|
381
|
|
|
{ |
|
382
|
|
|
// Build the topic result array |
|
383
|
|
|
$row_topic_views['subject'] = censor($row_topic_views['subject']); |
|
384
|
|
|
$top_topics_views[$row_topic_views['id_topic']] = array( |
|
385
|
|
|
'id' => $row_topic_views['id_topic'], |
|
386
|
|
|
'board' => array( |
|
387
|
|
|
'id' => $row_topic_views['id_board'], |
|
388
|
|
|
'name' => $row_topic_views['name'], |
|
389
|
|
|
'href' => $scripturl . '?board=' . $row_topic_views['id_board'] . '.0', |
|
390
|
|
|
'link' => '<a href="' . $scripturl . '?board=' . $row_topic_views['id_board'] . '.0">' . $row_topic_views['name'] . '</a>' |
|
391
|
|
|
), |
|
392
|
|
|
'subject' => $row_topic_views['subject'], |
|
393
|
|
|
'num_replies' => $row_topic_views['num_replies'], |
|
394
|
|
|
'num_views' => $row_topic_views['num_views'], |
|
395
|
|
|
'href' => $scripturl . '?topic=' . $row_topic_views['id_topic'] . '.0', |
|
396
|
|
|
'link' => '<a href="' . $scripturl . '?topic=' . $row_topic_views['id_topic'] . '.0">' . $row_topic_views['subject'] . '</a>' |
|
397
|
|
|
); |
|
398
|
|
|
|
|
399
|
|
|
if ($max_num_views < $row_topic_views['num_views']) |
|
400
|
|
|
$max_num_views = $row_topic_views['num_views']; |
|
401
|
|
|
} |
|
402
|
|
|
$db->free_result($topic_view_result); |
|
403
|
|
|
|
|
404
|
|
|
// Percentages and final formatting |
|
405
|
|
View Code Duplication |
foreach ($top_topics_views as $i => $topic) |
|
406
|
|
|
{ |
|
407
|
|
|
$top_topics_views[$i]['post_percent'] = round(($topic['num_views'] * 100) / $max_num_views); |
|
408
|
|
|
$top_topics_views[$i]['num_views'] = comma_format($top_topics_views[$i]['num_views']); |
|
409
|
|
|
} |
|
410
|
|
|
|
|
411
|
|
|
return $top_topics_views; |
|
412
|
|
|
} |
|
413
|
|
|
|
|
414
|
|
|
/** |
|
415
|
|
|
* Loads a list of top x topic starters |
|
416
|
|
|
* |
|
417
|
|
|
* - x is configurable via $modSettings['stats_limit']. |
|
418
|
|
|
* |
|
419
|
|
|
* @return array |
|
420
|
|
|
*/ |
|
421
|
|
|
function topTopicStarter() |
|
422
|
|
|
{ |
|
423
|
|
|
global $modSettings, $scripturl; |
|
424
|
|
|
|
|
425
|
|
|
$db = database(); |
|
426
|
|
|
$members = array(); |
|
427
|
|
|
$top_starters = array(); |
|
428
|
|
|
|
|
429
|
|
|
// Try to cache this when possible, because it's a little unavoidably slow. |
|
430
|
|
|
if (!Cache::instance()->getVar($members, 'stats_top_starters', 360) || empty($members)) |
|
431
|
|
|
{ |
|
432
|
|
|
$request = $db->query('', ' |
|
433
|
|
|
SELECT id_member_started, COUNT(*) AS hits |
|
434
|
|
|
FROM {db_prefix}topics' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? ' |
|
435
|
|
|
WHERE id_board != {int:recycle_board}' : '') . ' |
|
436
|
|
|
GROUP BY id_member_started', |
|
437
|
|
|
array( |
|
438
|
|
|
'recycle_board' => $modSettings['recycle_board'], |
|
439
|
|
|
) |
|
440
|
|
|
); |
|
441
|
|
|
while ($row = $db->fetch_row($request)) |
|
442
|
|
|
$members[$row[0]] = $row[1]; |
|
443
|
|
|
$db->free_result($request); |
|
444
|
|
|
arsort($members); |
|
445
|
|
|
$members = array_slice($members, 0, $modSettings['stats_limit'] ?? 10, true); |
|
446
|
|
|
|
|
447
|
|
|
Cache::instance()->put('stats_top_starters', $members, 360); |
|
448
|
|
|
} |
|
449
|
|
|
$max_num_topics = max($members); |
|
450
|
|
|
|
|
451
|
|
|
if (empty($members)) |
|
452
|
|
|
$members = array(0 => 0); |
|
453
|
|
|
|
|
454
|
|
|
// Find the top starters of topics |
|
455
|
|
|
$members_result = $db->query('7', ' |
|
456
|
|
|
SELECT id_member, real_name |
|
457
|
|
|
FROM {db_prefix}members |
|
458
|
|
|
WHERE id_member IN ({array_int:member_list})', |
|
459
|
|
|
array( |
|
460
|
|
|
'member_list' => array_keys($members), |
|
461
|
|
|
) |
|
462
|
|
|
); |
|
463
|
|
|
while ($row_members = $db->fetch_assoc($members_result)) |
|
464
|
|
|
{ |
|
465
|
|
|
// Our array of spammers, er topic starters ! |
|
466
|
|
|
$top_starters[$row_members['id_member']] = array( |
|
467
|
|
|
'name' => $row_members['real_name'], |
|
468
|
|
|
'id' => $row_members['id_member'], |
|
469
|
|
|
'num_topics' => comma_format($members[$row_members['id_member']]), |
|
470
|
|
|
'post_percent' => round(($members[$row_members['id_member']] * 100) / $max_num_topics), |
|
471
|
|
|
'href' => $scripturl . '?action=profile;u=' . $row_members['id_member'], |
|
472
|
|
|
'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row_members['id_member'] . '">' . $row_members['real_name'] . '</a>' |
|
473
|
|
|
); |
|
474
|
|
|
|
|
475
|
|
|
} |
|
476
|
|
|
$db->free_result($members_result); |
|
477
|
|
|
|
|
478
|
|
|
// Even spammers must be orderly. |
|
479
|
|
|
uksort($top_starters, function ($a, $b) use ($members) { |
|
480
|
|
|
return $members[$b] <=> $members[$a]; |
|
481
|
|
|
}); |
|
482
|
|
|
|
|
483
|
|
|
return $top_starters; |
|
484
|
|
|
} |
|
485
|
|
|
|
|
486
|
|
|
/** |
|
487
|
|
|
* Loads a list of top users by online time |
|
488
|
|
|
* |
|
489
|
|
|
* - x is configurable via $modSettings['stats_limit'], defaults to 10 |
|
490
|
|
|
* |
|
491
|
|
|
* @return array |
|
492
|
|
|
*/ |
|
493
|
|
|
function topTimeOnline() |
|
494
|
|
|
{ |
|
495
|
|
|
global $modSettings, $scripturl, $txt; |
|
496
|
|
|
|
|
497
|
|
|
$db = database(); |
|
498
|
|
|
|
|
499
|
|
|
$max_members = isset($modSettings['stats_limit']) ? $modSettings['stats_limit'] : 10; |
|
500
|
|
|
|
|
501
|
|
|
// Do we have something cached that will help speed this up? |
|
502
|
|
|
$temp = Cache::instance()->get('stats_total_time_members', 600); |
|
503
|
|
|
|
|
504
|
|
|
// Get the member data, sorted by total time logged in |
|
505
|
|
|
$members_result = $db->query('', ' |
|
506
|
|
|
SELECT id_member, real_name, total_time_logged_in |
|
507
|
|
|
FROM {db_prefix}members' . (!empty($temp) ? ' |
|
508
|
|
|
WHERE id_member IN ({array_int:member_list_cached})' : '') . ' |
|
509
|
|
|
ORDER BY total_time_logged_in DESC |
|
510
|
|
|
LIMIT {int:top_online}', |
|
511
|
|
|
array( |
|
512
|
|
|
'member_list_cached' => $temp, |
|
513
|
|
|
'top_online' => isset($modSettings['stats_limit']) ? $modSettings['stats_limit'] : 20, |
|
514
|
|
|
) |
|
515
|
|
|
); |
|
516
|
|
|
$top_time_online = array(); |
|
517
|
|
|
$temp2 = array(); |
|
518
|
|
|
$max_time_online = 1; |
|
519
|
|
|
while ($row_members = $db->fetch_assoc($members_result)) |
|
520
|
|
|
{ |
|
521
|
|
|
$temp2[] = (int) $row_members['id_member']; |
|
522
|
|
|
if (count($top_time_online) >= $max_members) |
|
523
|
|
|
continue; |
|
524
|
|
|
|
|
525
|
|
|
// Figure out the days, hours and minutes. |
|
526
|
|
|
$timeDays = floor($row_members['total_time_logged_in'] / 86400); |
|
527
|
|
|
$timeHours = floor(($row_members['total_time_logged_in'] % 86400) / 3600); |
|
528
|
|
|
|
|
529
|
|
|
// Figure out which things to show... (days, hours, minutes, etc.) |
|
530
|
|
|
$timelogged = ''; |
|
531
|
|
|
if ($timeDays > 0) |
|
532
|
|
|
$timelogged .= $timeDays . $txt['totalTimeLogged5']; |
|
533
|
|
|
|
|
534
|
|
|
if ($timeHours > 0) |
|
535
|
|
|
$timelogged .= $timeHours . $txt['totalTimeLogged6']; |
|
536
|
|
|
|
|
537
|
|
|
$timelogged .= floor(($row_members['total_time_logged_in'] % 3600) / 60) . $txt['totalTimeLogged7']; |
|
538
|
|
|
|
|
539
|
|
|
// Finally add it to the stats array |
|
540
|
|
|
$top_time_online[] = array( |
|
541
|
|
|
'id' => $row_members['id_member'], |
|
542
|
|
|
'name' => $row_members['real_name'], |
|
543
|
|
|
'time_online' => $timelogged, |
|
544
|
|
|
'seconds_online' => $row_members['total_time_logged_in'], |
|
545
|
|
|
'href' => $scripturl . '?action=profile;u=' . $row_members['id_member'], |
|
546
|
|
|
'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row_members['id_member'] . '">' . $row_members['real_name'] . '</a>' |
|
547
|
|
|
); |
|
548
|
|
|
|
|
549
|
|
|
if ($max_time_online < $row_members['total_time_logged_in']) |
|
550
|
|
|
$max_time_online = $row_members['total_time_logged_in']; |
|
551
|
|
|
} |
|
552
|
|
|
$db->free_result($members_result); |
|
553
|
|
|
|
|
554
|
|
|
// As always percentages are next |
|
555
|
|
|
foreach ($top_time_online as $i => $member) |
|
556
|
|
|
$top_time_online[$i]['time_percent'] = round(($member['seconds_online'] * 100) / $max_time_online); |
|
557
|
|
|
|
|
558
|
|
|
// Cache the ones we found for a bit, just so we don't have to look again. |
|
559
|
|
|
if ($temp !== $temp2) |
|
560
|
|
|
Cache::instance()->put('stats_total_time_members', $temp2, 600); |
|
561
|
|
|
|
|
562
|
|
|
return $top_time_online; |
|
563
|
|
|
} |
|
564
|
|
|
|
|
565
|
|
|
/** |
|
566
|
|
|
* Loads the monthly statistics and returns them in $context |
|
567
|
|
|
* |
|
568
|
|
|
* - page views, new registrations, topics posts, most on etc |
|
569
|
|
|
* |
|
570
|
|
|
*/ |
|
571
|
|
|
function monthlyActivity() |
|
572
|
|
|
{ |
|
573
|
|
|
global $context, $scripturl, $txt; |
|
574
|
|
|
|
|
575
|
|
|
$db = database(); |
|
576
|
|
|
|
|
577
|
|
|
$months_result = $db->query('', ' |
|
578
|
|
|
SELECT |
|
579
|
|
|
YEAR(date) AS stats_year, MONTH(date) AS stats_month, SUM(hits) AS hits, SUM(registers) AS registers, SUM(topics) AS topics, SUM(posts) AS posts, MAX(most_on) AS most_on, COUNT(*) AS num_days |
|
580
|
|
|
FROM {db_prefix}log_activity |
|
581
|
|
|
GROUP BY stats_year, stats_month', |
|
582
|
|
|
array() |
|
583
|
|
|
); |
|
584
|
|
|
while ($row_months = $db->fetch_assoc($months_result)) |
|
585
|
|
|
{ |
|
586
|
|
|
$id_month = $row_months['stats_year'] . sprintf('%02d', $row_months['stats_month']); |
|
587
|
|
|
$expanded = !empty($_SESSION['expanded_stats'][$row_months['stats_year']]) && in_array($row_months['stats_month'], $_SESSION['expanded_stats'][$row_months['stats_year']]); |
|
588
|
|
|
|
|
589
|
|
|
if (!isset($context['yearly'][$row_months['stats_year']])) |
|
590
|
|
|
$context['yearly'][$row_months['stats_year']] = array( |
|
591
|
|
|
'year' => $row_months['stats_year'], |
|
592
|
|
|
'new_topics' => 0, |
|
593
|
|
|
'new_posts' => 0, |
|
594
|
|
|
'new_members' => 0, |
|
595
|
|
|
'most_members_online' => 0, |
|
596
|
|
|
'hits' => 0, |
|
597
|
|
|
'num_months' => 0, |
|
598
|
|
|
'months' => array(), |
|
599
|
|
|
'expanded' => false, |
|
600
|
|
|
'current_year' => $row_months['stats_year'] == date('Y'), |
|
601
|
|
|
); |
|
602
|
|
|
|
|
603
|
|
|
$context['yearly'][$row_months['stats_year']]['months'][(int) $row_months['stats_month']] = array( |
|
604
|
|
|
'id' => $id_month, |
|
605
|
|
|
'date' => array( |
|
606
|
|
|
'month' => sprintf('%02d', $row_months['stats_month']), |
|
607
|
|
|
'year' => $row_months['stats_year'] |
|
608
|
|
|
), |
|
609
|
|
|
'href' => $scripturl . '?action=stats;' . ($expanded ? 'collapse' : 'expand') . '=' . $id_month . '#m' . $id_month, |
|
610
|
|
|
'link' => '<a href="' . $scripturl . '?action=stats;' . ($expanded ? 'collapse' : 'expand') . '=' . $id_month . '#m' . $id_month . '">' . $txt['months'][(int) $row_months['stats_month']] . ' ' . $row_months['stats_year'] . '</a>', |
|
611
|
|
|
'month' => $txt['months'][(int) $row_months['stats_month']], |
|
612
|
|
|
'year' => $row_months['stats_year'], |
|
613
|
|
|
'new_topics' => comma_format($row_months['topics']), |
|
614
|
|
|
'new_posts' => comma_format($row_months['posts']), |
|
615
|
|
|
'new_members' => comma_format($row_months['registers']), |
|
616
|
|
|
'most_members_online' => comma_format($row_months['most_on']), |
|
617
|
|
|
'hits' => comma_format($row_months['hits']), |
|
618
|
|
|
'num_days' => $row_months['num_days'], |
|
619
|
|
|
'days' => array(), |
|
620
|
|
|
'expanded' => $expanded |
|
621
|
|
|
); |
|
622
|
|
|
|
|
623
|
|
|
$context['yearly'][$row_months['stats_year']]['new_topics'] += $row_months['topics']; |
|
624
|
|
|
$context['yearly'][$row_months['stats_year']]['new_posts'] += $row_months['posts']; |
|
625
|
|
|
$context['yearly'][$row_months['stats_year']]['new_members'] += $row_months['registers']; |
|
626
|
|
|
$context['yearly'][$row_months['stats_year']]['hits'] += $row_months['hits']; |
|
627
|
|
|
$context['yearly'][$row_months['stats_year']]['num_months']++; |
|
628
|
|
|
$context['yearly'][$row_months['stats_year']]['expanded'] |= $expanded; |
|
629
|
|
|
$context['yearly'][$row_months['stats_year']]['most_members_online'] = max($context['yearly'][$row_months['stats_year']]['most_members_online'], $row_months['most_on']); |
|
630
|
|
|
} |
|
631
|
|
|
|
|
632
|
|
|
krsort($context['yearly']); |
|
633
|
|
|
} |
|
634
|
|
|
|
|
635
|
|
|
/** |
|
636
|
|
|
* Loads the statistics on a daily basis in $context. |
|
637
|
|
|
* |
|
638
|
|
|
* - called by action_stats(). |
|
639
|
|
|
* |
|
640
|
|
|
* @param string $condition_string |
|
641
|
|
|
* @param mixed[] $condition_parameters = array() |
|
642
|
|
|
*/ |
|
643
|
|
|
function getDailyStats($condition_string, $condition_parameters = array()) |
|
644
|
|
|
{ |
|
645
|
|
|
global $context; |
|
646
|
|
|
|
|
647
|
|
|
$db = database(); |
|
648
|
|
|
|
|
649
|
|
|
// Activity by day. |
|
650
|
|
|
$days_result = $db->query('', ' |
|
651
|
|
|
SELECT YEAR(date) AS stats_year, MONTH(date) AS stats_month, DAYOFMONTH(date) AS stats_day, topics, posts, registers, most_on, hits |
|
652
|
|
|
FROM {db_prefix}log_activity |
|
653
|
|
|
WHERE ' . $condition_string . ' |
|
654
|
|
|
ORDER BY stats_day DESC', |
|
655
|
|
|
$condition_parameters |
|
656
|
|
|
); |
|
657
|
|
|
while ($row_days = $db->fetch_assoc($days_result)) |
|
658
|
|
|
$context['yearly'][$row_days['stats_year']]['months'][(int) $row_days['stats_month']]['days'][] = array( |
|
659
|
|
|
'day' => sprintf('%02d', $row_days['stats_day']), |
|
660
|
|
|
'month' => sprintf('%02d', $row_days['stats_month']), |
|
661
|
|
|
'year' => $row_days['stats_year'], |
|
662
|
|
|
'new_topics' => comma_format($row_days['topics']), |
|
663
|
|
|
'new_posts' => comma_format($row_days['posts']), |
|
664
|
|
|
'new_members' => comma_format($row_days['registers']), |
|
665
|
|
|
'most_members_online' => comma_format($row_days['most_on']), |
|
666
|
|
|
'hits' => comma_format($row_days['hits']) |
|
667
|
|
|
); |
|
668
|
|
|
$db->free_result($days_result); |
|
669
|
|
|
} |
|
670
|
|
|
|
|
671
|
|
|
/** |
|
672
|
|
|
* Returns the number of topics a user has started, including ones on boards |
|
673
|
|
|
* they may no longer have access on. |
|
674
|
|
|
* |
|
675
|
|
|
* - Does not count topics that are in the recycle board |
|
676
|
|
|
* |
|
677
|
|
|
* @param int $memID |
|
678
|
|
|
*/ |
|
679
|
|
View Code Duplication |
function UserStatsTopicsStarted($memID) |
|
|
|
|
|
|
680
|
|
|
{ |
|
681
|
|
|
global $modSettings; |
|
682
|
|
|
|
|
683
|
|
|
$db = database(); |
|
684
|
|
|
|
|
685
|
|
|
// Number of topics started. |
|
686
|
|
|
$result = $db->query('', ' |
|
687
|
|
|
SELECT COUNT(*) |
|
688
|
|
|
FROM {db_prefix}topics |
|
689
|
|
|
WHERE id_member_started = {int:current_member}' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? ' |
|
690
|
|
|
AND id_board != {int:recycle_board}' : ''), |
|
691
|
|
|
array( |
|
692
|
|
|
'current_member' => $memID, |
|
693
|
|
|
'recycle_board' => $modSettings['recycle_board'], |
|
694
|
|
|
) |
|
695
|
|
|
); |
|
696
|
|
|
list ($num_topics) = $db->fetch_row($result); |
|
697
|
|
|
$db->free_result($result); |
|
698
|
|
|
|
|
699
|
|
|
return $num_topics; |
|
700
|
|
|
} |
|
701
|
|
|
|
|
702
|
|
|
/** |
|
703
|
|
|
* Returns the number of polls a user has started, including ones on boards |
|
704
|
|
|
* they may no longer have access on. |
|
705
|
|
|
* |
|
706
|
|
|
* - Does not count topics that are in the recycle board |
|
707
|
|
|
* |
|
708
|
|
|
* @param int $memID |
|
709
|
|
|
*/ |
|
710
|
|
|
function UserStatsPollsStarted($memID) |
|
711
|
|
|
{ |
|
712
|
|
|
global $modSettings; |
|
713
|
|
|
|
|
714
|
|
|
$db = database(); |
|
715
|
|
|
|
|
716
|
|
|
// Number polls started. |
|
717
|
|
|
$result = $db->query('', ' |
|
718
|
|
|
SELECT COUNT(*) |
|
719
|
|
|
FROM {db_prefix}topics |
|
720
|
|
|
WHERE id_member_started = {int:current_member}' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? ' |
|
721
|
|
|
AND id_board != {int:recycle_board}' : '') . ' |
|
722
|
|
|
AND id_poll != {int:no_poll}', |
|
723
|
|
|
array( |
|
724
|
|
|
'current_member' => $memID, |
|
725
|
|
|
'recycle_board' => $modSettings['recycle_board'], |
|
726
|
|
|
'no_poll' => 0, |
|
727
|
|
|
) |
|
728
|
|
|
); |
|
729
|
|
|
list ($num_polls) = $db->fetch_row($result); |
|
730
|
|
|
$db->free_result($result); |
|
731
|
|
|
|
|
732
|
|
|
return $num_polls; |
|
733
|
|
|
} |
|
734
|
|
|
|
|
735
|
|
|
/** |
|
736
|
|
|
* Returns the number of polls a user has voted in, including ones on boards |
|
737
|
|
|
* they may no longer have access on. |
|
738
|
|
|
* |
|
739
|
|
|
* @param int $memID |
|
740
|
|
|
*/ |
|
741
|
|
View Code Duplication |
function UserStatsPollsVoted($memID) |
|
|
|
|
|
|
742
|
|
|
{ |
|
743
|
|
|
$db = database(); |
|
744
|
|
|
|
|
745
|
|
|
// Number polls voted in. |
|
746
|
|
|
$result = $db->query('distinct_poll_votes', ' |
|
747
|
|
|
SELECT COUNT(DISTINCT id_poll) |
|
748
|
|
|
FROM {db_prefix}log_polls |
|
749
|
|
|
WHERE id_member = {int:current_member}', |
|
750
|
|
|
array( |
|
751
|
|
|
'current_member' => $memID, |
|
752
|
|
|
) |
|
753
|
|
|
); |
|
754
|
|
|
list ($num_votes) = $db->fetch_row($result); |
|
755
|
|
|
$db->free_result($result); |
|
756
|
|
|
|
|
757
|
|
|
return $num_votes; |
|
758
|
|
|
} |
|
759
|
|
|
|
|
760
|
|
|
/** |
|
761
|
|
|
* Finds the 1-N list of boards that a user posts in most often |
|
762
|
|
|
* |
|
763
|
|
|
* - Returns array with some basic stats of post percent per board |
|
764
|
|
|
* |
|
765
|
|
|
* @param int $memID |
|
766
|
|
|
* @param int $limit |
|
767
|
|
|
*/ |
|
768
|
|
|
function UserStatsMostPostedBoard($memID, $limit = 10) |
|
769
|
|
|
{ |
|
770
|
|
|
global $scripturl, $user_profile; |
|
771
|
|
|
|
|
772
|
|
|
$db = database(); |
|
773
|
|
|
|
|
774
|
|
|
// Find the board this member spammed most often. |
|
775
|
|
|
$result = $db->query('', ' |
|
776
|
|
|
SELECT |
|
777
|
|
|
b.id_board, MAX(b.name) AS name, MAX(b.num_posts) AS num_posts, COUNT(*) AS message_count |
|
778
|
|
|
FROM {db_prefix}messages AS m |
|
779
|
|
|
INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board) |
|
780
|
|
|
WHERE m.id_member = {int:current_member} |
|
781
|
|
|
AND b.count_posts = {int:count_enabled} |
|
782
|
|
|
AND {query_see_board} |
|
783
|
|
|
GROUP BY b.id_board |
|
784
|
|
|
ORDER BY message_count DESC |
|
785
|
|
|
LIMIT {int:limit}', |
|
786
|
|
|
array( |
|
787
|
|
|
'current_member' => $memID, |
|
788
|
|
|
'count_enabled' => 0, |
|
789
|
|
|
'limit' => (int) $limit, |
|
790
|
|
|
) |
|
791
|
|
|
); |
|
792
|
|
|
$popular_boards = array(); |
|
793
|
|
|
while ($row = $db->fetch_assoc($result)) |
|
794
|
|
|
{ |
|
795
|
|
|
// Build the board details that this member is responsible for |
|
796
|
|
|
$popular_boards[$row['id_board']] = array( |
|
797
|
|
|
'id' => $row['id_board'], |
|
798
|
|
|
'posts' => $row['message_count'], |
|
799
|
|
|
'href' => $scripturl . '?board=' . $row['id_board'] . '.0', |
|
800
|
|
|
'link' => '<a href="' . $scripturl . '?board=' . $row['id_board'] . '.0">' . $row['name'] . '</a>', |
|
801
|
|
|
'posts_percent' => $user_profile[$memID]['posts'] == 0 ? 0 : ($row['message_count'] * 100) / $user_profile[$memID]['posts'], |
|
802
|
|
|
'total_posts' => $row['num_posts'], |
|
803
|
|
|
'total_posts_member' => $user_profile[$memID]['posts'], |
|
804
|
|
|
); |
|
805
|
|
|
} |
|
806
|
|
|
$db->free_result($result); |
|
807
|
|
|
|
|
808
|
|
|
return $popular_boards; |
|
809
|
|
|
} |
|
810
|
|
|
|
|
811
|
|
|
/** |
|
812
|
|
|
* Finds the 1-N list of boards that a user participates in most often |
|
813
|
|
|
* |
|
814
|
|
|
* - Returns array with some basic stats of post percent per board as a percent of board activity |
|
815
|
|
|
* |
|
816
|
|
|
* @param int $memID |
|
817
|
|
|
* @param int $limit |
|
818
|
|
|
*/ |
|
819
|
|
|
function UserStatsMostActiveBoard($memID, $limit = 10) |
|
820
|
|
|
{ |
|
821
|
|
|
global $scripturl; |
|
822
|
|
|
|
|
823
|
|
|
$db = database(); |
|
824
|
|
|
|
|
825
|
|
|
// Find the board this member spammed most often. |
|
826
|
|
|
$result = $db->query('profile_board_stats', ' |
|
827
|
|
|
SELECT |
|
828
|
|
|
b.id_board, MAX(b.name) AS name, b.num_posts, COUNT(*) AS message_count, |
|
829
|
|
|
CASE WHEN COUNT(*) > MAX(b.num_posts) THEN 1 ELSE COUNT(*) / MAX(b.num_posts) END * 100 AS percentage |
|
830
|
|
|
FROM {db_prefix}messages AS m |
|
831
|
|
|
INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board) |
|
832
|
|
|
WHERE m.id_member = {int:current_member} |
|
833
|
|
|
AND {query_see_board} |
|
834
|
|
|
GROUP BY b.id_board, b.num_posts |
|
835
|
|
|
ORDER BY percentage DESC |
|
836
|
|
|
LIMIT {int:limit}', |
|
837
|
|
|
array( |
|
838
|
|
|
'current_member' => $memID, |
|
839
|
|
|
'limit' => (int) $limit, |
|
840
|
|
|
) |
|
841
|
|
|
); |
|
842
|
|
|
$board_activity = array(); |
|
843
|
|
|
while ($row = $db->fetch_assoc($result)) |
|
844
|
|
|
{ |
|
845
|
|
|
// What have they been doing in this board |
|
846
|
|
|
$board_activity[$row['id_board']] = array( |
|
847
|
|
|
'id' => $row['id_board'], |
|
848
|
|
|
'posts' => $row['message_count'], |
|
849
|
|
|
'href' => $scripturl . '?board=' . $row['id_board'] . '.0', |
|
850
|
|
|
'link' => '<a href="' . $scripturl . '?board=' . $row['id_board'] . '.0">' . $row['name'] . '</a>', |
|
851
|
|
|
'percent' => comma_format((float) $row['percentage'], 2), |
|
852
|
|
|
'posts_percent' => (float) $row['percentage'], |
|
853
|
|
|
'total_posts' => $row['num_posts'], |
|
854
|
|
|
); |
|
855
|
|
|
} |
|
856
|
|
|
$db->free_result($result); |
|
857
|
|
|
|
|
858
|
|
|
return $board_activity; |
|
859
|
|
|
} |
|
860
|
|
|
|
|
861
|
|
|
/** |
|
862
|
|
|
* Finds the users posting activity by time of day |
|
863
|
|
|
* |
|
864
|
|
|
* - Returns array with some basic stats of post percent per hour |
|
865
|
|
|
* |
|
866
|
|
|
* @param int $memID |
|
867
|
|
|
*/ |
|
868
|
|
|
function UserStatsPostingTime($memID) |
|
869
|
|
|
{ |
|
870
|
|
|
global $user_info, $modSettings; |
|
871
|
|
|
|
|
872
|
|
|
$posts_by_time = array(); |
|
873
|
|
|
$hours = array(); |
|
874
|
|
|
for ($hour = 0; $hour < 24; $hour++) |
|
875
|
|
|
{ |
|
876
|
|
|
$posts_by_time[$hour] = array( |
|
877
|
|
|
'hour' => $hour, |
|
878
|
|
|
'hour_format' => stripos($user_info['time_format'], '%p') === false ? $hour : date('g a', mktime($hour)), |
|
879
|
|
|
'posts' => 0, |
|
880
|
|
|
'posts_percent' => 0, |
|
881
|
|
|
'relative_percent' => 0, |
|
882
|
|
|
); |
|
883
|
|
|
} |
|
884
|
|
|
|
|
885
|
|
|
$db = database(); |
|
886
|
|
|
|
|
887
|
|
|
// Find the times when the users posts |
|
888
|
|
|
$result = $db->query('', ' |
|
889
|
|
|
SELECT |
|
890
|
|
|
poster_time |
|
891
|
|
|
FROM {db_prefix}messages |
|
892
|
|
|
WHERE id_member = {int:current_member}' . ($modSettings['totalMessages'] > 100000 ? ' |
|
893
|
|
|
AND id_topic > {int:top_ten_thousand_topics}' : ''), |
|
894
|
|
|
array( |
|
895
|
|
|
'current_member' => $memID, |
|
896
|
|
|
'top_ten_thousand_topics' => $modSettings['totalTopics'] - 10000, |
|
897
|
|
|
) |
|
898
|
|
|
); |
|
899
|
|
|
while (list ($poster_time) = $db->fetch_row($result)) |
|
900
|
|
|
{ |
|
901
|
|
|
// Cast as an integer to remove the leading 0. |
|
902
|
|
|
$hour = (int) standardTime($poster_time, '%H'); |
|
903
|
|
|
|
|
904
|
|
|
if (!isset($hours[$hour])) |
|
905
|
|
|
$hours[$hour] = 0; |
|
906
|
|
|
|
|
907
|
|
|
$hours[$hour]++; |
|
908
|
|
|
} |
|
909
|
|
|
$db->free_result($result); |
|
910
|
|
|
$maxPosts = max($hours); |
|
911
|
|
|
$totalPosts = array_sum($hours); |
|
912
|
|
|
|
|
913
|
|
|
foreach ($hours as $hour => $num) |
|
914
|
|
|
{ |
|
915
|
|
|
// When they post, hour by hour |
|
916
|
|
|
$posts_by_time[$hour] = array_merge($posts_by_time[$hour], array( |
|
917
|
|
|
'posts' => comma_format($num), |
|
918
|
|
|
'posts_percent' => round(($num * 100) / $totalPosts), |
|
919
|
|
|
'relative_percent' => round(($num * 100) / $maxPosts), |
|
920
|
|
|
)); |
|
921
|
|
|
} |
|
922
|
|
|
|
|
923
|
|
|
return $posts_by_time; |
|
924
|
|
|
} |
|
925
|
|
|
|
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.