Mercurial > hg > vamp-website
comparison forum/Sources/Stats.php @ 76:e3e11437ecea website
Add forum code
author | Chris Cannam |
---|---|
date | Sun, 07 Jul 2013 11:25:48 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
75:72f59aa7e503 | 76:e3e11437ecea |
---|---|
1 <?php | |
2 | |
3 /** | |
4 * Simple Machines Forum (SMF) | |
5 * | |
6 * @package SMF | |
7 * @author Simple Machines http://www.simplemachines.org | |
8 * @copyright 2011 Simple Machines | |
9 * @license http://www.simplemachines.org/about/smf/license.php BSD | |
10 * | |
11 * @version 2.0 | |
12 */ | |
13 | |
14 if (!defined('SMF')) | |
15 die('Hacking attempt...'); | |
16 | |
17 /* This function has only one job: providing a display for forum statistics. | |
18 As such, it has only one function: | |
19 | |
20 void DisplayStats() | |
21 - gets all the statistics in order and puts them in. | |
22 - uses the Stats template and language file. (and main sub template.) | |
23 - requires the view_stats permission. | |
24 - accessed from ?action=stats. | |
25 | |
26 void getDailyStats(string $condition) | |
27 - called by DisplayStats(). | |
28 - loads the statistics on a daily basis in $context. | |
29 | |
30 void SMStats() | |
31 - called by simplemachines.org. | |
32 - only returns anything if stats was enabled during installation. | |
33 - can also be accessed by the admin, to show what stats sm.org collects. | |
34 - does not return any data directly to sm.org, instead starts a new request for security. | |
35 | |
36 */ | |
37 | |
38 // Display some useful/interesting board statistics. | |
39 function DisplayStats() | |
40 { | |
41 global $txt, $scripturl, $modSettings, $user_info, $context, $smcFunc; | |
42 | |
43 isAllowedTo('view_stats'); | |
44 | |
45 if (!empty($_REQUEST['expand'])) | |
46 { | |
47 $context['robot_no_index'] = true; | |
48 | |
49 $month = (int) substr($_REQUEST['expand'], 4); | |
50 $year = (int) substr($_REQUEST['expand'], 0, 4); | |
51 if ($year > 1900 && $year < 2200 && $month >= 1 && $month <= 12) | |
52 $_SESSION['expanded_stats'][$year][] = $month; | |
53 } | |
54 elseif (!empty($_REQUEST['collapse'])) | |
55 { | |
56 $context['robot_no_index'] = true; | |
57 | |
58 $month = (int) substr($_REQUEST['collapse'], 4); | |
59 $year = (int) substr($_REQUEST['collapse'], 0, 4); | |
60 if (!empty($_SESSION['expanded_stats'][$year])) | |
61 $_SESSION['expanded_stats'][$year] = array_diff($_SESSION['expanded_stats'][$year], array($month)); | |
62 } | |
63 | |
64 // Handle the XMLHttpRequest. | |
65 if (isset($_REQUEST['xml'])) | |
66 { | |
67 // Collapsing stats only needs adjustments of the session variables. | |
68 if (!empty($_REQUEST['collapse'])) | |
69 obExit(false); | |
70 | |
71 $context['sub_template'] = 'stats'; | |
72 getDailyStats('YEAR(date) = {int:year} AND MONTH(date) = {int:month}', array('year' => $year, 'month' => $month)); | |
73 $context['yearly'][$year]['months'][$month]['date'] = array( | |
74 'month' => sprintf('%02d', $month), | |
75 'year' => $year, | |
76 ); | |
77 return; | |
78 } | |
79 | |
80 loadLanguage('Stats'); | |
81 loadTemplate('Stats'); | |
82 | |
83 // Build the link tree...... | |
84 $context['linktree'][] = array( | |
85 'url' => $scripturl . '?action=stats', | |
86 'name' => $txt['stats_center'] | |
87 ); | |
88 $context['page_title'] = $context['forum_name'] . ' - ' . $txt['stats_center']; | |
89 | |
90 $context['show_member_list'] = allowedTo('view_mlist'); | |
91 | |
92 // Get averages... | |
93 $result = $smcFunc['db_query']('', ' | |
94 SELECT | |
95 SUM(posts) AS posts, SUM(topics) AS topics, SUM(registers) AS registers, | |
96 SUM(most_on) AS most_on, MIN(date) AS date, SUM(hits) AS hits | |
97 FROM {db_prefix}log_activity', | |
98 array( | |
99 ) | |
100 ); | |
101 $row = $smcFunc['db_fetch_assoc']($result); | |
102 $smcFunc['db_free_result']($result); | |
103 | |
104 // This would be the amount of time the forum has been up... in days... | |
105 $total_days_up = ceil((time() - strtotime($row['date'])) / (60 * 60 * 24)); | |
106 | |
107 $context['average_posts'] = comma_format(round($row['posts'] / $total_days_up, 2)); | |
108 $context['average_topics'] = comma_format(round($row['topics'] / $total_days_up, 2)); | |
109 $context['average_members'] = comma_format(round($row['registers'] / $total_days_up, 2)); | |
110 $context['average_online'] = comma_format(round($row['most_on'] / $total_days_up, 2)); | |
111 $context['average_hits'] = comma_format(round($row['hits'] / $total_days_up, 2)); | |
112 | |
113 $context['num_hits'] = comma_format($row['hits'], 0); | |
114 | |
115 // How many users are online now. | |
116 $result = $smcFunc['db_query']('', ' | |
117 SELECT COUNT(*) | |
118 FROM {db_prefix}log_online', | |
119 array( | |
120 ) | |
121 ); | |
122 list ($context['users_online']) = $smcFunc['db_fetch_row']($result); | |
123 $smcFunc['db_free_result']($result); | |
124 | |
125 // Statistics such as number of boards, categories, etc. | |
126 $result = $smcFunc['db_query']('', ' | |
127 SELECT COUNT(*) | |
128 FROM {db_prefix}boards AS b | |
129 WHERE b.redirect = {string:blank_redirect}', | |
130 array( | |
131 'blank_redirect' => '', | |
132 ) | |
133 ); | |
134 list ($context['num_boards']) = $smcFunc['db_fetch_row']($result); | |
135 $smcFunc['db_free_result']($result); | |
136 | |
137 $result = $smcFunc['db_query']('', ' | |
138 SELECT COUNT(*) | |
139 FROM {db_prefix}categories AS c', | |
140 array( | |
141 ) | |
142 ); | |
143 list ($context['num_categories']) = $smcFunc['db_fetch_row']($result); | |
144 $smcFunc['db_free_result']($result); | |
145 | |
146 // Format the numbers nicely. | |
147 $context['users_online'] = comma_format($context['users_online']); | |
148 $context['num_boards'] = comma_format($context['num_boards']); | |
149 $context['num_categories'] = comma_format($context['num_categories']); | |
150 | |
151 $context['num_members'] = comma_format($modSettings['totalMembers']); | |
152 $context['num_posts'] = comma_format($modSettings['totalMessages']); | |
153 $context['num_topics'] = comma_format($modSettings['totalTopics']); | |
154 $context['most_members_online'] = array( | |
155 'number' => comma_format($modSettings['mostOnline']), | |
156 'date' => timeformat($modSettings['mostDate']) | |
157 ); | |
158 $context['latest_member'] = &$context['common_stats']['latest_member']; | |
159 | |
160 // Male vs. female ratio - let's calculate this only every four minutes. | |
161 if (($context['gender'] = cache_get_data('stats_gender', 240)) == null) | |
162 { | |
163 $result = $smcFunc['db_query']('', ' | |
164 SELECT COUNT(*) AS total_members, gender | |
165 FROM {db_prefix}members | |
166 GROUP BY gender', | |
167 array( | |
168 ) | |
169 ); | |
170 $context['gender'] = array(); | |
171 while ($row = $smcFunc['db_fetch_assoc']($result)) | |
172 { | |
173 // Assuming we're telling... male or female? | |
174 if (!empty($row['gender'])) | |
175 $context['gender'][$row['gender'] == 2 ? 'females' : 'males'] = $row['total_members']; | |
176 } | |
177 $smcFunc['db_free_result']($result); | |
178 | |
179 // Set these two zero if the didn't get set at all. | |
180 if (empty($context['gender']['males'])) | |
181 $context['gender']['males'] = 0; | |
182 if (empty($context['gender']['females'])) | |
183 $context['gender']['females'] = 0; | |
184 | |
185 // Try and come up with some "sensible" default states in case of a non-mixed board. | |
186 if ($context['gender']['males'] == $context['gender']['females']) | |
187 $context['gender']['ratio'] = '1:1'; | |
188 elseif ($context['gender']['males'] == 0) | |
189 $context['gender']['ratio'] = '0:1'; | |
190 elseif ($context['gender']['females'] == 0) | |
191 $context['gender']['ratio'] = '1:0'; | |
192 elseif ($context['gender']['males'] > $context['gender']['females']) | |
193 $context['gender']['ratio'] = round($context['gender']['males'] / $context['gender']['females'], 1) . ':1'; | |
194 elseif ($context['gender']['females'] > $context['gender']['males']) | |
195 $context['gender']['ratio'] = '1:' . round($context['gender']['females'] / $context['gender']['males'], 1); | |
196 | |
197 cache_put_data('stats_gender', $context['gender'], 240); | |
198 } | |
199 | |
200 $date = strftime('%Y-%m-%d', forum_time(false)); | |
201 | |
202 // Members online so far today. | |
203 $result = $smcFunc['db_query']('', ' | |
204 SELECT most_on | |
205 FROM {db_prefix}log_activity | |
206 WHERE date = {date:today_date} | |
207 LIMIT 1', | |
208 array( | |
209 'today_date' => $date, | |
210 ) | |
211 ); | |
212 list ($context['online_today']) = $smcFunc['db_fetch_row']($result); | |
213 $smcFunc['db_free_result']($result); | |
214 | |
215 $context['online_today'] = comma_format((int) $context['online_today']); | |
216 | |
217 // Poster top 10. | |
218 $members_result = $smcFunc['db_query']('', ' | |
219 SELECT id_member, real_name, posts | |
220 FROM {db_prefix}members | |
221 WHERE posts > {int:no_posts} | |
222 ORDER BY posts DESC | |
223 LIMIT 10', | |
224 array( | |
225 'no_posts' => 0, | |
226 ) | |
227 ); | |
228 $context['top_posters'] = array(); | |
229 $max_num_posts = 1; | |
230 while ($row_members = $smcFunc['db_fetch_assoc']($members_result)) | |
231 { | |
232 $context['top_posters'][] = array( | |
233 'name' => $row_members['real_name'], | |
234 'id' => $row_members['id_member'], | |
235 'num_posts' => $row_members['posts'], | |
236 'href' => $scripturl . '?action=profile;u=' . $row_members['id_member'], | |
237 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row_members['id_member'] . '">' . $row_members['real_name'] . '</a>' | |
238 ); | |
239 | |
240 if ($max_num_posts < $row_members['posts']) | |
241 $max_num_posts = $row_members['posts']; | |
242 } | |
243 $smcFunc['db_free_result']($members_result); | |
244 | |
245 foreach ($context['top_posters'] as $i => $poster) | |
246 { | |
247 $context['top_posters'][$i]['post_percent'] = round(($poster['num_posts'] * 100) / $max_num_posts); | |
248 $context['top_posters'][$i]['num_posts'] = comma_format($context['top_posters'][$i]['num_posts']); | |
249 } | |
250 | |
251 // Board top 10. | |
252 $boards_result = $smcFunc['db_query']('', ' | |
253 SELECT id_board, name, num_posts | |
254 FROM {db_prefix}boards AS b | |
255 WHERE {query_see_board}' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? ' | |
256 AND b.id_board != {int:recycle_board}' : '') . ' | |
257 AND b.redirect = {string:blank_redirect} | |
258 ORDER BY num_posts DESC | |
259 LIMIT 10', | |
260 array( | |
261 'recycle_board' => $modSettings['recycle_board'], | |
262 'blank_redirect' => '', | |
263 ) | |
264 ); | |
265 $context['top_boards'] = array(); | |
266 $max_num_posts = 1; | |
267 while ($row_board = $smcFunc['db_fetch_assoc']($boards_result)) | |
268 { | |
269 $context['top_boards'][] = array( | |
270 'id' => $row_board['id_board'], | |
271 'name' => $row_board['name'], | |
272 'num_posts' => $row_board['num_posts'], | |
273 'href' => $scripturl . '?board=' . $row_board['id_board'] . '.0', | |
274 'link' => '<a href="' . $scripturl . '?board=' . $row_board['id_board'] . '.0">' . $row_board['name'] . '</a>' | |
275 ); | |
276 | |
277 if ($max_num_posts < $row_board['num_posts']) | |
278 $max_num_posts = $row_board['num_posts']; | |
279 } | |
280 $smcFunc['db_free_result']($boards_result); | |
281 | |
282 foreach ($context['top_boards'] as $i => $board) | |
283 { | |
284 $context['top_boards'][$i]['post_percent'] = round(($board['num_posts'] * 100) / $max_num_posts); | |
285 $context['top_boards'][$i]['num_posts'] = comma_format($context['top_boards'][$i]['num_posts']); | |
286 } | |
287 | |
288 // Are you on a larger forum? If so, let's try to limit the number of topics we search through. | |
289 if ($modSettings['totalMessages'] > 100000) | |
290 { | |
291 $request = $smcFunc['db_query']('', ' | |
292 SELECT id_topic | |
293 FROM {db_prefix}topics | |
294 WHERE num_replies != {int:no_replies}' . ($modSettings['postmod_active'] ? ' | |
295 AND approved = {int:is_approved}' : '') . ' | |
296 ORDER BY num_replies DESC | |
297 LIMIT 100', | |
298 array( | |
299 'no_replies' => 0, | |
300 'is_approved' => 1, | |
301 ) | |
302 ); | |
303 $topic_ids = array(); | |
304 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
305 $topic_ids[] = $row['id_topic']; | |
306 $smcFunc['db_free_result']($request); | |
307 } | |
308 else | |
309 $topic_ids = array(); | |
310 | |
311 // Topic replies top 10. | |
312 $topic_reply_result = $smcFunc['db_query']('', ' | |
313 SELECT m.subject, t.num_replies, t.id_board, t.id_topic, b.name | |
314 FROM {db_prefix}topics AS t | |
315 INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) | |
316 INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? ' | |
317 AND b.id_board != {int:recycle_board}' : '') . ') | |
318 WHERE {query_see_board}' . (!empty($topic_ids) ? ' | |
319 AND t.id_topic IN ({array_int:topic_list})' : ($modSettings['postmod_active'] ? ' | |
320 AND t.approved = {int:is_approved}' : '')) . ' | |
321 ORDER BY t.num_replies DESC | |
322 LIMIT 10', | |
323 array( | |
324 'topic_list' => $topic_ids, | |
325 'recycle_board' => $modSettings['recycle_board'], | |
326 'is_approved' => 1, | |
327 ) | |
328 ); | |
329 $context['top_topics_replies'] = array(); | |
330 $max_num_replies = 1; | |
331 while ($row_topic_reply = $smcFunc['db_fetch_assoc']($topic_reply_result)) | |
332 { | |
333 censorText($row_topic_reply['subject']); | |
334 | |
335 $context['top_topics_replies'][] = array( | |
336 'id' => $row_topic_reply['id_topic'], | |
337 'board' => array( | |
338 'id' => $row_topic_reply['id_board'], | |
339 'name' => $row_topic_reply['name'], | |
340 'href' => $scripturl . '?board=' . $row_topic_reply['id_board'] . '.0', | |
341 'link' => '<a href="' . $scripturl . '?board=' . $row_topic_reply['id_board'] . '.0">' . $row_topic_reply['name'] . '</a>' | |
342 ), | |
343 'subject' => $row_topic_reply['subject'], | |
344 'num_replies' => $row_topic_reply['num_replies'], | |
345 'href' => $scripturl . '?topic=' . $row_topic_reply['id_topic'] . '.0', | |
346 'link' => '<a href="' . $scripturl . '?topic=' . $row_topic_reply['id_topic'] . '.0">' . $row_topic_reply['subject'] . '</a>' | |
347 ); | |
348 | |
349 if ($max_num_replies < $row_topic_reply['num_replies']) | |
350 $max_num_replies = $row_topic_reply['num_replies']; | |
351 } | |
352 $smcFunc['db_free_result']($topic_reply_result); | |
353 | |
354 foreach ($context['top_topics_replies'] as $i => $topic) | |
355 { | |
356 $context['top_topics_replies'][$i]['post_percent'] = round(($topic['num_replies'] * 100) / $max_num_replies); | |
357 $context['top_topics_replies'][$i]['num_replies'] = comma_format($context['top_topics_replies'][$i]['num_replies']); | |
358 } | |
359 | |
360 // Large forums may need a bit more prodding... | |
361 if ($modSettings['totalMessages'] > 100000) | |
362 { | |
363 $request = $smcFunc['db_query']('', ' | |
364 SELECT id_topic | |
365 FROM {db_prefix}topics | |
366 WHERE num_views != {int:no_views} | |
367 ORDER BY num_views DESC | |
368 LIMIT 100', | |
369 array( | |
370 'no_views' => 0, | |
371 ) | |
372 ); | |
373 $topic_ids = array(); | |
374 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
375 $topic_ids[] = $row['id_topic']; | |
376 $smcFunc['db_free_result']($request); | |
377 } | |
378 else | |
379 $topic_ids = array(); | |
380 | |
381 // Topic views top 10. | |
382 $topic_view_result = $smcFunc['db_query']('', ' | |
383 SELECT m.subject, t.num_views, t.id_board, t.id_topic, b.name | |
384 FROM {db_prefix}topics AS t | |
385 INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) | |
386 INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? ' | |
387 AND b.id_board != {int:recycle_board}' : '') . ') | |
388 WHERE {query_see_board}' . (!empty($topic_ids) ? ' | |
389 AND t.id_topic IN ({array_int:topic_list})' : ($modSettings['postmod_active'] ? ' | |
390 AND t.approved = {int:is_approved}' : '')) . ' | |
391 ORDER BY t.num_views DESC | |
392 LIMIT 10', | |
393 array( | |
394 'topic_list' => $topic_ids, | |
395 'recycle_board' => $modSettings['recycle_board'], | |
396 'is_approved' => 1, | |
397 ) | |
398 ); | |
399 $context['top_topics_views'] = array(); | |
400 $max_num_views = 1; | |
401 while ($row_topic_views = $smcFunc['db_fetch_assoc']($topic_view_result)) | |
402 { | |
403 censorText($row_topic_views['subject']); | |
404 | |
405 $context['top_topics_views'][] = array( | |
406 'id' => $row_topic_views['id_topic'], | |
407 'board' => array( | |
408 'id' => $row_topic_views['id_board'], | |
409 'name' => $row_topic_views['name'], | |
410 'href' => $scripturl . '?board=' . $row_topic_views['id_board'] . '.0', | |
411 'link' => '<a href="' . $scripturl . '?board=' . $row_topic_views['id_board'] . '.0">' . $row_topic_views['name'] . '</a>' | |
412 ), | |
413 'subject' => $row_topic_views['subject'], | |
414 'num_views' => $row_topic_views['num_views'], | |
415 'href' => $scripturl . '?topic=' . $row_topic_views['id_topic'] . '.0', | |
416 'link' => '<a href="' . $scripturl . '?topic=' . $row_topic_views['id_topic'] . '.0">' . $row_topic_views['subject'] . '</a>' | |
417 ); | |
418 | |
419 if ($max_num_views < $row_topic_views['num_views']) | |
420 $max_num_views = $row_topic_views['num_views']; | |
421 } | |
422 $smcFunc['db_free_result']($topic_view_result); | |
423 | |
424 foreach ($context['top_topics_views'] as $i => $topic) | |
425 { | |
426 $context['top_topics_views'][$i]['post_percent'] = round(($topic['num_views'] * 100) / $max_num_views); | |
427 $context['top_topics_views'][$i]['num_views'] = comma_format($context['top_topics_views'][$i]['num_views']); | |
428 } | |
429 | |
430 // Try to cache this when possible, because it's a little unavoidably slow. | |
431 if (($members = cache_get_data('stats_top_starters', 360)) == null) | |
432 { | |
433 $request = $smcFunc['db_query']('', ' | |
434 SELECT id_member_started, COUNT(*) AS hits | |
435 FROM {db_prefix}topics' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? ' | |
436 WHERE id_board != {int:recycle_board}' : '') . ' | |
437 GROUP BY id_member_started | |
438 ORDER BY hits DESC | |
439 LIMIT 20', | |
440 array( | |
441 'recycle_board' => $modSettings['recycle_board'], | |
442 ) | |
443 ); | |
444 $members = array(); | |
445 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
446 $members[$row['id_member_started']] = $row['hits']; | |
447 $smcFunc['db_free_result']($request); | |
448 | |
449 cache_put_data('stats_top_starters', $members, 360); | |
450 } | |
451 | |
452 if (empty($members)) | |
453 $members = array(0 => 0); | |
454 | |
455 // Topic poster top 10. | |
456 $members_result = $smcFunc['db_query']('top_topic_starters', ' | |
457 SELECT id_member, real_name | |
458 FROM {db_prefix}members | |
459 WHERE id_member IN ({array_int:member_list}) | |
460 ORDER BY FIND_IN_SET(id_member, {string:top_topic_posters}) | |
461 LIMIT 10', | |
462 array( | |
463 'member_list' => array_keys($members), | |
464 'top_topic_posters' => implode(',', array_keys($members)), | |
465 ) | |
466 ); | |
467 $context['top_starters'] = array(); | |
468 $max_num_topics = 1; | |
469 while ($row_members = $smcFunc['db_fetch_assoc']($members_result)) | |
470 { | |
471 $context['top_starters'][] = array( | |
472 'name' => $row_members['real_name'], | |
473 'id' => $row_members['id_member'], | |
474 'num_topics' => $members[$row_members['id_member']], | |
475 'href' => $scripturl . '?action=profile;u=' . $row_members['id_member'], | |
476 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row_members['id_member'] . '">' . $row_members['real_name'] . '</a>' | |
477 ); | |
478 | |
479 if ($max_num_topics < $members[$row_members['id_member']]) | |
480 $max_num_topics = $members[$row_members['id_member']]; | |
481 } | |
482 $smcFunc['db_free_result']($members_result); | |
483 | |
484 foreach ($context['top_starters'] as $i => $topic) | |
485 { | |
486 $context['top_starters'][$i]['post_percent'] = round(($topic['num_topics'] * 100) / $max_num_topics); | |
487 $context['top_starters'][$i]['num_topics'] = comma_format($context['top_starters'][$i]['num_topics']); | |
488 } | |
489 | |
490 // Time online top 10. | |
491 $temp = cache_get_data('stats_total_time_members', 600); | |
492 $members_result = $smcFunc['db_query']('', ' | |
493 SELECT id_member, real_name, total_time_logged_in | |
494 FROM {db_prefix}members' . (!empty($temp) ? ' | |
495 WHERE id_member IN ({array_int:member_list_cached})' : '') . ' | |
496 ORDER BY total_time_logged_in DESC | |
497 LIMIT 20', | |
498 array( | |
499 'member_list_cached' => $temp, | |
500 ) | |
501 ); | |
502 $context['top_time_online'] = array(); | |
503 $temp2 = array(); | |
504 $max_time_online = 1; | |
505 while ($row_members = $smcFunc['db_fetch_assoc']($members_result)) | |
506 { | |
507 $temp2[] = (int) $row_members['id_member']; | |
508 if (count($context['top_time_online']) >= 10) | |
509 continue; | |
510 | |
511 // Figure out the days, hours and minutes. | |
512 $timeDays = floor($row_members['total_time_logged_in'] / 86400); | |
513 $timeHours = floor(($row_members['total_time_logged_in'] % 86400) / 3600); | |
514 | |
515 // Figure out which things to show... (days, hours, minutes, etc.) | |
516 $timelogged = ''; | |
517 if ($timeDays > 0) | |
518 $timelogged .= $timeDays . $txt['totalTimeLogged5']; | |
519 if ($timeHours > 0) | |
520 $timelogged .= $timeHours . $txt['totalTimeLogged6']; | |
521 $timelogged .= floor(($row_members['total_time_logged_in'] % 3600) / 60) . $txt['totalTimeLogged7']; | |
522 | |
523 $context['top_time_online'][] = array( | |
524 'id' => $row_members['id_member'], | |
525 'name' => $row_members['real_name'], | |
526 'time_online' => $timelogged, | |
527 'seconds_online' => $row_members['total_time_logged_in'], | |
528 'href' => $scripturl . '?action=profile;u=' . $row_members['id_member'], | |
529 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row_members['id_member'] . '">' . $row_members['real_name'] . '</a>' | |
530 ); | |
531 | |
532 if ($max_time_online < $row_members['total_time_logged_in']) | |
533 $max_time_online = $row_members['total_time_logged_in']; | |
534 } | |
535 $smcFunc['db_free_result']($members_result); | |
536 | |
537 foreach ($context['top_time_online'] as $i => $member) | |
538 $context['top_time_online'][$i]['time_percent'] = round(($member['seconds_online'] * 100) / $max_time_online); | |
539 | |
540 // Cache the ones we found for a bit, just so we don't have to look again. | |
541 if ($temp !== $temp2) | |
542 cache_put_data('stats_total_time_members', $temp2, 480); | |
543 | |
544 // Activity by month. | |
545 $months_result = $smcFunc['db_query']('', ' | |
546 SELECT | |
547 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 | |
548 FROM {db_prefix}log_activity | |
549 GROUP BY stats_year, stats_month', | |
550 array() | |
551 ); | |
552 | |
553 $context['yearly'] = array(); | |
554 while ($row_months = $smcFunc['db_fetch_assoc']($months_result)) | |
555 { | |
556 $ID_MONTH = $row_months['stats_year'] . sprintf('%02d', $row_months['stats_month']); | |
557 $expanded = !empty($_SESSION['expanded_stats'][$row_months['stats_year']]) && in_array($row_months['stats_month'], $_SESSION['expanded_stats'][$row_months['stats_year']]); | |
558 | |
559 if (!isset($context['yearly'][$row_months['stats_year']])) | |
560 $context['yearly'][$row_months['stats_year']] = array( | |
561 'year' => $row_months['stats_year'], | |
562 'new_topics' => 0, | |
563 'new_posts' => 0, | |
564 'new_members' => 0, | |
565 'most_members_online' => 0, | |
566 'hits' => 0, | |
567 'num_months' => 0, | |
568 'months' => array(), | |
569 'expanded' => false, | |
570 'current_year' => $row_months['stats_year'] == date('Y'), | |
571 ); | |
572 | |
573 $context['yearly'][$row_months['stats_year']]['months'][(int) $row_months['stats_month']] = array( | |
574 'id' => $ID_MONTH, | |
575 'date' => array( | |
576 'month' => sprintf('%02d', $row_months['stats_month']), | |
577 'year' => $row_months['stats_year'] | |
578 ), | |
579 'href' => $scripturl . '?action=stats;' . ($expanded ? 'collapse' : 'expand') . '=' . $ID_MONTH . '#m' . $ID_MONTH, | |
580 '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>', | |
581 'month' => $txt['months'][(int) $row_months['stats_month']], | |
582 'year' => $row_months['stats_year'], | |
583 'new_topics' => comma_format($row_months['topics']), | |
584 'new_posts' => comma_format($row_months['posts']), | |
585 'new_members' => comma_format($row_months['registers']), | |
586 'most_members_online' => comma_format($row_months['most_on']), | |
587 'hits' => comma_format($row_months['hits']), | |
588 'num_days' => $row_months['num_days'], | |
589 'days' => array(), | |
590 'expanded' => $expanded | |
591 ); | |
592 | |
593 $context['yearly'][$row_months['stats_year']]['new_topics'] += $row_months['topics']; | |
594 $context['yearly'][$row_months['stats_year']]['new_posts'] += $row_months['posts']; | |
595 $context['yearly'][$row_months['stats_year']]['new_members'] += $row_months['registers']; | |
596 $context['yearly'][$row_months['stats_year']]['hits'] += $row_months['hits']; | |
597 $context['yearly'][$row_months['stats_year']]['num_months']++; | |
598 $context['yearly'][$row_months['stats_year']]['expanded'] |= $expanded; | |
599 $context['yearly'][$row_months['stats_year']]['most_members_online'] = max($context['yearly'][$row_months['stats_year']]['most_members_online'], $row_months['most_on']); | |
600 } | |
601 | |
602 krsort($context['yearly']); | |
603 | |
604 $context['collapsed_years'] = array(); | |
605 foreach ($context['yearly'] as $year => $data) | |
606 { | |
607 // This gets rid of the filesort on the query ;). | |
608 krsort($context['yearly'][$year]['months']); | |
609 | |
610 $context['yearly'][$year]['new_topics'] = comma_format($data['new_topics']); | |
611 $context['yearly'][$year]['new_posts'] = comma_format($data['new_posts']); | |
612 $context['yearly'][$year]['new_members'] = comma_format($data['new_members']); | |
613 $context['yearly'][$year]['most_members_online'] = comma_format($data['most_members_online']); | |
614 $context['yearly'][$year]['hits'] = comma_format($data['hits']); | |
615 | |
616 // Keep a list of collapsed years. | |
617 if (!$data['expanded'] && !$data['current_year']) | |
618 $context['collapsed_years'][] = $year; | |
619 } | |
620 | |
621 if (empty($_SESSION['expanded_stats'])) | |
622 return; | |
623 | |
624 $condition_text = array(); | |
625 $condition_params = array(); | |
626 foreach ($_SESSION['expanded_stats'] as $year => $months) | |
627 if (!empty($months)) | |
628 { | |
629 $condition_text[] = 'YEAR(date) = {int:year_' . $year . '} AND MONTH(date) IN ({array_int:months_' . $year . '})'; | |
630 $condition_params['year_' . $year] = $year; | |
631 $condition_params['months_' . $year] = $months; | |
632 } | |
633 | |
634 // No daily stats to even look at? | |
635 if (empty($condition_text)) | |
636 return; | |
637 | |
638 getDailyStats(implode(' OR ', $condition_text), $condition_params); | |
639 } | |
640 | |
641 function getDailyStats($condition_string, $condition_parameters = array()) | |
642 { | |
643 global $context, $smcFunc; | |
644 | |
645 // Activity by day. | |
646 $days_result = $smcFunc['db_query']('', ' | |
647 SELECT YEAR(date) AS stats_year, MONTH(date) AS stats_month, DAYOFMONTH(date) AS stats_day, topics, posts, registers, most_on, hits | |
648 FROM {db_prefix}log_activity | |
649 WHERE ' . $condition_string . ' | |
650 ORDER BY stats_day ASC', | |
651 $condition_parameters | |
652 ); | |
653 while ($row_days = $smcFunc['db_fetch_assoc']($days_result)) | |
654 $context['yearly'][$row_days['stats_year']]['months'][(int) $row_days['stats_month']]['days'][] = array( | |
655 'day' => sprintf('%02d', $row_days['stats_day']), | |
656 'month' => sprintf('%02d', $row_days['stats_month']), | |
657 'year' => $row_days['stats_year'], | |
658 'new_topics' => comma_format($row_days['topics']), | |
659 'new_posts' => comma_format($row_days['posts']), | |
660 'new_members' => comma_format($row_days['registers']), | |
661 'most_members_online' => comma_format($row_days['most_on']), | |
662 'hits' => comma_format($row_days['hits']) | |
663 ); | |
664 $smcFunc['db_free_result']($days_result); | |
665 } | |
666 | |
667 // This is the function which returns stats to simplemachines.org IF enabled! | |
668 // See http://www.simplemachines.org/about/stats.php for more info. | |
669 function SMStats() | |
670 { | |
671 global $modSettings, $user_info, $forum_version, $sourcedir; | |
672 | |
673 // First, is it disabled? | |
674 if (empty($modSettings['allow_sm_stats'])) | |
675 die(); | |
676 | |
677 // Are we saying who we are, and are we right? (OR an admin) | |
678 if (!$user_info['is_admin'] && (!isset($_GET['sid']) || $_GET['sid'] != $modSettings['allow_sm_stats'])) | |
679 die(); | |
680 | |
681 // Verify the referer... | |
682 if (!$user_info['is_admin'] && (!isset($_SERVER['HTTP_REFERER']) || md5($_SERVER['HTTP_REFERER']) != '746cb59a1a0d5cf4bd240e5a67c73085')) | |
683 die(); | |
684 | |
685 // Get some server versions. | |
686 require_once($sourcedir . '/Subs-Admin.php'); | |
687 $checkFor = array( | |
688 'php', | |
689 'db_server', | |
690 ); | |
691 $serverVersions = getServerVersions($checkFor); | |
692 | |
693 // Get the actual stats. | |
694 $stats_to_send = array( | |
695 'UID' => $modSettings['allow_sm_stats'], | |
696 'time_added' => time(), | |
697 'members' => $modSettings['totalMembers'], | |
698 'messages' => $modSettings['totalMessages'], | |
699 'topics' => $modSettings['totalTopics'], | |
700 'boards' => 0, | |
701 'php_version' => $serverVersions['php']['version'], | |
702 'database_type' => strtolower($serverVersions['db_server']['title']), | |
703 'database_version' => $serverVersions['db_server']['version'], | |
704 'smf_version' => $forum_version, | |
705 'smfd_version' => $modSettings['smfVersion'], | |
706 ); | |
707 | |
708 // Encode all the data, for security. | |
709 foreach ($stats_to_send as $k => $v) | |
710 $stats_to_send[$k] = urlencode($k) . '=' . urlencode($v); | |
711 | |
712 // Turn this into the query string! | |
713 $stats_to_send = implode('&', $stats_to_send); | |
714 | |
715 // If we're an admin, just plonk them out. | |
716 if ($user_info['is_admin']) | |
717 echo $stats_to_send; | |
718 else | |
719 { | |
720 // Connect to the collection script. | |
721 $fp = @fsockopen('www.simplemachines.org', 80, $errno, $errstr); | |
722 if ($fp) | |
723 { | |
724 $length = strlen($stats_to_send); | |
725 | |
726 $out = 'POST /smf/stats/collect_stats.php HTTP/1.1' . "\r\n"; | |
727 $out .= 'Host: www.simplemachines.org' . "\r\n"; | |
728 $out .= 'Content-Type: application/x-www-form-urlencoded' . "\r\n"; | |
729 $out .= 'Content-Length: ' . $length . "\r\n\r\n"; | |
730 $out .= $stats_to_send . "\r\n"; | |
731 $out .= 'Connection: Close' . "\r\n\r\n"; | |
732 fwrite($fp, $out); | |
733 fclose($fp); | |
734 } | |
735 } | |
736 | |
737 // Die. | |
738 die('OK'); | |
739 } | |
740 | |
741 ?> |