ViewWatchedUsers()   F
last analyzed

Complexity

Conditions 23
Paths > 20000

Size

Total Lines 206
Code Lines 126

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 23
eloc 126
c 0
b 0
f 0
nop 0
dl 0
loc 206
rs 0
nc 40960

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 https://www.simplemachines.org
10
 * @copyright 2022 Simple Machines and individual contributors
11
 * @license https://www.simplemachines.org/about/smf/license.php BSD
12
 *
13
 * @version 2.1.0
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 $smcFunc, $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
Bug introduced by
false of type false is incompatible with the type string expected by parameter $template_name of loadTemplate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

46
	loadTemplate(/** @scrutinizer ignore-type */ false, 'admin');
Loading history...
47
48
	$context['admin_preferences'] = !empty($options['admin_preferences']) ? $smcFunc['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 && allowedTo(array('issue_warning', 'view_warning_any')),
92
					'function' => 'ViewWarnings',
93
					'icon' => 'warning',
94
					'subsections' => array(
95
						'log' => array($txt['mc_warning_log'], array('view_warning_any', 'moderate_forum')),
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);
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 $smcFunc, $txt, $context, $options;
249
250
	loadTemplate('ModerationCenter');
251
	loadJavaScriptFile('admin.js', array('minimize' => true), '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']) ? $smcFunc['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, $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);
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
	if (($moderator_notes_total = cache_get_data('moderator_notes_total', 240)) === null)
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($smcFunc['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($smcFunc['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
	// Set up the comforting bits...
694
	$context['page_title'] = $txt['mc_reported_members'];
695
	$context['sub_template'] = 'reported_members';
696
697
	// Are we viewing open or closed reports?
698
	$context['view_closed'] = isset($_GET['sa']) && $_GET['sa'] == 'closed' ? 1 : 0;
699
700
	// Are we doing any work?
701
	if ((isset($_GET['ignore']) || isset($_GET['close'])) && isset($_GET['rid']))
702
	{
703
		checkSession('get');
704
		$_GET['rid'] = (int) $_GET['rid'];
705
706
		// Update the report...
707
		$smcFunc['db_query']('', '
708
			UPDATE {db_prefix}log_reported
709
			SET ' . (isset($_GET['ignore']) ? 'ignore_all = {int:ignore_all}' : 'closed = {int:closed}') . '
710
			WHERE id_report = {int:id_report}',
711
			array(
712
				'ignore_all' => isset($_GET['ignore']) ? (int) $_GET['ignore'] : 0,
713
				'closed' => isset($_GET['close']) ? (int) $_GET['close'] : 0,
714
				'id_report' => $_GET['rid'],
715
			)
716
		);
717
718
		// Get the board, topic and message for this report
719
		$request = $smcFunc['db_query']('', '
720
			SELECT id_member, membername
721
			FROM {db_prefix}log_reported
722
			WHERE id_report = {int:id_report}',
723
			array(
724
				'id_report' => $_GET['rid'],
725
			)
726
		);
727
728
		// Set up the data for the log...
729
		$extra = array('report' => $_GET['rid']);
730
		list($extra['member'], $extra['membername']) = $smcFunc['db_fetch_row']($request);
731
		$smcFunc['db_free_result']($request);
732
733
		// Stick this in string format for consistency
734
		$extra['member'] = (string) $extra['member'];
735
736
		// Tell the user about it.
737
		$context['report_member_action'] = isset($_GET['ignore']) ? (!empty($_GET['ignore']) ? 'ignore' : 'unignore') : (!empty($_GET['close']) ? 'close' : 'open');
738
739
		// Log this action
740
		logAction($context['report_member_action'] . '_user_report', $extra);
741
742
		// Time to update.
743
		updateSettings(array('last_mod_report_action' => time()));
744
		recountOpenReports('members');
745
	}
746
	elseif (isset($_POST['close']) && isset($_POST['close_selected']))
747
	{
748
		checkSession();
749
750
		// All the ones to update...
751
		$toClose = array();
752
		foreach ($_POST['close'] as $rid)
753
			$toClose[] = (int) $rid;
754
755
		if (!empty($toClose))
756
		{
757
			// Get the data for each of these reports
758
			$request = $smcFunc['db_query']('', '
759
				SELECT id_report, id_member, membername
760
				FROM {db_prefix}log_reported
761
				WHERE id_report IN ({array_int:report_list})',
762
				array(
763
					'report_list' => $toClose,
764
				)
765
			);
766
767
			$logs = array();
768
			while ($reports = $smcFunc['db_fetch_assoc']($request))
769
			{
770
				$logs[] = array(
771
					'action' => 'close_user_report',
772
					'log_type' => 'moderate',
773
					'extra' => array(
774
						'report' => $reports['id_report'],
775
						'membername' => $reports['membername'],
776
						'member' => (string) $reports['id_member'],
777
					),
778
				);
779
			}
780
781
			$smcFunc['db_free_result']($request);
782
783
			// Log the closing of all the reports
784
			logActions($logs);
785
786
			$smcFunc['db_query']('', '
787
				UPDATE {db_prefix}log_reported
788
				SET closed = {int:is_closed}
789
				WHERE id_report IN ({array_int:report_list})',
790
				array(
791
					'report_list' => $toClose,
792
					'is_closed' => 1,
793
				)
794
			);
795
796
			// Time to update.
797
			updateSettings(array('last_mod_report_action' => time()));
798
			recountOpenReports('members');
799
		}
800
801
		// Go on and tell the result.
802
		$context['report_member_action'] = 'close_all';
803
	}
804
805
	// How many entries are we viewing?
806
	$request = $smcFunc['db_query']('', '
807
		SELECT COUNT(*)
808
		FROM {db_prefix}log_reported AS lr
809
		WHERE lr.closed = {int:view_closed}
810
			AND lr.id_board = {int:not_a_reported_post}',
811
		array(
812
			'view_closed' => $context['view_closed'],
813
			'not_a_reported_post' => 0,
814
		)
815
	);
816
	list ($context['total_reports']) = $smcFunc['db_fetch_row']($request);
817
	$smcFunc['db_free_result']($request);
818
819
	// So, that means we can page index, yes?
820
	$context['page_index'] = constructPageIndex($scripturl . '?action=moderate;area=reportedmembers' . ($context['view_closed'] ? ';sa=closed' : ''), $_GET['start'], $context['total_reports'], 10);
821
	$context['start'] = $_GET['start'];
822
823
	// By George, that means we in a position to get the reports, golly good.
824
	$request = $smcFunc['db_query']('', '
825
		SELECT lr.id_report, lr.id_member, lr.time_started, lr.time_updated, lr.num_reports, lr.closed, lr.ignore_all,
826
			COALESCE(mem.real_name, lr.membername) AS user_name, COALESCE(mem.id_member, 0) AS id_user
827
		FROM {db_prefix}log_reported AS lr
828
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lr.id_member)
829
		WHERE lr.closed = {int:view_closed}
830
			AND lr.id_board = {int:not_a_reported_post}
831
		ORDER BY lr.time_updated DESC
832
		LIMIT {int:limit}, {int:max}',
833
		array(
834
			'view_closed' => $context['view_closed'],
835
			'not_a_reported_post' => 0,
836
			'limit' => $context['start'],
837
			'max' => 10,
838
		)
839
	);
840
	$context['reports'] = array();
841
	$report_ids = array();
842
	for ($i = 0; $row = $smcFunc['db_fetch_assoc']($request); $i++)
843
	{
844
		$report_ids[] = $row['id_report'];
845
		$context['reports'][$row['id_report']] = array(
846
			'id' => $row['id_report'],
847
			'report_href' => $scripturl . '?action=moderate;area=reportedmembers;report=' . $row['id_report'],
848
			'user' => array(
849
				'id' => $row['id_user'],
850
				'name' => $row['user_name'],
851
				'link' => $row['id_user'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_user'] . '">' . $row['user_name'] . '</a>' : $row['user_name'],
852
				'href' => $scripturl . '?action=profile;u=' . $row['id_user'],
853
			),
854
			'comments' => array(),
855
			'time_started' => timeformat($row['time_started']),
856
			'last_updated' => timeformat($row['time_updated']),
857
			'num_reports' => $row['num_reports'],
858
			'closed' => $row['closed'],
859
			'ignore' => $row['ignore_all']
860
		);
861
	}
862
	$smcFunc['db_free_result']($request);
863
864
	// Now get all the people who reported it.
865
	if (!empty($report_ids))
866
	{
867
		$request = $smcFunc['db_query']('', '
868
			SELECT lrc.id_comment, lrc.id_report, lrc.time_sent, lrc.comment,
869
				COALESCE(mem.id_member, 0) AS id_member, COALESCE(mem.real_name, lrc.membername) AS reporter
870
			FROM {db_prefix}log_reported_comments AS lrc
871
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lrc.id_member)
872
			WHERE lrc.id_report IN ({array_int:report_list})',
873
			array(
874
				'report_list' => $report_ids,
875
			)
876
		);
877
		while ($row = $smcFunc['db_fetch_assoc']($request))
878
		{
879
			$context['reports'][$row['id_report']]['comments'][] = array(
880
				'id' => $row['id_comment'],
881
				'message' => $row['comment'],
882
				'time' => timeformat($row['time_sent']),
883
				'member' => array(
884
					'id' => $row['id_member'],
885
					'name' => empty($row['reporter']) ? $txt['guest'] : $row['reporter'],
886
					'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['reporter'] . '</a>' : (empty($row['reporter']) ? $txt['guest'] : $row['reporter']),
887
					'href' => $row['id_member'] ? $scripturl . '?action=profile;u=' . $row['id_member'] : '',
888
				),
889
			);
890
		}
891
		$smcFunc['db_free_result']($request);
892
	}
893
894
	$context['report_manage_bans'] = allowedTo('manage_bans');
895
}
896
897
/**
898
 * Act as an entrace for all group related activity.
899
 *
900
 * @todo As for most things in this file, this needs to be moved somewhere appropriate?
901
 */
902
function ModerateGroups()
903
{
904
	global $context, $user_info;
905
906
	// You need to be allowed to moderate groups...
907
	if ($user_info['mod_cache']['gq'] == '0=1')
908
		isAllowedTo('manage_membergroups');
909
910
	// Load the group templates.
911
	loadTemplate('ModerationCenter');
912
913
	// Setup the subactions...
914
	$subActions = array(
915
		'requests' => 'GroupRequests',
916
		'view' => 'ViewGroups',
917
	);
918
919
	if (!isset($_GET['sa']) || !isset($subActions[$_GET['sa']]))
920
		$_GET['sa'] = 'view';
921
	$context['sub_action'] = $_GET['sa'];
922
923
	// Call the relevant function.
924
	call_helper($subActions[$context['sub_action']]);
925
}
926
927
/**
928
 * Show a notice sent to a user.
929
 */
930
function ShowNotice()
931
{
932
	global $smcFunc, $txt, $context;
933
934
	$context['page_title'] = $txt['show_notice'];
935
	$context['sub_template'] = 'show_notice';
936
	$context['template_layers'] = array();
937
938
	loadTemplate('ModerationCenter');
939
940
	// @todo Assumes nothing needs permission more than accessing moderation center!
941
	$id_notice = (int) $_GET['nid'];
942
	$request = $smcFunc['db_query']('', '
943
		SELECT body, subject
944
		FROM {db_prefix}log_member_notices
945
		WHERE id_notice = {int:id_notice}',
946
		array(
947
			'id_notice' => $id_notice,
948
		)
949
	);
950
	if ($smcFunc['db_num_rows']($request) == 0)
951
		fatal_lang_error('no_access', false);
952
	list ($context['notice_body'], $context['notice_subject']) = $smcFunc['db_fetch_row']($request);
953
	$smcFunc['db_free_result']($request);
954
955
	$context['notice_body'] = parse_bbc($context['notice_body'], false);
956
}
957
958
/**
959
 * View watched users.
960
 */
961
function ViewWatchedUsers()
962
{
963
	global $modSettings, $context, $txt, $scripturl, $sourcedir;
964
965
	// Some important context!
966
	$context['page_title'] = $txt['mc_watched_users_title'];
967
	$context['view_posts'] = isset($_GET['sa']) && $_GET['sa'] == 'post';
968
	$context['start'] = isset($_REQUEST['start']) ? (int) $_REQUEST['start'] : 0;
969
970
	loadTemplate('ModerationCenter');
971
972
	// Get some key settings!
973
	$modSettings['warning_watch'] = empty($modSettings['warning_watch']) ? 1 : $modSettings['warning_watch'];
974
975
	// Put some pretty tabs on cause we're gonna be doing hot stuff here...
976
	$context[$context['moderation_menu_name']]['tab_data'] = array(
977
		'title' => $txt['mc_watched_users_title'],
978
		'help' => '',
979
		'description' => $txt['mc_watched_users_desc'],
980
	);
981
982
	// First off - are we deleting?
983
	if (!empty($_REQUEST['delete']))
984
	{
985
		checkSession(!is_array($_REQUEST['delete']) ? 'get' : 'post');
986
987
		$toDelete = array();
988
		if (!is_array($_REQUEST['delete']))
989
			$toDelete[] = (int) $_REQUEST['delete'];
990
		else
991
			foreach ($_REQUEST['delete'] as $did)
992
				$toDelete[] = (int) $did;
993
994
		if (!empty($toDelete))
995
		{
996
			require_once($sourcedir . '/RemoveTopic.php');
997
			// If they don't have permission we'll let it error - either way no chance of a security slip here!
998
			foreach ($toDelete as $did)
999
				removeMessage($did);
1000
		}
1001
	}
1002
1003
	// Start preparing the list by grabbing relevant permissions.
1004
	if (!$context['view_posts'])
1005
	{
1006
		$approve_query = '';
1007
		$delete_boards = array();
1008
	}
1009
	else
1010
	{
1011
		// Still obey permissions!
1012
		$approve_boards = boardsAllowedTo('approve_posts');
1013
		$delete_boards = boardsAllowedTo('delete_any');
1014
1015
		if ($approve_boards == array(0))
1016
			$approve_query = '';
1017
		elseif (!empty($approve_boards))
1018
			$approve_query = ' AND m.id_board IN (' . implode(',', $approve_boards) . ')';
1019
		// Nada, zip, etc...
1020
		else
1021
			$approve_query = ' AND 1=0';
1022
	}
1023
1024
	require_once($sourcedir . '/Subs-List.php');
1025
1026
	// This is all the information required for a watched user listing.
1027
	$listOptions = array(
1028
		'id' => 'watch_user_list',
1029
		'title' => $txt['mc_watched_users_title'] . ' - ' . ($context['view_posts'] ? $txt['mc_watched_users_post'] : $txt['mc_watched_users_member']),
1030
		'items_per_page' => $modSettings['defaultMaxListItems'],
1031
		'no_items_label' => $context['view_posts'] ? $txt['mc_watched_users_no_posts'] : $txt['mc_watched_users_none'],
1032
		'base_href' => $scripturl . '?action=moderate;area=userwatch;sa=' . ($context['view_posts'] ? 'post' : 'member'),
1033
		'default_sort_col' => $context['view_posts'] ? '' : 'member',
1034
		'get_items' => array(
1035
			'function' => $context['view_posts'] ? 'list_getWatchedUserPosts' : 'list_getWatchedUsers',
1036
			'params' => array(
1037
				$approve_query,
1038
				$delete_boards,
1039
			),
1040
		),
1041
		'get_count' => array(
1042
			'function' => $context['view_posts'] ? 'list_getWatchedUserPostsCount' : 'list_getWatchedUserCount',
1043
			'params' => array(
1044
				$approve_query,
1045
			),
1046
		),
1047
		// This assumes we are viewing by user.
1048
		'columns' => array(
1049
			'member' => array(
1050
				'header' => array(
1051
					'value' => $txt['mc_watched_users_member'],
1052
				),
1053
				'data' => array(
1054
					'sprintf' => array(
1055
						'format' => '<a href="' . $scripturl . '?action=profile;u=%1$d">%2$s</a>',
1056
						'params' => array(
1057
							'id' => false,
1058
							'name' => false,
1059
						),
1060
					),
1061
				),
1062
				'sort' => array(
1063
					'default' => 'real_name',
1064
					'reverse' => 'real_name DESC',
1065
				),
1066
			),
1067
			'warning' => array(
1068
				'header' => array(
1069
					'value' => $txt['mc_watched_users_warning'],
1070
				),
1071
				'data' => array(
1072
					'function' => function($member) use ($scripturl)
1073
					{
1074
						return allowedTo('issue_warning') ? '<a href="' . $scripturl . '?action=profile;area=issuewarning;u=' . $member['id'] . '">' . $member['warning'] . '%</a>' : $member['warning'] . '%';
1075
					},
1076
				),
1077
				'sort' => array(
1078
					'default' => 'warning',
1079
					'reverse' => 'warning DESC',
1080
				),
1081
			),
1082
			'posts' => array(
1083
				'header' => array(
1084
					'value' => $txt['posts'],
1085
				),
1086
				'data' => array(
1087
					'sprintf' => array(
1088
						'format' => '<a href="' . $scripturl . '?action=profile;u=%1$d;area=showposts;sa=messages">%2$s</a>',
1089
						'params' => array(
1090
							'id' => false,
1091
							'posts' => false,
1092
						),
1093
					),
1094
				),
1095
				'sort' => array(
1096
					'default' => 'posts',
1097
					'reverse' => 'posts DESC',
1098
				),
1099
			),
1100
			'last_login' => array(
1101
				'header' => array(
1102
					'value' => $txt['mc_watched_users_last_login'],
1103
				),
1104
				'data' => array(
1105
					'db' => 'last_login',
1106
				),
1107
				'sort' => array(
1108
					'default' => 'last_login',
1109
					'reverse' => 'last_login DESC',
1110
				),
1111
			),
1112
			'last_post' => array(
1113
				'header' => array(
1114
					'value' => $txt['mc_watched_users_last_post'],
1115
				),
1116
				'data' => array(
1117
					'function' => function($member) use ($scripturl)
1118
					{
1119
						if ($member['last_post_id'])
1120
							return '<a href="' . $scripturl . '?msg=' . $member['last_post_id'] . '">' . $member['last_post'] . '</a>';
1121
						else
1122
							return $member['last_post'];
1123
					},
1124
				),
1125
			),
1126
		),
1127
		'form' => array(
1128
			'href' => $scripturl . '?action=moderate;area=userwatch;sa=post',
1129
			'include_sort' => true,
1130
			'include_start' => true,
1131
			'hidden_fields' => array(
1132
				$context['session_var'] => $context['session_id'],
1133
			),
1134
		),
1135
		'additional_rows' => array(
1136
			$context['view_posts'] ?
1137
				array(
1138
					'position' => 'bottom_of_list',
1139
					'value' => '
1140
					<input type="submit" name="delete_selected" value="' . $txt['quickmod_delete_selected'] . '" class="button">',
1141
					'class' => 'floatright',
1142
				) : array(),
1143
		),
1144
	);
1145
1146
	// If this is being viewed by posts we actually change the columns to call a template each time.
1147
	if ($context['view_posts'])
1148
	{
1149
		$listOptions['columns'] = array(
1150
			'posts' => array(
1151
				'data' => array(
1152
					'function' => function($post)
1153
					{
1154
						return template_user_watch_post_callback($post);
1155
					},
1156
					'class' => 'unique'
1157
				),
1158
			),
1159
		);
1160
	}
1161
1162
	// Create the watched user list.
1163
	createList($listOptions);
1164
1165
	$context['sub_template'] = 'show_list';
1166
	$context['default_list'] = 'watch_user_list';
1167
}
1168
1169
/**
1170
 * Callback for createList().
1171
 *
1172
 * @param string $approve_query Not used here
1173
 * @return int The number of users on the watch list
1174
 */
1175
function list_getWatchedUserCount($approve_query)
1176
{
1177
	global $smcFunc, $modSettings;
1178
1179
	$request = $smcFunc['db_query']('', '
1180
		SELECT COUNT(*)
1181
		FROM {db_prefix}members
1182
		WHERE warning >= {int:warning_watch}',
1183
		array(
1184
			'warning_watch' => $modSettings['warning_watch'],
1185
		)
1186
	);
1187
	list ($totalMembers) = $smcFunc['db_fetch_row']($request);
1188
	$smcFunc['db_free_result']($request);
1189
1190
	return $totalMembers;
1191
}
1192
1193
/**
1194
 * Callback for createList().
1195
 *
1196
 * @param int $start The item to start with (for pagination purposes)
1197
 * @param int $items_per_page The number of items to show per page
1198
 * @param string $sort A string indicating how to sort things
1199
 * @param string $approve_query A query for approving things. Not used here.
1200
 * @param string $dummy Not used here.
1201
 */
1202
function list_getWatchedUsers($start, $items_per_page, $sort, $approve_query, $dummy)
1203
{
1204
	global $smcFunc, $txt, $modSettings, $user_info;
1205
1206
	$request = $smcFunc['db_query']('', '
1207
		SELECT id_member, real_name, last_login, posts, warning
1208
		FROM {db_prefix}members
1209
		WHERE warning >= {int:warning_watch}
1210
		ORDER BY {raw:sort}
1211
		LIMIT {int:start}, {int:max}',
1212
		array(
1213
			'warning_watch' => $modSettings['warning_watch'],
1214
			'sort' => $sort,
1215
			'start' => $start,
1216
			'max' => $items_per_page,
1217
		)
1218
	);
1219
	$watched_users = array();
1220
	$members = array();
1221
	while ($row = $smcFunc['db_fetch_assoc']($request))
1222
	{
1223
		$watched_users[$row['id_member']] = array(
1224
			'id' => $row['id_member'],
1225
			'name' => $row['real_name'],
1226
			'last_login' => $row['last_login'] ? timeformat($row['last_login']) : $txt['never'],
1227
			'last_post' => $txt['not_applicable'],
1228
			'last_post_id' => 0,
1229
			'warning' => $row['warning'],
1230
			'posts' => $row['posts'],
1231
		);
1232
		$members[] = $row['id_member'];
1233
	}
1234
	$smcFunc['db_free_result']($request);
1235
1236
	if (!empty($members))
1237
	{
1238
		// First get the latest messages from these users.
1239
		$request = $smcFunc['db_query']('', '
1240
			SELECT m.id_member, MAX(m.id_msg) AS last_post_id
1241
			FROM {db_prefix}messages AS m' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : '
1242
				INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)') . '
1243
			WHERE {query_see_message_board}
1244
				AND m.id_member IN ({array_int:member_list})' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : '
1245
				AND m.approved = {int:is_approved}
1246
				AND t.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
1280
			WHERE {query_see_message_board}
1281
				AND 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
function list_getWatchedUserPostsCount($approve_query)
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)
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', array('view_warning_any', 'moderate_forum')),
1390
		'templates' => array('ViewWarningTemplates', 'issue_warning'),
1391
		'templateedit' => array('ModifyWarningTemplate', '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']][1])) ? $_REQUEST['sa'] : '';
1397
1398
	// In theory, 'log' is the default subaction. But if this user can't view the log, more work is needed.
1399
	if (empty($_REQUEST['sa']))
1400
	{
1401
		foreach ($subActions as $sa => $subAction)
1402
		{
1403
			if (empty($subAction[1]) || allowedTo($subAction[1]))
1404
			{
1405
				// If they can view the log, we can proceed as usual.
1406
				if ($sa === 'log')
1407
					$_REQUEST['sa'] = $sa;
1408
1409
				// Otherwise, redirect them to the first allowed subaction.
1410
				else
1411
					redirectexit('action=moderate;area=warnings;sa=' . $sa);
1412
			}
1413
		}
1414
1415
		// This shouldn't happen, but just in case...
1416
		if (empty($_REQUEST['sa']))
1417
			redirectexit('action=moderate;area=index');
1418
	}
1419
1420
	// Some of this stuff is overseas, so to speak.
1421
	loadTemplate('ModerationCenter');
1422
	loadLanguage('Profile');
1423
1424
	// Setup the admin tabs.
1425
	$context[$context['moderation_menu_name']]['tab_data'] = array(
1426
		'title' => $txt['mc_warnings'],
1427
		'description' => $txt['mc_warnings_description'],
1428
	);
1429
1430
	// Call the right function.
1431
	call_helper($subActions[$_REQUEST['sa']][0]);
1432
}
1433
1434
/**
1435
 * Simply put, look at the warning log!
1436
 */
1437
function ViewWarningLog()
1438
{
1439
	global $smcFunc, $modSettings, $context, $txt, $scripturl, $sourcedir;
1440
1441
	// Setup context as always.
1442
	$context['page_title'] = $txt['mc_warning_log_title'];
1443
1444
	loadLanguage('Modlog');
1445
1446
	// If we're coming from a search, get the variables.
1447
	if (!empty($_REQUEST['params']) && empty($_REQUEST['is_search']))
1448
	{
1449
		$search_params = base64_decode(strtr($_REQUEST['params'], array(' ' => '+')));
1450
		$search_params = $smcFunc['json_decode']($search_params, true);
1451
	}
1452
1453
	// This array houses all the valid search types.
1454
	$searchTypes = array(
1455
		'member' => array('sql' => 'member_name_col', 'label' => $txt['profile_warning_previous_issued']),
1456
		'recipient' => array('sql' => 'recipient_name', 'label' => $txt['mc_warnings_recipient']),
1457
	);
1458
1459
	// Do the column stuff!
1460
	$sort_types = array(
1461
		'member' => 'member_name_col',
1462
		'recipient' => 'recipient_name',
1463
	);
1464
1465
	// Setup the direction stuff...
1466
	$context['order'] = isset($_REQUEST['sort']) && isset($sort_types[$_REQUEST['sort']]) ? $_REQUEST['sort'] : 'member';
1467
1468
	if (!isset($search_params['string']) || (!empty($_REQUEST['search']) && $search_params['string'] != $_REQUEST['search']))
1469
		$search_params_string = empty($_REQUEST['search']) ? '' : $_REQUEST['search'];
1470
	else
1471
		$search_params_string = $search_params['string'];
1472
1473
	if (isset($_REQUEST['search_type']) || empty($search_params['type']) || !isset($searchTypes[$search_params['type']]))
1474
		$search_params_type = isset($_REQUEST['search_type']) && isset($searchTypes[$_REQUEST['search_type']]) ? $_REQUEST['search_type'] : (isset($searchTypes[$context['order']]) ? $context['order'] : 'member');
1475
	else
1476
		$search_params_type = $search_params['type'];
1477
1478
	$search_params = array(
1479
		'string' => $search_params_string,
1480
		'type' => $search_params_type,
1481
	);
1482
1483
	$context['url_start'] = '?action=moderate;area=warnings;sa=log;sort=' . $context['order'];
1484
1485
	// Setup the search context.
1486
	$context['search_params'] = empty($search_params['string']) ? '' : base64_encode($smcFunc['json_encode']($search_params));
1487
	$context['search'] = array(
1488
		'string' => $search_params['string'],
1489
		'type' => $search_params['type'],
1490
		'label' => $searchTypes[$search_params_type]['label'],
1491
	);
1492
1493
	require_once($sourcedir . '/Subs-List.php');
1494
1495
	// This is all the information required for a watched user listing.
1496
	$listOptions = array(
1497
		'id' => 'warning_list',
1498
		'title' => $txt['mc_warning_log_title'],
1499
		'items_per_page' => $modSettings['defaultMaxListItems'],
1500
		'no_items_label' => $txt['mc_warnings_none'],
1501
		'base_href' => $scripturl . '?action=moderate;area=warnings;sa=log;' . $context['session_var'] . '=' . $context['session_id'],
1502
		'default_sort_col' => 'time',
1503
		'get_items' => array(
1504
			'function' => 'list_getWarnings',
1505
		),
1506
		'get_count' => array(
1507
			'function' => 'list_getWarningCount',
1508
		),
1509
		// This assumes we are viewing by user.
1510
		'columns' => array(
1511
			'issuer' => array(
1512
				'header' => array(
1513
					'value' => $txt['profile_warning_previous_issued'],
1514
				),
1515
				'data' => array(
1516
					'db' => 'issuer_link',
1517
				),
1518
				'sort' => array(
1519
					'default' => 'member_name_col',
1520
					'reverse' => 'member_name_col DESC',
1521
				),
1522
			),
1523
			'recipient' => array(
1524
				'header' => array(
1525
					'value' => $txt['mc_warnings_recipient'],
1526
				),
1527
				'data' => array(
1528
					'db' => 'recipient_link',
1529
				),
1530
				'sort' => array(
1531
					'default' => 'recipient_name',
1532
					'reverse' => 'recipient_name DESC',
1533
				),
1534
			),
1535
			'time' => array(
1536
				'header' => array(
1537
					'value' => $txt['profile_warning_previous_time'],
1538
				),
1539
				'data' => array(
1540
					'db' => 'time',
1541
				),
1542
				'sort' => array(
1543
					'default' => 'lc.log_time DESC',
1544
					'reverse' => 'lc.log_time',
1545
				),
1546
			),
1547
			'reason' => array(
1548
				'header' => array(
1549
					'value' => $txt['profile_warning_previous_reason'],
1550
				),
1551
				'data' => array(
1552
					'function' => function($rowData) use ($scripturl, $txt)
1553
					{
1554
						$output = '
1555
							<div class="floatleft">
1556
								' . $rowData['reason'] . '
1557
							</div>';
1558
1559
						if (!empty($rowData['id_notice']))
1560
							$output .= '
1561
								&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" rel="noopener" title="' . $txt['profile_warning_previous_notice'] . '"><span class="main_icons filter centericon"></span></a>';
1562
						return $output;
1563
					},
1564
				),
1565
			),
1566
			'points' => array(
1567
				'header' => array(
1568
					'value' => $txt['profile_warning_previous_level'],
1569
				),
1570
				'data' => array(
1571
					'db' => 'counter',
1572
				),
1573
			),
1574
		),
1575
		'form' => array(
1576
			'href' => $scripturl . $context['url_start'],
1577
			'include_sort' => true,
1578
			'include_start' => true,
1579
			'hidden_fields' => array(
1580
				$context['session_var'] => $context['session_id'],
1581
				'params' => false
1582
			),
1583
		),
1584
		'additional_rows' => array(
1585
			array(
1586
				'position' => 'below_table_data',
1587
				'value' => '
1588
					' . $txt['modlog_search'] . ':
1589
					<input type="text" name="search" size="18" value="' . $smcFunc['htmlspecialchars']($context['search']['string']) . '">
1590
					<input type="submit" name="is_search" value="' . $txt['modlog_go'] . '" class="button">',
1591
				'class' => 'floatright',
1592
			),
1593
		),
1594
	);
1595
1596
	// Create the watched user list.
1597
	createList($listOptions);
1598
1599
	$context['sub_template'] = 'show_list';
1600
	$context['default_list'] = 'warning_list';
1601
}
1602
1603
/**
1604
 * Callback for createList().
1605
 *
1606
 * @return int The total number of warnings that have been issued
1607
 */
1608
function list_getWarningCount()
1609
{
1610
	global $smcFunc;
1611
1612
	$request = $smcFunc['db_query']('', '
1613
		SELECT COUNT(*)
1614
		FROM {db_prefix}log_comments
1615
		WHERE comment_type = {string:warning}',
1616
		array(
1617
			'warning' => 'warning',
1618
		)
1619
	);
1620
	list ($totalWarns) = $smcFunc['db_fetch_row']($request);
1621
	$smcFunc['db_free_result']($request);
1622
1623
	return $totalWarns;
1624
}
1625
1626
/**
1627
 * Callback for createList().
1628
 *
1629
 * @param int $start The item to start with (for pagination purposes)
1630
 * @param int $items_per_page The number of items to show per page
1631
 * @param string $sort A string indicating how to sort the results
1632
 * @return array An array of data about warning log entries
1633
 */
1634
function list_getWarnings($start, $items_per_page, $sort)
1635
{
1636
	global $smcFunc, $scripturl;
1637
1638
	$request = $smcFunc['db_query']('', '
1639
		SELECT COALESCE(mem.id_member, 0) AS id_member, COALESCE(mem.real_name, lc.member_name) AS member_name_col,
1640
			COALESCE(mem2.id_member, 0) AS id_recipient, COALESCE(mem2.real_name, lc.recipient_name) AS recipient_name,
1641
			lc.log_time, lc.body, lc.id_notice, lc.counter
1642
		FROM {db_prefix}log_comments AS lc
1643
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lc.id_member)
1644
			LEFT JOIN {db_prefix}members AS mem2 ON (mem2.id_member = lc.id_recipient)
1645
		WHERE lc.comment_type = {string:warning}
1646
		ORDER BY {raw:sort}
1647
		LIMIT {int:start}, {int:max}',
1648
		array(
1649
			'warning' => 'warning',
1650
			'start' => $start,
1651
			'max' => $items_per_page,
1652
			'sort' => $sort,
1653
		)
1654
	);
1655
	$warnings = array();
1656
	while ($row = $smcFunc['db_fetch_assoc']($request))
1657
	{
1658
		$warnings[] = array(
1659
			'issuer_link' => $row['id_member'] ? ('<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['member_name_col'] . '</a>') : $row['member_name_col'],
1660
			'recipient_link' => $row['id_recipient'] ? ('<a href="' . $scripturl . '?action=profile;u=' . $row['id_recipient'] . '">' . $row['recipient_name'] . '</a>') : $row['recipient_name'],
1661
			'time' => timeformat($row['log_time']),
1662
			'reason' => $row['body'],
1663
			'counter' => $row['counter'] > 0 ? '+' . $row['counter'] : $row['counter'],
1664
			'id_notice' => $row['id_notice'],
1665
		);
1666
	}
1667
	$smcFunc['db_free_result']($request);
1668
1669
	return $warnings;
1670
}
1671
1672
/**
1673
 * Load all the warning templates.
1674
 */
1675
function ViewWarningTemplates()
1676
{
1677
	global $smcFunc, $modSettings, $context, $txt, $scripturl, $sourcedir, $user_info;
1678
1679
	// Submitting a new one?
1680
	if (isset($_POST['add']))
1681
		return ModifyWarningTemplate();
0 ignored issues
show
Bug introduced by
Are you sure the usage of ModifyWarningTemplate() is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
1682
	elseif (isset($_POST['delete']) && !empty($_POST['deltpl']))
1683
	{
1684
		checkSession();
1685
		validateToken('mod-wt');
1686
1687
		// Log the actions.
1688
		$request = $smcFunc['db_query']('', '
1689
			SELECT recipient_name
1690
			FROM {db_prefix}log_comments
1691
			WHERE id_comment IN ({array_int:delete_ids})
1692
				AND comment_type = {string:warntpl}
1693
				AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})',
1694
			array(
1695
				'delete_ids' => $_POST['deltpl'],
1696
				'warntpl' => 'warntpl',
1697
				'generic' => 0,
1698
				'current_member' => $user_info['id'],
1699
			)
1700
		);
1701
		while ($row = $smcFunc['db_fetch_assoc']($request))
1702
			logAction('delete_warn_template', array('template' => $row['recipient_name']));
1703
		$smcFunc['db_free_result']($request);
1704
1705
		// Do the deletes.
1706
		$smcFunc['db_query']('', '
1707
			DELETE FROM {db_prefix}log_comments
1708
			WHERE id_comment IN ({array_int:delete_ids})
1709
				AND comment_type = {string:warntpl}
1710
				AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})',
1711
			array(
1712
				'delete_ids' => $_POST['deltpl'],
1713
				'warntpl' => 'warntpl',
1714
				'generic' => 0,
1715
				'current_member' => $user_info['id'],
1716
			)
1717
		);
1718
	}
1719
1720
	// Setup context as always.
1721
	$context['page_title'] = $txt['mc_warning_templates_title'];
1722
1723
	require_once($sourcedir . '/Subs-List.php');
1724
1725
	// This is all the information required for a watched user listing.
1726
	$listOptions = array(
1727
		'id' => 'warning_template_list',
1728
		'title' => $txt['mc_warning_templates_title'],
1729
		'items_per_page' => $modSettings['defaultMaxListItems'],
1730
		'no_items_label' => $txt['mc_warning_templates_none'],
1731
		'base_href' => $scripturl . '?action=moderate;area=warnings;sa=templates;' . $context['session_var'] . '=' . $context['session_id'],
1732
		'default_sort_col' => 'title',
1733
		'get_items' => array(
1734
			'function' => 'list_getWarningTemplates',
1735
		),
1736
		'get_count' => array(
1737
			'function' => 'list_getWarningTemplateCount',
1738
		),
1739
		// This assumes we are viewing by user.
1740
		'columns' => array(
1741
			'title' => array(
1742
				'header' => array(
1743
					'value' => $txt['mc_warning_templates_name'],
1744
				),
1745
				'data' => array(
1746
					'sprintf' => array(
1747
						'format' => '<a href="' . $scripturl . '?action=moderate;area=warnings;sa=templateedit;tid=%1$d">%2$s</a>',
1748
						'params' => array(
1749
							'id_comment' => false,
1750
							'title' => false,
1751
							'body' => false,
1752
						),
1753
					),
1754
				),
1755
				'sort' => array(
1756
					'default' => 'template_title',
1757
					'reverse' => 'template_title DESC',
1758
				),
1759
			),
1760
			'creator' => array(
1761
				'header' => array(
1762
					'value' => $txt['mc_warning_templates_creator'],
1763
				),
1764
				'data' => array(
1765
					'db' => 'creator',
1766
				),
1767
				'sort' => array(
1768
					'default' => 'creator_name',
1769
					'reverse' => 'creator_name DESC',
1770
				),
1771
			),
1772
			'time' => array(
1773
				'header' => array(
1774
					'value' => $txt['mc_warning_templates_time'],
1775
				),
1776
				'data' => array(
1777
					'db' => 'time',
1778
				),
1779
				'sort' => array(
1780
					'default' => 'lc.log_time DESC',
1781
					'reverse' => 'lc.log_time',
1782
				),
1783
			),
1784
			'delete' => array(
1785
				'header' => array(
1786
					'value' => '<input type="checkbox" onclick="invertAll(this, this.form);">',
1787
					'style' => 'width: 4%;',
1788
					'class' => 'centercol',
1789
				),
1790
				'data' => array(
1791
					'function' => function($rowData)
1792
					{
1793
						return '<input type="checkbox" name="deltpl[]" value="' . $rowData['id_comment'] . '">';
1794
					},
1795
					'class' => 'centercol',
1796
				),
1797
			),
1798
		),
1799
		'form' => array(
1800
			'href' => $scripturl . '?action=moderate;area=warnings;sa=templates',
1801
			'token' => 'mod-wt',
1802
		),
1803
		'additional_rows' => array(
1804
			array(
1805
				'position' => 'bottom_of_list',
1806
				'value' => '&nbsp;<input type="submit" name="delete" value="' . $txt['mc_warning_template_delete'] . '" data-confirm="' . $txt['mc_warning_template_delete_confirm'] . '" class="button you_sure">',
1807
			),
1808
			array(
1809
				'position' => 'bottom_of_list',
1810
				'value' => '<input type="submit" name="add" value="' . $txt['mc_warning_template_add'] . '" class="button">',
1811
			),
1812
		),
1813
	);
1814
1815
	// Create the watched user list.
1816
	createToken('mod-wt');
1817
	createList($listOptions);
1818
1819
	$context['sub_template'] = 'show_list';
1820
	$context['default_list'] = 'warning_template_list';
1821
}
1822
1823
/**
1824
 * Callback for createList().
1825
 *
1826
 * @return int The total number of warning templates
1827
 */
1828
function list_getWarningTemplateCount()
1829
{
1830
	global $smcFunc, $user_info;
1831
1832
	$request = $smcFunc['db_query']('', '
1833
		SELECT COUNT(*)
1834
		FROM {db_prefix}log_comments
1835
		WHERE comment_type = {string:warntpl}
1836
			AND (id_recipient = {string:generic} OR id_recipient = {int:current_member})',
1837
		array(
1838
			'warntpl' => 'warntpl',
1839
			'generic' => 0,
1840
			'current_member' => $user_info['id'],
1841
		)
1842
	);
1843
	list ($totalWarns) = $smcFunc['db_fetch_row']($request);
1844
	$smcFunc['db_free_result']($request);
1845
1846
	return $totalWarns;
1847
}
1848
1849
/**
1850
 * Callback for createList().
1851
 *
1852
 * @param int $start The item to start with (for pagination purposes)
1853
 * @param int $items_per_page The number of items to show per page
1854
 * @param string $sort A string indicating how to sort the results
1855
 * @return array An arrray of info about the available warning templates
1856
 */
1857
function list_getWarningTemplates($start, $items_per_page, $sort)
1858
{
1859
	global $smcFunc, $scripturl, $user_info;
1860
1861
	$request = $smcFunc['db_query']('', '
1862
		SELECT lc.id_comment, COALESCE(mem.id_member, 0) AS id_member,
1863
			COALESCE(mem.real_name, lc.member_name) AS creator_name, recipient_name AS template_title,
1864
			lc.log_time, lc.body
1865
		FROM {db_prefix}log_comments AS lc
1866
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lc.id_member)
1867
		WHERE lc.comment_type = {string:warntpl}
1868
			AND (id_recipient = {string:generic} OR id_recipient = {int:current_member})
1869
		ORDER BY ' . $sort . '
1870
		LIMIT ' . $start . ', ' . $items_per_page,
1871
		array(
1872
			'warntpl' => 'warntpl',
1873
			'generic' => 0,
1874
			'current_member' => $user_info['id'],
1875
		)
1876
	);
1877
	$templates = array();
1878
	while ($row = $smcFunc['db_fetch_assoc']($request))
1879
	{
1880
		$templates[] = array(
1881
			'id_comment' => $row['id_comment'],
1882
			'creator' => $row['id_member'] ? ('<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['creator_name'] . '</a>') : $row['creator_name'],
1883
			'time' => timeformat($row['log_time']),
1884
			'title' => $row['template_title'],
1885
			'body' => $smcFunc['htmlspecialchars']($row['body']),
1886
		);
1887
	}
1888
	$smcFunc['db_free_result']($request);
1889
1890
	return $templates;
1891
}
1892
1893
/**
1894
 * Edit a warning template.
1895
 */
1896
function ModifyWarningTemplate()
1897
{
1898
	global $smcFunc, $context, $txt, $user_info, $sourcedir;
1899
1900
	$context['id_template'] = isset($_REQUEST['tid']) ? (int) $_REQUEST['tid'] : 0;
1901
	$context['is_edit'] = $context['id_template'];
1902
1903
	// Standard template things.
1904
	$context['page_title'] = $context['is_edit'] ? $txt['mc_warning_template_modify'] : $txt['mc_warning_template_add'];
1905
	$context['sub_template'] = 'warn_template';
1906
	$context[$context['moderation_menu_name']]['current_subsection'] = 'templates';
1907
1908
	// Defaults.
1909
	$context['template_data'] = array(
1910
		'title' => '',
1911
		'body' => $txt['mc_warning_template_body_default'],
1912
		'personal' => false,
1913
		'can_edit_personal' => true,
1914
	);
1915
1916
	// If it's an edit load it.
1917
	if ($context['is_edit'])
1918
	{
1919
		$request = $smcFunc['db_query']('', '
1920
			SELECT id_member, id_recipient, recipient_name AS template_title, body
1921
			FROM {db_prefix}log_comments
1922
			WHERE id_comment = {int:id}
1923
				AND comment_type = {string:warntpl}
1924
				AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})',
1925
			array(
1926
				'id' => $context['id_template'],
1927
				'warntpl' => 'warntpl',
1928
				'generic' => 0,
1929
				'current_member' => $user_info['id'],
1930
			)
1931
		);
1932
		while ($row = $smcFunc['db_fetch_assoc']($request))
1933
		{
1934
			$context['template_data'] = array(
1935
				'title' => $row['template_title'],
1936
				'body' => $smcFunc['htmlspecialchars']($row['body']),
1937
				'personal' => $row['id_recipient'],
1938
				'can_edit_personal' => $row['id_member'] == $user_info['id'],
1939
			);
1940
		}
1941
		$smcFunc['db_free_result']($request);
1942
	}
1943
1944
	// Wait, we are saving?
1945
	if (isset($_POST['save']))
1946
	{
1947
		checkSession();
1948
		validateToken('mod-wt');
1949
1950
		// To check the BBC is pretty good...
1951
		require_once($sourcedir . '/Subs-Post.php');
1952
1953
		// Bit of cleaning!
1954
		$_POST['template_body'] = trim($_POST['template_body']);
1955
		$_POST['template_title'] = trim($_POST['template_title']);
1956
1957
		// Need something in both boxes.
1958
		if (!empty($_POST['template_body']) && !empty($_POST['template_title']))
1959
		{
1960
			// Safety first.
1961
			$_POST['template_title'] = $smcFunc['htmlspecialchars']($_POST['template_title']);
1962
1963
			// Clean up BBC.
1964
			preparsecode($_POST['template_body']);
1965
			// But put line breaks back!
1966
			$_POST['template_body'] = strtr($_POST['template_body'], array('<br>' => "\n"));
1967
1968
			// Is this personal?
1969
			$recipient_id = !empty($_POST['make_personal']) ? $user_info['id'] : 0;
1970
1971
			// If we are this far it's save time.
1972
			if ($context['is_edit'])
1973
			{
1974
				// Simple update...
1975
				$smcFunc['db_query']('', '
1976
					UPDATE {db_prefix}log_comments
1977
					SET id_recipient = {int:personal}, recipient_name = {string:title}, body = {string:body}
1978
					WHERE id_comment = {int:id}
1979
						AND comment_type = {string:warntpl}
1980
						AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})'.
1981
						($recipient_id ? ' AND id_member = {int:current_member}' : ''),
1982
					array(
1983
						'personal' => $recipient_id,
1984
						'title' => $_POST['template_title'],
1985
						'body' => $_POST['template_body'],
1986
						'id' => $context['id_template'],
1987
						'warntpl' => 'warntpl',
1988
						'generic' => 0,
1989
						'current_member' => $user_info['id'],
1990
					)
1991
				);
1992
1993
				// If it wasn't visible and now is they've effectively added it.
1994
				if ($context['template_data']['personal'] && !$recipient_id)
1995
					logAction('add_warn_template', array('template' => $_POST['template_title']));
1996
				// Conversely if they made it personal it's a delete.
1997
				elseif (!$context['template_data']['personal'] && $recipient_id)
1998
					logAction('delete_warn_template', array('template' => $_POST['template_title']));
1999
				// Otherwise just an edit.
2000
				else
2001
					logAction('modify_warn_template', array('template' => $_POST['template_title']));
2002
			}
2003
			else
2004
			{
2005
				$smcFunc['db_insert']('',
2006
					'{db_prefix}log_comments',
2007
					array(
2008
						'id_member' => 'int', 'member_name' => 'string', 'comment_type' => 'string', 'id_recipient' => 'int',
2009
						'recipient_name' => 'string-255', 'body' => 'string-65535', 'log_time' => 'int',
2010
					),
2011
					array(
2012
						$user_info['id'], $user_info['name'], 'warntpl', $recipient_id,
2013
						$_POST['template_title'], $_POST['template_body'], time(),
2014
					),
2015
					array('id_comment')
2016
				);
2017
2018
				logAction('add_warn_template', array('template' => $_POST['template_title']));
2019
			}
2020
2021
			// Get out of town...
2022
			redirectexit('action=moderate;area=warnings;sa=templates');
2023
		}
2024
		else
2025
		{
2026
			$context['warning_errors'] = array();
2027
			$context['template_data']['title'] = !empty($_POST['template_title']) ? $_POST['template_title'] : '';
2028
			$context['template_data']['body'] = !empty($_POST['template_body']) ? $_POST['template_body'] : $txt['mc_warning_template_body_default'];
2029
			$context['template_data']['personal'] = !empty($_POST['make_personal']);
2030
2031
			if (empty($_POST['template_title']))
2032
				$context['warning_errors'][] = $txt['mc_warning_template_error_no_title'];
2033
			if (empty($_POST['template_body']))
2034
				$context['warning_errors'][] = $txt['mc_warning_template_error_no_body'];
2035
		}
2036
	}
2037
2038
	createToken('mod-wt');
2039
}
2040
2041
/**
2042
 * Change moderation preferences.
2043
 */
2044
function ModerationSettings()
2045
{
2046
	global $context, $txt, $user_info;
2047
2048
	// Some useful context stuff.
2049
	loadTemplate('ModerationCenter');
2050
	$context['page_title'] = $txt['mc_settings'];
2051
	$context['sub_template'] = 'moderation_settings';
2052
	$context[$context['moderation_menu_name']]['tab_data'] = array(
2053
		'title' => $txt['mc_prefs_title'],
2054
		'help' => '',
2055
		'description' => $txt['mc_prefs_desc']
2056
	);
2057
2058
	$pref_binary = 5;
0 ignored issues
show
Unused Code introduced by
The assignment to $pref_binary is dead and can be removed.
Loading history...
2059
2060
	// Are we saving?
2061
	if (isset($_POST['save']))
2062
	{
2063
		checkSession();
2064
		validateToken('mod-set');
2065
2066
		/* Current format of mod_prefs is:
2067
			x|ABCD|yyy
2068
2069
			WHERE:
2070
				x = Show report count on forum header.
2071
				ABCD = Block indexes to show on moderation main page.
2072
				yyy = Integer with the following bit status:
2073
					- yyy & 4 = Notify about posts awaiting approval.
2074
		*/
2075
2076
		// Now check other options!
2077
		$pref_binary = 0;
2078
2079
		// Put it all together.
2080
		$mod_prefs = '0||' . $pref_binary;
2081
		updateMemberData($user_info['id'], array('mod_prefs' => $mod_prefs));
2082
	}
2083
2084
	// What blocks does the user currently have selected?
2085
	$context['mod_settings'] = array(
2086
	);
2087
2088
	createToken('mod-set');
2089
}
2090
2091
/**
2092
 * This ends a moderator session, requiring authentication to access the MCP again.
2093
 */
2094
function ModEndSession()
2095
{
2096
	// This is so easy!
2097
	unset($_SESSION['moderate_time']);
2098
2099
	// Clean any moderator tokens as well.
2100
	foreach ($_SESSION['token'] as $key => $token)
2101
		if (strpos($key, '-mod') !== false)
2102
			unset($_SESSION['token'][$key]);
2103
2104
	redirectexit();
2105
}
2106
2107
?>