Completed
Push — release-2.1 ( 15f485...ae1be0 )
by Mathias
08:27
created

Logging.php ➔ truncateArray()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 3
nop 2
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file concerns itself with logging, whether in the database or files.
5
 *
6
 * Simple Machines Forum (SMF)
7
 *
8
 * @package SMF
9
 * @author Simple Machines http://www.simplemachines.org
10
 * @copyright 2017 Simple Machines and individual contributors
11
 * @license http://www.simplemachines.org/about/smf/license.php BSD
12
 *
13
 * @version 2.1 Beta 3
14
 */
15
16
if (!defined('SMF'))
17
	die('No direct access...');
18
19
/**
20
 * Truncate the GET array to a specified length
21
 * @param array $arr The array to truncate
22
 * @param max_length $max_length The upperbound on the length
23
 *
24
 * @return array The truncated array
25
 */
26
function truncateArray($arr, $max_length=1900)
27
{
28
	$curr_length = array_sum(array_map("strlen", $arr));
29
	if ($curr_length <= $max_length)
30
		return $arr;
31
	else
32
	{
33
		// Truncate each element's value to a reasonable length
34
		$param_max = floor($max_length/count($arr));
35
		foreach ($arr as $key => &$value)
36
			$value = substr($value, 0, $param_max - strlen($key) - 5);
37
		return $arr;
38
	}
39
}
40
41
/**
42
 * Put this user in the online log.
43
 *
44
 * @param bool $force Whether to force logging the data
45
 */
46
function writeLog($force = false)
47
{
48
	global $user_info, $user_settings, $context, $modSettings, $settings, $topic, $board, $smcFunc, $sourcedir;
49
50
	// If we are showing who is viewing a topic, let's see if we are, and force an update if so - to make it accurate.
51
	if (!empty($settings['display_who_viewing']) && ($topic || $board))
52
	{
53
		// Take the opposite approach!
54
		$force = true;
55
		// Don't update for every page - this isn't wholly accurate but who cares.
56
		if ($topic)
57
		{
58
			if (isset($_SESSION['last_topic_id']) && $_SESSION['last_topic_id'] == $topic)
59
				$force = false;
60
			$_SESSION['last_topic_id'] = $topic;
61
		}
62
	}
63
64
	// Are they a spider we should be tracking? Mode = 1 gets tracked on its spider check...
65
	if (!empty($user_info['possibly_robot']) && !empty($modSettings['spider_mode']) && $modSettings['spider_mode'] > 1)
66
	{
67
		require_once($sourcedir . '/ManageSearchEngines.php');
68
		logSpider();
69
	}
70
71
	// Don't mark them as online more than every so often.
72
	if (!empty($_SESSION['log_time']) && $_SESSION['log_time'] >= (time() - 8) && !$force)
73
		return;
74
75
	if (!empty($modSettings['who_enabled']))
76
	{
77
		$serialized = truncateArray($_GET) + array('USER_AGENT' => $_SERVER['HTTP_USER_AGENT']);
78
79
		// In the case of a dlattach action, session_var may not be set.
80
		if (!isset($context['session_var']))
81
			$context['session_var'] = $_SESSION['session_var'];
82
83
		unset($serialized['sesc'], $serialized[$context['session_var']]);
84
		$serialized = json_encode($serialized);
85
	}
86
	else
87
		$serialized = '';
88
89
	// Guests use 0, members use their session ID.
90
	$session_id = $user_info['is_guest'] ? 'ip' . $user_info['ip'] : session_id();
91
92
	// Grab the last all-of-SMF-specific log_online deletion time.
93
	$do_delete = cache_get_data('log_online-update', 30) < time() - 30;
94
95
	// If the last click wasn't a long time ago, and there was a last click...
96
	if (!empty($_SESSION['log_time']) && $_SESSION['log_time'] >= time() - $modSettings['lastActive'] * 20)
97
	{
98
		if ($do_delete)
99
		{
100
			$smcFunc['db_query']('delete_log_online_interval', '
101
				DELETE FROM {db_prefix}log_online
102
				WHERE log_time < {int:log_time}
103
					AND session != {string:session}',
104
				array(
105
					'log_time' => time() - $modSettings['lastActive'] * 60,
106
					'session' => $session_id,
107
				)
108
			);
109
110
			// Cache when we did it last.
111
			cache_put_data('log_online-update', time(), 30);
112
		}
113
114
		$smcFunc['db_query']('', '
115
			UPDATE {db_prefix}log_online
116
			SET log_time = {int:log_time}, ip = {inet:ip}, url = {string:url}
117
			WHERE session = {string:session}',
118
			array(
119
				'log_time' => time(),
120
				'ip' => $user_info['ip'],
121
				'url' => $serialized,
122
				'session' => $session_id,
123
			)
124
		);
125
126
		// Guess it got deleted.
127
		if ($smcFunc['db_affected_rows']() == 0)
128
			$_SESSION['log_time'] = 0;
129
	}
130
	else
131
		$_SESSION['log_time'] = 0;
132
133
	// Otherwise, we have to delete and insert.
134
	if (empty($_SESSION['log_time']))
135
	{
136
		if ($do_delete || !empty($user_info['id']))
137
			$smcFunc['db_query']('', '
138
				DELETE FROM {db_prefix}log_online
139
				WHERE ' . ($do_delete ? 'log_time < {int:log_time}' : '') . ($do_delete && !empty($user_info['id']) ? ' OR ' : '') . (empty($user_info['id']) ? '' : 'id_member = {int:current_member}'),
140
				array(
141
					'current_member' => $user_info['id'],
142
					'log_time' => time() - $modSettings['lastActive'] * 60,
143
				)
144
			);
145
146
		$smcFunc['db_insert']($do_delete ? 'ignore' : 'replace',
147
			'{db_prefix}log_online',
148
			array('session' => 'string', 'id_member' => 'int', 'id_spider' => 'int', 'log_time' => 'int', 'ip' => 'inet', 'url' => 'string'),
149
			array($session_id, $user_info['id'], empty($_SESSION['id_robot']) ? 0 : $_SESSION['id_robot'], time(), $user_info['ip'], $serialized),
150
			array('session')
151
		);
152
	}
153
154
	// Mark your session as being logged.
155
	$_SESSION['log_time'] = time();
156
157
	// Well, they are online now.
158
	if (empty($_SESSION['timeOnlineUpdated']))
159
		$_SESSION['timeOnlineUpdated'] = time();
160
161
	// Set their login time, if not already done within the last minute.
162
	if (SMF != 'SSI' && !empty($user_info['last_login']) && $user_info['last_login'] < time() - 60 && (!isset($_REQUEST['action']) || !in_array($_REQUEST['action'], array('.xml', 'login2', 'logintfa'))))
163
	{
164
		// Don't count longer than 15 minutes.
165
		if (time() - $_SESSION['timeOnlineUpdated'] > 60 * 15)
166
			$_SESSION['timeOnlineUpdated'] = time();
167
168
		$user_settings['total_time_logged_in'] += time() - $_SESSION['timeOnlineUpdated'];
169
		updateMemberData($user_info['id'], array('last_login' => time(), 'member_ip' => $user_info['ip'], 'member_ip2' => $_SERVER['BAN_CHECK_IP'], 'total_time_logged_in' => $user_settings['total_time_logged_in']));
170
171
		if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2)
172
			cache_put_data('user_settings-' . $user_info['id'], $user_settings, 60);
173
174
		$user_info['total_time_logged_in'] += time() - $_SESSION['timeOnlineUpdated'];
175
		$_SESSION['timeOnlineUpdated'] = time();
176
	}
177
}
178
179
/**
180
 * Logs the last database error into a file.
181
 * Attempts to use the backup file first, to store the last database error
182
 * and only update db_last_error.php if the first was successful.
183
 */
184
function logLastDatabaseError()
185
{
186
	global $boarddir;
187
188
	// Make a note of the last modified time in case someone does this before us
189
	$last_db_error_change = @filemtime($boarddir . '/db_last_error.php');
190
191
	// save the old file before we do anything
192
	$file = $boarddir . '/db_last_error.php';
193
	$dberror_backup_fail = !@is_writable($boarddir . '/db_last_error_bak.php') || !@copy($file, $boarddir . '/db_last_error_bak.php');
194
	$dberror_backup_fail = !$dberror_backup_fail ? (!file_exists($boarddir . '/db_last_error_bak.php') || filesize($boarddir . '/db_last_error_bak.php') === 0) : $dberror_backup_fail;
195
196
	clearstatcache();
197
	if (filemtime($boarddir . '/db_last_error.php') === $last_db_error_change)
198
	{
199
		// Write the change
200
		$write_db_change =  '<' . '?' . "php\n" . '$db_last_error = ' . time() . ';' . "\n" . '?' . '>';
201
		$written_bytes = file_put_contents($boarddir . '/db_last_error.php', $write_db_change, LOCK_EX);
202
203
		// survey says ...
204
		if ($written_bytes !== strlen($write_db_change) && !$dberror_backup_fail)
205
		{
206
			// Oops. maybe we have no more disk space left, or some other troubles, troubles...
207
			// Copy the file back and run for your life!
208
			@copy($boarddir . '/db_last_error_bak.php', $boarddir . '/db_last_error.php');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
209
		}
210
		else
211
		{
212
			@touch($boarddir . '/' . 'Settings.php');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
213
			return true;
214
		}
215
	}
216
217
	return false;
218
}
219
220
/**
221
 * This function shows the debug information tracked when $db_show_debug = true
222
 * in Settings.php
223
 */
224
function displayDebug()
225
{
226
	global $context, $scripturl, $boarddir, $sourcedir, $cachedir, $settings, $modSettings;
227
	global $db_cache, $db_count, $cache_misses, $cache_count_misses, $db_show_debug, $cache_count, $cache_hits, $smcFunc, $txt;
228
229
	// Add to Settings.php if you want to show the debugging information.
230
	if (!isset($db_show_debug) || $db_show_debug !== true || (isset($_GET['action']) && $_GET['action'] == 'viewquery'))
231
		return;
232
233
	if (empty($_SESSION['view_queries']))
234
		$_SESSION['view_queries'] = 0;
235
	if (empty($context['debug']['language_files']))
236
		$context['debug']['language_files'] = array();
237
	if (empty($context['debug']['sheets']))
238
		$context['debug']['sheets'] = array();
239
240
	$files = get_included_files();
241
	$total_size = 0;
242
	for ($i = 0, $n = count($files); $i < $n; $i++)
243
	{
244
		if (file_exists($files[$i]))
245
			$total_size += filesize($files[$i]);
246
		$files[$i] = strtr($files[$i], array($boarddir => '.', $sourcedir => '(Sources)', $cachedir => '(Cache)', $settings['actual_theme_dir'] => '(Current Theme)'));
247
	}
248
249
	$warnings = 0;
250
	if (!empty($db_cache))
251
	{
252
		foreach ($db_cache as $q => $qq)
253
		{
254
			if (!empty($qq['w']))
255
				$warnings += count($qq['w']);
256
		}
257
258
		$_SESSION['debug'] = &$db_cache;
259
	}
260
261
	// Gotta have valid HTML ;).
262
	$temp = ob_get_contents();
263
	ob_clean();
264
265
	echo preg_replace('~</body>\s*</html>~', '', $temp), '
266
<div class="smalltext" style="text-align: left; margin: 1ex;">
267
	', $txt['debug_browser'], $context['browser_body_id'], ' <em>(', implode('</em>, <em>', array_reverse(array_keys($context['browser'], true))), ')</em><br>
268
	', $txt['debug_templates'], count($context['debug']['templates']), ': <em>', implode('</em>, <em>', $context['debug']['templates']), '</em>.<br>
269
	', $txt['debug_subtemplates'], count($context['debug']['sub_templates']), ': <em>', implode('</em>, <em>', $context['debug']['sub_templates']), '</em>.<br>
270
	', $txt['debug_language_files'], count($context['debug']['language_files']), ': <em>', implode('</em>, <em>', $context['debug']['language_files']), '</em>.<br>
271
	', $txt['debug_stylesheets'], count($context['debug']['sheets']), ': <em>', implode('</em>, <em>', $context['debug']['sheets']), '</em>.<br>
272
	', $txt['debug_hooks'], empty($context['debug']['hooks']) ? 0 : count($context['debug']['hooks']) . ' (<a href="javascript:void(0);" onclick="document.getElementById(\'debug_hooks\').style.display = \'inline\'; this.style.display = \'none\'; return false;">', $txt['debug_show'], '</a><span id="debug_hooks" style="display: none;"><em>' . implode('</em>, <em>', $context['debug']['hooks']), '</em></span>)', '<br>
273
	',(isset($context['debug']['instances']) ? ($txt['debug_instances'] . (empty($context['debug']['instances']) ? 0 : count($context['debug']['instances'])) . ' (<a href="javascript:void(0);" onclick="document.getElementById(\'debug_instances\').style.display = \'inline\'; this.style.display = \'none\'; return false;">'. $txt['debug_show'] .'</a><span id="debug_instances" style="display: none;"><em>'. implode('</em>, <em>', array_keys($context['debug']['instances'])) .'</em></span>)'. '<br>') : ''),'
274
	', $txt['debug_files_included'], count($files), ' - ', round($total_size / 1024), $txt['debug_kb'], ' (<a href="javascript:void(0);" onclick="document.getElementById(\'debug_include_info\').style.display = \'inline\'; this.style.display = \'none\'; return false;">', $txt['debug_show'], '</a><span id="debug_include_info" style="display: none;"><em>', implode('</em>, <em>', $files), '</em></span>)<br>';
275
276
	if (function_exists('memory_get_peak_usage'))
277
		echo $txt['debug_memory_use'], ceil(memory_get_peak_usage() / 1024), $txt['debug_kb'], '<br>';
278
279
	// What tokens are active?
280
	if (isset($_SESSION['token']))
281
		echo $txt['debug_tokens'] . '<em>' . implode(',</em> <em>', array_keys($_SESSION['token'])), '</em>.<br>';
282
283
	if (!empty($modSettings['cache_enable']) && !empty($cache_hits))
284
	{
285
		$missed_entries = array();
286
		$entries = array();
287
		$total_t = 0;
288
		$total_s = 0;
289
		foreach ($cache_hits as $cache_hit)
290
		{
291
			$entries[] = $cache_hit['d'] . ' ' . $cache_hit['k'] . ': ' . sprintf($txt['debug_cache_seconds_bytes'], comma_format($cache_hit['t'], 5), $cache_hit['s']);
292
			$total_t += $cache_hit['t'];
293
			$total_s += $cache_hit['s'];
294
		}
295
		if (!isset($cache_misses))
296
			$cache_misses = array();
297
		foreach ($cache_misses as $missed)
298
			$missed_entries[] = $missed['d'] . ' ' . $missed['k'];
299
300
		echo '
301
	', $txt['debug_cache_hits'], $cache_count, ': ', sprintf($txt['debug_cache_seconds_bytes_total'], comma_format($total_t, 5), comma_format($total_s)), ' (<a href="javascript:void(0);" onclick="document.getElementById(\'debug_cache_info\').style.display = \'inline\'; this.style.display = \'none\'; return false;">', $txt['debug_show'], '</a><span id="debug_cache_info" style="display: none;"><em>', implode('</em>, <em>', $entries), '</em></span>)<br>
302
	', $txt['debug_cache_misses'], $cache_count_misses, ': (<a href="javascript:void(0);" onclick="document.getElementById(\'debug_cache_misses_info\').style.display = \'inline\'; this.style.display = \'none\'; return false;">', $txt['debug_show'], '</a><span id="debug_cache_misses_info" style="display: none;"><em>', implode('</em>, <em>', $missed_entries), '</em></span>)<br>';
303
	}
304
305
	echo '
306
	<a href="', $scripturl, '?action=viewquery" target="_blank" class="new_win">', $warnings == 0 ? sprintf($txt['debug_queries_used'], (int) $db_count) : sprintf($txt['debug_queries_used_and_warnings'], (int) $db_count, $warnings), '</a><br>
307
	<br>';
308
309
	if ($_SESSION['view_queries'] == 1 && !empty($db_cache))
310
		foreach ($db_cache as $q => $qq)
311
		{
312
			$is_select = strpos(trim($qq['q']), 'SELECT') === 0 || preg_match('~^INSERT(?: IGNORE)? INTO \w+(?:\s+\([^)]+\))?\s+SELECT .+$~s', trim($qq['q'])) != 0;
313
			// Temporary tables created in earlier queries are not explainable.
314
			if ($is_select)
315
			{
316 View Code Duplication
				foreach (array('log_topics_unread', 'topics_posted_in', 'tmp_log_search_topics', 'tmp_log_search_messages') as $tmp)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
317
					if (strpos(trim($qq['q']), $tmp) !== false)
318
					{
319
						$is_select = false;
320
						break;
321
					}
322
			}
323
			// But actual creation of the temporary tables are.
324
			elseif (preg_match('~^CREATE TEMPORARY TABLE .+?SELECT .+$~s', trim($qq['q'])) != 0)
325
				$is_select = true;
326
327
			// Make the filenames look a bit better.
328 View Code Duplication
			if (isset($qq['f']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
329
				$qq['f'] = preg_replace('~^' . preg_quote($boarddir, '~') . '~', '...', $qq['f']);
330
331
			echo '
332
	<strong>', $is_select ? '<a href="' . $scripturl . '?action=viewquery;qq=' . ($q + 1) . '#qq' . $q . '" target="_blank" class="new_win" style="text-decoration: none;">' : '', nl2br(str_replace("\t", '&nbsp;&nbsp;&nbsp;', $smcFunc['htmlspecialchars'](ltrim($qq['q'], "\n\r")))) . ($is_select ? '</a></strong>' : '</strong>') . '<br>
333
	&nbsp;&nbsp;&nbsp;';
334 View Code Duplication
			if (!empty($qq['f']) && !empty($qq['l']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
335
				echo sprintf($txt['debug_query_in_line'], $qq['f'], $qq['l']);
336
337
			if (isset($qq['s'], $qq['t']) && isset($txt['debug_query_which_took_at']))
338
				echo sprintf($txt['debug_query_which_took_at'], round($qq['t'], 8), round($qq['s'], 8)) . '<br>';
339
			elseif (isset($qq['t']))
340
				echo sprintf($txt['debug_query_which_took'], round($qq['t'], 8)) . '<br>';
341
			echo '
342
	<br>';
343
		}
344
345
	echo '
346
	<a href="' . $scripturl . '?action=viewquery;sa=hide">', $txt['debug_' . (empty($_SESSION['view_queries']) ? 'show' : 'hide') . '_queries'], '</a>
347
</div></body></html>';
348
}
349
350
/**
351
 * Track Statistics.
352
 * Caches statistics changes, and flushes them if you pass nothing.
353
 * If '+' is used as a value, it will be incremented.
354
 * It does not actually commit the changes until the end of the page view.
355
 * It depends on the trackStats setting.
356
 *
357
 * @param array $stats An array of data
358
 * @return bool Whether or not the info was updated successfully
359
 */
360
function trackStats($stats = array())
361
{
362
	global $modSettings, $smcFunc;
363
	static $cache_stats = array();
364
365
	if (empty($modSettings['trackStats']))
366
		return false;
367
	if (!empty($stats))
368
		return $cache_stats = array_merge($cache_stats, $stats);
369
	elseif (empty($cache_stats))
370
		return false;
371
372
	$setStringUpdate = '';
373
	$insert_keys = array();
374
	$date = strftime('%Y-%m-%d', forum_time(false));
375
	$update_parameters = array(
376
		'current_date' => $date,
377
	);
378
	foreach ($cache_stats as $field => $change)
379
	{
380
		$setStringUpdate .= '
381
			' . $field . ' = ' . ($change === '+' ? $field . ' + 1' : '{int:' . $field . '}') . ',';
382
383
		if ($change === '+')
384
			$cache_stats[$field] = 1;
385
		else
386
			$update_parameters[$field] = $change;
387
		$insert_keys[$field] = 'int';
388
	}
389
390
	$smcFunc['db_query']('', '
391
		UPDATE {db_prefix}log_activity
392
		SET' . substr($setStringUpdate, 0, -1) . '
393
		WHERE date = {date:current_date}',
394
		$update_parameters
395
	);
396
	if ($smcFunc['db_affected_rows']() == 0)
397
	{
398
		$smcFunc['db_insert']('ignore',
399
			'{db_prefix}log_activity',
400
			array_merge($insert_keys, array('date' => 'date')),
401
			array_merge($cache_stats, array($date)),
402
			array('date')
403
		);
404
	}
405
406
	// Don't do this again.
407
	$cache_stats = array();
408
409
	return true;
410
}
411
412
/**
413
 * This function logs an action in the respective log. (database log)
414
 * You should use {@link logActions()} instead.
415
 * @example logAction('remove', array('starter' => $id_member_started));
416
 *
417
 * @param string $action The action to log
418
 * @param array $extra = array() An array of additional data
419
 * @param string $log_type What type of log ('admin', 'moderate', etc.)
420
 * @return int The ID of the row containing the logged data
421
 */
422
function logAction($action, $extra = array(), $log_type = 'moderate')
423
{
424
	return logActions(array(array(
425
		'action' => $action,
426
		'log_type' => $log_type,
427
		'extra' => $extra,
428
	)));
429
}
430
431
/**
432
 * Log changes to the forum, such as moderation events or administrative changes.
433
 * This behaves just like logAction() in SMF 2.0, except that it is designed to log multiple actions at once.
434
 *
435
 * @param array $logs An array of log data
436
 * @return int The last logged ID
437
 */
438
function logActions($logs)
439
{
440
	global $modSettings, $user_info, $smcFunc, $sourcedir;
441
442
	$inserts = array();
443
	$log_types = array(
444
		'moderate' => 1,
445
		'user' => 2,
446
		'admin' => 3,
447
	);
448
449
	// Make sure this particular log is enabled first...
450
	if (empty($modSettings['modlog_enabled']))
451
		unset ($log_types['moderate']);
452
	if (empty($modSettings['userlog_enabled']))
453
		unset ($log_types['user']);
454
	if (empty($modSettings['adminlog_enabled']))
455
		unset ($log_types['admin']);
456
457
	call_integration_hook('integrate_log_types', array(&$log_types));
458
459
	foreach ($logs as $log)
460
	{
461
		if (!isset($log_types[$log['log_type']]))
462
			return false;
463
464
		if (!is_array($log['extra']))
465
			trigger_error('logActions(): data is not an array with action \'' . $log['action'] . '\'', E_USER_NOTICE);
466
467
		// Pull out the parts we want to store separately, but also make sure that the data is proper
468 View Code Duplication
		if (isset($log['extra']['topic']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
469
		{
470
			if (!is_numeric($log['extra']['topic']))
471
				trigger_error('logActions(): data\'s topic is not a number', E_USER_NOTICE);
472
			$topic_id = empty($log['extra']['topic']) ? 0 : (int) $log['extra']['topic'];
473
			unset($log['extra']['topic']);
474
		}
475
		else
476
			$topic_id = 0;
477
478 View Code Duplication
		if (isset($log['extra']['message']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
479
		{
480
			if (!is_numeric($log['extra']['message']))
481
				trigger_error('logActions(): data\'s message is not a number', E_USER_NOTICE);
482
			$msg_id = empty($log['extra']['message']) ? 0 : (int) $log['extra']['message'];
483
			unset($log['extra']['message']);
484
		}
485
		else
486
			$msg_id = 0;
487
488
		// @todo cache this?
489
		// Is there an associated report on this?
490
		if (in_array($log['action'], array('move', 'remove', 'split', 'merge')))
491
		{
492
			$request = $smcFunc['db_query']('', '
493
				SELECT id_report
494
				FROM {db_prefix}log_reported
495
				WHERE {raw:column_name} = {int:reported}
496
				LIMIT 1',
497
				array(
498
					'column_name' => !empty($msg_id) ? 'id_msg' : 'id_topic',
499
					'reported' => !empty($msg_id) ? $msg_id : $topic_id,
500
			));
501
502
			// Alright, if we get any result back, update open reports.
503 View Code Duplication
			if ($smcFunc['db_num_rows']($request) > 0)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
504
			{
505
				require_once($sourcedir . '/ModerationCenter.php');
506
				require_once($sourcedir . '/Subs-ReportedContent.php');
507
				updateSettings(array('last_mod_report_action' => time()));
508
				recountOpenReports('posts');
509
			}
510
			$smcFunc['db_free_result']($request);
511
		}
512
513
		if (isset($log['extra']['member']) && !is_numeric($log['extra']['member']))
514
			trigger_error('logActions(): data\'s member is not a number', E_USER_NOTICE);
515
516 View Code Duplication
		if (isset($log['extra']['board']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
517
		{
518
			if (!is_numeric($log['extra']['board']))
519
				trigger_error('logActions(): data\'s board is not a number', E_USER_NOTICE);
520
			$board_id = empty($log['extra']['board']) ? 0 : (int) $log['extra']['board'];
521
			unset($log['extra']['board']);
522
		}
523
		else
524
			$board_id = 0;
525
526 View Code Duplication
		if (isset($log['extra']['board_to']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
527
		{
528
			if (!is_numeric($log['extra']['board_to']))
529
				trigger_error('logActions(): data\'s board_to is not a number', E_USER_NOTICE);
530
			if (empty($board_id))
531
			{
532
				$board_id = empty($log['extra']['board_to']) ? 0 : (int) $log['extra']['board_to'];
533
				unset($log['extra']['board_to']);
534
			}
535
		}
536
537
		if (isset($log['extra']['member_affected']))
538
			$memID = $log['extra']['member_affected'];
539
		else
540
			$memID = $user_info['id'];
541
542
		$inserts[] = array(
543
			time(), $log_types[$log['log_type']], $memID, $user_info['ip'], $log['action'],
544
			$board_id, $topic_id, $msg_id, json_encode($log['extra']),
545
		);
546
	}
547
548
	$id_action = $smcFunc['db_insert']('',
549
		'{db_prefix}log_actions',
550
		array(
551
			'log_time' => 'int', 'id_log' => 'int', 'id_member' => 'int', 'ip' => 'inet', 'action' => 'string',
552
			'id_board' => 'int', 'id_topic' => 'int', 'id_msg' => 'int', 'extra' => 'string-65534',
553
		),
554
		$inserts,
555
		array('id_action'),
556
		1
557
	);
558
559
	return $id_action;
560
}
561
562
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...