Modlog::getModLogEntries()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 6
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 0
cts 3
cp 0
crap 2
1
<?php
2
3
/**
4
 * The moderation log is this file's only job. It views it, and that's about all it does.
5
 *
6
 * @package   ElkArte Forum
7
 * @copyright ElkArte Forum contributors
8
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
9
 *
10
 * This file contains code covered by:
11
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
12
 *
13
 * @version 2.0 dev
14
 *
15
 */
16
17
namespace ElkArte\AdminController;
18
19
use ElkArte\AbstractController;
20
use ElkArte\Helper\Util;
21
use ElkArte\Languages\Txt;
22
23
/**
24
 * Admin and moderation log controller.
25
 * Depending on permissions, this class will display and allow to act on the log
26
 * for administrators or for moderators.
27
 */
28
class Modlog extends AbstractController
29
{
30
	/**
31
	 * Default method for this controller.
32
	 *
33
	 * @see AbstractController::action_index()
34
	 */
35
	public function action_index()
36
	{
37
		// We haz nothing to do. :P
38
		$this->action_log();
39
	}
40
41
	/**
42
	 * Prepares the information from the moderation log for viewing.
43
	 * Show the moderation log, or admin log...
44
	 * Disallows the deletion of events within twenty-four hours of now.
45
	 * Requires the admin_forum permission for admin log.
46
	 * Accessed via ?action=moderate;area=modlog.
47
	 *
48
	 * @uses Modlog template, main sub-template.
49
	 */
50
	public function action_log(): void
51
	{
52
		global $txt, $context;
53
54
		require_once(SUBSDIR . '/Modlog.subs.php');
55
56
		// Are we looking at the moderation log or the administration log.
57
		$context['log_type'] = $this->_req->compareQuery('sa', 'adminlog') ? 3 : 1;
58
59
		// Trying to view the admin log, lets check you can.
60
		if ($context['log_type'] === 3)
61
		{
62
			isAllowedTo('admin_forum');
63
		}
64
65
		// These change dependant on whether we are viewing the moderation or admin log.
66
		if ($context['log_type'] === 3 || $this->_req->query->action === 'admin')
67
		{
68
			$context['url_start'] = getUrl('admin', ['action' => 'admin', 'area' => 'logs', 'sa' => ($context['log_type'] == 3 ? 'adminlog' : 'modlog'), 'type' => $context['log_type']]);
69
		}
70
		else
71
		{
72
			$context['url_start'] = getUrl('action', ['action' => 'moderate', 'area' => 'modlog', 'type' => $context['log_type']]);
73
		}
74
75
		$context['can_delete'] = allowedTo('admin_forum');
76
77
		Txt::load('Modlog');
78
79
		$context['page_title'] = $context['log_type'] === 3 ? $txt['modlog_admin_log'] : $txt['modlog_view'];
80
81
		// The number of entries to show per page of log file.
82
		$context['displaypage'] = 30;
83
84
		// Amount of hours that must pass before allowed to empty the file.
85
		$context['hoursdisable'] = 24;
86
87
		// Handle deletion...
88
		if (isset($this->_req->post->removeall) && $context['can_delete'])
89
		{
90
			checkSession();
91
			validateToken('mod-ml');
92
			deleteLogAction($context['log_type'], $context['hoursdisable']);
93
		}
94
		elseif (!empty($this->_req->post->remove) && isset($this->_req->post->delete) && $context['can_delete'])
95
		{
96
			checkSession();
97
			validateToken('mod-ml');
98
			deleteLogAction($context['log_type'], $context['hoursdisable'], $this->_req->post->delete);
99
		}
100
101
		// If we're coming from a search, get the variables.
102
		$isSearch = $this->_req->getPost('is_search', 'trim', '');
103
		$searchParams = $this->_req->getPost('params', 'trim', '');
104
		$sort = $this->_req->getQuery('sort', 'trim', 'member');
105
		$search = $this->_req->getPost('search', 'trim', '');
106
		$searchType = $this->_req->getPost('search_type', 'trim', null);
107
108
		if (!empty($searchParams) && empty($isSearch))
109
		{
110
			$search_params = base64_decode(strtr($searchParams, [' ' => '+']));
111
			$search_params = @json_decode($search_params, true);
112
		}
113
114
		// This array houses all the valid quick search types.
115
		$searchTypes = [
116
			'action' => ['sql' => 'lm.action', 'label' => $txt['modlog_action']],
117
			'member' => ['sql' => 'mem.real_name', 'label' => $txt['modlog_member']],
118
			'position' => ['sql' => 'mg.group_name', 'label' => $txt['modlog_position']],
119
			'ip' => ['sql' => 'lm.ip', 'label' => $txt['modlog_ip']]
120
		];
121
122
		// Setup the allowed search
123
		$context['order'] = isset($searchTypes[$sort]) ? $sort : 'member';
124
125
		if (!isset($search_params['string']) || (!empty($search) && $search_params['string'] !== $search))
126
		{
127
			$search_params_string = $search;
128
		}
129
		else
130
		{
131
			$search_params_string = $search_params['string'];
132
		}
133
134
		if (isset($searchType) || empty($search_params['type']) || !isset($searchTypes[$search_params['type']]))
135
		{
136
			$search_params_type = isset($searchType, $searchTypes[$searchType]) ? $searchType : $context['order'];
137
		}
138
		else
139
		{
140
			$search_params_type = $search_params['type'];
141
		}
142
143
		$search_params_column = $searchTypes[$search_params_type]['sql'];
144
		$search_params = [
145
			'string' => $search_params_string,
146
			'type' => $search_params_type,
147
		];
148
149
		// Setup the search context.
150
		$context['search_params'] = empty($search_params['string']) ? '' : base64_encode(json_encode($search_params));
151
		$context['search'] = [
152
			'string' => $search_params['string'],
153
			'type' => $search_params['type'],
154
			'label' => $searchTypes[$search_params_type]['label'],
155
		];
156
157
		// If they are searching by action, then we must do some manual intervention to search in their language!
158
		if ($search_params['type'] === 'action' && !empty($search_params['string']))
159
		{
160
			// Build a regex which looks for the words
161
			$regex = '';
162
			$search = explode(' ', $search_params['string']);
163
			foreach ($search as $word)
164
			{
165
				$regex .= '(?=[\w\s]*' . $word . ')';
166
			}
167
168
			// For the moment they can only search for ONE action!
169
			foreach ($txt as $key => $text)
170
			{
171
				if (strpos($key, 'modlog_ac_') === 0 && preg_match('~' . $regex . '~i', $text))
172
				{
173
					$search_params['string'] = substr($key, 10);
174
					break;
175
				}
176
			}
177
		}
178
179
		// This is all the information required for a moderation/admin log listing.
180
		$listOptions = [
181
			'id' => 'moderation_log_list',
182
			'width' => '100%',
183
			'items_per_page' => $context['displaypage'],
184
			'no_items_label' => $txt['modlog_' . ($context['log_type'] == 3 ? 'admin_log_' : '') . 'no_entries_found'],
185
			'base_href' => $context['url_start'],
186
			'default_sort_col' => 'time',
187
			'get_items' => [
188
				'function' => fn($start, $items_per_page, $sort, $query_string, $query_params, $log_type) => $this->getModLogEntries($start, $items_per_page, $sort, $query_string, $query_params, $log_type),
189
				'params' => [
190
					(empty($search_params['string']) ? '' : ' INSTR({raw:sql_type}, {string:search_string})'),
191
					['sql_type' => $search_params_column, 'search_string' => $search_params['string']],
192
					$context['log_type'],
193
				],
194
			],
195
			'get_count' => [
196
				'function' => fn($query_string, $query_params, $log_type) => $this->getModLogEntryCount($query_string, $query_params, $log_type),
197
				'params' => [
198
					(empty($search_params['string']) ? '' : ' INSTR({raw:sql_type}, {string:search_string})'),
199
					['sql_type' => $search_params_column, 'search_string' => $search_params['string']],
200
					$context['log_type'],
201
				],
202
			],
203
			'columns' => [
204
				'action' => [
205
					'header' => [
206
						'value' => $txt['modlog_action'],
207
						'class' => 'lefttext',
208
					],
209
					'data' => [
210
						'db' => 'action_text',
211
						'class' => 'smalltext',
212
					],
213
					'sort' => [
214
						'default' => 'lm.action',
215
						'reverse' => 'lm.action DESC',
216
					],
217
				],
218
				'time' => [
219
					'header' => [
220
						'value' => $txt['modlog_date'],
221
						'class' => 'lefttext',
222
					],
223
					'data' => [
224
						'db' => 'time',
225
						'class' => 'smalltext',
226
					],
227
					'sort' => [
228
						'default' => 'lm.log_time DESC',
229
						'reverse' => 'lm.log_time',
230
					],
231
				],
232
				'moderator' => [
233
					'header' => [
234
						'value' => $txt['modlog_member'],
235
						'class' => 'lefttext',
236
					],
237
					'data' => [
238
						'db' => 'moderator_link',
239
						'class' => 'smalltext',
240
					],
241
					'sort' => [
242
						'default' => 'mem.real_name',
243
						'reverse' => 'mem.real_name DESC',
244
					],
245
				],
246
				'position' => [
247
					'header' => [
248
						'value' => $txt['modlog_position'],
249
						'class' => 'lefttext',
250
					],
251
					'data' => [
252
						'db' => 'position',
253
						'class' => 'smalltext',
254
					],
255
					'sort' => [
256
						'default' => 'mg.group_name',
257
						'reverse' => 'mg.group_name DESC',
258
					],
259
				],
260
				'ip' => [
261
					'header' => [
262
						'value' => $txt['modlog_ip'],
263
						'class' => 'lefttext',
264
					],
265
					'data' => [
266
						'db' => 'ip',
267
						'class' => 'smalltext',
268
					],
269
					'sort' => [
270
						'default' => 'lm.ip',
271
						'reverse' => 'lm.ip DESC',
272
					],
273
				],
274
				'delete' => [
275
					'header' => [
276
						'value' => '<input type="checkbox" name="all" class="input_check" onclick="invertAll(this, this.form);" />',
277
						'class' => 'centertext',
278
					],
279
					'data' => [
280
						'function' => static fn($entry) => '<input type="checkbox" name="delete[]" value="' . $entry['id'] . '"' . ($entry['editable'] ? '' : ' disabled="disabled"') . ' />',
281
						'class' => 'centertext',
282
					],
283
				],
284
			],
285
			'form' => [
286
				'href' => $context['url_start'],
287
				'include_sort' => true,
288
				'include_start' => true,
289
				'hidden_fields' => [
290
					$context['session_var'] => $context['session_id'],
291
					'params' => $context['search_params']
292
				],
293
				'token' => 'mod-ml',
294
			],
295
			'additional_rows' => [
296
				[
297
					'class' => 'submitbutton',
298
					'position' => 'below_table_data',
299
					'value' => '
300
						' . $txt['modlog_search'] . ' (' . $txt['modlog_by'] . ': ' . $context['search']['label'] . ')
301
						<input type="text" name="search" size="18" value="' . Util::htmlspecialchars($context['search']['string']) . '" class="input_text" />
302
						<input type="submit" name="is_search" value="' . $txt['modlog_go'] . '" />
303
						' . ($context['can_delete'] ? '|&nbsp;
304
						<input type="submit" name="remove" value="' . $txt['modlog_remove'] . '" onclick="return confirm(\'' . $txt['modlog_remove_selected_confirm'] . '\');" />
305
						<input type="submit" name="removeall" value="' . $txt['modlog_removeall'] . '" onclick="return confirm(\'' . $txt['modlog_remove_all_confirm'] . '\');"/>' : ''),
306
				],
307
			],
308
		];
309
310
		createToken('mod-ml');
311
312
		// Create the log listing
313
		createList($listOptions);
314
315
		$context['sub_template'] = 'show_list';
316
		$context['default_list'] = 'moderation_log_list';
317
	}
318
319
	/**
320
	 * Callback for createList()
321
	 * Returns a list of moderation log entries
322
	 * Uses list_getModLogEntries in modlog subs
323
	 *
324
	 * @param int $start The item to start with (for pagination purposes)
325
	 * @param int $items_per_page The number of items to show per page
326
	 * @param string $sort A string indicating how to sort the results
327
	 * @param string $query_string
328
	 * @param array $query_params
329
	 * @param int $log_type
330
	 *
331
	 * @return array
332
	 */
333
	public function getModLogEntries(int $start, int $items_per_page, string $sort, string $query_string, array $query_params, int $log_type): array
334
	{
335
		// Get all entries of $log_type
336
		return list_getModLogEntries($start, $items_per_page, $sort, $query_string, $query_params, $log_type);
337
	}
338
339
	/**
340
	 * Callback for createList()
341
	 * Returns a count of moderation/admin log entries
342
	 * Uses list_getModLogEntryCount in modlog subs
343
	 *
344
	 * @param string $query_string
345
	 * @param array $query_params
346
	 * @param int $log_type
347
	 *
348
	 * @return int number of entries
349
	 */
350
	public function getModLogEntryCount(string $query_string, array $query_params, int $log_type): int
351
	{
352
		// Get the count of our solved topic entries
353
		return list_getModLogEntryCount($query_string, $query_params, $log_type);
354
	}
355
}
356