Top_Stats_Member_Block::setup()   F
last analyzed

Complexity

Conditions 33
Paths 18464

Size

Total Lines 160
Code Lines 75

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 33
eloc 75
nc 18464
nop 2
dl 0
loc 160
rs 0
c 2
b 1
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
 * @package SimplePortal
5
 *
6
 * @author SimplePortal Team
7
 * @copyright 2015-2021 SimplePortal Team
8
 * @license BSD 3-clause
9
 * @version 1.0.0
10
 */
11
12
13
/**
14
 * Top stats block, shows the top x members who has achieved top position of various stats
15
 * Designed to be flexible so adding additional member stats is easy
16
 *
17
 * @param mixed[] $parameters
18
 *        'limit' => number of top posters to show
19
 *        'type' => top stat to show
20
 *        'sort_asc' => direction to show the list
21
 *        'last_active_limit'
22
 *        'enable_label' => use the label
23
 *        'list_label' => title for the list
24
 * @param int $id - not used in this block
25
 * @param boolean $return_parameters if true returns the configuration options for the block
26
 */
27
class Top_Stats_Member_Block extends SP_Abstract_Block
28
{
29
	protected $sp_topStatsSystem = array();
30
	protected $color_ids = array();
31
32
	/**
33
	 * Constructor, used to define block parameters
34
	 *
35
	 * @param Database|null $db
36
	 */
37
	public function __construct($db = null)
38
	{
39
		global $txt;
40
41
		$this->block_parameters = array(
42
			'type' => array(
43
				'0' => $txt['sp_topStatsMember_total_time_logged_in'],
44
				'1' => $txt['sp_topStatsMember_Posts'],
45
				'2' => $txt['sp_topStatsMember_Karma_Good'],
46
				'3' => $txt['sp_topStatsMember_Karma_Bad'],
47
				'4' => $txt['sp_topStatsMember_Karma_Total'],
48
				'5' => $txt['sp_topStatsMember_Likes_Received'],
49
				'6' => $txt['sp_topStatsMember_Likes_Given'],
50
				'7' => $txt['sp_topStatsMember_Likes_Total'],
51
			),
52
			'limit' => 'int',
53
			'sort_asc' => 'check',
54
			'last_active_limit' => 'int',
55
			'enable_label' => 'check',
56
			'list_label' => 'text',
57
		);
58
59
		parent::__construct($db);
60
		$this->setupSystemArray();
61
	}
62
63
	private function setupSystemArray()
64
	{
65
		global $txt;
66
67
		/*
68
		* The system setup array, the order depends on the $txt array of the select name
69
		*
70
		* 'mod_id' - Only used as information
71
		* 'field' - The members field that should be loaded.  Please don't forget to add mem. before the field names
72
		* 'order' - What is the field name i need to be sort after
73
		* 'where' - Here you can add additional where statements
74
		* 'output_text' - What should be displayed after the avatar and nickname
75
		*	 - For example if your field is karmaGood 'output_text' => $txt['karma'] . '%karmaGood%';
76
		* 'output_function' - With this you can add to the $row of the query some information.
77
		* 'reverse' - On true it change the reverse cause, if not set it will be false :)
78
		* 'enabled' - true = mod exists or is possible to use :D
79
		* 'error_msg' => $txt['my_error_msg']; You can insert here what kind of error message should appear if the modification not exists =D
80
		*/
81
		$this->sp_topStatsSystem = array(
82
			'0' => array(
83
				'name' => 'Total time logged in',
84
				'field' => 'mem.total_time_logged_in',
85
				'order' => 'mem.total_time_logged_in',
86
				'output_function' => function(&$row) {
87
					global $txt;
88
89
					// Figure out the days, hours and minutes.
90
					$timeDays = floor($row["total_time_logged_in"] / 86400);
91
					$timeHours = floor(($row["total_time_logged_in"] % 86400) / 3600);
92
93
					// Figure out which things to show... (days, hours, minutes, etc.)
94
					$timelogged = "";
95
					if ($timeDays > 0)
96
					{
97
						$timelogged .= $timeDays . $txt["totalTimeLogged5"];
98
					}
99
100
					if ($timeHours > 0)
101
					{
102
						$timelogged .= $timeHours . $txt["totalTimeLogged6"];
103
					}
104
105
					$timelogged .= floor(($row["total_time_logged_in"] % 3600) / 60) . $txt["totalTimeLogged7"];
106
					$row["timelogged"] = $timelogged;
107
				},
108
				'output_text' => ' %timelogged%',
109
				'reverse_sort_asc' => false,
110
				'enabled' => true,
111
			),
112
			'1' => array(
113
				'name' => 'Posts',
114
				'field' => 'mem.posts',
115
				'order' => 'mem.posts',
116
				'output_text' => ' %posts% ' . $txt['posts'],
117
				'enabled' => true,
118
			),
119
			'2' => array(
120
				'name' => 'Karma Good',
121
				'field' => 'mem.karma_good, mem.karma_bad',
122
				'order' => 'mem.karma_good',
123
				'output_function' => function(&$row) {
124
					$row["karma_total"] = $row["karma_good"] - $row["karma_bad"];
125
				},
126
				'output_text' => (!empty($this->_modSettings['karmaLabel']) ? $this->_modSettings['karmaLabel'] : '') . ($this->_modSettings['karmaMode'] == 1 ? ' %karma_total%' : ' +%karma_good%\-%karma_bad%'),
127
				'enabled' => !empty($this->_modSettings['karmaMode']),
128
				'error_msg' => $txt['sp_karma_is_disabled'],
129
			),
130
			'3' => array(
131
				'name' => 'Karma Bad',
132
				'field' => 'mem.karma_good, mem.karma_bad',
133
				'order' => 'mem.karma_bad',
134
				'output_function' => function(&$row) {
135
					$row["karma_total"] = $row["karma_good"] - $row["karma_bad"];
136
				},
137
				'output_text' => (!empty($this->_modSettings['karmaLabel']) ? $this->_modSettings['karmaLabel'] : '') . ($this->_modSettings['karmaMode'] == 1 ? ' %karma_total%' : ' +%karma_good%\-%karma_bad%'),
138
				'enabled' => !empty($this->_modSettings['karmaMode']),
139
				'error_msg' => $txt['sp_karma_is_disabled'],
140
			),
141
			'4' => array(
142
				'name' => 'Karma Total',
143
				'field' => 'mem.karma_good, mem.karma_bad',
144
				'order' => 'FLOOR(1000000+karma_good-karma_bad)',
145
				'output_function' => function(&$row) {
146
					$row["karma_total"] = $row["karma_good"] - $row["karma_bad"];
147
				},
148
				'output_text' => $this->_modSettings['karmaLabel'] . ($this->_modSettings['karmaMode'] == 1 ? ' %karma_total%' : ' &plusmn;%karma_good%\%karma_bad%'),
149
				'enabled' => !empty($this->_modSettings['karmaMode']),
150
				'error_msg' => $txt['sp_karma_is_disabled'],
151
			),
152
			'5' => array(
153
				'name' => 'Likes Received/Given',
154
				'field' => 'mem.likes_received',
155
				'order' => 'mem.likes_received',
156
				'output_text' => '%likes_received% ' . $txt['sp_topStatsMember_Likes_Received'],
157
				'enabled' => !empty($this->_modSettings['likes_enabled']),
158
				'error_msg' => $txt['sp_likes_is_disabled'],
159
			),
160
			'6' => array(
161
				'name' => 'Likes Given',
162
				'field' => 'mem.likes_given',
163
				'order' => 'mem.likes_given',
164
				'output_text' => '%likes_given% ' . $txt['sp_topStatsMember_Likes_Given'],
165
				'enabled' => !empty($this->_modSettings['likes_enabled']),
166
				'error_msg' => $txt['sp_likes_is_disabled'],
167
			),
168
			'7' => array(
169
				'name' => 'Likes Totals',
170
				'field' => 'mem.likes_received, mem.likes_given',
171
				'order' => 'mem.likes_received',
172
				'output_text' => $txt['sp_topStatsMember_Likes_Received'] . ':&nbsp;%likes_received% / ' . $txt['sp_topStatsMember_Likes_Given'] . ':&nbsp;%likes_given%',
173
				'enabled' => !empty($this->_modSettings['likes_enabled']),
174
				'error_msg' => $txt['sp_likes_is_disabled'],
175
			),
176
		);
177
	}
178
179
	/**
180
	 * Initializes a block for use.
181
	 *
182
	 * - Called from portal.subs as part of the sportal_load_blocks process
183
	 *
184
	 * @param mixed[] $parameters
185
	 * @param int $id
186
	 */
187
	public function setup($parameters, $id)
188
	{
189
		global $context, $scripturl;
190
191
		// Standard Variables
192
		$type = !empty($parameters['type']) ? $parameters['type'] : 0;
193
		$limit = !empty($parameters['limit']) ? (int) $parameters['limit'] : 5;
194
		$sort_asc = !empty($parameters['sort_asc']);
195
196
		// Time is in days, but we need seconds
197
		$last_active_limit = !empty($parameters['last_active_limit']) ? $parameters['last_active_limit'] * 86400 : 0;
198
		$this->data['enable_label'] = !empty($parameters['enable_label']);
199
		$this->data['list_label'] = !empty($parameters['list_label']) ? $parameters['list_label'] : '';
200
201
		// Setup current block type
202
		$current_system = $this->sp_topStatsSystem[$type];
203
204
		// Possible to output?
205
		if (empty($current_system['enabled']))
206
		{
207
			if (!empty($current_system['error_msg']))
208
			{
209
				$this->setTemplate('template_sp_topStatsMember_error');
210
				$this->data['error_msg'] = $current_system['error_msg'];
211
			}
212
213
			return;
214
		}
215
216
		// Sort in reverse?
217
		$sort_asc = !empty($current_system['reverse']) ? !$sort_asc : $sort_asc;
218
219
		// Build the where statement
220
		$where = array();
221
222
		// If this is already cached, use it
223
		$chache_id = 'sp_chache_' . $id . '_topStatsMember';
224
		if (empty($this->_modSettings['sp_disableChache']) && !empty($this->_modSettings[$chache_id]))
225
		{
226
			$data = explode(';', $this->_modSettings[$chache_id]);
227
228
			if ($data[0] == $type && $data[1] == $limit && !empty($data[2]) == $sort_asc && $data[3] > time() - 300) // 5 Minute cache
229
			{
230
				$where[] = 'mem.id_member IN (' . $data[4] . ')';
231
			}
232
			else
233
			{
234
				unset($this->_modSettings[$chache_id]);
235
			}
236
		}
237
238
		// Last active remove
239
		if (!empty($last_active_limit))
240
		{
241
			$timeLimit = time() - $last_active_limit;
242
			$where[] = "last_login > $timeLimit";
243
		}
244
245
		if (!empty($current_system['where']))
246
		{
247
			$where[] = $current_system['where'];
248
		}
249
250
		if (!empty($where))
251
		{
252
			$where = 'WHERE (' . implode(')
253
				AND (', $where) . ')';
254
		}
255
		else
256
		{
257
			$where = "";
258
		}
259
260
		// Finally make the query with the parameters we built
261
		$request = $this->_db->query('', '
262
			SELECT
263
				mem.id_member, mem.real_name, mem.avatar, mem.email_address,
264
				a.id_attach, a.attachment_type, a.filename,
265
				{raw:field}
266
			FROM {db_prefix}members as mem
267
				LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = mem.id_member)
268
			{raw:where}
269
			ORDER BY {raw:order} {raw:sort}
270
			LIMIT {int:limit}',
271
			array(
272
				// Prevent delete of user if the cache was available
273
				'limit' => isset($context['common_stats']['total_members']) && $context['common_stats']['total_members'] > 100 ? ($limit + 5) : $limit,
274
				'field' => $current_system['field'],
275
				'where' => $where,
276
				'order' => $current_system['order'],
277
				'sort' => ($sort_asc ? 'ASC' : 'DESC'),
278
			)
279
		);
280
		$this->data['members'] = array();
281
		$count = 1;
282
		$chache_member_ids = array();
283
		while ($row = $this->_db->fetch_assoc($request))
284
		{
285
			// Collect some to cache data
286
			$chache_member_ids[$row['id_member']] = $row['id_member'];
287
			if ($count++ > $limit)
288
			{
289
				continue;
290
			}
291
292
			$this->color_ids[$row['id_member']] = $row['id_member'];
293
294
			// Setup the row
295
			$output = '';
296
297
			// Prepare some data of the row?
298
			if (!empty($current_system['output_function']))
299
			{
300
				$current_system['output_function']($row);
301
			}
302
303
			if (!empty($current_system['output_text']))
304
			{
305
				$output = $current_system['output_text'];
306
				foreach ($row as $item => $replacewith)
307
				{
308
					$output = str_replace('%' . $item . '%', $replacewith, $output);
309
				}
310
			}
311
312
			$this->data['members'][] = array(
313
				'id' => $row['id_member'],
314
				'name' => $row['real_name'],
315
				'href' => $scripturl . '?action=profile;u=' . $row['id_member'],
316
				'link' => '<a style="font-size: 90%" href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>',
317
				'avatar' => determineAvatar(array(
318
					'avatar' => $row['avatar'],
319
					'filename' => $row['filename'],
320
					'id_attach' => $row['id_attach'],
321
					'email_address' => $row['email_address'],
322
					'attachment_type' => $row['attachment_type'],
323
				)),
324
				'output' => $output,
325
				'complete_row' => $row,
326
			);
327
		}
328
		$this->_db->free_result($request);
329
330
		// Update the cache, at least around 100 members are needed for a good working version
331
		if (empty($this->_modSettings['sp_disableChache']) && isset($context['common_stats']['total_members']) && $context['common_stats']['total_members'] > 0 && !empty($chache_member_ids) && count($chache_member_ids) > $limit && empty($this->_modSettings[$chache_id]))
332
		{
333
			$toCache = array($type, $limit, ($sort_asc ? 1 : 0), time(), implode(',', $chache_member_ids));
334
			updateSettings(array($chache_id => implode(';', $toCache)));
335
		}
336
		// One time error, if this happens the cache needs an update
337
		elseif (!empty($this->_modSettings[$chache_id]))
338
		{
339
			updateSettings(array($chache_id => '0;0;0;1000;0'));
340
		}
341
342
		// Color the id's
343
		$this->_colorids();
344
345
		// Set the template to use
346
		$this->setTemplate('template_sp_topStatsMember');
347
	}
348
349
	/**
350
	 * Provide the color profile id's
351
	 */
352
	private function _colorids()
353
	{
354
		global $color_profile;
355
356
		if (sp_loadColors($this->color_ids) !== false)
0 ignored issues
show
introduced by
The condition sp_loadColors($this->color_ids) !== false is always true.
Loading history...
357
		{
358
			foreach ($this->data['members'] as $k => $p)
359
			{
360
				if (!empty($color_profile[$p['id']]['link']))
361
				{
362
					$this->data['members'][$k]['link'] = $color_profile[$p['id']]['link'];
363
				}
364
			}
365
		}
366
	}
367
}
368
369
/**
370
 * Error template for this block
371
 *
372
 * @param mixed[] $data
373
 */
374
function template_sp_topStatsMember_error($data)
375
{
376
	echo $data['error_msg'];
377
}
378
379
/**
380
 * Main template for this block
381
 *
382
 * @param mixed[] $data
383
 */
384
function template_sp_topStatsMember($data)
385
{
386
	global $scripturl, $txt;
387
388
	// No one found, let them know
389
	if (empty($data['members']))
390
	{
391
		echo '
392
			', $txt['error_sp_no_members_found'];
393
394
		return;
395
	}
396
397
	// Finally, output the block
398
	echo '
399
			<table class="sp_fullwidth">';
400
401
	if ($data['enable_label'])
402
	{
403
		echo '
404
				<tr>
405
					<td class="sp_top_poster centertext" colspan="2">
406
						<strong>', $data['list_label'], '</strong>
407
					</td>
408
				</tr>';
409
	}
410
411
	foreach ($data['members'] as $member)
412
	{
413
		echo '
414
				<tr>
415
					<td class="sp_top_poster centertext">', !empty($member['avatar']['href']) ? '
416
						<a href="' . $scripturl . '?action=profile;u=' . $member['id'] . '">
417
							<img src="' . $member['avatar']['href'] . '" alt="' . $member['name'] . '" />
418
						</a>' : '', '
419
					</td>
420
					<td>
421
						', $member['link'], ' : <span class="smalltext">', $member['output'], '</span>
422
					</td>
423
				</tr>';
424
	}
425
426
	echo '
427
			</table>';
428
}
429