Completed
Pull Request — master (#3325)
by Emanuele
11:19
created

ModerationCenter_Controller::action_viewWarnings()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 14
dl 0
loc 25
rs 9.7998
c 0
b 0
f 0
nc 1
nop 0
ccs 0
cts 15
cp 0
crap 2
1
<?php
2
3
/**
4
 * Moderation Center, provides at a glance view of moderation items to the team
5
 *
6
 * @name      ElkArte Forum
7
 * @copyright ElkArte Forum contributors
8
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
9
 *
10
 * This file contains code covered by:
11
 * copyright:	2011 Simple Machines (http://www.simplemachines.org)
12
 * license:		BSD, See included LICENSE.TXT for terms and conditions.
13
 *
14
 * @version 1.1.6
15
 *
16
 */
17
18
/**
19
 * ModerationCenter_Controller Class
20
 * Provides overview of moderation items to the team
21
 */
22
class ModerationCenter_Controller extends Action_Controller
23
{
24
	/**
25
	 * Holds function array to pass to callMenu to call the right moderation area
26
	 * @var array
27
	 */
28
	private $_mod_include_data;
29
30
	/**
31
	 * Entry point for the moderation center.
32
	 *
33
	 * @see Action_Controller::action_index()
34
	 */
35
	public function action_index()
36
	{
37
		// Set up moderation menu.
38
		$this->prepareModcenter();
39
40
		// Now call the menu action.
41
		if (isset($this->_mod_include_data['file']))
42
			require_once($this->_mod_include_data['file']);
43
44
		callMenu($this->_mod_include_data);
45
	}
46
47
	/**
48
	 * Prepare menu, make checks, load files, and create moderation menu.
49
	 *
50
	 * This can be called from the class, or from outside, to
51
	 * set up moderation menu.
52
	 */
53
	public function prepareModcenter()
54
	{
55
		global $txt, $context, $scripturl, $modSettings, $user_info, $options;
56
57
		// Don't run this twice... and don't conflict with the admin bar.
58
		if (isset($context['admin_area']))
59
			return;
60
61
		$context['can_moderate_boards'] = $user_info['mod_cache']['bq'] != '0=1';
62
		$context['can_moderate_groups'] = $user_info['mod_cache']['gq'] != '0=1';
63
		$context['can_moderate_approvals'] = $modSettings['postmod_active'] && !empty($user_info['mod_cache']['ap']);
64
65
		// Everyone using this area must be allowed here!
66
		if (!$context['can_moderate_boards'] && !$context['can_moderate_groups'] && !$context['can_moderate_approvals'])
67
			isAllowedTo('access_mod_center');
68
69
		// We're gonna want a menu of some kind.
70
		require_once(SUBSDIR . '/Menu.subs.php');
71
72
		// Load the language, and the template.
73
		loadLanguage('ModerationCenter');
74
		loadCSSFile('admin.css');
75
76
		if (!empty($options['admin_preferences']))
77
		{
78
			$context['admin_preferences'] = serializeToJson($options['admin_preferences'], function ($array_form) {
79
				global $context;
80
81
				$context['admin_preferences'] = $array_form;
82
				require_once(SUBSDIR . '/Admin.subs.php');
83
				updateAdminPreferences();
84
			});
85
		}
86
		else
87
		{
88
			$context['admin_preferences'] = array();
89
		}
90
91
		$context['robot_no_index'] = true;
92
93
		// Moderation counts for things that this moderator can take care of
94
		require_once(SUBSDIR . '/Moderation.subs.php');
95
		$mod_counts = loadModeratorMenuCounts();
96
97
		// This is the menu structure - refer to subs/Menu.subs.php for the details.
98
		$moderation_areas = array(
99
			'main' => array(
100
				'title' => $txt['mc_main'],
101
				'areas' => array(
102
					'index' => array(
103
						'label' => $txt['moderation_center'],
104
						'controller' => 'ModerationCenter_Controller',
105
						'function' => 'action_moderationHome',
106
						'icon' => 'transparent.png',
107
						'class' => 'admin_img_home',
108
					),
109
					'settings' => array(
110
						'label' => $txt['mc_settings'],
111
						'controller' => 'ModerationCenter_Controller',
112
						'function' => 'action_moderationSettings',
113
						'icon' => 'transparent.png',
114
						'class' => 'admin_img_features',
115
					),
116
					'modlogoff' => array(
117
						'label' => $txt['mc_logoff'],
118
						'controller' => 'ModerationCenter_Controller',
119
						'function' => 'action_modEndSession',
120
						'enabled' => empty($modSettings['securityDisable_moderate']),
121
						'icon' => 'transparent.png',
122
						'class' => 'admin_img_exit',
123
					),
124
					'notice' => array(
125
						'controller' => 'ModerationCenter_Controller',
126
						'function' => 'action_showNotice',
127
						'select' => 'index',
128
						'icon' => 'transparent.png',
129
						'class' => 'admin_img_news',
130
					),
131
				),
132
			),
133
			'logs' => array(
134
				'title' => $txt['mc_logs'],
135
				'areas' => array(
136
					'modlog' => array(
137
						'label' => $txt['modlog_view'],
138
						'enabled' => !empty($modSettings['modlog_enabled']) && $context['can_moderate_boards'],
139
						'controller' => 'Modlog_Controller',
140
						'function' => 'action_log',
141
						'icon' => 'transparent.png',
142
						'class' => 'admin_img_logs',
143
					),
144
					'warnings' => array(
145
						'label' => $txt['mc_warnings'],
146
						'enabled' => in_array('w', $context['admin_features']) && !empty($modSettings['warning_enable']) && $context['can_moderate_boards'],
147
						'controller' => 'ModerationCenter_Controller',
148
						'function' => 'action_viewWarnings',
149
						'icon' => 'transparent.png',
150
						'class' => 'admin_img_reports',
151
						'subsections' => array(
152
							'log' => array($txt['mc_warning_log']),
153
							'templates' => array($txt['mc_warning_templates'], 'issue_warning'),
154
						),
155
					),
156
				),
157
			),
158
			'posts' => array(
159
				'title' => $txt['mc_posts'] . (!empty($mod_counts['pt_total']) ? ' [' . $mod_counts['pt_total'] . ']' : ''),
160
				'enabled' => $context['can_moderate_boards'] || $context['can_moderate_approvals'],
161
				'areas' => array(
162
					'postmod' => array(
163
						'label' => $txt['mc_unapproved_posts'] . (!empty($mod_counts['postmod']) ? ' [' . $mod_counts['postmod'] . ']' : ''),
164
						'enabled' => $context['can_moderate_approvals'],
165
						'controller' => 'PostModeration_Controller',
166
						'function' => 'action_index',
167
						'icon' => 'transparent.png',
168
						'class' => 'admin_img_posts',
169
						'custom_url' => $scripturl . '?action=moderate;area=postmod',
170
						'subsections' => array(
171
							'posts' => array($txt['mc_unapproved_replies']),
172
							'topics' => array($txt['mc_unapproved_topics']),
173
						),
174
					),
175
					'emailmod' => array(
176
						'label' => $txt['mc_emailerror'] . (!empty($mod_counts['emailmod']) ? ' [' . $mod_counts['emailmod'] . ']' : ''),
177
						'enabled' => !empty($modSettings['maillist_enabled']) && allowedTo('approve_emails'),
178
						'function' => 'UnapprovedEmails',
179
						'icon' => 'transparent.png',
180
						'class' => 'admin_img_mail',
181
						'custom_url' => $scripturl . '?action=admin;area=maillist;sa=emaillist',
182
					),
183
					'attachmod' => array(
184
						'label' => $txt['mc_unapproved_attachments'] . (!empty($mod_counts['attachments']) ? ' [' . $mod_counts['attachments'] . ']' : ''),
185
						'enabled' => $context['can_moderate_approvals'],
186
						'controller' => 'PostModeration_Controller',
187
						'function' => 'action_index',
188
						'icon' => 'transparent.png',
189
						'class' => 'admin_img_attachment',
190
						'custom_url' => $scripturl . '?action=moderate;area=attachmod;sa=attachments',
191
					),
192
					'reports' => array(
193
						'label' => $txt['mc_reported_posts'] . (!empty($mod_counts['reports']) ? ' [' . $mod_counts['reports'] . ']' : ''),
194
						'enabled' => $context['can_moderate_boards'],
195
						'controller' => 'ModerationCenter_Controller',
196
						'function' => 'action_reportedPosts',
197
						'icon' => 'transparent.png',
198
						'class' => 'admin_img_reports',
199
						'subsections' => array(
200
							'open' => array($txt['mc_reportedp_active'] . (!empty($mod_counts['reports']) ? ' [' . $mod_counts['reports'] . ']' : '')),
201
							'closed' => array($txt['mc_reportedp_closed']),
202
						),
203
					),
204
					'pm_reports' => array(
205
						'label' => $txt['mc_reported_pms'] . (!empty($mod_counts['pm_reports']) ? ' [' . $mod_counts['pm_reports'] . ']' : ''),
206
						'enabled' => $user_info['is_admin'],
207
						'controller' => 'ModerationCenter_Controller',
208
						'function' => 'action_reportedPosts',
209
						'subsections' => array(
210
							'open' => array($txt['mc_reportedp_active']),
211
							'closed' => array($txt['mc_reportedp_closed']),
212
						),
213
					),
214
				),
215
			),
216
			'groups' => array(
217
				'title' => $txt['mc_groups'] . (!empty($mod_counts['mg_total']) ? ' [' . $mod_counts['mg_total'] . ']' : ''),
218
				'enabled' => $context['can_moderate_groups'],
219
				'areas' => array(
220
					'userwatch' => array(
221
						'label' => $txt['mc_watched_users_title'],
222
						'enabled' => in_array('w', $context['admin_features']) && !empty($modSettings['warning_enable']) && $context['can_moderate_boards'],
223
						'controller' => 'ModerationCenter_Controller',
224
						'function' => 'action_viewWatchedUsers',
225
						'icon' => 'transparent.png',
226
						'class' => 'admin_img_permissions',
227
						'subsections' => array(
228
							'member' => array($txt['mc_watched_users_member']),
229
							'post' => array($txt['mc_watched_users_post']),
230
						),
231
					),
232
					'groups' => array(
233
						'label' => $txt['mc_group_requests'] . (!empty($mod_counts['groupreq']) ? ' [' . $mod_counts['groupreq'] . ']' : ''),
234
						'controller' => 'Groups_Controller',
235
						'function' => 'action_index',
236
						'icon' => 'transparent.png',
237
						'class' => 'admin_img_regcenter',
238
						'custom_url' => $scripturl . '?action=moderate;area=groups;sa=requests',
239
					),
240
					'members' => array(
241
						'enabled' => allowedTo('moderate_forum'),
242
						'label' => $txt['mc_member_requests'] . (!empty($mod_counts['memberreq']) ? ' [' . $mod_counts['memberreq'] . ']' : ''),
243
						'controller' => 'ManageMembers_Controller',
244
						'function' => 'action_approve',
245
						'icon' => 'transparent.png',
246
						'class' => 'admin_img_members',
247
						'custom_url' => $scripturl . '?action=admin;area=viewmembers;sa=browse;type=approve',
248
					),
249
					'viewgroups' => array(
250
						'label' => $txt['mc_view_groups'],
251
						'controller' => 'Groups_Controller',
252
						'function' => 'action_index',
253
						'icon' => 'transparent.png',
254
						'class' => 'admin_img_membergroups',
255
					),
256
				),
257
			),
258
		);
259
260
		// Make sure the administrator has a valid session...
261
		validateSession('moderate');
262
263
		// I don't know where we're going - I don't know where we've been...
264
		$menuOptions = array(
265
			'action' => 'moderate',
266
			'hook' => 'moderation',
267
			'disable_url_session_check' => true,
268
			'default_include_dir' => CONTROLLERDIR,
269
		);
270
271
		$mod_include_data = createMenu($moderation_areas, $menuOptions);
272
		unset($moderation_areas);
273
274
		// We got something - didn't we? DIDN'T WE!
275
		if ($mod_include_data === false)
276
			throw new Elk_Exception('no_access', false);
277
278
		// Retain the ID information in case required by a subaction.
279
		$context['moderation_menu_id'] = $context['max_menu_id'];
280
		$context['moderation_menu_name'] = 'menu_data_' . $context['moderation_menu_id'];
281
		$context[$context['moderation_menu_name']]['tab_data'] = array(
282
			'title' => $txt['moderation_center'],
283
			'help' => '',
284
			'description' => sprintf($txt['mc_description'], $context['user']['name'], $scripturl . '?action=moderate;area=settings'));
285
286
		// What a pleasant shortcut - even tho we're not *really* on the admin screen who cares...
287
		$context['admin_area'] = $mod_include_data['current_area'];
288
289
		// Build the link tree.
290
		$context['linktree'][] = array(
291
			'url' => $scripturl . '?action=moderate',
292
			'name' => $txt['moderation_center'],
293
		);
294
295
		if (isset($mod_include_data['current_area']) && $mod_include_data['current_area'] != 'index')
296
			$context['linktree'][] = array(
297
				'url' => $scripturl . '?action=moderate;area=' . $mod_include_data['current_area'],
298
				'name' => $mod_include_data['label'],
299
			);
300
301
		if (!empty($mod_include_data['current_subsection']) && $mod_include_data['subsections'][$mod_include_data['current_subsection']][0] != $mod_include_data['label'])
302
			$context['linktree'][] = array(
303
				'url' => $scripturl . '?action=moderate;area=' . $mod_include_data['current_area'] . ';sa=' . $mod_include_data['current_subsection'],
304
				'name' => $mod_include_data['subsections'][$mod_include_data['current_subsection']][0],
305
			);
306
307
		// Finally, store this, so that if we're called from the class, it can use it.
308
		$this->_mod_include_data = $mod_include_data;
309
	}
310
311
	/**
312
	 * This handler presents the home page of the moderation center.
313
	 */
314
	public function action_moderationHome()
315
	{
316
		global $txt, $context, $user_settings;
317
318
		loadTemplate('ModerationCenter');
319
		loadJavascriptFile('admin.js', array(), 'admin_scripts');
320
321
		$context['page_title'] = $txt['moderation_center'];
322
		$context['sub_template'] = 'moderation_center';
323
324
		// Start off with no blocks
325
		$valid_blocks = array();
326
327
		// Load what blocks the user actually can see...
328
		$valid_blocks['p'] = 'notes';
329
330
		if ($context['can_moderate_boards'])
331
		{
332
			$valid_blocks['a'] = 'actionRequired';
333
			$valid_blocks['r'] = 'reportedPosts';
334
		}
335
336
		if ($context['can_moderate_groups'])
337
			$valid_blocks['g'] = 'groupRequests';
338
339
		if ($context['can_moderate_boards'])
340
			$valid_blocks['w'] = 'watchedUsers';
341
342
		$valid_blocks['n'] = 'latestNews';
343
344
		if (empty($user_settings['mod_prefs']))
345
			$user_blocks = 'n' . ($context['can_moderate_boards'] ? 'wra' : '') . ($context['can_moderate_groups'] ? 'g' : '');
346
		else
347
			list (, $user_blocks) = explode('|', $user_settings['mod_prefs']);
348
349
		$user_blocks = str_split($user_blocks);
350
351
		$context['mod_blocks'] = array();
352
		foreach ($valid_blocks as $k => $block)
353
		{
354
			if (in_array($k, $user_blocks))
355
			{
356
				$block = 'block_' . $block;
357
358
				if (method_exists($this, $block))
359
					$context['mod_blocks'][] = $this->{$block}();
360
			}
361
		}
362
	}
363
364
	/**
365
	 * This ends a moderator session, requiring authentication to access the MCP again.
366
	 */
367
	public function action_modEndSession()
368
	{
369
		// This is so easy!
370
		unset($_SESSION['moderate_time']);
371
372
		// Clean any moderator tokens as well.
373
		cleanTokens(false, '-mod');
374
375
		redirectexit('action=moderate');
376
	}
377
378
	/**
379
	 * Show a warning notice sent to a user.
380
	 */
381
	public function action_showNotice()
382
	{
383
		global $txt, $context;
384
385
		// What notice have they asked to view
386
		$id_notice = $this->_req->getQuery('nid', 'intval', 0);
387
		$notice = moderatorNotice($id_notice);
388
389
		// legit?
390
		if (empty($notice) || !$context['can_moderate_boards'])
391
			throw new Elk_Exception('no_access', false);
392
393
		list ($context['notice_body'], $context['notice_subject']) = $notice;
394
395
		$parser = \BBC\ParserWrapper::instance();
396
397
		$context['notice_body'] = $parser->parseNotice($context['notice_body']);
398
		$context['page_title'] = $txt['show_notice'];
399
		$context['sub_template'] = 'show_notice';
400
401
		Template_Layers::instance()->removeAll();
402
		loadTemplate('ModerationCenter');
403
	}
404
405
	/**
406
	 * Browse all the reported posts.
407
	 *
408
	 * @todo this needs to be given its own file?
409
	 */
410
	public function action_reportedPosts()
411
	{
412
		global $txt, $context, $scripturl, $user_info;
413
414
		loadTemplate('ModerationCenter');
415
		require_once(SUBSDIR . '/Moderation.subs.php');
416
417
		// Put the open and closed options into tabs, because we can...
418
		$context[$context['moderation_menu_name']]['tab_data'] = array(
419
			'title' => $txt['mc_reported_posts'],
420
			'help' => '',
421
			'description' => $txt['mc_reported_posts_desc'],
422
		);
423
424
		// Set up the comforting bits...
425
		$context['page_title'] = $txt['mc_reported_posts'];
426
		$context['sub_template'] = 'reported_posts';
427
428
		// This comes under the umbrella of moderating posts.
429
		if ($user_info['mod_cache']['bq'] === '0=1')
430
			isAllowedTo('moderate_forum');
431
432
		// Are they wanting to view a particular report?
433
		if (!empty($this->_req->query->report))
434
			return $this->action_modReport();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->action_modReport() targeting ModerationCenter_Controller::action_modReport() 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...
435
436
		// This should not be needed...
437
		$show_pms = false;
438
		if ($context['admin_area'] === 'pm_reports')
439
		{
440
			$show_pms = true;
441
			isAllowedTo('admin_forum');
442
443
			// Put the open and closed options into tabs, because we can...
444
			$context[$context['moderation_menu_name']]['tab_data'] = array(
445
				'title' => $txt['mc_reported_pms'],
446
				'help' => '',
447
				'description' => $txt['mc_reported_pms_desc'],
448
			);
449
			$context['page_title'] = $txt['mc_reported_pms'];
450
		}
451
452
		// Are we viewing open or closed reports?
453
		$context['view_closed'] = $this->_req->getQuery('sa') === 'closed' ? 1 : 0;
454
455
		// Are we doing any work?
456
		if ((isset($this->_req->query->ignore) || isset($this->_req->query->close)) && isset($this->_req->query->rid))
457
		{
458
			checkSession('get');
459
			$rid = $this->_req->getQuery('rid', 'intval');
460
461
			// Update the report...
462
			if (isset($this->_req->query->ignore))
463
				updateReportsStatus($rid, 'ignore', (int) $this->_req->query->ignore);
464
			elseif (isset($this->_req->query->close))
465
				updateReportsStatus($rid, 'close', (int) $this->_req->query->close);
466
467
			// Time to update.
468
			updateSettings(array('last_mod_report_action' => time()));
469
			recountOpenReports(true, $show_pms);
470
		}
471
		elseif (isset($this->_req->post->close) && isset($this->_req->post->close_selected))
472
		{
473
			checkSession('post');
474
475
			// All the ones to update...
476
			$toClose = array_map('intval', $this->_req->post->close);
477
			if (!empty($toClose))
478
			{
479
				updateReportsStatus($toClose, 'close', 1);
480
481
				// Time to update.
482
				updateSettings(array('last_mod_report_action' => time()));
483
				recountOpenReports(true, $show_pms);
484
			}
485
		}
486
487
		// How many entries are we viewing?
488
		$context['total_reports'] = totalReports($context['view_closed'], $show_pms);
489
490
		// So, that means we can page index, yes?
491
		$context['page_index'] = constructPageIndex($scripturl . '?action=moderate;area=' . $context['admin_area'] . ($context['view_closed'] ? ';sa=closed' : ''), $this->_req->query->start, $context['total_reports'], 10);
492
		$context['start'] = $this->_req->query->start;
493
494
		// By George, that means we in a position to get the reports, golly good.
495
		$context['reports'] = getModReports($context['view_closed'], $context['start'], 10, $show_pms);
496
		$report_ids = array_keys($context['reports']);
497
		$report_boards_ids = array();
498
		$bbc_parser = \BBC\ParserWrapper::instance();
499
		foreach ($context['reports'] as $row)
500
		{
501
			$context['reports'][$row['id_report']] = array(
502
				'board' => $row['id_board'],
503
				'id' => $row['id_report'],
504
				'topic_href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'],
505
				'report_href' => $scripturl . '?action=moderate;area=' . $context['admin_area'] . ';report=' . $row['id_report'],
506
				'author' => array(
507
					'id' => $row['id_author'],
508
					'name' => $row['author_name'],
509
					'link' => $row['id_author'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_author'] . '">' . $row['author_name'] . '</a>' : $row['author_name'],
510
					'href' => $scripturl . '?action=profile;u=' . $row['id_author'],
511
				),
512
				'comments' => array(),
513
				'time_started' => standardTime($row['time_started']),
514
				'last_updated' => standardTime($row['time_updated']),
515
				'subject' => $row['subject'],
516
				'body' => $bbc_parser->parseReport($row['body']),
517
				'num_reports' => $row['num_reports'],
518
				'closed' => $row['closed'],
519
				'ignore' => $row['ignore_all'],
520
				'buttons' => array(
521
					'quickmod_check' => array(
522
						'checkbox' => !$context['view_closed'],
523
						'name' => 'close',
524
						'value' => $row['id_report'],
525
					),
526
					'details' => array(
527
						'href' => $scripturl . '?action=moderate;area=' . $context['admin_area'] . ';report=' . $row['id_report'],
528
						'text' => $txt['mc_reportedp_details'],
529
					),
530
					'ignore' => array(
531
						'href' => $scripturl . '?action=moderate;area=' . $context['admin_area'] . '' . ($context['view_closed'] ? ';sa=closed' : '') . ';ignore=' . ((int) !$row['ignore_all']) . ';rid=' . $row['id_report'] . ';start=' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id'],
532
						'text' => $row['ignore_all'] ? $txt['mc_reportedp_unignore'] : $txt['mc_reportedp_ignore'],
533
						'custom' => $row['ignore_all'] ? '' : 'onclick="return confirm(' . JavaScriptEscape($txt['mc_reportedp_ignore_confirm']) . ');"',
534
					),
535
					'close' => array(
536
						'href' => $scripturl . '?action=moderate;area=' . $context['admin_area'] . '' . ($context['view_closed'] ? ';sa=closed' : '') . ';close=' . ((int) !$row['closed']) . ';rid=' . $row['id_report'] . ';start=' . $context['start'] . ';' . $context['session_var'] . '=' . $context['session_id'],
537
						'text' => $context['view_closed'] ? $txt['mc_reportedp_open'] : $txt['mc_reportedp_close'],
538
					),
539
				),
540
			);
541
			$report_boards_ids[] = $row['id_board'];
542
		}
543
544
		// Get the names of boards these topics are in.
545
		if (!empty($report_ids))
546
		{
547
			require_once(SUBSDIR . '/Boards.subs.php');
548
			$board_names = getBoardList(array('included_boards' => $report_boards_ids), true);
549
550
			// Add the board name to the report array
551
			foreach ($context['reports'] as $id_report => $report)
552
				if (!empty($board_names[$report['board']]))
553
					$context['reports'][$id_report]['board_name'] = $board_names[$report['board']]['board_name'];
554
		}
555
556
		// Now get all the people who reported it.
557
		if (!empty($report_ids))
558
		{
559
			$comments = getReportsUserComments($report_ids);
560
			foreach ($comments as $id_rep => $rows)
561
			{
562
				foreach ($rows as $row)
563
					$context['reports'][$id_rep]['comments'][] = array(
564
						'id' => $row['id_comment'],
565
						'message' => $row['comment'],
566
						'raw_time' => $row['time_sent'],
567
						'time' => standardTime($row['time_sent']),
568
						'html_time' => htmlTime($row['time_sent']),
569
						'timestamp' => forum_time(true, $row['time_sent']),
570
						'member' => array(
571
							'id' => $row['id_member'],
572
							'name' => empty($row['reporter']) ? $txt['guest'] : $row['reporter'],
573
							'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['reporter'] . '</a>' : (empty($row['reporter']) ? $txt['guest'] : $row['reporter']),
574
							'href' => $row['id_member'] ? $scripturl . '?action=profile;u=' . $row['id_member'] : '',
575
						),
576
					);
577
			}
578
		}
579
	}
580
581
	/**
582
	 * Change moderation preferences.
583
	 */
584
	public function action_moderationSettings()
585
	{
586
		global $context, $txt, $user_settings, $user_info;
587
588
		// Some useful context stuff.
589
		loadTemplate('ModerationCenter');
590
		$context['page_title'] = $txt['mc_settings'];
591
		$context['sub_template'] = 'moderation_settings';
592
		$context[$context['moderation_menu_name']]['tab_data'] = array(
593
			'title' => $txt['mc_prefs_title'],
594
			'help' => '',
595
			'description' => $txt['mc_prefs_desc']
596
		);
597
598
		// What blocks can this user see?
599
		$context['homepage_blocks'] = array(
600
			'n' => $txt['mc_prefs_latest_news'],
601
			'p' => $txt['mc_notes'],
602
		);
603
604
		if ($context['can_moderate_groups'])
605
			$context['homepage_blocks']['g'] = $txt['mc_group_requests'];
606
607
		if ($context['can_moderate_boards'])
608
		{
609
			$context['homepage_blocks']['r'] = $txt['mc_reported_posts'];
610
			$context['homepage_blocks']['w'] = $txt['mc_watched_users'];
611
			$context['homepage_blocks']['a'] = $txt['mc_required'];
612
		}
613
614
		// Does the user have any settings yet?
615
		if (empty($user_settings['mod_prefs']))
616
		{
617
			$mod_blocks = 'np' . ($context['can_moderate_boards'] ? 'wra' : '') . ($context['can_moderate_groups'] ? 'g' : '');
618
			$pref_binary = 5;
619
			$show_reports = 1;
620
		}
621
		else
622
			list ($show_reports, $mod_blocks, $pref_binary) = explode('|', $user_settings['mod_prefs']);
623
624
		// Are we saving?
625
		if (isset($this->_req->post->save))
626
		{
627
			checkSession('post');
628
			validateToken('mod-set');
629
630
			/* Current format of mod_prefs is:
631
				x|ABCD|yyy
632
633
				WHERE:
634
					x = Show report count on forum header.
635
					ABCD = Block indexes to show on moderation main page.
636
					yyy = Integer with the following bit status:
637
						- yyy & 1 = Always notify on reports.
638
						- yyy & 2 = Notify on reports for moderators only.
639
						- yyy & 4 = Notify about posts awaiting approval.
640
			*/
641
642
			// Do blocks first!
643
			$mod_blocks = '';
644
			if (!empty($this->_req->post->mod_homepage))
645
				foreach ($this->_req->post->mod_homepage as $k => $v)
646
				{
647
					// Make sure they can add this...
648
					if (isset($context['homepage_blocks'][$k]))
649
						$mod_blocks .= $k;
650
				}
651
652
			// Now check other options!
653
			$pref_binary = 0;
654
655
			if ($context['can_moderate_approvals'] && !empty($this->_req->post->mod_notify_approval))
656
				$pref_binary |= 4;
657
658
			if ($context['can_moderate_boards'])
659
			{
660
				if (!empty($this->_req->post->mod_notify_report))
661
					$pref_binary |= ($this->_req->post->mod_notify_report == 2 ? 1 : 2);
662
663
				$show_reports = !empty($this->_req->post->mod_show_reports) ? 1 : 0;
664
			}
665
666
			// Put it all together.
667
			$mod_prefs = $show_reports . '|' . $mod_blocks . '|' . $pref_binary;
668
			require_once(SUBSDIR . '/Members.subs.php');
669
			updateMemberData($user_info['id'], array('mod_prefs' => $mod_prefs));
670
		}
671
672
		// What blocks does the user currently have selected?
673
		$context['mod_settings'] = array(
674
			'show_reports' => $show_reports,
675
			'notify_report' => $pref_binary & 2 ? 1 : ($pref_binary & 1 ? 2 : 0),
676
			'notify_approval' => $pref_binary & 4,
677
			'user_blocks' => str_split($mod_blocks),
678
		);
679
680
		createToken('mod-set');
681
	}
682
683
	/**
684
	 * Edit a warning template.
685
	 *
686
	 * @uses template_warn_template()
687
	 */
688
	public function action_modifyWarningTemplate()
689
	{
690
		global $context, $txt, $user_info;
691
692
		require_once(SUBSDIR . '/Moderation.subs.php');
693
		loadJavascriptFile('admin.js', array(), 'admin_scripts');
694
695
		$context['id_template'] = $this->_req->getQuery('tid', 'intval', 0);
696
		$context['is_edit'] = $context['id_template'];
697
698
		// Standard template things.
699
		$context['page_title'] = $context['is_edit'] ? $txt['mc_warning_template_modify'] : $txt['mc_warning_template_add'];
700
		$context['sub_template'] = 'warn_template';
701
		$context[$context['moderation_menu_name']]['current_subsection'] = 'templates';
702
703
		// Defaults.
704
		$context['template_data'] = array(
705
			'title' => '',
706
			'body' => $txt['mc_warning_template_body_default'],
707
			'personal' => false,
708
			'can_edit_personal' => true,
709
		);
710
711
		// If it's an edit load it.
712
		if ($context['is_edit'])
713
			modLoadTemplate($context['id_template']);
714
715
		// Wait, we are saving?
716
		if (isset($this->_req->post->save))
717
		{
718
			checkSession('post');
719
			validateToken('mod-wt');
720
721
			// To check the BBC is pretty good...
722
			require_once(SUBSDIR . '/Post.subs.php');
723
724
			// Bit of cleaning!
725
			$template_body = trim($this->_req->post->template_body);
726
			$template_title = trim($this->_req->post->template_title);
727
728
			// Need something in both boxes.
729
			if (!empty($template_body) && !empty($template_title))
730
			{
731
				// Safety first.
732
				$template_title = Util::htmlspecialchars($template_title);
733
734
				// Clean up BBC.
735
				preparsecode($template_body);
736
737
				// But put line breaks back!
738
				$template_body = strtr($template_body, array('<br />' => "\n"));
739
740
				// Is this personal?
741
				$recipient_id = !empty($this->_req->post->make_personal) ? $user_info['id'] : 0;
742
743
				// If we are this far it's save time.
744
				if ($context['is_edit'])
745
				{
746
					// Simple update...
747
					modAddUpdateTemplate($recipient_id, $template_title, $template_body, $context['id_template']);
748
749
					// If it wasn't visible and now is they've effectively added it.
750
					if ($context['template_data']['personal'] && !$recipient_id)
751
						logAction('add_warn_template', array('template' => $template_title));
752
					// Conversely if they made it personal it's a delete.
753
					elseif (!$context['template_data']['personal'] && $recipient_id)
754
						logAction('delete_warn_template', array('template' => $template_title));
755
					// Otherwise just an edit.
756
					else
757
						logAction('modify_warn_template', array('template' => $template_title));
758
				}
759
				else
760
				{
761
					modAddUpdateTemplate($recipient_id, $template_title, $template_body, $context['id_template'], false);
762
					logAction('add_warn_template', array('template' => $template_title));
763
				}
764
765
				// Get out of town...
766
				redirectexit('action=moderate;area=warnings;sa=templates');
767
			}
768
			else
769
			{
770
				$context['warning_errors'] = array();
771
				$context['template_data']['title'] = !empty($template_title) ? $template_title : '';
772
				$context['template_data']['body'] = !empty($template_body) ? $template_body : $txt['mc_warning_template_body_default'];
773
				$context['template_data']['personal'] = !empty($this->_req->post->make_personal);
774
775
				if (empty($template_title))
776
					$context['warning_errors'][] = $txt['mc_warning_template_error_no_title'];
777
778
				if (empty($template_body))
779
					$context['warning_errors'][] = $txt['mc_warning_template_error_no_body'];
780
			}
781
		}
782
783
		createToken('mod-wt');
784
	}
785
786
	/**
787
	 * Get details about the moderation report
788
	 *
789
	 * - report is specified in the url param report.
790
	 */
791
	public function action_modReport()
792
	{
793
		global $context, $scripturl, $txt;
794
795
		// Have to at least give us something
796
		$report = $this->_req->getQuery('report', 'intval', 0);
797
		if (empty($report))
798
			throw new Elk_Exception('mc_no_modreport_specified');
799
800
		// This should not be needed...
801
		$show_pms = false;
802
		if ($context['admin_area'] === 'pm_reports')
803
		{
804
			$show_pms = true;
805
			isAllowedTo('admin_forum');
806
		}
807
808
		// Get the report details, need this so we can limit access to a particular board
809
		$row = modReportDetails($report, $show_pms);
810
811
		// So did we find anything?
812
		if ($row === false)
813
			throw new Elk_Exception('mc_no_modreport_found');
814
815
		// Woohoo we found a report and they can see it!  Bad news is we have more work to do
816
		// If they are adding a comment then... add a comment.
817
		if (isset($this->_req->post->add_comment) && !empty($this->_req->post->mod_comment))
818
		{
819
			checkSession();
820
821
			$newComment = trim(Util::htmlspecialchars($this->_req->post->mod_comment));
822
823
			// In it goes.
824
			if (!empty($newComment))
825
			{
826
				addReportComment($report, $newComment);
827
828
				// Redirect to prevent double submission.
829
				redirectexit($scripturl . '?action=moderate;area=' . $context['admin_area'] . ';report=' . $report);
830
			}
831
		}
832
833
		$bbc_parser = \BBC\ParserWrapper::instance();
834
835
		$context['report'] = array(
836
			'id' => $row['id_report'],
837
			'topic_id' => $row['id_topic'],
838
			'board_id' => $row['id_board'],
839
			'message_id' => $row['id_msg'],
840
			'message_href' => $scripturl . '?msg=' . $row['id_msg'],
841
			'message_link' => '<a href="' . $scripturl . '?msg=' . $row['id_msg'] . '">' . $row['subject'] . '</a>',
842
			'report_href' => $scripturl . '?action=moderate;area=' . $context['admin_area'] . ';' . $context['admin_area'] . '=' . $row['id_report'],
843
			'author' => array(
844
				'id' => $row['id_author'],
845
				'name' => $row['author_name'],
846
				'link' => $row['id_author'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_author'] . '">' . $row['author_name'] . '</a>' : $row['author_name'],
847
				'href' => $scripturl . '?action=profile;u=' . $row['id_author'],
848
			),
849
			'comments' => array(),
850
			'mod_comments' => array(),
851
			'time_started' => standardTime($row['time_started']),
852
			'last_updated' => standardTime($row['time_updated']),
853
			'subject' => $row['subject'],
854
			'body' => $bbc_parser->parseReport($row['body']),
855
			'num_reports' => $row['num_reports'],
856
			'closed' => $row['closed'],
857
			'ignore' => $row['ignore_all']
858
		);
859
860
		// So what bad things do the reporters have to say about it?
861
		$comments = getReportsUserComments($context['report']['id']);
862
		foreach ($comments[$context['report']['id']] as $row)
863
		{
864
			$context['report']['comments'][] = array(
865
				'id' => $row['id_comment'],
866
				'message' => strtr($row['comment'], array("\n" => '<br />')),
867
				'time' => standardTime($row['time_sent']),
868
				'html_time' => htmlTime($row['time_sent']),
869
				'timestamp' => forum_time(true, $row['time_sent']),
870
				'member' => array(
871
					'id' => $row['id_member'],
872
					'name' => empty($row['reporter']) ? $txt['guest'] : $row['reporter'],
873
					'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['reporter'] . '</a>' : (empty($row['reporter']) ? $txt['guest'] : $row['reporter']),
874
					'href' => $row['id_member'] ? $scripturl . '?action=profile;u=' . $row['id_member'] : '',
875
					'ip' => !empty($row['member_ip']) && allowedTo('moderate_forum') ? '<a href="' . $scripturl . '?action=trackip;searchip=' . $row['member_ip'] . '">' . $row['member_ip'] . '</a>' : '',
876
				),
877
			);
878
		}
879
880
		// Hang about old chap, any comments from moderators on this one?
881
		$mod_comments = getReportModeratorsComments($context['report']['id']);
882
		foreach ($mod_comments as $row)
883
		{
884
			$context['report']['mod_comments'][] = array(
885
				'id' => $row['id_comment'],
886
				'message' => $bbc_parser->parseReport($row['body']),
887
				'time' => standardTime($row['log_time']),
888
				'html_time' => htmlTime($row['log_time']),
889
				'timestamp' => forum_time(true, $row['log_time']),
890
				'member' => array(
891
					'id' => $row['id_member'],
892
					'name' => $row['moderator'],
893
					'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['moderator'] . '</a>' : $row['moderator'],
894
					'href' => $scripturl . '?action=profile;u=' . $row['id_member'],
895
				),
896
			);
897
		}
898
899
		// What have the other moderators done to this message?
900
		require_once(SUBSDIR . '/Modlog.subs.php');
901
		loadLanguage('Modlog');
902
903
		// This is all the information from the moderation log.
904
		$listOptions = array(
905
			'id' => 'moderation_actions_list',
906
			'title' => $txt['mc_modreport_modactions'],
907
			'items_per_page' => 15,
908
			'no_items_label' => $txt['modlog_no_entries_found'],
909
			'base_href' => $scripturl . '?action=moderate;area=' . $context['admin_area'] . ';report=' . $context['report']['id'],
910
			'default_sort_col' => 'time',
911
			'get_items' => array(
912
				'function' => 'list_getModLogEntries',
913
				'params' => array(
914
					'lm.id_topic = {int:id_topic}',
915
					array('id_topic' => $context['report']['topic_id']),
916
					1,
917
				),
918
			),
919
			'get_count' => array(
920
				'function' => 'list_getModLogEntryCount',
921
				'params' => array(
922
					'lm.id_topic = {int:id_topic}',
923
					array('id_topic' => $context['report']['topic_id']),
924
					1,
925
				),
926
			),
927
			// This assumes we are viewing by user.
928
			'columns' => array(
929
				'action' => array(
930
					'header' => array(
931
						'value' => $txt['modlog_action'],
932
					),
933
					'data' => array(
934
						'db' => 'action_text',
935
						'class' => 'smalltext',
936
					),
937
					'sort' => array(
938
						'default' => 'lm.action',
939
						'reverse' => 'lm.action DESC',
940
					),
941
				),
942
				'time' => array(
943
					'header' => array(
944
						'value' => $txt['modlog_date'],
945
					),
946
					'data' => array(
947
						'db' => 'time',
948
						'class' => 'smalltext',
949
					),
950
					'sort' => array(
951
						'default' => 'lm.log_time',
952
						'reverse' => 'lm.log_time DESC',
953
					),
954
				),
955
				'moderator' => array(
956
					'header' => array(
957
						'value' => $txt['modlog_member'],
958
					),
959
					'data' => array(
960
						'db' => 'moderator_link',
961
						'class' => 'smalltext',
962
					),
963
					'sort' => array(
964
						'default' => 'mem.real_name',
965
						'reverse' => 'mem.real_name DESC',
966
					),
967
				),
968
				'position' => array(
969
					'header' => array(
970
						'value' => $txt['modlog_position'],
971
					),
972
					'data' => array(
973
						'db' => 'position',
974
						'class' => 'smalltext',
975
					),
976
					'sort' => array(
977
						'default' => 'mg.group_name',
978
						'reverse' => 'mg.group_name DESC',
979
					),
980
				),
981
				'ip' => array(
982
					'header' => array(
983
						'value' => $txt['modlog_ip'],
984
					),
985
					'data' => array(
986
						'db' => 'ip',
987
						'class' => 'smalltext',
988
					),
989
					'sort' => array(
990
						'default' => 'lm.ip',
991
						'reverse' => 'lm.ip DESC',
992
					),
993
				),
994
			),
995
		);
996
997
		// Create the watched user list.
998
		createList($listOptions);
999
1000
		// Make sure to get the correct tab selected.
1001
		if ($context['report']['closed'])
1002
			$context[$context['moderation_menu_name']]['current_subsection'] = 'closed';
1003
1004
		// Finally we are done :P
1005
		loadTemplate('ModerationCenter');
1006
		if ($context['admin_area'] === 'pm_reports')
1007
		{
1008
			$context['page_title'] = sprintf($txt['mc_view_pmreport'], $context['report']['author']['name']);
1009
			$context['section_title'] = sprintf($txt['mc_view_pmreport'], $context['report']['author']['link']);
1010
			$context['section_descripion'] = sprintf($txt['mc_pmreport_summary'], $context['report']['num_reports'], $context['report']['last_updated']);
1011
		}
1012
		else
1013
		{
1014
			$context['page_title'] = sprintf($txt['mc_viewmodreport'], $context['report']['subject'], $context['report']['author']['name']);
1015
			$context['section_title'] = sprintf($txt['mc_viewmodreport'], $context['report']['message_link'], $context['report']['author']['link']);
1016
			$context['section_descripion'] = sprintf($txt['mc_modreport_summary'], $context['report']['num_reports'], $context['report']['last_updated']);
1017
		}
1018
1019
		$context['sub_template'] = 'viewmodreport';
1020
	}
1021
1022
	/**
1023
	 * View watched users and their posts
1024
	 */
1025
	public function action_viewWatchedUsers()
1026
	{
1027
		global $modSettings, $context, $txt, $scripturl, $user_info;
1028
1029
		// Some important context!
1030
		$context['page_title'] = $txt['mc_watched_users_title'];
1031
		$context['view_posts'] = isset($this->_req->query->sa) && $this->_req->query->sa === 'post';
1032
		$context['start'] = $this->_req->getQuery('start', 'intval', 0);
1033
1034
		loadTemplate('ModerationCenter');
1035
1036
		// Get some key settings!
1037
		$modSettings['warning_watch'] = empty($modSettings['warning_watch']) ? 1 : $modSettings['warning_watch'];
1038
1039
		// Put some pretty tabs on cause we're gonna be doing hot stuff here...
1040
		$context[$context['moderation_menu_name']]['tab_data'] = array(
1041
			'title' => $txt['mc_watched_users_title'],
1042
			'help' => '',
1043
			'description' => $txt['mc_watched_users_desc'],
1044
		);
1045
1046
		// First off - are we deleting?
1047
		if (!empty($this->_req->query->delete) || !empty($this->_req->post->delete))
1048
		{
1049
			checkSession(isset($this->_req->query->delete) ? 'get' : 'post');
1050
1051
			// Clicked on remove or using checkboxes to multi delete
1052
			$toDelete = array();
1053
			if (isset($this->_req->query->delete))
1054
				$toDelete[] = (int) $this->_req->query->delete;
1055
			else
1056
				$toDelete = array_map('intval', $this->_req->post->delete);
1057
1058
			if (!empty($toDelete))
1059
			{
1060
				$remover = new MessagesDelete($modSettings['recycle_enable'], $modSettings['recycle_board']);
1061
1062
				// If they don't have permission we'll let it error - either way no chance of a security slip here!
1063
				foreach ($toDelete as $did)
1064
					$remover->removeMessage($did);
1065
			}
1066
		}
1067
1068
		// Start preparing the list by grabbing relevant permissions.
1069
		if (!$context['view_posts'])
1070
		{
1071
			$approve_query = '';
1072
			$delete_boards = array();
1073
		}
1074
		else
1075
		{
1076
			// Still obey permissions!
1077
			$approve_boards = !empty($user_info['mod_cache']['ap']) ? $user_info['mod_cache']['ap'] : boardsAllowedTo('approve_posts');
1078
			$delete_boards = boardsAllowedTo('delete_any');
1079
1080
			if ($approve_boards == array(0))
1081
				$approve_query = '';
1082
			elseif (!empty($approve_boards))
1083
				$approve_query = ' AND m.id_board IN (' . implode(',', $approve_boards) . ')';
1084
			// Nada, zip, etc...
1085
			else
1086
				$approve_query = ' AND 1=0';
1087
		}
1088
1089
		// This is all the information required for a watched user listing.
1090
		$listOptions = array(
1091
			'id' => 'watch_user_list',
1092
			'title' => $txt['mc_watched_users_title'] . ' - ' . ($context['view_posts'] ? $txt['mc_watched_users_post'] : $txt['mc_watched_users_member']),
1093
			'width' => '100%',
1094
			'items_per_page' => $modSettings['defaultMaxMessages'],
1095
			'no_items_label' => $context['view_posts'] ? $txt['mc_watched_users_no_posts'] : $txt['mc_watched_users_none'],
1096
			'base_href' => $scripturl . '?action=moderate;area=userwatch;sa=' . ($context['view_posts'] ? 'post' : 'member'),
1097
			'default_sort_col' => $context['view_posts'] ? '' : 'member',
1098
			'get_items' => array(
1099
				'function' => $context['view_posts'] ? array($this, 'list_getWatchedUserPosts') : array($this, 'list_getWatchedUsers'),
1100
				'params' => array(
1101
					$approve_query,
1102
					$delete_boards,
1103
				),
1104
			),
1105
			'get_count' => array(
1106
				'function' => $context['view_posts'] ? array($this, 'list_getWatchedUserPostsCount') : array($this, 'list_getWatchedUserCount'),
1107
				'params' => array(
1108
					$approve_query,
1109
				),
1110
			),
1111
			// This assumes we are viewing by user.
1112
			'columns' => array(
1113
				'member' => array(
1114
					'header' => array(
1115
						'value' => $txt['mc_watched_users_member'],
1116
					),
1117
					'data' => array(
1118
						'sprintf' => array(
1119
							'format' => '<a href="' . $scripturl . '?action=profile;u=%1$d">%2$s</a>',
1120
							'params' => array(
1121
								'id' => false,
1122
								'name' => false,
1123
							),
1124
						),
1125
					),
1126
					'sort' => array(
1127
						'default' => 'real_name',
1128
						'reverse' => 'real_name DESC',
1129
					),
1130
				),
1131
				'warning' => array(
1132
					'header' => array(
1133
						'value' => $txt['mc_watched_users_warning'],
1134
					),
1135
					'data' => array(
1136
						'function' => function ($member) {
1137
							global $scripturl;
1138
1139
							return allowedTo('issue_warning') ? '<a href="' . $scripturl . '?action=profile;area=issuewarning;u=' . $member['id'] . '">' . $member['warning'] . '%</a>' : $member['warning'] . '%';
1140
						},
1141
					),
1142
					'sort' => array(
1143
						'default' => 'warning',
1144
						'reverse' => 'warning DESC',
1145
					),
1146
				),
1147
				'posts' => array(
1148
					'header' => array(
1149
						'value' => $txt['posts'],
1150
					),
1151
					'data' => array(
1152
						'sprintf' => array(
1153
							'format' => '<a href="' . $scripturl . '?action=profile;u=%1$d;area=showposts;sa=messages">%2$s</a>',
1154
							'params' => array(
1155
								'id' => false,
1156
								'posts' => false,
1157
							),
1158
						),
1159
					),
1160
					'sort' => array(
1161
						'default' => 'posts',
1162
						'reverse' => 'posts DESC',
1163
					),
1164
				),
1165
				'last_login' => array(
1166
					'header' => array(
1167
						'value' => $txt['mc_watched_users_last_login'],
1168
					),
1169
					'data' => array(
1170
						'db' => 'last_login',
1171
					),
1172
					'sort' => array(
1173
						'default' => 'last_login',
1174
						'reverse' => 'last_login DESC',
1175
					),
1176
				),
1177
				'last_post' => array(
1178
					'header' => array(
1179
						'value' => $txt['mc_watched_users_last_post'],
1180
					),
1181
					'data' => array(
1182
						'function' => function ($member) {
1183
							global $scripturl;
1184
1185
							if ($member['last_post_id'])
1186
								return '<a href="' . $scripturl . '?msg=' . $member['last_post_id'] . '">' . $member['last_post'] . '</a>';
1187
							else
1188
								return $member['last_post'];
1189
						},
1190
					),
1191
				),
1192
			),
1193
			'form' => array(
1194
				'href' => $scripturl . '?action=moderate;area=userwatch;sa=post',
1195
				'include_sort' => true,
1196
				'include_start' => true,
1197
				'hidden_fields' => array(
1198
					$context['session_var'] => $context['session_id'],
1199
				),
1200
			),
1201
			'additional_rows' => array(
1202
				$context['view_posts'] ?
1203
				array(
1204
					'position' => 'below_table_data',
1205
					'value' => '
1206
						<input type="submit" name="delete_selected" value="' . $txt['quickmod_delete_selected'] . '" class="right_submit" />',
1207
				) : array(),
1208
			),
1209
		);
1210
1211
		// If this is being viewed by posts we actually change the columns to call a template each time.
1212
		if ($context['view_posts'])
1213
		{
1214
			$listOptions['columns'] = array(
1215
				'posts' => array(
1216
					'data' => array(
1217
						'function' => function ($post) {
1218
							return template_user_watch_post_callback($post);
1219
						},
1220
					),
1221
				),
1222
			);
1223
		}
1224
1225
		// Create the watched user list.
1226
		createList($listOptions);
1227
1228
		$context['sub_template'] = 'show_list';
1229
		$context['default_list'] = 'watch_user_list';
1230
	}
1231
1232
	/**
1233
	 * Simply put, look at the warning log!
1234
	 */
1235
	public function action_viewWarningLog()
1236
	{
1237
		global $modSettings, $context, $txt, $scripturl;
1238
1239
		// Setup context as always.
1240
		$context['page_title'] = $txt['mc_warning_log_title'];
1241
1242
		require_once(SUBSDIR . '/Moderation.subs.php');
1243
		loadLanguage('Modlog');
1244
1245
		// If we're coming in from a search, get the variables.
1246
		if (!empty($this->_req->post->params) && empty($this->_req->post->is_search))
1247
		{
1248
			$search_params = base64_decode(strtr($this->_req->post->params, array(' ' => '+')));
1249
			$search_params = @json_decode($search_params);
1250
		}
1251
1252
		// This array houses all the valid search types.
1253
		$searchTypes = array(
1254
			'member' => array('sql' => 'mem.real_name', 'label' => $txt['profile_warning_previous_issued']),
1255
			'recipient' => array('sql' => 'recipient_name', 'label' => $txt['mc_warnings_recipient']),
1256
		);
1257
1258
		// Setup the allowed quick search type
1259
		$context['order'] = isset($this->_req->query->sort) && isset($searchTypes[$this->_req->query->sort]) ? $this->_req->query->sort : 'member';
1260
		$context['url_start'] = '?action=moderate;area=warnings;sa=log;sort=' . $context['order'];
1261
1262
		if (!isset($search_params['string']) || (!empty($this->_req->post->search) && $search_params['string'] != $this->_req->post->search))
1263
			$search_params_string = empty($this->_req->post->search) ? '' : $this->_req->post->search;
1264
		else
1265
			$search_params_string = $search_params['string'];
1266
1267
		if (isset($this->_req->post->search_type) || empty($search_params['type']) || !isset($searchTypes[$search_params['type']]))
1268
			$search_params_type = isset($this->_req->post->search_type) && isset($searchTypes[$this->_req->post->search_type]) ? $this->_req->post->search_type : (isset($searchTypes[$context['order']]) ? $context['order'] : 'member');
1269
		else
1270
			$search_params_type = $search_params['type'];
1271
1272
		$search_params_column = $searchTypes[$search_params_type]['sql'];
1273
		$search_params = array(
1274
			'string' => $search_params_string,
1275
			'type' => $search_params_type,
1276
		);
1277
1278
		// Setup the search context.
1279
		$context['search_params'] = empty($search_params['string']) ? '' : base64_encode(json_encode($search_params));
1280
		$context['search'] = array(
1281
			'string' => $search_params['string'],
1282
			'type' => $search_params['type'],
1283
			'label' => $searchTypes[$search_params_type]['label'],
1284
		);
1285
1286
		// This is all the information required for a watched user listing.
1287
		$listOptions = array(
1288
			'id' => 'warning_list',
1289
			'title' => $txt['mc_warning_log_title'],
1290
			'items_per_page' => $modSettings['defaultMaxMessages'],
1291
			'no_items_label' => $txt['mc_warnings_none'],
1292
			'base_href' => $scripturl . '?action=moderate;area=warnings;sa=log;' . $context['session_var'] . '=' . $context['session_id'],
1293
			'default_sort_col' => 'time',
1294
			'get_items' => array(
1295
				'function' => array($this, 'list_getWarnings'),
1296
				'params' => array(
1297
					(!empty($search_params['string']) ? ' INSTR({raw:sql_type}, {string:search_string})' : ''),
1298
					array('sql_type' => $search_params_column, 'search_string' => $search_params['string']),
1299
				),
1300
			),
1301
			'get_count' => array(
1302
				'function' => array($this, 'list_getWarningCount'),
1303
				'params' => array(
1304
					(!empty($search_params['string']) ? ' INSTR({raw:sql_type}, {string:search_string})' : ''),
1305
					array('sql_type' => $search_params_column, 'search_string' => $search_params['string']),
1306
				),
1307
			),
1308
			// This assumes we are viewing by user.
1309
			'columns' => array(
1310
				'issuer' => array(
1311
					'header' => array(
1312
						'value' => $txt['profile_warning_previous_issued'],
1313
					),
1314
					'data' => array(
1315
						'db' => 'issuer_link',
1316
					),
1317
					'sort' => array(
1318
						'default' => 'member_name_col',
1319
						'reverse' => 'member_name_col DESC',
1320
					),
1321
				),
1322
				'recipient' => array(
1323
					'header' => array(
1324
						'value' => $txt['mc_warnings_recipient'],
1325
					),
1326
					'data' => array(
1327
						'db' => 'recipient_link',
1328
					),
1329
					'sort' => array(
1330
						'default' => 'recipient_name',
1331
						'reverse' => 'recipient_name DESC',
1332
					),
1333
				),
1334
				'time' => array(
1335
					'header' => array(
1336
						'value' => $txt['profile_warning_previous_time'],
1337
					),
1338
					'data' => array(
1339
						'db' => 'time',
1340
					),
1341
					'sort' => array(
1342
						'default' => 'lc.log_time DESC',
1343
						'reverse' => 'lc.log_time',
1344
					),
1345
				),
1346
				'reason' => array(
1347
					'header' => array(
1348
						'value' => $txt['profile_warning_previous_reason'],
1349
					),
1350
					'data' => array(
1351
						'function' => function ($warning) {
1352
							global $scripturl, $txt;
1353
1354
							$output = '
1355
								<div class="floatleft">
1356
									' . $warning['reason'] . '
1357
								</div>';
1358
1359
							// If a notice was sent, provide a link to it
1360
							if (!empty($warning['id_notice']))
1361
								$output .= '
1362
									<a href="' . $scripturl . '?action=moderate;area=notice;nid=' . $warning['id_notice'] . '" onclick="window.open(this.href, \'\', \'scrollbars=yes,resizable=yes,width=480,height=320\');return false;" target="_blank" class="new_win" title="' . $txt['profile_warning_previous_notice'] . '"><i class="icon icon-small i-search" title"' . $txt['profile_warning_previous_notice'] . '"></i></a>';
1363
							return $output;
1364
						},
1365
					),
1366
				),
1367
				'points' => array(
1368
					'header' => array(
1369
						'value' => $txt['profile_warning_previous_level'],
1370
					),
1371
					'data' => array(
1372
						'db' => 'counter',
1373
					),
1374
				),
1375
			),
1376
			'form' => array(
1377
				'href' => $scripturl . $context['url_start'],
1378
				'include_sort' => true,
1379
				'include_start' => true,
1380
				'hidden_fields' => array(
1381
					$context['session_var'] => $context['session_id'],
1382
					'params' => $context['search_params']
1383
				),
1384
			),
1385
			'additional_rows' => array(
1386
				array(
1387
					'class' => 'submitbutton',
1388
					'position' => 'below_table_data',
1389
					'value' => '
1390
						' . $txt['modlog_search'] . ' (' . $txt['modlog_by'] . ': ' . $context['search']['label'] . ')
1391
						<input type="text" name="search" size="18" value="' . Util::htmlspecialchars($context['search']['string']) . '" class="input_text" />
1392
						<input type="submit" name="is_search" value="' . $txt['modlog_go'] . '" />',
1393
				),
1394
			),
1395
		);
1396
1397
		// Create the watched user list.
1398
		createList($listOptions);
1399
1400
		$context['sub_template'] = 'show_list';
1401
		$context['default_list'] = 'warning_list';
1402
	}
1403
1404
	/**
1405
	 * View all the custom warning templates.
1406
	 *
1407
	 *  - Shows all the templates in the system
1408
	 *  - Provides for actions to add or delete them
1409
	 */
1410
	public function action_viewWarningTemplates()
1411
	{
1412
		global $modSettings, $context, $txt, $scripturl;
1413
1414
		require_once(SUBSDIR . '/Moderation.subs.php');
1415
1416
		// Submitting a new one?
1417
		if (isset($this->_req->post->add))
1418
		{
1419
			$this->action_modifyWarningTemplate();
1420
			return true;
1421
		}
1422
		// Deleting and existing one
1423
		elseif (isset($this->_req->post->delete) && !empty($this->_req->post->deltpl))
1424
		{
1425
			checkSession('post');
1426
			validateToken('mod-wt');
1427
1428
			removeWarningTemplate($this->_req->post->deltpl);
1429
		}
1430
1431
		// Setup context as always.
1432
		$context['page_title'] = $txt['mc_warning_templates_title'];
1433
1434
		// This is all the information required for a watched user listing.
1435
		$listOptions = array(
1436
			'id' => 'warning_template_list',
1437
			'title' => $txt['mc_warning_templates_title'],
1438
			'items_per_page' => $modSettings['defaultMaxMessages'],
1439
			'no_items_label' => $txt['mc_warning_templates_none'],
1440
			'base_href' => $scripturl . '?action=moderate;area=warnings;sa=templates;' . $context['session_var'] . '=' . $context['session_id'],
1441
			'default_sort_col' => 'title',
1442
			'get_items' => array(
1443
				'function' => array($this, 'list_getWarningTemplates'),
1444
			),
1445
			'get_count' => array(
1446
				'function' => array($this, 'list_getWarningTemplateCount'),
1447
			),
1448
			'columns' => array(
1449
				'title' => array(
1450
					'header' => array(
1451
						'value' => $txt['mc_warning_templates_name'],
1452
					),
1453
					'data' => array(
1454
						'sprintf' => array(
1455
							'format' => '<a href="' . $scripturl . '?action=moderate;area=warnings;sa=templateedit;tid=%1$d">%2$s</a>',
1456
							'params' => array(
1457
								'id_comment' => false,
1458
								'title' => false,
1459
								'body' => false,
1460
							),
1461
						),
1462
					),
1463
					'sort' => array(
1464
						'default' => 'template_title',
1465
						'reverse' => 'template_title DESC',
1466
					),
1467
				),
1468
				'creator' => array(
1469
					'header' => array(
1470
						'value' => $txt['mc_warning_templates_creator'],
1471
					),
1472
					'data' => array(
1473
						'db' => 'creator',
1474
					),
1475
					'sort' => array(
1476
						'default' => 'creator_name',
1477
						'reverse' => 'creator_name DESC',
1478
					),
1479
				),
1480
				'time' => array(
1481
					'header' => array(
1482
						'value' => $txt['mc_warning_templates_time'],
1483
					),
1484
					'data' => array(
1485
						'db' => 'time',
1486
					),
1487
					'sort' => array(
1488
						'default' => 'lc.log_time DESC',
1489
						'reverse' => 'lc.log_time',
1490
					),
1491
				),
1492
				'delete' => array(
1493
					'header' => array(
1494
						'value' => '<input type="checkbox" class="input_check" onclick="invertAll(this, this.form);" />',
1495
						'style' => 'width: 4%;text-align: center;',
1496
					),
1497
					'data' => array(
1498
						'function' => function ($rowData) {
1499
							return '<input type="checkbox" name="deltpl[]" value="' . $rowData['id_comment'] . '" class="input_check" />';
1500
						},
1501
						'class' => 'centertext',
1502
					),
1503
				),
1504
			),
1505
			'form' => array(
1506
				'href' => $scripturl . '?action=moderate;area=warnings;sa=templates',
1507
				'token' => 'mod-wt',
1508
			),
1509
			'additional_rows' => array(
1510
				array(
1511
					'position' => 'below_table_data',
1512
					'value' => '
1513
						<input type="submit" name="delete" value="' . $txt['mc_warning_template_delete'] . '" onclick="return confirm(\'' . $txt['mc_warning_template_delete_confirm'] . '\');" class="right_submit" />
1514
						<input type="submit" name="add" value="' . $txt['mc_warning_template_add'] . '" class="right_submit" />',
1515
				),
1516
			),
1517
		);
1518
1519
		// Create the watched user list.
1520
		createToken('mod-wt');
1521
		createList($listOptions);
1522
1523
		$context['sub_template'] = 'show_list';
1524
		$context['default_list'] = 'warning_template_list';
1525
	}
1526
1527
	/**
1528
	 * Entry point for viewing warning related stuff.
1529
	 */
1530
	public function action_viewWarnings()
1531
	{
1532
		global $context, $txt;
1533
1534
		// Some of this stuff is overseas, so to speak.
1535
		loadTemplate('ModerationCenter');
1536
		loadLanguage('Profile');
1537
1538
		$subActions = array(
1539
			'log' => array($this, 'action_viewWarningLog'),
1540
			'templateedit' => array($this, 'action_modifyWarningTemplate', 'permission' => 'issue_warning'),
1541
			'templates' => array($this, 'action_viewWarningTemplates', 'permission' => 'issue_warning'),
1542
		);
1543
1544
		// Setup the admin tabs.
1545
		$context[$context['moderation_menu_name']]['tab_data'] = array(
1546
			'title' => $txt['mc_warnings'],
1547
			'description' => $txt['mc_warnings_description'],
1548
		);
1549
1550
		// Call the right function.
1551
		$action = new Action('moderation_center');
1552
		$subAction = $action->initialize($subActions, 'log');
1553
		$context['sub_action'] = $subAction;
1554
		$action->dispatch($subAction);
1555
	}
1556
1557
	/**
1558
	 * Callback for createList() for watched users
1559
	 *
1560
	 * - returns count
1561
	 *
1562
	 * @uses watchedUserCount()
1563
	 */
1564
	public function list_getWatchedUserCount()
1565
	{
1566
		global $modSettings;
1567
1568
		return watchedUserCount($modSettings['warning_watch']);
1569
	}
1570
1571
	/**
1572
	 * Callback for createList() used in watched users
1573
	 *
1574
	 * @uses watchedUsers()
1575
	 * @param int $start The item to start with (for pagination purposes)
1576
	 * @param int $items_per_page  The number of items to show per page
1577
	 * @param string $sort A string indicating how to sort the results
1578
	 */
1579
	public function list_getWatchedUsers($start, $items_per_page, $sort)
1580
	{
1581
		// Find all our watched users
1582
		return watchedUsers($start, $items_per_page, $sort);
1583
	}
1584
1585
	/**
1586
	 * Callback for createList().
1587
	 *
1588
	 * @uses watchedUserPostsCount()
1589
	 * @param string $approve_query
1590
	 */
1591
	public function list_getWatchedUserPostsCount($approve_query)
1592
	{
1593
		global $modSettings;
1594
1595
		return watchedUserPostsCount($approve_query, $modSettings['warning_watch']);
1596
	}
1597
1598
	/**
1599
	 * Callback for createList().
1600
	 *
1601
	 * @uses watchedUserPosts()
1602
	 * @param int $start The item to start with (for pagination purposes)
1603
	 * @param int $items_per_page  The number of items to show per page
1604
	 * @param string $sort A string indicating how to sort the results
1605
	 * @param string $approve_query
1606
	 * @param int[] $delete_boards
1607
	 */
1608
	public function list_getWatchedUserPosts($start, $items_per_page, $sort, $approve_query, $delete_boards)
1609
	{
1610
		// Watched users posts
1611
		return watchedUserPosts($start, $items_per_page, $sort, $approve_query, $delete_boards);
1612
	}
1613
1614
	/**
1615
	 * Callback for createList() to get all the templates of a type from the system
1616
	 *
1617
	 * @uses warningTemplates()
1618
	 * @param int $start The item to start with (for pagination purposes)
1619
	 * @param int $items_per_page  The number of items to show per page
1620
	 * @param string $sort A string indicating how to sort the results
1621
	 * @param string $template_type type of template to load
1622
	 */
1623
	public function list_getWarningTemplates($start, $items_per_page, $sort, $template_type = 'warntpl')
1624
	{
1625
		return warningTemplates($start, $items_per_page, $sort, $template_type);
1626
	}
1627
1628
	/**
1629
	 * Callback for createList() to get the number of templates of a type in the system
1630
	 *
1631
	 * @uses warningTemplateCount()
1632
	 * @param string $template_type
1633
	 */
1634
	public function list_getWarningTemplateCount($template_type = 'warntpl')
1635
	{
1636
		return warningTemplateCount($template_type);
1637
	}
1638
1639
	/**
1640
	 * Callback for createList()
1641
	 *
1642
	 * - Used to get all issued warnings in the system
1643
	 * @uses warnings() function in moderation.subs
1644
	 *
1645
	 * @param int $start The item to start with (for pagination purposes)
1646
	 * @param int $items_per_page  The number of items to show per page
1647
	 * @param string $sort A string indicating how to sort the results
1648
	 * @param string $query_string
1649
	 * @param mixed[] $query_params
1650
	 */
1651
	public function list_getWarnings($start, $items_per_page, $sort, $query_string, $query_params)
1652
	{
1653
		return warnings($start, $items_per_page, $sort, $query_string, $query_params);
1654
	}
1655
1656
	/**
1657
	 * Callback for createList()
1658
	 *
1659
	 * - Get the total count of all current warnings
1660
	 * @uses warningCount() function in moderation.subs
1661
	 *
1662
	 * @param string $query_string
1663
	 * @param mixed[] $query_params
1664
	 */
1665
	public function list_getWarningCount($query_string, $query_params)
1666
	{
1667
		return warningCount($query_string, $query_params);
1668
	}
1669
1670
	/**
1671
	 * Show a list of all the group requests they can see.
1672
	 * Checks permissions for group moderation.
1673
	 */
1674
	public function block_groupRequests()
1675
	{
1676
		global $context, $user_info;
1677
1678
		// Make sure they can even moderate someone!
1679
		if ($user_info['mod_cache']['gq'] === '0=1')
1680
			return 'group_requests_block';
1681
1682
		$context['group_requests'] = groupRequests();
1683
1684
		return 'group_requests_block';
1685
	}
1686
1687
	/**
1688
	 * Just prepares the time stuff for the latest news.
1689
	 */
1690
	public function block_latestNews()
1691
	{
1692
		global $context, $user_info;
1693
1694
		$context['time_format'] = urlencode($user_info['time_format']);
1695
1696
		// Return the template to use.
1697
		return 'latest_news';
1698
	}
1699
1700
	/**
1701
	 * Show a list of the most active watched users.
1702
	 */
1703
	public function block_watchedUsers()
1704
	{
1705
		global $context, $scripturl;
1706
1707
		$watched_users = basicWatchedUsers();
1708
1709
		$context['watched_users'] = array();
1710
		if (is_array($watched_users) || is_object($watched_users))
1711
		{
1712
			foreach ($watched_users as $user)
1713
			{
1714
				$context['watched_users'][] = array(
1715
					'id' => $user['id_member'],
1716
					'name' => $user['real_name'],
1717
					'link' => '<a href="' . $scripturl . '?action=profile;u=' . $user['id_member'] . '">' . $user['real_name'] . '</a>',
1718
					'href' => $scripturl . '?action=profile;u=' . $user['id_member'],
1719
					'last_login' => !empty($user['last_login']) ? standardTime($user['last_login']) : '',
1720
				);
1721
			}
1722
		}
1723
1724
		return 'watched_users';
1725
	}
1726
1727
	/**
1728
	 * Shows a list of items requiring moderation action
1729
	 * Includes post, topic, attachment, group, member and PBE values with links to each
1730
	 */
1731
	public function block_actionRequired()
1732
	{
1733
		global $context;
1734
1735
		// Get the action totals
1736
		$mod_totals = loadModeratorMenuCounts();
1737
1738
		// This blocks total is only these fields
1739
		$context['mc_required'] = $mod_totals['attachments'] + $mod_totals['emailmod'] + $mod_totals['topics'] + $mod_totals['posts'] + $mod_totals['memberreq'] + $mod_totals['groupreq'] + + $mod_totals['reports'];
1740
		unset($mod_totals['postmod'], $mod_totals['pt_total'], $mod_totals['mg_total'], $mod_totals['grand_total']);
1741
		$context['required'] = $mod_totals;
1742
1743
		// Links to the areas
1744
		$context['links'] = array(
1745
			'attachments' => '?action=moderate;area=attachmod;sa=attachments',
1746
			'emailmod' => '?action=admin;area=maillist;sa=emaillist',
1747
			'topics' => '?action=moderate;area=postmod;sa=topics',
1748
			'posts' => '?action=moderate;area=postmod;sa=posts',
1749
			'memberreq' => '?action=admin;area=viewmembers;sa=browse;type=approve',
1750
			'groupreq' => '?action=moderate;area=groups;sa=requests',
1751
			'reports' => '?action=moderate;area=reports;sa=open',
1752
			'pm_reports' => '?action=moderate;area=pm_reports;sa=open',
1753
		);
1754
1755
		return 'action_required';
1756
	}
1757
1758
	/**
1759
	 * Show an area for the moderator to type into.
1760
	 */
1761
	public function block_notes()
1762
	{
1763
		global $context, $scripturl, $txt, $user_info;
1764
1765
		// Are we saving a note?
1766
		if (isset($this->_req->post->makenote) && isset($this->_req->post->new_note))
1767
		{
1768
			checkSession();
1769
1770
			$new_note = Util::htmlspecialchars(trim($this->_req->post->new_note));
1771
1772
			// Make sure they actually entered something.
1773
			if (!empty($new_note) && $new_note !== $txt['mc_click_add_note'])
1774
			{
1775
				// Insert it into the database then!
1776
				addModeratorNote($user_info['id'], $user_info['name'], $new_note);
1777
1778
				// Clear the cache.
1779
				Cache::instance()->remove('moderator_notes');
1780
				Cache::instance()->remove('moderator_notes_total');
1781
			}
1782
1783
			// Redirect otherwise people can resubmit.
1784
			redirectexit('action=moderate');
1785
		}
1786
1787
		// Bye... bye...
1788
		if (isset($this->_req->query->notes) && isset($this->_req->query->delete) && is_numeric($this->_req->query->delete))
1789
		{
1790
			checkSession('get');
1791
1792
			// Just checkin'!
1793
			$id_delete = (int) $this->_req->query->delete;
1794
1795
			// Lets delete it.
1796
			removeModeratorNote($id_delete);
1797
1798
			// Clear the cache.
1799
			Cache::instance()->remove('moderator_notes');
1800
			Cache::instance()->remove('moderator_notes_total');
1801
1802
			redirectexit('action=moderate');
1803
		}
1804
1805
		// How many notes in total?
1806
		$moderator_notes_total = countModeratorNotes();
1807
1808
		// Grab the current notes. We can only use the cache for the first page of notes.
1809
		$offset = isset($this->_req->query->notes) && isset($this->_req->query->start) ? $this->_req->query->start : 0;
1810
		$moderator_notes = moderatorNotes($offset);
1811
1812
		// Lets construct a page index.
1813
		$context['page_index'] = constructPageIndex($scripturl . '?action=moderate;area=index;notes', $this->_req->query->start, $moderator_notes_total, 10);
1814
		$context['start'] = $this->_req->query->start;
1815
1816
		$bbc_parser = \BBC\ParserWrapper::instance();
1817
1818
		$context['notes'] = array();
1819
		foreach ($moderator_notes as $note)
1820
		{
1821
			$context['notes'][] = array(
1822
				'author' => array(
1823
					'id' => $note['id_member'],
1824
					'link' => $note['id_member'] ? ('<a href="' . $scripturl . '?action=profile;u=' . $note['id_member'] . '" title="' . $txt['on'] . ' ' . strip_tags(standardTime($note['log_time'])) . '">' . $note['member_name'] . '</a>') : $note['member_name'],
1825
				),
1826
				'time' => standardTime($note['log_time']),
1827
				'html_time' => htmlTime($note['log_time']),
1828
				'timestamp' => forum_time(true, $note['log_time']),
1829
				'text' => $bbc_parser->parseReport($note['body']),
1830
				'delete_href' => $scripturl . '?action=moderate;area=index;notes;delete=' . $note['id_note'] . ';' . $context['session_var'] . '=' . $context['session_id'],
1831
			);
1832
		}
1833
1834
		return 'notes';
1835
	}
1836
1837
	/**
1838
	 * Show a list of the most recent reported posts.
1839
	 */
1840
	public function block_reportedPosts()
1841
	{
1842
		global $context, $user_info, $scripturl;
1843
1844
		if ($user_info['mod_cache']['bq'] === '0=1')
1845
			return 'reported_posts_block';
1846
1847
		$context['reported_posts'] = array();
1848
1849
		$reported_posts = reportedPosts(false);
1850
		foreach ($reported_posts as $i => $row)
1851
		{
1852
			$context['reported_posts'][] = array(
1853
				'id' => $row['id_report'],
1854
				'alternate' => $i % 2,
1855
				'topic_href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'],
1856
				'report_href' => $scripturl . '?action=moderate;area=' . $context['admin_area'] . ';report=' . $row['id_report'],
1857
				'author' => array(
1858
					'id' => $row['id_author'],
1859
					'name' => $row['author_name'],
1860
					'link' => $row['id_author'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_author'] . '">' . $row['author_name'] . '</a>' : $row['author_name'],
1861
					'href' => $scripturl . '?action=profile;u=' . $row['id_author'],
1862
				),
1863
				'comments' => array(),
1864
				'subject' => $row['subject'],
1865
				'num_reports' => $row['num_reports'],
1866
			);
1867
		}
1868
1869
		return 'reported_posts_block';
1870
	}
1871
}
1872