getMembersOnlineStats()   F
last analyzed

Complexity

Conditions 29
Paths 1563

Size

Total Lines 165
Code Lines 86

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 319.3213

Importance

Changes 0
Metric Value
cc 29
eloc 86
nc 1563
nop 1
dl 0
loc 165
ccs 20
cts 67
cp 0.2985
crap 319.3213
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Function to support online user functions
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
 * This file contains code covered by:
11
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
12
 *
13
 * @version 2.0 dev
14
 *
15
 */
16
17
use ElkArte\Cache\Cache;
18
use ElkArte\Helper\Util;
19
use ElkArte\User;
20
21
/**
22
 * Retrieve a list and several other statistics of the users currently online.
23
 *
24
 * - Used by the board index and SSI.
25
 * - Also returns the membergroups of the users that are currently online.
26
 * - (optionally) hides members that chose to hide their online presence.
27
 *
28
 * @param array $membersOnlineOptions
29
 * @return array
30
 * @package Members
31
 */
32
function getMembersOnlineStats($membersOnlineOptions)
33
{
34
	global $modSettings, $txt;
35 2
36
	$db = database();
37 2
38
	// The list can be sorted in several ways.
39
	$allowed_sort_options = [
40
		'', // No sorting.
41 2
		'log_time',
42
		'real_name',
43
		'show_online',
44
		'online_color',
45
		'group_name',
46
	];
47
48
	// Default the sorting method to 'most recent online members first'.
49
	if (!isset($membersOnlineOptions['sort']))
50 2
	{
51
		$membersOnlineOptions['sort'] = 'log_time';
52
		$membersOnlineOptions['reverse_sort'] = true;
53
	}
54
55
	// Not allowed sort method? Bang! Error!
56
	elseif (!in_array($membersOnlineOptions['sort'], $allowed_sort_options))
57 2
	{
58
		trigger_error('Sort method for getMembersOnlineStats() function is not allowed', E_USER_NOTICE);
59
	}
60
61
	// Get it from the cache and send it back.
62
	$temp = [];
63 2
	$cache = Cache::instance();
64 2
	if ($cache->levelHigherThan(1) && $cache->getVar($temp, 'membersOnlineStats-' . $membersOnlineOptions['sort'], 240))
65 2
	{
66
		return filter_members_online($temp, empty($membersOnlineOptions['reverse_sort']) ? 'ksort' : 'krsort');
67
	}
68
69
	// Initialize the array that'll be returned later on.
70
	$membersOnlineStats = [
71
		'users_online' => [],
72 2
		'list_users_online' => [],
73
		'online_groups' => [],
74
		'num_guests' => 0,
75
		'num_spiders' => 0,
76
		'num_buddies' => 0,
77
		'num_users_hidden' => 0,
78
		'num_users_online' => 0,
79
	];
80
81
	// Get any spiders if enabled.
82
	$spiders = [];
83 2
	$spider_finds = [];
84 2
	if (!empty($modSettings['show_spider_online']) && ($modSettings['show_spider_online'] < 3 || allowedTo('admin_forum')) && !empty($modSettings['spider_name_cache']))
85 2
	{
86
		$spiders = Util::unserialize($modSettings['spider_name_cache']);
87
	}
88
89
	// Load the users online right now.
90
	$request = $db->query('', '
91 2
		SELECT
92
			lo.id_member, lo.log_time, lo.id_spider, mem.real_name, mem.member_name, mem.show_online,
93
			mg.online_color, mg.id_group, mg.group_name
94
		FROM {db_prefix}log_online AS lo
95
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lo.id_member)
96
			LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:reg_mem_group} THEN mem.id_post_group ELSE mem.id_group END)',
97
		[
98
			'reg_mem_group' => 0,
99 2
		]
100
	);
101
	while (($row = $request->fetch_assoc()))
102 2
	{
103
		if (empty($row['real_name']))
104
		{
105
			// Do we think it's a spider?
106
			if ($row['id_spider'] && isset($spiders[$row['id_spider']]))
107
			{
108
				$spider_finds[$row['id_spider']] = isset($spider_finds[$row['id_spider']]) ? $spider_finds[$row['id_spider']] + 1 : 1;
109
				$membersOnlineStats['num_spiders']++;
110
			}
111
			// Guests are only nice for statistics.
112
			$membersOnlineStats['num_guests']++;
113
114
			continue;
115
		}
116
117
		if (empty($row['show_online']) && empty($membersOnlineOptions['show_hidden']))
118
		{
119
			// Just increase the stats and don't add this hidden user to any list.
120
			$membersOnlineStats['num_users_hidden']++;
121
			continue;
122
		}
123
124
		$href = getUrl('profile', ['action' => 'profile', 'u' => $row['id_member'], 'name' => $row['real_name']]);
125
126
		// Some basic color coding...
127
		if (!empty($row['online_color']))
128
		{
129
			$link = '<a href="' . $href . '" style="color: ' . $row['online_color'] . ';">' . $row['real_name'] . '</a>';
130
		}
131
		else
132
		{
133
			$link = '<a href="' . $href . '">' . $row['real_name'] . '</a>';
134
		}
135
136
		// Buddies get counted and highlighted.
137
		$is_buddy = in_array($row['id_member'], User::$info->buddies);
0 ignored issues
show
Bug introduced by
It seems like ElkArte\User::info->buddies can also be of type null; however, parameter $haystack of in_array() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

137
		$is_buddy = in_array($row['id_member'], /** @scrutinizer ignore-type */ User::$info->buddies);
Loading history...
Bug Best Practice introduced by
The property buddies does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
138
		if ($is_buddy)
139
		{
140
			$membersOnlineStats['num_buddies']++;
141
			$link = '<strong>' . $link . '</strong>';
142
		}
143
144
		// A lot of useful information for each member.
145
		$membersOnlineStats['users_online'][$row[$membersOnlineOptions['sort']] . '_' . $row['member_name']] = [
146
			'id' => $row['id_member'],
147
			'username' => $row['member_name'],
148
			'name' => $row['real_name'],
149
			'group' => $row['id_group'],
150
			'href' => $href,
151
			'link' => $link,
152
			'is_buddy' => $is_buddy,
153
			'hidden' => empty($row['show_online']),
154
			'is_last' => false,
155
		];
156
157
		// Store all distinct (primary) membergroups that are shown.
158
		if (!isset($membersOnlineStats['online_groups'][$row['id_group']]))
159
		{
160
			$membersOnlineStats['online_groups'][$row['id_group']] = [
161
				'id' => $row['id_group'],
162
				'name' => $row['group_name'],
163
				'color' => $row['online_color']
164
			];
165
		}
166
	}
167 2
	$request->free_result();
168
169
	// If there are spiders only and we're showing the detail, add them to the online list - at the bottom.
170 2
	if (!empty($spider_finds) && $modSettings['show_spider_online'] > 1)
171
	{
172
		$sort = $membersOnlineOptions['sort'] === 'log_time' && $membersOnlineOptions['reverse_sort'] ? 0 : 'zzz_';
173
		foreach ($spider_finds as $id => $count)
174
		{
175
			$link = $spiders[$id] . ($count > 1 ? ' (' . $count . ')' : '');
176
			$membersOnlineStats['users_online'][$sort . '_' . $spiders[$id]] = [
177
				'id' => 0,
178
				'username' => $spiders[$id],
179
				'name' => $link,
180
				'group' => $txt['spiders'],
181
				'href' => '',
182
				'link' => $link,
183
				'is_buddy' => false,
184
				'hidden' => false,
185
				'is_last' => false,
186
			];
187
			$membersOnlineStats['list_users_online'][$sort . '_' . $spiders[$id]] = $link;
188
		}
189
	}
190
191
	// Hidden and non-hidden members make up all online members.
192 2
	$membersOnlineStats['num_users_online'] = count($membersOnlineStats['users_online']) + $membersOnlineStats['num_users_hidden'] - (isset($modSettings['show_spider_online']) && $modSettings['show_spider_online'] > 1 ? count($spider_finds) : 0);
193
194 2
	Cache::instance()->put('membersOnlineStats-' . $membersOnlineOptions['sort'], $membersOnlineStats, 240);
195
196 2
	return filter_members_online($membersOnlineStats, empty($membersOnlineOptions['reverse_sort']) ? 'ksort' : 'krsort');
197
}
198
199
/**
200
 * Post-retrieval processing.
201
 * Needed mainly for when the cache is enabled and online users have to be
202
 * filtered out based on permissions.
203
 *
204
 * @param array $membersOnlineStats
205
 * @param string $sortFunction
206
 * @return array
207
 * @package Members
208
 */
209
function filter_members_online($membersOnlineStats, $sortFunction)
210
{
211
	foreach ($membersOnlineStats['users_online'] as $key => $row)
212 2
	{
213
		if (allowedTo('moderate_forum') === false && $row['hidden'])
214
		{
215
			continue;
216
		}
217
		// This is the compact version, simply implode it to show.
218
		$membersOnlineStats['list_users_online'][$key] = $row['hidden'] ? '<em>' . $row['link'] . '</em>' : $row['link'];
219
	}
220
221
	// Time to sort the list a bit.
222
	if (!empty($membersOnlineStats['users_online']))
223 2
	{
224
		// Sort the two lists.
225
		$sortFunction($membersOnlineStats['users_online']);
226
		$sortFunction($membersOnlineStats['list_users_online']);
227
228
		// Mark the last list item as 'is_last'.
229
		$userKeys = array_keys($membersOnlineStats['users_online']);
230
		$membersOnlineStats['users_online'][end($userKeys)]['is_last'] = true;
231
	}
232
233
	// Also sort the membergroups.
234
	ksort($membersOnlineStats['online_groups']);
235 2
236
	return $membersOnlineStats;
237 2
}
238
239
/**
240
 * Check if the number of users online is a record and store it.
241
 *
242
 * @param int $total_users_online
243
 * @package Members
244
 */
245
function trackStatsUsersOnline($total_users_online)
246
{
247
	global $modSettings;
248
249 2
	$db = database();
250
251 2
	$settingsToUpdate = [];
252
253 2
	// More members on now than ever were?  Update it!
254
	if (!isset($modSettings['mostOnline']) || $total_users_online >= $modSettings['mostOnline'])
255
	{
256 2
		$settingsToUpdate = [
257
			'mostOnline' => $total_users_online,
258
			'mostDate' => time()
259
		];
260
	}
261
262
	$date = Util::strftime('%Y-%m-%d', forum_time(false));
263
264 2
	// No entry exists for today yet?
265
	if (!isset($modSettings['mostOnlineUpdated']) || $modSettings['mostOnlineUpdated'] != $date)
266
	{
267 2
		$request = $db->query('', '
268
			SELECT 
269 2
				most_on
270
			FROM {db_prefix}log_activity
271
			WHERE date = {date:date}
272
			LIMIT 1',
273
			[
274
				'date' => $date,
275
			]
276 2
		);
277
278
		// The log_activity hasn't got an entry for today?
279
		if ($request->num_rows() === 0)
280
		{
281 2
			$db->insert('ignore',
282
				'{db_prefix}log_activity',
283 2
				['date' => 'date', 'most_on' => 'int'],
284 2
				[$date, $total_users_online],
285 2
				['date']
286 2
			);
287 2
		}
288
		// There's an entry in log_activity on today...
289
		else
290
		{
291
			list ($modSettings['mostOnlineToday']) = $request->fetch_row();
292
293
			if ($total_users_online > $modSettings['mostOnlineToday'])
294
			{
295
				trackStats(['most_on' => $total_users_online]);
296
			}
297
298
			$total_users_online = max($total_users_online, $modSettings['mostOnlineToday']);
299
		}
300
		$request->free_result();
301
302 2
		$settingsToUpdate['mostOnlineUpdated'] = $date;
303
		$settingsToUpdate['mostOnlineToday'] = $total_users_online;
304 2
	}
305 2
	// Highest number of users online today?
306
	elseif ($total_users_online > $modSettings['mostOnlineToday'])
307
	{
308
		trackStats(['most_on' => $total_users_online]);
309
		$settingsToUpdate['mostOnlineToday'] = $total_users_online;
310
	}
311
312
	if (!empty($settingsToUpdate))
313
	{
314 2
		updateSettings($settingsToUpdate);
315
	}
316
}
317