Failed Conditions
Branch release-2.1 (4e22cf)
by Rick
06:39
created

Logging.php ➔ writeLog()   F

Complexity

Conditions 38
Paths 7208

Size

Total Lines 132
Code Lines 64

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 38
eloc 64
nc 7208
nop 1
dl 0
loc 132
rs 2
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
 * 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 4
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
0 ignored issues
show
Documentation introduced by
Should the type for parameter $max_length not be integer?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
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));
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal strlen does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
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
		$encoded_get = 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($encoded_get['sesc'], $encoded_get[$context['session_var']]);
84
		$encoded_get = $smcFunc['json_encode']($encoded_get);
85
	}
86
	else
87
		$encoded_get = '';
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' => $encoded_get,
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'], $encoded_get),
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)
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']))
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']))
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
0 ignored issues
show
Documentation introduced by
Should the return type not be array|boolean? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
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']))
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']))
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?
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
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)
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']))
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']))
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, $smcFunc['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
?>