determineActions()   F
last analyzed

Complexity

Conditions 64
Paths 8513

Size

Total Lines 312
Code Lines 141

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 4160

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 64
eloc 141
c 1
b 0
f 0
nc 8513
nop 2
dl 0
loc 312
rs 0
ccs 0
cts 104
cp 0
crap 4160

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
 * This file contains nosey functions so show where a user is active
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 ElkArte\Cache\Cache;
15
use ElkArte\Helper\Util;
16
use ElkArte\Languages\Txt;
17
use ElkArte\User;
18
19
/**
20
 * Checks, who is viewing a topic or board
21
 *
22
 * @param int $id
23
 * @param string $session
24
 * @param string $type
25
 * @return array
26
 */
27
function viewers($id, $session, $type = 'topic')
28
{
29 2
	$db = database();
30
31
	// Make sure we have a default value
32 2
	if (!in_array($type, array('topic', 'board')))
33
	{
34
		$type = 'topic';
35
	}
36
37 2
	return $db->fetchQuery('
38
		SELECT
39
			lo.id_member, lo.log_time, mem.real_name, mem.member_name, mem.show_online,
40
			mg.online_color, mg.id_group, mg.group_name
41
		FROM {db_prefix}log_online AS lo
42
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lo.id_member)
43
			LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:reg_member_group} THEN mem.id_post_group ELSE mem.id_group END)
44
		WHERE INSTR(lo.url, {string:in_url_string}) > 0 OR lo.session = {string:session}',
45
		array(
46 2
			'reg_member_group' => 0,
47 2
			'in_url_string' => 's:5:"' . $type . '";i:' . $id . ';',
48 2
			'session' => $session
49
		)
50 2
	)->fetch_all();
51
}
52
53
/**
54
 * Format viewers list for display, for a topic or board.
55
 *
56
 * @param int $id id of the element (topic or board) we're watching
57
 * @param string $type = 'topic, 'topic' or 'board'
58
 */
59
function formatViewers($id, $type)
60
{
61
	global $context;
62 2
63
	// Lets say there's no one around. (what? could happen!)
64
	$context['view_members'] = array();
65 2
	$context['view_members_list'] = array();
66 2
	$context['view_num_hidden'] = 0;
67 2
	$context['view_num_guests'] = 0;
68 2
69
	$viewers = viewers($id, User::$info->is_guest ? 'ip' . User::$info->ip : session_id(), $type);
0 ignored issues
show
Bug Best Practice introduced by
The property ip does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property is_guest does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
70 2
71
	foreach ($viewers as $viewer)
72 2
	{
73
		// is this a guest?
74
		if (empty($viewer['id_member']))
75
		{
76
			$context['view_num_guests']++;
77
			continue;
78
		}
79
80
		$href = getUrl('profile', ['action' => 'profile', 'u' => $viewer['id_member'], 'name' => $viewer['real_name']]);
81
		// it's a member. We format them with links 'n stuff.
82
		if (!empty($viewer['online_color']))
83
		{
84
			$link = '<a href="' . $href . '" style="color: ' . $viewer['online_color'] . ';">' . $viewer['real_name'] . '</a>';
85
		}
86
		else
87
		{
88
			$link = '<a href="' . $href . '">' . $viewer['real_name'] . '</a>';
89
		}
90
91
		$is_buddy = in_array($viewer['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

91
		$is_buddy = in_array($viewer['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...
92
		if ($is_buddy)
93
		{
94
			$link = '<strong>' . $link . '</strong>';
95
		}
96
97
		// fill the summary list
98
		if (!empty($viewer['show_online']) || allowedTo('moderate_forum'))
99
		{
100
			$context['view_members_list'][$viewer['log_time'] . $viewer['member_name']] = empty($viewer['show_online']) ? '<em>' . $link . '</em>' : $link;
101
		}
102
103
		// fill the detailed list
104
		$context['view_members'][$viewer['log_time'] . $viewer['member_name']] = array(
105
			'id' => $viewer['id_member'],
106
			'username' => $viewer['member_name'],
107
			'name' => $viewer['real_name'],
108
			'group' => $viewer['id_group'],
109
			'href' => $href,
110
			'link' => $link,
111
			'is_buddy' => $is_buddy,
112
			'hidden' => empty($viewer['show_online']),
113
		);
114
115
		// add the hidden members to the count (and don't show them in the template)
116
		if (empty($viewer['show_online']))
117
		{
118
			$context['view_num_hidden']++;
119
		}
120
	}
121
122
	// Sort them out.
123
	krsort($context['view_members_list']);
124 2
	krsort($context['view_members']);
125 2
}
126 2
127
128
/**
129
 * This function determines the actions of the members passed in urls.
130
 *
131
 * Adding actions to the Who's Online list:
132
 * Adding actions to this list is actually relatively easy...
133
 * - for actions anyone should be able to see, just add a string named whoall_ACTION.
134
 *   (where ACTION is the action used in index.php.)
135
 * - for actions that have a subaction which should be represented differently, use whoall_ACTION_SUBACTION.
136
 * - for actions that include a topic, and should be restricted, use whotopic_ACTION.
137
 * - for actions that use a message, by msg or quote, use whopost_ACTION.
138
 * - for administrator-only actions, use whoadmin_ACTION.
139
 * - for actions that should be viewable only with certain permissions, use whoallow_ACTION and
140
 * add a list of possible permissions to the $allowedActions array, using ACTION as the key.
141
 *
142
 * @param mixed[]|string $urls a single url (string) or an array of arrays, each inner array being (serialized request data, id_member)
143
 * @param string|bool $preferred_prefix = false
144
 * @return mixed[]|string an array of descriptions if you passed an array, otherwise the string describing their current location.
145
 */
146
function determineActions($urls, $preferred_prefix = false)
147
{
148
	global $txt, $modSettings;
149
150
	$db = database();
151
152
	if (!allowedTo('who_view'))
153
	{
154
		return array();
155
	}
156
157
	Txt::load('Who');
158
159
	// Actions that require a specific permission level.
160
	$allowedActions = array(
161
		'admin' => array('moderate_forum', 'manage_membergroups', 'manage_bans', 'admin_forum', 'manage_permissions', 'send_mail', 'manage_attachments', 'manage_smileys', 'manage_boards', 'edit_news'),
162
		'ban' => array('manage_bans'),
163
		'boardrecount' => array('admin_forum'),
164
		'calendar' => array('calendar_view'),
165
		'editnews' => array('edit_news'),
166
		'mailing' => array('send_mail'),
167
		'maintain' => array('admin_forum'),
168
		'manageattachments' => array('manage_attachments'),
169
		'manageboards' => array('manage_boards'),
170
		'memberlist' => array('view_mlist'),
171
		'moderate' => array('access_mod_center', 'moderate_forum', 'manage_membergroups'),
172
		'optimizetables' => array('admin_forum'),
173
		'repairboards' => array('admin_forum'),
174
		'search' => array('search_posts'),
175
		'setcensor' => array('moderate_forum'),
176
		'setreserve' => array('moderate_forum'),
177
		'stats' => array('view_stats'),
178
		'viewErrorLog' => array('admin_forum'),
179
		'viewmembers' => array('moderate_forum'),
180
	);
181
182
	// Provide integration a way to add to the allowed action array
183
	call_integration_hook('integrate_whos_online_allowed', array(&$allowedActions));
184
185
	if (!is_array($urls))
186
	{
187
		$url_list = array(array($urls, User::$info->id));
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
188
	}
189
	else
190
	{
191
		$url_list = $urls;
192
	}
193
194
	// These are done to query these in large chunks. (instead of one by one.)
195
	$topic_ids = array();
196
	$profile_ids = array();
197
	$board_ids = array();
198
199
	$data = array();
200
	foreach ($url_list as $k => $url)
201
	{
202
		// Get the request parameters..
203
		$actions = Util::unserialize($url[0]);
204
		if ($actions === false)
205
		{
206
			continue;
207
		}
208
209
		// If it's the admin or moderation center, and there is an area set, use that instead.
210
		if (isset($actions['action']) && ($actions['action'] == 'admin' || $actions['action'] == 'moderate') && isset($actions['area']))
211
		{
212
			$actions['action'] = $actions['area'];
213
		}
214
215
		// Check if there was no action or the action is display.
216
		if (!isset($actions['action']) || $actions['action'] == 'display')
217
		{
218
			// It's a topic!  Must be!
219
			if (isset($actions['topic']))
220
			{
221
				// Assume they can't view it, and queue it up for later.
222
				$data[$k] = $txt['who_hidden'];
223
				$topic_ids[(int) $actions['topic']][$k] = $txt['who_topic'];
224
			}
225
			// It's a board!
226
			elseif (isset($actions['board']))
227
			{
228
				// Hide first, show later.
229
				$data[$k] = $txt['who_hidden'];
230
				$board_ids[$actions['board']][$k] = $txt['who_board'];
231
			}
232
			// It's the board index!!  It must be!
233
			else
234
			{
235
				$data[$k] = replaceBasicActionUrl($txt['who_index']);
236
			}
237
		}
238
		// Probably an error or some goon?
239
		elseif ($actions['action'] == '')
240
		{
241
			$data[$k] = replaceBasicActionUrl($txt['who_index']);
242
		}
243
		// Some other normal action...?
244
		else
245
		{
246
			// Viewing/editing a profile.
247
			if ($actions['action'] === 'profile')
248
			{
249
				// Whose?  Their own?
250
				if (empty($actions['u']))
251
				{
252
					require_once(SUBSDIR . '/Profile.subs.php');
253
					$memID = currentMemberID();
254
255
					if ($memID == User::$info->id)
256
					{
257
						$actions['u'] = $url[1];
258
					}
259
					else
260
					{
261
						$actions['u'] = $memID;
262
					}
263
				}
264
265
				$data[$k] = $txt['who_hidden'];
266
				$profile_ids[(int) $actions['u']][$k] = $actions['action'] === 'profile' ? $txt['who_viewprofile'] : $txt['who_profile'];
267
			}
268
			// Trying to post
269
			elseif (($actions['action'] === 'post' || $actions['action'] === 'post2' || $actions['action'] === 'topicbyemail') && empty($actions['topic']) && isset($actions['board']))
270
			{
271
				$data[$k] = $txt['who_hidden'];
272
				if ($actions['action'] === 'topicbyemail')
273
				{
274
					$board_ids[(int) $actions['board']][$k] = $txt['who_topicbyemail'];
275
				}
276
				else
277
				{
278
					$board_ids[(int) $actions['board']][$k] = isset($actions['poll']) ? $txt['who_poll'] : $txt['who_post'];
279
				}
280
			}
281
			// A subaction anyone can view... if the language string is there, show it.
282
			elseif (isset($actions['sa'], $txt['whoall_' . $actions['action'] . '_' . $actions['sa']]))
283
			{
284
				$data[$k] = $preferred_prefix && isset($txt[$preferred_prefix . $actions['action'] . '_' . $actions['sa']]) ? $txt[$preferred_prefix . $actions['action'] . '_' . $actions['sa']] : $txt['whoall_' . $actions['action'] . '_' . $actions['sa']];
0 ignored issues
show
Bug introduced by
Are you sure $preferred_prefix of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

284
				$data[$k] = $preferred_prefix && isset($txt[/** @scrutinizer ignore-type */ $preferred_prefix . $actions['action'] . '_' . $actions['sa']]) ? $txt[$preferred_prefix . $actions['action'] . '_' . $actions['sa']] : $txt['whoall_' . $actions['action'] . '_' . $actions['sa']];
Loading history...
285
			}
286
			// An action any old fellow can look at. (if $txt['whoall_' . $action] exists, we know everyone can see it.)
287
			elseif (isset($txt['whoall_' . $actions['action']]))
288
			{
289
				$data[$k] = $preferred_prefix && isset($txt[$preferred_prefix . $actions['action']]) ? $txt[$preferred_prefix . $actions['action']] : replaceBasicActionUrl($txt['whoall_' . $actions['action']]);
290
			}
291
			// Viewable if and only if they can see the board...
292
			elseif (isset($txt['whotopic_' . $actions['action']]))
293
			{
294
				// Find out what topic they are accessing.
295
				$topic = (int) ($actions['topic'] ?? ($actions['from'] ?? 0));
296
297
				$data[$k] = $txt['who_hidden'];
298
				$topic_ids[$topic][$k] = $txt['whotopic_' . $actions['action']];
299
			}
300
			// Viewable if and only if they can see the board...
301
			elseif (isset($actions['sa']) && isset($txt['whotopic_' . $actions['action'] . '_' . $actions['sa']]))
302
			{
303
				// Find out what topic they are accessing.
304
				$topic = (int) ($actions['topic'] ?? ($actions['from'] ?? 0));
305
306
				$data[$k] = $txt['who_hidden'];
307
				$topic_ids[$topic][$k] = $txt['whotopic_' . $actions['action'] . '_' . $actions['sa']];
308
			}
309
			elseif (isset($txt['whopost_' . $actions['action']]))
310
			{
311
				// Find out what message they are accessing.
312
				$msgid = (int) ($actions['msg'] ?? ($actions['quote'] ?? 0));
313
314
				$result = $db->query('', '
315
					SELECT 
316
						m.id_topic, m.subject
317
					FROM {db_prefix}messages AS m
318
						INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
319
						INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic' . ($modSettings['postmod_active'] ? ' AND t.approved = {int:is_approved}' : '') . ')
320
					WHERE m.id_msg = {int:id_msg}
321
						AND {query_see_board}' . ($modSettings['postmod_active'] ? '
322
						AND m.approved = {int:is_approved}' : '') . '
323
					LIMIT 1',
324
					array(
325
						'is_approved' => 1,
326
						'id_msg' => $msgid,
327
					)
328
				);
329
				list ($id_topic, $subject) = $result->fetch_row();
330
				$data[$k] = sprintf($txt['whopost_' . $actions['action']], getUrl('topic', ['topic' => $id_topic, 'start' => '0', 'subject' => $subject]), $subject);
331
				$result->free_result();
332
333
				if (empty($id_topic))
334
				{
335
					$data[$k] = $txt['who_hidden'];
336
				}
337
			}
338
			// Viewable only by administrators.. (if it starts with whoadmin, it's admin only!)
339
			elseif (allowedTo('moderate_forum') && isset($txt['whoadmin_' . $actions['action']]))
340
			{
341
				$data[$k] = $txt['whoadmin_' . $actions['action']];
342
			}
343
			// Viewable by permission level.
344
			elseif (isset($allowedActions[$actions['action']]))
345
			{
346
				if (allowedTo($allowedActions[$actions['action']]))
347
				{
348
					if (isset($actions['sa']) && isset($txt['whoallow_' . $actions['action'] . '_' . $actions['sa']]))
349
					{
350
						$data[$k] = replaceBasicActionUrl($txt['whoallow_' . $actions['action'] . '_' . $actions['sa']]);
351
					}
352
					else
353
					{
354
						$data[$k] = replaceBasicActionUrl($txt['whoallow_' . $actions['action']]);
355
					}
356
				}
357
				elseif (in_array('moderate_forum', $allowedActions[$actions['action']]))
358
				{
359
					$data[$k] = $txt['who_moderate'];
360
				}
361
				elseif (in_array('admin_forum', $allowedActions[$actions['action']]))
362
				{
363
					$data[$k] = $txt['who_admin'];
364
				}
365
				else
366
				{
367
					$data[$k] = $txt['who_hidden'];
368
				}
369
			}
370
			// Something we don't have details about, but it is an action, maybe an addon
371
			elseif (!empty($actions['action']))
372
			{
373
				$data[$k] = sprintf($txt['who_generic'], $actions['action']);
374
			}
375
			// We just don't know
376
			else
377
			{
378
				$data[$k] = $txt['who_unknown'];
379
			}
380
		}
381
382
		// Maybe the action is integrated into another system?
383
		if (count($integrate_actions = call_integration_hook('integrate_whos_online', array($actions))) > 0)
384
		{
385
			// Try each integration hook with this url and see if they can fill in the details
386
			foreach ($integrate_actions as $integrate_action)
387
			{
388
				if (!empty($integrate_action))
389
				{
390
					// Found it, all done then
391
					$data[$k] = $integrate_action;
392
					break;
393
				}
394
			}
395
		}
396
	}
397
398
	// Load topic names.
399
	if (!empty($topic_ids))
400
	{
401
		require_once(SUBSDIR . '/Topic.subs.php');
402
		$topics_data = topicsList(array_keys($topic_ids));
403
404
		foreach ($topics_data as $topic)
405
		{
406
			// Show the topic's subject for each of the members looking at this...
407
			foreach ($topic_ids[$topic['id_topic']] as $k => $session_text)
408
			{
409
				$data[$k] = sprintf($session_text, getUrl('topic', ['topic' => $topic['id_topic'], 'start' => '0', 'subject' => $topic['subject']]), $topic['subject']);
410
			}
411
		}
412
	}
413
414
	// Load board names.
415
	if (!empty($board_ids))
416
	{
417
		require_once(SUBSDIR . '/Boards.subs.php');
418
419
		$boards_list = getBoardList(array('included_boards' => array_keys($board_ids)), true);
420
		foreach ($boards_list as $board)
421
		{
422
			// Put the board name into the string for each member...
423
			foreach ($board_ids[$board['id_board']] as $k => $session_text)
424
			{
425
				$data[$k] = sprintf($session_text, getUrl('board', ['board' => $board['id_board'], 'start' => '0', 'name' => $board['board_name']]), $board['board_name']);
426
			}
427
		}
428
	}
429
430
	// Load member names for the profile.
431
	if (!empty($profile_ids) && (allowedTo('profile_view_any') || allowedTo('profile_view_own')))
432
	{
433
		require_once(SUBSDIR . '/Members.subs.php');
434
		$result = getBasicMemberData(array_keys($profile_ids));
435
		foreach ($result as $row)
436
		{
437
			// If they aren't allowed to view this person's profile, skip it.
438
			if (!allowedTo('profile_view_any') && User::$info->id != $row['id_member'])
439
			{
440
				continue;
441
			}
442
443
			// Set their action on each - session/text to sprintf.
444
			foreach ($profile_ids[$row['id_member']] as $k => $session_text)
445
			{
446
				$data[$k] = sprintf($session_text, getUrl('profile', ['action' => 'profile', 'u' => $row['id_member'], 'name' => $row['real_name']]), $row['real_name']);
447
			}
448
		}
449
	}
450
451
	if (!is_array($urls))
452
	{
453
		return $data[0] ?? false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $data[0] ?? false could also return false which is incompatible with the documented return type array<mixed,mixed>|string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
454
	}
455
	else
456
	{
457
		return $data;
458
	}
459
}
460