Issues (1061)

Sources/ModerationCenter.php (3 issues)

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 2020 Simple Machines and individual contributors
11
 * @license https://www.simplemachines.org/about/smf/license.php BSD
12
 *
13
 * @version 2.1 RC2
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
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 && $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);
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
1242
			WHERE {query_see_message_board}
1243
				AND m.id_member IN ({array_int:member_list})' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : '
1244
				AND m.approved = {int:is_approved}') . '
1245
			GROUP BY m.id_member',
1246
			array(
1247
				'member_list' => $members,
1248
				'is_approved' => 1,
1249
			)
1250
		);
1251
		$latest_posts = array();
1252
		while ($row = $smcFunc['db_fetch_assoc']($request))
1253
			$latest_posts[$row['id_member']] = $row['last_post_id'];
1254
1255
		if (!empty($latest_posts))
1256
		{
1257
			// Now get the time those messages were posted.
1258
			$request = $smcFunc['db_query']('', '
1259
				SELECT id_member, poster_time
1260
				FROM {db_prefix}messages
1261
				WHERE id_msg IN ({array_int:message_list})',
1262
				array(
1263
					'message_list' => $latest_posts,
1264
				)
1265
			);
1266
			while ($row = $smcFunc['db_fetch_assoc']($request))
1267
			{
1268
				$watched_users[$row['id_member']]['last_post'] = timeformat($row['poster_time']);
1269
				$watched_users[$row['id_member']]['last_post_id'] = $latest_posts[$row['id_member']];
1270
			}
1271
1272
			$smcFunc['db_free_result']($request);
1273
		}
1274
1275
		$request = $smcFunc['db_query']('', '
1276
			SELECT MAX(m.poster_time) AS last_post, MAX(m.id_msg) AS last_post_id, m.id_member
1277
			FROM {db_prefix}messages AS m
1278
			WHERE {query_see_message_board}
1279
				AND m.id_member IN ({array_int:member_list})' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : '
1280
				AND m.approved = {int:is_approved}') . '
1281
			GROUP BY m.id_member',
1282
			array(
1283
				'member_list' => $members,
1284
				'is_approved' => 1,
1285
			)
1286
		);
1287
		while ($row = $smcFunc['db_fetch_assoc']($request))
1288
		{
1289
			$watched_users[$row['id_member']]['last_post'] = timeformat($row['last_post']);
1290
			$watched_users[$row['id_member']]['last_post_id'] = $row['last_post_id'];
1291
		}
1292
		$smcFunc['db_free_result']($request);
1293
	}
1294
1295
	return $watched_users;
1296
}
1297
1298
/**
1299
 * Callback for createList().
1300
 *
1301
 * @param string $approve_query A query to pull only approved items
1302
 * @return int The total number of posts by watched users
1303
 */
1304
function list_getWatchedUserPostsCount($approve_query)
1305
{
1306
	global $smcFunc, $modSettings;
1307
1308
	$request = $smcFunc['db_query']('', '
1309
		SELECT COUNT(*)
1310
		FROM {db_prefix}messages AS m
1311
			INNER JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
1312
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
1313
		WHERE mem.warning >= {int:warning_watch}
1314
			AND {query_see_board}
1315
			' . $approve_query,
1316
		array(
1317
			'warning_watch' => $modSettings['warning_watch'],
1318
		)
1319
	);
1320
	list ($totalMemberPosts) = $smcFunc['db_fetch_row']($request);
1321
	$smcFunc['db_free_result']($request);
1322
1323
	return $totalMemberPosts;
1324
}
1325
1326
/**
1327
 * Callback for createList().
1328
 *
1329
 * @param int $start The item to start with (for pagination purposes)
1330
 * @param int $items_per_page The number of items to show per page
1331
 * @param string $sort A string indicating how to sort the results (not used here)
1332
 * @param string $approve_query A query to only pull approved items
1333
 * @param int[] $delete_boards An array containing the IDs of boards we can delete posts in
1334
 * @return array An array of info about posts by watched users
1335
 */
1336
function list_getWatchedUserPosts($start, $items_per_page, $sort, $approve_query, $delete_boards)
1337
{
1338
	global $smcFunc, $scripturl, $modSettings;
1339
1340
	$request = $smcFunc['db_query']('', '
1341
		SELECT m.id_msg, m.id_topic, m.id_board, m.id_member, m.subject, m.body, m.poster_time,
1342
			m.approved, mem.real_name, m.smileys_enabled
1343
		FROM {db_prefix}messages AS m
1344
			INNER JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
1345
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
1346
		WHERE mem.warning >= {int:warning_watch}
1347
			AND {query_see_board}
1348
			' . $approve_query . '
1349
		ORDER BY m.id_msg DESC
1350
		LIMIT {int:start}, {int:max}',
1351
		array(
1352
			'warning_watch' => $modSettings['warning_watch'],
1353
			'start' => $start,
1354
			'max' => $items_per_page,
1355
		)
1356
	);
1357
	$member_posts = array();
1358
	while ($row = $smcFunc['db_fetch_assoc']($request))
1359
	{
1360
		$row['subject'] = censorText($row['subject']);
1361
		$row['body'] = censorText($row['body']);
1362
1363
		$member_posts[$row['id_msg']] = array(
1364
			'id' => $row['id_msg'],
1365
			'id_topic' => $row['id_topic'],
1366
			'author_link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>',
1367
			'subject' => $row['subject'],
1368
			'body' => parse_bbc($row['body'], $row['smileys_enabled'], $row['id_msg']),
1369
			'poster_time' => timeformat($row['poster_time']),
1370
			'approved' => $row['approved'],
1371
			'can_delete' => $delete_boards == array(0) || in_array($row['id_board'], $delete_boards),
1372
		);
1373
	}
1374
	$smcFunc['db_free_result']($request);
1375
1376
	return $member_posts;
1377
}
1378
1379
/**
1380
 * Entry point for viewing warning related stuff.
1381
 */
1382
function ViewWarnings()
1383
{
1384
	global $context, $txt;
1385
1386
	$subActions = array(
1387
		'log' => array('ViewWarningLog'),
1388
		'templateedit' => array('ModifyWarningTemplate', 'issue_warning'),
1389
		'templates' => array('ViewWarningTemplates', 'issue_warning'),
1390
	);
1391
1392
	call_integration_hook('integrate_warning_log_actions', array(&$subActions));
1393
1394
	$_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) && (empty($subActions[$_REQUEST['sa']][1]) || allowedTo($subActions[$_REQUEST['sa']])) ? $_REQUEST['sa'] : 'log';
1395
1396
	// Some of this stuff is overseas, so to speak.
1397
	loadTemplate('ModerationCenter');
1398
	loadLanguage('Profile');
1399
1400
	// Setup the admin tabs.
1401
	$context[$context['moderation_menu_name']]['tab_data'] = array(
1402
		'title' => $txt['mc_warnings'],
1403
		'description' => $txt['mc_warnings_description'],
1404
	);
1405
1406
	// Call the right function.
1407
	call_helper($subActions[$_REQUEST['sa']][0]);
1408
}
1409
1410
/**
1411
 * Simply put, look at the warning log!
1412
 */
1413
function ViewWarningLog()
1414
{
1415
	global $smcFunc, $modSettings, $context, $txt, $scripturl, $sourcedir;
1416
1417
	// Setup context as always.
1418
	$context['page_title'] = $txt['mc_warning_log_title'];
1419
1420
	loadLanguage('Modlog');
1421
1422
	// If we're coming from a search, get the variables.
1423
	if (!empty($_REQUEST['params']) && empty($_REQUEST['is_search']))
1424
	{
1425
		$search_params = base64_decode(strtr($_REQUEST['params'], array(' ' => '+')));
1426
		$search_params = $smcFunc['json_decode']($search_params, true);
1427
	}
1428
1429
	// This array houses all the valid search types.
1430
	$searchTypes = array(
1431
		'member' => array('sql' => 'member_name_col', 'label' => $txt['profile_warning_previous_issued']),
1432
		'recipient' => array('sql' => 'recipient_name', 'label' => $txt['mc_warnings_recipient']),
1433
	);
1434
1435
	// Do the column stuff!
1436
	$sort_types = array(
1437
		'member' => 'member_name_col',
1438
		'recipient' => 'recipient_name',
1439
	);
1440
1441
	// Setup the direction stuff...
1442
	$context['order'] = isset($_REQUEST['sort']) && isset($sort_types[$_REQUEST['sort']]) ? $_REQUEST['sort'] : 'member';
1443
1444
	if (!isset($search_params['string']) || (!empty($_REQUEST['search']) && $search_params['string'] != $_REQUEST['search']))
1445
		$search_params_string = empty($_REQUEST['search']) ? '' : $_REQUEST['search'];
1446
	else
1447
		$search_params_string = $search_params['string'];
1448
1449
	if (isset($_REQUEST['search_type']) || empty($search_params['type']) || !isset($searchTypes[$search_params['type']]))
1450
		$search_params_type = isset($_REQUEST['search_type']) && isset($searchTypes[$_REQUEST['search_type']]) ? $_REQUEST['search_type'] : (isset($searchTypes[$context['order']]) ? $context['order'] : 'member');
1451
	else
1452
		$search_params_type = $search_params['type'];
1453
1454
	$search_params = array(
1455
		'string' => $search_params_string,
1456
		'type' => $search_params_type,
1457
	);
1458
1459
	$context['url_start'] = '?action=moderate;area=warnings;sa=log;sort=' . $context['order'];
1460
1461
	// Setup the search context.
1462
	$context['search_params'] = empty($search_params['string']) ? '' : base64_encode($smcFunc['json_encode']($search_params));
1463
	$context['search'] = array(
1464
		'string' => $search_params['string'],
1465
		'type' => $search_params['type'],
1466
		'label' => $searchTypes[$search_params_type]['label'],
1467
	);
1468
1469
	require_once($sourcedir . '/Subs-List.php');
1470
1471
	// This is all the information required for a watched user listing.
1472
	$listOptions = array(
1473
		'id' => 'warning_list',
1474
		'title' => $txt['mc_warning_log_title'],
1475
		'items_per_page' => $modSettings['defaultMaxListItems'],
1476
		'no_items_label' => $txt['mc_warnings_none'],
1477
		'base_href' => $scripturl . '?action=moderate;area=warnings;sa=log;' . $context['session_var'] . '=' . $context['session_id'],
1478
		'default_sort_col' => 'time',
1479
		'get_items' => array(
1480
			'function' => 'list_getWarnings',
1481
		),
1482
		'get_count' => array(
1483
			'function' => 'list_getWarningCount',
1484
		),
1485
		// This assumes we are viewing by user.
1486
		'columns' => array(
1487
			'issuer' => array(
1488
				'header' => array(
1489
					'value' => $txt['profile_warning_previous_issued'],
1490
				),
1491
				'data' => array(
1492
					'db' => 'issuer_link',
1493
				),
1494
				'sort' => array(
1495
					'default' => 'member_name_col',
1496
					'reverse' => 'member_name_col DESC',
1497
				),
1498
			),
1499
			'recipient' => array(
1500
				'header' => array(
1501
					'value' => $txt['mc_warnings_recipient'],
1502
				),
1503
				'data' => array(
1504
					'db' => 'recipient_link',
1505
				),
1506
				'sort' => array(
1507
					'default' => 'recipient_name',
1508
					'reverse' => 'recipient_name DESC',
1509
				),
1510
			),
1511
			'time' => array(
1512
				'header' => array(
1513
					'value' => $txt['profile_warning_previous_time'],
1514
				),
1515
				'data' => array(
1516
					'db' => 'time',
1517
				),
1518
				'sort' => array(
1519
					'default' => 'lc.log_time DESC',
1520
					'reverse' => 'lc.log_time',
1521
				),
1522
			),
1523
			'reason' => array(
1524
				'header' => array(
1525
					'value' => $txt['profile_warning_previous_reason'],
1526
				),
1527
				'data' => array(
1528
					'function' => function($rowData) use ($scripturl, $txt)
1529
					{
1530
						$output = '
1531
							<div class="floatleft">
1532
								' . $rowData['reason'] . '
1533
							</div>';
1534
1535
						if (!empty($rowData['id_notice']))
1536
							$output .= '
1537
								&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>';
1538
						return $output;
1539
					},
1540
				),
1541
			),
1542
			'points' => array(
1543
				'header' => array(
1544
					'value' => $txt['profile_warning_previous_level'],
1545
				),
1546
				'data' => array(
1547
					'db' => 'counter',
1548
				),
1549
			),
1550
		),
1551
		'form' => array(
1552
			'href' => $scripturl . $context['url_start'],
1553
			'include_sort' => true,
1554
			'include_start' => true,
1555
			'hidden_fields' => array(
1556
				$context['session_var'] => $context['session_id'],
1557
				'params' => false
1558
			),
1559
		),
1560
		'additional_rows' => array(
1561
			array(
1562
				'position' => 'below_table_data',
1563
				'value' => '
1564
					' . $txt['modlog_search'] . ':
1565
					<input type="text" name="search" size="18" value="' . $smcFunc['htmlspecialchars']($context['search']['string']) . '">
1566
					<input type="submit" name="is_search" value="' . $txt['modlog_go'] . '" class="button">',
1567
				'class' => 'floatright',
1568
			),
1569
		),
1570
	);
1571
1572
	// Create the watched user list.
1573
	createList($listOptions);
1574
1575
	$context['sub_template'] = 'show_list';
1576
	$context['default_list'] = 'warning_list';
1577
}
1578
1579
/**
1580
 * Callback for createList().
1581
 *
1582
 * @return int The total number of warnings that have been issued
1583
 */
1584
function list_getWarningCount()
1585
{
1586
	global $smcFunc;
1587
1588
	$request = $smcFunc['db_query']('', '
1589
		SELECT COUNT(*)
1590
		FROM {db_prefix}log_comments
1591
		WHERE comment_type = {string:warning}',
1592
		array(
1593
			'warning' => 'warning',
1594
		)
1595
	);
1596
	list ($totalWarns) = $smcFunc['db_fetch_row']($request);
1597
	$smcFunc['db_free_result']($request);
1598
1599
	return $totalWarns;
1600
}
1601
1602
/**
1603
 * Callback for createList().
1604
 *
1605
 * @param int $start The item to start with (for pagination purposes)
1606
 * @param int $items_per_page The number of items to show per page
1607
 * @param string $sort A string indicating how to sort the results
1608
 * @return array An array of data about warning log entries
1609
 */
1610
function list_getWarnings($start, $items_per_page, $sort)
1611
{
1612
	global $smcFunc, $scripturl;
1613
1614
	$request = $smcFunc['db_query']('', '
1615
		SELECT COALESCE(mem.id_member, 0) AS id_member, COALESCE(mem.real_name, lc.member_name) AS member_name_col,
1616
			COALESCE(mem2.id_member, 0) AS id_recipient, COALESCE(mem2.real_name, lc.recipient_name) AS recipient_name,
1617
			lc.log_time, lc.body, lc.id_notice, lc.counter
1618
		FROM {db_prefix}log_comments AS lc
1619
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lc.id_member)
1620
			LEFT JOIN {db_prefix}members AS mem2 ON (mem2.id_member = lc.id_recipient)
1621
		WHERE lc.comment_type = {string:warning}
1622
		ORDER BY {raw:sort}
1623
		LIMIT {int:start}, {int:max}',
1624
		array(
1625
			'warning' => 'warning',
1626
			'start' => $start,
1627
			'max' => $items_per_page,
1628
			'sort' => $sort,
1629
		)
1630
	);
1631
	$warnings = array();
1632
	while ($row = $smcFunc['db_fetch_assoc']($request))
1633
	{
1634
		$warnings[] = array(
1635
			'issuer_link' => $row['id_member'] ? ('<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['member_name_col'] . '</a>') : $row['member_name_col'],
1636
			'recipient_link' => $row['id_recipient'] ? ('<a href="' . $scripturl . '?action=profile;u=' . $row['id_recipient'] . '">' . $row['recipient_name'] . '</a>') : $row['recipient_name'],
1637
			'time' => timeformat($row['log_time']),
1638
			'reason' => $row['body'],
1639
			'counter' => $row['counter'] > 0 ? '+' . $row['counter'] : $row['counter'],
1640
			'id_notice' => $row['id_notice'],
1641
		);
1642
	}
1643
	$smcFunc['db_free_result']($request);
1644
1645
	return $warnings;
1646
}
1647
1648
/**
1649
 * Load all the warning templates.
1650
 */
1651
function ViewWarningTemplates()
1652
{
1653
	global $smcFunc, $modSettings, $context, $txt, $scripturl, $sourcedir, $user_info;
1654
1655
	// Submitting a new one?
1656
	if (isset($_POST['add']))
1657
		return ModifyWarningTemplate();
0 ignored issues
show
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...
1658
	elseif (isset($_POST['delete']) && !empty($_POST['deltpl']))
1659
	{
1660
		checkSession();
1661
		validateToken('mod-wt');
1662
1663
		// Log the actions.
1664
		$request = $smcFunc['db_query']('', '
1665
			SELECT recipient_name
1666
			FROM {db_prefix}log_comments
1667
			WHERE id_comment IN ({array_int:delete_ids})
1668
				AND comment_type = {string:warntpl}
1669
				AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})',
1670
			array(
1671
				'delete_ids' => $_POST['deltpl'],
1672
				'warntpl' => 'warntpl',
1673
				'generic' => 0,
1674
				'current_member' => $user_info['id'],
1675
			)
1676
		);
1677
		while ($row = $smcFunc['db_fetch_assoc']($request))
1678
			logAction('delete_warn_template', array('template' => $row['recipient_name']));
1679
		$smcFunc['db_free_result']($request);
1680
1681
		// Do the deletes.
1682
		$smcFunc['db_query']('', '
1683
			DELETE FROM {db_prefix}log_comments
1684
			WHERE id_comment IN ({array_int:delete_ids})
1685
				AND comment_type = {string:warntpl}
1686
				AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})',
1687
			array(
1688
				'delete_ids' => $_POST['deltpl'],
1689
				'warntpl' => 'warntpl',
1690
				'generic' => 0,
1691
				'current_member' => $user_info['id'],
1692
			)
1693
		);
1694
	}
1695
1696
	// Setup context as always.
1697
	$context['page_title'] = $txt['mc_warning_templates_title'];
1698
1699
	require_once($sourcedir . '/Subs-List.php');
1700
1701
	// This is all the information required for a watched user listing.
1702
	$listOptions = array(
1703
		'id' => 'warning_template_list',
1704
		'title' => $txt['mc_warning_templates_title'],
1705
		'items_per_page' => $modSettings['defaultMaxListItems'],
1706
		'no_items_label' => $txt['mc_warning_templates_none'],
1707
		'base_href' => $scripturl . '?action=moderate;area=warnings;sa=templates;' . $context['session_var'] . '=' . $context['session_id'],
1708
		'default_sort_col' => 'title',
1709
		'get_items' => array(
1710
			'function' => 'list_getWarningTemplates',
1711
		),
1712
		'get_count' => array(
1713
			'function' => 'list_getWarningTemplateCount',
1714
		),
1715
		// This assumes we are viewing by user.
1716
		'columns' => array(
1717
			'title' => array(
1718
				'header' => array(
1719
					'value' => $txt['mc_warning_templates_name'],
1720
				),
1721
				'data' => array(
1722
					'sprintf' => array(
1723
						'format' => '<a href="' . $scripturl . '?action=moderate;area=warnings;sa=templateedit;tid=%1$d">%2$s</a>',
1724
						'params' => array(
1725
							'id_comment' => false,
1726
							'title' => false,
1727
							'body' => false,
1728
						),
1729
					),
1730
				),
1731
				'sort' => array(
1732
					'default' => 'template_title',
1733
					'reverse' => 'template_title DESC',
1734
				),
1735
			),
1736
			'creator' => array(
1737
				'header' => array(
1738
					'value' => $txt['mc_warning_templates_creator'],
1739
				),
1740
				'data' => array(
1741
					'db' => 'creator',
1742
				),
1743
				'sort' => array(
1744
					'default' => 'creator_name',
1745
					'reverse' => 'creator_name DESC',
1746
				),
1747
			),
1748
			'time' => array(
1749
				'header' => array(
1750
					'value' => $txt['mc_warning_templates_time'],
1751
				),
1752
				'data' => array(
1753
					'db' => 'time',
1754
				),
1755
				'sort' => array(
1756
					'default' => 'lc.log_time DESC',
1757
					'reverse' => 'lc.log_time',
1758
				),
1759
			),
1760
			'delete' => array(
1761
				'header' => array(
1762
					'value' => '<input type="checkbox" onclick="invertAll(this, this.form);">',
1763
					'style' => 'width: 4%;',
1764
					'class' => 'centercol',
1765
				),
1766
				'data' => array(
1767
					'function' => function($rowData)
1768
					{
1769
						return '<input type="checkbox" name="deltpl[]" value="' . $rowData['id_comment'] . '">';
1770
					},
1771
					'class' => 'centercol',
1772
				),
1773
			),
1774
		),
1775
		'form' => array(
1776
			'href' => $scripturl . '?action=moderate;area=warnings;sa=templates',
1777
			'token' => 'mod-wt',
1778
		),
1779
		'additional_rows' => array(
1780
			array(
1781
				'position' => 'bottom_of_list',
1782
				'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">',
1783
			),
1784
			array(
1785
				'position' => 'bottom_of_list',
1786
				'value' => '<input type="submit" name="add" value="' . $txt['mc_warning_template_add'] . '" class="button">',
1787
			),
1788
		),
1789
	);
1790
1791
	// Create the watched user list.
1792
	createToken('mod-wt');
1793
	createList($listOptions);
1794
1795
	$context['sub_template'] = 'show_list';
1796
	$context['default_list'] = 'warning_template_list';
1797
}
1798
1799
/**
1800
 * Callback for createList().
1801
 *
1802
 * @return int The total number of warning templates
1803
 */
1804
function list_getWarningTemplateCount()
1805
{
1806
	global $smcFunc, $user_info;
1807
1808
	$request = $smcFunc['db_query']('', '
1809
		SELECT COUNT(*)
1810
		FROM {db_prefix}log_comments
1811
		WHERE comment_type = {string:warntpl}
1812
			AND (id_recipient = {string:generic} OR id_recipient = {int:current_member})',
1813
		array(
1814
			'warntpl' => 'warntpl',
1815
			'generic' => 0,
1816
			'current_member' => $user_info['id'],
1817
		)
1818
	);
1819
	list ($totalWarns) = $smcFunc['db_fetch_row']($request);
1820
	$smcFunc['db_free_result']($request);
1821
1822
	return $totalWarns;
1823
}
1824
1825
/**
1826
 * Callback for createList().
1827
 *
1828
 * @param int $start The item to start with (for pagination purposes)
1829
 * @param int $items_per_page The number of items to show per page
1830
 * @param string $sort A string indicating how to sort the results
1831
 * @return array An arrray of info about the available warning templates
1832
 */
1833
function list_getWarningTemplates($start, $items_per_page, $sort)
1834
{
1835
	global $smcFunc, $scripturl, $user_info;
1836
1837
	$request = $smcFunc['db_query']('', '
1838
		SELECT lc.id_comment, COALESCE(mem.id_member, 0) AS id_member,
1839
			COALESCE(mem.real_name, lc.member_name) AS creator_name, recipient_name AS template_title,
1840
			lc.log_time, lc.body
1841
		FROM {db_prefix}log_comments AS lc
1842
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lc.id_member)
1843
		WHERE lc.comment_type = {string:warntpl}
1844
			AND (id_recipient = {string:generic} OR id_recipient = {int:current_member})
1845
		ORDER BY ' . $sort . '
1846
		LIMIT ' . $start . ', ' . $items_per_page,
1847
		array(
1848
			'warntpl' => 'warntpl',
1849
			'generic' => 0,
1850
			'current_member' => $user_info['id'],
1851
		)
1852
	);
1853
	$templates = array();
1854
	while ($row = $smcFunc['db_fetch_assoc']($request))
1855
	{
1856
		$templates[] = array(
1857
			'id_comment' => $row['id_comment'],
1858
			'creator' => $row['id_member'] ? ('<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['creator_name'] . '</a>') : $row['creator_name'],
1859
			'time' => timeformat($row['log_time']),
1860
			'title' => $row['template_title'],
1861
			'body' => $smcFunc['htmlspecialchars']($row['body']),
1862
		);
1863
	}
1864
	$smcFunc['db_free_result']($request);
1865
1866
	return $templates;
1867
}
1868
1869
/**
1870
 * Edit a warning template.
1871
 */
1872
function ModifyWarningTemplate()
1873
{
1874
	global $smcFunc, $context, $txt, $user_info, $sourcedir;
1875
1876
	$context['id_template'] = isset($_REQUEST['tid']) ? (int) $_REQUEST['tid'] : 0;
1877
	$context['is_edit'] = $context['id_template'];
1878
1879
	// Standard template things.
1880
	$context['page_title'] = $context['is_edit'] ? $txt['mc_warning_template_modify'] : $txt['mc_warning_template_add'];
1881
	$context['sub_template'] = 'warn_template';
1882
	$context[$context['moderation_menu_name']]['current_subsection'] = 'templates';
1883
1884
	// Defaults.
1885
	$context['template_data'] = array(
1886
		'title' => '',
1887
		'body' => $txt['mc_warning_template_body_default'],
1888
		'personal' => false,
1889
		'can_edit_personal' => true,
1890
	);
1891
1892
	// If it's an edit load it.
1893
	if ($context['is_edit'])
1894
	{
1895
		$request = $smcFunc['db_query']('', '
1896
			SELECT id_member, id_recipient, recipient_name AS template_title, body
1897
			FROM {db_prefix}log_comments
1898
			WHERE id_comment = {int:id}
1899
				AND comment_type = {string:warntpl}
1900
				AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})',
1901
			array(
1902
				'id' => $context['id_template'],
1903
				'warntpl' => 'warntpl',
1904
				'generic' => 0,
1905
				'current_member' => $user_info['id'],
1906
			)
1907
		);
1908
		while ($row = $smcFunc['db_fetch_assoc']($request))
1909
		{
1910
			$context['template_data'] = array(
1911
				'title' => $row['template_title'],
1912
				'body' => $smcFunc['htmlspecialchars']($row['body']),
1913
				'personal' => $row['id_recipient'],
1914
				'can_edit_personal' => $row['id_member'] == $user_info['id'],
1915
			);
1916
		}
1917
		$smcFunc['db_free_result']($request);
1918
	}
1919
1920
	// Wait, we are saving?
1921
	if (isset($_POST['save']))
1922
	{
1923
		checkSession();
1924
		validateToken('mod-wt');
1925
1926
		// To check the BBC is pretty good...
1927
		require_once($sourcedir . '/Subs-Post.php');
1928
1929
		// Bit of cleaning!
1930
		$_POST['template_body'] = trim($_POST['template_body']);
1931
		$_POST['template_title'] = trim($_POST['template_title']);
1932
1933
		// Need something in both boxes.
1934
		if (!empty($_POST['template_body']) && !empty($_POST['template_title']))
1935
		{
1936
			// Safety first.
1937
			$_POST['template_title'] = $smcFunc['htmlspecialchars']($_POST['template_title']);
1938
1939
			// Clean up BBC.
1940
			preparsecode($_POST['template_body']);
1941
			// But put line breaks back!
1942
			$_POST['template_body'] = strtr($_POST['template_body'], array('<br>' => "\n"));
1943
1944
			// Is this personal?
1945
			$recipient_id = !empty($_POST['make_personal']) ? $user_info['id'] : 0;
1946
1947
			// If we are this far it's save time.
1948
			if ($context['is_edit'])
1949
			{
1950
				// Simple update...
1951
				$smcFunc['db_query']('', '
1952
					UPDATE {db_prefix}log_comments
1953
					SET id_recipient = {int:personal}, recipient_name = {string:title}, body = {string:body}
1954
					WHERE id_comment = {int:id}
1955
						AND comment_type = {string:warntpl}
1956
						AND (id_recipient = {int:generic} OR id_recipient = {int:current_member})'.
1957
						($recipient_id ? ' AND id_member = {int:current_member}' : ''),
1958
					array(
1959
						'personal' => $recipient_id,
1960
						'title' => $_POST['template_title'],
1961
						'body' => $_POST['template_body'],
1962
						'id' => $context['id_template'],
1963
						'warntpl' => 'warntpl',
1964
						'generic' => 0,
1965
						'current_member' => $user_info['id'],
1966
					)
1967
				);
1968
1969
				// If it wasn't visible and now is they've effectively added it.
1970
				if ($context['template_data']['personal'] && !$recipient_id)
1971
					logAction('add_warn_template', array('template' => $_POST['template_title']));
1972
				// Conversely if they made it personal it's a delete.
1973
				elseif (!$context['template_data']['personal'] && $recipient_id)
1974
					logAction('delete_warn_template', array('template' => $_POST['template_title']));
1975
				// Otherwise just an edit.
1976
				else
1977
					logAction('modify_warn_template', array('template' => $_POST['template_title']));
1978
			}
1979
			else
1980
			{
1981
				$smcFunc['db_insert']('',
1982
					'{db_prefix}log_comments',
1983
					array(
1984
						'id_member' => 'int', 'member_name' => 'string', 'comment_type' => 'string', 'id_recipient' => 'int',
1985
						'recipient_name' => 'string-255', 'body' => 'string-65535', 'log_time' => 'int',
1986
					),
1987
					array(
1988
						$user_info['id'], $user_info['name'], 'warntpl', $recipient_id,
1989
						$_POST['template_title'], $_POST['template_body'], time(),
1990
					),
1991
					array('id_comment')
1992
				);
1993
1994
				logAction('add_warn_template', array('template' => $_POST['template_title']));
1995
			}
1996
1997
			// Get out of town...
1998
			redirectexit('action=moderate;area=warnings;sa=templates');
1999
		}
2000
		else
2001
		{
2002
			$context['warning_errors'] = array();
2003
			$context['template_data']['title'] = !empty($_POST['template_title']) ? $_POST['template_title'] : '';
2004
			$context['template_data']['body'] = !empty($_POST['template_body']) ? $_POST['template_body'] : $txt['mc_warning_template_body_default'];
2005
			$context['template_data']['personal'] = !empty($_POST['make_personal']);
2006
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
	$pref_binary = 5;
0 ignored issues
show
The assignment to $pref_binary is dead and can be removed.
Loading history...
2035
2036
	// Are we saving?
2037
	if (isset($_POST['save']))
2038
	{
2039
		checkSession();
2040
		validateToken('mod-set');
2041
2042
		/* Current format of mod_prefs is:
2043
			x|ABCD|yyy
2044
2045
			WHERE:
2046
				x = Show report count on forum header.
2047
				ABCD = Block indexes to show on moderation main page.
2048
				yyy = Integer with the following bit status:
2049
					- yyy & 4 = Notify about posts awaiting approval.
2050
		*/
2051
2052
		// Now check other options!
2053
		$pref_binary = 0;
2054
2055
		// Put it all together.
2056
		$mod_prefs = '0||' . $pref_binary;
2057
		updateMemberData($user_info['id'], array('mod_prefs' => $mod_prefs));
2058
	}
2059
2060
	// What blocks does the user currently have selected?
2061
	$context['mod_settings'] = array(
2062
	);
2063
2064
	createToken('mod-set');
2065
}
2066
2067
/**
2068
 * This ends a moderator session, requiring authentication to access the MCP again.
2069
 */
2070
function ModEndSession()
2071
{
2072
	// This is so easy!
2073
	unset($_SESSION['moderate_time']);
2074
2075
	// Clean any moderator tokens as well.
2076
	foreach ($_SESSION['token'] as $key => $token)
2077
		if (strpos($key, '-mod') !== false)
2078
			unset($_SESSION['token'][$key]);
2079
2080
	redirectexit();
2081
}
2082
2083
?>