|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* The moderation log is this file's only job. |
|
5
|
|
|
* It views it, and that's about all it does. |
|
6
|
|
|
* |
|
7
|
|
|
* Simple Machines Forum (SMF) |
|
8
|
|
|
* |
|
9
|
|
|
* @package SMF |
|
10
|
|
|
* @author Simple Machines http://www.simplemachines.org |
|
11
|
|
|
* @copyright 2017 Simple Machines and individual contributors |
|
12
|
|
|
* @license http://www.simplemachines.org/about/smf/license.php BSD |
|
13
|
|
|
* |
|
14
|
|
|
* @version 2.1 Beta 4 |
|
15
|
|
|
*/ |
|
16
|
|
|
|
|
17
|
|
|
if (!defined('SMF')) |
|
18
|
|
|
die('No direct access...'); |
|
19
|
|
|
|
|
20
|
|
|
/** |
|
21
|
|
|
* Prepares the information from the moderation log for viewing. |
|
22
|
|
|
* Show the moderation log. |
|
23
|
|
|
* If clearing the log, leaves a message in the log to indicate it was cleared, by whom and when. |
|
24
|
|
|
* Requires the admin_forum permission. |
|
25
|
|
|
* Accessed via ?action=moderate;area=modlog. |
|
26
|
|
|
* |
|
27
|
|
|
* @uses Modlog template, main sub-template. |
|
28
|
|
|
*/ |
|
29
|
|
|
function ViewModlog() |
|
30
|
|
|
{ |
|
31
|
|
|
global $txt, $context, $scripturl, $sourcedir, $smcFunc; |
|
32
|
|
|
|
|
33
|
|
|
// Are we looking at the moderation log or the administration log. |
|
34
|
|
|
$context['log_type'] = isset($_REQUEST['sa']) && $_REQUEST['sa'] == 'adminlog' ? 3 : 1; |
|
35
|
|
|
if ($context['log_type'] == 3) |
|
36
|
|
|
isAllowedTo('admin_forum'); |
|
37
|
|
|
|
|
38
|
|
|
// These change dependant on whether we are viewing the moderation or admin log. |
|
39
|
|
|
if ($context['log_type'] == 3 || $_REQUEST['action'] == 'admin') |
|
40
|
|
|
$context['url_start'] = '?action=admin;area=logs;sa=' . ($context['log_type'] == 3 ? 'adminlog' : 'modlog') . ';type=' . $context['log_type']; |
|
41
|
|
|
else |
|
42
|
|
|
$context['url_start'] = '?action=moderate;area=modlog;type=' . $context['log_type']; |
|
43
|
|
|
|
|
44
|
|
|
$context['can_delete'] = allowedTo('admin_forum'); |
|
45
|
|
|
|
|
46
|
|
|
loadLanguage('Modlog'); |
|
47
|
|
|
|
|
48
|
|
|
$context['page_title'] = $context['log_type'] == 3 ? $txt['modlog_admin_log'] : $txt['modlog_view']; |
|
49
|
|
|
|
|
50
|
|
|
// The number of entries to show per page of log file. |
|
51
|
|
|
$context['displaypage'] = 30; |
|
52
|
|
|
|
|
53
|
|
|
// Handle deletion... |
|
54
|
|
|
if (isset($_POST['removeall']) && $context['can_delete']) |
|
55
|
|
|
{ |
|
56
|
|
|
checkSession(); |
|
57
|
|
|
validateToken('mod-ml'); |
|
58
|
|
|
|
|
59
|
|
|
$smcFunc['db_query']('', ' |
|
60
|
|
|
DELETE FROM {db_prefix}log_actions |
|
61
|
|
|
WHERE id_log = {int:moderate_log}', |
|
62
|
|
|
array( |
|
63
|
|
|
'moderate_log' => $context['log_type'], |
|
64
|
|
|
) |
|
65
|
|
|
); |
|
66
|
|
|
|
|
67
|
|
|
$log_type = isset($_REQUEST['sa']) && $_REQUEST['sa'] == 'adminlog' ? 'admin' : 'moderate'; |
|
68
|
|
|
logAction('clearlog_' . $log_type, array(), $log_type); |
|
69
|
|
|
|
|
70
|
|
|
} |
|
71
|
|
|
elseif (!empty($_POST['remove']) && isset($_POST['delete']) && $context['can_delete']) |
|
72
|
|
|
{ |
|
73
|
|
|
checkSession(); |
|
74
|
|
|
validateToken('mod-ml'); |
|
75
|
|
|
|
|
76
|
|
|
// No sneaky removing the 'cleared the log' entries. |
|
77
|
|
|
$smcFunc['db_query']('', ' |
|
78
|
|
|
DELETE FROM {db_prefix}log_actions |
|
79
|
|
|
WHERE id_log = {int:moderate_log} |
|
80
|
|
|
AND id_action IN ({array_string:delete_actions}) |
|
81
|
|
|
AND action NOT LIKE {string:clearlog}', |
|
82
|
|
|
array( |
|
83
|
|
|
'delete_actions' => array_unique($_POST['delete']), |
|
84
|
|
|
'moderate_log' => $context['log_type'], |
|
85
|
|
|
'clearlog' => 'clearlog_%', |
|
86
|
|
|
) |
|
87
|
|
|
); |
|
88
|
|
|
} |
|
89
|
|
|
|
|
90
|
|
|
// Do the column stuff! |
|
91
|
|
|
$sort_types = array( |
|
92
|
|
|
'action' =>'lm.action', |
|
93
|
|
|
'time' => 'lm.log_time', |
|
94
|
|
|
'member' => 'mem.real_name', |
|
95
|
|
|
'group' => 'mg.group_name', |
|
96
|
|
|
'ip' => 'lm.ip', |
|
97
|
|
|
); |
|
98
|
|
|
|
|
99
|
|
|
// Setup the direction stuff... |
|
100
|
|
|
$context['order'] = isset($_REQUEST['sort']) && isset($sort_types[$_REQUEST['sort']]) ? $_REQUEST['sort'] : 'time'; |
|
101
|
|
|
|
|
102
|
|
|
// If we're coming from a search, get the variables. |
|
103
|
|
View Code Duplication |
if (!empty($_REQUEST['params']) && empty($_REQUEST['is_search'])) |
|
|
|
|
|
|
104
|
|
|
{ |
|
105
|
|
|
$search_params = base64_decode(strtr($_REQUEST['params'], array(' ' => '+'))); |
|
106
|
|
|
$search_params = $smcFunc['json_decode']($search_params, true); |
|
107
|
|
|
} |
|
108
|
|
|
|
|
109
|
|
|
// This array houses all the valid search types. |
|
110
|
|
|
$searchTypes = array( |
|
111
|
|
|
'action' => array('sql' => 'lm.action', 'label' => $txt['modlog_action']), |
|
112
|
|
|
'member' => array('sql' => 'mem.real_name', 'label' => $txt['modlog_member']), |
|
113
|
|
|
'group' => array('sql' => 'mg.group_name', 'label' => $txt['modlog_position']), |
|
114
|
|
|
'ip' => array('sql' => 'lm.ip', 'label' => $txt['modlog_ip']) |
|
115
|
|
|
); |
|
116
|
|
|
|
|
117
|
|
|
if (!isset($search_params['string']) || (!empty($_REQUEST['search']) && $search_params['string'] != $_REQUEST['search'])) |
|
118
|
|
|
$search_params_string = empty($_REQUEST['search']) ? '' : $_REQUEST['search']; |
|
119
|
|
|
else |
|
120
|
|
|
$search_params_string = $search_params['string']; |
|
121
|
|
|
|
|
122
|
|
View Code Duplication |
if (isset($_REQUEST['search_type']) || empty($search_params['type']) || !isset($searchTypes[$search_params['type']])) |
|
|
|
|
|
|
123
|
|
|
$search_params_type = isset($_REQUEST['search_type']) && isset($searchTypes[$_REQUEST['search_type']]) ? $_REQUEST['search_type'] : (isset($searchTypes[$context['order']]) ? $context['order'] : 'member'); |
|
124
|
|
|
else |
|
125
|
|
|
$search_params_type = $search_params['type']; |
|
126
|
|
|
|
|
127
|
|
|
$search_params_column = $searchTypes[$search_params_type]['sql']; |
|
128
|
|
|
$search_params = array( |
|
129
|
|
|
'string' => $search_params_string, |
|
130
|
|
|
'type' => $search_params_type, |
|
131
|
|
|
); |
|
132
|
|
|
|
|
133
|
|
|
// Setup the search context. |
|
134
|
|
|
$context['search_params'] = empty($search_params['string']) ? '' : base64_encode($smcFunc['json_encode']($search_params)); |
|
135
|
|
|
$context['search'] = array( |
|
136
|
|
|
'string' => $search_params['string'], |
|
137
|
|
|
'type' => $search_params['type'], |
|
138
|
|
|
'label' => $searchTypes[$search_params_type]['label'], |
|
139
|
|
|
); |
|
140
|
|
|
|
|
141
|
|
|
// If they are searching by action, then we must do some manual intervention to search in their language! |
|
142
|
|
|
if ($search_params['type'] == 'action' && !empty($search_params['string'])) |
|
143
|
|
|
{ |
|
144
|
|
|
// For the moment they can only search for ONE action! |
|
145
|
|
|
foreach ($txt as $key => $text) |
|
146
|
|
|
{ |
|
147
|
|
|
if (substr($key, 0, 10) == 'modlog_ac_' && strpos($text, $search_params['string']) !== false) |
|
148
|
|
|
{ |
|
149
|
|
|
$search_params['string'] = substr($key, 10); |
|
150
|
|
|
break; |
|
151
|
|
|
} |
|
152
|
|
|
} |
|
153
|
|
|
} |
|
154
|
|
|
|
|
155
|
|
|
require_once($sourcedir . '/Subs-List.php'); |
|
156
|
|
|
|
|
157
|
|
|
// This is all the information required for a watched user listing. |
|
158
|
|
|
$listOptions = array( |
|
159
|
|
|
'id' => 'moderation_log_list', |
|
160
|
|
|
'width' => '100%', |
|
161
|
|
|
'items_per_page' => $context['displaypage'], |
|
162
|
|
|
'no_items_label' => $txt['modlog_' . ($context['log_type'] == 3 ? 'admin_log_' : '') . 'no_entries_found'], |
|
163
|
|
|
'base_href' => $scripturl . $context['url_start'] . (!empty($context['search_params']) ? ';params=' . $context['search_params'] : ''), |
|
164
|
|
|
'default_sort_col' => 'time', |
|
165
|
|
|
'get_items' => array( |
|
166
|
|
|
'function' => 'list_getModLogEntries', |
|
167
|
|
|
'params' => array( |
|
168
|
|
|
(!empty($search_params['string']) ? ' INSTR({raw:sql_type}, {string:search_string})' : ''), |
|
169
|
|
|
array('sql_type' => $search_params_column, 'search_string' => $search_params['string']), |
|
170
|
|
|
$context['log_type'], |
|
171
|
|
|
), |
|
172
|
|
|
), |
|
173
|
|
|
'get_count' => array( |
|
174
|
|
|
'function' => 'list_getModLogEntryCount', |
|
175
|
|
|
'params' => array( |
|
176
|
|
|
(!empty($search_params['string']) ? ' INSTR({raw:sql_type}, {string:search_string})' : ''), |
|
177
|
|
|
array('sql_type' => $search_params_column, 'search_string' => $search_params['string']), |
|
178
|
|
|
$context['log_type'], |
|
179
|
|
|
), |
|
180
|
|
|
), |
|
181
|
|
|
// This assumes we are viewing by user. |
|
182
|
|
|
'columns' => array( |
|
183
|
|
|
'action' => array( |
|
184
|
|
|
'header' => array( |
|
185
|
|
|
'value' => $txt['modlog_action'], |
|
186
|
|
|
'class' => 'lefttext', |
|
187
|
|
|
), |
|
188
|
|
|
'data' => array( |
|
189
|
|
|
'db' => 'action_text', |
|
190
|
|
|
'class' => 'smalltext', |
|
191
|
|
|
), |
|
192
|
|
|
'sort' => array( |
|
193
|
|
|
'default' => 'lm.action', |
|
194
|
|
|
'reverse' => 'lm.action DESC', |
|
195
|
|
|
), |
|
196
|
|
|
), |
|
197
|
|
|
'time' => array( |
|
198
|
|
|
'header' => array( |
|
199
|
|
|
'value' => $txt['modlog_date'], |
|
200
|
|
|
'class' => 'lefttext', |
|
201
|
|
|
), |
|
202
|
|
|
'data' => array( |
|
203
|
|
|
'db' => 'time', |
|
204
|
|
|
'class' => 'smalltext', |
|
205
|
|
|
), |
|
206
|
|
|
'sort' => array( |
|
207
|
|
|
'default' => 'lm.log_time DESC', |
|
208
|
|
|
'reverse' => 'lm.log_time', |
|
209
|
|
|
), |
|
210
|
|
|
), |
|
211
|
|
|
'moderator' => array( |
|
212
|
|
|
'header' => array( |
|
213
|
|
|
'value' => $txt['modlog_member'], |
|
214
|
|
|
'class' => 'lefttext', |
|
215
|
|
|
), |
|
216
|
|
|
'data' => array( |
|
217
|
|
|
'db' => 'moderator_link', |
|
218
|
|
|
'class' => 'smalltext', |
|
219
|
|
|
), |
|
220
|
|
|
'sort' => array( |
|
221
|
|
|
'default' => 'mem.real_name', |
|
222
|
|
|
'reverse' => 'mem.real_name DESC', |
|
223
|
|
|
), |
|
224
|
|
|
), |
|
225
|
|
|
'position' => array( |
|
226
|
|
|
'header' => array( |
|
227
|
|
|
'value' => $txt['modlog_position'], |
|
228
|
|
|
'class' => 'lefttext', |
|
229
|
|
|
), |
|
230
|
|
|
'data' => array( |
|
231
|
|
|
'db' => 'position', |
|
232
|
|
|
'class' => 'smalltext', |
|
233
|
|
|
), |
|
234
|
|
|
'sort' => array( |
|
235
|
|
|
'default' => 'mg.group_name', |
|
236
|
|
|
'reverse' => 'mg.group_name DESC', |
|
237
|
|
|
), |
|
238
|
|
|
), |
|
239
|
|
|
'ip' => array( |
|
240
|
|
|
'header' => array( |
|
241
|
|
|
'value' => $txt['modlog_ip'], |
|
242
|
|
|
'class' => 'lefttext', |
|
243
|
|
|
), |
|
244
|
|
|
'data' => array( |
|
245
|
|
|
'db' => 'ip', |
|
246
|
|
|
'class' => 'smalltext', |
|
247
|
|
|
), |
|
248
|
|
|
'sort' => array( |
|
249
|
|
|
'default' => 'lm.ip', |
|
250
|
|
|
'reverse' => 'lm.ip DESC', |
|
251
|
|
|
), |
|
252
|
|
|
), |
|
253
|
|
|
'delete' => array( |
|
254
|
|
|
'header' => array( |
|
255
|
|
|
'value' => '<input type="checkbox" name="all" onclick="invertAll(this, this.form);">', |
|
256
|
|
|
'class' => 'centercol', |
|
257
|
|
|
), |
|
258
|
|
|
'data' => array( |
|
259
|
|
|
'function' => function ($entry) |
|
260
|
|
|
{ |
|
261
|
|
|
return '<input type="checkbox" name="delete[]" value="' . $entry['id'] . '"' . ($entry['editable'] ? '' : ' disabled') . '>'; |
|
262
|
|
|
}, |
|
263
|
|
|
'class' => 'centercol', |
|
264
|
|
|
), |
|
265
|
|
|
), |
|
266
|
|
|
), |
|
267
|
|
|
'form' => array( |
|
268
|
|
|
'href' => $scripturl . $context['url_start'], |
|
269
|
|
|
'include_sort' => true, |
|
270
|
|
|
'include_start' => true, |
|
271
|
|
|
'hidden_fields' => array( |
|
272
|
|
|
$context['session_var'] => $context['session_id'], |
|
273
|
|
|
'params' => $context['search_params'] |
|
274
|
|
|
), |
|
275
|
|
|
'token' => 'mod-ml', |
|
276
|
|
|
), |
|
277
|
|
|
'additional_rows' => array( |
|
278
|
|
|
array( |
|
279
|
|
|
'position' => 'below_table_data', |
|
280
|
|
|
'value' => ' |
|
281
|
|
|
' . $txt['modlog_search'] . ' (' . $txt['modlog_by'] . ': ' . $context['search']['label'] . '): |
|
282
|
|
|
<input type="text" name="search" size="18" value="' . $smcFunc['htmlspecialchars']($context['search']['string']) . '"> |
|
283
|
|
|
<input type="submit" name="is_search" value="' . $txt['modlog_go'] . '" class="button_submit" style="float:none"> |
|
284
|
|
|
' . ($context['can_delete'] ? ' |
|
285
|
|
|
<input type="submit" name="remove" value="' . $txt['modlog_remove'] . '" data-confirm="' . $txt['modlog_remove_selected_confirm'] . '" class="button_submit you_sure"> |
|
286
|
|
|
<input type="submit" name="removeall" value="' . $txt['modlog_removeall'] . '" data-confirm="' . $txt['modlog_remove_all_confirm'] . '" class="button_submit you_sure">' : ''), |
|
287
|
|
|
'class' => 'floatright', |
|
288
|
|
|
), |
|
289
|
|
|
), |
|
290
|
|
|
); |
|
291
|
|
|
|
|
292
|
|
|
createToken('mod-ml'); |
|
293
|
|
|
|
|
294
|
|
|
// Create the watched user list. |
|
295
|
|
|
createList($listOptions); |
|
296
|
|
|
|
|
297
|
|
|
$context['sub_template'] = 'show_list'; |
|
298
|
|
|
$context['default_list'] = 'moderation_log_list'; |
|
299
|
|
|
|
|
300
|
|
|
if (isset($context['moderation_menu_name'])) |
|
301
|
|
|
$context[$context['moderation_menu_name']]['tab_data'] = array( |
|
302
|
|
|
'title' => $txt['modlog_' . ($context['log_type'] == 3 ? 'admin' : 'moderation') . '_log'], |
|
303
|
|
|
'help' => $context['log_type'] == 3 ? 'adminlog' : 'modlog', |
|
304
|
|
|
'description' => $txt['modlog_' . ($context['log_type'] == 3 ? 'admin' : 'moderation') . '_log_desc'] |
|
305
|
|
|
); |
|
306
|
|
|
} |
|
307
|
|
|
|
|
308
|
|
|
/** |
|
309
|
|
|
* Get the number of mod log entries. |
|
310
|
|
|
* Callback for createList() in ViewModlog(). |
|
311
|
|
|
* |
|
312
|
|
|
* @param string $query_string An extra string for the WHERE clause in the query to further filter results |
|
313
|
|
|
* @param array $query_params An array of parameters for the query_string |
|
314
|
|
|
* @param int $log_type The log type (1 for mod log, 3 for admin log) |
|
315
|
|
|
* @param bool $ignore_boards Whether to ignore board restrictions |
|
316
|
|
|
*/ |
|
317
|
|
|
function list_getModLogEntryCount($query_string = '', $query_params = array(), $log_type = 1, $ignore_boards = false) |
|
318
|
|
|
{ |
|
319
|
|
|
global $smcFunc, $user_info; |
|
320
|
|
|
|
|
321
|
|
|
$modlog_query = allowedTo('admin_forum') || $user_info['mod_cache']['bq'] == '1=1' ? '1=1' : (($user_info['mod_cache']['bq'] == '0=1' || $ignore_boards) ? 'lm.id_board = 0 AND lm.id_topic = 0' : (strtr($user_info['mod_cache']['bq'], array('id_board' => 'b.id_board')) . ' AND ' . strtr($user_info['mod_cache']['bq'], array('id_board' => 't.id_board')))); |
|
322
|
|
|
|
|
323
|
|
|
$result = $smcFunc['db_query']('', ' |
|
324
|
|
|
SELECT COUNT(*) |
|
325
|
|
|
FROM {db_prefix}log_actions AS lm |
|
326
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lm.id_member) |
|
327
|
|
|
LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:reg_group_id} THEN mem.id_post_group ELSE mem.id_group END) |
|
328
|
|
|
LEFT JOIN {db_prefix}boards AS b ON (b.id_board = lm.id_board) |
|
329
|
|
|
LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = lm.id_topic) |
|
330
|
|
|
WHERE id_log = {int:log_type} |
|
331
|
|
|
AND {raw:modlog_query}' |
|
332
|
|
|
. (!empty($query_string) ? ' |
|
333
|
|
|
AND ' . $query_string : ''), |
|
334
|
|
|
array_merge($query_params, array( |
|
335
|
|
|
'reg_group_id' => 0, |
|
336
|
|
|
'log_type' => $log_type, |
|
337
|
|
|
'modlog_query' => $modlog_query, |
|
338
|
|
|
)) |
|
339
|
|
|
); |
|
340
|
|
|
list ($entry_count) = $smcFunc['db_fetch_row']($result); |
|
341
|
|
|
$smcFunc['db_free_result']($result); |
|
342
|
|
|
|
|
343
|
|
|
return $entry_count; |
|
344
|
|
|
} |
|
345
|
|
|
|
|
346
|
|
|
/** |
|
347
|
|
|
* Gets the moderation log entries that match the specified parameters. |
|
348
|
|
|
* Callback for createList() in ViewModlog(). |
|
349
|
|
|
* |
|
350
|
|
|
* @param int $start The item to start with (for pagination purposes) |
|
351
|
|
|
* @param int $items_per_page The number of items to show per page |
|
352
|
|
|
* @param string $sort A string indicating how to sort the results |
|
353
|
|
|
* @param string $query_string An extra string for the WHERE clause of the query, to further filter results |
|
354
|
|
|
* @param array $query_params An array of parameters for the query string |
|
355
|
|
|
* @param int $log_type The log type - 1 for mod log or 3 for admin log |
|
356
|
|
|
* @param bool $ignore_boards Whether to ignore board restrictions |
|
357
|
|
|
* @return array An array of info about the mod log entries |
|
358
|
|
|
*/ |
|
359
|
|
|
function list_getModLogEntries($start, $items_per_page, $sort, $query_string = '', $query_params = array(), $log_type = 1, $ignore_boards = false) |
|
360
|
|
|
{ |
|
361
|
|
|
global $scripturl, $txt, $smcFunc, $user_info; |
|
362
|
|
|
|
|
363
|
|
|
$modlog_query = allowedTo('admin_forum') || $user_info['mod_cache']['bq'] == '1=1' ? '1=1' : (($user_info['mod_cache']['bq'] == '0=1' || $ignore_boards) ? 'lm.id_board = 0 AND lm.id_topic = 0' : (strtr($user_info['mod_cache']['bq'], array('id_board' => 'b.id_board')) . ' AND ' . strtr($user_info['mod_cache']['bq'], array('id_board' => 't.id_board')))); |
|
364
|
|
|
|
|
365
|
|
|
// Can they see the IP address? |
|
366
|
|
|
$seeIP = allowedTo('moderate_forum'); |
|
367
|
|
|
|
|
368
|
|
|
// Here we have the query getting the log details. |
|
369
|
|
|
$result = $smcFunc['db_query']('', ' |
|
370
|
|
|
SELECT |
|
371
|
|
|
lm.id_action, lm.id_member, lm.ip, lm.log_time, lm.action, lm.id_board, lm.id_topic, lm.id_msg, lm.extra, |
|
372
|
|
|
mem.real_name, mg.group_name |
|
373
|
|
|
FROM {db_prefix}log_actions AS lm |
|
374
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lm.id_member) |
|
375
|
|
|
LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:reg_group_id} THEN mem.id_post_group ELSE mem.id_group END) |
|
376
|
|
|
LEFT JOIN {db_prefix}boards AS b ON (b.id_board = lm.id_board) |
|
377
|
|
|
LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = lm.id_topic) |
|
378
|
|
|
WHERE id_log = {int:log_type} |
|
379
|
|
|
AND {raw:modlog_query}' |
|
380
|
|
|
. (!empty($query_string) ? ' |
|
381
|
|
|
AND ' . $query_string : '') . ' |
|
382
|
|
|
ORDER BY {raw:sort} |
|
383
|
|
|
LIMIT {int:start}, {int:max}', |
|
384
|
|
|
array_merge($query_params, array( |
|
385
|
|
|
'reg_group_id' => 0, |
|
386
|
|
|
'log_type' => $log_type, |
|
387
|
|
|
'modlog_query' => $modlog_query, |
|
388
|
|
|
'sort' => $sort, |
|
389
|
|
|
'start' => $start, |
|
390
|
|
|
'max' => $items_per_page, |
|
391
|
|
|
)) |
|
392
|
|
|
); |
|
393
|
|
|
|
|
394
|
|
|
// Arrays for decoding objects into. |
|
395
|
|
|
$topics = array(); |
|
396
|
|
|
$boards = array(); |
|
397
|
|
|
$members = array(); |
|
398
|
|
|
$messages = array(); |
|
399
|
|
|
$entries = array(); |
|
400
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($result)) |
|
401
|
|
|
{ |
|
402
|
|
|
$row['extra'] = $smcFunc['json_decode']($row['extra'], true); |
|
403
|
|
|
|
|
404
|
|
|
// Corrupt? |
|
405
|
|
|
$row['extra'] = is_array($row['extra']) ? $row['extra'] : array(); |
|
406
|
|
|
|
|
407
|
|
|
// Add on some of the column stuff info |
|
408
|
|
|
if (!empty($row['id_board'])) |
|
409
|
|
|
{ |
|
410
|
|
|
if ($row['action'] == 'move') |
|
411
|
|
|
$row['extra']['board_to'] = $row['id_board']; |
|
412
|
|
|
else |
|
413
|
|
|
$row['extra']['board'] = $row['id_board']; |
|
414
|
|
|
} |
|
415
|
|
|
|
|
416
|
|
|
if (!empty($row['id_topic'])) |
|
417
|
|
|
$row['extra']['topic'] = $row['id_topic']; |
|
418
|
|
|
if (!empty($row['id_msg'])) |
|
419
|
|
|
$row['extra']['message'] = $row['id_msg']; |
|
420
|
|
|
|
|
421
|
|
|
// Is this associated with a topic? |
|
422
|
|
View Code Duplication |
if (isset($row['extra']['topic'])) |
|
|
|
|
|
|
423
|
|
|
$topics[(int) $row['extra']['topic']][] = $row['id_action']; |
|
424
|
|
View Code Duplication |
if (isset($row['extra']['new_topic'])) |
|
|
|
|
|
|
425
|
|
|
$topics[(int) $row['extra']['new_topic']][] = $row['id_action']; |
|
426
|
|
|
|
|
427
|
|
|
// How about a member? |
|
428
|
|
|
if (isset($row['extra']['member'])) |
|
429
|
|
|
{ |
|
430
|
|
|
// Guests don't have names! |
|
431
|
|
|
if (empty($row['extra']['member'])) |
|
432
|
|
|
$row['extra']['member'] = $txt['modlog_parameter_guest']; |
|
433
|
|
|
else |
|
434
|
|
|
{ |
|
435
|
|
|
// Try to find it... |
|
436
|
|
|
$members[(int) $row['extra']['member']][] = $row['id_action']; |
|
437
|
|
|
} |
|
438
|
|
|
} |
|
439
|
|
|
|
|
440
|
|
|
// Associated with a board? |
|
441
|
|
View Code Duplication |
if (isset($row['extra']['board_to'])) |
|
|
|
|
|
|
442
|
|
|
$boards[(int) $row['extra']['board_to']][] = $row['id_action']; |
|
443
|
|
View Code Duplication |
if (isset($row['extra']['board_from'])) |
|
|
|
|
|
|
444
|
|
|
$boards[(int) $row['extra']['board_from']][] = $row['id_action']; |
|
445
|
|
View Code Duplication |
if (isset($row['extra']['board'])) |
|
|
|
|
|
|
446
|
|
|
$boards[(int) $row['extra']['board']][] = $row['id_action']; |
|
447
|
|
|
|
|
448
|
|
|
// A message? |
|
449
|
|
|
if (isset($row['extra']['message'])) |
|
450
|
|
|
$messages[(int) $row['extra']['message']][] = $row['id_action']; |
|
451
|
|
|
|
|
452
|
|
|
// IP Info? |
|
453
|
|
|
if (isset($row['extra']['ip_range'])) |
|
454
|
|
|
if ($seeIP) |
|
455
|
|
|
$row['extra']['ip_range'] = '<a href="' . $scripturl . '?action=trackip;searchip=' . $row['extra']['ip_range'] . '">' . $row['extra']['ip_range'] . '</a>'; |
|
456
|
|
|
else |
|
457
|
|
|
$row['extra']['ip_range'] = $txt['logged']; |
|
458
|
|
|
|
|
459
|
|
|
// Email? |
|
460
|
|
|
if (isset($row['extra']['email'])) |
|
461
|
|
|
$row['extra']['email'] = '<a href="mailto:' . $row['extra']['email'] . '">' . $row['extra']['email'] . '</a>'; |
|
462
|
|
|
|
|
463
|
|
|
// Bans are complex. |
|
464
|
|
|
if ($row['action'] == 'ban' || $row['action'] == 'banremove') |
|
465
|
|
|
{ |
|
466
|
|
|
$row['action_text'] = $txt['modlog_ac_ban' . ($row['action'] == 'banremove' ? '_remove' : '')]; |
|
467
|
|
|
foreach (array('member', 'email', 'ip_range', 'hostname') as $type) |
|
468
|
|
|
if (isset($row['extra'][$type])) |
|
469
|
|
|
$row['action_text'] .= $txt['modlog_ac_ban_trigger_' . $type]; |
|
470
|
|
|
} |
|
471
|
|
|
|
|
472
|
|
|
// The array to go to the template. Note here that action is set to a "default" value of the action doesn't match anything in the descriptions. Allows easy adding of logging events with basic details. |
|
473
|
|
|
$entries[$row['id_action']] = array( |
|
474
|
|
|
'id' => $row['id_action'], |
|
475
|
|
|
'ip' => $seeIP ? inet_dtop($row['ip']) : $txt['logged'], |
|
476
|
|
|
'position' => empty($row['real_name']) && empty($row['group_name']) ? $txt['guest'] : $row['group_name'], |
|
477
|
|
|
'moderator_link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>' : (empty($row['real_name']) ? ($txt['guest'] . (!empty($row['extra']['member_acted']) ? ' (' . $row['extra']['member_acted'] . ')' : '')) : $row['real_name']), |
|
478
|
|
|
'time' => timeformat($row['log_time']), |
|
479
|
|
|
'timestamp' => forum_time(true, $row['log_time']), |
|
480
|
|
|
'editable' => substr($row['action'], 0, 8) !== 'clearlog', |
|
481
|
|
|
'extra' => $row['extra'], |
|
482
|
|
|
'action' => $row['action'], |
|
483
|
|
|
'action_text' => isset($row['action_text']) ? $row['action_text'] : '', |
|
484
|
|
|
); |
|
485
|
|
|
} |
|
486
|
|
|
$smcFunc['db_free_result']($result); |
|
487
|
|
|
|
|
488
|
|
|
if (!empty($boards)) |
|
489
|
|
|
{ |
|
490
|
|
|
$request = $smcFunc['db_query']('', ' |
|
491
|
|
|
SELECT id_board, name |
|
492
|
|
|
FROM {db_prefix}boards |
|
493
|
|
|
WHERE id_board IN ({array_int:board_list}) |
|
494
|
|
|
LIMIT {int:limit}', |
|
495
|
|
|
array( |
|
496
|
|
|
'board_list' => array_keys($boards), |
|
497
|
|
|
'limit' => count(array_keys($boards)), |
|
498
|
|
|
) |
|
499
|
|
|
); |
|
500
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
501
|
|
|
{ |
|
502
|
|
|
foreach ($boards[$row['id_board']] as $action) |
|
503
|
|
|
{ |
|
504
|
|
|
// Make the board number into a link - dealing with moving too. |
|
505
|
|
|
if (isset($entries[$action]['extra']['board_to']) && $entries[$action]['extra']['board_to'] == $row['id_board']) |
|
506
|
|
|
$entries[$action]['extra']['board_to'] = '<a href="' . $scripturl . '?board=' . $row['id_board'] . '.0">' . $row['name'] . '</a>'; |
|
507
|
|
View Code Duplication |
elseif (isset($entries[$action]['extra']['board_from']) && $entries[$action]['extra']['board_from'] == $row['id_board']) |
|
|
|
|
|
|
508
|
|
|
$entries[$action]['extra']['board_from'] = '<a href="' . $scripturl . '?board=' . $row['id_board'] . '.0">' . $row['name'] . '</a>'; |
|
509
|
|
View Code Duplication |
elseif (isset($entries[$action]['extra']['board']) && $entries[$action]['extra']['board'] == $row['id_board']) |
|
|
|
|
|
|
510
|
|
|
$entries[$action]['extra']['board'] = '<a href="' . $scripturl . '?board=' . $row['id_board'] . '.0">' . $row['name'] . '</a>'; |
|
511
|
|
|
} |
|
512
|
|
|
} |
|
513
|
|
|
$smcFunc['db_free_result']($request); |
|
514
|
|
|
} |
|
515
|
|
|
|
|
516
|
|
|
if (!empty($topics)) |
|
517
|
|
|
{ |
|
518
|
|
|
$request = $smcFunc['db_query']('', ' |
|
519
|
|
|
SELECT ms.subject, t.id_topic |
|
520
|
|
|
FROM {db_prefix}topics AS t |
|
521
|
|
|
INNER JOIN {db_prefix}messages AS ms ON (ms.id_msg = t.id_first_msg) |
|
522
|
|
|
WHERE t.id_topic IN ({array_int:topic_list}) |
|
523
|
|
|
LIMIT {int:limit}', |
|
524
|
|
|
array( |
|
525
|
|
|
'topic_list' => array_keys($topics), |
|
526
|
|
|
'limit' => count(array_keys($topics)), |
|
527
|
|
|
) |
|
528
|
|
|
); |
|
529
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
530
|
|
|
{ |
|
531
|
|
|
foreach ($topics[$row['id_topic']] as $action) |
|
532
|
|
|
{ |
|
533
|
|
|
$this_action = &$entries[$action]; |
|
534
|
|
|
|
|
535
|
|
|
// This isn't used in the current theme. |
|
536
|
|
|
$this_action['topic'] = array( |
|
537
|
|
|
'id' => $row['id_topic'], |
|
538
|
|
|
'subject' => $row['subject'], |
|
539
|
|
|
'href' => $scripturl . '?topic=' . $row['id_topic'] . '.0', |
|
540
|
|
|
'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.0">' . $row['subject'] . '</a>' |
|
541
|
|
|
); |
|
542
|
|
|
|
|
543
|
|
|
// Make the topic number into a link - dealing with splitting too. |
|
544
|
|
|
if (isset($this_action['extra']['topic']) && $this_action['extra']['topic'] == $row['id_topic']) |
|
545
|
|
|
$this_action['extra']['topic'] = '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.' . (isset($this_action['extra']['message']) ? 'msg' . $this_action['extra']['message'] . '#msg' . $this_action['extra']['message'] : '0') . '">' . $row['subject'] . '</a>'; |
|
546
|
|
|
elseif (isset($this_action['extra']['new_topic']) && $this_action['extra']['new_topic'] == $row['id_topic']) |
|
547
|
|
|
$this_action['extra']['new_topic'] = '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.' . (isset($this_action['extra']['message']) ? 'msg' . $this_action['extra']['message'] . '#msg' . $this_action['extra']['message'] : '0') . '">' . $row['subject'] . '</a>'; |
|
548
|
|
|
} |
|
549
|
|
|
} |
|
550
|
|
|
$smcFunc['db_free_result']($request); |
|
551
|
|
|
} |
|
552
|
|
|
|
|
553
|
|
|
if (!empty($messages)) |
|
554
|
|
|
{ |
|
555
|
|
|
$request = $smcFunc['db_query']('', ' |
|
556
|
|
|
SELECT id_msg, subject |
|
557
|
|
|
FROM {db_prefix}messages |
|
558
|
|
|
WHERE id_msg IN ({array_int:message_list}) |
|
559
|
|
|
LIMIT {int:limit}', |
|
560
|
|
|
array( |
|
561
|
|
|
'message_list' => array_keys($messages), |
|
562
|
|
|
'limit' => count(array_keys($messages)), |
|
563
|
|
|
) |
|
564
|
|
|
); |
|
565
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
566
|
|
|
{ |
|
567
|
|
|
foreach ($messages[$row['id_msg']] as $action) |
|
568
|
|
|
{ |
|
569
|
|
|
$this_action = &$entries[$action]; |
|
570
|
|
|
|
|
571
|
|
|
// This isn't used in the current theme. |
|
572
|
|
|
$this_action['message'] = array( |
|
573
|
|
|
'id' => $row['id_msg'], |
|
574
|
|
|
'subject' => $row['subject'], |
|
575
|
|
|
'href' => $scripturl . '?msg=' . $row['id_msg'], |
|
576
|
|
|
'link' => '<a href="' . $scripturl . '?msg=' . $row['id_msg'] . '">' . $row['subject'] . '</a>', |
|
577
|
|
|
); |
|
578
|
|
|
|
|
579
|
|
|
// Make the message number into a link. |
|
580
|
|
|
if (isset($this_action['extra']['message']) && $this_action['extra']['message'] == $row['id_msg']) |
|
581
|
|
|
$this_action['extra']['message'] = '<a href="' . $scripturl . '?msg=' . $row['id_msg'] . '">' . $row['subject'] . '</a>'; |
|
582
|
|
|
} |
|
583
|
|
|
} |
|
584
|
|
|
$smcFunc['db_free_result']($request); |
|
585
|
|
|
} |
|
586
|
|
|
|
|
587
|
|
|
if (!empty($members)) |
|
588
|
|
|
{ |
|
589
|
|
|
$request = $smcFunc['db_query']('', ' |
|
590
|
|
|
SELECT real_name, id_member |
|
591
|
|
|
FROM {db_prefix}members |
|
592
|
|
|
WHERE id_member IN ({array_int:member_list}) |
|
593
|
|
|
LIMIT {int:limit}', |
|
594
|
|
|
array( |
|
595
|
|
|
'member_list' => array_keys($members), |
|
596
|
|
|
'limit' => count(array_keys($members)), |
|
597
|
|
|
) |
|
598
|
|
|
); |
|
599
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
600
|
|
|
{ |
|
601
|
|
|
foreach ($members[$row['id_member']] as $action) |
|
602
|
|
|
{ |
|
603
|
|
|
// Not used currently. |
|
604
|
|
|
$entries[$action]['member'] = array( |
|
605
|
|
|
'id' => $row['id_member'], |
|
606
|
|
|
'name' => $row['real_name'], |
|
607
|
|
|
'href' => $scripturl . '?action=profile;u=' . $row['id_member'], |
|
608
|
|
|
'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>' |
|
609
|
|
|
); |
|
610
|
|
|
// Make the member number into a name. |
|
611
|
|
|
$entries[$action]['extra']['member'] = '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>'; |
|
612
|
|
|
} |
|
613
|
|
|
} |
|
614
|
|
|
$smcFunc['db_free_result']($request); |
|
615
|
|
|
} |
|
616
|
|
|
|
|
617
|
|
|
// Do some formatting of the action string. |
|
618
|
|
|
foreach ($entries as $k => $entry) |
|
619
|
|
|
{ |
|
620
|
|
|
// Make any message info links so its easier to go find that message. |
|
621
|
|
|
if (isset($entry['extra']['message']) && (empty($entry['message']) || empty($entry['message']['id']))) |
|
622
|
|
|
$entries[$k]['extra']['message'] = '<a href="' . $scripturl . '?msg=' . $entry['extra']['message'] . '">' . $entry['extra']['message'] . '</a>'; |
|
623
|
|
|
|
|
624
|
|
|
// Mark up any deleted members, topics and boards. |
|
625
|
|
|
foreach (array('board', 'board_from', 'board_to', 'member', 'topic', 'new_topic') as $type) |
|
626
|
|
|
if (!empty($entry['extra'][$type]) && is_numeric($entry['extra'][$type])) |
|
627
|
|
|
$entries[$k]['extra'][$type] = sprintf($txt['modlog_id'], $entry['extra'][$type]); |
|
628
|
|
|
|
|
629
|
|
|
if (isset($entry['extra']['report'])) |
|
630
|
|
|
{ |
|
631
|
|
|
// Member profile reports go in a different area |
|
632
|
|
|
if (stristr($entry['action'], 'user_report')) |
|
633
|
|
|
$entries[$k]['extra']['report'] = '<a href="' . $scripturl . '?action=moderate;area=reportedmembers;sa=details;rid=' . $entry['extra']['report'] . '">' . $txt['modlog_report'] . '</a>'; |
|
634
|
|
|
else |
|
635
|
|
|
$entries[$k]['extra']['report'] = '<a href="' . $scripturl . '?action=moderate;area=reportedposts;sa=details;rid=' . $entry['extra']['report'] . '">' . $txt['modlog_report'] . '</a>'; |
|
636
|
|
|
} |
|
637
|
|
|
|
|
638
|
|
|
if (empty($entries[$k]['action_text'])) |
|
639
|
|
|
$entries[$k]['action_text'] = isset($txt['modlog_ac_' . $entry['action']]) ? $txt['modlog_ac_' . $entry['action']] : $entry['action']; |
|
640
|
|
|
$entries[$k]['action_text'] = preg_replace_callback('~\{([A-Za-z\d_]+)\}~i', |
|
641
|
|
|
function ($matches) use ($entries, $k) |
|
642
|
|
|
{ |
|
643
|
|
|
return isset($entries[$k]['extra'][$matches[1]]) ? $entries[$k]['extra'][$matches[1]] : ''; |
|
644
|
|
|
}, $entries[$k]['action_text']); |
|
645
|
|
|
} |
|
646
|
|
|
|
|
647
|
|
|
// Back we go! |
|
648
|
|
|
return $entries; |
|
649
|
|
|
} |
|
650
|
|
|
|
|
651
|
|
|
?> |
|
|
|
|
|
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.