Completed
Push — release-2.1 ( 4c82a0...64d581 )
by Rick
09:29
created

ModerationCenter.php ➔ ModerationMain()   F

Complexity

Conditions 21
Paths 9217

Size

Total Lines 218
Code Lines 151

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 21
eloc 151
nc 9217
nop 1
dl 0
loc 218
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
 * Moderation Center.
5
 *
6
 * Simple Machines Forum (SMF)
7
 *
8
 * @package SMF
9
 * @author Simple Machines http://www.simplemachines.org
10
 * @copyright 2016 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
 * Entry point for the moderation center.
21
 *
22
 * @param bool $dont_call If true, doesn't call the function for the appropriate mod area
23
 */
24
function ModerationMain($dont_call = false)
25
{
26
	global $txt, $context, $scripturl, $modSettings, $user_info, $sourcedir, $options;
27
28
	// Don't run this twice... and don't conflict with the admin bar.
29
	if (isset($context['admin_area']))
30
		return;
31
32
	$context['can_moderate_boards'] = $user_info['mod_cache']['bq'] != '0=1';
33
	$context['can_moderate_groups'] = $user_info['mod_cache']['gq'] != '0=1';
34
	$context['can_moderate_approvals'] = $modSettings['postmod_active'] && !empty($user_info['mod_cache']['ap']);
35
	$context['can_moderate_users'] = allowedTo('moderate_forum');
36
37
	// Everyone using this area must be allowed here!
38
	if (!$context['can_moderate_boards'] && !$context['can_moderate_groups'] && !$context['can_moderate_approvals'] && !$context['can_moderate_users'])
39
		isAllowedTo('access_mod_center');
40
41
	// We're gonna want a menu of some kind.
42
	require_once($sourcedir . '/Subs-Menu.php');
43
44
	// Load the language, and the template.
45
	loadLanguage('ModerationCenter');
46
	loadTemplate(false, 'admin');
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
47
48
	$context['admin_preferences'] = !empty($options['admin_preferences']) ? smf_json_decode($options['admin_preferences'], true) : array();
49
	$context['robot_no_index'] = true;
50
51
	// This is the menu structure - refer to Subs-Menu.php for the details.
52
	$moderation_areas = array(
53
		'main' => array(
54
			'title' => $txt['mc_main'],
55
			'areas' => array(
56
				'index' => array(
57
					'label' => $txt['moderation_center'],
58
					'function' => 'ModerationHome',
59
					'icon' => 'administration',
60
				),
61
				'settings' => array(
62
					'label' => $txt['mc_settings'],
63
					'function' => 'ModerationSettings',
64
					'icon' => 'features',
65
				),
66
				'modlogoff' => array(
67
					'label' => $txt['mc_logoff'],
68
					'function' => 'ModEndSession',
69
					'enabled' => empty($modSettings['securityDisable_moderate']),
70
					'icon' => 'exit',
71
				),
72
				'notice' => array(
73
					'file' => 'ModerationCenter.php',
74
					'function' => 'ShowNotice',
75
					'select' => 'index'
76
				),
77
			),
78
		),
79
		'logs' => array(
80
			'title' => $txt['mc_logs'],
81
			'areas' => array(
82
				'modlog' => array(
83
					'label' => $txt['modlog_view'],
84
					'enabled' => !empty($modSettings['modlog_enabled']) && $context['can_moderate_boards'],
85
					'file' => 'Modlog.php',
86
					'function' => 'ViewModlog',
87
					'icon' => 'logs',
88
				),
89
				'warnings' => array(
90
					'label' => $txt['mc_warnings'],
91
					'enabled' => $modSettings['warning_settings'][0] == 1 && $context['can_moderate_boards'],
92
					'function' => 'ViewWarnings',
93
					'icon' => 'warning',
94
					'subsections' => array(
95
						'log' => array($txt['mc_warning_log']),
96
						'templates' => array($txt['mc_warning_templates'], 'issue_warning'),
97
					),
98
				),
99
			),
100
		),
101
		'posts' => array(
102
			'title' => $txt['mc_posts'],
103
			'enabled' => $context['can_moderate_boards'] || $context['can_moderate_approvals'],
104
			'areas' => array(
105
				'postmod' => array(
106
					'label' => $txt['mc_unapproved_posts'],
107
					'enabled' => $context['can_moderate_approvals'],
108
					'file' => 'PostModeration.php',
109
					'function' => 'PostModerationMain',
110
					'icon' => 'posts',
111
					'custom_url' => $scripturl . '?action=moderate;area=postmod',
112
					'subsections' => array(
113
						'posts' => array($txt['mc_unapproved_replies']),
114
						'topics' => array($txt['mc_unapproved_topics']),
115
					),
116
				),
117
				'attachmod' => array(
118
					'label' => $txt['mc_unapproved_attachments'],
119
					'enabled' => $context['can_moderate_approvals'],
120
					'file' => 'PostModeration.php',
121
					'function' => 'PostModerationMain',
122
					'icon' => 'post_moderation_attach',
123
					'custom_url' => $scripturl . '?action=moderate;area=attachmod;sa=attachments',
124
				),
125
				'reportedposts' => array(
126
					'label' => $txt['mc_reported_posts'],
127
					'enabled' => $context['can_moderate_boards'],
128
					'file' => 'ReportedContent.php',
129
					'function' => 'ReportedContent',
130
					'icon' => 'reports',
131
					'subsections' => array(
132
						'show' => array($txt['mc_reportedp_active']),
133
						'closed' => array($txt['mc_reportedp_closed']),
134
					),
135
				),
136
			),
137
		),
138
		'groups' => array(
139
			'title' => $txt['mc_groups'],
140
			'enabled' => $context['can_moderate_groups'],
141
			'areas' => array(
142
				'groups' => array(
143
					'label' => $txt['mc_group_requests'],
144
					'file' => 'Groups.php',
145
					'function' => 'Groups',
146
					'icon' => 'members_request',
147
					'custom_url' => $scripturl . '?action=moderate;area=groups;sa=requests',
148
				),
149
				'viewgroups' => array(
150
					'label' => $txt['mc_view_groups'],
151
					'file' => 'Groups.php',
152
					'function' => 'Groups',
153
					'icon' => 'membergroups',
154
				),
155
			),
156
		),
157
		'members' => array(
158
			'title' => $txt['mc_members'],
159
			'enabled' => $context['can_moderate_users'] || ($modSettings['warning_settings'][0] == 1 && $context['can_moderate_boards']),
160
			'areas' => array(
161
				'userwatch' => array(
162
					'label' => $txt['mc_watched_users_title'],
163
					'enabled' => $modSettings['warning_settings'][0] == 1 && $context['can_moderate_boards'],
164
					'function' => 'ViewWatchedUsers',
165
					'icon' => 'members_watched',
166
					'subsections' => array(
167
						'member' => array($txt['mc_watched_users_member']),
168
						'post' => array($txt['mc_watched_users_post']),
169
					),
170
				),
171
				'reportedmembers' => array(
172
					'label' => $txt['mc_reported_members_title'],
173
					'enabled' => $context['can_moderate_users'],
174
					'file' => 'ReportedContent.php',
175
					'function' => 'ReportedContent',
176
					'icon' => 'members_watched',
177
					'subsections' => array(
178
						'open' => array($txt['mc_reportedp_active']),
179
						'closed' => array($txt['mc_reportedp_closed']),
180
					),
181
				),
182
			),
183
		)
184
	);
185
186
	// Make sure the administrator has a valid session...
187
	validateSession('moderate');
188
189
	// I don't know where we're going - I don't know where we've been...
190
	$menuOptions = array(
191
		'action' => 'moderate',
192
		'disable_url_session_check' => true,
193
	);
194
	$mod_include_data = createMenu($moderation_areas, $menuOptions);
195
	unset($moderation_areas);
196
197
	// We got something - didn't we? DIDN'T WE!
198
	if ($mod_include_data == false)
199
		fatal_lang_error('no_access', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
200
201
	// Retain the ID information in case required by a subaction.
202
	$context['moderation_menu_id'] = $context['max_menu_id'];
203
	$context['moderation_menu_name'] = 'menu_data_' . $context['moderation_menu_id'];
204
205
	// @todo: html in here is not good
206
	$context[$context['moderation_menu_name']]['tab_data'] = array(
207
		'title' => $txt['moderation_center'],
208
		'help' => '',
209
		'description' => '
210
			<strong>' . $txt['hello_guest'] . ' ' . $context['user']['name'] . '!</strong>
211
			<br><br>
212
			' . $txt['mc_description']);
213
214
	// What a pleasant shortcut - even tho we're not *really* on the admin screen who cares...
215
	$context['admin_area'] = $mod_include_data['current_area'];
216
217
	// Build the link tree.
218
	$context['linktree'][] = array(
219
		'url' => $scripturl . '?action=moderate',
220
		'name' => $txt['moderation_center'],
221
	);
222
	if (isset($mod_include_data['current_area']) && $mod_include_data['current_area'] != 'index')
223
		$context['linktree'][] = array(
224
			'url' => $scripturl . '?action=moderate;area=' . $mod_include_data['current_area'],
225
			'name' => $mod_include_data['label'],
226
		);
227
	if (!empty($mod_include_data['current_subsection']) && $mod_include_data['subsections'][$mod_include_data['current_subsection']][0] != $mod_include_data['label'])
228
		$context['linktree'][] = array(
229
			'url' => $scripturl . '?action=moderate;area=' . $mod_include_data['current_area'] . ';sa=' . $mod_include_data['current_subsection'],
230
			'name' => $mod_include_data['subsections'][$mod_include_data['current_subsection']][0],
231
		);
232
233
	// Now - finally - the bit before the encore - the main performance of course!
234
	if (!$dont_call)
235
	{
236
		if (isset($mod_include_data['file']))
237
			require_once($sourcedir . '/' . $mod_include_data['file']);
238
239
		call_helper($mod_include_data['function']);
240
	}
241
}
242
243
/**
244
 * This function basically is the home page of the moderation center.
245
 */
246
function ModerationHome()
247
{
248
	global $txt, $context, $options;
249
250
	loadTemplate('ModerationCenter');
251
	loadJavaScriptFile('admin.js', array(), 'smf_admin');
252
253
	$context['page_title'] = $txt['moderation_center'];
254
	$context['sub_template'] = 'moderation_center';
255
256
	// Handle moderators notes.
257
	ModBlockNotes();
258
259
	// Load what blocks the user actually can see...
260
	$valid_blocks = array();
261
262
	if ($context['can_moderate_groups'])
263
		$valid_blocks['g'] = 'GroupRequests';
264
	if ($context['can_moderate_boards'])
265
	{
266
		$valid_blocks['r'] = 'ReportedPosts';
267
		$valid_blocks['w'] = 'WatchedUsers';
268
	}
269
	if ($context['can_moderate_users'])
270
	{
271
		// This falls under the category of moderating users as well...
272
		if (!$context['can_moderate_boards'])
273
			$valid_blocks['w'] = 'WatchedUsers';
274
275
		$valid_blocks['rm'] = 'ReportedMembers';
276
	}
277
278
	call_integration_hook('integrate_mod_centre_blocks', array(&$valid_blocks));
279
280
	$context['mod_blocks'] = array();
281
	foreach ($valid_blocks as $k => $block)
282
	{
283
		$block = 'ModBlock' . $block;
284
		if (function_exists($block))
285
			$context['mod_blocks'][] = $block();
286
	}
287
288
	$context['admin_prefs'] = !empty($options['admin_preferences']) ? smf_json_decode($options['admin_preferences'], true) : array();
289
}
290
291
/**
292
 * Show a list of the most active watched users.
293
 */
294
function ModBlockWatchedUsers()
295
{
296
	global $context, $smcFunc, $scripturl, $modSettings;
297
298
	if (($watched_users = cache_get_data('recent_user_watches', 240)) === null)
299
	{
300
		$modSettings['warning_watch'] = empty($modSettings['warning_watch']) ? 1 : $modSettings['warning_watch'];
301
		$request = $smcFunc['db_query']('', '
302
			SELECT id_member, real_name, last_login
303
			FROM {db_prefix}members
304
			WHERE warning >= {int:warning_watch}
305
			ORDER BY last_login DESC
306
			LIMIT 10',
307
			array(
308
				'warning_watch' => $modSettings['warning_watch'],
309
			)
310
		);
311
		$watched_users = array();
312
		while ($row = $smcFunc['db_fetch_assoc']($request))
313
			$watched_users[] = $row;
314
		$smcFunc['db_free_result']($request);
315
316
		cache_put_data('recent_user_watches', $watched_users, 240);
317
	}
318
319
	$context['watched_users'] = array();
320
	foreach ($watched_users as $user)
321
	{
322
		$context['watched_users'][] = array(
323
			'id' => $user['id_member'],
324
			'name' => $user['real_name'],
325
			'link' => '<a href="' . $scripturl . '?action=profile;u=' . $user['id_member'] . '">' . $user['real_name'] . '</a>',
326
			'href' => $scripturl . '?action=profile;u=' . $user['id_member'],
327
			'last_login' => !empty($user['last_login']) ? timeformat($user['last_login']) : '',
328
		);
329
	}
330
331
	return 'watched_users';
332
}
333
334
/**
335
 * Show an area for the moderator to type into.
336
 */
337
function ModBlockNotes()
338
{
339
	global $context, $smcFunc, $scripturl, $txt, $user_info;
340
341
	// Set a nice and informative message.
342
	$context['report_post_action'] = !empty($_SESSION['rc_confirmation']) ? $_SESSION['rc_confirmation'] : array();
343
	unset($_SESSION['rc_confirmation']);
344
345
	// Are we saving a note?
346
	if (isset($_GET['modnote']) && isset($_POST['makenote']) && isset($_POST['new_note']))
347
	{
348
		checkSession();
349
		validateToken('mod-modnote-add');
350
351
		$_POST['new_note'] = $smcFunc['htmlspecialchars'](trim($_POST['new_note']));
352
		// Make sure they actually entered something.
353
		if (!empty($_POST['new_note']))
354
		{
355
			// Insert it into the database then!
356
			$smcFunc['db_insert']('',
357
				'{db_prefix}log_comments',
358
				array(
359
					'id_member' => 'int', 'member_name' => 'string', 'comment_type' => 'string', 'recipient_name' => 'string',
360
					'body' => 'string', 'log_time' => 'int',
361
				),
362
				array(
363
					$user_info['id'], $user_info['name'], 'modnote', '', $_POST['new_note'], time(),
364
				),
365
				array('id_comment')
366
			);
367
368
			// Clear the cache.
369
			cache_put_data('moderator_notes', null, 240);
370
			cache_put_data('moderator_notes_total', null, 240);
371
		}
372
373
		// Everything went better than expected!
374
		$_SESSION['rc_confirmation'] = 'message_saved';
375
376
		// Redirect otherwise people can resubmit.
377
		redirectexit('action=moderate');
378
	}
379
380
	// Bye... bye...
381
	if (isset($_GET['notes']) && isset($_GET['delete']) && is_numeric($_GET['delete']))
382
	{
383
		checkSession('get');
384
		validateToken('mod-modnote-del', 'get');
385
386
		// No sneaky stuff now!
387
		if (!allowedTo('admin_forum'))
388
		{
389
			// Is this your note?
390
			$get_owner = $smcFunc['db_query']('', '
391
				SELECT id_member
392
				FROM {db_prefix}log_comments
393
				WHERE id_comment = {int:note}
394
					AND comment_type = {literal:modnote}
395
					AND id_member = {int:user}',
396
				array(
397
					'note' => $_GET['delete'],
398
					'user' => $user_info['id'],
399
				)
400
			);
401
402
			$note_owner = $smcFunc['db_num_rows']($get_owner);
403
			$smcFunc['db_free_result']($get_owner);
404
405
			if(empty($note_owner))
406
				fatal_lang_error('mc_notes_delete_own', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
407
		}
408
409
		// Lets delete it.
410
		$smcFunc['db_query']('', '
411
			DELETE FROM {db_prefix}log_comments
412
			WHERE id_comment = {int:note}
413
				AND comment_type = {literal:modnote}',
414
			array(
415
				'note' => $_GET['delete'],
416
			)
417
		);
418
419
		// Clear the cache.
420
		cache_put_data('moderator_notes', null, 240);
421
		cache_put_data('moderator_notes_total', null, 240);
422
423
		// Tell them the message was deleted.
424
		$_SESSION['rc_confirmation'] = 'message_deleted';
425
426
		redirectexit('action=moderate');
427
	}
428
429
	// How many notes in total?
430 View Code Duplication
	if (($moderator_notes_total = cache_get_data('moderator_notes_total', 240)) === null)
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...
431
	{
432
		$request = $smcFunc['db_query']('', '
433
			SELECT COUNT(*)
434
			FROM {db_prefix}log_comments AS lc
435
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lc.id_member)
436
			WHERE lc.comment_type = {literal:modnote}',
437
			array(
438
			)
439
		);
440
		list ($moderator_notes_total) = $smcFunc['db_fetch_row']($request);
441
		$smcFunc['db_free_result']($request);
442
443
		cache_put_data('moderator_notes_total', $moderator_notes_total, 240);
444
	}
445
446
	// Grab the current notes. We can only use the cache for the first page of notes.
447
	$offset = isset($_GET['notes']) && isset($_GET['start']) ? $_GET['start'] : 0;
448
	if ($offset != 0 || ($moderator_notes = cache_get_data('moderator_notes', 240)) === null)
449
	{
450
		$request = $smcFunc['db_query']('', '
451
			SELECT COALESCE(mem.id_member, 0) AS id_member, COALESCE(mem.real_name, lc.member_name) AS member_name,
452
				lc.log_time, lc.body, lc.id_comment AS id_note
453
			FROM {db_prefix}log_comments AS lc
454
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lc.id_member)
455
			WHERE lc.comment_type = {literal:modnote}
456
			ORDER BY id_comment DESC
457
			LIMIT {int:offset}, 10',
458
			array(
459
				'offset' => $offset,
460
			)
461
		);
462
		$moderator_notes = array();
463
		while ($row = $smcFunc['db_fetch_assoc']($request))
464
			$moderator_notes[] = $row;
465
		$smcFunc['db_free_result']($request);
466
467
		if ($offset == 0)
468
			cache_put_data('moderator_notes', $moderator_notes, 240);
469
	}
470
471
	// Lets construct a page index.
472
	$context['page_index'] = constructPageIndex($scripturl . '?action=moderate;area=index;notes', $_GET['start'], $moderator_notes_total, 10);
473
	$context['start'] = $_GET['start'];
474
475
	$context['notes'] = array();
476
	foreach ($moderator_notes as $note)
477
	{
478
		$context['notes'][] = array(
479
			'author' => array(
480
				'id' => $note['id_member'],
481
				'link' => $note['id_member'] ? ('<a href="' . $scripturl . '?action=profile;u=' . $note['id_member'] . '">' . $note['member_name'] . '</a>') : $note['member_name'],
482
			),
483
			'time' => timeformat($note['log_time']),
484
			'text' => parse_bbc($note['body']),
485
			'delete_href' => $scripturl . '?action=moderate;area=index;notes;delete=' . $note['id_note'] . ';' . $context['session_var'] . '=' . $context['session_id'],
486
			'can_delete' => allowedTo('admin_forum') || $note['id_member'] == $user_info['id'],
487
		);
488
	}
489
490
	// Couple tokens for add/delete modnotes
491
	createToken('mod-modnote-add');
492
	createToken('mod-modnote-del', 'get');
493
494
	return 'notes';
495
}
496
497
/**
498
 * Show a list of the most recent reported posts.
499
 */
500
function ModBlockReportedPosts()
501
{
502
	global $context, $user_info, $scripturl, $smcFunc;
503
504
	// Got the info already?
505
	$cachekey = md5(json_encode($user_info['mod_cache']['bq']));
506
	$context['reported_posts'] = array();
507
	if ($user_info['mod_cache']['bq'] == '0=1')
508
		return 'reported_posts_block';
509
510
	if (($reported_posts = cache_get_data('reported_posts_' . $cachekey, 90)) === null)
511
	{
512
		// By George, that means we in a position to get the reports, jolly good.
513
		$request = $smcFunc['db_query']('', '
514
			SELECT lr.id_report, lr.id_msg, lr.id_topic, lr.id_board, lr.id_member, lr.subject,
515
				lr.num_reports, COALESCE(mem.real_name, lr.membername) AS author_name,
516
				COALESCE(mem.id_member, 0) AS id_author
517
			FROM {db_prefix}log_reported AS lr
518
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lr.id_member)
519
			WHERE ' . ($user_info['mod_cache']['bq'] == '1=1' || $user_info['mod_cache']['bq'] == '0=1' ? $user_info['mod_cache']['bq'] : 'lr.' . $user_info['mod_cache']['bq']) . '
520
				AND lr.id_board != {int:not_a_reported_post}
521
				AND lr.closed = {int:not_closed}
522
				AND lr.ignore_all = {int:not_ignored}
523
			ORDER BY lr.time_updated DESC
524
			LIMIT 10',
525
			array(
526
				'not_a_reported_post' => 0,
527
				'not_closed' => 0,
528
				'not_ignored' => 0,
529
			)
530
		);
531
		$reported_posts = array();
532
		while ($row = $smcFunc['db_fetch_assoc']($request))
533
			$reported_posts[] = $row;
534
		$smcFunc['db_free_result']($request);
535
536
		// Cache it.
537
		cache_put_data('reported_posts_' . $cachekey, $reported_posts, 90);
538
	}
539
540
	$context['reported_posts'] = array();
541
	foreach ($reported_posts as $i => $row)
542
	{
543
		$context['reported_posts'][] = array(
544
			'id' => $row['id_report'],
545
			'topic_href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'],
546
			'report_href' => $scripturl . '?action=moderate;area=reportedposts;sa=details;rid=' . $row['id_report'],
547
			'report_link' => '<a href="' . $scripturl . '?action=moderate;area=reportedposts;sa=details;rid=' . $row['id_report'] . '">' . $row['subject'] . '</a>',
548
			'author' => array(
549
				'id' => $row['id_author'],
550
				'name' => $row['author_name'],
551
				'link' => $row['id_author'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_author'] . '">' . $row['author_name'] . '</a>' : $row['author_name'],
552
				'href' => $scripturl . '?action=profile;u=' . $row['id_author'],
553
			),
554
			'subject' => $row['subject'],
555
			'num_reports' => $row['num_reports'],
556
		);
557
	}
558
559
	return 'reported_posts_block';
560
}
561
562
/**
563
 * Show a list of all the group requests they can see.
564
 */
565
function ModBlockGroupRequests()
566
{
567
	global $context, $user_info, $scripturl, $smcFunc;
568
569
	$context['group_requests'] = array();
570
	// Make sure they can even moderate someone!
571
	if ($user_info['mod_cache']['gq'] == '0=1')
572
		return 'group_requests_block';
573
574
	// What requests are outstanding?
575
	$request = $smcFunc['db_query']('', '
576
		SELECT lgr.id_request, lgr.id_member, lgr.id_group, lgr.time_applied, mem.member_name, mg.group_name, mem.real_name
577
		FROM {db_prefix}log_group_requests AS lgr
578
			INNER JOIN {db_prefix}members AS mem ON (mem.id_member = lgr.id_member)
579
			INNER JOIN {db_prefix}membergroups AS mg ON (mg.id_group = lgr.id_group)
580
		WHERE ' . ($user_info['mod_cache']['gq'] == '1=1' || $user_info['mod_cache']['gq'] == '0=1' ? $user_info['mod_cache']['gq'] : 'lgr.' . $user_info['mod_cache']['gq']) . '
581
			AND lgr.status = {int:status_open}
582
		ORDER BY lgr.id_request DESC
583
		LIMIT 10',
584
		array(
585
			'status_open' => 0,
586
		)
587
	);
588
	for ($i = 0; $row = $smcFunc['db_fetch_assoc']($request); $i ++)
589
	{
590
		$context['group_requests'][] = array(
591
			'id' => $row['id_request'],
592
			'request_href' => $scripturl . '?action=groups;sa=requests;gid=' . $row['id_group'],
593
			'member' => array(
594
				'id' => $row['id_member'],
595
				'name' => $row['real_name'],
596
				'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>',
597
				'href' => $scripturl . '?action=profile;u=' . $row['id_member'],
598
			),
599
			'group' => array(
600
				'id' => $row['id_group'],
601
				'name' => $row['group_name'],
602
			),
603
			'time_submitted' => timeformat($row['time_applied']),
604
		);
605
	}
606
	$smcFunc['db_free_result']($request);
607
608
	return 'group_requests_block';
609
}
610
611
/**
612
 * Show a list of the most recent reported posts.
613
 */
614
function ModBlockReportedMembers()
615
{
616
	global $context, $scripturl, $smcFunc;
617
618
	// Got the info already?
619
	$cachekey = md5(json_encode((int) allowedTo('moderate_forum')));
620
	$context['reported_users'] = array();
621
	if (!allowedTo('moderate_forum'))
622
		return 'reported_users_block';
623
624
	if (($reported_users = cache_get_data('reported_users_' . $cachekey, 90)) === null)
625
	{
626
		// By George, that means we in a position to get the reports, jolly good.
627
		$request = $smcFunc['db_query']('', '
628
			SELECT lr.id_report, lr.id_member,
629
				lr.num_reports, COALESCE(mem.real_name, lr.membername) AS user_name,
630
				COALESCE(mem.id_member, 0) AS id_user
631
			FROM {db_prefix}log_reported AS lr
632
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lr.id_member)
633
			WHERE lr.id_board = {int:not_a_reported_post}
634
				AND lr.closed = {int:not_closed}
635
				AND lr.ignore_all = {int:not_ignored}
636
			ORDER BY lr.time_updated DESC
637
			LIMIT 10',
638
			array(
639
				'not_a_reported_post' => 0,
640
				'not_closed' => 0,
641
				'not_ignored' => 0,
642
			)
643
		);
644
		$reported_users = array();
645
		while ($row = $smcFunc['db_fetch_assoc']($request))
646
			$reported_users[] = $row;
647
		$smcFunc['db_free_result']($request);
648
649
		// Cache it.
650
		cache_put_data('reported_users_' . $cachekey, $reported_users, 90);
651
	}
652
653
	$context['reported_users'] = array();
654
	foreach ($reported_users as $i => $row)
655
	{
656
		$context['reported_users'][] = array(
657
			'id' => $row['id_report'],
658
			'report_href' => $scripturl . '?action=moderate;area=reportedmembers;report=' . $row['id_report'],
659
			'user' => array(
660
				'id' => $row['id_user'],
661
				'name' => $row['user_name'],
662
				'link' => $row['id_user'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_user'] . '">' . $row['user_name'] . '</a>' : $row['user_name'],
663
				'href' => $scripturl . '?action=profile;u=' . $row['id_user'],
664
			),
665
			'num_reports' => $row['num_reports'],
666
		);
667
	}
668
669
	return 'reported_users_block';
670
}
671
672
/**
673
 * Browse all the reported users...
674
 */
675
function ReportedMembers()
676
{
677
	global $txt, $context, $scripturl, $smcFunc;
678
679
	loadTemplate('ModerationCenter');
680
681
	// Set an empty var for the server response.
682
	$context['report_member_action'] = '';
683
684
	// Put the open and closed options into tabs, because we can...
685
	$context[$context['moderation_menu_name']]['tab_data'] = array(
686
		'title' => $txt['mc_reported_members'],
687
		'help' => '',
688
		'description' => $txt['mc_reported_members_desc'],
689
	);
690
691
	isAllowedTo('moderate_forum');
692
693
	// Are they wanting to view a particular report?
694
	if (!empty($_REQUEST['report']))
695
		return MemberReport();
696
697
	// Set up the comforting bits...
698
	$context['page_title'] = $txt['mc_reported_members'];
699
	$context['sub_template'] = 'reported_members';
700
701
	// Are we viewing open or closed reports?
702
	$context['view_closed'] = isset($_GET['sa']) && $_GET['sa'] == 'closed' ? 1 : 0;
703
704
	// Are we doing any work?
705
	if ((isset($_GET['ignore']) || isset($_GET['close'])) && isset($_GET['rid']))
706
	{
707
		checkSession('get');
708
		$_GET['rid'] = (int) $_GET['rid'];
709
710
		// Update the report...
711
		$smcFunc['db_query']('', '
712
			UPDATE {db_prefix}log_reported
713
			SET ' . (isset($_GET['ignore']) ? 'ignore_all = {int:ignore_all}' : 'closed = {int:closed}') . '
714
			WHERE id_report = {int:id_report}',
715
			array(
716
				'ignore_all' => isset($_GET['ignore']) ? (int) $_GET['ignore'] : 0,
717
				'closed' => isset($_GET['close']) ? (int) $_GET['close'] : 0,
718
				'id_report' => $_GET['rid'],
719
			)
720
		);
721
722
		// Get the board, topic and message for this report
723
		$request = $smcFunc['db_query']('', '
724
			SELECT id_member, membername
725
			FROM {db_prefix}log_reported
726
			WHERE id_report = {int:id_report}',
727
			array(
728
				'id_report' => $_GET['rid'],
729
			)
730
		);
731
732
		// Set up the data for the log...
733
		$extra = array('report' => $_GET['rid']);
734
		list($extra['member'], $extra['membername']) = $smcFunc['db_fetch_row']($request);
735
		$smcFunc['db_free_result']($request);
736
737
		// Stick this in string format for consistency
738
		$extra['member'] = (string)$extra['member'];
739
740
		// Tell the user about it.
741
		$context['report_member_action'] = isset($_GET['ignore']) ? (!empty($_GET['ignore']) ? 'ignore' : 'unignore') : (!empty($_GET['close']) ? 'close' : 'open');
742
743
		// Log this action
744
		logAction($context['report_member_action'] . '_user_report', $extra);
745
746
		// Time to update.
747
		updateSettings(array('last_mod_report_action' => time()));
748
		recountOpenReports('members');
749
	}
750
	elseif (isset($_POST['close']) && isset($_POST['close_selected']))
751
	{
752
		checkSession();
753
754
		// All the ones to update...
755
		$toClose = array();
756
		foreach ($_POST['close'] as $rid)
757
			$toClose[] = (int) $rid;
758
759
		if (!empty($toClose))
760
		{
761
			// Get the data for each of these reports
762
			$request = $smcFunc['db_query']('', '
763
				SELECT id_report, id_member, membername
764
				FROM {db_prefix}log_reported
765
				WHERE id_report IN ({array_int:report_list})',
766
				array(
767
					'report_list' => $toClose,
768
				)
769
			);
770
771
			$logs = array();
772
			while ($reports = $smcFunc['db_fetch_assoc']($request))
773
			{
774
				$logs[] = array(
775
					'action' => 'close_user_report',
776
					'log_type' => 'moderate',
777
					'extra' => array(
778
						'report' => $reports['id_report'],
779
						'membername' => $reports['membername'],
780
						'member' => (string)$reports['id_member'],
781
					),
782
				);
783
			}
784
785
			$smcFunc['db_free_result']($request);
786
787
			// Log the closing of all the reports
788
			logActions($logs);
789
790
			$smcFunc['db_query']('', '
791
				UPDATE {db_prefix}log_reported
792
				SET closed = {int:is_closed}
793
				WHERE id_report IN ({array_int:report_list})',
794
				array(
795
					'report_list' => $toClose,
796
					'is_closed' => 1,
797
				)
798
			);
799
800
			// Time to update.
801
			updateSettings(array('last_mod_report_action' => time()));
802
			recountOpenReports('members');
803
		}
804
805
		// Go on and tell the result.
806
		$context['report_member_action'] = 'close_all';
807
	}
808
809
	// How many entries are we viewing?
810
	$request = $smcFunc['db_query']('', '
811
		SELECT COUNT(*)
812
		FROM {db_prefix}log_reported AS lr
813
		WHERE lr.closed = {int:view_closed}
814
			AND lr.id_board = {int:not_a_reported_post}',
815
		array(
816
			'view_closed' => $context['view_closed'],
817
			'not_a_reported_post' => 0,
818
		)
819
	);
820
	list ($context['total_reports']) = $smcFunc['db_fetch_row']($request);
821
	$smcFunc['db_free_result']($request);
822
823
	// So, that means we can page index, yes?
824
	$context['page_index'] = constructPageIndex($scripturl . '?action=moderate;area=reportedmembers' . ($context['view_closed'] ? ';sa=closed' : ''), $_GET['start'], $context['total_reports'], 10);
825
	$context['start'] = $_GET['start'];
826
827
	// By George, that means we in a position to get the reports, golly good.
828
	$request = $smcFunc['db_query']('', '
829
		SELECT lr.id_report, lr.id_member, lr.time_started, lr.time_updated, lr.num_reports, lr.closed, lr.ignore_all,
830
			COALESCE(mem.real_name, lr.membername) AS user_name, COALESCE(mem.id_member, 0) AS id_user
831
		FROM {db_prefix}log_reported AS lr
832
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lr.id_member)
833
		WHERE lr.closed = {int:view_closed}
834
			AND lr.id_board = {int:not_a_reported_post}
835
		ORDER BY lr.time_updated DESC
836
		LIMIT {int:limit}, {int:max}',
837
		array(
838
			'view_closed' => $context['view_closed'],
839
			'not_a_reported_post' => 0,
840
			'limit' => $context['start'],
841
			'max' => 10,
842
		)
843
	);
844
	$context['reports'] = array();
845
	$report_ids = array();
846
	for ($i = 0; $row = $smcFunc['db_fetch_assoc']($request); $i++)
847
	{
848
		$report_ids[] = $row['id_report'];
849
		$context['reports'][$row['id_report']] = array(
850
			'id' => $row['id_report'],
851
			'report_href' => $scripturl . '?action=moderate;area=reportedmembers;report=' . $row['id_report'],
852
			'user' => array(
853
				'id' => $row['id_user'],
854
				'name' => $row['user_name'],
855
				'link' => $row['id_user'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_user'] . '">' . $row['user_name'] . '</a>' : $row['user_name'],
856
				'href' => $scripturl . '?action=profile;u=' . $row['id_user'],
857
			),
858
			'comments' => array(),
859
			'time_started' => timeformat($row['time_started']),
860
			'last_updated' => timeformat($row['time_updated']),
861
			'num_reports' => $row['num_reports'],
862
			'closed' => $row['closed'],
863
			'ignore' => $row['ignore_all']
864
		);
865
	}
866
	$smcFunc['db_free_result']($request);
867
868
	// Now get all the people who reported it.
869 View Code Duplication
	if (!empty($report_ids))
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...
870
	{
871
		$request = $smcFunc['db_query']('', '
872
			SELECT lrc.id_comment, lrc.id_report, lrc.time_sent, lrc.comment,
873
				COALESCE(mem.id_member, 0) AS id_member, COALESCE(mem.real_name, lrc.membername) AS reporter
874
			FROM {db_prefix}log_reported_comments AS lrc
875
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lrc.id_member)
876
			WHERE lrc.id_report IN ({array_int:report_list})',
877
			array(
878
				'report_list' => $report_ids,
879
			)
880
		);
881
		while ($row = $smcFunc['db_fetch_assoc']($request))
882
		{
883
			$context['reports'][$row['id_report']]['comments'][] = array(
884
				'id' => $row['id_comment'],
885
				'message' => $row['comment'],
886
				'time' => timeformat($row['time_sent']),
887
				'member' => array(
888
					'id' => $row['id_member'],
889
					'name' => empty($row['reporter']) ? $txt['guest'] : $row['reporter'],
890
					'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['reporter'] . '</a>' : (empty($row['reporter']) ? $txt['guest'] : $row['reporter']),
891
					'href' => $row['id_member'] ? $scripturl . '?action=profile;u=' . $row['id_member'] : '',
892
				),
893
			);
894
		}
895
		$smcFunc['db_free_result']($request);
896
	}
897
898
	$context['report_manage_bans'] = allowedTo('manage_bans');
899
}
900
901
/**
902
 * Act as an entrace for all group related activity.
903
 * @todo As for most things in this file, this needs to be moved somewhere appropriate?
904
 */
905
function ModerateGroups()
906
{
907
	global $context, $user_info;
908
909
	// You need to be allowed to moderate groups...
910
	if ($user_info['mod_cache']['gq'] == '0=1')
911
		isAllowedTo('manage_membergroups');
912
913
	// Load the group templates.
914
	loadTemplate('ModerationCenter');
915
916
	// Setup the subactions...
917
	$subActions = array(
918
		'requests' => 'GroupRequests',
919
		'view' => 'ViewGroups',
920
	);
921
922
	if (!isset($_GET['sa']) || !isset($subActions[$_GET['sa']]))
923
		$_GET['sa'] = 'view';
924
	$context['sub_action'] = $_GET['sa'];
925
926
	// Call the relevant function.
927
	call_helper($subActions[$context['sub_action']]);
928
}
929
930
/**
931
 * Show a notice sent to a user.
932
 */
933
function ShowNotice()
934
{
935
	global $smcFunc, $txt, $context;
936
937
	$context['page_title'] = $txt['show_notice'];
938
	$context['sub_template'] = 'show_notice';
939
	$context['template_layers'] = array();
940
941
	loadTemplate('ModerationCenter');
942
943
	// @todo Assumes nothing needs permission more than accessing moderation center!
944
	$id_notice = (int) $_GET['nid'];
945
	$request = $smcFunc['db_query']('', '
946
		SELECT body, subject
947
		FROM {db_prefix}log_member_notices
948
		WHERE id_notice = {int:id_notice}',
949
		array(
950
			'id_notice' => $id_notice,
951
		)
952
	);
953
	if ($smcFunc['db_num_rows']($request) == 0)
954
		fatal_lang_error('no_access', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
955
	list ($context['notice_body'], $context['notice_subject']) = $smcFunc['db_fetch_row']($request);
956
	$smcFunc['db_free_result']($request);
957
958
	$context['notice_body'] = parse_bbc($context['notice_body'], false);
959
}
960
961
/**
962
 * View watched users.
963
 */
964
function ViewWatchedUsers()
965
{
966
	global $modSettings, $context, $txt, $scripturl, $sourcedir;
967
968
	// Some important context!
969
	$context['page_title'] = $txt['mc_watched_users_title'];
970
	$context['view_posts'] = isset($_GET['sa']) && $_GET['sa'] == 'post';
971
	$context['start'] = isset($_REQUEST['start']) ? (int) $_REQUEST['start'] : 0;
972
973
	loadTemplate('ModerationCenter');
974
975
	// Get some key settings!
976
	$modSettings['warning_watch'] = empty($modSettings['warning_watch']) ? 1 : $modSettings['warning_watch'];
977
978
	// Put some pretty tabs on cause we're gonna be doing hot stuff here...
979
	$context[$context['moderation_menu_name']]['tab_data'] = array(
980
		'title' => $txt['mc_watched_users_title'],
981
		'help' => '',
982
		'description' => $txt['mc_watched_users_desc'],
983
	);
984
985
	// First off - are we deleting?
986
	if (!empty($_REQUEST['delete']))
987
	{
988
		checkSession(!is_array($_REQUEST['delete']) ? 'get' : 'post');
989
990
		$toDelete = array();
991
		if (!is_array($_REQUEST['delete']))
992
			$toDelete[] = (int) $_REQUEST['delete'];
993
		else
994
			foreach ($_REQUEST['delete'] as $did)
995
				$toDelete[] = (int) $did;
996
997
		if (!empty($toDelete))
998
		{
999
			require_once($sourcedir . '/RemoveTopic.php');
1000
			// If they don't have permission we'll let it error - either way no chance of a security slip here!
1001
			foreach ($toDelete as $did)
1002
				removeMessage($did);
1003
		}
1004
	}
1005
1006
	// Start preparing the list by grabbing relevant permissions.
1007
	if (!$context['view_posts'])
1008
	{
1009
		$approve_query = '';
1010
		$delete_boards = array();
1011
	}
1012
	else
1013
	{
1014
		// Still obey permissions!
1015
		$approve_boards = boardsAllowedTo('approve_posts');
1016
		$delete_boards = boardsAllowedTo('delete_any');
1017
1018 View Code Duplication
		if ($approve_boards == array(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...
1019
			$approve_query = '';
1020
		elseif (!empty($approve_boards))
1021
			$approve_query = ' AND m.id_board IN (' . implode(',', $approve_boards) . ')';
1022
		// Nada, zip, etc...
1023
		else
1024
			$approve_query = ' AND 1=0';
1025
	}
1026
1027
	require_once($sourcedir . '/Subs-List.php');
1028
1029
	// This is all the information required for a watched user listing.
1030
	$listOptions = array(
1031
		'id' => 'watch_user_list',
1032
		'title' => $txt['mc_watched_users_title'] . ' - ' . ($context['view_posts'] ? $txt['mc_watched_users_post'] : $txt['mc_watched_users_member']),
1033
		'width' => '100%',
1034
		'items_per_page' => $modSettings['defaultMaxListItems'],
1035
		'no_items_label' => $context['view_posts'] ? $txt['mc_watched_users_no_posts'] : $txt['mc_watched_users_none'],
1036
		'base_href' => $scripturl . '?action=moderate;area=userwatch;sa=' . ($context['view_posts'] ? 'post' : 'member'),
1037
		'default_sort_col' => $context['view_posts'] ? '' : 'member',
1038
		'get_items' => array(
1039
			'function' => $context['view_posts'] ? 'list_getWatchedUserPosts' : 'list_getWatchedUsers',
1040
			'params' => array(
1041
				$approve_query,
1042
				$delete_boards,
1043
			),
1044
		),
1045
		'get_count' => array(
1046
			'function' => $context['view_posts'] ? 'list_getWatchedUserPostsCount' : 'list_getWatchedUserCount',
1047
			'params' => array(
1048
				$approve_query,
1049
			),
1050
		),
1051
		// This assumes we are viewing by user.
1052
		'columns' => array(
1053
			'member' => array(
1054
				'header' => array(
1055
					'value' => $txt['mc_watched_users_member'],
1056
				),
1057
				'data' => array(
1058
					'sprintf' => array(
1059
						'format' => '<a href="' . $scripturl . '?action=profile;u=%1$d">%2$s</a>',
1060
						'params' => array(
1061
							'id' => false,
1062
							'name' => false,
1063
						),
1064
					),
1065
				),
1066
				'sort' => array(
1067
					'default' => 'real_name',
1068
					'reverse' => 'real_name DESC',
1069
				),
1070
			),
1071
			'warning' => array(
1072
				'header' => array(
1073
					'value' => $txt['mc_watched_users_warning'],
1074
				),
1075
				'data' => array(
1076
					'function' => function ($member) use ($scripturl)
1077
					{
1078
						return allowedTo('issue_warning') ? '<a href="' . $scripturl . '?action=profile;area=issuewarning;u=' . $member['id'] . '">' . $member['warning'] . '%</a>' : $member['warning'] . '%';
1079
					},
1080
				),
1081
				'sort' => array(
1082
					'default' => 'warning',
1083
					'reverse' => 'warning DESC',
1084
				),
1085
			),
1086
			'posts' => array(
1087
				'header' => array(
1088
					'value' => $txt['posts'],
1089
				),
1090
				'data' => array(
1091
					'sprintf' => array(
1092
						'format' => '<a href="' . $scripturl . '?action=profile;u=%1$d;area=showposts;sa=messages">%2$s</a>',
1093
						'params' => array(
1094
							'id' => false,
1095
							'posts' => false,
1096
						),
1097
					),
1098
				),
1099
				'sort' => array(
1100
					'default' => 'posts',
1101
					'reverse' => 'posts DESC',
1102
				),
1103
			),
1104
			'last_login' => array(
1105
				'header' => array(
1106
					'value' => $txt['mc_watched_users_last_login'],
1107
				),
1108
				'data' => array(
1109
					'db' => 'last_login',
1110
				),
1111
				'sort' => array(
1112
					'default' => 'last_login',
1113
					'reverse' => 'last_login DESC',
1114
				),
1115
			),
1116
			'last_post' => array(
1117
				'header' => array(
1118
					'value' => $txt['mc_watched_users_last_post'],
1119
				),
1120
				'data' => array(
1121
					'function' => function ($member) use ($scripturl)
1122
					{
1123
						if ($member['last_post_id'])
1124
							return '<a href="' . $scripturl . '?msg=' . $member['last_post_id'] . '">' . $member['last_post'] . '</a>';
1125
						else
1126
							return $member['last_post'];
1127
					},
1128
				),
1129
			),
1130
		),
1131
		'form' => array(
1132
			'href' => $scripturl . '?action=moderate;area=userwatch;sa=post',
1133
			'include_sort' => true,
1134
			'include_start' => true,
1135
			'hidden_fields' => array(
1136
				$context['session_var'] => $context['session_id'],
1137
			),
1138
		),
1139
		'additional_rows' => array(
1140
			$context['view_posts'] ?
1141
			array(
1142
				'position' => 'bottom_of_list',
1143
				'value' => '
1144
					<input type="submit" name="delete_selected" value="' . $txt['quickmod_delete_selected'] . '" class="button_submit">',
1145
				'class' => 'floatright',
1146
			) : array(),
1147
		),
1148
	);
1149
1150
	// If this is being viewed by posts we actually change the columns to call a template each time.
1151
	if ($context['view_posts'])
1152
	{
1153
		$listOptions['columns'] = array(
1154
			'posts' => array(
1155
				'data' => array(
1156
					'function' => function ($post)
1157
					{
1158
						return template_user_watch_post_callback($post);
1159
					},
1160
				),
1161
			),
1162
		);
1163
	}
1164
1165
	// Create the watched user list.
1166
	createList($listOptions);
1167
1168
	$context['sub_template'] = 'show_list';
1169
	$context['default_list'] = 'watch_user_list';
1170
}
1171
1172
/**
1173
 * Callback for createList().
1174
 * @param string $approve_query Not used here
1175
 * @return int The number of users on the watch list
1176
 */
1177 View Code Duplication
function list_getWatchedUserCount($approve_query)
0 ignored issues
show
Unused Code introduced by
The parameter $approve_query is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This function seems to be duplicated in 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...
1178
{
1179
	global $smcFunc, $modSettings;
1180
1181
	$request = $smcFunc['db_query']('', '
1182
		SELECT COUNT(*)
1183
		FROM {db_prefix}members
1184
		WHERE warning >= {int:warning_watch}',
1185
		array(
1186
			'warning_watch' => $modSettings['warning_watch'],
1187
		)
1188
	);
1189
	list ($totalMembers) = $smcFunc['db_fetch_row']($request);
1190
	$smcFunc['db_free_result']($request);
1191
1192
	return $totalMembers;
1193
}
1194
1195
/**
1196
 * Callback for createList().
1197
 *
1198
 * @param int $start The item to start with (for pagination purposes)
1199
 * @param int $items_per_page The number of items to show per page
1200
 * @param string $sort A string indicating how to sort things
1201
 * @param string $approve_query A query for approving things. Not used here.
1202
 * @param string $dummy Not used here.
1203
 */
1204
function list_getWatchedUsers($start, $items_per_page, $sort, $approve_query, $dummy)
0 ignored issues
show
Unused Code introduced by
The parameter $approve_query is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $dummy is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1205
{
1206
	global $smcFunc, $txt, $modSettings, $user_info;
1207
1208
	$request = $smcFunc['db_query']('', '
1209
		SELECT id_member, real_name, last_login, posts, warning
1210
		FROM {db_prefix}members
1211
		WHERE warning >= {int:warning_watch}
1212
		ORDER BY {raw:sort}
1213
		LIMIT {int:start}, {int:max}',
1214
		array(
1215
			'warning_watch' => $modSettings['warning_watch'],
1216
			'sort' => $sort,
1217
			'start' => $start,
1218
			'max' => $items_per_page,
1219
		)
1220
	);
1221
	$watched_users = array();
1222
	$members = array();
1223
	while ($row = $smcFunc['db_fetch_assoc']($request))
1224
	{
1225
		$watched_users[$row['id_member']] = array(
1226
			'id' => $row['id_member'],
1227
			'name' => $row['real_name'],
1228
			'last_login' => $row['last_login'] ? timeformat($row['last_login']) : $txt['never'],
1229
			'last_post' => $txt['not_applicable'],
1230
			'last_post_id' => 0,
1231
			'warning' => $row['warning'],
1232
			'posts' => $row['posts'],
1233
		);
1234
		$members[] = $row['id_member'];
1235
	}
1236
	$smcFunc['db_free_result']($request);
1237
1238
	if (!empty($members))
1239
	{
1240
		// First get the latest messages from these users.
1241
		$request = $smcFunc['db_query']('', '
1242
			SELECT m.id_member, MAX(m.id_msg) AS last_post_id
1243
			FROM {db_prefix}messages AS m' . ($user_info['query_see_board'] == '1=1' ? '' : '
1244
				INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board AND {query_see_board})') . '
1245
			WHERE m.id_member IN ({array_int:member_list})' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : '
1246
				AND m.approved = {int:is_approved}') . '
1247
			GROUP BY m.id_member',
1248
			array(
1249
				'member_list' => $members,
1250
				'is_approved' => 1,
1251
			)
1252
		);
1253
		$latest_posts = array();
1254
		while ($row = $smcFunc['db_fetch_assoc']($request))
1255
			$latest_posts[$row['id_member']] = $row['last_post_id'];
1256
1257
		if (!empty($latest_posts))
1258
		{
1259
			// Now get the time those messages were posted.
1260
			$request = $smcFunc['db_query']('', '
1261
				SELECT id_member, poster_time
1262
				FROM {db_prefix}messages
1263
				WHERE id_msg IN ({array_int:message_list})',
1264
				array(
1265
					'message_list' => $latest_posts,
1266
				)
1267
			);
1268
			while ($row = $smcFunc['db_fetch_assoc']($request))
1269
			{
1270
				$watched_users[$row['id_member']]['last_post'] = timeformat($row['poster_time']);
1271
				$watched_users[$row['id_member']]['last_post_id'] = $latest_posts[$row['id_member']];
1272
			}
1273
1274
			$smcFunc['db_free_result']($request);
1275
		}
1276
1277
		$request = $smcFunc['db_query']('', '
1278
			SELECT MAX(m.poster_time) AS last_post, MAX(m.id_msg) AS last_post_id, m.id_member
1279
			FROM {db_prefix}messages AS m' . ($user_info['query_see_board'] == '1=1' ? '' : '
1280
				INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board AND {query_see_board})') . '
1281
			WHERE m.id_member IN ({array_int:member_list})' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : '
1282
				AND m.approved = {int:is_approved}') . '
1283
			GROUP BY m.id_member',
1284
			array(
1285
				'member_list' => $members,
1286
				'is_approved' => 1,
1287
			)
1288
		);
1289
		while ($row = $smcFunc['db_fetch_assoc']($request))
1290
		{
1291
			$watched_users[$row['id_member']]['last_post'] = timeformat($row['last_post']);
1292
			$watched_users[$row['id_member']]['last_post_id'] = $row['last_post_id'];
1293
		}
1294
		$smcFunc['db_free_result']($request);
1295
	}
1296
1297
	return $watched_users;
1298
}
1299
1300
/**
1301
 * Callback for createList().
1302
 *
1303
 * @param string $approve_query A query to pull only approved items
1304
 * @return int The total number of posts by watched users
1305
 */
1306 View Code Duplication
function list_getWatchedUserPostsCount($approve_query)
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in 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...
1307
{
1308
	global $smcFunc, $modSettings;
1309
1310
	$request = $smcFunc['db_query']('', '
1311
		SELECT COUNT(*)
1312
			FROM {db_prefix}messages AS m
1313
				INNER JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
1314
				INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
1315
			WHERE mem.warning >= {int:warning_watch}
1316
				AND {query_see_board}
1317
				' . $approve_query,
1318
		array(
1319
			'warning_watch' => $modSettings['warning_watch'],
1320
		)
1321
	);
1322
	list ($totalMemberPosts) = $smcFunc['db_fetch_row']($request);
1323
	$smcFunc['db_free_result']($request);
1324
1325
	return $totalMemberPosts;
1326
}
1327
1328
/**
1329
 * Callback for createList().
1330
 *
1331
 * @param int $start The item to start with (for pagination purposes)
1332
 * @param int $items_per_page The number of items to show per page
1333
 * @param string $sort A string indicating how to sort the results (not used here)
1334
 * @param string $approve_query A query to only pull approved items
1335
 * @param int[] $delete_boards An array containing the IDs of boards we can delete posts in
1336
 * @return array An array of info about posts by watched users
1337
 */
1338
function list_getWatchedUserPosts($start, $items_per_page, $sort, $approve_query, $delete_boards)
0 ignored issues
show
Unused Code introduced by
The parameter $sort is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1339
{
1340
	global $smcFunc, $scripturl, $modSettings;
1341
1342
	$request = $smcFunc['db_query']('', '
1343
		SELECT m.id_msg, m.id_topic, m.id_board, m.id_member, m.subject, m.body, m.poster_time,
1344
			m.approved, mem.real_name, m.smileys_enabled
1345
		FROM {db_prefix}messages AS m
1346
			INNER JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
1347
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
1348
		WHERE mem.warning >= {int:warning_watch}
1349
			AND {query_see_board}
1350
			' . $approve_query . '
1351
		ORDER BY m.id_msg DESC
1352
		LIMIT {int:start}, {int:max}',
1353
		array(
1354
			'warning_watch' => $modSettings['warning_watch'],
1355
			'start' => $start,
1356
			'max' => $items_per_page,
1357
		)
1358
	);
1359
	$member_posts = array();
1360
	while ($row = $smcFunc['db_fetch_assoc']($request))
1361
	{
1362
		$row['subject'] = censorText($row['subject']);
1363
		$row['body'] = censorText($row['body']);
1364
1365
		$member_posts[$row['id_msg']] = array(
1366
			'id' => $row['id_msg'],
1367
			'id_topic' => $row['id_topic'],
1368
			'author_link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>',
1369
			'subject' => $row['subject'],
1370
			'body' => parse_bbc($row['body'], $row['smileys_enabled'], $row['id_msg']),
1371
			'poster_time' => timeformat($row['poster_time']),
1372
			'approved' => $row['approved'],
1373
			'can_delete' => $delete_boards == array(0) || in_array($row['id_board'], $delete_boards),
1374
		);
1375
	}
1376
	$smcFunc['db_free_result']($request);
1377
1378
	return $member_posts;
1379
}
1380
1381
/**
1382
 * Entry point for viewing warning related stuff.
1383
 */
1384
function ViewWarnings()
1385
{
1386
	global $context, $txt;
1387
1388
	$subActions = array(
1389
		'log' => array('ViewWarningLog'),
1390
		'templateedit' => array('ModifyWarningTemplate', 'issue_warning'),
1391
		'templates' => array('ViewWarningTemplates', 'issue_warning'),
1392
	);
1393
1394
	call_integration_hook('integrate_warning_log_actions', array(&$subActions));
1395
1396
	$_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) && (empty($subActions[$_REQUEST['sa']][1]) || allowedTo($subActions[$_REQUEST['sa']]))? $_REQUEST['sa'] : 'log';
1397
1398
	// Some of this stuff is overseas, so to speak.
1399
	loadTemplate('ModerationCenter');
1400
	loadLanguage('Profile');
1401
1402
	// Setup the admin tabs.
1403
	$context[$context['moderation_menu_name']]['tab_data'] = array(
1404
		'title' => $txt['mc_warnings'],
1405
		'description' => $txt['mc_warnings_description'],
1406
	);
1407
1408
	// Call the right function.
1409
	call_helper($subActions[$_REQUEST['sa']][0]);
1410
}
1411
1412
/**
1413
 * Simply put, look at the warning log!
1414
 */
1415
function ViewWarningLog()
1416
{
1417
	global $smcFunc, $modSettings, $context, $txt, $scripturl, $sourcedir;
1418
1419
	// Setup context as always.
1420
	$context['page_title'] = $txt['mc_warning_log_title'];
1421
1422
	loadLanguage('Modlog');
1423
1424
	// If we're coming from a search, get the variables.
1425 View Code Duplication
	if (!empty($_REQUEST['params']) && empty($_REQUEST['is_search']))
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...
1426
	{
1427
		$search_params = base64_decode(strtr($_REQUEST['params'], array(' ' => '+')));
1428
		$search_params = smf_json_decode($search_params, true);
1429
	}
1430
1431
	// This array houses all the valid search types.
1432
	$searchTypes = array(
1433
		'member' => array('sql' => 'member_name_col', 'label' => $txt['profile_warning_previous_issued']),
1434
		'recipient' => array('sql' => 'recipient_name', 'label' => $txt['mc_warnings_recipient']),
1435
	);
1436
1437
	// Do the column stuff!
1438
	$sort_types = array(
1439
		'member' => 'member_name_col',
1440
		'recipient' => 'recipient_name',
1441
	);
1442
1443
	// Setup the direction stuff...
1444
	$context['order'] = isset($_REQUEST['sort']) && isset($sort_types[$_REQUEST['sort']]) ? $_REQUEST['sort'] : 'member';
1445
1446
	if (!isset($search_params['string']) || (!empty($_REQUEST['search']) && $search_params['string'] != $_REQUEST['search']))
1447
		$search_params_string = empty($_REQUEST['search']) ? '' : $_REQUEST['search'];
1448
	else
1449
		$search_params_string = $search_params['string'];
1450
1451 View Code Duplication
	if (isset($_REQUEST['search_type']) || empty($search_params['type']) || !isset($searchTypes[$search_params['type']]))
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...
1452
		$search_params_type = isset($_REQUEST['search_type']) && isset($searchTypes[$_REQUEST['search_type']]) ? $_REQUEST['search_type'] : (isset($searchTypes[$context['order']]) ? $context['order'] : 'member');
1453
	else
1454
		$search_params_type = $search_params['type'];
1455
1456
	$search_params_column = $searchTypes[$search_params_type]['sql'];
0 ignored issues
show
Unused Code introduced by
$search_params_column is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1457
	$search_params = array(
1458
		'string' => $search_params_string,
1459
		'type' => $search_params_type,
1460
	);
1461
1462
	$context['url_start'] = '?action=moderate;area=warnings;sa=log;sort='.  $context['order'];
1463
1464
	// Setup the search context.
1465
	$context['search_params'] = empty($search_params['string']) ? '' : base64_encode(json_encode($search_params));
1466
	$context['search'] = array(
1467
		'string' => $search_params['string'],
1468
		'type' => $search_params['type'],
1469
		'label' => $searchTypes[$search_params_type]['label'],
1470
	);
1471
1472
	require_once($sourcedir . '/Subs-List.php');
1473
1474
	// This is all the information required for a watched user listing.
1475
	$listOptions = array(
1476
		'id' => 'warning_list',
1477
		'title' => $txt['mc_warning_log_title'],
1478
		'items_per_page' => $modSettings['defaultMaxListItems'],
1479
		'no_items_label' => $txt['mc_warnings_none'],
1480
		'base_href' => $scripturl . '?action=moderate;area=warnings;sa=log;' . $context['session_var'] . '=' . $context['session_id'],
1481
		'default_sort_col' => 'time',
1482
		'get_items' => array(
1483
			'function' => 'list_getWarnings',
1484
		),
1485
		'get_count' => array(
1486
			'function' => 'list_getWarningCount',
1487
		),
1488
		// This assumes we are viewing by user.
1489
		'columns' => array(
1490
			'issuer' => array(
1491
				'header' => array(
1492
					'value' => $txt['profile_warning_previous_issued'],
1493
				),
1494
				'data' => array(
1495
					'db' => 'issuer_link',
1496
				),
1497
				'sort' => array(
1498
					'default' => 'member_name_col',
1499
					'reverse' => 'member_name_col DESC',
1500
				),
1501
			),
1502
			'recipient' => array(
1503
				'header' => array(
1504
					'value' => $txt['mc_warnings_recipient'],
1505
				),
1506
				'data' => array(
1507
					'db' => 'recipient_link',
1508
				),
1509
				'sort' => array(
1510
					'default' => 'recipient_name',
1511
					'reverse' => 'recipient_name DESC',
1512
				),
1513
			),
1514
			'time' => array(
1515
				'header' => array(
1516
					'value' => $txt['profile_warning_previous_time'],
1517
				),
1518
				'data' => array(
1519
					'db' => 'time',
1520
				),
1521
				'sort' => array(
1522
					'default' => 'lc.log_time DESC',
1523
					'reverse' => 'lc.log_time',
1524
				),
1525
			),
1526
			'reason' => array(
1527
				'header' => array(
1528
					'value' => $txt['profile_warning_previous_reason'],
1529
				),
1530
				'data' => array(
1531 View Code Duplication
					'function' => function ($rowData) use ($scripturl, $txt)
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...
1532
					{
1533
						$output = '
1534
							<div class="floatleft">
1535
								' . $rowData['reason'] . '
1536
							</div>';
1537
1538
						if (!empty($rowData['id_notice']))
1539
							$output .= '
1540
								&nbsp;<a href="' . $scripturl . '?action=moderate;area=notice;nid=' . $rowData['id_notice'] . '" onclick="window.open(this.href, \'\', \'scrollbars=yes,resizable=yes,width=400,height=250\');return false;" target="_blank" class="new_win" title="' . $txt['profile_warning_previous_notice'] . '"><span class="generic_icons filter centericon"></span></a>';
1541
						return $output;
1542
					},
1543
				),
1544
			),
1545
			'points' => array(
1546
				'header' => array(
1547
					'value' => $txt['profile_warning_previous_level'],
1548
				),
1549
				'data' => array(
1550
					'db' => 'counter',
1551
				),
1552
			),
1553
		),
1554
		'form' => array(
1555
			'href' => $scripturl . $context['url_start'],
1556
			'include_sort' => true,
1557
			'include_start' => true,
1558
			'hidden_fields' => array(
1559
				$context['session_var'] => $context['session_id'],
1560
				'params' => false
1561
			),
1562
		),
1563
		'additional_rows' => array(
1564
			array(
1565
				'position' => 'below_table_data',
1566
				'value' => '
1567
					' . $txt['modlog_search'] .':
1568
					<input type="text" name="search" size="18" value="' . $smcFunc['htmlspecialchars']($context['search']['string']) . '" class="input_text">
1569
					<input type="submit" name="is_search" value="' . $txt['modlog_go'] . '" class="button_submit">',
1570
				'class' => 'floatright',
1571
			),
1572
		),
1573
	);
1574
1575
	// Create the watched user list.
1576
	createList($listOptions);
1577
1578
	$context['sub_template'] = 'show_list';
1579
	$context['default_list'] = 'warning_list';
1580
}
1581
1582
/**
1583
 * Callback for createList().
1584
 * @return int The total number of warnings that have been issued
1585
 */
1586
function list_getWarningCount()
1587
{
1588
	global $smcFunc;
1589
1590
	$request = $smcFunc['db_query']('', '
1591
		SELECT COUNT(*)
1592
		FROM {db_prefix}log_comments
1593
		WHERE comment_type = {string:warning}',
1594
		array(
1595
			'warning' => 'warning',
1596
		)
1597
	);
1598
	list ($totalWarns) = $smcFunc['db_fetch_row']($request);
1599
	$smcFunc['db_free_result']($request);
1600
1601
	return $totalWarns;
1602
}
1603
1604
/**
1605
 * Callback for createList().
1606
 *
1607
 * @param int $start The item to start with (for pagination purposes)
1608
 * @param int $items_per_page The number of items to show per page
1609
 * @param string $sort A string indicating how to sort the results
1610
 * @return array An array of data about warning log entries
1611
 */
1612
function list_getWarnings($start, $items_per_page, $sort)
1613
{
1614
	global $smcFunc, $scripturl;
1615
1616
	$request = $smcFunc['db_query']('', '
1617
		SELECT COALESCE(mem.id_member, 0) AS id_member, COALESCE(mem.real_name, lc.member_name) AS member_name_col,
1618
			COALESCE(mem2.id_member, 0) AS id_recipient, COALESCE(mem2.real_name, lc.recipient_name) AS recipient_name,
1619
			lc.log_time, lc.body, lc.id_notice, lc.counter
1620
		FROM {db_prefix}log_comments AS lc
1621
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lc.id_member)
1622
			LEFT JOIN {db_prefix}members AS mem2 ON (mem2.id_member = lc.id_recipient)
1623
		WHERE lc.comment_type = {string:warning}
1624
		ORDER BY {raw:sort}
1625
		LIMIT {int:start}, {int:max}',
1626
		array(
1627
			'warning' => 'warning',
1628
			'start' => $start,
1629
			'max' => $items_per_page,
1630
			'sort' => $sort,
1631
		)
1632
	);
1633
	$warnings = array();
1634
	while ($row = $smcFunc['db_fetch_assoc']($request))
1635
	{
1636
		$warnings[] = array(
1637
			'issuer_link' => $row['id_member'] ? ('<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['member_name_col'] . '</a>') : $row['member_name_col'],
1638
			'recipient_link' => $row['id_recipient'] ? ('<a href="' . $scripturl . '?action=profile;u=' . $row['id_recipient'] . '">' . $row['recipient_name'] . '</a>') : $row['recipient_name'],
1639
			'time' => timeformat($row['log_time']),
1640
			'reason' => $row['body'],
1641
			'counter' => $row['counter'] > 0 ? '+' . $row['counter'] : $row['counter'],
1642
			'id_notice' => $row['id_notice'],
1643
		);
1644
	}
1645
	$smcFunc['db_free_result']($request);
1646
1647
	return $warnings;
1648
}
1649
1650
/**
1651
 * Load all the warning templates.
1652
 */
1653
function ViewWarningTemplates()
1654
{
1655
	global $smcFunc, $modSettings, $context, $txt, $scripturl, $sourcedir, $user_info;
1656
1657
	// Submitting a new one?
1658
	if (isset($_POST['add']))
1659
		return ModifyWarningTemplate();
1660
	elseif (isset($_POST['delete']) && !empty($_POST['deltpl']))
1661
	{
1662
		checkSession();
1663
		validateToken('mod-wt');
1664
1665
		// Log the actions.
1666
		$request = $smcFunc['db_query']('', '
1667
			SELECT recipient_name
1668
			FROM {db_prefix}log_comments
1669
			WHERE id_comment IN ({array_int:delete_ids})
1670
				AND comment_type = {string:warntpl}
1671
				AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})',
1672
			array(
1673
				'delete_ids' => $_POST['deltpl'],
1674
				'warntpl' => 'warntpl',
1675
				'generic' => 0,
1676
				'current_member' => $user_info['id'],
1677
			)
1678
		);
1679
		while ($row = $smcFunc['db_fetch_assoc']($request))
1680
			logAction('delete_warn_template', array('template' => $row['recipient_name']));
1681
		$smcFunc['db_free_result']($request);
1682
1683
		// Do the deletes.
1684
		$smcFunc['db_query']('', '
1685
			DELETE FROM {db_prefix}log_comments
1686
			WHERE id_comment IN ({array_int:delete_ids})
1687
				AND comment_type = {string:warntpl}
1688
				AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})',
1689
			array(
1690
				'delete_ids' => $_POST['deltpl'],
1691
				'warntpl' => 'warntpl',
1692
				'generic' => 0,
1693
				'current_member' => $user_info['id'],
1694
			)
1695
		);
1696
	}
1697
1698
	// Setup context as always.
1699
	$context['page_title'] = $txt['mc_warning_templates_title'];
1700
1701
	require_once($sourcedir . '/Subs-List.php');
1702
1703
	// This is all the information required for a watched user listing.
1704
	$listOptions = array(
1705
		'id' => 'warning_template_list',
1706
		'title' => $txt['mc_warning_templates_title'],
1707
		'items_per_page' => $modSettings['defaultMaxListItems'],
1708
		'no_items_label' => $txt['mc_warning_templates_none'],
1709
		'base_href' => $scripturl . '?action=moderate;area=warnings;sa=templates;' . $context['session_var'] . '=' . $context['session_id'],
1710
		'default_sort_col' => 'title',
1711
		'get_items' => array(
1712
			'function' => 'list_getWarningTemplates',
1713
		),
1714
		'get_count' => array(
1715
			'function' => 'list_getWarningTemplateCount',
1716
		),
1717
		// This assumes we are viewing by user.
1718
		'columns' => array(
1719
			'title' => array(
1720
				'header' => array(
1721
					'value' => $txt['mc_warning_templates_name'],
1722
				),
1723
				'data' => array(
1724
					'sprintf' => array(
1725
						'format' => '<a href="' . $scripturl . '?action=moderate;area=warnings;sa=templateedit;tid=%1$d">%2$s</a>',
1726
						'params' => array(
1727
							'id_comment' => false,
1728
							'title' => false,
1729
							'body' => false,
1730
						),
1731
					),
1732
				),
1733
				'sort' => array(
1734
					'default' => 'template_title',
1735
					'reverse' => 'template_title DESC',
1736
				),
1737
			),
1738
			'creator' => array(
1739
				'header' => array(
1740
					'value' => $txt['mc_warning_templates_creator'],
1741
				),
1742
				'data' => array(
1743
					'db' => 'creator',
1744
				),
1745
				'sort' => array(
1746
					'default' => 'creator_name',
1747
					'reverse' => 'creator_name DESC',
1748
				),
1749
			),
1750
			'time' => array(
1751
				'header' => array(
1752
					'value' => $txt['mc_warning_templates_time'],
1753
				),
1754
				'data' => array(
1755
					'db' => 'time',
1756
				),
1757
				'sort' => array(
1758
					'default' => 'lc.log_time DESC',
1759
					'reverse' => 'lc.log_time',
1760
				),
1761
			),
1762
			'delete' => array(
1763
				'header' => array(
1764
					'value' => '<input type="checkbox" class="input_check" onclick="invertAll(this, this.form);">',
1765
					'style' => 'width: 4%;',
1766
					'class' => 'centercol',
1767
				),
1768
				'data' => array(
1769
					'function' => function ($rowData)
1770
					{
1771
						return '<input type="checkbox" name="deltpl[]" value="' . $rowData['id_comment'] . '" class="input_check">';
1772
					},
1773
					'class' => 'centercol',
1774
				),
1775
			),
1776
		),
1777
		'form' => array(
1778
			'href' => $scripturl . '?action=moderate;area=warnings;sa=templates',
1779
			'token' => 'mod-wt',
1780
		),
1781
		'additional_rows' => array(
1782
			array(
1783
				'position' => 'bottom_of_list',
1784
				'value' => '&nbsp;<input type="submit" name="delete" value="' . $txt['mc_warning_template_delete'] . '" data-confirm="' . $txt['mc_warning_template_delete_confirm'] . '" class="button_submit you_sure">',
1785
			),
1786
			array(
1787
				'position' => 'bottom_of_list',
1788
				'value' => '<input type="submit" name="add" value="' . $txt['mc_warning_template_add'] . '" class="button_submit">',
1789
			),
1790
		),
1791
	);
1792
1793
	// Create the watched user list.
1794
	createToken('mod-wt');
1795
	createList($listOptions);
1796
1797
	$context['sub_template'] = 'show_list';
1798
	$context['default_list'] = 'warning_template_list';
1799
}
1800
1801
/**
1802
  * Callback for createList().
1803
  * @return int The total number of warning templates
1804
  */
1805 View Code Duplication
function list_getWarningTemplateCount()
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in 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...
1806
{
1807
	global $smcFunc, $user_info;
1808
1809
	$request = $smcFunc['db_query']('', '
1810
		SELECT COUNT(*)
1811
		FROM {db_prefix}log_comments
1812
		WHERE comment_type = {string:warntpl}
1813
			AND (id_recipient = {string:generic} OR id_recipient = {int:current_member})',
1814
		array(
1815
			'warntpl' => 'warntpl',
1816
			'generic' => 0,
1817
			'current_member' => $user_info['id'],
1818
		)
1819
	);
1820
	list ($totalWarns) = $smcFunc['db_fetch_row']($request);
1821
	$smcFunc['db_free_result']($request);
1822
1823
	return $totalWarns;
1824
}
1825
1826
/**
1827
 * Callback for createList().
1828
 *
1829
 * @param int $start The item to start with (for pagination purposes)
1830
 * @param int $items_per_page The number of items to show per page
1831
 * @param string $sort A string indicating how to sort the results
1832
 * @return array An arrray of info about the available warning templates
1833
 */
1834
function list_getWarningTemplates($start, $items_per_page, $sort)
1835
{
1836
	global $smcFunc, $scripturl, $user_info;
1837
1838
	$request = $smcFunc['db_query']('', '
1839
		SELECT lc.id_comment, COALESCE(mem.id_member, 0) AS id_member,
1840
			COALESCE(mem.real_name, lc.member_name) AS creator_name, recipient_name AS template_title,
1841
			lc.log_time, lc.body
1842
		FROM {db_prefix}log_comments AS lc
1843
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lc.id_member)
1844
		WHERE lc.comment_type = {string:warntpl}
1845
			AND (id_recipient = {string:generic} OR id_recipient = {int:current_member})
1846
		ORDER BY ' . $sort . '
1847
		LIMIT ' . $start . ', ' . $items_per_page,
1848
		array(
1849
			'warntpl' => 'warntpl',
1850
			'generic' => 0,
1851
			'current_member' => $user_info['id'],
1852
		)
1853
	);
1854
	$templates = array();
1855
	while ($row = $smcFunc['db_fetch_assoc']($request))
1856
	{
1857
		$templates[] = array(
1858
			'id_comment' => $row['id_comment'],
1859
			'creator' => $row['id_member'] ? ('<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['creator_name'] . '</a>') : $row['creator_name'],
1860
			'time' => timeformat($row['log_time']),
1861
			'title' => $row['template_title'],
1862
			'body' => $smcFunc['htmlspecialchars']($row['body']),
1863
		);
1864
	}
1865
	$smcFunc['db_free_result']($request);
1866
1867
	return $templates;
1868
}
1869
1870
/**
1871
 * Edit a warning template.
1872
 */
1873
function ModifyWarningTemplate()
1874
{
1875
	global $smcFunc, $context, $txt, $user_info, $sourcedir;
1876
1877
	$context['id_template'] = isset($_REQUEST['tid']) ? (int) $_REQUEST['tid'] : 0;
1878
	$context['is_edit'] = $context['id_template'];
1879
1880
	// Standard template things.
1881
	$context['page_title'] = $context['is_edit'] ? $txt['mc_warning_template_modify'] : $txt['mc_warning_template_add'];
1882
	$context['sub_template'] = 'warn_template';
1883
	$context[$context['moderation_menu_name']]['current_subsection'] = 'templates';
1884
1885
	// Defaults.
1886
	$context['template_data'] = array(
1887
		'title' => '',
1888
		'body' => $txt['mc_warning_template_body_default'],
1889
		'personal' => false,
1890
		'can_edit_personal' => true,
1891
	);
1892
1893
	// If it's an edit load it.
1894
	if ($context['is_edit'])
1895
	{
1896
		$request = $smcFunc['db_query']('', '
1897
			SELECT id_member, id_recipient, recipient_name AS template_title, body
1898
			FROM {db_prefix}log_comments
1899
			WHERE id_comment = {int:id}
1900
				AND comment_type = {string:warntpl}
1901
				AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})',
1902
			array(
1903
				'id' => $context['id_template'],
1904
				'warntpl' => 'warntpl',
1905
				'generic' => 0,
1906
				'current_member' => $user_info['id'],
1907
			)
1908
		);
1909
		while ($row = $smcFunc['db_fetch_assoc']($request))
1910
		{
1911
			$context['template_data'] = array(
1912
				'title' => $row['template_title'],
1913
				'body' => $smcFunc['htmlspecialchars']($row['body']),
1914
				'personal' => $row['id_recipient'],
1915
				'can_edit_personal' => $row['id_member'] == $user_info['id'],
1916
			);
1917
		}
1918
		$smcFunc['db_free_result']($request);
1919
	}
1920
1921
	// Wait, we are saving?
1922
	if (isset($_POST['save']))
1923
	{
1924
		checkSession();
1925
		validateToken('mod-wt');
1926
1927
		// To check the BBC is pretty good...
1928
		require_once($sourcedir . '/Subs-Post.php');
1929
1930
		// Bit of cleaning!
1931
		$_POST['template_body'] = trim($_POST['template_body']);
1932
		$_POST['template_title'] = trim($_POST['template_title']);
1933
1934
		// Need something in both boxes.
1935
		if (!empty($_POST['template_body']) && !empty($_POST['template_title']))
1936
		{
1937
			// Safety first.
1938
			$_POST['template_title'] = $smcFunc['htmlspecialchars']($_POST['template_title']);
1939
1940
			// Clean up BBC.
1941
			preparsecode($_POST['template_body']);
1942
			// But put line breaks back!
1943
			$_POST['template_body'] = strtr($_POST['template_body'], array('<br>' => "\n"));
1944
1945
			// Is this personal?
1946
			$recipient_id = !empty($_POST['make_personal']) ? $user_info['id'] : 0;
1947
1948
			// If we are this far it's save time.
1949
			if ($context['is_edit'])
1950
			{
1951
				// Simple update...
1952
				$smcFunc['db_query']('', '
1953
					UPDATE {db_prefix}log_comments
1954
					SET id_recipient = {int:personal}, recipient_name = {string:title}, body = {string:body}
1955
					WHERE id_comment = {int:id}
1956
						AND comment_type = {string:warntpl}
1957
						AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})'.
1958
						($recipient_id ? ' AND id_member = {int:current_member}' : ''),
1959
					array(
1960
						'personal' => $recipient_id,
1961
						'title' => $_POST['template_title'],
1962
						'body' => $_POST['template_body'],
1963
						'id' => $context['id_template'],
1964
						'warntpl' => 'warntpl',
1965
						'generic' => 0,
1966
						'current_member' => $user_info['id'],
1967
					)
1968
				);
1969
1970
				// If it wasn't visible and now is they've effectively added it.
1971
				if ($context['template_data']['personal'] && !$recipient_id)
1972
					logAction('add_warn_template', array('template' => $_POST['template_title']));
1973
				// Conversely if they made it personal it's a delete.
1974
				elseif (!$context['template_data']['personal'] && $recipient_id)
1975
					logAction('delete_warn_template', array('template' => $_POST['template_title']));
1976
				// Otherwise just an edit.
1977
				else
1978
					logAction('modify_warn_template', array('template' => $_POST['template_title']));
1979
			}
1980
			else
1981
			{
1982
				$smcFunc['db_insert']('',
1983
					'{db_prefix}log_comments',
1984
					array(
1985
						'id_member' => 'int', 'member_name' => 'string', 'comment_type' => 'string', 'id_recipient' => 'int',
1986
						'recipient_name' => 'string-255', 'body' => 'string-65535', 'log_time' => 'int',
1987
					),
1988
					array(
1989
						$user_info['id'], $user_info['name'], 'warntpl', $recipient_id,
1990
						$_POST['template_title'], $_POST['template_body'], time(),
1991
					),
1992
					array('id_comment')
1993
				);
1994
1995
				logAction('add_warn_template', array('template' => $_POST['template_title']));
1996
			}
1997
1998
			// Get out of town...
1999
			redirectexit('action=moderate;area=warnings;sa=templates');
2000
		}
2001
		else
2002
		{
2003
			$context['warning_errors'] = array();
2004
			$context['template_data']['title'] = !empty($_POST['template_title']) ? $_POST['template_title'] : '';
2005
			$context['template_data']['body'] = !empty($_POST['template_body']) ? $_POST['template_body'] : $txt['mc_warning_template_body_default'];
2006
			$context['template_data']['personal'] = !empty($_POST['make_personal']);
2007
			if (empty($_POST['template_title']))
2008
				$context['warning_errors'][] = $txt['mc_warning_template_error_no_title'];
2009
			if (empty($_POST['template_body']))
2010
				$context['warning_errors'][] = $txt['mc_warning_template_error_no_body'];
2011
		}
2012
	}
2013
2014
	createToken('mod-wt');
2015
}
2016
2017
/**
2018
 * Change moderation preferences.
2019
 */
2020
function ModerationSettings()
2021
{
2022
	global $context, $txt, $user_info;
2023
2024
	// Some useful context stuff.
2025
	loadTemplate('ModerationCenter');
2026
	$context['page_title'] = $txt['mc_settings'];
2027
	$context['sub_template'] = 'moderation_settings';
2028
	$context[$context['moderation_menu_name']]['tab_data'] = array(
2029
		'title' => $txt['mc_prefs_title'],
2030
		'help' => '',
2031
		'description' => $txt['mc_prefs_desc']
2032
	);
2033
2034
	$mod_blocks = '';
0 ignored issues
show
Unused Code introduced by
$mod_blocks is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2035
	$pref_binary = 5;
2036
	$show_reports = 0;
0 ignored issues
show
Unused Code introduced by
$show_reports is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2037
2038
	// Are we saving?
2039
	if (isset($_POST['save']))
2040
	{
2041
		checkSession();
2042
		validateToken('mod-set');
2043
2044
		/* Current format of mod_prefs is:
2045
			x|ABCD|yyy
2046
2047
			WHERE:
2048
				x = Show report count on forum header.
2049
				ABCD = Block indexes to show on moderation main page.
2050
				yyy = Integer with the following bit status:
2051
					- yyy & 4 = Notify about posts awaiting approval.
2052
		*/
2053
2054
		// Now check other options!
2055
		$pref_binary = 0;
2056
2057
		if ($context['can_moderate_approvals'] && !empty($_POST['mod_notify_approval']))
2058
			$pref_binary |= 4;
2059
2060
		// Put it all together.
2061
		$mod_prefs = '0||' . $pref_binary;
2062
		updateMemberData($user_info['id'], array('mod_prefs' => $mod_prefs));
2063
	}
2064
2065
	// What blocks does the user currently have selected?
2066
	$context['mod_settings'] = array(
2067
		'notify_approval' => $pref_binary & 4,
2068
	);
2069
2070
	createToken('mod-set');
2071
}
2072
2073
/**
2074
 * This ends a moderator session, requiring authentication to access the MCP again.
2075
 */
2076
function ModEndSession()
2077
{
2078
	// This is so easy!
2079
	unset($_SESSION['moderate_time']);
2080
2081
	// Clean any moderator tokens as well.
2082 View Code Duplication
	foreach ($_SESSION['token'] as $key => $token)
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...
2083
		if (strpos($key, '-mod') !== false)
2084
			unset($_SESSION['token'][$key]);
2085
2086
	redirectexit();
2087
}
2088
2089
?>
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...